1 | v2: dropped a couple of cadence_gem changes to ID regs that | 1 | Hi; this is a collection of mostly GIC related patches for rc3. |
---|---|---|---|
2 | caused new clang sanitizer warnings. | 2 | The "Update cached state after LPI state changes" fix is important |
3 | and fixes what would otherwise be a regression since we enable the | ||
4 | ITS by default in the virt board now. The others are not regressions | ||
5 | but I think are OK for rc3 as they're fairly self contained (and two | ||
6 | of them are fixes to new-in-6.2 functionality). | ||
3 | 7 | ||
8 | thanks | ||
4 | -- PMM | 9 | -- PMM |
5 | 10 | ||
6 | The following changes since commit dddb37495b844270088e68e3bf30b764d48d863f: | 11 | The following changes since commit dd4b0de45965538f19bb40c7ddaaba384a8c613a: |
7 | 12 | ||
8 | Merge remote-tracking branch 'remotes/awilliam/tags/vfio-updates-20181015.0' into staging (2018-10-15 18:44:04 +0100) | 13 | Fix version for v6.2.0-rc2 release (2021-11-26 11:58:54 +0100) |
9 | 14 | ||
10 | are available in the Git repository at: | 15 | are available in the Git repository at: |
11 | 16 | ||
12 | https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20181016-1 | 17 | https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20211129 |
13 | 18 | ||
14 | for you to fetch changes up to 2ef297af07196c29446556537861f8e7dfeeae7b: | 19 | for you to fetch changes up to 90feffad2aafe856ed2af75313b2c1669ba671e9: |
15 | 20 | ||
16 | coccinelle: new inplace-byteswaps.cocci to remove inplace-byteswapping calls (2018-10-16 17:14:55 +0100) | 21 | hw/intc/arm_gicv3: fix handling of LPIs in list registers (2021-11-29 10:10:21 +0000) |
17 | 22 | ||
18 | ---------------------------------------------------------------- | 23 | ---------------------------------------------------------------- |
19 | target-arm queue: | 24 | target-arm queue: |
20 | * hw/arm/virt: add DT property /secure-chosen/stdout-path indicating secure UART | 25 | * virt: Diagnose attempts to enable MTE or virt when using HVF accelerator |
21 | * target/arm: Fix aarch64_sve_change_el wrt EL0 | 26 | * GICv3 ITS: Allow clearing of ITS CTLR Enabled bit |
22 | * target/arm: Define fields of ISAR registers | 27 | * GICv3: Update cached state after LPI state changes |
23 | * target/arm: Align cortex-r5 id_isar0 | 28 | * GICv3: Fix handling of LPIs in list registers |
24 | * target/arm: Fix cortex-a7 id_isar0 | ||
25 | * net/cadence_gem: Fix various bugs, add support for new | ||
26 | features that will be used by the Xilinx Versal board | ||
27 | * target-arm: powerctl: Enable HVC when starting CPUs to EL2 | ||
28 | * target/arm: Add the Cortex-A72 | ||
29 | * target/arm: Mark PMINTENCLR and PMINTENCLR_EL1 accesses as possibly doing IO | ||
30 | * target/arm: Mask PMOVSR writes based on supported counters | ||
31 | * target/arm: Initialize ARMMMUFaultInfo in v7m_stack_read/write | ||
32 | * coccinelle: new inplace-byteswaps.cocci to remove inplace-byteswapping calls | ||
33 | 29 | ||
34 | ---------------------------------------------------------------- | 30 | ---------------------------------------------------------------- |
35 | Aaron Lindsay (2): | 31 | Alexander Graf (1): |
36 | target/arm: Mark PMINTENCLR and PMINTENCLR_EL1 accesses as possibly doing IO | 32 | hw/arm/virt: Extend nested and mte checks to hvf |
37 | target/arm: Mask PMOVSR writes based on supported counters | ||
38 | 33 | ||
39 | Edgar E. Iglesias (8): | 34 | Peter Maydell (3): |
40 | net: cadence_gem: Disable TSU feature bit | 35 | hw/intc/arm_gicv3: Update cached state after LPI state changes |
41 | net: cadence_gem: Use uint32_t for 32bit descriptor words | 36 | hw/intc/arm_gicv3: Add new gicv3_intid_is_special() function |
42 | net: cadence_gem: Add macro with max number of descriptor words | 37 | hw/intc/arm_gicv3: fix handling of LPIs in list registers |
43 | net: cadence_gem: Add support for extended descriptors | ||
44 | net: cadence_gem: Add support for selecting the DMA MemoryRegion | ||
45 | net: cadence_gem: Implement support for 64bit descriptor addresses | ||
46 | target-arm: powerctl: Enable HVC when starting CPUs to EL2 | ||
47 | target/arm: Add the Cortex-A72 | ||
48 | 38 | ||
49 | Jerome Forissier (1): | 39 | Shashi Mallela (1): |
50 | hw/arm/virt: add DT property /secure-chosen/stdout-path indicating secure UART | 40 | hw/intc: cannot clear GICv3 ITS CTLR[Enabled] bit |
51 | 41 | ||
52 | Peter Maydell (2): | 42 | hw/intc/gicv3_internal.h | 30 ++++++++++++++++++++++++++++++ |
53 | target/arm: Initialize ARMMMUFaultInfo in v7m_stack_read/write | 43 | hw/arm/virt.c | 15 +++++++++------ |
54 | coccinelle: new inplace-byteswaps.cocci to remove inplace-byteswapping calls | 44 | hw/intc/arm_gicv3.c | 6 ++++-- |
45 | hw/intc/arm_gicv3_cpuif.c | 9 ++++----- | ||
46 | hw/intc/arm_gicv3_its.c | 7 ++++--- | ||
47 | hw/intc/arm_gicv3_redist.c | 14 ++++++++++---- | ||
48 | 6 files changed, 61 insertions(+), 20 deletions(-) | ||
55 | 49 | ||
56 | Richard Henderson (4): | ||
57 | target/arm: Fix aarch64_sve_change_el wrt EL0 | ||
58 | target/arm: Define fields of ISAR registers | ||
59 | target/arm: Align cortex-r5 id_isar0 | ||
60 | target/arm: Fix cortex-a7 id_isar0 | ||
61 | |||
62 | include/hw/net/cadence_gem.h | 7 +- | ||
63 | target/arm/cpu.h | 95 ++++++++++++++- | ||
64 | hw/arm/virt.c | 4 + | ||
65 | hw/net/cadence_gem.c | 185 ++++++++++++++++++++--------- | ||
66 | target/arm/arm-powerctl.c | 10 ++ | ||
67 | target/arm/cpu.c | 7 +- | ||
68 | target/arm/cpu64.c | 66 +++++++++- | ||
69 | target/arm/helper.c | 27 +++-- | ||
70 | target/arm/op_helper.c | 6 +- | ||
71 | scripts/coccinelle/inplace-byteswaps.cocci | 65 ++++++++++ | ||
72 | 10 files changed, 402 insertions(+), 70 deletions(-) | ||
73 | create mode 100644 scripts/coccinelle/inplace-byteswaps.cocci | ||
74 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Alexander Graf <agraf@csgraf.de> | ||
1 | 2 | ||
3 | The virt machine has properties to enable MTE and Nested Virtualization | ||
4 | support. However, its check to ensure the backing accel implementation | ||
5 | supports it today only looks for KVM and bails out if it finds it. | ||
6 | |||
7 | Extend the checks to HVF as well as it does not support either today. | ||
8 | This will cause QEMU to print a useful error message rather than | ||
9 | silently ignoring the attempt by the user to enable either MTE or | ||
10 | the Virtualization extensions. | ||
11 | |||
12 | Reported-by: saar amar <saaramar5@gmail.com> | ||
13 | Signed-off-by: Alexander Graf <agraf@csgraf.de> | ||
14 | Message-id: 20211123122859.22452-1-agraf@csgraf.de | ||
15 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
16 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
17 | --- | ||
18 | hw/arm/virt.c | 15 +++++++++------ | ||
19 | 1 file changed, 9 insertions(+), 6 deletions(-) | ||
20 | |||
21 | diff --git a/hw/arm/virt.c b/hw/arm/virt.c | ||
22 | index XXXXXXX..XXXXXXX 100644 | ||
23 | --- a/hw/arm/virt.c | ||
24 | +++ b/hw/arm/virt.c | ||
25 | @@ -XXX,XX +XXX,XX @@ | ||
26 | #include "sysemu/runstate.h" | ||
27 | #include "sysemu/tpm.h" | ||
28 | #include "sysemu/kvm.h" | ||
29 | +#include "sysemu/hvf.h" | ||
30 | #include "hw/loader.h" | ||
31 | #include "qapi/error.h" | ||
32 | #include "qemu/bitops.h" | ||
33 | @@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine) | ||
34 | exit(1); | ||
35 | } | ||
36 | |||
37 | - if (vms->virt && kvm_enabled()) { | ||
38 | - error_report("mach-virt: KVM does not support providing " | ||
39 | - "Virtualization extensions to the guest CPU"); | ||
40 | + if (vms->virt && (kvm_enabled() || hvf_enabled())) { | ||
41 | + error_report("mach-virt: %s does not support providing " | ||
42 | + "Virtualization extensions to the guest CPU", | ||
43 | + kvm_enabled() ? "KVM" : "HVF"); | ||
44 | exit(1); | ||
45 | } | ||
46 | |||
47 | - if (vms->mte && kvm_enabled()) { | ||
48 | - error_report("mach-virt: KVM does not support providing " | ||
49 | - "MTE to the guest CPU"); | ||
50 | + if (vms->mte && (kvm_enabled() || hvf_enabled())) { | ||
51 | + error_report("mach-virt: %s does not support providing " | ||
52 | + "MTE to the guest CPU", | ||
53 | + kvm_enabled() ? "KVM" : "HVF"); | ||
54 | exit(1); | ||
55 | } | ||
56 | |||
57 | -- | ||
58 | 2.25.1 | ||
59 | |||
60 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | From: Shashi Mallela <shashi.mallela@linaro.org> | ||
1 | 2 | ||
3 | When Enabled bit is cleared in GITS_CTLR,ITS feature continues | ||
4 | to be enabled.This patch fixes the issue. | ||
5 | |||
6 | Signed-off-by: Shashi Mallela <shashi.mallela@linaro.org> | ||
7 | Tested-by: Alex Bennée <alex.bennee@linaro.org> | ||
8 | Reviewed-by: Peter Maydell <peter.maydell@linaro.org> | ||
9 | Message-id: 20211124182246.67691-1-shashi.mallela@linaro.org | ||
10 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
11 | --- | ||
12 | hw/intc/arm_gicv3_its.c | 7 ++++--- | ||
13 | 1 file changed, 4 insertions(+), 3 deletions(-) | ||
14 | |||
15 | diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c | ||
16 | index XXXXXXX..XXXXXXX 100644 | ||
17 | --- a/hw/intc/arm_gicv3_its.c | ||
18 | +++ b/hw/intc/arm_gicv3_its.c | ||
19 | @@ -XXX,XX +XXX,XX @@ static bool its_writel(GICv3ITSState *s, hwaddr offset, | ||
20 | |||
21 | switch (offset) { | ||
22 | case GITS_CTLR: | ||
23 | - s->ctlr |= (value & ~(s->ctlr)); | ||
24 | - | ||
25 | - if (s->ctlr & ITS_CTLR_ENABLED) { | ||
26 | + if (value & R_GITS_CTLR_ENABLED_MASK) { | ||
27 | + s->ctlr |= ITS_CTLR_ENABLED; | ||
28 | extract_table_params(s); | ||
29 | extract_cmdq_params(s); | ||
30 | s->creadr = 0; | ||
31 | process_cmdq(s); | ||
32 | + } else { | ||
33 | + s->ctlr &= ~ITS_CTLR_ENABLED; | ||
34 | } | ||
35 | break; | ||
36 | case GITS_CBASER: | ||
37 | -- | ||
38 | 2.25.1 | ||
39 | |||
40 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | The logic of gicv3_redist_update() is as follows: | ||
2 | * it must be called in any code path that changes the state of | ||
3 | (only) redistributor interrupts | ||
4 | * if it finds a redistributor interrupt that is (now) higher | ||
5 | priority than the previous highest-priority pending interrupt, | ||
6 | then this must be the new highest-priority pending interrupt | ||
7 | * if it does *not* find a better redistributor interrupt, then: | ||
8 | - if the previous state was "no interrupts pending" then | ||
9 | the new state is still "no interrupts pending" | ||
10 | - if the previous best interrupt was not a redistributor | ||
11 | interrupt then that remains the best interrupt | ||
12 | - if the previous best interrupt *was* a redistributor interrupt, | ||
13 | then the new best interrupt must be some non-redistributor | ||
14 | interrupt, but we don't know which so must do a full scan | ||
1 | 15 | ||
16 | In commit 17fb5e36aabd4b2c125 we effectively added the LPI interrupts | ||
17 | as a kind of "redistributor interrupt" for this purpose, by adding | ||
18 | cs->hpplpi to the set of things that gicv3_redist_update() considers | ||
19 | before it gives up and decides to do a full scan of distributor | ||
20 | interrupts. However we didn't quite get this right: | ||
21 | * the condition check for "was the previous best interrupt a | ||
22 | redistributor interrupt" must be updated to include LPIs | ||
23 | in what it considers to be redistributor interrupts | ||
24 | * every code path which updates the LPI state which | ||
25 | gicv3_redist_update() checks must also call gicv3_redist_update(): | ||
26 | this is cs->hpplpi and the GICR_CTLR ENABLE_LPIS bit | ||
27 | |||
28 | This commit fixes this by: | ||
29 | * correcting the test on cs->hppi.irq in gicv3_redist_update() | ||
30 | * making gicv3_redist_update_lpi() always call gicv3_redist_update() | ||
31 | * introducing a new gicv3_redist_update_lpi_only() for the one | ||
32 | callsite (the post-load hook) which must not call | ||
33 | gicv3_redist_update() | ||
34 | * making gicv3_redist_lpi_pending() always call gicv3_redist_update(), | ||
35 | either directly or via gicv3_redist_update_lpi() | ||
36 | * removing a couple of now-unnecessary calls to gicv3_redist_update() | ||
37 | from some callers of those two functions | ||
38 | * calling gicv3_redist_update() when the GICR_CTLR ENABLE_LPIS | ||
39 | bit is cleared | ||
40 | |||
41 | (This means that the not-file-local gicv3_redist_* LPI related | ||
42 | functions now all take care of the updates of internally cached | ||
43 | GICv3 information, in the same way the older functions | ||
44 | gicv3_redist_set_irq() and gicv3_redist_send_sgi() do.) | ||
45 | |||
46 | The visible effect of this bug was that when the guest acknowledged | ||
47 | an LPI by reading ICC_IAR1_EL1, we marked it as not pending in the | ||
48 | LPI data structure but still left it in cs->hppi so we would offer it | ||
49 | to the guest again. In particular for setups using an emulated GICv3 | ||
50 | and ITS and using devices which use LPIs (ie PCI devices) a Linux | ||
51 | guest would complain "irq 54: nobody cared" and then hang. (The hang | ||
52 | was intermittent, presumably depending on the timing between | ||
53 | different interrupts arriving and being completed.) | ||
54 | |||
55 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
56 | Tested-by: Alex Bennée <alex.bennee@linaro.org> | ||
57 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
58 | Message-id: 20211124202005.989935-1-peter.maydell@linaro.org | ||
59 | --- | ||
60 | hw/intc/gicv3_internal.h | 17 +++++++++++++++++ | ||
61 | hw/intc/arm_gicv3.c | 6 ++++-- | ||
62 | hw/intc/arm_gicv3_redist.c | 14 ++++++++++---- | ||
63 | 3 files changed, 31 insertions(+), 6 deletions(-) | ||
64 | |||
65 | diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h | ||
66 | index XXXXXXX..XXXXXXX 100644 | ||
67 | --- a/hw/intc/gicv3_internal.h | ||
68 | +++ b/hw/intc/gicv3_internal.h | ||
69 | @@ -XXX,XX +XXX,XX @@ void gicv3_dist_set_irq(GICv3State *s, int irq, int level); | ||
70 | void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level); | ||
71 | void gicv3_redist_process_lpi(GICv3CPUState *cs, int irq, int level); | ||
72 | void gicv3_redist_lpi_pending(GICv3CPUState *cs, int irq, int level); | ||
73 | +/** | ||
74 | + * gicv3_redist_update_lpi: | ||
75 | + * @cs: GICv3CPUState | ||
76 | + * | ||
77 | + * Scan the LPI pending table and recalculate the highest priority | ||
78 | + * pending LPI and also the overall highest priority pending interrupt. | ||
79 | + */ | ||
80 | void gicv3_redist_update_lpi(GICv3CPUState *cs); | ||
81 | +/** | ||
82 | + * gicv3_redist_update_lpi_only: | ||
83 | + * @cs: GICv3CPUState | ||
84 | + * | ||
85 | + * Scan the LPI pending table and recalculate cs->hpplpi only, | ||
86 | + * without calling gicv3_redist_update() to recalculate the overall | ||
87 | + * highest priority pending interrupt. This should be called after | ||
88 | + * an incoming migration has loaded new state. | ||
89 | + */ | ||
90 | +void gicv3_redist_update_lpi_only(GICv3CPUState *cs); | ||
91 | void gicv3_redist_send_sgi(GICv3CPUState *cs, int grp, int irq, bool ns); | ||
92 | void gicv3_init_cpuif(GICv3State *s); | ||
93 | |||
94 | diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c | ||
95 | index XXXXXXX..XXXXXXX 100644 | ||
96 | --- a/hw/intc/arm_gicv3.c | ||
97 | +++ b/hw/intc/arm_gicv3.c | ||
98 | @@ -XXX,XX +XXX,XX @@ static void gicv3_redist_update_noirqset(GICv3CPUState *cs) | ||
99 | * interrupt has reduced in priority and any other interrupt could | ||
100 | * now be the new best one). | ||
101 | */ | ||
102 | - if (!seenbetter && cs->hppi.prio != 0xff && cs->hppi.irq < GIC_INTERNAL) { | ||
103 | + if (!seenbetter && cs->hppi.prio != 0xff && | ||
104 | + (cs->hppi.irq < GIC_INTERNAL || | ||
105 | + cs->hppi.irq >= GICV3_LPI_INTID_START)) { | ||
106 | gicv3_full_update_noirqset(cs->gic); | ||
107 | } | ||
108 | } | ||
109 | @@ -XXX,XX +XXX,XX @@ static void arm_gicv3_post_load(GICv3State *s) | ||
110 | * pending interrupt, but don't set IRQ or FIQ lines. | ||
111 | */ | ||
112 | for (i = 0; i < s->num_cpu; i++) { | ||
113 | - gicv3_redist_update_lpi(&s->cpu[i]); | ||
114 | + gicv3_redist_update_lpi_only(&s->cpu[i]); | ||
115 | } | ||
116 | gicv3_full_update_noirqset(s); | ||
117 | /* Repopulate the cache of GICv3CPUState pointers for target CPUs */ | ||
118 | diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c | ||
119 | index XXXXXXX..XXXXXXX 100644 | ||
120 | --- a/hw/intc/arm_gicv3_redist.c | ||
121 | +++ b/hw/intc/arm_gicv3_redist.c | ||
122 | @@ -XXX,XX +XXX,XX @@ static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr offset, | ||
123 | cs->gicr_ctlr |= GICR_CTLR_ENABLE_LPIS; | ||
124 | /* Check for any pending interr in pending table */ | ||
125 | gicv3_redist_update_lpi(cs); | ||
126 | - gicv3_redist_update(cs); | ||
127 | } else { | ||
128 | cs->gicr_ctlr &= ~GICR_CTLR_ENABLE_LPIS; | ||
129 | + /* cs->hppi might have been an LPI; recalculate */ | ||
130 | + gicv3_redist_update(cs); | ||
131 | } | ||
132 | } | ||
133 | return MEMTX_OK; | ||
134 | @@ -XXX,XX +XXX,XX @@ static void gicv3_redist_check_lpi_priority(GICv3CPUState *cs, int irq) | ||
135 | } | ||
136 | } | ||
137 | |||
138 | -void gicv3_redist_update_lpi(GICv3CPUState *cs) | ||
139 | +void gicv3_redist_update_lpi_only(GICv3CPUState *cs) | ||
140 | { | ||
141 | /* | ||
142 | * This function scans the LPI pending table and for each pending | ||
143 | @@ -XXX,XX +XXX,XX @@ void gicv3_redist_update_lpi(GICv3CPUState *cs) | ||
144 | } | ||
145 | } | ||
146 | |||
147 | +void gicv3_redist_update_lpi(GICv3CPUState *cs) | ||
148 | +{ | ||
149 | + gicv3_redist_update_lpi_only(cs); | ||
150 | + gicv3_redist_update(cs); | ||
151 | +} | ||
152 | + | ||
153 | void gicv3_redist_lpi_pending(GICv3CPUState *cs, int irq, int level) | ||
154 | { | ||
155 | /* | ||
156 | @@ -XXX,XX +XXX,XX @@ void gicv3_redist_lpi_pending(GICv3CPUState *cs, int irq, int level) | ||
157 | */ | ||
158 | if (level) { | ||
159 | gicv3_redist_check_lpi_priority(cs, irq); | ||
160 | + gicv3_redist_update(cs); | ||
161 | } else { | ||
162 | if (irq == cs->hpplpi.irq) { | ||
163 | gicv3_redist_update_lpi(cs); | ||
164 | @@ -XXX,XX +XXX,XX @@ void gicv3_redist_process_lpi(GICv3CPUState *cs, int irq, int level) | ||
165 | |||
166 | /* set/clear the pending bit for this irq */ | ||
167 | gicv3_redist_lpi_pending(cs, irq, level); | ||
168 | - | ||
169 | - gicv3_redist_update(cs); | ||
170 | } | ||
171 | |||
172 | void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level) | ||
173 | -- | ||
174 | 2.25.1 | ||
175 | |||
176 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | The GICv3/v4 pseudocode has a function IsSpecial() which returns true | ||
2 | if passed a "special" interrupt ID number (anything between 1020 and | ||
3 | 1023 inclusive). We open-code this condition in a couple of places, | ||
4 | so abstract it out into a new function gicv3_intid_is_special(). | ||
1 | 5 | ||
6 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
7 | Reviewed-by: Marc Zyngier <maz@kernel.org> | ||
8 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
9 | --- | ||
10 | hw/intc/gicv3_internal.h | 13 +++++++++++++ | ||
11 | hw/intc/arm_gicv3_cpuif.c | 4 ++-- | ||
12 | 2 files changed, 15 insertions(+), 2 deletions(-) | ||
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(MAPC, RDBASE, 16, 32) | ||
19 | |||
20 | /* Functions internal to the emulated GICv3 */ | ||
21 | |||
22 | +/** | ||
23 | + * gicv3_intid_is_special: | ||
24 | + * @intid: interrupt ID | ||
25 | + * | ||
26 | + * Return true if @intid is a special interrupt ID (1020 to | ||
27 | + * 1023 inclusive). This corresponds to the GIC spec pseudocode | ||
28 | + * IsSpecial() function. | ||
29 | + */ | ||
30 | +static inline bool gicv3_intid_is_special(int intid) | ||
31 | +{ | ||
32 | + return intid >= INTID_SECURE && intid <= INTID_SPURIOUS; | ||
33 | +} | ||
34 | + | ||
35 | /** | ||
36 | * gicv3_redist_update: | ||
37 | * @cs: GICv3CPUState for this redistributor | ||
38 | diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c | ||
39 | index XXXXXXX..XXXXXXX 100644 | ||
40 | --- a/hw/intc/arm_gicv3_cpuif.c | ||
41 | +++ b/hw/intc/arm_gicv3_cpuif.c | ||
42 | @@ -XXX,XX +XXX,XX @@ static uint64_t icc_iar0_read(CPUARMState *env, const ARMCPRegInfo *ri) | ||
43 | intid = icc_hppir0_value(cs, env); | ||
44 | } | ||
45 | |||
46 | - if (!(intid >= INTID_SECURE && intid <= INTID_SPURIOUS)) { | ||
47 | + if (!gicv3_intid_is_special(intid)) { | ||
48 | icc_activate_irq(cs, intid); | ||
49 | } | ||
50 | |||
51 | @@ -XXX,XX +XXX,XX @@ static uint64_t icc_iar1_read(CPUARMState *env, const ARMCPRegInfo *ri) | ||
52 | intid = icc_hppir1_value(cs, env); | ||
53 | } | ||
54 | |||
55 | - if (!(intid >= INTID_SECURE && intid <= INTID_SPURIOUS)) { | ||
56 | + if (!gicv3_intid_is_special(intid)) { | ||
57 | icc_activate_irq(cs, intid); | ||
58 | } | ||
59 | |||
60 | -- | ||
61 | 2.25.1 | ||
62 | |||
63 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | It is valid for an OS to put virtual interrupt ID values into the | ||
2 | list registers ICH_LR<n> which are greater than 1023. This | ||
3 | corresponds to (for example) KVM using the in-kernel emulated ITS to | ||
4 | give a (nested) guest an ITS. LPIs are delivered by the L1 kernel to | ||
5 | the L2 guest via the list registers in the same way as non-LPI | ||
6 | interrupts. | ||
1 | 7 | ||
8 | QEMU's code for handling writes to ICV_IARn (which happen when the L2 | ||
9 | guest acknowledges an interrupt) and to ICV_EOIRn (which happen at | ||
10 | the end of the interrupt) did not consider LPIs, so it would | ||
11 | incorrectly treat interrupt IDs above 1023 as invalid. Fix this by | ||
12 | using the correct condition, which is gicv3_intid_is_special(). | ||
13 | |||
14 | Note that the condition in icv_dir_write() is correct -- LPIs | ||
15 | are not valid there and so we want to ignore both "special" ID | ||
16 | values and LPIs. | ||
17 | |||
18 | (In the pseudocode this logic is in: | ||
19 | - VirtualReadIAR0(), VirtualReadIAR1(), which call IsSpecial() | ||
20 | - VirtualWriteEOIR0(), VirtualWriteEOIR1(), which call | ||
21 | VirtualIdentifierValid(data, TRUE) meaning "LPIs OK" | ||
22 | - VirtualWriteDIR(), which calls VirtualIdentifierValid(data, FALSE) | ||
23 | meaning "LPIs not OK") | ||
24 | |||
25 | This bug doesn't seem to have any visible effect on Linux L2 guests | ||
26 | most of the time, because the two bugs cancel each other out: we | ||
27 | neither mark the interrupt active nor deactivate it. However it does | ||
28 | mean that the L2 vCPU priority while the LPI handler is running will | ||
29 | not be correct, so the interrupt handler could be unexpectedly | ||
30 | interrupted by a different interrupt. | ||
31 | |||
32 | (NB: this has nothing to do with using QEMU's emulated ITS.) | ||
33 | |||
34 | Signed-off-by: Peter Maydell <peter.maydell@linaro.org> | ||
35 | Reviewed-by: Marc Zyngier <maz@kernel.org> | ||
36 | --- | ||
37 | hw/intc/arm_gicv3_cpuif.c | 5 ++--- | ||
38 | 1 file changed, 2 insertions(+), 3 deletions(-) | ||
39 | |||
40 | diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c | ||
41 | index XXXXXXX..XXXXXXX 100644 | ||
42 | --- a/hw/intc/arm_gicv3_cpuif.c | ||
43 | +++ b/hw/intc/arm_gicv3_cpuif.c | ||
44 | @@ -XXX,XX +XXX,XX @@ static uint64_t icv_iar_read(CPUARMState *env, const ARMCPRegInfo *ri) | ||
45 | |||
46 | if (thisgrp == grp && icv_hppi_can_preempt(cs, lr)) { | ||
47 | intid = ich_lr_vintid(lr); | ||
48 | - if (intid < INTID_SECURE) { | ||
49 | + if (!gicv3_intid_is_special(intid)) { | ||
50 | icv_activate_irq(cs, idx, grp); | ||
51 | } else { | ||
52 | /* Interrupt goes from Pending to Invalid */ | ||
53 | @@ -XXX,XX +XXX,XX @@ static void icv_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri, | ||
54 | trace_gicv3_icv_eoir_write(ri->crm == 8 ? 0 : 1, | ||
55 | gicv3_redist_affid(cs), value); | ||
56 | |||
57 | - if (irq >= GICV3_MAXIRQ) { | ||
58 | - /* Also catches special interrupt numbers and LPIs */ | ||
59 | + if (gicv3_intid_is_special(irq)) { | ||
60 | return; | ||
61 | } | ||
62 | |||
63 | -- | ||
64 | 2.25.1 | ||
65 | |||
66 | diff view generated by jsdifflib |