1
Hi; here's the first arm pullreq for the 8.2 cycle. These are
1
Hi; here's a target-arm pullreq to go in before softfreeze.
2
pretty much all bug fixes (mostly for the experimental FEAT_RME),
2
This is actually pretty much entirely bugfixes (since the
3
rather than any major features.
3
SEL2 timers we implement here are a missing part of a feature
4
we claim to already implement).
4
5
6
thanks
5
-- PMM
7
-- PMM
6
8
7
The following changes since commit b0dd9a7d6dd15a6898e9c585b521e6bec79b25aa:
9
The following changes since commit 98c7362b1efe651327385a25874a73e008c6549e:
8
10
9
Open 8.2 development tree (2023-08-22 07:14:07 -0700)
11
Merge tag 'accel-cpus-20250306' of https://github.com/philmd/qemu into staging (2025-03-07 07:39:49 +0800)
10
12
11
are available in the Git repository at:
13
are available in the Git repository at:
12
14
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20230824
15
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20250307
14
16
15
for you to fetch changes up to cd1e4db73646006039f25879af3bff55b2295ff3:
17
for you to fetch changes up to 0ce0739d46983e5e88fa9c149cb305689c9d8c6f:
16
18
17
target/arm: Fix 64-bit SSRA (2023-08-22 17:31:14 +0100)
19
target/rx: Remove TCG_CALL_NO_WG from helpers which write env (2025-03-07 15:03:20 +0000)
18
20
19
----------------------------------------------------------------
21
----------------------------------------------------------------
20
target-arm queue:
22
target-arm queue:
21
* hw/gpio/nrf51: implement DETECT signal
23
* hw/arm/smmu-common: Remove the repeated ttb field
22
* accel/kvm: Specify default IPA size for arm64
24
* hw/gpio: npcm7xx: fixup out-of-bounds access
23
* ptw: refactor, fix some FEAT_RME bugs
25
* tests/functional/test_arm_sx1: Check whether the serial console is working
24
* target/arm: Adjust PAR_EL1.SH for Device and Normal-NC memory types
26
* target/arm: Fix minor bugs in generic timer register handling
25
* target/arm/helper: Implement CNTHCTL_EL2.CNT[VP]MASK
27
* target/arm: Implement SEL2 physical and virtual timers
26
* Fix SME ST1Q
28
* target/arm: Correct STRD, LDRD atomicity and fault behaviour
27
* Fix 64-bit SSRA
29
* target/arm: Make dummy debug registers RAZ, not NOP
30
* util/qemu-timer.c: Don't warp timer from timerlist_rearm()
31
* include/exec/memop.h: Expand comment for MO_ATOM_SUBALIGN
32
* hw/arm/smmu: Introduce smmu_configs_inv_sid_range() helper
33
* target/rx: Set exception vector base to 0xffffff80
34
* target/rx: Remove TCG_CALL_NO_WG from helpers which write env
28
35
29
----------------------------------------------------------------
36
----------------------------------------------------------------
30
Akihiko Odaki (6):
37
Alex Bennée (4):
31
kvm: Introduce kvm_arch_get_default_type hook
38
target/arm: Implement SEL2 physical and virtual timers
32
accel/kvm: Specify default IPA size for arm64
39
target/arm: Document the architectural names of our GTIMERs
33
mips: Report an error when KVM_VM_MIPS_VZ is unavailable
40
hw/arm: enable secure EL2 timers for virt machine
34
accel/kvm: Use negative KVM type for error propagation
41
hw/arm: enable secure EL2 timers for sbsa machine
35
accel/kvm: Free as when an error occurred
36
accel/kvm: Make kvm_dirty_ring_reaper_init() void
37
42
38
Chris Laplante (6):
43
JianChunfu (2):
39
hw/gpio/nrf51: implement DETECT signal
44
hw/arm/smmu-common: Remove the repeated ttb field
40
qtest: factor out qtest_install_gpio_out_intercept
45
hw/arm/smmu: Introduce smmu_configs_inv_sid_range() helper
41
qtest: implement named interception of out-GPIO
42
qtest: bail from irq_intercept_in if name is specified
43
qtest: irq_intercept_[out/in]: return FAIL if no intercepts are installed
44
qtest: microbit-test: add tests for nRF51 DETECT
45
46
46
Jean-Philippe Brucker (6):
47
Keith Packard (2):
47
target/arm/ptw: Load stage-2 tables from realm physical space
48
target/rx: Set exception vector base to 0xffffff80
48
target/arm/helper: Fix tlbmask and tlbbits for TLBI VAE2*
49
target/rx: Remove TCG_CALL_NO_WG from helpers which write env
49
target/arm: Skip granule protection checks for AT instructions
50
target/arm: Pass security space rather than flag for AT instructions
51
target/arm/helper: Check SCR_EL3.{NSE, NS} encoding for AT instructions
52
target/arm/helper: Implement CNTHCTL_EL2.CNT[VP]MASK
53
50
54
Peter Maydell (15):
51
Patrick Venture (1):
55
target/arm/ptw: Don't set fi->s1ptw for UnsuppAtomicUpdate fault
52
hw/gpio: npcm7xx: fixup out-of-bounds access
56
target/arm/ptw: Don't report GPC faults on stage 1 ptw as stage2 faults
57
target/arm/ptw: Set s1ns bit in fault info more consistently
58
target/arm/ptw: Pass ptw into get_phys_addr_pmsa*() and get_phys_addr_disabled()
59
target/arm/ptw: Pass ARMSecurityState to regime_translation_disabled()
60
target/arm/ptw: Pass an ARMSecuritySpace to arm_hcr_el2_eff_secstate()
61
target/arm: Pass an ARMSecuritySpace to arm_is_el2_enabled_secstate()
62
target/arm/ptw: Only fold in NSTable bit effects in Secure state
63
target/arm/ptw: Remove last uses of ptw->in_secure
64
target/arm/ptw: Remove S1Translate::in_secure
65
target/arm/ptw: Drop S1Translate::out_secure
66
target/arm/ptw: Set attributes correctly for MMU disabled data accesses
67
target/arm/ptw: Check for block descriptors at invalid levels
68
target/arm/ptw: Report stage 2 fault level for stage 2 faults on stage 1 ptw
69
target/arm: Adjust PAR_EL1.SH for Device and Normal-NC memory types
70
53
71
Richard Henderson (2):
54
Peter Maydell (11):
72
target/arm: Fix SME ST1Q
55
target/arm: Apply correct timer offset when calculating deadlines
73
target/arm: Fix 64-bit SSRA
56
target/arm: Don't apply CNTVOFF_EL2 for EL2_VIRT timer
57
target/arm: Make CNTPS_* UNDEF from Secure EL1 when Secure EL2 is enabled
58
target/arm: Always apply CNTVOFF_EL2 for CNTV_TVAL_EL02 accesses
59
target/arm: Refactor handling of timer offset for direct register accesses
60
target/arm: Correct LDRD atomicity and fault behaviour
61
target/arm: Correct STRD atomicity
62
target/arm: Drop unused address_offset from op_addr_{rr, ri}_post()
63
target/arm: Make dummy debug registers RAZ, not NOP
64
util/qemu-timer.c: Don't warp timer from timerlist_rearm()
65
include/exec/memop.h: Expand comment for MO_ATOM_SUBALIGN
74
66
75
include/hw/gpio/nrf51_gpio.h | 1 +
67
Thomas Huth (1):
76
include/sysemu/kvm.h | 2 +
68
tests/functional/test_arm_sx1: Check whether the serial console is working
77
target/arm/cpu.h | 19 ++--
69
78
target/arm/internals.h | 25 ++---
70
MAINTAINERS | 1 +
79
target/mips/kvm_mips.h | 9 --
71
hw/arm/smmu-internal.h | 5 -
80
tests/qtest/libqtest.h | 11 +++
72
include/exec/memop.h | 8 +-
81
accel/kvm/kvm-all.c | 19 ++--
73
include/hw/arm/bsa.h | 2 +
82
hw/arm/virt.c | 2 +-
74
include/hw/arm/smmu-common.h | 7 +-
83
hw/gpio/nrf51_gpio.c | 14 ++-
75
target/arm/cpu.h | 2 +
84
hw/mips/loongson3_virt.c | 2 -
76
target/arm/gtimer.h | 14 +-
85
hw/ppc/spapr.c | 2 +-
77
target/arm/internals.h | 5 +-
86
softmmu/qtest.c | 52 +++++++---
78
target/rx/helper.h | 34 ++--
87
target/arm/cpu.c | 6 ++
79
hw/arm/sbsa-ref.c | 2 +
88
target/arm/helper.c | 207 ++++++++++++++++++++++++++++----------
80
hw/arm/smmu-common.c | 21 +++
89
target/arm/kvm.c | 7 ++
81
hw/arm/smmuv3.c | 19 +--
90
target/arm/ptw.c | 231 ++++++++++++++++++++++++++-----------------
82
hw/arm/virt.c | 2 +
91
target/arm/tcg/sme_helper.c | 2 +-
83
hw/gpio/npcm7xx_gpio.c | 3 +-
92
target/arm/tcg/translate.c | 2 +-
84
target/arm/cpu.c | 4 +
93
target/i386/kvm/kvm.c | 5 +
85
target/arm/debug_helper.c | 7 +-
94
target/mips/kvm.c | 3 +-
86
target/arm/helper.c | 324 ++++++++++++++++++++++++++++++++-------
95
target/ppc/kvm.c | 5 +
87
target/arm/tcg/op_helper.c | 8 +-
96
target/riscv/kvm.c | 5 +
88
target/arm/tcg/translate.c | 147 +++++++++++-------
97
target/s390x/kvm/kvm.c | 5 +
89
target/rx/helper.c | 2 +-
98
tests/qtest/libqtest.c | 6 ++
90
util/qemu-timer.c | 4 -
99
tests/qtest/microbit-test.c | 44 +++++++++
91
hw/arm/trace-events | 3 +-
100
target/arm/trace-events | 7 +-
92
tests/functional/test_arm_sx1.py | 7 +-
101
26 files changed, 494 insertions(+), 199 deletions(-)
93
23 files changed, 455 insertions(+), 176 deletions(-)
94
diff view generated by jsdifflib
Deleted patch
1
From: Chris Laplante <chris@laplante.io>
2
1
3
Implement nRF51 DETECT signal in the GPIO peripheral.
4
5
The reference manual makes mention of a per-pin DETECT signal, but these
6
are not exposed to the user. See https://devzone.nordicsemi.com/f/nordic-q-a/39858/gpio-per-pin-detect-signal-available
7
for more information. Currently, I don't see a reason to model these.
8
9
Signed-off-by: Chris Laplante <chris@laplante.io>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20230728160324.1159090-2-chris@laplante.io
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
include/hw/gpio/nrf51_gpio.h | 1 +
15
hw/gpio/nrf51_gpio.c | 14 +++++++++++++-
16
2 files changed, 14 insertions(+), 1 deletion(-)
17
18
diff --git a/include/hw/gpio/nrf51_gpio.h b/include/hw/gpio/nrf51_gpio.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/gpio/nrf51_gpio.h
21
+++ b/include/hw/gpio/nrf51_gpio.h
22
@@ -XXX,XX +XXX,XX @@ struct NRF51GPIOState {
23
uint32_t old_out_connected;
24
25
qemu_irq output[NRF51_GPIO_PINS];
26
+ qemu_irq detect;
27
};
28
29
30
diff --git a/hw/gpio/nrf51_gpio.c b/hw/gpio/nrf51_gpio.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/gpio/nrf51_gpio.c
33
+++ b/hw/gpio/nrf51_gpio.c
34
@@ -XXX,XX +XXX,XX @@ static void update_state(NRF51GPIOState *s)
35
int pull;
36
size_t i;
37
bool connected_out, dir, connected_in, out, in, input;
38
+ bool assert_detect = false;
39
40
for (i = 0; i < NRF51_GPIO_PINS; i++) {
41
pull = pull_value(s->cnf[i]);
42
@@ -XXX,XX +XXX,XX @@ static void update_state(NRF51GPIOState *s)
43
qemu_log_mask(LOG_GUEST_ERROR,
44
"GPIO pin %zu short circuited\n", i);
45
}
46
- if (!connected_in) {
47
+ if (connected_in) {
48
+ uint32_t detect_config = extract32(s->cnf[i], 16, 2);
49
+ if ((detect_config == 2) && (in == 1)) {
50
+ assert_detect = true;
51
+ }
52
+ if ((detect_config == 3) && (in == 0)) {
53
+ assert_detect = true;
54
+ }
55
+ } else {
56
/*
57
* Floating input: the output stimulates IN if connected,
58
* otherwise pull-up/pull-down resistors put a value on both
59
@@ -XXX,XX +XXX,XX @@ static void update_state(NRF51GPIOState *s)
60
}
61
update_output_irq(s, i, connected_out, out);
62
}
63
+
64
+ qemu_set_irq(s->detect, assert_detect);
65
}
66
67
/*
68
@@ -XXX,XX +XXX,XX @@ static void nrf51_gpio_init(Object *obj)
69
70
qdev_init_gpio_in(DEVICE(s), nrf51_gpio_set, NRF51_GPIO_PINS);
71
qdev_init_gpio_out(DEVICE(s), s->output, NRF51_GPIO_PINS);
72
+ qdev_init_gpio_out_named(DEVICE(s), &s->detect, "detect", 1);
73
}
74
75
static void nrf51_gpio_class_init(ObjectClass *klass, void *data)
76
--
77
2.34.1
diff view generated by jsdifflib
Deleted patch
1
From: Chris Laplante <chris@laplante.io>
2
1
3
Signed-off-by: Chris Laplante <chris@laplante.io>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 20230728160324.1159090-3-chris@laplante.io
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
softmmu/qtest.c | 16 ++++++++++------
9
1 file changed, 10 insertions(+), 6 deletions(-)
10
11
diff --git a/softmmu/qtest.c b/softmmu/qtest.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/softmmu/qtest.c
14
+++ b/softmmu/qtest.c
15
@@ -XXX,XX +XXX,XX @@ void qtest_set_command_cb(bool (*pc_cb)(CharBackend *chr, gchar **words))
16
process_command_cb = pc_cb;
17
}
18
19
+static void qtest_install_gpio_out_intercept(DeviceState *dev, const char *name, int n)
20
+{
21
+ qemu_irq *disconnected = g_new0(qemu_irq, 1);
22
+ qemu_irq icpt = qemu_allocate_irq(qtest_irq_handler,
23
+ disconnected, n);
24
+
25
+ *disconnected = qdev_intercept_gpio_out(dev, icpt, name, n);
26
+}
27
+
28
static void qtest_process_command(CharBackend *chr, gchar **words)
29
{
30
const gchar *command;
31
@@ -XXX,XX +XXX,XX @@ static void qtest_process_command(CharBackend *chr, gchar **words)
32
if (words[0][14] == 'o') {
33
int i;
34
for (i = 0; i < ngl->num_out; ++i) {
35
- qemu_irq *disconnected = g_new0(qemu_irq, 1);
36
- qemu_irq icpt = qemu_allocate_irq(qtest_irq_handler,
37
- disconnected, i);
38
-
39
- *disconnected = qdev_intercept_gpio_out(dev, icpt,
40
- ngl->name, i);
41
+ qtest_install_gpio_out_intercept(dev, ngl->name, i);
42
}
43
} else {
44
qemu_irq_intercept_in(ngl->in, qtest_irq_handler,
45
--
46
2.34.1
diff view generated by jsdifflib
1
From: Jean-Philippe Brucker <jean-philippe@linaro.org>
1
From: JianChunfu <jansef.jian@hj-micro.com>
2
2
3
At the moment we only handle Secure and Nonsecure security spaces for
3
SMMUTransCfg->ttb is never used in QEMU, TT base address
4
the AT instructions. Add support for Realm and Root.
4
can be accessed by SMMUTransCfg->tt[i]->ttb.
5
5
6
For AArch64, arm_security_space() gives the desired space. ARM DDI0487J
6
Signed-off-by: JianChunfu <jansef.jian@hj-micro.com>
7
says (R_NYXTL):
7
Reviewed-by: Eric Auger <eric.auger@redhat.com>
8
8
Message-id: 20250221031034.69822-1-jansef.jian@hj-micro.com
9
If EL3 is implemented, then when an address translation instruction
10
that applies to an Exception level lower than EL3 is executed, the
11
Effective value of SCR_EL3.{NSE, NS} determines the target Security
12
state that the instruction applies to.
13
14
For AArch32, some instructions can access NonSecure space from Secure,
15
so we still need to pass the state explicitly to do_ats_write().
16
17
Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Message-id: 20230809123706.1842548-5-jean-philippe@linaro.org
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
10
---
22
target/arm/internals.h | 18 +++++++++---------
11
include/hw/arm/smmu-common.h | 1 -
23
target/arm/helper.c | 27 ++++++++++++---------------
12
1 file changed, 1 deletion(-)
24
target/arm/ptw.c | 12 ++++++------
25
3 files changed, 27 insertions(+), 30 deletions(-)
26
13
27
diff --git a/target/arm/internals.h b/target/arm/internals.h
14
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
28
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/internals.h
16
--- a/include/hw/arm/smmu-common.h
30
+++ b/target/arm/internals.h
17
+++ b/include/hw/arm/smmu-common.h
31
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
18
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUTransCfg {
32
__attribute__((nonnull));
19
/* Used by stage-1 only. */
33
20
bool aa64; /* arch64 or aarch32 translation table */
34
/**
21
bool record_faults; /* record fault events */
35
- * get_phys_addr_with_secure_nogpc: get the physical address for a virtual
22
- uint64_t ttb; /* TT base address */
36
- * address
23
uint8_t oas; /* output address width */
37
+ * get_phys_addr_with_space_nogpc: get the physical address for a virtual
24
uint8_t tbi; /* Top Byte Ignore */
38
+ * address
25
int asid;
39
* @env: CPUARMState
40
* @address: virtual address to get physical address for
41
* @access_type: 0 for read, 1 for write, 2 for execute
42
* @mmu_idx: MMU index indicating required translation regime
43
- * @is_secure: security state for the access
44
+ * @space: security space for the access
45
* @result: set on translation success.
46
* @fi: set to fault info if the translation fails
47
*
48
- * Similar to get_phys_addr, but use the given security regime and don't perform
49
+ * Similar to get_phys_addr, but use the given security space and don't perform
50
* a Granule Protection Check on the resulting address.
51
*/
52
-bool get_phys_addr_with_secure_nogpc(CPUARMState *env, target_ulong address,
53
- MMUAccessType access_type,
54
- ARMMMUIdx mmu_idx, bool is_secure,
55
- GetPhysAddrResult *result,
56
- ARMMMUFaultInfo *fi)
57
+bool get_phys_addr_with_space_nogpc(CPUARMState *env, target_ulong address,
58
+ MMUAccessType access_type,
59
+ ARMMMUIdx mmu_idx, ARMSecuritySpace space,
60
+ GetPhysAddrResult *result,
61
+ ARMMMUFaultInfo *fi)
62
__attribute__((nonnull));
63
64
bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
65
diff --git a/target/arm/helper.c b/target/arm/helper.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/target/arm/helper.c
68
+++ b/target/arm/helper.c
69
@@ -XXX,XX +XXX,XX @@ static int par_el1_shareability(GetPhysAddrResult *res)
70
71
static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
72
MMUAccessType access_type, ARMMMUIdx mmu_idx,
73
- bool is_secure)
74
+ ARMSecuritySpace ss)
75
{
76
bool ret;
77
uint64_t par64;
78
@@ -XXX,XX +XXX,XX @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
79
* I_MXTJT: Granule protection checks are not performed on the final address
80
* of a successful translation.
81
*/
82
- ret = get_phys_addr_with_secure_nogpc(env, value, access_type, mmu_idx,
83
- is_secure, &res, &fi);
84
+ ret = get_phys_addr_with_space_nogpc(env, value, access_type, mmu_idx, ss,
85
+ &res, &fi);
86
87
/*
88
* ATS operations only do S1 or S1+S2 translations, so we never
89
@@ -XXX,XX +XXX,XX @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
90
uint64_t par64;
91
ARMMMUIdx mmu_idx;
92
int el = arm_current_el(env);
93
- bool secure = arm_is_secure_below_el3(env);
94
+ ARMSecuritySpace ss = arm_security_space(env);
95
96
switch (ri->opc2 & 6) {
97
case 0:
98
@@ -XXX,XX +XXX,XX @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
99
switch (el) {
100
case 3:
101
mmu_idx = ARMMMUIdx_E3;
102
- secure = true;
103
break;
104
case 2:
105
- g_assert(!secure); /* ARMv8.4-SecEL2 is 64-bit only */
106
+ g_assert(ss != ARMSS_Secure); /* ARMv8.4-SecEL2 is 64-bit only */
107
/* fall through */
108
case 1:
109
if (ri->crm == 9 && (env->uncached_cpsr & CPSR_PAN)) {
110
@@ -XXX,XX +XXX,XX @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
111
switch (el) {
112
case 3:
113
mmu_idx = ARMMMUIdx_E10_0;
114
- secure = true;
115
break;
116
case 2:
117
- g_assert(!secure); /* ARMv8.4-SecEL2 is 64-bit only */
118
+ g_assert(ss != ARMSS_Secure); /* ARMv8.4-SecEL2 is 64-bit only */
119
mmu_idx = ARMMMUIdx_Stage1_E0;
120
break;
121
case 1:
122
@@ -XXX,XX +XXX,XX @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
123
case 4:
124
/* stage 1+2 NonSecure PL1: ATS12NSOPR, ATS12NSOPW */
125
mmu_idx = ARMMMUIdx_E10_1;
126
- secure = false;
127
+ ss = ARMSS_NonSecure;
128
break;
129
case 6:
130
/* stage 1+2 NonSecure PL0: ATS12NSOUR, ATS12NSOUW */
131
mmu_idx = ARMMMUIdx_E10_0;
132
- secure = false;
133
+ ss = ARMSS_NonSecure;
134
break;
135
default:
136
g_assert_not_reached();
137
}
138
139
- par64 = do_ats_write(env, value, access_type, mmu_idx, secure);
140
+ par64 = do_ats_write(env, value, access_type, mmu_idx, ss);
141
142
A32_BANKED_CURRENT_REG_SET(env, par, par64);
143
#else
144
@@ -XXX,XX +XXX,XX @@ static void ats1h_write(CPUARMState *env, const ARMCPRegInfo *ri,
145
uint64_t par64;
146
147
/* There is no SecureEL2 for AArch32. */
148
- par64 = do_ats_write(env, value, access_type, ARMMMUIdx_E2, false);
149
+ par64 = do_ats_write(env, value, access_type, ARMMMUIdx_E2,
150
+ ARMSS_NonSecure);
151
152
A32_BANKED_CURRENT_REG_SET(env, par, par64);
153
#else
154
@@ -XXX,XX +XXX,XX @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
155
#ifdef CONFIG_TCG
156
MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD;
157
ARMMMUIdx mmu_idx;
158
- int secure = arm_is_secure_below_el3(env);
159
uint64_t hcr_el2 = arm_hcr_el2_eff(env);
160
bool regime_e20 = (hcr_el2 & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE);
161
162
@@ -XXX,XX +XXX,XX @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
163
break;
164
case 6: /* AT S1E3R, AT S1E3W */
165
mmu_idx = ARMMMUIdx_E3;
166
- secure = true;
167
break;
168
default:
169
g_assert_not_reached();
170
@@ -XXX,XX +XXX,XX @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
171
}
172
173
env->cp15.par_el[1] = do_ats_write(env, value, access_type,
174
- mmu_idx, secure);
175
+ mmu_idx, arm_security_space(env));
176
#else
177
/* Handled by hardware accelerator. */
178
g_assert_not_reached();
179
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
180
index XXXXXXX..XXXXXXX 100644
181
--- a/target/arm/ptw.c
182
+++ b/target/arm/ptw.c
183
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_gpc(CPUARMState *env, S1Translate *ptw,
184
return false;
185
}
186
187
-bool get_phys_addr_with_secure_nogpc(CPUARMState *env, target_ulong address,
188
- MMUAccessType access_type,
189
- ARMMMUIdx mmu_idx, bool is_secure,
190
- GetPhysAddrResult *result,
191
- ARMMMUFaultInfo *fi)
192
+bool get_phys_addr_with_space_nogpc(CPUARMState *env, target_ulong address,
193
+ MMUAccessType access_type,
194
+ ARMMMUIdx mmu_idx, ARMSecuritySpace space,
195
+ GetPhysAddrResult *result,
196
+ ARMMMUFaultInfo *fi)
197
{
198
S1Translate ptw = {
199
.in_mmu_idx = mmu_idx,
200
- .in_space = arm_secure_to_space(is_secure),
201
+ .in_space = space,
202
};
203
return get_phys_addr_nogpc(env, &ptw, address, access_type, result, fi);
204
}
205
--
26
--
206
2.34.1
27
2.43.0
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Patrick Venture <venture@google.com>
2
2
3
A typo, noted in the bug report, resulting in an
3
The reg isn't validated to be a possible register before
4
incorrect write offset.
4
it's dereferenced for one case. The mmio space registered
5
for the gpio device is 4KiB but there aren't that many
6
registers in the struct.
5
7
6
Cc: qemu-stable@nongnu.org
8
Cc: qemu-stable@nongnu.org
7
Fixes: 7390e0e9ab8 ("target/arm: Implement SME LD1, ST1")
9
Fixes: 526dbbe0874 ("hw/gpio: Add GPIO model for Nuvoton NPCM7xx")
8
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1833
10
Signed-off-by: Patrick Venture <venture@google.com>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Message-id: 20230818214255.146905-1-richard.henderson@linaro.org
12
Message-id: 20250226024603.493148-1-venture@google.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
---
14
target/arm/tcg/sme_helper.c | 2 +-
15
hw/gpio/npcm7xx_gpio.c | 3 +--
15
1 file changed, 1 insertion(+), 1 deletion(-)
16
1 file changed, 1 insertion(+), 2 deletions(-)
16
17
17
diff --git a/target/arm/tcg/sme_helper.c b/target/arm/tcg/sme_helper.c
18
diff --git a/hw/gpio/npcm7xx_gpio.c b/hw/gpio/npcm7xx_gpio.c
18
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/tcg/sme_helper.c
20
--- a/hw/gpio/npcm7xx_gpio.c
20
+++ b/target/arm/tcg/sme_helper.c
21
+++ b/hw/gpio/npcm7xx_gpio.c
21
@@ -XXX,XX +XXX,XX @@ static inline void HNAME##_host(void *za, intptr_t off, void *host) \
22
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_gpio_regs_write(void *opaque, hwaddr addr, uint64_t v,
22
{ \
23
return;
23
uint64_t *ptr = za + off; \
24
}
24
HOST(host, ptr[BE]); \
25
25
- HOST(host + 1, ptr[!BE]); \
26
- diff = s->regs[reg] ^ value;
26
+ HOST(host + 8, ptr[!BE]); \
27
-
27
} \
28
switch (reg) {
28
static inline void VNAME##_v_host(void *za, intptr_t off, void *host) \
29
case NPCM7XX_GPIO_TLOCK1:
29
{ \
30
case NPCM7XX_GPIO_TLOCK2:
31
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_gpio_regs_write(void *opaque, hwaddr addr, uint64_t v,
32
case NPCM7XX_GPIO_PU:
33
case NPCM7XX_GPIO_PD:
34
case NPCM7XX_GPIO_IEM:
35
+ diff = s->regs[reg] ^ value;
36
s->regs[reg] = value;
37
npcm7xx_gpio_update_pins(s, diff);
38
break;
30
--
39
--
31
2.34.1
40
2.43.0
32
41
33
42
diff view generated by jsdifflib
1
From: Jean-Philippe Brucker <jean-philippe@linaro.org>
1
From: Thomas Huth <thuth@redhat.com>
2
2
3
In realm state, stage-2 translation tables are fetched from the realm
3
The kernel that is used in the sx1 test prints the usual Linux log
4
physical address space (R_PGRQD).
4
onto the serial console, but this test currently ignores it. To
5
make sure that the serial device is working properly, let's check
6
for some strings in the output here.
5
7
6
Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
8
While we're at it, also add the test to the corresponding section
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
in the MAINTAINERS file.
8
Message-id: 20230809123706.1842548-2-jean-philippe@linaro.org
10
11
Signed-off-by: Thomas Huth <thuth@redhat.com>
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
13
Message-id: 20250226104833.1176253-1-thuth@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
15
---
11
target/arm/ptw.c | 26 ++++++++++++++++++--------
16
MAINTAINERS | 1 +
12
1 file changed, 18 insertions(+), 8 deletions(-)
17
tests/functional/test_arm_sx1.py | 7 ++++---
18
2 files changed, 5 insertions(+), 3 deletions(-)
13
19
14
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
20
diff --git a/MAINTAINERS b/MAINTAINERS
15
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/ptw.c
22
--- a/MAINTAINERS
17
+++ b/target/arm/ptw.c
23
+++ b/MAINTAINERS
18
@@ -XXX,XX +XXX,XX @@ static ARMMMUIdx ptw_idx_for_stage_2(CPUARMState *env, ARMMMUIdx stage2idx)
24
@@ -XXX,XX +XXX,XX @@ S: Maintained
19
25
F: hw/*/omap*
20
/*
26
F: include/hw/arm/omap.h
21
* We're OK to check the current state of the CPU here because
27
F: docs/system/arm/sx1.rst
22
- * (1) we always invalidate all TLBs when the SCR_EL3.NS bit changes
28
+F: tests/functional/test_arm_sx1.py
23
+ * (1) we always invalidate all TLBs when the SCR_EL3.NS or SCR_EL3.NSE bit
29
24
+ * changes.
30
IPack
25
* (2) there's no way to do a lookup that cares about Stage 2 for a
31
M: Alberto Garcia <berto@igalia.com>
26
* different security state to the current one for AArch64, and AArch32
32
diff --git a/tests/functional/test_arm_sx1.py b/tests/functional/test_arm_sx1.py
27
* never has a secure EL2. (AArch32 ATS12NSO[UP][RW] allow EL3 to do
33
index XXXXXXX..XXXXXXX 100755
28
* an NS stage 1+2 lookup while the NS bit is 0.)
34
--- a/tests/functional/test_arm_sx1.py
29
*/
35
+++ b/tests/functional/test_arm_sx1.py
30
- if (!arm_is_secure_below_el3(env) || !arm_el_is_aa64(env, 3)) {
36
@@ -XXX,XX +XXX,XX @@ def test_arm_sx1_initrd(self):
31
+ if (!arm_el_is_aa64(env, 3)) {
37
self.vm.add_args('-append', f'kunit.enable=0 rdinit=/sbin/init {self.CONSOLE_ARGS}')
32
return ARMMMUIdx_Phys_NS;
38
self.vm.add_args('-no-reboot')
33
}
39
self.launch_kernel(zimage_path,
34
- if (stage2idx == ARMMMUIdx_Stage2_S) {
40
- initrd=initrd_path)
35
- s2walk_secure = !(env->cp15.vstcr_el2 & VSTCR_SW);
41
+ initrd=initrd_path,
36
- } else {
42
+ wait_for='Boot successful')
37
- s2walk_secure = !(env->cp15.vtcr_el2 & VTCR_NSW);
43
self.vm.wait(timeout=120)
38
- }
44
39
- return s2walk_secure ? ARMMMUIdx_Phys_S : ARMMMUIdx_Phys_NS;
45
def test_arm_sx1_sd(self):
40
46
@@ -XXX,XX +XXX,XX @@ def test_arm_sx1_sd(self):
41
+ switch (arm_security_space_below_el3(env)) {
47
self.vm.add_args('-no-reboot')
42
+ case ARMSS_NonSecure:
48
self.vm.add_args('-snapshot')
43
+ return ARMMMUIdx_Phys_NS;
49
self.vm.add_args('-drive', f'format=raw,if=sd,file={sd_fs_path}')
44
+ case ARMSS_Realm:
50
- self.launch_kernel(zimage_path)
45
+ return ARMMMUIdx_Phys_Realm;
51
+ self.launch_kernel(zimage_path, wait_for='Boot successful')
46
+ case ARMSS_Secure:
52
self.vm.wait(timeout=120)
47
+ if (stage2idx == ARMMMUIdx_Stage2_S) {
53
48
+ s2walk_secure = !(env->cp15.vstcr_el2 & VSTCR_SW);
54
def test_arm_sx1_flash(self):
49
+ } else {
55
@@ -XXX,XX +XXX,XX @@ def test_arm_sx1_flash(self):
50
+ s2walk_secure = !(env->cp15.vtcr_el2 & VTCR_NSW);
56
self.vm.add_args('-no-reboot')
51
+ }
57
self.vm.add_args('-snapshot')
52
+ return s2walk_secure ? ARMMMUIdx_Phys_S : ARMMMUIdx_Phys_NS;
58
self.vm.add_args('-drive', f'format=raw,if=pflash,file={flash_path}')
53
+ default:
59
- self.launch_kernel(zimage_path)
54
+ g_assert_not_reached();
60
+ self.launch_kernel(zimage_path, wait_for='Boot successful')
55
+ }
61
self.vm.wait(timeout=120)
56
}
62
57
63
if __name__ == '__main__':
58
static bool regime_translation_big_endian(CPUARMState *env, ARMMMUIdx mmu_idx)
59
--
64
--
60
2.34.1
65
2.43.0
66
67
diff view generated by jsdifflib
1
The architecture doesn't permit block descriptors at any arbitrary
1
When we are calculating timer deadlines, the correct definition of
2
level of the page table walk; it depends on the granule size which
2
whether or not to apply an offset to the physical count is described
3
levels are permitted. We implemented only a partial version of this
3
in the Arm ARM DDI4087 rev L.a section D12.2.4.1. This is different
4
check which assumes that block descriptors are valid at all levels
4
from when the offset should be applied for a direct read of the
5
except level 3, which meant that we wouldn't deliver the Translation
5
counter sysreg.
6
fault for all cases of this sort of guest page table error.
7
6
8
Implement the logic corresponding to the pseudocode
7
We got this right for the EL1 physical timer and for the EL1 virtual
9
AArch64.DecodeDescriptorType() and AArch64.BlockDescSupported().
8
timer, but got all the rest wrong: they should be using a zero offset
9
always.
10
10
11
Factor the offset calculation out into a function that has a comment
12
documenting exactly which offset it is calculating and which gets the
13
HYP, SEC, and HYPVIRT cases right.
14
15
Cc: qemu-stable@nongnu.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
Message-id: 20230807141514.19075-14-peter.maydell@linaro.org
18
Message-id: 20250204125009.2281315-2-peter.maydell@linaro.org
14
---
19
---
15
target/arm/ptw.c | 25 +++++++++++++++++++++++--
20
target/arm/helper.c | 29 +++++++++++++++++++++++++++--
16
1 file changed, 23 insertions(+), 2 deletions(-)
21
1 file changed, 27 insertions(+), 2 deletions(-)
17
22
18
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
23
diff --git a/target/arm/helper.c b/target/arm/helper.c
19
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/ptw.c
25
--- a/target/arm/helper.c
21
+++ b/target/arm/ptw.c
26
+++ b/target/arm/helper.c
22
@@ -XXX,XX +XXX,XX @@ static int check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, uint64_t tcr,
27
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_phys_cnt_offset(CPUARMState *env)
23
return INT_MIN;
28
return gt_phys_raw_cnt_offset(env);
24
}
29
}
25
30
26
+static bool lpae_block_desc_valid(ARMCPU *cpu, bool ds,
31
+static uint64_t gt_indirect_access_timer_offset(CPUARMState *env, int timeridx)
27
+ ARMGranuleSize gran, int level)
28
+{
32
+{
29
+ /*
33
+ /*
30
+ * See pseudocode AArch46.BlockDescSupported(): block descriptors
34
+ * Return the timer offset to use for indirect accesses to the timer.
31
+ * are not valid at all levels, depending on the page size.
35
+ * This is the Offset value as defined in D12.2.4.1 "Operation of the
36
+ * CompareValue views of the timers".
37
+ *
38
+ * The condition here is not always the same as the condition for
39
+ * whether to apply an offset register when doing a direct read of
40
+ * the counter sysreg; those conditions are described in the
41
+ * access pseudocode for each counter register.
32
+ */
42
+ */
33
+ switch (gran) {
43
+ switch (timeridx) {
34
+ case Gran4K:
44
+ case GTIMER_PHYS:
35
+ return (level == 0 && ds) || level == 1 || level == 2;
45
+ return gt_phys_raw_cnt_offset(env);
36
+ case Gran16K:
46
+ case GTIMER_VIRT:
37
+ return (level == 1 && ds) || level == 2;
47
+ return env->cp15.cntvoff_el2;
38
+ case Gran64K:
48
+ case GTIMER_HYP:
39
+ return (level == 1 && arm_pamax(cpu) == 52) || level == 2;
49
+ case GTIMER_SEC:
50
+ case GTIMER_HYPVIRT:
51
+ return 0;
40
+ default:
52
+ default:
41
+ g_assert_not_reached();
53
+ g_assert_not_reached();
42
+ }
54
+ }
43
+}
55
+}
44
+
56
+
45
/**
57
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
46
* get_phys_addr_lpae: perform one stage of page table walk, LPAE format
58
{
47
*
59
ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
48
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
60
@@ -XXX,XX +XXX,XX @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
49
new_descriptor = descriptor;
61
* Timer enabled: calculate and set current ISTATUS, irq, and
50
62
* reset timer to when ISTATUS next has to change
51
restart_atomic_update:
63
*/
52
- if (!(descriptor & 1) || (!(descriptor & 2) && (level == 3))) {
64
- uint64_t offset = timeridx == GTIMER_VIRT ?
53
- /* Invalid, or the Reserved level 3 encoding */
65
- cpu->env.cp15.cntvoff_el2 : gt_phys_raw_cnt_offset(&cpu->env);
54
+ if (!(descriptor & 1) ||
66
+ uint64_t offset = gt_indirect_access_timer_offset(&cpu->env, timeridx);
55
+ (!(descriptor & 2) &&
67
uint64_t count = gt_get_countervalue(&cpu->env);
56
+ !lpae_block_desc_valid(cpu, param.ds, param.gran, level))) {
68
/* Note that this must be unsigned 64 bit arithmetic: */
57
+ /* Invalid, or a block descriptor at an invalid level */
69
int istatus = count - offset >= gt->cval;
58
goto do_translation_fault;
59
}
60
61
--
70
--
62
2.34.1
71
2.43.0
72
73
diff view generated by jsdifflib
1
From: Jean-Philippe Brucker <jean-philippe@linaro.org>
1
The CNTVOFF_EL2 offset register should only be applied for accessses
2
to CNTVCT_EL0 and for the EL1 virtual timer (CNTV_*). We were
3
incorrectly applying it for the EL2 virtual timer (CNTHV_*).
2
4
3
The AT instruction is UNDEFINED if the {NSE,NS} configuration is
5
Cc: qemu-stable@nongnu.org
4
invalid. Add a function to check this on all AT instructions that apply
5
to an EL lower than 3.
6
7
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
9
Message-id: 20230809123706.1842548-6-jean-philippe@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Message-id: 20250204125009.2281315-3-peter.maydell@linaro.org
12
---
9
---
13
target/arm/helper.c | 38 +++++++++++++++++++++++++++-----------
10
target/arm/helper.c | 2 --
14
1 file changed, 27 insertions(+), 11 deletions(-)
11
1 file changed, 2 deletions(-)
15
12
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper.c
15
--- a/target/arm/helper.c
19
+++ b/target/arm/helper.c
16
+++ b/target/arm/helper.c
20
@@ -XXX,XX +XXX,XX @@ static void ats1h_write(CPUARMState *env, const ARMCPRegInfo *ri,
17
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
21
#endif /* CONFIG_TCG */
18
22
}
19
switch (timeridx) {
23
20
case GTIMER_VIRT:
24
+static CPAccessResult at_e012_access(CPUARMState *env, const ARMCPRegInfo *ri,
21
- case GTIMER_HYPVIRT:
25
+ bool isread)
22
offset = gt_virt_cnt_offset(env);
26
+{
23
break;
27
+ /*
24
case GTIMER_PHYS:
28
+ * R_NYXTL: instruction is UNDEFINED if it applies to an Exception level
25
@@ -XXX,XX +XXX,XX @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
29
+ * lower than EL3 and the combination SCR_EL3.{NSE,NS} is reserved. This can
26
30
+ * only happen when executing at EL3 because that combination also causes an
27
switch (timeridx) {
31
+ * illegal exception return. We don't need to check FEAT_RME either, because
28
case GTIMER_VIRT:
32
+ * scr_write() ensures that the NSE bit is not set otherwise.
29
- case GTIMER_HYPVIRT:
33
+ */
30
offset = gt_virt_cnt_offset(env);
34
+ if ((env->cp15.scr_el3 & (SCR_NSE | SCR_NS)) == SCR_NSE) {
31
break;
35
+ return CP_ACCESS_TRAP;
32
case GTIMER_PHYS:
36
+ }
37
+ return CP_ACCESS_OK;
38
+}
39
+
40
static CPAccessResult at_s1e2_access(CPUARMState *env, const ARMCPRegInfo *ri,
41
bool isread)
42
{
43
@@ -XXX,XX +XXX,XX @@ static CPAccessResult at_s1e2_access(CPUARMState *env, const ARMCPRegInfo *ri,
44
!(env->cp15.scr_el3 & (SCR_NS | SCR_EEL2))) {
45
return CP_ACCESS_TRAP;
46
}
47
- return CP_ACCESS_OK;
48
+ return at_e012_access(env, ri, isread);
49
}
50
51
static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
52
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
53
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 0,
54
.access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
55
.fgt = FGT_ATS1E1R,
56
- .writefn = ats_write64 },
57
+ .accessfn = at_e012_access, .writefn = ats_write64 },
58
{ .name = "AT_S1E1W", .state = ARM_CP_STATE_AA64,
59
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 1,
60
.access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
61
.fgt = FGT_ATS1E1W,
62
- .writefn = ats_write64 },
63
+ .accessfn = at_e012_access, .writefn = ats_write64 },
64
{ .name = "AT_S1E0R", .state = ARM_CP_STATE_AA64,
65
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 2,
66
.access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
67
.fgt = FGT_ATS1E0R,
68
- .writefn = ats_write64 },
69
+ .accessfn = at_e012_access, .writefn = ats_write64 },
70
{ .name = "AT_S1E0W", .state = ARM_CP_STATE_AA64,
71
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 8, .opc2 = 3,
72
.access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
73
.fgt = FGT_ATS1E0W,
74
- .writefn = ats_write64 },
75
+ .accessfn = at_e012_access, .writefn = ats_write64 },
76
{ .name = "AT_S12E1R", .state = ARM_CP_STATE_AA64,
77
.opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 4,
78
.access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
79
- .writefn = ats_write64 },
80
+ .accessfn = at_e012_access, .writefn = ats_write64 },
81
{ .name = "AT_S12E1W", .state = ARM_CP_STATE_AA64,
82
.opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 5,
83
.access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
84
- .writefn = ats_write64 },
85
+ .accessfn = at_e012_access, .writefn = ats_write64 },
86
{ .name = "AT_S12E0R", .state = ARM_CP_STATE_AA64,
87
.opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 6,
88
.access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
89
- .writefn = ats_write64 },
90
+ .accessfn = at_e012_access, .writefn = ats_write64 },
91
{ .name = "AT_S12E0W", .state = ARM_CP_STATE_AA64,
92
.opc0 = 1, .opc1 = 4, .crn = 7, .crm = 8, .opc2 = 7,
93
.access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
94
- .writefn = ats_write64 },
95
+ .accessfn = at_e012_access, .writefn = ats_write64 },
96
/* AT S1E2* are elsewhere as they UNDEF from EL3 if EL2 is not present */
97
{ .name = "AT_S1E3R", .state = ARM_CP_STATE_AA64,
98
.opc0 = 1, .opc1 = 6, .crn = 7, .crm = 8, .opc2 = 0,
99
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo ats1e1_reginfo[] = {
100
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 0,
101
.access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
102
.fgt = FGT_ATS1E1RP,
103
- .writefn = ats_write64 },
104
+ .accessfn = at_e012_access, .writefn = ats_write64 },
105
{ .name = "AT_S1E1WP", .state = ARM_CP_STATE_AA64,
106
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 1,
107
.access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
108
.fgt = FGT_ATS1E1WP,
109
- .writefn = ats_write64 },
110
+ .accessfn = at_e012_access, .writefn = ats_write64 },
111
};
112
113
static const ARMCPRegInfo ats1cp_reginfo[] = {
114
--
33
--
115
2.34.1
34
2.43.0
35
36
diff view generated by jsdifflib
1
The PAR_EL1.SH field documents that for the cases of:
1
When we added Secure EL2 support, we missed that this needs an update
2
* Device memory
2
to the access code for the EL3 physical timer registers. These are
3
* Normal memory with both Inner and Outer Non-Cacheable
3
supposed to UNDEF from Secure EL1 when Secure EL2 is enabled.
4
the field should be 0b10 rather than whatever was in the
5
translation table descriptor field. (In the pseudocode this
6
is handled by PAREncodeShareability().) Perform this
7
adjustment when assembling a PAR value.
8
4
5
(Note for stable backporting: for backports to branches where
6
CP_ACCESS_UNDEFINED is not defined, the old name to use instead
7
is CP_ACCESS_TRAP_UNCATEGORIZED.)
8
9
Cc: qemu-stable@nongnu.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Message-id: 20230807141514.19075-16-peter.maydell@linaro.org
12
Message-id: 20250204125009.2281315-4-peter.maydell@linaro.org
12
---
13
---
13
target/arm/helper.c | 15 ++++++++++++++-
14
target/arm/helper.c | 3 +++
14
1 file changed, 14 insertions(+), 1 deletion(-)
15
1 file changed, 3 insertions(+)
15
16
16
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper.c
19
--- a/target/arm/helper.c
19
+++ b/target/arm/helper.c
20
+++ b/target/arm/helper.c
20
@@ -XXX,XX +XXX,XX @@ static CPAccessResult ats_access(CPUARMState *env, const ARMCPRegInfo *ri,
21
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_stimer_access(CPUARMState *env,
21
}
22
if (!arm_is_secure(env)) {
22
23
return CP_ACCESS_UNDEFINED;
23
#ifdef CONFIG_TCG
24
}
24
+static int par_el1_shareability(GetPhysAddrResult *res)
25
+ if (arm_is_el2_enabled(env)) {
25
+{
26
+ return CP_ACCESS_UNDEFINED;
26
+ /*
27
+ }
27
+ * The PAR_EL1.SH field must be 0b10 for Device or Normal-NC
28
if (!(env->cp15.scr_el3 & SCR_ST)) {
28
+ * memory -- see pseudocode PAREncodeShareability().
29
return CP_ACCESS_TRAP_EL3;
29
+ */
30
}
30
+ if (((res->cacheattrs.attrs & 0xf0) == 0) ||
31
+ res->cacheattrs.attrs == 0x44 || res->cacheattrs.attrs == 0x40) {
32
+ return 2;
33
+ }
34
+ return res->cacheattrs.shareability;
35
+}
36
+
37
static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
38
MMUAccessType access_type, ARMMMUIdx mmu_idx,
39
bool is_secure)
40
@@ -XXX,XX +XXX,XX @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
41
par64 |= (1 << 9); /* NS */
42
}
43
par64 |= (uint64_t)res.cacheattrs.attrs << 56; /* ATTR */
44
- par64 |= res.cacheattrs.shareability << 7; /* SH */
45
+ par64 |= par_el1_shareability(&res) << 7; /* SH */
46
} else {
47
uint32_t fsr = arm_fi_to_lfsc(&fi);
48
49
--
31
--
50
2.34.1
32
2.43.0
33
34
diff view generated by jsdifflib
1
From: Akihiko Odaki <akihiko.odaki@daynix.com>
1
Currently we handle CNTV_TVAL_EL02 by calling gt_tval_read() for the
2
EL1 virt timer. This is almost correct, but the underlying
3
CNTV_TVAL_EL0 register behaves slightly differently. CNTV_TVAL_EL02
4
always applies the CNTVOFF_EL2 offset; CNTV_TVAL_EL0 doesn't do so if
5
we're at EL2 and HCR_EL2.E2H is 1.
2
6
3
kvm_arch_get_default_type() returns the default KVM type. This hook is
7
We were getting this wrong, because we ended up in
4
particularly useful to derive a KVM type that is valid for "none"
8
gt_virt_cnt_offset() and did the E2H check.
5
machine model, which is used by libvirt to probe the availability of
6
KVM.
7
9
8
For MIPS, the existing mips_kvm_type() is reused. This function ensures
10
Factor out the tval read/write calculation from the selection of the
9
the availability of VZ which is mandatory to use KVM on the current
11
offset, so that we can special case gt_virt_tval_read() and
10
QEMU.
12
gt_virt_tval_write() to unconditionally pass CNTVOFF_EL2.
11
13
12
Cc: qemu-stable@nongnu.org
14
Cc: qemu-stable@nongnu.org
13
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
14
Message-id: 20230727073134.134102-2-akihiko.odaki@daynix.com
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
[PMM: added doc comment for new function]
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
16
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
17
Message-id: 20250204125009.2281315-5-peter.maydell@linaro.org
19
---
18
---
20
include/sysemu/kvm.h | 2 ++
19
target/arm/helper.c | 36 +++++++++++++++++++++++++++---------
21
target/mips/kvm_mips.h | 9 ---------
20
1 file changed, 27 insertions(+), 9 deletions(-)
22
accel/kvm/kvm-all.c | 4 +++-
23
hw/mips/loongson3_virt.c | 2 --
24
target/arm/kvm.c | 5 +++++
25
target/i386/kvm/kvm.c | 5 +++++
26
target/mips/kvm.c | 2 +-
27
target/ppc/kvm.c | 5 +++++
28
target/riscv/kvm.c | 5 +++++
29
target/s390x/kvm/kvm.c | 5 +++++
30
10 files changed, 31 insertions(+), 13 deletions(-)
31
21
32
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
22
diff --git a/target/arm/helper.c b/target/arm/helper.c
33
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
34
--- a/include/sysemu/kvm.h
24
--- a/target/arm/helper.c
35
+++ b/include/sysemu/kvm.h
25
+++ b/target/arm/helper.c
36
@@ -XXX,XX +XXX,XX @@ int kvm_arch_get_registers(CPUState *cpu);
26
@@ -XXX,XX +XXX,XX @@ static void gt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
37
27
gt_recalc_timer(env_archcpu(env), timeridx);
38
int kvm_arch_put_registers(CPUState *cpu, int level);
39
40
+int kvm_arch_get_default_type(MachineState *ms);
41
+
42
int kvm_arch_init(MachineState *ms, KVMState *s);
43
44
int kvm_arch_init_vcpu(CPUState *cpu);
45
diff --git a/target/mips/kvm_mips.h b/target/mips/kvm_mips.h
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/mips/kvm_mips.h
48
+++ b/target/mips/kvm_mips.h
49
@@ -XXX,XX +XXX,XX @@ void kvm_mips_reset_vcpu(MIPSCPU *cpu);
50
int kvm_mips_set_interrupt(MIPSCPU *cpu, int irq, int level);
51
int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level);
52
53
-#ifdef CONFIG_KVM
54
-int mips_kvm_type(MachineState *machine, const char *vm_type);
55
-#else
56
-static inline int mips_kvm_type(MachineState *machine, const char *vm_type)
57
-{
58
- return 0;
59
-}
60
-#endif
61
-
62
#endif /* KVM_MIPS_H */
63
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/accel/kvm/kvm-all.c
66
+++ b/accel/kvm/kvm-all.c
67
@@ -XXX,XX +XXX,XX @@ static int kvm_init(MachineState *ms)
68
KVMState *s;
69
const KVMCapabilityInfo *missing_cap;
70
int ret;
71
- int type = 0;
72
+ int type;
73
uint64_t dirty_log_manual_caps;
74
75
qemu_mutex_init(&kml_slots_lock);
76
@@ -XXX,XX +XXX,XX @@ static int kvm_init(MachineState *ms)
77
type = mc->kvm_type(ms, kvm_type);
78
} else if (mc->kvm_type) {
79
type = mc->kvm_type(ms, NULL);
80
+ } else {
81
+ type = kvm_arch_get_default_type(ms);
82
}
83
84
do {
85
diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/hw/mips/loongson3_virt.c
88
+++ b/hw/mips/loongson3_virt.c
89
@@ -XXX,XX +XXX,XX @@
90
#include "qemu/datadir.h"
91
#include "qapi/error.h"
92
#include "elf.h"
93
-#include "kvm_mips.h"
94
#include "hw/char/serial.h"
95
#include "hw/intc/loongson_liointc.h"
96
#include "hw/mips/mips.h"
97
@@ -XXX,XX +XXX,XX @@ static void loongson3v_machine_class_init(ObjectClass *oc, void *data)
98
mc->max_cpus = LOONGSON_MAX_VCPUS;
99
mc->default_ram_id = "loongson3.highram";
100
mc->default_ram_size = 1600 * MiB;
101
- mc->kvm_type = mips_kvm_type;
102
mc->minimum_page_bits = 14;
103
mc->default_nic = "virtio-net-pci";
104
}
28
}
105
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
29
106
index XXXXXXX..XXXXXXX 100644
30
+static uint64_t do_tval_read(CPUARMState *env, int timeridx, uint64_t offset)
107
--- a/target/arm/kvm.c
108
+++ b/target/arm/kvm.c
109
@@ -XXX,XX +XXX,XX @@ int kvm_arm_get_max_vm_ipa_size(MachineState *ms, bool *fixed_ipa)
110
return ret > 0 ? ret : 40;
111
}
112
113
+int kvm_arch_get_default_type(MachineState *ms)
114
+{
31
+{
115
+ return 0;
32
+ return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
33
+ (gt_get_countervalue(env) - offset));
116
+}
34
+}
117
+
35
+
118
int kvm_arch_init(MachineState *ms, KVMState *s)
36
static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
37
int timeridx)
119
{
38
{
120
int ret = 0;
39
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
121
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
40
break;
122
index XXXXXXX..XXXXXXX 100644
41
}
123
--- a/target/i386/kvm/kvm.c
42
124
+++ b/target/i386/kvm/kvm.c
43
- return (uint32_t)(env->cp15.c14_timer[timeridx].cval -
125
@@ -XXX,XX +XXX,XX @@ static void register_smram_listener(Notifier *n, void *unused)
44
- (gt_get_countervalue(env) - offset));
126
&smram_address_space, 1, "kvm-smram");
45
+ return do_tval_read(env, timeridx, offset);
127
}
128
129
+int kvm_arch_get_default_type(MachineState *ms)
130
+{
131
+ return 0;
132
+}
46
+}
133
+
47
+
134
int kvm_arch_init(MachineState *ms, KVMState *s)
48
+static void do_tval_write(CPUARMState *env, int timeridx, uint64_t value,
49
+ uint64_t offset)
50
+{
51
+ trace_arm_gt_tval_write(timeridx, value);
52
+ env->cp15.c14_timer[timeridx].cval = gt_get_countervalue(env) - offset +
53
+ sextract64(value, 0, 32);
54
+ gt_recalc_timer(env_archcpu(env), timeridx);
55
}
56
57
static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
58
@@ -XXX,XX +XXX,XX @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
59
offset = gt_phys_cnt_offset(env);
60
break;
61
}
62
-
63
- trace_arm_gt_tval_write(timeridx, value);
64
- env->cp15.c14_timer[timeridx].cval = gt_get_countervalue(env) - offset +
65
- sextract64(value, 0, 32);
66
- gt_recalc_timer(env_archcpu(env), timeridx);
67
+ do_tval_write(env, timeridx, value, offset);
68
}
69
70
static void gt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
71
@@ -XXX,XX +XXX,XX @@ static void gt_virt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
72
73
static uint64_t gt_virt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
135
{
74
{
136
uint64_t identity_base = 0xfffbc000;
75
- return gt_tval_read(env, ri, GTIMER_VIRT);
137
diff --git a/target/mips/kvm.c b/target/mips/kvm.c
76
+ /*
138
index XXXXXXX..XXXXXXX 100644
77
+ * This is CNTV_TVAL_EL02; unlike the underlying CNTV_TVAL_EL0
139
--- a/target/mips/kvm.c
78
+ * we always apply CNTVOFF_EL2. Special case that here rather
140
+++ b/target/mips/kvm.c
79
+ * than going into the generic gt_tval_read() and then having
141
@@ -XXX,XX +XXX,XX @@ int kvm_arch_msi_data_to_gsi(uint32_t data)
80
+ * to re-detect that it's this register.
142
abort();
81
+ * Note that the accessfn/perms mean we know we're at EL2 or EL3 here.
82
+ */
83
+ return do_tval_read(env, GTIMER_VIRT, env->cp15.cntvoff_el2);
143
}
84
}
144
85
145
-int mips_kvm_type(MachineState *machine, const char *vm_type)
86
static void gt_virt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
146
+int kvm_arch_get_default_type(MachineState *machine)
87
uint64_t value)
147
{
88
{
148
#if defined(KVM_CAP_MIPS_VZ)
89
- gt_tval_write(env, ri, GTIMER_VIRT, value);
149
int r;
90
+ /* Similarly for writes to CNTV_TVAL_EL02 */
150
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
91
+ do_tval_write(env, GTIMER_VIRT, value, env->cp15.cntvoff_el2);
151
index XXXXXXX..XXXXXXX 100644
152
--- a/target/ppc/kvm.c
153
+++ b/target/ppc/kvm.c
154
@@ -XXX,XX +XXX,XX @@ static int kvm_ppc_register_host_cpu_type(void);
155
static void kvmppc_get_cpu_characteristics(KVMState *s);
156
static int kvmppc_get_dec_bits(void);
157
158
+int kvm_arch_get_default_type(MachineState *ms)
159
+{
160
+ return 0;
161
+}
162
+
163
int kvm_arch_init(MachineState *ms, KVMState *s)
164
{
165
cap_interrupt_unset = kvm_check_extension(s, KVM_CAP_PPC_UNSET_IRQ);
166
diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c
167
index XXXXXXX..XXXXXXX 100644
168
--- a/target/riscv/kvm.c
169
+++ b/target/riscv/kvm.c
170
@@ -XXX,XX +XXX,XX @@ int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,
171
return 0;
172
}
92
}
173
93
174
+int kvm_arch_get_default_type(MachineState *ms)
94
static void gt_virt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
175
+{
176
+ return 0;
177
+}
178
+
179
int kvm_arch_init(MachineState *ms, KVMState *s)
180
{
181
return 0;
182
diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c
183
index XXXXXXX..XXXXXXX 100644
184
--- a/target/s390x/kvm/kvm.c
185
+++ b/target/s390x/kvm/kvm.c
186
@@ -XXX,XX +XXX,XX @@ static void ccw_machine_class_foreach(ObjectClass *oc, void *opaque)
187
mc->default_cpu_type = S390_CPU_TYPE_NAME("host");
188
}
189
190
+int kvm_arch_get_default_type(MachineState *ms)
191
+{
192
+ return 0;
193
+}
194
+
195
int kvm_arch_init(MachineState *ms, KVMState *s)
196
{
197
object_class_foreach(ccw_machine_class_foreach, TYPE_S390_CCW_MACHINE,
198
--
95
--
199
2.34.1
96
2.43.0
200
97
201
98
diff view generated by jsdifflib
1
From: Jean-Philippe Brucker <jean-philippe@linaro.org>
1
When reading or writing the timer registers, sometimes we need to
2
2
apply one of the timer offsets. Specifically, this happens for
3
GPC checks are not performed on the output address for AT instructions,
3
direct reads of the counter registers CNTPCT_EL0 and CNTVCT_EL0 (and
4
as stated by ARM DDI 0487J in D8.12.2:
4
their self-synchronized variants CNTVCTSS_EL0 and CNTPCTSS_EL0). It
5
5
also applies for direct reads and writes of the CNT*_TVAL_EL*
6
When populating PAR_EL1 with the result of an address translation
6
registers that provide the 32-bit downcounting view of each timer.
7
instruction, granule protection checks are not performed on the final
7
8
output address of a successful translation.
8
We currently do this with duplicated code in gt_tval_read() and
9
9
gt_tval_write() and a special-case in gt_virt_cnt_read() and
10
Rename get_phys_addr_with_secure(), since it's only used to handle AT
10
gt_cnt_read(). Refactor this so that we handle it all in a single
11
instructions.
11
function gt_direct_access_timer_offset(), to parallel how we handle
12
12
the offset for indirect accesses.
13
Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
13
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
The call in the WFIT helper previously to gt_virt_cnt_offset() is
15
Message-id: 20230809123706.1842548-4-jean-philippe@linaro.org
15
now to gt_direct_access_timer_offset(); this is the correct
16
behaviour, but it's not immediately obvious that it shouldn't be
17
considered an indirect access, so we add an explanatory comment.
18
19
This commit should make no behavioural changes.
20
21
(Cc to stable because the following bugfix commit will
22
depend on this one.)
23
24
Cc: qemu-stable@nongnu.org
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
26
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
27
Message-id: 20250204125009.2281315-6-peter.maydell@linaro.org
17
---
28
---
18
target/arm/internals.h | 25 ++++++++++++++-----------
29
target/arm/internals.h | 5 +-
19
target/arm/helper.c | 8 ++++++--
30
target/arm/helper.c | 103 +++++++++++++++++++------------------
20
target/arm/ptw.c | 11 ++++++-----
31
target/arm/tcg/op_helper.c | 8 ++-
21
3 files changed, 26 insertions(+), 18 deletions(-)
32
3 files changed, 62 insertions(+), 54 deletions(-)
22
33
23
diff --git a/target/arm/internals.h b/target/arm/internals.h
34
diff --git a/target/arm/internals.h b/target/arm/internals.h
24
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/internals.h
36
--- a/target/arm/internals.h
26
+++ b/target/arm/internals.h
37
+++ b/target/arm/internals.h
27
@@ -XXX,XX +XXX,XX @@ typedef struct GetPhysAddrResult {
38
@@ -XXX,XX +XXX,XX @@ int delete_hw_watchpoint(target_ulong addr, target_ulong len, int type);
28
} GetPhysAddrResult;
39
uint64_t gt_get_countervalue(CPUARMState *env);
29
40
/*
30
/**
41
* Return the currently applicable offset between the system counter
31
- * get_phys_addr_with_secure: get the physical address for a virtual address
42
- * and CNTVCT_EL0 (this will be either 0 or the value of CNTVOFF_EL2).
32
+ * get_phys_addr: get the physical address for a virtual address
43
+ * and the counter for the specified timer, as used for direct register
33
* @env: CPUARMState
44
+ * accesses.
34
* @address: virtual address to get physical address for
35
* @access_type: 0 for read, 1 for write, 2 for execute
36
* @mmu_idx: MMU index indicating required translation regime
37
- * @is_secure: security state for the access
38
* @result: set on translation success.
39
* @fi: set to fault info if the translation fails
40
*
41
@@ -XXX,XX +XXX,XX @@ typedef struct GetPhysAddrResult {
42
* * for PSMAv5 based systems we don't bother to return a full FSR format
43
* value.
44
*/
45
*/
45
-bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
46
-uint64_t gt_virt_cnt_offset(CPUARMState *env);
46
- MMUAccessType access_type,
47
+uint64_t gt_direct_access_timer_offset(CPUARMState *env, int timeridx);
47
- ARMMMUIdx mmu_idx, bool is_secure,
48
48
- GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
49
/*
49
+bool get_phys_addr(CPUARMState *env, target_ulong address,
50
* Return mask of ARMMMUIdxBit values corresponding to an "invalidate
50
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
51
+ GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
52
__attribute__((nonnull));
53
54
/**
55
- * get_phys_addr: get the physical address for a virtual address
56
+ * get_phys_addr_with_secure_nogpc: get the physical address for a virtual
57
+ * address
58
* @env: CPUARMState
59
* @address: virtual address to get physical address for
60
* @access_type: 0 for read, 1 for write, 2 for execute
61
* @mmu_idx: MMU index indicating required translation regime
62
+ * @is_secure: security state for the access
63
* @result: set on translation success.
64
* @fi: set to fault info if the translation fails
65
*
66
- * Similarly, but use the security regime of @mmu_idx.
67
+ * Similar to get_phys_addr, but use the given security regime and don't perform
68
+ * a Granule Protection Check on the resulting address.
69
*/
70
-bool get_phys_addr(CPUARMState *env, target_ulong address,
71
- MMUAccessType access_type, ARMMMUIdx mmu_idx,
72
- GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
73
+bool get_phys_addr_with_secure_nogpc(CPUARMState *env, target_ulong address,
74
+ MMUAccessType access_type,
75
+ ARMMMUIdx mmu_idx, bool is_secure,
76
+ GetPhysAddrResult *result,
77
+ ARMMMUFaultInfo *fi)
78
__attribute__((nonnull));
79
80
bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
81
diff --git a/target/arm/helper.c b/target/arm/helper.c
51
diff --git a/target/arm/helper.c b/target/arm/helper.c
82
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
83
--- a/target/arm/helper.c
53
--- a/target/arm/helper.c
84
+++ b/target/arm/helper.c
54
+++ b/target/arm/helper.c
85
@@ -XXX,XX +XXX,XX @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
55
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_phys_raw_cnt_offset(CPUARMState *env)
86
ARMMMUFaultInfo fi = {};
56
return 0;
87
GetPhysAddrResult res = {};
57
}
88
58
89
- ret = get_phys_addr_with_secure(env, value, access_type, mmu_idx,
59
-static uint64_t gt_phys_cnt_offset(CPUARMState *env)
90
- is_secure, &res, &fi);
60
-{
61
- if (arm_current_el(env) >= 2) {
62
- return 0;
63
- }
64
- return gt_phys_raw_cnt_offset(env);
65
-}
66
-
67
static uint64_t gt_indirect_access_timer_offset(CPUARMState *env, int timeridx)
68
{
69
/*
70
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_indirect_access_timer_offset(CPUARMState *env, int timeridx)
71
}
72
}
73
74
+uint64_t gt_direct_access_timer_offset(CPUARMState *env, int timeridx)
75
+{
91
+ /*
76
+ /*
92
+ * I_MXTJT: Granule protection checks are not performed on the final address
77
+ * Return the timer offset to use for direct accesses to the
93
+ * of a successful translation.
78
+ * counter registers CNTPCT and CNTVCT, and for direct accesses
79
+ * to the CNT*_TVAL registers.
80
+ *
81
+ * This isn't exactly the same as the indirect-access offset,
82
+ * because here we also care about what EL the register access
83
+ * is being made from.
84
+ *
85
+ * This corresponds to the access pseudocode for the registers.
94
+ */
86
+ */
95
+ ret = get_phys_addr_with_secure_nogpc(env, value, access_type, mmu_idx,
87
+ uint64_t hcr;
96
+ is_secure, &res, &fi);
88
+
97
89
+ switch (timeridx) {
98
/*
90
+ case GTIMER_PHYS:
99
* ATS operations only do S1 or S1+S2 translations, so we never
91
+ if (arm_current_el(env) >= 2) {
100
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
92
+ return 0;
93
+ }
94
+ return gt_phys_raw_cnt_offset(env);
95
+ case GTIMER_VIRT:
96
+ switch (arm_current_el(env)) {
97
+ case 2:
98
+ hcr = arm_hcr_el2_eff(env);
99
+ if (hcr & HCR_E2H) {
100
+ return 0;
101
+ }
102
+ break;
103
+ case 0:
104
+ hcr = arm_hcr_el2_eff(env);
105
+ if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
106
+ return 0;
107
+ }
108
+ break;
109
+ }
110
+ return env->cp15.cntvoff_el2;
111
+ case GTIMER_HYP:
112
+ case GTIMER_SEC:
113
+ case GTIMER_HYPVIRT:
114
+ return 0;
115
+ default:
116
+ g_assert_not_reached();
117
+ }
118
+}
119
+
120
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
121
{
122
ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
123
@@ -XXX,XX +XXX,XX @@ static void gt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri,
124
125
static uint64_t gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
126
{
127
- return gt_get_countervalue(env) - gt_phys_cnt_offset(env);
128
-}
129
-
130
-uint64_t gt_virt_cnt_offset(CPUARMState *env)
131
-{
132
- uint64_t hcr;
133
-
134
- switch (arm_current_el(env)) {
135
- case 2:
136
- hcr = arm_hcr_el2_eff(env);
137
- if (hcr & HCR_E2H) {
138
- return 0;
139
- }
140
- break;
141
- case 0:
142
- hcr = arm_hcr_el2_eff(env);
143
- if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
144
- return 0;
145
- }
146
- break;
147
- }
148
-
149
- return env->cp15.cntvoff_el2;
150
+ uint64_t offset = gt_direct_access_timer_offset(env, GTIMER_PHYS);
151
+ return gt_get_countervalue(env) - offset;
152
}
153
154
static uint64_t gt_virt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
155
{
156
- return gt_get_countervalue(env) - gt_virt_cnt_offset(env);
157
+ uint64_t offset = gt_direct_access_timer_offset(env, GTIMER_VIRT);
158
+ return gt_get_countervalue(env) - offset;
159
}
160
161
static void gt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
162
@@ -XXX,XX +XXX,XX @@ static uint64_t do_tval_read(CPUARMState *env, int timeridx, uint64_t offset)
163
static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri,
164
int timeridx)
165
{
166
- uint64_t offset = 0;
167
-
168
- switch (timeridx) {
169
- case GTIMER_VIRT:
170
- offset = gt_virt_cnt_offset(env);
171
- break;
172
- case GTIMER_PHYS:
173
- offset = gt_phys_cnt_offset(env);
174
- break;
175
- }
176
+ uint64_t offset = gt_direct_access_timer_offset(env, timeridx);
177
178
return do_tval_read(env, timeridx, offset);
179
}
180
@@ -XXX,XX +XXX,XX @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
181
int timeridx,
182
uint64_t value)
183
{
184
- uint64_t offset = 0;
185
+ uint64_t offset = gt_direct_access_timer_offset(env, timeridx);
186
187
- switch (timeridx) {
188
- case GTIMER_VIRT:
189
- offset = gt_virt_cnt_offset(env);
190
- break;
191
- case GTIMER_PHYS:
192
- offset = gt_phys_cnt_offset(env);
193
- break;
194
- }
195
do_tval_write(env, timeridx, value, offset);
196
}
197
198
diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c
101
index XXXXXXX..XXXXXXX 100644
199
index XXXXXXX..XXXXXXX 100644
102
--- a/target/arm/ptw.c
200
--- a/target/arm/tcg/op_helper.c
103
+++ b/target/arm/ptw.c
201
+++ b/target/arm/tcg/op_helper.c
104
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_gpc(CPUARMState *env, S1Translate *ptw,
202
@@ -XXX,XX +XXX,XX @@ void HELPER(wfit)(CPUARMState *env, uint64_t timeout)
105
return false;
203
int target_el = check_wfx_trap(env, false, &excp);
106
}
204
/* The WFIT should time out when CNTVCT_EL0 >= the specified value. */
107
205
uint64_t cntval = gt_get_countervalue(env);
108
-bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
206
- uint64_t offset = gt_virt_cnt_offset(env);
109
- MMUAccessType access_type, ARMMMUIdx mmu_idx,
207
+ /*
110
- bool is_secure, GetPhysAddrResult *result,
208
+ * We want the value that we would get if we read CNTVCT_EL0 from
111
- ARMMMUFaultInfo *fi)
209
+ * the current exception level, so the direct_access offset, not
112
+bool get_phys_addr_with_secure_nogpc(CPUARMState *env, target_ulong address,
210
+ * the indirect_access one. Compare the pseudocode LocalTimeoutEvent(),
113
+ MMUAccessType access_type,
211
+ * which calls VirtualCounterTimer().
114
+ ARMMMUIdx mmu_idx, bool is_secure,
212
+ */
115
+ GetPhysAddrResult *result,
213
+ uint64_t offset = gt_direct_access_timer_offset(env, GTIMER_VIRT);
116
+ ARMMMUFaultInfo *fi)
214
uint64_t cntvct = cntval - offset;
117
{
215
uint64_t nexttick;
118
S1Translate ptw = {
216
119
.in_mmu_idx = mmu_idx,
120
.in_space = arm_secure_to_space(is_secure),
121
};
122
- return get_phys_addr_gpc(env, &ptw, address, access_type, result, fi);
123
+ return get_phys_addr_nogpc(env, &ptw, address, access_type, result, fi);
124
}
125
126
bool get_phys_addr(CPUARMState *env, target_ulong address,
127
--
217
--
128
2.34.1
218
2.43.0
219
220
diff view generated by jsdifflib
1
From: Jean-Philippe Brucker <jean-philippe@linaro.org>
1
From: Alex Bennée <alex.bennee@linaro.org>
2
2
3
When FEAT_RME is implemented, these bits override the value of
3
When FEAT_SEL2 was implemented the SEL2 timers were missed. This
4
CNT[VP]_CTL_EL0.IMASK in Realm and Root state. Move the IRQ state update
4
shows up when building the latest Hafnium with SPMC_AT_EL=2. The
5
into a new gt_update_irq() function and test those bits every time we
5
actual implementation utilises the same logic as the rest of the
6
recompute the IRQ state.
6
timers so all we need to do is:
7
7
8
Since we're removing the IRQ state from some trace events, add a new
8
- define the timers and their access functions
9
trace event for gt_update_irq().
9
- conditionally add the correct system registers
10
10
- create a new accessfn as the rules are subtly different to the
11
Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
11
existing secure timer
12
Message-id: 20230809123706.1842548-7-jean-philippe@linaro.org
12
13
[PMM: only register change hook if not USER_ONLY and if TCG]
13
Fixes: e9152ee91c (target/arm: add ARMv8.4-SEL2 system registers)
14
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
17
Message-id: 20250204125009.2281315-7-peter.maydell@linaro.org
18
Cc: qemu-stable@nongnu.org
19
Cc: Andrei Homescu <ahomescu@google.com>
20
Cc: Arve Hjønnevåg <arve@google.com>
21
Cc: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
22
[PMM: CP_ACCESS_TRAP_UNCATEGORIZED -> CP_ACCESS_UNDEFINED;
23
offset logic now in gt_{indirect,direct}_access_timer_offset() ]
24
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
26
---
17
target/arm/cpu.h | 4 +++
27
include/hw/arm/bsa.h | 2 +
18
target/arm/cpu.c | 6 ++++
28
target/arm/cpu.h | 2 +
19
target/arm/helper.c | 65 ++++++++++++++++++++++++++++++++++-------
29
target/arm/gtimer.h | 4 +-
20
target/arm/trace-events | 7 +++--
30
target/arm/cpu.c | 4 ++
21
4 files changed, 68 insertions(+), 14 deletions(-)
31
target/arm/helper.c | 163 +++++++++++++++++++++++++++++++++++++++++++
22
32
5 files changed, 174 insertions(+), 1 deletion(-)
33
34
diff --git a/include/hw/arm/bsa.h b/include/hw/arm/bsa.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/include/hw/arm/bsa.h
37
+++ b/include/hw/arm/bsa.h
38
@@ -XXX,XX +XXX,XX @@
39
#define QEMU_ARM_BSA_H
40
41
/* These are architectural INTID values */
42
+#define ARCH_TIMER_S_EL2_VIRT_IRQ 19
43
+#define ARCH_TIMER_S_EL2_IRQ 20
44
#define VIRTUAL_PMU_IRQ 23
45
#define ARCH_GIC_MAINT_IRQ 25
46
#define ARCH_TIMER_NS_EL2_IRQ 26
23
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
47
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
24
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/cpu.h
49
--- a/target/arm/cpu.h
26
+++ b/target/arm/cpu.h
50
+++ b/target/arm/cpu.h
27
@@ -XXX,XX +XXX,XX @@ struct ArchCPU {
51
@@ -XXX,XX +XXX,XX @@ void arm_gt_vtimer_cb(void *opaque);
52
void arm_gt_htimer_cb(void *opaque);
53
void arm_gt_stimer_cb(void *opaque);
54
void arm_gt_hvtimer_cb(void *opaque);
55
+void arm_gt_sel2timer_cb(void *opaque);
56
+void arm_gt_sel2vtimer_cb(void *opaque);
57
58
unsigned int gt_cntfrq_period_ns(ARMCPU *cpu);
59
void gt_rme_post_el_change(ARMCPU *cpu, void *opaque);
60
diff --git a/target/arm/gtimer.h b/target/arm/gtimer.h
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/gtimer.h
63
+++ b/target/arm/gtimer.h
64
@@ -XXX,XX +XXX,XX @@ enum {
65
GTIMER_HYP = 2,
66
GTIMER_SEC = 3,
67
GTIMER_HYPVIRT = 4,
68
-#define NUM_GTIMERS 5
69
+ GTIMER_S_EL2_PHYS = 5, /* CNTHPS_* ; only if FEAT_SEL2 */
70
+ GTIMER_S_EL2_VIRT = 6, /* CNTHVS_* ; only if FEAT_SEL2 */
71
+#define NUM_GTIMERS 7
28
};
72
};
29
73
30
unsigned int gt_cntfrq_period_ns(ARMCPU *cpu);
74
#endif
31
+void gt_rme_post_el_change(ARMCPU *cpu, void *opaque);
32
33
void arm_cpu_post_init(Object *obj);
34
35
@@ -XXX,XX +XXX,XX @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
36
#define HSTR_TTEE (1 << 16)
37
#define HSTR_TJDBX (1 << 17)
38
39
+#define CNTHCTL_CNTVMASK (1 << 18)
40
+#define CNTHCTL_CNTPMASK (1 << 19)
41
+
42
/* Return the current FPSCR value. */
43
uint32_t vfp_get_fpscr(CPUARMState *env);
44
void vfp_set_fpscr(CPUARMState *env, uint32_t val);
45
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
75
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
46
index XXXXXXX..XXXXXXX 100644
76
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/cpu.c
77
--- a/target/arm/cpu.c
48
+++ b/target/arm/cpu.c
78
+++ b/target/arm/cpu.c
49
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
79
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
50
set_feature(env, ARM_FEATURE_VBAR);
80
arm_gt_stimer_cb, cpu);
81
cpu->gt_timer[GTIMER_HYPVIRT] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
82
arm_gt_hvtimer_cb, cpu);
83
+ cpu->gt_timer[GTIMER_S_EL2_PHYS] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
84
+ arm_gt_sel2timer_cb, cpu);
85
+ cpu->gt_timer[GTIMER_S_EL2_VIRT] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
86
+ arm_gt_sel2vtimer_cb, cpu);
51
}
87
}
52
88
#endif
53
+#ifndef CONFIG_USER_ONLY
54
+ if (tcg_enabled() && cpu_isar_feature(aa64_rme, cpu)) {
55
+ arm_register_el_change_hook(cpu, &gt_rme_post_el_change, 0);
56
+ }
57
+#endif
58
+
59
register_cp_regs_for_features(cpu);
60
arm_cpu_register_gdb_regs_for_features(cpu);
61
89
62
diff --git a/target/arm/helper.c b/target/arm/helper.c
90
diff --git a/target/arm/helper.c b/target/arm/helper.c
63
index XXXXXXX..XXXXXXX 100644
91
index XXXXXXX..XXXXXXX 100644
64
--- a/target/arm/helper.c
92
--- a/target/arm/helper.c
65
+++ b/target/arm/helper.c
93
+++ b/target/arm/helper.c
66
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_get_countervalue(CPUARMState *env)
94
@@ -XXX,XX +XXX,XX @@ static CPAccessResult gt_stimer_access(CPUARMState *env,
67
return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / gt_cntfrq_period_ns(cpu);
68
}
69
70
+static void gt_update_irq(ARMCPU *cpu, int timeridx)
71
+{
72
+ CPUARMState *env = &cpu->env;
73
+ uint64_t cnthctl = env->cp15.cnthctl_el2;
74
+ ARMSecuritySpace ss = arm_security_space(env);
75
+ /* ISTATUS && !IMASK */
76
+ int irqstate = (env->cp15.c14_timer[timeridx].ctl & 6) == 4;
77
+
78
+ /*
79
+ * If bit CNTHCTL_EL2.CNT[VP]MASK is set, it overrides IMASK.
80
+ * It is RES0 in Secure and NonSecure state.
81
+ */
82
+ if ((ss == ARMSS_Root || ss == ARMSS_Realm) &&
83
+ ((timeridx == GTIMER_VIRT && (cnthctl & CNTHCTL_CNTVMASK)) ||
84
+ (timeridx == GTIMER_PHYS && (cnthctl & CNTHCTL_CNTPMASK)))) {
85
+ irqstate = 0;
86
+ }
87
+
88
+ qemu_set_irq(cpu->gt_timer_outputs[timeridx], irqstate);
89
+ trace_arm_gt_update_irq(timeridx, irqstate);
90
+}
91
+
92
+void gt_rme_post_el_change(ARMCPU *cpu, void *ignored)
93
+{
94
+ /*
95
+ * Changing security state between Root and Secure/NonSecure, which may
96
+ * happen when switching EL, can change the effective value of CNTHCTL_EL2
97
+ * mask bits. Update the IRQ state accordingly.
98
+ */
99
+ gt_update_irq(cpu, GTIMER_VIRT);
100
+ gt_update_irq(cpu, GTIMER_PHYS);
101
+}
102
+
103
static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
104
{
105
ARMGenericTimer *gt = &cpu->env.cp15.c14_timer[timeridx];
106
@@ -XXX,XX +XXX,XX @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
107
/* Note that this must be unsigned 64 bit arithmetic: */
108
int istatus = count - offset >= gt->cval;
109
uint64_t nexttick;
110
- int irqstate;
111
112
gt->ctl = deposit32(gt->ctl, 2, 1, istatus);
113
114
- irqstate = (istatus && !(gt->ctl & 2));
115
- qemu_set_irq(cpu->gt_timer_outputs[timeridx], irqstate);
116
-
117
if (istatus) {
118
/* Next transition is when count rolls back over to zero */
119
nexttick = UINT64_MAX;
120
@@ -XXX,XX +XXX,XX @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
121
} else {
122
timer_mod(cpu->gt_timer[timeridx], nexttick);
123
}
124
- trace_arm_gt_recalc(timeridx, irqstate, nexttick);
125
+ trace_arm_gt_recalc(timeridx, nexttick);
126
} else {
127
/* Timer disabled: ISTATUS and timer output always clear */
128
gt->ctl &= ~4;
129
- qemu_set_irq(cpu->gt_timer_outputs[timeridx], 0);
130
timer_del(cpu->gt_timer[timeridx]);
131
trace_arm_gt_recalc_disabled(timeridx);
132
}
133
+ gt_update_irq(cpu, timeridx);
134
}
135
136
static void gt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri,
137
@@ -XXX,XX +XXX,XX @@ static void gt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
138
* IMASK toggled: don't need to recalculate,
139
* just set the interrupt line based on ISTATUS
140
*/
141
- int irqstate = (oldval & 4) && !(value & 2);
142
-
143
- trace_arm_gt_imask_toggle(timeridx, irqstate);
144
- qemu_set_irq(cpu->gt_timer_outputs[timeridx], irqstate);
145
+ trace_arm_gt_imask_toggle(timeridx);
146
+ gt_update_irq(cpu, timeridx);
147
}
95
}
148
}
96
}
149
97
150
@@ -XXX,XX +XXX,XX @@ static void gt_virt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
98
+static CPAccessResult gt_sel2timer_access(CPUARMState *env,
151
gt_ctl_write(env, ri, GTIMER_VIRT, value);
99
+ const ARMCPRegInfo *ri,
100
+ bool isread)
101
+{
102
+ /*
103
+ * The AArch64 register view of the secure EL2 timers are mostly
104
+ * accessible from EL3 and EL2 although can also be trapped to EL2
105
+ * from EL1 depending on nested virt config.
106
+ */
107
+ switch (arm_current_el(env)) {
108
+ case 0: /* UNDEFINED */
109
+ return CP_ACCESS_UNDEFINED;
110
+ case 1:
111
+ if (!arm_is_secure(env)) {
112
+ /* UNDEFINED */
113
+ return CP_ACCESS_UNDEFINED;
114
+ } else if (arm_hcr_el2_eff(env) & HCR_NV) {
115
+ /* Aarch64.SystemAccessTrap(EL2, 0x18) */
116
+ return CP_ACCESS_TRAP_EL2;
117
+ }
118
+ /* UNDEFINED */
119
+ return CP_ACCESS_UNDEFINED;
120
+ case 2:
121
+ if (!arm_is_secure(env)) {
122
+ /* UNDEFINED */
123
+ return CP_ACCESS_UNDEFINED;
124
+ }
125
+ return CP_ACCESS_OK;
126
+ case 3:
127
+ if (env->cp15.scr_el3 & SCR_EEL2) {
128
+ return CP_ACCESS_OK;
129
+ } else {
130
+ return CP_ACCESS_UNDEFINED;
131
+ }
132
+ default:
133
+ g_assert_not_reached();
134
+ }
135
+}
136
+
137
uint64_t gt_get_countervalue(CPUARMState *env)
138
{
139
ARMCPU *cpu = env_archcpu(env);
140
@@ -XXX,XX +XXX,XX @@ static uint64_t gt_indirect_access_timer_offset(CPUARMState *env, int timeridx)
141
case GTIMER_HYP:
142
case GTIMER_SEC:
143
case GTIMER_HYPVIRT:
144
+ case GTIMER_S_EL2_PHYS:
145
+ case GTIMER_S_EL2_VIRT:
146
return 0;
147
default:
148
g_assert_not_reached();
149
@@ -XXX,XX +XXX,XX @@ uint64_t gt_direct_access_timer_offset(CPUARMState *env, int timeridx)
150
case GTIMER_HYP:
151
case GTIMER_SEC:
152
case GTIMER_HYPVIRT:
153
+ case GTIMER_S_EL2_PHYS:
154
+ case GTIMER_S_EL2_VIRT:
155
return 0;
156
default:
157
g_assert_not_reached();
158
@@ -XXX,XX +XXX,XX @@ static void gt_sec_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
159
gt_ctl_write(env, ri, GTIMER_SEC, value);
152
}
160
}
153
161
154
+static void gt_cnthctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
162
+static void gt_sec_pel2_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
155
+ uint64_t value)
163
+{
156
+{
164
+ gt_timer_reset(env, ri, GTIMER_S_EL2_PHYS);
157
+ ARMCPU *cpu = env_archcpu(env);
165
+}
158
+ uint32_t oldval = env->cp15.cnthctl_el2;
166
+
159
+
167
+static void gt_sec_pel2_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
160
+ raw_write(env, ri, value);
168
+ uint64_t value)
161
+
169
+{
162
+ if ((oldval ^ value) & CNTHCTL_CNTVMASK) {
170
+ gt_cval_write(env, ri, GTIMER_S_EL2_PHYS, value);
163
+ gt_update_irq(cpu, GTIMER_VIRT);
171
+}
164
+ } else if ((oldval ^ value) & CNTHCTL_CNTPMASK) {
172
+
165
+ gt_update_irq(cpu, GTIMER_PHYS);
173
+static uint64_t gt_sec_pel2_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
166
+ }
174
+{
167
+}
175
+ return gt_tval_read(env, ri, GTIMER_S_EL2_PHYS);
168
+
176
+}
169
static void gt_cntvoff_write(CPUARMState *env, const ARMCPRegInfo *ri,
177
+
170
uint64_t value)
178
+static void gt_sec_pel2_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
179
+ uint64_t value)
180
+{
181
+ gt_tval_write(env, ri, GTIMER_S_EL2_PHYS, value);
182
+}
183
+
184
+static void gt_sec_pel2_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
185
+ uint64_t value)
186
+{
187
+ gt_ctl_write(env, ri, GTIMER_S_EL2_PHYS, value);
188
+}
189
+
190
+static void gt_sec_vel2_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
191
+{
192
+ gt_timer_reset(env, ri, GTIMER_S_EL2_VIRT);
193
+}
194
+
195
+static void gt_sec_vel2_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
196
+ uint64_t value)
197
+{
198
+ gt_cval_write(env, ri, GTIMER_S_EL2_VIRT, value);
199
+}
200
+
201
+static uint64_t gt_sec_vel2_tval_read(CPUARMState *env, const ARMCPRegInfo *ri)
202
+{
203
+ return gt_tval_read(env, ri, GTIMER_S_EL2_VIRT);
204
+}
205
+
206
+static void gt_sec_vel2_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
207
+ uint64_t value)
208
+{
209
+ gt_tval_write(env, ri, GTIMER_S_EL2_VIRT, value);
210
+}
211
+
212
+static void gt_sec_vel2_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
213
+ uint64_t value)
214
+{
215
+ gt_ctl_write(env, ri, GTIMER_S_EL2_VIRT, value);
216
+}
217
+
218
static void gt_hv_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
171
{
219
{
172
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
220
gt_timer_reset(env, ri, GTIMER_HYPVIRT);
173
* reset values as IMPDEF. We choose to reset to 3 to comply with
221
@@ -XXX,XX +XXX,XX @@ void arm_gt_stimer_cb(void *opaque)
174
* both ARMv7 and ARMv8.
222
gt_recalc_timer(cpu, GTIMER_SEC);
175
*/
223
}
176
- .access = PL2_RW, .resetvalue = 3,
224
177
+ .access = PL2_RW, .type = ARM_CP_IO, .resetvalue = 3,
225
+void arm_gt_sel2timer_cb(void *opaque)
178
+ .writefn = gt_cnthctl_write, .raw_writefn = raw_write,
226
+{
179
.fieldoffset = offsetof(CPUARMState, cp15.cnthctl_el2) },
227
+ ARMCPU *cpu = opaque;
180
{ .name = "CNTVOFF_EL2", .state = ARM_CP_STATE_AA64,
228
+
181
.opc0 = 3, .opc1 = 4, .crn = 14, .crm = 0, .opc2 = 3,
229
+ gt_recalc_timer(cpu, GTIMER_S_EL2_PHYS);
182
diff --git a/target/arm/trace-events b/target/arm/trace-events
230
+}
183
index XXXXXXX..XXXXXXX 100644
231
+
184
--- a/target/arm/trace-events
232
+void arm_gt_sel2vtimer_cb(void *opaque)
185
+++ b/target/arm/trace-events
233
+{
186
@@ -XXX,XX +XXX,XX @@
234
+ ARMCPU *cpu = opaque;
187
# See docs/devel/tracing.rst for syntax documentation.
235
+
188
236
+ gt_recalc_timer(cpu, GTIMER_S_EL2_VIRT);
189
# helper.c
237
+}
190
-arm_gt_recalc(int timer, int irqstate, uint64_t nexttick) "gt recalc: timer %d irqstate %d next tick 0x%" PRIx64
238
+
191
-arm_gt_recalc_disabled(int timer) "gt recalc: timer %d irqstate 0 timer disabled"
239
void arm_gt_hvtimer_cb(void *opaque)
192
+arm_gt_recalc(int timer, uint64_t nexttick) "gt recalc: timer %d next tick 0x%" PRIx64
240
{
193
+arm_gt_recalc_disabled(int timer) "gt recalc: timer %d timer disabled"
241
ARMCPU *cpu = opaque;
194
arm_gt_cval_write(int timer, uint64_t value) "gt_cval_write: timer %d value 0x%" PRIx64
242
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_sec_cp_reginfo[] = {
195
arm_gt_tval_write(int timer, uint64_t value) "gt_tval_write: timer %d value 0x%" PRIx64
243
.access = PL2_RW, .accessfn = sel2_access,
196
arm_gt_ctl_write(int timer, uint64_t value) "gt_ctl_write: timer %d value 0x%" PRIx64
244
.nv2_redirect_offset = 0x48,
197
-arm_gt_imask_toggle(int timer, int irqstate) "gt_ctl_write: timer %d IMASK toggle, new irqstate %d"
245
.fieldoffset = offsetof(CPUARMState, cp15.vstcr_el2) },
198
+arm_gt_imask_toggle(int timer) "gt_ctl_write: timer %d IMASK toggle"
246
+#ifndef CONFIG_USER_ONLY
199
arm_gt_cntvoff_write(uint64_t value) "gt_cntvoff_write: value 0x%" PRIx64
247
+ /* Secure EL2 Physical Timer */
200
+arm_gt_update_irq(int timer, int irqstate) "gt_update_irq: timer %d irqstate %d"
248
+ { .name = "CNTHPS_TVAL_EL2", .state = ARM_CP_STATE_AA64,
201
249
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 5, .opc2 = 0,
202
# kvm.c
250
+ .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL2_RW,
203
kvm_arm_fixup_msi_route(uint64_t iova, uint64_t gpa) "MSI iova = 0x%"PRIx64" is translated into 0x%"PRIx64
251
+ .accessfn = gt_sel2timer_access,
252
+ .readfn = gt_sec_pel2_tval_read,
253
+ .writefn = gt_sec_pel2_tval_write,
254
+ .resetfn = gt_sec_pel2_timer_reset,
255
+ },
256
+ { .name = "CNTHPS_CTL_EL2", .state = ARM_CP_STATE_AA64,
257
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 5, .opc2 = 1,
258
+ .type = ARM_CP_IO, .access = PL2_RW,
259
+ .accessfn = gt_sel2timer_access,
260
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_S_EL2_PHYS].ctl),
261
+ .resetvalue = 0,
262
+ .writefn = gt_sec_pel2_ctl_write, .raw_writefn = raw_write,
263
+ },
264
+ { .name = "CNTHPS_CVAL_EL2", .state = ARM_CP_STATE_AA64,
265
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 5, .opc2 = 2,
266
+ .type = ARM_CP_IO, .access = PL2_RW,
267
+ .accessfn = gt_sel2timer_access,
268
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_S_EL2_PHYS].cval),
269
+ .writefn = gt_sec_pel2_cval_write, .raw_writefn = raw_write,
270
+ },
271
+ /* Secure EL2 Virtual Timer */
272
+ { .name = "CNTHVS_TVAL_EL2", .state = ARM_CP_STATE_AA64,
273
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 4, .opc2 = 0,
274
+ .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL2_RW,
275
+ .accessfn = gt_sel2timer_access,
276
+ .readfn = gt_sec_vel2_tval_read,
277
+ .writefn = gt_sec_vel2_tval_write,
278
+ .resetfn = gt_sec_vel2_timer_reset,
279
+ },
280
+ { .name = "CNTHVS_CTL_EL2", .state = ARM_CP_STATE_AA64,
281
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 4, .opc2 = 1,
282
+ .type = ARM_CP_IO, .access = PL2_RW,
283
+ .accessfn = gt_sel2timer_access,
284
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_S_EL2_VIRT].ctl),
285
+ .resetvalue = 0,
286
+ .writefn = gt_sec_vel2_ctl_write, .raw_writefn = raw_write,
287
+ },
288
+ { .name = "CNTHVS_CVAL_EL2", .state = ARM_CP_STATE_AA64,
289
+ .opc0 = 3, .opc1 = 4, .crn = 14, .crm = 4, .opc2 = 2,
290
+ .type = ARM_CP_IO, .access = PL2_RW,
291
+ .accessfn = gt_sel2timer_access,
292
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_S_EL2_VIRT].cval),
293
+ .writefn = gt_sec_vel2_cval_write, .raw_writefn = raw_write,
294
+ },
295
+#endif
296
};
297
298
static CPAccessResult nsacr_access(CPUARMState *env, const ARMCPRegInfo *ri,
204
--
299
--
205
2.34.1
300
2.43.0
301
302
diff view generated by jsdifflib
1
From: Akihiko Odaki <akihiko.odaki@daynix.com>
1
From: Alex Bennée <alex.bennee@linaro.org>
2
2
3
Before this change, the default KVM type, which is used for non-virt
3
As we are about to add more physical and virtual timers let's make it
4
machine models, was 0.
4
clear what each timer does.
5
5
6
The kernel documentation says:
6
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
7
> On arm64, the physical address size for a VM (IPA Size limit) is
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
> limited to 40bits by default. The limit can be configured if the host
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
> supports the extension KVM_CAP_ARM_VM_IPA_SIZE. When supported, use
9
Message-id: 20250204125009.2281315-8-peter.maydell@linaro.org
10
> KVM_VM_TYPE_ARM_IPA_SIZE(IPA_Bits) to set the size in the machine type
10
[PMM: Add timer register name prefix to each comment]
11
> identifier, where IPA_Bits is the maximum width of any physical
12
> address used by the VM. The IPA_Bits is encoded in bits[7-0] of the
13
> machine type identifier.
14
>
15
> e.g, to configure a guest to use 48bit physical address size::
16
>
17
> vm_fd = ioctl(dev_fd, KVM_CREATE_VM, KVM_VM_TYPE_ARM_IPA_SIZE(48));
18
>
19
> The requested size (IPA_Bits) must be:
20
>
21
> == =========================================================
22
> 0 Implies default size, 40bits (for backward compatibility)
23
> N Implies N bits, where N is a positive integer such that,
24
> 32 <= N <= Host_IPA_Limit
25
> == =========================================================
26
27
> Host_IPA_Limit is the maximum possible value for IPA_Bits on the host
28
> and is dependent on the CPU capability and the kernel configuration.
29
> The limit can be retrieved using KVM_CAP_ARM_VM_IPA_SIZE of the
30
> KVM_CHECK_EXTENSION ioctl() at run-time.
31
>
32
> Creation of the VM will fail if the requested IPA size (whether it is
33
> implicit or explicit) is unsupported on the host.
34
https://docs.kernel.org/virt/kvm/api.html#kvm-create-vm
35
36
So if Host_IPA_Limit < 40, specifying 0 as the type will fail. This
37
actually confused libvirt, which uses "none" machine model to probe the
38
KVM availability, on M2 MacBook Air.
39
40
Fix this by using Host_IPA_Limit as the default type when
41
KVM_CAP_ARM_VM_IPA_SIZE is available.
42
43
Cc: qemu-stable@nongnu.org
44
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
45
Message-id: 20230727073134.134102-3-akihiko.odaki@daynix.com
46
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
47
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
48
---
13
---
49
target/arm/kvm.c | 4 +++-
14
target/arm/gtimer.h | 10 +++++-----
50
1 file changed, 3 insertions(+), 1 deletion(-)
15
1 file changed, 5 insertions(+), 5 deletions(-)
51
16
52
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
17
diff --git a/target/arm/gtimer.h b/target/arm/gtimer.h
53
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/kvm.c
19
--- a/target/arm/gtimer.h
55
+++ b/target/arm/kvm.c
20
+++ b/target/arm/gtimer.h
56
@@ -XXX,XX +XXX,XX @@ int kvm_arm_get_max_vm_ipa_size(MachineState *ms, bool *fixed_ipa)
21
@@ -XXX,XX +XXX,XX @@
57
22
#define TARGET_ARM_GTIMER_H
58
int kvm_arch_get_default_type(MachineState *ms)
23
59
{
24
enum {
60
- return 0;
25
- GTIMER_PHYS = 0,
61
+ bool fixed_ipa;
26
- GTIMER_VIRT = 1,
62
+ int size = kvm_arm_get_max_vm_ipa_size(ms, &fixed_ipa);
27
- GTIMER_HYP = 2,
63
+ return fixed_ipa ? 0 : size;
28
- GTIMER_SEC = 3,
64
}
29
- GTIMER_HYPVIRT = 4,
65
30
+ GTIMER_PHYS = 0, /* CNTP_* ; EL1 physical timer */
66
int kvm_arch_init(MachineState *ms, KVMState *s)
31
+ GTIMER_VIRT = 1, /* CNTV_* ; EL1 virtual timer */
32
+ GTIMER_HYP = 2, /* CNTHP_* ; EL2 physical timer */
33
+ GTIMER_SEC = 3, /* CNTPS_* ; EL3 physical timer */
34
+ GTIMER_HYPVIRT = 4, /* CNTHV_* ; EL2 virtual timer ; only if FEAT_VHE */
35
GTIMER_S_EL2_PHYS = 5, /* CNTHPS_* ; only if FEAT_SEL2 */
36
GTIMER_S_EL2_VIRT = 6, /* CNTHVS_* ; only if FEAT_SEL2 */
37
#define NUM_GTIMERS 7
67
--
38
--
68
2.34.1
39
2.43.0
40
41
diff view generated by jsdifflib
1
From: Akihiko Odaki <akihiko.odaki@daynix.com>
1
From: Alex Bennée <alex.bennee@linaro.org>
2
2
3
On MIPS, kvm_arch_get_default_type() returns a negative value when an
3
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
4
error occurred so handle the case. Also, let other machines return
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
negative values when errors occur and declare returning a negative
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
value as the correct way to propagate an error that happened when
6
Message-id: 20250204125009.2281315-9-peter.maydell@linaro.org
7
determining KVM type.
7
Cc: qemu-stable@nongnu.org
8
9
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
10
Message-id: 20230727073134.134102-5-akihiko.odaki@daynix.com
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
14
---
10
---
15
accel/kvm/kvm-all.c | 5 +++++
11
hw/arm/virt.c | 2 ++
16
hw/arm/virt.c | 2 +-
12
1 file changed, 2 insertions(+)
17
hw/ppc/spapr.c | 2 +-
18
3 files changed, 7 insertions(+), 2 deletions(-)
19
13
20
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/accel/kvm/kvm-all.c
23
+++ b/accel/kvm/kvm-all.c
24
@@ -XXX,XX +XXX,XX @@ static int kvm_init(MachineState *ms)
25
type = kvm_arch_get_default_type(ms);
26
}
27
28
+ if (type < 0) {
29
+ ret = -EINVAL;
30
+ goto err;
31
+ }
32
+
33
do {
34
ret = kvm_ioctl(s, KVM_CREATE_VM, type);
35
} while (ret == -EINTR);
36
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
14
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
37
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/arm/virt.c
16
--- a/hw/arm/virt.c
39
+++ b/hw/arm/virt.c
17
+++ b/hw/arm/virt.c
40
@@ -XXX,XX +XXX,XX @@ static int virt_kvm_type(MachineState *ms, const char *type_str)
18
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
41
"require an IPA range (%d bits) larger than "
19
[GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
42
"the one supported by the host (%d bits)",
20
[GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
43
requested_pa_size, max_vm_pa_size);
21
[GTIMER_HYPVIRT] = ARCH_TIMER_NS_EL2_VIRT_IRQ,
44
- exit(1);
22
+ [GTIMER_S_EL2_PHYS] = ARCH_TIMER_S_EL2_IRQ,
45
+ return -1;
23
+ [GTIMER_S_EL2_VIRT] = ARCH_TIMER_S_EL2_VIRT_IRQ,
46
}
24
};
47
/*
25
48
* We return the requested PA log size, unless KVM only supports
26
for (unsigned irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
49
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/ppc/spapr.c
52
+++ b/hw/ppc/spapr.c
53
@@ -XXX,XX +XXX,XX @@ static int spapr_kvm_type(MachineState *machine, const char *vm_type)
54
}
55
56
error_report("Unknown kvm-type specified '%s'", vm_type);
57
- exit(1);
58
+ return -1;
59
}
60
61
/*
62
--
27
--
63
2.34.1
28
2.43.0
64
29
65
30
diff view generated by jsdifflib
1
From: Akihiko Odaki <akihiko.odaki@daynix.com>
1
From: Alex Bennée <alex.bennee@linaro.org>
2
2
3
The returned value was always zero and had no meaning.
3
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
4
5
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
6
Message-id: 20230727073134.134102-7-akihiko.odaki@daynix.com
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Message-id: 20250204125009.2281315-10-peter.maydell@linaro.org
7
Cc: qemu-stable@nongnu.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
9
---
11
accel/kvm/kvm-all.c | 9 ++-------
10
hw/arm/sbsa-ref.c | 2 ++
12
1 file changed, 2 insertions(+), 7 deletions(-)
11
1 file changed, 2 insertions(+)
13
12
14
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
13
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/accel/kvm/kvm-all.c
15
--- a/hw/arm/sbsa-ref.c
17
+++ b/accel/kvm/kvm-all.c
16
+++ b/hw/arm/sbsa-ref.c
18
@@ -XXX,XX +XXX,XX @@ static void *kvm_dirty_ring_reaper_thread(void *data)
17
@@ -XXX,XX +XXX,XX @@ static void create_gic(SBSAMachineState *sms, MemoryRegion *mem)
19
return NULL;
18
[GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
20
}
19
[GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
21
20
[GTIMER_HYPVIRT] = ARCH_TIMER_NS_EL2_VIRT_IRQ,
22
-static int kvm_dirty_ring_reaper_init(KVMState *s)
21
+ [GTIMER_S_EL2_PHYS] = ARCH_TIMER_S_EL2_IRQ,
23
+static void kvm_dirty_ring_reaper_init(KVMState *s)
22
+ [GTIMER_S_EL2_VIRT] = ARCH_TIMER_S_EL2_VIRT_IRQ,
24
{
23
};
25
struct KVMDirtyRingReaper *r = &s->reaper;
24
26
25
for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
27
qemu_thread_create(&r->reaper_thr, "kvm-reaper",
28
kvm_dirty_ring_reaper_thread,
29
s, QEMU_THREAD_JOINABLE);
30
-
31
- return 0;
32
}
33
34
static int kvm_dirty_ring_init(KVMState *s)
35
@@ -XXX,XX +XXX,XX @@ static int kvm_init(MachineState *ms)
36
}
37
38
if (s->kvm_dirty_ring_size) {
39
- ret = kvm_dirty_ring_reaper_init(s);
40
- if (ret) {
41
- goto err;
42
- }
43
+ kvm_dirty_ring_reaper_init(s);
44
}
45
46
if (kvm_check_extension(kvm_state, KVM_CAP_BINARY_STATS_FD)) {
47
--
26
--
48
2.34.1
27
2.43.0
49
28
50
29
diff view generated by jsdifflib
1
In commit 6d2654ffacea813916176 we created the S1Translate struct and
1
Our LDRD implementation is wrong in two respects:
2
used it to plumb through various arguments that we were previously
3
passing one-at-a-time to get_phys_addr_v5(), get_phys_addr_v6(), and
4
get_phys_addr_lpae(). Extend that pattern to get_phys_addr_pmsav5(),
5
get_phys_addr_pmsav7(), get_phys_addr_pmsav8() and
6
get_phys_addr_disabled(), so that all the get_phys_addr_* functions
7
we call from get_phys_addr_nogpc() take the S1Translate struct rather
8
than the mmu_idx and is_secure bool.
9
2
10
(This refactoring is a prelude to having the called functions look
3
* if the address is 4-aligned and the load crosses a page boundary
11
at ptw->is_space rather than using an is_secure boolean.)
4
and the second load faults and the first load was to the
5
base register (as in cases like "ldrd r2, r3, [r2]", then we
6
must not update the base register before taking the fault
7
* if the address is 8-aligned the access must be a 64-bit
8
single-copy atomic access, not two 32-bit accesses
12
9
10
Rewrite the handling of the loads in LDRD to use a single
11
tcg_gen_qemu_ld_i64() and split the result into the destination
12
registers. This allows us to get the atomicity requirements
13
right, and also implicitly means that we won't update the
14
base register too early for the page-crossing case.
15
16
Note that because we no longer increment 'addr' by 4 in the course of
17
performing the LDRD we must change the adjustment value we pass to
18
op_addr_ri_post() and op_addr_rr_post(): it no longer needs to
19
subtract 4 to get the correct value to use if doing base register
20
writeback.
21
22
STRD has the same problem with not getting the atomicity right;
23
we will deal with that in the following commit.
24
25
Cc: qemu-stable@nongnu.org
26
Reported-by: Stu Grossman <stu.grossman@gmail.com>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
28
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20230807141514.19075-5-peter.maydell@linaro.org
29
Message-id: 20250227142746.1698904-2-peter.maydell@linaro.org
16
---
30
---
17
target/arm/ptw.c | 57 ++++++++++++++++++++++++++++++------------------
31
target/arm/tcg/translate.c | 70 +++++++++++++++++++++++++-------------
18
1 file changed, 36 insertions(+), 21 deletions(-)
32
1 file changed, 46 insertions(+), 24 deletions(-)
19
33
20
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
34
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
21
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/ptw.c
36
--- a/target/arm/tcg/translate.c
23
+++ b/target/arm/ptw.c
37
+++ b/target/arm/tcg/translate.c
24
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
38
@@ -XXX,XX +XXX,XX @@ static bool op_store_rr(DisasContext *s, arg_ldst_rr *a,
25
return true;
39
return true;
26
}
40
}
27
41
28
-static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address,
42
+static void do_ldrd_load(DisasContext *s, TCGv_i32 addr, int rt, int rt2)
29
- MMUAccessType access_type, ARMMMUIdx mmu_idx,
43
+{
30
- bool is_secure, GetPhysAddrResult *result,
44
+ /*
31
+static bool get_phys_addr_pmsav5(CPUARMState *env,
45
+ * LDRD is required to be an atomic 64-bit access if the
32
+ S1Translate *ptw,
46
+ * address is 8-aligned, two atomic 32-bit accesses if
33
+ uint32_t address,
47
+ * it's only 4-aligned, and to give an alignment fault
34
+ MMUAccessType access_type,
48
+ * if it's not 4-aligned. This is MO_ALIGN_4 | MO_ATOM_SUBALIGN.
35
+ GetPhysAddrResult *result,
49
+ * Rt is always the word from the lower address, and Rt2 the
36
ARMMMUFaultInfo *fi)
50
+ * data from the higher address, regardless of endianness.
51
+ * So (like gen_load_exclusive) we avoid gen_aa32_ld_i64()
52
+ * so we don't get its SCTLR_B check, and instead do a 64-bit access
53
+ * using MO_BE if appropriate and then split the two halves.
54
+ *
55
+ * For M-profile, and for A-profile before LPAE, the 64-bit
56
+ * atomicity is not required. We could model that using
57
+ * the looser MO_ATOM_IFALIGN_PAIR, but providing a higher
58
+ * level of atomicity than required is harmless (we would not
59
+ * currently generate better code for IFALIGN_PAIR here).
60
+ *
61
+ * This also gives us the correct behaviour of not updating
62
+ * rt if the load of rt2 faults; this is required for cases
63
+ * like "ldrd r2, r3, [r2]" where rt is also the base register.
64
+ */
65
+ int mem_idx = get_mem_index(s);
66
+ MemOp opc = MO_64 | MO_ALIGN_4 | MO_ATOM_SUBALIGN | s->be_data;
67
+ TCGv taddr = gen_aa32_addr(s, addr, opc);
68
+ TCGv_i64 t64 = tcg_temp_new_i64();
69
+ TCGv_i32 tmp = tcg_temp_new_i32();
70
+ TCGv_i32 tmp2 = tcg_temp_new_i32();
71
+
72
+ tcg_gen_qemu_ld_i64(t64, taddr, mem_idx, opc);
73
+ if (s->be_data == MO_BE) {
74
+ tcg_gen_extr_i64_i32(tmp2, tmp, t64);
75
+ } else {
76
+ tcg_gen_extr_i64_i32(tmp, tmp2, t64);
77
+ }
78
+ store_reg(s, rt, tmp);
79
+ store_reg(s, rt2, tmp2);
80
+}
81
+
82
static bool trans_LDRD_rr(DisasContext *s, arg_ldst_rr *a)
37
{
83
{
38
int n;
84
- int mem_idx = get_mem_index(s);
39
uint32_t mask;
85
- TCGv_i32 addr, tmp;
40
uint32_t base;
86
+ TCGv_i32 addr;
41
+ ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
87
42
bool is_user = regime_is_user(env, mmu_idx);
88
if (!ENABLE_ARCH_5TE) {
43
+ bool is_secure = arm_space_is_secure(ptw->in_space);
89
return false;
44
90
@@ -XXX,XX +XXX,XX @@ static bool trans_LDRD_rr(DisasContext *s, arg_ldst_rr *a)
45
if (regime_translation_disabled(env, mmu_idx, is_secure)) {
91
}
46
/* MPU disabled. */
92
addr = op_addr_rr_pre(s, a);
47
@@ -XXX,XX +XXX,XX @@ static bool pmsav7_use_background_region(ARMCPU *cpu, ARMMMUIdx mmu_idx,
93
48
return regime_sctlr(env, mmu_idx) & SCTLR_BR;
94
- tmp = tcg_temp_new_i32();
95
- gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
96
- store_reg(s, a->rt, tmp);
97
-
98
- tcg_gen_addi_i32(addr, addr, 4);
99
-
100
- tmp = tcg_temp_new_i32();
101
- gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
102
- store_reg(s, a->rt + 1, tmp);
103
+ do_ldrd_load(s, addr, a->rt, a->rt + 1);
104
105
/* LDRD w/ base writeback is undefined if the registers overlap. */
106
- op_addr_rr_post(s, a, addr, -4);
107
+ op_addr_rr_post(s, a, addr, 0);
108
return true;
49
}
109
}
50
110
51
-static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
111
@@ -XXX,XX +XXX,XX @@ static bool op_store_ri(DisasContext *s, arg_ldst_ri *a,
52
- MMUAccessType access_type, ARMMMUIdx mmu_idx,
112
53
- bool secure, GetPhysAddrResult *result,
113
static bool op_ldrd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
54
+static bool get_phys_addr_pmsav7(CPUARMState *env,
55
+ S1Translate *ptw,
56
+ uint32_t address,
57
+ MMUAccessType access_type,
58
+ GetPhysAddrResult *result,
59
ARMMMUFaultInfo *fi)
60
{
114
{
61
ARMCPU *cpu = env_archcpu(env);
115
- int mem_idx = get_mem_index(s);
62
int n;
116
- TCGv_i32 addr, tmp;
63
+ ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
117
+ TCGv_i32 addr;
64
bool is_user = regime_is_user(env, mmu_idx);
118
65
+ bool secure = arm_space_is_secure(ptw->in_space);
119
addr = op_addr_ri_pre(s, a);
66
120
67
result->f.phys_addr = address;
121
- tmp = tcg_temp_new_i32();
68
result->f.lg_page_size = TARGET_PAGE_BITS;
122
- gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
69
@@ -XXX,XX +XXX,XX @@ void v8m_security_lookup(CPUARMState *env, uint32_t address,
123
- store_reg(s, a->rt, tmp);
70
}
124
-
125
- tcg_gen_addi_i32(addr, addr, 4);
126
-
127
- tmp = tcg_temp_new_i32();
128
- gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
129
- store_reg(s, rt2, tmp);
130
+ do_ldrd_load(s, addr, a->rt, rt2);
131
132
/* LDRD w/ base writeback is undefined if the registers overlap. */
133
- op_addr_ri_post(s, a, addr, -4);
134
+ op_addr_ri_post(s, a, addr, 0);
135
return true;
71
}
136
}
72
137
73
-static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address,
74
- MMUAccessType access_type, ARMMMUIdx mmu_idx,
75
- bool secure, GetPhysAddrResult *result,
76
+static bool get_phys_addr_pmsav8(CPUARMState *env,
77
+ S1Translate *ptw,
78
+ uint32_t address,
79
+ MMUAccessType access_type,
80
+ GetPhysAddrResult *result,
81
ARMMMUFaultInfo *fi)
82
{
83
V8M_SAttributes sattrs = {};
84
+ ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
85
+ bool secure = arm_space_is_secure(ptw->in_space);
86
bool ret;
87
88
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
89
@@ -XXX,XX +XXX,XX @@ static ARMCacheAttrs combine_cacheattrs(uint64_t hcr,
90
* MMU disabled. S1 addresses within aa64 translation regimes are
91
* still checked for bounds -- see AArch64.S1DisabledOutput().
92
*/
93
-static bool get_phys_addr_disabled(CPUARMState *env, target_ulong address,
94
+static bool get_phys_addr_disabled(CPUARMState *env,
95
+ S1Translate *ptw,
96
+ target_ulong address,
97
MMUAccessType access_type,
98
- ARMMMUIdx mmu_idx, bool is_secure,
99
GetPhysAddrResult *result,
100
ARMMMUFaultInfo *fi)
101
{
102
+ ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
103
+ bool is_secure = arm_space_is_secure(ptw->in_space);
104
uint8_t memattr = 0x00; /* Device nGnRnE */
105
uint8_t shareability = 0; /* non-shareable */
106
int r_el;
107
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw,
108
case ARMMMUIdx_Phys_Root:
109
case ARMMMUIdx_Phys_Realm:
110
/* Checking Phys early avoids special casing later vs regime_el. */
111
- return get_phys_addr_disabled(env, address, access_type, mmu_idx,
112
- is_secure, result, fi);
113
+ return get_phys_addr_disabled(env, ptw, address, access_type,
114
+ result, fi);
115
116
case ARMMMUIdx_Stage1_E0:
117
case ARMMMUIdx_Stage1_E1:
118
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw,
119
120
if (arm_feature(env, ARM_FEATURE_V8)) {
121
/* PMSAv8 */
122
- ret = get_phys_addr_pmsav8(env, address, access_type, mmu_idx,
123
- is_secure, result, fi);
124
+ ret = get_phys_addr_pmsav8(env, ptw, address, access_type,
125
+ result, fi);
126
} else if (arm_feature(env, ARM_FEATURE_V7)) {
127
/* PMSAv7 */
128
- ret = get_phys_addr_pmsav7(env, address, access_type, mmu_idx,
129
- is_secure, result, fi);
130
+ ret = get_phys_addr_pmsav7(env, ptw, address, access_type,
131
+ result, fi);
132
} else {
133
/* Pre-v7 MPU */
134
- ret = get_phys_addr_pmsav5(env, address, access_type, mmu_idx,
135
- is_secure, result, fi);
136
+ ret = get_phys_addr_pmsav5(env, ptw, address, access_type,
137
+ result, fi);
138
}
139
qemu_log_mask(CPU_LOG_MMU, "PMSA MPU lookup for %s at 0x%08" PRIx32
140
" mmu_idx %u -> %s (prot %c%c%c)\n",
141
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw,
142
/* Definitely a real MMU, not an MPU */
143
144
if (regime_translation_disabled(env, mmu_idx, is_secure)) {
145
- return get_phys_addr_disabled(env, address, access_type, mmu_idx,
146
- is_secure, result, fi);
147
+ return get_phys_addr_disabled(env, ptw, address, access_type,
148
+ result, fi);
149
}
150
151
if (regime_using_lpae_format(env, mmu_idx)) {
152
--
138
--
153
2.34.1
139
2.43.0
diff view generated by jsdifflib
1
The s1ns bit in ARMMMUFaultInfo is documented as "true if
1
Our STRD implementation doesn't correctly implement the requirement:
2
we faulted on a non-secure IPA while in secure state". Both the
2
* if the address is 8-aligned the access must be a 64-bit
3
places which look at this bit only do so after having confirmed
3
single-copy atomic access, not two 32-bit accesses
4
that this is a stage 2 fault and we're dealing with Secure EL2,
5
which leaves the ptw.c code free to set the bit to any random
6
value in the other cases.
7
4
8
Instead of taking advantage of that freedom, consistently
5
Rewrite the handling of STRD to use a single tcg_gen_qemu_st_i64()
9
make the bit be set to false for the "not a stage 2 fault
6
of a value produced by concatenating the two 32 bit source registers.
10
for Secure EL2" cases. This removes some cases where we
7
This allows us to get the atomicity right.
11
were using an 'is_secure' boolean and leaving the reader
12
guessing about whether that was the right thing for Realm
13
and Root cases.
14
8
9
As with the LDRD change, now that we don't update 'addr' in the
10
course of performing the store we need to adjust the offset
11
we pass to op_addr_ri_post() and op_addr_rr_post().
12
13
Cc: qemu-stable@nongnu.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20230807141514.19075-4-peter.maydell@linaro.org
16
Message-id: 20250227142746.1698904-3-peter.maydell@linaro.org
18
---
17
---
19
target/arm/ptw.c | 19 +++++++++++++++----
18
target/arm/tcg/translate.c | 59 +++++++++++++++++++++++++-------------
20
1 file changed, 15 insertions(+), 4 deletions(-)
19
1 file changed, 39 insertions(+), 20 deletions(-)
21
20
22
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
21
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
23
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/ptw.c
23
--- a/target/arm/tcg/translate.c
25
+++ b/target/arm/ptw.c
24
+++ b/target/arm/tcg/translate.c
26
@@ -XXX,XX +XXX,XX @@ static ARMSecuritySpace S2_security_space(ARMSecuritySpace s1_space,
25
@@ -XXX,XX +XXX,XX @@ static bool trans_LDRD_rr(DisasContext *s, arg_ldst_rr *a)
27
}
26
return true;
28
}
27
}
29
28
30
+static bool fault_s1ns(ARMSecuritySpace space, ARMMMUIdx s2_mmu_idx)
29
+static void do_strd_store(DisasContext *s, TCGv_i32 addr, int rt, int rt2)
31
+{
30
+{
32
+ /*
31
+ /*
33
+ * For stage 2 faults in Secure EL22, S1NS indicates
32
+ * STRD is required to be an atomic 64-bit access if the
34
+ * whether the faulting IPA is in the Secure or NonSecure
33
+ * address is 8-aligned, two atomic 32-bit accesses if
35
+ * IPA space. For all other kinds of fault, it is false.
34
+ * it's only 4-aligned, and to give an alignment fault
35
+ * if it's not 4-aligned.
36
+ * Rt is always the word from the lower address, and Rt2 the
37
+ * data from the higher address, regardless of endianness.
38
+ * So (like gen_store_exclusive) we avoid gen_aa32_ld_i64()
39
+ * so we don't get its SCTLR_B check, and instead do a 64-bit access
40
+ * using MO_BE if appropriate, using a value constructed
41
+ * by putting the two halves together in the right order.
42
+ *
43
+ * As with LDRD, the 64-bit atomicity is not required for
44
+ * M-profile, or for A-profile before LPAE, and we provide
45
+ * the higher guarantee always for simplicity.
36
+ */
46
+ */
37
+ return space == ARMSS_Secure && regime_is_stage2(s2_mmu_idx)
47
+ int mem_idx = get_mem_index(s);
38
+ && s2_mmu_idx == ARMMMUIdx_Stage2_S;
48
+ MemOp opc = MO_64 | MO_ALIGN_4 | MO_ATOM_SUBALIGN | s->be_data;
49
+ TCGv taddr = gen_aa32_addr(s, addr, opc);
50
+ TCGv_i32 t1 = load_reg(s, rt);
51
+ TCGv_i32 t2 = load_reg(s, rt2);
52
+ TCGv_i64 t64 = tcg_temp_new_i64();
53
+
54
+ if (s->be_data == MO_BE) {
55
+ tcg_gen_concat_i32_i64(t64, t2, t1);
56
+ } else {
57
+ tcg_gen_concat_i32_i64(t64, t1, t2);
58
+ }
59
+ tcg_gen_qemu_st_i64(t64, taddr, mem_idx, opc);
39
+}
60
+}
40
+
61
+
41
/* Translate a S1 pagetable walk through S2 if needed. */
62
static bool trans_STRD_rr(DisasContext *s, arg_ldst_rr *a)
42
static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
63
{
43
hwaddr addr, ARMMMUFaultInfo *fi)
64
- int mem_idx = get_mem_index(s);
44
@@ -XXX,XX +XXX,XX @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
65
- TCGv_i32 addr, tmp;
45
fi->s2addr = addr;
66
+ TCGv_i32 addr;
46
fi->stage2 = true;
67
47
fi->s1ptw = true;
68
if (!ENABLE_ARCH_5TE) {
48
- fi->s1ns = !is_secure;
69
return false;
49
+ fi->s1ns = fault_s1ns(ptw->in_space, s2_mmu_idx);
70
@@ -XXX,XX +XXX,XX @@ static bool trans_STRD_rr(DisasContext *s, arg_ldst_rr *a)
50
return false;
51
}
52
}
71
}
53
@@ -XXX,XX +XXX,XX @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
72
addr = op_addr_rr_pre(s, a);
54
fi->s2addr = addr;
73
55
fi->stage2 = regime_is_stage2(s2_mmu_idx);
74
- tmp = load_reg(s, a->rt);
56
fi->s1ptw = fi->stage2;
75
- gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
57
- fi->s1ns = !is_secure;
76
+ do_strd_store(s, addr, a->rt, a->rt + 1);
58
+ fi->s1ns = fault_s1ns(ptw->in_space, s2_mmu_idx);
77
59
return false;
78
- tcg_gen_addi_i32(addr, addr, 4);
60
}
79
-
61
80
- tmp = load_reg(s, a->rt + 1);
62
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_casq_ptw(CPUARMState *env, uint64_t old_val,
81
- gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
63
fi->s2addr = ptw->out_virt;
82
-
64
fi->stage2 = true;
83
- op_addr_rr_post(s, a, addr, -4);
65
fi->s1ptw = true;
84
+ op_addr_rr_post(s, a, addr, 0);
66
- fi->s1ns = !ptw->in_secure;
67
+ fi->s1ns = fault_s1ns(ptw->in_space, ptw->in_ptw_idx);
68
return 0;
69
}
70
71
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
72
fi->level = level;
73
/* Tag the error as S2 for failed S1 PTW at S2 or ordinary S2. */
74
fi->stage2 = fi->s1ptw || regime_is_stage2(mmu_idx);
75
- fi->s1ns = mmu_idx == ARMMMUIdx_Stage2;
76
+ fi->s1ns = fault_s1ns(ptw->in_space, mmu_idx);
77
return true;
85
return true;
78
}
86
}
79
87
88
@@ -XXX,XX +XXX,XX @@ static bool trans_LDRD_ri_t32(DisasContext *s, arg_ldst_ri2 *a)
89
90
static bool op_strd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
91
{
92
- int mem_idx = get_mem_index(s);
93
- TCGv_i32 addr, tmp;
94
+ TCGv_i32 addr;
95
96
addr = op_addr_ri_pre(s, a);
97
98
- tmp = load_reg(s, a->rt);
99
- gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
100
+ do_strd_store(s, addr, a->rt, rt2);
101
102
- tcg_gen_addi_i32(addr, addr, 4);
103
-
104
- tmp = load_reg(s, rt2);
105
- gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | MO_ALIGN);
106
-
107
- op_addr_ri_post(s, a, addr, -4);
108
+ op_addr_ri_post(s, a, addr, 0);
109
return true;
110
}
111
80
--
112
--
81
2.34.1
113
2.43.0
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
All the callers of op_addr_rr_post() and op_addr_ri_post() now pass in
2
zero for the address_offset, so we can remove that argument.
2
3
3
Typo applied byte-wise shift instead of double-word shift.
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Cc: qemu-stable@nongnu.org
6
Fixes: 631e565450c ("target/arm: Create gen_gvec_[us]sra")
7
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1737
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Message-id: 20230821022025.397682-1-richard.henderson@linaro.org
7
Message-id: 20250227142746.1698904-4-peter.maydell@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
8
---
13
target/arm/tcg/translate.c | 2 +-
9
target/arm/tcg/translate.c | 26 +++++++++++++-------------
14
1 file changed, 1 insertion(+), 1 deletion(-)
10
1 file changed, 13 insertions(+), 13 deletions(-)
15
11
16
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
12
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/tcg/translate.c
14
--- a/target/arm/tcg/translate.c
19
+++ b/target/arm/tcg/translate.c
15
+++ b/target/arm/tcg/translate.c
20
@@ -XXX,XX +XXX,XX @@ void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
16
@@ -XXX,XX +XXX,XX @@ static TCGv_i32 op_addr_rr_pre(DisasContext *s, arg_ldst_rr *a)
21
.vece = MO_32 },
17
}
22
{ .fni8 = gen_ssra64_i64,
18
23
.fniv = gen_ssra_vec,
19
static void op_addr_rr_post(DisasContext *s, arg_ldst_rr *a,
24
- .fno = gen_helper_gvec_ssra_b,
20
- TCGv_i32 addr, int address_offset)
25
+ .fno = gen_helper_gvec_ssra_d,
21
+ TCGv_i32 addr)
26
.prefer_i64 = TCG_TARGET_REG_BITS == 64,
22
{
27
.opt_opc = vecop_list,
23
if (!a->p) {
28
.load_dest = true,
24
TCGv_i32 ofs = load_reg(s, a->rm);
25
@@ -XXX,XX +XXX,XX @@ static void op_addr_rr_post(DisasContext *s, arg_ldst_rr *a,
26
} else if (!a->w) {
27
return;
28
}
29
- tcg_gen_addi_i32(addr, addr, address_offset);
30
store_reg(s, a->rn, addr);
31
}
32
33
@@ -XXX,XX +XXX,XX @@ static bool op_load_rr(DisasContext *s, arg_ldst_rr *a,
34
* Perform base writeback before the loaded value to
35
* ensure correct behavior with overlapping index registers.
36
*/
37
- op_addr_rr_post(s, a, addr, 0);
38
+ op_addr_rr_post(s, a, addr);
39
store_reg_from_load(s, a->rt, tmp);
40
return true;
41
}
42
@@ -XXX,XX +XXX,XX @@ static bool op_store_rr(DisasContext *s, arg_ldst_rr *a,
43
gen_aa32_st_i32(s, tmp, addr, mem_idx, mop);
44
disas_set_da_iss(s, mop, issinfo);
45
46
- op_addr_rr_post(s, a, addr, 0);
47
+ op_addr_rr_post(s, a, addr);
48
return true;
49
}
50
51
@@ -XXX,XX +XXX,XX @@ static bool trans_LDRD_rr(DisasContext *s, arg_ldst_rr *a)
52
do_ldrd_load(s, addr, a->rt, a->rt + 1);
53
54
/* LDRD w/ base writeback is undefined if the registers overlap. */
55
- op_addr_rr_post(s, a, addr, 0);
56
+ op_addr_rr_post(s, a, addr);
57
return true;
58
}
59
60
@@ -XXX,XX +XXX,XX @@ static bool trans_STRD_rr(DisasContext *s, arg_ldst_rr *a)
61
62
do_strd_store(s, addr, a->rt, a->rt + 1);
63
64
- op_addr_rr_post(s, a, addr, 0);
65
+ op_addr_rr_post(s, a, addr);
66
return true;
67
}
68
69
@@ -XXX,XX +XXX,XX @@ static TCGv_i32 op_addr_ri_pre(DisasContext *s, arg_ldst_ri *a)
70
}
71
72
static void op_addr_ri_post(DisasContext *s, arg_ldst_ri *a,
73
- TCGv_i32 addr, int address_offset)
74
+ TCGv_i32 addr)
75
{
76
+ int address_offset = 0;
77
if (!a->p) {
78
if (a->u) {
79
- address_offset += a->imm;
80
+ address_offset = a->imm;
81
} else {
82
- address_offset -= a->imm;
83
+ address_offset = -a->imm;
84
}
85
} else if (!a->w) {
86
return;
87
@@ -XXX,XX +XXX,XX @@ static bool op_load_ri(DisasContext *s, arg_ldst_ri *a,
88
* Perform base writeback before the loaded value to
89
* ensure correct behavior with overlapping index registers.
90
*/
91
- op_addr_ri_post(s, a, addr, 0);
92
+ op_addr_ri_post(s, a, addr);
93
store_reg_from_load(s, a->rt, tmp);
94
return true;
95
}
96
@@ -XXX,XX +XXX,XX @@ static bool op_store_ri(DisasContext *s, arg_ldst_ri *a,
97
gen_aa32_st_i32(s, tmp, addr, mem_idx, mop);
98
disas_set_da_iss(s, mop, issinfo);
99
100
- op_addr_ri_post(s, a, addr, 0);
101
+ op_addr_ri_post(s, a, addr);
102
return true;
103
}
104
105
@@ -XXX,XX +XXX,XX @@ static bool op_ldrd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
106
do_ldrd_load(s, addr, a->rt, rt2);
107
108
/* LDRD w/ base writeback is undefined if the registers overlap. */
109
- op_addr_ri_post(s, a, addr, 0);
110
+ op_addr_ri_post(s, a, addr);
111
return true;
112
}
113
114
@@ -XXX,XX +XXX,XX @@ static bool op_strd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
115
116
do_strd_store(s, addr, a->rt, rt2);
117
118
- op_addr_ri_post(s, a, addr, 0);
119
+ op_addr_ri_post(s, a, addr);
120
return true;
121
}
122
29
--
123
--
30
2.34.1
124
2.43.0
31
125
32
126
diff view generated by jsdifflib
1
When we report faults due to stage 2 faults during a stage 1
1
In debug_helper.c we provide a few dummy versions of
2
page table walk, the 'level' parameter should be the level
2
debug registers:
3
of the walk in stage 2 that faulted, not the level of the
3
* DBGVCR (AArch32 only): enable bits for vector-catch
4
walk in stage 1. Correct the reporting of these faults.
4
debug events
5
* MDCCINT_EL1: interrupt enable bits for the DCC
6
debug communications channel
7
* DBGVCR32_EL2: the AArch64 accessor for the state in
8
DBGVCR
5
9
10
We implemented these only to stop Linux crashing on startup,
11
but we chose to implement them as ARM_CP_NOP. This worked
12
for Linux where it only cares about trying to write to these
13
registers, but is very confusing behaviour for anything that
14
wants to read the registers (perhaps for context state switches),
15
because the destination register will be left with whatever
16
random value it happened to have before the read.
17
18
Model these registers instead as RAZ.
19
20
Fixes: 5e8b12ffbb8c68 ("target-arm: Implement minimal DBGVCR, OSDLR_EL1, MDCCSR_EL0")
21
Fixes: 5dbdc4342f479d ("target-arm: Implement dummy MDCCINT_EL1")
22
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2708
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230807141514.19075-15-peter.maydell@linaro.org
25
Message-id: 20250228162424.1917269-1-peter.maydell@linaro.org
9
---
26
---
10
target/arm/ptw.c | 10 +++++++---
27
target/arm/debug_helper.c | 7 ++++---
11
1 file changed, 7 insertions(+), 3 deletions(-)
28
1 file changed, 4 insertions(+), 3 deletions(-)
12
29
13
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
30
diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c
14
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/ptw.c
32
--- a/target/arm/debug_helper.c
16
+++ b/target/arm/ptw.c
33
+++ b/target/arm/debug_helper.c
17
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
34
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
18
do_translation_fault:
35
{ .name = "DBGVCR",
19
fi->type = ARMFault_Translation;
36
.cp = 14, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0,
20
do_fault:
37
.access = PL1_RW, .accessfn = access_tda,
21
- fi->level = level;
38
- .type = ARM_CP_NOP },
22
- /* Tag the error as S2 for failed S1 PTW at S2 or ordinary S2. */
39
+ .type = ARM_CP_CONST, .resetvalue = 0 },
23
- fi->stage2 = fi->s1ptw || regime_is_stage2(mmu_idx);
40
/*
24
+ if (fi->s1ptw) {
41
* Dummy MDCCINT_EL1, since we don't implement the Debug Communications
25
+ /* Retain the existing stage 2 fi->level */
42
* Channel but Linux may try to access this register. The 32-bit
26
+ assert(fi->stage2);
43
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
27
+ } else {
44
{ .name = "MDCCINT_EL1", .state = ARM_CP_STATE_BOTH,
28
+ fi->level = level;
45
.cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0,
29
+ fi->stage2 = regime_is_stage2(mmu_idx);
46
.access = PL1_RW, .accessfn = access_tdcc,
30
+ }
47
- .type = ARM_CP_NOP },
31
fi->s1ns = fault_s1ns(ptw->in_space, mmu_idx);
48
+ .type = ARM_CP_CONST, .resetvalue = 0 },
32
return true;
49
/*
33
}
50
* Dummy DBGCLAIM registers.
51
* "The architecture does not define any functionality for the CLAIM tag bits.",
52
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo debug_aa32_el1_reginfo[] = {
53
{ .name = "DBGVCR32_EL2", .state = ARM_CP_STATE_AA64,
54
.opc0 = 2, .opc1 = 4, .crn = 0, .crm = 7, .opc2 = 0,
55
.access = PL2_RW, .accessfn = access_dbgvcr32,
56
- .type = ARM_CP_NOP | ARM_CP_EL3_NO_EL2_KEEP },
57
+ .type = ARM_CP_CONST | ARM_CP_EL3_NO_EL2_KEEP,
58
+ .resetvalue = 0 },
59
};
60
61
static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
34
--
62
--
35
2.34.1
63
2.43.0
diff view generated by jsdifflib
1
From: Akihiko Odaki <akihiko.odaki@daynix.com>
1
Currently we call icount_start_warp_timer() from timerlist_rearm().
2
This produces incorrect behaviour, because timerlist_rearm() is
3
called, for instance, when a timer callback modifies its timer. We
4
cannot decide here to warp the timer forwards to the next timer
5
deadline merely because all_cpu_threads_idle() is true, because the
6
timer callback we were called from (or some other callback later in
7
the list of callbacks being invoked) may be about to raise a CPU
8
interrupt and move a CPU from idle to ready.
2
9
3
On MIPS, QEMU requires KVM_VM_MIPS_VZ type for KVM. Report an error in
10
The only valid place to choose to warp the timer forward is from the
4
such a case as other architectures do when an error occurred during KVM
11
main loop, when we know we have no outstanding IO or timer callbacks
5
type decision.
12
that might be about to wake up a CPU.
6
13
7
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
14
For Arm guests, this bug was mostly latent until the refactoring
8
Message-id: 20230727073134.134102-4-akihiko.odaki@daynix.com
15
commit f6fc36deef6abc ("target/arm/helper: Implement
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
CNTHCTL_EL2.CNT[VP]MASK"), which exposed it because it refactored a
17
timer callback so that it happened to call timer_mod() first and
18
raise the interrupt second, when it had previously raised the
19
interrupt first and called timer_mod() afterwards.
20
21
This call seems to have originally derived from the
22
pre-record-and-replay icount code, which (as of e.g. commit
23
db1a49726c3c in 2010) in this location did a call to
24
qemu_notify_event(), necessary to get the icount code in the vCPU
25
round-robin thread to stop and recalculate the icount deadline when a
26
timer was reprogrammed from the IO thread. In current QEMU,
27
everything is done on the vCPU thread when we are in icount mode, so
28
there's no need to try to notify another thread here.
29
30
I suspect that the other reason why this call was doing icount timer
31
warping is that it pre-dates commit efab87cf79077a from 2015, which
32
added a call to icount_start_warp_timer() to main_loop_wait(). Once
33
the call in timerlist_rearm() has been removed, if the timer
34
callbacks don't cause any CPU to be woken up then we will end up
35
calling icount_start_warp_timer() from main_loop_wait() when the rr
36
main loop code calls rr_wait_io_event().
37
38
Remove the incorrect call from timerlist_rearm().
39
40
Cc: qemu-stable@nongnu.org
41
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2703
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
42
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
43
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
44
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
45
Tested-by: Alex Bennée <alex.bennee@linaro.org>
46
Message-id: 20250210135804.3526943-1-peter.maydell@linaro.org
12
---
47
---
13
target/mips/kvm.c | 1 +
48
util/qemu-timer.c | 4 ----
14
1 file changed, 1 insertion(+)
49
1 file changed, 4 deletions(-)
15
50
16
diff --git a/target/mips/kvm.c b/target/mips/kvm.c
51
diff --git a/util/qemu-timer.c b/util/qemu-timer.c
17
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
18
--- a/target/mips/kvm.c
53
--- a/util/qemu-timer.c
19
+++ b/target/mips/kvm.c
54
+++ b/util/qemu-timer.c
20
@@ -XXX,XX +XXX,XX @@ int kvm_arch_get_default_type(MachineState *machine)
55
@@ -XXX,XX +XXX,XX @@ static bool timer_mod_ns_locked(QEMUTimerList *timer_list,
21
}
56
22
#endif
57
static void timerlist_rearm(QEMUTimerList *timer_list)
23
58
{
24
+ error_report("KVM_VM_MIPS_VZ type is not available");
59
- /* Interrupt execution to force deadline recalculation. */
25
return -1;
60
- if (icount_enabled() && timer_list->clock->type == QEMU_CLOCK_VIRTUAL) {
61
- icount_start_warp_timer();
62
- }
63
timerlist_notify(timer_list);
26
}
64
}
27
65
28
--
66
--
29
2.34.1
67
2.43.0
30
68
31
69
diff view generated by jsdifflib
1
When the MMU is disabled, data accesses should be Device nGnRnE,
1
Expand the example in the comment documenting MO_ATOM_SUBALIGN,
2
Outer Shareable, Untagged. We handle the other cases from
2
to be clearer about the atomicity guarantees it represents.
3
AArch64.S1DisabledOutput() correctly but missed this one.
4
Device nGnRnE is memattr == 0, so the only part we were missing
5
was that shareability should be set to 2 for both insn fetches
6
and data accesses.
7
3
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20230807141514.19075-13-peter.maydell@linaro.org
6
Message-id: 20250228103222.1838913-1-peter.maydell@linaro.org
11
---
7
---
12
target/arm/ptw.c | 12 +++++++-----
8
include/exec/memop.h | 8 ++++++--
13
1 file changed, 7 insertions(+), 5 deletions(-)
9
1 file changed, 6 insertions(+), 2 deletions(-)
14
10
15
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
11
diff --git a/include/exec/memop.h b/include/exec/memop.h
16
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/ptw.c
13
--- a/include/exec/memop.h
18
+++ b/target/arm/ptw.c
14
+++ b/include/exec/memop.h
19
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_disabled(CPUARMState *env,
15
@@ -XXX,XX +XXX,XX @@ typedef enum MemOp {
20
}
16
* Depending on alignment, one or both will be single-copy atomic.
21
}
17
* This is the atomicity e.g. of Arm FEAT_LSE2 LDP.
22
}
18
* MO_ATOM_SUBALIGN: the operation is single-copy atomic by parts
23
- if (memattr == 0 && access_type == MMU_INST_FETCH) {
19
- * by the alignment. E.g. if the address is 0 mod 4, then each
24
- if (regime_sctlr(env, mmu_idx) & SCTLR_I) {
20
- * 4-byte subobject is single-copy atomic.
25
- memattr = 0xee; /* Normal, WT, RA, NT */
21
+ * by the alignment. E.g. if an 8-byte value is accessed at an
26
- } else {
22
+ * address which is 0 mod 8, then the whole 8-byte access is
27
- memattr = 0x44; /* Normal, NC, No */
23
+ * single-copy atomic; otherwise, if it is accessed at 0 mod 4
28
+ if (memattr == 0) {
24
+ * then each 4-byte subobject is single-copy atomic; otherwise
29
+ if (access_type == MMU_INST_FETCH) {
25
+ * if it is accessed at 0 mod 2 then the four 2-byte subobjects
30
+ if (regime_sctlr(env, mmu_idx) & SCTLR_I) {
26
+ * are single-copy atomic.
31
+ memattr = 0xee; /* Normal, WT, RA, NT */
27
* This is the atomicity e.g. of IBM Power.
32
+ } else {
28
* MO_ATOM_NONE: the operation has no atomicity requirements.
33
+ memattr = 0x44; /* Normal, NC, No */
29
*
34
+ }
35
}
36
shareability = 2; /* outer shareable */
37
}
38
--
30
--
39
2.34.1
31
2.43.0
diff view generated by jsdifflib
1
From: Jean-Philippe Brucker <jean-philippe@linaro.org>
1
From: JianChunfu <jansef.jian@hj-micro.com>
2
2
3
When HCR_EL2.E2H is enabled, TLB entries are formed using the EL2&0
3
Use a similar terminology smmu_hash_remove_by_sid_range() as the one
4
translation regime, instead of the EL2 translation regime. The TLB VAE2*
4
being used for other hash table matching functions since
5
instructions invalidate the regime that corresponds to the current value
5
smmuv3_invalidate_ste() name is not self explanatory, and introduce a
6
of HCR_EL2.E2H.
6
helper that invokes the g_hash_table_foreach_remove.
7
7
8
At the moment we only invalidate the EL2 translation regime. This causes
8
No functional change intended.
9
problems with RMM, which issues TLBI VAE2IS instructions with
10
HCR_EL2.E2H enabled. Update vae2_tlbmask() to take HCR_EL2.E2H into
11
account.
12
9
13
Add vae2_tlbbits() as well, since the top-byte-ignore configuration is
10
Signed-off-by: JianChunfu <jansef.jian@hj-micro.com>
14
different between the EL2&0 and EL2 regime.
11
Reviewed-by: Eric Auger <eric.auger@redhat.com>
15
12
Message-id: 20250228031438.3916-1-jansef.jian@hj-micro.com
16
Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Message-id: 20230809123706.1842548-3-jean-philippe@linaro.org
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
14
---
21
target/arm/helper.c | 50 ++++++++++++++++++++++++++++++++++++---------
15
hw/arm/smmu-internal.h | 5 -----
22
1 file changed, 40 insertions(+), 10 deletions(-)
16
include/hw/arm/smmu-common.h | 6 ++++++
17
hw/arm/smmu-common.c | 21 +++++++++++++++++++++
18
hw/arm/smmuv3.c | 19 ++-----------------
19
hw/arm/trace-events | 3 ++-
20
5 files changed, 31 insertions(+), 23 deletions(-)
23
21
24
diff --git a/target/arm/helper.c b/target/arm/helper.c
22
diff --git a/hw/arm/smmu-internal.h b/hw/arm/smmu-internal.h
25
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/helper.c
24
--- a/hw/arm/smmu-internal.h
27
+++ b/target/arm/helper.c
25
+++ b/hw/arm/smmu-internal.h
28
@@ -XXX,XX +XXX,XX @@ static int vae1_tlbmask(CPUARMState *env)
26
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUIOTLBPageInvInfo {
29
return mask;
27
uint64_t mask;
28
} SMMUIOTLBPageInvInfo;
29
30
-typedef struct SMMUSIDRange {
31
- uint32_t start;
32
- uint32_t end;
33
-} SMMUSIDRange;
34
-
35
#endif
36
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/hw/arm/smmu-common.h
39
+++ b/include/hw/arm/smmu-common.h
40
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUIOTLBKey {
41
uint8_t level;
42
} SMMUIOTLBKey;
43
44
+typedef struct SMMUSIDRange {
45
+ uint32_t start;
46
+ uint32_t end;
47
+} SMMUSIDRange;
48
+
49
struct SMMUState {
50
/* <private> */
51
SysBusDevice dev;
52
@@ -XXX,XX +XXX,XX @@ void smmu_iotlb_inv_iova(SMMUState *s, int asid, int vmid, dma_addr_t iova,
53
uint8_t tg, uint64_t num_pages, uint8_t ttl);
54
void smmu_iotlb_inv_ipa(SMMUState *s, int vmid, dma_addr_t ipa, uint8_t tg,
55
uint64_t num_pages, uint8_t ttl);
56
+void smmu_configs_inv_sid_range(SMMUState *s, SMMUSIDRange sid_range);
57
/* Unmap the range of all the notifiers registered to any IOMMU mr */
58
void smmu_inv_notifiers_all(SMMUState *s);
59
60
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/hw/arm/smmu-common.c
63
+++ b/hw/arm/smmu-common.c
64
@@ -XXX,XX +XXX,XX @@ static gboolean smmu_hash_remove_by_vmid_ipa(gpointer key, gpointer value,
65
((entry->iova & ~info->mask) == info->iova);
30
}
66
}
31
67
32
+static int vae2_tlbmask(CPUARMState *env)
68
+static gboolean
69
+smmu_hash_remove_by_sid_range(gpointer key, gpointer value, gpointer user_data)
33
+{
70
+{
34
+ uint64_t hcr = arm_hcr_el2_eff(env);
71
+ SMMUDevice *sdev = (SMMUDevice *)key;
35
+ uint16_t mask;
72
+ uint32_t sid = smmu_get_sid(sdev);
73
+ SMMUSIDRange *sid_range = (SMMUSIDRange *)user_data;
36
+
74
+
37
+ if (hcr & HCR_E2H) {
75
+ if (sid < sid_range->start || sid > sid_range->end) {
38
+ mask = ARMMMUIdxBit_E20_2 |
76
+ return false;
39
+ ARMMMUIdxBit_E20_2_PAN |
40
+ ARMMMUIdxBit_E20_0;
41
+ } else {
42
+ mask = ARMMMUIdxBit_E2;
43
+ }
77
+ }
44
+ return mask;
78
+ trace_smmu_config_cache_inv(sid);
79
+ return true;
45
+}
80
+}
46
+
81
+
47
/* Return 56 if TBI is enabled, 64 otherwise. */
82
+void smmu_configs_inv_sid_range(SMMUState *s, SMMUSIDRange sid_range)
48
static int tlbbits_for_regime(CPUARMState *env, ARMMMUIdx mmu_idx,
49
uint64_t addr)
50
@@ -XXX,XX +XXX,XX @@ static int vae1_tlbbits(CPUARMState *env, uint64_t addr)
51
return tlbbits_for_regime(env, mmu_idx, addr);
52
}
53
54
+static int vae2_tlbbits(CPUARMState *env, uint64_t addr)
55
+{
83
+{
56
+ uint64_t hcr = arm_hcr_el2_eff(env);
84
+ trace_smmu_configs_inv_sid_range(sid_range.start, sid_range.end);
57
+ ARMMMUIdx mmu_idx;
85
+ g_hash_table_foreach_remove(s->configs, smmu_hash_remove_by_sid_range,
58
+
86
+ &sid_range);
59
+ /*
60
+ * Only the regime of the mmu_idx below is significant.
61
+ * Regime EL2&0 has two ranges with separate TBI configuration, while EL2
62
+ * only has one.
63
+ */
64
+ if (hcr & HCR_E2H) {
65
+ mmu_idx = ARMMMUIdx_E20_2;
66
+ } else {
67
+ mmu_idx = ARMMMUIdx_E2;
68
+ }
69
+
70
+ return tlbbits_for_regime(env, mmu_idx, addr);
71
+}
87
+}
72
+
88
+
73
static void tlbi_aa64_vmalle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
89
void smmu_iotlb_inv_iova(SMMUState *s, int asid, int vmid, dma_addr_t iova,
74
uint64_t value)
90
uint8_t tg, uint64_t num_pages, uint8_t ttl)
75
{
91
{
76
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae2_write(CPUARMState *env, const ARMCPRegInfo *ri,
92
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
77
* flush-last-level-only.
93
index XXXXXXX..XXXXXXX 100644
78
*/
94
--- a/hw/arm/smmuv3.c
79
CPUState *cs = env_cpu(env);
95
+++ b/hw/arm/smmuv3.c
80
- int mask = e2_tlbmask(env);
96
@@ -XXX,XX +XXX,XX @@ static void smmuv3_flush_config(SMMUDevice *sdev)
81
+ int mask = vae2_tlbmask(env);
97
SMMUv3State *s = sdev->smmu;
82
uint64_t pageaddr = sextract64(value << 12, 0, 56);
98
SMMUState *bc = &s->smmu_state;
83
+ int bits = vae2_tlbbits(env, pageaddr);
99
84
100
- trace_smmuv3_config_cache_inv(smmu_get_sid(sdev));
85
- tlb_flush_page_by_mmuidx(cs, pageaddr, mask);
101
+ trace_smmu_config_cache_inv(smmu_get_sid(sdev));
86
+ tlb_flush_page_bits_by_mmuidx(cs, pageaddr, mask, bits);
102
g_hash_table_remove(bc->configs, sdev);
87
}
103
}
88
104
89
static void tlbi_aa64_vae3_write(CPUARMState *env, const ARMCPRegInfo *ri,
105
@@ -XXX,XX +XXX,XX @@ static void smmuv3_range_inval(SMMUState *s, Cmd *cmd, SMMUStage stage)
90
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
106
}
91
uint64_t value)
92
{
93
CPUState *cs = env_cpu(env);
94
+ int mask = vae2_tlbmask(env);
95
uint64_t pageaddr = sextract64(value << 12, 0, 56);
96
- int bits = tlbbits_for_regime(env, ARMMMUIdx_E2, pageaddr);
97
+ int bits = vae2_tlbbits(env, pageaddr);
98
99
- tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
100
- ARMMMUIdxBit_E2, bits);
101
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits);
102
}
107
}
103
108
104
static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
109
-static gboolean
105
@@ -XXX,XX +XXX,XX @@ static void tlbi_aa64_rvae1is_write(CPUARMState *env,
110
-smmuv3_invalidate_ste(gpointer key, gpointer value, gpointer user_data)
106
do_rvae_write(env, value, vae1_tlbmask(env), true);
107
}
108
109
-static int vae2_tlbmask(CPUARMState *env)
110
-{
111
-{
111
- return ARMMMUIdxBit_E2;
112
- SMMUDevice *sdev = (SMMUDevice *)key;
113
- uint32_t sid = smmu_get_sid(sdev);
114
- SMMUSIDRange *sid_range = (SMMUSIDRange *)user_data;
115
-
116
- if (sid < sid_range->start || sid > sid_range->end) {
117
- return false;
118
- }
119
- trace_smmuv3_config_cache_inv(sid);
120
- return true;
112
-}
121
-}
113
-
122
-
114
static void tlbi_aa64_rvae2_write(CPUARMState *env,
123
static int smmuv3_cmdq_consume(SMMUv3State *s)
115
const ARMCPRegInfo *ri,
124
{
116
uint64_t value)
125
SMMUState *bs = ARM_SMMU(s);
126
@@ -XXX,XX +XXX,XX @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
127
sid_range.end = sid_range.start + mask;
128
129
trace_smmuv3_cmdq_cfgi_ste_range(sid_range.start, sid_range.end);
130
- g_hash_table_foreach_remove(bs->configs, smmuv3_invalidate_ste,
131
- &sid_range);
132
+ smmu_configs_inv_sid_range(bs, sid_range);
133
break;
134
}
135
case SMMU_CMD_CFGI_CD:
136
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
137
index XXXXXXX..XXXXXXX 100644
138
--- a/hw/arm/trace-events
139
+++ b/hw/arm/trace-events
140
@@ -XXX,XX +XXX,XX @@ smmu_iotlb_inv_asid_vmid(int asid, int vmid) "IOTLB invalidate asid=%d vmid=%d"
141
smmu_iotlb_inv_vmid(int vmid) "IOTLB invalidate vmid=%d"
142
smmu_iotlb_inv_vmid_s1(int vmid) "IOTLB invalidate vmid=%d"
143
smmu_iotlb_inv_iova(int asid, uint64_t addr) "IOTLB invalidate asid=%d addr=0x%"PRIx64
144
+smmu_configs_inv_sid_range(uint32_t start, uint32_t end) "Config cache INV SID range from 0x%x to 0x%x"
145
+smmu_config_cache_inv(uint32_t sid) "Config cache INV for sid=0x%x"
146
smmu_inv_notifiers_mr(const char *name) "iommu mr=%s"
147
smmu_iotlb_lookup_hit(int asid, int vmid, uint64_t addr, uint32_t hit, uint32_t miss, uint32_t p) "IOTLB cache HIT asid=%d vmid=%d addr=0x%"PRIx64" hit=%d miss=%d hit rate=%d"
148
smmu_iotlb_lookup_miss(int asid, int vmid, uint64_t addr, uint32_t hit, uint32_t miss, uint32_t p) "IOTLB cache MISS asid=%d vmid=%d addr=0x%"PRIx64" hit=%d miss=%d hit rate=%d"
149
@@ -XXX,XX +XXX,XX @@ smmuv3_cmdq_tlbi_nh(int vmid) "vmid=%d"
150
smmuv3_cmdq_tlbi_nsnh(void) ""
151
smmuv3_cmdq_tlbi_nh_asid(int asid) "asid=%d"
152
smmuv3_cmdq_tlbi_s12_vmid(int vmid) "vmid=%d"
153
-smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid=0x%x"
154
smmuv3_notify_flag_add(const char *iommu) "ADD SMMUNotifier node for iommu mr=%s"
155
smmuv3_notify_flag_del(const char *iommu) "DEL SMMUNotifier node for iommu mr=%s"
156
smmuv3_inv_notifiers_iova(const char *name, int asid, int vmid, uint64_t iova, uint8_t tg, uint64_t num_pages, int stage) "iommu mr=%s asid=%d vmid=%d iova=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64" stage=%d"
117
--
157
--
118
2.34.1
158
2.43.0
diff view generated by jsdifflib
1
From: Chris Laplante <chris@laplante.io>
1
From: Keith Packard <keithp@keithp.com>
2
2
3
This is much better than just silently failing with OK.
3
The documentation says the vector is at 0xffffff80, instead of the
4
previous value of 0xffffffc0. That value must have been a bug because
5
the standard vector values (20, 21, 23, 25, 30) were all
6
past the end of the array.
4
7
5
Signed-off-by: Chris Laplante <chris@laplante.io>
8
Signed-off-by: Keith Packard <keithp@keithp.com>
6
Message-id: 20230728160324.1159090-6-chris@laplante.io
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
11
---
10
softmmu/qtest.c | 12 ++++++++++--
12
target/rx/helper.c | 2 +-
11
1 file changed, 10 insertions(+), 2 deletions(-)
13
1 file changed, 1 insertion(+), 1 deletion(-)
12
14
13
diff --git a/softmmu/qtest.c b/softmmu/qtest.c
15
diff --git a/target/rx/helper.c b/target/rx/helper.c
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/softmmu/qtest.c
17
--- a/target/rx/helper.c
16
+++ b/softmmu/qtest.c
18
+++ b/target/rx/helper.c
17
@@ -XXX,XX +XXX,XX @@ static void qtest_process_command(CharBackend *chr, gchar **words)
19
@@ -XXX,XX +XXX,XX @@ void rx_cpu_do_interrupt(CPUState *cs)
18
NamedGPIOList *ngl;
20
cpu_stl_data(env, env->isp, env->pc);
19
bool is_named;
21
20
bool is_outbound;
22
if (vec < 0x100) {
21
+ bool interception_succeeded = false;
23
- env->pc = cpu_ldl_data(env, 0xffffffc0 + vec * 4);
22
24
+ env->pc = cpu_ldl_data(env, 0xffffff80 + vec * 4);
23
g_assert(words[1]);
25
} else {
24
is_named = words[2] != NULL;
26
env->pc = cpu_ldl_data(env, env->intb + (vec & 0xff) * 4);
25
@@ -XXX,XX +XXX,XX @@ static void qtest_process_command(CharBackend *chr, gchar **words)
26
for (i = 0; i < ngl->num_out; ++i) {
27
qtest_install_gpio_out_intercept(dev, ngl->name, i);
28
}
29
+ interception_succeeded = true;
30
}
31
} else {
32
qemu_irq_intercept_in(ngl->in, qtest_irq_handler,
33
ngl->num_in);
34
+ interception_succeeded = true;
35
}
36
}
27
}
37
- irq_intercept_dev = dev;
38
+
39
qtest_send_prefix(chr);
40
- qtest_send(chr, "OK\n");
41
+ if (interception_succeeded) {
42
+ irq_intercept_dev = dev;
43
+ qtest_send(chr, "OK\n");
44
+ } else {
45
+ qtest_send(chr, "FAIL No intercepts installed\n");
46
+ }
47
} else if (strcmp(words[0], "set_irq_in") == 0) {
48
DeviceState *dev;
49
qemu_irq irq;
50
--
28
--
51
2.34.1
29
2.43.0
diff view generated by jsdifflib
1
From: Chris Laplante <chris@laplante.io>
1
From: Keith Packard <keithp@keithp.com>
2
2
3
Adds qtest_irq_intercept_out_named method, which utilizes a new optional
3
Functions which modify TCG globals must not be marked TCG_CALL_NO_WG,
4
name parameter to the irq_intercept_out qtest command.
4
as that tells the optimizer that TCG global values already loaded in
5
machine registers are still valid, and so any changes which these
6
helpers make to the CPU state may be ignored.
5
7
6
Signed-off-by: Chris Laplante <chris@laplante.io>
8
The target/rx code chooses to put (among other things) all the PSW
7
Message-id: 20230728160324.1159090-4-chris@laplante.io
9
bits and also ACC into globals, so the NO_WG flag on various
10
functions that touch the PSW or ACC is incorrect and must be removed.
11
This includes all the floating point helper functions, because
12
update_fpsw() will update PSW Z and S.
13
14
Signed-off-by: Keith Packard <keithp@keithp.com>
15
[PMM: Clarified commit message]
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
18
---
11
tests/qtest/libqtest.h | 11 +++++++++++
19
target/rx/helper.h | 34 +++++++++++++++++-----------------
12
softmmu/qtest.c | 18 ++++++++++--------
20
1 file changed, 17 insertions(+), 17 deletions(-)
13
tests/qtest/libqtest.c | 6 ++++++
14
3 files changed, 27 insertions(+), 8 deletions(-)
15
21
16
diff --git a/tests/qtest/libqtest.h b/tests/qtest/libqtest.h
22
diff --git a/target/rx/helper.h b/target/rx/helper.h
17
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/qtest/libqtest.h
24
--- a/target/rx/helper.h
19
+++ b/tests/qtest/libqtest.h
25
+++ b/target/rx/helper.h
20
@@ -XXX,XX +XXX,XX @@ void qtest_irq_intercept_in(QTestState *s, const char *string);
26
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_1(raise_privilege_violation, noreturn, env)
21
*/
27
DEF_HELPER_1(wait, noreturn, env)
22
void qtest_irq_intercept_out(QTestState *s, const char *string);
28
DEF_HELPER_2(rxint, noreturn, env, i32)
23
29
DEF_HELPER_1(rxbrk, noreturn, env)
24
+/**
30
-DEF_HELPER_FLAGS_3(fadd, TCG_CALL_NO_WG, f32, env, f32, f32)
25
+ * qtest_irq_intercept_out_named:
31
-DEF_HELPER_FLAGS_3(fsub, TCG_CALL_NO_WG, f32, env, f32, f32)
26
+ * @s: #QTestState instance to operate on.
32
-DEF_HELPER_FLAGS_3(fmul, TCG_CALL_NO_WG, f32, env, f32, f32)
27
+ * @qom_path: QOM path of a device.
33
-DEF_HELPER_FLAGS_3(fdiv, TCG_CALL_NO_WG, f32, env, f32, f32)
28
+ * @name: Name of the GPIO out pin
34
-DEF_HELPER_FLAGS_3(fcmp, TCG_CALL_NO_WG, void, env, f32, f32)
29
+ *
35
-DEF_HELPER_FLAGS_2(ftoi, TCG_CALL_NO_WG, i32, env, f32)
30
+ * Associate a qtest irq with the named GPIO-out pin of the device
36
-DEF_HELPER_FLAGS_2(round, TCG_CALL_NO_WG, i32, env, f32)
31
+ * whose path is specified by @string and whose name is @name.
37
-DEF_HELPER_FLAGS_2(itof, TCG_CALL_NO_WG, f32, env, i32)
32
+ */
38
+DEF_HELPER_3(fadd, f32, env, f32, f32)
33
+void qtest_irq_intercept_out_named(QTestState *s, const char *qom_path, const char *name);
39
+DEF_HELPER_3(fsub, f32, env, f32, f32)
34
+
40
+DEF_HELPER_3(fmul, f32, env, f32, f32)
35
/**
41
+DEF_HELPER_3(fdiv, f32, env, f32, f32)
36
* qtest_set_irq_in:
42
+DEF_HELPER_3(fcmp, void, env, f32, f32)
37
* @s: QTestState instance to operate on.
43
+DEF_HELPER_2(ftoi, i32, env, f32)
38
diff --git a/softmmu/qtest.c b/softmmu/qtest.c
44
+DEF_HELPER_2(round, i32, env, f32)
39
index XXXXXXX..XXXXXXX 100644
45
+DEF_HELPER_2(itof, f32, env, i32)
40
--- a/softmmu/qtest.c
46
DEF_HELPER_2(set_fpsw, void, env, i32)
41
+++ b/softmmu/qtest.c
47
-DEF_HELPER_FLAGS_2(racw, TCG_CALL_NO_WG, void, env, i32)
42
@@ -XXX,XX +XXX,XX @@ static void qtest_process_command(CharBackend *chr, gchar **words)
48
-DEF_HELPER_FLAGS_2(set_psw_rte, TCG_CALL_NO_WG, void, env, i32)
43
|| strcmp(words[0], "irq_intercept_in") == 0) {
49
-DEF_HELPER_FLAGS_2(set_psw, TCG_CALL_NO_WG, void, env, i32)
44
DeviceState *dev;
50
+DEF_HELPER_2(racw, void, env, i32)
45
NamedGPIOList *ngl;
51
+DEF_HELPER_2(set_psw_rte, void, env, i32)
46
+ bool is_outbound;
52
+DEF_HELPER_2(set_psw, void, env, i32)
47
53
DEF_HELPER_1(pack_psw, i32, env)
48
g_assert(words[1]);
54
-DEF_HELPER_FLAGS_3(div, TCG_CALL_NO_WG, i32, env, i32, i32)
49
+ is_outbound = words[0][14] == 'o';
55
-DEF_HELPER_FLAGS_3(divu, TCG_CALL_NO_WG, i32, env, i32, i32)
50
dev = DEVICE(object_resolve_path(words[1], NULL));
56
-DEF_HELPER_FLAGS_1(scmpu, TCG_CALL_NO_WG, void, env)
51
if (!dev) {
57
+DEF_HELPER_3(div, i32, env, i32, i32)
52
qtest_send_prefix(chr);
58
+DEF_HELPER_3(divu, i32, env, i32, i32)
53
@@ -XXX,XX +XXX,XX @@ static void qtest_process_command(CharBackend *chr, gchar **words)
59
+DEF_HELPER_1(scmpu, void, env)
54
}
60
DEF_HELPER_1(smovu, void, env)
55
61
DEF_HELPER_1(smovf, void, env)
56
QLIST_FOREACH(ngl, &dev->gpios, node) {
62
DEF_HELPER_1(smovb, void, env)
57
- /* We don't support intercept of named GPIOs yet */
63
DEF_HELPER_2(sstr, void, env, i32)
58
- if (ngl->name) {
64
-DEF_HELPER_FLAGS_2(swhile, TCG_CALL_NO_WG, void, env, i32)
59
- continue;
65
-DEF_HELPER_FLAGS_2(suntil, TCG_CALL_NO_WG, void, env, i32)
60
- }
66
-DEF_HELPER_FLAGS_2(rmpa, TCG_CALL_NO_WG, void, env, i32)
61
- if (words[0][14] == 'o') {
67
+DEF_HELPER_2(swhile, void, env, i32)
62
- int i;
68
+DEF_HELPER_2(suntil, void, env, i32)
63
- for (i = 0; i < ngl->num_out; ++i) {
69
+DEF_HELPER_2(rmpa, void, env, i32)
64
- qtest_install_gpio_out_intercept(dev, ngl->name, i);
70
DEF_HELPER_1(satr, void, env)
65
+ /* We don't support inbound interception of named GPIOs yet */
66
+ if (is_outbound) {
67
+ /* NULL is valid and matchable, for "unnamed GPIO" */
68
+ if (g_strcmp0(ngl->name, words[2]) == 0) {
69
+ int i;
70
+ for (i = 0; i < ngl->num_out; ++i) {
71
+ qtest_install_gpio_out_intercept(dev, ngl->name, i);
72
+ }
73
}
74
} else {
75
qemu_irq_intercept_in(ngl->in, qtest_irq_handler,
76
diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c
77
index XXXXXXX..XXXXXXX 100644
78
--- a/tests/qtest/libqtest.c
79
+++ b/tests/qtest/libqtest.c
80
@@ -XXX,XX +XXX,XX @@ void qtest_irq_intercept_out(QTestState *s, const char *qom_path)
81
qtest_rsp(s);
82
}
83
84
+void qtest_irq_intercept_out_named(QTestState *s, const char *qom_path, const char *name)
85
+{
86
+ qtest_sendf(s, "irq_intercept_out %s %s\n", qom_path, name);
87
+ qtest_rsp(s);
88
+}
89
+
90
void qtest_irq_intercept_in(QTestState *s, const char *qom_path)
91
{
92
qtest_sendf(s, "irq_intercept_in %s\n", qom_path);
93
--
71
--
94
2.34.1
72
2.43.0
diff view generated by jsdifflib
Deleted patch
1
From: Chris Laplante <chris@laplante.io>
2
1
3
Named interception of in-GPIOs is not supported yet.
4
5
Signed-off-by: Chris Laplante <chris@laplante.io>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20230728160324.1159090-5-chris@laplante.io
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
softmmu/qtest.c | 8 ++++++++
11
1 file changed, 8 insertions(+)
12
13
diff --git a/softmmu/qtest.c b/softmmu/qtest.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/softmmu/qtest.c
16
+++ b/softmmu/qtest.c
17
@@ -XXX,XX +XXX,XX @@ static void qtest_process_command(CharBackend *chr, gchar **words)
18
|| strcmp(words[0], "irq_intercept_in") == 0) {
19
DeviceState *dev;
20
NamedGPIOList *ngl;
21
+ bool is_named;
22
bool is_outbound;
23
24
g_assert(words[1]);
25
+ is_named = words[2] != NULL;
26
is_outbound = words[0][14] == 'o';
27
dev = DEVICE(object_resolve_path(words[1], NULL));
28
if (!dev) {
29
@@ -XXX,XX +XXX,XX @@ static void qtest_process_command(CharBackend *chr, gchar **words)
30
return;
31
}
32
33
+ if (is_named && !is_outbound) {
34
+ qtest_send_prefix(chr);
35
+ qtest_send(chr, "FAIL Interception of named in-GPIOs not yet supported\n");
36
+ return;
37
+ }
38
+
39
if (irq_intercept_dev) {
40
qtest_send_prefix(chr);
41
if (irq_intercept_dev != dev) {
42
--
43
2.34.1
diff view generated by jsdifflib
Deleted patch
1
From: Chris Laplante <chris@laplante.io>
2
1
3
Exercise the DETECT mechanism of the GPIO peripheral.
4
5
Signed-off-by: Chris Laplante <chris@laplante.io>
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20230728160324.1159090-7-chris@laplante.io
8
[PMM: fixed coding style nits]
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
tests/qtest/microbit-test.c | 44 +++++++++++++++++++++++++++++++++++++
12
1 file changed, 44 insertions(+)
13
14
diff --git a/tests/qtest/microbit-test.c b/tests/qtest/microbit-test.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/qtest/microbit-test.c
17
+++ b/tests/qtest/microbit-test.c
18
@@ -XXX,XX +XXX,XX @@ static void test_nrf51_gpio(void)
19
qtest_quit(qts);
20
}
21
22
+static void test_nrf51_gpio_detect(void)
23
+{
24
+ QTestState *qts = qtest_init("-M microbit");
25
+ int i;
26
+
27
+ /* Connect input buffer on pins 1-7, configure SENSE for high level */
28
+ for (i = 1; i <= 7; i++) {
29
+ qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START + i * 4,
30
+ deposit32(0, 16, 2, 2));
31
+ }
32
+
33
+ qtest_irq_intercept_out_named(qts, "/machine/nrf51/gpio", "detect");
34
+
35
+ for (i = 1; i <= 7; i++) {
36
+ /* Set pin high */
37
+ qtest_set_irq_in(qts, "/machine/nrf51", "unnamed-gpio-in", i, 1);
38
+ uint32_t actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_IN);
39
+ g_assert_cmpuint(actual, ==, 1 << i);
40
+
41
+ /* Check that DETECT is high */
42
+ g_assert_true(qtest_get_irq(qts, 0));
43
+
44
+ /* Set pin low, check that DETECT goes low. */
45
+ qtest_set_irq_in(qts, "/machine/nrf51", "unnamed-gpio-in", i, 0);
46
+ actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_IN);
47
+ g_assert_cmpuint(actual, ==, 0x0);
48
+ g_assert_false(qtest_get_irq(qts, 0));
49
+ }
50
+
51
+ /* Set pin 0 high, check that DETECT doesn't fire */
52
+ qtest_set_irq_in(qts, "/machine/nrf51", "unnamed-gpio-in", 0, 1);
53
+ g_assert_false(qtest_get_irq(qts, 0));
54
+ qtest_set_irq_in(qts, "/machine/nrf51", "unnamed-gpio-in", 0, 0);
55
+
56
+ /* Set pins 1, 2, and 3 high, then set 3 low. Check DETECT is still high */
57
+ for (i = 1; i <= 3; i++) {
58
+ qtest_set_irq_in(qts, "/machine/nrf51", "unnamed-gpio-in", i, 1);
59
+ }
60
+ g_assert_true(qtest_get_irq(qts, 0));
61
+ qtest_set_irq_in(qts, "/machine/nrf51", "unnamed-gpio-in", 3, 0);
62
+ g_assert_true(qtest_get_irq(qts, 0));
63
+}
64
+
65
static void timer_task(QTestState *qts, hwaddr task)
66
{
67
qtest_writel(qts, NRF51_TIMER_BASE + task, NRF51_TRIGGER_TASK);
68
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
69
70
qtest_add_func("/microbit/nrf51/uart", test_nrf51_uart);
71
qtest_add_func("/microbit/nrf51/gpio", test_nrf51_gpio);
72
+ qtest_add_func("/microbit/nrf51/gpio_detect", test_nrf51_gpio_detect);
73
qtest_add_func("/microbit/nrf51/nvmc", test_nrf51_nvmc);
74
qtest_add_func("/microbit/nrf51/timer", test_nrf51_timer);
75
qtest_add_func("/microbit/microbit/i2c", test_microbit_i2c);
76
--
77
2.34.1
diff view generated by jsdifflib
Deleted patch
1
From: Akihiko Odaki <akihiko.odaki@daynix.com>
2
1
3
An error may occur after s->as is allocated, for example if the
4
KVM_CREATE_VM ioctl call fails.
5
6
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
7
Message-id: 20230727073134.134102-6-akihiko.odaki@daynix.com
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
[PMM: tweaked commit message]
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
accel/kvm/kvm-all.c | 1 +
13
1 file changed, 1 insertion(+)
14
15
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/accel/kvm/kvm-all.c
18
+++ b/accel/kvm/kvm-all.c
19
@@ -XXX,XX +XXX,XX @@ err:
20
if (s->fd != -1) {
21
close(s->fd);
22
}
23
+ g_free(s->as);
24
g_free(s->memory_listener.slots);
25
26
return ret;
27
--
28
2.34.1
diff view generated by jsdifflib
Deleted patch
1
For an Unsupported Atomic Update fault where the stage 1 translation
2
table descriptor update can't be done because it's to an unsupported
3
memory type, this is a stage 1 abort (per the Arm ARM R_VSXXT). This
4
means we should not set fi->s1ptw, because this will cause the code
5
in the get_phys_addr_lpae() error-exit path to mark it as stage 2.
6
1
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230807141514.19075-2-peter.maydell@linaro.org
10
---
11
target/arm/ptw.c | 1 -
12
1 file changed, 1 deletion(-)
13
14
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/ptw.c
17
+++ b/target/arm/ptw.c
18
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_casq_ptw(CPUARMState *env, uint64_t old_val,
19
20
if (unlikely(!host)) {
21
fi->type = ARMFault_UnsuppAtomicUpdate;
22
- fi->s1ptw = true;
23
return 0;
24
}
25
26
--
27
2.34.1
diff view generated by jsdifflib
Deleted patch
1
In S1_ptw_translate() we set up the ARMMMUFaultInfo if the attempt to
2
translate the page descriptor address into a physical address fails.
3
This used to only be possible if we are doing a stage 2 ptw for that
4
descriptor address, and so the code always sets fi->stage2 and
5
fi->s1ptw to true. However, with FEAT_RME it is also possible for
6
the lookup of the page descriptor address to fail because of a
7
Granule Protection Check fault. These should not be reported as
8
stage 2, otherwise arm_deliver_fault() will incorrectly set
9
HPFAR_EL2. Similarly the s1ptw bit should only be set for stage 2
10
faults on stage 1 translation table walks, i.e. not for GPC faults.
11
1
12
Add a comment to the the other place where we might detect a
13
stage2-fault-on-stage-1-ptw, in arm_casq_ptw(), noting why we know in
14
that case that it must really be a stage 2 fault and not a GPC fault.
15
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Message-id: 20230807141514.19075-3-peter.maydell@linaro.org
19
---
20
target/arm/ptw.c | 10 ++++++++--
21
1 file changed, 8 insertions(+), 2 deletions(-)
22
23
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/ptw.c
26
+++ b/target/arm/ptw.c
27
@@ -XXX,XX +XXX,XX @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
28
fi->type = ARMFault_GPCFOnWalk;
29
}
30
fi->s2addr = addr;
31
- fi->stage2 = true;
32
- fi->s1ptw = true;
33
+ fi->stage2 = regime_is_stage2(s2_mmu_idx);
34
+ fi->s1ptw = fi->stage2;
35
fi->s1ns = !is_secure;
36
return false;
37
}
38
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_casq_ptw(CPUARMState *env, uint64_t old_val,
39
env->tlb_fi = NULL;
40
41
if (unlikely(flags & TLB_INVALID_MASK)) {
42
+ /*
43
+ * We know this must be a stage 2 fault because the granule
44
+ * protection table does not separately track read and write
45
+ * permission, so all GPC faults are caught in S1_ptw_translate():
46
+ * we only get here for "readable but not writeable".
47
+ */
48
assert(fi->type != ARMFault_None);
49
fi->s2addr = ptw->out_virt;
50
fi->stage2 = true;
51
--
52
2.34.1
diff view generated by jsdifflib
Deleted patch
1
Plumb the ARMSecurityState through to regime_translation_disabled()
2
rather than just a bool is_secure.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230807141514.19075-6-peter.maydell@linaro.org
7
---
8
target/arm/ptw.c | 15 ++++++++-------
9
1 file changed, 8 insertions(+), 7 deletions(-)
10
11
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/ptw.c
14
+++ b/target/arm/ptw.c
15
@@ -XXX,XX +XXX,XX @@ static uint64_t regime_ttbr(CPUARMState *env, ARMMMUIdx mmu_idx, int ttbrn)
16
17
/* Return true if the specified stage of address translation is disabled */
18
static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx,
19
- bool is_secure)
20
+ ARMSecuritySpace space)
21
{
22
uint64_t hcr_el2;
23
+ bool is_secure = arm_space_is_secure(space);
24
25
if (arm_feature(env, ARM_FEATURE_M)) {
26
switch (env->v7m.mpu_ctrl[is_secure] &
27
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav5(CPUARMState *env,
28
uint32_t base;
29
ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
30
bool is_user = regime_is_user(env, mmu_idx);
31
- bool is_secure = arm_space_is_secure(ptw->in_space);
32
33
- if (regime_translation_disabled(env, mmu_idx, is_secure)) {
34
+ if (regime_translation_disabled(env, mmu_idx, ptw->in_space)) {
35
/* MPU disabled. */
36
result->f.phys_addr = address;
37
result->f.prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
38
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_pmsav7(CPUARMState *env,
39
result->f.lg_page_size = TARGET_PAGE_BITS;
40
result->f.prot = 0;
41
42
- if (regime_translation_disabled(env, mmu_idx, secure) ||
43
+ if (regime_translation_disabled(env, mmu_idx, ptw->in_space) ||
44
m_is_ppb_region(env, address)) {
45
/*
46
* MPU disabled or M profile PPB access: use default memory map.
47
@@ -XXX,XX +XXX,XX @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
48
* are done in arm_v7m_load_vector(), which always does a direct
49
* read using address_space_ldl(), rather than going via this function.
50
*/
51
- if (regime_translation_disabled(env, mmu_idx, secure)) { /* MPU disabled */
52
+ if (regime_translation_disabled(env, mmu_idx, arm_secure_to_space(secure))) {
53
+ /* MPU disabled */
54
hit = true;
55
} else if (m_is_ppb_region(env, address)) {
56
hit = true;
57
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw,
58
*/
59
ptw->in_mmu_idx = mmu_idx = s1_mmu_idx;
60
if (arm_feature(env, ARM_FEATURE_EL2) &&
61
- !regime_translation_disabled(env, ARMMMUIdx_Stage2, is_secure)) {
62
+ !regime_translation_disabled(env, ARMMMUIdx_Stage2, ptw->in_space)) {
63
return get_phys_addr_twostage(env, ptw, address, access_type,
64
result, fi);
65
}
66
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw,
67
68
/* Definitely a real MMU, not an MPU */
69
70
- if (regime_translation_disabled(env, mmu_idx, is_secure)) {
71
+ if (regime_translation_disabled(env, mmu_idx, ptw->in_space)) {
72
return get_phys_addr_disabled(env, ptw, address, access_type,
73
result, fi);
74
}
75
--
76
2.34.1
diff view generated by jsdifflib
Deleted patch
1
arm_hcr_el2_eff_secstate() takes a bool secure, which it uses to
2
determine whether EL2 is enabled in the current security state.
3
With the advent of FEAT_RME this is no longer sufficient, because
4
EL2 can be enabled for Secure state but not for Root, and both
5
of those will pass 'secure == true' in the callsites in ptw.c.
6
1
7
As it happens in all of our callsites in ptw.c we either avoid making
8
the call or else avoid using the returned value if we're doing a
9
translation for Root, so this is not a behaviour change even if the
10
experimental FEAT_RME is enabled. But it is less confusing in the
11
ptw.c code if we avoid the use of a bool secure that duplicates some
12
of the information in the ArmSecuritySpace argument.
13
14
Make arm_hcr_el2_eff_secstate() take an ARMSecuritySpace argument
15
instead. Because we always want to know the HCR_EL2 for the
16
security state defined by the current effective value of
17
SCR_EL3.{NSE,NS}, it makes no sense to pass ARMSS_Root here,
18
and we assert that callers don't do that.
19
20
To avoid the assert(), we thus push the call to
21
arm_hcr_el2_eff_secstate() down into the cases in
22
regime_translation_disabled() that need it, rather than calling the
23
function and ignoring the result for the Root space translations.
24
All other calls to this function in ptw.c are already in places
25
where we have confirmed that the mmu_idx is a stage 2 translation
26
or that the regime EL is not 3.
27
28
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
30
Message-id: 20230807141514.19075-7-peter.maydell@linaro.org
31
---
32
target/arm/cpu.h | 2 +-
33
target/arm/helper.c | 8 +++++---
34
target/arm/ptw.c | 15 +++++++--------
35
3 files changed, 13 insertions(+), 12 deletions(-)
36
37
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/cpu.h
40
+++ b/target/arm/cpu.h
41
@@ -XXX,XX +XXX,XX @@ static inline bool arm_is_el2_enabled(CPUARMState *env)
42
* "for all purposes other than a direct read or write access of HCR_EL2."
43
* Not included here is HCR_RW.
44
*/
45
-uint64_t arm_hcr_el2_eff_secstate(CPUARMState *env, bool secure);
46
+uint64_t arm_hcr_el2_eff_secstate(CPUARMState *env, ARMSecuritySpace space);
47
uint64_t arm_hcr_el2_eff(CPUARMState *env);
48
uint64_t arm_hcrx_el2_eff(CPUARMState *env);
49
50
diff --git a/target/arm/helper.c b/target/arm/helper.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/helper.c
53
+++ b/target/arm/helper.c
54
@@ -XXX,XX +XXX,XX @@ static void hcr_writelow(CPUARMState *env, const ARMCPRegInfo *ri,
55
* Bits that are not included here:
56
* RW (read from SCR_EL3.RW as needed)
57
*/
58
-uint64_t arm_hcr_el2_eff_secstate(CPUARMState *env, bool secure)
59
+uint64_t arm_hcr_el2_eff_secstate(CPUARMState *env, ARMSecuritySpace space)
60
{
61
uint64_t ret = env->cp15.hcr_el2;
62
63
- if (!arm_is_el2_enabled_secstate(env, secure)) {
64
+ assert(space != ARMSS_Root);
65
+
66
+ if (!arm_is_el2_enabled_secstate(env, arm_space_is_secure(space))) {
67
/*
68
* "This register has no effect if EL2 is not enabled in the
69
* current Security state". This is ARMv8.4-SecEL2 speak for
70
@@ -XXX,XX +XXX,XX @@ uint64_t arm_hcr_el2_eff(CPUARMState *env)
71
if (arm_feature(env, ARM_FEATURE_M)) {
72
return 0;
73
}
74
- return arm_hcr_el2_eff_secstate(env, arm_is_secure_below_el3(env));
75
+ return arm_hcr_el2_eff_secstate(env, arm_security_space_below_el3(env));
76
}
77
78
/*
79
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/target/arm/ptw.c
82
+++ b/target/arm/ptw.c
83
@@ -XXX,XX +XXX,XX @@ static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx,
84
ARMSecuritySpace space)
85
{
86
uint64_t hcr_el2;
87
- bool is_secure = arm_space_is_secure(space);
88
89
if (arm_feature(env, ARM_FEATURE_M)) {
90
+ bool is_secure = arm_space_is_secure(space);
91
switch (env->v7m.mpu_ctrl[is_secure] &
92
(R_V7M_MPU_CTRL_ENABLE_MASK | R_V7M_MPU_CTRL_HFNMIENA_MASK)) {
93
case R_V7M_MPU_CTRL_ENABLE_MASK:
94
@@ -XXX,XX +XXX,XX @@ static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx,
95
}
96
}
97
98
- hcr_el2 = arm_hcr_el2_eff_secstate(env, is_secure);
99
100
switch (mmu_idx) {
101
case ARMMMUIdx_Stage2:
102
case ARMMMUIdx_Stage2_S:
103
/* HCR.DC means HCR.VM behaves as 1 */
104
+ hcr_el2 = arm_hcr_el2_eff_secstate(env, space);
105
return (hcr_el2 & (HCR_DC | HCR_VM)) == 0;
106
107
case ARMMMUIdx_E10_0:
108
case ARMMMUIdx_E10_1:
109
case ARMMMUIdx_E10_1_PAN:
110
/* TGE means that EL0/1 act as if SCTLR_EL1.M is zero */
111
+ hcr_el2 = arm_hcr_el2_eff_secstate(env, space);
112
if (hcr_el2 & HCR_TGE) {
113
return true;
114
}
115
@@ -XXX,XX +XXX,XX @@ static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx,
116
case ARMMMUIdx_Stage1_E1:
117
case ARMMMUIdx_Stage1_E1_PAN:
118
/* HCR.DC means SCTLR_EL1.M behaves as 0 */
119
+ hcr_el2 = arm_hcr_el2_eff_secstate(env, space);
120
if (hcr_el2 & HCR_DC) {
121
return true;
122
}
123
@@ -XXX,XX +XXX,XX @@ static bool fault_s1ns(ARMSecuritySpace space, ARMMMUIdx s2_mmu_idx)
124
static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
125
hwaddr addr, ARMMMUFaultInfo *fi)
126
{
127
- bool is_secure = ptw->in_secure;
128
ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
129
ARMMMUIdx s2_mmu_idx = ptw->in_ptw_idx;
130
uint8_t pte_attrs;
131
@@ -XXX,XX +XXX,XX @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
132
}
133
134
if (regime_is_stage2(s2_mmu_idx)) {
135
- uint64_t hcr = arm_hcr_el2_eff_secstate(env, is_secure);
136
+ uint64_t hcr = arm_hcr_el2_eff_secstate(env, ptw->in_space);
137
138
if ((hcr & HCR_PTW) && S2_attrs_are_device(hcr, pte_attrs)) {
139
/*
140
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_disabled(CPUARMState *env,
141
ARMMMUFaultInfo *fi)
142
{
143
ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
144
- bool is_secure = arm_space_is_secure(ptw->in_space);
145
uint8_t memattr = 0x00; /* Device nGnRnE */
146
uint8_t shareability = 0; /* non-shareable */
147
int r_el;
148
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_disabled(CPUARMState *env,
149
150
/* Fill in cacheattr a-la AArch64.TranslateAddressS1Off. */
151
if (r_el == 1) {
152
- uint64_t hcr = arm_hcr_el2_eff_secstate(env, is_secure);
153
+ uint64_t hcr = arm_hcr_el2_eff_secstate(env, ptw->in_space);
154
if (hcr & HCR_DC) {
155
if (hcr & HCR_DCT) {
156
memattr = 0xf0; /* Tagged, Normal, WB, RWA */
157
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
158
{
159
hwaddr ipa;
160
int s1_prot, s1_lgpgsz;
161
- bool is_secure = ptw->in_secure;
162
ARMSecuritySpace in_space = ptw->in_space;
163
bool ret, ipa_secure;
164
ARMCacheAttrs cacheattrs1;
165
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
166
}
167
168
/* Combine the S1 and S2 cache attributes. */
169
- hcr = arm_hcr_el2_eff_secstate(env, is_secure);
170
+ hcr = arm_hcr_el2_eff_secstate(env, in_space);
171
if (hcr & HCR_DC) {
172
/*
173
* HCR.DC forces the first stage attributes to
174
--
175
2.34.1
diff view generated by jsdifflib
Deleted patch
1
Pass an ARMSecuritySpace instead of a bool secure to
2
arm_is_el2_enabled_secstate(). This doesn't change behaviour.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230807141514.19075-8-peter.maydell@linaro.org
7
---
8
target/arm/cpu.h | 13 ++++++++-----
9
target/arm/helper.c | 2 +-
10
2 files changed, 9 insertions(+), 6 deletions(-)
11
12
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.h
15
+++ b/target/arm/cpu.h
16
@@ -XXX,XX +XXX,XX @@ static inline bool arm_is_secure(CPUARMState *env)
17
18
/*
19
* Return true if the current security state has AArch64 EL2 or AArch32 Hyp.
20
- * This corresponds to the pseudocode EL2Enabled()
21
+ * This corresponds to the pseudocode EL2Enabled().
22
*/
23
-static inline bool arm_is_el2_enabled_secstate(CPUARMState *env, bool secure)
24
+static inline bool arm_is_el2_enabled_secstate(CPUARMState *env,
25
+ ARMSecuritySpace space)
26
{
27
+ assert(space != ARMSS_Root);
28
return arm_feature(env, ARM_FEATURE_EL2)
29
- && (!secure || (env->cp15.scr_el3 & SCR_EEL2));
30
+ && (space != ARMSS_Secure || (env->cp15.scr_el3 & SCR_EEL2));
31
}
32
33
static inline bool arm_is_el2_enabled(CPUARMState *env)
34
{
35
- return arm_is_el2_enabled_secstate(env, arm_is_secure_below_el3(env));
36
+ return arm_is_el2_enabled_secstate(env, arm_security_space_below_el3(env));
37
}
38
39
#else
40
@@ -XXX,XX +XXX,XX @@ static inline bool arm_is_secure(CPUARMState *env)
41
return false;
42
}
43
44
-static inline bool arm_is_el2_enabled_secstate(CPUARMState *env, bool secure)
45
+static inline bool arm_is_el2_enabled_secstate(CPUARMState *env,
46
+ ARMSecuritySpace space)
47
{
48
return false;
49
}
50
diff --git a/target/arm/helper.c b/target/arm/helper.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/helper.c
53
+++ b/target/arm/helper.c
54
@@ -XXX,XX +XXX,XX @@ uint64_t arm_hcr_el2_eff_secstate(CPUARMState *env, ARMSecuritySpace space)
55
56
assert(space != ARMSS_Root);
57
58
- if (!arm_is_el2_enabled_secstate(env, arm_space_is_secure(space))) {
59
+ if (!arm_is_el2_enabled_secstate(env, space)) {
60
/*
61
* "This register has no effect if EL2 is not enabled in the
62
* current Security state". This is ARMv8.4-SecEL2 speak for
63
--
64
2.34.1
diff view generated by jsdifflib
Deleted patch
1
When we do a translation in Secure state, the NSTable bits in table
2
descriptors may downgrade us to NonSecure; we update ptw->in_secure
3
and ptw->in_space accordingly. We guard that check correctly with a
4
conditional that means it's only applied for Secure stage 1
5
translations. However, later on in get_phys_addr_lpae() we fold the
6
effects of the NSTable bits into the final descriptor attributes
7
bits, and there we do it unconditionally regardless of the CPU state.
8
That means that in Realm state (where in_secure is false) we will set
9
bit 5 in attrs, and later use it to decide to output to non-secure
10
space.
11
1
12
We don't in fact need to do this folding in at all any more (since
13
commit 2f1ff4e7b9f30c): if an NSTable bit was set then we have
14
already set ptw->in_space to ARMSS_NonSecure, and in that situation
15
we don't look at attrs bit 5. The only thing we still need to deal
16
with is the real NS bit in the final descriptor word, so we can just
17
drop the code that ORed in the NSTable bit.
18
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20230807141514.19075-9-peter.maydell@linaro.org
22
---
23
target/arm/ptw.c | 3 +--
24
1 file changed, 1 insertion(+), 2 deletions(-)
25
26
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/ptw.c
29
+++ b/target/arm/ptw.c
30
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
31
* Extract attributes from the (modified) descriptor, and apply
32
* table descriptors. Stage 2 table descriptors do not include
33
* any attribute fields. HPD disables all the table attributes
34
- * except NSTable.
35
+ * except NSTable (which we have already handled).
36
*/
37
attrs = new_descriptor & (MAKE_64BIT_MASK(2, 10) | MAKE_64BIT_MASK(50, 14));
38
if (!regime_is_stage2(mmu_idx)) {
39
- attrs |= !ptw->in_secure << 5; /* NS */
40
if (!param.hpd) {
41
attrs |= extract64(tableattrs, 0, 2) << 53; /* XN, PXN */
42
/*
43
--
44
2.34.1
diff view generated by jsdifflib
Deleted patch
1
Replace the last uses of ptw->in_secure with appropriate
2
checks on ptw->in_space.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230807141514.19075-10-peter.maydell@linaro.org
7
---
8
target/arm/ptw.c | 11 +++++++----
9
1 file changed, 7 insertions(+), 4 deletions(-)
10
11
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/ptw.c
14
+++ b/target/arm/ptw.c
15
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw,
16
ARMMMUFaultInfo *fi)
17
{
18
ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
19
- bool is_secure = ptw->in_secure;
20
ARMMMUIdx s1_mmu_idx;
21
22
/*
23
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw,
24
* cannot upgrade a NonSecure translation regime's attributes
25
* to Secure or Realm.
26
*/
27
- result->f.attrs.secure = is_secure;
28
result->f.attrs.space = ptw->in_space;
29
+ result->f.attrs.secure = arm_space_is_secure(ptw->in_space);
30
31
switch (mmu_idx) {
32
case ARMMMUIdx_Phys_S:
33
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw,
34
case ARMMMUIdx_Stage1_E0:
35
case ARMMMUIdx_Stage1_E1:
36
case ARMMMUIdx_Stage1_E1_PAN:
37
- /* First stage lookup uses second stage for ptw. */
38
- ptw->in_ptw_idx = is_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
39
+ /*
40
+ * First stage lookup uses second stage for ptw; only
41
+ * Secure has both S and NS IPA and starts with Stage2_S.
42
+ */
43
+ ptw->in_ptw_idx = (ptw->in_space == ARMSS_Secure) ?
44
+ ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
45
break;
46
47
case ARMMMUIdx_Stage2:
48
--
49
2.34.1
diff view generated by jsdifflib
Deleted patch
1
We no longer look at the in_secure field of the S1Translate struct
2
anyway, so we can remove it and all the code which sets it.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20230807141514.19075-11-peter.maydell@linaro.org
7
---
8
target/arm/ptw.c | 13 -------------
9
1 file changed, 13 deletions(-)
10
11
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/ptw.c
14
+++ b/target/arm/ptw.c
15
@@ -XXX,XX +XXX,XX @@ typedef struct S1Translate {
16
* value being Stage2 vs Stage2_S distinguishes those.
17
*/
18
ARMSecuritySpace in_space;
19
- /*
20
- * in_secure: whether the translation regime is a Secure one.
21
- * This is always equal to arm_space_is_secure(in_space).
22
- * If a Secure ptw is "downgraded" to NonSecure by an NSTable bit,
23
- * this field is updated accordingly.
24
- */
25
- bool in_secure;
26
/*
27
* in_debug: is this a QEMU debug access (gdbstub, etc)? Debug
28
* accesses will not update the guest page table access flags
29
@@ -XXX,XX +XXX,XX @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
30
S1Translate s2ptw = {
31
.in_mmu_idx = s2_mmu_idx,
32
.in_ptw_idx = ptw_idx_for_stage_2(env, s2_mmu_idx),
33
- .in_secure = arm_space_is_secure(s2_space),
34
.in_space = s2_space,
35
.in_debug = true,
36
};
37
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
38
QEMU_BUILD_BUG_ON(ARMMMUIdx_Phys_S + 1 != ARMMMUIdx_Phys_NS);
39
QEMU_BUILD_BUG_ON(ARMMMUIdx_Stage2_S + 1 != ARMMMUIdx_Stage2);
40
ptw->in_ptw_idx += 1;
41
- ptw->in_secure = false;
42
ptw->in_space = ARMSS_NonSecure;
43
}
44
45
@@ -XXX,XX +XXX,XX @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
46
47
ptw->in_s1_is_el0 = ptw->in_mmu_idx == ARMMMUIdx_Stage1_E0;
48
ptw->in_mmu_idx = ipa_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
49
- ptw->in_secure = ipa_secure;
50
ptw->in_space = ipa_space;
51
ptw->in_ptw_idx = ptw_idx_for_stage_2(env, ptw->in_mmu_idx);
52
53
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
54
{
55
S1Translate ptw = {
56
.in_mmu_idx = mmu_idx,
57
- .in_secure = is_secure,
58
.in_space = arm_secure_to_space(is_secure),
59
};
60
return get_phys_addr_gpc(env, &ptw, address, access_type, result, fi);
61
@@ -XXX,XX +XXX,XX @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
62
}
63
64
ptw.in_space = ss;
65
- ptw.in_secure = arm_space_is_secure(ss);
66
return get_phys_addr_gpc(env, &ptw, address, access_type, result, fi);
67
}
68
69
@@ -XXX,XX +XXX,XX @@ hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr,
70
S1Translate ptw = {
71
.in_mmu_idx = mmu_idx,
72
.in_space = ss,
73
- .in_secure = arm_space_is_secure(ss),
74
.in_debug = true,
75
};
76
GetPhysAddrResult res = {};
77
--
78
2.34.1
diff view generated by jsdifflib
Deleted patch
1
We only use S1Translate::out_secure in two places, where we are
2
setting up MemTxAttrs for a page table load. We can use
3
arm_space_is_secure(ptw->out_space) instead, which guarantees
4
that we're setting the MemTxAttrs secure and space fields
5
consistently, and allows us to drop the out_secure field in
6
S1Translate entirely.
7
1
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20230807141514.19075-12-peter.maydell@linaro.org
11
---
12
target/arm/ptw.c | 7 ++-----
13
1 file changed, 2 insertions(+), 5 deletions(-)
14
15
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/ptw.c
18
+++ b/target/arm/ptw.c
19
@@ -XXX,XX +XXX,XX @@ typedef struct S1Translate {
20
* Stage 2 is indicated by in_mmu_idx set to ARMMMUIdx_Stage2{,_S}.
21
*/
22
bool in_s1_is_el0;
23
- bool out_secure;
24
bool out_rw;
25
bool out_be;
26
ARMSecuritySpace out_space;
27
@@ -XXX,XX +XXX,XX @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
28
pte_attrs = s2.cacheattrs.attrs;
29
ptw->out_host = NULL;
30
ptw->out_rw = false;
31
- ptw->out_secure = s2.f.attrs.secure;
32
ptw->out_space = s2.f.attrs.space;
33
} else {
34
#ifdef CONFIG_TCG
35
@@ -XXX,XX +XXX,XX @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
36
ptw->out_phys = full->phys_addr | (addr & ~TARGET_PAGE_MASK);
37
ptw->out_rw = full->prot & PAGE_WRITE;
38
pte_attrs = full->pte_attrs;
39
- ptw->out_secure = full->attrs.secure;
40
ptw->out_space = full->attrs.space;
41
#else
42
g_assert_not_reached();
43
@@ -XXX,XX +XXX,XX @@ static uint32_t arm_ldl_ptw(CPUARMState *env, S1Translate *ptw,
44
} else {
45
/* Page tables are in MMIO. */
46
MemTxAttrs attrs = {
47
- .secure = ptw->out_secure,
48
.space = ptw->out_space,
49
+ .secure = arm_space_is_secure(ptw->out_space),
50
};
51
AddressSpace *as = arm_addressspace(cs, attrs);
52
MemTxResult result = MEMTX_OK;
53
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_ldq_ptw(CPUARMState *env, S1Translate *ptw,
54
} else {
55
/* Page tables are in MMIO. */
56
MemTxAttrs attrs = {
57
- .secure = ptw->out_secure,
58
.space = ptw->out_space,
59
+ .secure = arm_space_is_secure(ptw->out_space),
60
};
61
AddressSpace *as = arm_addressspace(cs, attrs);
62
MemTxResult result = MEMTX_OK;
63
--
64
2.34.1
diff view generated by jsdifflib