1 | ARM bugfixes for rc1... | 1 | The following changes since commit 41fb4c14ee500125dc0ce6fb573cf84b8db29ed0: |
---|---|---|---|
2 | 2 | ||
3 | Merge tag 'linux-user-for-7.0-pull-request' of https://gitlab.com/laurent_vivier/qemu into staging (2022-01-06 11:22:42 -0800) | ||
3 | 4 | ||
4 | The following changes since commit f291910db61b5812e68f1e76afb3ade41d567bea: | 5 | are available in the Git repository at: |
5 | 6 | ||
6 | Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2017-11-09' into staging (2017-11-13 13:13:12 +0000) | 7 | https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220107 |
7 | 8 | ||
8 | are available in the git repository at: | 9 | for you to fetch changes up to b8905cc2dde95ca6be5e56d77053b1ca0b8fc182: |
9 | 10 | ||
10 | git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20171113 | 11 | hw/arm: kudo add lm75s on bus 13 (2022-01-07 17:08:01 +0000) |
11 | |||
12 | for you to fetch changes up to d25f2a72272b9ffe0d06710d6217d1169bc2cc7d: | ||
13 | |||
14 | accel/tcg/translate-all: expand cpu_restore_state addr check (2017-11-13 13:55:27 +0000) | ||
15 | 12 | ||
16 | ---------------------------------------------------------------- | 13 | ---------------------------------------------------------------- |
17 | target-arm queue: | 14 | target-arm queue: |
18 | * translate-a64.c: silence gcc5 warning | 15 | * Add dummy Aspeed AST2600 Display Port MCU (DPMCU) |
19 | * highbank: validate register offset before access | 16 | * Add missing FEAT_TLBIOS instructions |
20 | * MAINTAINERS: Add entries for Smartfusion2 | 17 | * arm_gicv3_its: Various bug fixes and cleanups |
21 | * accel/tcg/translate-all: expand cpu_restore_state addr check | 18 | * kudo-bmc: Add more devices |
22 | (so usermode insn aborts don't crash with an assertion failure) | ||
23 | * fix TCG initialization of some Arm boards by allowing them | ||
24 | to specify min/default number of CPUs to create | ||
25 | 19 | ||
26 | ---------------------------------------------------------------- | 20 | ---------------------------------------------------------------- |
27 | Alex Bennée (1): | 21 | Chris Rauer (1): |
28 | accel/tcg/translate-all: expand cpu_restore_state addr check | 22 | hw/arm: Add kudo i2c eeproms. |
29 | 23 | ||
30 | Alistair Francis (2): | 24 | Idan Horowitz (1): |
31 | xlnx-zynqmp: Properly support the smp command line option | 25 | target/arm: Add missing FEAT_TLBIOS instructions |
32 | xlnx-zcu102: Add an info message deprecating the EP108 | ||
33 | 26 | ||
34 | Emilio G. Cota (4): | 27 | Patrick Venture (2): |
35 | arm/translate-a64: mark path as unreachable to eliminate warning | 28 | hw/arm: add i2c muxes to kudo-bmc |
36 | qom: move CPUClass.tcg_initialize to a global | 29 | hw/arm: kudo add lm75s on bus 13 |
37 | xlnx-zcu102: Specify the max number of CPUs for the EP108 | ||
38 | hw: add .min_cpus and .default_cpus fields to machine_class | ||
39 | 30 | ||
40 | Prasad J Pandit (1): | 31 | Peter Maydell (13): |
41 | highbank: validate register offset before access | 32 | hw/intc/arm_gicv3_its: Correct off-by-one bounds check on rdbase |
33 | hw/intc/arm_gicv3_its: Remove redundant ITS_CTLR_ENABLED define | ||
34 | hw/intc/arm_gicv3_its: Remove maxids union from TableDesc | ||
35 | hw/intc/arm_gicv3_its: Don't return early in extract_table_params() loop | ||
36 | hw/intc/arm_gicv3_its: Reduce code duplication in extract_table_params() | ||
37 | hw/intc/arm_gicv3_its: Correct setting of TableDesc entry_sz | ||
38 | hw/intc/arm_gicv3_its: Don't misuse GITS_TYPE_PHYSICAL define | ||
39 | hw/intc/arm_gicv3_its: Correct handling of MAPI | ||
40 | hw/intc/arm_gicv3_its: Use FIELD macros for DTEs | ||
41 | hw/intc/arm_gicv3_its: Correct comment about CTE RDBase field size | ||
42 | hw/intc/arm_gicv3_its: Use FIELD macros for CTEs | ||
43 | hw/intc/arm_gicv3_its: Fix various off-by-one errors | ||
44 | hw/intc/arm_gicv3_its: Rename max_l2_entries to num_l2_entries | ||
42 | 45 | ||
43 | Subbaraya Sundeep (1): | 46 | Shengtan Mao (1): |
44 | MAINTAINERS: Add entries for Smartfusion2 | 47 | hw/arm: attach MMC to kudo-bmc |
45 | 48 | ||
46 | include/exec/exec-all.h | 11 ++++++++++ | 49 | Troy Lee (1): |
47 | include/hw/boards.h | 5 +++++ | 50 | Add dummy Aspeed AST2600 Display Port MCU (DPMCU) |
48 | include/qom/cpu.h | 1 - | ||
49 | accel/tcg/translate-all.c | 52 ++++++++++++++++++++++++++-------------------- | ||
50 | exec.c | 5 +++-- | ||
51 | hw/arm/exynos4_boards.c | 12 ++++------- | ||
52 | hw/arm/highbank.c | 17 +++++++++++++-- | ||
53 | hw/arm/raspi.c | 2 ++ | ||
54 | hw/arm/xlnx-zcu102.c | 9 +++++++- | ||
55 | hw/arm/xlnx-zynqmp.c | 26 ++++++++++++++--------- | ||
56 | target/arm/translate-a64.c | 2 ++ | ||
57 | vl.c | 21 ++++++++++++++++--- | ||
58 | MAINTAINERS | 17 +++++++++++++++ | ||
59 | qemu-doc.texi | 7 +++++++ | ||
60 | 14 files changed, 137 insertions(+), 50 deletions(-) | ||
61 | 51 | ||
52 | hw/intc/gicv3_internal.h | 40 +++--- | ||
53 | include/hw/arm/aspeed_soc.h | 2 + | ||
54 | include/hw/intc/arm_gicv3_its_common.h | 9 +- | ||
55 | hw/arm/aspeed_ast2600.c | 8 ++ | ||
56 | hw/arm/npcm7xx_boards.c | 27 ++++ | ||
57 | hw/intc/arm_gicv3_its.c | 234 +++++++++++++++------------------ | ||
58 | target/arm/helper.c | 32 +++++ | ||
59 | 7 files changed, 197 insertions(+), 155 deletions(-) | ||
60 | diff view generated by jsdifflib |
1 | From: Alistair Francis <alistair.francis@xilinx.com> | 1 | From: Troy Lee <troy_lee@aspeedtech.com> |
---|---|---|---|
2 | 2 | ||
3 | The EP108 was an early access development board that is no longer used. | 3 | AST2600 Display Port MCU introduces 0x18000000~0x1803FFFF as it's memory |
4 | Add an info message to convert any users to the ZCU102 instead. On QEMU | 4 | and io address. If guest machine try to access DPMCU memory, it will |
5 | they are both identical. | 5 | cause a fatal error. |
6 | 6 | ||
7 | This patch also updated the qemu-doc.texi file to indicate that the | 7 | Signed-off-by: Troy Lee <troy_lee@aspeedtech.com> |
8 | EP108 has been deprecated. | 8 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> |
9 | 9 | Reviewed-by: Cédric Le Goater <clg@kaod.org> | |
10 | Signed-off-by: Alistair Francis <alistair.francis@xilinx.com> | 10 | Message-id: 20211210083034.726610-1-troy_lee@aspeedtech.com |
11 | Reviewed-by: Emilio G. Cota <cota@braap.org> | ||
12 | Message-id: 1510343626-25861-4-git-send-email-cota@braap.org | ||
13 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 11 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
14 | --- | 12 | --- |
15 | hw/arm/xlnx-zcu102.c | 3 +++ | 13 | include/hw/arm/aspeed_soc.h | 2 ++ |
16 | qemu-doc.texi | 7 +++++++ | 14 | hw/arm/aspeed_ast2600.c | 8 ++++++++ |
17 | 2 files changed, 10 insertions(+) | 15 | 2 files changed, 10 insertions(+) |
18 | 16 | ||
19 | diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c | 17 | diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h |
20 | index XXXXXXX..XXXXXXX 100644 | 18 | index XXXXXXX..XXXXXXX 100644 |
21 | --- a/hw/arm/xlnx-zcu102.c | 19 | --- a/include/hw/arm/aspeed_soc.h |
22 | +++ b/hw/arm/xlnx-zcu102.c | 20 | +++ b/include/hw/arm/aspeed_soc.h |
23 | @@ -XXX,XX +XXX,XX @@ static void xlnx_ep108_init(MachineState *machine) | 21 | @@ -XXX,XX +XXX,XX @@ enum { |
24 | { | 22 | ASPEED_DEV_EMMC, |
25 | XlnxZCU102 *s = EP108_MACHINE(machine); | 23 | ASPEED_DEV_KCS, |
26 | 24 | ASPEED_DEV_HACE, | |
27 | + info_report("The Xilinx EP108 machine is deprecated, please use the " | 25 | + ASPEED_DEV_DPMCU, |
28 | + "ZCU102 machine instead. It has the same features supported."); | 26 | + ASPEED_DEV_DP, |
27 | }; | ||
28 | |||
29 | #endif /* ASPEED_SOC_H */ | ||
30 | diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c | ||
31 | index XXXXXXX..XXXXXXX 100644 | ||
32 | --- a/hw/arm/aspeed_ast2600.c | ||
33 | +++ b/hw/arm/aspeed_ast2600.c | ||
34 | @@ -XXX,XX +XXX,XX @@ | ||
35 | #include "sysemu/sysemu.h" | ||
36 | |||
37 | #define ASPEED_SOC_IOMEM_SIZE 0x00200000 | ||
38 | +#define ASPEED_SOC_DPMCU_SIZE 0x00040000 | ||
39 | |||
40 | static const hwaddr aspeed_soc_ast2600_memmap[] = { | ||
41 | [ASPEED_DEV_SRAM] = 0x10000000, | ||
42 | + [ASPEED_DEV_DPMCU] = 0x18000000, | ||
43 | /* 0x16000000 0x17FFFFFF : AHB BUS do LPC Bus bridge */ | ||
44 | [ASPEED_DEV_IOMEM] = 0x1E600000, | ||
45 | [ASPEED_DEV_PWM] = 0x1E610000, | ||
46 | @@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_soc_ast2600_memmap[] = { | ||
47 | [ASPEED_DEV_SCU] = 0x1E6E2000, | ||
48 | [ASPEED_DEV_XDMA] = 0x1E6E7000, | ||
49 | [ASPEED_DEV_ADC] = 0x1E6E9000, | ||
50 | + [ASPEED_DEV_DP] = 0x1E6EB000, | ||
51 | [ASPEED_DEV_VIDEO] = 0x1E700000, | ||
52 | [ASPEED_DEV_SDHCI] = 0x1E740000, | ||
53 | [ASPEED_DEV_EMMC] = 0x1E750000, | ||
54 | @@ -XXX,XX +XXX,XX @@ static const int aspeed_soc_ast2600_irqmap[] = { | ||
55 | [ASPEED_DEV_ETH3] = 32, | ||
56 | [ASPEED_DEV_ETH4] = 33, | ||
57 | [ASPEED_DEV_KCS] = 138, /* 138 -> 142 */ | ||
58 | + [ASPEED_DEV_DP] = 62, | ||
59 | }; | ||
60 | |||
61 | static qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int ctrl) | ||
62 | @@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) | ||
63 | memory_region_add_subregion(get_system_memory(), | ||
64 | sc->memmap[ASPEED_DEV_SRAM], &s->sram); | ||
65 | |||
66 | + /* DPMCU */ | ||
67 | + create_unimplemented_device("aspeed.dpmcu", sc->memmap[ASPEED_DEV_DPMCU], | ||
68 | + ASPEED_SOC_DPMCU_SIZE); | ||
29 | + | 69 | + |
30 | xlnx_zynqmp_init(s, machine); | 70 | /* SCU */ |
31 | } | 71 | if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) { |
32 | 72 | return; | |
33 | diff --git a/qemu-doc.texi b/qemu-doc.texi | ||
34 | index XXXXXXX..XXXXXXX 100644 | ||
35 | --- a/qemu-doc.texi | ||
36 | +++ b/qemu-doc.texi | ||
37 | @@ -XXX,XX +XXX,XX @@ or ``ivshmem-doorbell`` device types. | ||
38 | The ``spapr-pci-vfio-host-bridge'' device type is replaced by | ||
39 | the ``spapr-pci-host-bridge'' device type. | ||
40 | |||
41 | +@section System emulator machines | ||
42 | + | ||
43 | +@subsection Xilinx EP108 (since 2.11.0) | ||
44 | + | ||
45 | +The ``xlnx-ep108'' machine has been replaced by the ``xlnx-zcu102'' machine. | ||
46 | +The ``xlnx-zcu102'' machine has the same features and capabilites in QEMU. | ||
47 | + | ||
48 | @node License | ||
49 | @appendix License | ||
50 | |||
51 | -- | 73 | -- |
52 | 2.7.4 | 74 | 2.25.1 |
53 | 75 | ||
54 | 76 | diff view generated by jsdifflib |
1 | From: Subbaraya Sundeep <sundeep.lkml@gmail.com> | 1 | From: Idan Horowitz <idan.horowitz@gmail.com> |
---|---|---|---|
2 | 2 | ||
3 | Voluntarily add myself as maintainer for Smartfusion2 | 3 | Some of the instructions added by the FEAT_TLBIOS extension were forgotten |
4 | when the extension was originally added to QEMU. | ||
4 | 5 | ||
5 | Signed-off-by: Subbaraya Sundeep <sundeep.lkml@gmail.com> | 6 | Fixes: 7113d618505b ("target/arm: Add support for FEAT_TLBIOS") |
6 | Reviewed-by: Alistair Francis <alistair.francis@xilinx.com> | 7 | Signed-off-by: Idan Horowitz <idan.horowitz@gmail.com> |
7 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | 8 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> |
8 | Message-id: 1510552520-3566-1-git-send-email-sundeep.lkml@gmail.com | 9 | Message-id: 20211231103928.1455657-1-idan.horowitz@gmail.com |
9 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
10 | --- | 11 | --- |
11 | MAINTAINERS | 17 +++++++++++++++++ | 12 | target/arm/helper.c | 32 ++++++++++++++++++++++++++++++++ |
12 | 1 file changed, 17 insertions(+) | 13 | 1 file changed, 32 insertions(+) |
13 | 14 | ||
14 | diff --git a/MAINTAINERS b/MAINTAINERS | 15 | diff --git a/target/arm/helper.c b/target/arm/helper.c |
15 | index XXXXXXX..XXXXXXX 100644 | 16 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/MAINTAINERS | 17 | --- a/target/arm/helper.c |
17 | +++ b/MAINTAINERS | 18 | +++ b/target/arm/helper.c |
18 | @@ -XXX,XX +XXX,XX @@ M: Alistair Francis <alistair@alistair23.me> | 19 | @@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo tlbios_reginfo[] = { |
19 | S: Maintained | 20 | .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 0, |
20 | F: hw/arm/netduino2.c | 21 | .access = PL1_W, .type = ARM_CP_NO_RAW, |
21 | 22 | .writefn = tlbi_aa64_vmalle1is_write }, | |
22 | +SmartFusion2 | 23 | + { .name = "TLBI_VAE1OS", .state = ARM_CP_STATE_AA64, |
23 | +M: Subbaraya Sundeep <sundeep.lkml@gmail.com> | 24 | + .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 1, |
24 | +S: Maintained | 25 | + .access = PL1_W, .type = ARM_CP_NO_RAW, |
25 | +F: hw/arm/msf2-soc.c | 26 | + .writefn = tlbi_aa64_vae1is_write }, |
26 | +F: hw/misc/msf2-sysreg.c | 27 | { .name = "TLBI_ASIDE1OS", .state = ARM_CP_STATE_AA64, |
27 | +F: hw/timer/mss-timer.c | 28 | .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 2, |
28 | +F: hw/ssi/mss-spi.c | 29 | .access = PL1_W, .type = ARM_CP_NO_RAW, |
29 | +F: include/hw/arm/msf2-soc.h | 30 | .writefn = tlbi_aa64_vmalle1is_write }, |
30 | +F: include/hw/misc/msf2-sysreg.h | 31 | + { .name = "TLBI_VAAE1OS", .state = ARM_CP_STATE_AA64, |
31 | +F: include/hw/timer/mss-timer.h | 32 | + .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 3, |
32 | +F: include/hw/ssi/mss-spi.h | 33 | + .access = PL1_W, .type = ARM_CP_NO_RAW, |
33 | + | 34 | + .writefn = tlbi_aa64_vae1is_write }, |
34 | +Emcraft M2S-FG484 | 35 | + { .name = "TLBI_VALE1OS", .state = ARM_CP_STATE_AA64, |
35 | +M: Subbaraya Sundeep <sundeep.lkml@gmail.com> | 36 | + .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 5, |
36 | +S: Maintained | 37 | + .access = PL1_W, .type = ARM_CP_NO_RAW, |
37 | +F: hw/arm/msf2-som.c | 38 | + .writefn = tlbi_aa64_vae1is_write }, |
38 | + | 39 | + { .name = "TLBI_VAALE1OS", .state = ARM_CP_STATE_AA64, |
39 | CRIS Machines | 40 | + .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 7, |
40 | ------------- | 41 | + .access = PL1_W, .type = ARM_CP_NO_RAW, |
41 | Axis Dev88 | 42 | + .writefn = tlbi_aa64_vae1is_write }, |
43 | { .name = "TLBI_ALLE2OS", .state = ARM_CP_STATE_AA64, | ||
44 | .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 0, | ||
45 | .access = PL2_W, .type = ARM_CP_NO_RAW, | ||
46 | .writefn = tlbi_aa64_alle2is_write }, | ||
47 | + { .name = "TLBI_VAE2OS", .state = ARM_CP_STATE_AA64, | ||
48 | + .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 1, | ||
49 | + .access = PL2_W, .type = ARM_CP_NO_RAW, | ||
50 | + .writefn = tlbi_aa64_vae2is_write }, | ||
51 | { .name = "TLBI_ALLE1OS", .state = ARM_CP_STATE_AA64, | ||
52 | .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 4, | ||
53 | .access = PL2_W, .type = ARM_CP_NO_RAW, | ||
54 | .writefn = tlbi_aa64_alle1is_write }, | ||
55 | + { .name = "TLBI_VALE2OS", .state = ARM_CP_STATE_AA64, | ||
56 | + .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 5, | ||
57 | + .access = PL2_W, .type = ARM_CP_NO_RAW, | ||
58 | + .writefn = tlbi_aa64_vae2is_write }, | ||
59 | { .name = "TLBI_VMALLS12E1OS", .state = ARM_CP_STATE_AA64, | ||
60 | .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 6, | ||
61 | .access = PL2_W, .type = ARM_CP_NO_RAW, | ||
62 | @@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo tlbios_reginfo[] = { | ||
63 | .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 0, | ||
64 | .access = PL3_W, .type = ARM_CP_NO_RAW, | ||
65 | .writefn = tlbi_aa64_alle3is_write }, | ||
66 | + { .name = "TLBI_VAE3OS", .state = ARM_CP_STATE_AA64, | ||
67 | + .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 1, | ||
68 | + .access = PL3_W, .type = ARM_CP_NO_RAW, | ||
69 | + .writefn = tlbi_aa64_vae3is_write }, | ||
70 | + { .name = "TLBI_VALE3OS", .state = ARM_CP_STATE_AA64, | ||
71 | + .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 5, | ||
72 | + .access = PL3_W, .type = ARM_CP_NO_RAW, | ||
73 | + .writefn = tlbi_aa64_vae3is_write }, | ||
74 | REGINFO_SENTINEL | ||
75 | }; | ||
76 | |||
42 | -- | 77 | -- |
43 | 2.7.4 | 78 | 2.25.1 |
44 | 79 | ||
45 | 80 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | The checks in the ITS on the rdbase values in guest commands are | ||
2 | off-by-one: they permit the guest to pass us a value equal to | ||
3 | s->gicv3->num_cpu, but the valid values are 0...num_cpu-1. This | ||
4 | meant the guest could cause us to index off the end of the | ||
5 | s->gicv3->cpu[] array when calling gicv3_redist_process_lpi(), and we | ||
6 | would probably crash. | ||
1 | 7 | ||
8 | (This is not a security bug, because this code is only usable | ||
9 | with emulation, not with KVM.) | ||
10 | |||
11 | Cc: qemu-stable@nongnu.org | ||
12 | Fixes: 17fb5e36aabd4b ("hw/intc: GICv3 redistributor ITS processing") | ||
13 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
14 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
15 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
16 | --- | ||
17 | hw/intc/arm_gicv3_its.c | 4 ++-- | ||
18 | 1 file changed, 2 insertions(+), 2 deletions(-) | ||
19 | |||
20 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c | ||
21 | index XXXXXXX..XXXXXXX 100644 | ||
22 | --- a/hw/intc/arm_gicv3_its.c | ||
23 | +++ b/hw/intc/arm_gicv3_its.c | ||
24 | @@ -XXX,XX +XXX,XX @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset, | ||
25 | */ | ||
26 | rdbase = (cte & GITS_CTE_RDBASE_PROCNUM_MASK) >> 1U; | ||
27 | |||
28 | - if (rdbase > s->gicv3->num_cpu) { | ||
29 | + if (rdbase >= s->gicv3->num_cpu) { | ||
30 | return result; | ||
31 | } | ||
32 | |||
33 | @@ -XXX,XX +XXX,XX @@ static bool process_mapc(GICv3ITSState *s, uint32_t offset) | ||
34 | |||
35 | valid = (value & CMD_FIELD_VALID_MASK); | ||
36 | |||
37 | - if ((icid > s->ct.maxids.max_collids) || (rdbase > s->gicv3->num_cpu)) { | ||
38 | + if ((icid > s->ct.maxids.max_collids) || (rdbase >= s->gicv3->num_cpu)) { | ||
39 | qemu_log_mask(LOG_GUEST_ERROR, | ||
40 | "ITS MAPC: invalid collection table attributes " | ||
41 | "icid %d rdbase %" PRIu64 "\n", icid, rdbase); | ||
42 | -- | ||
43 | 2.25.1 | ||
44 | |||
45 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | We currently define a bitmask for the GITS_CTLR ENABLED bit in | ||
2 | two ways: as ITS_CTLR_ENABLED, and via the FIELD() macro as | ||
3 | R_GITS_CTLR_ENABLED_MASK. Consistently use the FIELD macro version | ||
4 | everywhere and remove the redundant ITS_CTLR_ENABLED define. | ||
1 | 5 | ||
6 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
7 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
8 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
9 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
10 | --- | ||
11 | hw/intc/gicv3_internal.h | 2 -- | ||
12 | hw/intc/arm_gicv3_its.c | 20 ++++++++++---------- | ||
13 | 2 files changed, 10 insertions(+), 12 deletions(-) | ||
14 | |||
15 | diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h | ||
16 | index XXXXXXX..XXXXXXX 100644 | ||
17 | --- a/hw/intc/gicv3_internal.h | ||
18 | +++ b/hw/intc/gicv3_internal.h | ||
19 | @@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1) | ||
20 | |||
21 | #define GITS_IDREGS 0xFFD0 | ||
22 | |||
23 | -#define ITS_CTLR_ENABLED (1U) /* ITS Enabled */ | ||
24 | - | ||
25 | #define GITS_BASER_RO_MASK (R_GITS_BASER_ENTRYSIZE_MASK | \ | ||
26 | R_GITS_BASER_TYPE_MASK) | ||
27 | |||
28 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c | ||
29 | index XXXXXXX..XXXXXXX 100644 | ||
30 | --- a/hw/intc/arm_gicv3_its.c | ||
31 | +++ b/hw/intc/arm_gicv3_its.c | ||
32 | @@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s) | ||
33 | uint8_t cmd; | ||
34 | int i; | ||
35 | |||
36 | - if (!(s->ctlr & ITS_CTLR_ENABLED)) { | ||
37 | + if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) { | ||
38 | return; | ||
39 | } | ||
40 | |||
41 | @@ -XXX,XX +XXX,XX @@ static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset, | ||
42 | |||
43 | switch (offset) { | ||
44 | case GITS_TRANSLATER: | ||
45 | - if (s->ctlr & ITS_CTLR_ENABLED) { | ||
46 | + if (s->ctlr & R_GITS_CTLR_ENABLED_MASK) { | ||
47 | devid = attrs.requester_id; | ||
48 | result = process_its_cmd(s, data, devid, NONE); | ||
49 | } | ||
50 | @@ -XXX,XX +XXX,XX @@ static bool its_writel(GICv3ITSState *s, hwaddr offset, | ||
51 | switch (offset) { | ||
52 | case GITS_CTLR: | ||
53 | if (value & R_GITS_CTLR_ENABLED_MASK) { | ||
54 | - s->ctlr |= ITS_CTLR_ENABLED; | ||
55 | + s->ctlr |= R_GITS_CTLR_ENABLED_MASK; | ||
56 | extract_table_params(s); | ||
57 | extract_cmdq_params(s); | ||
58 | s->creadr = 0; | ||
59 | process_cmdq(s); | ||
60 | } else { | ||
61 | - s->ctlr &= ~ITS_CTLR_ENABLED; | ||
62 | + s->ctlr &= ~R_GITS_CTLR_ENABLED_MASK; | ||
63 | } | ||
64 | break; | ||
65 | case GITS_CBASER: | ||
66 | @@ -XXX,XX +XXX,XX @@ static bool its_writel(GICv3ITSState *s, hwaddr offset, | ||
67 | * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is | ||
68 | * already enabled | ||
69 | */ | ||
70 | - if (!(s->ctlr & ITS_CTLR_ENABLED)) { | ||
71 | + if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) { | ||
72 | s->cbaser = deposit64(s->cbaser, 0, 32, value); | ||
73 | s->creadr = 0; | ||
74 | s->cwriter = s->creadr; | ||
75 | @@ -XXX,XX +XXX,XX @@ static bool its_writel(GICv3ITSState *s, hwaddr offset, | ||
76 | * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is | ||
77 | * already enabled | ||
78 | */ | ||
79 | - if (!(s->ctlr & ITS_CTLR_ENABLED)) { | ||
80 | + if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) { | ||
81 | s->cbaser = deposit64(s->cbaser, 32, 32, value); | ||
82 | s->creadr = 0; | ||
83 | s->cwriter = s->creadr; | ||
84 | @@ -XXX,XX +XXX,XX @@ static bool its_writel(GICv3ITSState *s, hwaddr offset, | ||
85 | * IMPDEF choice:- GITS_BASERn register becomes RO if ITS is | ||
86 | * already enabled | ||
87 | */ | ||
88 | - if (!(s->ctlr & ITS_CTLR_ENABLED)) { | ||
89 | + if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) { | ||
90 | index = (offset - GITS_BASER) / 8; | ||
91 | |||
92 | if (offset & 7) { | ||
93 | @@ -XXX,XX +XXX,XX @@ static bool its_writell(GICv3ITSState *s, hwaddr offset, | ||
94 | * IMPDEF choice:- GITS_BASERn register becomes RO if ITS is | ||
95 | * already enabled | ||
96 | */ | ||
97 | - if (!(s->ctlr & ITS_CTLR_ENABLED)) { | ||
98 | + if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) { | ||
99 | index = (offset - GITS_BASER) / 8; | ||
100 | s->baser[index] &= GITS_BASER_RO_MASK; | ||
101 | s->baser[index] |= (value & ~GITS_BASER_RO_MASK); | ||
102 | @@ -XXX,XX +XXX,XX @@ static bool its_writell(GICv3ITSState *s, hwaddr offset, | ||
103 | * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is | ||
104 | * already enabled | ||
105 | */ | ||
106 | - if (!(s->ctlr & ITS_CTLR_ENABLED)) { | ||
107 | + if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) { | ||
108 | s->cbaser = value; | ||
109 | s->creadr = 0; | ||
110 | s->cwriter = s->creadr; | ||
111 | @@ -XXX,XX +XXX,XX @@ static void gicv3_its_reset(DeviceState *dev) | ||
112 | |||
113 | static void gicv3_its_post_load(GICv3ITSState *s) | ||
114 | { | ||
115 | - if (s->ctlr & ITS_CTLR_ENABLED) { | ||
116 | + if (s->ctlr & R_GITS_CTLR_ENABLED_MASK) { | ||
117 | extract_table_params(s); | ||
118 | extract_cmdq_params(s); | ||
119 | } | ||
120 | -- | ||
121 | 2.25.1 | ||
122 | |||
123 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | The TableDesc struct defines properties of the in-guest-memory tables | ||
2 | which the guest tells us about by writing to the GITS_BASER<n> | ||
3 | registers. This struct currently has a union 'maxids', but all the | ||
4 | fields of the union have the same type (uint32_t) and do the same | ||
5 | thing (record one-greater-than the maximum ID value that can be used | ||
6 | as an index into the table). | ||
1 | 7 | ||
8 | We're about to add another table type (the GICv4 vPE table); rather | ||
9 | than adding another specifically-named union field for that table | ||
10 | type with the same type as the other union fields, remove the union | ||
11 | entirely and just have a 'uint32_t max_ids' struct field. | ||
12 | |||
13 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
14 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
15 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
16 | --- | ||
17 | include/hw/intc/arm_gicv3_its_common.h | 5 +---- | ||
18 | hw/intc/arm_gicv3_its.c | 20 ++++++++++---------- | ||
19 | 2 files changed, 11 insertions(+), 14 deletions(-) | ||
20 | |||
21 | diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h | ||
22 | index XXXXXXX..XXXXXXX 100644 | ||
23 | --- a/include/hw/intc/arm_gicv3_its_common.h | ||
24 | +++ b/include/hw/intc/arm_gicv3_its_common.h | ||
25 | @@ -XXX,XX +XXX,XX @@ typedef struct { | ||
26 | uint16_t entry_sz; | ||
27 | uint32_t page_sz; | ||
28 | uint32_t max_entries; | ||
29 | - union { | ||
30 | - uint32_t max_devids; | ||
31 | - uint32_t max_collids; | ||
32 | - } maxids; | ||
33 | + uint32_t max_ids; | ||
34 | uint64_t base_addr; | ||
35 | } TableDesc; | ||
36 | |||
37 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c | ||
38 | index XXXXXXX..XXXXXXX 100644 | ||
39 | --- a/hw/intc/arm_gicv3_its.c | ||
40 | +++ b/hw/intc/arm_gicv3_its.c | ||
41 | @@ -XXX,XX +XXX,XX @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset, | ||
42 | * In this implementation, in case of guest errors we ignore the | ||
43 | * command and move onto the next command in the queue. | ||
44 | */ | ||
45 | - if (devid > s->dt.maxids.max_devids) { | ||
46 | + if (devid > s->dt.max_ids) { | ||
47 | qemu_log_mask(LOG_GUEST_ERROR, | ||
48 | "%s: invalid command attributes: devid %d>%d", | ||
49 | - __func__, devid, s->dt.maxids.max_devids); | ||
50 | + __func__, devid, s->dt.max_ids); | ||
51 | |||
52 | } else if (!dte_valid || !ite_valid || !cte_valid) { | ||
53 | qemu_log_mask(LOG_GUEST_ERROR, | ||
54 | @@ -XXX,XX +XXX,XX @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset, | ||
55 | max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1; | ||
56 | } | ||
57 | |||
58 | - if ((devid > s->dt.maxids.max_devids) || (icid > s->ct.maxids.max_collids) | ||
59 | + if ((devid > s->dt.max_ids) || (icid > s->ct.max_ids) | ||
60 | || !dte_valid || (eventid > max_eventid) || | ||
61 | (!ignore_pInt && (((pIntid < GICV3_LPI_INTID_START) || | ||
62 | (pIntid > max_Intid)) && (pIntid != INTID_SPURIOUS)))) { | ||
63 | @@ -XXX,XX +XXX,XX @@ static bool process_mapc(GICv3ITSState *s, uint32_t offset) | ||
64 | |||
65 | valid = (value & CMD_FIELD_VALID_MASK); | ||
66 | |||
67 | - if ((icid > s->ct.maxids.max_collids) || (rdbase >= s->gicv3->num_cpu)) { | ||
68 | + if ((icid > s->ct.max_ids) || (rdbase >= s->gicv3->num_cpu)) { | ||
69 | qemu_log_mask(LOG_GUEST_ERROR, | ||
70 | "ITS MAPC: invalid collection table attributes " | ||
71 | "icid %d rdbase %" PRIu64 "\n", icid, rdbase); | ||
72 | @@ -XXX,XX +XXX,XX @@ static bool process_mapd(GICv3ITSState *s, uint64_t value, uint32_t offset) | ||
73 | |||
74 | valid = (value & CMD_FIELD_VALID_MASK); | ||
75 | |||
76 | - if ((devid > s->dt.maxids.max_devids) || | ||
77 | + if ((devid > s->dt.max_ids) || | ||
78 | (size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) { | ||
79 | qemu_log_mask(LOG_GUEST_ERROR, | ||
80 | "ITS MAPD: invalid device table attributes " | ||
81 | @@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s) | ||
82 | (page_sz / s->dt.entry_sz)); | ||
83 | } | ||
84 | |||
85 | - s->dt.maxids.max_devids = (1UL << (FIELD_EX64(s->typer, GITS_TYPER, | ||
86 | - DEVBITS) + 1)); | ||
87 | + s->dt.max_ids = (1UL << (FIELD_EX64(s->typer, GITS_TYPER, | ||
88 | + DEVBITS) + 1)); | ||
89 | |||
90 | s->dt.base_addr = baser_base_addr(value, page_sz); | ||
91 | |||
92 | @@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s) | ||
93 | } | ||
94 | |||
95 | if (FIELD_EX64(s->typer, GITS_TYPER, CIL)) { | ||
96 | - s->ct.maxids.max_collids = (1UL << (FIELD_EX64(s->typer, | ||
97 | - GITS_TYPER, CIDBITS) + 1)); | ||
98 | + s->ct.max_ids = (1UL << (FIELD_EX64(s->typer, | ||
99 | + GITS_TYPER, CIDBITS) + 1)); | ||
100 | } else { | ||
101 | /* 16-bit CollectionId supported when CIL == 0 */ | ||
102 | - s->ct.maxids.max_collids = (1UL << 16); | ||
103 | + s->ct.max_ids = (1UL << 16); | ||
104 | } | ||
105 | |||
106 | s->ct.base_addr = baser_base_addr(value, page_sz); | ||
107 | -- | ||
108 | 2.25.1 | ||
109 | |||
110 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | In extract_table_params() we process each GITS_BASER<n> register. If | ||
2 | the register's Valid bit is not set, this means there is no | ||
3 | in-guest-memory table and so we should not try to interpret the other | ||
4 | fields in the register. This was incorrectly coded as a 'return' | ||
5 | rather than a 'break', so instead of looping round to process the | ||
6 | next GITS_BASER<n> we would stop entirely, treating any later tables | ||
7 | as being not valid also. | ||
1 | 8 | ||
9 | This has no real guest-visible effects because (since we don't have | ||
10 | GITS_TYPER.HCC != 0) the guest must in any case set up all the | ||
11 | GITS_BASER<n> to point to valid tables, so this only happens in an | ||
12 | odd misbehaving-guest corner case. | ||
13 | |||
14 | Fix the check to 'break', so that we leave the case statement and | ||
15 | loop back around to the next GITS_BASER<n>. | ||
16 | |||
17 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
18 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
19 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
20 | --- | ||
21 | hw/intc/arm_gicv3_its.c | 4 ++-- | ||
22 | 1 file changed, 2 insertions(+), 2 deletions(-) | ||
23 | |||
24 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c | ||
25 | index XXXXXXX..XXXXXXX 100644 | ||
26 | --- a/hw/intc/arm_gicv3_its.c | ||
27 | +++ b/hw/intc/arm_gicv3_its.c | ||
28 | @@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s) | ||
29 | s->dt.valid = FIELD_EX64(value, GITS_BASER, VALID); | ||
30 | |||
31 | if (!s->dt.valid) { | ||
32 | - return; | ||
33 | + break; | ||
34 | } | ||
35 | |||
36 | s->dt.page_sz = page_sz; | ||
37 | @@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s) | ||
38 | * hence writes are discarded if ct.valid is 0 | ||
39 | */ | ||
40 | if (!s->ct.valid) { | ||
41 | - return; | ||
42 | + break; | ||
43 | } | ||
44 | |||
45 | s->ct.page_sz = page_sz; | ||
46 | -- | ||
47 | 2.25.1 | ||
48 | |||
49 | diff view generated by jsdifflib |
1 | From: Alex Bennée <alex.bennee@linaro.org> | 1 | The extract_table_params() decodes the fields in the GITS_BASER<n> |
---|---|---|---|
2 | registers into TableDesc structs. Since the fields are the same for | ||
3 | all the GITS_BASER<n> registers, there is currently a lot of code | ||
4 | duplication within the switch (type) statement. Refactor so that the | ||
5 | cases include only what is genuinely different for each type: | ||
6 | the calculation of the number of bits in the ID value that indexes | ||
7 | into the table. | ||
2 | 8 | ||
3 | We are still seeing signals during translation time when we walk over | 9 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
4 | a page protection boundary. This expands the check to ensure the host | 10 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> |
5 | PC is inside the code generation buffer. The original suggestion was | 11 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> |
6 | to check versus tcg_ctx.code_gen_ptr but as we now segment the | 12 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> |
7 | translation buffer we have to settle for just a general check for | 13 | --- |
8 | being inside. | 14 | hw/intc/arm_gicv3_its.c | 97 +++++++++++++++++------------------------ |
15 | 1 file changed, 40 insertions(+), 57 deletions(-) | ||
9 | 16 | ||
10 | I've also fixed up the declaration to make it clear it can deal with | 17 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c |
11 | invalid addresses. A later patch will fix up the call sites. | ||
12 | |||
13 | Signed-off-by: Alex Bennée <alex.bennee@linaro.org> | ||
14 | Reported-by: Peter Maydell <peter.maydell@linaro.org> | ||
15 | Reviewed-by: Laurent Vivier <laurent@vivier.eu> | ||
16 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
17 | Message-id: 20171108153245.20740-2-alex.bennee@linaro.org | ||
18 | Suggested-by: Paolo Bonzini <pbonzini@redhat.com> | ||
19 | Cc: Richard Henderson <rth@twiddle.net> | ||
20 | Tested-by: Peter Maydell <peter.maydell@linaro.org> | ||
21 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
22 | --- | ||
23 | include/exec/exec-all.h | 11 ++++++++++ | ||
24 | accel/tcg/translate-all.c | 52 ++++++++++++++++++++++++++--------------------- | ||
25 | 2 files changed, 40 insertions(+), 23 deletions(-) | ||
26 | |||
27 | diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h | ||
28 | index XXXXXXX..XXXXXXX 100644 | 18 | index XXXXXXX..XXXXXXX 100644 |
29 | --- a/include/exec/exec-all.h | 19 | --- a/hw/intc/arm_gicv3_its.c |
30 | +++ b/include/exec/exec-all.h | 20 | +++ b/hw/intc/arm_gicv3_its.c |
31 | @@ -XXX,XX +XXX,XX @@ void restore_state_to_opc(CPUArchState *env, struct TranslationBlock *tb, | 21 | @@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s) |
32 | target_ulong *data); | 22 | uint64_t value; |
33 | 23 | ||
34 | void cpu_gen_init(void); | 24 | for (int i = 0; i < 8; i++) { |
25 | + TableDesc *td; | ||
26 | + int idbits; | ||
35 | + | 27 | + |
36 | +/** | 28 | value = s->baser[i]; |
37 | + * cpu_restore_state: | 29 | |
38 | + * @cpu: the vCPU state is to be restore to | 30 | if (!value) { |
39 | + * @searched_pc: the host PC the fault occurred at | 31 | @@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s) |
40 | + * @return: true if state was restored, false otherwise | 32 | type = FIELD_EX64(value, GITS_BASER, TYPE); |
41 | + * | 33 | |
42 | + * Attempt to restore the state for a fault occurring in translated | 34 | switch (type) { |
43 | + * code. If the searched_pc is not in translated code no state is | 35 | - |
44 | + * restored and the function returns false. | 36 | case GITS_BASER_TYPE_DEVICE: |
45 | + */ | 37 | - memset(&s->dt, 0 , sizeof(s->dt)); |
46 | bool cpu_restore_state(CPUState *cpu, uintptr_t searched_pc); | 38 | - s->dt.valid = FIELD_EX64(value, GITS_BASER, VALID); |
47 | 39 | - | |
48 | void QEMU_NORETURN cpu_loop_exit_noexc(CPUState *cpu); | 40 | - if (!s->dt.valid) { |
49 | diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c | 41 | - break; |
50 | index XXXXXXX..XXXXXXX 100644 | 42 | - } |
51 | --- a/accel/tcg/translate-all.c | 43 | - |
52 | +++ b/accel/tcg/translate-all.c | 44 | - s->dt.page_sz = page_sz; |
53 | @@ -XXX,XX +XXX,XX @@ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb, | 45 | - s->dt.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT); |
54 | return 0; | 46 | - s->dt.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE); |
47 | - | ||
48 | - if (!s->dt.indirect) { | ||
49 | - s->dt.max_entries = (num_pages * page_sz) / s->dt.entry_sz; | ||
50 | - } else { | ||
51 | - s->dt.max_entries = (((num_pages * page_sz) / | ||
52 | - L1TABLE_ENTRY_SIZE) * | ||
53 | - (page_sz / s->dt.entry_sz)); | ||
54 | - } | ||
55 | - | ||
56 | - s->dt.max_ids = (1UL << (FIELD_EX64(s->typer, GITS_TYPER, | ||
57 | - DEVBITS) + 1)); | ||
58 | - | ||
59 | - s->dt.base_addr = baser_base_addr(value, page_sz); | ||
60 | - | ||
61 | + td = &s->dt; | ||
62 | + idbits = FIELD_EX64(s->typer, GITS_TYPER, DEVBITS) + 1; | ||
63 | break; | ||
64 | - | ||
65 | case GITS_BASER_TYPE_COLLECTION: | ||
66 | - memset(&s->ct, 0 , sizeof(s->ct)); | ||
67 | - s->ct.valid = FIELD_EX64(value, GITS_BASER, VALID); | ||
68 | - | ||
69 | - /* | ||
70 | - * GITS_TYPER.HCC is 0 for this implementation | ||
71 | - * hence writes are discarded if ct.valid is 0 | ||
72 | - */ | ||
73 | - if (!s->ct.valid) { | ||
74 | - break; | ||
75 | - } | ||
76 | - | ||
77 | - s->ct.page_sz = page_sz; | ||
78 | - s->ct.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT); | ||
79 | - s->ct.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE); | ||
80 | - | ||
81 | - if (!s->ct.indirect) { | ||
82 | - s->ct.max_entries = (num_pages * page_sz) / s->ct.entry_sz; | ||
83 | - } else { | ||
84 | - s->ct.max_entries = (((num_pages * page_sz) / | ||
85 | - L1TABLE_ENTRY_SIZE) * | ||
86 | - (page_sz / s->ct.entry_sz)); | ||
87 | - } | ||
88 | - | ||
89 | + td = &s->ct; | ||
90 | if (FIELD_EX64(s->typer, GITS_TYPER, CIL)) { | ||
91 | - s->ct.max_ids = (1UL << (FIELD_EX64(s->typer, | ||
92 | - GITS_TYPER, CIDBITS) + 1)); | ||
93 | + idbits = FIELD_EX64(s->typer, GITS_TYPER, CIDBITS) + 1; | ||
94 | } else { | ||
95 | /* 16-bit CollectionId supported when CIL == 0 */ | ||
96 | - s->ct.max_ids = (1UL << 16); | ||
97 | + idbits = 16; | ||
98 | } | ||
99 | - | ||
100 | - s->ct.base_addr = baser_base_addr(value, page_sz); | ||
101 | - | ||
102 | break; | ||
103 | - | ||
104 | default: | ||
105 | - break; | ||
106 | + /* | ||
107 | + * GITS_BASER<n>.TYPE is read-only, so GITS_BASER_RO_MASK | ||
108 | + * ensures we will only see type values corresponding to | ||
109 | + * the values set up in gicv3_its_reset(). | ||
110 | + */ | ||
111 | + g_assert_not_reached(); | ||
112 | } | ||
113 | + | ||
114 | + memset(td, 0, sizeof(*td)); | ||
115 | + td->valid = FIELD_EX64(value, GITS_BASER, VALID); | ||
116 | + /* | ||
117 | + * If GITS_BASER<n>.Valid is 0 for any <n> then we will not process | ||
118 | + * interrupts. (GITS_TYPER.HCC is 0 for this implementation, so we | ||
119 | + * do not have a special case where the GITS_BASER<n>.Valid bit is 0 | ||
120 | + * for the register corresponding to the Collection table but we | ||
121 | + * still have to process interrupts using non-memory-backed | ||
122 | + * Collection table entries.) | ||
123 | + */ | ||
124 | + if (!td->valid) { | ||
125 | + continue; | ||
126 | + } | ||
127 | + td->page_sz = page_sz; | ||
128 | + td->indirect = FIELD_EX64(value, GITS_BASER, INDIRECT); | ||
129 | + td->entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE); | ||
130 | + td->base_addr = baser_base_addr(value, page_sz); | ||
131 | + if (!td->indirect) { | ||
132 | + td->max_entries = (num_pages * page_sz) / td->entry_sz; | ||
133 | + } else { | ||
134 | + td->max_entries = (((num_pages * page_sz) / | ||
135 | + L1TABLE_ENTRY_SIZE) * | ||
136 | + (page_sz / td->entry_sz)); | ||
137 | + } | ||
138 | + td->max_ids = 1ULL << idbits; | ||
139 | } | ||
55 | } | 140 | } |
56 | 141 | ||
57 | -bool cpu_restore_state(CPUState *cpu, uintptr_t retaddr) | ||
58 | +bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc) | ||
59 | { | ||
60 | TranslationBlock *tb; | ||
61 | bool r = false; | ||
62 | + uintptr_t check_offset; | ||
63 | |||
64 | - /* A retaddr of zero is invalid so we really shouldn't have ended | ||
65 | - * up here. The target code has likely forgotten to check retaddr | ||
66 | - * != 0 before attempting to restore state. We return early to | ||
67 | - * avoid blowing up on a recursive tb_lock(). The target must have | ||
68 | - * previously survived a failed cpu_restore_state because | ||
69 | - * tb_find_pc(0) would have failed anyway. It still should be | ||
70 | - * fixed though. | ||
71 | + /* The host_pc has to be in the region of current code buffer. If | ||
72 | + * it is not we will not be able to resolve it here. The two cases | ||
73 | + * where host_pc will not be correct are: | ||
74 | + * | ||
75 | + * - fault during translation (instruction fetch) | ||
76 | + * - fault from helper (not using GETPC() macro) | ||
77 | + * | ||
78 | + * Either way we need return early to avoid blowing up on a | ||
79 | + * recursive tb_lock() as we can't resolve it here. | ||
80 | + * | ||
81 | + * We are using unsigned arithmetic so if host_pc < | ||
82 | + * tcg_init_ctx.code_gen_buffer check_offset will wrap to way | ||
83 | + * above the code_gen_buffer_size | ||
84 | */ | ||
85 | - | ||
86 | - if (!retaddr) { | ||
87 | - return r; | ||
88 | - } | ||
89 | - | ||
90 | - tb_lock(); | ||
91 | - tb = tb_find_pc(retaddr); | ||
92 | - if (tb) { | ||
93 | - cpu_restore_state_from_tb(cpu, tb, retaddr); | ||
94 | - if (tb->cflags & CF_NOCACHE) { | ||
95 | - /* one-shot translation, invalidate it immediately */ | ||
96 | - tb_phys_invalidate(tb, -1); | ||
97 | - tb_remove(tb); | ||
98 | + check_offset = host_pc - (uintptr_t) tcg_init_ctx.code_gen_buffer; | ||
99 | + | ||
100 | + if (check_offset < tcg_init_ctx.code_gen_buffer_size) { | ||
101 | + tb_lock(); | ||
102 | + tb = tb_find_pc(host_pc); | ||
103 | + if (tb) { | ||
104 | + cpu_restore_state_from_tb(cpu, tb, host_pc); | ||
105 | + if (tb->cflags & CF_NOCACHE) { | ||
106 | + /* one-shot translation, invalidate it immediately */ | ||
107 | + tb_phys_invalidate(tb, -1); | ||
108 | + tb_remove(tb); | ||
109 | + } | ||
110 | + r = true; | ||
111 | } | ||
112 | - r = true; | ||
113 | + tb_unlock(); | ||
114 | } | ||
115 | - tb_unlock(); | ||
116 | |||
117 | return r; | ||
118 | } | ||
119 | -- | 142 | -- |
120 | 2.7.4 | 143 | 2.25.1 |
121 | 144 | ||
122 | 145 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | We set the TableDesc entry_sz field from the appropriate | ||
2 | GITS_BASER.ENTRYSIZE field. That ID register field specifies the | ||
3 | number of bytes per table entry minus one. However when we use | ||
4 | td->entry_sz we assume it to be the number of bytes per table entry | ||
5 | (for instance we calculate the number of entries in a page by | ||
6 | dividing the page size by the entry size). | ||
1 | 7 | ||
8 | The effects of this bug are: | ||
9 | * we miscalculate the maximum number of entries in the table, | ||
10 | so our checks on guest index values are wrong (too lax) | ||
11 | * when looking up an entry in the second level of an indirect | ||
12 | table, we calculate an incorrect index into the L2 table. | ||
13 | Because we make the same incorrect calculation on both | ||
14 | reads and writes of the L2 table, the guest won't notice | ||
15 | unless it's unlucky enough to use an index value that | ||
16 | causes us to index off the end of the L2 table page and | ||
17 | cause guest memory corruption in whatever follows | ||
18 | |||
19 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
20 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
21 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
22 | --- | ||
23 | hw/intc/arm_gicv3_its.c | 2 +- | ||
24 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
25 | |||
26 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c | ||
27 | index XXXXXXX..XXXXXXX 100644 | ||
28 | --- a/hw/intc/arm_gicv3_its.c | ||
29 | +++ b/hw/intc/arm_gicv3_its.c | ||
30 | @@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s) | ||
31 | } | ||
32 | td->page_sz = page_sz; | ||
33 | td->indirect = FIELD_EX64(value, GITS_BASER, INDIRECT); | ||
34 | - td->entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE); | ||
35 | + td->entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE) + 1; | ||
36 | td->base_addr = baser_base_addr(value, page_sz); | ||
37 | if (!td->indirect) { | ||
38 | td->max_entries = (num_pages * page_sz) / td->entry_sz; | ||
39 | -- | ||
40 | 2.25.1 | ||
41 | |||
42 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | The GITS_TYPE_PHYSICAL define is the value we set the | ||
2 | GITS_TYPER.Physical field to -- this is 1 to indicate that we support | ||
3 | physical LPIs. (Support for virtual LPIs is the GITS_TYPER.Virtual | ||
4 | field.) We also use this define as the *value* that we write into an | ||
5 | interrupt translation table entry's INTTYPE field, which should be 1 | ||
6 | for a physical interrupt and 0 for a virtual interrupt. Finally, we | ||
7 | use it as a *mask* when we read the interrupt translation table entry | ||
8 | INTTYPE field. | ||
1 | 9 | ||
10 | Untangle this confusion: define an ITE_INTTYPE_VIRTUAL and | ||
11 | ITE_INTTYPE_PHYSICAL to be the valid values of the ITE INTTYPE | ||
12 | field, and replace the ad-hoc collection of ITE_ENTRY_* defines with | ||
13 | use of the FIELD() macro to define the fields of an ITE and the | ||
14 | FIELD_EX64() and FIELD_DP64() macros to read and write them. | ||
15 | We use ITE in the new setup, rather than ITE_ENTRY, because | ||
16 | ITE stands for "Interrupt translation entry" and so the extra | ||
17 | "entry" would be redundant. | ||
18 | |||
19 | We take the opportunity to correct the name of the field that holds | ||
20 | the GICv4 'doorbell' interrupt ID (this is always the value 1023 in a | ||
21 | GICv3, which is why we were calling it the 'spurious' field). | ||
22 | |||
23 | The GITS_TYPE_PHYSICAL define is then used in only one place, where | ||
24 | we set the initial GITS_TYPER value. Since GITS_TYPER.Physical is | ||
25 | essentially a boolean, hiding the '1' value behind a macro is more | ||
26 | confusing than helpful, so expand out the macro there and remove the | ||
27 | define entirely. | ||
28 | |||
29 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
30 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
31 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
32 | --- | ||
33 | hw/intc/gicv3_internal.h | 26 ++++++++++++++------------ | ||
34 | hw/intc/arm_gicv3_its.c | 30 +++++++++++++----------------- | ||
35 | 2 files changed, 27 insertions(+), 29 deletions(-) | ||
36 | |||
37 | diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h | ||
38 | index XXXXXXX..XXXXXXX 100644 | ||
39 | --- a/hw/intc/gicv3_internal.h | ||
40 | +++ b/hw/intc/gicv3_internal.h | ||
41 | @@ -XXX,XX +XXX,XX @@ FIELD(MAPC, RDBASE, 16, 32) | ||
42 | #define L2_TABLE_VALID_MASK CMD_FIELD_VALID_MASK | ||
43 | #define TABLE_ENTRY_VALID_MASK (1ULL << 0) | ||
44 | |||
45 | -/** | ||
46 | - * Default features advertised by this version of ITS | ||
47 | - */ | ||
48 | -/* Physical LPIs supported */ | ||
49 | -#define GITS_TYPE_PHYSICAL (1U << 0) | ||
50 | - | ||
51 | /* | ||
52 | * 12 bytes Interrupt translation Table Entry size | ||
53 | * as per Table 5.3 in GICv3 spec | ||
54 | * ITE Lower 8 Bytes | ||
55 | * Bits: | 49 ... 26 | 25 ... 2 | 1 | 0 | | ||
56 | - * Values: | 1023 | IntNum | IntType | Valid | | ||
57 | + * Values: | Doorbell | IntNum | IntType | Valid | | ||
58 | * ITE Higher 4 Bytes | ||
59 | * Bits: | 31 ... 16 | 15 ...0 | | ||
60 | * Values: | vPEID | ICID | | ||
61 | + * (When Doorbell is unused, as it always is in GICv3, it is 1023) | ||
62 | */ | ||
63 | #define ITS_ITT_ENTRY_SIZE 0xC | ||
64 | -#define ITE_ENTRY_INTTYPE_SHIFT 1 | ||
65 | -#define ITE_ENTRY_INTID_SHIFT 2 | ||
66 | -#define ITE_ENTRY_INTID_MASK MAKE_64BIT_MASK(2, 24) | ||
67 | -#define ITE_ENTRY_INTSP_SHIFT 26 | ||
68 | -#define ITE_ENTRY_ICID_MASK MAKE_64BIT_MASK(0, 16) | ||
69 | + | ||
70 | +FIELD(ITE_L, VALID, 0, 1) | ||
71 | +FIELD(ITE_L, INTTYPE, 1, 1) | ||
72 | +FIELD(ITE_L, INTID, 2, 24) | ||
73 | +FIELD(ITE_L, DOORBELL, 26, 24) | ||
74 | + | ||
75 | +FIELD(ITE_H, ICID, 0, 16) | ||
76 | +FIELD(ITE_H, VPEID, 16, 16) | ||
77 | + | ||
78 | +/* Possible values for ITE_L INTTYPE */ | ||
79 | +#define ITE_INTTYPE_VIRTUAL 0 | ||
80 | +#define ITE_INTTYPE_PHYSICAL 1 | ||
81 | |||
82 | /* 16 bits EventId */ | ||
83 | #define ITS_IDBITS GICD_TYPER_IDBITS | ||
84 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c | ||
85 | index XXXXXXX..XXXXXXX 100644 | ||
86 | --- a/hw/intc/arm_gicv3_its.c | ||
87 | +++ b/hw/intc/arm_gicv3_its.c | ||
88 | @@ -XXX,XX +XXX,XX @@ static bool get_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte, | ||
89 | MEMTXATTRS_UNSPECIFIED, res); | ||
90 | |||
91 | if (*res == MEMTX_OK) { | ||
92 | - if (ite.itel & TABLE_ENTRY_VALID_MASK) { | ||
93 | - if ((ite.itel >> ITE_ENTRY_INTTYPE_SHIFT) & | ||
94 | - GITS_TYPE_PHYSICAL) { | ||
95 | - *pIntid = (ite.itel & ITE_ENTRY_INTID_MASK) >> | ||
96 | - ITE_ENTRY_INTID_SHIFT; | ||
97 | - *icid = ite.iteh & ITE_ENTRY_ICID_MASK; | ||
98 | + if (FIELD_EX64(ite.itel, ITE_L, VALID)) { | ||
99 | + int inttype = FIELD_EX64(ite.itel, ITE_L, INTTYPE); | ||
100 | + if (inttype == ITE_INTTYPE_PHYSICAL) { | ||
101 | + *pIntid = FIELD_EX64(ite.itel, ITE_L, INTID); | ||
102 | + *icid = FIELD_EX32(ite.iteh, ITE_H, ICID); | ||
103 | status = true; | ||
104 | } | ||
105 | } | ||
106 | @@ -XXX,XX +XXX,XX @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset, | ||
107 | MemTxResult res = MEMTX_OK; | ||
108 | uint16_t icid = 0; | ||
109 | uint64_t dte = 0; | ||
110 | - IteEntry ite; | ||
111 | - uint32_t int_spurious = INTID_SPURIOUS; | ||
112 | bool result = false; | ||
113 | |||
114 | devid = ((value & DEVID_MASK) >> DEVID_SHIFT); | ||
115 | @@ -XXX,XX +XXX,XX @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset, | ||
116 | */ | ||
117 | } else { | ||
118 | /* add ite entry to interrupt translation table */ | ||
119 | - ite.itel = (dte_valid & TABLE_ENTRY_VALID_MASK) | | ||
120 | - (GITS_TYPE_PHYSICAL << ITE_ENTRY_INTTYPE_SHIFT); | ||
121 | - | ||
122 | + IteEntry ite = {}; | ||
123 | + ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, dte_valid); | ||
124 | + ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL); | ||
125 | if (ignore_pInt) { | ||
126 | - ite.itel |= (eventid << ITE_ENTRY_INTID_SHIFT); | ||
127 | + ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, eventid); | ||
128 | } else { | ||
129 | - ite.itel |= (pIntid << ITE_ENTRY_INTID_SHIFT); | ||
130 | + ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid); | ||
131 | } | ||
132 | - ite.itel |= (int_spurious << ITE_ENTRY_INTSP_SHIFT); | ||
133 | - ite.iteh = icid; | ||
134 | + ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS); | ||
135 | + ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, icid); | ||
136 | |||
137 | result = update_ite(s, eventid, dte, ite); | ||
138 | } | ||
139 | @@ -XXX,XX +XXX,XX @@ static void gicv3_arm_its_realize(DeviceState *dev, Error **errp) | ||
140 | "gicv3-its-sysmem"); | ||
141 | |||
142 | /* set the ITS default features supported */ | ||
143 | - s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL, | ||
144 | - GITS_TYPE_PHYSICAL); | ||
145 | + s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL, 1); | ||
146 | s->typer = FIELD_DP64(s->typer, GITS_TYPER, ITT_ENTRY_SIZE, | ||
147 | ITS_ITT_ENTRY_SIZE - 1); | ||
148 | s->typer = FIELD_DP64(s->typer, GITS_TYPER, IDBITS, ITS_IDBITS); | ||
149 | -- | ||
150 | 2.25.1 | ||
151 | |||
152 | diff view generated by jsdifflib |
1 | From: "Emilio G. Cota" <cota@braap.org> | 1 | The MAPI command takes arguments DeviceID, EventID, ICID, and is |
---|---|---|---|
2 | defined to be equivalent to MAPTI DeviceID, EventID, EventID, ICID. | ||
3 | (That is, where MAPTI takes an explicit pINTID, MAPI uses the EventID | ||
4 | as the pINTID.) | ||
2 | 5 | ||
3 | Fixes the following warning when compiling with gcc 5.4.0 with -O1 | 6 | We didn't quite get this right. In particular the error checks for |
4 | optimizations and --enable-debug: | 7 | MAPI include "EventID does not specify a valid LPI identifier", which |
8 | is the same as MAPTI's error check for the pINTID field. QEMU's code | ||
9 | skips the pINTID error check entirely in the MAPI case. | ||
5 | 10 | ||
6 | target/arm/translate-a64.c: In function ‘aarch64_tr_translate_insn’: | 11 | We can fix this bug and in the process simplify the code by switching |
7 | target/arm/translate-a64.c:2361:8: error: ‘post_index’ may be used uninitialized in this function [-Werror=maybe-uninitialized] | 12 | to the obvious implementation of setting pIntid = eventid early |
8 | if (!post_index) { | 13 | if ignore_pInt is true. |
9 | ^ | ||
10 | target/arm/translate-a64.c:2307:10: note: ‘post_index’ was declared here | ||
11 | bool post_index; | ||
12 | ^ | ||
13 | target/arm/translate-a64.c:2386:8: error: ‘writeback’ may be used uninitialized in this function [-Werror=maybe-uninitialized] | ||
14 | if (writeback) { | ||
15 | ^ | ||
16 | target/arm/translate-a64.c:2308:10: note: ‘writeback’ was declared here | ||
17 | bool writeback; | ||
18 | ^ | ||
19 | 14 | ||
20 | Note that idx comes from selecting 2 bits, and therefore its value | 15 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
21 | can be at most 3. | 16 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> |
17 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
18 | --- | ||
19 | hw/intc/arm_gicv3_its.c | 18 +++++++----------- | ||
20 | 1 file changed, 7 insertions(+), 11 deletions(-) | ||
22 | 21 | ||
23 | Signed-off-by: Emilio G. Cota <cota@braap.org> | 22 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c |
24 | Acked-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
25 | Message-id: 1510087611-1851-1-git-send-email-cota@braap.org | ||
26 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
27 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
28 | --- | ||
29 | target/arm/translate-a64.c | 2 ++ | ||
30 | 1 file changed, 2 insertions(+) | ||
31 | |||
32 | diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c | ||
33 | index XXXXXXX..XXXXXXX 100644 | 23 | index XXXXXXX..XXXXXXX 100644 |
34 | --- a/target/arm/translate-a64.c | 24 | --- a/hw/intc/arm_gicv3_its.c |
35 | +++ b/target/arm/translate-a64.c | 25 | +++ b/hw/intc/arm_gicv3_its.c |
36 | @@ -XXX,XX +XXX,XX @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn, | 26 | @@ -XXX,XX +XXX,XX @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset, |
37 | post_index = false; | 27 | |
38 | writeback = true; | 28 | eventid = (value & EVENTID_MASK); |
39 | break; | 29 | |
40 | + default: | 30 | - if (!ignore_pInt) { |
41 | + g_assert_not_reached(); | 31 | + if (ignore_pInt) { |
32 | + pIntid = eventid; | ||
33 | + } else { | ||
34 | pIntid = ((value & pINTID_MASK) >> pINTID_SHIFT); | ||
42 | } | 35 | } |
43 | 36 | ||
44 | if (rn == 31) { | 37 | @@ -XXX,XX +XXX,XX @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset, |
38 | |||
39 | max_eventid = (1UL << (((dte >> 1U) & SIZE_MASK) + 1)); | ||
40 | |||
41 | - if (!ignore_pInt) { | ||
42 | - max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1; | ||
43 | - } | ||
44 | + max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1; | ||
45 | |||
46 | if ((devid > s->dt.max_ids) || (icid > s->ct.max_ids) | ||
47 | || !dte_valid || (eventid > max_eventid) || | ||
48 | - (!ignore_pInt && (((pIntid < GICV3_LPI_INTID_START) || | ||
49 | - (pIntid > max_Intid)) && (pIntid != INTID_SPURIOUS)))) { | ||
50 | + (((pIntid < GICV3_LPI_INTID_START) || (pIntid > max_Intid)) && | ||
51 | + (pIntid != INTID_SPURIOUS))) { | ||
52 | qemu_log_mask(LOG_GUEST_ERROR, | ||
53 | "%s: invalid command attributes " | ||
54 | "devid %d or icid %d or eventid %d or pIntid %d or" | ||
55 | @@ -XXX,XX +XXX,XX @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset, | ||
56 | IteEntry ite = {}; | ||
57 | ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, dte_valid); | ||
58 | ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL); | ||
59 | - if (ignore_pInt) { | ||
60 | - ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, eventid); | ||
61 | - } else { | ||
62 | - ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid); | ||
63 | - } | ||
64 | + ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid); | ||
65 | ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS); | ||
66 | ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, icid); | ||
67 | |||
45 | -- | 68 | -- |
46 | 2.7.4 | 69 | 2.25.1 |
47 | 70 | ||
48 | 71 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | Currently the ITS code that reads and writes DTEs uses open-coded | ||
2 | shift-and-mask to assemble the various fields into the 64-bit DTE | ||
3 | word. The names of the macros used for mask and shift values are | ||
4 | also somewhat inconsistent, and don't follow our usual convention | ||
5 | that a MASK macro should specify the bits in their place in the word. | ||
6 | Replace all these with use of the FIELD macro. | ||
1 | 7 | ||
8 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
9 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
10 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
11 | --- | ||
12 | hw/intc/gicv3_internal.h | 7 ++++--- | ||
13 | hw/intc/arm_gicv3_its.c | 20 +++++++++----------- | ||
14 | 2 files changed, 13 insertions(+), 14 deletions(-) | ||
15 | |||
16 | diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h | ||
17 | index XXXXXXX..XXXXXXX 100644 | ||
18 | --- a/hw/intc/gicv3_internal.h | ||
19 | +++ b/hw/intc/gicv3_internal.h | ||
20 | @@ -XXX,XX +XXX,XX @@ FIELD(ITE_H, VPEID, 16, 16) | ||
21 | * Valid = 1 bit,ITTAddr = 44 bits,Size = 5 bits | ||
22 | */ | ||
23 | #define GITS_DTE_SIZE (0x8ULL) | ||
24 | -#define GITS_DTE_ITTADDR_SHIFT 6 | ||
25 | -#define GITS_DTE_ITTADDR_MASK MAKE_64BIT_MASK(GITS_DTE_ITTADDR_SHIFT, \ | ||
26 | - ITTADDR_LENGTH) | ||
27 | + | ||
28 | +FIELD(DTE, VALID, 0, 1) | ||
29 | +FIELD(DTE, SIZE, 1, 5) | ||
30 | +FIELD(DTE, ITTADDR, 6, 44) | ||
31 | |||
32 | /* | ||
33 | * 8 bytes Collection Table Entry size | ||
34 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c | ||
35 | index XXXXXXX..XXXXXXX 100644 | ||
36 | --- a/hw/intc/arm_gicv3_its.c | ||
37 | +++ b/hw/intc/arm_gicv3_its.c | ||
38 | @@ -XXX,XX +XXX,XX @@ static bool update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte, | ||
39 | uint64_t itt_addr; | ||
40 | MemTxResult res = MEMTX_OK; | ||
41 | |||
42 | - itt_addr = (dte & GITS_DTE_ITTADDR_MASK) >> GITS_DTE_ITTADDR_SHIFT; | ||
43 | + itt_addr = FIELD_EX64(dte, DTE, ITTADDR); | ||
44 | itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */ | ||
45 | |||
46 | address_space_stq_le(as, itt_addr + (eventid * (sizeof(uint64_t) + | ||
47 | @@ -XXX,XX +XXX,XX @@ static bool get_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte, | ||
48 | bool status = false; | ||
49 | IteEntry ite = {}; | ||
50 | |||
51 | - itt_addr = (dte & GITS_DTE_ITTADDR_MASK) >> GITS_DTE_ITTADDR_SHIFT; | ||
52 | + itt_addr = FIELD_EX64(dte, DTE, ITTADDR); | ||
53 | itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */ | ||
54 | |||
55 | ite.itel = address_space_ldq_le(as, itt_addr + | ||
56 | @@ -XXX,XX +XXX,XX @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset, | ||
57 | if (res != MEMTX_OK) { | ||
58 | return result; | ||
59 | } | ||
60 | - dte_valid = dte & TABLE_ENTRY_VALID_MASK; | ||
61 | + dte_valid = FIELD_EX64(dte, DTE, VALID); | ||
62 | |||
63 | if (dte_valid) { | ||
64 | - max_eventid = (1UL << (((dte >> 1U) & SIZE_MASK) + 1)); | ||
65 | + max_eventid = 1UL << (FIELD_EX64(dte, DTE, SIZE) + 1); | ||
66 | |||
67 | ite_valid = get_ite(s, eventid, dte, &icid, &pIntid, &res); | ||
68 | |||
69 | @@ -XXX,XX +XXX,XX @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset, | ||
70 | if (res != MEMTX_OK) { | ||
71 | return result; | ||
72 | } | ||
73 | - dte_valid = dte & TABLE_ENTRY_VALID_MASK; | ||
74 | - | ||
75 | - max_eventid = (1UL << (((dte >> 1U) & SIZE_MASK) + 1)); | ||
76 | - | ||
77 | + dte_valid = FIELD_EX64(dte, DTE, VALID); | ||
78 | + max_eventid = 1UL << (FIELD_EX64(dte, DTE, SIZE) + 1); | ||
79 | max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1; | ||
80 | |||
81 | if ((devid > s->dt.max_ids) || (icid > s->ct.max_ids) | ||
82 | @@ -XXX,XX +XXX,XX @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid, | ||
83 | if (s->dt.valid) { | ||
84 | if (valid) { | ||
85 | /* add mapping entry to device table */ | ||
86 | - dte = (valid & TABLE_ENTRY_VALID_MASK) | | ||
87 | - ((size & SIZE_MASK) << 1U) | | ||
88 | - (itt_addr << GITS_DTE_ITTADDR_SHIFT); | ||
89 | + dte = FIELD_DP64(dte, DTE, VALID, 1); | ||
90 | + dte = FIELD_DP64(dte, DTE, SIZE, size); | ||
91 | + dte = FIELD_DP64(dte, DTE, ITTADDR, itt_addr); | ||
92 | } | ||
93 | } else { | ||
94 | return true; | ||
95 | -- | ||
96 | 2.25.1 | ||
97 | |||
98 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | The comment says that in our CTE format the RDBase field is 36 bits; | ||
2 | in fact for us it is only 16 bits, because we use the RDBase format | ||
3 | where it specifies a 16-bit CPU number. The code already uses | ||
4 | RDBASE_PROCNUM_LENGTH (16) as the field width, so fix the comment | ||
5 | to match it. | ||
1 | 6 | ||
7 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
8 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
9 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
10 | --- | ||
11 | hw/intc/gicv3_internal.h | 2 +- | ||
12 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
13 | |||
14 | diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/hw/intc/gicv3_internal.h | ||
17 | +++ b/hw/intc/gicv3_internal.h | ||
18 | @@ -XXX,XX +XXX,XX @@ FIELD(DTE, ITTADDR, 6, 44) | ||
19 | |||
20 | /* | ||
21 | * 8 bytes Collection Table Entry size | ||
22 | - * Valid = 1 bit,RDBase = 36 bits(considering max RDBASE) | ||
23 | + * Valid = 1 bit, RDBase = 16 bits | ||
24 | */ | ||
25 | #define GITS_CTE_SIZE (0x8ULL) | ||
26 | #define GITS_CTE_RDBASE_PROCNUM_MASK MAKE_64BIT_MASK(1, RDBASE_PROCNUM_LENGTH) | ||
27 | -- | ||
28 | 2.25.1 | ||
29 | |||
30 | diff view generated by jsdifflib |
1 | From: Alistair Francis <alistair.francis@xilinx.com> | 1 | Use FIELD macros to handle CTEs, rather than ad-hoc mask-and-shift. |
---|---|---|---|
2 | 2 | ||
3 | Allow the -smp command line option to control the number of CPUs we | 3 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
4 | create. | 4 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> |
5 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
6 | --- | ||
7 | hw/intc/gicv3_internal.h | 3 ++- | ||
8 | hw/intc/arm_gicv3_its.c | 7 ++++--- | ||
9 | 2 files changed, 6 insertions(+), 4 deletions(-) | ||
5 | 10 | ||
6 | Signed-off-by: Alistair Francis <alistair.francis@xilinx.com> | 11 | diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h |
7 | Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> | ||
8 | Reviewed-by: Emilio G. Cota <cota@braap.org> | ||
9 | Tested-by: Emilio G. Cota <cota@braap.org> | ||
10 | Message-id: 1510343626-25861-3-git-send-email-cota@braap.org | ||
11 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
12 | --- | ||
13 | hw/arm/xlnx-zcu102.c | 3 ++- | ||
14 | hw/arm/xlnx-zynqmp.c | 26 ++++++++++++++++---------- | ||
15 | 2 files changed, 18 insertions(+), 11 deletions(-) | ||
16 | |||
17 | diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c | ||
18 | index XXXXXXX..XXXXXXX 100644 | 12 | index XXXXXXX..XXXXXXX 100644 |
19 | --- a/hw/arm/xlnx-zcu102.c | 13 | --- a/hw/intc/gicv3_internal.h |
20 | +++ b/hw/arm/xlnx-zcu102.c | 14 | +++ b/hw/intc/gicv3_internal.h |
21 | @@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data) | 15 | @@ -XXX,XX +XXX,XX @@ FIELD(DTE, ITTADDR, 6, 44) |
22 | { | 16 | * Valid = 1 bit, RDBase = 16 bits |
23 | MachineClass *mc = MACHINE_CLASS(oc); | 17 | */ |
24 | 18 | #define GITS_CTE_SIZE (0x8ULL) | |
25 | - mc->desc = "Xilinx ZynqMP ZCU102 board"; | 19 | -#define GITS_CTE_RDBASE_PROCNUM_MASK MAKE_64BIT_MASK(1, RDBASE_PROCNUM_LENGTH) |
26 | + mc->desc = "Xilinx ZynqMP ZCU102 board with 4xA53s and 2xR5s based on " \ | 20 | +FIELD(CTE, VALID, 0, 1) |
27 | + "the value of smp"; | 21 | +FIELD(CTE, RDBASE, 1, RDBASE_PROCNUM_LENGTH) |
28 | mc->init = xlnx_zcu102_init; | 22 | |
29 | mc->block_default_type = IF_IDE; | 23 | /* Special interrupt IDs */ |
30 | mc->units_per_default_bus = 1; | 24 | #define INTID_SECURE 1020 |
31 | diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c | 25 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c |
32 | index XXXXXXX..XXXXXXX 100644 | 26 | index XXXXXXX..XXXXXXX 100644 |
33 | --- a/hw/arm/xlnx-zynqmp.c | 27 | --- a/hw/intc/arm_gicv3_its.c |
34 | +++ b/hw/arm/xlnx-zynqmp.c | 28 | +++ b/hw/intc/arm_gicv3_its.c |
35 | @@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_create_rpu(XlnxZynqMPState *s, const char *boot_cpu, | 29 | @@ -XXX,XX +XXX,XX @@ static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte, |
36 | { | 30 | MEMTXATTRS_UNSPECIFIED, res); |
37 | Error *err = NULL; | ||
38 | int i; | ||
39 | + int num_rpus = MIN(smp_cpus - XLNX_ZYNQMP_NUM_APU_CPUS, XLNX_ZYNQMP_NUM_RPU_CPUS); | ||
40 | |||
41 | - for (i = 0; i < XLNX_ZYNQMP_NUM_RPU_CPUS; i++) { | ||
42 | + for (i = 0; i < num_rpus; i++) { | ||
43 | char *name; | ||
44 | |||
45 | object_initialize(&s->rpu_cpu[i], sizeof(s->rpu_cpu[i]), | ||
46 | @@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj) | ||
47 | { | ||
48 | XlnxZynqMPState *s = XLNX_ZYNQMP(obj); | ||
49 | int i; | ||
50 | + int num_apus = MIN(smp_cpus, XLNX_ZYNQMP_NUM_APU_CPUS); | ||
51 | |||
52 | - for (i = 0; i < XLNX_ZYNQMP_NUM_APU_CPUS; i++) { | ||
53 | + for (i = 0; i < num_apus; i++) { | ||
54 | object_initialize(&s->apu_cpu[i], sizeof(s->apu_cpu[i]), | ||
55 | "cortex-a53-" TYPE_ARM_CPU); | ||
56 | object_property_add_child(obj, "apu-cpu[*]", OBJECT(&s->apu_cpu[i]), | ||
57 | @@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) | ||
58 | MemoryRegion *system_memory = get_system_memory(); | ||
59 | uint8_t i; | ||
60 | uint64_t ram_size; | ||
61 | + int num_apus = MIN(smp_cpus, XLNX_ZYNQMP_NUM_APU_CPUS); | ||
62 | const char *boot_cpu = s->boot_cpu ? s->boot_cpu : "apu-cpu[0]"; | ||
63 | ram_addr_t ddr_low_size, ddr_high_size; | ||
64 | qemu_irq gic_spi[GIC_NUM_SPI_INTR]; | ||
65 | @@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) | ||
66 | |||
67 | qdev_prop_set_uint32(DEVICE(&s->gic), "num-irq", GIC_NUM_SPI_INTR + 32); | ||
68 | qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 2); | ||
69 | - qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", XLNX_ZYNQMP_NUM_APU_CPUS); | ||
70 | + qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", num_apus); | ||
71 | |||
72 | /* Realize APUs before realizing the GIC. KVM requires this. */ | ||
73 | - for (i = 0; i < XLNX_ZYNQMP_NUM_APU_CPUS; i++) { | ||
74 | + for (i = 0; i < num_apus; i++) { | ||
75 | char *name; | ||
76 | |||
77 | object_property_set_int(OBJECT(&s->apu_cpu[i]), QEMU_PSCI_CONDUIT_SMC, | ||
78 | @@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) | ||
79 | } | ||
80 | } | 31 | } |
81 | 32 | ||
82 | - for (i = 0; i < XLNX_ZYNQMP_NUM_APU_CPUS; i++) { | 33 | - return (*cte & TABLE_ENTRY_VALID_MASK) != 0; |
83 | + for (i = 0; i < num_apus; i++) { | 34 | + return FIELD_EX64(*cte, CTE, VALID); |
84 | qemu_irq irq; | 35 | } |
85 | 36 | ||
86 | sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i, | 37 | static bool update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte, |
87 | @@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) | 38 | @@ -XXX,XX +XXX,XX @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset, |
39 | * Current implementation only supports rdbase == procnum | ||
40 | * Hence rdbase physical address is ignored | ||
41 | */ | ||
42 | - rdbase = (cte & GITS_CTE_RDBASE_PROCNUM_MASK) >> 1U; | ||
43 | + rdbase = FIELD_EX64(cte, CTE, RDBASE); | ||
44 | |||
45 | if (rdbase >= s->gicv3->num_cpu) { | ||
46 | return result; | ||
47 | @@ -XXX,XX +XXX,XX @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid, | ||
48 | |||
49 | if (valid) { | ||
50 | /* add mapping entry to collection table */ | ||
51 | - cte = (valid & TABLE_ENTRY_VALID_MASK) | (rdbase << 1ULL); | ||
52 | + cte = FIELD_DP64(cte, CTE, VALID, 1); | ||
53 | + cte = FIELD_DP64(cte, CTE, RDBASE, rdbase); | ||
88 | } | 54 | } |
89 | 55 | ||
90 | if (s->has_rpu) { | 56 | /* |
91 | - xlnx_zynqmp_create_rpu(s, boot_cpu, &err); | ||
92 | - if (err) { | ||
93 | - error_propagate(errp, err); | ||
94 | - return; | ||
95 | - } | ||
96 | + info_report("The 'has_rpu' property is no longer required, to use the " | ||
97 | + "RPUs just use -smp 6."); | ||
98 | + } | ||
99 | + | ||
100 | + xlnx_zynqmp_create_rpu(s, boot_cpu, &err); | ||
101 | + if (err) { | ||
102 | + error_propagate(errp, err); | ||
103 | + return; | ||
104 | } | ||
105 | |||
106 | if (!s->boot_cpu_ptr) { | ||
107 | -- | 57 | -- |
108 | 2.7.4 | 58 | 2.25.1 |
109 | 59 | ||
110 | 60 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | The ITS code has to check whether various parameters passed in | ||
2 | commands are in-bounds, where the limit is defined in terms of the | ||
3 | number of bits that are available for the parameter. (For example, | ||
4 | the GITS_TYPER.Devbits ID register field specifies the number of | ||
5 | DeviceID bits minus 1, and device IDs passed in the MAPTI and MAPD | ||
6 | command packets must fit in that many bits.) | ||
1 | 7 | ||
8 | Currently we have off-by-one bugs in many of these bounds checks. | ||
9 | The typical problem is that we define a max_foo as 1 << n. In | ||
10 | the Devbits example, we set | ||
11 | s->dt.max_ids = 1UL << (GITS_TYPER.Devbits + 1). | ||
12 | However later when we do the bounds check we write | ||
13 | if (devid > s->dt.max_ids) { /* command error */ } | ||
14 | which incorrectly permits a devid of 1 << n. | ||
15 | |||
16 | These bugs will not cause QEMU crashes because the ID values being | ||
17 | checked are only used for accesses into tables held in guest memory | ||
18 | which we access with address_space_*() functions, but they are | ||
19 | incorrect behaviour of our emulation. | ||
20 | |||
21 | Fix them by standardizing on this pattern: | ||
22 | * bounds limits are named num_foos and are the 2^n value | ||
23 | (equal to the number of valid foo values) | ||
24 | * bounds checks are either | ||
25 | if (fooid < num_foos) { good } | ||
26 | or | ||
27 | if (fooid >= num_foos) { bad } | ||
28 | |||
29 | In this commit we fix the handling of the number of IDs | ||
30 | in the device table and the collection table, and the number | ||
31 | of commands that will fit in the command queue. | ||
32 | |||
33 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
34 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
35 | --- | ||
36 | include/hw/intc/arm_gicv3_its_common.h | 6 +++--- | ||
37 | hw/intc/arm_gicv3_its.c | 26 +++++++++++++------------- | ||
38 | 2 files changed, 16 insertions(+), 16 deletions(-) | ||
39 | |||
40 | diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h | ||
41 | index XXXXXXX..XXXXXXX 100644 | ||
42 | --- a/include/hw/intc/arm_gicv3_its_common.h | ||
43 | +++ b/include/hw/intc/arm_gicv3_its_common.h | ||
44 | @@ -XXX,XX +XXX,XX @@ typedef struct { | ||
45 | bool indirect; | ||
46 | uint16_t entry_sz; | ||
47 | uint32_t page_sz; | ||
48 | - uint32_t max_entries; | ||
49 | - uint32_t max_ids; | ||
50 | + uint32_t num_entries; | ||
51 | + uint32_t num_ids; | ||
52 | uint64_t base_addr; | ||
53 | } TableDesc; | ||
54 | |||
55 | typedef struct { | ||
56 | bool valid; | ||
57 | - uint32_t max_entries; | ||
58 | + uint32_t num_entries; | ||
59 | uint64_t base_addr; | ||
60 | } CmdQDesc; | ||
61 | |||
62 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c | ||
63 | index XXXXXXX..XXXXXXX 100644 | ||
64 | --- a/hw/intc/arm_gicv3_its.c | ||
65 | +++ b/hw/intc/arm_gicv3_its.c | ||
66 | @@ -XXX,XX +XXX,XX @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset, | ||
67 | * In this implementation, in case of guest errors we ignore the | ||
68 | * command and move onto the next command in the queue. | ||
69 | */ | ||
70 | - if (devid > s->dt.max_ids) { | ||
71 | + if (devid >= s->dt.num_ids) { | ||
72 | qemu_log_mask(LOG_GUEST_ERROR, | ||
73 | - "%s: invalid command attributes: devid %d>%d", | ||
74 | - __func__, devid, s->dt.max_ids); | ||
75 | + "%s: invalid command attributes: devid %d>=%d", | ||
76 | + __func__, devid, s->dt.num_ids); | ||
77 | |||
78 | } else if (!dte_valid || !ite_valid || !cte_valid) { | ||
79 | qemu_log_mask(LOG_GUEST_ERROR, | ||
80 | @@ -XXX,XX +XXX,XX @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset, | ||
81 | max_eventid = 1UL << (FIELD_EX64(dte, DTE, SIZE) + 1); | ||
82 | max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1; | ||
83 | |||
84 | - if ((devid > s->dt.max_ids) || (icid > s->ct.max_ids) | ||
85 | + if ((devid >= s->dt.num_ids) || (icid >= s->ct.num_ids) | ||
86 | || !dte_valid || (eventid > max_eventid) || | ||
87 | (((pIntid < GICV3_LPI_INTID_START) || (pIntid > max_Intid)) && | ||
88 | (pIntid != INTID_SPURIOUS))) { | ||
89 | @@ -XXX,XX +XXX,XX @@ static bool process_mapc(GICv3ITSState *s, uint32_t offset) | ||
90 | |||
91 | valid = (value & CMD_FIELD_VALID_MASK); | ||
92 | |||
93 | - if ((icid > s->ct.max_ids) || (rdbase >= s->gicv3->num_cpu)) { | ||
94 | + if ((icid >= s->ct.num_ids) || (rdbase >= s->gicv3->num_cpu)) { | ||
95 | qemu_log_mask(LOG_GUEST_ERROR, | ||
96 | "ITS MAPC: invalid collection table attributes " | ||
97 | "icid %d rdbase %" PRIu64 "\n", icid, rdbase); | ||
98 | @@ -XXX,XX +XXX,XX @@ static bool process_mapd(GICv3ITSState *s, uint64_t value, uint32_t offset) | ||
99 | |||
100 | valid = (value & CMD_FIELD_VALID_MASK); | ||
101 | |||
102 | - if ((devid > s->dt.max_ids) || | ||
103 | + if ((devid >= s->dt.num_ids) || | ||
104 | (size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) { | ||
105 | qemu_log_mask(LOG_GUEST_ERROR, | ||
106 | "ITS MAPD: invalid device table attributes " | ||
107 | @@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s) | ||
108 | |||
109 | wr_offset = FIELD_EX64(s->cwriter, GITS_CWRITER, OFFSET); | ||
110 | |||
111 | - if (wr_offset > s->cq.max_entries) { | ||
112 | + if (wr_offset >= s->cq.num_entries) { | ||
113 | qemu_log_mask(LOG_GUEST_ERROR, | ||
114 | "%s: invalid write offset " | ||
115 | "%d\n", __func__, wr_offset); | ||
116 | @@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s) | ||
117 | |||
118 | rd_offset = FIELD_EX64(s->creadr, GITS_CREADR, OFFSET); | ||
119 | |||
120 | - if (rd_offset > s->cq.max_entries) { | ||
121 | + if (rd_offset >= s->cq.num_entries) { | ||
122 | qemu_log_mask(LOG_GUEST_ERROR, | ||
123 | "%s: invalid read offset " | ||
124 | "%d\n", __func__, rd_offset); | ||
125 | @@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s) | ||
126 | } | ||
127 | if (result) { | ||
128 | rd_offset++; | ||
129 | - rd_offset %= s->cq.max_entries; | ||
130 | + rd_offset %= s->cq.num_entries; | ||
131 | s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, OFFSET, rd_offset); | ||
132 | } else { | ||
133 | /* | ||
134 | @@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s) | ||
135 | td->entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE) + 1; | ||
136 | td->base_addr = baser_base_addr(value, page_sz); | ||
137 | if (!td->indirect) { | ||
138 | - td->max_entries = (num_pages * page_sz) / td->entry_sz; | ||
139 | + td->num_entries = (num_pages * page_sz) / td->entry_sz; | ||
140 | } else { | ||
141 | - td->max_entries = (((num_pages * page_sz) / | ||
142 | + td->num_entries = (((num_pages * page_sz) / | ||
143 | L1TABLE_ENTRY_SIZE) * | ||
144 | (page_sz / td->entry_sz)); | ||
145 | } | ||
146 | - td->max_ids = 1ULL << idbits; | ||
147 | + td->num_ids = 1ULL << idbits; | ||
148 | } | ||
149 | } | ||
150 | |||
151 | @@ -XXX,XX +XXX,XX @@ static void extract_cmdq_params(GICv3ITSState *s) | ||
152 | s->cq.valid = FIELD_EX64(value, GITS_CBASER, VALID); | ||
153 | |||
154 | if (s->cq.valid) { | ||
155 | - s->cq.max_entries = (num_pages * GITS_PAGE_SIZE_4K) / | ||
156 | + s->cq.num_entries = (num_pages * GITS_PAGE_SIZE_4K) / | ||
157 | GITS_CMDQ_ENTRY_SIZE; | ||
158 | s->cq.base_addr = FIELD_EX64(value, GITS_CBASER, PHYADDR); | ||
159 | s->cq.base_addr <<= R_GITS_CBASER_PHYADDR_SHIFT; | ||
160 | -- | ||
161 | 2.25.1 | ||
162 | |||
163 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | In several places we have a local variable max_l2_entries which is | ||
2 | the number of entries which will fit in a level 2 table. The | ||
3 | calculations done on this value are correct; rename it to | ||
4 | num_l2_entries to fit the convention we're using in this code. | ||
1 | 5 | ||
6 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
7 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
8 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
9 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
10 | --- | ||
11 | hw/intc/arm_gicv3_its.c | 24 ++++++++++++------------ | ||
12 | 1 file changed, 12 insertions(+), 12 deletions(-) | ||
13 | |||
14 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c | ||
15 | index XXXXXXX..XXXXXXX 100644 | ||
16 | --- a/hw/intc/arm_gicv3_its.c | ||
17 | +++ b/hw/intc/arm_gicv3_its.c | ||
18 | @@ -XXX,XX +XXX,XX @@ static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte, | ||
19 | uint64_t value; | ||
20 | bool valid_l2t; | ||
21 | uint32_t l2t_id; | ||
22 | - uint32_t max_l2_entries; | ||
23 | + uint32_t num_l2_entries; | ||
24 | |||
25 | if (s->ct.indirect) { | ||
26 | l2t_id = icid / (s->ct.page_sz / L1TABLE_ENTRY_SIZE); | ||
27 | @@ -XXX,XX +XXX,XX @@ static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte, | ||
28 | valid_l2t = (value & L2_TABLE_VALID_MASK) != 0; | ||
29 | |||
30 | if (valid_l2t) { | ||
31 | - max_l2_entries = s->ct.page_sz / s->ct.entry_sz; | ||
32 | + num_l2_entries = s->ct.page_sz / s->ct.entry_sz; | ||
33 | |||
34 | l2t_addr = value & ((1ULL << 51) - 1); | ||
35 | |||
36 | *cte = address_space_ldq_le(as, l2t_addr + | ||
37 | - ((icid % max_l2_entries) * GITS_CTE_SIZE), | ||
38 | + ((icid % num_l2_entries) * GITS_CTE_SIZE), | ||
39 | MEMTXATTRS_UNSPECIFIED, res); | ||
40 | } | ||
41 | } | ||
42 | @@ -XXX,XX +XXX,XX @@ static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res) | ||
43 | uint64_t value; | ||
44 | bool valid_l2t; | ||
45 | uint32_t l2t_id; | ||
46 | - uint32_t max_l2_entries; | ||
47 | + uint32_t num_l2_entries; | ||
48 | |||
49 | if (s->dt.indirect) { | ||
50 | l2t_id = devid / (s->dt.page_sz / L1TABLE_ENTRY_SIZE); | ||
51 | @@ -XXX,XX +XXX,XX @@ static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res) | ||
52 | valid_l2t = (value & L2_TABLE_VALID_MASK) != 0; | ||
53 | |||
54 | if (valid_l2t) { | ||
55 | - max_l2_entries = s->dt.page_sz / s->dt.entry_sz; | ||
56 | + num_l2_entries = s->dt.page_sz / s->dt.entry_sz; | ||
57 | |||
58 | l2t_addr = value & ((1ULL << 51) - 1); | ||
59 | |||
60 | value = address_space_ldq_le(as, l2t_addr + | ||
61 | - ((devid % max_l2_entries) * GITS_DTE_SIZE), | ||
62 | + ((devid % num_l2_entries) * GITS_DTE_SIZE), | ||
63 | MEMTXATTRS_UNSPECIFIED, res); | ||
64 | } | ||
65 | } | ||
66 | @@ -XXX,XX +XXX,XX @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid, | ||
67 | uint64_t l2t_addr; | ||
68 | bool valid_l2t; | ||
69 | uint32_t l2t_id; | ||
70 | - uint32_t max_l2_entries; | ||
71 | + uint32_t num_l2_entries; | ||
72 | uint64_t cte = 0; | ||
73 | MemTxResult res = MEMTX_OK; | ||
74 | |||
75 | @@ -XXX,XX +XXX,XX @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid, | ||
76 | valid_l2t = (value & L2_TABLE_VALID_MASK) != 0; | ||
77 | |||
78 | if (valid_l2t) { | ||
79 | - max_l2_entries = s->ct.page_sz / s->ct.entry_sz; | ||
80 | + num_l2_entries = s->ct.page_sz / s->ct.entry_sz; | ||
81 | |||
82 | l2t_addr = value & ((1ULL << 51) - 1); | ||
83 | |||
84 | address_space_stq_le(as, l2t_addr + | ||
85 | - ((icid % max_l2_entries) * GITS_CTE_SIZE), | ||
86 | + ((icid % num_l2_entries) * GITS_CTE_SIZE), | ||
87 | cte, MEMTXATTRS_UNSPECIFIED, &res); | ||
88 | } | ||
89 | } else { | ||
90 | @@ -XXX,XX +XXX,XX @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid, | ||
91 | uint64_t l2t_addr; | ||
92 | bool valid_l2t; | ||
93 | uint32_t l2t_id; | ||
94 | - uint32_t max_l2_entries; | ||
95 | + uint32_t num_l2_entries; | ||
96 | uint64_t dte = 0; | ||
97 | MemTxResult res = MEMTX_OK; | ||
98 | |||
99 | @@ -XXX,XX +XXX,XX @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid, | ||
100 | valid_l2t = (value & L2_TABLE_VALID_MASK) != 0; | ||
101 | |||
102 | if (valid_l2t) { | ||
103 | - max_l2_entries = s->dt.page_sz / s->dt.entry_sz; | ||
104 | + num_l2_entries = s->dt.page_sz / s->dt.entry_sz; | ||
105 | |||
106 | l2t_addr = value & ((1ULL << 51) - 1); | ||
107 | |||
108 | address_space_stq_le(as, l2t_addr + | ||
109 | - ((devid % max_l2_entries) * GITS_DTE_SIZE), | ||
110 | + ((devid % num_l2_entries) * GITS_DTE_SIZE), | ||
111 | dte, MEMTXATTRS_UNSPECIFIED, &res); | ||
112 | } | ||
113 | } else { | ||
114 | -- | ||
115 | 2.25.1 | ||
116 | |||
117 | diff view generated by jsdifflib |
1 | From: "Emilio G. Cota" <cota@braap.org> | 1 | From: Chris Rauer <crauer@google.com> |
---|---|---|---|
2 | 2 | ||
3 | max_cpus needs to be an upper bound on the number of vCPUs | 3 | Signed-off-by: Chris Rauer <crauer@google.com> |
4 | initialized; otherwise TCG region initialization breaks. | 4 | Reviewed-by: Hao Wu <wuhaotsh@google.com> |
5 | 5 | Reviewed-by: Patrick Venture <venture@google.com> | |
6 | Some boards initialize a hard-coded number of vCPUs, which is not | 6 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> |
7 | captured by the global max_cpus and therefore breaks TCG initialization. | 7 | Message-id: 20220102215844.2888833-2-venture@google.com |
8 | Fix it by adding the .min_cpus field to machine_class. | ||
9 | |||
10 | This commit also changes some user-facing behaviour: we now die if | ||
11 | -smp is below this hard-coded vCPU minimum instead of silently | ||
12 | ignoring the passed -smp value (sometimes announcing this by printing | ||
13 | a warning). However, the introduction of .default_cpus lessens the | ||
14 | likelihood that users will notice this: if -smp isn't set, we now | ||
15 | assign the value in .default_cpus to both smp_cpus and max_cpus. IOW, | ||
16 | if a user does not set -smp, they always get a correct number of vCPUs. | ||
17 | |||
18 | This change fixes 3468b59 ("tcg: enable multiple TCG contexts in | ||
19 | softmmu", 2017-10-24), which broke TCG initialization for some | ||
20 | ARM boards. | ||
21 | |||
22 | Fixes: 3468b59e18b179bc63c7ce934de912dfa9596122 | ||
23 | Reported-by: Thomas Huth <thuth@redhat.com> | ||
24 | Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> | ||
25 | Reviewed-by: Alistair Francis <alistair.francis@xilinx.com> | ||
26 | Signed-off-by: Emilio G. Cota <cota@braap.org> | ||
27 | Message-id: 1510343626-25861-6-git-send-email-cota@braap.org | ||
28 | Suggested-by: Peter Maydell <peter.maydell@linaro.org> | ||
29 | Signed-off-by: Emilio G. Cota <cota@braap.org> | ||
30 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 8 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
31 | --- | 9 | --- |
32 | include/hw/boards.h | 5 +++++ | 10 | hw/arm/npcm7xx_boards.c | 8 ++++++++ |
33 | hw/arm/exynos4_boards.c | 12 ++++-------- | 11 | 1 file changed, 8 insertions(+) |
34 | hw/arm/raspi.c | 2 ++ | ||
35 | hw/arm/xlnx-zcu102.c | 2 ++ | ||
36 | vl.c | 21 ++++++++++++++++++--- | ||
37 | 5 files changed, 31 insertions(+), 11 deletions(-) | ||
38 | 12 | ||
39 | diff --git a/include/hw/boards.h b/include/hw/boards.h | 13 | diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c |
40 | index XXXXXXX..XXXXXXX 100644 | 14 | index XXXXXXX..XXXXXXX 100644 |
41 | --- a/include/hw/boards.h | 15 | --- a/hw/arm/npcm7xx_boards.c |
42 | +++ b/include/hw/boards.h | 16 | +++ b/hw/arm/npcm7xx_boards.c |
43 | @@ -XXX,XX +XXX,XX @@ typedef struct { | 17 | @@ -XXX,XX +XXX,XX @@ static void quanta_gbs_i2c_init(NPCM7xxState *soc) |
44 | 18 | */ | |
45 | /** | 19 | } |
46 | * MachineClass: | 20 | |
47 | + * @max_cpus: maximum number of CPUs supported. Default: 1 | 21 | +static void kudo_bmc_i2c_init(NPCM7xxState *soc) |
48 | + * @min_cpus: minimum number of CPUs supported. Default: 1 | 22 | +{ |
49 | + * @default_cpus: number of CPUs instantiated if none are specified. Default: 1 | 23 | + at24c_eeprom_init(soc, 4, 0x50, 8192); /* mbfru */ |
50 | * @get_hotplug_handler: this function is called during bus-less | 24 | + at24c_eeprom_init(soc, 14, 0x55, 8192); /* bmcfru */ |
51 | * device hotplug. If defined it returns pointer to an instance | 25 | + /* TODO: Add remaining i2c devices. */ |
52 | * of HotplugHandler object, which handles hotplug operation | 26 | +} |
53 | @@ -XXX,XX +XXX,XX @@ struct MachineClass { | 27 | + |
54 | BlockInterfaceType block_default_type; | 28 | static void npcm750_evb_init(MachineState *machine) |
55 | int units_per_default_bus; | ||
56 | int max_cpus; | ||
57 | + int min_cpus; | ||
58 | + int default_cpus; | ||
59 | unsigned int no_serial:1, | ||
60 | no_parallel:1, | ||
61 | use_virtcon:1, | ||
62 | diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c | ||
63 | index XXXXXXX..XXXXXXX 100644 | ||
64 | --- a/hw/arm/exynos4_boards.c | ||
65 | +++ b/hw/arm/exynos4_boards.c | ||
66 | @@ -XXX,XX +XXX,XX @@ | ||
67 | #include "qemu-common.h" | ||
68 | #include "cpu.h" | ||
69 | #include "sysemu/sysemu.h" | ||
70 | -#include "sysemu/qtest.h" | ||
71 | #include "hw/sysbus.h" | ||
72 | #include "net/net.h" | ||
73 | #include "hw/arm/arm.h" | ||
74 | @@ -XXX,XX +XXX,XX @@ exynos4_boards_init_common(MachineState *machine, | ||
75 | Exynos4BoardType board_type) | ||
76 | { | 29 | { |
77 | Exynos4BoardState *s = g_new(Exynos4BoardState, 1); | 30 | NPCM7xxState *soc; |
78 | - MachineClass *mc = MACHINE_GET_CLASS(machine); | 31 | @@ -XXX,XX +XXX,XX @@ static void kudo_bmc_init(MachineState *machine) |
79 | - | 32 | npcm7xx_connect_flash(&soc->fiu[1], 0, "mx66u51235f", |
80 | - if (smp_cpus != EXYNOS4210_NCPUS && !qtest_enabled()) { | 33 | drive_get(IF_MTD, 3, 0)); |
81 | - error_report("%s board supports only %d CPU cores, ignoring smp_cpus" | 34 | |
82 | - " value", | 35 | + kudo_bmc_i2c_init(soc); |
83 | - mc->name, EXYNOS4210_NCPUS); | 36 | npcm7xx_load_kernel(machine, soc); |
84 | - } | ||
85 | |||
86 | exynos4_board_binfo.ram_size = exynos4_board_ram_size[board_type]; | ||
87 | exynos4_board_binfo.board_id = exynos4_board_id[board_type]; | ||
88 | @@ -XXX,XX +XXX,XX @@ static void nuri_class_init(ObjectClass *oc, void *data) | ||
89 | mc->desc = "Samsung NURI board (Exynos4210)"; | ||
90 | mc->init = nuri_init; | ||
91 | mc->max_cpus = EXYNOS4210_NCPUS; | ||
92 | + mc->min_cpus = EXYNOS4210_NCPUS; | ||
93 | + mc->default_cpus = EXYNOS4210_NCPUS; | ||
94 | mc->ignore_memory_transaction_failures = true; | ||
95 | } | 37 | } |
96 | 38 | ||
97 | @@ -XXX,XX +XXX,XX @@ static void smdkc210_class_init(ObjectClass *oc, void *data) | ||
98 | mc->desc = "Samsung SMDKC210 board (Exynos4210)"; | ||
99 | mc->init = smdkc210_init; | ||
100 | mc->max_cpus = EXYNOS4210_NCPUS; | ||
101 | + mc->min_cpus = EXYNOS4210_NCPUS; | ||
102 | + mc->default_cpus = EXYNOS4210_NCPUS; | ||
103 | mc->ignore_memory_transaction_failures = true; | ||
104 | } | ||
105 | |||
106 | diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c | ||
107 | index XXXXXXX..XXXXXXX 100644 | ||
108 | --- a/hw/arm/raspi.c | ||
109 | +++ b/hw/arm/raspi.c | ||
110 | @@ -XXX,XX +XXX,XX @@ static void raspi2_machine_init(MachineClass *mc) | ||
111 | mc->no_floppy = 1; | ||
112 | mc->no_cdrom = 1; | ||
113 | mc->max_cpus = BCM2836_NCPUS; | ||
114 | + mc->min_cpus = BCM2836_NCPUS; | ||
115 | + mc->default_cpus = BCM2836_NCPUS; | ||
116 | mc->default_ram_size = 1024 * 1024 * 1024; | ||
117 | mc->ignore_memory_transaction_failures = true; | ||
118 | }; | ||
119 | diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c | ||
120 | index XXXXXXX..XXXXXXX 100644 | ||
121 | --- a/hw/arm/xlnx-zcu102.c | ||
122 | +++ b/hw/arm/xlnx-zcu102.c | ||
123 | @@ -XXX,XX +XXX,XX @@ static void xlnx_ep108_machine_class_init(ObjectClass *oc, void *data) | ||
124 | mc->units_per_default_bus = 1; | ||
125 | mc->ignore_memory_transaction_failures = true; | ||
126 | mc->max_cpus = XLNX_ZYNQMP_NUM_APU_CPUS + XLNX_ZYNQMP_NUM_RPU_CPUS; | ||
127 | + mc->default_cpus = XLNX_ZYNQMP_NUM_APU_CPUS; | ||
128 | } | ||
129 | |||
130 | static const TypeInfo xlnx_ep108_machine_init_typeinfo = { | ||
131 | @@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data) | ||
132 | mc->units_per_default_bus = 1; | ||
133 | mc->ignore_memory_transaction_failures = true; | ||
134 | mc->max_cpus = XLNX_ZYNQMP_NUM_APU_CPUS + XLNX_ZYNQMP_NUM_RPU_CPUS; | ||
135 | + mc->default_cpus = XLNX_ZYNQMP_NUM_APU_CPUS; | ||
136 | } | ||
137 | |||
138 | static const TypeInfo xlnx_zcu102_machine_init_typeinfo = { | ||
139 | diff --git a/vl.c b/vl.c | ||
140 | index XXXXXXX..XXXXXXX 100644 | ||
141 | --- a/vl.c | ||
142 | +++ b/vl.c | ||
143 | @@ -XXX,XX +XXX,XX @@ Chardev *virtcon_hds[MAX_VIRTIO_CONSOLES]; | ||
144 | Chardev *sclp_hds[MAX_SCLP_CONSOLES]; | ||
145 | int win2k_install_hack = 0; | ||
146 | int singlestep = 0; | ||
147 | -int smp_cpus = 1; | ||
148 | -unsigned int max_cpus = 1; | ||
149 | +int smp_cpus; | ||
150 | +unsigned int max_cpus; | ||
151 | int smp_cores = 1; | ||
152 | int smp_threads = 1; | ||
153 | int acpi_enabled = 1; | ||
154 | @@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv, char **envp) | ||
155 | exit(0); | ||
156 | } | ||
157 | |||
158 | + /* machine_class: default to UP */ | ||
159 | + machine_class->max_cpus = machine_class->max_cpus ?: 1; | ||
160 | + machine_class->min_cpus = machine_class->min_cpus ?: 1; | ||
161 | + machine_class->default_cpus = machine_class->default_cpus ?: 1; | ||
162 | + | ||
163 | + /* default to machine_class->default_cpus */ | ||
164 | + smp_cpus = machine_class->default_cpus; | ||
165 | + max_cpus = machine_class->default_cpus; | ||
166 | + | ||
167 | smp_parse(qemu_opts_find(qemu_find_opts("smp-opts"), NULL)); | ||
168 | |||
169 | - machine_class->max_cpus = machine_class->max_cpus ?: 1; /* Default to UP */ | ||
170 | + /* sanity-check smp_cpus and max_cpus against machine_class */ | ||
171 | + if (smp_cpus < machine_class->min_cpus) { | ||
172 | + error_report("Invalid SMP CPUs %d. The min CPUs " | ||
173 | + "supported by machine '%s' is %d", smp_cpus, | ||
174 | + machine_class->name, machine_class->min_cpus); | ||
175 | + exit(1); | ||
176 | + } | ||
177 | if (max_cpus > machine_class->max_cpus) { | ||
178 | error_report("Invalid SMP CPUs %d. The max CPUs " | ||
179 | "supported by machine '%s' is %d", max_cpus, | ||
180 | -- | 39 | -- |
181 | 2.7.4 | 40 | 2.25.1 |
182 | 41 | ||
183 | 42 | diff view generated by jsdifflib |
1 | From: "Emilio G. Cota" <cota@braap.org> | 1 | From: Shengtan Mao <stmao@google.com> |
---|---|---|---|
2 | 2 | ||
3 | Just like the zcu102, the ep108 can instantiate several CPUs. | 3 | Signed-off-by: Shengtan Mao <stmao@google.com> |
4 | 4 | Reviewed-by: Hao Wu <wuhaotsh@google.com> | |
5 | Signed-off-by: Emilio G. Cota <cota@braap.org> | 5 | Reviewed-by: Chris Rauer <crauer@google.com> |
6 | Reviewed-by: Alistair Francis <alistair.francis@xilinx.com> | 6 | Message-id: 20220102215844.2888833-3-venture@google.com |
7 | Message-id: 1510343626-25861-5-git-send-email-cota@braap.org | ||
8 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 7 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
9 | --- | 8 | --- |
10 | hw/arm/xlnx-zcu102.c | 1 + | 9 | hw/arm/npcm7xx_boards.c | 1 + |
11 | 1 file changed, 1 insertion(+) | 10 | 1 file changed, 1 insertion(+) |
12 | 11 | ||
13 | diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c | 12 | diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c |
14 | index XXXXXXX..XXXXXXX 100644 | 13 | index XXXXXXX..XXXXXXX 100644 |
15 | --- a/hw/arm/xlnx-zcu102.c | 14 | --- a/hw/arm/npcm7xx_boards.c |
16 | +++ b/hw/arm/xlnx-zcu102.c | 15 | +++ b/hw/arm/npcm7xx_boards.c |
17 | @@ -XXX,XX +XXX,XX @@ static void xlnx_ep108_machine_class_init(ObjectClass *oc, void *data) | 16 | @@ -XXX,XX +XXX,XX @@ static void kudo_bmc_init(MachineState *machine) |
18 | mc->block_default_type = IF_IDE; | 17 | drive_get(IF_MTD, 3, 0)); |
19 | mc->units_per_default_bus = 1; | 18 | |
20 | mc->ignore_memory_transaction_failures = true; | 19 | kudo_bmc_i2c_init(soc); |
21 | + mc->max_cpus = XLNX_ZYNQMP_NUM_APU_CPUS + XLNX_ZYNQMP_NUM_RPU_CPUS; | 20 | + sdhci_attach_drive(&soc->mmc.sdhci, 0); |
21 | npcm7xx_load_kernel(machine, soc); | ||
22 | } | 22 | } |
23 | 23 | ||
24 | static const TypeInfo xlnx_ep108_machine_init_typeinfo = { | ||
25 | -- | 24 | -- |
26 | 2.7.4 | 25 | 2.25.1 |
27 | 26 | ||
28 | 27 | diff view generated by jsdifflib |
1 | From: Prasad J Pandit <pjp@fedoraproject.org> | 1 | From: Patrick Venture <venture@google.com> |
---|---|---|---|
2 | 2 | ||
3 | An 'offset' parameter sent to highbank register r/w functions | 3 | Signed-off-by: Patrick Venture <venture@google.com> |
4 | could be greater than number(NUM_REGS=0x200) of hb registers, | 4 | Reviewed-by: Hao Wu <wuhaotsh@google.com> |
5 | leading to an OOB access issue. Add check to avoid it. | 5 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> |
6 | 6 | Message-id: 20220102215844.2888833-4-venture@google.com | |
7 | Reported-by: Moguofang (Dennis mo) <moguofang@huawei.com> | ||
8 | Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org> | ||
9 | Message-id: 20171113062658.9697-1-ppandit@redhat.com | ||
10 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
11 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 7 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
12 | --- | 8 | --- |
13 | hw/arm/highbank.c | 17 +++++++++++++++-- | 9 | hw/arm/npcm7xx_boards.c | 9 +++++++++ |
14 | 1 file changed, 15 insertions(+), 2 deletions(-) | 10 | 1 file changed, 9 insertions(+) |
15 | 11 | ||
16 | diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c | 12 | diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c |
17 | index XXXXXXX..XXXXXXX 100644 | 13 | index XXXXXXX..XXXXXXX 100644 |
18 | --- a/hw/arm/highbank.c | 14 | --- a/hw/arm/npcm7xx_boards.c |
19 | +++ b/hw/arm/highbank.c | 15 | +++ b/hw/arm/npcm7xx_boards.c |
20 | @@ -XXX,XX +XXX,XX @@ | 16 | @@ -XXX,XX +XXX,XX @@ static void quanta_gbs_i2c_init(NPCM7xxState *soc) |
21 | #include "hw/ide/ahci.h" | 17 | |
22 | #include "hw/cpu/a9mpcore.h" | 18 | static void kudo_bmc_i2c_init(NPCM7xxState *soc) |
23 | #include "hw/cpu/a15mpcore.h" | 19 | { |
24 | +#include "qemu/log.h" | 20 | + i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), TYPE_PCA9548, 0x75); |
25 | 21 | + i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), TYPE_PCA9548, 0x77); | |
26 | #define SMP_BOOT_ADDR 0x100 | 22 | + |
27 | #define SMP_BOOT_REG 0x40 | 23 | + i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 4), TYPE_PCA9548, 0x77); |
28 | @@ -XXX,XX +XXX,XX @@ static void hb_regs_write(void *opaque, hwaddr offset, | 24 | + |
29 | } | 25 | at24c_eeprom_init(soc, 4, 0x50, 8192); /* mbfru */ |
30 | } | 26 | + |
31 | 27 | + i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 13), TYPE_PCA9548, 0x77); | |
32 | - regs[offset/4] = value; | 28 | + |
33 | + if (offset / 4 >= NUM_REGS) { | 29 | at24c_eeprom_init(soc, 14, 0x55, 8192); /* bmcfru */ |
34 | + qemu_log_mask(LOG_GUEST_ERROR, | 30 | + |
35 | + "highbank: bad write offset 0x%" HWADDR_PRIx "\n", offset); | 31 | /* TODO: Add remaining i2c devices. */ |
36 | + return; | ||
37 | + } | ||
38 | + regs[offset / 4] = value; | ||
39 | } | 32 | } |
40 | 33 | ||
41 | static uint64_t hb_regs_read(void *opaque, hwaddr offset, | ||
42 | unsigned size) | ||
43 | { | ||
44 | + uint32_t value; | ||
45 | uint32_t *regs = opaque; | ||
46 | - uint32_t value = regs[offset/4]; | ||
47 | + | ||
48 | + if (offset / 4 >= NUM_REGS) { | ||
49 | + qemu_log_mask(LOG_GUEST_ERROR, | ||
50 | + "highbank: bad read offset 0x%" HWADDR_PRIx "\n", offset); | ||
51 | + return 0; | ||
52 | + } | ||
53 | + value = regs[offset / 4]; | ||
54 | |||
55 | if ((offset == 0x100) || (offset == 0x108) || (offset == 0x10C)) { | ||
56 | value |= 0x30000000; | ||
57 | -- | 34 | -- |
58 | 2.7.4 | 35 | 2.25.1 |
59 | 36 | ||
60 | 37 | diff view generated by jsdifflib |
1 | From: "Emilio G. Cota" <cota@braap.org> | 1 | From: Patrick Venture <venture@google.com> |
---|---|---|---|
2 | 2 | ||
3 | 55c3cee ("qom: Introduce CPUClass.tcg_initialize", 2017-10-24) | 3 | Add the four lm75s behind the mux on bus 13. |
4 | introduces a per-CPUClass bool that we check so that the target CPU | ||
5 | is initialized for TCG only once. This works well except when | ||
6 | we end up creating more than one CPUClass, in which case we end | ||
7 | up incorrectly initializing TCG more than once, i.e. once for | ||
8 | each CPUClass. | ||
9 | 4 | ||
10 | This can be replicated with: | 5 | Tested by booting the firmware: |
11 | $ aarch64-softmmu/qemu-system-aarch64 -machine xlnx-zcu102 -smp 6 \ | 6 | lm75 42-0048: hwmon0: sensor 'lm75' |
12 | -global driver=xlnx,,zynqmp,property=has_rpu,value=on | 7 | lm75 43-0049: supply vs not found, using dummy regulator |
13 | In this case the class name of the "RPUs" is prefixed by "cortex-r5-", | 8 | lm75 43-0049: hwmon1: sensor 'lm75' |
14 | whereas the "regular" CPUs are prefixed by "cortex-a53-". This | 9 | lm75 44-0048: supply vs not found, using dummy regulator |
15 | results in two CPUClass instances being created. | 10 | lm75 44-0048: hwmon2: sensor 'lm75' |
11 | lm75 45-0049: supply vs not found, using dummy regulator | ||
12 | lm75 45-0049: hwmon3: sensor 'lm75' | ||
16 | 13 | ||
17 | Fix it by introducing a static variable, so that only the first | 14 | Signed-off-by: Patrick Venture <venture@google.com> |
18 | target CPU being initialized will initialize the target-dependent | 15 | Reviewed-by: Titus Rwantare <titusr@google.com> |
19 | part of TCG, regardless of CPUClass instances. | 16 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> |
20 | 17 | Message-id: 20220102215844.2888833-5-venture@google.com | |
21 | Fixes: 55c3ceef61fcf06fc98ddc752b7cce788ce7680b | ||
22 | Signed-off-by: Emilio G. Cota <cota@braap.org> | ||
23 | Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> | ||
24 | Reviewed-by: Alistair Francis <alistair.francis@xilinx.com> | ||
25 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
26 | Tested-by: Alistair Francis <alistair.francis@xilinx.com> | ||
27 | Message-id: 1510343626-25861-2-git-send-email-cota@braap.org | ||
28 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 18 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
29 | --- | 19 | --- |
30 | include/qom/cpu.h | 1 - | 20 | hw/arm/npcm7xx_boards.c | 11 ++++++++++- |
31 | exec.c | 5 +++-- | 21 | 1 file changed, 10 insertions(+), 1 deletion(-) |
32 | 2 files changed, 3 insertions(+), 3 deletions(-) | ||
33 | 22 | ||
34 | diff --git a/include/qom/cpu.h b/include/qom/cpu.h | 23 | diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c |
35 | index XXXXXXX..XXXXXXX 100644 | 24 | index XXXXXXX..XXXXXXX 100644 |
36 | --- a/include/qom/cpu.h | 25 | --- a/hw/arm/npcm7xx_boards.c |
37 | +++ b/include/qom/cpu.h | 26 | +++ b/hw/arm/npcm7xx_boards.c |
38 | @@ -XXX,XX +XXX,XX @@ typedef struct CPUClass { | 27 | @@ -XXX,XX +XXX,XX @@ static void quanta_gbs_i2c_init(NPCM7xxState *soc) |
39 | /* Keep non-pointer data at the end to minimize holes. */ | 28 | |
40 | int gdb_num_core_regs; | 29 | static void kudo_bmc_i2c_init(NPCM7xxState *soc) |
41 | bool gdb_stop_before_watchpoint; | ||
42 | - bool tcg_initialized; | ||
43 | } CPUClass; | ||
44 | |||
45 | #ifdef HOST_WORDS_BIGENDIAN | ||
46 | diff --git a/exec.c b/exec.c | ||
47 | index XXXXXXX..XXXXXXX 100644 | ||
48 | --- a/exec.c | ||
49 | +++ b/exec.c | ||
50 | @@ -XXX,XX +XXX,XX @@ void cpu_exec_initfn(CPUState *cpu) | ||
51 | void cpu_exec_realizefn(CPUState *cpu, Error **errp) | ||
52 | { | 30 | { |
53 | CPUClass *cc = CPU_GET_CLASS(cpu); | 31 | + I2CSlave *i2c_mux; |
54 | + static bool tcg_target_initialized; | 32 | + |
55 | 33 | i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), TYPE_PCA9548, 0x75); | |
56 | cpu_list_add(cpu); | 34 | i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), TYPE_PCA9548, 0x77); |
57 | 35 | ||
58 | - if (tcg_enabled() && !cc->tcg_initialized) { | 36 | @@ -XXX,XX +XXX,XX @@ static void kudo_bmc_i2c_init(NPCM7xxState *soc) |
59 | - cc->tcg_initialized = true; | 37 | |
60 | + if (tcg_enabled() && !tcg_target_initialized) { | 38 | at24c_eeprom_init(soc, 4, 0x50, 8192); /* mbfru */ |
61 | + tcg_target_initialized = true; | 39 | |
62 | cc->tcg_initialize(); | 40 | - i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 13), TYPE_PCA9548, 0x77); |
63 | } | 41 | + i2c_mux = i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 13), |
42 | + TYPE_PCA9548, 0x77); | ||
43 | + | ||
44 | + /* tmp105 is compatible with the lm75 */ | ||
45 | + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 2), "tmp105", 0x48); | ||
46 | + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 3), "tmp105", 0x49); | ||
47 | + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 4), "tmp105", 0x48); | ||
48 | + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 5), "tmp105", 0x49); | ||
49 | |||
50 | at24c_eeprom_init(soc, 14, 0x55, 8192); /* bmcfru */ | ||
64 | 51 | ||
65 | -- | 52 | -- |
66 | 2.7.4 | 53 | 2.25.1 |
67 | 54 | ||
68 | 55 | diff view generated by jsdifflib |