1 | ARM queue for 2.10: all M profile bugfixes... | 1 | The following changes since commit 41fb4c14ee500125dc0ce6fb573cf84b8db29ed0: |
---|---|---|---|
2 | 2 | ||
3 | thanks | 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) |
4 | -- PMM | ||
5 | 4 | ||
6 | The following changes since commit 25dd0e77898c3e10796d4cbeb35e8af5ba6ce975: | 5 | are available in the Git repository at: |
7 | 6 | ||
8 | Merge remote-tracking branch 'remotes/mjt/tags/trivial-patches-fetch' into staging (2017-07-31 11:27:43 +0100) | 7 | https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220107 |
9 | 8 | ||
10 | are available in the git repository at: | 9 | for you to fetch changes up to b8905cc2dde95ca6be5e56d77053b1ca0b8fc182: |
11 | 10 | ||
12 | git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20170731 | 11 | hw/arm: kudo add lm75s on bus 13 (2022-01-07 17:08:01 +0000) |
13 | |||
14 | for you to fetch changes up to 89cbc3778a3d61761e2231e740269218c9a8a41d: | ||
15 | |||
16 | hw/mps2_scc: fix incorrect properties (2017-07-31 13:11:56 +0100) | ||
17 | 12 | ||
18 | ---------------------------------------------------------------- | 13 | ---------------------------------------------------------------- |
19 | target-arm queue: | 14 | target-arm queue: |
20 | * fix broken properties on MPS2 SCC device | 15 | * Add dummy Aspeed AST2600 Display Port MCU (DPMCU) |
21 | * fix MPU trace handling of write vs exec | 16 | * Add missing FEAT_TLBIOS instructions |
22 | * fix MPU M profile bugs: | 17 | * arm_gicv3_its: Various bug fixes and cleanups |
23 | - not handling system space or PPB region correctly | 18 | * kudo-bmc: Add more devices |
24 | - not resetting state | ||
25 | - not migrating MPU_RNR | ||
26 | 19 | ||
27 | ---------------------------------------------------------------- | 20 | ---------------------------------------------------------------- |
28 | Peter Maydell (6): | 21 | Chris Rauer (1): |
29 | target/arm: Correct MPU trace handling of write vs execute | 22 | hw/arm: Add kudo i2c eeproms. |
30 | target/arm: Don't do MPU lookups for addresses in M profile PPB region | ||
31 | target/arm: Don't allow guest to make System space executable for M profile | ||
32 | target/arm: Rename cp15.c6_rgnr to pmsav7.rnr | ||
33 | target/arm: Move PMSAv7 reset into arm_cpu_reset() so M profile MPUs get reset | ||
34 | target/arm: Migrate MPU_RNR register state for M profile cores | ||
35 | 23 | ||
36 | Philippe Mathieu-Daudé (1): | 24 | Idan Horowitz (1): |
37 | hw/mps2_scc: fix incorrect properties | 25 | target/arm: Add missing FEAT_TLBIOS instructions |
38 | 26 | ||
39 | target/arm/cpu.h | 3 +-- | 27 | Patrick Venture (2): |
40 | hw/intc/armv7m_nvic.c | 14 +++++----- | 28 | hw/arm: add i2c muxes to kudo-bmc |
41 | hw/misc/mps2-scc.c | 4 +-- | 29 | hw/arm: kudo add lm75s on bus 13 |
42 | target/arm/cpu.c | 14 ++++++++++ | ||
43 | target/arm/helper.c | 71 ++++++++++++++++++++++++++++++++++----------------- | ||
44 | target/arm/machine.c | 30 +++++++++++++++++++++- | ||
45 | 6 files changed, 101 insertions(+), 35 deletions(-) | ||
46 | 30 | ||
31 | Peter Maydell (13): | ||
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 | ||
45 | |||
46 | Shengtan Mao (1): | ||
47 | hw/arm: attach MMC to kudo-bmc | ||
48 | |||
49 | Troy Lee (1): | ||
50 | Add dummy Aspeed AST2600 Display Port MCU (DPMCU) | ||
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 |
New patch | |||
---|---|---|---|
1 | From: Troy Lee <troy_lee@aspeedtech.com> | ||
1 | 2 | ||
3 | AST2600 Display Port MCU introduces 0x18000000~0x1803FFFF as it's memory | ||
4 | and io address. If guest machine try to access DPMCU memory, it will | ||
5 | cause a fatal error. | ||
6 | |||
7 | Signed-off-by: Troy Lee <troy_lee@aspeedtech.com> | ||
8 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
9 | Reviewed-by: Cédric Le Goater <clg@kaod.org> | ||
10 | Message-id: 20211210083034.726610-1-troy_lee@aspeedtech.com | ||
11 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
12 | --- | ||
13 | include/hw/arm/aspeed_soc.h | 2 ++ | ||
14 | hw/arm/aspeed_ast2600.c | 8 ++++++++ | ||
15 | 2 files changed, 10 insertions(+) | ||
16 | |||
17 | diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h | ||
18 | index XXXXXXX..XXXXXXX 100644 | ||
19 | --- a/include/hw/arm/aspeed_soc.h | ||
20 | +++ b/include/hw/arm/aspeed_soc.h | ||
21 | @@ -XXX,XX +XXX,XX @@ enum { | ||
22 | ASPEED_DEV_EMMC, | ||
23 | ASPEED_DEV_KCS, | ||
24 | ASPEED_DEV_HACE, | ||
25 | + ASPEED_DEV_DPMCU, | ||
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); | ||
69 | + | ||
70 | /* SCU */ | ||
71 | if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) { | ||
72 | return; | ||
73 | -- | ||
74 | 2.25.1 | ||
75 | |||
76 | diff view generated by jsdifflib |
1 | When the PMSAv7 implementation was originally added it was for R profile | 1 | From: Idan Horowitz <idan.horowitz@gmail.com> |
---|---|---|---|
2 | CPUs only, and reset was handled using the cpreg .resetfn hooks. | ||
3 | Unfortunately for M profile cores this doesn't work, because they do | ||
4 | not register any cpregs. Move the reset handling into arm_cpu_reset(), | ||
5 | where it will work for both R profile and M profile cores. | ||
6 | 2 | ||
3 | Some of the instructions added by the FEAT_TLBIOS extension were forgotten | ||
4 | when the extension was originally added to QEMU. | ||
5 | |||
6 | Fixes: 7113d618505b ("target/arm: Add support for FEAT_TLBIOS") | ||
7 | Signed-off-by: Idan Horowitz <idan.horowitz@gmail.com> | ||
8 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
9 | Message-id: 20211231103928.1455657-1-idan.horowitz@gmail.com | ||
7 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
8 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
9 | Message-id: 1501153150-19984-5-git-send-email-peter.maydell@linaro.org | ||
10 | --- | 11 | --- |
11 | target/arm/cpu.c | 14 ++++++++++++++ | 12 | target/arm/helper.c | 32 ++++++++++++++++++++++++++++++++ |
12 | target/arm/helper.c | 28 ++++++++++++---------------- | 13 | 1 file changed, 32 insertions(+) |
13 | 2 files changed, 26 insertions(+), 16 deletions(-) | ||
14 | 14 | ||
15 | diff --git a/target/arm/cpu.c b/target/arm/cpu.c | ||
16 | index XXXXXXX..XXXXXXX 100644 | ||
17 | --- a/target/arm/cpu.c | ||
18 | +++ b/target/arm/cpu.c | ||
19 | @@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s) | ||
20 | |||
21 | env->vfp.xregs[ARM_VFP_FPEXC] = 0; | ||
22 | #endif | ||
23 | + | ||
24 | + if (arm_feature(env, ARM_FEATURE_PMSA) && | ||
25 | + arm_feature(env, ARM_FEATURE_V7)) { | ||
26 | + if (cpu->pmsav7_dregion > 0) { | ||
27 | + memset(env->pmsav7.drbar, 0, | ||
28 | + sizeof(*env->pmsav7.drbar) * cpu->pmsav7_dregion); | ||
29 | + memset(env->pmsav7.drsr, 0, | ||
30 | + sizeof(*env->pmsav7.drsr) * cpu->pmsav7_dregion); | ||
31 | + memset(env->pmsav7.dracr, 0, | ||
32 | + sizeof(*env->pmsav7.dracr) * cpu->pmsav7_dregion); | ||
33 | + } | ||
34 | + env->pmsav7.rnr = 0; | ||
35 | + } | ||
36 | + | ||
37 | set_flush_to_zero(1, &env->vfp.standard_fp_status); | ||
38 | set_flush_inputs_to_zero(1, &env->vfp.standard_fp_status); | ||
39 | set_default_nan_mode(1, &env->vfp.standard_fp_status); | ||
40 | diff --git a/target/arm/helper.c b/target/arm/helper.c | 15 | diff --git a/target/arm/helper.c b/target/arm/helper.c |
41 | index XXXXXXX..XXXXXXX 100644 | 16 | index XXXXXXX..XXXXXXX 100644 |
42 | --- a/target/arm/helper.c | 17 | --- a/target/arm/helper.c |
43 | +++ b/target/arm/helper.c | 18 | +++ b/target/arm/helper.c |
44 | @@ -XXX,XX +XXX,XX @@ static void pmsav7_write(CPUARMState *env, const ARMCPRegInfo *ri, | 19 | @@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo tlbios_reginfo[] = { |
45 | *u32p = value; | 20 | .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 0, |
46 | } | 21 | .access = PL1_W, .type = ARM_CP_NO_RAW, |
47 | 22 | .writefn = tlbi_aa64_vmalle1is_write }, | |
48 | -static void pmsav7_reset(CPUARMState *env, const ARMCPRegInfo *ri) | 23 | + { .name = "TLBI_VAE1OS", .state = ARM_CP_STATE_AA64, |
49 | -{ | 24 | + .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 1, |
50 | - ARMCPU *cpu = arm_env_get_cpu(env); | 25 | + .access = PL1_W, .type = ARM_CP_NO_RAW, |
51 | - uint32_t *u32p = *(uint32_t **)raw_ptr(env, ri); | 26 | + .writefn = tlbi_aa64_vae1is_write }, |
52 | - | 27 | { .name = "TLBI_ASIDE1OS", .state = ARM_CP_STATE_AA64, |
53 | - if (!u32p) { | 28 | .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 2, |
54 | - return; | 29 | .access = PL1_W, .type = ARM_CP_NO_RAW, |
55 | - } | 30 | .writefn = tlbi_aa64_vmalle1is_write }, |
56 | - | 31 | + { .name = "TLBI_VAAE1OS", .state = ARM_CP_STATE_AA64, |
57 | - memset(u32p, 0, sizeof(*u32p) * cpu->pmsav7_dregion); | 32 | + .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 3, |
58 | -} | 33 | + .access = PL1_W, .type = ARM_CP_NO_RAW, |
59 | - | 34 | + .writefn = tlbi_aa64_vae1is_write }, |
60 | static void pmsav7_rgnr_write(CPUARMState *env, const ARMCPRegInfo *ri, | 35 | + { .name = "TLBI_VALE1OS", .state = ARM_CP_STATE_AA64, |
61 | uint64_t value) | 36 | + .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 5, |
62 | { | 37 | + .access = PL1_W, .type = ARM_CP_NO_RAW, |
63 | @@ -XXX,XX +XXX,XX @@ static void pmsav7_rgnr_write(CPUARMState *env, const ARMCPRegInfo *ri, | 38 | + .writefn = tlbi_aa64_vae1is_write }, |
64 | } | 39 | + { .name = "TLBI_VAALE1OS", .state = ARM_CP_STATE_AA64, |
65 | 40 | + .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 7, | |
66 | static const ARMCPRegInfo pmsav7_cp_reginfo[] = { | 41 | + .access = PL1_W, .type = ARM_CP_NO_RAW, |
67 | + /* Reset for all these registers is handled in arm_cpu_reset(), | 42 | + .writefn = tlbi_aa64_vae1is_write }, |
68 | + * because the PMSAv7 is also used by M-profile CPUs, which do | 43 | { .name = "TLBI_ALLE2OS", .state = ARM_CP_STATE_AA64, |
69 | + * not register cpregs but still need the state to be reset. | 44 | .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 0, |
70 | + */ | 45 | .access = PL2_W, .type = ARM_CP_NO_RAW, |
71 | { .name = "DRBAR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 1, .opc2 = 0, | 46 | .writefn = tlbi_aa64_alle2is_write }, |
72 | .access = PL1_RW, .type = ARM_CP_NO_RAW, | 47 | + { .name = "TLBI_VAE2OS", .state = ARM_CP_STATE_AA64, |
73 | .fieldoffset = offsetof(CPUARMState, pmsav7.drbar), | 48 | + .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 1, |
74 | - .readfn = pmsav7_read, .writefn = pmsav7_write, .resetfn = pmsav7_reset }, | 49 | + .access = PL2_W, .type = ARM_CP_NO_RAW, |
75 | + .readfn = pmsav7_read, .writefn = pmsav7_write, | 50 | + .writefn = tlbi_aa64_vae2is_write }, |
76 | + .resetfn = arm_cp_reset_ignore }, | 51 | { .name = "TLBI_ALLE1OS", .state = ARM_CP_STATE_AA64, |
77 | { .name = "DRSR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 1, .opc2 = 2, | 52 | .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 4, |
78 | .access = PL1_RW, .type = ARM_CP_NO_RAW, | 53 | .access = PL2_W, .type = ARM_CP_NO_RAW, |
79 | .fieldoffset = offsetof(CPUARMState, pmsav7.drsr), | 54 | .writefn = tlbi_aa64_alle1is_write }, |
80 | - .readfn = pmsav7_read, .writefn = pmsav7_write, .resetfn = pmsav7_reset }, | 55 | + { .name = "TLBI_VALE2OS", .state = ARM_CP_STATE_AA64, |
81 | + .readfn = pmsav7_read, .writefn = pmsav7_write, | 56 | + .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 5, |
82 | + .resetfn = arm_cp_reset_ignore }, | 57 | + .access = PL2_W, .type = ARM_CP_NO_RAW, |
83 | { .name = "DRACR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 1, .opc2 = 4, | 58 | + .writefn = tlbi_aa64_vae2is_write }, |
84 | .access = PL1_RW, .type = ARM_CP_NO_RAW, | 59 | { .name = "TLBI_VMALLS12E1OS", .state = ARM_CP_STATE_AA64, |
85 | .fieldoffset = offsetof(CPUARMState, pmsav7.dracr), | 60 | .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 6, |
86 | - .readfn = pmsav7_read, .writefn = pmsav7_write, .resetfn = pmsav7_reset }, | 61 | .access = PL2_W, .type = ARM_CP_NO_RAW, |
87 | + .readfn = pmsav7_read, .writefn = pmsav7_write, | 62 | @@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo tlbios_reginfo[] = { |
88 | + .resetfn = arm_cp_reset_ignore }, | 63 | .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 0, |
89 | { .name = "RGNR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 2, .opc2 = 0, | 64 | .access = PL3_W, .type = ARM_CP_NO_RAW, |
90 | .access = PL1_RW, | 65 | .writefn = tlbi_aa64_alle3is_write }, |
91 | .fieldoffset = offsetof(CPUARMState, pmsav7.rnr), | 66 | + { .name = "TLBI_VAE3OS", .state = ARM_CP_STATE_AA64, |
92 | - .writefn = pmsav7_rgnr_write }, | 67 | + .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 1, |
93 | + .writefn = pmsav7_rgnr_write, | 68 | + .access = PL3_W, .type = ARM_CP_NO_RAW, |
94 | + .resetfn = arm_cp_reset_ignore }, | 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 }, | ||
95 | REGINFO_SENTINEL | 74 | REGINFO_SENTINEL |
96 | }; | 75 | }; |
97 | 76 | ||
98 | -- | 77 | -- |
99 | 2.7.4 | 78 | 2.25.1 |
100 | 79 | ||
101 | 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 |
1 | The PMSAv7 region number register is migrated for R profile | 1 | We currently define a bitmask for the GITS_CTLR ENABLED bit in |
---|---|---|---|
2 | cores using the cpreg scheme, but M profile doesn't use | 2 | two ways: as ITS_CTLR_ENABLED, and via the FIELD() macro as |
3 | cpregs, and so we weren't migrating the MPU_RNR register state | 3 | R_GITS_CTLR_ENABLED_MASK. Consistently use the FIELD macro version |
4 | at all. Fix that by adding a migration subsection for the | 4 | everywhere and remove the redundant ITS_CTLR_ENABLED define. |
5 | M profile case. | ||
6 | 5 | ||
7 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 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> | ||
8 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | 9 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> |
9 | Message-id: 1501153150-19984-6-git-send-email-peter.maydell@linaro.org | ||
10 | --- | 10 | --- |
11 | target/arm/machine.c | 28 ++++++++++++++++++++++++++++ | 11 | hw/intc/gicv3_internal.h | 2 -- |
12 | 1 file changed, 28 insertions(+) | 12 | hw/intc/arm_gicv3_its.c | 20 ++++++++++---------- |
13 | 2 files changed, 10 insertions(+), 12 deletions(-) | ||
13 | 14 | ||
14 | diff --git a/target/arm/machine.c b/target/arm/machine.c | 15 | diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h |
15 | index XXXXXXX..XXXXXXX 100644 | 16 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/target/arm/machine.c | 17 | --- a/hw/intc/gicv3_internal.h |
17 | +++ b/target/arm/machine.c | 18 | +++ b/hw/intc/gicv3_internal.h |
18 | @@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_pmsav7 = { | 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; | ||
19 | } | 39 | } |
20 | }; | 40 | |
21 | 41 | @@ -XXX,XX +XXX,XX @@ static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset, | |
22 | +static bool pmsav7_rnr_needed(void *opaque) | 42 | |
23 | +{ | 43 | switch (offset) { |
24 | + ARMCPU *cpu = opaque; | 44 | case GITS_TRANSLATER: |
25 | + CPUARMState *env = &cpu->env; | 45 | - if (s->ctlr & ITS_CTLR_ENABLED) { |
26 | + | 46 | + if (s->ctlr & R_GITS_CTLR_ENABLED_MASK) { |
27 | + /* For R profile cores pmsav7.rnr is migrated via the cpreg | 47 | devid = attrs.requester_id; |
28 | + * "RGNR" definition in helper.h. For M profile we have to | 48 | result = process_its_cmd(s, data, devid, NONE); |
29 | + * migrate it separately. | 49 | } |
30 | + */ | 50 | @@ -XXX,XX +XXX,XX @@ static bool its_writel(GICv3ITSState *s, hwaddr offset, |
31 | + return arm_feature(env, ARM_FEATURE_M); | 51 | switch (offset) { |
32 | +} | 52 | case GITS_CTLR: |
33 | + | 53 | if (value & R_GITS_CTLR_ENABLED_MASK) { |
34 | +static const VMStateDescription vmstate_pmsav7_rnr = { | 54 | - s->ctlr |= ITS_CTLR_ENABLED; |
35 | + .name = "cpu/pmsav7-rnr", | 55 | + s->ctlr |= R_GITS_CTLR_ENABLED_MASK; |
36 | + .version_id = 1, | 56 | extract_table_params(s); |
37 | + .minimum_version_id = 1, | 57 | extract_cmdq_params(s); |
38 | + .needed = pmsav7_rnr_needed, | 58 | s->creadr = 0; |
39 | + .fields = (VMStateField[]) { | 59 | process_cmdq(s); |
40 | + VMSTATE_UINT32(env.pmsav7.rnr, ARMCPU), | 60 | } else { |
41 | + VMSTATE_END_OF_LIST() | 61 | - s->ctlr &= ~ITS_CTLR_ENABLED; |
42 | + } | 62 | + s->ctlr &= ~R_GITS_CTLR_ENABLED_MASK; |
43 | +}; | 63 | } |
44 | + | 64 | break; |
45 | static int get_cpsr(QEMUFile *f, void *opaque, size_t size, | 65 | case GITS_CBASER: |
46 | VMStateField *field) | 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) | ||
47 | { | 114 | { |
48 | @@ -XXX,XX +XXX,XX @@ const VMStateDescription vmstate_arm_cpu = { | 115 | - if (s->ctlr & ITS_CTLR_ENABLED) { |
49 | &vmstate_iwmmxt, | 116 | + if (s->ctlr & R_GITS_CTLR_ENABLED_MASK) { |
50 | &vmstate_m, | 117 | extract_table_params(s); |
51 | &vmstate_thumb2ee, | 118 | extract_cmdq_params(s); |
52 | + /* pmsav7_rnr must come before pmsav7 so that we have the | ||
53 | + * region number before we test it in the VMSTATE_VALIDATE | ||
54 | + * in vmstate_pmsav7. | ||
55 | + */ | ||
56 | + &vmstate_pmsav7_rnr, | ||
57 | &vmstate_pmsav7, | ||
58 | NULL | ||
59 | } | 119 | } |
60 | -- | 120 | -- |
61 | 2.7.4 | 121 | 2.25.1 |
62 | 122 | ||
63 | 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 |
1 | Correct off-by-one bug in the PSMAv7 MPU tracing where it would print | 1 | In extract_table_params() we process each GITS_BASER<n> register. If |
---|---|---|---|
2 | a write access as "reading", an insn fetch as "writing", and a read | 2 | the register's Valid bit is not set, this means there is no |
3 | access as "execute". | 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. | ||
4 | 8 | ||
5 | Since we have an MMUAccessType enum now, we can make the code clearer | 9 | This has no real guest-visible effects because (since we don't have |
6 | in the process by using that rather than the raw 0/1/2 values. | 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>. | ||
7 | 16 | ||
8 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 17 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
9 | Reviewed-by: Richard Henderson <rth@twiddle.net> | 18 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> |
10 | Message-id: 1500906792-18010-1-git-send-email-peter.maydell@linaro.org | 19 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> |
11 | --- | 20 | --- |
12 | target/arm/helper.c | 4 ++-- | 21 | hw/intc/arm_gicv3_its.c | 4 ++-- |
13 | 1 file changed, 2 insertions(+), 2 deletions(-) | 22 | 1 file changed, 2 insertions(+), 2 deletions(-) |
14 | 23 | ||
15 | diff --git a/target/arm/helper.c b/target/arm/helper.c | 24 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c |
16 | index XXXXXXX..XXXXXXX 100644 | 25 | index XXXXXXX..XXXXXXX 100644 |
17 | --- a/target/arm/helper.c | 26 | --- a/hw/intc/arm_gicv3_its.c |
18 | +++ b/target/arm/helper.c | 27 | +++ b/hw/intc/arm_gicv3_its.c |
19 | @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr(CPUARMState *env, target_ulong address, | 28 | @@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s) |
20 | phys_ptr, prot, fsr); | 29 | s->dt.valid = FIELD_EX64(value, GITS_BASER, VALID); |
21 | qemu_log_mask(CPU_LOG_MMU, "PMSAv7 MPU lookup for %s at 0x%08" PRIx32 | 30 | |
22 | " mmu_idx %u -> %s (prot %c%c%c)\n", | 31 | if (!s->dt.valid) { |
23 | - access_type == 1 ? "reading" : | 32 | - return; |
24 | - (access_type == 2 ? "writing" : "execute"), | 33 | + break; |
25 | + access_type == MMU_DATA_LOAD ? "reading" : | 34 | } |
26 | + (access_type == MMU_DATA_STORE ? "writing" : "execute"), | 35 | |
27 | (uint32_t)address, mmu_idx, | 36 | s->dt.page_sz = page_sz; |
28 | ret ? "Miss" : "Hit", | 37 | @@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s) |
29 | *prot & PAGE_READ ? 'r' : '-', | 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; | ||
30 | -- | 46 | -- |
31 | 2.7.4 | 47 | 2.25.1 |
32 | 48 | ||
33 | 49 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
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. | ||
1 | 8 | ||
9 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
10 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
11 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> | ||
12 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
13 | --- | ||
14 | hw/intc/arm_gicv3_its.c | 97 +++++++++++++++++------------------------ | ||
15 | 1 file changed, 40 insertions(+), 57 deletions(-) | ||
16 | |||
17 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c | ||
18 | index XXXXXXX..XXXXXXX 100644 | ||
19 | --- a/hw/intc/arm_gicv3_its.c | ||
20 | +++ b/hw/intc/arm_gicv3_its.c | ||
21 | @@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s) | ||
22 | uint64_t value; | ||
23 | |||
24 | for (int i = 0; i < 8; i++) { | ||
25 | + TableDesc *td; | ||
26 | + int idbits; | ||
27 | + | ||
28 | value = s->baser[i]; | ||
29 | |||
30 | if (!value) { | ||
31 | @@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s) | ||
32 | type = FIELD_EX64(value, GITS_BASER, TYPE); | ||
33 | |||
34 | switch (type) { | ||
35 | - | ||
36 | case GITS_BASER_TYPE_DEVICE: | ||
37 | - memset(&s->dt, 0 , sizeof(s->dt)); | ||
38 | - s->dt.valid = FIELD_EX64(value, GITS_BASER, VALID); | ||
39 | - | ||
40 | - if (!s->dt.valid) { | ||
41 | - break; | ||
42 | - } | ||
43 | - | ||
44 | - s->dt.page_sz = page_sz; | ||
45 | - s->dt.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT); | ||
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 | } | ||
140 | } | ||
141 | |||
142 | -- | ||
143 | 2.25.1 | ||
144 | |||
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 |
New patch | |||
---|---|---|---|
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.) | ||
1 | 5 | ||
6 | We didn't quite get this right. In particular the error checks for | ||
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. | ||
10 | |||
11 | We can fix this bug and in the process simplify the code by switching | ||
12 | to the obvious implementation of setting pIntid = eventid early | ||
13 | if ignore_pInt is true. | ||
14 | |||
15 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
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(-) | ||
21 | |||
22 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c | ||
23 | index XXXXXXX..XXXXXXX 100644 | ||
24 | --- a/hw/intc/arm_gicv3_its.c | ||
25 | +++ b/hw/intc/arm_gicv3_its.c | ||
26 | @@ -XXX,XX +XXX,XX @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset, | ||
27 | |||
28 | eventid = (value & EVENTID_MASK); | ||
29 | |||
30 | - if (!ignore_pInt) { | ||
31 | + if (ignore_pInt) { | ||
32 | + pIntid = eventid; | ||
33 | + } else { | ||
34 | pIntid = ((value & pINTID_MASK) >> pINTID_SHIFT); | ||
35 | } | ||
36 | |||
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 | |||
68 | -- | ||
69 | 2.25.1 | ||
70 | |||
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 | Almost all of the PMSAv7 state is in the pmsav7 substruct of | 1 | Use FIELD macros to handle CTEs, rather than ad-hoc mask-and-shift. |
---|---|---|---|
2 | the ARM CPU state structure. The exception is the region | ||
3 | number register, which is in cp15.c6_rgnr. This exception | ||
4 | is a bit odd for M profile, which otherwise generally does | ||
5 | not store state in the cp15 substruct. | ||
6 | |||
7 | Rename cp15.c6_rgnr to pmsav7.rnr accordingly. | ||
8 | 2 | ||
9 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 3 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
10 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | 4 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> |
11 | Message-id: 1501153150-19984-4-git-send-email-peter.maydell@linaro.org | 5 | Reviewed-by: Richard Henderson <richard.henderson@linaro.org> |
12 | --- | 6 | --- |
13 | target/arm/cpu.h | 3 +-- | 7 | hw/intc/gicv3_internal.h | 3 ++- |
14 | hw/intc/armv7m_nvic.c | 14 +++++++------- | 8 | hw/intc/arm_gicv3_its.c | 7 ++++--- |
15 | target/arm/helper.c | 6 +++--- | 9 | 2 files changed, 6 insertions(+), 4 deletions(-) |
16 | target/arm/machine.c | 2 +- | ||
17 | 4 files changed, 12 insertions(+), 13 deletions(-) | ||
18 | 10 | ||
19 | diff --git a/target/arm/cpu.h b/target/arm/cpu.h | 11 | diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h |
20 | index XXXXXXX..XXXXXXX 100644 | 12 | index XXXXXXX..XXXXXXX 100644 |
21 | --- a/target/arm/cpu.h | 13 | --- a/hw/intc/gicv3_internal.h |
22 | +++ b/target/arm/cpu.h | 14 | +++ b/hw/intc/gicv3_internal.h |
23 | @@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState { | 15 | @@ -XXX,XX +XXX,XX @@ FIELD(DTE, ITTADDR, 6, 44) |
24 | uint64_t par_el[4]; | 16 | * Valid = 1 bit, RDBase = 16 bits |
25 | }; | 17 | */ |
26 | 18 | #define GITS_CTE_SIZE (0x8ULL) | |
27 | - uint32_t c6_rgnr; | 19 | -#define GITS_CTE_RDBASE_PROCNUM_MASK MAKE_64BIT_MASK(1, RDBASE_PROCNUM_LENGTH) |
28 | - | 20 | +FIELD(CTE, VALID, 0, 1) |
29 | uint32_t c9_insn; /* Cache lockdown registers. */ | 21 | +FIELD(CTE, RDBASE, 1, RDBASE_PROCNUM_LENGTH) |
30 | uint32_t c9_data; | 22 | |
31 | uint64_t c9_pmcr; /* performance monitor control register */ | 23 | /* Special interrupt IDs */ |
32 | @@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState { | 24 | #define INTID_SECURE 1020 |
33 | uint32_t *drbar; | 25 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c |
34 | uint32_t *drsr; | ||
35 | uint32_t *dracr; | ||
36 | + uint32_t rnr; | ||
37 | } pmsav7; | ||
38 | |||
39 | void *nvic; | ||
40 | diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c | ||
41 | index XXXXXXX..XXXXXXX 100644 | 26 | index XXXXXXX..XXXXXXX 100644 |
42 | --- a/hw/intc/armv7m_nvic.c | 27 | --- a/hw/intc/arm_gicv3_its.c |
43 | +++ b/hw/intc/armv7m_nvic.c | 28 | +++ b/hw/intc/arm_gicv3_its.c |
44 | @@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset) | 29 | @@ -XXX,XX +XXX,XX @@ static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte, |
45 | case 0xd94: /* MPU_CTRL */ | 30 | MEMTXATTRS_UNSPECIFIED, res); |
46 | return cpu->env.v7m.mpu_ctrl; | ||
47 | case 0xd98: /* MPU_RNR */ | ||
48 | - return cpu->env.cp15.c6_rgnr; | ||
49 | + return cpu->env.pmsav7.rnr; | ||
50 | case 0xd9c: /* MPU_RBAR */ | ||
51 | case 0xda4: /* MPU_RBAR_A1 */ | ||
52 | case 0xdac: /* MPU_RBAR_A2 */ | ||
53 | case 0xdb4: /* MPU_RBAR_A3 */ | ||
54 | { | ||
55 | - int region = cpu->env.cp15.c6_rgnr; | ||
56 | + int region = cpu->env.pmsav7.rnr; | ||
57 | |||
58 | if (region >= cpu->pmsav7_dregion) { | ||
59 | return 0; | ||
60 | @@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset) | ||
61 | case 0xdb0: /* MPU_RASR_A2 */ | ||
62 | case 0xdb8: /* MPU_RASR_A3 */ | ||
63 | { | ||
64 | - int region = cpu->env.cp15.c6_rgnr; | ||
65 | + int region = cpu->env.pmsav7.rnr; | ||
66 | |||
67 | if (region >= cpu->pmsav7_dregion) { | ||
68 | return 0; | ||
69 | @@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value) | ||
70 | PRIu32 "/%" PRIu32 "\n", | ||
71 | value, cpu->pmsav7_dregion); | ||
72 | } else { | ||
73 | - cpu->env.cp15.c6_rgnr = value; | ||
74 | + cpu->env.pmsav7.rnr = value; | ||
75 | } | ||
76 | break; | ||
77 | case 0xd9c: /* MPU_RBAR */ | ||
78 | @@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value) | ||
79 | region, cpu->pmsav7_dregion); | ||
80 | return; | ||
81 | } | ||
82 | - cpu->env.cp15.c6_rgnr = region; | ||
83 | + cpu->env.pmsav7.rnr = region; | ||
84 | } else { | ||
85 | - region = cpu->env.cp15.c6_rgnr; | ||
86 | + region = cpu->env.pmsav7.rnr; | ||
87 | } | ||
88 | |||
89 | if (region >= cpu->pmsav7_dregion) { | ||
90 | @@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value) | ||
91 | case 0xdb0: /* MPU_RASR_A2 */ | ||
92 | case 0xdb8: /* MPU_RASR_A3 */ | ||
93 | { | ||
94 | - int region = cpu->env.cp15.c6_rgnr; | ||
95 | + int region = cpu->env.pmsav7.rnr; | ||
96 | |||
97 | if (region >= cpu->pmsav7_dregion) { | ||
98 | return; | ||
99 | diff --git a/target/arm/helper.c b/target/arm/helper.c | ||
100 | index XXXXXXX..XXXXXXX 100644 | ||
101 | --- a/target/arm/helper.c | ||
102 | +++ b/target/arm/helper.c | ||
103 | @@ -XXX,XX +XXX,XX @@ static uint64_t pmsav7_read(CPUARMState *env, const ARMCPRegInfo *ri) | ||
104 | return 0; | ||
105 | } | 31 | } |
106 | 32 | ||
107 | - u32p += env->cp15.c6_rgnr; | 33 | - return (*cte & TABLE_ENTRY_VALID_MASK) != 0; |
108 | + u32p += env->pmsav7.rnr; | 34 | + return FIELD_EX64(*cte, CTE, VALID); |
109 | return *u32p; | ||
110 | } | 35 | } |
111 | 36 | ||
112 | @@ -XXX,XX +XXX,XX @@ static void pmsav7_write(CPUARMState *env, const ARMCPRegInfo *ri, | 37 | static bool update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte, |
113 | return; | 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); | ||
114 | } | 54 | } |
115 | 55 | ||
116 | - u32p += env->cp15.c6_rgnr; | 56 | /* |
117 | + u32p += env->pmsav7.rnr; | ||
118 | tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */ | ||
119 | *u32p = value; | ||
120 | } | ||
121 | @@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo pmsav7_cp_reginfo[] = { | ||
122 | .readfn = pmsav7_read, .writefn = pmsav7_write, .resetfn = pmsav7_reset }, | ||
123 | { .name = "RGNR", .cp = 15, .crn = 6, .opc1 = 0, .crm = 2, .opc2 = 0, | ||
124 | .access = PL1_RW, | ||
125 | - .fieldoffset = offsetof(CPUARMState, cp15.c6_rgnr), | ||
126 | + .fieldoffset = offsetof(CPUARMState, pmsav7.rnr), | ||
127 | .writefn = pmsav7_rgnr_write }, | ||
128 | REGINFO_SENTINEL | ||
129 | }; | ||
130 | diff --git a/target/arm/machine.c b/target/arm/machine.c | ||
131 | index XXXXXXX..XXXXXXX 100644 | ||
132 | --- a/target/arm/machine.c | ||
133 | +++ b/target/arm/machine.c | ||
134 | @@ -XXX,XX +XXX,XX @@ static bool pmsav7_rgnr_vmstate_validate(void *opaque, int version_id) | ||
135 | { | ||
136 | ARMCPU *cpu = opaque; | ||
137 | |||
138 | - return cpu->env.cp15.c6_rgnr < cpu->pmsav7_dregion; | ||
139 | + return cpu->env.pmsav7.rnr < cpu->pmsav7_dregion; | ||
140 | } | ||
141 | |||
142 | static const VMStateDescription vmstate_pmsav7 = { | ||
143 | -- | 57 | -- |
144 | 2.7.4 | 58 | 2.25.1 |
145 | 59 | ||
146 | 60 | diff view generated by jsdifflib |
1 | The M profile PMSAv7 specification says that if the address being looked | 1 | The ITS code has to check whether various parameters passed in |
---|---|---|---|
2 | up is in the PPB region (0xe0000000 - 0xe00fffff) then we do not use | 2 | commands are in-bounds, where the limit is defined in terms of the |
3 | the MPU regions but always use the default memory map. Implement this | 3 | number of bits that are available for the parameter. (For example, |
4 | (we were previously behaving like an R profile PMSAv7, which does not | 4 | the GITS_TYPER.Devbits ID register field specifies the number of |
5 | special case this). | 5 | DeviceID bits minus 1, and device IDs passed in the MAPTI and MAPD |
6 | command packets must fit in that many bits.) | ||
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. | ||
6 | 32 | ||
7 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 33 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
8 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | 34 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> |
9 | Message-id: 1501153150-19984-2-git-send-email-peter.maydell@linaro.org | ||
10 | --- | 35 | --- |
11 | target/arm/helper.c | 17 ++++++++++++++++- | 36 | include/hw/intc/arm_gicv3_its_common.h | 6 +++--- |
12 | 1 file changed, 16 insertions(+), 1 deletion(-) | 37 | hw/intc/arm_gicv3_its.c | 26 +++++++++++++------------- |
38 | 2 files changed, 16 insertions(+), 16 deletions(-) | ||
13 | 39 | ||
14 | diff --git a/target/arm/helper.c b/target/arm/helper.c | 40 | diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h |
15 | index XXXXXXX..XXXXXXX 100644 | 41 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/target/arm/helper.c | 42 | --- a/include/hw/intc/arm_gicv3_its_common.h |
17 | +++ b/target/arm/helper.c | 43 | +++ b/include/hw/intc/arm_gicv3_its_common.h |
18 | @@ -XXX,XX +XXX,XX @@ static bool pmsav7_use_background_region(ARMCPU *cpu, | 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; | ||
19 | } | 148 | } |
20 | } | 149 | } |
21 | 150 | ||
22 | +static inline bool m_is_ppb_region(CPUARMState *env, uint32_t address) | 151 | @@ -XXX,XX +XXX,XX @@ static void extract_cmdq_params(GICv3ITSState *s) |
23 | +{ | 152 | s->cq.valid = FIELD_EX64(value, GITS_CBASER, VALID); |
24 | + /* True if address is in the M profile PPB region 0xe0000000 - 0xe00fffff */ | 153 | |
25 | + return arm_feature(env, ARM_FEATURE_M) && | 154 | if (s->cq.valid) { |
26 | + extract32(address, 20, 12) == 0xe00; | 155 | - s->cq.max_entries = (num_pages * GITS_PAGE_SIZE_4K) / |
27 | +} | 156 | + s->cq.num_entries = (num_pages * GITS_PAGE_SIZE_4K) / |
28 | + | 157 | GITS_CMDQ_ENTRY_SIZE; |
29 | static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, | 158 | s->cq.base_addr = FIELD_EX64(value, GITS_CBASER, PHYADDR); |
30 | int access_type, ARMMMUIdx mmu_idx, | 159 | s->cq.base_addr <<= R_GITS_CBASER_PHYADDR_SHIFT; |
31 | hwaddr *phys_ptr, int *prot, uint32_t *fsr) | ||
32 | @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, | ||
33 | *phys_ptr = address; | ||
34 | *prot = 0; | ||
35 | |||
36 | - if (regime_translation_disabled(env, mmu_idx)) { /* MPU disabled */ | ||
37 | + if (regime_translation_disabled(env, mmu_idx) || | ||
38 | + m_is_ppb_region(env, address)) { | ||
39 | + /* MPU disabled or M profile PPB access: use default memory map. | ||
40 | + * The other case which uses the default memory map in the | ||
41 | + * v7M ARM ARM pseudocode is exception vector reads from the vector | ||
42 | + * table. In QEMU those accesses are done in arm_v7m_load_vector(), | ||
43 | + * which always does a direct read using address_space_ldl(), rather | ||
44 | + * than going via this function, so we don't need to check that here. | ||
45 | + */ | ||
46 | get_phys_addr_pmsav7_default(env, mmu_idx, address, prot); | ||
47 | } else { /* MPU enabled */ | ||
48 | for (n = (int)cpu->pmsav7_dregion - 1; n >= 0; n--) { | ||
49 | -- | 160 | -- |
50 | 2.7.4 | 161 | 2.25.1 |
51 | 162 | ||
52 | 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 | For an M profile v7PMSA, the system space (0xe0000000 - 0xffffffff) can | 1 | From: Chris Rauer <crauer@google.com> |
---|---|---|---|
2 | never be executable, even if the guest tries to set the MPU registers | ||
3 | up that way. Enforce this restriction. | ||
4 | 2 | ||
3 | Signed-off-by: Chris Rauer <crauer@google.com> | ||
4 | Reviewed-by: Hao Wu <wuhaotsh@google.com> | ||
5 | Reviewed-by: Patrick Venture <venture@google.com> | ||
6 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
7 | Message-id: 20220102215844.2888833-2-venture@google.com | ||
5 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 8 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
6 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
7 | Message-id: 1501153150-19984-3-git-send-email-peter.maydell@linaro.org | ||
8 | --- | 9 | --- |
9 | target/arm/helper.c | 16 +++++++++++++++- | 10 | hw/arm/npcm7xx_boards.c | 8 ++++++++ |
10 | 1 file changed, 15 insertions(+), 1 deletion(-) | 11 | 1 file changed, 8 insertions(+) |
11 | 12 | ||
12 | diff --git a/target/arm/helper.c b/target/arm/helper.c | 13 | diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c |
13 | index XXXXXXX..XXXXXXX 100644 | 14 | index XXXXXXX..XXXXXXX 100644 |
14 | --- a/target/arm/helper.c | 15 | --- a/hw/arm/npcm7xx_boards.c |
15 | +++ b/target/arm/helper.c | 16 | +++ b/hw/arm/npcm7xx_boards.c |
16 | @@ -XXX,XX +XXX,XX @@ static inline bool m_is_ppb_region(CPUARMState *env, uint32_t address) | 17 | @@ -XXX,XX +XXX,XX @@ static void quanta_gbs_i2c_init(NPCM7xxState *soc) |
17 | extract32(address, 20, 12) == 0xe00; | 18 | */ |
18 | } | 19 | } |
19 | 20 | ||
20 | +static inline bool m_is_system_region(CPUARMState *env, uint32_t address) | 21 | +static void kudo_bmc_i2c_init(NPCM7xxState *soc) |
21 | +{ | 22 | +{ |
22 | + /* True if address is in the M profile system region | 23 | + at24c_eeprom_init(soc, 4, 0x50, 8192); /* mbfru */ |
23 | + * 0xe0000000 - 0xffffffff | 24 | + at24c_eeprom_init(soc, 14, 0x55, 8192); /* bmcfru */ |
24 | + */ | 25 | + /* TODO: Add remaining i2c devices. */ |
25 | + return arm_feature(env, ARM_FEATURE_M) && extract32(address, 29, 3) == 0x7; | ||
26 | +} | 26 | +} |
27 | + | 27 | + |
28 | static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, | 28 | static void npcm750_evb_init(MachineState *machine) |
29 | int access_type, ARMMMUIdx mmu_idx, | 29 | { |
30 | hwaddr *phys_ptr, int *prot, uint32_t *fsr) | 30 | NPCM7xxState *soc; |
31 | @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, | 31 | @@ -XXX,XX +XXX,XX @@ static void kudo_bmc_init(MachineState *machine) |
32 | get_phys_addr_pmsav7_default(env, mmu_idx, address, prot); | 32 | npcm7xx_connect_flash(&soc->fiu[1], 0, "mx66u51235f", |
33 | } else { /* a MPU hit! */ | 33 | drive_get(IF_MTD, 3, 0)); |
34 | uint32_t ap = extract32(env->pmsav7.dracr[n], 8, 3); | 34 | |
35 | + uint32_t xn = extract32(env->pmsav7.dracr[n], 12, 1); | 35 | + kudo_bmc_i2c_init(soc); |
36 | + | 36 | npcm7xx_load_kernel(machine, soc); |
37 | + if (m_is_system_region(env, address)) { | 37 | } |
38 | + /* System space is always execute never */ | 38 | |
39 | + xn = 1; | ||
40 | + } | ||
41 | |||
42 | if (is_user) { /* User mode AP bit decoding */ | ||
43 | switch (ap) { | ||
44 | @@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, | ||
45 | } | ||
46 | |||
47 | /* execute never */ | ||
48 | - if (env->pmsav7.dracr[n] & (1 << 12)) { | ||
49 | + if (xn) { | ||
50 | *prot &= ~PAGE_EXEC; | ||
51 | } | ||
52 | } | ||
53 | -- | 39 | -- |
54 | 2.7.4 | 40 | 2.25.1 |
55 | 41 | ||
56 | 42 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Shengtan Mao <stmao@google.com> | ||
1 | 2 | ||
3 | Signed-off-by: Shengtan Mao <stmao@google.com> | ||
4 | Reviewed-by: Hao Wu <wuhaotsh@google.com> | ||
5 | Reviewed-by: Chris Rauer <crauer@google.com> | ||
6 | Message-id: 20220102215844.2888833-3-venture@google.com | ||
7 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
8 | --- | ||
9 | hw/arm/npcm7xx_boards.c | 1 + | ||
10 | 1 file changed, 1 insertion(+) | ||
11 | |||
12 | diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c | ||
13 | index XXXXXXX..XXXXXXX 100644 | ||
14 | --- a/hw/arm/npcm7xx_boards.c | ||
15 | +++ b/hw/arm/npcm7xx_boards.c | ||
16 | @@ -XXX,XX +XXX,XX @@ static void kudo_bmc_init(MachineState *machine) | ||
17 | drive_get(IF_MTD, 3, 0)); | ||
18 | |||
19 | kudo_bmc_i2c_init(soc); | ||
20 | + sdhci_attach_drive(&soc->mmc.sdhci, 0); | ||
21 | npcm7xx_load_kernel(machine, soc); | ||
22 | } | ||
23 | |||
24 | -- | ||
25 | 2.25.1 | ||
26 | |||
27 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Patrick Venture <venture@google.com> | ||
1 | 2 | ||
3 | Signed-off-by: Patrick Venture <venture@google.com> | ||
4 | Reviewed-by: Hao Wu <wuhaotsh@google.com> | ||
5 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
6 | Message-id: 20220102215844.2888833-4-venture@google.com | ||
7 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
8 | --- | ||
9 | hw/arm/npcm7xx_boards.c | 9 +++++++++ | ||
10 | 1 file changed, 9 insertions(+) | ||
11 | |||
12 | diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c | ||
13 | index XXXXXXX..XXXXXXX 100644 | ||
14 | --- a/hw/arm/npcm7xx_boards.c | ||
15 | +++ b/hw/arm/npcm7xx_boards.c | ||
16 | @@ -XXX,XX +XXX,XX @@ static void quanta_gbs_i2c_init(NPCM7xxState *soc) | ||
17 | |||
18 | static void kudo_bmc_i2c_init(NPCM7xxState *soc) | ||
19 | { | ||
20 | + i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), TYPE_PCA9548, 0x75); | ||
21 | + i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), TYPE_PCA9548, 0x77); | ||
22 | + | ||
23 | + i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 4), TYPE_PCA9548, 0x77); | ||
24 | + | ||
25 | at24c_eeprom_init(soc, 4, 0x50, 8192); /* mbfru */ | ||
26 | + | ||
27 | + i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 13), TYPE_PCA9548, 0x77); | ||
28 | + | ||
29 | at24c_eeprom_init(soc, 14, 0x55, 8192); /* bmcfru */ | ||
30 | + | ||
31 | /* TODO: Add remaining i2c devices. */ | ||
32 | } | ||
33 | |||
34 | -- | ||
35 | 2.25.1 | ||
36 | |||
37 | diff view generated by jsdifflib |
1 | From: Philippe Mathieu-Daudé <f4bug@amsat.org> | 1 | From: Patrick Venture <venture@google.com> |
---|---|---|---|
2 | 2 | ||
3 | Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | 3 | Add the four lm75s behind the mux on bus 13. |
4 | Message-id: 20170729234930.725-1-f4bug@amsat.org | 4 | |
5 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | 5 | Tested by booting the firmware: |
6 | lm75 42-0048: hwmon0: sensor 'lm75' | ||
7 | lm75 43-0049: supply vs not found, using dummy regulator | ||
8 | lm75 43-0049: hwmon1: sensor 'lm75' | ||
9 | lm75 44-0048: supply vs not found, using dummy regulator | ||
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' | ||
13 | |||
14 | Signed-off-by: Patrick Venture <venture@google.com> | ||
15 | Reviewed-by: Titus Rwantare <titusr@google.com> | ||
16 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | ||
17 | Message-id: 20220102215844.2888833-5-venture@google.com | ||
6 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | 18 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> |
7 | --- | 19 | --- |
8 | hw/misc/mps2-scc.c | 4 ++-- | 20 | hw/arm/npcm7xx_boards.c | 11 ++++++++++- |
9 | 1 file changed, 2 insertions(+), 2 deletions(-) | 21 | 1 file changed, 10 insertions(+), 1 deletion(-) |
10 | 22 | ||
11 | diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c | 23 | diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c |
12 | index XXXXXXX..XXXXXXX 100644 | 24 | index XXXXXXX..XXXXXXX 100644 |
13 | --- a/hw/misc/mps2-scc.c | 25 | --- a/hw/arm/npcm7xx_boards.c |
14 | +++ b/hw/misc/mps2-scc.c | 26 | +++ b/hw/arm/npcm7xx_boards.c |
15 | @@ -XXX,XX +XXX,XX @@ static Property mps2_scc_properties[] = { | 27 | @@ -XXX,XX +XXX,XX @@ static void quanta_gbs_i2c_init(NPCM7xxState *soc) |
16 | /* Values for various read-only ID registers (which are specific | 28 | |
17 | * to the board model or FPGA image) | 29 | static void kudo_bmc_i2c_init(NPCM7xxState *soc) |
18 | */ | 30 | { |
19 | - DEFINE_PROP_UINT32("scc-cfg4", MPS2SCC, aid, 0), | 31 | + I2CSlave *i2c_mux; |
20 | + DEFINE_PROP_UINT32("scc-cfg4", MPS2SCC, cfg4, 0), | 32 | + |
21 | DEFINE_PROP_UINT32("scc-aid", MPS2SCC, aid, 0), | 33 | i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), TYPE_PCA9548, 0x75); |
22 | - DEFINE_PROP_UINT32("scc-id", MPS2SCC, aid, 0), | 34 | i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), TYPE_PCA9548, 0x77); |
23 | + DEFINE_PROP_UINT32("scc-id", MPS2SCC, id, 0), | 35 | |
24 | /* These are the initial settings for the source clocks on the board. | 36 | @@ -XXX,XX +XXX,XX @@ static void kudo_bmc_i2c_init(NPCM7xxState *soc) |
25 | * In hardware they can be configured via a config file read by the | 37 | |
26 | * motherboard configuration controller to suit the FPGA image. | 38 | at24c_eeprom_init(soc, 4, 0x50, 8192); /* mbfru */ |
39 | |||
40 | - i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 13), TYPE_PCA9548, 0x77); | ||
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 */ | ||
51 | |||
27 | -- | 52 | -- |
28 | 2.7.4 | 53 | 2.25.1 |
29 | 54 | ||
30 | 55 | diff view generated by jsdifflib |