1 | Small pullreq with some bug fixes to go into rc1. | 1 | v2: dropped USHL/SSHL patch |
---|---|---|---|
2 | 2 | ||
3 | -- PMM | 3 | The following changes since commit 785a602eae7ad97076b9794ebaba072ad4a9f74f: |
4 | 4 | ||
5 | The following changes since commit 5ca634afcf83215a9a54ca6e66032325b5ffb5f6: | 5 | Merge remote-tracking branch 'remotes/kraxel/tags/vga-20190613-pull-request' into staging (2019-06-13 13:25:25 +0100) |
6 | |||
7 | Merge remote-tracking branch 'remotes/philmd/tags/sdmmc-20210322' into staging (2021-03-22 18:50:25 +0000) | ||
8 | 6 | ||
9 | are available in the Git repository at: | 7 | are available in the Git repository at: |
10 | 8 | ||
11 | https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210323 | 9 | https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190613-1 |
12 | 10 | ||
13 | for you to fetch changes up to dad90de78e9e9d47cefcbcd30115706b98e6ec87: | 11 | for you to fetch changes up to 18cf951af9a27ae573a6fa17f9d0c103f7b7679b: |
14 | 12 | ||
15 | target/arm: Set ARMMMUFaultInfo.level in user-only arm_cpu_tlb_fill (2021-03-23 14:07:55 +0000) | 13 | target/arm: Fix short-vector increment behaviour (2019-06-13 15:14:06 +0100) |
16 | 14 | ||
17 | ---------------------------------------------------------------- | 15 | ---------------------------------------------------------------- |
18 | target-arm queue: | 16 | target-arm queue: |
19 | * hw/arm/virt: Disable pl011 clock migration if needed | 17 | * convert aarch32 VFP decoder to decodetree |
20 | * target/arm: Make M-profile VTOR loads on reset handle memory aliasing | 18 | (includes tightening up decode in a few places) |
21 | * target/arm: Set ARMMMUFaultInfo.level in user-only arm_cpu_tlb_fill | 19 | * fix minor bugs in VFP short-vector handling |
20 | * hw/core/bus.c: Only the main system bus can have no parent | ||
21 | * smmuv3: Fix decoding of ID register range | ||
22 | * Implement NSACR gating of floating point | ||
23 | * Use tcg_gen_gvec_bitsel | ||
22 | 24 | ||
23 | ---------------------------------------------------------------- | 25 | ---------------------------------------------------------------- |
24 | Gavin Shan (1): | 26 | Peter Maydell (44): |
25 | hw/arm/virt: Disable pl011 clock migration if needed | 27 | target/arm: Implement NSACR gating of floating point |
28 | hw/arm/smmuv3: Fix decoding of ID register range | ||
29 | hw/core/bus.c: Only the main system bus can have no parent | ||
30 | target/arm: Add stubs for AArch32 VFP decodetree | ||
31 | target/arm: Factor out VFP access checking code | ||
32 | target/arm: Fix Cortex-R5F MVFR values | ||
33 | target/arm: Explicitly enable VFP short-vectors for aarch32 -cpu max | ||
34 | target/arm: Convert the VSEL instructions to decodetree | ||
35 | target/arm: Convert VMINNM, VMAXNM to decodetree | ||
36 | target/arm: Convert VRINTA/VRINTN/VRINTP/VRINTM to decodetree | ||
37 | target/arm: Convert VCVTA/VCVTN/VCVTP/VCVTM to decodetree | ||
38 | target/arm: Move the VFP trans_* functions to translate-vfp.inc.c | ||
39 | target/arm: Add helpers for VFP register loads and stores | ||
40 | target/arm: Convert "double-precision" register moves to decodetree | ||
41 | target/arm: Convert "single-precision" register moves to decodetree | ||
42 | target/arm: Convert VFP two-register transfer insns to decodetree | ||
43 | target/arm: Convert VFP VLDR and VSTR to decodetree | ||
44 | target/arm: Convert the VFP load/store multiple insns to decodetree | ||
45 | target/arm: Remove VLDR/VSTR/VLDM/VSTM use of cpu_F0s and cpu_F0d | ||
46 | target/arm: Convert VFP VMLA to decodetree | ||
47 | target/arm: Convert VFP VMLS to decodetree | ||
48 | target/arm: Convert VFP VNMLS to decodetree | ||
49 | target/arm: Convert VFP VNMLA to decodetree | ||
50 | target/arm: Convert VMUL to decodetree | ||
51 | target/arm: Convert VNMUL to decodetree | ||
52 | target/arm: Convert VADD to decodetree | ||
53 | target/arm: Convert VSUB to decodetree | ||
54 | target/arm: Convert VDIV to decodetree | ||
55 | target/arm: Convert VFP fused multiply-add insns to decodetree | ||
56 | target/arm: Convert VMOV (imm) to decodetree | ||
57 | target/arm: Convert VABS to decodetree | ||
58 | target/arm: Convert VNEG to decodetree | ||
59 | target/arm: Convert VSQRT to decodetree | ||
60 | target/arm: Convert VMOV (register) to decodetree | ||
61 | target/arm: Convert VFP comparison insns to decodetree | ||
62 | target/arm: Convert the VCVT-from-f16 insns to decodetree | ||
63 | target/arm: Convert the VCVT-to-f16 insns to decodetree | ||
64 | target/arm: Convert VFP round insns to decodetree | ||
65 | target/arm: Convert double-single precision conversion insns to decodetree | ||
66 | target/arm: Convert integer-to-float insns to decodetree | ||
67 | target/arm: Convert VJCVT to decodetree | ||
68 | target/arm: Convert VCVT fp/fixed-point conversion insns to decodetree | ||
69 | target/arm: Convert float-to-integer VCVT insns to decodetree | ||
70 | target/arm: Fix short-vector increment behaviour | ||
26 | 71 | ||
27 | Peter Maydell (5): | 72 | Richard Henderson (3): |
28 | memory: Make flatview_cb return bool, not int | 73 | target/arm: Use tcg_gen_gvec_bitsel |
29 | memory: Document flatview_for_each_range() | 74 | target/arm: Fix output of PAuth Auth |
30 | memory: Add offset_in_region to flatview_cb arguments | 75 | decodetree: Fix comparison of Field |
31 | hw/core/loader: Add new function rom_ptr_for_as() | ||
32 | target/arm: Make M-profile VTOR loads on reset handle memory aliasing | ||
33 | 76 | ||
34 | Richard Henderson (1): | 77 | target/arm/Makefile.objs | 13 + |
35 | target/arm: Set ARMMMUFaultInfo.level in user-only arm_cpu_tlb_fill | 78 | tests/tcg/aarch64/Makefile.target | 2 +- |
79 | target/arm/cpu.h | 11 + | ||
80 | target/arm/translate-a64.h | 2 + | ||
81 | target/arm/translate.h | 3 - | ||
82 | hw/arm/smmuv3.c | 2 +- | ||
83 | hw/core/bus.c | 21 +- | ||
84 | target/arm/cpu.c | 6 + | ||
85 | target/arm/helper.c | 75 +- | ||
86 | target/arm/pauth_helper.c | 4 +- | ||
87 | target/arm/translate-a64.c | 15 +- | ||
88 | target/arm/translate-vfp.inc.c | 2672 +++++++++++++++++++++++++++++++++++++ | ||
89 | target/arm/translate.c | 1581 +--------------------- | ||
90 | tests/tcg/aarch64/pauth-2.c | 61 + | ||
91 | scripts/decodetree.py | 2 +- | ||
92 | target/arm/vfp-uncond.decode | 63 + | ||
93 | target/arm/vfp.decode | 242 ++++ | ||
94 | 17 files changed, 3203 insertions(+), 1572 deletions(-) | ||
95 | create mode 100644 target/arm/translate-vfp.inc.c | ||
96 | create mode 100644 tests/tcg/aarch64/pauth-2.c | ||
97 | create mode 100644 target/arm/vfp-uncond.decode | ||
98 | create mode 100644 target/arm/vfp.decode | ||
36 | 99 | ||
37 | include/exec/memory.h | 32 +++++++++++++++--- | ||
38 | include/hw/char/pl011.h | 1 + | ||
39 | include/hw/loader.h | 31 +++++++++++++++++ | ||
40 | hw/char/pl011.c | 9 +++++ | ||
41 | hw/core/loader.c | 75 +++++++++++++++++++++++++++++++++++++++++ | ||
42 | hw/core/machine.c | 1 + | ||
43 | softmmu/memory.c | 4 ++- | ||
44 | target/arm/cpu.c | 2 +- | ||
45 | target/arm/tlb_helper.c | 1 + | ||
46 | tests/qtest/fuzz/generic_fuzz.c | 11 +++--- | ||
47 | 10 files changed, 157 insertions(+), 10 deletions(-) | ||
48 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Gavin Shan <gshan@redhat.com> | ||
2 | 1 | ||
3 | A clock is added by commit aac63e0e6ea3 ("hw/char/pl011: add a clock | ||
4 | input") since v5.2.0 which corresponds to virt-5.2 machine type. It | ||
5 | causes backwards migration failure from upstream to downstream (v5.1.0) | ||
6 | when the machine type is specified with virt-5.1. | ||
7 | |||
8 | This fixes the issue by following instructions from section "Connecting | ||
9 | subsections to properties" in docs/devel/migration.rst. With this applied, | ||
10 | the PL011 clock is migrated based on the machine type. | ||
11 | |||
12 | virt-5.2 or newer: migration | ||
13 | virt-5.1 or older: non-migration | ||
14 | |||
15 | Cc: qemu-stable@nongnu.org # v5.2.0+ | ||
16 | Fixes: aac63e0e6ea3 ("hw/char/pl011: add a clock input") | ||
17 | Suggested-by: Andrew Jones <drjones@redhat.com> | ||
18 | Signed-off-by: Gavin Shan <gshan@redhat.com> | ||
19 | Reviewed-by: Andrew Jones <drjones@redhat.com> | ||
20 | Message-id: 20210318023801.18287-1-gshan@redhat.com | ||
21 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
22 | --- | ||
23 | include/hw/char/pl011.h | 1 + | ||
24 | hw/char/pl011.c | 9 +++++++++ | ||
25 | hw/core/machine.c | 1 + | ||
26 | 3 files changed, 11 insertions(+) | ||
27 | |||
28 | diff --git a/include/hw/char/pl011.h b/include/hw/char/pl011.h | ||
29 | index XXXXXXX..XXXXXXX 100644 | ||
30 | --- a/include/hw/char/pl011.h | ||
31 | +++ b/include/hw/char/pl011.h | ||
32 | @@ -XXX,XX +XXX,XX @@ struct PL011State { | ||
33 | CharBackend chr; | ||
34 | qemu_irq irq[6]; | ||
35 | Clock *clk; | ||
36 | + bool migrate_clk; | ||
37 | const unsigned char *id; | ||
38 | }; | ||
39 | |||
40 | diff --git a/hw/char/pl011.c b/hw/char/pl011.c | ||
41 | index XXXXXXX..XXXXXXX 100644 | ||
42 | --- a/hw/char/pl011.c | ||
43 | +++ b/hw/char/pl011.c | ||
44 | @@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps pl011_ops = { | ||
45 | .endianness = DEVICE_NATIVE_ENDIAN, | ||
46 | }; | ||
47 | |||
48 | +static bool pl011_clock_needed(void *opaque) | ||
49 | +{ | ||
50 | + PL011State *s = PL011(opaque); | ||
51 | + | ||
52 | + return s->migrate_clk; | ||
53 | +} | ||
54 | + | ||
55 | static const VMStateDescription vmstate_pl011_clock = { | ||
56 | .name = "pl011/clock", | ||
57 | .version_id = 1, | ||
58 | .minimum_version_id = 1, | ||
59 | + .needed = pl011_clock_needed, | ||
60 | .fields = (VMStateField[]) { | ||
61 | VMSTATE_CLOCK(clk, PL011State), | ||
62 | VMSTATE_END_OF_LIST() | ||
63 | @@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_pl011 = { | ||
64 | |||
65 | static Property pl011_properties[] = { | ||
66 | DEFINE_PROP_CHR("chardev", PL011State, chr), | ||
67 | + DEFINE_PROP_BOOL("migrate-clk", PL011State, migrate_clk, true), | ||
68 | DEFINE_PROP_END_OF_LIST(), | ||
69 | }; | ||
70 | |||
71 | diff --git a/hw/core/machine.c b/hw/core/machine.c | ||
72 | index XXXXXXX..XXXXXXX 100644 | ||
73 | --- a/hw/core/machine.c | ||
74 | +++ b/hw/core/machine.c | ||
75 | @@ -XXX,XX +XXX,XX @@ GlobalProperty hw_compat_5_1[] = { | ||
76 | { "virtio-scsi-device", "num_queues", "1"}, | ||
77 | { "nvme", "use-intel-id", "on"}, | ||
78 | { "pvpanic", "events", "1"}, /* PVPANIC_PANICKED */ | ||
79 | + { "pl011", "migrate-clk", "off" }, | ||
80 | }; | ||
81 | const size_t hw_compat_5_1_len = G_N_ELEMENTS(hw_compat_5_1); | ||
82 | |||
83 | -- | ||
84 | 2.20.1 | ||
85 | |||
86 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | The return value of the flatview_cb callback passed to the | ||
2 | flatview_for_each_range() function is zero if the iteration through | ||
3 | the ranges should continue, or non-zero to break out of it. Use a | ||
4 | bool for this rather than int. | ||
5 | 1 | ||
6 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
7 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
8 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
9 | Message-id: 20210318174823.18066-2-peter.maydell@linaro.org | ||
10 | --- | ||
11 | include/exec/memory.h | 6 +++--- | ||
12 | tests/qtest/fuzz/generic_fuzz.c | 8 ++++---- | ||
13 | 2 files changed, 7 insertions(+), 7 deletions(-) | ||
14 | |||
15 | diff --git a/include/exec/memory.h b/include/exec/memory.h | ||
16 | index XXXXXXX..XXXXXXX 100644 | ||
17 | --- a/include/exec/memory.h | ||
18 | +++ b/include/exec/memory.h | ||
19 | @@ -XXX,XX +XXX,XX @@ static inline FlatView *address_space_to_flatview(AddressSpace *as) | ||
20 | return qatomic_rcu_read(&as->current_map); | ||
21 | } | ||
22 | |||
23 | -typedef int (*flatview_cb)(Int128 start, | ||
24 | - Int128 len, | ||
25 | - const MemoryRegion*, void*); | ||
26 | +typedef bool (*flatview_cb)(Int128 start, | ||
27 | + Int128 len, | ||
28 | + const MemoryRegion*, void*); | ||
29 | |||
30 | void flatview_for_each_range(FlatView *fv, flatview_cb cb , void *opaque); | ||
31 | |||
32 | diff --git a/tests/qtest/fuzz/generic_fuzz.c b/tests/qtest/fuzz/generic_fuzz.c | ||
33 | index XXXXXXX..XXXXXXX 100644 | ||
34 | --- a/tests/qtest/fuzz/generic_fuzz.c | ||
35 | +++ b/tests/qtest/fuzz/generic_fuzz.c | ||
36 | @@ -XXX,XX +XXX,XX @@ struct get_io_cb_info { | ||
37 | address_range result; | ||
38 | }; | ||
39 | |||
40 | -static int get_io_address_cb(Int128 start, Int128 size, | ||
41 | - const MemoryRegion *mr, void *opaque) { | ||
42 | +static bool get_io_address_cb(Int128 start, Int128 size, | ||
43 | + const MemoryRegion *mr, void *opaque) { | ||
44 | struct get_io_cb_info *info = opaque; | ||
45 | if (g_hash_table_lookup(fuzzable_memoryregions, mr)) { | ||
46 | if (info->index == 0) { | ||
47 | info->result.addr = (ram_addr_t)start; | ||
48 | info->result.size = (ram_addr_t)size; | ||
49 | info->found = 1; | ||
50 | - return 1; | ||
51 | + return true; | ||
52 | } | ||
53 | info->index--; | ||
54 | } | ||
55 | - return 0; | ||
56 | + return false; | ||
57 | } | ||
58 | |||
59 | /* | ||
60 | -- | ||
61 | 2.20.1 | ||
62 | |||
63 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Add a documentation comment describing flatview_for_each_range(). | ||
2 | 1 | ||
3 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
4 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
5 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
6 | Message-id: 20210318174823.18066-3-peter.maydell@linaro.org | ||
7 | --- | ||
8 | include/exec/memory.h | 26 ++++++++++++++++++++++++-- | ||
9 | 1 file changed, 24 insertions(+), 2 deletions(-) | ||
10 | |||
11 | diff --git a/include/exec/memory.h b/include/exec/memory.h | ||
12 | index XXXXXXX..XXXXXXX 100644 | ||
13 | --- a/include/exec/memory.h | ||
14 | +++ b/include/exec/memory.h | ||
15 | @@ -XXX,XX +XXX,XX @@ static inline FlatView *address_space_to_flatview(AddressSpace *as) | ||
16 | return qatomic_rcu_read(&as->current_map); | ||
17 | } | ||
18 | |||
19 | +/** | ||
20 | + * typedef flatview_cb: callback for flatview_for_each_range() | ||
21 | + * | ||
22 | + * @start: start address of the range within the FlatView | ||
23 | + * @len: length of the range in bytes | ||
24 | + * @mr: MemoryRegion covering this range | ||
25 | + * @opaque: data pointer passed to flatview_for_each_range() | ||
26 | + * | ||
27 | + * Returns: true to stop the iteration, false to keep going. | ||
28 | + */ | ||
29 | typedef bool (*flatview_cb)(Int128 start, | ||
30 | Int128 len, | ||
31 | - const MemoryRegion*, void*); | ||
32 | + const MemoryRegion *mr, | ||
33 | + void *opaque); | ||
34 | |||
35 | -void flatview_for_each_range(FlatView *fv, flatview_cb cb , void *opaque); | ||
36 | +/** | ||
37 | + * flatview_for_each_range: Iterate through a FlatView | ||
38 | + * @fv: the FlatView to iterate through | ||
39 | + * @cb: function to call for each range | ||
40 | + * @opaque: opaque data pointer to pass to @cb | ||
41 | + * | ||
42 | + * A FlatView is made up of a list of non-overlapping ranges, each of | ||
43 | + * which is a slice of a MemoryRegion. This function iterates through | ||
44 | + * each range in @fv, calling @cb. The callback function can terminate | ||
45 | + * iteration early by returning 'true'. | ||
46 | + */ | ||
47 | +void flatview_for_each_range(FlatView *fv, flatview_cb cb, void *opaque); | ||
48 | |||
49 | /** | ||
50 | * struct MemoryRegionSection: describes a fragment of a #MemoryRegion | ||
51 | -- | ||
52 | 2.20.1 | ||
53 | |||
54 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | The function flatview_for_each_range() calls a callback for each | ||
2 | range in a FlatView. Currently the callback gets the start and | ||
3 | length of the range and the MemoryRegion involved, but not the offset | ||
4 | within the MemoryRegion. Add this to the callback's arguments; we're | ||
5 | going to want it for a new use in the next commit. | ||
6 | 1 | ||
7 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
8 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
9 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
10 | Message-id: 20210318174823.18066-4-peter.maydell@linaro.org | ||
11 | --- | ||
12 | include/exec/memory.h | 2 ++ | ||
13 | softmmu/memory.c | 4 +++- | ||
14 | tests/qtest/fuzz/generic_fuzz.c | 5 ++++- | ||
15 | 3 files changed, 9 insertions(+), 2 deletions(-) | ||
16 | |||
17 | diff --git a/include/exec/memory.h b/include/exec/memory.h | ||
18 | index XXXXXXX..XXXXXXX 100644 | ||
19 | --- a/include/exec/memory.h | ||
20 | +++ b/include/exec/memory.h | ||
21 | @@ -XXX,XX +XXX,XX @@ static inline FlatView *address_space_to_flatview(AddressSpace *as) | ||
22 | * @start: start address of the range within the FlatView | ||
23 | * @len: length of the range in bytes | ||
24 | * @mr: MemoryRegion covering this range | ||
25 | + * @offset_in_region: offset of the first byte of the range within @mr | ||
26 | * @opaque: data pointer passed to flatview_for_each_range() | ||
27 | * | ||
28 | * Returns: true to stop the iteration, false to keep going. | ||
29 | @@ -XXX,XX +XXX,XX @@ static inline FlatView *address_space_to_flatview(AddressSpace *as) | ||
30 | typedef bool (*flatview_cb)(Int128 start, | ||
31 | Int128 len, | ||
32 | const MemoryRegion *mr, | ||
33 | + hwaddr offset_in_region, | ||
34 | void *opaque); | ||
35 | |||
36 | /** | ||
37 | diff --git a/softmmu/memory.c b/softmmu/memory.c | ||
38 | index XXXXXXX..XXXXXXX 100644 | ||
39 | --- a/softmmu/memory.c | ||
40 | +++ b/softmmu/memory.c | ||
41 | @@ -XXX,XX +XXX,XX @@ void flatview_for_each_range(FlatView *fv, flatview_cb cb , void *opaque) | ||
42 | assert(cb); | ||
43 | |||
44 | FOR_EACH_FLAT_RANGE(fr, fv) { | ||
45 | - if (cb(fr->addr.start, fr->addr.size, fr->mr, opaque)) | ||
46 | + if (cb(fr->addr.start, fr->addr.size, fr->mr, | ||
47 | + fr->offset_in_region, opaque)) { | ||
48 | break; | ||
49 | + } | ||
50 | } | ||
51 | } | ||
52 | |||
53 | diff --git a/tests/qtest/fuzz/generic_fuzz.c b/tests/qtest/fuzz/generic_fuzz.c | ||
54 | index XXXXXXX..XXXXXXX 100644 | ||
55 | --- a/tests/qtest/fuzz/generic_fuzz.c | ||
56 | +++ b/tests/qtest/fuzz/generic_fuzz.c | ||
57 | @@ -XXX,XX +XXX,XX @@ struct get_io_cb_info { | ||
58 | }; | ||
59 | |||
60 | static bool get_io_address_cb(Int128 start, Int128 size, | ||
61 | - const MemoryRegion *mr, void *opaque) { | ||
62 | + const MemoryRegion *mr, | ||
63 | + hwaddr offset_in_region, | ||
64 | + void *opaque) | ||
65 | +{ | ||
66 | struct get_io_cb_info *info = opaque; | ||
67 | if (g_hash_table_lookup(fuzzable_memoryregions, mr)) { | ||
68 | if (info->index == 0) { | ||
69 | -- | ||
70 | 2.20.1 | ||
71 | |||
72 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | For accesses to rom blob data before or during reset, we have a | ||
2 | function rom_ptr() which looks for a rom blob that would be loaded to | ||
3 | the specified address, and returns a pointer into the rom blob data | ||
4 | corresponding to that address. This allows board or CPU code to say | ||
5 | "what is the data that is going to be loaded to this address?". | ||
6 | 1 | ||
7 | However, this function does not take account of memory region | ||
8 | aliases. If for instance a machine model has RAM at address | ||
9 | 0x0000_0000 which is aliased to also appear at 0x1000_0000, a | ||
10 | rom_ptr() query for address 0x0000_0000 will only return a match if | ||
11 | the guest image provided by the user was loaded at 0x0000_0000 and | ||
12 | not if it was loaded at 0x1000_0000, even though they are the same | ||
13 | RAM and a run-time guest CPU read of 0x0000_0000 will read the data | ||
14 | loaded to 0x1000_0000. | ||
15 | |||
16 | Provide a new function rom_ptr_for_as() which takes an AddressSpace | ||
17 | argument, so that it can check whether the MemoryRegion corresponding | ||
18 | to the address is also mapped anywhere else in the AddressSpace and | ||
19 | look for rom blobs that loaded to that alias. | ||
20 | |||
21 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
22 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
23 | Message-id: 20210318174823.18066-5-peter.maydell@linaro.org | ||
24 | --- | ||
25 | include/hw/loader.h | 31 +++++++++++++++++++ | ||
26 | hw/core/loader.c | 75 +++++++++++++++++++++++++++++++++++++++++++++ | ||
27 | 2 files changed, 106 insertions(+) | ||
28 | |||
29 | diff --git a/include/hw/loader.h b/include/hw/loader.h | ||
30 | index XXXXXXX..XXXXXXX 100644 | ||
31 | --- a/include/hw/loader.h | ||
32 | +++ b/include/hw/loader.h | ||
33 | @@ -XXX,XX +XXX,XX @@ void rom_transaction_end(bool commit); | ||
34 | |||
35 | int rom_copy(uint8_t *dest, hwaddr addr, size_t size); | ||
36 | void *rom_ptr(hwaddr addr, size_t size); | ||
37 | +/** | ||
38 | + * rom_ptr_for_as: Return a pointer to ROM blob data for the address | ||
39 | + * @as: AddressSpace to look for the ROM blob in | ||
40 | + * @addr: Address within @as | ||
41 | + * @size: size of data required in bytes | ||
42 | + * | ||
43 | + * Returns: pointer into the data which backs the matching ROM blob, | ||
44 | + * or NULL if no blob covers the address range. | ||
45 | + * | ||
46 | + * This function looks for a ROM blob which covers the specified range | ||
47 | + * of bytes of length @size starting at @addr within the address space | ||
48 | + * @as. This is useful for code which runs as part of board | ||
49 | + * initialization or CPU reset which wants to read data that is part | ||
50 | + * of a user-supplied guest image or other guest memory contents, but | ||
51 | + * which runs before the ROM loader's reset function has copied the | ||
52 | + * blobs into guest memory. | ||
53 | + * | ||
54 | + * rom_ptr_for_as() will look not just for blobs loaded directly to | ||
55 | + * the specified address, but also for blobs which were loaded to an | ||
56 | + * alias of the region at a different location in the AddressSpace. | ||
57 | + * In other words, if a machine model has RAM at address 0x0000_0000 | ||
58 | + * which is aliased to also appear at 0x1000_0000, rom_ptr_for_as() | ||
59 | + * will return the correct data whether the guest image was linked and | ||
60 | + * loaded at 0x0000_0000 or 0x1000_0000. Contrast rom_ptr(), which | ||
61 | + * will only return data if the image load address is an exact match | ||
62 | + * with the queried address. | ||
63 | + * | ||
64 | + * New code should prefer to use rom_ptr_for_as() instead of | ||
65 | + * rom_ptr(). | ||
66 | + */ | ||
67 | +void *rom_ptr_for_as(AddressSpace *as, hwaddr addr, size_t size); | ||
68 | void hmp_info_roms(Monitor *mon, const QDict *qdict); | ||
69 | |||
70 | #define rom_add_file_fixed(_f, _a, _i) \ | ||
71 | diff --git a/hw/core/loader.c b/hw/core/loader.c | ||
72 | index XXXXXXX..XXXXXXX 100644 | ||
73 | --- a/hw/core/loader.c | ||
74 | +++ b/hw/core/loader.c | ||
75 | @@ -XXX,XX +XXX,XX @@ void *rom_ptr(hwaddr addr, size_t size) | ||
76 | return rom->data + (addr - rom->addr); | ||
77 | } | ||
78 | |||
79 | +typedef struct FindRomCBData { | ||
80 | + size_t size; /* Amount of data we want from ROM, in bytes */ | ||
81 | + MemoryRegion *mr; /* MR at the unaliased guest addr */ | ||
82 | + hwaddr xlat; /* Offset of addr within mr */ | ||
83 | + void *rom; /* Output: rom data pointer, if found */ | ||
84 | +} FindRomCBData; | ||
85 | + | ||
86 | +static bool find_rom_cb(Int128 start, Int128 len, const MemoryRegion *mr, | ||
87 | + hwaddr offset_in_region, void *opaque) | ||
88 | +{ | ||
89 | + FindRomCBData *cbdata = opaque; | ||
90 | + hwaddr alias_addr; | ||
91 | + | ||
92 | + if (mr != cbdata->mr) { | ||
93 | + return false; | ||
94 | + } | ||
95 | + | ||
96 | + alias_addr = int128_get64(start) + cbdata->xlat - offset_in_region; | ||
97 | + cbdata->rom = rom_ptr(alias_addr, cbdata->size); | ||
98 | + if (!cbdata->rom) { | ||
99 | + return false; | ||
100 | + } | ||
101 | + /* Found a match, stop iterating */ | ||
102 | + return true; | ||
103 | +} | ||
104 | + | ||
105 | +void *rom_ptr_for_as(AddressSpace *as, hwaddr addr, size_t size) | ||
106 | +{ | ||
107 | + /* | ||
108 | + * Find any ROM data for the given guest address range. If there | ||
109 | + * is a ROM blob then return a pointer to the host memory | ||
110 | + * corresponding to 'addr'; otherwise return NULL. | ||
111 | + * | ||
112 | + * We look not only for ROM blobs that were loaded directly to | ||
113 | + * addr, but also for ROM blobs that were loaded to aliases of | ||
114 | + * that memory at other addresses within the AddressSpace. | ||
115 | + * | ||
116 | + * Note that we do not check @as against the 'as' member in the | ||
117 | + * 'struct Rom' returned by rom_ptr(). The Rom::as is the | ||
118 | + * AddressSpace which the rom blob should be written to, whereas | ||
119 | + * our @as argument is the AddressSpace which we are (effectively) | ||
120 | + * reading from, and the same underlying RAM will often be visible | ||
121 | + * in multiple AddressSpaces. (A common example is a ROM blob | ||
122 | + * written to the 'system' address space but then read back via a | ||
123 | + * CPU's cpu->as pointer.) This does mean we might potentially | ||
124 | + * return a false-positive match if a ROM blob was loaded into an | ||
125 | + * AS which is entirely separate and distinct from the one we're | ||
126 | + * querying, but this issue exists also for rom_ptr() and hasn't | ||
127 | + * caused any problems in practice. | ||
128 | + */ | ||
129 | + FlatView *fv; | ||
130 | + void *rom; | ||
131 | + hwaddr len_unused; | ||
132 | + FindRomCBData cbdata = {}; | ||
133 | + | ||
134 | + /* Easy case: there's data at the actual address */ | ||
135 | + rom = rom_ptr(addr, size); | ||
136 | + if (rom) { | ||
137 | + return rom; | ||
138 | + } | ||
139 | + | ||
140 | + RCU_READ_LOCK_GUARD(); | ||
141 | + | ||
142 | + fv = address_space_to_flatview(as); | ||
143 | + cbdata.mr = flatview_translate(fv, addr, &cbdata.xlat, &len_unused, | ||
144 | + false, MEMTXATTRS_UNSPECIFIED); | ||
145 | + if (!cbdata.mr) { | ||
146 | + /* Nothing at this address, so there can't be any aliasing */ | ||
147 | + return NULL; | ||
148 | + } | ||
149 | + cbdata.size = size; | ||
150 | + flatview_for_each_range(fv, find_rom_cb, &cbdata); | ||
151 | + return cbdata.rom; | ||
152 | +} | ||
153 | + | ||
154 | void hmp_info_roms(Monitor *mon, const QDict *qdict) | ||
155 | { | ||
156 | Rom *rom; | ||
157 | -- | ||
158 | 2.20.1 | ||
159 | |||
160 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | For Arm M-profile CPUs, on reset the CPU must load its initial PC and | ||
2 | SP from a vector table in guest memory. Because we can't guarantee | ||
3 | reset ordering, we have to handle the possibility that the ROM blob | ||
4 | loader's reset function has not yet run when the CPU resets, in which | ||
5 | case the data in an ELF file specified by the user won't be in guest | ||
6 | memory to be read yet. | ||
7 | 1 | ||
8 | We work around the reset ordering problem by checking whether the ROM | ||
9 | blob loader has any data for the address where the vector table is, | ||
10 | using rom_ptr(). Unfortunately this does not handle the possibility | ||
11 | of memory aliasing. For many M-profile boards, memory can be | ||
12 | accessed via multiple possible physical addresses; if the board has | ||
13 | the vector table at address X but the user's ELF file loads data via | ||
14 | a different address Y which is an alias to the same underlying guest | ||
15 | RAM then rom_ptr() will not find it. | ||
16 | |||
17 | Use the new rom_ptr_for_as() function, which deals with memory | ||
18 | aliasing when locating a relevant ROM blob. | ||
19 | |||
20 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
21 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
22 | Message-id: 20210318174823.18066-6-peter.maydell@linaro.org | ||
23 | --- | ||
24 | target/arm/cpu.c | 2 +- | ||
25 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
26 | |||
27 | diff --git a/target/arm/cpu.c b/target/arm/cpu.c | ||
28 | index XXXXXXX..XXXXXXX 100644 | ||
29 | --- a/target/arm/cpu.c | ||
30 | +++ b/target/arm/cpu.c | ||
31 | @@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev) | ||
32 | |||
33 | /* Load the initial SP and PC from offset 0 and 4 in the vector table */ | ||
34 | vecbase = env->v7m.vecbase[env->v7m.secure]; | ||
35 | - rom = rom_ptr(vecbase, 8); | ||
36 | + rom = rom_ptr_for_as(s->as, vecbase, 8); | ||
37 | if (rom) { | ||
38 | /* Address zero is covered by ROM which hasn't yet been | ||
39 | * copied into physical memory. | ||
40 | -- | ||
41 | 2.20.1 | ||
42 | |||
43 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | From: Richard Henderson <richard.henderson@linaro.org> | ||
2 | 1 | ||
3 | Pretend the fault always happens at page table level 3. | ||
4 | |||
5 | Failure to set this leaves level = 0, which is impossible for | ||
6 | ARMFault_Permission, and produces an invalid syndrome, which | ||
7 | reaches g_assert_not_reached in cpu_loop. | ||
8 | |||
9 | Fixes: 8db94ab4e5db ("linux-user/aarch64: Pass syndrome to EXC_*_ABORT") | ||
10 | Reported-by: Laurent Vivier <laurent@vivier.eu> | ||
11 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | ||
12 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
13 | Message-id: 20210320000606.1788699-1-richard.henderson@linaro.org | ||
14 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
15 | --- | ||
16 | target/arm/tlb_helper.c | 1 + | ||
17 | 1 file changed, 1 insertion(+) | ||
18 | |||
19 | diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c | ||
20 | index XXXXXXX..XXXXXXX 100644 | ||
21 | --- a/target/arm/tlb_helper.c | ||
22 | +++ b/target/arm/tlb_helper.c | ||
23 | @@ -XXX,XX +XXX,XX @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size, | ||
24 | } else { | ||
25 | fi.type = ARMFault_Translation; | ||
26 | } | ||
27 | + fi.level = 3; | ||
28 | |||
29 | /* now we have a real cpu fault */ | ||
30 | cpu_restore_state(cs, retaddr, true); | ||
31 | -- | ||
32 | 2.20.1 | ||
33 | |||
34 | diff view generated by jsdifflib |