1 |
commit: ab12906b61c4c483c4ea5eb9d9728f718aec4702 |
2 |
Author: David Gibson <david <AT> gibson <DOT> dropbear <DOT> id <DOT> au> |
3 |
AuthorDate: Mon Sep 10 02:30:57 2012 +0000 |
4 |
Commit: Doug Goldstein <cardoe <AT> gentoo <DOT> org> |
5 |
CommitDate: Wed Oct 24 07:04:36 2012 +0000 |
6 |
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/qemu-kvm.git;a=commit;h=ab12906b |
7 |
|
8 |
cpu_physical_memory_write_rom() needs to do TB invalidates |
9 |
|
10 |
cpu_physical_memory_write_rom(), despite the name, can also be used to |
11 |
write images into RAM - and will often be used that way if the machine |
12 |
uses load_image_targphys() into RAM addresses. |
13 |
|
14 |
However, cpu_physical_memory_write_rom(), unlike cpu_physical_memory_rw() |
15 |
doesn't invalidate any cached TBs which might be affected by the region |
16 |
written. |
17 |
|
18 |
This was breaking reset (under full emu) on the pseries machine - we loaded |
19 |
our firmware image into RAM, and while executing it rewrite the code at |
20 |
the entry point (correctly causing a TB invalidate/refresh). When we |
21 |
reset the firmware image was reloaded, but the TB from the rewrite was |
22 |
still active and caused us to get an illegal instruction trap. |
23 |
|
24 |
This patch fixes the bug by duplicating the tb invalidate code from |
25 |
cpu_physical_memory_rw() in cpu_physical_memory_write_rom(). |
26 |
|
27 |
Signed-off-by: David Gibson <david <AT> gibson.dropbear.id.au> |
28 |
Signed-off-by: Anthony Liguori <aliguori <AT> us.ibm.com> |
29 |
(cherry picked from commit 0b57e287138728f72d88b06e69b970c5d745c44a) |
30 |
|
31 |
--- |
32 |
exec.c | 7 +++++++ |
33 |
1 files changed, 7 insertions(+), 0 deletions(-) |
34 |
|
35 |
diff --git a/exec.c b/exec.c |
36 |
index 0a67f07..8e97f93 100644 |
37 |
--- a/exec.c |
38 |
+++ b/exec.c |
39 |
@@ -3625,6 +3625,13 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr, |
40 |
/* ROM/RAM case */ |
41 |
ptr = qemu_get_ram_ptr(addr1); |
42 |
memcpy(ptr, buf, l); |
43 |
+ if (!cpu_physical_memory_is_dirty(addr1)) { |
44 |
+ /* invalidate code */ |
45 |
+ tb_invalidate_phys_page_range(addr1, addr1 + l, 0); |
46 |
+ /* set dirty bit */ |
47 |
+ cpu_physical_memory_set_dirty_flags( |
48 |
+ addr1, (0xff & ~CODE_DIRTY_FLAG)); |
49 |
+ } |
50 |
qemu_put_ram_ptr(ptr); |
51 |
} |
52 |
len -= l; |