1 | Arm patch queue -- these are all bug fix patches but we might | 1 | target-arm queue for rc1 -- these are all bug fixes. |
---|---|---|---|
2 | as well put them in to rc0... | ||
3 | 2 | ||
4 | thanks | 3 | thanks |
5 | -- PMM | 4 | -- PMM |
6 | 5 | ||
7 | The following changes since commit 2c8cfc0b52b5a4d123c26c0b5fdf941be24805be: | 6 | The following changes since commit b9404bf592e7ba74180e1a54ed7a266ec6ee67f2: |
8 | 7 | ||
9 | Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging (2018-03-19 11:44:26 +0000) | 8 | Merge remote-tracking branch 'remotes/dgilbert/tags/pull-hmp-20190715' into staging (2019-07-15 12:22:07 +0100) |
10 | 9 | ||
11 | are available in the Git repository at: | 10 | are available in the Git repository at: |
12 | 11 | ||
13 | git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180319 | 12 | https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190715 |
14 | 13 | ||
15 | for you to fetch changes up to ff72cb6b46b95bb530787add5277c211af3d31c6: | 14 | for you to fetch changes up to 51c9122e92b776a3f16af0b9282f1dc5012e2a19: |
16 | 15 | ||
17 | hw/arm/raspi: Provide spin-loop code for AArch64 CPUs (2018-03-19 18:23:24 +0000) | 16 | target/arm: NS BusFault on vector table fetch escalates to NS HardFault (2019-07-15 14:17:04 +0100) |
18 | 17 | ||
19 | ---------------------------------------------------------------- | 18 | ---------------------------------------------------------------- |
20 | target-arm queue: | 19 | target-arm queue: |
21 | * fsl-imx6: Fix incorrect Ethernet interrupt defines | 20 | * report ARMv8-A FP support for AArch32 -cpu max |
22 | * dump: Update correct kdump phys_base field for AArch64 | 21 | * hw/ssi/xilinx_spips: Avoid AXI writes to the LQSPI linear memory |
23 | * char: i.MX: Add support for "TX complete" interrupt | 22 | * hw/ssi/xilinx_spips: Avoid out-of-bound access to lqspi_buf[] |
24 | * bcm2836/raspi: Fix various bugs resulting in panics trying | 23 | * hw/ssi/mss-spi: Avoid crash when reading empty RX FIFO |
25 | to boot a Debian Linux kernel on raspi3 | 24 | * hw/display/xlnx_dp: Avoid crash when reading empty RX FIFO |
25 | * hw/arm/virt: Fix non-secure flash mode | ||
26 | * pl031: Correctly migrate state when using -rtc clock=host | ||
27 | * fix regression that meant arm926 and arm1026 lost VFP | ||
28 | double-precision support | ||
29 | * v8M: NS BusFault on vector table fetch escalates to NS HardFault | ||
26 | 30 | ||
27 | ---------------------------------------------------------------- | 31 | ---------------------------------------------------------------- |
28 | Andrey Smirnov (2): | 32 | Alex Bennée (1): |
29 | char: i.MX: Simplify imx_update() | 33 | target/arm: report ARMv8-A FP support for AArch32 -cpu max |
30 | char: i.MX: Add support for "TX complete" interrupt | ||
31 | 34 | ||
32 | Guenter Roeck (1): | 35 | David Engraf (1): |
33 | fsl-imx6: Swap Ethernet interrupt defines | 36 | hw/arm/virt: Fix non-secure flash mode |
34 | 37 | ||
35 | Peter Maydell (9): | 38 | Peter Maydell (3): |
36 | hw/arm/raspi: Don't do board-setup or secure-boot for raspi3 | 39 | pl031: Correctly migrate state when using -rtc clock=host |
37 | hw/arm/boot: assert that secure_boot and secure_board_setup are false for AArch64 | 40 | target/arm: Set VFP-related MVFR0 fields for arm926 and arm1026 |
38 | hw/arm/boot: If booting a kernel in EL2, set SCR_EL3.HCE | 41 | target/arm: NS BusFault on vector table fetch escalates to NS HardFault |
39 | hw/arm/bcm2386: Fix parent type of bcm2386 | ||
40 | hw/arm/bcm2836: Rename bcm2836 type/struct to bcm283x | ||
41 | hw/arm/bcm2836: Create proper bcm2837 device | ||
42 | hw/arm/bcm2836: Use correct affinity values for BCM2837 | ||
43 | hw/arm/bcm2836: Hardcode correct CPU type | ||
44 | hw/arm/raspi: Provide spin-loop code for AArch64 CPUs | ||
45 | 42 | ||
46 | Wei Huang (1): | 43 | Philippe Mathieu-Daudé (5): |
47 | dump: Update correct kdump phys_base field for AArch64 | 44 | hw/ssi/xilinx_spips: Convert lqspi_read() to read_with_attrs |
45 | hw/ssi/xilinx_spips: Avoid AXI writes to the LQSPI linear memory | ||
46 | hw/ssi/xilinx_spips: Avoid out-of-bound access to lqspi_buf[] | ||
47 | hw/ssi/mss-spi: Avoid crash when reading empty RX FIFO | ||
48 | hw/display/xlnx_dp: Avoid crash when reading empty RX FIFO | ||
48 | 49 | ||
49 | include/hw/arm/bcm2836.h | 31 +++++++++++++--- | 50 | include/hw/timer/pl031.h | 2 ++ |
50 | include/hw/arm/fsl-imx6.h | 4 +- | 51 | hw/arm/virt.c | 2 +- |
51 | include/hw/char/imx_serial.h | 3 ++ | 52 | hw/core/machine.c | 1 + |
52 | dump.c | 14 +++++-- | 53 | hw/display/xlnx_dp.c | 15 +++++--- |
53 | hw/arm/bcm2836.c | 87 +++++++++++++++++++++++++++++++------------- | 54 | hw/ssi/mss-spi.c | 8 ++++- |
54 | hw/arm/boot.c | 12 ++++++ | 55 | hw/ssi/xilinx_spips.c | 43 +++++++++++++++------- |
55 | hw/arm/raspi.c | 77 +++++++++++++++++++++++++++++++-------- | 56 | hw/timer/pl031.c | 92 +++++++++++++++++++++++++++++++++++++++++++++--- |
56 | hw/char/imx_serial.c | 44 ++++++++++++++++------ | 57 | target/arm/cpu.c | 16 +++++++++ |
57 | hw/net/imx_fec.c | 28 +++++++++++++- | 58 | target/arm/m_helper.c | 21 ++++++++--- |
58 | 9 files changed, 237 insertions(+), 63 deletions(-) | 59 | 9 files changed, 174 insertions(+), 26 deletions(-) |
59 | 60 | diff view generated by jsdifflib |
1 | The BCM2837 sets the Aff1 field of the MPIDR affinity values for the | 1 | From: Alex Bennée <alex.bennee@linaro.org> |
---|---|---|---|
2 | CPUs to 0, whereas the BCM2836 uses 0xf. Set this correctly, as it | ||
3 | is required for Linux to boot. | ||
4 | 2 | ||
3 | When we converted to using feature bits in 602f6e42cfbf we missed out | ||
4 | the fact (dp && arm_dc_feature(s, ARM_FEATURE_V8)) was supported for | ||
5 | -cpu max configurations. This caused a regression in the GCC test | ||
6 | suite. Fix this by setting the appropriate bits in mvfr1.FPHP to | ||
7 | report ARMv8-A with FP support (but not ARMv8.2-FP16). | ||
8 | |||
9 | Fixes: https://bugs.launchpad.net/qemu/+bug/1836078 | ||
10 | Signed-off-by: Alex Bennée <alex.bennee@linaro.org> | ||
11 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
12 | Message-id: 20190711103737.10017-1-alex.bennee@linaro.org | ||
5 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 13 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
6 | Reviewed-by: Andrew Baumann <Andrew.Baumann@microsoft.com> | ||
7 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
8 | Message-id: 20180313153458.26822-8-peter.maydell@linaro.org | ||
9 | --- | 14 | --- |
10 | hw/arm/bcm2836.c | 11 +++++++---- | 15 | target/arm/cpu.c | 4 ++++ |
11 | 1 file changed, 7 insertions(+), 4 deletions(-) | 16 | 1 file changed, 4 insertions(+) |
12 | 17 | ||
13 | diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c | 18 | diff --git a/target/arm/cpu.c b/target/arm/cpu.c |
14 | index XXXXXXX..XXXXXXX 100644 | 19 | index XXXXXXX..XXXXXXX 100644 |
15 | --- a/hw/arm/bcm2836.c | 20 | --- a/target/arm/cpu.c |
16 | +++ b/hw/arm/bcm2836.c | 21 | +++ b/target/arm/cpu.c |
17 | @@ -XXX,XX +XXX,XX @@ | 22 | @@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj) |
18 | 23 | t = FIELD_DP32(t, ID_ISAR6, SPECRES, 1); | |
19 | struct BCM283XInfo { | 24 | cpu->isar.id_isar6 = t; |
20 | const char *name; | 25 | |
21 | + int clusterid; | 26 | + t = cpu->isar.mvfr1; |
22 | }; | 27 | + t = FIELD_DP32(t, MVFR1, FPHP, 2); /* v8.0 FP support */ |
23 | 28 | + cpu->isar.mvfr1 = t; | |
24 | static const BCM283XInfo bcm283x_socs[] = { | 29 | + |
25 | { | 30 | t = cpu->isar.mvfr2; |
26 | .name = TYPE_BCM2836, | 31 | t = FIELD_DP32(t, MVFR2, SIMDMISC, 3); /* SIMD MaxNum */ |
27 | + .clusterid = 0xf, | 32 | t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */ |
28 | }, | ||
29 | { | ||
30 | .name = TYPE_BCM2837, | ||
31 | + .clusterid = 0x0, | ||
32 | }, | ||
33 | }; | ||
34 | |||
35 | @@ -XXX,XX +XXX,XX @@ static void bcm2836_init(Object *obj) | ||
36 | static void bcm2836_realize(DeviceState *dev, Error **errp) | ||
37 | { | ||
38 | BCM283XState *s = BCM283X(dev); | ||
39 | + BCM283XClass *bc = BCM283X_GET_CLASS(dev); | ||
40 | + const BCM283XInfo *info = bc->info; | ||
41 | Object *obj; | ||
42 | Error *err = NULL; | ||
43 | int n; | ||
44 | @@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp) | ||
45 | qdev_get_gpio_in_named(DEVICE(&s->control), "gpu-fiq", 0)); | ||
46 | |||
47 | for (n = 0; n < BCM283X_NCPUS; n++) { | ||
48 | - /* Mirror bcm2836, which has clusterid set to 0xf | ||
49 | - * TODO: this should be converted to a property of ARM_CPU | ||
50 | - */ | ||
51 | - s->cpus[n].mp_affinity = 0xF00 | n; | ||
52 | + /* TODO: this should be converted to a property of ARM_CPU */ | ||
53 | + s->cpus[n].mp_affinity = (info->clusterid << 8) | n; | ||
54 | |||
55 | /* set periphbase/CBAR value for CPU-local registers */ | ||
56 | object_property_set_int(OBJECT(&s->cpus[n]), | ||
57 | -- | 33 | -- |
58 | 2.16.2 | 34 | 2.20.1 |
59 | 35 | ||
60 | 36 | diff view generated by jsdifflib |
1 | Now we have separate types for BCM2386 and BCM2387, we might as well | 1 | From: Philippe Mathieu-Daudé <philmd@redhat.com> |
---|---|---|---|
2 | just hard-code the CPU type they use rather than having it passed | ||
3 | through as an object property. This then lets us put the initialization | ||
4 | of the CPU object in init rather than realize. | ||
5 | 2 | ||
6 | Note that this change means that it's no longer possible on | 3 | In the next commit we will implement the write_with_attrs() |
7 | the command line to use -cpu to ask for a different kind of | 4 | handler. To avoid using different APIs, convert the read() |
8 | CPU than the SoC supports. This was never a supported thing to | 5 | handler first. |
9 | do anyway; we were just not sanity-checking the command line. | ||
10 | 6 | ||
11 | This does require us to only build the bcm2837 object on | 7 | Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com> |
12 | TARGET_AARCH64 configs, since otherwise it won't instantiate | 8 | Tested-by: Francisco Iglesias <frasse.iglesias@gmail.com> |
13 | due to the missing cortex-a53 device and "make check" will fail. | 9 | Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> |
10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
11 | --- | ||
12 | hw/ssi/xilinx_spips.c | 23 +++++++++++------------ | ||
13 | 1 file changed, 11 insertions(+), 12 deletions(-) | ||
14 | 14 | ||
15 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 15 | diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c |
16 | Reviewed-by: Andrew Baumann <Andrew.Baumann@microsoft.com> | ||
17 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
18 | Message-id: 20180313153458.26822-9-peter.maydell@linaro.org | ||
19 | --- | ||
20 | hw/arm/bcm2836.c | 24 +++++++++++++++--------- | ||
21 | hw/arm/raspi.c | 2 -- | ||
22 | 2 files changed, 15 insertions(+), 11 deletions(-) | ||
23 | |||
24 | diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c | ||
25 | index XXXXXXX..XXXXXXX 100644 | 16 | index XXXXXXX..XXXXXXX 100644 |
26 | --- a/hw/arm/bcm2836.c | 17 | --- a/hw/ssi/xilinx_spips.c |
27 | +++ b/hw/arm/bcm2836.c | 18 | +++ b/hw/ssi/xilinx_spips.c |
28 | @@ -XXX,XX +XXX,XX @@ | 19 | @@ -XXX,XX +XXX,XX @@ static void lqspi_load_cache(void *opaque, hwaddr addr) |
29 | 20 | } | |
30 | struct BCM283XInfo { | 21 | } |
31 | const char *name; | 22 | |
32 | + const char *cpu_type; | 23 | -static uint64_t |
33 | int clusterid; | 24 | -lqspi_read(void *opaque, hwaddr addr, unsigned int size) |
34 | }; | 25 | +static MemTxResult lqspi_read(void *opaque, hwaddr addr, uint64_t *value, |
35 | 26 | + unsigned size, MemTxAttrs attrs) | |
36 | static const BCM283XInfo bcm283x_socs[] = { | ||
37 | { | ||
38 | .name = TYPE_BCM2836, | ||
39 | + .cpu_type = ARM_CPU_TYPE_NAME("cortex-a15"), | ||
40 | .clusterid = 0xf, | ||
41 | }, | ||
42 | +#ifdef TARGET_AARCH64 | ||
43 | { | ||
44 | .name = TYPE_BCM2837, | ||
45 | + .cpu_type = ARM_CPU_TYPE_NAME("cortex-a53"), | ||
46 | .clusterid = 0x0, | ||
47 | }, | ||
48 | +#endif | ||
49 | }; | ||
50 | |||
51 | static void bcm2836_init(Object *obj) | ||
52 | { | 27 | { |
53 | BCM283XState *s = BCM283X(obj); | 28 | - XilinxQSPIPS *q = opaque; |
54 | + BCM283XClass *bc = BCM283X_GET_CLASS(obj); | 29 | - uint32_t ret; |
55 | + const BCM283XInfo *info = bc->info; | 30 | + XilinxQSPIPS *q = XILINX_QSPIPS(opaque); |
56 | + int n; | 31 | |
32 | if (addr >= q->lqspi_cached_addr && | ||
33 | addr <= q->lqspi_cached_addr + LQSPI_CACHE_SIZE - 4) { | ||
34 | uint8_t *retp = &q->lqspi_buf[addr - q->lqspi_cached_addr]; | ||
35 | - ret = cpu_to_le32(*(uint32_t *)retp); | ||
36 | - DB_PRINT_L(1, "addr: %08x, data: %08x\n", (unsigned)addr, | ||
37 | - (unsigned)ret); | ||
38 | - return ret; | ||
39 | - } else { | ||
40 | - lqspi_load_cache(opaque, addr); | ||
41 | - return lqspi_read(opaque, addr, size); | ||
42 | + *value = cpu_to_le32(*(uint32_t *)retp); | ||
43 | + DB_PRINT_L(1, "addr: %08" HWADDR_PRIx ", data: %08" PRIx64 "\n", | ||
44 | + addr, *value); | ||
45 | + return MEMTX_OK; | ||
46 | } | ||
57 | + | 47 | + |
58 | + for (n = 0; n < BCM283X_NCPUS; n++) { | 48 | + lqspi_load_cache(opaque, addr); |
59 | + object_initialize(&s->cpus[n], sizeof(s->cpus[n]), | 49 | + return lqspi_read(opaque, addr, value, size, attrs); |
60 | + info->cpu_type); | ||
61 | + object_property_add_child(obj, "cpu[*]", OBJECT(&s->cpus[n]), | ||
62 | + &error_abort); | ||
63 | + } | ||
64 | |||
65 | object_initialize(&s->control, sizeof(s->control), TYPE_BCM2836_CONTROL); | ||
66 | object_property_add_child(obj, "control", OBJECT(&s->control), NULL); | ||
67 | @@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp) | ||
68 | |||
69 | /* common peripherals from bcm2835 */ | ||
70 | |||
71 | - obj = OBJECT(dev); | ||
72 | - for (n = 0; n < BCM283X_NCPUS; n++) { | ||
73 | - object_initialize(&s->cpus[n], sizeof(s->cpus[n]), | ||
74 | - s->cpu_type); | ||
75 | - object_property_add_child(obj, "cpu[*]", OBJECT(&s->cpus[n]), | ||
76 | - &error_abort); | ||
77 | - } | ||
78 | - | ||
79 | obj = object_property_get_link(OBJECT(dev), "ram", &err); | ||
80 | if (obj == NULL) { | ||
81 | error_setg(errp, "%s: required ram link not found: %s", | ||
82 | @@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp) | ||
83 | } | 50 | } |
84 | 51 | ||
85 | static Property bcm2836_props[] = { | 52 | static const MemoryRegionOps lqspi_ops = { |
86 | - DEFINE_PROP_STRING("cpu-type", BCM283XState, cpu_type), | 53 | - .read = lqspi_read, |
87 | DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus, | 54 | + .read_with_attrs = lqspi_read, |
88 | BCM283X_NCPUS), | 55 | .endianness = DEVICE_NATIVE_ENDIAN, |
89 | DEFINE_PROP_END_OF_LIST() | 56 | .valid = { |
90 | diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c | 57 | .min_access_size = 1, |
91 | index XXXXXXX..XXXXXXX 100644 | ||
92 | --- a/hw/arm/raspi.c | ||
93 | +++ b/hw/arm/raspi.c | ||
94 | @@ -XXX,XX +XXX,XX @@ static void raspi_init(MachineState *machine, int version) | ||
95 | /* Setup the SOC */ | ||
96 | object_property_add_const_link(OBJECT(&s->soc), "ram", OBJECT(&s->ram), | ||
97 | &error_abort); | ||
98 | - object_property_set_str(OBJECT(&s->soc), machine->cpu_type, "cpu-type", | ||
99 | - &error_abort); | ||
100 | object_property_set_int(OBJECT(&s->soc), smp_cpus, "enabled-cpus", | ||
101 | &error_abort); | ||
102 | int board_rev = version == 3 ? 0xa02082 : 0xa21041; | ||
103 | -- | 58 | -- |
104 | 2.16.2 | 59 | 2.20.1 |
105 | 60 | ||
106 | 61 | diff view generated by jsdifflib |
1 | The raspi3 has AArch64 CPUs, which means that our smpboot | 1 | From: Philippe Mathieu-Daudé <philmd@redhat.com> |
---|---|---|---|
2 | code for keeping the secondary CPUs in a pen needs to have | ||
3 | a version for A64 as well as A32. Without this, the | ||
4 | secondary CPUs go into an infinite loop of taking undefined | ||
5 | instruction exceptions. | ||
6 | 2 | ||
3 | Lei Sun found while auditing the code that a CPU write would | ||
4 | trigger a NULL pointer dereference. | ||
5 | |||
6 | >From UG1085 datasheet [*] AXI writes in this region are ignored | ||
7 | and generates an AXI Slave Error (SLVERR). | ||
8 | |||
9 | Fix by implementing the write_with_attrs() handler. | ||
10 | Return MEMTX_ERROR when the region is accessed (this error maps | ||
11 | to an AXI slave error). | ||
12 | |||
13 | [*] https://www.xilinx.com/support/documentation/user_guides/ug1085-zynq-ultrascale-trm.pdf | ||
14 | |||
15 | Reported-by: Lei Sun <slei.casper@gmail.com> | ||
16 | Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com> | ||
17 | Tested-by: Francisco Iglesias <frasse.iglesias@gmail.com> | ||
18 | Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
7 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 19 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
8 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
9 | Message-id: 20180313153458.26822-10-peter.maydell@linaro.org | ||
10 | --- | 20 | --- |
11 | hw/arm/raspi.c | 41 ++++++++++++++++++++++++++++++++++++++++- | 21 | hw/ssi/xilinx_spips.c | 16 ++++++++++++++++ |
12 | 1 file changed, 40 insertions(+), 1 deletion(-) | 22 | 1 file changed, 16 insertions(+) |
13 | 23 | ||
14 | diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c | 24 | diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c |
15 | index XXXXXXX..XXXXXXX 100644 | 25 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/hw/arm/raspi.c | 26 | --- a/hw/ssi/xilinx_spips.c |
17 | +++ b/hw/arm/raspi.c | 27 | +++ b/hw/ssi/xilinx_spips.c |
18 | @@ -XXX,XX +XXX,XX @@ | 28 | @@ -XXX,XX +XXX,XX @@ static MemTxResult lqspi_read(void *opaque, hwaddr addr, uint64_t *value, |
19 | #define BOARDSETUP_ADDR (MVBAR_ADDR + 0x20) /* board setup code */ | 29 | return lqspi_read(opaque, addr, value, size, attrs); |
20 | #define FIRMWARE_ADDR_2 0x8000 /* Pi 2 loads kernel.img here by default */ | ||
21 | #define FIRMWARE_ADDR_3 0x80000 /* Pi 3 loads kernel.img here by default */ | ||
22 | +#define SPINTABLE_ADDR 0xd8 /* Pi 3 bootloader spintable */ | ||
23 | |||
24 | /* Table of Linux board IDs for different Pi versions */ | ||
25 | static const int raspi_boardid[] = {[1] = 0xc42, [2] = 0xc43, [3] = 0xc44}; | ||
26 | @@ -XXX,XX +XXX,XX @@ static void write_smpboot(ARMCPU *cpu, const struct arm_boot_info *info) | ||
27 | info->smp_loader_start); | ||
28 | } | 30 | } |
29 | 31 | ||
30 | +static void write_smpboot64(ARMCPU *cpu, const struct arm_boot_info *info) | 32 | +static MemTxResult lqspi_write(void *opaque, hwaddr offset, uint64_t value, |
33 | + unsigned size, MemTxAttrs attrs) | ||
31 | +{ | 34 | +{ |
32 | + /* Unlike the AArch32 version we don't need to call the board setup hook. | 35 | + /* |
33 | + * The mechanism for doing the spin-table is also entirely different. | 36 | + * From UG1085, Chapter 24 (Quad-SPI controllers): |
34 | + * We must have four 64-bit fields at absolute addresses | 37 | + * - Writes are ignored |
35 | + * 0xd8, 0xe0, 0xe8, 0xf0 in RAM, which are the flag variables for | 38 | + * - AXI writes generate an external AXI slave error (SLVERR) |
36 | + * our CPUs, and which we must ensure are zero initialized before | ||
37 | + * the primary CPU goes into the kernel. We put these variables inside | ||
38 | + * a rom blob, so that the reset for ROM contents zeroes them for us. | ||
39 | + */ | 39 | + */ |
40 | + static const uint32_t smpboot[] = { | 40 | + qemu_log_mask(LOG_GUEST_ERROR, "%s Unexpected %u-bit access to 0x%" PRIx64 |
41 | + 0xd2801b05, /* mov x5, 0xd8 */ | 41 | + " (value: 0x%" PRIx64 "\n", |
42 | + 0xd53800a6, /* mrs x6, mpidr_el1 */ | 42 | + __func__, size << 3, offset, value); |
43 | + 0x924004c6, /* and x6, x6, #0x3 */ | ||
44 | + 0xd503205f, /* spin: wfe */ | ||
45 | + 0xf86678a4, /* ldr x4, [x5,x6,lsl #3] */ | ||
46 | + 0xb4ffffc4, /* cbz x4, spin */ | ||
47 | + 0xd2800000, /* mov x0, #0x0 */ | ||
48 | + 0xd2800001, /* mov x1, #0x0 */ | ||
49 | + 0xd2800002, /* mov x2, #0x0 */ | ||
50 | + 0xd2800003, /* mov x3, #0x0 */ | ||
51 | + 0xd61f0080, /* br x4 */ | ||
52 | + }; | ||
53 | + | 43 | + |
54 | + static const uint64_t spintables[] = { | 44 | + return MEMTX_ERROR; |
55 | + 0, 0, 0, 0 | ||
56 | + }; | ||
57 | + | ||
58 | + rom_add_blob_fixed("raspi_smpboot", smpboot, sizeof(smpboot), | ||
59 | + info->smp_loader_start); | ||
60 | + rom_add_blob_fixed("raspi_spintables", spintables, sizeof(spintables), | ||
61 | + SPINTABLE_ADDR); | ||
62 | +} | 45 | +} |
63 | + | 46 | + |
64 | static void write_board_setup(ARMCPU *cpu, const struct arm_boot_info *info) | 47 | static const MemoryRegionOps lqspi_ops = { |
65 | { | 48 | .read_with_attrs = lqspi_read, |
66 | arm_write_secure_board_setup_dummy_smc(cpu, info, MVBAR_ADDR); | 49 | + .write_with_attrs = lqspi_write, |
67 | @@ -XXX,XX +XXX,XX @@ static void setup_boot(MachineState *machine, int version, size_t ram_size) | 50 | .endianness = DEVICE_NATIVE_ENDIAN, |
68 | /* Pi2 and Pi3 requires SMP setup */ | 51 | .valid = { |
69 | if (version >= 2) { | 52 | .min_access_size = 1, |
70 | binfo.smp_loader_start = SMPBOOT_ADDR; | ||
71 | - binfo.write_secondary_boot = write_smpboot; | ||
72 | + if (version == 2) { | ||
73 | + binfo.write_secondary_boot = write_smpboot; | ||
74 | + } else { | ||
75 | + binfo.write_secondary_boot = write_smpboot64; | ||
76 | + } | ||
77 | binfo.secondary_cpu_reset_hook = reset_secondary; | ||
78 | } | ||
79 | |||
80 | -- | 53 | -- |
81 | 2.16.2 | 54 | 2.20.1 |
82 | 55 | ||
83 | 56 | diff view generated by jsdifflib |
1 | From: Wei Huang <wei@redhat.com> | 1 | From: Philippe Mathieu-Daudé <philmd@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | For guest kernel that supports KASLR, the load address can change every | 3 | Both lqspi_read() and lqspi_load_cache() expect a 32-bit |
4 | time when guest VM runs. To find the physical base address correctly, | 4 | aligned address. |
5 | current QEMU dump searches VMCOREINFO for the string "NUMBER(phys_base)=". | ||
6 | However this string pattern is only available on x86_64. AArch64 uses a | ||
7 | different field, called "NUMBER(PHYS_OFFSET)=". This patch makes sure | ||
8 | QEMU dump uses the correct string on AArch64. | ||
9 | 5 | ||
10 | Signed-off-by: Wei Huang <wei@redhat.com> | 6 | >From UG1085 datasheet [*] chapter on 'Quad-SPI Controller': |
11 | Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> | 7 | |
12 | Message-id: 1520615003-20869-1-git-send-email-wei@redhat.com | 8 | Transfer Size Limitations |
9 | |||
10 | Because of the 32-bit wide TX, RX, and generic FIFO, all | ||
11 | APB/AXI transfers must be an integer multiple of 4-bytes. | ||
12 | Shorter transfers are not possible. | ||
13 | |||
14 | Set MemoryRegionOps.impl values to force 32-bit accesses, | ||
15 | this way we are sure we do not access the lqspi_buf[] array | ||
16 | out of bound. | ||
17 | |||
18 | [*] https://www.xilinx.com/support/documentation/user_guides/ug1085-zynq-ultrascale-trm.pdf | ||
19 | |||
20 | Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com> | ||
21 | Tested-by: Francisco Iglesias <frasse.iglesias@gmail.com> | ||
22 | Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||
13 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 23 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
14 | --- | 24 | --- |
15 | dump.c | 14 +++++++++++--- | 25 | hw/ssi/xilinx_spips.c | 4 ++++ |
16 | 1 file changed, 11 insertions(+), 3 deletions(-) | 26 | 1 file changed, 4 insertions(+) |
17 | 27 | ||
18 | diff --git a/dump.c b/dump.c | 28 | diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c |
19 | index XXXXXXX..XXXXXXX 100644 | 29 | index XXXXXXX..XXXXXXX 100644 |
20 | --- a/dump.c | 30 | --- a/hw/ssi/xilinx_spips.c |
21 | +++ b/dump.c | 31 | +++ b/hw/ssi/xilinx_spips.c |
22 | @@ -XXX,XX +XXX,XX @@ static void vmcoreinfo_update_phys_base(DumpState *s) | 32 | @@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps lqspi_ops = { |
23 | 33 | .read_with_attrs = lqspi_read, | |
24 | lines = g_strsplit((char *)vmci, "\n", -1); | 34 | .write_with_attrs = lqspi_write, |
25 | for (i = 0; lines[i]; i++) { | 35 | .endianness = DEVICE_NATIVE_ENDIAN, |
26 | - if (g_str_has_prefix(lines[i], "NUMBER(phys_base)=")) { | 36 | + .impl = { |
27 | - if (qemu_strtou64(lines[i] + 18, NULL, 16, | 37 | + .min_access_size = 4, |
28 | + const char *prefix = NULL; | 38 | + .max_access_size = 4, |
29 | + | 39 | + }, |
30 | + if (s->dump_info.d_machine == EM_X86_64) { | 40 | .valid = { |
31 | + prefix = "NUMBER(phys_base)="; | 41 | .min_access_size = 1, |
32 | + } else if (s->dump_info.d_machine == EM_AARCH64) { | 42 | .max_access_size = 4 |
33 | + prefix = "NUMBER(PHYS_OFFSET)="; | ||
34 | + } | ||
35 | + | ||
36 | + if (prefix && g_str_has_prefix(lines[i], prefix)) { | ||
37 | + if (qemu_strtou64(lines[i] + strlen(prefix), NULL, 16, | ||
38 | &phys_base) < 0) { | ||
39 | - warn_report("Failed to read NUMBER(phys_base)="); | ||
40 | + warn_report("Failed to read %s", prefix); | ||
41 | } else { | ||
42 | s->dump_info.phys_base = phys_base; | ||
43 | } | ||
44 | -- | 43 | -- |
45 | 2.16.2 | 44 | 2.20.1 |
46 | 45 | ||
47 | 46 | diff view generated by jsdifflib |
1 | From: Guenter Roeck <linux@roeck-us.net> | 1 | From: Philippe Mathieu-Daudé <philmd@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | The sabrelite machine model used by qemu-system-arm is based on the | 3 | Reading the RX_DATA register when the RX_FIFO is empty triggers |
4 | Freescale/NXP i.MX6Q processor. This SoC has an on-board ethernet | 4 | an abort. This can be easily reproduced: |
5 | controller which is supported in QEMU using the imx_fec.c module | ||
6 | (actually called imx.enet for this model.) | ||
7 | 5 | ||
8 | The include/hw/arm/fsm-imx6.h file defines the interrupt vectors for the | 6 | $ qemu-system-arm -M emcraft-sf2 -monitor stdio -S |
9 | imx.enet device like this: | 7 | QEMU 4.0.50 monitor - type 'help' for more information |
8 | (qemu) x 0x40001010 | ||
9 | Aborted (core dumped) | ||
10 | 10 | ||
11 | #define FSL_IMX6_ENET_MAC_1588_IRQ 118 | 11 | (gdb) bt |
12 | #define FSL_IMX6_ENET_MAC_IRQ 119 | 12 | #1 0x00007f035874f895 in abort () at /lib64/libc.so.6 |
13 | #2 0x00005628686591ff in fifo8_pop (fifo=0x56286a9a4c68) at util/fifo8.c:66 | ||
14 | #3 0x00005628683e0b8e in fifo32_pop (fifo=0x56286a9a4c68) at include/qemu/fifo32.h:137 | ||
15 | #4 0x00005628683e0efb in spi_read (opaque=0x56286a9a4850, addr=4, size=4) at hw/ssi/mss-spi.c:168 | ||
16 | #5 0x0000562867f96801 in memory_region_read_accessor (mr=0x56286a9a4b60, addr=16, value=0x7ffeecb0c5c8, size=4, shift=0, mask=4294967295, attrs=...) at memory.c:439 | ||
17 | #6 0x0000562867f96cdb in access_with_adjusted_size (addr=16, value=0x7ffeecb0c5c8, size=4, access_size_min=1, access_size_max=4, access_fn=0x562867f967c3 <memory_region_read_accessor>, mr=0x56286a9a4b60, attrs=...) at memory.c:569 | ||
18 | #7 0x0000562867f99940 in memory_region_dispatch_read1 (mr=0x56286a9a4b60, addr=16, pval=0x7ffeecb0c5c8, size=4, attrs=...) at memory.c:1420 | ||
19 | #8 0x0000562867f99a08 in memory_region_dispatch_read (mr=0x56286a9a4b60, addr=16, pval=0x7ffeecb0c5c8, size=4, attrs=...) at memory.c:1447 | ||
20 | #9 0x0000562867f38721 in flatview_read_continue (fv=0x56286aec6360, addr=1073745936, attrs=..., buf=0x7ffeecb0c7c0 "\340ǰ\354\376\177", len=4, addr1=16, l=4, mr=0x56286a9a4b60) at exec.c:3385 | ||
21 | #10 0x0000562867f38874 in flatview_read (fv=0x56286aec6360, addr=1073745936, attrs=..., buf=0x7ffeecb0c7c0 "\340ǰ\354\376\177", len=4) at exec.c:3423 | ||
22 | #11 0x0000562867f388ea in address_space_read_full (as=0x56286aa3e890, addr=1073745936, attrs=..., buf=0x7ffeecb0c7c0 "\340ǰ\354\376\177", len=4) at exec.c:3436 | ||
23 | #12 0x0000562867f389c5 in address_space_rw (as=0x56286aa3e890, addr=1073745936, attrs=..., buf=0x7ffeecb0c7c0 "\340ǰ\354\376\177", len=4, is_write=false) at exec.c:3466 | ||
24 | #13 0x0000562867f3bdd7 in cpu_memory_rw_debug (cpu=0x56286aa19d00, addr=1073745936, buf=0x7ffeecb0c7c0 "\340ǰ\354\376\177", len=4, is_write=0) at exec.c:3976 | ||
25 | #14 0x000056286811ed51 in memory_dump (mon=0x56286a8c32d0, count=1, format=120, wsize=4, addr=1073745936, is_physical=0) at monitor/misc.c:730 | ||
26 | #15 0x000056286811eff1 in hmp_memory_dump (mon=0x56286a8c32d0, qdict=0x56286b15c400) at monitor/misc.c:785 | ||
27 | #16 0x00005628684740ee in handle_hmp_command (mon=0x56286a8c32d0, cmdline=0x56286a8caeb2 "0x40001010") at monitor/hmp.c:1082 | ||
13 | 28 | ||
14 | According to https://www.nxp.com/docs/en/reference-manual/IMX6DQRM.pdf, | 29 | From the datasheet "Actel SmartFusion Microcontroller Subsystem |
15 | page 225, in Table 3-1. ARM Cortex A9 domain interrupt summary, | 30 | User's Guide" Rev.1, Table 13-3 "SPI Register Summary", this |
16 | interrupts are as follows. | 31 | register has a reset value of 0. |
17 | 32 | ||
18 | 150 ENET MAC 0 IRQ | 33 | Check the FIFO is not empty before accessing it, else log an |
19 | 151 ENET MAC 0 1588 Timer interrupt | 34 | error message. |
20 | 35 | ||
21 | where | 36 | Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> |
22 | 37 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> | |
23 | 150 - 32 == 118 | 38 | Message-id: 20190709113715.7761-3-philmd@redhat.com |
24 | 151 - 32 == 119 | ||
25 | |||
26 | In other words, the vector definitions in the fsl-imx6.h file are reversed. | ||
27 | |||
28 | Fixing the interrupts alone causes problems with older Linux kernels: | ||
29 | The Ethernet interface will fail to probe with Linux v4.9 and earlier. | ||
30 | Linux v4.1 and earlier will crash due to a bug in Ethernet driver probe | ||
31 | error handling. This is a Linux kernel problem, not a qemu problem: | ||
32 | the Linux kernel only worked by accident since it requested both interrupts. | ||
33 | |||
34 | For backward compatibility, generate the Ethernet interrupt on both interrupt | ||
35 | lines. This was shown to work from all Linux kernel releases starting with | ||
36 | v3.16. | ||
37 | |||
38 | Link: https://bugs.launchpad.net/qemu/+bug/1753309 | ||
39 | Signed-off-by: Guenter Roeck <linux@roeck-us.net> | ||
40 | Message-id: 1520723090-22130-1-git-send-email-linux@roeck-us.net | ||
41 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
42 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 39 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
43 | --- | 40 | --- |
44 | include/hw/arm/fsl-imx6.h | 4 ++-- | 41 | hw/ssi/mss-spi.c | 8 +++++++- |
45 | hw/net/imx_fec.c | 28 +++++++++++++++++++++++++++- | 42 | 1 file changed, 7 insertions(+), 1 deletion(-) |
46 | 2 files changed, 29 insertions(+), 3 deletions(-) | ||
47 | 43 | ||
48 | diff --git a/include/hw/arm/fsl-imx6.h b/include/hw/arm/fsl-imx6.h | 44 | diff --git a/hw/ssi/mss-spi.c b/hw/ssi/mss-spi.c |
49 | index XXXXXXX..XXXXXXX 100644 | 45 | index XXXXXXX..XXXXXXX 100644 |
50 | --- a/include/hw/arm/fsl-imx6.h | 46 | --- a/hw/ssi/mss-spi.c |
51 | +++ b/include/hw/arm/fsl-imx6.h | 47 | +++ b/hw/ssi/mss-spi.c |
52 | @@ -XXX,XX +XXX,XX @@ typedef struct FslIMX6State { | 48 | @@ -XXX,XX +XXX,XX @@ spi_read(void *opaque, hwaddr addr, unsigned int size) |
53 | #define FSL_IMX6_HDMI_MASTER_IRQ 115 | 49 | case R_SPI_RX: |
54 | #define FSL_IMX6_HDMI_CEC_IRQ 116 | 50 | s->regs[R_SPI_STATUS] &= ~S_RXFIFOFUL; |
55 | #define FSL_IMX6_MLB150_LOW_IRQ 117 | 51 | s->regs[R_SPI_STATUS] &= ~S_RXCHOVRF; |
56 | -#define FSL_IMX6_ENET_MAC_1588_IRQ 118 | 52 | - ret = fifo32_pop(&s->rx_fifo); |
57 | -#define FSL_IMX6_ENET_MAC_IRQ 119 | 53 | + if (fifo32_is_empty(&s->rx_fifo)) { |
58 | +#define FSL_IMX6_ENET_MAC_IRQ 118 | 54 | + qemu_log_mask(LOG_GUEST_ERROR, |
59 | +#define FSL_IMX6_ENET_MAC_1588_IRQ 119 | 55 | + "%s: Reading empty RX_FIFO\n", |
60 | #define FSL_IMX6_PCIE1_IRQ 120 | 56 | + __func__); |
61 | #define FSL_IMX6_PCIE2_IRQ 121 | 57 | + } else { |
62 | #define FSL_IMX6_PCIE3_IRQ 122 | 58 | + ret = fifo32_pop(&s->rx_fifo); |
63 | diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c | 59 | + } |
64 | index XXXXXXX..XXXXXXX 100644 | 60 | if (fifo32_is_empty(&s->rx_fifo)) { |
65 | --- a/hw/net/imx_fec.c | 61 | s->regs[R_SPI_STATUS] |= S_RXFIFOEMP; |
66 | +++ b/hw/net/imx_fec.c | 62 | } |
67 | @@ -XXX,XX +XXX,XX @@ static void imx_enet_write_bd(IMXENETBufDesc *bd, dma_addr_t addr) | ||
68 | |||
69 | static void imx_eth_update(IMXFECState *s) | ||
70 | { | ||
71 | - if (s->regs[ENET_EIR] & s->regs[ENET_EIMR] & ENET_INT_TS_TIMER) { | ||
72 | + /* | ||
73 | + * Previous versions of qemu had the ENET_INT_MAC and ENET_INT_TS_TIMER | ||
74 | + * interrupts swapped. This worked with older versions of Linux (4.14 | ||
75 | + * and older) since Linux associated both interrupt lines with Ethernet | ||
76 | + * MAC interrupts. Specifically, | ||
77 | + * - Linux 4.15 and later have separate interrupt handlers for the MAC and | ||
78 | + * timer interrupts. Those versions of Linux fail with versions of QEMU | ||
79 | + * with swapped interrupt assignments. | ||
80 | + * - In linux 4.14, both interrupt lines were registered with the Ethernet | ||
81 | + * MAC interrupt handler. As a result, all versions of qemu happen to | ||
82 | + * work, though that is accidental. | ||
83 | + * - In Linux 4.9 and older, the timer interrupt was registered directly | ||
84 | + * with the Ethernet MAC interrupt handler. The MAC interrupt was | ||
85 | + * redirected to a GPIO interrupt to work around erratum ERR006687. | ||
86 | + * This was implemented using the SOC's IOMUX block. In qemu, this GPIO | ||
87 | + * interrupt never fired since IOMUX is currently not supported in qemu. | ||
88 | + * Linux instead received MAC interrupts on the timer interrupt. | ||
89 | + * As a result, qemu versions with the swapped interrupt assignment work, | ||
90 | + * albeit accidentally, but qemu versions with the correct interrupt | ||
91 | + * assignment fail. | ||
92 | + * | ||
93 | + * To ensure that all versions of Linux work, generate ENET_INT_MAC | ||
94 | + * interrrupts on both interrupt lines. This should be changed if and when | ||
95 | + * qemu supports IOMUX. | ||
96 | + */ | ||
97 | + if (s->regs[ENET_EIR] & s->regs[ENET_EIMR] & | ||
98 | + (ENET_INT_MAC | ENET_INT_TS_TIMER)) { | ||
99 | qemu_set_irq(s->irq[1], 1); | ||
100 | } else { | ||
101 | qemu_set_irq(s->irq[1], 0); | ||
102 | -- | 63 | -- |
103 | 2.16.2 | 64 | 2.20.1 |
104 | 65 | ||
105 | 66 | diff view generated by jsdifflib |
1 | From: Andrey Smirnov <andrew.smirnov@gmail.com> | 1 | From: Philippe Mathieu-Daudé <philmd@redhat.com> |
---|---|---|---|
2 | 2 | ||
3 | Code of imx_update() is slightly confusing since the "flags" variable | 3 | In the previous commit we fixed a crash when the guest read a |
4 | doesn't really corespond to anything in real hardware and server as a | 4 | register that pop from an empty FIFO. |
5 | kitchensink accumulating events normally reported via USR1 and USR2 | 5 | By auditing the repository, we found another similar use with |
6 | registers. | 6 | an easy way to reproduce: |
7 | 7 | ||
8 | Change the code to explicitly evaluate state of interrupts reported | 8 | $ qemu-system-aarch64 -M xlnx-zcu102 -monitor stdio -S |
9 | via USR1 and USR2 against corresponding masking bits and use the to | 9 | QEMU 4.0.50 monitor - type 'help' for more information |
10 | detemine if IRQ line should be asserted or not. | 10 | (qemu) xp/b 0xfd4a0134 |
11 | Aborted (core dumped) | ||
11 | 12 | ||
12 | NOTE: Check for UTS1_TXEMPTY being set has been dropped for two | 13 | (gdb) bt |
13 | reasons: | 14 | #0 0x00007f6936dea57f in raise () at /lib64/libc.so.6 |
15 | #1 0x00007f6936dd4895 in abort () at /lib64/libc.so.6 | ||
16 | #2 0x0000561ad32975ec in xlnx_dp_aux_pop_rx_fifo (s=0x7f692babee70) at hw/display/xlnx_dp.c:431 | ||
17 | #3 0x0000561ad3297dc0 in xlnx_dp_read (opaque=0x7f692babee70, offset=77, size=4) at hw/display/xlnx_dp.c:667 | ||
18 | #4 0x0000561ad321b896 in memory_region_read_accessor (mr=0x7f692babf620, addr=308, value=0x7ffe05c1db88, size=4, shift=0, mask=4294967295, attrs=...) at memory.c:439 | ||
19 | #5 0x0000561ad321bd70 in access_with_adjusted_size (addr=308, value=0x7ffe05c1db88, size=1, access_size_min=4, access_size_max=4, access_fn=0x561ad321b858 <memory_region_read_accessor>, mr=0x7f692babf620, attrs=...) at memory.c:569 | ||
20 | #6 0x0000561ad321e9d5 in memory_region_dispatch_read1 (mr=0x7f692babf620, addr=308, pval=0x7ffe05c1db88, size=1, attrs=...) at memory.c:1420 | ||
21 | #7 0x0000561ad321ea9d in memory_region_dispatch_read (mr=0x7f692babf620, addr=308, pval=0x7ffe05c1db88, size=1, attrs=...) at memory.c:1447 | ||
22 | #8 0x0000561ad31bd742 in flatview_read_continue (fv=0x561ad69c04f0, addr=4249485620, attrs=..., buf=0x7ffe05c1dcf0 "\020\335\301\005\376\177", len=1, addr1=308, l=1, mr=0x7f692babf620) at exec.c:3385 | ||
23 | #9 0x0000561ad31bd895 in flatview_read (fv=0x561ad69c04f0, addr=4249485620, attrs=..., buf=0x7ffe05c1dcf0 "\020\335\301\005\376\177", len=1) at exec.c:3423 | ||
24 | #10 0x0000561ad31bd90b in address_space_read_full (as=0x561ad5bb3020, addr=4249485620, attrs=..., buf=0x7ffe05c1dcf0 "\020\335\301\005\376\177", len=1) at exec.c:3436 | ||
25 | #11 0x0000561ad33b1c42 in address_space_read (len=1, buf=0x7ffe05c1dcf0 "\020\335\301\005\376\177", attrs=..., addr=4249485620, as=0x561ad5bb3020) at include/exec/memory.h:2131 | ||
26 | #12 0x0000561ad33b1c42 in memory_dump (mon=0x561ad59c4530, count=1, format=120, wsize=1, addr=4249485620, is_physical=1) at monitor/misc.c:723 | ||
27 | #13 0x0000561ad33b1fc1 in hmp_physical_memory_dump (mon=0x561ad59c4530, qdict=0x561ad6c6fd00) at monitor/misc.c:795 | ||
28 | #14 0x0000561ad37b4a9f in handle_hmp_command (mon=0x561ad59c4530, cmdline=0x561ad59d0f22 "/b 0x00000000fd4a0134") at monitor/hmp.c:1082 | ||
14 | 29 | ||
15 | 1. Emulation code implements a single character FIFO, so this flag | 30 | Fix by checking the FIFO is not empty before popping from it. |
16 | will always be set since characters are trasmitted as a part of | ||
17 | the code emulating "push" into the FIFO | ||
18 | 31 | ||
19 | 2. imx_update() is really just a function doing ORing and maksing | 32 | The datasheet is not clear about the reset value of this register, |
20 | of reported events, so checking for UTS1_TXEMPTY should happen, | 33 | we choose to return '0'. |
21 | if it's ever really needed should probably happen outside of | ||
22 | it. | ||
23 | 34 | ||
24 | Cc: qemu-devel@nongnu.org | 35 | Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> |
25 | Cc: qemu-arm@nongnu.org | 36 | Reviewed-by: Alistair Francis <alistair.francis@wdc.com> |
26 | Cc: Bill Paul <wpaul@windriver.com> | 37 | Message-id: 20190709113715.7761-4-philmd@redhat.com |
27 | Cc: Peter Maydell <peter.maydell@linaro.org> | ||
28 | Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> | ||
29 | Message-id: 20180315191141.6789-1-andrew.smirnov@gmail.com | ||
30 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
31 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 38 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
32 | --- | 39 | --- |
33 | hw/char/imx_serial.c | 24 ++++++++++++++++-------- | 40 | hw/display/xlnx_dp.c | 15 +++++++++++---- |
34 | 1 file changed, 16 insertions(+), 8 deletions(-) | 41 | 1 file changed, 11 insertions(+), 4 deletions(-) |
35 | 42 | ||
36 | diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c | 43 | diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c |
37 | index XXXXXXX..XXXXXXX 100644 | 44 | index XXXXXXX..XXXXXXX 100644 |
38 | --- a/hw/char/imx_serial.c | 45 | --- a/hw/display/xlnx_dp.c |
39 | +++ b/hw/char/imx_serial.c | 46 | +++ b/hw/display/xlnx_dp.c |
40 | @@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_imx_serial = { | 47 | @@ -XXX,XX +XXX,XX @@ static uint8_t xlnx_dp_aux_pop_rx_fifo(XlnxDPState *s) |
41 | 48 | uint8_t ret; | |
42 | static void imx_update(IMXSerialState *s) | 49 | |
43 | { | 50 | if (fifo8_is_empty(&s->rx_fifo)) { |
44 | - uint32_t flags; | 51 | - DPRINTF("rx_fifo underflow..\n"); |
45 | + uint32_t usr1; | 52 | - abort(); |
46 | + uint32_t usr2; | 53 | + qemu_log_mask(LOG_GUEST_ERROR, |
47 | + uint32_t mask; | 54 | + "%s: Reading empty RX_FIFO\n", |
48 | 55 | + __func__); | |
49 | - flags = (s->usr1 & s->ucr1) & (USR1_TRDY|USR1_RRDY); | 56 | + /* |
50 | - if (s->ucr1 & UCR1_TXMPTYEN) { | 57 | + * The datasheet is not clear about the reset value, it seems |
51 | - flags |= (s->uts1 & UTS1_TXEMPTY); | 58 | + * to be unspecified. We choose to return '0'. |
52 | - } else { | 59 | + */ |
53 | - flags &= ~USR1_TRDY; | 60 | + ret = 0; |
54 | - } | 61 | + } else { |
55 | + /* | 62 | + ret = fifo8_pop(&s->rx_fifo); |
56 | + * Lucky for us TRDY and RRDY has the same offset in both USR1 and | 63 | + DPRINTF("pop 0x%" PRIX8 " from rx_fifo.\n", ret); |
57 | + * UCR1, so we can get away with something as simple as the | 64 | } |
58 | + * following: | 65 | - ret = fifo8_pop(&s->rx_fifo); |
59 | + */ | 66 | - DPRINTF("pop 0x%" PRIX8 " from rx_fifo.\n", ret); |
60 | + usr1 = s->usr1 & s->ucr1 & (USR1_TRDY | USR1_RRDY); | 67 | return ret; |
61 | + /* | ||
62 | + * Bits that we want in USR2 are not as conveniently laid out, | ||
63 | + * unfortunately. | ||
64 | + */ | ||
65 | + mask = (s->ucr1 & UCR1_TXMPTYEN) ? USR2_TXFE : 0; | ||
66 | + usr2 = s->usr2 & mask; | ||
67 | |||
68 | - qemu_set_irq(s->irq, !!flags); | ||
69 | + qemu_set_irq(s->irq, usr1 || usr2); | ||
70 | } | 68 | } |
71 | 69 | ||
72 | static void imx_serial_reset(IMXSerialState *s) | ||
73 | -- | 70 | -- |
74 | 2.16.2 | 71 | 2.20.1 |
75 | 72 | ||
76 | 73 | diff view generated by jsdifflib |
1 | From: Andrey Smirnov <andrew.smirnov@gmail.com> | 1 | From: David Engraf <david.engraf@sysgo.com> |
---|---|---|---|
2 | 2 | ||
3 | Add support for "TX complete"/TXDC interrupt generate by real HW since | 3 | Using the whole 128 MiB flash in non-secure mode is not working because |
4 | it is needed to support guests other than Linux. | 4 | virt_flash_fdt() expects the same address for secure_sysmem and sysmem. |
5 | This is not correctly handled by caller because it forwards NULL for | ||
6 | secure_sysmem in non-secure flash mode. | ||
5 | 7 | ||
6 | Based on the patch by Bill Paul as found here: | 8 | Fixed by using sysmem when secure_sysmem is NULL. |
7 | https://bugs.launchpad.net/qemu/+bug/1753314 | ||
8 | 9 | ||
9 | Cc: qemu-devel@nongnu.org | 10 | Signed-off-by: David Engraf <david.engraf@sysgo.com> |
10 | Cc: qemu-arm@nongnu.org | 11 | Message-id: 20190712075002.14326-1-david.engraf@sysgo.com |
11 | Cc: Bill Paul <wpaul@windriver.com> | ||
12 | Cc: Peter Maydell <peter.maydell@linaro.org> | ||
13 | Signed-off-by: Bill Paul <wpaul@windriver.com> | ||
14 | Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> | ||
15 | Message-id: 20180315191141.6789-2-andrew.smirnov@gmail.com | ||
16 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 12 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> |
17 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 13 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
18 | --- | 14 | --- |
19 | include/hw/char/imx_serial.h | 3 +++ | 15 | hw/arm/virt.c | 2 +- |
20 | hw/char/imx_serial.c | 20 +++++++++++++++++--- | 16 | 1 file changed, 1 insertion(+), 1 deletion(-) |
21 | 2 files changed, 20 insertions(+), 3 deletions(-) | ||
22 | 17 | ||
23 | diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h | 18 | diff --git a/hw/arm/virt.c b/hw/arm/virt.c |
24 | index XXXXXXX..XXXXXXX 100644 | 19 | index XXXXXXX..XXXXXXX 100644 |
25 | --- a/include/hw/char/imx_serial.h | 20 | --- a/hw/arm/virt.c |
26 | +++ b/include/hw/char/imx_serial.h | 21 | +++ b/hw/arm/virt.c |
27 | @@ -XXX,XX +XXX,XX @@ | 22 | @@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine) |
28 | #define UCR2_RXEN (1<<1) /* Receiver enable */ | 23 | &machine->device_memory->mr); |
29 | #define UCR2_SRST (1<<0) /* Reset complete */ | 24 | } |
30 | 25 | ||
31 | +#define UCR4_TCEN BIT(3) /* TX complete interrupt enable */ | 26 | - virt_flash_fdt(vms, sysmem, secure_sysmem); |
32 | + | 27 | + virt_flash_fdt(vms, sysmem, secure_sysmem ?: sysmem); |
33 | #define UTS1_TXEMPTY (1<<6) | 28 | |
34 | #define UTS1_RXEMPTY (1<<5) | 29 | create_gic(vms, pic); |
35 | #define UTS1_TXFULL (1<<4) | 30 | |
36 | @@ -XXX,XX +XXX,XX @@ typedef struct IMXSerialState { | ||
37 | uint32_t ubmr; | ||
38 | uint32_t ubrc; | ||
39 | uint32_t ucr3; | ||
40 | + uint32_t ucr4; | ||
41 | |||
42 | qemu_irq irq; | ||
43 | CharBackend chr; | ||
44 | diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c | ||
45 | index XXXXXXX..XXXXXXX 100644 | ||
46 | --- a/hw/char/imx_serial.c | ||
47 | +++ b/hw/char/imx_serial.c | ||
48 | @@ -XXX,XX +XXX,XX @@ | ||
49 | |||
50 | static const VMStateDescription vmstate_imx_serial = { | ||
51 | .name = TYPE_IMX_SERIAL, | ||
52 | - .version_id = 1, | ||
53 | - .minimum_version_id = 1, | ||
54 | + .version_id = 2, | ||
55 | + .minimum_version_id = 2, | ||
56 | .fields = (VMStateField[]) { | ||
57 | VMSTATE_INT32(readbuff, IMXSerialState), | ||
58 | VMSTATE_UINT32(usr1, IMXSerialState), | ||
59 | @@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_imx_serial = { | ||
60 | VMSTATE_UINT32(ubmr, IMXSerialState), | ||
61 | VMSTATE_UINT32(ubrc, IMXSerialState), | ||
62 | VMSTATE_UINT32(ucr3, IMXSerialState), | ||
63 | + VMSTATE_UINT32(ucr4, IMXSerialState), | ||
64 | VMSTATE_END_OF_LIST() | ||
65 | }, | ||
66 | }; | ||
67 | @@ -XXX,XX +XXX,XX @@ static void imx_update(IMXSerialState *s) | ||
68 | * unfortunately. | ||
69 | */ | ||
70 | mask = (s->ucr1 & UCR1_TXMPTYEN) ? USR2_TXFE : 0; | ||
71 | + /* | ||
72 | + * TCEN and TXDC are both bit 3 | ||
73 | + */ | ||
74 | + mask |= s->ucr4 & UCR4_TCEN; | ||
75 | + | ||
76 | usr2 = s->usr2 & mask; | ||
77 | |||
78 | qemu_set_irq(s->irq, usr1 || usr2); | ||
79 | @@ -XXX,XX +XXX,XX @@ static uint64_t imx_serial_read(void *opaque, hwaddr offset, | ||
80 | return s->ucr3; | ||
81 | |||
82 | case 0x23: /* UCR4 */ | ||
83 | + return s->ucr4; | ||
84 | + | ||
85 | case 0x29: /* BRM Incremental */ | ||
86 | return 0x0; /* TODO */ | ||
87 | |||
88 | @@ -XXX,XX +XXX,XX @@ static void imx_serial_write(void *opaque, hwaddr offset, | ||
89 | * qemu_chr_fe_write and background I/O callbacks */ | ||
90 | qemu_chr_fe_write_all(&s->chr, &ch, 1); | ||
91 | s->usr1 &= ~USR1_TRDY; | ||
92 | + s->usr2 &= ~USR2_TXDC; | ||
93 | imx_update(s); | ||
94 | s->usr1 |= USR1_TRDY; | ||
95 | + s->usr2 |= USR2_TXDC; | ||
96 | imx_update(s); | ||
97 | } | ||
98 | break; | ||
99 | @@ -XXX,XX +XXX,XX @@ static void imx_serial_write(void *opaque, hwaddr offset, | ||
100 | s->ucr3 = value & 0xffff; | ||
101 | break; | ||
102 | |||
103 | - case 0x2d: /* UTS1 */ | ||
104 | case 0x23: /* UCR4 */ | ||
105 | + s->ucr4 = value & 0xffff; | ||
106 | + imx_update(s); | ||
107 | + break; | ||
108 | + | ||
109 | + case 0x2d: /* UTS1 */ | ||
110 | qemu_log_mask(LOG_UNIMP, "[%s]%s: Unimplemented reg 0x%" | ||
111 | HWADDR_PRIx "\n", TYPE_IMX_SERIAL, __func__, offset); | ||
112 | /* TODO */ | ||
113 | -- | 31 | -- |
114 | 2.16.2 | 32 | 2.20.1 |
115 | 33 | ||
116 | 34 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | For the rpi1 and 2 we want to boot the Linux kernel via some | ||
2 | custom setup code that makes sure that the SMC instruction | ||
3 | acts as a no-op, because it's used for cache maintenance. | ||
4 | The rpi3 boots AArch64 kernels, which don't need SMC for | ||
5 | cache maintenance and always expect to be booted non-secure. | ||
6 | Don't fill in the aarch32-specific parts of the binfo struct. | ||
7 | 1 | ||
8 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
9 | Reviewed-by: Andrew Baumann <Andrew.Baumann@microsoft.com> | ||
10 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
11 | Message-id: 20180313153458.26822-2-peter.maydell@linaro.org | ||
12 | --- | ||
13 | hw/arm/raspi.c | 17 +++++++++++++---- | ||
14 | 1 file changed, 13 insertions(+), 4 deletions(-) | ||
15 | |||
16 | diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c | ||
17 | index XXXXXXX..XXXXXXX 100644 | ||
18 | --- a/hw/arm/raspi.c | ||
19 | +++ b/hw/arm/raspi.c | ||
20 | @@ -XXX,XX +XXX,XX @@ static void setup_boot(MachineState *machine, int version, size_t ram_size) | ||
21 | binfo.board_id = raspi_boardid[version]; | ||
22 | binfo.ram_size = ram_size; | ||
23 | binfo.nb_cpus = smp_cpus; | ||
24 | - binfo.board_setup_addr = BOARDSETUP_ADDR; | ||
25 | - binfo.write_board_setup = write_board_setup; | ||
26 | - binfo.secure_board_setup = true; | ||
27 | - binfo.secure_boot = true; | ||
28 | + | ||
29 | + if (version <= 2) { | ||
30 | + /* The rpi1 and 2 require some custom setup code to run in Secure | ||
31 | + * mode before booting a kernel (to set up the SMC vectors so | ||
32 | + * that we get a no-op SMC; this is used by Linux to call the | ||
33 | + * firmware for some cache maintenance operations. | ||
34 | + * The rpi3 doesn't need this. | ||
35 | + */ | ||
36 | + binfo.board_setup_addr = BOARDSETUP_ADDR; | ||
37 | + binfo.write_board_setup = write_board_setup; | ||
38 | + binfo.secure_board_setup = true; | ||
39 | + binfo.secure_boot = true; | ||
40 | + } | ||
41 | |||
42 | /* Pi2 and Pi3 requires SMP setup */ | ||
43 | if (version >= 2) { | ||
44 | -- | ||
45 | 2.16.2 | ||
46 | |||
47 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Add some assertions that if we're about to boot an AArch64 kernel, | ||
2 | the board code has not mistakenly set either secure_boot or | ||
3 | secure_board_setup. It doesn't make sense to set secure_boot, | ||
4 | because all AArch64 kernels must be booted in non-secure mode. | ||
5 | 1 | ||
6 | It might in theory make sense to set secure_board_setup, but | ||
7 | we don't currently support that, because only the AArch32 | ||
8 | bootloader[] code calls this hook; bootloader_aarch64[] does not. | ||
9 | Since we don't have a current need for this functionality, just | ||
10 | assert that we don't try to use it. If it's needed we'll add | ||
11 | it later. | ||
12 | |||
13 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
14 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
15 | Message-id: 20180313153458.26822-3-peter.maydell@linaro.org | ||
16 | --- | ||
17 | hw/arm/boot.c | 7 +++++++ | ||
18 | 1 file changed, 7 insertions(+) | ||
19 | |||
20 | diff --git a/hw/arm/boot.c b/hw/arm/boot.c | ||
21 | index XXXXXXX..XXXXXXX 100644 | ||
22 | --- a/hw/arm/boot.c | ||
23 | +++ b/hw/arm/boot.c | ||
24 | @@ -XXX,XX +XXX,XX @@ static void do_cpu_reset(void *opaque) | ||
25 | } else { | ||
26 | env->pstate = PSTATE_MODE_EL1h; | ||
27 | } | ||
28 | + /* AArch64 kernels never boot in secure mode */ | ||
29 | + assert(!info->secure_boot); | ||
30 | + /* This hook is only supported for AArch32 currently: | ||
31 | + * bootloader_aarch64[] will not call the hook, and | ||
32 | + * the code above has already dropped us into EL2 or EL1. | ||
33 | + */ | ||
34 | + assert(!info->secure_board_setup); | ||
35 | } | ||
36 | |||
37 | /* Set to non-secure if not a secure boot */ | ||
38 | -- | ||
39 | 2.16.2 | ||
40 | |||
41 | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | If we're directly booting a Linux kernel and the CPU supports both | ||
2 | EL3 and EL2, we start the kernel in EL2, as it expects. We must also | ||
3 | set the SCR_EL3.HCE bit in this situation, so that the HVC | ||
4 | instruction is enabled rather than UNDEFing. Otherwise at least some | ||
5 | kernels will panic when trying to initialize KVM in the guest. | ||
6 | 1 | ||
7 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
8 | Message-id: 20180313153458.26822-4-peter.maydell@linaro.org | ||
9 | --- | ||
10 | hw/arm/boot.c | 5 +++++ | ||
11 | 1 file changed, 5 insertions(+) | ||
12 | |||
13 | diff --git a/hw/arm/boot.c b/hw/arm/boot.c | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/hw/arm/boot.c | ||
16 | +++ b/hw/arm/boot.c | ||
17 | @@ -XXX,XX +XXX,XX @@ static void do_cpu_reset(void *opaque) | ||
18 | assert(!info->secure_board_setup); | ||
19 | } | ||
20 | |||
21 | + if (arm_feature(env, ARM_FEATURE_EL2)) { | ||
22 | + /* If we have EL2 then Linux expects the HVC insn to work */ | ||
23 | + env->cp15.scr_el3 |= SCR_HCE; | ||
24 | + } | ||
25 | + | ||
26 | /* Set to non-secure if not a secure boot */ | ||
27 | if (!info->secure_boot && | ||
28 | (cs != first_cpu || !info->secure_board_setup)) { | ||
29 | -- | ||
30 | 2.16.2 | ||
31 | |||
32 | diff view generated by jsdifflib |
1 | The bcm2837 is pretty similar to the bcm2836, but it does have | 1 | The PL031 RTC tracks the difference between the guest RTC |
---|---|---|---|
2 | some differences. Notably, the MPIDR affinity aff1 values it | 2 | and the host RTC using a tick_offset field. For migration, |
3 | sets for the CPUs are 0x0, rather than the 0xf that the bcm2836 | 3 | however, we currently always migrate the offset between |
4 | uses, and if this is wrong Linux will not boot. | 4 | the guest and the vm_clock, even if the RTC clock is not |
5 | 5 | the same as the vm_clock; this was an attempt to retain | |
6 | Rather than trying to have one device with properties that | 6 | migration backwards compatibility. |
7 | configure it differently for the two cases, create two | 7 | |
8 | separate QOM devices for the two SoCs. We use the same approach | 8 | Unfortunately this results in the RTC behaving oddly across |
9 | as hw/arm/aspeed_soc.c and share code and have a data table | 9 | a VM state save and restore -- since the VM clock stands still |
10 | that might differ per-SoC. For the moment the two types don't | 10 | across save-then-restore, regardless of how much real world |
11 | actually have different behaviour. | 11 | time has elapsed, the guest RTC ends up out of sync with the |
12 | 12 | host RTC in the restored VM. | |
13 | |||
14 | Fix this by migrating the raw tick_offset. To retain migration | ||
15 | compatibility as far as possible, we have a new property | ||
16 | migrate-tick-offset; by default this is 'true' and we will | ||
17 | migrate the true tick offset in a new subsection; if the | ||
18 | incoming data has no subsection we fall back to the old | ||
19 | vm_clock-based offset information, so old->new migration | ||
20 | compatibility is preserved. For complete new->old migration | ||
21 | compatibility, the property is set to 'false' for 4.0 and | ||
22 | earlier machine types (this will only affect 'virt-4.0' | ||
23 | and below, as none of the other pl031-using machines are | ||
24 | versioned). | ||
25 | |||
26 | Reported-by: Russell King <rmk@armlinux.org.uk> | ||
13 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 27 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
14 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | 28 | Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com> |
15 | Message-id: 20180313153458.26822-7-peter.maydell@linaro.org | 29 | Message-id: 20190709143912.28905-1-peter.maydell@linaro.org |
16 | --- | 30 | --- |
17 | include/hw/arm/bcm2836.h | 19 +++++++++++++++++++ | 31 | include/hw/timer/pl031.h | 2 + |
18 | hw/arm/bcm2836.c | 37 ++++++++++++++++++++++++++++++++----- | 32 | hw/core/machine.c | 1 + |
19 | hw/arm/raspi.c | 3 ++- | 33 | hw/timer/pl031.c | 92 ++++++++++++++++++++++++++++++++++++++-- |
20 | 3 files changed, 53 insertions(+), 6 deletions(-) | 34 | 3 files changed, 91 insertions(+), 4 deletions(-) |
21 | 35 | ||
22 | diff --git a/include/hw/arm/bcm2836.h b/include/hw/arm/bcm2836.h | 36 | diff --git a/include/hw/timer/pl031.h b/include/hw/timer/pl031.h |
23 | index XXXXXXX..XXXXXXX 100644 | 37 | index XXXXXXX..XXXXXXX 100644 |
24 | --- a/include/hw/arm/bcm2836.h | 38 | --- a/include/hw/timer/pl031.h |
25 | +++ b/include/hw/arm/bcm2836.h | 39 | +++ b/include/hw/timer/pl031.h |
26 | @@ -XXX,XX +XXX,XX @@ | 40 | @@ -XXX,XX +XXX,XX @@ typedef struct PL031State { |
27 | 41 | */ | |
28 | #define BCM283X_NCPUS 4 | 42 | uint32_t tick_offset_vmstate; |
29 | 43 | uint32_t tick_offset; | |
30 | +/* These type names are for specific SoCs; other than instantiating | 44 | + bool tick_offset_migrated; |
31 | + * them, code using these devices should always handle them via the | 45 | + bool migrate_tick_offset; |
32 | + * BCM283x base class, so they have no BCM2836(obj) etc macros. | 46 | |
33 | + */ | 47 | uint32_t mr; |
34 | +#define TYPE_BCM2836 "bcm2836" | 48 | uint32_t lr; |
35 | +#define TYPE_BCM2837 "bcm2837" | 49 | diff --git a/hw/core/machine.c b/hw/core/machine.c |
36 | + | ||
37 | typedef struct BCM283XState { | ||
38 | /*< private >*/ | ||
39 | DeviceState parent_obj; | ||
40 | @@ -XXX,XX +XXX,XX @@ typedef struct BCM283XState { | ||
41 | BCM2835PeripheralState peripherals; | ||
42 | } BCM283XState; | ||
43 | |||
44 | +typedef struct BCM283XInfo BCM283XInfo; | ||
45 | + | ||
46 | +typedef struct BCM283XClass { | ||
47 | + DeviceClass parent_class; | ||
48 | + const BCM283XInfo *info; | ||
49 | +} BCM283XClass; | ||
50 | + | ||
51 | +#define BCM283X_CLASS(klass) \ | ||
52 | + OBJECT_CLASS_CHECK(BCM283XClass, (klass), TYPE_BCM283X) | ||
53 | +#define BCM283X_GET_CLASS(obj) \ | ||
54 | + OBJECT_GET_CLASS(BCM283XClass, (obj), TYPE_BCM283X) | ||
55 | + | ||
56 | #endif /* BCM2836_H */ | ||
57 | diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c | ||
58 | index XXXXXXX..XXXXXXX 100644 | 50 | index XXXXXXX..XXXXXXX 100644 |
59 | --- a/hw/arm/bcm2836.c | 51 | --- a/hw/core/machine.c |
60 | +++ b/hw/arm/bcm2836.c | 52 | +++ b/hw/core/machine.c |
61 | @@ -XXX,XX +XXX,XX @@ | 53 | @@ -XXX,XX +XXX,XX @@ GlobalProperty hw_compat_4_0[] = { |
62 | /* "QA7" (Pi2) interrupt controller and mailboxes etc. */ | 54 | { "virtio-gpu-pci", "edid", "false" }, |
63 | #define BCM2836_CONTROL_BASE 0x40000000 | 55 | { "virtio-device", "use-started", "false" }, |
64 | 56 | { "virtio-balloon-device", "qemu-4-0-config-size", "true" }, | |
65 | +struct BCM283XInfo { | 57 | + { "pl031", "migrate-tick-offset", "false" }, |
66 | + const char *name; | 58 | }; |
59 | const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0); | ||
60 | |||
61 | diff --git a/hw/timer/pl031.c b/hw/timer/pl031.c | ||
62 | index XXXXXXX..XXXXXXX 100644 | ||
63 | --- a/hw/timer/pl031.c | ||
64 | +++ b/hw/timer/pl031.c | ||
65 | @@ -XXX,XX +XXX,XX @@ static int pl031_pre_save(void *opaque) | ||
66 | { | ||
67 | PL031State *s = opaque; | ||
68 | |||
69 | - /* tick_offset is base_time - rtc_clock base time. Instead, we want to | ||
70 | - * store the base time relative to the QEMU_CLOCK_VIRTUAL for backwards-compatibility. */ | ||
71 | + /* | ||
72 | + * The PL031 device model code uses the tick_offset field, which is | ||
73 | + * the offset between what the guest RTC should read and what the | ||
74 | + * QEMU rtc_clock reads: | ||
75 | + * guest_rtc = rtc_clock + tick_offset | ||
76 | + * and so | ||
77 | + * tick_offset = guest_rtc - rtc_clock | ||
78 | + * | ||
79 | + * We want to migrate this offset, which sounds straightforward. | ||
80 | + * Unfortunately older versions of QEMU migrated a conversion of this | ||
81 | + * offset into an offset from the vm_clock. (This was in turn an | ||
82 | + * attempt to be compatible with even older QEMU versions, but it | ||
83 | + * has incorrect behaviour if the rtc_clock is not the same as the | ||
84 | + * vm_clock.) So we put the actual tick_offset into a migration | ||
85 | + * subsection, and the backwards-compatible time-relative-to-vm_clock | ||
86 | + * in the main migration state. | ||
87 | + * | ||
88 | + * Calculate base time relative to QEMU_CLOCK_VIRTUAL: | ||
89 | + */ | ||
90 | int64_t delta = qemu_clock_get_ns(rtc_clock) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); | ||
91 | s->tick_offset_vmstate = s->tick_offset + delta / NANOSECONDS_PER_SECOND; | ||
92 | |||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | +static int pl031_pre_load(void *opaque) | ||
97 | +{ | ||
98 | + PL031State *s = opaque; | ||
99 | + | ||
100 | + s->tick_offset_migrated = false; | ||
101 | + return 0; | ||
102 | +} | ||
103 | + | ||
104 | static int pl031_post_load(void *opaque, int version_id) | ||
105 | { | ||
106 | PL031State *s = opaque; | ||
107 | |||
108 | - int64_t delta = qemu_clock_get_ns(rtc_clock) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); | ||
109 | - s->tick_offset = s->tick_offset_vmstate - delta / NANOSECONDS_PER_SECOND; | ||
110 | + /* | ||
111 | + * If we got the tick_offset subsection, then we can just use | ||
112 | + * the value in that. Otherwise the source is an older QEMU and | ||
113 | + * has given us the offset from the vm_clock; convert it back to | ||
114 | + * an offset from the rtc_clock. This will cause time to incorrectly | ||
115 | + * go backwards compared to the host RTC, but this is unavoidable. | ||
116 | + */ | ||
117 | + | ||
118 | + if (!s->tick_offset_migrated) { | ||
119 | + int64_t delta = qemu_clock_get_ns(rtc_clock) - | ||
120 | + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); | ||
121 | + s->tick_offset = s->tick_offset_vmstate - | ||
122 | + delta / NANOSECONDS_PER_SECOND; | ||
123 | + } | ||
124 | pl031_set_alarm(s); | ||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | +static int pl031_tick_offset_post_load(void *opaque, int version_id) | ||
129 | +{ | ||
130 | + PL031State *s = opaque; | ||
131 | + | ||
132 | + s->tick_offset_migrated = true; | ||
133 | + return 0; | ||
134 | +} | ||
135 | + | ||
136 | +static bool pl031_tick_offset_needed(void *opaque) | ||
137 | +{ | ||
138 | + PL031State *s = opaque; | ||
139 | + | ||
140 | + return s->migrate_tick_offset; | ||
141 | +} | ||
142 | + | ||
143 | +static const VMStateDescription vmstate_pl031_tick_offset = { | ||
144 | + .name = "pl031/tick-offset", | ||
145 | + .version_id = 1, | ||
146 | + .minimum_version_id = 1, | ||
147 | + .needed = pl031_tick_offset_needed, | ||
148 | + .post_load = pl031_tick_offset_post_load, | ||
149 | + .fields = (VMStateField[]) { | ||
150 | + VMSTATE_UINT32(tick_offset, PL031State), | ||
151 | + VMSTATE_END_OF_LIST() | ||
152 | + } | ||
67 | +}; | 153 | +}; |
68 | + | 154 | + |
69 | +static const BCM283XInfo bcm283x_socs[] = { | 155 | static const VMStateDescription vmstate_pl031 = { |
70 | + { | 156 | .name = "pl031", |
71 | + .name = TYPE_BCM2836, | 157 | .version_id = 1, |
158 | .minimum_version_id = 1, | ||
159 | .pre_save = pl031_pre_save, | ||
160 | + .pre_load = pl031_pre_load, | ||
161 | .post_load = pl031_post_load, | ||
162 | .fields = (VMStateField[]) { | ||
163 | VMSTATE_UINT32(tick_offset_vmstate, PL031State), | ||
164 | @@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_pl031 = { | ||
165 | VMSTATE_UINT32(im, PL031State), | ||
166 | VMSTATE_UINT32(is, PL031State), | ||
167 | VMSTATE_END_OF_LIST() | ||
72 | + }, | 168 | + }, |
73 | + { | 169 | + .subsections = (const VMStateDescription*[]) { |
74 | + .name = TYPE_BCM2837, | 170 | + &vmstate_pl031_tick_offset, |
75 | + }, | 171 | + NULL |
172 | } | ||
173 | }; | ||
174 | |||
175 | +static Property pl031_properties[] = { | ||
176 | + /* | ||
177 | + * True to correctly migrate the tick offset of the RTC. False to | ||
178 | + * obtain backward migration compatibility with older QEMU versions, | ||
179 | + * at the expense of the guest RTC going backwards compared with the | ||
180 | + * host RTC when the VM is saved/restored if using -rtc host. | ||
181 | + * (Even if set to 'true' older QEMU can migrate forward to newer QEMU; | ||
182 | + * 'false' also permits newer QEMU to migrate to older QEMU.) | ||
183 | + */ | ||
184 | + DEFINE_PROP_BOOL("migrate-tick-offset", | ||
185 | + PL031State, migrate_tick_offset, true), | ||
186 | + DEFINE_PROP_END_OF_LIST() | ||
76 | +}; | 187 | +}; |
77 | + | 188 | + |
78 | static void bcm2836_init(Object *obj) | 189 | static void pl031_class_init(ObjectClass *klass, void *data) |
79 | { | 190 | { |
80 | BCM283XState *s = BCM283X(obj); | 191 | DeviceClass *dc = DEVICE_CLASS(klass); |
81 | @@ -XXX,XX +XXX,XX @@ static Property bcm2836_props[] = { | 192 | |
82 | DEFINE_PROP_END_OF_LIST() | 193 | dc->vmsd = &vmstate_pl031; |
83 | }; | 194 | + dc->props = pl031_properties; |
84 | |||
85 | -static void bcm2836_class_init(ObjectClass *oc, void *data) | ||
86 | +static void bcm283x_class_init(ObjectClass *oc, void *data) | ||
87 | { | ||
88 | DeviceClass *dc = DEVICE_CLASS(oc); | ||
89 | + BCM283XClass *bc = BCM283X_CLASS(oc); | ||
90 | |||
91 | - dc->props = bcm2836_props; | ||
92 | + bc->info = data; | ||
93 | dc->realize = bcm2836_realize; | ||
94 | + dc->props = bcm2836_props; | ||
95 | } | 195 | } |
96 | 196 | ||
97 | -static const TypeInfo bcm2836_type_info = { | 197 | static const TypeInfo pl031_info = { |
98 | +static const TypeInfo bcm283x_type_info = { | ||
99 | .name = TYPE_BCM283X, | ||
100 | .parent = TYPE_DEVICE, | ||
101 | .instance_size = sizeof(BCM283XState), | ||
102 | .instance_init = bcm2836_init, | ||
103 | - .class_init = bcm2836_class_init, | ||
104 | + .class_size = sizeof(BCM283XClass), | ||
105 | + .abstract = true, | ||
106 | }; | ||
107 | |||
108 | static void bcm2836_register_types(void) | ||
109 | { | ||
110 | - type_register_static(&bcm2836_type_info); | ||
111 | + int i; | ||
112 | + | ||
113 | + type_register_static(&bcm283x_type_info); | ||
114 | + for (i = 0; i < ARRAY_SIZE(bcm283x_socs); i++) { | ||
115 | + TypeInfo ti = { | ||
116 | + .name = bcm283x_socs[i].name, | ||
117 | + .parent = TYPE_BCM283X, | ||
118 | + .class_init = bcm283x_class_init, | ||
119 | + .class_data = (void *) &bcm283x_socs[i], | ||
120 | + }; | ||
121 | + type_register(&ti); | ||
122 | + } | ||
123 | } | ||
124 | |||
125 | type_init(bcm2836_register_types) | ||
126 | diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c | ||
127 | index XXXXXXX..XXXXXXX 100644 | ||
128 | --- a/hw/arm/raspi.c | ||
129 | +++ b/hw/arm/raspi.c | ||
130 | @@ -XXX,XX +XXX,XX @@ static void raspi_init(MachineState *machine, int version) | ||
131 | BusState *bus; | ||
132 | DeviceState *carddev; | ||
133 | |||
134 | - object_initialize(&s->soc, sizeof(s->soc), TYPE_BCM283X); | ||
135 | + object_initialize(&s->soc, sizeof(s->soc), | ||
136 | + version == 3 ? TYPE_BCM2837 : TYPE_BCM2836); | ||
137 | object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc), | ||
138 | &error_abort); | ||
139 | |||
140 | -- | 198 | -- |
141 | 2.16.2 | 199 | 2.20.1 |
142 | 200 | ||
143 | 201 | diff view generated by jsdifflib |
1 | Our BCM2836 type is really a generic one that can be any of | 1 | The ARMv5 architecture didn't specify detailed per-feature ID |
---|---|---|---|
2 | the bcm283x family. Rename it accordingly. We change only | 2 | registers. Now that we're using the MVFR0 register fields to |
3 | the names which are visible via the header file to the | 3 | gate the existence of VFP instructions, we need to set up |
4 | rest of the QEMU code, leaving private function names | 4 | the correct values in the cpu->isar structure so that we still |
5 | in bcm2836.c as they are. | 5 | provide an FPU to the guest. |
6 | 6 | ||
7 | This is a preliminary to making bcm283x be an abstract | 7 | This fixes a regression in the arm926 and arm1026 CPUs, which |
8 | parent class to specific types for the bcm2836 and bcm2837. | 8 | are the only ones that both have VFP and are ARMv5 or earlier. |
9 | This regression was introduced by the VFP refactoring, and more | ||
10 | specifically by commits 1120827fa182f0e76 and 266bd25c485597c, | ||
11 | which accidentally disabled VFP short-vector support and | ||
12 | double-precision support on these CPUs. | ||
9 | 13 | ||
14 | Fixes: 1120827fa182f0e | ||
15 | Fixes: 266bd25c485597c | ||
16 | Fixes: https://bugs.launchpad.net/qemu/+bug/1836192 | ||
17 | Reported-by: Christophe Lyon <christophe.lyon@linaro.org> | ||
10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 18 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
11 | Reviewed-by: Andrew Baumann <Andrew.Baumann@microsoft.com> | 19 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> |
12 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | 20 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> |
13 | Message-id: 20180313153458.26822-6-peter.maydell@linaro.org | 21 | Tested-by: Christophe Lyon <christophe.lyon@linaro.org> |
22 | Message-id: 20190711131241.22231-1-peter.maydell@linaro.org | ||
14 | --- | 23 | --- |
15 | include/hw/arm/bcm2836.h | 12 ++++++------ | 24 | target/arm/cpu.c | 12 ++++++++++++ |
16 | hw/arm/bcm2836.c | 17 +++++++++-------- | 25 | 1 file changed, 12 insertions(+) |
17 | hw/arm/raspi.c | 16 ++++++++-------- | ||
18 | 3 files changed, 23 insertions(+), 22 deletions(-) | ||
19 | 26 | ||
20 | diff --git a/include/hw/arm/bcm2836.h b/include/hw/arm/bcm2836.h | 27 | diff --git a/target/arm/cpu.c b/target/arm/cpu.c |
21 | index XXXXXXX..XXXXXXX 100644 | 28 | index XXXXXXX..XXXXXXX 100644 |
22 | --- a/include/hw/arm/bcm2836.h | 29 | --- a/target/arm/cpu.c |
23 | +++ b/include/hw/arm/bcm2836.h | 30 | +++ b/target/arm/cpu.c |
24 | @@ -XXX,XX +XXX,XX @@ | 31 | @@ -XXX,XX +XXX,XX @@ static void arm926_initfn(Object *obj) |
25 | #include "hw/arm/bcm2835_peripherals.h" | 32 | * set the field to indicate Jazelle support within QEMU. |
26 | #include "hw/intc/bcm2836_control.h" | 33 | */ |
27 | 34 | cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1); | |
28 | -#define TYPE_BCM2836 "bcm2836" | 35 | + /* |
29 | -#define BCM2836(obj) OBJECT_CHECK(BCM2836State, (obj), TYPE_BCM2836) | 36 | + * Similarly, we need to set MVFR0 fields to enable double precision |
30 | +#define TYPE_BCM283X "bcm283x" | 37 | + * and short vector support even though ARMv5 doesn't have this register. |
31 | +#define BCM283X(obj) OBJECT_CHECK(BCM283XState, (obj), TYPE_BCM283X) | 38 | + */ |
32 | 39 | + cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1); | |
33 | -#define BCM2836_NCPUS 4 | 40 | + cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1); |
34 | +#define BCM283X_NCPUS 4 | ||
35 | |||
36 | -typedef struct BCM2836State { | ||
37 | +typedef struct BCM283XState { | ||
38 | /*< private >*/ | ||
39 | DeviceState parent_obj; | ||
40 | /*< public >*/ | ||
41 | @@ -XXX,XX +XXX,XX @@ typedef struct BCM2836State { | ||
42 | char *cpu_type; | ||
43 | uint32_t enabled_cpus; | ||
44 | |||
45 | - ARMCPU cpus[BCM2836_NCPUS]; | ||
46 | + ARMCPU cpus[BCM283X_NCPUS]; | ||
47 | BCM2836ControlState control; | ||
48 | BCM2835PeripheralState peripherals; | ||
49 | -} BCM2836State; | ||
50 | +} BCM283XState; | ||
51 | |||
52 | #endif /* BCM2836_H */ | ||
53 | diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c | ||
54 | index XXXXXXX..XXXXXXX 100644 | ||
55 | --- a/hw/arm/bcm2836.c | ||
56 | +++ b/hw/arm/bcm2836.c | ||
57 | @@ -XXX,XX +XXX,XX @@ | ||
58 | |||
59 | static void bcm2836_init(Object *obj) | ||
60 | { | ||
61 | - BCM2836State *s = BCM2836(obj); | ||
62 | + BCM283XState *s = BCM283X(obj); | ||
63 | |||
64 | object_initialize(&s->control, sizeof(s->control), TYPE_BCM2836_CONTROL); | ||
65 | object_property_add_child(obj, "control", OBJECT(&s->control), NULL); | ||
66 | @@ -XXX,XX +XXX,XX @@ static void bcm2836_init(Object *obj) | ||
67 | |||
68 | static void bcm2836_realize(DeviceState *dev, Error **errp) | ||
69 | { | ||
70 | - BCM2836State *s = BCM2836(dev); | ||
71 | + BCM283XState *s = BCM283X(dev); | ||
72 | Object *obj; | ||
73 | Error *err = NULL; | ||
74 | int n; | ||
75 | @@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp) | ||
76 | /* common peripherals from bcm2835 */ | ||
77 | |||
78 | obj = OBJECT(dev); | ||
79 | - for (n = 0; n < BCM2836_NCPUS; n++) { | ||
80 | + for (n = 0; n < BCM283X_NCPUS; n++) { | ||
81 | object_initialize(&s->cpus[n], sizeof(s->cpus[n]), | ||
82 | s->cpu_type); | ||
83 | object_property_add_child(obj, "cpu[*]", OBJECT(&s->cpus[n]), | ||
84 | @@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp) | ||
85 | sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 1, | ||
86 | qdev_get_gpio_in_named(DEVICE(&s->control), "gpu-fiq", 0)); | ||
87 | |||
88 | - for (n = 0; n < BCM2836_NCPUS; n++) { | ||
89 | + for (n = 0; n < BCM283X_NCPUS; n++) { | ||
90 | /* Mirror bcm2836, which has clusterid set to 0xf | ||
91 | * TODO: this should be converted to a property of ARM_CPU | ||
92 | */ | ||
93 | @@ -XXX,XX +XXX,XX @@ static void bcm2836_realize(DeviceState *dev, Error **errp) | ||
94 | } | 41 | } |
95 | 42 | ||
96 | static Property bcm2836_props[] = { | 43 | static void arm946_initfn(Object *obj) |
97 | - DEFINE_PROP_STRING("cpu-type", BCM2836State, cpu_type), | 44 | @@ -XXX,XX +XXX,XX @@ static void arm1026_initfn(Object *obj) |
98 | - DEFINE_PROP_UINT32("enabled-cpus", BCM2836State, enabled_cpus, BCM2836_NCPUS), | 45 | * set the field to indicate Jazelle support within QEMU. |
99 | + DEFINE_PROP_STRING("cpu-type", BCM283XState, cpu_type), | 46 | */ |
100 | + DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus, | 47 | cpu->isar.id_isar1 = FIELD_DP32(cpu->isar.id_isar1, ID_ISAR1, JAZELLE, 1); |
101 | + BCM283X_NCPUS), | 48 | + /* |
102 | DEFINE_PROP_END_OF_LIST() | 49 | + * Similarly, we need to set MVFR0 fields to enable double precision |
103 | }; | 50 | + * and short vector support even though ARMv5 doesn't have this register. |
104 | 51 | + */ | |
105 | @@ -XXX,XX +XXX,XX @@ static void bcm2836_class_init(ObjectClass *oc, void *data) | 52 | + cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1); |
106 | } | 53 | + cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPDP, 1); |
107 | 54 | ||
108 | static const TypeInfo bcm2836_type_info = { | 55 | { |
109 | - .name = TYPE_BCM2836, | 56 | /* The 1026 had an IFAR at c6,c0,0,1 rather than the ARMv6 c6,c0,0,2 */ |
110 | + .name = TYPE_BCM283X, | ||
111 | .parent = TYPE_DEVICE, | ||
112 | - .instance_size = sizeof(BCM2836State), | ||
113 | + .instance_size = sizeof(BCM283XState), | ||
114 | .instance_init = bcm2836_init, | ||
115 | .class_init = bcm2836_class_init, | ||
116 | }; | ||
117 | diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c | ||
118 | index XXXXXXX..XXXXXXX 100644 | ||
119 | --- a/hw/arm/raspi.c | ||
120 | +++ b/hw/arm/raspi.c | ||
121 | @@ -XXX,XX +XXX,XX @@ | ||
122 | static const int raspi_boardid[] = {[1] = 0xc42, [2] = 0xc43, [3] = 0xc44}; | ||
123 | |||
124 | typedef struct RasPiState { | ||
125 | - BCM2836State soc; | ||
126 | + BCM283XState soc; | ||
127 | MemoryRegion ram; | ||
128 | } RasPiState; | ||
129 | |||
130 | @@ -XXX,XX +XXX,XX @@ static void raspi_init(MachineState *machine, int version) | ||
131 | BusState *bus; | ||
132 | DeviceState *carddev; | ||
133 | |||
134 | - object_initialize(&s->soc, sizeof(s->soc), TYPE_BCM2836); | ||
135 | + object_initialize(&s->soc, sizeof(s->soc), TYPE_BCM283X); | ||
136 | object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc), | ||
137 | &error_abort); | ||
138 | |||
139 | @@ -XXX,XX +XXX,XX @@ static void raspi2_machine_init(MachineClass *mc) | ||
140 | mc->no_floppy = 1; | ||
141 | mc->no_cdrom = 1; | ||
142 | mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a15"); | ||
143 | - mc->max_cpus = BCM2836_NCPUS; | ||
144 | - mc->min_cpus = BCM2836_NCPUS; | ||
145 | - mc->default_cpus = BCM2836_NCPUS; | ||
146 | + mc->max_cpus = BCM283X_NCPUS; | ||
147 | + mc->min_cpus = BCM283X_NCPUS; | ||
148 | + mc->default_cpus = BCM283X_NCPUS; | ||
149 | mc->default_ram_size = 1024 * 1024 * 1024; | ||
150 | mc->ignore_memory_transaction_failures = true; | ||
151 | }; | ||
152 | @@ -XXX,XX +XXX,XX @@ static void raspi3_machine_init(MachineClass *mc) | ||
153 | mc->no_floppy = 1; | ||
154 | mc->no_cdrom = 1; | ||
155 | mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a53"); | ||
156 | - mc->max_cpus = BCM2836_NCPUS; | ||
157 | - mc->min_cpus = BCM2836_NCPUS; | ||
158 | - mc->default_cpus = BCM2836_NCPUS; | ||
159 | + mc->max_cpus = BCM283X_NCPUS; | ||
160 | + mc->min_cpus = BCM283X_NCPUS; | ||
161 | + mc->default_cpus = BCM283X_NCPUS; | ||
162 | mc->default_ram_size = 1024 * 1024 * 1024; | ||
163 | } | ||
164 | DEFINE_MACHINE("raspi3", raspi3_machine_init) | ||
165 | -- | 57 | -- |
166 | 2.16.2 | 58 | 2.20.1 |
167 | 59 | ||
168 | 60 | diff view generated by jsdifflib |
1 | The TypeInfo and state struct for bcm2386 disagree about what the | 1 | In the M-profile architecture, when we do a vector table fetch and it |
---|---|---|---|
2 | parent class is -- the TypeInfo says it's TYPE_SYS_BUS_DEVICE, | 2 | fails, we need to report a HardFault. Whether this is a Secure HF or |
3 | but the BCM2386State struct only defines the parent_obj field | 3 | a NonSecure HF depends on several things. If AIRCR.BFHFNMINS is 0 |
4 | as DeviceState. This would have caused problems if anything | 4 | then HF is always Secure, because there is no NonSecure HardFault. |
5 | actually tried to treat the object as a TYPE_SYS_BUS_DEVICE. | 5 | Otherwise, the answer depends on whether the 'underlying exception' |
6 | Fix the TypeInfo to use TYPE_DEVICE as the parent, since we don't | 6 | (MemManage, BusFault, SecureFault) targets Secure or NonSecure. (In |
7 | need any of the additional functionality TYPE_SYS_BUS_DEVICE | 7 | the pseudocode, this is handled in the Vector() function: the final |
8 | provides. | 8 | exc.isSecure is calculated by looking at the exc.isSecure from the |
9 | exception returned from the memory access, not the isSecure input | ||
10 | argument.) | ||
11 | |||
12 | We weren't doing this correctly, because we were looking at | ||
13 | the target security domain of the exception we were trying to | ||
14 | load the vector table entry for. This produces errors of two kinds: | ||
15 | * a load from the NS vector table which hits the "NS access | ||
16 | to S memory" SecureFault should end up as a Secure HardFault, | ||
17 | but we were raising an NS HardFault | ||
18 | * a load from the S vector table which causes a BusFault | ||
19 | should raise an NS HardFault if BFHFNMINS == 1 (because | ||
20 | in that case all BusFaults are NonSecure), but we were raising | ||
21 | a Secure HardFault | ||
22 | |||
23 | Correct the logic. | ||
24 | |||
25 | We also fix a comment error where we claimed that we might | ||
26 | be escalating MemManage to HardFault, and forgot about SecureFault. | ||
27 | (Vector loads can never hit MPU access faults, because they're | ||
28 | always aligned and always use the default address map.) | ||
9 | 29 | ||
10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 30 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
11 | Reviewed-by: Andrew Baumann <Andrew.Baumann@microsoft.com> | 31 | Message-id: 20190705094823.28905-1-peter.maydell@linaro.org |
12 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
13 | Message-id: 20180313153458.26822-5-peter.maydell@linaro.org | ||
14 | --- | 32 | --- |
15 | hw/arm/bcm2836.c | 2 +- | 33 | target/arm/m_helper.c | 21 +++++++++++++++++---- |
16 | 1 file changed, 1 insertion(+), 1 deletion(-) | 34 | 1 file changed, 17 insertions(+), 4 deletions(-) |
17 | 35 | ||
18 | diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c | 36 | diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c |
19 | index XXXXXXX..XXXXXXX 100644 | 37 | index XXXXXXX..XXXXXXX 100644 |
20 | --- a/hw/arm/bcm2836.c | 38 | --- a/target/arm/m_helper.c |
21 | +++ b/hw/arm/bcm2836.c | 39 | +++ b/target/arm/m_helper.c |
22 | @@ -XXX,XX +XXX,XX @@ static void bcm2836_class_init(ObjectClass *oc, void *data) | 40 | @@ -XXX,XX +XXX,XX @@ static bool arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure, |
23 | 41 | if (sattrs.ns) { | |
24 | static const TypeInfo bcm2836_type_info = { | 42 | attrs.secure = false; |
25 | .name = TYPE_BCM2836, | 43 | } else if (!targets_secure) { |
26 | - .parent = TYPE_SYS_BUS_DEVICE, | 44 | - /* NS access to S memory */ |
27 | + .parent = TYPE_DEVICE, | 45 | + /* |
28 | .instance_size = sizeof(BCM2836State), | 46 | + * NS access to S memory: the underlying exception which we escalate |
29 | .instance_init = bcm2836_init, | 47 | + * to HardFault is SecureFault, which always targets Secure. |
30 | .class_init = bcm2836_class_init, | 48 | + */ |
49 | + exc_secure = true; | ||
50 | goto load_fail; | ||
51 | } | ||
52 | } | ||
53 | @@ -XXX,XX +XXX,XX @@ static bool arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure, | ||
54 | vector_entry = address_space_ldl(arm_addressspace(cs, attrs), addr, | ||
55 | attrs, &result); | ||
56 | if (result != MEMTX_OK) { | ||
57 | + /* | ||
58 | + * Underlying exception is BusFault: its target security state | ||
59 | + * depends on BFHFNMINS. | ||
60 | + */ | ||
61 | + exc_secure = !(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK); | ||
62 | goto load_fail; | ||
63 | } | ||
64 | *pvec = vector_entry; | ||
65 | @@ -XXX,XX +XXX,XX @@ load_fail: | ||
66 | /* | ||
67 | * All vector table fetch fails are reported as HardFault, with | ||
68 | * HFSR.VECTTBL and .FORCED set. (FORCED is set because | ||
69 | - * technically the underlying exception is a MemManage or BusFault | ||
70 | + * technically the underlying exception is a SecureFault or BusFault | ||
71 | * that is escalated to HardFault.) This is a terminal exception, | ||
72 | * so we will either take the HardFault immediately or else enter | ||
73 | * lockup (the latter case is handled in armv7m_nvic_set_pending_derived()). | ||
74 | + * The HardFault is Secure if BFHFNMINS is 0 (meaning that all HFs are | ||
75 | + * secure); otherwise it targets the same security state as the | ||
76 | + * underlying exception. | ||
77 | */ | ||
78 | - exc_secure = targets_secure || | ||
79 | - !(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK); | ||
80 | + if (!(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) { | ||
81 | + exc_secure = true; | ||
82 | + } | ||
83 | env->v7m.hfsr |= R_V7M_HFSR_VECTTBL_MASK | R_V7M_HFSR_FORCED_MASK; | ||
84 | armv7m_nvic_set_pending_derived(env->nvic, ARMV7M_EXCP_HARD, exc_secure); | ||
85 | return false; | ||
31 | -- | 86 | -- |
32 | 2.16.2 | 87 | 2.20.1 |
33 | 88 | ||
34 | 89 | diff view generated by jsdifflib |