]>
Commit | Line | Data |
---|---|---|
f324c4a6 WB |
1 | From 56daf5912f942155224af873b056f981fca2de8b Mon Sep 17 00:00:00 2001 |
2 | From: Paolo Bonzini <pbonzini@redhat.com> | |
3 | Date: Sat, 4 Jul 2015 00:24:51 +0200 | |
4 | Subject: [PATCH 3/4] exec: skip MMIO regions correctly in | |
5 | cpu_physical_memory_write_rom_internal | |
6 | ||
7 | Loading the BIOS in the mac99 machine is interesting, because there is a | |
8 | PROM in the middle of the BIOS region (from 16K to 32K). Before memory | |
9 | region accesses were clamped, when QEMU was asked to load a BIOS from | |
10 | 0xfff00000 to 0xffffffff it would put even those 16K from the BIOS file | |
11 | into the region. This is weird because those 16K were not actually | |
12 | visible between 0xfff04000 and 0xfff07fff. However, it worked. | |
13 | ||
14 | After clamping was added, this also worked. In this case, the | |
15 | cpu_physical_memory_write_rom_internal function split the write in | |
16 | three parts: the first 16K were copied, the PROM area (second 16K) were | |
17 | ignored, then the rest was copied. | |
18 | ||
19 | Problems then started with commit 965eb2f (exec: do not clamp accesses | |
20 | to MMIO regions, 2015-06-17). Clamping accesses is not done for MMIO | |
21 | regions because they can overlap wildly, and MMIO registers can be | |
22 | expected to perform full-width accesses based only on their address | |
23 | (with no respect for adjacent registers that could decode to completely | |
24 | different MemoryRegions). However, this lack of clamping also applied | |
25 | to the PROM area! cpu_physical_memory_write_rom_internal thus failed | |
26 | to copy the third range above, i.e. only copied the first 16K of the BIOS. | |
27 | ||
28 | In effect, address_space_translate is expecting _something else_ to do | |
29 | the clamping for MMIO regions if the incoming length is large. This | |
30 | "something else" is memory_access_size in the case of address_space_rw, | |
31 | so use the same logic in cpu_physical_memory_write_rom_internal. | |
32 | ||
33 | Reported-by: Alexander Graf <agraf@redhat.com> | |
34 | Reviewed-by: Laurent Vivier <lvivier@redhat.com> | |
35 | Tested-by: Laurent Vivier <lvivier@redhat.com> | |
36 | Fixes: 965eb2f | |
37 | Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> | |
38 | --- | |
39 | exec.c | 14 +++++++++++++- | |
40 | 1 file changed, 13 insertions(+), 1 deletion(-) | |
41 | ||
42 | diff --git a/exec.c b/exec.c | |
43 | index 03c9995..80c9d79 100644 | |
44 | --- a/exec.c | |
45 | +++ b/exec.c | |
46 | @@ -341,6 +341,18 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x | |
47 | *xlat = addr + section->offset_within_region; | |
48 | ||
49 | mr = section->mr; | |
50 | + | |
51 | + /* MMIO registers can be expected to perform full-width accesses based only | |
52 | + * on their address, without considering adjacent registers that could | |
53 | + * decode to completely different MemoryRegions. When such registers | |
54 | + * exist (e.g. I/O ports 0xcf8 and 0xcf9 on most PC chipsets), MMIO | |
55 | + * regions overlap wildly. For this reason we cannot clamp the accesses | |
56 | + * here. | |
57 | + * | |
58 | + * If the length is small (as is the case for address_space_ldl/stl), | |
59 | + * everything works fine. If the incoming length is large, however, | |
60 | + * the caller really has to do the clamping through memory_access_size. | |
61 | + */ | |
62 | if (memory_region_is_ram(mr)) { | |
63 | diff = int128_sub(mr->size, int128_make64(addr)); | |
64 | *plen = int128_get64(int128_min(diff, int128_make64(*plen))); | |
65 | @@ -2236,7 +2248,7 @@ static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as, | |
66 | ||
67 | if (!(memory_region_is_ram(mr) || | |
68 | memory_region_is_romd(mr))) { | |
69 | - /* do nothing */ | |
70 | + l = memory_access_size(mr, l, addr1); | |
71 | } else { | |
72 | addr1 += memory_region_get_ram_addr(mr); | |
73 | /* ROM/RAM case */ | |
74 | -- | |
75 | 2.1.4 | |
76 |