* [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS
@ 2025-07-27 8:01 Richard Henderson
2025-07-27 8:01 ` [PATCH 01/82] target/arm: Add prot_check parameter to pmsav8_mpu_lookup Richard Henderson
` (81 more replies)
0 siblings, 82 replies; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Based-on: 20250727074202.83141-1-richard.henderson@linaro.org
("[PATCH for-10.2 v9 0/6] target/arm: Add FEAT_MEC to max cpu")
Based-on: 20250725230849.13026-1-richard.henderson@linaro.org
("[PATCH for-10.2 v2 0/3] linux-user/aarch64: Syndrome fixes and enhancements")
Tree: https://gitlab.com/rth7680/qemu/-/tree/tgt-arm-gcs
This includes the prerequisite features, ATS1A and S1PIE, and
not a prerequisite but closely related, S2PIE.
This passes the linux kselftests for gcs, with a 48-bit VA.
I also include a few smoke tests in tests/tcg/.
There's something subtly wrong with a 52-bit VA. Most everything
works fine, but the first GCS lookup faults on a missing level 3
page table entry: a Translation fault, not a Permission fault.
The kernel then panics. Either there's something amiss with our
implementation of FEAT_LPA2, or there's a kernel bug.
This includes a best-effort linux-user implementation. Since we
don't have softmmu in user-only (yet), gcs stack pages get normal
read/write access. This means we cannot write-protect the pages
in the same way the system implementation can. But all of the
other parts of GCS work fine, which is good enough for testing.
r~
Richard Henderson (82):
target/arm: Add prot_check parameter to pmsav8_mpu_lookup
target/arm: Add in_prot_check to S1Translate
target/arm: Skip permission check from
arm_cpu_get_phys_page_attrs_debug
target/arm: Introduce get_phys_addr_for_at
target/arm: Skip AF and DB updates for AccessType_AT
target/arm: Add prot_check parameter to do_ats_write
target/arm: Fill in HFG[RWI]TR_EL2 bits for Arm v9.5
target/arm: Remove outdated comment for ZCR_EL12
target/arm: Implement FEAT_ATS1A
target/arm: Add isar feature test for FEAT_S1PIE, FEAT_S2PIE
target/arm: Enable TCR2_ELx.PIE
target/arm: Implement PIR_ELx, PIRE0_ELx, S2PIR_EL2 registers
target/arm: Force HPD for stage2 translations
target/arm: Cache NV1 early in get_phys_addr_lpae
target/arm: Populate PIE in aa64_va_parameters
target/arm: Implement get_S1prot_indirect
target/arm: Implement get_S2prot_indirect
target/arm: Do not migrate env->exception
target/arm: Expand CPUARMState.exception.syndrome to 64 bits
target/arm: Expand syndrome parameter to raise_exception*
target/arm: Implement dirtybit check for PIE
target/arm: Enable FEAT_S1PIE and FEAT_S2PIE on -cpu max
include/hw/core/cpu: Introduce MMUIdxMap
include/hw/core/cpu: Introduce cpu_tlb_fast
include/hw/core/cpu: Invert the indexing into CPUTLBDescFast
target/hppa: Adjust mmu indexes to begin with 0
include/exec/memopidx: Adjust for 32 mmu indexes
include/hw/core/cpu: Widen MMUIdxMap
target/arm: Split out mmuidx.h from cpu.h
target/arm: Convert arm_mmu_idx_to_el from switch to table
target/arm: Remove unused env argument from regime_el
target/arm: Convert regime_el from switch to table
target/arm: Convert regime_has_2_ranges from switch to table
target/arm: Remove unused env argument from regime_is_pan
target/arm: Convert regime_is_pan from switch to table
target/arm: Remove unused env argument from regime_is_user
target/arm: Convert regime_is_user from switch to table
target/arm: Convert arm_mmu_idx_is_stage1_of_2 from switch to table
target/arm: Convert regime_is_stage2 to table
target/arm: Introduce mmu indexes for GCS
target/arm: Introduce regime_to_gcs
target/arm: Support page protections for GCS mmu indexes
target/arm: Implement gcs bit for data abort
target/arm: Add GCS cpregs
target/arm: Add GCS enable and trap levels to DisasContext
target/arm: Implement FEAT_CHK
target/arm: Expand pstate to 64 bits
target/arm: Add syndrome data for EC_GCS
target/arm: Implement EXLOCKException for ELR_ELx and SPSR_ELx
target/arm: Split {arm,core}_user_mem_index
target/arm: Introduce delay_exception{_el}
target/arm: Emit HSTR trap exception out of line
target/arm: Emit v7m LTPSIZE exception out of line
target/arm: Implement GCSSTR, GCSSTTR
target/arm: Implement GCSB
target/arm: Implement GCSPUSHM
target/arm: Implement GCSPOPM
target/arm: Implement GCSPUSHX
target/arm: Implement GCSPOPX
target/arm: Implement GCSPOPCX
target/arm: Implement GCSSS1
target/arm: Implement GCSSS2
target/arm: Add gcs record for BL
target/arm: Add gcs record for BLR
target/arm: Add gcs record for BLR with PAuth
target/arm: Load gcs record for RET
target/arm: Load gcs record for RET with PAuth
target/arm: Copy EXLOCKEn to EXLOCK on exception to the same EL
target/arm: Implement EXLOCK check during exception return
target/arm: Enable FEAT_GCS with -cpu max
linux-user/aarch64: Implement prctls for GCS
linux-user/aarch64: Allocate new gcs stack on clone
linux-user/aarch64: Release gcs stack on thread exit
linux-user/aarch64: Implement map_shadow_stack syscall
target/arm: Enable GCSPR_EL0 for read in user-mode
linux-user/aarch64: Inject SIGSEGV for GCS faults
linux-user/aarch64: Generate GCS signal records
linux-user: Change exported get_elf_hwcap to abi_ulong
linux-user/aarch64: Enable GCS in HWCAP
tests/tcg/aarch64: Add gcsstr
tests/tcg/aarch64: Add gcspushm
tests/tcg/aarch64: Add gcsss
include/exec/cputlb.h | 32 +--
include/exec/memopidx.h | 9 +-
include/hw/core/cpu.h | 20 +-
linux-user/aarch64/gcs-internal.h | 38 +++
linux-user/aarch64/target_prctl.h | 96 +++++++
linux-user/aarch64/target_signal.h | 1 +
linux-user/loader.h | 2 +-
linux-user/qemu.h | 5 +
target/arm/cpregs.h | 46 ++-
target/arm/cpu-features.h | 20 ++
target/arm/cpu.h | 242 ++--------------
target/arm/internals.h | 170 ++---------
target/arm/mmuidx-internal.h | 111 ++++++++
target/arm/mmuidx.h | 241 ++++++++++++++++
target/arm/syndrome.h | 35 +++
target/arm/tcg/translate.h | 46 ++-
target/hppa/cpu.h | 28 +-
tests/tcg/aarch64/gcs.h | 80 ++++++
accel/tcg/cputlb.c | 49 ++--
linux-user/aarch64/cpu_loop.c | 5 +
linux-user/aarch64/signal.c | 129 ++++++++-
linux-user/elfload.c | 11 +-
linux-user/syscall.c | 114 ++++++++
target/arm/cpregs-gcs.c | 141 ++++++++++
target/arm/cpu.c | 17 +-
target/arm/gdbstub64.c | 1 +
target/arm/helper.c | 270 ++++++++++++++----
target/arm/machine.c | 62 +++-
target/arm/mmuidx.c | 66 +++++
target/arm/ptw.c | 430 +++++++++++++++++++++-------
target/arm/tcg-stubs.c | 2 +-
target/arm/tcg/cpregs-at.c | 69 +++--
target/arm/tcg/cpu64.c | 4 +
target/arm/tcg/helper-a64.c | 13 +-
target/arm/tcg/hflags.c | 38 +++
target/arm/tcg/m_helper.c | 4 +-
target/arm/tcg/mte_helper.c | 2 +-
target/arm/tcg/op_helper.c | 8 +-
target/arm/tcg/tlb-insns.c | 47 +++-
target/arm/tcg/tlb_helper.c | 13 +-
target/arm/tcg/translate-a64.c | 437 ++++++++++++++++++++++++++---
target/arm/tcg/translate.c | 78 +++--
tcg/tcg.c | 3 +-
tests/tcg/aarch64/gcspushm.c | 77 +++++
tests/tcg/aarch64/gcsss.c | 74 +++++
tests/tcg/aarch64/gcsstr.c | 48 ++++
docs/system/arm/emulation.rst | 5 +
target/arm/meson.build | 9 +-
target/arm/tcg/a64.decode | 5 +
tests/tcg/aarch64/Makefile.target | 5 +
50 files changed, 2764 insertions(+), 694 deletions(-)
create mode 100644 linux-user/aarch64/gcs-internal.h
create mode 100644 target/arm/mmuidx-internal.h
create mode 100644 target/arm/mmuidx.h
create mode 100644 tests/tcg/aarch64/gcs.h
create mode 100644 target/arm/cpregs-gcs.c
create mode 100644 target/arm/mmuidx.c
create mode 100644 tests/tcg/aarch64/gcspushm.c
create mode 100644 tests/tcg/aarch64/gcsss.c
create mode 100644 tests/tcg/aarch64/gcsstr.c
--
2.43.0
^ permalink raw reply [flat|nested] 188+ messages in thread
* [PATCH 01/82] target/arm: Add prot_check parameter to pmsav8_mpu_lookup
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 20:27 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 02/82] target/arm: Add in_prot_check to S1Translate Richard Henderson
` (80 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Separate the access_type from the protection check.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/internals.h | 5 +++--
target/arm/ptw.c | 11 ++++++-----
target/arm/tcg/m_helper.c | 4 ++--
3 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 118659815f..326b5a73cf 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1626,8 +1626,9 @@ bool get_phys_addr_with_space_nogpc(CPUARMState *env, vaddr address,
__attribute__((nonnull));
bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
- MMUAccessType access_type, ARMMMUIdx mmu_idx,
- bool is_secure, GetPhysAddrResult *result,
+ MMUAccessType access_type, unsigned prot_check,
+ ARMMMUIdx mmu_idx, bool is_secure,
+ GetPhysAddrResult *result,
ARMMMUFaultInfo *fi, uint32_t *mregion);
void arm_log_exception(CPUState *cs);
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 561bf2678e..a914e7e23c 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -2561,8 +2561,9 @@ static uint32_t *regime_rlar(CPUARMState *env, ARMMMUIdx mmu_idx,
}
bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
- MMUAccessType access_type, ARMMMUIdx mmu_idx,
- bool secure, GetPhysAddrResult *result,
+ MMUAccessType access_type, unsigned prot_check,
+ ARMMMUIdx mmu_idx, bool secure,
+ GetPhysAddrResult *result,
ARMMMUFaultInfo *fi, uint32_t *mregion)
{
/*
@@ -2750,7 +2751,7 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
if (arm_feature(env, ARM_FEATURE_M)) {
fi->level = 1;
}
- return !(result->f.prot & (1 << access_type));
+ return (prot_check & ~result->f.prot) != 0;
}
static bool v8m_is_sau_exempt(CPUARMState *env,
@@ -2952,8 +2953,8 @@ static bool get_phys_addr_pmsav8(CPUARMState *env,
}
}
- ret = pmsav8_mpu_lookup(env, address, access_type, mmu_idx, secure,
- result, fi, NULL);
+ ret = pmsav8_mpu_lookup(env, address, access_type, 1 << access_type,
+ mmu_idx, secure, result, fi, NULL);
if (sattrs.subpage) {
result->f.lg_page_size = 0;
}
diff --git a/target/arm/tcg/m_helper.c b/target/arm/tcg/m_helper.c
index 28307b5615..d856e3bc8e 100644
--- a/target/arm/tcg/m_helper.c
+++ b/target/arm/tcg/m_helper.c
@@ -2829,8 +2829,8 @@ uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op)
ARMMMUFaultInfo fi = {};
/* We can ignore the return value as prot is always set */
- pmsav8_mpu_lookup(env, addr, MMU_DATA_LOAD, mmu_idx, targetsec,
- &res, &fi, &mregion);
+ pmsav8_mpu_lookup(env, addr, MMU_DATA_LOAD, PAGE_READ, mmu_idx,
+ targetsec, &res, &fi, &mregion);
if (mregion == -1) {
mrvalid = false;
mregion = 0;
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 02/82] target/arm: Add in_prot_check to S1Translate
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
2025-07-27 8:01 ` [PATCH 01/82] target/arm: Add prot_check parameter to pmsav8_mpu_lookup Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 20:27 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 03/82] target/arm: Skip permission check from arm_cpu_get_phys_page_attrs_debug Richard Henderson
` (79 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Separate the access_type from the protection check.
Save the trouble of modifying all helper functions
by passing the new data in the control structure.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/ptw.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index a914e7e23c..1b90e33f52 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -64,6 +64,12 @@ typedef struct S1Translate {
* Stage 2 is indicated by in_mmu_idx set to ARMMMUIdx_Stage2{,_S}.
*/
bool in_s1_is_el0;
+ /*
+ * The set of PAGE_* bits to be use in the permission check.
+ * This is normally directly related to the access_type, but
+ * may be suppressed for debug or AT insns.
+ */
+ uint8_t in_prot_check;
bool out_rw;
bool out_be;
ARMSecuritySpace out_space;
@@ -581,6 +587,7 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
.in_ptw_idx = ptw_idx_for_stage_2(env, s2_mmu_idx),
.in_space = s2_space,
.in_debug = true,
+ .in_prot_check = PAGE_READ,
};
GetPhysAddrResult s2 = { };
@@ -1089,7 +1096,7 @@ static bool get_phys_addr_v5(CPUARMState *env, S1Translate *ptw,
}
result->f.prot = ap_to_rw_prot(env, ptw->in_mmu_idx, ap, domain_prot);
result->f.prot |= result->f.prot ? PAGE_EXEC : 0;
- if (!(result->f.prot & (1 << access_type))) {
+ if (ptw->in_prot_check & ~result->f.prot) {
/* Access permission fault. */
fi->type = ARMFault_Permission;
goto do_fault;
@@ -1243,7 +1250,7 @@ static bool get_phys_addr_v6(CPUARMState *env, S1Translate *ptw,
result->f.prot = get_S1prot(env, mmu_idx, false, user_rw, prot_rw,
xn, pxn, result->f.attrs.space, out_space);
- if (!(result->f.prot & (1 << access_type))) {
+ if (ptw->in_prot_check & ~result->f.prot) {
/* Access permission fault. */
fi->type = ARMFault_Permission;
goto do_fault;
@@ -2123,7 +2130,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
result->f.tlb_fill_flags = 0;
}
- if (!(result->f.prot & (1 << access_type))) {
+ if (ptw->in_prot_check & ~result->f.prot) {
fi->type = ARMFault_Permission;
goto do_fault;
}
@@ -2537,7 +2544,7 @@ static bool get_phys_addr_pmsav7(CPUARMState *env,
fi->type = ARMFault_Permission;
fi->level = 1;
- return !(result->f.prot & (1 << access_type));
+ return (ptw->in_prot_check & ~result->f.prot) != 0;
}
static uint32_t *regime_rbar(CPUARMState *env, ARMMMUIdx mmu_idx,
@@ -2953,7 +2960,7 @@ static bool get_phys_addr_pmsav8(CPUARMState *env,
}
}
- ret = pmsav8_mpu_lookup(env, address, access_type, 1 << access_type,
+ ret = pmsav8_mpu_lookup(env, address, access_type, ptw->in_prot_check,
mmu_idx, secure, result, fi, NULL);
if (sattrs.subpage) {
result->f.lg_page_size = 0;
@@ -3625,6 +3632,7 @@ bool get_phys_addr(CPUARMState *env, vaddr address,
S1Translate ptw = {
.in_mmu_idx = mmu_idx,
.in_space = arm_mmu_idx_to_security_space(env, mmu_idx),
+ .in_prot_check = 1 << access_type,
};
return get_phys_addr_gpc(env, &ptw, address, access_type,
@@ -3638,6 +3646,7 @@ static hwaddr arm_cpu_get_phys_page(CPUARMState *env, vaddr addr,
.in_mmu_idx = mmu_idx,
.in_space = arm_mmu_idx_to_security_space(env, mmu_idx),
.in_debug = true,
+ .in_prot_check = PAGE_READ,
};
GetPhysAddrResult res = {};
ARMMMUFaultInfo fi = {};
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 03/82] target/arm: Skip permission check from arm_cpu_get_phys_page_attrs_debug
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
2025-07-27 8:01 ` [PATCH 01/82] target/arm: Add prot_check parameter to pmsav8_mpu_lookup Richard Henderson
2025-07-27 8:01 ` [PATCH 02/82] target/arm: Add in_prot_check to S1Translate Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 20:28 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 04/82] target/arm: Introduce get_phys_addr_for_at Richard Henderson
` (78 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Do not require read permission when translating addresses
for debugging purposes.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/ptw.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 1b90e33f52..c7db93b95c 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -3646,7 +3646,7 @@ static hwaddr arm_cpu_get_phys_page(CPUARMState *env, vaddr addr,
.in_mmu_idx = mmu_idx,
.in_space = arm_mmu_idx_to_security_space(env, mmu_idx),
.in_debug = true,
- .in_prot_check = PAGE_READ,
+ .in_prot_check = 0,
};
GetPhysAddrResult res = {};
ARMMMUFaultInfo fi = {};
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 04/82] target/arm: Introduce get_phys_addr_for_at
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (2 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 03/82] target/arm: Skip permission check from arm_cpu_get_phys_page_attrs_debug Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 20:29 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 05/82] target/arm: Skip AF and DB updates for AccessType_AT Richard Henderson
` (77 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Rename get_phys_addr_with_space_nogpc for its only
caller, do_ats_write. Drop the MemOp memop argument
as it doesn't make sense in the new context. Replace
the access_type parameter with prot_check.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/internals.h | 18 +++++++-----------
target/arm/ptw.c | 21 ++++++++++++++-------
target/arm/tcg/cpregs-at.c | 11 ++---------
3 files changed, 23 insertions(+), 27 deletions(-)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 326b5a73cf..0dd1b214c8 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1604,25 +1604,21 @@ bool get_phys_addr(CPUARMState *env, vaddr address,
__attribute__((nonnull));
/**
- * get_phys_addr_with_space_nogpc: get the physical address for a virtual
- * address
+ * get_phys_addr_for_at:
* @env: CPUARMState
* @address: virtual address to get physical address for
- * @access_type: 0 for read, 1 for write, 2 for execute
- * @memop: memory operation feeding this access, or 0 for none
+ * @prot_check: PAGE_{READ,WRITE,EXEC}, or 0
* @mmu_idx: MMU index indicating required translation regime
* @space: security space for the access
* @result: set on translation success.
* @fi: set to fault info if the translation fails
*
- * Similar to get_phys_addr, but use the given security space and don't perform
- * a Granule Protection Check on the resulting address.
+ * Similar to get_phys_addr, but for use by AccessType_AT, i.e.
+ * system instructions for address translation.
*/
-bool get_phys_addr_with_space_nogpc(CPUARMState *env, vaddr address,
- MMUAccessType access_type, MemOp memop,
- ARMMMUIdx mmu_idx, ARMSecuritySpace space,
- GetPhysAddrResult *result,
- ARMMMUFaultInfo *fi)
+bool get_phys_addr_for_at(CPUARMState *env, vaddr address, unsigned prot_check,
+ ARMMMUIdx mmu_idx, ARMSecuritySpace space,
+ GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
__attribute__((nonnull));
bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index c7db93b95c..1866c494ef 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -3545,18 +3545,25 @@ static bool get_phys_addr_gpc(CPUARMState *env, S1Translate *ptw,
return false;
}
-bool get_phys_addr_with_space_nogpc(CPUARMState *env, vaddr address,
- MMUAccessType access_type, MemOp memop,
- ARMMMUIdx mmu_idx, ARMSecuritySpace space,
- GetPhysAddrResult *result,
- ARMMMUFaultInfo *fi)
+bool get_phys_addr_for_at(CPUARMState *env, vaddr address,
+ unsigned prot_check, ARMMMUIdx mmu_idx,
+ ARMSecuritySpace space, GetPhysAddrResult *result,
+ ARMMMUFaultInfo *fi)
{
S1Translate ptw = {
.in_mmu_idx = mmu_idx,
.in_space = space,
+ .in_prot_check = prot_check,
};
- return get_phys_addr_nogpc(env, &ptw, address, access_type,
- memop, result, fi);
+ /*
+ * I_MXTJT: Granule protection checks are not performed on the final
+ * address of a successful translation. This is a translation not a
+ * memory reference, so MMU_DATA_LOAD is arbitrary (the exact protection
+ * check is handled or bypassed by .in_prot_check) and "memop = MO_8"
+ * bypasses any alignment check.
+ */
+ return get_phys_addr_nogpc(env, &ptw, address,
+ MMU_DATA_LOAD, MO_8, result, fi);
}
static ARMSecuritySpace
diff --git a/target/arm/tcg/cpregs-at.c b/target/arm/tcg/cpregs-at.c
index 398a61d398..2ff0b3e76f 100644
--- a/target/arm/tcg/cpregs-at.c
+++ b/target/arm/tcg/cpregs-at.c
@@ -27,19 +27,12 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
MMUAccessType access_type, ARMMMUIdx mmu_idx,
ARMSecuritySpace ss)
{
- bool ret;
uint64_t par64;
bool format64 = false;
ARMMMUFaultInfo fi = {};
GetPhysAddrResult res = {};
-
- /*
- * I_MXTJT: Granule protection checks are not performed on the final
- * address of a successful translation. This is a translation not a
- * memory reference, so "memop = none = 0".
- */
- ret = get_phys_addr_with_space_nogpc(env, value, access_type, 0,
- mmu_idx, ss, &res, &fi);
+ bool ret = get_phys_addr_for_at(env, value, 1 << access_type,
+ mmu_idx, ss, &res, &fi);
/*
* ATS operations only do S1 or S1+S2 translations, so we never
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 05/82] target/arm: Skip AF and DB updates for AccessType_AT
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (3 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 04/82] target/arm: Introduce get_phys_addr_for_at Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 20:31 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 06/82] target/arm: Add prot_check parameter to do_ats_write Richard Henderson
` (76 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
We are required to skip DB update for AT instructions, and
we are allowed to skip AF updates. Choose to skip both.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/ptw.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 1866c494ef..efbad7af1f 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -58,6 +58,12 @@ typedef struct S1Translate {
* and will not change the state of the softmmu TLBs.
*/
bool in_debug;
+ /*
+ * in_at: is this AccessType_AT?
+ * This is also set for debug, because at heart that is also
+ * an address translation, and simplifies a test.
+ */
+ bool in_at;
/*
* If this is stage 2 of a stage 1+2 page table walk, then this must
* be true if stage 1 is an EL0 access; otherwise this is ignored.
@@ -1929,7 +1935,12 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
descaddr &= ~(hwaddr)(page_size - 1);
descaddr |= (address & (page_size - 1));
- if (likely(!ptw->in_debug)) {
+ /*
+ * For AccessType_AT, DB is not updated (AArch64.SetDirtyFlag),
+ * and it is IMPLEMENTATION DEFINED whether AF is updated
+ * (AArch64.SetAccessFlag; qemu chooses to not update).
+ */
+ if (likely(!ptw->in_at)) {
/*
* Access flag.
* If HA is enabled, prepare to update the descriptor below.
@@ -3553,6 +3564,7 @@ bool get_phys_addr_for_at(CPUARMState *env, vaddr address,
S1Translate ptw = {
.in_mmu_idx = mmu_idx,
.in_space = space,
+ .in_at = true,
.in_prot_check = prot_check,
};
/*
@@ -3653,6 +3665,7 @@ static hwaddr arm_cpu_get_phys_page(CPUARMState *env, vaddr addr,
.in_mmu_idx = mmu_idx,
.in_space = arm_mmu_idx_to_security_space(env, mmu_idx),
.in_debug = true,
+ .in_at = true,
.in_prot_check = 0,
};
GetPhysAddrResult res = {};
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 06/82] target/arm: Add prot_check parameter to do_ats_write
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (4 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 05/82] target/arm: Skip AF and DB updates for AccessType_AT Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 20:35 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 07/82] target/arm: Fill in HFG[RWI]TR_EL2 bits for Arm v9.5 Richard Henderson
` (75 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Separate protection check from access type, in preparation
for skipping the protection check altogether.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/tcg/cpregs-at.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/target/arm/tcg/cpregs-at.c b/target/arm/tcg/cpregs-at.c
index 2ff0b3e76f..bebf168997 100644
--- a/target/arm/tcg/cpregs-at.c
+++ b/target/arm/tcg/cpregs-at.c
@@ -24,14 +24,14 @@ static int par_el1_shareability(GetPhysAddrResult *res)
}
static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
- MMUAccessType access_type, ARMMMUIdx mmu_idx,
+ unsigned prot_check, ARMMMUIdx mmu_idx,
ARMSecuritySpace ss)
{
uint64_t par64;
bool format64 = false;
ARMMMUFaultInfo fi = {};
GetPhysAddrResult res = {};
- bool ret = get_phys_addr_for_at(env, value, 1 << access_type,
+ bool ret = get_phys_addr_for_at(env, value, prot_check,
mmu_idx, ss, &res, &fi);
/*
@@ -191,7 +191,7 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
{
- MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD;
+ unsigned access_perm = ri->opc2 & 1 ? PAGE_WRITE : PAGE_READ;
uint64_t par64;
ARMMMUIdx mmu_idx;
int el = arm_current_el(env);
@@ -253,7 +253,7 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
g_assert_not_reached();
}
- par64 = do_ats_write(env, value, access_type, mmu_idx, ss);
+ par64 = do_ats_write(env, value, access_perm, mmu_idx, ss);
A32_BANKED_CURRENT_REG_SET(env, par, par64);
}
@@ -261,11 +261,11 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
static void ats1h_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value)
{
- MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD;
+ unsigned access_perm = ri->opc2 & 1 ? PAGE_WRITE : PAGE_READ;
uint64_t par64;
/* There is no SecureEL2 for AArch32. */
- par64 = do_ats_write(env, value, access_type, ARMMMUIdx_E2,
+ par64 = do_ats_write(env, value, access_perm, ARMMMUIdx_E2,
ARMSS_NonSecure);
A32_BANKED_CURRENT_REG_SET(env, par, par64);
@@ -309,7 +309,7 @@ static CPAccessResult at_s1e01_access(CPUARMState *env, const ARMCPRegInfo *ri,
static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value)
{
- MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD;
+ unsigned access_perm = ri->opc2 & 1 ? PAGE_WRITE : PAGE_READ;
ARMMMUIdx mmu_idx;
uint64_t hcr_el2 = arm_hcr_el2_eff(env);
bool regime_e20 = (hcr_el2 & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE);
@@ -352,7 +352,7 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
}
ss = for_el3 ? arm_security_space(env) : arm_security_space_below_el3(env);
- env->cp15.par_el[1] = do_ats_write(env, value, access_type, mmu_idx, ss);
+ env->cp15.par_el[1] = do_ats_write(env, value, access_perm, mmu_idx, ss);
}
static CPAccessResult ats_access(CPUARMState *env, const ARMCPRegInfo *ri,
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 07/82] target/arm: Fill in HFG[RWI]TR_EL2 bits for Arm v9.5
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (5 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 06/82] target/arm: Add prot_check parameter to do_ats_write Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 20:35 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 08/82] target/arm: Remove outdated comment for ZCR_EL12 Richard Henderson
` (74 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpregs.h | 28 ++++++++++++++++++++++++++--
1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
index c9506aa6d5..1d103b577f 100644
--- a/target/arm/cpregs.h
+++ b/target/arm/cpregs.h
@@ -408,10 +408,19 @@ FIELD(HFGRTR_EL2, ERXPFGCTL_EL1, 47, 1)
FIELD(HFGRTR_EL2, ERXPFGCDN_EL1, 48, 1)
FIELD(HFGRTR_EL2, ERXADDR_EL1, 49, 1)
FIELD(HFGRTR_EL2, NACCDATA_EL1, 50, 1)
-/* 51-53: RES0 */
+/* 51: RES0 */
+FIELD(HFGRTR_EL2, NGCS_EL0, 52, 1)
+FIELD(HFGRTR_EL2, NGCS_EL1, 53, 1)
FIELD(HFGRTR_EL2, NSMPRI_EL1, 54, 1)
FIELD(HFGRTR_EL2, NTPIDR2_EL0, 55, 1)
-/* 56-63: RES0 */
+FIELD(HFGRTR_EL2, NRCWMASK_EL1, 56, 1)
+FIELD(HFGRTR_EL2, NPIRE0_EL1, 57, 1)
+FIELD(HFGRTR_EL2, NPIR_EL1, 58, 1)
+FIELD(HFGRTR_EL2, NPOR_EL0, 59, 1)
+FIELD(HFGRTR_EL2, NPOR_EL1, 60, 1)
+FIELD(HFGRTR_EL2, NS2POR_EL1, 61, 1)
+FIELD(HFGRTR_EL2, NMAIR2_EL1, 62, 1)
+FIELD(HFGRTR_EL2, NAMAIR2_EL1, 63, 1)
/* These match HFGRTR but bits for RO registers are RES0 */
FIELD(HFGWTR_EL2, AFSR0_EL1, 0, 1)
@@ -452,8 +461,18 @@ FIELD(HFGWTR_EL2, ERXPFGCTL_EL1, 47, 1)
FIELD(HFGWTR_EL2, ERXPFGCDN_EL1, 48, 1)
FIELD(HFGWTR_EL2, ERXADDR_EL1, 49, 1)
FIELD(HFGWTR_EL2, NACCDATA_EL1, 50, 1)
+FIELD(HFGWTR_EL2, NGCS_EL0, 52, 1)
+FIELD(HFGWTR_EL2, NGCS_EL1, 53, 1)
FIELD(HFGWTR_EL2, NSMPRI_EL1, 54, 1)
FIELD(HFGWTR_EL2, NTPIDR2_EL0, 55, 1)
+FIELD(HFGWTR_EL2, NRCWMASK_EL1, 56, 1)
+FIELD(HFGWTR_EL2, NPIRE0_EL1, 57, 1)
+FIELD(HFGWTR_EL2, NPIR_EL1, 58, 1)
+FIELD(HFGWTR_EL2, NPOR_EL0, 59, 1)
+FIELD(HFGWTR_EL2, NPOR_EL1, 60, 1)
+FIELD(HFGWTR_EL2, NS2POR_EL1, 61, 1)
+FIELD(HFGWTR_EL2, NMAIR2_EL1, 62, 1)
+FIELD(HFGWTR_EL2, NAMAIR2_EL1, 63, 1)
FIELD(HFGITR_EL2, ICIALLUIS, 0, 1)
FIELD(HFGITR_EL2, ICIALLU, 1, 1)
@@ -512,6 +531,11 @@ FIELD(HFGITR_EL2, SVC_EL1, 53, 1)
FIELD(HFGITR_EL2, DCCVAC, 54, 1)
FIELD(HFGITR_EL2, NBRBINJ, 55, 1)
FIELD(HFGITR_EL2, NBRBIALL, 56, 1)
+FIELD(HFGITR_EL2, NGCSPUSHM_EL1, 57, 1)
+FIELD(HFGITR_EL2, NGCSSTR_EL1, 58, 1)
+FIELD(HFGITR_EL2, NGCSEPP, 59, 1)
+FIELD(HFGITR_EL2, COSPRCTX, 60, 1)
+FIELD(HFGITR_EL2, ATS1E1A, 62, 1)
FIELD(HDFGRTR_EL2, DBGBCRN_EL1, 0, 1)
FIELD(HDFGRTR_EL2, DBGBVRN_EL1, 1, 1)
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 08/82] target/arm: Remove outdated comment for ZCR_EL12
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (6 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 07/82] target/arm: Fill in HFG[RWI]TR_EL2 bits for Arm v9.5 Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 20:36 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 09/82] target/arm: Implement FEAT_ATS1A Richard Henderson
` (73 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
The comment about not being included in the summary table
has been out of date for quite a while.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/helper.c | 5 -----
1 file changed, 5 deletions(-)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 20b69a12df..dc6c82b7e2 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -4566,11 +4566,6 @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
{ K(3, 0, 14, 1, 0), K(3, 4, 14, 1, 0), K(3, 5, 14, 1, 0),
"CNTKCTL", "CNTHCTL_EL2", "CNTKCTL_EL12" },
- /*
- * Note that redirection of ZCR is mentioned in the description
- * of ZCR_EL2, and aliasing in the description of ZCR_EL1, but
- * not in the summary table.
- */
{ K(3, 0, 1, 2, 0), K(3, 4, 1, 2, 0), K(3, 5, 1, 2, 0),
"ZCR_EL1", "ZCR_EL2", "ZCR_EL12", isar_feature_aa64_sve },
{ K(3, 0, 1, 2, 6), K(3, 4, 1, 2, 6), K(3, 5, 1, 2, 6),
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 09/82] target/arm: Implement FEAT_ATS1A
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (7 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 08/82] target/arm: Remove outdated comment for ZCR_EL12 Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 20:38 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 10/82] target/arm: Add isar feature test for FEAT_S1PIE, FEAT_S2PIE Richard Henderson
` (72 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Implement FEAT_ATS1A and enable for -cpu max.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpregs.h | 1 +
target/arm/cpu-features.h | 5 ++++
target/arm/tcg/cpregs-at.c | 44 +++++++++++++++++++++++++++++++++++
target/arm/tcg/cpu64.c | 1 +
docs/system/arm/emulation.rst | 1 +
5 files changed, 52 insertions(+)
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
index 1d103b577f..2a4826f5c4 100644
--- a/target/arm/cpregs.h
+++ b/target/arm/cpregs.h
@@ -854,6 +854,7 @@ typedef enum FGTBit {
DO_BIT(HFGITR, DVPRCTX),
DO_BIT(HFGITR, CPPRCTX),
DO_BIT(HFGITR, DCCVAC),
+ DO_BIT(HFGITR, ATS1E1A),
} FGTBit;
#undef DO_BIT
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index 9579d93cec..7f2ca51b4c 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -609,6 +609,11 @@ static inline bool isar_feature_aa64_lut(const ARMISARegisters *id)
return FIELD_EX64_IDREG(id, ID_AA64ISAR2, LUT);
}
+static inline bool isar_feature_aa64_ats1a(const ARMISARegisters *id)
+{
+ return FIELD_EX64_IDREG(id, ID_AA64ISAR2, ATS1A);
+}
+
static inline bool isar_feature_aa64_fp_simd(const ARMISARegisters *id)
{
/* We always set the AdvSIMD and FP fields identically. */
diff --git a/target/arm/tcg/cpregs-at.c b/target/arm/tcg/cpregs-at.c
index bebf168997..0e8f229aa7 100644
--- a/target/arm/tcg/cpregs-at.c
+++ b/target/arm/tcg/cpregs-at.c
@@ -488,6 +488,47 @@ static const ARMCPRegInfo ats1cp_reginfo[] = {
.writefn = ats_write },
};
+static void ats_s1e1a(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
+{
+ uint64_t hcr_el2 = arm_hcr_el2_eff(env);
+ bool regime_e20 = (hcr_el2 & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE);
+ ARMMMUIdx mmu_idx = regime_e20 ? ARMMMUIdx_E20_2 : ARMMMUIdx_Stage1_E1;
+ ARMSecuritySpace ss = arm_security_space_below_el3(env);
+
+ env->cp15.par_el[1] = do_ats_write(env, value, 0, mmu_idx, ss);
+}
+
+static void ats_s1e2a(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
+{
+ uint64_t hcr_el2 = arm_hcr_el2_eff(env);
+ ARMMMUIdx mmu_idx = hcr_el2 & HCR_E2H ? ARMMMUIdx_E20_2 : ARMMMUIdx_E2;
+ ARMSecuritySpace ss = arm_security_space_below_el3(env);
+
+ env->cp15.par_el[1] = do_ats_write(env, value, 0, mmu_idx, ss);
+}
+
+static void ats_s1e3a(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
+{
+ env->cp15.par_el[1] = do_ats_write(env, value, 0, ARMMMUIdx_E3,
+ arm_security_space(env));
+}
+
+static const ARMCPRegInfo ats1a_reginfo[] = {
+ { .name = "AT_S1E1A", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 2,
+ .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
+ .fgt = FGT_ATS1E1A,
+ .accessfn = at_s1e01_access, .writefn = ats_s1e1a },
+ { .name = "AT_S1E2A", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 4, .crn = 7, .crm = 9, .opc2 = 2,
+ .access = PL2_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
+ .accessfn = at_s1e2_access, .writefn = ats_s1e2a },
+ { .name = "AT_S1E3A", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 6, .crn = 7, .crm = 9, .opc2 = 2,
+ .access = PL3_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
+ .writefn = ats_s1e3a },
+};
+
void define_at_insn_regs(ARMCPU *cpu)
{
CPUARMState *env = &cpu->env;
@@ -509,4 +550,7 @@ void define_at_insn_regs(ARMCPU *cpu)
if (cpu_isar_feature(aa32_ats1e1, cpu)) {
define_arm_cp_regs(cpu, ats1cp_reginfo);
}
+ if (cpu_isar_feature(aa64_ats1a, cpu)) {
+ define_arm_cp_regs(cpu, ats1a_reginfo);
+ }
}
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index c54aa528c6..22ccc4f697 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -1178,6 +1178,7 @@ void aarch64_max_tcg_initfn(Object *obj)
t = FIELD_DP64(t, ID_AA64ISAR2, MOPS, 1); /* FEAT_MOPS */
t = FIELD_DP64(t, ID_AA64ISAR2, BC, 1); /* FEAT_HBC */
t = FIELD_DP64(t, ID_AA64ISAR2, WFXT, 2); /* FEAT_WFxT */
+ t = FIELD_DP64(t, ID_AA64ISAR2, ATS1A, 1); /* FEAT_ATS1A */
SET_IDREG(isar, ID_AA64ISAR2, t);
t = GET_IDREG(isar, ID_AA64PFR0);
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
index d207a9f266..1489c262b8 100644
--- a/docs/system/arm/emulation.rst
+++ b/docs/system/arm/emulation.rst
@@ -23,6 +23,7 @@ the following architecture extensions:
- FEAT_AFP (Alternate floating-point behavior)
- FEAT_Armv9_Crypto (Armv9 Cryptographic Extension)
- FEAT_ASID16 (16 bit ASID)
+- FEAT_ATS1A (Address Translation operations that ignore stage 1 permissions)
- FEAT_BBM at level 2 (Translation table break-before-make levels)
- FEAT_BF16 (AArch64 BFloat16 instructions)
- FEAT_BTI (Branch Target Identification)
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 10/82] target/arm: Add isar feature test for FEAT_S1PIE, FEAT_S2PIE
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (8 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 09/82] target/arm: Implement FEAT_ATS1A Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 20:38 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 11/82] target/arm: Enable TCR2_ELx.PIE Richard Henderson
` (71 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpu-features.h | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index 7f2ca51b4c..83875c06bb 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -919,6 +919,16 @@ static inline bool isar_feature_aa64_sctlr2(const ARMISARegisters *id)
return FIELD_EX64_IDREG(id, ID_AA64MMFR3, SCTLRX) != 0;
}
+static inline bool isar_feature_aa64_s1pie(const ARMISARegisters *id)
+{
+ return FIELD_EX64_IDREG(id, ID_AA64MMFR3, S1PIE) != 0;
+}
+
+static inline bool isar_feature_aa64_s2pie(const ARMISARegisters *id)
+{
+ return FIELD_EX64_IDREG(id, ID_AA64MMFR3, S2PIE) != 0;
+}
+
static inline bool isar_feature_aa64_mec(const ARMISARegisters *id)
{
return FIELD_EX64_IDREG(id, ID_AA64MMFR3, MEC) != 0;
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 11/82] target/arm: Enable TCR2_ELx.PIE
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (9 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 10/82] target/arm: Add isar feature test for FEAT_S1PIE, FEAT_S2PIE Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 20:39 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 12/82] target/arm: Implement PIR_ELx, PIRE0_ELx, S2PIR_EL2 registers Richard Henderson
` (70 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/helper.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index dc6c82b7e2..61ba9ba5b2 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6202,8 +6202,12 @@ static CPAccessResult tcr2_el1_access(CPUARMState *env, const ARMCPRegInfo *ri,
static void tcr2_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value)
{
+ ARMCPU *cpu = env_archcpu(env);
uint64_t valid_mask = 0;
+ if (cpu_isar_feature(aa64_s1pie, cpu)) {
+ valid_mask |= TCR2_PIE;
+ }
value &= valid_mask;
raw_write(env, ri, value);
}
@@ -6211,11 +6215,15 @@ static void tcr2_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
static void tcr2_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value)
{
+ ARMCPU *cpu = env_archcpu(env);
uint64_t valid_mask = 0;
- if (cpu_isar_feature(aa64_mec, env_archcpu(env))) {
+ if (cpu_isar_feature(aa64_mec, cpu)) {
valid_mask |= TCR2_AMEC0 | TCR2_AMEC1;
}
+ if (cpu_isar_feature(aa64_s1pie, cpu)) {
+ valid_mask |= TCR2_PIE;
+ }
value &= valid_mask;
raw_write(env, ri, value);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 12/82] target/arm: Implement PIR_ELx, PIRE0_ELx, S2PIR_EL2 registers
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (10 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 11/82] target/arm: Enable TCR2_ELx.PIE Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 20:41 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 13/82] target/arm: Force HPD for stage2 translations Richard Henderson
` (69 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpregs.h | 2 ++
target/arm/cpu.h | 4 +++
target/arm/cpu.c | 4 +++
target/arm/helper.c | 70 +++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 80 insertions(+)
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
index 2a4826f5c4..9efe9238c1 100644
--- a/target/arm/cpregs.h
+++ b/target/arm/cpregs.h
@@ -776,6 +776,8 @@ typedef enum FGTBit {
DO_BIT(HFGRTR, ERRIDR_EL1),
DO_REV_BIT(HFGRTR, NSMPRI_EL1),
DO_REV_BIT(HFGRTR, NTPIDR2_EL0),
+ DO_REV_BIT(HFGRTR, NPIRE0_EL1),
+ DO_REV_BIT(HFGRTR, NPIR_EL1),
/* Trap bits in HDFGRTR_EL2 / HDFGWTR_EL2, starting from bit 0. */
DO_BIT(HDFGRTR, DBGBCRN_EL1),
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index defe2852f2..fb87fcc3e6 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -369,6 +369,9 @@ typedef struct CPUArchState {
uint64_t tcr2_el[3];
uint64_t vtcr_el2; /* Virtualization Translation Control. */
uint64_t vstcr_el2; /* Secure Virtualization Translation Control. */
+ uint64_t pir_el[4]; /* PIRE0_EL1, PIR_EL1, PIR_EL2, PIR_EL3 */
+ uint64_t pire0_el2;
+ uint64_t s2pir_el2;
uint32_t c2_data; /* MPU data cacheable bits. */
uint32_t c2_insn; /* MPU instruction cacheable bits. */
union { /* MMU domain access control register
@@ -1738,6 +1741,7 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
#define SCR_ENTP2 (1ULL << 41)
#define SCR_TCR2EN (1ULL << 43)
#define SCR_SCTLR2EN (1ULL << 44)
+#define SCR_PIEN (1ULL << 45)
#define SCR_GPF (1ULL << 48)
#define SCR_MECEN (1ULL << 49)
#define SCR_NSE (1ULL << 62)
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index f0545a276e..b472992b4a 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -650,6 +650,10 @@ void arm_emulate_firmware_reset(CPUState *cpustate, int target_el)
if (cpu_isar_feature(aa64_sctlr2, cpu)) {
env->cp15.scr_el3 |= SCR_SCTLR2EN;
}
+ if (cpu_isar_feature(aa64_s1pie, cpu) ||
+ cpu_isar_feature(aa64_s2pie, cpu)) {
+ env->cp15.scr_el3 |= SCR_PIEN;
+ }
if (cpu_isar_feature(aa64_mec, cpu)) {
env->cp15.scr_el3 |= SCR_MECEN;
}
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 61ba9ba5b2..6353b2dea1 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -747,6 +747,10 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
if (cpu_isar_feature(aa64_sctlr2, cpu)) {
valid_mask |= SCR_SCTLR2EN;
}
+ if (cpu_isar_feature(aa64_s1pie, cpu) ||
+ cpu_isar_feature(aa64_s2pie, cpu)) {
+ valid_mask |= SCR_PIEN;
+ }
if (cpu_isar_feature(aa64_mec, cpu)) {
valid_mask |= SCR_MECEN;
}
@@ -4578,6 +4582,11 @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
"SCXTNUM_EL1", "SCXTNUM_EL2", "SCXTNUM_EL12",
isar_feature_aa64_scxtnum },
+ { K(3, 0, 10, 2, 3), K(3, 4, 10, 2, 3), K(3, 5, 10, 2, 3),
+ "PIR_EL1", "PIR_EL2", "PIR_EL12", isar_feature_aa64_s1pie },
+ { K(3, 0, 10, 2, 2), K(3, 4, 10, 2, 2), K(3, 5, 10, 2, 2),
+ "PIRE0_EL1", "PIRE0_EL2", "PIRE0_EL12", isar_feature_aa64_s1pie },
+
/* TODO: ARMv8.2-SPE -- PMSCR_EL2 */
/* TODO: ARMv8.4-Trace -- TRFCR_EL2 */
};
@@ -6242,6 +6251,60 @@ static const ARMCPRegInfo tcr2_reginfo[] = {
.fieldoffset = offsetof(CPUARMState, cp15.tcr2_el[2]) },
};
+static CPAccessResult pien_access(CPUARMState *env, const ARMCPRegInfo *ri,
+ bool isread)
+{
+ if (arm_feature(env, ARM_FEATURE_EL3)
+ && !(env->cp15.scr_el3 & SCR_PIEN)
+ && arm_current_el(env) < 3) {
+ return CP_ACCESS_TRAP_EL3;
+ }
+ return CP_ACCESS_OK;
+}
+
+static CPAccessResult pien_el1_access(CPUARMState *env, const ARMCPRegInfo *ri,
+ bool isread)
+{
+ CPAccessResult ret = access_tvm_trvm(env, ri, isread);
+ if (ret == CP_ACCESS_OK) {
+ ret = pien_access(env, ri, isread);
+ }
+ return ret;
+}
+
+static const ARMCPRegInfo s1pie_reginfo[] = {
+ { .name = "PIR_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .opc2 = 3, .crn = 10, .crm = 2,
+ .access = PL1_RW, .accessfn = pien_el1_access,
+ .fgt = FGT_NPIR_EL1, .nv2_redirect_offset = 0x2a0 | NV2_REDIR_NV1,
+ .fieldoffset = offsetof(CPUARMState, cp15.pir_el[1]) },
+ { .name = "PIR_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .opc2 = 3, .crn = 10, .crm = 2,
+ .access = PL2_RW, .accessfn = pien_access,
+ .fieldoffset = offsetof(CPUARMState, cp15.pir_el[2]) },
+ { .name = "PIR_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .opc2 = 3, .crn = 10, .crm = 2,
+ .access = PL3_RW,
+ .fieldoffset = offsetof(CPUARMState, cp15.pir_el[3]) },
+ { .name = "PIRE0_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .opc2 = 2, .crn = 10, .crm = 2,
+ .access = PL1_RW, .accessfn = pien_el1_access,
+ .fgt = FGT_NPIRE0_EL1, .nv2_redirect_offset = 0x290 | NV2_REDIR_NV1,
+ .fieldoffset = offsetof(CPUARMState, cp15.pir_el[0]) },
+ { .name = "PIRE0_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .opc2 = 2, .crn = 10, .crm = 2,
+ .access = PL2_RW, .accessfn = pien_access,
+ .fieldoffset = offsetof(CPUARMState, cp15.pire0_el2) },
+};
+
+static const ARMCPRegInfo s2pie_reginfo[] = {
+ { .name = "S2PIR_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .opc2 = 5, .crn = 10, .crm = 2,
+ .access = PL2_RW, .accessfn = pien_access,
+ .nv2_redirect_offset = 0x2b0,
+ .fieldoffset = offsetof(CPUARMState, cp15.s2pir_el2) },
+};
+
void register_cp_regs_for_features(ARMCPU *cpu)
{
/* Register all the coprocessor registers based on feature bits */
@@ -7479,6 +7542,13 @@ void register_cp_regs_for_features(ARMCPU *cpu)
define_arm_cp_regs(cpu, tcr2_reginfo);
}
+ if (cpu_isar_feature(aa64_s1pie, cpu)) {
+ define_arm_cp_regs(cpu, s1pie_reginfo);
+ }
+ if (cpu_isar_feature(aa64_s2pie, cpu)) {
+ define_arm_cp_regs(cpu, s2pie_reginfo);
+ }
+
if (cpu_isar_feature(aa64_mec, cpu)) {
define_arm_cp_regs(cpu, mec_reginfo);
if (cpu_isar_feature(aa64_mte, cpu)) {
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 13/82] target/arm: Force HPD for stage2 translations
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (11 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 12/82] target/arm: Implement PIR_ELx, PIRE0_ELx, S2PIR_EL2 registers Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 20:42 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 14/82] target/arm: Cache NV1 early in get_phys_addr_lpae Richard Henderson
` (68 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Stage2 translations do not have hierarchial permissions.
Setting HPD means we can eliminate an extra check against
regime_is_stage2.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/helper.c | 7 +++++--
target/arm/ptw.c | 24 +++++++++++++-----------
2 files changed, 18 insertions(+), 13 deletions(-)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 6353b2dea1..a6130f7dcd 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -9639,8 +9639,11 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
tsz = extract32(tcr, 0, 6);
gran = tg0_to_gran_size(extract32(tcr, 14, 2));
if (stage2) {
- /* VTCR_EL2 */
- hpd = false;
+ /*
+ * Stage2 does not have hierarchical permissions.
+ * Thus disabling them makes things easier during ptw.
+ */
+ hpd = true;
} else {
hpd = extract32(tcr, 24, 1);
}
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index efbad7af1f..2eb2041edb 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -1472,8 +1472,12 @@ static ARMVAParameters aa32_va_parameters(CPUARMState *env, uint32_t va,
}
tsz = sextract32(tcr, 0, 4) + 8;
select = 0;
- hpd = false;
epd = false;
+ /*
+ * Stage2 does not have hierarchical permissions.
+ * Thus disabling them makes things easier during ptw.
+ */
+ hpd = true;
} else if (el == 2) {
/* HTCR */
tsz = extract32(tcr, 0, 3);
@@ -1979,16 +1983,14 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
* except NSTable (which we have already handled).
*/
attrs = new_descriptor & (MAKE_64BIT_MASK(2, 10) | MAKE_64BIT_MASK(50, 14));
- if (!regime_is_stage2(mmu_idx)) {
- if (!param.hpd) {
- attrs |= extract64(tableattrs, 0, 2) << 53; /* XN, PXN */
- /*
- * The sense of AP[1] vs APTable[0] is reversed, as APTable[0] == 1
- * means "force PL1 access only", which means forcing AP[1] to 0.
- */
- attrs &= ~(extract64(tableattrs, 2, 1) << 6); /* !APT[0] => AP[1] */
- attrs |= extract32(tableattrs, 3, 1) << 7; /* APT[1] => AP[2] */
- }
+ if (!param.hpd) {
+ attrs |= extract64(tableattrs, 0, 2) << 53; /* XN, PXN */
+ /*
+ * The sense of AP[1] vs APTable[0] is reversed, as APTable[0] == 1
+ * means "force PL1 access only", which means forcing AP[1] to 0.
+ */
+ attrs &= ~(extract64(tableattrs, 2, 1) << 6); /* !APT[0] => AP[1] */
+ attrs |= extract32(tableattrs, 3, 1) << 7; /* APT[1] => AP[2] */
}
ap = extract32(attrs, 6, 2);
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 14/82] target/arm: Cache NV1 early in get_phys_addr_lpae
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (12 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 13/82] target/arm: Force HPD for stage2 translations Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 20:43 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 15/82] target/arm: Populate PIE in aa64_va_parameters Richard Henderson
` (67 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
We were not using the correct security space in the existing call
to nv_nv1_enabled, because it may have been modified for NSTable.
Cache it early, as we will shortly need it elsewhere as well.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/ptw.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 2eb2041edb..a5a3c03a4c 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -76,6 +76,8 @@ typedef struct S1Translate {
* may be suppressed for debug or AT insns.
*/
uint8_t in_prot_check;
+ /* Cached EffectiveHCR_EL2_NVx() bit */
+ bool in_nv1;
bool out_rw;
bool out_be;
ARMSecuritySpace out_space;
@@ -1642,12 +1644,6 @@ static bool lpae_block_desc_valid(ARMCPU *cpu, bool ds,
}
}
-static bool nv_nv1_enabled(CPUARMState *env, S1Translate *ptw)
-{
- uint64_t hcr = arm_hcr_el2_eff_secstate(env, ptw->in_space);
- return (hcr & (HCR_NV | HCR_NV1)) == (HCR_NV | HCR_NV1);
-}
-
/**
* get_phys_addr_lpae: perform one stage of page table walk, LPAE format
*
@@ -1699,6 +1695,10 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
!arm_el_is_aa64(env, 1));
level = 0;
+ /* Cache NV1 before we adjust ptw->in_space for NSTable. */
+ ptw->in_nv1 = (arm_hcr_el2_eff_secstate(env, ptw->in_space)
+ & (HCR_NV | HCR_NV1)) == (HCR_NV | HCR_NV1);
+
/*
* If TxSZ is programmed to a value larger than the maximum,
* or smaller than the effective minimum, it is IMPLEMENTATION
@@ -2074,7 +2074,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
xn = extract64(attrs, 54, 1);
pxn = extract64(attrs, 53, 1);
- if (el == 1 && nv_nv1_enabled(env, ptw)) {
+ if (el == 1 && ptw->in_nv1) {
/*
* With FEAT_NV, when HCR_EL2.{NV,NV1} == {1,1}, the block/page
* descriptor bit 54 holds PXN, 53 is RES0, and the effective value
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 15/82] target/arm: Populate PIE in aa64_va_parameters
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (13 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 14/82] target/arm: Cache NV1 early in get_phys_addr_lpae Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 20:45 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 16/82] target/arm: Implement get_S1prot_indirect Richard Henderson
` (66 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Select the PIE bit for the translation regime.
With PIE, the PTE layout changes, forcing HPD.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/internals.h | 3 ++-
target/arm/helper.c | 19 ++++++++++++++++++-
2 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 0dd1b214c8..d5f501bb30 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1488,7 +1488,7 @@ static inline int arm_granule_bits(ARMGranuleSize gran)
/*
* Parameters of a given virtual address, as extracted from the
- * translation control register (TCR) for a given regime.
+ * translation controls for a given regime.
*/
typedef struct ARMVAParameters {
unsigned tsz : 8;
@@ -1503,6 +1503,7 @@ typedef struct ARMVAParameters {
bool ha : 1;
bool hd : 1;
ARMGranuleSize gran : 2;
+ bool pie : 1;
} ARMVAParameters;
/**
diff --git a/target/arm/helper.c b/target/arm/helper.c
index a6130f7dcd..ecce93fb97 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -9628,11 +9628,12 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
bool el1_is_aa32)
{
uint64_t tcr = regime_tcr(env, mmu_idx);
- bool epd, hpd, tsz_oob, ds, ha, hd;
+ bool epd, hpd, tsz_oob, ds, ha, hd, pie = false;
int select, tsz, tbi, max_tsz, min_tsz, ps, sh;
ARMGranuleSize gran;
ARMCPU *cpu = env_archcpu(env);
bool stage2 = regime_is_stage2(mmu_idx);
+ int r_el = regime_el(env, mmu_idx);
if (!regime_has_2_ranges(mmu_idx)) {
select = 0;
@@ -9644,8 +9645,17 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
* Thus disabling them makes things easier during ptw.
*/
hpd = true;
+ pie = extract64(tcr, 36, 1) && cpu_isar_feature(aa64_s2pie, cpu);
} else {
hpd = extract32(tcr, 24, 1);
+ if (r_el == 3) {
+ pie = (extract64(tcr, 35, 1)
+ && cpu_isar_feature(aa64_s1pie, cpu));
+ } else {
+ pie = ((env->cp15.tcr2_el[2] & TCR2_PIE)
+ && (!arm_feature(env, ARM_FEATURE_EL3)
+ || (env->cp15.scr_el3 & SCR_TCR2EN)));
+ }
}
epd = false;
sh = extract32(tcr, 12, 2);
@@ -9685,7 +9695,13 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
regime_is_user(env, mmu_idx)) {
epd = true;
}
+
+ pie = ((env->cp15.tcr2_el[r_el] & TCR2_PIE)
+ && (!arm_feature(env, ARM_FEATURE_EL3)
+ || (env->cp15.scr_el3 & SCR_TCR2EN))
+ && (r_el == 2 || arm_hcrx_el2_eff(env) & HCRX_TCR2EN));
}
+ hpd |= pie;
gran = sanitize_gran_size(cpu, gran, stage2);
@@ -9764,6 +9780,7 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
.ha = ha,
.hd = ha && hd,
.gran = gran,
+ .pie = pie,
};
}
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 16/82] target/arm: Implement get_S1prot_indirect
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (14 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 15/82] target/arm: Populate PIE in aa64_va_parameters Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-31 21:15 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 17/82] target/arm: Implement get_S2prot_indirect Richard Henderson
` (65 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
This approximately corresponds to AArch64.S1IndirectBasePermissions
and the tail of AArch64.S1ComputePermissions which applies WXN.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/ptw.c | 169 +++++++++++++++++++++++++++++++++++++++--------
1 file changed, 143 insertions(+), 26 deletions(-)
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index a5a3c03a4c..7fd1cee98a 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -1449,6 +1449,106 @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
return prot_rw | PAGE_EXEC;
}
+/* Extra page permission bits, during get_S1prot_indirect only. */
+#define PAGE_GCS (1 << 3)
+#define PAGE_WXN (1 << 4)
+#define PAGE_OVERLAY (1 << 5)
+QEMU_BUILD_BUG_ON(PAGE_RWX & (PAGE_GCS | PAGE_WXN | PAGE_OVERLAY));
+
+static int get_S1prot_indirect(CPUARMState *env, S1Translate *ptw,
+ ARMMMUIdx mmu_idx, int pi_index, int po_index,
+ ARMSecuritySpace in_pa, ARMSecuritySpace out_pa)
+{
+ static const uint8_t perm_table[16] = {
+ /* 0 */ PAGE_OVERLAY, /* no access */
+ /* 1 */ PAGE_OVERLAY | PAGE_READ,
+ /* 2 */ PAGE_OVERLAY | PAGE_EXEC,
+ /* 3 */ PAGE_OVERLAY | PAGE_READ | PAGE_EXEC,
+ /* 4 */ PAGE_OVERLAY, /* reserved */
+ /* 5 */ PAGE_OVERLAY | PAGE_READ | PAGE_WRITE,
+ /* 6 */ PAGE_OVERLAY | PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_WXN,
+ /* 7 */ PAGE_OVERLAY | PAGE_READ | PAGE_WRITE | PAGE_EXEC,
+ /* 8 */ PAGE_READ,
+ /* 9 */ PAGE_READ | PAGE_GCS,
+ /* A */ PAGE_READ | PAGE_EXEC,
+ /* B */ 0, /* reserved */
+ /* C */ PAGE_READ | PAGE_WRITE,
+ /* D */ 0, /* reserved */
+ /* E */ PAGE_READ | PAGE_WRITE | PAGE_EXEC,
+ /* F */ 0, /* reserved */
+ };
+
+ uint32_t el = regime_el(env, mmu_idx);
+ uint64_t pir = env->cp15.pir_el[el];
+ uint64_t pire0 = 0;
+ int perm;
+
+ if (el < 3) {
+ if (arm_feature(env, ARM_FEATURE_EL3)
+ && !(env->cp15.scr_el3 & SCR_PIEN)) {
+ pir = 0;
+ } else if (el == 2) {
+ pire0 = env->cp15.pire0_el2;
+ } else if (!ptw->in_nv1) {
+ pire0 = env->cp15.pir_el[0];
+ }
+ }
+ perm = perm_table[extract64(pir, pi_index * 4, 4)];
+
+ if (regime_has_2_ranges(mmu_idx)) {
+ int p_perm = perm;
+ int u_perm = perm_table[extract64(pire0, pi_index * 4, 4)];
+
+ if ((p_perm & (PAGE_EXEC | PAGE_GCS)) &&
+ (u_perm & (PAGE_WRITE | PAGE_GCS))) {
+ p_perm &= ~(PAGE_RWX | PAGE_GCS);
+ u_perm &= ~(PAGE_RWX | PAGE_GCS);
+ }
+ if ((u_perm & (PAGE_RWX | PAGE_GCS)) && regime_is_pan(env, mmu_idx)) {
+ p_perm &= ~(PAGE_READ | PAGE_WRITE);
+ }
+ perm = regime_is_user(env, mmu_idx) ? u_perm : p_perm;
+ }
+
+ if (in_pa != out_pa) {
+ switch (in_pa) {
+ case ARMSS_Root:
+ /*
+ * R_ZWRVD: permission fault for insn fetched from non-Root,
+ * I_WWBFB: SIF has no effect in EL3.
+ */
+ perm &= ~(PAGE_EXEC | PAGE_GCS);
+ break;
+ case ARMSS_Realm:
+ /*
+ * R_PKTDS: permission fault for insn fetched from non-Realm,
+ * for Realm EL2 or EL2&0. The corresponding fault for EL1&0
+ * happens during any stage2 translation.
+ */
+ if (el == 2) {
+ perm &= ~(PAGE_EXEC | PAGE_GCS);
+ }
+ break;
+ case ARMSS_Secure:
+ if (env->cp15.scr_el3 & SCR_SIF) {
+ perm &= ~(PAGE_EXEC | PAGE_GCS);
+ }
+ break;
+ default:
+ /* Input NonSecure must have output NonSecure. */
+ g_assert_not_reached();
+ }
+ }
+
+ if (perm & PAGE_WXN) {
+ perm &= ~PAGE_EXEC;
+ }
+
+ /* TODO: FEAT_GCS */
+
+ return perm & PAGE_RWX;
+}
+
static ARMVAParameters aa32_va_parameters(CPUARMState *env, uint32_t va,
ARMMMUIdx mmu_idx)
{
@@ -1678,7 +1778,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
int32_t stride;
int addrsize, inputsize, outputsize;
uint64_t tcr = regime_tcr(env, mmu_idx);
- int ap, xn, pxn;
+ int ap;
uint32_t el = regime_el(env, mmu_idx);
uint64_t descaddrmask;
bool aarch64 = arm_el_is_aa64(env, el);
@@ -2006,7 +2106,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
out_space = ARMSS_NonSecure;
result->f.prot = get_S2prot_noexecute(ap);
} else {
- xn = extract64(attrs, 53, 2);
+ int xn = extract64(attrs, 53, 2);
result->f.prot = get_S2prot(env, ap, xn, ptw->in_s1_is_el0);
}
@@ -2022,7 +2122,6 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
int nse, ns = extract32(attrs, 5, 1);
uint8_t attrindx;
uint64_t mair;
- int user_rw, prot_rw;
switch (out_space) {
case ARMSS_Root:
@@ -2071,33 +2170,51 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
default:
g_assert_not_reached();
}
- xn = extract64(attrs, 54, 1);
- pxn = extract64(attrs, 53, 1);
- if (el == 1 && ptw->in_nv1) {
+ if (param.pie) {
+ int pi = extract64(attrs, 6, 1)
+ | (extract64(attrs, 51, 1) << 1)
+ | (extract64(attrs, 53, 2) << 2);
+ int po = extract64(attrs, 60, 3);
/*
- * With FEAT_NV, when HCR_EL2.{NV,NV1} == {1,1}, the block/page
- * descriptor bit 54 holds PXN, 53 is RES0, and the effective value
- * of UXN is 0. Similarly for bits 59 and 60 in table descriptors
- * (which we have already folded into bits 53 and 54 of attrs).
- * AP[1] (descriptor bit 6, our ap bit 0) is treated as 0.
- * Similarly, APTable[0] from the table descriptor is treated as 0;
- * we already folded this into AP[1] and squashing that to 0 does
- * the right thing.
+ * Note that we modified ptw->in_space earlier for NSTable, but
+ * result->f.attrs retains a copy of the original security space.
*/
- pxn = xn;
- xn = 0;
- ap &= ~1;
- }
+ result->f.prot = get_S1prot_indirect(env, ptw, mmu_idx, pi, po,
+ result->f.attrs.space,
+ out_space);
+ } else {
+ int xn = extract64(attrs, 54, 1);
+ int pxn = extract64(attrs, 53, 1);
+ int user_rw, prot_rw;
- user_rw = simple_ap_to_rw_prot_is_user(ap, true);
- prot_rw = simple_ap_to_rw_prot_is_user(ap, false);
- /*
- * Note that we modified ptw->in_space earlier for NSTable, but
- * result->f.attrs retains a copy of the original security space.
- */
- result->f.prot = get_S1prot(env, mmu_idx, aarch64, user_rw, prot_rw,
- xn, pxn, result->f.attrs.space, out_space);
+ if (el == 1 && ptw->in_nv1) {
+ /*
+ * With FEAT_NV, when HCR_EL2.{NV,NV1} == {1,1},
+ * the block/page descriptor bit 54 holds PXN,
+ * 53 is RES0, and the effective value of UXN is 0.
+ * Similarly for bits 59 and 60 in table descriptors
+ * (which we have already folded into bits 53 and 54 of attrs).
+ * AP[1] (descriptor bit 6, our ap bit 0) is treated as 0.
+ * Similarly, APTable[0] from the table descriptor is treated
+ * as 0; we already folded this into AP[1] and squashing
+ * that to 0 does the right thing.
+ */
+ pxn = xn;
+ xn = 0;
+ ap &= ~1;
+ }
+
+ user_rw = simple_ap_to_rw_prot_is_user(ap, true);
+ prot_rw = simple_ap_to_rw_prot_is_user(ap, false);
+ /*
+ * Note that we modified ptw->in_space earlier for NSTable, but
+ * result->f.attrs retains a copy of the original security space.
+ */
+ result->f.prot = get_S1prot(env, mmu_idx, aarch64,
+ user_rw, prot_rw, xn, pxn,
+ result->f.attrs.space, out_space);
+ }
/* Index into MAIR registers for cache attributes */
attrindx = extract32(attrs, 2, 3);
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 17/82] target/arm: Implement get_S2prot_indirect
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (15 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 16/82] target/arm: Implement get_S1prot_indirect Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-31 21:13 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 18/82] target/arm: Do not migrate env->exception Richard Henderson
` (64 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Move the stage2 permissions for normal accesses to
GetPhysAddrResult.s2prot. Put the stage2 permissions
for page table walking in CPUTLBEntryFull.prot.
This allows the permission checks in S1_ptw_translate
and arm_casq_ptw to see the right permission.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/internals.h | 7 ++++
target/arm/ptw.c | 81 +++++++++++++++++++++++++++++++-----------
2 files changed, 68 insertions(+), 20 deletions(-)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index d5f501bb30..f0e888ff93 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1574,6 +1574,13 @@ typedef struct ARMCacheAttrs {
typedef struct GetPhysAddrResult {
CPUTLBEntryFull f;
ARMCacheAttrs cacheattrs;
+ /*
+ * For ARMMMUIdx_Stage2*, the protection installed into f.prot
+ * is the result for AccessType_TTW, i.e. the page table walk itself.
+ * The protection installed info s2prot is the one to be merged
+ * with the stage1 protection.
+ */
+ int s2prot;
} GetPhysAddrResult;
/**
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 7fd1cee98a..323fc8052d 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -1281,7 +1281,7 @@ do_fault:
* @xn: XN (execute-never) bits
* @s1_is_el0: true if this is S2 of an S1+2 walk for EL0
*/
-static int get_S2prot_noexecute(int s2ap)
+static int get_S2prot(CPUARMState *env, int s2ap, int xn, bool s1_is_el0)
{
int prot = 0;
@@ -1291,12 +1291,6 @@ static int get_S2prot_noexecute(int s2ap)
if (s2ap & 2) {
prot |= PAGE_WRITE;
}
- return prot;
-}
-
-static int get_S2prot(CPUARMState *env, int s2ap, int xn, bool s1_is_el0)
-{
- int prot = get_S2prot_noexecute(s2ap);
if (cpu_isar_feature(any_tts2uxn, env_archcpu(env))) {
switch (xn) {
@@ -1328,6 +1322,44 @@ static int get_S2prot(CPUARMState *env, int s2ap, int xn, bool s1_is_el0)
return prot;
}
+static int get_S2prot_indirect(CPUARMState *env, GetPhysAddrResult *result,
+ int pi_index, int po_index, bool s1_is_el0)
+{
+ /* Last index is (priv, unpriv, ttw) */
+ static const uint8_t perm_table[16][3] = {
+ /* 0 */ { 0, 0, 0 }, /* no access */
+ /* 1 */ { 0, 0, 0 }, /* reserved */
+ /* 2 */ { PAGE_READ, PAGE_READ, PAGE_READ | PAGE_WRITE },
+ /* 3 */ { PAGE_READ, PAGE_READ, PAGE_READ | PAGE_WRITE },
+ /* 4 */ { PAGE_WRITE, PAGE_WRITE, 0 },
+ /* 5 */ { 0, 0, 0 }, /* reserved */
+ /* 6 */ { PAGE_READ, PAGE_READ, PAGE_READ | PAGE_WRITE },
+ /* 7 */ { PAGE_READ, PAGE_READ, PAGE_READ | PAGE_WRITE },
+ /* 8 */ { PAGE_READ, PAGE_READ, PAGE_READ },
+ /* 9 */ { PAGE_READ, PAGE_READ | PAGE_EXEC, PAGE_READ },
+ /* A */ { PAGE_READ | PAGE_EXEC, PAGE_READ, PAGE_READ },
+ /* B */ { PAGE_READ | PAGE_EXEC, PAGE_READ | PAGE_EXEC, PAGE_READ },
+ /* C */ { PAGE_READ | PAGE_WRITE,
+ PAGE_READ | PAGE_WRITE,
+ PAGE_READ | PAGE_WRITE },
+ /* D */ { PAGE_READ | PAGE_WRITE,
+ PAGE_READ | PAGE_WRITE | PAGE_EXEC,
+ PAGE_READ | PAGE_WRITE },
+ /* E */ { PAGE_READ | PAGE_WRITE | PAGE_EXEC,
+ PAGE_READ | PAGE_WRITE,
+ PAGE_READ | PAGE_WRITE },
+ /* F */ { PAGE_READ | PAGE_WRITE | PAGE_EXEC,
+ PAGE_READ | PAGE_WRITE | PAGE_EXEC,
+ PAGE_READ | PAGE_WRITE },
+ };
+
+ uint64_t pir = (env->cp15.scr_el3 & SCR_PIEN ? env->cp15.s2pir_el2 : 0);
+ int s2pi = extract64(pir, pi_index * 4, 4);
+
+ result->f.prot = perm_table[s2pi][2];
+ return perm_table[s2pi][s1_is_el0];
+}
+
/*
* Translate section/page access permissions to protection flags
* @env: CPUARMState
@@ -1778,7 +1810,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
int32_t stride;
int addrsize, inputsize, outputsize;
uint64_t tcr = regime_tcr(env, mmu_idx);
- int ap;
+ int ap, prot;
uint32_t el = regime_el(env, mmu_idx);
uint64_t descaddrmask;
bool aarch64 = arm_el_is_aa64(env, el);
@@ -2096,6 +2128,18 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
ap = extract32(attrs, 6, 2);
out_space = ptw->in_space;
if (regime_is_stage2(mmu_idx)) {
+ if (param.pie) {
+ int pi = extract64(attrs, 6, 1)
+ | (extract64(attrs, 51, 1) << 1)
+ | (extract64(attrs, 53, 2) << 2);
+ int po = extract64(attrs, 60, 3);
+ prot = get_S2prot_indirect(env, result, pi, po, ptw->in_s1_is_el0);
+ } else {
+ int xn = extract64(attrs, 53, 2);
+ prot = get_S2prot(env, ap, xn, ptw->in_s1_is_el0);
+ /* Install TTW permissions in f.prot. */
+ result->f.prot = prot & (PAGE_READ | PAGE_WRITE);
+ }
/*
* R_GYNXY: For stage2 in Realm security state, bit 55 is NS.
* The bit remains ignored for other security states.
@@ -2104,11 +2148,9 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
*/
if (out_space == ARMSS_Realm && extract64(attrs, 55, 1)) {
out_space = ARMSS_NonSecure;
- result->f.prot = get_S2prot_noexecute(ap);
- } else {
- int xn = extract64(attrs, 53, 2);
- result->f.prot = get_S2prot(env, ap, xn, ptw->in_s1_is_el0);
+ prot &= ~PAGE_EXEC;
}
+ result->s2prot = prot;
result->cacheattrs.is_s2_format = true;
result->cacheattrs.attrs = extract32(attrs, 2, 4);
@@ -2180,9 +2222,8 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
* Note that we modified ptw->in_space earlier for NSTable, but
* result->f.attrs retains a copy of the original security space.
*/
- result->f.prot = get_S1prot_indirect(env, ptw, mmu_idx, pi, po,
- result->f.attrs.space,
- out_space);
+ prot = get_S1prot_indirect(env, ptw, mmu_idx, pi, po,
+ result->f.attrs.space, out_space);
} else {
int xn = extract64(attrs, 54, 1);
int pxn = extract64(attrs, 53, 1);
@@ -2211,10 +2252,10 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
* Note that we modified ptw->in_space earlier for NSTable, but
* result->f.attrs retains a copy of the original security space.
*/
- result->f.prot = get_S1prot(env, mmu_idx, aarch64,
- user_rw, prot_rw, xn, pxn,
- result->f.attrs.space, out_space);
+ prot = get_S1prot(env, mmu_idx, aarch64, user_rw, prot_rw, xn, pxn,
+ result->f.attrs.space, out_space);
}
+ result->f.prot = prot;
/* Index into MAIR registers for cache attributes */
attrindx = extract32(attrs, 2, 3);
@@ -2260,7 +2301,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
result->f.tlb_fill_flags = 0;
}
- if (ptw->in_prot_check & ~result->f.prot) {
+ if (ptw->in_prot_check & ~prot) {
fi->type = ARMFault_Permission;
goto do_fault;
}
@@ -3458,7 +3499,7 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
fi->s2addr = ipa;
/* Combine the S1 and S2 perms. */
- result->f.prot &= s1_prot;
+ result->f.prot = s1_prot & result->s2prot;
/* If S2 fails, return early. */
if (ret) {
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 18/82] target/arm: Do not migrate env->exception
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (16 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 17/82] target/arm: Implement get_S2prot_indirect Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 20:46 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 19/82] target/arm: Expand CPUARMState.exception.syndrome to 64 bits Richard Henderson
` (63 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
These are not architectural state, only placeholders
between identifying the exception and delivering it.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/machine.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/target/arm/machine.c b/target/arm/machine.c
index 6986915bee..8dbeca2867 100644
--- a/target/arm/machine.c
+++ b/target/arm/machine.c
@@ -1085,9 +1085,9 @@ const VMStateDescription vmstate_arm_cpu = {
VMSTATE_UINT64(env.exclusive_val, ARMCPU),
VMSTATE_UINT64(env.exclusive_high, ARMCPU),
VMSTATE_UNUSED(sizeof(uint64_t)),
- VMSTATE_UINT32(env.exception.syndrome, ARMCPU),
- VMSTATE_UINT32(env.exception.fsr, ARMCPU),
- VMSTATE_UINT64(env.exception.vaddress, ARMCPU),
+ VMSTATE_UNUSED(sizeof(uint32_t)),
+ VMSTATE_UNUSED(sizeof(uint32_t)),
+ VMSTATE_UNUSED(sizeof(uint64_t)),
VMSTATE_TIMER_PTR(gt_timer[GTIMER_PHYS], ARMCPU),
VMSTATE_TIMER_PTR(gt_timer[GTIMER_VIRT], ARMCPU),
{
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 19/82] target/arm: Expand CPUARMState.exception.syndrome to 64 bits
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (17 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 18/82] target/arm: Do not migrate env->exception Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 20:47 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 20/82] target/arm: Expand syndrome parameter to raise_exception* Richard Henderson
` (62 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
This will be used for storing the ISS2 portion of the
ESR_ELx registers in aarch64 state. Re-order the fsr
member to eliminate two structure holes.
Drop the comment about "if we implement EL2" since we
have already done so.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpu.h | 7 ++-----
target/arm/helper.c | 2 +-
2 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index fb87fcc3e6..4940bd6a45 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -644,13 +644,10 @@ typedef struct CPUArchState {
* entry process.
*/
struct {
- uint32_t syndrome; /* AArch64 format syndrome register */
- uint32_t fsr; /* AArch32 format fault status register info */
+ uint64_t syndrome; /* AArch64 format syndrome register */
uint64_t vaddress; /* virtual addr associated with exception, if any */
+ uint32_t fsr; /* AArch32 format fault status register info */
uint32_t target_el; /* EL the exception should be targeted for */
- /* If we implement EL2 we will also need to store information
- * about the intermediate physical address for stage 2 faults.
- */
} exception;
/* Information associated with an SError */
diff --git a/target/arm/helper.c b/target/arm/helper.c
index ecce93fb97..154bda3cd4 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -9438,7 +9438,7 @@ void arm_cpu_do_interrupt(CPUState *cs)
new_el);
if (qemu_loglevel_mask(CPU_LOG_INT)
&& !excp_is_internal(cs->exception_index)) {
- qemu_log_mask(CPU_LOG_INT, "...with ESR 0x%x/0x%" PRIx32 "\n",
+ qemu_log_mask(CPU_LOG_INT, "...with ESR 0x%x/0x%" PRIx64 "\n",
syn_get_ec(env->exception.syndrome),
env->exception.syndrome);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 20/82] target/arm: Expand syndrome parameter to raise_exception*
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (18 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 19/82] target/arm: Expand CPUARMState.exception.syndrome to 64 bits Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 20:47 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 21/82] target/arm: Implement dirtybit check for PIE Richard Henderson
` (61 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Prepare for raising exceptions with 64-bit syndromes.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/internals.h | 6 +++---
target/arm/tcg-stubs.c | 2 +-
target/arm/tcg/op_helper.c | 4 ++--
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index f0e888ff93..fc82dd65e8 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -306,14 +306,14 @@ FIELD(CNTHCTL, CNTPMASK, 19, 1)
* and never returns because we will longjump back up to the CPU main loop.
*/
G_NORETURN void raise_exception(CPUARMState *env, uint32_t excp,
- uint32_t syndrome, uint32_t target_el);
+ uint64_t syndrome, uint32_t target_el);
/*
* Similarly, but also use unwinding to restore cpu state.
*/
G_NORETURN void raise_exception_ra(CPUARMState *env, uint32_t excp,
- uint32_t syndrome, uint32_t target_el,
- uintptr_t ra);
+ uint64_t syndrome, uint32_t target_el,
+ uintptr_t ra);
/*
* For AArch64, map a given EL to an index in the banked_spsr array.
diff --git a/target/arm/tcg-stubs.c b/target/arm/tcg-stubs.c
index aac99b2672..aeeede8066 100644
--- a/target/arm/tcg-stubs.c
+++ b/target/arm/tcg-stubs.c
@@ -16,7 +16,7 @@ void write_v7m_exception(CPUARMState *env, uint32_t new_exc)
g_assert_not_reached();
}
-void raise_exception_ra(CPUARMState *env, uint32_t excp, uint32_t syndrome,
+void raise_exception_ra(CPUARMState *env, uint32_t excp, uint64_t syndrome,
uint32_t target_el, uintptr_t ra)
{
g_assert_not_reached();
diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c
index 575e566280..46a3b911ec 100644
--- a/target/arm/tcg/op_helper.c
+++ b/target/arm/tcg/op_helper.c
@@ -46,7 +46,7 @@ int exception_target_el(CPUARMState *env)
}
void raise_exception(CPUARMState *env, uint32_t excp,
- uint32_t syndrome, uint32_t target_el)
+ uint64_t syndrome, uint32_t target_el)
{
CPUState *cs = env_cpu(env);
@@ -70,7 +70,7 @@ void raise_exception(CPUARMState *env, uint32_t excp,
cpu_loop_exit(cs);
}
-void raise_exception_ra(CPUARMState *env, uint32_t excp, uint32_t syndrome,
+void raise_exception_ra(CPUARMState *env, uint32_t excp, uint64_t syndrome,
uint32_t target_el, uintptr_t ra)
{
CPUState *cs = env_cpu(env);
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 21/82] target/arm: Implement dirtybit check for PIE
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (19 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 20/82] target/arm: Expand syndrome parameter to raise_exception* Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 20:50 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 22/82] target/arm: Enable FEAT_S1PIE and FEAT_S2PIE on -cpu max Richard Henderson
` (60 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Both S1PIE and S2PIE have a bit to make software tracking
of dirty pages easier.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/internals.h | 1 +
target/arm/ptw.c | 16 ++++++++++++++++
target/arm/tcg/tlb_helper.c | 12 +++++++++---
3 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index fc82dd65e8..b6499683cc 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -754,6 +754,7 @@ struct ARMMMUFaultInfo {
bool s1ptw;
bool s1ns;
bool ea;
+ bool dirtybit; /* FEAT_S1PIE, FEAT_S2PIE */
};
/**
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 323fc8052d..820d5e65a0 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -2306,6 +2306,22 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
goto do_fault;
}
+ /* S1PIE and S2PIE both have a bit for software dirty page tracking. */
+ if (access_type == MMU_DATA_STORE && param.pie) {
+ /*
+ * For S1PIE, bit 7 is nDirty and both HA and HD are checked.
+ * For S2PIE, bit 7 is Dirty and only HD is checked.
+ */
+ bool bit7 = extract64(attrs, 7, 1);
+ if (regime_is_stage2(mmu_idx)
+ ? !bit7 && !param.hd
+ : bit7 && !(param.ha && param.hd)) {
+ fi->type = ARMFault_Permission;
+ fi->dirtybit = true;
+ goto do_fault;
+ }
+ }
+
/* If FEAT_HAFDBS has made changes, update the PTE. */
if (new_descriptor != descriptor) {
new_descriptor = arm_casq_ptw(env, descriptor, new_descriptor, ptw, fi);
diff --git a/target/arm/tcg/tlb_helper.c b/target/arm/tcg/tlb_helper.c
index 23c72a99f5..ae2acd6727 100644
--- a/target/arm/tcg/tlb_helper.c
+++ b/target/arm/tcg/tlb_helper.c
@@ -24,13 +24,13 @@ bool arm_s1_regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx)
return regime_using_lpae_format(env, mmu_idx);
}
-static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
+static inline uint64_t merge_syn_data_abort(uint32_t template_syn,
ARMMMUFaultInfo *fi,
unsigned int target_el,
bool same_el, bool is_write,
int fsc)
{
- uint32_t syn;
+ uint64_t syn;
/*
* ISV is only set for stage-2 data aborts routed to EL2 and
@@ -75,6 +75,10 @@ static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
/* Merge the runtime syndrome with the template syndrome. */
syn |= template_syn;
}
+
+ /* Form ISS2 at the top of the syndrome. */
+ syn |= (uint64_t)fi->dirtybit << 37;
+
return syn;
}
@@ -176,7 +180,9 @@ void arm_deliver_fault(ARMCPU *cpu, vaddr addr,
int target_el = exception_target_el(env);
int current_el = arm_current_el(env);
bool same_el;
- uint32_t syn, exc, fsr, fsc;
+ uint32_t exc, fsr, fsc;
+ uint64_t syn;
+
/*
* We know this must be a data or insn abort, and that
* env->exception.syndrome contains the template syndrome set
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 22/82] target/arm: Enable FEAT_S1PIE and FEAT_S2PIE on -cpu max
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (20 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 21/82] target/arm: Implement dirtybit check for PIE Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 20:50 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 23/82] include/hw/core/cpu: Introduce MMUIdxMap Richard Henderson
` (59 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/tcg/cpu64.c | 2 ++
docs/system/arm/emulation.rst | 2 ++
2 files changed, 4 insertions(+)
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index 22ccc4f697..f4a41c854f 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -1253,6 +1253,8 @@ void aarch64_max_tcg_initfn(Object *obj)
t = FIELD_DP64(t, ID_AA64MMFR3, SCTLRX, 1); /* FEAT_SCTLR2 */
t = FIELD_DP64(t, ID_AA64MMFR3, MEC, 1); /* FEAT_MEC */
t = FIELD_DP64(t, ID_AA64MMFR3, SPEC_FPACC, 1); /* FEAT_FPACC_SPEC */
+ t = FIELD_DP64(t, ID_AA64MMFR3, S1PIE, 1); /* FEAT_S1PIE */
+ t = FIELD_DP64(t, ID_AA64MMFR3, S2PIE, 1); /* FEAT_S2PIE */
SET_IDREG(isar, ID_AA64MMFR3, t);
t = GET_IDREG(isar, ID_AA64ZFR0);
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
index 1489c262b8..6ebf9c9ce9 100644
--- a/docs/system/arm/emulation.rst
+++ b/docs/system/arm/emulation.rst
@@ -123,6 +123,8 @@ the following architecture extensions:
- FEAT_RME (Realm Management Extension) (NB: support status in QEMU is experimental)
- FEAT_RNG (Random number generator)
- FEAT_RPRES (Increased precision of FRECPE and FRSQRTE)
+- FEAT_S1PIE (Stage 1 permission indirections)
+- FEAT_S2PIE (Stage 2 permission indirections)
- FEAT_S2FWB (Stage 2 forced Write-Back)
- FEAT_SB (Speculation Barrier)
- FEAT_SCTLR2 (Extension to SCTLR_ELx)
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 23/82] include/hw/core/cpu: Introduce MMUIdxMap
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (21 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 22/82] target/arm: Enable FEAT_S1PIE and FEAT_S2PIE on -cpu max Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 20:52 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 24/82] include/hw/core/cpu: Introduce cpu_tlb_fast Richard Henderson
` (58 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Use a typedef instead of uint16_t directly when
describing sets of mmu indexes.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/exec/cputlb.h | 32 ++++++++++++++++----------------
include/hw/core/cpu.h | 6 +++---
accel/tcg/cputlb.c | 30 +++++++++++++++---------------
3 files changed, 34 insertions(+), 34 deletions(-)
diff --git a/include/exec/cputlb.h b/include/exec/cputlb.h
index 03ed7e2165..9bec0e7890 100644
--- a/include/exec/cputlb.h
+++ b/include/exec/cputlb.h
@@ -150,7 +150,7 @@ void tlb_flush_all_cpus_synced(CPUState *src_cpu);
* MMU indexes.
*/
void tlb_flush_page_by_mmuidx(CPUState *cpu, vaddr addr,
- uint16_t idxmap);
+ MMUIdxMap idxmap);
/**
* tlb_flush_page_by_mmuidx_all_cpus_synced:
@@ -165,7 +165,7 @@ void tlb_flush_page_by_mmuidx(CPUState *cpu, vaddr addr,
* translations using the flushed TLBs.
*/
void tlb_flush_page_by_mmuidx_all_cpus_synced(CPUState *cpu, vaddr addr,
- uint16_t idxmap);
+ MMUIdxMap idxmap);
/**
* tlb_flush_by_mmuidx:
@@ -176,7 +176,7 @@ void tlb_flush_page_by_mmuidx_all_cpus_synced(CPUState *cpu, vaddr addr,
* Flush all entries from the TLB of the specified CPU, for the specified
* MMU indexes.
*/
-void tlb_flush_by_mmuidx(CPUState *cpu, uint16_t idxmap);
+void tlb_flush_by_mmuidx(CPUState *cpu, MMUIdxMap idxmap);
/**
* tlb_flush_by_mmuidx_all_cpus_synced:
@@ -189,7 +189,7 @@ void tlb_flush_by_mmuidx(CPUState *cpu, uint16_t idxmap);
* When this function returns, no CPUs will subsequently perform
* translations using the flushed TLBs.
*/
-void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, uint16_t idxmap);
+void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, MMUIdxMap idxmap);
/**
* tlb_flush_page_bits_by_mmuidx
@@ -201,11 +201,11 @@ void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, uint16_t idxmap);
* Similar to tlb_flush_page_mask, but with a bitmap of indexes.
*/
void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, vaddr addr,
- uint16_t idxmap, unsigned bits);
+ MMUIdxMap idxmap, unsigned bits);
/* Similarly, with broadcast and syncing. */
void tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *cpu, vaddr addr,
- uint16_t idxmap,
+ MMUIdxMap idxmap,
unsigned bits);
/**
@@ -220,14 +220,14 @@ void tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *cpu, vaddr addr,
* comparing only the low @bits worth of each virtual page.
*/
void tlb_flush_range_by_mmuidx(CPUState *cpu, vaddr addr,
- vaddr len, uint16_t idxmap,
+ vaddr len, MMUIdxMap idxmap,
unsigned bits);
/* Similarly, with broadcast and syncing. */
void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState *cpu,
vaddr addr,
vaddr len,
- uint16_t idxmap,
+ MMUIdxMap idxmap,
unsigned bits);
#else
static inline void tlb_flush_page(CPUState *cpu, vaddr addr)
@@ -243,42 +243,42 @@ static inline void tlb_flush_all_cpus_synced(CPUState *src_cpu)
{
}
static inline void tlb_flush_page_by_mmuidx(CPUState *cpu,
- vaddr addr, uint16_t idxmap)
+ vaddr addr, MMUIdxMap idxmap)
{
}
-static inline void tlb_flush_by_mmuidx(CPUState *cpu, uint16_t idxmap)
+static inline void tlb_flush_by_mmuidx(CPUState *cpu, MMUIdxMap idxmap)
{
}
static inline void tlb_flush_page_by_mmuidx_all_cpus_synced(CPUState *cpu,
vaddr addr,
- uint16_t idxmap)
+ MMUIdxMap idxmap)
{
}
static inline void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu,
- uint16_t idxmap)
+ MMUIdxMap idxmap)
{
}
static inline void tlb_flush_page_bits_by_mmuidx(CPUState *cpu,
vaddr addr,
- uint16_t idxmap,
+ MMUIdxMap idxmap,
unsigned bits)
{
}
static inline void
tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *cpu, vaddr addr,
- uint16_t idxmap, unsigned bits)
+ MMUIdxMap idxmap, unsigned bits)
{
}
static inline void tlb_flush_range_by_mmuidx(CPUState *cpu, vaddr addr,
- vaddr len, uint16_t idxmap,
+ vaddr len, MMUIdxMap idxmap,
unsigned bits)
{
}
static inline void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState *cpu,
vaddr addr,
vaddr len,
- uint16_t idxmap,
+ MMUIdxMap idxmap,
unsigned bits)
{
}
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 5eaf41a566..1153cadb70 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -198,10 +198,10 @@ struct CPUClass {
};
/*
- * Fix the number of mmu modes to 16, which is also the maximum
- * supported by the softmmu tlb api.
+ * Fix the number of mmu modes to 16.
*/
#define NB_MMU_MODES 16
+typedef uint16_t MMUIdxMap;
/* Use a fully associative victim tlb of 8 entries. */
#define CPU_VTLB_SIZE 8
@@ -306,7 +306,7 @@ typedef struct CPUTLBCommon {
* mmu_idx N since the last time that mmu_idx was flushed.
* Protected by tlb_c.lock.
*/
- uint16_t dirty;
+ MMUIdxMap dirty;
/*
* Statistics. These are not lock protected, but are read and
* written atomically. This allows the monitor to print a snapshot
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index 87e14bde4f..d324f33339 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -370,8 +370,8 @@ static void flush_all_helper(CPUState *src, run_on_cpu_func fn,
static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, run_on_cpu_data data)
{
- uint16_t asked = data.host_int;
- uint16_t all_dirty, work, to_clean;
+ MMUIdxMap asked = data.host_int;
+ MMUIdxMap all_dirty, work, to_clean;
int64_t now = get_clock_realtime();
assert_cpu_is_self(cpu);
@@ -408,7 +408,7 @@ static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, run_on_cpu_data data)
}
}
-void tlb_flush_by_mmuidx(CPUState *cpu, uint16_t idxmap)
+void tlb_flush_by_mmuidx(CPUState *cpu, MMUIdxMap idxmap)
{
tlb_debug("mmu_idx: 0x%" PRIx16 "\n", idxmap);
@@ -422,7 +422,7 @@ void tlb_flush(CPUState *cpu)
tlb_flush_by_mmuidx(cpu, ALL_MMUIDX_BITS);
}
-void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *src_cpu, uint16_t idxmap)
+void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *src_cpu, MMUIdxMap idxmap)
{
const run_on_cpu_func fn = tlb_flush_by_mmuidx_async_work;
@@ -531,7 +531,7 @@ static void tlb_flush_page_locked(CPUState *cpu, int midx, vaddr page)
*/
static void tlb_flush_page_by_mmuidx_async_0(CPUState *cpu,
vaddr addr,
- uint16_t idxmap)
+ MMUIdxMap idxmap)
{
int mmu_idx;
@@ -570,14 +570,14 @@ static void tlb_flush_page_by_mmuidx_async_1(CPUState *cpu,
{
vaddr addr_and_idxmap = data.target_ptr;
vaddr addr = addr_and_idxmap & TARGET_PAGE_MASK;
- uint16_t idxmap = addr_and_idxmap & ~TARGET_PAGE_MASK;
+ MMUIdxMap idxmap = addr_and_idxmap & ~TARGET_PAGE_MASK;
tlb_flush_page_by_mmuidx_async_0(cpu, addr, idxmap);
}
typedef struct {
vaddr addr;
- uint16_t idxmap;
+ MMUIdxMap idxmap;
} TLBFlushPageByMMUIdxData;
/**
@@ -599,7 +599,7 @@ static void tlb_flush_page_by_mmuidx_async_2(CPUState *cpu,
g_free(d);
}
-void tlb_flush_page_by_mmuidx(CPUState *cpu, vaddr addr, uint16_t idxmap)
+void tlb_flush_page_by_mmuidx(CPUState *cpu, vaddr addr, MMUIdxMap idxmap)
{
tlb_debug("addr: %016" VADDR_PRIx " mmu_idx:%" PRIx16 "\n", addr, idxmap);
@@ -618,7 +618,7 @@ void tlb_flush_page(CPUState *cpu, vaddr addr)
void tlb_flush_page_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
vaddr addr,
- uint16_t idxmap)
+ MMUIdxMap idxmap)
{
tlb_debug("addr: %016" VADDR_PRIx " mmu_idx:%"PRIx16"\n", addr, idxmap);
@@ -715,8 +715,8 @@ static void tlb_flush_range_locked(CPUState *cpu, int midx,
typedef struct {
vaddr addr;
vaddr len;
- uint16_t idxmap;
- uint16_t bits;
+ MMUIdxMap idxmap;
+ unsigned bits;
} TLBFlushRangeData;
static void tlb_flush_range_by_mmuidx_async_0(CPUState *cpu,
@@ -766,7 +766,7 @@ static void tlb_flush_range_by_mmuidx_async_1(CPUState *cpu,
}
void tlb_flush_range_by_mmuidx(CPUState *cpu, vaddr addr,
- vaddr len, uint16_t idxmap,
+ vaddr len, MMUIdxMap idxmap,
unsigned bits)
{
TLBFlushRangeData d;
@@ -797,7 +797,7 @@ void tlb_flush_range_by_mmuidx(CPUState *cpu, vaddr addr,
}
void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, vaddr addr,
- uint16_t idxmap, unsigned bits)
+ MMUIdxMap idxmap, unsigned bits)
{
tlb_flush_range_by_mmuidx(cpu, addr, TARGET_PAGE_SIZE, idxmap, bits);
}
@@ -805,7 +805,7 @@ void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, vaddr addr,
void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
vaddr addr,
vaddr len,
- uint16_t idxmap,
+ MMUIdxMap idxmap,
unsigned bits)
{
TLBFlushRangeData d, *p;
@@ -847,7 +847,7 @@ void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
void tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
vaddr addr,
- uint16_t idxmap,
+ MMUIdxMap idxmap,
unsigned bits)
{
tlb_flush_range_by_mmuidx_all_cpus_synced(src_cpu, addr, TARGET_PAGE_SIZE,
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 24/82] include/hw/core/cpu: Introduce cpu_tlb_fast
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (22 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 23/82] include/hw/core/cpu: Introduce MMUIdxMap Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 20:53 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 25/82] include/hw/core/cpu: Invert the indexing into CPUTLBDescFast Richard Henderson
` (57 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Encapsulate access to cpu->neg.tlb.f[] in a function.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/hw/core/cpu.h | 7 +++++++
accel/tcg/cputlb.c | 16 ++++++++--------
2 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 1153cadb70..bd835b07d5 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -593,6 +593,13 @@ static inline CPUArchState *cpu_env(CPUState *cpu)
return (CPUArchState *)(cpu + 1);
}
+#ifdef CONFIG_TCG
+static inline CPUTLBDescFast *cpu_tlb_fast(CPUState *cpu, int mmu_idx)
+{
+ return &cpu->neg.tlb.f[mmu_idx];
+}
+#endif
+
typedef QTAILQ_HEAD(CPUTailQ, CPUState) CPUTailQ;
extern CPUTailQ cpus_queue;
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index d324f33339..2a6aa01c57 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -129,7 +129,7 @@ static inline uint64_t tlb_addr_write(const CPUTLBEntry *entry)
static inline uintptr_t tlb_index(CPUState *cpu, uintptr_t mmu_idx,
vaddr addr)
{
- uintptr_t size_mask = cpu->neg.tlb.f[mmu_idx].mask >> CPU_TLB_ENTRY_BITS;
+ uintptr_t size_mask = cpu_tlb_fast(cpu, mmu_idx)->mask >> CPU_TLB_ENTRY_BITS;
return (addr >> TARGET_PAGE_BITS) & size_mask;
}
@@ -138,7 +138,7 @@ static inline uintptr_t tlb_index(CPUState *cpu, uintptr_t mmu_idx,
static inline CPUTLBEntry *tlb_entry(CPUState *cpu, uintptr_t mmu_idx,
vaddr addr)
{
- return &cpu->neg.tlb.f[mmu_idx].table[tlb_index(cpu, mmu_idx, addr)];
+ return &cpu_tlb_fast(cpu, mmu_idx)->table[tlb_index(cpu, mmu_idx, addr)];
}
static void tlb_window_reset(CPUTLBDesc *desc, int64_t ns,
@@ -292,7 +292,7 @@ static void tlb_flush_one_mmuidx_locked(CPUState *cpu, int mmu_idx,
int64_t now)
{
CPUTLBDesc *desc = &cpu->neg.tlb.d[mmu_idx];
- CPUTLBDescFast *fast = &cpu->neg.tlb.f[mmu_idx];
+ CPUTLBDescFast *fast = cpu_tlb_fast(cpu, mmu_idx);
tlb_mmu_resize_locked(desc, fast, now);
tlb_mmu_flush_locked(desc, fast);
@@ -331,7 +331,7 @@ void tlb_init(CPUState *cpu)
cpu->neg.tlb.c.dirty = 0;
for (i = 0; i < NB_MMU_MODES; i++) {
- tlb_mmu_init(&cpu->neg.tlb.d[i], &cpu->neg.tlb.f[i], now);
+ tlb_mmu_init(&cpu->neg.tlb.d[i], cpu_tlb_fast(cpu, i), now);
}
}
@@ -342,7 +342,7 @@ void tlb_destroy(CPUState *cpu)
qemu_spin_destroy(&cpu->neg.tlb.c.lock);
for (i = 0; i < NB_MMU_MODES; i++) {
CPUTLBDesc *desc = &cpu->neg.tlb.d[i];
- CPUTLBDescFast *fast = &cpu->neg.tlb.f[i];
+ CPUTLBDescFast *fast = cpu_tlb_fast(cpu, i);
g_free(fast->table);
g_free(desc->fulltlb);
@@ -667,7 +667,7 @@ static void tlb_flush_range_locked(CPUState *cpu, int midx,
unsigned bits)
{
CPUTLBDesc *d = &cpu->neg.tlb.d[midx];
- CPUTLBDescFast *f = &cpu->neg.tlb.f[midx];
+ CPUTLBDescFast *f = cpu_tlb_fast(cpu, midx);
vaddr mask = MAKE_64BIT_MASK(0, bits);
/*
@@ -923,7 +923,7 @@ void tlb_reset_dirty(CPUState *cpu, uintptr_t start, uintptr_t length)
qemu_spin_lock(&cpu->neg.tlb.c.lock);
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
CPUTLBDesc *desc = &cpu->neg.tlb.d[mmu_idx];
- CPUTLBDescFast *fast = &cpu->neg.tlb.f[mmu_idx];
+ CPUTLBDescFast *fast = cpu_tlb_fast(cpu, mmu_idx);
unsigned int n = tlb_n_entries(fast);
unsigned int i;
@@ -1316,7 +1316,7 @@ static bool victim_tlb_hit(CPUState *cpu, size_t mmu_idx, size_t index,
if (cmp == page) {
/* Found entry in victim tlb, swap tlb and iotlb. */
- CPUTLBEntry tmptlb, *tlb = &cpu->neg.tlb.f[mmu_idx].table[index];
+ CPUTLBEntry tmptlb, *tlb = &cpu_tlb_fast(cpu, mmu_idx)->table[index];
qemu_spin_lock(&cpu->neg.tlb.c.lock);
copy_tlb_helper_locked(&tmptlb, tlb);
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 25/82] include/hw/core/cpu: Invert the indexing into CPUTLBDescFast
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (23 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 24/82] include/hw/core/cpu: Introduce cpu_tlb_fast Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 21:00 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 26/82] target/hppa: Adjust mmu indexes to begin with 0 Richard Henderson
` (56 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
This array is within CPUNegativeOffsetState, which means the
last element of the array has an offset from env with the
smallest magnitude. This can be encoded into fewer bits
when generating TCG fast path memory references.
When we changed the NB_MMU_MODES to be a global constant,
rather than a per-target value, we pessimized the code
generated for targets which use only a few mmu indexes.
By inverting the array index, we counteract that.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/hw/core/cpu.h | 6 +++++-
tcg/tcg.c | 3 ++-
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index bd835b07d5..85b1ab4022 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -596,7 +596,11 @@ static inline CPUArchState *cpu_env(CPUState *cpu)
#ifdef CONFIG_TCG
static inline CPUTLBDescFast *cpu_tlb_fast(CPUState *cpu, int mmu_idx)
{
- return &cpu->neg.tlb.f[mmu_idx];
+ /*
+ * Invert the index order of the CPUTLBDescFast array so that lower
+ * mmu_idx have negative offsets from env with smaller absolute values.
+ */
+ return &cpu->neg.tlb.f[NB_MMU_MODES - 1 - mmu_idx];
}
#endif
diff --git a/tcg/tcg.c b/tcg/tcg.c
index afac55a203..615675d185 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -425,7 +425,8 @@ static uintptr_t G_GNUC_UNUSED get_jmp_target_addr(TCGContext *s, int which)
static int __attribute__((unused))
tlb_mask_table_ofs(TCGContext *s, int which)
{
- return (offsetof(CPUNegativeOffsetState, tlb.f[which]) -
+ /* Invert the index order -- see cpu_tlb_fast. */
+ return (offsetof(CPUNegativeOffsetState, tlb.f[NB_MMU_MODES - 1 - which]) -
sizeof(CPUNegativeOffsetState));
}
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 26/82] target/hppa: Adjust mmu indexes to begin with 0
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (24 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 25/82] include/hw/core/cpu: Invert the indexing into CPUTLBDescFast Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 21:03 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 27/82] include/exec/memopidx: Adjust for 32 mmu indexes Richard Henderson
` (55 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
This is a logical reversion of 2ad04500543, though
there have been additions to the set of mmu indexes
since then. The impetus to that original patch,
"9-15 will use shorter assembler instructions when
run on a x86-64 host" is now handled generically.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/hppa/cpu.h | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index 11d59d11ca..672ab3750c 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -29,21 +29,21 @@
#include "qemu/interval-tree.h"
#include "hw/registerfields.h"
-#define MMU_ABS_W_IDX 6
-#define MMU_ABS_IDX 7
-#define MMU_KERNEL_IDX 8
-#define MMU_KERNEL_P_IDX 9
-#define MMU_PL1_IDX 10
-#define MMU_PL1_P_IDX 11
-#define MMU_PL2_IDX 12
-#define MMU_PL2_P_IDX 13
-#define MMU_USER_IDX 14
-#define MMU_USER_P_IDX 15
+#define MMU_KERNEL_IDX 0
+#define MMU_KERNEL_P_IDX 1
+#define MMU_PL1_IDX 2
+#define MMU_PL1_P_IDX 3
+#define MMU_PL2_IDX 4
+#define MMU_PL2_P_IDX 5
+#define MMU_USER_IDX 6
+#define MMU_USER_P_IDX 7
+#define MMU_ABS_IDX 8
+#define MMU_ABS_W_IDX 9
-#define MMU_IDX_MMU_DISABLED(MIDX) ((MIDX) < MMU_KERNEL_IDX)
-#define MMU_IDX_TO_PRIV(MIDX) (((MIDX) - MMU_KERNEL_IDX) / 2)
-#define MMU_IDX_TO_P(MIDX) (((MIDX) - MMU_KERNEL_IDX) & 1)
-#define PRIV_P_TO_MMU_IDX(PRIV, P) ((PRIV) * 2 + !!(P) + MMU_KERNEL_IDX)
+#define MMU_IDX_MMU_DISABLED(MIDX) ((MIDX) >= MMU_ABS_IDX)
+#define MMU_IDX_TO_PRIV(MIDX) ((MIDX) / 2)
+#define MMU_IDX_TO_P(MIDX) ((MIDX) & 1)
+#define PRIV_P_TO_MMU_IDX(PRIV, P) ((PRIV) * 2 + !!(P))
#define PRIV_KERNEL 0
#define PRIV_USER 3
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 27/82] include/exec/memopidx: Adjust for 32 mmu indexes
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (25 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 26/82] target/hppa: Adjust mmu indexes to begin with 0 Richard Henderson
@ 2025-07-27 8:01 ` Richard Henderson
2025-07-30 21:03 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 28/82] include/hw/core/cpu: Widen MMUIdxMap Richard Henderson
` (54 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:01 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/exec/memopidx.h | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/include/exec/memopidx.h b/include/exec/memopidx.h
index eb7f1591a3..66d9c58b3a 100644
--- a/include/exec/memopidx.h
+++ b/include/exec/memopidx.h
@@ -25,9 +25,10 @@ typedef uint32_t MemOpIdx;
static inline MemOpIdx make_memop_idx(MemOp op, unsigned idx)
{
#ifdef CONFIG_DEBUG_TCG
- assert(idx <= 15);
+ assert(idx <= 31);
+ assert(clz32(op) >= 5);
#endif
- return (op << 4) | idx;
+ return (op << 5) | idx;
}
/**
@@ -38,7 +39,7 @@ static inline MemOpIdx make_memop_idx(MemOp op, unsigned idx)
*/
static inline MemOp get_memop(MemOpIdx oi)
{
- return oi >> 4;
+ return oi >> 5;
}
/**
@@ -49,7 +50,7 @@ static inline MemOp get_memop(MemOpIdx oi)
*/
static inline unsigned get_mmuidx(MemOpIdx oi)
{
- return oi & 15;
+ return oi & 31;
}
#endif
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 28/82] include/hw/core/cpu: Widen MMUIdxMap
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (26 preceding siblings ...)
2025-07-27 8:01 ` [PATCH 27/82] include/exec/memopidx: Adjust for 32 mmu indexes Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-30 21:07 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 29/82] target/arm: Split out mmuidx.h from cpu.h Richard Henderson
` (53 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Widen MMUIdxMap to 32 bits. Do not yet expand NB_MMU_MODES,
but widen the map type in preparation.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/hw/core/cpu.h | 2 +-
accel/tcg/cputlb.c | 3 ---
2 files changed, 1 insertion(+), 4 deletions(-)
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 85b1ab4022..a95559c538 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -201,7 +201,7 @@ struct CPUClass {
* Fix the number of mmu modes to 16.
*/
#define NB_MMU_MODES 16
-typedef uint16_t MMUIdxMap;
+typedef uint32_t MMUIdxMap;
/* Use a fully associative victim tlb of 8 entries. */
#define CPU_VTLB_SIZE 8
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index 2a6aa01c57..416aaa1040 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -89,9 +89,6 @@
*/
QEMU_BUILD_BUG_ON(sizeof(vaddr) > sizeof(run_on_cpu_data));
-/* We currently can't handle more than 16 bits in the MMUIDX bitmask.
- */
-QEMU_BUILD_BUG_ON(NB_MMU_MODES > 16);
#define ALL_MMUIDX_BITS ((1 << NB_MMU_MODES) - 1)
static inline size_t tlb_n_entries(CPUTLBDescFast *fast)
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 29/82] target/arm: Split out mmuidx.h from cpu.h
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (27 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 28/82] include/hw/core/cpu: Widen MMUIdxMap Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-30 21:07 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 30/82] target/arm: Convert arm_mmu_idx_to_el from switch to table Richard Henderson
` (52 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpu.h | 207 +-----------------------------------------
target/arm/mmuidx.h | 216 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 217 insertions(+), 206 deletions(-)
create mode 100644 target/arm/mmuidx.h
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 4940bd6a45..da42bd4466 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -33,6 +33,7 @@
#include "target/arm/multiprocessing.h"
#include "target/arm/gtimer.h"
#include "target/arm/cpu-sysregs.h"
+#include "target/arm/mmuidx.h"
#define EXCP_UDEF 1 /* undefined instruction */
#define EXCP_SWI 2 /* software interrupt */
@@ -2736,212 +2737,6 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
#define TYPE_ARM_HOST_CPU "host-" TYPE_ARM_CPU
-/* ARM has the following "translation regimes" (as the ARM ARM calls them):
- *
- * If EL3 is 64-bit:
- * + NonSecure EL1 & 0 stage 1
- * + NonSecure EL1 & 0 stage 2
- * + NonSecure EL2
- * + NonSecure EL2 & 0 (ARMv8.1-VHE)
- * + Secure EL1 & 0 stage 1
- * + Secure EL1 & 0 stage 2 (FEAT_SEL2)
- * + Secure EL2 (FEAT_SEL2)
- * + Secure EL2 & 0 (FEAT_SEL2)
- * + Realm EL1 & 0 stage 1 (FEAT_RME)
- * + Realm EL1 & 0 stage 2 (FEAT_RME)
- * + Realm EL2 (FEAT_RME)
- * + EL3
- * If EL3 is 32-bit:
- * + NonSecure PL1 & 0 stage 1
- * + NonSecure PL1 & 0 stage 2
- * + NonSecure PL2
- * + Secure PL1 & 0
- * (reminder: for 32 bit EL3, Secure PL1 is *EL3*, not EL1.)
- *
- * For QEMU, an mmu_idx is not quite the same as a translation regime because:
- * 1. we need to split the "EL1 & 0" and "EL2 & 0" regimes into two mmu_idxes,
- * because they may differ in access permissions even if the VA->PA map is
- * the same
- * 2. we want to cache in our TLB the full VA->IPA->PA lookup for a stage 1+2
- * translation, which means that we have one mmu_idx that deals with two
- * concatenated translation regimes [this sort of combined s1+2 TLB is
- * architecturally permitted]
- * 3. we don't need to allocate an mmu_idx to translations that we won't be
- * handling via the TLB. The only way to do a stage 1 translation without
- * the immediate stage 2 translation is via the ATS or AT system insns,
- * which can be slow-pathed and always do a page table walk.
- * The only use of stage 2 translations is either as part of an s1+2
- * lookup or when loading the descriptors during a stage 1 page table walk,
- * and in both those cases we don't use the TLB.
- * 4. we can also safely fold together the "32 bit EL3" and "64 bit EL3"
- * translation regimes, because they map reasonably well to each other
- * and they can't both be active at the same time.
- * 5. we want to be able to use the TLB for accesses done as part of a
- * stage1 page table walk, rather than having to walk the stage2 page
- * table over and over.
- * 6. we need separate EL1/EL2 mmu_idx for handling the Privileged Access
- * Never (PAN) bit within PSTATE.
- * 7. we fold together most secure and non-secure regimes for A-profile,
- * because there are no banked system registers for aarch64, so the
- * process of switching between secure and non-secure is
- * already heavyweight.
- * 8. we cannot fold together Stage 2 Secure and Stage 2 NonSecure,
- * because both are in use simultaneously for Secure EL2.
- *
- * This gives us the following list of cases:
- *
- * EL0 EL1&0 stage 1+2 (aka NS PL0 PL1&0 stage 1+2)
- * EL1 EL1&0 stage 1+2 (aka NS PL1 PL1&0 stage 1+2)
- * EL1 EL1&0 stage 1+2 +PAN (aka NS PL1 P1&0 stage 1+2 +PAN)
- * EL0 EL2&0
- * EL2 EL2&0
- * EL2 EL2&0 +PAN
- * EL2 (aka NS PL2)
- * EL3 (aka AArch32 S PL1 PL1&0)
- * AArch32 S PL0 PL1&0 (we call this EL30_0)
- * AArch32 S PL1 PL1&0 +PAN (we call this EL30_3_PAN)
- * Stage2 Secure
- * Stage2 NonSecure
- * plus one TLB per Physical address space: S, NS, Realm, Root
- *
- * for a total of 16 different mmu_idx.
- *
- * R profile CPUs have an MPU, but can use the same set of MMU indexes
- * as A profile. They only need to distinguish EL0 and EL1 (and
- * EL2 for cores like the Cortex-R52).
- *
- * M profile CPUs are rather different as they do not have a true MMU.
- * They have the following different MMU indexes:
- * User
- * Privileged
- * User, execution priority negative (ie the MPU HFNMIENA bit may apply)
- * Privileged, execution priority negative (ditto)
- * If the CPU supports the v8M Security Extension then there are also:
- * Secure User
- * Secure Privileged
- * Secure User, execution priority negative
- * Secure Privileged, execution priority negative
- *
- * The ARMMMUIdx and the mmu index value used by the core QEMU TLB code
- * are not quite the same -- different CPU types (most notably M profile
- * vs A/R profile) would like to use MMU indexes with different semantics,
- * but since we don't ever need to use all of those in a single CPU we
- * can avoid having to set NB_MMU_MODES to "total number of A profile MMU
- * modes + total number of M profile MMU modes". The lower bits of
- * ARMMMUIdx are the core TLB mmu index, and the higher bits are always
- * the same for any particular CPU.
- * Variables of type ARMMUIdx are always full values, and the core
- * index values are in variables of type 'int'.
- *
- * Our enumeration includes at the end some entries which are not "true"
- * mmu_idx values in that they don't have corresponding TLBs and are only
- * valid for doing slow path page table walks.
- *
- * The constant names here are patterned after the general style of the names
- * of the AT/ATS operations.
- * The values used are carefully arranged to make mmu_idx => EL lookup easy.
- * For M profile we arrange them to have a bit for priv, a bit for negpri
- * and a bit for secure.
- */
-#define ARM_MMU_IDX_A 0x10 /* A profile */
-#define ARM_MMU_IDX_NOTLB 0x20 /* does not have a TLB */
-#define ARM_MMU_IDX_M 0x40 /* M profile */
-
-/* Meanings of the bits for M profile mmu idx values */
-#define ARM_MMU_IDX_M_PRIV 0x1
-#define ARM_MMU_IDX_M_NEGPRI 0x2
-#define ARM_MMU_IDX_M_S 0x4 /* Secure */
-
-#define ARM_MMU_IDX_TYPE_MASK \
- (ARM_MMU_IDX_A | ARM_MMU_IDX_M | ARM_MMU_IDX_NOTLB)
-#define ARM_MMU_IDX_COREIDX_MASK 0xf
-
-typedef enum ARMMMUIdx {
- /*
- * A-profile.
- */
- ARMMMUIdx_E10_0 = 0 | ARM_MMU_IDX_A,
- ARMMMUIdx_E20_0 = 1 | ARM_MMU_IDX_A,
- ARMMMUIdx_E10_1 = 2 | ARM_MMU_IDX_A,
- ARMMMUIdx_E20_2 = 3 | ARM_MMU_IDX_A,
- ARMMMUIdx_E10_1_PAN = 4 | ARM_MMU_IDX_A,
- ARMMMUIdx_E20_2_PAN = 5 | ARM_MMU_IDX_A,
- ARMMMUIdx_E2 = 6 | ARM_MMU_IDX_A,
- ARMMMUIdx_E3 = 7 | ARM_MMU_IDX_A,
- ARMMMUIdx_E30_0 = 8 | ARM_MMU_IDX_A,
- ARMMMUIdx_E30_3_PAN = 9 | ARM_MMU_IDX_A,
-
- /*
- * Used for second stage of an S12 page table walk, or for descriptor
- * loads during first stage of an S1 page table walk. Note that both
- * are in use simultaneously for SecureEL2: the security state for
- * the S2 ptw is selected by the NS bit from the S1 ptw.
- */
- ARMMMUIdx_Stage2_S = 10 | ARM_MMU_IDX_A,
- ARMMMUIdx_Stage2 = 11 | ARM_MMU_IDX_A,
-
- /* TLBs with 1-1 mapping to the physical address spaces. */
- ARMMMUIdx_Phys_S = 12 | ARM_MMU_IDX_A,
- ARMMMUIdx_Phys_NS = 13 | ARM_MMU_IDX_A,
- ARMMMUIdx_Phys_Root = 14 | ARM_MMU_IDX_A,
- ARMMMUIdx_Phys_Realm = 15 | ARM_MMU_IDX_A,
-
- /*
- * These are not allocated TLBs and are used only for AT system
- * instructions or for the first stage of an S12 page table walk.
- */
- ARMMMUIdx_Stage1_E0 = 0 | ARM_MMU_IDX_NOTLB,
- ARMMMUIdx_Stage1_E1 = 1 | ARM_MMU_IDX_NOTLB,
- ARMMMUIdx_Stage1_E1_PAN = 2 | ARM_MMU_IDX_NOTLB,
-
- /*
- * M-profile.
- */
- ARMMMUIdx_MUser = ARM_MMU_IDX_M,
- ARMMMUIdx_MPriv = ARM_MMU_IDX_M | ARM_MMU_IDX_M_PRIV,
- ARMMMUIdx_MUserNegPri = ARMMMUIdx_MUser | ARM_MMU_IDX_M_NEGPRI,
- ARMMMUIdx_MPrivNegPri = ARMMMUIdx_MPriv | ARM_MMU_IDX_M_NEGPRI,
- ARMMMUIdx_MSUser = ARMMMUIdx_MUser | ARM_MMU_IDX_M_S,
- ARMMMUIdx_MSPriv = ARMMMUIdx_MPriv | ARM_MMU_IDX_M_S,
- ARMMMUIdx_MSUserNegPri = ARMMMUIdx_MUserNegPri | ARM_MMU_IDX_M_S,
- ARMMMUIdx_MSPrivNegPri = ARMMMUIdx_MPrivNegPri | ARM_MMU_IDX_M_S,
-} ARMMMUIdx;
-
-/*
- * Bit macros for the core-mmu-index values for each index,
- * for use when calling tlb_flush_by_mmuidx() and friends.
- */
-#define TO_CORE_BIT(NAME) \
- ARMMMUIdxBit_##NAME = 1 << (ARMMMUIdx_##NAME & ARM_MMU_IDX_COREIDX_MASK)
-
-typedef enum ARMMMUIdxBit {
- TO_CORE_BIT(E10_0),
- TO_CORE_BIT(E20_0),
- TO_CORE_BIT(E10_1),
- TO_CORE_BIT(E10_1_PAN),
- TO_CORE_BIT(E2),
- TO_CORE_BIT(E20_2),
- TO_CORE_BIT(E20_2_PAN),
- TO_CORE_BIT(E3),
- TO_CORE_BIT(E30_0),
- TO_CORE_BIT(E30_3_PAN),
- TO_CORE_BIT(Stage2),
- TO_CORE_BIT(Stage2_S),
-
- TO_CORE_BIT(MUser),
- TO_CORE_BIT(MPriv),
- TO_CORE_BIT(MUserNegPri),
- TO_CORE_BIT(MPrivNegPri),
- TO_CORE_BIT(MSUser),
- TO_CORE_BIT(MSPriv),
- TO_CORE_BIT(MSUserNegPri),
- TO_CORE_BIT(MSPrivNegPri),
-} ARMMMUIdxBit;
-
-#undef TO_CORE_BIT
-
-#define MMU_USER_IDX 0
-
/* Indexes used when registering address spaces with cpu_address_space_init */
typedef enum ARMASIdx {
ARMASIdx_NS = 0,
diff --git a/target/arm/mmuidx.h b/target/arm/mmuidx.h
new file mode 100644
index 0000000000..5b9b4bc84f
--- /dev/null
+++ b/target/arm/mmuidx.h
@@ -0,0 +1,216 @@
+/*
+ * QEMU Arm software mmu index definitions
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef TARGET_ARM_MMUIDX_H
+#define TARGET_ARM_MMUIDX_H
+
+/*
+ * Arm has the following "translation regimes" (as the Arm ARM calls them):
+ *
+ * If EL3 is 64-bit:
+ * + NonSecure EL1 & 0 stage 1
+ * + NonSecure EL1 & 0 stage 2
+ * + NonSecure EL2
+ * + NonSecure EL2 & 0 (ARMv8.1-VHE)
+ * + Secure EL1 & 0 stage 1
+ * + Secure EL1 & 0 stage 2 (FEAT_SEL2)
+ * + Secure EL2 (FEAT_SEL2)
+ * + Secure EL2 & 0 (FEAT_SEL2)
+ * + Realm EL1 & 0 stage 1 (FEAT_RME)
+ * + Realm EL1 & 0 stage 2 (FEAT_RME)
+ * + Realm EL2 (FEAT_RME)
+ * + EL3
+ * If EL3 is 32-bit:
+ * + NonSecure PL1 & 0 stage 1
+ * + NonSecure PL1 & 0 stage 2
+ * + NonSecure PL2
+ * + Secure PL1 & 0
+ * (reminder: for 32 bit EL3, Secure PL1 is *EL3*, not EL1.)
+ *
+ * For QEMU, an mmu_idx is not quite the same as a translation regime because:
+ * 1. we need to split the "EL1 & 0" and "EL2 & 0" regimes into two mmu_idxes,
+ * because they may differ in access permissions even if the VA->PA map is
+ * the same
+ * 2. we want to cache in our TLB the full VA->IPA->PA lookup for a stage 1+2
+ * translation, which means that we have one mmu_idx that deals with two
+ * concatenated translation regimes [this sort of combined s1+2 TLB is
+ * architecturally permitted]
+ * 3. we don't need to allocate an mmu_idx to translations that we won't be
+ * handling via the TLB. The only way to do a stage 1 translation without
+ * the immediate stage 2 translation is via the ATS or AT system insns,
+ * which can be slow-pathed and always do a page table walk.
+ * The only use of stage 2 translations is either as part of an s1+2
+ * lookup or when loading the descriptors during a stage 1 page table walk,
+ * and in both those cases we don't use the TLB.
+ * 4. we can also safely fold together the "32 bit EL3" and "64 bit EL3"
+ * translation regimes, because they map reasonably well to each other
+ * and they can't both be active at the same time.
+ * 5. we want to be able to use the TLB for accesses done as part of a
+ * stage1 page table walk, rather than having to walk the stage2 page
+ * table over and over.
+ * 6. we need separate EL1/EL2 mmu_idx for handling the Privileged Access
+ * Never (PAN) bit within PSTATE.
+ * 7. we fold together most secure and non-secure regimes for A-profile,
+ * because there are no banked system registers for aarch64, so the
+ * process of switching between secure and non-secure is
+ * already heavyweight.
+ * 8. we cannot fold together Stage 2 Secure and Stage 2 NonSecure,
+ * because both are in use simultaneously for Secure EL2.
+ *
+ * This gives us the following list of cases:
+ *
+ * EL0 EL1&0 stage 1+2 (aka NS PL0 PL1&0 stage 1+2)
+ * EL1 EL1&0 stage 1+2 (aka NS PL1 PL1&0 stage 1+2)
+ * EL1 EL1&0 stage 1+2 +PAN (aka NS PL1 P1&0 stage 1+2 +PAN)
+ * EL0 EL2&0
+ * EL2 EL2&0
+ * EL2 EL2&0 +PAN
+ * EL2 (aka NS PL2)
+ * EL3 (aka AArch32 S PL1 PL1&0)
+ * AArch32 S PL0 PL1&0 (we call this EL30_0)
+ * AArch32 S PL1 PL1&0 +PAN (we call this EL30_3_PAN)
+ * Stage2 Secure
+ * Stage2 NonSecure
+ * plus one TLB per Physical address space: S, NS, Realm, Root
+ *
+ * for a total of 16 different mmu_idx.
+ *
+ * R profile CPUs have an MPU, but can use the same set of MMU indexes
+ * as A profile. They only need to distinguish EL0 and EL1 (and
+ * EL2 for cores like the Cortex-R52).
+ *
+ * M profile CPUs are rather different as they do not have a true MMU.
+ * They have the following different MMU indexes:
+ * User
+ * Privileged
+ * User, execution priority negative (ie the MPU HFNMIENA bit may apply)
+ * Privileged, execution priority negative (ditto)
+ * If the CPU supports the v8M Security Extension then there are also:
+ * Secure User
+ * Secure Privileged
+ * Secure User, execution priority negative
+ * Secure Privileged, execution priority negative
+ *
+ * The ARMMMUIdx and the mmu index value used by the core QEMU TLB code
+ * are not quite the same -- different CPU types (most notably M profile
+ * vs A/R profile) would like to use MMU indexes with different semantics,
+ * but since we don't ever need to use all of those in a single CPU we
+ * can avoid having to set NB_MMU_MODES to "total number of A profile MMU
+ * modes + total number of M profile MMU modes". The lower bits of
+ * ARMMMUIdx are the core TLB mmu index, and the higher bits are always
+ * the same for any particular CPU.
+ * Variables of type ARMMUIdx are always full values, and the core
+ * index values are in variables of type 'int'.
+ *
+ * Our enumeration includes at the end some entries which are not "true"
+ * mmu_idx values in that they don't have corresponding TLBs and are only
+ * valid for doing slow path page table walks.
+ *
+ * The constant names here are patterned after the general style of the names
+ * of the AT/ATS operations.
+ * The values used are carefully arranged to make mmu_idx => EL lookup easy.
+ * For M profile we arrange them to have a bit for priv, a bit for negpri
+ * and a bit for secure.
+ */
+#define ARM_MMU_IDX_A 0x10 /* A profile */
+#define ARM_MMU_IDX_NOTLB 0x20 /* does not have a TLB */
+#define ARM_MMU_IDX_M 0x40 /* M profile */
+
+/* Meanings of the bits for M profile mmu idx values */
+#define ARM_MMU_IDX_M_PRIV 0x1
+#define ARM_MMU_IDX_M_NEGPRI 0x2
+#define ARM_MMU_IDX_M_S 0x4 /* Secure */
+
+#define ARM_MMU_IDX_TYPE_MASK \
+ (ARM_MMU_IDX_A | ARM_MMU_IDX_M | ARM_MMU_IDX_NOTLB)
+#define ARM_MMU_IDX_COREIDX_MASK 0xf
+
+typedef enum ARMMMUIdx {
+ /*
+ * A-profile.
+ */
+ ARMMMUIdx_E10_0 = 0 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E20_0 = 1 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E10_1 = 2 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E20_2 = 3 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E10_1_PAN = 4 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E20_2_PAN = 5 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E2 = 6 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E3 = 7 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E30_0 = 8 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E30_3_PAN = 9 | ARM_MMU_IDX_A,
+
+ /*
+ * Used for second stage of an S12 page table walk, or for descriptor
+ * loads during first stage of an S1 page table walk. Note that both
+ * are in use simultaneously for SecureEL2: the security state for
+ * the S2 ptw is selected by the NS bit from the S1 ptw.
+ */
+ ARMMMUIdx_Stage2_S = 10 | ARM_MMU_IDX_A,
+ ARMMMUIdx_Stage2 = 11 | ARM_MMU_IDX_A,
+
+ /* TLBs with 1-1 mapping to the physical address spaces. */
+ ARMMMUIdx_Phys_S = 12 | ARM_MMU_IDX_A,
+ ARMMMUIdx_Phys_NS = 13 | ARM_MMU_IDX_A,
+ ARMMMUIdx_Phys_Root = 14 | ARM_MMU_IDX_A,
+ ARMMMUIdx_Phys_Realm = 15 | ARM_MMU_IDX_A,
+
+ /*
+ * These are not allocated TLBs and are used only for AT system
+ * instructions or for the first stage of an S12 page table walk.
+ */
+ ARMMMUIdx_Stage1_E0 = 0 | ARM_MMU_IDX_NOTLB,
+ ARMMMUIdx_Stage1_E1 = 1 | ARM_MMU_IDX_NOTLB,
+ ARMMMUIdx_Stage1_E1_PAN = 2 | ARM_MMU_IDX_NOTLB,
+
+ /*
+ * M-profile.
+ */
+ ARMMMUIdx_MUser = ARM_MMU_IDX_M,
+ ARMMMUIdx_MPriv = ARM_MMU_IDX_M | ARM_MMU_IDX_M_PRIV,
+ ARMMMUIdx_MUserNegPri = ARMMMUIdx_MUser | ARM_MMU_IDX_M_NEGPRI,
+ ARMMMUIdx_MPrivNegPri = ARMMMUIdx_MPriv | ARM_MMU_IDX_M_NEGPRI,
+ ARMMMUIdx_MSUser = ARMMMUIdx_MUser | ARM_MMU_IDX_M_S,
+ ARMMMUIdx_MSPriv = ARMMMUIdx_MPriv | ARM_MMU_IDX_M_S,
+ ARMMMUIdx_MSUserNegPri = ARMMMUIdx_MUserNegPri | ARM_MMU_IDX_M_S,
+ ARMMMUIdx_MSPrivNegPri = ARMMMUIdx_MPrivNegPri | ARM_MMU_IDX_M_S,
+} ARMMMUIdx;
+
+/*
+ * Bit macros for the core-mmu-index values for each index,
+ * for use when calling tlb_flush_by_mmuidx() and friends.
+ */
+#define TO_CORE_BIT(NAME) \
+ ARMMMUIdxBit_##NAME = 1 << (ARMMMUIdx_##NAME & ARM_MMU_IDX_COREIDX_MASK)
+
+typedef enum ARMMMUIdxBit {
+ TO_CORE_BIT(E10_0),
+ TO_CORE_BIT(E20_0),
+ TO_CORE_BIT(E10_1),
+ TO_CORE_BIT(E10_1_PAN),
+ TO_CORE_BIT(E2),
+ TO_CORE_BIT(E20_2),
+ TO_CORE_BIT(E20_2_PAN),
+ TO_CORE_BIT(E3),
+ TO_CORE_BIT(E30_0),
+ TO_CORE_BIT(E30_3_PAN),
+ TO_CORE_BIT(Stage2),
+ TO_CORE_BIT(Stage2_S),
+
+ TO_CORE_BIT(MUser),
+ TO_CORE_BIT(MPriv),
+ TO_CORE_BIT(MUserNegPri),
+ TO_CORE_BIT(MPrivNegPri),
+ TO_CORE_BIT(MSUser),
+ TO_CORE_BIT(MSPriv),
+ TO_CORE_BIT(MSUserNegPri),
+ TO_CORE_BIT(MSPrivNegPri),
+} ARMMMUIdxBit;
+
+#undef TO_CORE_BIT
+
+#define MMU_USER_IDX 0
+
+#endif /* TARGET_ARM_MMUIDX_H */
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 30/82] target/arm: Convert arm_mmu_idx_to_el from switch to table
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (28 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 29/82] target/arm: Split out mmuidx.h from cpu.h Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-30 21:10 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 31/82] target/arm: Remove unused env argument from regime_el Richard Henderson
` (51 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
In an effort to keep all ARMMMUIdx data in one place, begin construction
of an info table describing all of the properties of the mmu_idx. Begin
with the access EL.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/internals.h | 3 +--
target/arm/mmuidx-internal.h | 27 ++++++++++++++++++++++++
target/arm/helper.c | 27 ------------------------
target/arm/mmuidx.c | 41 ++++++++++++++++++++++++++++++++++++
target/arm/meson.build | 7 +++++-
5 files changed, 75 insertions(+), 30 deletions(-)
create mode 100644 target/arm/mmuidx-internal.h
create mode 100644 target/arm/mmuidx.c
diff --git a/target/arm/internals.h b/target/arm/internals.h
index b6499683cc..2dc82330ec 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -34,6 +34,7 @@
#include "system/memory.h"
#include "syndrome.h"
#include "cpu-features.h"
+#include "mmuidx-internal.h"
/* register banks for CPU modes */
#define BANK_USRSYS 0
@@ -986,8 +987,6 @@ static inline ARMMMUIdx core_to_aa64_mmu_idx(int mmu_idx)
return mmu_idx | ARM_MMU_IDX_A;
}
-int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx);
-
/* Return the MMU index for a v7M CPU in the specified security state */
ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate);
diff --git a/target/arm/mmuidx-internal.h b/target/arm/mmuidx-internal.h
new file mode 100644
index 0000000000..35d41495cd
--- /dev/null
+++ b/target/arm/mmuidx-internal.h
@@ -0,0 +1,27 @@
+/*
+ * QEMU Arm software mmu index internal definitions
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef TARGET_ARM_MMUIDX_INTERNAL_H
+#define TARGET_ARM_MMUIDX_INTERNAL_H
+
+#include "mmuidx.h"
+#include "tcg/debug-assert.h"
+#include "hw/registerfields.h"
+
+
+FIELD(MMUIDXINFO, EL, 0, 2)
+FIELD(MMUIDXINFO, ELVALID, 2, 1)
+
+extern const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8];
+
+/* Return the exception level associated with this mmu index. */
+static inline int arm_mmu_idx_to_el(ARMMMUIdx idx)
+{
+ tcg_debug_assert((unsigned)idx < ARRAY_SIZE(arm_mmuidx_table));
+ tcg_debug_assert(FIELD_EX32(arm_mmuidx_table[idx], MMUIDXINFO, ELVALID));
+ return FIELD_EX32(arm_mmuidx_table[idx], MMUIDXINFO, EL);
+}
+
+#endif /* TARGET_ARM_MMUIDX_INTERNAL_H */
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 154bda3cd4..a97838a04e 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -9895,33 +9895,6 @@ int fp_exception_el(CPUARMState *env, int cur_el)
return 0;
}
-/* Return the exception level we're running at if this is our mmu_idx */
-int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
-{
- if (mmu_idx & ARM_MMU_IDX_M) {
- return mmu_idx & ARM_MMU_IDX_M_PRIV;
- }
-
- switch (mmu_idx) {
- case ARMMMUIdx_E10_0:
- case ARMMMUIdx_E20_0:
- case ARMMMUIdx_E30_0:
- return 0;
- case ARMMMUIdx_E10_1:
- case ARMMMUIdx_E10_1_PAN:
- return 1;
- case ARMMMUIdx_E2:
- case ARMMMUIdx_E20_2:
- case ARMMMUIdx_E20_2_PAN:
- return 2;
- case ARMMMUIdx_E3:
- case ARMMMUIdx_E30_3_PAN:
- return 3;
- default:
- g_assert_not_reached();
- }
-}
-
#ifndef CONFIG_TCG
ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate)
{
diff --git a/target/arm/mmuidx.c b/target/arm/mmuidx.c
new file mode 100644
index 0000000000..309b1d68df
--- /dev/null
+++ b/target/arm/mmuidx.c
@@ -0,0 +1,41 @@
+/*
+ * QEMU Arm software mmu index definitions
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "mmuidx-internal.h"
+
+
+#define EL(X) ((X << R_MMUIDXINFO_EL_SHIFT) | R_MMUIDXINFO_ELVALID_MASK)
+
+const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8] = {
+ /*
+ * A-profile.
+ */
+ [ARMMMUIdx_E10_0] = EL(0),
+ [ARMMMUIdx_E10_1] = EL(1),
+ [ARMMMUIdx_E10_1_PAN] = EL(1),
+
+ [ARMMMUIdx_E20_0] = EL(0),
+ [ARMMMUIdx_E20_2] = EL(2),
+ [ARMMMUIdx_E20_2_PAN] = EL(2),
+
+ [ARMMMUIdx_E2] = EL(2),
+
+ [ARMMMUIdx_E3] = EL(3),
+ [ARMMMUIdx_E30_0] = EL(0),
+ [ARMMMUIdx_E30_3_PAN] = EL(3),
+
+ /*
+ * M-profile.
+ */
+ [ARMMMUIdx_MUser] = EL(0),
+ [ARMMMUIdx_MPriv] = EL(1),
+ [ARMMMUIdx_MUserNegPri] = EL(0),
+ [ARMMMUIdx_MPrivNegPri] = EL(1),
+ [ARMMMUIdx_MSUser] = EL(0),
+ [ARMMMUIdx_MSPriv] = EL(1),
+ [ARMMMUIdx_MSUserNegPri] = EL(0),
+ [ARMMMUIdx_MSPrivNegPri] = EL(1),
+};
diff --git a/target/arm/meson.build b/target/arm/meson.build
index 07d9271aa4..91630a1f72 100644
--- a/target/arm/meson.build
+++ b/target/arm/meson.build
@@ -6,7 +6,12 @@ arm_ss.add(files(
arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
'cpu64.c',
- 'gdbstub64.c'))
+ 'gdbstub64.c'
+))
+
+arm_common_ss.add(files(
+ 'mmuidx.c',
+))
arm_system_ss = ss.source_set()
arm_common_system_ss = ss.source_set()
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 31/82] target/arm: Remove unused env argument from regime_el
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (29 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 30/82] target/arm: Convert arm_mmu_idx_to_el from switch to table Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-30 21:13 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 32/82] target/arm: Convert regime_el from switch to table Richard Henderson
` (50 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/internals.h | 8 ++++----
target/arm/helper.c | 2 +-
target/arm/ptw.c | 34 +++++++++++++++++-----------------
target/arm/tcg/mte_helper.c | 2 +-
4 files changed, 23 insertions(+), 23 deletions(-)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 2dc82330ec..4991d6ab7f 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1076,7 +1076,7 @@ static inline bool regime_is_stage2(ARMMMUIdx mmu_idx)
}
/* Return the exception level which controls this address translation regime */
-static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
+static inline uint32_t regime_el(ARMMMUIdx mmu_idx)
{
switch (mmu_idx) {
case ARMMMUIdx_E20_0:
@@ -1130,7 +1130,7 @@ static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
/* Return the SCTLR value which controls this address translation regime */
static inline uint64_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)
{
- return env->cp15.sctlr_el[regime_el(env, mmu_idx)];
+ return env->cp15.sctlr_el[regime_el(mmu_idx)];
}
/*
@@ -1162,13 +1162,13 @@ static inline uint64_t regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
v |= env->cp15.vtcr_el2 & VTCR_SHARED_FIELD_MASK;
return v;
}
- return env->cp15.tcr_el[regime_el(env, mmu_idx)];
+ return env->cp15.tcr_el[regime_el(mmu_idx)];
}
/* Return true if the translation regime is using LPAE format page tables */
static inline bool regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx)
{
- int el = regime_el(env, mmu_idx);
+ int el = regime_el(mmu_idx);
if (el == 2 || arm_el_is_aa64(env, el)) {
return true;
}
diff --git a/target/arm/helper.c b/target/arm/helper.c
index a97838a04e..461572f918 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -9633,7 +9633,7 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
ARMGranuleSize gran;
ARMCPU *cpu = env_archcpu(env);
bool stage2 = regime_is_stage2(mmu_idx);
- int r_el = regime_el(env, mmu_idx);
+ int r_el = regime_el(mmu_idx);
if (!regime_has_2_ranges(mmu_idx)) {
select = 0;
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 820d5e65a0..30c83334b6 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -232,9 +232,9 @@ static uint64_t regime_ttbr(CPUARMState *env, ARMMMUIdx mmu_idx, int ttbrn)
return env->cp15.vsttbr_el2;
}
if (ttbrn == 0) {
- return env->cp15.ttbr0_el[regime_el(env, mmu_idx)];
+ return env->cp15.ttbr0_el[regime_el(mmu_idx)];
} else {
- return env->cp15.ttbr1_el[regime_el(env, mmu_idx)];
+ return env->cp15.ttbr1_el[regime_el(mmu_idx)];
}
}
@@ -1023,7 +1023,7 @@ static bool get_phys_addr_v5(CPUARMState *env, S1Translate *ptw,
}
type = (desc & 3);
domain = (desc >> 5) & 0x0f;
- if (regime_el(env, ptw->in_mmu_idx) == 1) {
+ if (regime_el(ptw->in_mmu_idx) == 1) {
dacr = env->cp15.dacr_ns;
} else {
dacr = env->cp15.dacr_s;
@@ -1163,7 +1163,7 @@ static bool get_phys_addr_v6(CPUARMState *env, S1Translate *ptw,
/* Page or Section. */
domain = (desc >> 5) & 0x0f;
}
- if (regime_el(env, mmu_idx) == 1) {
+ if (regime_el(mmu_idx) == 1) {
dacr = env->cp15.dacr_ns;
} else {
dacr = env->cp15.dacr_s;
@@ -1454,7 +1454,7 @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
xn = pxn || (user_rw & PAGE_WRITE);
}
} else if (arm_feature(env, ARM_FEATURE_V7)) {
- switch (regime_el(env, mmu_idx)) {
+ switch (regime_el(mmu_idx)) {
case 1:
case 3:
if (is_user) {
@@ -1510,7 +1510,7 @@ static int get_S1prot_indirect(CPUARMState *env, S1Translate *ptw,
/* F */ 0, /* reserved */
};
- uint32_t el = regime_el(env, mmu_idx);
+ uint32_t el = regime_el(mmu_idx);
uint64_t pir = env->cp15.pir_el[el];
uint64_t pire0 = 0;
int perm;
@@ -1585,7 +1585,7 @@ static ARMVAParameters aa32_va_parameters(CPUARMState *env, uint32_t va,
ARMMMUIdx mmu_idx)
{
uint64_t tcr = regime_tcr(env, mmu_idx);
- uint32_t el = regime_el(env, mmu_idx);
+ uint32_t el = regime_el(mmu_idx);
int select, tsz;
bool epd, hpd;
@@ -1811,7 +1811,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
int addrsize, inputsize, outputsize;
uint64_t tcr = regime_tcr(env, mmu_idx);
int ap, prot;
- uint32_t el = regime_el(env, mmu_idx);
+ uint32_t el = regime_el(mmu_idx);
uint64_t descaddrmask;
bool aarch64 = arm_el_is_aa64(env, el);
uint64_t descriptor, new_descriptor;
@@ -2259,7 +2259,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
/* Index into MAIR registers for cache attributes */
attrindx = extract32(attrs, 2, 3);
- mair = env->cp15.mair_el[regime_el(env, mmu_idx)];
+ mair = env->cp15.mair_el[regime_el(mmu_idx)];
assert(attrindx <= 7);
result->cacheattrs.is_s2_format = false;
result->cacheattrs.attrs = extract64(mair, attrindx * 8, 8);
@@ -2737,7 +2737,7 @@ static bool get_phys_addr_pmsav7(CPUARMState *env,
static uint32_t *regime_rbar(CPUARMState *env, ARMMMUIdx mmu_idx,
uint32_t secure)
{
- if (regime_el(env, mmu_idx) == 2) {
+ if (regime_el(mmu_idx) == 2) {
return env->pmsav8.hprbar;
} else {
return env->pmsav8.rbar[secure];
@@ -2747,7 +2747,7 @@ static uint32_t *regime_rbar(CPUARMState *env, ARMMMUIdx mmu_idx,
static uint32_t *regime_rlar(CPUARMState *env, ARMMMUIdx mmu_idx,
uint32_t secure)
{
- if (regime_el(env, mmu_idx) == 2) {
+ if (regime_el(mmu_idx) == 2) {
return env->pmsav8.hprlar;
} else {
return env->pmsav8.rlar[secure];
@@ -2779,7 +2779,7 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
uint32_t addr_page_limit = addr_page_base + (TARGET_PAGE_SIZE - 1);
int region_counter;
- if (regime_el(env, mmu_idx) == 2) {
+ if (regime_el(mmu_idx) == 2) {
region_counter = cpu->pmsav8r_hdregion;
} else {
region_counter = cpu->pmsav7_dregion;
@@ -2905,7 +2905,7 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
xn = 1;
}
- if (regime_el(env, mmu_idx) == 2) {
+ if (regime_el(mmu_idx) == 2) {
result->f.prot = simple_ap_to_rw_prot_is_user(ap,
mmu_idx != ARMMMUIdx_E2);
} else {
@@ -2914,7 +2914,7 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
if (!arm_feature(env, ARM_FEATURE_M)) {
uint8_t attrindx = extract32(matched_rlar, 1, 3);
- uint64_t mair = env->cp15.mair_el[regime_el(env, mmu_idx)];
+ uint64_t mair = env->cp15.mair_el[regime_el(mmu_idx)];
uint8_t sh = extract32(matched_rlar, 3, 2);
if (regime_sctlr(env, mmu_idx) & SCTLR_WXN &&
@@ -2922,7 +2922,7 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
xn = 0x1;
}
- if ((regime_el(env, mmu_idx) == 1) &&
+ if ((regime_el(mmu_idx) == 1) &&
regime_sctlr(env, mmu_idx) & SCTLR_UWXN && ap == 0x1) {
pxn = 0x1;
}
@@ -3407,7 +3407,7 @@ static bool get_phys_addr_disabled(CPUARMState *env,
break;
default:
- r_el = regime_el(env, mmu_idx);
+ r_el = regime_el(mmu_idx);
if (arm_el_is_aa64(env, r_el)) {
int pamax = arm_pamax(env_archcpu(env));
uint64_t tcr = env->cp15.tcr_el[r_el];
@@ -3659,7 +3659,7 @@ static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw,
*/
if (address < 0x02000000 && mmu_idx != ARMMMUIdx_Stage2
&& !arm_feature(env, ARM_FEATURE_V8)) {
- if (regime_el(env, mmu_idx) == 3) {
+ if (regime_el(mmu_idx) == 3) {
address += env->cp15.fcseidr_s;
} else {
address += env->cp15.fcseidr_ns;
diff --git a/target/arm/tcg/mte_helper.c b/target/arm/tcg/mte_helper.c
index 0efc18a181..ed30026b7d 100644
--- a/target/arm/tcg/mte_helper.c
+++ b/target/arm/tcg/mte_helper.c
@@ -604,7 +604,7 @@ void mte_check_fail(CPUARMState *env, uint32_t desc,
int el, reg_el, tcf;
uint64_t sctlr;
- reg_el = regime_el(env, arm_mmu_idx);
+ reg_el = regime_el(arm_mmu_idx);
sctlr = env->cp15.sctlr_el[reg_el];
switch (arm_mmu_idx) {
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 32/82] target/arm: Convert regime_el from switch to table
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (30 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 31/82] target/arm: Remove unused env argument from regime_el Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-30 21:15 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 33/82] target/arm: Convert regime_has_2_ranges " Richard Henderson
` (49 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/internals.h | 35 ----------------------------
target/arm/mmuidx-internal.h | 13 +++++++++++
target/arm/mmuidx.c | 44 +++++++++++++++++++++---------------
3 files changed, 39 insertions(+), 53 deletions(-)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 4991d6ab7f..3b730a5d81 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1075,41 +1075,6 @@ static inline bool regime_is_stage2(ARMMMUIdx mmu_idx)
return mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S;
}
-/* Return the exception level which controls this address translation regime */
-static inline uint32_t regime_el(ARMMMUIdx mmu_idx)
-{
- switch (mmu_idx) {
- case ARMMMUIdx_E20_0:
- case ARMMMUIdx_E20_2:
- case ARMMMUIdx_E20_2_PAN:
- case ARMMMUIdx_Stage2:
- case ARMMMUIdx_Stage2_S:
- case ARMMMUIdx_E2:
- return 2;
- case ARMMMUIdx_E3:
- case ARMMMUIdx_E30_0:
- case ARMMMUIdx_E30_3_PAN:
- return 3;
- case ARMMMUIdx_E10_0:
- case ARMMMUIdx_Stage1_E0:
- case ARMMMUIdx_Stage1_E1:
- case ARMMMUIdx_Stage1_E1_PAN:
- case ARMMMUIdx_E10_1:
- case ARMMMUIdx_E10_1_PAN:
- case ARMMMUIdx_MPrivNegPri:
- case ARMMMUIdx_MUserNegPri:
- case ARMMMUIdx_MPriv:
- case ARMMMUIdx_MUser:
- case ARMMMUIdx_MSPrivNegPri:
- case ARMMMUIdx_MSUserNegPri:
- case ARMMMUIdx_MSPriv:
- case ARMMMUIdx_MSUser:
- return 1;
- default:
- g_assert_not_reached();
- }
-}
-
static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
{
switch (mmu_idx) {
diff --git a/target/arm/mmuidx-internal.h b/target/arm/mmuidx-internal.h
index 35d41495cd..1a4770401b 100644
--- a/target/arm/mmuidx-internal.h
+++ b/target/arm/mmuidx-internal.h
@@ -13,6 +13,8 @@
FIELD(MMUIDXINFO, EL, 0, 2)
FIELD(MMUIDXINFO, ELVALID, 2, 1)
+FIELD(MMUIDXINFO, REL, 3, 2)
+FIELD(MMUIDXINFO, RELVALID, 5, 1)
extern const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8];
@@ -24,4 +26,15 @@ static inline int arm_mmu_idx_to_el(ARMMMUIdx idx)
return FIELD_EX32(arm_mmuidx_table[idx], MMUIDXINFO, EL);
}
+/*
+ * Return the exception level for the address translation regime
+ * associated with this mmu index.
+ */
+static inline uint32_t regime_el(ARMMMUIdx idx)
+{
+ tcg_debug_assert((unsigned)idx < ARRAY_SIZE(arm_mmuidx_table));
+ tcg_debug_assert(FIELD_EX32(arm_mmuidx_table[idx], MMUIDXINFO, RELVALID));
+ return FIELD_EX32(arm_mmuidx_table[idx], MMUIDXINFO, REL);
+}
+
#endif /* TARGET_ARM_MMUIDX_INTERNAL_H */
diff --git a/target/arm/mmuidx.c b/target/arm/mmuidx.c
index 309b1d68df..6dfefa56c2 100644
--- a/target/arm/mmuidx.c
+++ b/target/arm/mmuidx.c
@@ -8,34 +8,42 @@
#define EL(X) ((X << R_MMUIDXINFO_EL_SHIFT) | R_MMUIDXINFO_ELVALID_MASK)
+#define REL(X) ((X << R_MMUIDXINFO_REL_SHIFT) | R_MMUIDXINFO_RELVALID_MASK)
const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8] = {
/*
* A-profile.
*/
- [ARMMMUIdx_E10_0] = EL(0),
- [ARMMMUIdx_E10_1] = EL(1),
- [ARMMMUIdx_E10_1_PAN] = EL(1),
+ [ARMMMUIdx_E10_0] = EL(0) | REL(1),
+ [ARMMMUIdx_E10_1] = EL(1) | REL(1),
+ [ARMMMUIdx_E10_1_PAN] = EL(1) | REL(1),
- [ARMMMUIdx_E20_0] = EL(0),
- [ARMMMUIdx_E20_2] = EL(2),
- [ARMMMUIdx_E20_2_PAN] = EL(2),
+ [ARMMMUIdx_E20_0] = EL(0) | REL(2),
+ [ARMMMUIdx_E20_2] = EL(2) | REL(2),
+ [ARMMMUIdx_E20_2_PAN] = EL(2) | REL(2),
- [ARMMMUIdx_E2] = EL(2),
+ [ARMMMUIdx_E2] = EL(2) | REL(2),
- [ARMMMUIdx_E3] = EL(3),
- [ARMMMUIdx_E30_0] = EL(0),
- [ARMMMUIdx_E30_3_PAN] = EL(3),
+ [ARMMMUIdx_E3] = EL(3) | REL(3),
+ [ARMMMUIdx_E30_0] = EL(0) | REL(3),
+ [ARMMMUIdx_E30_3_PAN] = EL(3) | REL(3),
+
+ [ARMMMUIdx_Stage2_S] = REL(2),
+ [ARMMMUIdx_Stage2] = REL(2),
+
+ [ARMMMUIdx_Stage1_E0] = REL(1),
+ [ARMMMUIdx_Stage1_E1] = REL(1),
+ [ARMMMUIdx_Stage1_E1_PAN] = REL(1),
/*
* M-profile.
*/
- [ARMMMUIdx_MUser] = EL(0),
- [ARMMMUIdx_MPriv] = EL(1),
- [ARMMMUIdx_MUserNegPri] = EL(0),
- [ARMMMUIdx_MPrivNegPri] = EL(1),
- [ARMMMUIdx_MSUser] = EL(0),
- [ARMMMUIdx_MSPriv] = EL(1),
- [ARMMMUIdx_MSUserNegPri] = EL(0),
- [ARMMMUIdx_MSPrivNegPri] = EL(1),
+ [ARMMMUIdx_MUser] = EL(0) | REL(1),
+ [ARMMMUIdx_MPriv] = EL(1) | REL(1),
+ [ARMMMUIdx_MUserNegPri] = EL(0) | REL(1),
+ [ARMMMUIdx_MPrivNegPri] = EL(1) | REL(1),
+ [ARMMMUIdx_MSUser] = EL(0) | REL(1),
+ [ARMMMUIdx_MSPriv] = EL(1) | REL(1),
+ [ARMMMUIdx_MSUserNegPri] = EL(0) | REL(1),
+ [ARMMMUIdx_MSPrivNegPri] = EL(1) | REL(1),
};
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 33/82] target/arm: Convert regime_has_2_ranges from switch to table
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (31 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 32/82] target/arm: Convert regime_el from switch to table Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-30 21:16 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 34/82] target/arm: Remove unused env argument from regime_is_pan Richard Henderson
` (48 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/internals.h | 28 ----------------------------
target/arm/mmuidx-internal.h | 17 +++++++++++++++++
target/arm/mmuidx.c | 19 ++++++++++---------
3 files changed, 27 insertions(+), 37 deletions(-)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 3b730a5d81..0322646753 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1029,34 +1029,6 @@ static inline void arm_call_el_change_hook(ARMCPU *cpu)
}
}
-/*
- * Return true if this address translation regime has two ranges.
- * Note that this will not return the correct answer for AArch32
- * Secure PL1&0 (i.e. mmu indexes E3, E30_0, E30_3_PAN), but it is
- * never called from a context where EL3 can be AArch32. (The
- * correct return value for ARMMMUIdx_E3 would be different for
- * that case, so we can't just make the function return the
- * correct value anyway; we would need an extra "bool e3_is_aarch32"
- * argument which all the current callsites would pass as 'false'.)
- */
-static inline bool regime_has_2_ranges(ARMMMUIdx mmu_idx)
-{
- switch (mmu_idx) {
- case ARMMMUIdx_Stage1_E0:
- case ARMMMUIdx_Stage1_E1:
- case ARMMMUIdx_Stage1_E1_PAN:
- case ARMMMUIdx_E10_0:
- case ARMMMUIdx_E10_1:
- case ARMMMUIdx_E10_1_PAN:
- case ARMMMUIdx_E20_0:
- case ARMMMUIdx_E20_2:
- case ARMMMUIdx_E20_2_PAN:
- return true;
- default:
- return false;
- }
-}
-
static inline bool regime_is_pan(CPUARMState *env, ARMMMUIdx mmu_idx)
{
switch (mmu_idx) {
diff --git a/target/arm/mmuidx-internal.h b/target/arm/mmuidx-internal.h
index 1a4770401b..76d50a0645 100644
--- a/target/arm/mmuidx-internal.h
+++ b/target/arm/mmuidx-internal.h
@@ -15,6 +15,7 @@ FIELD(MMUIDXINFO, EL, 0, 2)
FIELD(MMUIDXINFO, ELVALID, 2, 1)
FIELD(MMUIDXINFO, REL, 3, 2)
FIELD(MMUIDXINFO, RELVALID, 5, 1)
+FIELD(MMUIDXINFO, 2RANGES, 6, 1)
extern const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8];
@@ -37,4 +38,20 @@ static inline uint32_t regime_el(ARMMMUIdx idx)
return FIELD_EX32(arm_mmuidx_table[idx], MMUIDXINFO, REL);
}
+/*
+ * Return true if this address translation regime has two ranges.
+ * Note that this will not return the correct answer for AArch32
+ * Secure PL1&0 (i.e. mmu indexes E3, E30_0, E30_3_PAN), but it is
+ * never called from a context where EL3 can be AArch32. (The
+ * correct return value for ARMMMUIdx_E3 would be different for
+ * that case, so we can't just make the function return the
+ * correct value anyway; we would need an extra "bool e3_is_aarch32"
+ * argument which all the current callsites would pass as 'false'.)
+ */
+static inline bool regime_has_2_ranges(ARMMMUIdx idx)
+{
+ tcg_debug_assert((unsigned)idx < ARRAY_SIZE(arm_mmuidx_table));
+ return FIELD_EX32(arm_mmuidx_table[idx], MMUIDXINFO, 2RANGES);
+}
+
#endif /* TARGET_ARM_MMUIDX_INTERNAL_H */
diff --git a/target/arm/mmuidx.c b/target/arm/mmuidx.c
index 6dfefa56c2..f880d21606 100644
--- a/target/arm/mmuidx.c
+++ b/target/arm/mmuidx.c
@@ -9,18 +9,19 @@
#define EL(X) ((X << R_MMUIDXINFO_EL_SHIFT) | R_MMUIDXINFO_ELVALID_MASK)
#define REL(X) ((X << R_MMUIDXINFO_REL_SHIFT) | R_MMUIDXINFO_RELVALID_MASK)
+#define R2 R_MMUIDXINFO_2RANGES_MASK
const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8] = {
/*
* A-profile.
*/
- [ARMMMUIdx_E10_0] = EL(0) | REL(1),
- [ARMMMUIdx_E10_1] = EL(1) | REL(1),
- [ARMMMUIdx_E10_1_PAN] = EL(1) | REL(1),
+ [ARMMMUIdx_E10_0] = EL(0) | REL(1) | R2,
+ [ARMMMUIdx_E10_1] = EL(1) | REL(1) | R2,
+ [ARMMMUIdx_E10_1_PAN] = EL(1) | REL(1) | R2,
- [ARMMMUIdx_E20_0] = EL(0) | REL(2),
- [ARMMMUIdx_E20_2] = EL(2) | REL(2),
- [ARMMMUIdx_E20_2_PAN] = EL(2) | REL(2),
+ [ARMMMUIdx_E20_0] = EL(0) | REL(2) | R2,
+ [ARMMMUIdx_E20_2] = EL(2) | REL(2) | R2,
+ [ARMMMUIdx_E20_2_PAN] = EL(2) | REL(2) | R2,
[ARMMMUIdx_E2] = EL(2) | REL(2),
@@ -31,9 +32,9 @@ const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8] = {
[ARMMMUIdx_Stage2_S] = REL(2),
[ARMMMUIdx_Stage2] = REL(2),
- [ARMMMUIdx_Stage1_E0] = REL(1),
- [ARMMMUIdx_Stage1_E1] = REL(1),
- [ARMMMUIdx_Stage1_E1_PAN] = REL(1),
+ [ARMMMUIdx_Stage1_E0] = REL(1) | R2,
+ [ARMMMUIdx_Stage1_E1] = REL(1) | R2,
+ [ARMMMUIdx_Stage1_E1_PAN] = REL(1) | R2,
/*
* M-profile.
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 34/82] target/arm: Remove unused env argument from regime_is_pan
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (32 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 33/82] target/arm: Convert regime_has_2_ranges " Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-30 21:17 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 35/82] target/arm: Convert regime_is_pan from switch to table Richard Henderson
` (47 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/internals.h | 2 +-
target/arm/ptw.c | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 0322646753..962fc423a6 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1029,7 +1029,7 @@ static inline void arm_call_el_change_hook(ARMCPU *cpu)
}
}
-static inline bool regime_is_pan(CPUARMState *env, ARMMMUIdx mmu_idx)
+static inline bool regime_is_pan(ARMMMUIdx mmu_idx)
{
switch (mmu_idx) {
case ARMMMUIdx_Stage1_E1_PAN:
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 30c83334b6..c75b15b263 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -1394,10 +1394,10 @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
* We make the IMPDEF choices that SCR_EL3.SIF and Realm EL2&0
* do not affect EPAN.
*/
- if (user_rw && regime_is_pan(env, mmu_idx)) {
+ if (user_rw && regime_is_pan(mmu_idx)) {
prot_rw = 0;
} else if (cpu_isar_feature(aa64_pan3, cpu) && is_aa64 &&
- regime_is_pan(env, mmu_idx) &&
+ regime_is_pan(mmu_idx) &&
(regime_sctlr(env, mmu_idx) & SCTLR_EPAN) && !xn) {
prot_rw = 0;
}
@@ -1536,7 +1536,7 @@ static int get_S1prot_indirect(CPUARMState *env, S1Translate *ptw,
p_perm &= ~(PAGE_RWX | PAGE_GCS);
u_perm &= ~(PAGE_RWX | PAGE_GCS);
}
- if ((u_perm & (PAGE_RWX | PAGE_GCS)) && regime_is_pan(env, mmu_idx)) {
+ if ((u_perm & (PAGE_RWX | PAGE_GCS)) && regime_is_pan(mmu_idx)) {
p_perm &= ~(PAGE_READ | PAGE_WRITE);
}
perm = regime_is_user(env, mmu_idx) ? u_perm : p_perm;
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 35/82] target/arm: Convert regime_is_pan from switch to table
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (33 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 34/82] target/arm: Remove unused env argument from regime_is_pan Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-30 21:17 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 36/82] target/arm: Remove unused env argument from regime_is_user Richard Henderson
` (46 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/internals.h | 13 -------------
target/arm/mmuidx-internal.h | 8 ++++++++
target/arm/mmuidx.c | 9 +++++----
3 files changed, 13 insertions(+), 17 deletions(-)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 962fc423a6..f665971b97 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1029,19 +1029,6 @@ static inline void arm_call_el_change_hook(ARMCPU *cpu)
}
}
-static inline bool regime_is_pan(ARMMMUIdx mmu_idx)
-{
- switch (mmu_idx) {
- case ARMMMUIdx_Stage1_E1_PAN:
- case ARMMMUIdx_E10_1_PAN:
- case ARMMMUIdx_E20_2_PAN:
- case ARMMMUIdx_E30_3_PAN:
- return true;
- default:
- return false;
- }
-}
-
static inline bool regime_is_stage2(ARMMMUIdx mmu_idx)
{
return mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S;
diff --git a/target/arm/mmuidx-internal.h b/target/arm/mmuidx-internal.h
index 76d50a0645..5a7259a557 100644
--- a/target/arm/mmuidx-internal.h
+++ b/target/arm/mmuidx-internal.h
@@ -16,6 +16,7 @@ FIELD(MMUIDXINFO, ELVALID, 2, 1)
FIELD(MMUIDXINFO, REL, 3, 2)
FIELD(MMUIDXINFO, RELVALID, 5, 1)
FIELD(MMUIDXINFO, 2RANGES, 6, 1)
+FIELD(MMUIDXINFO, PAN, 7, 1)
extern const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8];
@@ -54,4 +55,11 @@ static inline bool regime_has_2_ranges(ARMMMUIdx idx)
return FIELD_EX32(arm_mmuidx_table[idx], MMUIDXINFO, 2RANGES);
}
+/* Return true if Privileged Access Never is enabled for this mmu index. */
+static inline bool regime_is_pan(ARMMMUIdx idx)
+{
+ tcg_debug_assert((unsigned)idx < ARRAY_SIZE(arm_mmuidx_table));
+ return FIELD_EX32(arm_mmuidx_table[idx], MMUIDXINFO, PAN);
+}
+
#endif /* TARGET_ARM_MMUIDX_INTERNAL_H */
diff --git a/target/arm/mmuidx.c b/target/arm/mmuidx.c
index f880d21606..98db02b8e5 100644
--- a/target/arm/mmuidx.c
+++ b/target/arm/mmuidx.c
@@ -10,6 +10,7 @@
#define EL(X) ((X << R_MMUIDXINFO_EL_SHIFT) | R_MMUIDXINFO_ELVALID_MASK)
#define REL(X) ((X << R_MMUIDXINFO_REL_SHIFT) | R_MMUIDXINFO_RELVALID_MASK)
#define R2 R_MMUIDXINFO_2RANGES_MASK
+#define PAN R_MMUIDXINFO_PAN_MASK
const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8] = {
/*
@@ -17,24 +18,24 @@ const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8] = {
*/
[ARMMMUIdx_E10_0] = EL(0) | REL(1) | R2,
[ARMMMUIdx_E10_1] = EL(1) | REL(1) | R2,
- [ARMMMUIdx_E10_1_PAN] = EL(1) | REL(1) | R2,
+ [ARMMMUIdx_E10_1_PAN] = EL(1) | REL(1) | R2 | PAN,
[ARMMMUIdx_E20_0] = EL(0) | REL(2) | R2,
[ARMMMUIdx_E20_2] = EL(2) | REL(2) | R2,
- [ARMMMUIdx_E20_2_PAN] = EL(2) | REL(2) | R2,
+ [ARMMMUIdx_E20_2_PAN] = EL(2) | REL(2) | R2 | PAN,
[ARMMMUIdx_E2] = EL(2) | REL(2),
[ARMMMUIdx_E3] = EL(3) | REL(3),
[ARMMMUIdx_E30_0] = EL(0) | REL(3),
- [ARMMMUIdx_E30_3_PAN] = EL(3) | REL(3),
+ [ARMMMUIdx_E30_3_PAN] = EL(3) | REL(3) | PAN,
[ARMMMUIdx_Stage2_S] = REL(2),
[ARMMMUIdx_Stage2] = REL(2),
[ARMMMUIdx_Stage1_E0] = REL(1) | R2,
[ARMMMUIdx_Stage1_E1] = REL(1) | R2,
- [ARMMMUIdx_Stage1_E1_PAN] = REL(1) | R2,
+ [ARMMMUIdx_Stage1_E1_PAN] = REL(1) | R2 | PAN,
/*
* M-profile.
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 36/82] target/arm: Remove unused env argument from regime_is_user
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (34 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 35/82] target/arm: Convert regime_is_pan from switch to table Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-30 21:18 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 37/82] target/arm: Convert regime_is_user from switch to table Richard Henderson
` (45 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/internals.h | 2 +-
target/arm/helper.c | 2 +-
target/arm/ptw.c | 16 ++++++++--------
3 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index f665971b97..ea210c7179 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1034,7 +1034,7 @@ static inline bool regime_is_stage2(ARMMMUIdx mmu_idx)
return mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S;
}
-static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
+static inline bool regime_is_user(ARMMMUIdx mmu_idx)
{
switch (mmu_idx) {
case ARMMMUIdx_E10_0:
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 461572f918..d82f2b1131 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -9692,7 +9692,7 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
ds = extract64(tcr, 59, 1);
if (e0pd && cpu_isar_feature(aa64_e0pd, cpu) &&
- regime_is_user(env, mmu_idx)) {
+ regime_is_user(mmu_idx)) {
epd = true;
}
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index c75b15b263..493ec78c1a 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -964,7 +964,7 @@ static int ap_to_rw_prot(CPUARMState *env, ARMMMUIdx mmu_idx,
int ap, int domain_prot)
{
return ap_to_rw_prot_is_user(env, mmu_idx, ap, domain_prot,
- regime_is_user(env, mmu_idx));
+ regime_is_user(mmu_idx));
}
/*
@@ -990,7 +990,7 @@ static int simple_ap_to_rw_prot_is_user(int ap, bool is_user)
static int simple_ap_to_rw_prot(CPUARMState *env, ARMMMUIdx mmu_idx, int ap)
{
- return simple_ap_to_rw_prot_is_user(ap, regime_is_user(env, mmu_idx));
+ return simple_ap_to_rw_prot_is_user(ap, regime_is_user(mmu_idx));
}
static bool get_phys_addr_v5(CPUARMState *env, S1Translate *ptw,
@@ -1377,7 +1377,7 @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
ARMSecuritySpace in_pa, ARMSecuritySpace out_pa)
{
ARMCPU *cpu = env_archcpu(env);
- bool is_user = regime_is_user(env, mmu_idx);
+ bool is_user = regime_is_user(mmu_idx);
bool have_wxn;
int wxn = 0;
@@ -1539,7 +1539,7 @@ static int get_S1prot_indirect(CPUARMState *env, S1Translate *ptw,
if ((u_perm & (PAGE_RWX | PAGE_GCS)) && regime_is_pan(mmu_idx)) {
p_perm &= ~(PAGE_READ | PAGE_WRITE);
}
- perm = regime_is_user(env, mmu_idx) ? u_perm : p_perm;
+ perm = regime_is_user(mmu_idx) ? u_perm : p_perm;
}
if (in_pa != out_pa) {
@@ -2384,7 +2384,7 @@ static bool get_phys_addr_pmsav5(CPUARMState *env,
uint32_t mask;
uint32_t base;
ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
- bool is_user = regime_is_user(env, mmu_idx);
+ bool is_user = regime_is_user(mmu_idx);
if (regime_translation_disabled(env, mmu_idx, ptw->in_space)) {
/* MPU disabled. */
@@ -2551,7 +2551,7 @@ static bool get_phys_addr_pmsav7(CPUARMState *env,
ARMCPU *cpu = env_archcpu(env);
int n;
ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
- bool is_user = regime_is_user(env, mmu_idx);
+ bool is_user = regime_is_user(mmu_idx);
bool secure = arm_space_is_secure(ptw->in_space);
result->f.phys_addr = address;
@@ -2771,7 +2771,7 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
* memory system to use a subpage.
*/
ARMCPU *cpu = env_archcpu(env);
- bool is_user = regime_is_user(env, mmu_idx);
+ bool is_user = regime_is_user(mmu_idx);
int n;
int matchregion = -1;
bool hit = false;
@@ -3651,7 +3651,7 @@ static bool get_phys_addr_nogpc(CPUARMState *env, S1Translate *ptw,
break;
}
- result->f.attrs.user = regime_is_user(env, mmu_idx);
+ result->f.attrs.user = regime_is_user(mmu_idx);
/*
* Fast Context Switch Extension. This doesn't exist at all in v8.
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 37/82] target/arm: Convert regime_is_user from switch to table
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (35 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 36/82] target/arm: Remove unused env argument from regime_is_user Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-30 21:21 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 38/82] target/arm: Convert arm_mmu_idx_is_stage1_of_2 " Richard Henderson
` (44 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/internals.h | 17 -----------------
target/arm/mmuidx-internal.h | 12 ++++++++++++
target/arm/mmuidx.c | 6 ++++--
3 files changed, 16 insertions(+), 19 deletions(-)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index ea210c7179..c6f3ae470b 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1034,23 +1034,6 @@ static inline bool regime_is_stage2(ARMMMUIdx mmu_idx)
return mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S;
}
-static inline bool regime_is_user(ARMMMUIdx mmu_idx)
-{
- switch (mmu_idx) {
- case ARMMMUIdx_E10_0:
- case ARMMMUIdx_E20_0:
- case ARMMMUIdx_E30_0:
- case ARMMMUIdx_Stage1_E0:
- case ARMMMUIdx_MUser:
- case ARMMMUIdx_MSUser:
- case ARMMMUIdx_MUserNegPri:
- case ARMMMUIdx_MSUserNegPri:
- return true;
- default:
- return false;
- }
-}
-
/* Return the SCTLR value which controls this address translation regime */
static inline uint64_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)
{
diff --git a/target/arm/mmuidx-internal.h b/target/arm/mmuidx-internal.h
index 5a7259a557..ef1f94a23f 100644
--- a/target/arm/mmuidx-internal.h
+++ b/target/arm/mmuidx-internal.h
@@ -17,6 +17,7 @@ FIELD(MMUIDXINFO, REL, 3, 2)
FIELD(MMUIDXINFO, RELVALID, 5, 1)
FIELD(MMUIDXINFO, 2RANGES, 6, 1)
FIELD(MMUIDXINFO, PAN, 7, 1)
+FIELD(MMUIDXINFO, USER, 8, 1)
extern const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8];
@@ -62,4 +63,15 @@ static inline bool regime_is_pan(ARMMMUIdx idx)
return FIELD_EX32(arm_mmuidx_table[idx], MMUIDXINFO, PAN);
}
+/*
+ * Return true if the exception level associated with this mmu index is 0.
+ * Differs from arm_mmu_idx_to_el(idx) == 0 in that this allows querying
+ * Stage1 and Stage2 mmu indexes.
+ */
+static inline bool regime_is_user(ARMMMUIdx idx)
+{
+ tcg_debug_assert((unsigned)idx < ARRAY_SIZE(arm_mmuidx_table));
+ return FIELD_EX32(arm_mmuidx_table[idx], MMUIDXINFO, USER);
+}
+
#endif /* TARGET_ARM_MMUIDX_INTERNAL_H */
diff --git a/target/arm/mmuidx.c b/target/arm/mmuidx.c
index 98db02b8e5..1c1e062bfe 100644
--- a/target/arm/mmuidx.c
+++ b/target/arm/mmuidx.c
@@ -7,10 +7,12 @@
#include "mmuidx-internal.h"
-#define EL(X) ((X << R_MMUIDXINFO_EL_SHIFT) | R_MMUIDXINFO_ELVALID_MASK)
+#define EL(X) ((X << R_MMUIDXINFO_EL_SHIFT) | R_MMUIDXINFO_ELVALID_MASK | \
+ ((X == 0) << R_MMUIDXINFO_USER_SHIFT))
#define REL(X) ((X << R_MMUIDXINFO_REL_SHIFT) | R_MMUIDXINFO_RELVALID_MASK)
#define R2 R_MMUIDXINFO_2RANGES_MASK
#define PAN R_MMUIDXINFO_PAN_MASK
+#define USER R_MMUIDXINFO_USER_MASK
const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8] = {
/*
@@ -33,7 +35,7 @@ const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8] = {
[ARMMMUIdx_Stage2_S] = REL(2),
[ARMMMUIdx_Stage2] = REL(2),
- [ARMMMUIdx_Stage1_E0] = REL(1) | R2,
+ [ARMMMUIdx_Stage1_E0] = REL(1) | R2 | USER,
[ARMMMUIdx_Stage1_E1] = REL(1) | R2,
[ARMMMUIdx_Stage1_E1_PAN] = REL(1) | R2 | PAN,
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 38/82] target/arm: Convert arm_mmu_idx_is_stage1_of_2 from switch to table
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (36 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 37/82] target/arm: Convert regime_is_user from switch to table Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-30 21:23 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 39/82] target/arm: Convert regime_is_stage2 " Richard Henderson
` (43 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/internals.h | 19 -------------------
target/arm/mmuidx-internal.h | 8 ++++++++
target/arm/mmuidx.c | 7 ++++---
3 files changed, 12 insertions(+), 22 deletions(-)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index c6f3ae470b..4f99ec69f8 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1282,25 +1282,6 @@ ARMMMUIdx stage_1_mmu_idx(ARMMMUIdx mmu_idx);
ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env);
#endif
-/**
- * arm_mmu_idx_is_stage1_of_2:
- * @mmu_idx: The ARMMMUIdx to test
- *
- * Return true if @mmu_idx is a NOTLB mmu_idx that is the
- * first stage of a two stage regime.
- */
-static inline bool arm_mmu_idx_is_stage1_of_2(ARMMMUIdx mmu_idx)
-{
- switch (mmu_idx) {
- case ARMMMUIdx_Stage1_E0:
- case ARMMMUIdx_Stage1_E1:
- case ARMMMUIdx_Stage1_E1_PAN:
- return true;
- default:
- return false;
- }
-}
-
static inline uint32_t aarch32_cpsr_valid_mask(uint64_t features,
const ARMISARegisters *id)
{
diff --git a/target/arm/mmuidx-internal.h b/target/arm/mmuidx-internal.h
index ef1f94a23f..f297eefe2b 100644
--- a/target/arm/mmuidx-internal.h
+++ b/target/arm/mmuidx-internal.h
@@ -18,6 +18,7 @@ FIELD(MMUIDXINFO, RELVALID, 5, 1)
FIELD(MMUIDXINFO, 2RANGES, 6, 1)
FIELD(MMUIDXINFO, PAN, 7, 1)
FIELD(MMUIDXINFO, USER, 8, 1)
+FIELD(MMUIDXINFO, STAGE1, 9, 1)
extern const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8];
@@ -74,4 +75,11 @@ static inline bool regime_is_user(ARMMMUIdx idx)
return FIELD_EX32(arm_mmuidx_table[idx], MMUIDXINFO, USER);
}
+/* Return true if this mmu index is stage 1 of a 2-stage translation. */
+static inline bool arm_mmu_idx_is_stage1_of_2(ARMMMUIdx idx)
+{
+ tcg_debug_assert((unsigned)idx < ARRAY_SIZE(arm_mmuidx_table));
+ return FIELD_EX32(arm_mmuidx_table[idx], MMUIDXINFO, STAGE1);
+}
+
#endif /* TARGET_ARM_MMUIDX_INTERNAL_H */
diff --git a/target/arm/mmuidx.c b/target/arm/mmuidx.c
index 1c1e062bfe..c5b43a5932 100644
--- a/target/arm/mmuidx.c
+++ b/target/arm/mmuidx.c
@@ -13,6 +13,7 @@
#define R2 R_MMUIDXINFO_2RANGES_MASK
#define PAN R_MMUIDXINFO_PAN_MASK
#define USER R_MMUIDXINFO_USER_MASK
+#define S1 R_MMUIDXINFO_STAGE1_MASK
const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8] = {
/*
@@ -35,9 +36,9 @@ const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8] = {
[ARMMMUIdx_Stage2_S] = REL(2),
[ARMMMUIdx_Stage2] = REL(2),
- [ARMMMUIdx_Stage1_E0] = REL(1) | R2 | USER,
- [ARMMMUIdx_Stage1_E1] = REL(1) | R2,
- [ARMMMUIdx_Stage1_E1_PAN] = REL(1) | R2 | PAN,
+ [ARMMMUIdx_Stage1_E0] = REL(1) | R2 | S1 | USER,
+ [ARMMMUIdx_Stage1_E1] = REL(1) | R2 | S1,
+ [ARMMMUIdx_Stage1_E1_PAN] = REL(1) | R2 | S1 | PAN,
/*
* M-profile.
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 39/82] target/arm: Convert regime_is_stage2 to table
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (37 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 38/82] target/arm: Convert arm_mmu_idx_is_stage1_of_2 " Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-30 21:23 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 40/82] target/arm: Introduce mmu indexes for GCS Richard Henderson
` (42 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
This wasn't using a switch, but two comparisons.
Convert it to arm_mmuidx_table for consistency.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/internals.h | 5 -----
target/arm/mmuidx-internal.h | 8 ++++++++
target/arm/mmuidx.c | 5 +++--
3 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 4f99ec69f8..805f4a1876 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1029,11 +1029,6 @@ static inline void arm_call_el_change_hook(ARMCPU *cpu)
}
}
-static inline bool regime_is_stage2(ARMMMUIdx mmu_idx)
-{
- return mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S;
-}
-
/* Return the SCTLR value which controls this address translation regime */
static inline uint64_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)
{
diff --git a/target/arm/mmuidx-internal.h b/target/arm/mmuidx-internal.h
index f297eefe2b..ecf43d7709 100644
--- a/target/arm/mmuidx-internal.h
+++ b/target/arm/mmuidx-internal.h
@@ -19,6 +19,7 @@ FIELD(MMUIDXINFO, 2RANGES, 6, 1)
FIELD(MMUIDXINFO, PAN, 7, 1)
FIELD(MMUIDXINFO, USER, 8, 1)
FIELD(MMUIDXINFO, STAGE1, 9, 1)
+FIELD(MMUIDXINFO, STAGE2, 10, 1)
extern const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8];
@@ -82,4 +83,11 @@ static inline bool arm_mmu_idx_is_stage1_of_2(ARMMMUIdx idx)
return FIELD_EX32(arm_mmuidx_table[idx], MMUIDXINFO, STAGE1);
}
+/* Return true if this mmu index is stage 2 of a 2-stage translation. */
+static inline bool regime_is_stage2(ARMMMUIdx idx)
+{
+ tcg_debug_assert((unsigned)idx < ARRAY_SIZE(arm_mmuidx_table));
+ return FIELD_EX32(arm_mmuidx_table[idx], MMUIDXINFO, STAGE2);
+}
+
#endif /* TARGET_ARM_MMUIDX_INTERNAL_H */
diff --git a/target/arm/mmuidx.c b/target/arm/mmuidx.c
index c5b43a5932..61a682e655 100644
--- a/target/arm/mmuidx.c
+++ b/target/arm/mmuidx.c
@@ -14,6 +14,7 @@
#define PAN R_MMUIDXINFO_PAN_MASK
#define USER R_MMUIDXINFO_USER_MASK
#define S1 R_MMUIDXINFO_STAGE1_MASK
+#define S2 R_MMUIDXINFO_STAGE2_MASK
const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8] = {
/*
@@ -33,8 +34,8 @@ const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8] = {
[ARMMMUIdx_E30_0] = EL(0) | REL(3),
[ARMMMUIdx_E30_3_PAN] = EL(3) | REL(3) | PAN,
- [ARMMMUIdx_Stage2_S] = REL(2),
- [ARMMMUIdx_Stage2] = REL(2),
+ [ARMMMUIdx_Stage2_S] = REL(2) | S2,
+ [ARMMMUIdx_Stage2] = REL(2) | S2,
[ARMMMUIdx_Stage1_E0] = REL(1) | R2 | S1 | USER,
[ARMMMUIdx_Stage1_E1] = REL(1) | R2 | S1,
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 40/82] target/arm: Introduce mmu indexes for GCS
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (38 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 39/82] target/arm: Convert regime_is_stage2 " Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-30 21:28 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 41/82] target/arm: Introduce regime_to_gcs Richard Henderson
` (41 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/hw/core/cpu.h | 5 ++-
target/arm/mmuidx-internal.h | 8 ++++
target/arm/mmuidx.h | 71 ++++++++++++++++++++++++------------
target/arm/helper.c | 15 ++++++--
target/arm/mmuidx.c | 9 +++++
target/arm/ptw.c | 20 ++++++++++
target/arm/tcg/tlb-insns.c | 47 ++++++++++++++++--------
7 files changed, 132 insertions(+), 43 deletions(-)
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index a95559c538..bca13bf38d 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -198,9 +198,10 @@ struct CPUClass {
};
/*
- * Fix the number of mmu modes to 16.
+ * Fix the number of mmu modes across all targets.
+ * Current maximum is target/arm/.
*/
-#define NB_MMU_MODES 16
+#define NB_MMU_MODES 22
typedef uint32_t MMUIdxMap;
/* Use a fully associative victim tlb of 8 entries. */
diff --git a/target/arm/mmuidx-internal.h b/target/arm/mmuidx-internal.h
index ecf43d7709..f5de104460 100644
--- a/target/arm/mmuidx-internal.h
+++ b/target/arm/mmuidx-internal.h
@@ -20,6 +20,7 @@ FIELD(MMUIDXINFO, PAN, 7, 1)
FIELD(MMUIDXINFO, USER, 8, 1)
FIELD(MMUIDXINFO, STAGE1, 9, 1)
FIELD(MMUIDXINFO, STAGE2, 10, 1)
+FIELD(MMUIDXINFO, GCS, 11, 1)
extern const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8];
@@ -90,4 +91,11 @@ static inline bool regime_is_stage2(ARMMMUIdx idx)
return FIELD_EX32(arm_mmuidx_table[idx], MMUIDXINFO, STAGE2);
}
+/* Return true if this mmu index implies AccessType_GCS. */
+static inline bool regime_is_gcs(ARMMMUIdx idx)
+{
+ tcg_debug_assert((unsigned)idx < ARRAY_SIZE(arm_mmuidx_table));
+ return FIELD_EX32(arm_mmuidx_table[idx], MMUIDXINFO, GCS);
+}
+
#endif /* TARGET_ARM_MMUIDX_INTERNAL_H */
diff --git a/target/arm/mmuidx.h b/target/arm/mmuidx.h
index 5b9b4bc84f..8d8d27337e 100644
--- a/target/arm/mmuidx.h
+++ b/target/arm/mmuidx.h
@@ -58,24 +58,31 @@
* already heavyweight.
* 8. we cannot fold together Stage 2 Secure and Stage 2 NonSecure,
* because both are in use simultaneously for Secure EL2.
+ * 9. we need separate indexes for handling AccessType_GCS.
*
* This gives us the following list of cases:
*
* EL0 EL1&0 stage 1+2 (aka NS PL0 PL1&0 stage 1+2)
+ * EL0 EL1&0 stage 1+2 +GCS
* EL1 EL1&0 stage 1+2 (aka NS PL1 PL1&0 stage 1+2)
* EL1 EL1&0 stage 1+2 +PAN (aka NS PL1 P1&0 stage 1+2 +PAN)
+ * EL1 EL1&0 stage 1+2 +GCS
* EL0 EL2&0
+ * EL0 EL2&0 +GCS
* EL2 EL2&0
* EL2 EL2&0 +PAN
+ * EL2 EL2&0 +GCS
* EL2 (aka NS PL2)
+ * EL2 +GCS
* EL3 (aka AArch32 S PL1 PL1&0)
+ * EL3 +GCS
* AArch32 S PL0 PL1&0 (we call this EL30_0)
* AArch32 S PL1 PL1&0 +PAN (we call this EL30_3_PAN)
* Stage2 Secure
* Stage2 NonSecure
* plus one TLB per Physical address space: S, NS, Realm, Root
*
- * for a total of 16 different mmu_idx.
+ * for a total of 22 different mmu_idx.
*
* R profile CPUs have an MPU, but can use the same set of MMU indexes
* as A profile. They only need to distinguish EL0 and EL1 (and
@@ -114,9 +121,9 @@
* For M profile we arrange them to have a bit for priv, a bit for negpri
* and a bit for secure.
*/
-#define ARM_MMU_IDX_A 0x10 /* A profile */
-#define ARM_MMU_IDX_NOTLB 0x20 /* does not have a TLB */
-#define ARM_MMU_IDX_M 0x40 /* M profile */
+#define ARM_MMU_IDX_A 0x20 /* A profile */
+#define ARM_MMU_IDX_NOTLB 0x40 /* does not have a TLB */
+#define ARM_MMU_IDX_M 0x80 /* M profile */
/* Meanings of the bits for M profile mmu idx values */
#define ARM_MMU_IDX_M_PRIV 0x1
@@ -125,22 +132,32 @@
#define ARM_MMU_IDX_TYPE_MASK \
(ARM_MMU_IDX_A | ARM_MMU_IDX_M | ARM_MMU_IDX_NOTLB)
-#define ARM_MMU_IDX_COREIDX_MASK 0xf
+#define ARM_MMU_IDX_COREIDX_MASK 0x1f
typedef enum ARMMMUIdx {
/*
* A-profile.
*/
- ARMMMUIdx_E10_0 = 0 | ARM_MMU_IDX_A,
- ARMMMUIdx_E20_0 = 1 | ARM_MMU_IDX_A,
- ARMMMUIdx_E10_1 = 2 | ARM_MMU_IDX_A,
- ARMMMUIdx_E20_2 = 3 | ARM_MMU_IDX_A,
- ARMMMUIdx_E10_1_PAN = 4 | ARM_MMU_IDX_A,
- ARMMMUIdx_E20_2_PAN = 5 | ARM_MMU_IDX_A,
- ARMMMUIdx_E2 = 6 | ARM_MMU_IDX_A,
- ARMMMUIdx_E3 = 7 | ARM_MMU_IDX_A,
- ARMMMUIdx_E30_0 = 8 | ARM_MMU_IDX_A,
- ARMMMUIdx_E30_3_PAN = 9 | ARM_MMU_IDX_A,
+
+ ARMMMUIdx_E10_0 = 0 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E10_0_GCS = 1 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E10_1 = 2 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E10_1_PAN = 3 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E10_1_GCS = 4 | ARM_MMU_IDX_A,
+
+ ARMMMUIdx_E20_0 = 5 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E20_0_GCS = 6 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E20_2 = 7 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E20_2_PAN = 8 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E20_2_GCS = 9 | ARM_MMU_IDX_A,
+
+ ARMMMUIdx_E2 = 10 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E2_GCS = 11 | ARM_MMU_IDX_A,
+
+ ARMMMUIdx_E3 = 12 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E3_GCS = 13 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E30_0 = 14 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E30_3_PAN = 15 | ARM_MMU_IDX_A,
/*
* Used for second stage of an S12 page table walk, or for descriptor
@@ -148,14 +165,14 @@ typedef enum ARMMMUIdx {
* are in use simultaneously for SecureEL2: the security state for
* the S2 ptw is selected by the NS bit from the S1 ptw.
*/
- ARMMMUIdx_Stage2_S = 10 | ARM_MMU_IDX_A,
- ARMMMUIdx_Stage2 = 11 | ARM_MMU_IDX_A,
+ ARMMMUIdx_Stage2_S = 16 | ARM_MMU_IDX_A,
+ ARMMMUIdx_Stage2 = 17 | ARM_MMU_IDX_A,
/* TLBs with 1-1 mapping to the physical address spaces. */
- ARMMMUIdx_Phys_S = 12 | ARM_MMU_IDX_A,
- ARMMMUIdx_Phys_NS = 13 | ARM_MMU_IDX_A,
- ARMMMUIdx_Phys_Root = 14 | ARM_MMU_IDX_A,
- ARMMMUIdx_Phys_Realm = 15 | ARM_MMU_IDX_A,
+ ARMMMUIdx_Phys_S = 18 | ARM_MMU_IDX_A,
+ ARMMMUIdx_Phys_NS = 19 | ARM_MMU_IDX_A,
+ ARMMMUIdx_Phys_Root = 20 | ARM_MMU_IDX_A,
+ ARMMMUIdx_Phys_Realm = 21 | ARM_MMU_IDX_A,
/*
* These are not allocated TLBs and are used only for AT system
@@ -164,6 +181,8 @@ typedef enum ARMMMUIdx {
ARMMMUIdx_Stage1_E0 = 0 | ARM_MMU_IDX_NOTLB,
ARMMMUIdx_Stage1_E1 = 1 | ARM_MMU_IDX_NOTLB,
ARMMMUIdx_Stage1_E1_PAN = 2 | ARM_MMU_IDX_NOTLB,
+ ARMMMUIdx_Stage1_E0_GCS = 3 | ARM_MMU_IDX_NOTLB,
+ ARMMMUIdx_Stage1_E1_GCS = 4 | ARM_MMU_IDX_NOTLB,
/*
* M-profile.
@@ -187,13 +206,19 @@ typedef enum ARMMMUIdx {
typedef enum ARMMMUIdxBit {
TO_CORE_BIT(E10_0),
- TO_CORE_BIT(E20_0),
+ TO_CORE_BIT(E10_0_GCS),
TO_CORE_BIT(E10_1),
TO_CORE_BIT(E10_1_PAN),
- TO_CORE_BIT(E2),
+ TO_CORE_BIT(E10_1_GCS),
+ TO_CORE_BIT(E20_0),
+ TO_CORE_BIT(E20_0_GCS),
TO_CORE_BIT(E20_2),
TO_CORE_BIT(E20_2_PAN),
+ TO_CORE_BIT(E20_2_GCS),
+ TO_CORE_BIT(E2),
+ TO_CORE_BIT(E2_GCS),
TO_CORE_BIT(E3),
+ TO_CORE_BIT(E3_GCS),
TO_CORE_BIT(E30_0),
TO_CORE_BIT(E30_3_PAN),
TO_CORE_BIT(Stage2),
diff --git a/target/arm/helper.c b/target/arm/helper.c
index d82f2b1131..7ba802f2d6 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -401,7 +401,9 @@ int alle1_tlbmask(CPUARMState *env)
*/
return (ARMMMUIdxBit_E10_1 |
ARMMMUIdxBit_E10_1_PAN |
+ ARMMMUIdxBit_E10_1_GCS |
ARMMMUIdxBit_E10_0 |
+ ARMMMUIdxBit_E10_0_GCS |
ARMMMUIdxBit_Stage2 |
ARMMMUIdxBit_Stage2_S);
}
@@ -788,12 +790,17 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
*/
if (changed & (SCR_NS | SCR_NSE)) {
tlb_flush_by_mmuidx(env_cpu(env), (ARMMMUIdxBit_E10_0 |
+ ARMMMUIdxBit_E10_0_GCS |
ARMMMUIdxBit_E20_0 |
+ ARMMMUIdxBit_E20_0_GCS |
ARMMMUIdxBit_E10_1 |
- ARMMMUIdxBit_E20_2 |
ARMMMUIdxBit_E10_1_PAN |
+ ARMMMUIdxBit_E10_1_GCS |
+ ARMMMUIdxBit_E20_2 |
ARMMMUIdxBit_E20_2_PAN |
- ARMMMUIdxBit_E2));
+ ARMMMUIdxBit_E20_2_GCS |
+ ARMMMUIdxBit_E2 |
+ ARMMMUIdxBit_E2_GCS));
}
}
@@ -2759,7 +2766,9 @@ static void vmsa_tcr_ttbr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
(arm_hcr_el2_eff(env) & HCR_E2H)) {
uint16_t mask = ARMMMUIdxBit_E20_2 |
ARMMMUIdxBit_E20_2_PAN |
- ARMMMUIdxBit_E20_0;
+ ARMMMUIdxBit_E20_2_GCS |
+ ARMMMUIdxBit_E20_0 |
+ ARMMMUIdxBit_E20_0_GCS;
tlb_flush_by_mmuidx(env_cpu(env), mask);
}
raw_write(env, ri, value);
diff --git a/target/arm/mmuidx.c b/target/arm/mmuidx.c
index 61a682e655..42b003db9c 100644
--- a/target/arm/mmuidx.c
+++ b/target/arm/mmuidx.c
@@ -15,22 +15,29 @@
#define USER R_MMUIDXINFO_USER_MASK
#define S1 R_MMUIDXINFO_STAGE1_MASK
#define S2 R_MMUIDXINFO_STAGE2_MASK
+#define GCS R_MMUIDXINFO_GCS_MASK
const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8] = {
/*
* A-profile.
*/
[ARMMMUIdx_E10_0] = EL(0) | REL(1) | R2,
+ [ARMMMUIdx_E10_0_GCS] = EL(0) | REL(1) | R2 | GCS,
[ARMMMUIdx_E10_1] = EL(1) | REL(1) | R2,
[ARMMMUIdx_E10_1_PAN] = EL(1) | REL(1) | R2 | PAN,
+ [ARMMMUIdx_E10_1_GCS] = EL(1) | REL(1) | R2 | GCS,
[ARMMMUIdx_E20_0] = EL(0) | REL(2) | R2,
+ [ARMMMUIdx_E20_0_GCS] = EL(0) | REL(2) | R2 | GCS,
[ARMMMUIdx_E20_2] = EL(2) | REL(2) | R2,
[ARMMMUIdx_E20_2_PAN] = EL(2) | REL(2) | R2 | PAN,
+ [ARMMMUIdx_E20_2_GCS] = EL(2) | REL(2) | R2 | GCS,
[ARMMMUIdx_E2] = EL(2) | REL(2),
+ [ARMMMUIdx_E2_GCS] = EL(2) | REL(2) | GCS,
[ARMMMUIdx_E3] = EL(3) | REL(3),
+ [ARMMMUIdx_E3_GCS] = EL(3) | REL(3) | GCS,
[ARMMMUIdx_E30_0] = EL(0) | REL(3),
[ARMMMUIdx_E30_3_PAN] = EL(3) | REL(3) | PAN,
@@ -38,8 +45,10 @@ const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8] = {
[ARMMMUIdx_Stage2] = REL(2) | S2,
[ARMMMUIdx_Stage1_E0] = REL(1) | R2 | S1 | USER,
+ [ARMMMUIdx_Stage1_E0_GCS] = REL(1) | R2 | S1 | USER | GCS,
[ARMMMUIdx_Stage1_E1] = REL(1) | R2 | S1,
[ARMMMUIdx_Stage1_E1_PAN] = REL(1) | R2 | S1 | PAN,
+ [ARMMMUIdx_Stage1_E1_GCS] = REL(1) | R2 | S1 | GCS,
/*
* M-profile.
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 493ec78c1a..ee887d9a02 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -166,6 +166,10 @@ ARMMMUIdx stage_1_mmu_idx(ARMMMUIdx mmu_idx)
return ARMMMUIdx_Stage1_E1;
case ARMMMUIdx_E10_1_PAN:
return ARMMMUIdx_Stage1_E1_PAN;
+ case ARMMMUIdx_E10_0_GCS:
+ return ARMMMUIdx_Stage1_E0_GCS;
+ case ARMMMUIdx_E10_1_GCS:
+ return ARMMMUIdx_Stage1_E1_GCS;
default:
return mmu_idx;
}
@@ -273,8 +277,10 @@ static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx,
return (hcr_el2 & (HCR_DC | HCR_VM)) == 0;
case ARMMMUIdx_E10_0:
+ case ARMMMUIdx_E10_0_GCS:
case ARMMMUIdx_E10_1:
case ARMMMUIdx_E10_1_PAN:
+ case ARMMMUIdx_E10_1_GCS:
/* TGE means that EL0/1 act as if SCTLR_EL1.M is zero */
hcr_el2 = arm_hcr_el2_eff_secstate(env, space);
if (hcr_el2 & HCR_TGE) {
@@ -283,8 +289,10 @@ static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx,
break;
case ARMMMUIdx_Stage1_E0:
+ case ARMMMUIdx_Stage1_E0_GCS:
case ARMMMUIdx_Stage1_E1:
case ARMMMUIdx_Stage1_E1_PAN:
+ case ARMMMUIdx_Stage1_E1_GCS:
/* HCR.DC means SCTLR_EL1.M behaves as 0 */
hcr_el2 = arm_hcr_el2_eff_secstate(env, space);
if (hcr_el2 & HCR_DC) {
@@ -293,10 +301,14 @@ static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx,
break;
case ARMMMUIdx_E20_0:
+ case ARMMMUIdx_E20_0_GCS:
case ARMMMUIdx_E20_2:
case ARMMMUIdx_E20_2_PAN:
+ case ARMMMUIdx_E20_2_GCS:
case ARMMMUIdx_E2:
+ case ARMMMUIdx_E2_GCS:
case ARMMMUIdx_E3:
+ case ARMMMUIdx_E3_GCS:
case ARMMMUIdx_E30_0:
case ARMMMUIdx_E30_3_PAN:
break;
@@ -3761,15 +3773,22 @@ arm_mmu_idx_to_security_space(CPUARMState *env, ARMMMUIdx mmu_idx)
switch (mmu_idx) {
case ARMMMUIdx_E10_0:
+ case ARMMMUIdx_E10_0_GCS:
case ARMMMUIdx_E10_1:
case ARMMMUIdx_E10_1_PAN:
+ case ARMMMUIdx_E10_1_GCS:
case ARMMMUIdx_E20_0:
+ case ARMMMUIdx_E20_0_GCS:
case ARMMMUIdx_E20_2:
case ARMMMUIdx_E20_2_PAN:
+ case ARMMMUIdx_E20_2_GCS:
case ARMMMUIdx_Stage1_E0:
+ case ARMMMUIdx_Stage1_E0_GCS:
case ARMMMUIdx_Stage1_E1:
case ARMMMUIdx_Stage1_E1_PAN:
+ case ARMMMUIdx_Stage1_E1_GCS:
case ARMMMUIdx_E2:
+ case ARMMMUIdx_E2_GCS:
ss = arm_security_space_below_el3(env);
break;
case ARMMMUIdx_Stage2:
@@ -3798,6 +3817,7 @@ arm_mmu_idx_to_security_space(CPUARMState *env, ARMMMUIdx mmu_idx)
ss = ARMSS_Secure;
break;
case ARMMMUIdx_E3:
+ case ARMMMUIdx_E3_GCS:
case ARMMMUIdx_E30_0:
case ARMMMUIdx_E30_3_PAN:
if (arm_feature(env, ARM_FEATURE_AARCH64) &&
diff --git a/target/arm/tcg/tlb-insns.c b/target/arm/tcg/tlb-insns.c
index 95c26c6d46..1a0a332583 100644
--- a/target/arm/tcg/tlb-insns.c
+++ b/target/arm/tcg/tlb-insns.c
@@ -149,7 +149,8 @@ static void tlbimva_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
CPUState *cs = env_cpu(env);
uint64_t pageaddr = value & ~MAKE_64BIT_MASK(0, 12);
- tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_E2);
+ tlb_flush_page_by_mmuidx(cs, pageaddr,
+ ARMMMUIdxBit_E2 | ARMMMUIdxBit_E2_GCS);
}
static void tlbimva_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -159,7 +160,8 @@ static void tlbimva_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t pageaddr = value & ~MAKE_64BIT_MASK(0, 12);
tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
- ARMMMUIdxBit_E2);
+ ARMMMUIdxBit_E2 |
+ ARMMMUIdxBit_E2_GCS);
}
static void tlbiipas2_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -202,7 +204,7 @@ static void tlbiall_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri,
{
CPUState *cs = env_cpu(env);
- tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E2);
+ tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E2 | ARMMMUIdxBit_E2_GCS);
}
static void tlbiall_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -210,7 +212,8 @@ static void tlbiall_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
{
CPUState *cs = env_cpu(env);
- tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_E2);
+ tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_E2 |
+ ARMMMUIdxBit_E2_GCS);
}
/*
@@ -228,12 +231,16 @@ static int vae1_tlbmask(CPUARMState *env)
if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
mask = ARMMMUIdxBit_E20_2 |
ARMMMUIdxBit_E20_2_PAN |
- ARMMMUIdxBit_E20_0;
+ ARMMMUIdxBit_E20_2_GCS |
+ ARMMMUIdxBit_E20_0 |
+ ARMMMUIdxBit_E20_0_GCS;
} else {
/* This is AArch64 only, so we don't need to touch the EL30_x TLBs */
mask = ARMMMUIdxBit_E10_1 |
ARMMMUIdxBit_E10_1_PAN |
- ARMMMUIdxBit_E10_0;
+ ARMMMUIdxBit_E10_1_GCS |
+ ARMMMUIdxBit_E10_0 |
+ ARMMMUIdxBit_E10_0_GCS;
}
return mask;
}
@@ -246,13 +253,20 @@ static int vae2_tlbmask(CPUARMState *env)
if (hcr & HCR_E2H) {
mask = ARMMMUIdxBit_E20_2 |
ARMMMUIdxBit_E20_2_PAN |
- ARMMMUIdxBit_E20_0;
+ ARMMMUIdxBit_E20_2_GCS |
+ ARMMMUIdxBit_E20_0 |
+ ARMMMUIdxBit_E20_0_GCS;
} else {
- mask = ARMMMUIdxBit_E2;
+ mask = ARMMMUIdxBit_E2 | ARMMMUIdxBit_E2_GCS;
}
return mask;
}
+static int vae3_tlbmask(void)
+{
+ return ARMMMUIdxBit_E3 | ARMMMUIdxBit_E3_GCS;
+}
+
/* Return 56 if TBI is enabled, 64 otherwise. */
static int tlbbits_for_regime(CPUARMState *env, ARMMMUIdx mmu_idx,
uint64_t addr)
@@ -325,9 +339,12 @@ static void tlbi_aa64_vmalle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
static int e2_tlbmask(CPUARMState *env)
{
return (ARMMMUIdxBit_E20_0 |
+ ARMMMUIdxBit_E20_0_GCS |
ARMMMUIdxBit_E20_2 |
ARMMMUIdxBit_E20_2_PAN |
- ARMMMUIdxBit_E2);
+ ARMMMUIdxBit_E20_2_GCS |
+ ARMMMUIdxBit_E2 |
+ ARMMMUIdxBit_E2_GCS);
}
static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -354,7 +371,7 @@ static void tlbi_aa64_alle3_write(CPUARMState *env, const ARMCPRegInfo *ri,
ARMCPU *cpu = env_archcpu(env);
CPUState *cs = CPU(cpu);
- tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E3);
+ tlb_flush_by_mmuidx(cs, vae3_tlbmask());
}
static void tlbi_aa64_alle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -380,7 +397,7 @@ static void tlbi_aa64_alle3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
{
CPUState *cs = env_cpu(env);
- tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_E3);
+ tlb_flush_by_mmuidx_all_cpus_synced(cs, vae3_tlbmask());
}
static void tlbi_aa64_vae2_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -411,7 +428,7 @@ static void tlbi_aa64_vae3_write(CPUARMState *env, const ARMCPRegInfo *ri,
CPUState *cs = CPU(cpu);
uint64_t pageaddr = sextract64(value << 12, 0, 56);
- tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_E3);
+ tlb_flush_page_by_mmuidx(cs, pageaddr, vae3_tlbmask());
}
static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -465,7 +482,7 @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
int bits = tlbbits_for_regime(env, ARMMMUIdx_E3, pageaddr);
tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
- ARMMMUIdxBit_E3, bits);
+ vae3_tlbmask(), bits);
}
static int ipas2e1_tlbmask(CPUARMState *env, int64_t value)
@@ -963,7 +980,7 @@ static void tlbi_aa64_rvae3_write(CPUARMState *env,
* flush-last-level-only.
*/
- do_rvae_write(env, value, ARMMMUIdxBit_E3, tlb_force_broadcast(env));
+ do_rvae_write(env, value, vae3_tlbmask(), tlb_force_broadcast(env));
}
static void tlbi_aa64_rvae3is_write(CPUARMState *env,
@@ -977,7 +994,7 @@ static void tlbi_aa64_rvae3is_write(CPUARMState *env,
* flush-last-level-only or inner/outer specific flushes.
*/
- do_rvae_write(env, value, ARMMMUIdxBit_E3, true);
+ do_rvae_write(env, value, vae3_tlbmask(), true);
}
static void tlbi_aa64_ripas2e1_write(CPUARMState *env, const ARMCPRegInfo *ri,
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 41/82] target/arm: Introduce regime_to_gcs
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (39 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 40/82] target/arm: Introduce mmu indexes for GCS Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-30 21:33 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 42/82] target/arm: Support page protections for GCS mmu indexes Richard Henderson
` (40 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Add a lookup from any a64 mmu index to the gcs mmu index
within the same translation regime.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/mmuidx-internal.h | 10 ++++++++++
target/arm/mmuidx.c | 24 +++++++++++++-----------
2 files changed, 23 insertions(+), 11 deletions(-)
diff --git a/target/arm/mmuidx-internal.h b/target/arm/mmuidx-internal.h
index f5de104460..b6954cbf40 100644
--- a/target/arm/mmuidx-internal.h
+++ b/target/arm/mmuidx-internal.h
@@ -21,6 +21,7 @@ FIELD(MMUIDXINFO, USER, 8, 1)
FIELD(MMUIDXINFO, STAGE1, 9, 1)
FIELD(MMUIDXINFO, STAGE2, 10, 1)
FIELD(MMUIDXINFO, GCS, 11, 1)
+FIELD(MMUIDXINFO, TG, 12, 5)
extern const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8];
@@ -98,4 +99,13 @@ static inline bool regime_is_gcs(ARMMMUIdx idx)
return FIELD_EX32(arm_mmuidx_table[idx], MMUIDXINFO, GCS);
}
+/* Return the GCS MMUIdx for a given regime. */
+static inline ARMMMUIdx regime_to_gcs(ARMMMUIdx idx)
+{
+ tcg_debug_assert((unsigned)idx < ARRAY_SIZE(arm_mmuidx_table));
+ uint32_t core = FIELD_EX32(arm_mmuidx_table[idx], MMUIDXINFO, TG);
+ tcg_debug_assert(core != 0); /* core 0 is E10_0, not a GCS index */
+ return core | ARM_MMU_IDX_A;
+}
+
#endif /* TARGET_ARM_MMUIDX_INTERNAL_H */
diff --git a/target/arm/mmuidx.c b/target/arm/mmuidx.c
index 42b003db9c..a4663c8d87 100644
--- a/target/arm/mmuidx.c
+++ b/target/arm/mmuidx.c
@@ -16,27 +16,29 @@
#define S1 R_MMUIDXINFO_STAGE1_MASK
#define S2 R_MMUIDXINFO_STAGE2_MASK
#define GCS R_MMUIDXINFO_GCS_MASK
+#define TG(X) \
+ ((ARMMMUIdx_##X##_GCS & ARM_MMU_IDX_COREIDX_MASK) << R_MMUIDXINFO_TG_SHIFT)
const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8] = {
/*
* A-profile.
*/
- [ARMMMUIdx_E10_0] = EL(0) | REL(1) | R2,
+ [ARMMMUIdx_E10_0] = EL(0) | REL(1) | R2 | TG(E10_0),
[ARMMMUIdx_E10_0_GCS] = EL(0) | REL(1) | R2 | GCS,
- [ARMMMUIdx_E10_1] = EL(1) | REL(1) | R2,
- [ARMMMUIdx_E10_1_PAN] = EL(1) | REL(1) | R2 | PAN,
+ [ARMMMUIdx_E10_1] = EL(1) | REL(1) | R2 | TG(E10_1),
+ [ARMMMUIdx_E10_1_PAN] = EL(1) | REL(1) | R2 | TG(E10_1) | PAN,
[ARMMMUIdx_E10_1_GCS] = EL(1) | REL(1) | R2 | GCS,
- [ARMMMUIdx_E20_0] = EL(0) | REL(2) | R2,
+ [ARMMMUIdx_E20_0] = EL(0) | REL(2) | R2 | TG(E20_0),
[ARMMMUIdx_E20_0_GCS] = EL(0) | REL(2) | R2 | GCS,
- [ARMMMUIdx_E20_2] = EL(2) | REL(2) | R2,
- [ARMMMUIdx_E20_2_PAN] = EL(2) | REL(2) | R2 | PAN,
+ [ARMMMUIdx_E20_2] = EL(2) | REL(2) | R2 | TG(E20_2),
+ [ARMMMUIdx_E20_2_PAN] = EL(2) | REL(2) | R2 | TG(E20_2) | PAN,
[ARMMMUIdx_E20_2_GCS] = EL(2) | REL(2) | R2 | GCS,
- [ARMMMUIdx_E2] = EL(2) | REL(2),
+ [ARMMMUIdx_E2] = EL(2) | REL(2) | TG(E2),
[ARMMMUIdx_E2_GCS] = EL(2) | REL(2) | GCS,
- [ARMMMUIdx_E3] = EL(3) | REL(3),
+ [ARMMMUIdx_E3] = EL(3) | REL(3) | TG(E3),
[ARMMMUIdx_E3_GCS] = EL(3) | REL(3) | GCS,
[ARMMMUIdx_E30_0] = EL(0) | REL(3),
[ARMMMUIdx_E30_3_PAN] = EL(3) | REL(3) | PAN,
@@ -44,10 +46,10 @@ const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8] = {
[ARMMMUIdx_Stage2_S] = REL(2) | S2,
[ARMMMUIdx_Stage2] = REL(2) | S2,
- [ARMMMUIdx_Stage1_E0] = REL(1) | R2 | S1 | USER,
+ [ARMMMUIdx_Stage1_E0] = REL(1) | R2 | S1 | USER | TG(Stage1_E0),
[ARMMMUIdx_Stage1_E0_GCS] = REL(1) | R2 | S1 | USER | GCS,
- [ARMMMUIdx_Stage1_E1] = REL(1) | R2 | S1,
- [ARMMMUIdx_Stage1_E1_PAN] = REL(1) | R2 | S1 | PAN,
+ [ARMMMUIdx_Stage1_E1] = REL(1) | R2 | S1 | TG(Stage1_E1),
+ [ARMMMUIdx_Stage1_E1_PAN] = REL(1) | R2 | S1 | TG(Stage1_E1) | PAN,
[ARMMMUIdx_Stage1_E1_GCS] = REL(1) | R2 | S1 | GCS,
/*
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 42/82] target/arm: Support page protections for GCS mmu indexes
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (40 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 41/82] target/arm: Introduce regime_to_gcs Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 18:40 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 43/82] target/arm: Implement gcs bit for data abort Richard Henderson
` (39 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Take read and write from the s1perms.gcs bit computed
by the Arm pseudocode.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/ptw.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index ee887d9a02..3c84f0f024 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -1584,12 +1584,16 @@ static int get_S1prot_indirect(CPUARMState *env, S1Translate *ptw,
}
}
- if (perm & PAGE_WXN) {
+ if (regime_is_gcs(mmu_idx)) {
+ /*
+ * Note that the one s1perms.gcs bit controls both read and write
+ * access via AccessType_GCS. See AArch64.S1CheckPermissions.
+ */
+ perm = (perm & PAGE_GCS ? PAGE_READ | PAGE_WRITE : 0);
+ } else if (perm & PAGE_WXN) {
perm &= ~PAGE_EXEC;
}
- /* TODO: FEAT_GCS */
-
return perm & PAGE_RWX;
}
@@ -2236,6 +2240,13 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
*/
prot = get_S1prot_indirect(env, ptw, mmu_idx, pi, po,
result->f.attrs.space, out_space);
+ } else if (regime_is_gcs(mmu_idx)) {
+ /*
+ * While one must use indirect permissions to successfully
+ * use GCS instructions, AArch64.S1DirectBasePermissions
+ * faithfully supplies s1perms.gcs = 0, Just In Case.
+ */
+ prot = 0;
} else {
int xn = extract64(attrs, 54, 1);
int pxn = extract64(attrs, 53, 1);
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 43/82] target/arm: Implement gcs bit for data abort
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (41 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 42/82] target/arm: Support page protections for GCS mmu indexes Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 18:41 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 44/82] target/arm: Add GCS cpregs Richard Henderson
` (38 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/internals.h | 1 +
target/arm/ptw.c | 1 +
target/arm/tcg/tlb_helper.c | 1 +
3 files changed, 3 insertions(+)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 805f4a1876..7a42f8be0b 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -756,6 +756,7 @@ struct ARMMMUFaultInfo {
bool s1ns;
bool ea;
bool dirtybit; /* FEAT_S1PIE, FEAT_S2PIE */
+ bool gcs;
};
/**
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 3c84f0f024..ce9626b627 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -2393,6 +2393,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
fi->stage2 = regime_is_stage2(mmu_idx);
}
fi->s1ns = fault_s1ns(ptw->in_space, mmu_idx);
+ fi->gcs = regime_is_gcs(mmu_idx);
return true;
}
diff --git a/target/arm/tcg/tlb_helper.c b/target/arm/tcg/tlb_helper.c
index ae2acd6727..37c7651799 100644
--- a/target/arm/tcg/tlb_helper.c
+++ b/target/arm/tcg/tlb_helper.c
@@ -78,6 +78,7 @@ static inline uint64_t merge_syn_data_abort(uint32_t template_syn,
/* Form ISS2 at the top of the syndrome. */
syn |= (uint64_t)fi->dirtybit << 37;
+ syn |= (uint64_t)fi->gcs << 40;
return syn;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 44/82] target/arm: Add GCS cpregs
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (42 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 43/82] target/arm: Implement gcs bit for data abort Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 18:45 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 45/82] target/arm: Add GCS enable and trap levels to DisasContext Richard Henderson
` (37 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Add isar_feature_aa64_gcs.
Enable SCR_GCSEN in scr_write.
Enable HCRX_GCSEN in hcrx_write.
Default HCRX_GCSEN on if EL2 disabled.
Add the GCSCR* and GCSPR* registers.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpregs.h | 2 +
target/arm/cpu-features.h | 5 +++
target/arm/cpu.h | 12 ++++++
target/arm/internals.h | 3 ++
target/arm/cpregs-gcs.c | 79 +++++++++++++++++++++++++++++++++++++++
target/arm/cpu.c | 3 ++
target/arm/helper.c | 10 +++++
target/arm/meson.build | 2 +
8 files changed, 116 insertions(+)
create mode 100644 target/arm/cpregs-gcs.c
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
index 9efe9238c1..bc6adf5956 100644
--- a/target/arm/cpregs.h
+++ b/target/arm/cpregs.h
@@ -774,6 +774,8 @@ typedef enum FGTBit {
DO_BIT(HFGRTR, VBAR_EL1),
DO_BIT(HFGRTR, ICC_IGRPENN_EL1),
DO_BIT(HFGRTR, ERRIDR_EL1),
+ DO_REV_BIT(HFGRTR, NGCS_EL0),
+ DO_REV_BIT(HFGRTR, NGCS_EL1),
DO_REV_BIT(HFGRTR, NSMPRI_EL1),
DO_REV_BIT(HFGRTR, NTPIDR2_EL0),
DO_REV_BIT(HFGRTR, NPIRE0_EL1),
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index 83875c06bb..e3754df786 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -719,6 +719,11 @@ static inline bool isar_feature_aa64_nmi(const ARMISARegisters *id)
return FIELD_EX64_IDREG(id, ID_AA64PFR1, NMI) != 0;
}
+static inline bool isar_feature_aa64_gcs(const ARMISARegisters *id)
+{
+ return FIELD_EX64_IDREG(id, ID_AA64PFR1, GCS) != 0;
+}
+
static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id)
{
return FIELD_SEX64_IDREG(id, ID_AA64MMFR0, TGRAN4) >= 1;
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index da42bd4466..1da73196f0 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -591,6 +591,9 @@ typedef struct CPUArchState {
uint64_t mecid_rl_a_el3;
uint64_t vmecid_p_el2;
uint64_t vmecid_a_el2;
+
+ uint64_t gcscr_el[4]; /* GCSCRE0_EL1, GCSCR_EL[123] */
+ uint64_t gcspr_el[4]; /* GCSPR_EL[0123] */
} cp15;
struct {
@@ -1735,6 +1738,7 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
#define SCR_ENAS0 (1ULL << 36)
#define SCR_ADEN (1ULL << 37)
#define SCR_HXEN (1ULL << 38)
+#define SCR_GCSEN (1ULL << 39)
#define SCR_TRNDR (1ULL << 40)
#define SCR_ENTP2 (1ULL << 41)
#define SCR_TCR2EN (1ULL << 43)
@@ -1744,6 +1748,14 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
#define SCR_MECEN (1ULL << 49)
#define SCR_NSE (1ULL << 62)
+/* GCSCR_ELx fields */
+#define GCSCR_PCRSEL (1ULL << 0)
+#define GCSCR_RVCHKEN (1ULL << 5)
+#define GCSCR_EXLOCKEN (1ULL << 6)
+#define GCSCR_PUSHMEN (1ULL << 8)
+#define GCSCR_STREN (1ULL << 9)
+#define GCSCRE0_NTR (1ULL << 10)
+
/* Return the current FPSCR value. */
uint32_t vfp_get_fpscr(CPUARMState *env);
void vfp_set_fpscr(CPUARMState *env, uint32_t val);
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 7a42f8be0b..350b8bc678 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -253,6 +253,7 @@ FIELD(VTCR, SL2, 33, 1)
#define HCRX_MSCEN (1ULL << 11)
#define HCRX_TCR2EN (1ULL << 14)
#define HCRX_SCTLR2EN (1ULL << 15)
+#define HCRX_GCSEN (1ULL << 22)
#define HPFAR_NS (1ULL << 63)
@@ -1778,6 +1779,8 @@ void define_tlb_insn_regs(ARMCPU *cpu);
void define_at_insn_regs(ARMCPU *cpu);
/* Add the cpreg definitions for PM cpregs */
void define_pm_cpregs(ARMCPU *cpu);
+/* Add the cpreg definitions for GCS cpregs */
+void define_gcs_cpregs(ARMCPU *cpu);
/* Effective value of MDCR_EL2 */
static inline uint64_t arm_mdcr_el2_eff(CPUARMState *env)
diff --git a/target/arm/cpregs-gcs.c b/target/arm/cpregs-gcs.c
new file mode 100644
index 0000000000..9c06100d2b
--- /dev/null
+++ b/target/arm/cpregs-gcs.c
@@ -0,0 +1,79 @@
+/*
+ * QEMU ARM CP Register GCS regiters and instructions
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/timer.h"
+#include "exec/icount.h"
+#include "hw/irq.h"
+#include "cpu.h"
+#include "cpu-features.h"
+#include "cpregs.h"
+#include "internals.h"
+
+
+static CPAccessResult access_gcs(CPUARMState *env, const ARMCPRegInfo *ri,
+ bool isread)
+{
+ if (arm_current_el(env) < 3
+ && arm_feature(env, ARM_FEATURE_EL3)
+ && !(env->cp15.scr_el3 & SCR_GCSEN)) {
+ return CP_ACCESS_TRAP_EL3;
+ }
+ return CP_ACCESS_OK;
+}
+
+static CPAccessResult access_gcs_el0(CPUARMState *env, const ARMCPRegInfo *ri,
+ bool isread)
+{
+ if (arm_current_el(env) == 0 && !(env->cp15.gcscr_el[0] & GCSCRE0_NTR)) {
+ return CP_ACCESS_TRAP_EL1;
+ }
+ return access_gcs(env, ri, isread);
+}
+
+static const ARMCPRegInfo gcs_reginfo[] = {
+ { .name = "GCSCRE0_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 2, .crm = 5, .opc2 = 2,
+ .access = PL1_RW, .accessfn = access_gcs, .fgt = FGT_NGCS_EL0,
+ .fieldoffset = offsetof(CPUARMState, cp15.gcscr_el[0]) },
+ { .name = "GCSCR_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 2, .crm = 5, .opc2 = 0,
+ .access = PL1_RW, .accessfn = access_gcs, .fgt = FGT_NGCS_EL1,
+ .nv2_redirect_offset = 0x8d0 | NV2_REDIR_NV1,
+ .fieldoffset = offsetof(CPUARMState, cp15.gcscr_el[1]) },
+ { .name = "GCSCR_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 5, .opc2 = 0,
+ .access = PL2_RW, .accessfn = access_gcs,
+ .fieldoffset = offsetof(CPUARMState, cp15.gcscr_el[2]) },
+ { .name = "GCSCR_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 2, .crm = 5, .opc2 = 0,
+ .access = PL3_RW,
+ .fieldoffset = offsetof(CPUARMState, cp15.gcscr_el[3]) },
+
+ { .name = "GCSPR_EL0", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 3, .crn = 2, .crm = 5, .opc2 = 1,
+ .access = PL0_R | PL1_W, .accessfn = access_gcs_el0, .fgt = FGT_NGCS_EL0,
+ .fieldoffset = offsetof(CPUARMState, cp15.gcspr_el[0]) },
+ { .name = "GCSPR_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 2, .crm = 5, .opc2 = 1,
+ .access = PL1_RW, .accessfn = access_gcs, .fgt = FGT_NGCS_EL1,
+ .nv2_redirect_offset = 0x8c0 | NV2_REDIR_NV1,
+ .fieldoffset = offsetof(CPUARMState, cp15.gcspr_el[1]) },
+ { .name = "GCSPR_EL2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 5, .opc2 = 1,
+ .access = PL2_RW, .accessfn = access_gcs,
+ .fieldoffset = offsetof(CPUARMState, cp15.gcspr_el[2]) },
+ { .name = "GCSPR_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 2, .crm = 5, .opc2 = 1,
+ .access = PL3_RW,
+ .fieldoffset = offsetof(CPUARMState, cp15.gcspr_el[2]) },
+};
+
+void define_gcs_cpregs(ARMCPU *cpu)
+{
+ if (cpu_isar_feature(aa64_gcs, cpu)) {
+ define_arm_cp_regs(cpu, gcs_reginfo);
+ }
+}
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index b472992b4a..d9318c5325 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -644,6 +644,9 @@ void arm_emulate_firmware_reset(CPUState *cpustate, int target_el)
if (cpu_isar_feature(aa64_fgt, cpu)) {
env->cp15.scr_el3 |= SCR_FGTEN;
}
+ if (cpu_isar_feature(aa64_gcs, cpu)) {
+ env->cp15.scr_el3 |= SCR_GCSEN;
+ }
if (cpu_isar_feature(aa64_tcr2, cpu)) {
env->cp15.scr_el3 |= SCR_TCR2EN;
}
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 7ba802f2d6..f006ecabf3 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -743,6 +743,9 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
if (cpu_isar_feature(aa64_ecv, cpu)) {
valid_mask |= SCR_ECVEN;
}
+ if (cpu_isar_feature(aa64_gcs, cpu)) {
+ valid_mask |= SCR_GCSEN;
+ }
if (cpu_isar_feature(aa64_tcr2, cpu)) {
valid_mask |= SCR_TCR2EN;
}
@@ -3947,6 +3950,9 @@ static void hcrx_write(CPUARMState *env, const ARMCPRegInfo *ri,
if (cpu_isar_feature(aa64_sctlr2, cpu)) {
valid_mask |= HCRX_SCTLR2EN;
}
+ if (cpu_isar_feature(aa64_gcs, cpu)) {
+ valid_mask |= HCRX_GCSEN;
+ }
/* Clear RES0 bits. */
env->cp15.hcrx_el2 = value & valid_mask;
@@ -4017,6 +4023,9 @@ uint64_t arm_hcrx_el2_eff(CPUARMState *env)
if (cpu_isar_feature(aa64_sctlr2, cpu)) {
hcrx |= HCRX_SCTLR2EN;
}
+ if (cpu_isar_feature(aa64_gcs, cpu)) {
+ hcrx |= HCRX_GCSEN;
+ }
return hcrx;
}
if (arm_feature(env, ARM_FEATURE_EL3) && !(env->cp15.scr_el3 & SCR_HXEN)) {
@@ -7574,6 +7583,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
}
define_pm_cpregs(cpu);
+ define_gcs_cpregs(cpu);
#ifndef CONFIG_USER_ONLY
/*
diff --git a/target/arm/meson.build b/target/arm/meson.build
index 91630a1f72..8c82304fde 100644
--- a/target/arm/meson.build
+++ b/target/arm/meson.build
@@ -27,6 +27,7 @@ arm_user_ss.add(when: 'TARGET_AARCH64', if_false: files(
'cpu32-stubs.c',
))
arm_user_ss.add(files(
+ 'cpregs-gcs.c',
'cpregs-pmu.c',
'debug_helper.c',
'helper.c',
@@ -42,6 +43,7 @@ arm_common_system_ss.add(files(
'arch_dump.c',
'arm-powerctl.c',
'cortex-regs.c',
+ 'cpregs-gcs.c',
'cpregs-pmu.c',
'debug_helper.c',
'helper.c',
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 45/82] target/arm: Add GCS enable and trap levels to DisasContext
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (43 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 44/82] target/arm: Add GCS cpregs Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 18:54 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 46/82] target/arm: Implement FEAT_CHK Richard Henderson
` (36 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Pipe GCSEnabled, GCSReturnValueCheckEnabled, and CheckGCSSTREnabled
through hflags to the translator.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpu.h | 3 +++
target/arm/tcg/translate.h | 6 ++++++
target/arm/tcg/hflags.c | 38 ++++++++++++++++++++++++++++++++++
target/arm/tcg/translate-a64.c | 3 +++
4 files changed, 50 insertions(+)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 1da73196f0..98360b70b8 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2918,6 +2918,9 @@ FIELD(TBFLAG_A64, NV2_MEM_BE, 36, 1)
FIELD(TBFLAG_A64, AH, 37, 1) /* FPCR.AH */
FIELD(TBFLAG_A64, NEP, 38, 1) /* FPCR.NEP */
FIELD(TBFLAG_A64, ZT0EXC_EL, 39, 2)
+FIELD(TBFLAG_A64, GCS_EN, 41, 1)
+FIELD(TBFLAG_A64, GCS_RVCEN, 42, 1)
+FIELD(TBFLAG_A64, GCSSTR_EL, 43, 2)
/*
* Helpers for using the above. Note that only the A64 accessors use
diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h
index f974996f3f..3e63dad2b6 100644
--- a/target/arm/tcg/translate.h
+++ b/target/arm/tcg/translate.h
@@ -164,6 +164,12 @@ typedef struct DisasContext {
bool fpcr_ah;
/* True if FPCR.NEP is 1 (FEAT_AFP scalar upper-element result handling) */
bool fpcr_nep;
+ /* True if GCSEnabled. */
+ bool gcs_en;
+ /* True if GCSReturnValueCheckEnabled. */
+ bool gcs_rvcen;
+ /* GCSSTR exception EL or 0 if enabled */
+ uint8_t gcsstr_el;
/*
* >= 0, a copy of PSTATE.BTYPE, which will be 0 without v8.5-BTI.
* < 0, set by the current instruction.
diff --git a/target/arm/tcg/hflags.c b/target/arm/tcg/hflags.c
index 59ab526375..2e3a9cf0d3 100644
--- a/target/arm/tcg/hflags.c
+++ b/target/arm/tcg/hflags.c
@@ -449,6 +449,44 @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
DP_TBFLAG_A64(flags, TCMA, aa64_va_parameter_tcma(tcr, mmu_idx));
}
+ if (cpu_isar_feature(aa64_gcs, env_archcpu(env))) {
+ /* C.f. GCSEnabled */
+ if (env->cp15.gcscr_el[el] & GCSCR_PCRSEL) {
+ switch (el) {
+ default:
+ if (!el_is_in_host(env, el)
+ && !(arm_hcrx_el2_eff(env) & HCRX_GCSEN)) {
+ break;
+ }
+ /* fall through */
+ case 2:
+ if (arm_feature(env, ARM_FEATURE_EL3)
+ && !(env->cp15.scr_el3 & SCR_GCSEN)) {
+ break;
+ }
+ /* fall through */
+ case 3:
+ DP_TBFLAG_A64(flags, GCS_EN, 1);
+ break;
+ }
+ }
+
+ /* C.f. GCSReturnValueCheckEnabled */
+ if (env->cp15.gcscr_el[el] & GCSCR_RVCHKEN) {
+ DP_TBFLAG_A64(flags, GCS_RVCEN, 1);
+ }
+
+ /* C.f. CheckGCSSTREnabled */
+ if (!(env->cp15.gcscr_el[el] & GCSCR_STREN)) {
+ DP_TBFLAG_A64(flags, GCSSTR_EL, el ? el : 1);
+ } else if (el == 1
+ && EX_TBFLAG_ANY(flags, FGT_ACTIVE)
+ && !FIELD_EX64(env->cp15.fgt_exec[FGTREG_HFGITR],
+ HFGITR_EL2, NGCSSTR_EL1)) {
+ DP_TBFLAG_A64(flags, GCSSTR_EL, 2);
+ }
+ }
+
if (env->vfp.fpcr & FPCR_AH) {
DP_TBFLAG_A64(flags, AH, 1);
}
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index dbf47595db..7831b3dab3 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -10162,6 +10162,9 @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
dc->nv2_mem_be = EX_TBFLAG_A64(tb_flags, NV2_MEM_BE);
dc->fpcr_ah = EX_TBFLAG_A64(tb_flags, AH);
dc->fpcr_nep = EX_TBFLAG_A64(tb_flags, NEP);
+ dc->gcs_en = EX_TBFLAG_A64(tb_flags, GCS_EN);
+ dc->gcs_rvcen = EX_TBFLAG_A64(tb_flags, GCS_RVCEN);
+ dc->gcsstr_el = EX_TBFLAG_A64(tb_flags, GCSSTR_EL);
dc->vec_len = 0;
dc->vec_stride = 0;
dc->cp_regs = arm_cpu->cp_regs;
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 46/82] target/arm: Implement FEAT_CHK
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (44 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 45/82] target/arm: Add GCS enable and trap levels to DisasContext Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-29 16:01 ` Gustavo Romero
2025-07-31 18:59 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 47/82] target/arm: Expand pstate to 64 bits Richard Henderson
` (35 subsequent siblings)
81 siblings, 2 replies; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
This feature contains only the CHKFEAT instruction. It has
no ID enable, being back-allocated into the hint nop space.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/tcg/translate-a64.c | 14 ++++++++++++++
docs/system/arm/emulation.rst | 1 +
target/arm/tcg/a64.decode | 1 +
3 files changed, 16 insertions(+)
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 7831b3dab3..34d22cac8a 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -2124,6 +2124,20 @@ static bool trans_AUTIBSP(DisasContext *s, arg_AUTIBSP *a)
return true;
}
+static bool trans_CHKFEAT(DisasContext *s, arg_CHKFEAT *a)
+{
+ uint64_t feat_en = 0;
+
+ if (s->gcs_en) {
+ feat_en |= 1 << 0;
+ }
+ if (feat_en) {
+ TCGv_i64 x16 = cpu_reg(s, 16);
+ tcg_gen_andi_i64(x16, x16, ~feat_en);
+ }
+ return true;
+}
+
static bool trans_CLREX(DisasContext *s, arg_CLREX *a)
{
tcg_gen_movi_i64(cpu_exclusive_addr, -1);
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
index 6ebf9c9ce9..b894aced89 100644
--- a/docs/system/arm/emulation.rst
+++ b/docs/system/arm/emulation.rst
@@ -28,6 +28,7 @@ the following architecture extensions:
- FEAT_BF16 (AArch64 BFloat16 instructions)
- FEAT_BTI (Branch Target Identification)
- FEAT_CCIDX (Extended cache index)
+- FEAT_CHK (Check Feature Status)
- FEAT_CMOW (Control for cache maintenance permission)
- FEAT_CRC32 (CRC32 instructions)
- FEAT_Crypto (Cryptographic Extension)
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
index 8c798cde2b..4315ed8dab 100644
--- a/target/arm/tcg/a64.decode
+++ b/target/arm/tcg/a64.decode
@@ -246,6 +246,7 @@ ERETA 1101011 0100 11111 00001 m:1 11111 11111 &reta # ERETAA, ERETAB
AUTIASP 1101 0101 0000 0011 0010 0011 101 11111
AUTIBZ 1101 0101 0000 0011 0010 0011 110 11111
AUTIBSP 1101 0101 0000 0011 0010 0011 111 11111
+ CHKFEAT 1101 0101 0000 0011 0010 0101 000 11111
]
# The canonical NOP has CRm == op2 == 0, but all of the space
# that isn't specifically allocated to an instruction must NOP
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 47/82] target/arm: Expand pstate to 64 bits
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (45 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 46/82] target/arm: Implement FEAT_CHK Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 19:13 ` Pierrick Bouvier
2025-08-01 20:22 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 48/82] target/arm: Add syndrome data for EC_GCS Richard Henderson
` (34 subsequent siblings)
81 siblings, 2 replies; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
The ARM now defines 36 bits in SPSR_ELx in aarch64 mode, so
it's time to bite the bullet and extend PSTATE to match.
Most changes are straightforward, adjusting printf formats,
changing local variable types. More complex is migration,
where to maintain backward compatibility a new pstate64
record is introduced, and only when one of the extensions
that sets bits 32-35 are active.
The fate of gdbstub is left undecided for the moment.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpu.h | 8 +++---
target/arm/tcg/translate.h | 20 ++++++-------
target/arm/cpu.c | 6 ++--
target/arm/gdbstub64.c | 1 +
target/arm/helper.c | 11 ++++----
target/arm/machine.c | 56 +++++++++++++++++++++++++++++++++++++
target/arm/tcg/helper-a64.c | 2 +-
7 files changed, 81 insertions(+), 23 deletions(-)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 98360b70b8..7769c4ae3c 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -268,7 +268,7 @@ typedef struct CPUArchState {
uint64_t xregs[32];
uint64_t pc;
/* PSTATE isn't an architectural register for ARMv8. However, it is
- * convenient for us to assemble the underlying state into a 32 bit format
+ * convenient for us to assemble the underlying state into a 64 bit format
* identical to the architectural format used for the SPSR. (This is also
* what the Linux kernel's 'pstate' field in signal handlers and KVM's
* 'pstate' register are.) Of the PSTATE bits:
@@ -280,7 +280,7 @@ typedef struct CPUArchState {
* SM and ZA are kept in env->svcr
* all other bits are stored in their correct places in env->pstate
*/
- uint32_t pstate;
+ uint64_t pstate;
bool aarch64; /* True if CPU is in aarch64 state; inverse of PSTATE.nRW */
bool thumb; /* True if CPU is in thumb mode; cpsr[5] */
@@ -1556,7 +1556,7 @@ static inline unsigned int aarch64_pstate_mode(unsigned int el, bool handler)
* interprocessing, so we don't attempt to sync with the cpsr state used by
* the 32 bit decoder.
*/
-static inline uint32_t pstate_read(CPUARMState *env)
+static inline uint64_t pstate_read(CPUARMState *env)
{
int ZF;
@@ -1566,7 +1566,7 @@ static inline uint32_t pstate_read(CPUARMState *env)
| env->pstate | env->daif | (env->btype << 10);
}
-static inline void pstate_write(CPUARMState *env, uint32_t val)
+static inline void pstate_write(CPUARMState *env, uint64_t val)
{
env->ZF = (~val) & PSTATE_Z;
env->NF = val;
diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h
index 3e63dad2b6..1479f5bf74 100644
--- a/target/arm/tcg/translate.h
+++ b/target/arm/tcg/translate.h
@@ -378,27 +378,27 @@ static inline TCGv_i32 get_ahp_flag(void)
}
/* Set bits within PSTATE. */
-static inline void set_pstate_bits(uint32_t bits)
+static inline void set_pstate_bits(uint64_t bits)
{
- TCGv_i32 p = tcg_temp_new_i32();
+ TCGv_i64 p = tcg_temp_new_i64();
tcg_debug_assert(!(bits & CACHED_PSTATE_BITS));
- tcg_gen_ld_i32(p, tcg_env, offsetof(CPUARMState, pstate));
- tcg_gen_ori_i32(p, p, bits);
- tcg_gen_st_i32(p, tcg_env, offsetof(CPUARMState, pstate));
+ tcg_gen_ld_i64(p, tcg_env, offsetof(CPUARMState, pstate));
+ tcg_gen_ori_i64(p, p, bits);
+ tcg_gen_st_i64(p, tcg_env, offsetof(CPUARMState, pstate));
}
/* Clear bits within PSTATE. */
-static inline void clear_pstate_bits(uint32_t bits)
+static inline void clear_pstate_bits(uint64_t bits)
{
- TCGv_i32 p = tcg_temp_new_i32();
+ TCGv_i64 p = tcg_temp_new_i64();
tcg_debug_assert(!(bits & CACHED_PSTATE_BITS));
- tcg_gen_ld_i32(p, tcg_env, offsetof(CPUARMState, pstate));
- tcg_gen_andi_i32(p, p, ~bits);
- tcg_gen_st_i32(p, tcg_env, offsetof(CPUARMState, pstate));
+ tcg_gen_ld_i64(p, tcg_env, offsetof(CPUARMState, pstate));
+ tcg_gen_andi_i64(p, p, ~bits);
+ tcg_gen_st_i64(p, tcg_env, offsetof(CPUARMState, pstate));
}
/* If the singlestep state is Active-not-pending, advance to Active-pending. */
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index d9318c5325..ec63297165 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1208,7 +1208,7 @@ static void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags)
{
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
- uint32_t psr = pstate_read(env);
+ uint64_t psr = pstate_read(env);
int i, j;
int el = arm_current_el(env);
uint64_t hcr = arm_hcr_el2_eff(env);
@@ -1230,7 +1230,7 @@ static void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags)
} else {
ns_status = "";
}
- qemu_fprintf(f, "PSTATE=%08x %c%c%c%c %sEL%d%c",
+ qemu_fprintf(f, "PSTATE=%016" PRIx64 " %c%c%c%c %sEL%d%c",
psr,
psr & PSTATE_N ? 'N' : '-',
psr & PSTATE_Z ? 'Z' : '-',
@@ -1247,7 +1247,7 @@ static void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags)
(FIELD_EX64(env->svcr, SVCR, SM) ? 'S' : '-'));
}
if (cpu_isar_feature(aa64_bti, cpu)) {
- qemu_fprintf(f, " BTYPE=%d", (psr & PSTATE_BTYPE) >> 10);
+ qemu_fprintf(f, " BTYPE=%d", (int)(psr & PSTATE_BTYPE) >> 10);
}
qemu_fprintf(f, "%s%s%s",
(hcr & HCR_NV) ? " NV" : "",
diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
index 64ee9b3b56..3cef47281a 100644
--- a/target/arm/gdbstub64.c
+++ b/target/arm/gdbstub64.c
@@ -47,6 +47,7 @@ int aarch64_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
case 32:
return gdb_get_reg64(mem_buf, env->pc);
case 33:
+ /* pstate is now a 64-bit value; can we simply adjust the xml? */
return gdb_get_reg32(mem_buf, pstate_read(env));
}
/* Unknown register. */
diff --git a/target/arm/helper.c b/target/arm/helper.c
index f006ecabf3..e404ba0f71 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -9185,8 +9185,8 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
CPUARMState *env = &cpu->env;
unsigned int new_el = env->exception.target_el;
vaddr addr = env->cp15.vbar_el[new_el];
- unsigned int new_mode = aarch64_pstate_mode(new_el, true);
- unsigned int old_mode;
+ uint64_t new_mode = aarch64_pstate_mode(new_el, true);
+ uint64_t old_mode;
unsigned int cur_el = arm_current_el(env);
int rt;
@@ -9334,7 +9334,7 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
* If NV2 is disabled, change SPSR when NV,NV1 == 1,0 (I_ZJRNN)
* If NV2 is enabled, change SPSR when NV is 1 (I_DBTLM)
*/
- old_mode = deposit32(old_mode, 2, 2, 2);
+ old_mode = deposit64(old_mode, 2, 2, 2);
}
}
} else {
@@ -9347,7 +9347,7 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
}
env->banked_spsr[aarch64_banked_spsr_index(new_el)] = old_mode;
- qemu_log_mask(CPU_LOG_INT, "...with SPSR 0x%x\n", old_mode);
+ qemu_log_mask(CPU_LOG_INT, "...with SPSR 0x%" PRIx64 "\n", old_mode);
qemu_log_mask(CPU_LOG_INT, "...with ELR 0x%" PRIx64 "\n",
env->elr_el[new_el]);
@@ -9401,7 +9401,8 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
env->pc = addr;
- qemu_log_mask(CPU_LOG_INT, "...to EL%d PC 0x%" PRIx64 " PSTATE 0x%x\n",
+ qemu_log_mask(CPU_LOG_INT, "...to EL%d PC 0x%" PRIx64
+ " PSTATE 0x%" PRIx64 "\n",
new_el, env->pc, pstate_read(env));
}
diff --git a/target/arm/machine.c b/target/arm/machine.c
index 8dbeca2867..9b00c14b4a 100644
--- a/target/arm/machine.c
+++ b/target/arm/machine.c
@@ -836,6 +836,61 @@ static const VMStateInfo vmstate_cpsr = {
.put = put_cpsr,
};
+static int get_pstate64_1(QEMUFile *f, void *opaque, size_t size,
+ const VMStateField *field)
+{
+ ARMCPU *cpu = opaque;
+ CPUARMState *env = &cpu->env;
+ uint64_t val = qemu_get_be64(f);
+
+ env->aarch64 = ((val & PSTATE_nRW) == 0);
+ pstate_write(env, val);
+ return 0;
+}
+
+static int put_pstate64_1(QEMUFile *f, void *opaque, size_t size,
+ const VMStateField *field, JSONWriter *vmdesc)
+{
+ ARMCPU *cpu = opaque;
+ CPUARMState *env = &cpu->env;
+ uint64_t val = pstate_read(env);
+
+ qemu_put_be64(f, val);
+ return 0;
+}
+
+static const VMStateInfo vmstate_pstate64_1 = {
+ .name = "pstate64",
+ .get = get_pstate64_1,
+ .put = put_pstate64_1,
+};
+
+static bool pstate64_needed(void *opaque)
+{
+ ARMCPU *cpu = opaque;
+ CPUARMState *env = &cpu->env;
+
+ return is_a64(env) && pstate_read(env) > UINT32_MAX;
+}
+
+static const VMStateDescription vmstate_pstate64 = {
+ .name = "cpu/pstate64",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = pstate64_needed,
+ .fields = (const VMStateField[]) {
+ {
+ .name = "pstate64",
+ .version_id = 0,
+ .size = sizeof(uint64_t),
+ .info = &vmstate_pstate64_1,
+ .flags = VMS_SINGLE,
+ .offset = 0,
+ },
+ VMSTATE_END_OF_LIST()
+ },
+};
+
static int get_power(QEMUFile *f, void *opaque, size_t size,
const VMStateField *field)
{
@@ -1119,6 +1174,7 @@ const VMStateDescription vmstate_arm_cpu = {
&vmstate_serror,
&vmstate_irq_line_state,
&vmstate_wfxt_timer,
+ &vmstate_pstate64,
NULL
}
};
diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c
index 71c6c44ee8..f61adf1f80 100644
--- a/target/arm/tcg/helper-a64.c
+++ b/target/arm/tcg/helper-a64.c
@@ -639,7 +639,7 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
ARMCPU *cpu = env_archcpu(env);
int cur_el = arm_current_el(env);
unsigned int spsr_idx = aarch64_banked_spsr_index(cur_el);
- uint32_t spsr = env->banked_spsr[spsr_idx];
+ uint64_t spsr = env->banked_spsr[spsr_idx];
int new_el;
bool return_to_aa64 = (spsr & PSTATE_nRW) == 0;
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 48/82] target/arm: Add syndrome data for EC_GCS
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (46 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 47/82] target/arm: Expand pstate to 64 bits Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 19:35 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 49/82] target/arm: Implement EXLOCKException for ELR_ELx and SPSR_ELx Richard Henderson
` (33 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/syndrome.h | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h
index c48d3b8587..bff61f052c 100644
--- a/target/arm/syndrome.h
+++ b/target/arm/syndrome.h
@@ -63,6 +63,7 @@ enum arm_exception_class {
EC_MOP = 0x27,
EC_AA32_FPTRAP = 0x28,
EC_AA64_FPTRAP = 0x2c,
+ EC_GCS = 0x2d,
EC_SERROR = 0x2f,
EC_BREAKPOINT = 0x30,
EC_BREAKPOINT_SAME_EL = 0x31,
@@ -83,6 +84,23 @@ typedef enum {
SME_ET_InaccessibleZT0,
} SMEExceptionType;
+typedef enum {
+ GCS_ET_DataCheck,
+ GCS_ET_EXLOCK,
+ GCS_ET_GCSSTR_GCSSTTR,
+} GCSExceptionType;
+
+typedef enum {
+ GCS_IT_RET_nPauth = 0,
+ GCS_IT_GCSPOPM = 1,
+ GCS_IT_RET_PauthA = 2,
+ GCS_IT_RET_PauthB = 3,
+ GCS_IT_GCSSS1 = 4,
+ GCS_IT_GCSSS2 = 5,
+ GCS_IT_GCSPOPCX = 8,
+ GCS_IT_GCSPOPX = 9,
+} GCSInstructionType;
+
#define ARM_EL_EC_LENGTH 6
#define ARM_EL_EC_SHIFT 26
#define ARM_EL_IL_SHIFT 25
@@ -351,6 +369,23 @@ static inline uint32_t syn_pcalignment(void)
return (EC_PCALIGNMENT << ARM_EL_EC_SHIFT) | ARM_EL_IL;
}
+static inline uint32_t syn_gcs_data_check(GCSInstructionType it, int rn)
+{
+ return ((EC_GCS << ARM_EL_EC_SHIFT) | ARM_EL_IL |
+ (GCS_ET_DataCheck << 20) | (rn << 5) | it);
+}
+
+static inline uint32_t syn_gcs_exlock(void)
+{
+ return (EC_GCS << ARM_EL_EC_SHIFT) | ARM_EL_IL | (GCS_ET_EXLOCK << 20);
+}
+
+static inline uint32_t syn_gcs_gcsstr(int ra, int rn)
+{
+ return ((EC_GCS << ARM_EL_EC_SHIFT) | ARM_EL_IL |
+ (GCS_ET_GCSSTR_GCSSTTR << 20) | (ra << 10) | (rn << 5));
+}
+
static inline uint32_t syn_serror(uint32_t extra)
{
return (EC_SERROR << ARM_EL_EC_SHIFT) | ARM_EL_IL | extra;
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 49/82] target/arm: Implement EXLOCKException for ELR_ELx and SPSR_ELx
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (47 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 48/82] target/arm: Add syndrome data for EC_GCS Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 20:53 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 50/82] target/arm: Split {arm,core}_user_mem_index Richard Henderson
` (32 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
If PSTATE.EXLOCK is set, and the GCS EXLOCK enable bit is set,
and nested virt is in the appropriate state, then we need to
raise an EXLOCK exception.
Since PSTATE.EXLOCK cannot be set without GCS being present
and enabled, no explicit check for GCS is required.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpregs.h | 3 ++
target/arm/cpu.h | 1 +
target/arm/helper.c | 83 +++++++++++++++++++++++++++++++++++---
target/arm/tcg/op_helper.c | 4 ++
4 files changed, 85 insertions(+), 6 deletions(-)
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
index bc6adf5956..15894332b2 100644
--- a/target/arm/cpregs.h
+++ b/target/arm/cpregs.h
@@ -346,6 +346,9 @@ typedef enum CPAccessResult {
* specified target EL.
*/
CP_ACCESS_UNDEFINED = (2 << 2),
+
+ /* Access fails with EXLOCK, a GCS exception syndrome. */
+ CP_ACCESS_EXLOCK = (3 << 2),
} CPAccessResult;
/* Indexes into fgt_read[] */
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 7769c4ae3c..8eee722a9e 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1520,6 +1520,7 @@ void pmu_init(ARMCPU *cpu);
#define PSTATE_C (1U << 29)
#define PSTATE_Z (1U << 30)
#define PSTATE_N (1U << 31)
+#define PSTATE_EXLOCK (1ULL << 34)
#define PSTATE_NZCV (PSTATE_N | PSTATE_Z | PSTATE_C | PSTATE_V)
#define PSTATE_DAIF (PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F)
#define CACHED_PSTATE_BITS (PSTATE_NZCV | PSTATE_DAIF | PSTATE_BTYPE)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index e404ba0f71..2514a03c0e 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -3435,6 +3435,77 @@ static CPAccessResult access_nv1(CPUARMState *env, const ARMCPRegInfo *ri,
return CP_ACCESS_OK;
}
+static CPAccessResult access_exlock_el1(CPUARMState *env,
+ const ARMCPRegInfo *ri, bool isread)
+{
+ int el = arm_current_el(env);
+
+ if (el == 1) {
+ uint64_t hcr = arm_hcr_el2_eff(env);
+
+ /*
+ * EXLOCK check is disabled for NVx in 'x11'.
+ * Since we have to diagnose that, dispatch NV1 trap too.
+ */
+ if ((hcr & HCR_NV) && (hcr & HCR_NV1)) {
+ if (hcr & HCR_NV2) {
+ return CP_ACCESS_OK;
+ }
+ return CP_ACCESS_TRAP_EL2;
+ }
+ }
+
+ if (!isread &&
+ (env->pstate & PSTATE_EXLOCK) &&
+ (el_is_in_host(env, el) ? el == 2 : el == 1) &&
+ (env->cp15.gcscr_el[el] & GCSCR_EXLOCKEN)) {
+ return CP_ACCESS_EXLOCK;
+ }
+ return CP_ACCESS_OK;
+}
+
+static CPAccessResult access_exlock_el2(CPUARMState *env,
+ const ARMCPRegInfo *ri, bool isread)
+{
+ int el = arm_current_el(env);
+
+ if (el == 3) {
+ return CP_ACCESS_OK;
+ }
+ if (el == 1) {
+ uint64_t hcr = arm_hcr_el2_eff(env);
+
+ /*
+ * EXLOCK check is disabled for NVx in 'xx1'.
+ * Since we have to diagnose that, dispatch NV1 trap too.
+ */
+ if (hcr & HCR_NV) {
+ if (hcr & HCR_NV2) {
+ return CP_ACCESS_OK;
+ }
+ return CP_ACCESS_TRAP_EL2;
+ }
+ }
+
+ if (!isread &&
+ (env->pstate & PSTATE_EXLOCK) &&
+ (env->cp15.gcscr_el[el] & GCSCR_EXLOCKEN)) {
+ return CP_ACCESS_EXLOCK;
+ }
+ return CP_ACCESS_OK;
+}
+
+static CPAccessResult access_exlock_el3(CPUARMState *env,
+ const ARMCPRegInfo *ri, bool isread)
+{
+ if (!isread &&
+ (env->pstate & PSTATE_EXLOCK) &&
+ (env->cp15.gcscr_el[3] & GCSCR_EXLOCKEN)) {
+ return CP_ACCESS_EXLOCK;
+ }
+ return CP_ACCESS_OK;
+}
+
#ifdef CONFIG_USER_ONLY
/*
* `IC IVAU` is handled to improve compatibility with JITs that dual-map their
@@ -3606,13 +3677,13 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
{ .name = "ELR_EL1", .state = ARM_CP_STATE_AA64,
.type = ARM_CP_ALIAS,
.opc0 = 3, .opc1 = 0, .crn = 4, .crm = 0, .opc2 = 1,
- .access = PL1_RW, .accessfn = access_nv1,
+ .access = PL1_RW, .accessfn = access_exlock_el1,
.nv2_redirect_offset = 0x230 | NV2_REDIR_NV1,
.fieldoffset = offsetof(CPUARMState, elr_el[1]) },
{ .name = "SPSR_EL1", .state = ARM_CP_STATE_AA64,
.type = ARM_CP_ALIAS,
.opc0 = 3, .opc1 = 0, .crn = 4, .crm = 0, .opc2 = 0,
- .access = PL1_RW, .accessfn = access_nv1,
+ .access = PL1_RW, .accessfn = access_exlock_el1,
.nv2_redirect_offset = 0x160 | NV2_REDIR_NV1,
.fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_SVC]) },
/*
@@ -4083,7 +4154,7 @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
{ .name = "ELR_EL2", .state = ARM_CP_STATE_AA64,
.type = ARM_CP_ALIAS | ARM_CP_NV2_REDIRECT,
.opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 1,
- .access = PL2_RW,
+ .access = PL2_RW, .accessfn = access_exlock_el2,
.fieldoffset = offsetof(CPUARMState, elr_el[2]) },
{ .name = "ESR_EL2", .state = ARM_CP_STATE_BOTH,
.type = ARM_CP_NV2_REDIRECT,
@@ -4101,7 +4172,7 @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
{ .name = "SPSR_EL2", .state = ARM_CP_STATE_AA64,
.type = ARM_CP_ALIAS | ARM_CP_NV2_REDIRECT,
.opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 0,
- .access = PL2_RW,
+ .access = PL2_RW, .accessfn = access_exlock_el2,
.fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_HYP]) },
{ .name = "VBAR_EL2", .state = ARM_CP_STATE_BOTH,
.opc0 = 3, .opc1 = 4, .crn = 12, .crm = 0, .opc2 = 0,
@@ -4383,7 +4454,7 @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
{ .name = "ELR_EL3", .state = ARM_CP_STATE_AA64,
.type = ARM_CP_ALIAS,
.opc0 = 3, .opc1 = 6, .crn = 4, .crm = 0, .opc2 = 1,
- .access = PL3_RW,
+ .access = PL3_RW, .accessfn = access_exlock_el3,
.fieldoffset = offsetof(CPUARMState, elr_el[3]) },
{ .name = "ESR_EL3", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 6, .crn = 5, .crm = 2, .opc2 = 0,
@@ -4394,7 +4465,7 @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
{ .name = "SPSR_EL3", .state = ARM_CP_STATE_AA64,
.type = ARM_CP_ALIAS,
.opc0 = 3, .opc1 = 6, .crn = 4, .crm = 0, .opc2 = 0,
- .access = PL3_RW,
+ .access = PL3_RW, .accessfn = access_exlock_el3,
.fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_MON]) },
{ .name = "VBAR_EL3", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 6, .crn = 12, .crm = 0, .opc2 = 0,
diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c
index 46a3b911ec..56e117c01e 100644
--- a/target/arm/tcg/op_helper.c
+++ b/target/arm/tcg/op_helper.c
@@ -887,6 +887,10 @@ const void *HELPER(access_check_cp_reg)(CPUARMState *env, uint32_t key,
}
syndrome = syn_uncategorized();
break;
+ case CP_ACCESS_EXLOCK:
+ /* CP_ACCESS_EXLOCK is always directed to the current EL */
+ syndrome = syn_gcs_exlock();
+ break;
default:
g_assert_not_reached();
}
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 50/82] target/arm: Split {arm,core}_user_mem_index
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (48 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 49/82] target/arm: Implement EXLOCKException for ELR_ELx and SPSR_ELx Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:06 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 51/82] target/arm: Introduce delay_exception{_el} Richard Henderson
` (31 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Separate current to unpriv and arm to core mmu conversions
into two separate functions.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/tcg/translate-a64.c | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 34d22cac8a..eaeafdf138 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -93,7 +93,7 @@ void a64_translate_init(void)
}
/*
- * Return the core mmu_idx to use for A64 load/store insns which
+ * Return the full arm mmu_idx to use for A64 load/store insns which
* have a "unprivileged load/store" variant. Those insns access
* EL0 if executed from an EL which has control over EL0 (usually
* EL1) but behave like normal loads and stores if executed from
@@ -103,7 +103,7 @@ void a64_translate_init(void)
* normal encoding (in which case we will return the same
* thing as get_mem_index().
*/
-static int get_a64_user_mem_index(DisasContext *s, bool unpriv)
+static ARMMMUIdx arm_user_mem_index(DisasContext *s, bool unpriv)
{
/*
* If AccType_UNPRIV is not used, the insn uses AccType_NORMAL,
@@ -130,7 +130,13 @@ static int get_a64_user_mem_index(DisasContext *s, bool unpriv)
g_assert_not_reached();
}
}
- return arm_to_core_mmu_idx(useridx);
+ return useridx;
+}
+
+/* Return the core mmu_idx per above. */
+static int core_user_mem_index(DisasContext *s, bool unpriv)
+{
+ return arm_to_core_mmu_idx(arm_user_mem_index(s, unpriv));
}
static void set_btype_raw(int val)
@@ -3539,7 +3545,7 @@ static void op_addr_ldst_imm_pre(DisasContext *s, arg_ldst_imm *a,
if (!a->p) {
tcg_gen_addi_i64(*dirty_addr, *dirty_addr, offset);
}
- memidx = get_a64_user_mem_index(s, a->unpriv);
+ memidx = core_user_mem_index(s, a->unpriv);
*clean_addr = gen_mte_check1_mmuidx(s, *dirty_addr, is_store,
a->w || a->rn != 31,
mop, a->unpriv, memidx);
@@ -3560,7 +3566,7 @@ static bool trans_STR_i(DisasContext *s, arg_ldst_imm *a)
{
bool iss_sf, iss_valid = !a->w;
TCGv_i64 clean_addr, dirty_addr, tcg_rt;
- int memidx = get_a64_user_mem_index(s, a->unpriv);
+ int memidx = core_user_mem_index(s, a->unpriv);
MemOp mop = finalize_memop(s, a->sz + a->sign * MO_SIGN);
op_addr_ldst_imm_pre(s, a, &clean_addr, &dirty_addr, a->imm, true, mop);
@@ -3578,7 +3584,7 @@ static bool trans_LDR_i(DisasContext *s, arg_ldst_imm *a)
{
bool iss_sf, iss_valid = !a->w;
TCGv_i64 clean_addr, dirty_addr, tcg_rt;
- int memidx = get_a64_user_mem_index(s, a->unpriv);
+ int memidx = core_user_mem_index(s, a->unpriv);
MemOp mop = finalize_memop(s, a->sz + a->sign * MO_SIGN);
op_addr_ldst_imm_pre(s, a, &clean_addr, &dirty_addr, a->imm, false, mop);
@@ -4427,7 +4433,7 @@ static bool do_SET(DisasContext *s, arg_set *a, bool is_epilogue,
return false;
}
- memidx = get_a64_user_mem_index(s, a->unpriv);
+ memidx = core_user_mem_index(s, a->unpriv);
/*
* We pass option_a == true, matching our implementation;
@@ -4481,8 +4487,8 @@ static bool do_CPY(DisasContext *s, arg_cpy *a, bool is_epilogue, CpyFn fn)
return false;
}
- rmemidx = get_a64_user_mem_index(s, runpriv);
- wmemidx = get_a64_user_mem_index(s, wunpriv);
+ rmemidx = core_user_mem_index(s, runpriv);
+ wmemidx = core_user_mem_index(s, wunpriv);
/*
* We pass option_a == true, matching our implementation;
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 51/82] target/arm: Introduce delay_exception{_el}
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (49 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 50/82] target/arm: Split {arm,core}_user_mem_index Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:09 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 52/82] target/arm: Emit HSTR trap exception out of line Richard Henderson
` (30 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Add infrastructure to raise an exception out of line.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/tcg/translate.h | 20 +++++++++++++
target/arm/tcg/translate-a64.c | 2 ++
target/arm/tcg/translate.c | 53 ++++++++++++++++++++++++++++++++++
3 files changed, 75 insertions(+)
diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h
index 1479f5bf74..a40cbd4479 100644
--- a/target/arm/tcg/translate.h
+++ b/target/arm/tcg/translate.h
@@ -21,9 +21,25 @@ typedef struct DisasLabel {
target_ulong pc_save;
} DisasLabel;
+/*
+ * Emit an exception call out of line.
+ */
+typedef struct DisasDelayException {
+ struct DisasDelayException *next;
+ TCGLabel *lab;
+ target_long pc_curr;
+ target_long pc_save;
+ int condexec_mask;
+ int condexec_cond;
+ uint32_t excp;
+ uint32_t syn;
+ uint32_t target_el;
+} DisasDelayException;
+
typedef struct DisasContext {
DisasContextBase base;
const ARMISARegisters *isar;
+ DisasDelayException *delay_excp_list;
/* The address of the current instruction being translated. */
target_ulong pc_curr;
@@ -365,6 +381,10 @@ void gen_exception_insn_el(DisasContext *s, target_long pc_diff, int excp,
uint32_t syn, uint32_t target_el);
void gen_exception_insn(DisasContext *s, target_long pc_diff,
int excp, uint32_t syn);
+TCGLabel *delay_exception_el(DisasContext *s, int excp,
+ uint32_t syn, uint32_t target_el);
+TCGLabel *delay_exception(DisasContext *s, int excp, uint32_t syn);
+void emit_delayed_exceptions(DisasContext *s);
/* Return state of Alternate Half-precision flag, caller frees result */
static inline TCGv_i32 get_ahp_flag(void)
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index eaeafdf138..d803c10ac7 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -10411,6 +10411,8 @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
break;
}
}
+
+ emit_delayed_exceptions(dc);
}
const TranslatorOps aarch64_translator_ops = {
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
index f7d6d8ce19..c4dd3a747c 100644
--- a/target/arm/tcg/translate.c
+++ b/target/arm/tcg/translate.c
@@ -1090,6 +1090,57 @@ void gen_exception_insn(DisasContext *s, target_long pc_diff,
s->base.is_jmp = DISAS_NORETURN;
}
+TCGLabel *delay_exception_el(DisasContext *s, int excp,
+ uint32_t syn, uint32_t target_el)
+{
+ /* Use tcg_malloc for automatic release on longjmp out of translation. */
+ DisasDelayException *e = tcg_malloc(sizeof(DisasDelayException));
+
+ memset(e, 0, sizeof(*e));
+
+ /* Save enough of the current state to satisfy gen_exception_insn. */
+ e->pc_curr = s->pc_curr;
+ e->pc_save = s->pc_save;
+ if (!s->aarch64) {
+ e->condexec_cond = s->condexec_cond;
+ e->condexec_mask = s->condexec_mask;
+ }
+
+ e->excp = excp;
+ e->syn = syn;
+ e->target_el = target_el;
+
+ e->next = s->delay_excp_list;
+ s->delay_excp_list = e;
+
+ e->lab = gen_new_label();
+ return e->lab;
+}
+
+TCGLabel *delay_exception(DisasContext *s, int excp, uint32_t syn)
+{
+ return delay_exception_el(s, excp, syn, 0);
+}
+
+void emit_delayed_exceptions(DisasContext *s)
+{
+ for (DisasDelayException *e = s->delay_excp_list; e ; e = e->next) {
+ gen_set_label(e->lab);
+
+ /* Restore the insn state to satisfy gen_exception_insn. */
+ s->pc_curr = e->pc_curr;
+ s->pc_save = e->pc_save;
+ s->condexec_cond = e->condexec_cond;
+ s->condexec_mask = e->condexec_mask;
+
+ if (e->target_el) {
+ gen_exception_insn_el(s, 0, e->excp, e->syn, e->target_el);
+ } else {
+ gen_exception_insn(s, 0, e->excp, e->syn);
+ }
+ }
+}
+
static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
{
gen_set_condexec(s);
@@ -8107,6 +8158,8 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
gen_goto_tb(dc, 1, curr_insn_len(dc));
}
}
+
+ emit_delayed_exceptions(dc);
}
static const TranslatorOps arm_translator_ops = {
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 52/82] target/arm: Emit HSTR trap exception out of line
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (50 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 51/82] target/arm: Introduce delay_exception{_el} Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:10 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 53/82] target/arm: Emit v7m LTPSIZE " Richard Henderson
` (29 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Use delay_exception_el to move the exception out of line.
Use TCG_COND_TSTNE instead of separate AND+NE.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/tcg/translate.c | 18 ++++--------------
1 file changed, 4 insertions(+), 14 deletions(-)
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
index c4dd3a747c..f6fdfaa551 100644
--- a/target/arm/tcg/translate.c
+++ b/target/arm/tcg/translate.c
@@ -3033,21 +3033,11 @@ static void do_coproc_insn(DisasContext *s, int cpnum, int is64,
if (maskbit != 4 && maskbit != 14) {
/* T4 and T14 are RES0 so never cause traps */
- TCGv_i32 t;
- DisasLabel over = gen_disas_label(s);
+ TCGLabel *fail = delay_exception_el(s, EXCP_UDEF, syndrome, 2);
+ TCGv_i32 t =
+ load_cpu_offset(offsetoflow32(CPUARMState, cp15.hstr_el2));
- t = load_cpu_offset(offsetoflow32(CPUARMState, cp15.hstr_el2));
- tcg_gen_andi_i32(t, t, 1u << maskbit);
- tcg_gen_brcondi_i32(TCG_COND_EQ, t, 0, over.label);
-
- gen_exception_insn_el(s, 0, EXCP_UDEF, syndrome, 2);
- /*
- * gen_exception_insn() will set is_jmp to DISAS_NORETURN,
- * but since we're conditionally branching over it, we want
- * to assume continue-to-next-instruction.
- */
- s->base.is_jmp = DISAS_NEXT;
- set_disas_label(s, over);
+ tcg_gen_brcondi_i32(TCG_COND_TSTNE, t, 1u << maskbit, fail);
}
}
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 53/82] target/arm: Emit v7m LTPSIZE exception out of line
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (51 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 52/82] target/arm: Emit HSTR trap exception out of line Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:10 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 54/82] target/arm: Implement GCSSTR, GCSSTTR Richard Henderson
` (28 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/tcg/translate.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
index f6fdfaa551..e787acfc66 100644
--- a/target/arm/tcg/translate.c
+++ b/target/arm/tcg/translate.c
@@ -6885,11 +6885,10 @@ static bool trans_LE(DisasContext *s, arg_LE *a)
if (!a->tp && dc_isar_feature(aa32_mve, s) && fpu_active) {
/* Need to do a runtime check for LTPSIZE != 4 */
- DisasLabel skipexc = gen_disas_label(s);
+ TCGLabel *fail = delay_exception(s, EXCP_INVSTATE, syn_uncategorized());
+
tmp = load_cpu_field(v7m.ltpsize);
- tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 4, skipexc.label);
- gen_exception_insn(s, 0, EXCP_INVSTATE, syn_uncategorized());
- set_disas_label(s, skipexc);
+ tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 4, fail);
}
if (a->f) {
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 54/82] target/arm: Implement GCSSTR, GCSSTTR
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (52 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 53/82] target/arm: Emit v7m LTPSIZE " Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:25 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 55/82] target/arm: Implement GCSB Richard Henderson
` (27 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Note that CreateAccDescGCS() does not enable tagchecked,
and Data Aborts from GCS instructions do not set iss.isv.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/tcg/translate-a64.c | 42 ++++++++++++++++++++++++++++++++++
target/arm/tcg/a64.decode | 3 +++
2 files changed, 45 insertions(+)
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index d803c10ac7..e0548f7180 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -139,6 +139,12 @@ static int core_user_mem_index(DisasContext *s, bool unpriv)
return arm_to_core_mmu_idx(arm_user_mem_index(s, unpriv));
}
+/* For a given translation regime, return the core mmu_idx for gcs access. */
+static int core_gcs_mem_index(ARMMMUIdx armidx)
+{
+ return arm_to_core_mmu_idx(regime_to_gcs(armidx));
+}
+
static void set_btype_raw(int val)
{
tcg_gen_st_i32(tcg_constant_i32(val), tcg_env,
@@ -3902,6 +3908,42 @@ static bool trans_STLR_i(DisasContext *s, arg_ldapr_stlr_i *a)
return true;
}
+static bool trans_GCSSTR(DisasContext *s, arg_GCSSTR *a)
+{
+ ARMMMUIdx armidx;
+
+ if (!dc_isar_feature(aa64_gcs, s)) {
+ return false;
+ }
+
+ /*
+ * The pseudocode for GCSSTTR is
+ *
+ * effective_el = AArch64.IsUnprivAccessPriv() ? PSTATE.EL : EL0;
+ * if (effective_el == PSTATE.EL) CheckGCSSTREnabled();
+ *
+ * We have cached the result of IsUnprivAccessPriv in DisasContext,
+ * but since we need the result of arm_user_mem_index anyway, use
+ * the mmu_idx test as a proxy for the effective_el test.
+ */
+ armidx = arm_user_mem_index(s, a->unpriv);
+ if (armidx == s->mmu_idx && s->gcsstr_el != 0) {
+ gen_exception_insn_el(s, 0, EXCP_UDEF,
+ syn_gcs_gcsstr(a->rn, a->rt),
+ s->gcsstr_el);
+ return true;
+ }
+
+ if (a->rn == 31) {
+ gen_check_sp_alignment(s);
+ }
+ tcg_gen_qemu_st_i64(cpu_reg(s, a->rt),
+ clean_data_tbi(s, cpu_reg_sp(s, a->rn)),
+ core_gcs_mem_index(armidx),
+ finalize_memop(s, MO_64 | MO_ALIGN));
+ return true;
+}
+
static bool trans_LD_mult(DisasContext *s, arg_ldst_mult *a)
{
TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
index 4315ed8dab..d034d96b37 100644
--- a/target/arm/tcg/a64.decode
+++ b/target/arm/tcg/a64.decode
@@ -554,6 +554,9 @@ LDAPR_i 10 011001 10 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext
LDAPR_i 00 011001 11 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=1 sz=0
LDAPR_i 01 011001 11 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=1 sz=1
+# GCSSTR, GCSSTTR
+GCSSTR 11011001 000 11111 000 unpriv:1 11 rn:5 rt:5
+
# Load/store multiple structures
# The 4-bit opcode in [15:12] encodes repeat count and structure elements
&ldst_mult rm rn rt sz q p rpt selem
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 55/82] target/arm: Implement GCSB
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (53 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 54/82] target/arm: Implement GCSSTR, GCSSTTR Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:27 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 56/82] target/arm: Implement GCSPUSHM Richard Henderson
` (26 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/tcg/translate-a64.c | 8 ++++++++
target/arm/tcg/a64.decode | 1 +
2 files changed, 9 insertions(+)
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index e0548f7180..45ff7bb0b2 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -2072,6 +2072,14 @@ static bool trans_ESB(DisasContext *s, arg_ESB *a)
return true;
}
+static bool trans_GCSB(DisasContext *s, arg_GCSB *a)
+{
+ if (dc_isar_feature(aa64_gcs, s)) {
+ tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL);
+ }
+ return true;
+}
+
static bool trans_PACIAZ(DisasContext *s, arg_PACIAZ *a)
{
if (s->pauth_active) {
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
index d034d96b37..e8b0ef07eb 100644
--- a/target/arm/tcg/a64.decode
+++ b/target/arm/tcg/a64.decode
@@ -238,6 +238,7 @@ ERETA 1101011 0100 11111 00001 m:1 11111 11111 &reta # ERETAA, ERETAB
AUTIA1716 1101 0101 0000 0011 0010 0001 100 11111
AUTIB1716 1101 0101 0000 0011 0010 0001 110 11111
ESB 1101 0101 0000 0011 0010 0010 000 11111
+ GCSB 1101 0101 0000 0011 0010 0010 011 11111
PACIAZ 1101 0101 0000 0011 0010 0011 000 11111
PACIASP 1101 0101 0000 0011 0010 0011 001 11111
PACIBZ 1101 0101 0000 0011 0010 0011 010 11111
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 56/82] target/arm: Implement GCSPUSHM
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (54 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 55/82] target/arm: Implement GCSB Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:33 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 57/82] target/arm: Implement GCSPOPM Richard Henderson
` (25 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpregs.h | 3 +++
target/arm/cpregs-gcs.c | 16 ++++++++++++++++
target/arm/tcg/translate-a64.c | 18 ++++++++++++++++++
3 files changed, 37 insertions(+)
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
index 15894332b2..93358e6123 100644
--- a/target/arm/cpregs.h
+++ b/target/arm/cpregs.h
@@ -46,6 +46,8 @@ enum {
ARM_CP_DC_ZVA = 0x0005,
ARM_CP_DC_GVA = 0x0006,
ARM_CP_DC_GZVA = 0x0007,
+ /* Special: gcs instructions */
+ ARM_CP_GCSPUSHM = 0x0008,
/* Flag: reads produce resetvalue; writes ignored. */
ARM_CP_CONST = 1 << 4,
@@ -861,6 +863,7 @@ typedef enum FGTBit {
DO_BIT(HFGITR, DVPRCTX),
DO_BIT(HFGITR, CPPRCTX),
DO_BIT(HFGITR, DCCVAC),
+ DO_REV_BIT(HFGITR, NGCSPUSHM_EL1),
DO_BIT(HFGITR, ATS1E1A),
} FGTBit;
diff --git a/target/arm/cpregs-gcs.c b/target/arm/cpregs-gcs.c
index 9c06100d2b..38987372c9 100644
--- a/target/arm/cpregs-gcs.c
+++ b/target/arm/cpregs-gcs.c
@@ -33,6 +33,17 @@ static CPAccessResult access_gcs_el0(CPUARMState *env, const ARMCPRegInfo *ri,
return access_gcs(env, ri, isread);
}
+static CPAccessResult access_gcspushm(CPUARMState *env, const ARMCPRegInfo *ri,
+ bool isread)
+{
+ int el = arm_current_el(env);
+
+ if (!(env->cp15.gcscr_el[el] & GCSCR_PUSHMEN)) {
+ return CP_ACCESS_TRAP_BIT | (el ? el : 1);
+ }
+ return CP_ACCESS_OK;
+}
+
static const ARMCPRegInfo gcs_reginfo[] = {
{ .name = "GCSCRE0_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 2, .crm = 5, .opc2 = 2,
@@ -69,6 +80,11 @@ static const ARMCPRegInfo gcs_reginfo[] = {
.opc0 = 3, .opc1 = 6, .crn = 2, .crm = 5, .opc2 = 1,
.access = PL3_RW,
.fieldoffset = offsetof(CPUARMState, cp15.gcspr_el[2]) },
+
+ { .name = "GCSPUSHM", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 7, .opc2 = 0,
+ .access = PL0_W, .accessfn = access_gcspushm,
+ .fgt = FGT_NGCSPUSHM_EL1, .type = ARM_CP_GCSPUSHM },
};
void define_gcs_cpregs(ARMCPU *cpu)
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 45ff7bb0b2..a5810be2f7 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -420,6 +420,19 @@ static MemOp check_ordered_align(DisasContext *s, int rn, int imm,
return finalize_memop(s, mop);
}
+static void gen_add_gcs_record(DisasContext *s, TCGv_i64 value)
+{
+ TCGv_i64 addr = tcg_temp_new_i64();
+ int sp_off = offsetof(CPUARMState, cp15.gcspr_el[s->current_el]);
+ int mmuidx = core_gcs_mem_index(s->mmu_idx);
+ MemOp mop = finalize_memop(s, MO_64 | MO_ALIGN);
+
+ tcg_gen_ld_i64(addr, tcg_env, sp_off);
+ tcg_gen_addi_i64(addr, addr, -8);
+ tcg_gen_qemu_st_i64(value, clean_data_tbi(s, addr), mmuidx, mop);
+ tcg_gen_st_i64(addr, tcg_env, sp_off);
+}
+
typedef struct DisasCompare64 {
TCGCond cond;
TCGv_i64 value;
@@ -2765,6 +2778,11 @@ static void handle_sys(DisasContext *s, bool isread,
}
}
return;
+ case ARM_CP_GCSPUSHM:
+ if (s->gcs_en) {
+ gen_add_gcs_record(s, cpu_reg(s, rt));
+ }
+ return;
default:
g_assert_not_reached();
}
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 57/82] target/arm: Implement GCSPOPM
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (55 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 56/82] target/arm: Implement GCSPUSHM Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:34 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 58/82] target/arm: Implement GCSPUSHX Richard Henderson
` (24 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpregs.h | 1 +
target/arm/cpregs-gcs.c | 3 +++
target/arm/tcg/translate-a64.c | 27 +++++++++++++++++++++++++++
3 files changed, 31 insertions(+)
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
index 93358e6123..9b19520346 100644
--- a/target/arm/cpregs.h
+++ b/target/arm/cpregs.h
@@ -48,6 +48,7 @@ enum {
ARM_CP_DC_GZVA = 0x0007,
/* Special: gcs instructions */
ARM_CP_GCSPUSHM = 0x0008,
+ ARM_CP_GCSPOPM = 0x0009,
/* Flag: reads produce resetvalue; writes ignored. */
ARM_CP_CONST = 1 << 4,
diff --git a/target/arm/cpregs-gcs.c b/target/arm/cpregs-gcs.c
index 38987372c9..74a1697840 100644
--- a/target/arm/cpregs-gcs.c
+++ b/target/arm/cpregs-gcs.c
@@ -85,6 +85,9 @@ static const ARMCPRegInfo gcs_reginfo[] = {
.opc0 = 1, .opc1 = 3, .crn = 7, .crm = 7, .opc2 = 0,
.access = PL0_W, .accessfn = access_gcspushm,
.fgt = FGT_NGCSPUSHM_EL1, .type = ARM_CP_GCSPUSHM },
+ { .name = "GCSPOPM", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 7, .opc2 = 1,
+ .access = PL0_R, .type = ARM_CP_GCSPOPM },
};
void define_gcs_cpregs(ARMCPU *cpu)
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index a5810be2f7..0279111cd2 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -2502,6 +2502,27 @@ static void gen_sysreg_undef(DisasContext *s, bool isread,
gen_exception_insn(s, 0, EXCP_UDEF, syndrome);
}
+static void gen_gcspopm(DisasContext *s, int rt)
+{
+ int sp_off = offsetof(CPUARMState, cp15.gcspr_el[s->current_el]);
+ int mmuidx = core_gcs_mem_index(s->mmu_idx);
+ MemOp mop = finalize_memop(s, MO_64 | MO_ALIGN);
+ TCGv_i64 addr = tcg_temp_new_i64();
+ TCGv_i64 value = tcg_temp_new_i64();
+ TCGLabel *fail_label =
+ delay_exception(s, EXCP_UDEF, syn_gcs_data_check(GCS_IT_GCSPOPM, rt));
+
+ /* The value at top-of-stack must have low 2 bits clear. */
+ tcg_gen_ld_i64(addr, tcg_env, sp_off);
+ tcg_gen_qemu_ld_i64(value, clean_data_tbi(s, addr), mmuidx, mop);
+ tcg_gen_brcondi_i64(TCG_COND_TSTNE, value, 3, fail_label);
+
+ /* Complete the pop and return the value. */
+ tcg_gen_addi_i64(addr, addr, 8);
+ tcg_gen_st_i64(addr, tcg_env, sp_off);
+ tcg_gen_mov_i64(cpu_reg(s, rt), value);
+}
+
/* MRS - move from system register
* MSR (register) - move to system register
* SYS
@@ -2783,6 +2804,12 @@ static void handle_sys(DisasContext *s, bool isread,
gen_add_gcs_record(s, cpu_reg(s, rt));
}
return;
+ case ARM_CP_GCSPOPM:
+ /* Note that X[rt] is unchanged if !GCSEnabled. */
+ if (s->gcs_en) {
+ gen_gcspopm(s, rt);
+ }
+ return;
default:
g_assert_not_reached();
}
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 58/82] target/arm: Implement GCSPUSHX
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (56 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 57/82] target/arm: Implement GCSPOPM Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:36 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 59/82] target/arm: Implement GCSPOPX Richard Henderson
` (23 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpregs.h | 2 ++
target/arm/cpregs-gcs.c | 17 +++++++++++++++
target/arm/tcg/translate-a64.c | 40 ++++++++++++++++++++++++++++++++++
3 files changed, 59 insertions(+)
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
index 9b19520346..3d76afd20b 100644
--- a/target/arm/cpregs.h
+++ b/target/arm/cpregs.h
@@ -49,6 +49,7 @@ enum {
/* Special: gcs instructions */
ARM_CP_GCSPUSHM = 0x0008,
ARM_CP_GCSPOPM = 0x0009,
+ ARM_CP_GCSPUSHX = 0x000a,
/* Flag: reads produce resetvalue; writes ignored. */
ARM_CP_CONST = 1 << 4,
@@ -865,6 +866,7 @@ typedef enum FGTBit {
DO_BIT(HFGITR, CPPRCTX),
DO_BIT(HFGITR, DCCVAC),
DO_REV_BIT(HFGITR, NGCSPUSHM_EL1),
+ DO_REV_BIT(HFGITR, NGCSEPP),
DO_BIT(HFGITR, ATS1E1A),
} FGTBit;
diff --git a/target/arm/cpregs-gcs.c b/target/arm/cpregs-gcs.c
index 74a1697840..6f25543426 100644
--- a/target/arm/cpregs-gcs.c
+++ b/target/arm/cpregs-gcs.c
@@ -44,6 +44,19 @@ static CPAccessResult access_gcspushm(CPUARMState *env, const ARMCPRegInfo *ri,
return CP_ACCESS_OK;
}
+static CPAccessResult access_gcspushx(CPUARMState *env, const ARMCPRegInfo *ri,
+ bool isread)
+{
+ /* Trap if lock taken, and enabled. */
+ if (!(env->pstate & PSTATE_EXLOCK)) {
+ int el = arm_current_el(env);
+ if (env->cp15.gcscr_el[el] & GCSCR_EXLOCKEN) {
+ return CP_ACCESS_EXLOCK;
+ }
+ }
+ return CP_ACCESS_OK;
+}
+
static const ARMCPRegInfo gcs_reginfo[] = {
{ .name = "GCSCRE0_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 2, .crm = 5, .opc2 = 2,
@@ -88,6 +101,10 @@ static const ARMCPRegInfo gcs_reginfo[] = {
{ .name = "GCSPOPM", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 3, .crn = 7, .crm = 7, .opc2 = 1,
.access = PL0_R, .type = ARM_CP_GCSPOPM },
+ { .name = "GCSPUSHX", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 7, .opc2 = 4,
+ .access = PL1_W, .accessfn = access_gcspushx, .fgt = FGT_NGCSEPP,
+ .type = ARM_CP_GCSPUSHX },
};
void define_gcs_cpregs(ARMCPU *cpu)
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 0279111cd2..732d65f54e 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -2523,6 +2523,38 @@ static void gen_gcspopm(DisasContext *s, int rt)
tcg_gen_mov_i64(cpu_reg(s, rt), value);
}
+static void gen_gcspushx(DisasContext *s)
+{
+ int sp_off = offsetof(CPUARMState, cp15.gcspr_el[s->current_el]);
+ int spsr_idx = aarch64_banked_spsr_index(s->current_el);
+ int spsr_off = offsetof(CPUARMState, banked_spsr[spsr_idx]);
+ int elr_off = offsetof(CPUARMState, elr_el[s->current_el]);
+ int mmuidx = core_gcs_mem_index(s->mmu_idx);
+ MemOp mop = finalize_memop(s, MO_64 | MO_ALIGN);
+ TCGv_i64 addr = tcg_temp_new_i64();
+ TCGv_i64 tmp = tcg_temp_new_i64();
+
+ tcg_gen_ld_i64(addr, tcg_env, sp_off);
+
+ tcg_gen_addi_i64(addr, addr, -8);
+ tcg_gen_qemu_st_i64(cpu_reg(s, 30), addr, mmuidx, mop);
+
+ tcg_gen_ld_i64(tmp, tcg_env, spsr_off);
+ tcg_gen_addi_i64(addr, addr, -8);
+ tcg_gen_qemu_st_i64(tmp, addr, mmuidx, mop);
+
+ tcg_gen_ld_i64(tmp, tcg_env, elr_off);
+ tcg_gen_addi_i64(addr, addr, -8);
+ tcg_gen_qemu_st_i64(tmp, addr, mmuidx, mop);
+
+ tcg_gen_addi_i64(addr, addr, -8);
+ tcg_gen_qemu_st_i64(tcg_constant_i64(0b1001), addr, mmuidx, mop);
+
+ tcg_gen_st_i64(addr, tcg_env, sp_off);
+
+ clear_pstate_bits(PSTATE_EXLOCK);
+}
+
/* MRS - move from system register
* MSR (register) - move to system register
* SYS
@@ -2810,6 +2842,14 @@ static void handle_sys(DisasContext *s, bool isread,
gen_gcspopm(s, rt);
}
return;
+ case ARM_CP_GCSPUSHX:
+ /* Choose the CONSTRAINED UNPREDICTABLE for UNDEF. */
+ if (rt != 31) {
+ unallocated_encoding(s);
+ } else if (s->gcs_en) {
+ gen_gcspushx(s);
+ }
+ return;
default:
g_assert_not_reached();
}
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 59/82] target/arm: Implement GCSPOPX
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (57 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 58/82] target/arm: Implement GCSPUSHX Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:37 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 60/82] target/arm: Implement GCSPOPCX Richard Henderson
` (22 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpregs.h | 1 +
target/arm/cpregs-gcs.c | 3 +++
target/arm/tcg/translate-a64.c | 37 ++++++++++++++++++++++++++++++++++
3 files changed, 41 insertions(+)
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
index 3d76afd20b..084ea00e51 100644
--- a/target/arm/cpregs.h
+++ b/target/arm/cpregs.h
@@ -50,6 +50,7 @@ enum {
ARM_CP_GCSPUSHM = 0x0008,
ARM_CP_GCSPOPM = 0x0009,
ARM_CP_GCSPUSHX = 0x000a,
+ ARM_CP_GCSPOPX = 0x000b,
/* Flag: reads produce resetvalue; writes ignored. */
ARM_CP_CONST = 1 << 4,
diff --git a/target/arm/cpregs-gcs.c b/target/arm/cpregs-gcs.c
index 6f25543426..2bdd41c796 100644
--- a/target/arm/cpregs-gcs.c
+++ b/target/arm/cpregs-gcs.c
@@ -105,6 +105,9 @@ static const ARMCPRegInfo gcs_reginfo[] = {
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 7, .opc2 = 4,
.access = PL1_W, .accessfn = access_gcspushx, .fgt = FGT_NGCSEPP,
.type = ARM_CP_GCSPUSHX },
+ { .name = "GCSPOPX", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 7, .opc2 = 6,
+ .access = PL1_W, .type = ARM_CP_GCSPOPX },
};
void define_gcs_cpregs(ARMCPU *cpu)
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 732d65f54e..773ed3044d 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -2555,6 +2555,35 @@ static void gen_gcspushx(DisasContext *s)
clear_pstate_bits(PSTATE_EXLOCK);
}
+static void gen_gcspopx(DisasContext *s)
+{
+ int sp_off = offsetof(CPUARMState, cp15.gcspr_el[s->current_el]);
+ int mmuidx = core_gcs_mem_index(s->mmu_idx);
+ MemOp mop = finalize_memop(s, MO_64 | MO_ALIGN);
+ TCGv_i64 addr = tcg_temp_new_i64();
+ TCGv_i64 tmp = tcg_temp_new_i64();
+ TCGLabel *fail_label =
+ delay_exception(s, EXCP_UDEF, syn_gcs_data_check(GCS_IT_GCSPOPX, 31));
+
+ /* The value at top-of-stack must be an exception token. */
+ tcg_gen_ld_i64(addr, tcg_env, sp_off);
+ tcg_gen_qemu_ld_i64(tmp, addr, mmuidx, mop);
+ tcg_gen_brcondi_i64(TCG_COND_NE, tmp, 0b1001, fail_label);
+
+ /*
+ * The other three values in the exception return record
+ * are ignored, but are loaded anyway to raise faults.
+ */
+ tcg_gen_addi_i64(addr, addr, 8);
+ tcg_gen_qemu_ld_i64(tmp, addr, mmuidx, mop);
+ tcg_gen_addi_i64(addr, addr, 8);
+ tcg_gen_qemu_ld_i64(tmp, addr, mmuidx, mop);
+ tcg_gen_addi_i64(addr, addr, 8);
+ tcg_gen_qemu_ld_i64(tmp, addr, mmuidx, mop);
+ tcg_gen_addi_i64(addr, addr, 8);
+ tcg_gen_st_i64(addr, tcg_env, sp_off);
+}
+
/* MRS - move from system register
* MSR (register) - move to system register
* SYS
@@ -2850,6 +2879,14 @@ static void handle_sys(DisasContext *s, bool isread,
gen_gcspushx(s);
}
return;
+ case ARM_CP_GCSPOPX:
+ /* Choose the CONSTRAINED UNPREDICTABLE for UNDEF. */
+ if (rt != 31) {
+ unallocated_encoding(s);
+ } else if (s->gcs_en) {
+ gen_gcspopx(s);
+ }
+ return;
default:
g_assert_not_reached();
}
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 60/82] target/arm: Implement GCSPOPCX
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (58 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 59/82] target/arm: Implement GCSPOPX Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:38 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 61/82] target/arm: Implement GCSSS1 Richard Henderson
` (21 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpregs.h | 1 +
target/arm/cpregs-gcs.c | 17 ++++++++++
target/arm/tcg/translate-a64.c | 58 ++++++++++++++++++++++++++++++++++
3 files changed, 76 insertions(+)
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
index 084ea00e51..392a0a264f 100644
--- a/target/arm/cpregs.h
+++ b/target/arm/cpregs.h
@@ -51,6 +51,7 @@ enum {
ARM_CP_GCSPOPM = 0x0009,
ARM_CP_GCSPUSHX = 0x000a,
ARM_CP_GCSPOPX = 0x000b,
+ ARM_CP_GCSPOPCX = 0x000c,
/* Flag: reads produce resetvalue; writes ignored. */
ARM_CP_CONST = 1 << 4,
diff --git a/target/arm/cpregs-gcs.c b/target/arm/cpregs-gcs.c
index 2bdd41c796..ab53a4314f 100644
--- a/target/arm/cpregs-gcs.c
+++ b/target/arm/cpregs-gcs.c
@@ -57,6 +57,19 @@ static CPAccessResult access_gcspushx(CPUARMState *env, const ARMCPRegInfo *ri,
return CP_ACCESS_OK;
}
+static CPAccessResult access_gcspopcx(CPUARMState *env, const ARMCPRegInfo *ri,
+ bool isread)
+{
+ /* Trap if lock not taken, and enabled. */
+ if (env->pstate & PSTATE_EXLOCK) {
+ int el = arm_current_el(env);
+ if (env->cp15.gcscr_el[el] & GCSCR_EXLOCKEN) {
+ return CP_ACCESS_EXLOCK;
+ }
+ }
+ return CP_ACCESS_OK;
+}
+
static const ARMCPRegInfo gcs_reginfo[] = {
{ .name = "GCSCRE0_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 2, .crm = 5, .opc2 = 2,
@@ -105,6 +118,10 @@ static const ARMCPRegInfo gcs_reginfo[] = {
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 7, .opc2 = 4,
.access = PL1_W, .accessfn = access_gcspushx, .fgt = FGT_NGCSEPP,
.type = ARM_CP_GCSPUSHX },
+ { .name = "GCSPOPCX", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 7, .opc2 = 5,
+ .access = PL1_W, .accessfn = access_gcspopcx, .fgt = FGT_NGCSEPP,
+ .type = ARM_CP_GCSPOPCX },
{ .name = "GCSPOPX", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 7, .opc2 = 6,
.access = PL1_W, .type = ARM_CP_GCSPOPX },
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 773ed3044d..af91b7f95f 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -2555,6 +2555,56 @@ static void gen_gcspushx(DisasContext *s)
clear_pstate_bits(PSTATE_EXLOCK);
}
+static void gen_gcspopcx(DisasContext *s)
+{
+ int sp_off = offsetof(CPUARMState, cp15.gcspr_el[s->current_el]);
+ int spsr_idx = aarch64_banked_spsr_index(s->current_el);
+ int spsr_off = offsetof(CPUARMState, banked_spsr[spsr_idx]);
+ int elr_off = offsetof(CPUARMState, elr_el[s->current_el]);
+ int gcscr_off = offsetof(CPUARMState, cp15.gcscr_el[s->current_el]);
+ int pstate_off = offsetof(CPUARMState, pstate);
+ int mmuidx = core_gcs_mem_index(s->mmu_idx);
+ MemOp mop = finalize_memop(s, MO_64 | MO_ALIGN);
+ TCGv_i64 addr = tcg_temp_new_i64();
+ TCGv_i64 tmp1 = tcg_temp_new_i64();
+ TCGv_i64 tmp2 = tcg_temp_new_i64();
+ TCGLabel *fail_label =
+ delay_exception(s, EXCP_UDEF, syn_gcs_data_check(GCS_IT_GCSPOPCX, 31));
+
+ /* The value at top-of-stack must be an exception token. */
+ tcg_gen_ld_i64(addr, tcg_env, sp_off);
+ tcg_gen_qemu_ld_i64(tmp1, addr, mmuidx, mop);
+ tcg_gen_brcondi_i64(TCG_COND_NE, tmp1, 0b1001, fail_label);
+
+ /* Validate in turn, ELR ... */
+ tcg_gen_addi_i64(addr, addr, 8);
+ tcg_gen_qemu_ld_i64(tmp1, addr, mmuidx, mop);
+ tcg_gen_ld_i64(tmp2, tcg_env, elr_off);
+ tcg_gen_brcond_i64(TCG_COND_NE, tmp1, tmp2, fail_label);
+
+ /* ... SPSR ... */
+ tcg_gen_addi_i64(addr, addr, 8);
+ tcg_gen_qemu_ld_i64(tmp1, addr, mmuidx, mop);
+ tcg_gen_ld_i64(tmp2, tcg_env, spsr_off);
+ tcg_gen_brcond_i64(TCG_COND_NE, tmp1, tmp2, fail_label);
+
+ /* ... and LR. */
+ tcg_gen_addi_i64(addr, addr, 8);
+ tcg_gen_qemu_ld_i64(tmp1, addr, mmuidx, mop);
+ tcg_gen_brcond_i64(TCG_COND_NE, tmp1, cpu_reg(s, 30), fail_label);
+
+ /* Writeback stack pointer after pop. */
+ tcg_gen_addi_i64(addr, addr, 8);
+ tcg_gen_st_i64(addr, tcg_env, sp_off);
+
+ /* PSTATE.EXLOCK = GetCurrentEXLOCKEN(). */
+ tcg_gen_ld_i64(tmp1, tcg_env, gcscr_off);
+ tcg_gen_ld_i64(tmp2, tcg_env, pstate_off);
+ tcg_gen_shri_i64(tmp1, tmp1, ctz64(GCSCR_EXLOCKEN));
+ tcg_gen_deposit_i64(tmp2, tmp2, tmp1, ctz64(PSTATE_EXLOCK), 1);
+ tcg_gen_st_i64(tmp2, tcg_env, pstate_off);
+}
+
static void gen_gcspopx(DisasContext *s)
{
int sp_off = offsetof(CPUARMState, cp15.gcspr_el[s->current_el]);
@@ -2879,6 +2929,14 @@ static void handle_sys(DisasContext *s, bool isread,
gen_gcspushx(s);
}
return;
+ case ARM_CP_GCSPOPCX:
+ /* Choose the CONSTRAINED UNPREDICTABLE for UNDEF. */
+ if (rt != 31) {
+ unallocated_encoding(s);
+ } else if (s->gcs_en) {
+ gen_gcspopcx(s);
+ }
+ return;
case ARM_CP_GCSPOPX:
/* Choose the CONSTRAINED UNPREDICTABLE for UNDEF. */
if (rt != 31) {
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 61/82] target/arm: Implement GCSSS1
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (59 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 60/82] target/arm: Implement GCSPOPCX Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:43 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 62/82] target/arm: Implement GCSSS2 Richard Henderson
` (20 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpregs.h | 1 +
target/arm/cpregs-gcs.c | 3 +++
target/arm/tcg/translate-a64.c | 32 ++++++++++++++++++++++++++++++++
3 files changed, 36 insertions(+)
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
index 392a0a264f..ee8b870e17 100644
--- a/target/arm/cpregs.h
+++ b/target/arm/cpregs.h
@@ -52,6 +52,7 @@ enum {
ARM_CP_GCSPUSHX = 0x000a,
ARM_CP_GCSPOPX = 0x000b,
ARM_CP_GCSPOPCX = 0x000c,
+ ARM_CP_GCSSS1 = 0x000d,
/* Flag: reads produce resetvalue; writes ignored. */
ARM_CP_CONST = 1 << 4,
diff --git a/target/arm/cpregs-gcs.c b/target/arm/cpregs-gcs.c
index ab53a4314f..bdafc60786 100644
--- a/target/arm/cpregs-gcs.c
+++ b/target/arm/cpregs-gcs.c
@@ -114,6 +114,9 @@ static const ARMCPRegInfo gcs_reginfo[] = {
{ .name = "GCSPOPM", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 3, .crn = 7, .crm = 7, .opc2 = 1,
.access = PL0_R, .type = ARM_CP_GCSPOPM },
+ { .name = "GCSSS1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 7, .opc2 = 2,
+ .access = PL0_W, .type = ARM_CP_GCSSS1 },
{ .name = "GCSPUSHX", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 7, .opc2 = 4,
.access = PL1_W, .accessfn = access_gcspushx, .fgt = FGT_NGCSEPP,
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index af91b7f95f..e4c7801740 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -2634,6 +2634,33 @@ static void gen_gcspopx(DisasContext *s)
tcg_gen_st_i64(addr, tcg_env, sp_off);
}
+static void gen_gcsss1(DisasContext *s, int rt)
+{
+ int sp_off = offsetof(CPUARMState, cp15.gcspr_el[s->current_el]);
+ int mmuidx = core_gcs_mem_index(s->mmu_idx);
+ MemOp mop = finalize_memop(s, MO_64 | MO_ALIGN);
+ TCGv_i64 inptr = cpu_reg(s, rt);
+ TCGv_i64 cmp = tcg_temp_new_i64();
+ TCGv_i64 new = tcg_temp_new_i64();
+ TCGv_i64 old = tcg_temp_new_i64();
+ TCGLabel *fail_label =
+ delay_exception(s, EXCP_UDEF, syn_gcs_data_check(GCS_IT_GCSSS1, rt));
+
+ /* Compute the valid cap entry that the new stack must have. */
+ tcg_gen_ld_i64(new, tcg_env, sp_off);
+ tcg_gen_deposit_i64(cmp, inptr, tcg_constant_i64(1), 0, 12);
+ /* Compute the in-progress cap entry for the old stack. */
+ tcg_gen_deposit_i64(new, new, tcg_constant_i64(5), 0, 3);
+
+ /* Swap the valid cap the with the in-progress cap. */
+ tcg_gen_atomic_cmpxchg_i64(old, inptr, cmp, new, mmuidx, mop);
+ tcg_gen_brcond_i64(TCG_COND_NE, old, cmp, fail_label);
+
+ /* The new stack had a valid cap: change gcspr. */
+ tcg_gen_andi_i64(new, inptr, ~7);
+ tcg_gen_st_i64(new, tcg_env, sp_off);
+}
+
/* MRS - move from system register
* MSR (register) - move to system register
* SYS
@@ -2945,6 +2972,11 @@ static void handle_sys(DisasContext *s, bool isread,
gen_gcspopx(s);
}
return;
+ case ARM_CP_GCSSS1:
+ if (s->gcs_en) {
+ gen_gcsss1(s, rt);
+ }
+ return;
default:
g_assert_not_reached();
}
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 62/82] target/arm: Implement GCSSS2
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (60 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 61/82] target/arm: Implement GCSSS1 Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:45 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 63/82] target/arm: Add gcs record for BL Richard Henderson
` (19 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpregs.h | 1 +
target/arm/cpregs-gcs.c | 3 +++
target/arm/tcg/translate-a64.c | 37 ++++++++++++++++++++++++++++++++++
3 files changed, 41 insertions(+)
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
index ee8b870e17..1ee0bfd132 100644
--- a/target/arm/cpregs.h
+++ b/target/arm/cpregs.h
@@ -53,6 +53,7 @@ enum {
ARM_CP_GCSPOPX = 0x000b,
ARM_CP_GCSPOPCX = 0x000c,
ARM_CP_GCSSS1 = 0x000d,
+ ARM_CP_GCSSS2 = 0x000e,
/* Flag: reads produce resetvalue; writes ignored. */
ARM_CP_CONST = 1 << 4,
diff --git a/target/arm/cpregs-gcs.c b/target/arm/cpregs-gcs.c
index bdafc60786..558e223838 100644
--- a/target/arm/cpregs-gcs.c
+++ b/target/arm/cpregs-gcs.c
@@ -117,6 +117,9 @@ static const ARMCPRegInfo gcs_reginfo[] = {
{ .name = "GCSSS1", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 3, .crn = 7, .crm = 7, .opc2 = 2,
.access = PL0_W, .type = ARM_CP_GCSSS1 },
+ { .name = "GCSSS2", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 7, .opc2 = 3,
+ .access = PL0_R, .type = ARM_CP_GCSSS2 },
{ .name = "GCSPUSHX", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 7, .opc2 = 4,
.access = PL1_W, .accessfn = access_gcspushx, .fgt = FGT_NGCSEPP,
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index e4c7801740..88fe5ac4ef 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -2661,6 +2661,38 @@ static void gen_gcsss1(DisasContext *s, int rt)
tcg_gen_st_i64(new, tcg_env, sp_off);
}
+static void gen_gcsss2(DisasContext *s, int rt)
+{
+ int sp_off = offsetof(CPUARMState, cp15.gcspr_el[s->current_el]);
+ int mmuidx = core_gcs_mem_index(s->mmu_idx);
+ MemOp mop = finalize_memop(s, MO_64 | MO_ALIGN);
+ TCGv_i64 inptr = tcg_temp_new_i64();
+ TCGv_i64 outptr = tcg_temp_new_i64();
+ TCGv_i64 tmp = tcg_temp_new_i64();
+ TCGLabel *fail_label =
+ delay_exception(s, EXCP_UDEF, syn_gcs_data_check(GCS_IT_GCSSS2, rt));
+
+ /* Validate that the new stack has an in-progress cap. */
+ tcg_gen_ld_i64(inptr, tcg_env, sp_off);
+ tcg_gen_qemu_ld_i64(outptr, inptr, mmuidx, mop);
+ tcg_gen_andi_i64(tmp, outptr, 7);
+ tcg_gen_brcondi_i64(TCG_COND_NE, tmp, 5, fail_label);
+
+ /* Push a valid cap to the old stack. */
+ tcg_gen_andi_i64(outptr, outptr, ~7);
+ tcg_gen_addi_i64(outptr, outptr, -8);
+ tcg_gen_deposit_i64(tmp, outptr, tcg_constant_i64(1), 0, 12);
+ tcg_gen_qemu_st_i64(tmp, outptr, mmuidx, mop);
+
+ /* Pop the in-progress cap from the new stack. */
+ tcg_gen_addi_i64(inptr, inptr, 8);
+ tcg_gen_st_i64(inptr, tcg_env, sp_off);
+ tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL);
+
+ /* Return a pointer to the old stack cap. */
+ tcg_gen_mov_i64(cpu_reg(s, rt), outptr);
+}
+
/* MRS - move from system register
* MSR (register) - move to system register
* SYS
@@ -2977,6 +3009,11 @@ static void handle_sys(DisasContext *s, bool isread,
gen_gcsss1(s, rt);
}
return;
+ case ARM_CP_GCSSS2:
+ if (s->gcs_en) {
+ gen_gcsss2(s, rt);
+ }
+ return;
default:
g_assert_not_reached();
}
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 63/82] target/arm: Add gcs record for BL
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (61 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 62/82] target/arm: Implement GCSSS2 Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:45 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 64/82] target/arm: Add gcs record for BLR Richard Henderson
` (18 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/tcg/translate-a64.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 88fe5ac4ef..6fd3032613 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -1667,7 +1667,14 @@ static bool trans_B(DisasContext *s, arg_i *a)
static bool trans_BL(DisasContext *s, arg_i *a)
{
- gen_pc_plus_diff(s, cpu_reg(s, 30), curr_insn_len(s));
+ TCGv_i64 link = tcg_temp_new_i64();
+
+ gen_pc_plus_diff(s, link, 4);
+ if (s->gcs_en) {
+ gen_add_gcs_record(s, link);
+ }
+ tcg_gen_mov_i64(cpu_reg(s, 30), link);
+
reset_btype(s);
gen_goto_tb(s, 0, a->imm);
return true;
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 64/82] target/arm: Add gcs record for BLR
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (62 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 63/82] target/arm: Add gcs record for BL Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:46 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 65/82] target/arm: Add gcs record for BLR with PAuth Richard Henderson
` (17 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/tcg/translate-a64.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 6fd3032613..4c3cc3d943 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -1771,15 +1771,15 @@ static bool trans_BR(DisasContext *s, arg_r *a)
static bool trans_BLR(DisasContext *s, arg_r *a)
{
- TCGv_i64 dst = cpu_reg(s, a->rn);
- TCGv_i64 lr = cpu_reg(s, 30);
- if (dst == lr) {
- TCGv_i64 tmp = tcg_temp_new_i64();
- tcg_gen_mov_i64(tmp, dst);
- dst = tmp;
+ TCGv_i64 link = tcg_temp_new_i64();
+
+ gen_pc_plus_diff(s, link, 4);
+ if (s->gcs_en) {
+ gen_add_gcs_record(s, link);
}
- gen_pc_plus_diff(s, lr, curr_insn_len(s));
- gen_a64_set_pc(s, dst);
+ gen_a64_set_pc(s, cpu_reg(s, a->rn));
+ tcg_gen_mov_i64(cpu_reg(s, 30), link);
+
set_btype_for_blr(s);
s->base.is_jmp = DISAS_JUMP;
return true;
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 65/82] target/arm: Add gcs record for BLR with PAuth
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (63 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 64/82] target/arm: Add gcs record for BLR Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:46 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 66/82] target/arm: Load gcs record for RET Richard Henderson
` (16 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/tcg/translate-a64.c | 31 ++++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 4c3cc3d943..a945fd3b33 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -1831,20 +1831,20 @@ static bool trans_BRAZ(DisasContext *s, arg_braz *a)
static bool trans_BLRAZ(DisasContext *s, arg_braz *a)
{
- TCGv_i64 dst, lr;
+ TCGv_i64 dst, link;
if (!dc_isar_feature(aa64_pauth, s)) {
return false;
}
-
dst = auth_branch_target(s, cpu_reg(s, a->rn), tcg_constant_i64(0), !a->m);
- lr = cpu_reg(s, 30);
- if (dst == lr) {
- TCGv_i64 tmp = tcg_temp_new_i64();
- tcg_gen_mov_i64(tmp, dst);
- dst = tmp;
+
+ link = tcg_temp_new_i64();
+ gen_pc_plus_diff(s, link, 4);
+ if (s->gcs_en) {
+ gen_add_gcs_record(s, link);
}
- gen_pc_plus_diff(s, lr, curr_insn_len(s));
+ tcg_gen_mov_i64(cpu_reg(s, 30), link);
+
gen_a64_set_pc(s, dst);
set_btype_for_blr(s);
s->base.is_jmp = DISAS_JUMP;
@@ -1881,19 +1881,20 @@ static bool trans_BRA(DisasContext *s, arg_bra *a)
static bool trans_BLRA(DisasContext *s, arg_bra *a)
{
- TCGv_i64 dst, lr;
+ TCGv_i64 dst, link;
if (!dc_isar_feature(aa64_pauth, s)) {
return false;
}
dst = auth_branch_target(s, cpu_reg(s, a->rn), cpu_reg_sp(s, a->rm), !a->m);
- lr = cpu_reg(s, 30);
- if (dst == lr) {
- TCGv_i64 tmp = tcg_temp_new_i64();
- tcg_gen_mov_i64(tmp, dst);
- dst = tmp;
+
+ link = tcg_temp_new_i64();
+ gen_pc_plus_diff(s, link, 4);
+ if (s->gcs_en) {
+ gen_add_gcs_record(s, link);
}
- gen_pc_plus_diff(s, lr, curr_insn_len(s));
+ tcg_gen_mov_i64(cpu_reg(s, 30), link);
+
gen_a64_set_pc(s, dst);
set_btype_for_blr(s);
s->base.is_jmp = DISAS_JUMP;
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 66/82] target/arm: Load gcs record for RET
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (64 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 65/82] target/arm: Add gcs record for BLR with PAuth Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:47 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 67/82] target/arm: Load gcs record for RET with PAuth Richard Henderson
` (15 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/tcg/translate-a64.c | 32 +++++++++++++++++++++++++++++++-
1 file changed, 31 insertions(+), 1 deletion(-)
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index a945fd3b33..49e17548c1 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -433,6 +433,30 @@ static void gen_add_gcs_record(DisasContext *s, TCGv_i64 value)
tcg_gen_st_i64(addr, tcg_env, sp_off);
}
+static void gen_load_check_gcs_record(DisasContext *s, TCGv_i64 target,
+ GCSInstructionType it, int rt)
+{
+ int sp_off = offsetof(CPUARMState, cp15.gcspr_el[s->current_el]);
+ int mmuidx = core_gcs_mem_index(s->mmu_idx);
+ MemOp mop = finalize_memop(s, MO_64 | MO_ALIGN);
+ TCGv_i64 addr = tcg_temp_new_i64();
+ TCGv_i64 rec_va = tcg_temp_new_i64();
+
+ tcg_gen_ld_i64(addr, tcg_env, sp_off);
+ tcg_gen_qemu_ld_i64(rec_va, clean_data_tbi(s, addr), mmuidx, mop);
+
+ if (s->gcs_rvcen) {
+ TCGLabel *fail_label =
+ delay_exception(s, EXCP_UDEF, syn_gcs_data_check(it, rt));
+
+ tcg_gen_brcond_i64(TCG_COND_NE, rec_va, target, fail_label);
+ }
+
+ gen_a64_set_pc(s, rec_va);
+ tcg_gen_addi_i64(addr, addr, 8);
+ tcg_gen_st_i64(addr, tcg_env, sp_off);
+}
+
typedef struct DisasCompare64 {
TCGCond cond;
TCGv_i64 value;
@@ -1787,7 +1811,13 @@ static bool trans_BLR(DisasContext *s, arg_r *a)
static bool trans_RET(DisasContext *s, arg_r *a)
{
- gen_a64_set_pc(s, cpu_reg(s, a->rn));
+ TCGv_i64 target = cpu_reg(s, a->rn);
+
+ if (s->gcs_en) {
+ gen_load_check_gcs_record(s, target, GCS_IT_RET_nPauth, a->rn);
+ } else {
+ gen_a64_set_pc(s, target);
+ }
s->base.is_jmp = DISAS_JUMP;
return true;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 67/82] target/arm: Load gcs record for RET with PAuth
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (65 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 66/82] target/arm: Load gcs record for RET Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:48 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 68/82] target/arm: Copy EXLOCKEn to EXLOCK on exception to the same EL Richard Henderson
` (14 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/tcg/translate-a64.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 49e17548c1..23186850f8 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -1890,7 +1890,12 @@ static bool trans_RETA(DisasContext *s, arg_reta *a)
}
dst = auth_branch_target(s, cpu_reg(s, 30), cpu_X[31], !a->m);
- gen_a64_set_pc(s, dst);
+ if (s->gcs_en) {
+ GCSInstructionType it = a->m ? GCS_IT_RET_PauthB : GCS_IT_RET_PauthA;
+ gen_load_check_gcs_record(s, dst, it, 30);
+ } else {
+ gen_a64_set_pc(s, dst);
+ }
s->base.is_jmp = DISAS_JUMP;
return true;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 68/82] target/arm: Copy EXLOCKEn to EXLOCK on exception to the same EL
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (66 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 67/82] target/arm: Load gcs record for RET with PAuth Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:48 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 69/82] target/arm: Implement EXLOCK check during exception return Richard Henderson
` (13 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Per R_WTXBY, PSTATE.EXLOCK is 0 on an exception to a higher EL,
and copied from EXLOCKEn otherwise.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/helper.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 2514a03c0e..23e54684c4 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -9300,8 +9300,13 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
} else {
addr += 0x600;
}
- } else if (pstate_read(env) & PSTATE_SP) {
- addr += 0x200;
+ } else {
+ if (pstate_read(env) & PSTATE_SP) {
+ addr += 0x200;
+ }
+ if (is_a64(env) && (env->cp15.gcscr_el[new_el] & GCSCR_EXLOCKEN)) {
+ new_mode |= PSTATE_EXLOCK;
+ }
}
switch (cs->exception_index) {
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 69/82] target/arm: Implement EXLOCK check during exception return
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (67 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 68/82] target/arm: Copy EXLOCKEn to EXLOCK on exception to the same EL Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:49 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 70/82] target/arm: Enable FEAT_GCS with -cpu max Richard Henderson
` (12 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/tcg/helper-a64.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c
index f61adf1f80..7ab7ddf7c4 100644
--- a/target/arm/tcg/helper-a64.c
+++ b/target/arm/tcg/helper-a64.c
@@ -694,6 +694,17 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
goto illegal_return;
}
+ /*
+ * If GetCurrentEXLOCKEN, the exception return path must use GCSPOPCX,
+ * which will set PSTATE.EXLOCK. We need not explicitly check FEAT_GCS,
+ * because GCSCR_ELx cannot be set without it.
+ */
+ if (new_el == cur_el &&
+ (env->cp15.gcscr_el[cur_el] & GCSCR_EXLOCKEN) &&
+ !(env->pstate & PSTATE_EXLOCK)) {
+ goto illegal_return;
+ }
+
bql_lock();
arm_call_pre_el_change_hook(cpu);
bql_unlock();
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 70/82] target/arm: Enable FEAT_GCS with -cpu max
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (68 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 69/82] target/arm: Implement EXLOCK check during exception return Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:49 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 71/82] linux-user/aarch64: Implement prctls for GCS Richard Henderson
` (11 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/tcg/cpu64.c | 1 +
docs/system/arm/emulation.rst | 1 +
2 files changed, 2 insertions(+)
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index f4a41c854f..0c3408c0a0 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -1205,6 +1205,7 @@ void aarch64_max_tcg_initfn(Object *obj)
t = FIELD_DP64(t, ID_AA64PFR1, SME, 2); /* FEAT_SME2 */
t = FIELD_DP64(t, ID_AA64PFR1, CSV2_FRAC, 0); /* FEAT_CSV2_3 */
t = FIELD_DP64(t, ID_AA64PFR1, NMI, 1); /* FEAT_NMI */
+ t = FIELD_DP64(t, ID_AA64PFR1, GCS, 1); /* FEAT_GCS */
SET_IDREG(isar, ID_AA64PFR1, t);
t = GET_IDREG(isar, ID_AA64MMFR0);
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
index b894aced89..9e3df48e00 100644
--- a/docs/system/arm/emulation.rst
+++ b/docs/system/arm/emulation.rst
@@ -72,6 +72,7 @@ the following architecture extensions:
- FEAT_FRINTTS (Floating-point to integer instructions)
- FEAT_FlagM (Flag manipulation instructions v2)
- FEAT_FlagM2 (Enhancements to flag manipulation instructions)
+- FEAT_GCS (Guarded Control Stack Extension)
- FEAT_GTG (Guest translation granule size)
- FEAT_HAFDBS (Hardware management of the access flag and dirty bit state)
- FEAT_HBC (Hinted conditional branches)
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 71/82] linux-user/aarch64: Implement prctls for GCS
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (69 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 70/82] target/arm: Enable FEAT_GCS with -cpu max Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:53 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 72/82] linux-user/aarch64: Allocate new gcs stack on clone Richard Henderson
` (10 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
This is PR_GET_SHADOW_STACK_STATUS, PR_SET_SHADOW_STACK_STATUS,
and PR_LOCK_SHADOW_STACK_STATUS.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/aarch64/gcs-internal.h | 38 ++++++++++++
linux-user/aarch64/target_prctl.h | 96 +++++++++++++++++++++++++++++++
linux-user/qemu.h | 5 ++
linux-user/syscall.c | 29 ++++++++++
4 files changed, 168 insertions(+)
create mode 100644 linux-user/aarch64/gcs-internal.h
diff --git a/linux-user/aarch64/gcs-internal.h b/linux-user/aarch64/gcs-internal.h
new file mode 100644
index 0000000000..e586c7e80e
--- /dev/null
+++ b/linux-user/aarch64/gcs-internal.h
@@ -0,0 +1,38 @@
+/*
+ * AArch64 gcs functions for linux-user
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef AARCH64_GCS_INTERNAL_H
+#define AARCH64_GCS_INTERNAL_H
+
+#ifndef PR_SHADOW_STACK_ENABLE
+# define PR_SHADOW_STACK_ENABLE (1U << 0)
+# define PR_SHADOW_STACK_WRITE (1U << 1)
+# define PR_SHADOW_STACK_PUSH (1U << 2)
+#endif
+
+static inline uint64_t gcs_get_el0_mode(CPUArchState *env)
+{
+ uint64_t cr = env->cp15.gcscr_el[0];
+ abi_ulong flags = 0;
+
+ flags |= cr & GCSCR_PCRSEL ? PR_SHADOW_STACK_ENABLE : 0;
+ flags |= cr & GCSCR_STREN ? PR_SHADOW_STACK_WRITE : 0;
+ flags |= cr & GCSCR_PUSHMEN ? PR_SHADOW_STACK_PUSH : 0;
+
+ return flags;
+}
+
+static inline void gcs_set_el0_mode(CPUArchState *env, uint64_t flags)
+{
+ uint64_t cr = GCSCRE0_NTR;
+
+ cr |= flags & PR_SHADOW_STACK_ENABLE ? GCSCR_RVCHKEN | GCSCR_PCRSEL : 0;
+ cr |= flags & PR_SHADOW_STACK_WRITE ? GCSCR_STREN : 0;
+ cr |= flags & PR_SHADOW_STACK_PUSH ? GCSCR_PUSHMEN : 0;
+
+ env->cp15.gcscr_el[0] = cr;
+}
+
+#endif
diff --git a/linux-user/aarch64/target_prctl.h b/linux-user/aarch64/target_prctl.h
index ed75b9e4b5..621be5727f 100644
--- a/linux-user/aarch64/target_prctl.h
+++ b/linux-user/aarch64/target_prctl.h
@@ -6,8 +6,10 @@
#ifndef AARCH64_TARGET_PRCTL_H
#define AARCH64_TARGET_PRCTL_H
+#include "qemu/units.h"
#include "target/arm/cpu-features.h"
#include "mte_user_helper.h"
+#include "gcs-internal.h"
static abi_long do_prctl_sve_get_vl(CPUArchState *env)
{
@@ -206,4 +208,98 @@ static abi_long do_prctl_get_tagged_addr_ctrl(CPUArchState *env)
}
#define do_prctl_get_tagged_addr_ctrl do_prctl_get_tagged_addr_ctrl
+static abi_long do_prctl_get_shadow_stack_status(CPUArchState *env,
+ abi_long arg2)
+{
+ ARMCPU *cpu = env_archcpu(env);
+
+ if (!cpu_isar_feature(aa64_gcs, cpu)) {
+ return -TARGET_EINVAL;
+ }
+ return put_user_ual(gcs_get_el0_mode(env), arg2);
+}
+#define do_prctl_get_shadow_stack_status do_prctl_get_shadow_stack_status
+
+static abi_long gcs_alloc(abi_ulong hint, abi_ulong size)
+{
+ /*
+ * Without softmmu, we cannot protect GCS memory properly.
+ * Make do with normal read/write permissions. This at least allows
+ * emulation of correct programs which don't access the gcs stack
+ * with normal instructions.
+ */
+ return target_mmap(hint, size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS |
+ (hint ? MAP_FIXED_NOREPLACE : 0), -1, 0);
+}
+
+static abi_ulong gcs_new_stack(TaskState *ts)
+{
+ /* Use guest_stack_size as a proxy for RLIMIT_STACK. */
+ abi_ulong size = MIN(MAX(guest_stack_size / 2, TARGET_PAGE_SIZE), 2 * GiB);
+ abi_ulong base = gcs_alloc(0, size);
+
+ if (base == -1) {
+ return -1;
+ }
+
+ ts->gcs_base = base;
+ ts->gcs_size = size;
+ return base + size - 8;
+}
+
+static abi_long do_prctl_set_shadow_stack_status(CPUArchState *env,
+ abi_long new_mode)
+{
+ ARMCPU *cpu = env_archcpu(env);
+ TaskState *ts = get_task_state(env_cpu(env));
+ abi_long cur_mode;
+
+ if (!cpu_isar_feature(aa64_gcs, cpu)) {
+ return -TARGET_EINVAL;
+ }
+ if (new_mode & ~(PR_SHADOW_STACK_ENABLE |
+ PR_SHADOW_STACK_WRITE |
+ PR_SHADOW_STACK_PUSH)) {
+ return -TARGET_EINVAL;
+ }
+
+ cur_mode = gcs_get_el0_mode(env);
+ if ((new_mode ^ cur_mode) & ts->gcs_el0_locked) {
+ return -TARGET_EBUSY;
+ }
+
+ if (new_mode & ~cur_mode & PR_SHADOW_STACK_ENABLE) {
+ abi_long gcspr;
+
+ if (ts->gcs_base || env->cp15.gcspr_el[0]) {
+ return -EINVAL;
+ }
+ gcspr = gcs_new_stack(ts);
+ if (gcspr == -1) {
+ return -TARGET_ENOMEM;
+ }
+ env->cp15.gcspr_el[0] = gcspr;
+ }
+
+ gcs_set_el0_mode(env, new_mode);
+ arm_rebuild_hflags(env);
+ return 0;
+}
+#define do_prctl_set_shadow_stack_status do_prctl_set_shadow_stack_status
+
+static abi_long do_prctl_lock_shadow_stack_status(CPUArchState *env,
+ abi_long arg2)
+{
+ ARMCPU *cpu = env_archcpu(env);
+ TaskState *ts = get_task_state(env_cpu(env));
+
+ if (!cpu_isar_feature(aa64_gcs, cpu)) {
+ return -EINVAL;
+ }
+ ts->gcs_el0_locked |= arg2;
+ return 0;
+}
+#define do_prctl_lock_shadow_stack_status do_prctl_lock_shadow_stack_status
+
#endif /* AARCH64_TARGET_PRCTL_H */
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 0b19fa43e6..6f0bfa83db 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -126,6 +126,11 @@ struct TaskState {
/* Extra fields for semihosted binaries. */
abi_ulong heap_base;
abi_ulong heap_limit;
+#endif
+#if defined(TARGET_AARCH64)
+ vaddr gcs_base;
+ abi_ulong gcs_size;
+ abi_ulong gcs_el0_locked;
#endif
abi_ulong stack_base;
int used; /* non zero if used */
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 91360a072c..2f1e881046 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6351,6 +6351,11 @@ abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
# define PR_SME_VL_LEN_MASK 0xffff
# define PR_SME_VL_INHERIT (1 << 17)
#endif
+#ifndef PR_GET_SHADOW_STACK_STATUS
+# define PR_GET_SHADOW_STACK_STATUS 74
+# define PR_SET_SHADOW_STACK_STATUS 75
+# define PR_LOCK_SHADOW_STACK_STATUS 76
+#endif
#include "target_prctl.h"
@@ -6397,6 +6402,15 @@ static abi_long do_prctl_inval1(CPUArchState *env, abi_long arg2)
#ifndef do_prctl_sme_set_vl
#define do_prctl_sme_set_vl do_prctl_inval1
#endif
+#ifndef do_prctl_get_shadow_stack_status
+#define do_prctl_get_shadow_stack_status do_prctl_inval1
+#endif
+#ifndef do_prctl_set_shadow_stack_status
+#define do_prctl_set_shadow_stack_status do_prctl_inval1
+#endif
+#ifndef do_prctl_lock_shadow_stack_status
+#define do_prctl_lock_shadow_stack_status do_prctl_inval1
+#endif
static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
abi_long arg3, abi_long arg4, abi_long arg5)
@@ -6467,6 +6481,21 @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
return -TARGET_EINVAL;
}
return do_prctl_get_tagged_addr_ctrl(env);
+ case PR_GET_SHADOW_STACK_STATUS:
+ if (arg3 || arg4 || arg5) {
+ return -TARGET_EINVAL;
+ }
+ return do_prctl_get_shadow_stack_status(env, arg2);
+ case PR_SET_SHADOW_STACK_STATUS:
+ if (arg3 || arg4 || arg5) {
+ return -TARGET_EINVAL;
+ }
+ return do_prctl_set_shadow_stack_status(env, arg2);
+ case PR_LOCK_SHADOW_STACK_STATUS:
+ if (arg3 || arg4 || arg5) {
+ return -TARGET_EINVAL;
+ }
+ return do_prctl_lock_shadow_stack_status(env, arg2);
case PR_GET_UNALIGN:
return do_prctl_get_unalign(env, arg2);
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 72/82] linux-user/aarch64: Allocate new gcs stack on clone
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (70 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 71/82] linux-user/aarch64: Implement prctls for GCS Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:54 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 73/82] linux-user/aarch64: Release gcs stack on thread exit Richard Henderson
` (9 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Allocate the new stack early, so that error reporting need
not clean up other objects.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/syscall.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 2f1e881046..91210775ed 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6652,6 +6652,21 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
ts = g_new0(TaskState, 1);
init_task_state(ts);
+#ifdef TARGET_AARCH64
+ /*
+ * If GCS is enabled in the parent thread, it is also enabled
+ * in the child thread, but with a newly allocated stack.
+ */
+ abi_long new_gcspr = 0;
+ if (env->cp15.gcscr_el[0] & GCSCR_PCRSEL) {
+ new_gcspr = gcs_new_stack(ts);
+ if (new_gcspr == -1) {
+ g_free(ts);
+ return -TARGET_ENOMEM;
+ }
+ }
+#endif
+
/* Grab a mutex so that thread setup appears atomic. */
pthread_mutex_lock(&clone_lock);
@@ -6676,6 +6691,11 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
ts->info = parent_ts->info;
ts->signal_mask = parent_ts->signal_mask;
+#ifdef TARGET_AARCH64
+ ts->gcs_el0_locked = parent_ts->gcs_el0_locked;
+ new_env->cp15.gcspr_el[0] = new_gcspr;
+#endif
+
if (flags & CLONE_CHILD_CLEARTID) {
ts->child_tidptr = child_tidptr;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 73/82] linux-user/aarch64: Release gcs stack on thread exit
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (71 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 72/82] linux-user/aarch64: Allocate new gcs stack on clone Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:54 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 74/82] linux-user/aarch64: Implement map_shadow_stack syscall Richard Henderson
` (8 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/syscall.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 91210775ed..dfe114ceb3 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -9309,6 +9309,12 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
}
+#ifdef TARGET_AARCH64
+ if (ts->gcs_base) {
+ target_munmap(ts->gcs_base, ts->gcs_size);
+ }
+#endif
+
object_unparent(OBJECT(cpu));
object_unref(OBJECT(cpu));
/*
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 74/82] linux-user/aarch64: Implement map_shadow_stack syscall
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (72 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 73/82] linux-user/aarch64: Release gcs stack on thread exit Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:55 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 75/82] target/arm: Enable GCSPR_EL0 for read in user-mode Richard Henderson
` (7 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/syscall.c | 59 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 59 insertions(+)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index dfe114ceb3..0a7ce7a262 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6356,6 +6356,12 @@ abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
# define PR_SET_SHADOW_STACK_STATUS 75
# define PR_LOCK_SHADOW_STACK_STATUS 76
#endif
+#ifndef SHADOW_STACK_SET_TOKEN
+# define SHADOW_STACK_SET_TOKEN (1u << 0)
+#endif
+#ifndef SHADOW_STACK_SET_MARKER
+# define SHADOW_STACK_SET_MARKER (1u << 1)
+#endif
#include "target_prctl.h"
@@ -6571,6 +6577,54 @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
}
}
+#ifdef TARGET_AARCH64
+static abi_long do_map_shadow_stack(CPUArchState *env, abi_ulong addr,
+ abi_ulong size, abi_int flags)
+{
+ ARMCPU *cpu = env_archcpu(env);
+ abi_ulong alloc_size;
+
+ if (!cpu_isar_feature(aa64_gcs, cpu)) {
+ return -TARGET_EOPNOTSUPP;
+ }
+ if (flags & ~(SHADOW_STACK_SET_TOKEN | SHADOW_STACK_SET_MARKER)) {
+ return -TARGET_EINVAL;
+ }
+ if (addr & ~TARGET_PAGE_MASK) {
+ return -TARGET_EINVAL;
+ }
+ if (size == 8 || !QEMU_IS_ALIGNED(size, 8)) {
+ return -TARGET_EINVAL;
+ }
+
+ alloc_size = TARGET_PAGE_ALIGN(size);
+ if (alloc_size < size) {
+ return -TARGET_EOVERFLOW;
+ }
+
+ mmap_lock();
+ addr = gcs_alloc(addr, alloc_size);
+ if (addr != -1) {
+ if (flags & SHADOW_STACK_SET_TOKEN) {
+ abi_ptr cap_ptr = addr + size - 8;
+ uint64_t cap_val;
+
+ if (flags & SHADOW_STACK_SET_MARKER) {
+ /* Leave an extra empty frame at top-of-stack. */
+ cap_ptr -= 8;
+ }
+ cap_val = (cap_ptr & TARGET_PAGE_MASK) | 1;
+ if (put_user_u64(cap_val, cap_ptr)) {
+ /* Allocation succeeded above. */
+ g_assert_not_reached();
+ }
+ }
+ }
+ mmap_unlock();
+ return get_errno(addr);
+}
+#endif
+
#define NEW_STACK_SIZE 0x40000
@@ -13945,6 +13999,11 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
return do_riscv_hwprobe(cpu_env, arg1, arg2, arg3, arg4, arg5);
#endif
+#ifdef TARGET_AARCH64
+ case TARGET_NR_map_shadow_stack:
+ return do_map_shadow_stack(cpu_env, arg1, arg2, arg3);
+#endif
+
default:
qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num);
return -TARGET_ENOSYS;
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 75/82] target/arm: Enable GCSPR_EL0 for read in user-mode
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (73 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 74/82] linux-user/aarch64: Implement map_shadow_stack syscall Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:56 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 76/82] linux-user/aarch64: Inject SIGSEGV for GCS faults Richard Henderson
` (6 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpu.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index ec63297165..284d1870ec 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -317,6 +317,10 @@ static void arm_cpu_reset_hold(Object *obj, ResetType type)
env->cp15.mdscr_el1 |= 1 << 12;
/* Enable FEAT_MOPS */
env->cp15.sctlr_el[1] |= SCTLR_MSCEN;
+ /* For Linux, GCSPR_EL0 is always readable. */
+ if (cpu_isar_feature(aa64_gcs, cpu)) {
+ env->cp15.gcscr_el[0] = GCSCRE0_NTR;
+ }
#else
/* Reset into the highest available EL */
if (arm_feature(env, ARM_FEATURE_EL3)) {
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 76/82] linux-user/aarch64: Inject SIGSEGV for GCS faults
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (74 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 75/82] target/arm: Enable GCSPR_EL0 for read in user-mode Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:56 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 77/82] linux-user/aarch64: Generate GCS signal records Richard Henderson
` (5 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/aarch64/target_signal.h | 1 +
linux-user/aarch64/cpu_loop.c | 5 +++++
2 files changed, 6 insertions(+)
diff --git a/linux-user/aarch64/target_signal.h b/linux-user/aarch64/target_signal.h
index 6f66a50bfd..e509ac1032 100644
--- a/linux-user/aarch64/target_signal.h
+++ b/linux-user/aarch64/target_signal.h
@@ -7,6 +7,7 @@
#define TARGET_SEGV_MTEAERR 8 /* Asynchronous ARM MTE error */
#define TARGET_SEGV_MTESERR 9 /* Synchronous ARM MTE exception */
+#define TARGET_SEGV_CPERR 10 /* Control protection fault */
#define TARGET_ARCH_HAS_SETUP_FRAME
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c
index 7e9788abfb..00ff51c883 100644
--- a/linux-user/aarch64/cpu_loop.c
+++ b/linux-user/aarch64/cpu_loop.c
@@ -89,6 +89,11 @@ static void signal_for_exception(CPUARMState *env, vaddr addr)
si_code = TARGET_ILL_ILLOPN;
break;
+ case EC_GCS:
+ si_signo = TARGET_SIGSEGV;
+ si_code = TARGET_SEGV_CPERR;
+ break;
+
case EC_MOP:
/*
* FIXME: The kernel fixes up wrong-option exceptions.
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 77/82] linux-user/aarch64: Generate GCS signal records
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (75 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 76/82] linux-user/aarch64: Inject SIGSEGV for GCS faults Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:57 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 78/82] linux-user: Change exported get_elf_hwcap to abi_ulong Richard Henderson
` (4 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Here we must push and pop a cap on the GCS stack as
well as the gcs record on the normal stack.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/aarch64/signal.c | 129 ++++++++++++++++++++++++++++++++++--
1 file changed, 123 insertions(+), 6 deletions(-)
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
index ef97be3ac7..a1957a330c 100644
--- a/linux-user/aarch64/signal.c
+++ b/linux-user/aarch64/signal.c
@@ -22,6 +22,7 @@
#include "signal-common.h"
#include "linux-user/trace.h"
#include "target/arm/cpu-features.h"
+#include "gcs-internal.h"
struct target_sigcontext {
uint64_t fault_address;
@@ -152,6 +153,16 @@ struct target_zt_context {
QEMU_BUILD_BUG_ON(TARGET_ZT_SIG_REG_BYTES != \
sizeof_field(CPUARMState, za_state.zt0));
+#define TARGET_GCS_MAGIC 0x47435300
+#define GCS_SIGNAL_CAP(X) ((X) & TARGET_PAGE_MASK)
+
+struct target_gcs_context {
+ struct target_aarch64_ctx head;
+ uint64_t gcspr;
+ uint64_t features_enabled;
+ uint64_t reserved;
+};
+
struct target_rt_sigframe {
struct target_siginfo info;
struct target_ucontext uc;
@@ -322,6 +333,35 @@ static void target_setup_zt_record(struct target_zt_context *zt,
}
}
+static bool target_setup_gcs_record(struct target_gcs_context *ctx,
+ CPUARMState *env, uint64_t return_addr)
+{
+ uint64_t mode = gcs_get_el0_mode(env);
+ uint64_t gcspr = env->cp15.gcspr_el[0];
+
+ if (mode & PR_SHADOW_STACK_ENABLE) {
+ /* Push a cap for the signal frame. */
+ gcspr -= 8;
+ if (put_user_u64(GCS_SIGNAL_CAP(gcspr), gcspr)) {
+ return false;
+ }
+
+ /* Push a gcs entry for the trampoline. */
+ if (put_user_u64(return_addr, gcspr - 8)) {
+ return false;
+ }
+ env->cp15.gcspr_el[0] = gcspr - 8;
+ }
+
+ __put_user(TARGET_GCS_MAGIC, &ctx->head.magic);
+ __put_user(sizeof(*ctx), &ctx->head.size);
+ __put_user(gcspr, &ctx->gcspr);
+ __put_user(mode, &ctx->features_enabled);
+ __put_user(0, &ctx->reserved);
+
+ return true;
+}
+
static void target_restore_general_frame(CPUARMState *env,
struct target_rt_sigframe *sf)
{
@@ -502,6 +542,55 @@ static bool target_restore_zt_record(CPUARMState *env,
return true;
}
+static bool target_restore_gcs_record(CPUARMState *env,
+ struct target_gcs_context *ctx,
+ bool *rebuild_hflags)
+{
+ TaskState *ts = get_task_state(env_cpu(env));
+ uint64_t cur_mode = gcs_get_el0_mode(env);
+ uint64_t new_mode, gcspr;
+
+ __get_user(new_mode, &ctx->features_enabled);
+ __get_user(gcspr, &ctx->gcspr);
+
+ if (new_mode & ~(PR_SHADOW_STACK_ENABLE |
+ PR_SHADOW_STACK_WRITE |
+ PR_SHADOW_STACK_PUSH)) {
+ return false;
+ }
+ if ((new_mode ^ cur_mode) & ts->gcs_el0_locked) {
+ return false;
+ }
+ if (new_mode & ~cur_mode & PR_SHADOW_STACK_ENABLE) {
+ return false;
+ }
+
+ if (new_mode & PR_SHADOW_STACK_ENABLE) {
+ uint64_t cap;
+
+ /* Pop and clear the signal cap. */
+ if (get_user_u64(cap, gcspr)) {
+ return false;
+ }
+ if (cap != GCS_SIGNAL_CAP(gcspr)) {
+ return false;
+ }
+ if (put_user_u64(0, gcspr)) {
+ return false;
+ }
+ gcspr += 8;
+ } else {
+ new_mode = 0;
+ }
+
+ env->cp15.gcspr_el[0] = gcspr;
+ if (new_mode != cur_mode) {
+ *rebuild_hflags = true;
+ gcs_set_el0_mode(env, new_mode);
+ }
+ return true;
+}
+
static int target_restore_sigframe(CPUARMState *env,
struct target_rt_sigframe *sf)
{
@@ -511,8 +600,10 @@ static int target_restore_sigframe(CPUARMState *env,
struct target_za_context *za = NULL;
struct target_tpidr2_context *tpidr2 = NULL;
struct target_zt_context *zt = NULL;
+ struct target_gcs_context *gcs = NULL;
uint64_t extra_datap = 0;
bool used_extra = false;
+ bool rebuild_hflags = false;
int sve_size = 0;
int za_size = 0;
int zt_size = 0;
@@ -582,6 +673,15 @@ static int target_restore_sigframe(CPUARMState *env,
zt_size = size;
break;
+ case TARGET_GCS_MAGIC:
+ if (gcs
+ || size != sizeof(struct target_gcs_context)
+ || !cpu_isar_feature(aa64_gcs, env_archcpu(env))) {
+ goto err;
+ }
+ gcs = (struct target_gcs_context *)ctx;
+ break;
+
case TARGET_EXTRA_MAGIC:
if (extra || size != sizeof(struct target_extra_context)) {
goto err;
@@ -612,6 +712,10 @@ static int target_restore_sigframe(CPUARMState *env,
goto err;
}
+ if (gcs && !target_restore_gcs_record(env, gcs, &rebuild_hflags)) {
+ goto err;
+ }
+
/* SVE data, if present, overwrites FPSIMD data. */
if (sve && !target_restore_sve_record(env, sve, sve_size, &svcr)) {
goto err;
@@ -631,6 +735,9 @@ static int target_restore_sigframe(CPUARMState *env,
}
if (env->svcr != svcr) {
env->svcr = svcr;
+ rebuild_hflags = true;
+ }
+ if (rebuild_hflags) {
arm_rebuild_hflags(env);
}
unlock_user(extra, extra_datap, 0);
@@ -701,7 +808,7 @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
uc.tuc_mcontext.__reserved),
};
int fpsimd_ofs, fr_ofs, sve_ofs = 0, za_ofs = 0, tpidr2_ofs = 0;
- int zt_ofs = 0, esr_ofs = 0;
+ int zt_ofs = 0, esr_ofs = 0, gcs_ofs = 0;
int sve_size = 0, za_size = 0, tpidr2_size = 0, zt_size = 0;
struct target_rt_sigframe *frame;
struct target_rt_frame_record *fr;
@@ -720,6 +827,11 @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
&layout);
}
+ if (env->cp15.gcspr_el[0]) {
+ gcs_ofs = alloc_sigframe_space(sizeof(struct target_gcs_context),
+ &layout);
+ }
+
/* SVE state needs saving only if it exists. */
if (cpu_isar_feature(aa64_sve, env_archcpu(env)) ||
cpu_isar_feature(aa64_sme, env_archcpu(env))) {
@@ -779,6 +891,12 @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
goto give_sigsegv;
}
+ if (ka->sa_flags & TARGET_SA_RESTORER) {
+ return_addr = ka->sa_restorer;
+ } else {
+ return_addr = default_rt_sigreturn;
+ }
+
target_setup_general_frame(frame, env, set);
target_setup_fpsimd_record((void *)frame + fpsimd_ofs, env);
if (esr_ofs) {
@@ -786,6 +904,10 @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
/* Leave ESR_EL1 clear while it's not relevant. */
env->cp15.esr_el[1] = 0;
}
+ if (gcs_ofs &&
+ !target_setup_gcs_record((void *)frame + gcs_ofs, env, return_addr)) {
+ goto give_sigsegv;
+ }
target_setup_end_record((void *)frame + layout.std_end_ofs);
if (layout.extra_ofs) {
target_setup_extra_record((void *)frame + layout.extra_ofs,
@@ -811,11 +933,6 @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
__put_user(env->xregs[29], &fr->fp);
__put_user(env->xregs[30], &fr->lr);
- if (ka->sa_flags & TARGET_SA_RESTORER) {
- return_addr = ka->sa_restorer;
- } else {
- return_addr = default_rt_sigreturn;
- }
env->xregs[0] = usig;
env->xregs[29] = frame_addr + fr_ofs;
env->xregs[30] = return_addr;
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 78/82] linux-user: Change exported get_elf_hwcap to abi_ulong
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (76 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 77/82] linux-user/aarch64: Generate GCS signal records Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:58 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 79/82] linux-user/aarch64: Enable GCS in HWCAP Richard Henderson
` (3 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
AArch64 is about to add the first 64-bit hwcap bit, so we
have to expand the return type. Since the only user
assigns this to a abi_ulong, match that type.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/loader.h | 2 +-
linux-user/elfload.c | 10 +++++-----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/linux-user/loader.h b/linux-user/loader.h
index e102e6f410..e1badd4393 100644
--- a/linux-user/loader.h
+++ b/linux-user/loader.h
@@ -99,7 +99,7 @@ abi_long memcpy_to_target(abi_ulong dest, const void *src,
extern unsigned long guest_stack_size;
#if defined(TARGET_S390X) || defined(TARGET_AARCH64) || defined(TARGET_ARM)
-uint32_t get_elf_hwcap(void);
+abi_ulong get_elf_hwcap(void);
const char *elf_hwcap_str(uint32_t bit);
#endif
#if defined(TARGET_AARCH64) || defined(TARGET_ARM)
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index ea214105ff..d87d1a16e0 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -511,10 +511,10 @@ static bool init_guest_commpage(void)
#define ELF_HWCAP get_elf_hwcap()
#define ELF_HWCAP2 get_elf_hwcap2()
-uint32_t get_elf_hwcap(void)
+abi_ulong get_elf_hwcap(void)
{
ARMCPU *cpu = ARM_CPU(thread_cpu);
- uint32_t hwcaps = 0;
+ abi_ulong hwcaps = 0;
hwcaps |= ARM_HWCAP_ARM_SWP;
hwcaps |= ARM_HWCAP_ARM_HALF;
@@ -841,10 +841,10 @@ enum {
#define GET_FEATURE_ID(feat, hwcap) \
do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0)
-uint32_t get_elf_hwcap(void)
+abi_ulong get_elf_hwcap(void)
{
ARMCPU *cpu = ARM_CPU(thread_cpu);
- uint32_t hwcaps = 0;
+ abi_ulong hwcaps = 0;
hwcaps |= ARM_HWCAP_A64_FP;
hwcaps |= ARM_HWCAP_A64_ASIMD;
@@ -1824,7 +1824,7 @@ static inline void init_thread(struct target_pt_regs *regs,
#define GET_FEATURE(_feat, _hwcap) \
do { if (s390_has_feat(_feat)) { hwcap |= _hwcap; } } while (0)
-uint32_t get_elf_hwcap(void)
+abi_ulong get_elf_hwcap(void)
{
/*
* Let's assume we always have esan3 and zarch.
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 79/82] linux-user/aarch64: Enable GCS in HWCAP
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (77 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 78/82] linux-user: Change exported get_elf_hwcap to abi_ulong Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 21:58 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 80/82] tests/tcg/aarch64: Add gcsstr Richard Henderson
` (2 subsequent siblings)
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/elfload.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index d87d1a16e0..e71dcdec1b 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -877,6 +877,7 @@ abi_ulong get_elf_hwcap(void)
GET_FEATURE_ID(aa64_dcpop, ARM_HWCAP_A64_DCPOP);
GET_FEATURE_ID(aa64_rcpc_8_3, ARM_HWCAP_A64_LRCPC);
GET_FEATURE_ID(aa64_rcpc_8_4, ARM_HWCAP_A64_ILRCPC);
+ GET_FEATURE_ID(aa64_gcs, ARM_HWCAP_A64_GCS);
return hwcaps;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 80/82] tests/tcg/aarch64: Add gcsstr
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (78 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 79/82] linux-user/aarch64: Enable GCS in HWCAP Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 22:05 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 81/82] tests/tcg/aarch64: Add gcspushm Richard Henderson
2025-07-27 8:02 ` [PATCH 82/82] tests/tcg/aarch64: Add gcsss Richard Henderson
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Add some infrastructure for testing gcs in userspace.
Validate successful and trapped executions of GCSSTR.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tests/tcg/aarch64/gcs.h | 71 +++++++++++++++++++++++++++++++
tests/tcg/aarch64/gcsstr.c | 48 +++++++++++++++++++++
tests/tcg/aarch64/Makefile.target | 5 +++
3 files changed, 124 insertions(+)
create mode 100644 tests/tcg/aarch64/gcs.h
create mode 100644 tests/tcg/aarch64/gcsstr.c
diff --git a/tests/tcg/aarch64/gcs.h b/tests/tcg/aarch64/gcs.h
new file mode 100644
index 0000000000..99cb4d4e38
--- /dev/null
+++ b/tests/tcg/aarch64/gcs.h
@@ -0,0 +1,71 @@
+/*
+ * Linux kernel fallback API definitions for GCS and test helpers.
+ *
+ * Copyright (c) 2025 Linaro Ltd
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <sys/prctl.h>
+#include <sys/syscall.h>
+
+#ifndef PR_GET_SHADOW_STACK_STATUS
+#define PR_GET_SHADOW_STACK_STATUS 74
+#endif
+#ifndef PR_SET_SHADOW_STACK_STATUS
+#define PR_SET_SHADOW_STACK_STATUS 75
+#endif
+#ifndef PR_LOCK_SHADOW_STACK_STATUS
+#define PR_LOCK_SHADOW_STACK_STATUS 76
+#endif
+#ifndef PR_SHADOW_STACK_ENABLE
+# define PR_SHADOW_STACK_ENABLE (1 << 0)
+# define PR_SHADOW_STACK_WRITE (1 << 1)
+# define PR_SHADOW_STACK_PUSH (1 << 2)
+#endif
+#ifndef SHADOW_STACK_SET_TOKEN
+#define SHADOW_STACK_SET_TOKEN (1 << 0)
+#endif
+#ifndef SHADOW_STACK_SET_MARKER
+#define SHADOW_STACK_SET_MARKER (1 << 1)
+#endif
+#ifndef SEGV_CPERR
+#define SEGV_CPERR 10
+#endif
+#ifndef __NR_map_shadow_stack
+#define __NR_map_shadow_stack 453
+#endif
+
+/*
+ * Macros, and implement the syscall inline, lest we fail
+ * the checked return from any function call.
+ */
+#define enable_gcs(flags) \
+ do { \
+ register long num __asm__ ("x8") = __NR_prctl; \
+ register long arg1 __asm__ ("x0") = PR_SET_SHADOW_STACK_STATUS; \
+ register long arg2 __asm__ ("x1") = PR_SHADOW_STACK_ENABLE | flags; \
+ register long arg3 __asm__ ("x2") = 0; \
+ register long arg4 __asm__ ("x3") = 0; \
+ register long arg5 __asm__ ("x4") = 0; \
+ asm volatile("svc #0" \
+ : "+r"(arg1) \
+ : "r"(arg2), "r"(arg3), "r"(arg4), "r"(arg5), "r"(num) \
+ : "memory", "cc"); \
+ if (arg1) { \
+ errno = -arg1; \
+ perror("PR_SET_SHADOW_STACK_STATUS"); \
+ exit(2); \
+ } \
+ } while (0)
+
+#define gcspr() \
+ ({ uint64_t *r; asm volatile("mrs %0, s3_3_c2_c5_1" : "=r"(r)); r; })
diff --git a/tests/tcg/aarch64/gcsstr.c b/tests/tcg/aarch64/gcsstr.c
new file mode 100644
index 0000000000..b045aee925
--- /dev/null
+++ b/tests/tcg/aarch64/gcsstr.c
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "gcs.h"
+
+/*
+ * A single garbage store to the gcs stack.
+ * The asm inside must be unique, so disallow inlining.
+ */
+void __attribute__((noinline))
+test_gcsstr(void)
+{
+ register uint64_t *ptr __asm__("x0") = gcspr();
+ /* GCSSTR x1, x0 */
+ __asm__("inst_gcsstr: .inst 0xd91f1c01" : : "r"(--ptr));
+}
+
+static void test_sigsegv(int sig, siginfo_t *info, void *vuc)
+{
+ ucontext_t *uc = vuc;
+ uint64_t inst_gcsstr;
+
+ __asm__("adr %0, inst_gcsstr" : "=r"(inst_gcsstr));
+ assert(uc->uc_mcontext.pc == inst_gcsstr);
+ assert(info->si_code == SEGV_CPERR);
+ /* TODO: Dig for ESR and verify syndrome. */
+ exit(0);
+}
+
+int main()
+{
+ struct sigaction sa = {
+ .sa_sigaction = test_sigsegv,
+ .sa_flags = SA_SIGINFO,
+ };
+
+ /* Enable GCSSTR and test the store succeeds. */
+ enable_gcs(PR_SHADOW_STACK_WRITE);
+ test_gcsstr();
+
+ /* Disable GCSSTR and test the resulting sigsegv. */
+ enable_gcs(0);
+ if (sigaction(SIGSEGV, &sa, NULL) < 0) {
+ perror("sigaction");
+ exit(1);
+ }
+ test_gcsstr();
+ abort();
+}
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
index 16ddcf4f88..0347a36e8d 100644
--- a/tests/tcg/aarch64/Makefile.target
+++ b/tests/tcg/aarch64/Makefile.target
@@ -75,6 +75,11 @@ AARCH64_TESTS += $(SME_TESTS)
$(SME_TESTS): CFLAGS += $(CROSS_AS_HAS_ARMV9_SME)
endif
+# GCS Tests
+GCS_TESTS += gcsstr
+AARCH64_TESTS += $(GCS_TESTS)
+$(GCS_TESTS): gcs.h
+
# System Registers Tests
AARCH64_TESTS += sysregs
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 81/82] tests/tcg/aarch64: Add gcspushm
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (79 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 80/82] tests/tcg/aarch64: Add gcsstr Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 22:11 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 82/82] tests/tcg/aarch64: Add gcsss Richard Henderson
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Validate successful and trapped executions of GCSPUSHM, GCSPOPM.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tests/tcg/aarch64/gcspushm.c | 77 +++++++++++++++++++++++++++++++
tests/tcg/aarch64/Makefile.target | 2 +-
2 files changed, 78 insertions(+), 1 deletion(-)
create mode 100644 tests/tcg/aarch64/gcspushm.c
diff --git a/tests/tcg/aarch64/gcspushm.c b/tests/tcg/aarch64/gcspushm.c
new file mode 100644
index 0000000000..0c7cc09065
--- /dev/null
+++ b/tests/tcg/aarch64/gcspushm.c
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "gcs.h"
+
+
+#define GCSPUSHM "sys #3, c7, c7, #0, %[push]"
+#define GCSPOPM "sysl %[pop], #3, c7, c7, #1"
+
+static volatile uint64_t test_pc;
+
+static void test_sigsegv(int sig, siginfo_t *info, void *vuc)
+{
+ ucontext_t *uc = vuc;
+
+ assert(uc->uc_mcontext.pc == test_pc);
+ assert(info->si_code == SEGV_CPERR);
+ /* TODO: Dig for ESR and verify syndrome. */
+ uc->uc_mcontext.pc += 4;
+}
+
+static void test_sigill(int sig, siginfo_t *info, void *vuc)
+{
+ ucontext_t *uc = vuc;
+
+ assert(uc->uc_mcontext.pc == test_pc);
+ assert(info->si_code == ILL_ILLOPC);
+ uc->uc_mcontext.pc += 4;
+}
+
+int main()
+{
+ struct sigaction sa = { .sa_flags = SA_SIGINFO };
+ uint64_t tmp, old, new;
+
+ enable_gcs(PR_SHADOW_STACK_PUSH);
+
+ /* Valid value -- low 2 bits clear */
+ old = 0xdeadbeeffeedcaec;
+ asm volatile(GCSPUSHM "\n\t" GCSPOPM
+ : [pop] "=r" (new)
+ : [push] "r" (old));
+ assert(old == new);
+
+ sa.sa_sigaction = test_sigsegv;
+ if (sigaction(SIGSEGV, &sa, NULL) < 0) {
+ perror("sigaction");
+ exit(1);
+ }
+
+ /* Invalid value -- SIGSEGV via EC_GCS */
+ asm volatile("adr %[tmp], 0f\n\t"
+ "str %[tmp], %[test]\n\t"
+ GCSPUSHM "\n"
+ "0:" GCSPOPM
+ : [tmp] "=&r" (tmp),
+ [test] "=m" (test_pc),
+ [pop] "=r" (new)
+ : [push] "r" (1));
+
+ enable_gcs(0);
+
+ sa.sa_sigaction = test_sigill;
+ if (sigaction(SIGILL, &sa, NULL) < 0) {
+ perror("sigaction");
+ exit(1);
+ }
+
+ /* Pushm is disabled -- SIGILL via EC_SYSTEMREGISTERTRAP */
+ asm volatile("adr %[tmp], 0f\n\t"
+ "str %[tmp], %[test]\n"
+ "0:\t" GCSPUSHM
+ : [tmp] "=&r" (tmp),
+ [test] "=m" (test_pc)
+ : [push] "r" (1));
+
+ exit(0);
+}
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
index 0347a36e8d..c6f401c317 100644
--- a/tests/tcg/aarch64/Makefile.target
+++ b/tests/tcg/aarch64/Makefile.target
@@ -76,7 +76,7 @@ $(SME_TESTS): CFLAGS += $(CROSS_AS_HAS_ARMV9_SME)
endif
# GCS Tests
-GCS_TESTS += gcsstr
+GCS_TESTS += gcsstr gcspushm
AARCH64_TESTS += $(GCS_TESTS)
$(GCS_TESTS): gcs.h
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* [PATCH 82/82] tests/tcg/aarch64: Add gcsss
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
` (80 preceding siblings ...)
2025-07-27 8:02 ` [PATCH 81/82] tests/tcg/aarch64: Add gcspushm Richard Henderson
@ 2025-07-27 8:02 ` Richard Henderson
2025-07-31 22:14 ` Pierrick Bouvier
81 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-07-27 8:02 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Validate stack switching and recursion depth.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tests/tcg/aarch64/gcs.h | 9 ++++
tests/tcg/aarch64/gcsss.c | 74 +++++++++++++++++++++++++++++++
tests/tcg/aarch64/Makefile.target | 2 +-
3 files changed, 84 insertions(+), 1 deletion(-)
create mode 100644 tests/tcg/aarch64/gcsss.c
diff --git a/tests/tcg/aarch64/gcs.h b/tests/tcg/aarch64/gcs.h
index 99cb4d4e38..e821963cb8 100644
--- a/tests/tcg/aarch64/gcs.h
+++ b/tests/tcg/aarch64/gcs.h
@@ -69,3 +69,12 @@
#define gcspr() \
({ uint64_t *r; asm volatile("mrs %0, s3_3_c2_c5_1" : "=r"(r)); r; })
+
+#define gcsss1(val) \
+ do { \
+ asm volatile("sys #3, c7, c7, #2, %0" : : "r"(val) : "memory"); \
+ } while (0)
+
+#define gcsss2() \
+ ({ uint64_t *r; \
+ asm volatile("sysl %0, #3, c7, c7, #3" : "=r"(r) : : "memory"); r; })
diff --git a/tests/tcg/aarch64/gcsss.c b/tests/tcg/aarch64/gcsss.c
new file mode 100644
index 0000000000..9550c68e7e
--- /dev/null
+++ b/tests/tcg/aarch64/gcsss.c
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "gcs.h"
+
+#define IN_PROGRESS(X) ((uint64_t)(X) | 5)
+#define CAP(X) (((uint64_t)(X) & ~0xfff) + 1)
+
+static uint64_t * __attribute__((noinline)) recurse(size_t index)
+{
+ if (index == 0) {
+ return gcspr();
+ }
+ return recurse(index - 1);
+}
+
+int main()
+{
+ void *tmp;
+ uint64_t *alt_stack, *alt_cap;
+ uint64_t *orig_pr, *orig_cap;
+ uint64_t *bottom;
+ size_t pagesize = getpagesize();
+ size_t words;
+
+ enable_gcs(0);
+ orig_pr = gcspr();
+
+ /* Allocate a guard page before and after. */
+ tmp = mmap(0, 3 * pagesize, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
+ assert(tmp != MAP_FAILED);
+
+ /* map_shadow_stack won't replace existing mappings */
+ munmap(tmp + pagesize, pagesize);
+
+ /* Allocate a new stack between the guards. */
+ alt_stack = (uint64_t *)
+ syscall(__NR_map_shadow_stack, tmp + pagesize, pagesize,
+ SHADOW_STACK_SET_TOKEN);
+ assert(alt_stack == tmp + pagesize);
+
+ words = pagesize / 8;
+ alt_cap = alt_stack + words - 1;
+
+ /* SHADOW_STACK_SET_TOKEN set the cap. */
+ assert(*alt_cap == CAP(alt_cap));
+
+ /* Swap to the alt stack, one step at a time. */
+ gcsss1(alt_cap);
+
+ assert(gcspr() == alt_cap);
+ assert(*alt_cap == IN_PROGRESS(orig_pr));
+
+ orig_cap = gcsss2();
+
+ assert(orig_cap == orig_pr - 1);
+ assert(*orig_cap == CAP(orig_cap));
+ assert(gcspr() == alt_stack + words);
+
+ /* We should be able to use the whole stack. */
+ bottom = recurse(words - 1);
+ assert(bottom == alt_stack);
+
+ /* We should be back where we started. */
+ assert(gcspr() == alt_stack + words);
+
+ /* Swap back to the original stack. */
+ gcsss1(orig_cap);
+ tmp = gcsss2();
+
+ assert(gcspr() == orig_pr);
+ assert(tmp == alt_cap);
+
+ exit(0);
+}
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
index c6f401c317..b858f8692e 100644
--- a/tests/tcg/aarch64/Makefile.target
+++ b/tests/tcg/aarch64/Makefile.target
@@ -76,7 +76,7 @@ $(SME_TESTS): CFLAGS += $(CROSS_AS_HAS_ARMV9_SME)
endif
# GCS Tests
-GCS_TESTS += gcsstr gcspushm
+GCS_TESTS += gcsstr gcspushm gcsss
AARCH64_TESTS += $(GCS_TESTS)
$(GCS_TESTS): gcs.h
--
2.43.0
^ permalink raw reply related [flat|nested] 188+ messages in thread
* Re: [PATCH 46/82] target/arm: Implement FEAT_CHK
2025-07-27 8:02 ` [PATCH 46/82] target/arm: Implement FEAT_CHK Richard Henderson
@ 2025-07-29 16:01 ` Gustavo Romero
2025-07-29 17:21 ` Richard Henderson
2025-07-31 18:59 ` Pierrick Bouvier
1 sibling, 1 reply; 188+ messages in thread
From: Gustavo Romero @ 2025-07-29 16:01 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
Hi Richard,
On 7/27/25 05:02, Richard Henderson wrote:
> This feature contains only the CHKFEAT instruction. It has
> no ID enable, being back-allocated into the hint nop space.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/tcg/translate-a64.c | 14 ++++++++++++++
> docs/system/arm/emulation.rst | 1 +
> target/arm/tcg/a64.decode | 1 +
> 3 files changed, 16 insertions(+)
>
> diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
> index 7831b3dab3..34d22cac8a 100644
> --- a/target/arm/tcg/translate-a64.c
> +++ b/target/arm/tcg/translate-a64.c
> @@ -2124,6 +2124,20 @@ static bool trans_AUTIBSP(DisasContext *s, arg_AUTIBSP *a)
> return true;
> }
>
> +static bool trans_CHKFEAT(DisasContext *s, arg_CHKFEAT *a)
> +{
> + uint64_t feat_en = 0;
> +
> + if (s->gcs_en) {
> + feat_en |= 1 << 0;
I understand that CHKFEAT is currently only tied to GCS but will cover more features
in the future so we can keep feat_en |= 1 << 0 even if it could gate TCG andi directly
on s->gcs_en and do andi with 0. ok.
It's curious that this instruction is tied to x16, it seems easy to use any other
general purpose register to query for the features.
> + }
> + if (feat_en) {
> + TCGv_i64 x16 = cpu_reg(s, 16);
> + tcg_gen_andi_i64(x16, x16, ~feat_en);
> + }
> + return true;
> +}
> +
> static bool trans_CLREX(DisasContext *s, arg_CLREX *a)
> {
> tcg_gen_movi_i64(cpu_exclusive_addr, -1);
> diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
> index 6ebf9c9ce9..b894aced89 100644
> --- a/docs/system/arm/emulation.rst
> +++ b/docs/system/arm/emulation.rst
> @@ -28,6 +28,7 @@ the following architecture extensions:
> - FEAT_BF16 (AArch64 BFloat16 instructions)
> - FEAT_BTI (Branch Target Identification)
> - FEAT_CCIDX (Extended cache index)
> +- FEAT_CHK (Check Feature Status)
> - FEAT_CMOW (Control for cache maintenance permission)
> - FEAT_CRC32 (CRC32 instructions)
> - FEAT_Crypto (Cryptographic Extension)
> diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
> index 8c798cde2b..4315ed8dab 100644
> --- a/target/arm/tcg/a64.decode
> +++ b/target/arm/tcg/a64.decode
> @@ -246,6 +246,7 @@ ERETA 1101011 0100 11111 00001 m:1 11111 11111 &reta # ERETAA, ERETAB
> AUTIASP 1101 0101 0000 0011 0010 0011 101 11111
> AUTIBZ 1101 0101 0000 0011 0010 0011 110 11111
> AUTIBSP 1101 0101 0000 0011 0010 0011 111 11111
> + CHKFEAT 1101 0101 0000 0011 0010 0101 000 11111
> ]
> # The canonical NOP has CRm == op2 == 0, but all of the space
> # that isn't specifically allocated to an instruction must NOP
Reviewed-by: Gustavo Romero <gustavo.romero@linaro.org>
Cheers,
Gustavo
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 46/82] target/arm: Implement FEAT_CHK
2025-07-29 16:01 ` Gustavo Romero
@ 2025-07-29 17:21 ` Richard Henderson
0 siblings, 0 replies; 188+ messages in thread
From: Richard Henderson @ 2025-07-29 17:21 UTC (permalink / raw)
To: Gustavo Romero, qemu-devel; +Cc: qemu-arm
On 7/29/25 06:01, Gustavo Romero wrote:
>> +static bool trans_CHKFEAT(DisasContext *s, arg_CHKFEAT *a)
>> +{
>> + uint64_t feat_en = 0;
>> +
>> + if (s->gcs_en) {
>> + feat_en |= 1 << 0;
>
> I understand that CHKFEAT is currently only tied to GCS but will cover more features
> in the future so we can keep feat_en |= 1 << 0 even if it could gate TCG andi directly
> on s->gcs_en and do andi with 0. ok.
Yep.
>
> It's curious that this instruction is tied to x16, it seems easy to use any other
> general purpose register to query for the features.
That's because the instruction is allocated from HINT space, which means that it executes
as a NOP on cpus that don't support FEAT_CHK. The HINT space is limited, and it would be
wastefull to allocate 32 such insns, one for each register.
r~
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 01/82] target/arm: Add prot_check parameter to pmsav8_mpu_lookup
2025-07-27 8:01 ` [PATCH 01/82] target/arm: Add prot_check parameter to pmsav8_mpu_lookup Richard Henderson
@ 2025-07-30 20:27 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 20:27 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> Separate the access_type from the protection check.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/internals.h | 5 +++--
> target/arm/ptw.c | 11 ++++++-----
> target/arm/tcg/m_helper.c | 4 ++--
> 3 files changed, 11 insertions(+), 9 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 02/82] target/arm: Add in_prot_check to S1Translate
2025-07-27 8:01 ` [PATCH 02/82] target/arm: Add in_prot_check to S1Translate Richard Henderson
@ 2025-07-30 20:27 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 20:27 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> Separate the access_type from the protection check.
> Save the trouble of modifying all helper functions
> by passing the new data in the control structure.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/ptw.c | 19 ++++++++++++++-----
> 1 file changed, 14 insertions(+), 5 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 03/82] target/arm: Skip permission check from arm_cpu_get_phys_page_attrs_debug
2025-07-27 8:01 ` [PATCH 03/82] target/arm: Skip permission check from arm_cpu_get_phys_page_attrs_debug Richard Henderson
@ 2025-07-30 20:28 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 20:28 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> Do not require read permission when translating addresses
> for debugging purposes.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/ptw.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 04/82] target/arm: Introduce get_phys_addr_for_at
2025-07-27 8:01 ` [PATCH 04/82] target/arm: Introduce get_phys_addr_for_at Richard Henderson
@ 2025-07-30 20:29 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 20:29 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> Rename get_phys_addr_with_space_nogpc for its only
> caller, do_ats_write. Drop the MemOp memop argument
> as it doesn't make sense in the new context. Replace
> the access_type parameter with prot_check.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/internals.h | 18 +++++++-----------
> target/arm/ptw.c | 21 ++++++++++++++-------
> target/arm/tcg/cpregs-at.c | 11 ++---------
> 3 files changed, 23 insertions(+), 27 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 05/82] target/arm: Skip AF and DB updates for AccessType_AT
2025-07-27 8:01 ` [PATCH 05/82] target/arm: Skip AF and DB updates for AccessType_AT Richard Henderson
@ 2025-07-30 20:31 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 20:31 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> We are required to skip DB update for AT instructions, and
> we are allowed to skip AF updates. Choose to skip both.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/ptw.c | 15 ++++++++++++++-
> 1 file changed, 14 insertions(+), 1 deletion(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 06/82] target/arm: Add prot_check parameter to do_ats_write
2025-07-27 8:01 ` [PATCH 06/82] target/arm: Add prot_check parameter to do_ats_write Richard Henderson
@ 2025-07-30 20:35 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 20:35 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> Separate protection check from access type, in preparation
> for skipping the protection check altogether.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/tcg/cpregs-at.c | 16 ++++++++--------
> 1 file changed, 8 insertions(+), 8 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 07/82] target/arm: Fill in HFG[RWI]TR_EL2 bits for Arm v9.5
2025-07-27 8:01 ` [PATCH 07/82] target/arm: Fill in HFG[RWI]TR_EL2 bits for Arm v9.5 Richard Henderson
@ 2025-07-30 20:35 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 20:35 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/cpregs.h | 28 ++++++++++++++++++++++++++--
> 1 file changed, 26 insertions(+), 2 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 08/82] target/arm: Remove outdated comment for ZCR_EL12
2025-07-27 8:01 ` [PATCH 08/82] target/arm: Remove outdated comment for ZCR_EL12 Richard Henderson
@ 2025-07-30 20:36 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 20:36 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> The comment about not being included in the summary table
> has been out of date for quite a while.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/helper.c | 5 -----
> 1 file changed, 5 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 09/82] target/arm: Implement FEAT_ATS1A
2025-07-27 8:01 ` [PATCH 09/82] target/arm: Implement FEAT_ATS1A Richard Henderson
@ 2025-07-30 20:38 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 20:38 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> Implement FEAT_ATS1A and enable for -cpu max.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/cpregs.h | 1 +
> target/arm/cpu-features.h | 5 ++++
> target/arm/tcg/cpregs-at.c | 44 +++++++++++++++++++++++++++++++++++
> target/arm/tcg/cpu64.c | 1 +
> docs/system/arm/emulation.rst | 1 +
> 5 files changed, 52 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 10/82] target/arm: Add isar feature test for FEAT_S1PIE, FEAT_S2PIE
2025-07-27 8:01 ` [PATCH 10/82] target/arm: Add isar feature test for FEAT_S1PIE, FEAT_S2PIE Richard Henderson
@ 2025-07-30 20:38 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 20:38 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/cpu-features.h | 10 ++++++++++
> 1 file changed, 10 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 11/82] target/arm: Enable TCR2_ELx.PIE
2025-07-27 8:01 ` [PATCH 11/82] target/arm: Enable TCR2_ELx.PIE Richard Henderson
@ 2025-07-30 20:39 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 20:39 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/helper.c | 10 +++++++++-
> 1 file changed, 9 insertions(+), 1 deletion(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 12/82] target/arm: Implement PIR_ELx, PIRE0_ELx, S2PIR_EL2 registers
2025-07-27 8:01 ` [PATCH 12/82] target/arm: Implement PIR_ELx, PIRE0_ELx, S2PIR_EL2 registers Richard Henderson
@ 2025-07-30 20:41 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 20:41 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/cpregs.h | 2 ++
> target/arm/cpu.h | 4 +++
> target/arm/cpu.c | 4 +++
> target/arm/helper.c | 70 +++++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 80 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 13/82] target/arm: Force HPD for stage2 translations
2025-07-27 8:01 ` [PATCH 13/82] target/arm: Force HPD for stage2 translations Richard Henderson
@ 2025-07-30 20:42 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 20:42 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> Stage2 translations do not have hierarchial permissions.
> Setting HPD means we can eliminate an extra check against
> regime_is_stage2.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/helper.c | 7 +++++--
> target/arm/ptw.c | 24 +++++++++++++-----------
> 2 files changed, 18 insertions(+), 13 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 14/82] target/arm: Cache NV1 early in get_phys_addr_lpae
2025-07-27 8:01 ` [PATCH 14/82] target/arm: Cache NV1 early in get_phys_addr_lpae Richard Henderson
@ 2025-07-30 20:43 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 20:43 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> We were not using the correct security space in the existing call
> to nv_nv1_enabled, because it may have been modified for NSTable.
>
> Cache it early, as we will shortly need it elsewhere as well.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/ptw.c | 14 +++++++-------
> 1 file changed, 7 insertions(+), 7 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 15/82] target/arm: Populate PIE in aa64_va_parameters
2025-07-27 8:01 ` [PATCH 15/82] target/arm: Populate PIE in aa64_va_parameters Richard Henderson
@ 2025-07-30 20:45 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 20:45 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> Select the PIE bit for the translation regime.
> With PIE, the PTE layout changes, forcing HPD.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/internals.h | 3 ++-
> target/arm/helper.c | 19 ++++++++++++++++++-
> 2 files changed, 20 insertions(+), 2 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 18/82] target/arm: Do not migrate env->exception
2025-07-27 8:01 ` [PATCH 18/82] target/arm: Do not migrate env->exception Richard Henderson
@ 2025-07-30 20:46 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 20:46 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> These are not architectural state, only placeholders
> between identifying the exception and delivering it.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/machine.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 19/82] target/arm: Expand CPUARMState.exception.syndrome to 64 bits
2025-07-27 8:01 ` [PATCH 19/82] target/arm: Expand CPUARMState.exception.syndrome to 64 bits Richard Henderson
@ 2025-07-30 20:47 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 20:47 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> This will be used for storing the ISS2 portion of the
> ESR_ELx registers in aarch64 state. Re-order the fsr
> member to eliminate two structure holes.
>
> Drop the comment about "if we implement EL2" since we
> have already done so.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/cpu.h | 7 ++-----
> target/arm/helper.c | 2 +-
> 2 files changed, 3 insertions(+), 6 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 20/82] target/arm: Expand syndrome parameter to raise_exception*
2025-07-27 8:01 ` [PATCH 20/82] target/arm: Expand syndrome parameter to raise_exception* Richard Henderson
@ 2025-07-30 20:47 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 20:47 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> Prepare for raising exceptions with 64-bit syndromes.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/internals.h | 6 +++---
> target/arm/tcg-stubs.c | 2 +-
> target/arm/tcg/op_helper.c | 4 ++--
> 3 files changed, 6 insertions(+), 6 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 21/82] target/arm: Implement dirtybit check for PIE
2025-07-27 8:01 ` [PATCH 21/82] target/arm: Implement dirtybit check for PIE Richard Henderson
@ 2025-07-30 20:50 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 20:50 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> Both S1PIE and S2PIE have a bit to make software tracking
> of dirty pages easier.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/internals.h | 1 +
> target/arm/ptw.c | 16 ++++++++++++++++
> target/arm/tcg/tlb_helper.c | 12 +++++++++---
> 3 files changed, 26 insertions(+), 3 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 22/82] target/arm: Enable FEAT_S1PIE and FEAT_S2PIE on -cpu max
2025-07-27 8:01 ` [PATCH 22/82] target/arm: Enable FEAT_S1PIE and FEAT_S2PIE on -cpu max Richard Henderson
@ 2025-07-30 20:50 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 20:50 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/tcg/cpu64.c | 2 ++
> docs/system/arm/emulation.rst | 2 ++
> 2 files changed, 4 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 23/82] include/hw/core/cpu: Introduce MMUIdxMap
2025-07-27 8:01 ` [PATCH 23/82] include/hw/core/cpu: Introduce MMUIdxMap Richard Henderson
@ 2025-07-30 20:52 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 20:52 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> Use a typedef instead of uint16_t directly when
> describing sets of mmu indexes.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> include/exec/cputlb.h | 32 ++++++++++++++++----------------
> include/hw/core/cpu.h | 6 +++---
> accel/tcg/cputlb.c | 30 +++++++++++++++---------------
> 3 files changed, 34 insertions(+), 34 deletions(-)
That's cleaner, and definitely help to see we're going to increase the
number of mmu indexes.
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 24/82] include/hw/core/cpu: Introduce cpu_tlb_fast
2025-07-27 8:01 ` [PATCH 24/82] include/hw/core/cpu: Introduce cpu_tlb_fast Richard Henderson
@ 2025-07-30 20:53 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 20:53 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> Encapsulate access to cpu->neg.tlb.f[] in a function.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> include/hw/core/cpu.h | 7 +++++++
> accel/tcg/cputlb.c | 16 ++++++++--------
> 2 files changed, 15 insertions(+), 8 deletions(-)
>
> diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
> index 1153cadb70..bd835b07d5 100644
> --- a/include/hw/core/cpu.h
> +++ b/include/hw/core/cpu.h
> @@ -593,6 +593,13 @@ static inline CPUArchState *cpu_env(CPUState *cpu)
> return (CPUArchState *)(cpu + 1);
> }
>
> +#ifdef CONFIG_TCG
> +static inline CPUTLBDescFast *cpu_tlb_fast(CPUState *cpu, int mmu_idx)
> +{
> + return &cpu->neg.tlb.f[mmu_idx];
> +}
> +#endif
> +
> typedef QTAILQ_HEAD(CPUTailQ, CPUState) CPUTailQ;
> extern CPUTailQ cpus_queue;
>
> diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
> index d324f33339..2a6aa01c57 100644
> --- a/accel/tcg/cputlb.c
> +++ b/accel/tcg/cputlb.c
> @@ -129,7 +129,7 @@ static inline uint64_t tlb_addr_write(const CPUTLBEntry *entry)
> static inline uintptr_t tlb_index(CPUState *cpu, uintptr_t mmu_idx,
> vaddr addr)
> {
> - uintptr_t size_mask = cpu->neg.tlb.f[mmu_idx].mask >> CPU_TLB_ENTRY_BITS;
> + uintptr_t size_mask = cpu_tlb_fast(cpu, mmu_idx)->mask >> CPU_TLB_ENTRY_BITS;
>
> return (addr >> TARGET_PAGE_BITS) & size_mask;
> }
> @@ -138,7 +138,7 @@ static inline uintptr_t tlb_index(CPUState *cpu, uintptr_t mmu_idx,
> static inline CPUTLBEntry *tlb_entry(CPUState *cpu, uintptr_t mmu_idx,
> vaddr addr)
> {
> - return &cpu->neg.tlb.f[mmu_idx].table[tlb_index(cpu, mmu_idx, addr)];
> + return &cpu_tlb_fast(cpu, mmu_idx)->table[tlb_index(cpu, mmu_idx, addr)];
> }
>
> static void tlb_window_reset(CPUTLBDesc *desc, int64_t ns,
> @@ -292,7 +292,7 @@ static void tlb_flush_one_mmuidx_locked(CPUState *cpu, int mmu_idx,
> int64_t now)
> {
> CPUTLBDesc *desc = &cpu->neg.tlb.d[mmu_idx];
> - CPUTLBDescFast *fast = &cpu->neg.tlb.f[mmu_idx];
> + CPUTLBDescFast *fast = cpu_tlb_fast(cpu, mmu_idx);
>
> tlb_mmu_resize_locked(desc, fast, now);
> tlb_mmu_flush_locked(desc, fast);
> @@ -331,7 +331,7 @@ void tlb_init(CPUState *cpu)
> cpu->neg.tlb.c.dirty = 0;
>
> for (i = 0; i < NB_MMU_MODES; i++) {
> - tlb_mmu_init(&cpu->neg.tlb.d[i], &cpu->neg.tlb.f[i], now);
> + tlb_mmu_init(&cpu->neg.tlb.d[i], cpu_tlb_fast(cpu, i), now);
> }
> }
>
> @@ -342,7 +342,7 @@ void tlb_destroy(CPUState *cpu)
> qemu_spin_destroy(&cpu->neg.tlb.c.lock);
> for (i = 0; i < NB_MMU_MODES; i++) {
> CPUTLBDesc *desc = &cpu->neg.tlb.d[i];
> - CPUTLBDescFast *fast = &cpu->neg.tlb.f[i];
> + CPUTLBDescFast *fast = cpu_tlb_fast(cpu, i);
>
> g_free(fast->table);
> g_free(desc->fulltlb);
> @@ -667,7 +667,7 @@ static void tlb_flush_range_locked(CPUState *cpu, int midx,
> unsigned bits)
> {
> CPUTLBDesc *d = &cpu->neg.tlb.d[midx];
> - CPUTLBDescFast *f = &cpu->neg.tlb.f[midx];
> + CPUTLBDescFast *f = cpu_tlb_fast(cpu, midx);
> vaddr mask = MAKE_64BIT_MASK(0, bits);
>
> /*
> @@ -923,7 +923,7 @@ void tlb_reset_dirty(CPUState *cpu, uintptr_t start, uintptr_t length)
> qemu_spin_lock(&cpu->neg.tlb.c.lock);
> for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
> CPUTLBDesc *desc = &cpu->neg.tlb.d[mmu_idx];
> - CPUTLBDescFast *fast = &cpu->neg.tlb.f[mmu_idx];
> + CPUTLBDescFast *fast = cpu_tlb_fast(cpu, mmu_idx);
> unsigned int n = tlb_n_entries(fast);
> unsigned int i;
>
> @@ -1316,7 +1316,7 @@ static bool victim_tlb_hit(CPUState *cpu, size_t mmu_idx, size_t index,
>
> if (cmp == page) {
> /* Found entry in victim tlb, swap tlb and iotlb. */
> - CPUTLBEntry tmptlb, *tlb = &cpu->neg.tlb.f[mmu_idx].table[index];
> + CPUTLBEntry tmptlb, *tlb = &cpu_tlb_fast(cpu, mmu_idx)->table[index];
>
> qemu_spin_lock(&cpu->neg.tlb.c.lock);
> copy_tlb_helper_locked(&tmptlb, tlb);
It's sad, my eyes were just getting used to read those accesses :)
More seriously, that's clearer, thanks.
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 25/82] include/hw/core/cpu: Invert the indexing into CPUTLBDescFast
2025-07-27 8:01 ` [PATCH 25/82] include/hw/core/cpu: Invert the indexing into CPUTLBDescFast Richard Henderson
@ 2025-07-30 21:00 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 21:00 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> This array is within CPUNegativeOffsetState, which means the
> last element of the array has an offset from env with the
> smallest magnitude. This can be encoded into fewer bits
> when generating TCG fast path memory references.
>
> When we changed the NB_MMU_MODES to be a global constant,
> rather than a per-target value, we pessimized the code
> generated for targets which use only a few mmu indexes.
> By inverting the array index, we counteract that.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> include/hw/core/cpu.h | 6 +++++-
> tcg/tcg.c | 3 ++-
> 2 files changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
> index bd835b07d5..85b1ab4022 100644
> --- a/include/hw/core/cpu.h
> +++ b/include/hw/core/cpu.h
> @@ -596,7 +596,11 @@ static inline CPUArchState *cpu_env(CPUState *cpu)
> #ifdef CONFIG_TCG
> static inline CPUTLBDescFast *cpu_tlb_fast(CPUState *cpu, int mmu_idx)
> {
> - return &cpu->neg.tlb.f[mmu_idx];
> + /*
> + * Invert the index order of the CPUTLBDescFast array so that lower
> + * mmu_idx have negative offsets from env with smaller absolute values.
> + */
> + return &cpu->neg.tlb.f[NB_MMU_MODES - 1 - mmu_idx];
> }
> #endif
>
> diff --git a/tcg/tcg.c b/tcg/tcg.c
> index afac55a203..615675d185 100644
> --- a/tcg/tcg.c
> +++ b/tcg/tcg.c
> @@ -425,7 +425,8 @@ static uintptr_t G_GNUC_UNUSED get_jmp_target_addr(TCGContext *s, int which)
> static int __attribute__((unused))
> tlb_mask_table_ofs(TCGContext *s, int which)
> {
> - return (offsetof(CPUNegativeOffsetState, tlb.f[which]) -
> + /* Invert the index order -- see cpu_tlb_fast. */
> + return (offsetof(CPUNegativeOffsetState, tlb.f[NB_MMU_MODES - 1 - which]) -
> sizeof(CPUNegativeOffsetState));
> }
>
There are some comments left behind that can become confusing with this
change. Could be changed with previous commit.
tcg/aarch64/tcg-target.c.inc:
/* Load cpu->neg.tlb.f[mmu_idx].{mask,table} into {tmp0,tmp1}. */
tcg/arm/tcg-target.c.inc:
/* Load cpu->neg.tlb.f[mmu_idx].{mask,table} into {r0,r1}. */
As a proposal, it could be worth to add a small function
mmuidx_to_entry() which does the inversion. This way, we save the
comment in tlb_mask_table_ofs.
Else,
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 26/82] target/hppa: Adjust mmu indexes to begin with 0
2025-07-27 8:01 ` [PATCH 26/82] target/hppa: Adjust mmu indexes to begin with 0 Richard Henderson
@ 2025-07-30 21:03 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 21:03 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> This is a logical reversion of 2ad04500543, though
> there have been additions to the set of mmu indexes
> since then. The impetus to that original patch,
> "9-15 will use shorter assembler instructions when
> run on a x86-64 host" is now handled generically.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/hppa/cpu.h | 28 ++++++++++++++--------------
> 1 file changed, 14 insertions(+), 14 deletions(-)
Thanks for mentioning the original commit, else it would be hard to follow.
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 27/82] include/exec/memopidx: Adjust for 32 mmu indexes
2025-07-27 8:01 ` [PATCH 27/82] include/exec/memopidx: Adjust for 32 mmu indexes Richard Henderson
@ 2025-07-30 21:03 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 21:03 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> include/exec/memopidx.h | 9 +++++----
> 1 file changed, 5 insertions(+), 4 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 28/82] include/hw/core/cpu: Widen MMUIdxMap
2025-07-27 8:02 ` [PATCH 28/82] include/hw/core/cpu: Widen MMUIdxMap Richard Henderson
@ 2025-07-30 21:07 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 21:07 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Widen MMUIdxMap to 32 bits. Do not yet expand NB_MMU_MODES,
> but widen the map type in preparation.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> include/hw/core/cpu.h | 2 +-
> accel/tcg/cputlb.c | 3 ---
> 2 files changed, 1 insertion(+), 4 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 29/82] target/arm: Split out mmuidx.h from cpu.h
2025-07-27 8:02 ` [PATCH 29/82] target/arm: Split out mmuidx.h from cpu.h Richard Henderson
@ 2025-07-30 21:07 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 21:07 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/cpu.h | 207 +-----------------------------------------
> target/arm/mmuidx.h | 216 ++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 217 insertions(+), 206 deletions(-)
> create mode 100644 target/arm/mmuidx.h
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 30/82] target/arm: Convert arm_mmu_idx_to_el from switch to table
2025-07-27 8:02 ` [PATCH 30/82] target/arm: Convert arm_mmu_idx_to_el from switch to table Richard Henderson
@ 2025-07-30 21:10 ` Pierrick Bouvier
2025-07-30 21:12 ` Pierrick Bouvier
0 siblings, 1 reply; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 21:10 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> In an effort to keep all ARMMMUIdx data in one place, begin construction
> of an info table describing all of the properties of the mmu_idx. Begin
> with the access EL.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/internals.h | 3 +--
> target/arm/mmuidx-internal.h | 27 ++++++++++++++++++++++++
> target/arm/helper.c | 27 ------------------------
> target/arm/mmuidx.c | 41 ++++++++++++++++++++++++++++++++++++
> target/arm/meson.build | 7 +++++-
> 5 files changed, 75 insertions(+), 30 deletions(-)
> create mode 100644 target/arm/mmuidx-internal.h
> create mode 100644 target/arm/mmuidx.c
What's the benefit to explicitely size arm_mmuidx_table on declaration
and definition?
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 30/82] target/arm: Convert arm_mmu_idx_to_el from switch to table
2025-07-30 21:10 ` Pierrick Bouvier
@ 2025-07-30 21:12 ` Pierrick Bouvier
2025-07-30 21:31 ` Pierrick Bouvier
0 siblings, 1 reply; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 21:12 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/30/25 2:10 PM, Pierrick Bouvier wrote:
> On 7/27/25 1:02 AM, Richard Henderson wrote:
>> In an effort to keep all ARMMMUIdx data in one place, begin construction
>> of an info table describing all of the properties of the mmu_idx. Begin
>> with the access EL.
>>
>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>> ---
>> target/arm/internals.h | 3 +--
>> target/arm/mmuidx-internal.h | 27 ++++++++++++++++++++++++
>> target/arm/helper.c | 27 ------------------------
>> target/arm/mmuidx.c | 41 ++++++++++++++++++++++++++++++++++++
>> target/arm/meson.build | 7 +++++-
>> 5 files changed, 75 insertions(+), 30 deletions(-)
>> create mode 100644 target/arm/mmuidx-internal.h
>> create mode 100644 target/arm/mmuidx.c
>
> What's the benefit to explicitely size arm_mmuidx_table on declaration
> and definition?
>
I missed the:
tcg_debug_assert((unsigned)idx < ARRAY_SIZE(arm_mmuidx_table)), which
does not see definition of the table.
Maybe it would be easier to declare size in the header, and reuse it on
both sides (declaration, definition instead of ARM_MMU_IDX_M + 8).
> Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 31/82] target/arm: Remove unused env argument from regime_el
2025-07-27 8:02 ` [PATCH 31/82] target/arm: Remove unused env argument from regime_el Richard Henderson
@ 2025-07-30 21:13 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 21:13 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/internals.h | 8 ++++----
> target/arm/helper.c | 2 +-
> target/arm/ptw.c | 34 +++++++++++++++++-----------------
> target/arm/tcg/mte_helper.c | 2 +-
> 4 files changed, 23 insertions(+), 23 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 32/82] target/arm: Convert regime_el from switch to table
2025-07-27 8:02 ` [PATCH 32/82] target/arm: Convert regime_el from switch to table Richard Henderson
@ 2025-07-30 21:15 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 21:15 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/internals.h | 35 ----------------------------
> target/arm/mmuidx-internal.h | 13 +++++++++++
> target/arm/mmuidx.c | 44 +++++++++++++++++++++---------------
> 3 files changed, 39 insertions(+), 53 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 33/82] target/arm: Convert regime_has_2_ranges from switch to table
2025-07-27 8:02 ` [PATCH 33/82] target/arm: Convert regime_has_2_ranges " Richard Henderson
@ 2025-07-30 21:16 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 21:16 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/internals.h | 28 ----------------------------
> target/arm/mmuidx-internal.h | 17 +++++++++++++++++
> target/arm/mmuidx.c | 19 ++++++++++---------
> 3 files changed, 27 insertions(+), 37 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 34/82] target/arm: Remove unused env argument from regime_is_pan
2025-07-27 8:02 ` [PATCH 34/82] target/arm: Remove unused env argument from regime_is_pan Richard Henderson
@ 2025-07-30 21:17 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 21:17 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/internals.h | 2 +-
> target/arm/ptw.c | 6 +++---
> 2 files changed, 4 insertions(+), 4 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 35/82] target/arm: Convert regime_is_pan from switch to table
2025-07-27 8:02 ` [PATCH 35/82] target/arm: Convert regime_is_pan from switch to table Richard Henderson
@ 2025-07-30 21:17 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 21:17 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/internals.h | 13 -------------
> target/arm/mmuidx-internal.h | 8 ++++++++
> target/arm/mmuidx.c | 9 +++++----
> 3 files changed, 13 insertions(+), 17 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 36/82] target/arm: Remove unused env argument from regime_is_user
2025-07-27 8:02 ` [PATCH 36/82] target/arm: Remove unused env argument from regime_is_user Richard Henderson
@ 2025-07-30 21:18 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 21:18 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/internals.h | 2 +-
> target/arm/helper.c | 2 +-
> target/arm/ptw.c | 16 ++++++++--------
> 3 files changed, 10 insertions(+), 10 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 37/82] target/arm: Convert regime_is_user from switch to table
2025-07-27 8:02 ` [PATCH 37/82] target/arm: Convert regime_is_user from switch to table Richard Henderson
@ 2025-07-30 21:21 ` Pierrick Bouvier
2025-08-01 3:53 ` Richard Henderson
0 siblings, 1 reply; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 21:21 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/internals.h | 17 -----------------
> target/arm/mmuidx-internal.h | 12 ++++++++++++
> target/arm/mmuidx.c | 6 ++++--
> 3 files changed, 16 insertions(+), 19 deletions(-)
>
> diff --git a/target/arm/internals.h b/target/arm/internals.h
> index ea210c7179..c6f3ae470b 100644
> --- a/target/arm/internals.h
> +++ b/target/arm/internals.h
> @@ -1034,23 +1034,6 @@ static inline bool regime_is_stage2(ARMMMUIdx mmu_idx)
> return mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S;
> }
>
> -static inline bool regime_is_user(ARMMMUIdx mmu_idx)
> -{
> - switch (mmu_idx) {
> - case ARMMMUIdx_E10_0:
> - case ARMMMUIdx_E20_0:
> - case ARMMMUIdx_E30_0:
> - case ARMMMUIdx_Stage1_E0:
> - case ARMMMUIdx_MUser:
> - case ARMMMUIdx_MSUser:
> - case ARMMMUIdx_MUserNegPri:
> - case ARMMMUIdx_MSUserNegPri:
> - return true;
> - default:
> - return false;
> - }
> -}
> -
> /* Return the SCTLR value which controls this address translation regime */
> static inline uint64_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)
> {
> diff --git a/target/arm/mmuidx-internal.h b/target/arm/mmuidx-internal.h
> index 5a7259a557..ef1f94a23f 100644
> --- a/target/arm/mmuidx-internal.h
> +++ b/target/arm/mmuidx-internal.h
> @@ -17,6 +17,7 @@ FIELD(MMUIDXINFO, REL, 3, 2)
> FIELD(MMUIDXINFO, RELVALID, 5, 1)
> FIELD(MMUIDXINFO, 2RANGES, 6, 1)
> FIELD(MMUIDXINFO, PAN, 7, 1)
> +FIELD(MMUIDXINFO, USER, 8, 1)
>
> extern const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8];
>
> @@ -62,4 +63,15 @@ static inline bool regime_is_pan(ARMMMUIdx idx)
> return FIELD_EX32(arm_mmuidx_table[idx], MMUIDXINFO, PAN);
> }
>
> +/*
> + * Return true if the exception level associated with this mmu index is 0.
> + * Differs from arm_mmu_idx_to_el(idx) == 0 in that this allows querying
> + * Stage1 and Stage2 mmu indexes.
> + */
> +static inline bool regime_is_user(ARMMMUIdx idx)
> +{
> + tcg_debug_assert((unsigned)idx < ARRAY_SIZE(arm_mmuidx_table));
> + return FIELD_EX32(arm_mmuidx_table[idx], MMUIDXINFO, USER);
> +}
> +
> #endif /* TARGET_ARM_MMUIDX_INTERNAL_H */
> diff --git a/target/arm/mmuidx.c b/target/arm/mmuidx.c
> index 98db02b8e5..1c1e062bfe 100644
> --- a/target/arm/mmuidx.c
> +++ b/target/arm/mmuidx.c
> @@ -7,10 +7,12 @@
> #include "mmuidx-internal.h"
>
>
> -#define EL(X) ((X << R_MMUIDXINFO_EL_SHIFT) | R_MMUIDXINFO_ELVALID_MASK)
> +#define EL(X) ((X << R_MMUIDXINFO_EL_SHIFT) | R_MMUIDXINFO_ELVALID_MASK | \
> + ((X == 0) << R_MMUIDXINFO_USER_SHIFT))
> #define REL(X) ((X << R_MMUIDXINFO_REL_SHIFT) | R_MMUIDXINFO_RELVALID_MASK)
> #define R2 R_MMUIDXINFO_2RANGES_MASK
> #define PAN R_MMUIDXINFO_PAN_MASK
> +#define USER R_MMUIDXINFO_USER_MASK
>
> const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8] = {
> /*
> @@ -33,7 +35,7 @@ const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8] = {
> [ARMMMUIdx_Stage2_S] = REL(2),
> [ARMMMUIdx_Stage2] = REL(2),
>
> - [ARMMMUIdx_Stage1_E0] = REL(1) | R2,
> + [ARMMMUIdx_Stage1_E0] = REL(1) | R2 | USER,
> [ARMMMUIdx_Stage1_E1] = REL(1) | R2,
> [ARMMMUIdx_Stage1_E1_PAN] = REL(1) | R2 | PAN,
>
Maybe I missed something, but what about other entries that were
initially treated in the switch?
- ARMMMUIdx_E.0_0
- ARMMMUIdx_M*User
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 38/82] target/arm: Convert arm_mmu_idx_is_stage1_of_2 from switch to table
2025-07-27 8:02 ` [PATCH 38/82] target/arm: Convert arm_mmu_idx_is_stage1_of_2 " Richard Henderson
@ 2025-07-30 21:23 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 21:23 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/internals.h | 19 -------------------
> target/arm/mmuidx-internal.h | 8 ++++++++
> target/arm/mmuidx.c | 7 ++++---
> 3 files changed, 12 insertions(+), 22 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 39/82] target/arm: Convert regime_is_stage2 to table
2025-07-27 8:02 ` [PATCH 39/82] target/arm: Convert regime_is_stage2 " Richard Henderson
@ 2025-07-30 21:23 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 21:23 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> This wasn't using a switch, but two comparisons.
> Convert it to arm_mmuidx_table for consistency.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/internals.h | 5 -----
> target/arm/mmuidx-internal.h | 8 ++++++++
> target/arm/mmuidx.c | 5 +++--
> 3 files changed, 11 insertions(+), 7 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 40/82] target/arm: Introduce mmu indexes for GCS
2025-07-27 8:02 ` [PATCH 40/82] target/arm: Introduce mmu indexes for GCS Richard Henderson
@ 2025-07-30 21:28 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 21:28 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> include/hw/core/cpu.h | 5 ++-
> target/arm/mmuidx-internal.h | 8 ++++
> target/arm/mmuidx.h | 71 ++++++++++++++++++++++++------------
> target/arm/helper.c | 15 ++++++--
> target/arm/mmuidx.c | 9 +++++
> target/arm/ptw.c | 20 ++++++++++
> target/arm/tcg/tlb-insns.c | 47 ++++++++++++++++--------
> 7 files changed, 132 insertions(+), 43 deletions(-)
Finally getting there :)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 30/82] target/arm: Convert arm_mmu_idx_to_el from switch to table
2025-07-30 21:12 ` Pierrick Bouvier
@ 2025-07-30 21:31 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 21:31 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/30/25 2:12 PM, Pierrick Bouvier wrote:
> On 7/30/25 2:10 PM, Pierrick Bouvier wrote:
>> On 7/27/25 1:02 AM, Richard Henderson wrote:
>>> In an effort to keep all ARMMMUIdx data in one place, begin construction
>>> of an info table describing all of the properties of the mmu_idx. Begin
>>> with the access EL.
>>>
>>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>>> ---
>>> target/arm/internals.h | 3 +--
>>> target/arm/mmuidx-internal.h | 27 ++++++++++++++++++++++++
>>> target/arm/helper.c | 27 ------------------------
>>> target/arm/mmuidx.c | 41 ++++++++++++++++++++++++++++++++++++
>>> target/arm/meson.build | 7 +++++-
>>> 5 files changed, 75 insertions(+), 30 deletions(-)
>>> create mode 100644 target/arm/mmuidx-internal.h
>>> create mode 100644 target/arm/mmuidx.c
>>
>> What's the benefit to explicitely size arm_mmuidx_table on declaration
>> and definition?
>>
>
> I missed the:
> tcg_debug_assert((unsigned)idx < ARRAY_SIZE(arm_mmuidx_table)), which
> does not see definition of the table.
>
> Maybe it would be easier to declare size in the header, and reuse it on
> both sides (declaration, definition instead of ARM_MMU_IDX_M + 8).
>
Finally, the ARM_MMU_IDX_M + 8 is not a problem.
That said, given how much we repeat
(unsigned)idx < ARRAY_SIZE(arm_mmuidx_table),
it's definitely worth having a 'arm_mmuidx_is_valid' static inline
function for that.
>> Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
>>
>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 41/82] target/arm: Introduce regime_to_gcs
2025-07-27 8:02 ` [PATCH 41/82] target/arm: Introduce regime_to_gcs Richard Henderson
@ 2025-07-30 21:33 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-30 21:33 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Add a lookup from any a64 mmu index to the gcs mmu index
> within the same translation regime.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/mmuidx-internal.h | 10 ++++++++++
> target/arm/mmuidx.c | 24 +++++++++++++-----------
> 2 files changed, 23 insertions(+), 11 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 42/82] target/arm: Support page protections for GCS mmu indexes
2025-07-27 8:02 ` [PATCH 42/82] target/arm: Support page protections for GCS mmu indexes Richard Henderson
@ 2025-07-31 18:40 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 18:40 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Take read and write from the s1perms.gcs bit computed
> by the Arm pseudocode.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/ptw.c | 17 ++++++++++++++---
> 1 file changed, 14 insertions(+), 3 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 43/82] target/arm: Implement gcs bit for data abort
2025-07-27 8:02 ` [PATCH 43/82] target/arm: Implement gcs bit for data abort Richard Henderson
@ 2025-07-31 18:41 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 18:41 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/internals.h | 1 +
> target/arm/ptw.c | 1 +
> target/arm/tcg/tlb_helper.c | 1 +
> 3 files changed, 3 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 44/82] target/arm: Add GCS cpregs
2025-07-27 8:02 ` [PATCH 44/82] target/arm: Add GCS cpregs Richard Henderson
@ 2025-07-31 18:45 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 18:45 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Add isar_feature_aa64_gcs.
> Enable SCR_GCSEN in scr_write.
> Enable HCRX_GCSEN in hcrx_write.
> Default HCRX_GCSEN on if EL2 disabled.
> Add the GCSCR* and GCSPR* registers.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/cpregs.h | 2 +
> target/arm/cpu-features.h | 5 +++
> target/arm/cpu.h | 12 ++++++
> target/arm/internals.h | 3 ++
> target/arm/cpregs-gcs.c | 79 +++++++++++++++++++++++++++++++++++++++
> target/arm/cpu.c | 3 ++
> target/arm/helper.c | 10 +++++
> target/arm/meson.build | 2 +
> 8 files changed, 116 insertions(+)
> create mode 100644 target/arm/cpregs-gcs.c
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 45/82] target/arm: Add GCS enable and trap levels to DisasContext
2025-07-27 8:02 ` [PATCH 45/82] target/arm: Add GCS enable and trap levels to DisasContext Richard Henderson
@ 2025-07-31 18:54 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 18:54 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Pipe GCSEnabled, GCSReturnValueCheckEnabled, and CheckGCSSTREnabled
> through hflags to the translator.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/cpu.h | 3 +++
> target/arm/tcg/translate.h | 6 ++++++
> target/arm/tcg/hflags.c | 38 ++++++++++++++++++++++++++++++++++
> target/arm/tcg/translate-a64.c | 3 +++
> 4 files changed, 50 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 46/82] target/arm: Implement FEAT_CHK
2025-07-27 8:02 ` [PATCH 46/82] target/arm: Implement FEAT_CHK Richard Henderson
2025-07-29 16:01 ` Gustavo Romero
@ 2025-07-31 18:59 ` Pierrick Bouvier
1 sibling, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 18:59 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> This feature contains only the CHKFEAT instruction. It has
> no ID enable, being back-allocated into the hint nop space.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/tcg/translate-a64.c | 14 ++++++++++++++
> docs/system/arm/emulation.rst | 1 +
> target/arm/tcg/a64.decode | 1 +
> 3 files changed, 16 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 47/82] target/arm: Expand pstate to 64 bits
2025-07-27 8:02 ` [PATCH 47/82] target/arm: Expand pstate to 64 bits Richard Henderson
@ 2025-07-31 19:13 ` Pierrick Bouvier
2025-08-01 4:24 ` Richard Henderson
` (2 more replies)
2025-08-01 20:22 ` Pierrick Bouvier
1 sibling, 3 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 19:13 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> The ARM now defines 36 bits in SPSR_ELx in aarch64 mode, so
> it's time to bite the bullet and extend PSTATE to match.
>
> Most changes are straightforward, adjusting printf formats,
> changing local variable types. More complex is migration,
> where to maintain backward compatibility a new pstate64
> record is introduced, and only when one of the extensions
> that sets bits 32-35 are active.
>
> The fate of gdbstub is left undecided for the moment.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/cpu.h | 8 +++---
> target/arm/tcg/translate.h | 20 ++++++-------
> target/arm/cpu.c | 6 ++--
> target/arm/gdbstub64.c | 1 +
> target/arm/helper.c | 11 ++++----
> target/arm/machine.c | 56 +++++++++++++++++++++++++++++++++++++
> target/arm/tcg/helper-a64.c | 2 +-
> 7 files changed, 81 insertions(+), 23 deletions(-)
...
> diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
> index 64ee9b3b56..3cef47281a 100644
> --- a/target/arm/gdbstub64.c
> +++ b/target/arm/gdbstub64.c
> @@ -47,6 +47,7 @@ int aarch64_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
> case 32:
> return gdb_get_reg64(mem_buf, env->pc);
> case 33:
> + /* pstate is now a 64-bit value; can we simply adjust the xml? */
> return gdb_get_reg32(mem_buf, pstate_read(env));
> }
If I'm correct, we currently don't expose PSTATE through gdbstub, but
only CPSR. This was a bit confusing for me, considering that CPSR is not
even supposed to exist in Aarch64.
Maybe it's a good opportunity to expose PSTATE instead, which could have
a 64 bits size. This way, we don't break any workflow.
...
> diff --git a/target/arm/machine.c b/target/arm/machine.c
> index 8dbeca2867..9b00c14b4a 100644
> --- a/target/arm/machine.c
> +++ b/target/arm/machine.c
> @@ -836,6 +836,61 @@ static const VMStateInfo vmstate_cpsr = {
> .put = put_cpsr,
> };
>
> +static int get_pstate64_1(QEMUFile *f, void *opaque, size_t size,
> + const VMStateField *field)
> +{
> + ARMCPU *cpu = opaque;
> + CPUARMState *env = &cpu->env;
> + uint64_t val = qemu_get_be64(f);
> +
> + env->aarch64 = ((val & PSTATE_nRW) == 0);
> + pstate_write(env, val);
> + return 0;
> +}
> +
> +static int put_pstate64_1(QEMUFile *f, void *opaque, size_t size,
> + const VMStateField *field, JSONWriter *vmdesc)
> +{
> + ARMCPU *cpu = opaque;
> + CPUARMState *env = &cpu->env;
> + uint64_t val = pstate_read(env);
> +
> + qemu_put_be64(f, val);
> + return 0;
> +}
> +
> +static const VMStateInfo vmstate_pstate64_1 = {
> + .name = "pstate64",
> + .get = get_pstate64_1,
> + .put = put_pstate64_1,
> +};
> +
> +static bool pstate64_needed(void *opaque)
> +{
> + ARMCPU *cpu = opaque;
> + CPUARMState *env = &cpu->env;
> +
> + return is_a64(env) && pstate_read(env) > UINT32_MAX;
> +}
> +
> +static const VMStateDescription vmstate_pstate64 = {
> + .name = "cpu/pstate64",
> + .version_id = 1,
> + .minimum_version_id = 1,
> + .needed = pstate64_needed,
> + .fields = (const VMStateField[]) {
> + {
> + .name = "pstate64",
> + .version_id = 0,
> + .size = sizeof(uint64_t),
> + .info = &vmstate_pstate64_1,
> + .flags = VMS_SINGLE,
> + .offset = 0,
> + },
> + VMSTATE_END_OF_LIST()
> + },
> +};
> +
> static int get_power(QEMUFile *f, void *opaque, size_t size,
> const VMStateField *field)
> {
> @@ -1119,6 +1174,7 @@ const VMStateDescription vmstate_arm_cpu = {
> &vmstate_serror,
> &vmstate_irq_line_state,
> &vmstate_wfxt_timer,
> + &vmstate_pstate64,
> NULL
> }
> };
> diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c
> index 71c6c44ee8..f61adf1f80 100644
> --- a/target/arm/tcg/helper-a64.c
> +++ b/target/arm/tcg/helper-a64.c
> @@ -639,7 +639,7 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
> ARMCPU *cpu = env_archcpu(env);
> int cur_el = arm_current_el(env);
> unsigned int spsr_idx = aarch64_banked_spsr_index(cur_el);
> - uint32_t spsr = env->banked_spsr[spsr_idx];
> + uint64_t spsr = env->banked_spsr[spsr_idx];
> int new_el;
> bool return_to_aa64 = (spsr & PSTATE_nRW) == 0;
>
Would that be better or worse to simply save the upper 32 bits,
considering that cpsr already holds the lower ones in Aarch64 mode?
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 48/82] target/arm: Add syndrome data for EC_GCS
2025-07-27 8:02 ` [PATCH 48/82] target/arm: Add syndrome data for EC_GCS Richard Henderson
@ 2025-07-31 19:35 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 19:35 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/syndrome.h | 35 +++++++++++++++++++++++++++++++++++
> 1 file changed, 35 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 49/82] target/arm: Implement EXLOCKException for ELR_ELx and SPSR_ELx
2025-07-27 8:02 ` [PATCH 49/82] target/arm: Implement EXLOCKException for ELR_ELx and SPSR_ELx Richard Henderson
@ 2025-07-31 20:53 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 20:53 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> If PSTATE.EXLOCK is set, and the GCS EXLOCK enable bit is set,
> and nested virt is in the appropriate state, then we need to
> raise an EXLOCK exception.
>
> Since PSTATE.EXLOCK cannot be set without GCS being present
> and enabled, no explicit check for GCS is required.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/cpregs.h | 3 ++
> target/arm/cpu.h | 1 +
> target/arm/helper.c | 83 +++++++++++++++++++++++++++++++++++---
> target/arm/tcg/op_helper.c | 4 ++
> 4 files changed, 85 insertions(+), 6 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 50/82] target/arm: Split {arm,core}_user_mem_index
2025-07-27 8:02 ` [PATCH 50/82] target/arm: Split {arm,core}_user_mem_index Richard Henderson
@ 2025-07-31 21:06 ` Pierrick Bouvier
2025-07-31 21:24 ` Pierrick Bouvier
0 siblings, 1 reply; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:06 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Separate current to unpriv and arm to core mmu conversions
> into two separate functions.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/tcg/translate-a64.c | 24 +++++++++++++++---------
> 1 file changed, 15 insertions(+), 9 deletions(-)
If I followed correctly, we replaced all calls to get_a64_user_mem_index
by core_user_mem_index. Thus, why not rename directly the function
get_a64_user_mem_index in core_user_mem_index?
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 51/82] target/arm: Introduce delay_exception{_el}
2025-07-27 8:02 ` [PATCH 51/82] target/arm: Introduce delay_exception{_el} Richard Henderson
@ 2025-07-31 21:09 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:09 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Add infrastructure to raise an exception out of line.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/tcg/translate.h | 20 +++++++++++++
> target/arm/tcg/translate-a64.c | 2 ++
> target/arm/tcg/translate.c | 53 ++++++++++++++++++++++++++++++++++
> 3 files changed, 75 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 52/82] target/arm: Emit HSTR trap exception out of line
2025-07-27 8:02 ` [PATCH 52/82] target/arm: Emit HSTR trap exception out of line Richard Henderson
@ 2025-07-31 21:10 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:10 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Use delay_exception_el to move the exception out of line.
> Use TCG_COND_TSTNE instead of separate AND+NE.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/tcg/translate.c | 18 ++++--------------
> 1 file changed, 4 insertions(+), 14 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 53/82] target/arm: Emit v7m LTPSIZE exception out of line
2025-07-27 8:02 ` [PATCH 53/82] target/arm: Emit v7m LTPSIZE " Richard Henderson
@ 2025-07-31 21:10 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:10 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/tcg/translate.c | 7 +++----
> 1 file changed, 3 insertions(+), 4 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 17/82] target/arm: Implement get_S2prot_indirect
2025-07-27 8:01 ` [PATCH 17/82] target/arm: Implement get_S2prot_indirect Richard Henderson
@ 2025-07-31 21:13 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:13 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> Move the stage2 permissions for normal accesses to
> GetPhysAddrResult.s2prot. Put the stage2 permissions
> for page table walking in CPUTLBEntryFull.prot.
> This allows the permission checks in S1_ptw_translate
> and arm_casq_ptw to see the right permission.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/internals.h | 7 ++++
> target/arm/ptw.c | 81 +++++++++++++++++++++++++++++++-----------
> 2 files changed, 68 insertions(+), 20 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 16/82] target/arm: Implement get_S1prot_indirect
2025-07-27 8:01 ` [PATCH 16/82] target/arm: Implement get_S1prot_indirect Richard Henderson
@ 2025-07-31 21:15 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:15 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:01 AM, Richard Henderson wrote:
> This approximately corresponds to AArch64.S1IndirectBasePermissions
> and the tail of AArch64.S1ComputePermissions which applies WXN.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/ptw.c | 169 +++++++++++++++++++++++++++++++++++++++--------
> 1 file changed, 143 insertions(+), 26 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 50/82] target/arm: Split {arm,core}_user_mem_index
2025-07-31 21:06 ` Pierrick Bouvier
@ 2025-07-31 21:24 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:24 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/31/25 2:06 PM, Pierrick Bouvier wrote:
> On 7/27/25 1:02 AM, Richard Henderson wrote:
>> Separate current to unpriv and arm to core mmu conversions
>> into two separate functions.
>>
>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>> ---
>> target/arm/tcg/translate-a64.c | 24 +++++++++++++++---------
>> 1 file changed, 15 insertions(+), 9 deletions(-)
>
> If I followed correctly, we replaced all calls to get_a64_user_mem_index
> by core_user_mem_index. Thus, why not rename directly the function
> get_a64_user_mem_index in core_user_mem_index?
>
Patch 54 uses arm_user_mem_index.
> Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 54/82] target/arm: Implement GCSSTR, GCSSTTR
2025-07-27 8:02 ` [PATCH 54/82] target/arm: Implement GCSSTR, GCSSTTR Richard Henderson
@ 2025-07-31 21:25 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:25 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Note that CreateAccDescGCS() does not enable tagchecked,
> and Data Aborts from GCS instructions do not set iss.isv.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/tcg/translate-a64.c | 42 ++++++++++++++++++++++++++++++++++
> target/arm/tcg/a64.decode | 3 +++
> 2 files changed, 45 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 55/82] target/arm: Implement GCSB
2025-07-27 8:02 ` [PATCH 55/82] target/arm: Implement GCSB Richard Henderson
@ 2025-07-31 21:27 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:27 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/tcg/translate-a64.c | 8 ++++++++
> target/arm/tcg/a64.decode | 1 +
> 2 files changed, 9 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 56/82] target/arm: Implement GCSPUSHM
2025-07-27 8:02 ` [PATCH 56/82] target/arm: Implement GCSPUSHM Richard Henderson
@ 2025-07-31 21:33 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:33 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/cpregs.h | 3 +++
> target/arm/cpregs-gcs.c | 16 ++++++++++++++++
> target/arm/tcg/translate-a64.c | 18 ++++++++++++++++++
> 3 files changed, 37 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 57/82] target/arm: Implement GCSPOPM
2025-07-27 8:02 ` [PATCH 57/82] target/arm: Implement GCSPOPM Richard Henderson
@ 2025-07-31 21:34 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:34 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/cpregs.h | 1 +
> target/arm/cpregs-gcs.c | 3 +++
> target/arm/tcg/translate-a64.c | 27 +++++++++++++++++++++++++++
> 3 files changed, 31 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 58/82] target/arm: Implement GCSPUSHX
2025-07-27 8:02 ` [PATCH 58/82] target/arm: Implement GCSPUSHX Richard Henderson
@ 2025-07-31 21:36 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:36 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/cpregs.h | 2 ++
> target/arm/cpregs-gcs.c | 17 +++++++++++++++
> target/arm/tcg/translate-a64.c | 40 ++++++++++++++++++++++++++++++++++
> 3 files changed, 59 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 59/82] target/arm: Implement GCSPOPX
2025-07-27 8:02 ` [PATCH 59/82] target/arm: Implement GCSPOPX Richard Henderson
@ 2025-07-31 21:37 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:37 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/cpregs.h | 1 +
> target/arm/cpregs-gcs.c | 3 +++
> target/arm/tcg/translate-a64.c | 37 ++++++++++++++++++++++++++++++++++
> 3 files changed, 41 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 60/82] target/arm: Implement GCSPOPCX
2025-07-27 8:02 ` [PATCH 60/82] target/arm: Implement GCSPOPCX Richard Henderson
@ 2025-07-31 21:38 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:38 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/cpregs.h | 1 +
> target/arm/cpregs-gcs.c | 17 ++++++++++
> target/arm/tcg/translate-a64.c | 58 ++++++++++++++++++++++++++++++++++
> 3 files changed, 76 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 61/82] target/arm: Implement GCSSS1
2025-07-27 8:02 ` [PATCH 61/82] target/arm: Implement GCSSS1 Richard Henderson
@ 2025-07-31 21:43 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:43 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/cpregs.h | 1 +
> target/arm/cpregs-gcs.c | 3 +++
> target/arm/tcg/translate-a64.c | 32 ++++++++++++++++++++++++++++++++
> 3 files changed, 36 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 62/82] target/arm: Implement GCSSS2
2025-07-27 8:02 ` [PATCH 62/82] target/arm: Implement GCSSS2 Richard Henderson
@ 2025-07-31 21:45 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:45 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/cpregs.h | 1 +
> target/arm/cpregs-gcs.c | 3 +++
> target/arm/tcg/translate-a64.c | 37 ++++++++++++++++++++++++++++++++++
> 3 files changed, 41 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 63/82] target/arm: Add gcs record for BL
2025-07-27 8:02 ` [PATCH 63/82] target/arm: Add gcs record for BL Richard Henderson
@ 2025-07-31 21:45 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:45 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/tcg/translate-a64.c | 9 ++++++++-
> 1 file changed, 8 insertions(+), 1 deletion(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 64/82] target/arm: Add gcs record for BLR
2025-07-27 8:02 ` [PATCH 64/82] target/arm: Add gcs record for BLR Richard Henderson
@ 2025-07-31 21:46 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:46 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/tcg/translate-a64.c | 16 ++++++++--------
> 1 file changed, 8 insertions(+), 8 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 65/82] target/arm: Add gcs record for BLR with PAuth
2025-07-27 8:02 ` [PATCH 65/82] target/arm: Add gcs record for BLR with PAuth Richard Henderson
@ 2025-07-31 21:46 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:46 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/tcg/translate-a64.c | 31 ++++++++++++++++---------------
> 1 file changed, 16 insertions(+), 15 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 66/82] target/arm: Load gcs record for RET
2025-07-27 8:02 ` [PATCH 66/82] target/arm: Load gcs record for RET Richard Henderson
@ 2025-07-31 21:47 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:47 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/tcg/translate-a64.c | 32 +++++++++++++++++++++++++++++++-
> 1 file changed, 31 insertions(+), 1 deletion(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 67/82] target/arm: Load gcs record for RET with PAuth
2025-07-27 8:02 ` [PATCH 67/82] target/arm: Load gcs record for RET with PAuth Richard Henderson
@ 2025-07-31 21:48 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:48 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/tcg/translate-a64.c | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 68/82] target/arm: Copy EXLOCKEn to EXLOCK on exception to the same EL
2025-07-27 8:02 ` [PATCH 68/82] target/arm: Copy EXLOCKEn to EXLOCK on exception to the same EL Richard Henderson
@ 2025-07-31 21:48 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:48 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Per R_WTXBY, PSTATE.EXLOCK is 0 on an exception to a higher EL,
> and copied from EXLOCKEn otherwise.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/helper.c | 9 +++++++--
> 1 file changed, 7 insertions(+), 2 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 69/82] target/arm: Implement EXLOCK check during exception return
2025-07-27 8:02 ` [PATCH 69/82] target/arm: Implement EXLOCK check during exception return Richard Henderson
@ 2025-07-31 21:49 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:49 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/tcg/helper-a64.c | 11 +++++++++++
> 1 file changed, 11 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 70/82] target/arm: Enable FEAT_GCS with -cpu max
2025-07-27 8:02 ` [PATCH 70/82] target/arm: Enable FEAT_GCS with -cpu max Richard Henderson
@ 2025-07-31 21:49 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:49 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/tcg/cpu64.c | 1 +
> docs/system/arm/emulation.rst | 1 +
> 2 files changed, 2 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 71/82] linux-user/aarch64: Implement prctls for GCS
2025-07-27 8:02 ` [PATCH 71/82] linux-user/aarch64: Implement prctls for GCS Richard Henderson
@ 2025-07-31 21:53 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:53 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> This is PR_GET_SHADOW_STACK_STATUS, PR_SET_SHADOW_STACK_STATUS,
> and PR_LOCK_SHADOW_STACK_STATUS.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> linux-user/aarch64/gcs-internal.h | 38 ++++++++++++
> linux-user/aarch64/target_prctl.h | 96 +++++++++++++++++++++++++++++++
> linux-user/qemu.h | 5 ++
> linux-user/syscall.c | 29 ++++++++++
> 4 files changed, 168 insertions(+)
> create mode 100644 linux-user/aarch64/gcs-internal.h
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 72/82] linux-user/aarch64: Allocate new gcs stack on clone
2025-07-27 8:02 ` [PATCH 72/82] linux-user/aarch64: Allocate new gcs stack on clone Richard Henderson
@ 2025-07-31 21:54 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:54 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Allocate the new stack early, so that error reporting need
> not clean up other objects.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> linux-user/syscall.c | 20 ++++++++++++++++++++
> 1 file changed, 20 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 73/82] linux-user/aarch64: Release gcs stack on thread exit
2025-07-27 8:02 ` [PATCH 73/82] linux-user/aarch64: Release gcs stack on thread exit Richard Henderson
@ 2025-07-31 21:54 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:54 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> linux-user/syscall.c | 6 ++++++
> 1 file changed, 6 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 74/82] linux-user/aarch64: Implement map_shadow_stack syscall
2025-07-27 8:02 ` [PATCH 74/82] linux-user/aarch64: Implement map_shadow_stack syscall Richard Henderson
@ 2025-07-31 21:55 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:55 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> linux-user/syscall.c | 59 ++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 59 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 75/82] target/arm: Enable GCSPR_EL0 for read in user-mode
2025-07-27 8:02 ` [PATCH 75/82] target/arm: Enable GCSPR_EL0 for read in user-mode Richard Henderson
@ 2025-07-31 21:56 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:56 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/cpu.c | 4 ++++
> 1 file changed, 4 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 76/82] linux-user/aarch64: Inject SIGSEGV for GCS faults
2025-07-27 8:02 ` [PATCH 76/82] linux-user/aarch64: Inject SIGSEGV for GCS faults Richard Henderson
@ 2025-07-31 21:56 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:56 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> linux-user/aarch64/target_signal.h | 1 +
> linux-user/aarch64/cpu_loop.c | 5 +++++
> 2 files changed, 6 insertions(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 77/82] linux-user/aarch64: Generate GCS signal records
2025-07-27 8:02 ` [PATCH 77/82] linux-user/aarch64: Generate GCS signal records Richard Henderson
@ 2025-07-31 21:57 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:57 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Here we must push and pop a cap on the GCS stack as
> well as the gcs record on the normal stack.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> linux-user/aarch64/signal.c | 129 ++++++++++++++++++++++++++++++++++--
> 1 file changed, 123 insertions(+), 6 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 78/82] linux-user: Change exported get_elf_hwcap to abi_ulong
2025-07-27 8:02 ` [PATCH 78/82] linux-user: Change exported get_elf_hwcap to abi_ulong Richard Henderson
@ 2025-07-31 21:58 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:58 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> AArch64 is about to add the first 64-bit hwcap bit, so we
> have to expand the return type. Since the only user
> assigns this to a abi_ulong, match that type.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> linux-user/loader.h | 2 +-
> linux-user/elfload.c | 10 +++++-----
> 2 files changed, 6 insertions(+), 6 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 79/82] linux-user/aarch64: Enable GCS in HWCAP
2025-07-27 8:02 ` [PATCH 79/82] linux-user/aarch64: Enable GCS in HWCAP Richard Henderson
@ 2025-07-31 21:58 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 21:58 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> linux-user/elfload.c | 1 +
> 1 file changed, 1 insertion(+)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 80/82] tests/tcg/aarch64: Add gcsstr
2025-07-27 8:02 ` [PATCH 80/82] tests/tcg/aarch64: Add gcsstr Richard Henderson
@ 2025-07-31 22:05 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 22:05 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Add some infrastructure for testing gcs in userspace.
> Validate successful and trapped executions of GCSSTR.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> tests/tcg/aarch64/gcs.h | 71 +++++++++++++++++++++++++++++++
> tests/tcg/aarch64/gcsstr.c | 48 +++++++++++++++++++++
> tests/tcg/aarch64/Makefile.target | 5 +++
> 3 files changed, 124 insertions(+)
> create mode 100644 tests/tcg/aarch64/gcs.h
> create mode 100644 tests/tcg/aarch64/gcsstr.c
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 81/82] tests/tcg/aarch64: Add gcspushm
2025-07-27 8:02 ` [PATCH 81/82] tests/tcg/aarch64: Add gcspushm Richard Henderson
@ 2025-07-31 22:11 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 22:11 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Validate successful and trapped executions of GCSPUSHM, GCSPOPM.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> tests/tcg/aarch64/gcspushm.c | 77 +++++++++++++++++++++++++++++++
> tests/tcg/aarch64/Makefile.target | 2 +-
> 2 files changed, 78 insertions(+), 1 deletion(-)
> create mode 100644 tests/tcg/aarch64/gcspushm.c
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 82/82] tests/tcg/aarch64: Add gcsss
2025-07-27 8:02 ` [PATCH 82/82] tests/tcg/aarch64: Add gcsss Richard Henderson
@ 2025-07-31 22:14 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-07-31 22:14 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> Validate stack switching and recursion depth.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> tests/tcg/aarch64/gcs.h | 9 ++++
> tests/tcg/aarch64/gcsss.c | 74 +++++++++++++++++++++++++++++++
> tests/tcg/aarch64/Makefile.target | 2 +-
> 3 files changed, 84 insertions(+), 1 deletion(-)
> create mode 100644 tests/tcg/aarch64/gcsss.c
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 37/82] target/arm: Convert regime_is_user from switch to table
2025-07-30 21:21 ` Pierrick Bouvier
@ 2025-08-01 3:53 ` Richard Henderson
2025-08-01 16:10 ` Pierrick Bouvier
2025-08-01 18:06 ` Peter Maydell
0 siblings, 2 replies; 188+ messages in thread
From: Richard Henderson @ 2025-08-01 3:53 UTC (permalink / raw)
To: Pierrick Bouvier, qemu-devel; +Cc: qemu-arm
On 7/31/25 07:21, Pierrick Bouvier wrote:
>> #include "mmuidx-internal.h"
>> -#define EL(X) ((X << R_MMUIDXINFO_EL_SHIFT) | R_MMUIDXINFO_ELVALID_MASK)
>> +#define EL(X) ((X << R_MMUIDXINFO_EL_SHIFT) | R_MMUIDXINFO_ELVALID_MASK | \
>> + ((X == 0) << R_MMUIDXINFO_USER_SHIFT))
>> #define REL(X) ((X << R_MMUIDXINFO_REL_SHIFT) | R_MMUIDXINFO_RELVALID_MASK)
>> #define R2 R_MMUIDXINFO_2RANGES_MASK
>> #define PAN R_MMUIDXINFO_PAN_MASK
>> +#define USER R_MMUIDXINFO_USER_MASK
>> const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8] = {
>> /*
>> @@ -33,7 +35,7 @@ const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8] = {
>> [ARMMMUIdx_Stage2_S] = REL(2),
>> [ARMMMUIdx_Stage2] = REL(2),
>> - [ARMMMUIdx_Stage1_E0] = REL(1) | R2,
>> + [ARMMMUIdx_Stage1_E0] = REL(1) | R2 | USER,
>> [ARMMMUIdx_Stage1_E1] = REL(1) | R2,
>> [ARMMMUIdx_Stage1_E1_PAN] = REL(1) | R2 | PAN,
>
> Maybe I missed something, but what about other entries that were initially treated in the
> switch?
> - ARMMMUIdx_E.0_0
> - ARMMMUIdx_M*User
See the change to EL().
I'm not sure why ARMMMUIdx_Stage1_* is excluded from arm_mmu_idx_to_el(), but I don't
change that in this patch series.
r~
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 47/82] target/arm: Expand pstate to 64 bits
2025-07-31 19:13 ` Pierrick Bouvier
@ 2025-08-01 4:24 ` Richard Henderson
2025-08-01 12:35 ` Manos Pitsidianakis
2025-08-01 4:29 ` Richard Henderson
2025-08-01 13:22 ` Peter Maydell
2 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-08-01 4:24 UTC (permalink / raw)
To: Pierrick Bouvier, qemu-devel; +Cc: qemu-arm, Thiago Jung Bauermann
On 8/1/25 05:13, Pierrick Bouvier wrote:
> On 7/27/25 1:02 AM, Richard Henderson wrote:
>> The ARM now defines 36 bits in SPSR_ELx in aarch64 mode, so
>> it's time to bite the bullet and extend PSTATE to match.
>>
>> Most changes are straightforward, adjusting printf formats,
>> changing local variable types. More complex is migration,
>> where to maintain backward compatibility a new pstate64
>> record is introduced, and only when one of the extensions
>> that sets bits 32-35 are active.
>>
>> The fate of gdbstub is left undecided for the moment.
...
>> diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
>> index 64ee9b3b56..3cef47281a 100644
>> --- a/target/arm/gdbstub64.c
>> +++ b/target/arm/gdbstub64.c
>> @@ -47,6 +47,7 @@ int aarch64_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf,
>> int n)
>> case 32:
>> return gdb_get_reg64(mem_buf, env->pc);
>> case 33:
>> + /* pstate is now a 64-bit value; can we simply adjust the xml? */
>> return gdb_get_reg32(mem_buf, pstate_read(env));
>> }
>
> If I'm correct, we currently don't expose PSTATE through gdbstub, but only CPSR. This was
> a bit confusing for me, considering that CPSR is not even supposed to exist in Aarch64.
Correct. An old error, for sure.
> Maybe it's a good opportunity to expose PSTATE instead, which could have a 64 bits size.
> This way, we don't break any workflow.
Hmm, perhaps adding a "org.gnu.gdb.aarch64.pstate" xml with just one 64-bit value is the
best solution. Thiago?
r~
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 47/82] target/arm: Expand pstate to 64 bits
2025-07-31 19:13 ` Pierrick Bouvier
2025-08-01 4:24 ` Richard Henderson
@ 2025-08-01 4:29 ` Richard Henderson
2025-08-01 16:12 ` Pierrick Bouvier
2025-08-01 13:22 ` Peter Maydell
2 siblings, 1 reply; 188+ messages in thread
From: Richard Henderson @ 2025-08-01 4:29 UTC (permalink / raw)
To: Pierrick Bouvier, qemu-devel; +Cc: qemu-arm
On 8/1/25 05:13, Pierrick Bouvier wrote:
>> diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c
>> index 71c6c44ee8..f61adf1f80 100644
>> --- a/target/arm/tcg/helper-a64.c
>> +++ b/target/arm/tcg/helper-a64.c
>> @@ -639,7 +639,7 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
>> ARMCPU *cpu = env_archcpu(env);
>> int cur_el = arm_current_el(env);
>> unsigned int spsr_idx = aarch64_banked_spsr_index(cur_el);
>> - uint32_t spsr = env->banked_spsr[spsr_idx];
>> + uint64_t spsr = env->banked_spsr[spsr_idx];
>> int new_el;
>> bool return_to_aa64 = (spsr & PSTATE_nRW) == 0;
>
> Would that be better or worse to simply save the upper 32 bits, considering that cpsr
> already holds the lower ones in Aarch64 mode?
I don't understand this comment.
(1) banked_spsr[] is already uint64_t
(2) SPSR_ELx is supposed to be uint64_t
(3) We were accidentally dropping the high bits of spsr here
because the local variable had the wrong type, before it
gets sent to pstate_write().
r~
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 47/82] target/arm: Expand pstate to 64 bits
2025-08-01 4:24 ` Richard Henderson
@ 2025-08-01 12:35 ` Manos Pitsidianakis
0 siblings, 0 replies; 188+ messages in thread
From: Manos Pitsidianakis @ 2025-08-01 12:35 UTC (permalink / raw)
To: Richard Henderson
Cc: Pierrick Bouvier, qemu-devel, qemu-arm, Thiago Jung Bauermann
On Fri, Aug 1, 2025 at 7:25 AM Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> On 8/1/25 05:13, Pierrick Bouvier wrote:
> > On 7/27/25 1:02 AM, Richard Henderson wrote:
> >> The ARM now defines 36 bits in SPSR_ELx in aarch64 mode, so
> >> it's time to bite the bullet and extend PSTATE to match.
> >>
> >> Most changes are straightforward, adjusting printf formats,
> >> changing local variable types. More complex is migration,
> >> where to maintain backward compatibility a new pstate64
> >> record is introduced, and only when one of the extensions
> >> that sets bits 32-35 are active.
> >>
> >> The fate of gdbstub is left undecided for the moment.
> ...
> >> diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
> >> index 64ee9b3b56..3cef47281a 100644
> >> --- a/target/arm/gdbstub64.c
> >> +++ b/target/arm/gdbstub64.c
> >> @@ -47,6 +47,7 @@ int aarch64_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf,
> >> int n)
> >> case 32:
> >> return gdb_get_reg64(mem_buf, env->pc);
> >> case 33:
> >> + /* pstate is now a 64-bit value; can we simply adjust the xml? */
> >> return gdb_get_reg32(mem_buf, pstate_read(env));
> >> }
> >
> > If I'm correct, we currently don't expose PSTATE through gdbstub, but only CPSR. This was
> > a bit confusing for me, considering that CPSR is not even supposed to exist in Aarch64.
>
> Correct. An old error, for sure.
>
>
> > Maybe it's a good opportunity to expose PSTATE instead, which could have a 64 bits size.
> > This way, we don't break any workflow.
>
> Hmm, perhaps adding a "org.gnu.gdb.aarch64.pstate" xml with just one 64-bit value is the
> best solution. Thiago?
A single line in gdb-xml/aarch64-core.xml should be enough:
<reg name="PSTATE" bitsize="64" />
I'd keep cpsr even if it's now effectively duplicated. It comes from
gdb's upstream aarch64 schema so it's deeply ingrained by now.
Then you can do `info registers $PSTATE` in gdb after adding the reg
getter in gdbstub.
I think it could be possible to define a
<flags id="pstate_flags" size="8">
...
</flags>
type that re-uses the cpsr_flags type definition by setting a field
<field start="0" end="31" type = "cpsr_flags" /> but I haven't tried
it.
>
>
> r~
>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 47/82] target/arm: Expand pstate to 64 bits
2025-07-31 19:13 ` Pierrick Bouvier
2025-08-01 4:24 ` Richard Henderson
2025-08-01 4:29 ` Richard Henderson
@ 2025-08-01 13:22 ` Peter Maydell
2025-08-01 16:26 ` Pierrick Bouvier
2025-08-01 18:45 ` Manos Pitsidianakis
2 siblings, 2 replies; 188+ messages in thread
From: Peter Maydell @ 2025-08-01 13:22 UTC (permalink / raw)
To: Pierrick Bouvier; +Cc: Richard Henderson, qemu-devel, qemu-arm
On Thu, 31 Jul 2025 at 21:34, Pierrick Bouvier
<pierrick.bouvier@linaro.org> wrote:
>
> On 7/27/25 1:02 AM, Richard Henderson wrote:
> > diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
> > index 64ee9b3b56..3cef47281a 100644
> > --- a/target/arm/gdbstub64.c
> > +++ b/target/arm/gdbstub64.c
> > @@ -47,6 +47,7 @@ int aarch64_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
> > case 32:
> > return gdb_get_reg64(mem_buf, env->pc);
> > case 33:
> > + /* pstate is now a 64-bit value; can we simply adjust the xml? */
> > return gdb_get_reg32(mem_buf, pstate_read(env));
> > }
>
> If I'm correct, we currently don't expose PSTATE through gdbstub, but
> only CPSR. This was a bit confusing for me, considering that CPSR is not
> even supposed to exist in Aarch64.
> Maybe it's a good opportunity to expose PSTATE instead, which could have
> a 64 bits size. This way, we don't break any workflow.
Architecturally, PSTATE is simply an abstract bundling together of
different information: it is not a particular format of a value,
whether 32 or 64 bit or otherwise. (This makes it different to
AArch32 CPSR, which really is a guest-visible register.)
The thing that *is* defined architecturally is the SPSR_ELx format, which
is where various bits of PSTATE get saved when reporting an exception up
to a higher exception level (and which is pretty much the AArch32 CPSR
format when the lower EL is AArch32). (Note that not *all* of PSTATE
appears in the SPSR_ELx: for example the SME SM and ZA bits are
considered part of PSTATE but they aren't saved into SPSR_ELx.)
For convenience, various pieces of software pass around information
in that SPSR_ELx format. Calling this either "CPSR" or "PSTATE"
is not really correct, but either is perhaps less confusing than
calling it SPSR when the context is that of the code running at the
lower EL rather than the higher.
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/include/asm/kgdb.h#n41
suggests that expanding the existing pstate to 64 bits is probably
likely to produce problems. Perhaps we should define a pstate_high
or something for the top 32 bits?
(I'll see if I can find out if anybody's already looked at this
for the native debug case.)
thanks
-- PMM
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 37/82] target/arm: Convert regime_is_user from switch to table
2025-08-01 3:53 ` Richard Henderson
@ 2025-08-01 16:10 ` Pierrick Bouvier
2025-08-01 18:06 ` Peter Maydell
1 sibling, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-08-01 16:10 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/31/25 8:53 PM, Richard Henderson wrote:
> On 7/31/25 07:21, Pierrick Bouvier wrote:
>>> #include "mmuidx-internal.h"
>>> -#define EL(X) ((X << R_MMUIDXINFO_EL_SHIFT) | R_MMUIDXINFO_ELVALID_MASK)
>>> +#define EL(X) ((X << R_MMUIDXINFO_EL_SHIFT) | R_MMUIDXINFO_ELVALID_MASK | \
>>> + ((X == 0) << R_MMUIDXINFO_USER_SHIFT))
>>> #define REL(X) ((X << R_MMUIDXINFO_REL_SHIFT) | R_MMUIDXINFO_RELVALID_MASK)
>>> #define R2 R_MMUIDXINFO_2RANGES_MASK
>>> #define PAN R_MMUIDXINFO_PAN_MASK
>>> +#define USER R_MMUIDXINFO_USER_MASK
>>> const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8] = {
>>> /*
>>> @@ -33,7 +35,7 @@ const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8] = {
>>> [ARMMMUIdx_Stage2_S] = REL(2),
>>> [ARMMMUIdx_Stage2] = REL(2),
>>> - [ARMMMUIdx_Stage1_E0] = REL(1) | R2,
>>> + [ARMMMUIdx_Stage1_E0] = REL(1) | R2 | USER,
>>> [ARMMMUIdx_Stage1_E1] = REL(1) | R2,
>>> [ARMMMUIdx_Stage1_E1_PAN] = REL(1) | R2 | PAN,
>>
>> Maybe I missed something, but what about other entries that were initially treated in the
>> switch?
>> - ARMMMUIdx_E.0_0
>> - ARMMMUIdx_M*User
>
> See the change to EL().
>
Ok.
> I'm not sure why ARMMMUIdx_Stage1_* is excluded from arm_mmu_idx_to_el(), but I don't
> change that in this patch series.
>
Maybe it could be more explicit to either tag all concerned entries with
USER, than rely on EL(0) adding the magic, since this fails to apply for
ARMMMUIdx_Stage1_E0. It's just a suggestion for readability though.
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
>
> r~
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 47/82] target/arm: Expand pstate to 64 bits
2025-08-01 4:29 ` Richard Henderson
@ 2025-08-01 16:12 ` Pierrick Bouvier
2025-08-01 20:19 ` Richard Henderson
0 siblings, 1 reply; 188+ messages in thread
From: Pierrick Bouvier @ 2025-08-01 16:12 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/31/25 9:29 PM, Richard Henderson wrote:
> On 8/1/25 05:13, Pierrick Bouvier wrote:
>>> diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c
>>> index 71c6c44ee8..f61adf1f80 100644
>>> --- a/target/arm/tcg/helper-a64.c
>>> +++ b/target/arm/tcg/helper-a64.c
>>> @@ -639,7 +639,7 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
>>> ARMCPU *cpu = env_archcpu(env);
>>> int cur_el = arm_current_el(env);
>>> unsigned int spsr_idx = aarch64_banked_spsr_index(cur_el);
>>> - uint32_t spsr = env->banked_spsr[spsr_idx];
>>> + uint64_t spsr = env->banked_spsr[spsr_idx];
>>> int new_el;
>>> bool return_to_aa64 = (spsr & PSTATE_nRW) == 0;
>>
>> Would that be better or worse to simply save the upper 32 bits, considering that cpsr
>> already holds the lower ones in Aarch64 mode?
>
> I don't understand this comment.
>
> (1) banked_spsr[] is already uint64_t
> (2) SPSR_ELx is supposed to be uint64_t
> (3) We were accidentally dropping the high bits of spsr here
> because the local variable had the wrong type, before it
> gets sent to pstate_write().
>
My comment was related to vmstate_pstate64. Sorry it was confusing as I
left the last change concerning helper-a64.c, which was not related at all.
So the comment was that vmstate_cpsr already contains the lower 32 bits
of pstate, and thus we could save only the upper part in the new field.
>
> r~
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 47/82] target/arm: Expand pstate to 64 bits
2025-08-01 13:22 ` Peter Maydell
@ 2025-08-01 16:26 ` Pierrick Bouvier
2025-08-01 16:37 ` Peter Maydell
2025-08-01 18:45 ` Manos Pitsidianakis
1 sibling, 1 reply; 188+ messages in thread
From: Pierrick Bouvier @ 2025-08-01 16:26 UTC (permalink / raw)
To: Peter Maydell; +Cc: Richard Henderson, qemu-devel, qemu-arm
On 8/1/25 6:22 AM, Peter Maydell wrote:
> On Thu, 31 Jul 2025 at 21:34, Pierrick Bouvier
> <pierrick.bouvier@linaro.org> wrote:
>>
>> On 7/27/25 1:02 AM, Richard Henderson wrote:
>>> diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
>>> index 64ee9b3b56..3cef47281a 100644
>>> --- a/target/arm/gdbstub64.c
>>> +++ b/target/arm/gdbstub64.c
>>> @@ -47,6 +47,7 @@ int aarch64_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
>>> case 32:
>>> return gdb_get_reg64(mem_buf, env->pc);
>>> case 33:
>>> + /* pstate is now a 64-bit value; can we simply adjust the xml? */
>>> return gdb_get_reg32(mem_buf, pstate_read(env));
>>> }
>>
>> If I'm correct, we currently don't expose PSTATE through gdbstub, but
>> only CPSR. This was a bit confusing for me, considering that CPSR is not
>> even supposed to exist in Aarch64.
>> Maybe it's a good opportunity to expose PSTATE instead, which could have
>> a 64 bits size. This way, we don't break any workflow.
>
> Architecturally, PSTATE is simply an abstract bundling together of
> different information: it is not a particular format of a value,
> whether 32 or 64 bit or otherwise. (This makes it different to
> AArch32 CPSR, which really is a guest-visible register.)
>
I see.
Then maybe what we really miss are the special registers associated to
PSTATE (CurrentEL, DAIF, NZCV, ...) which are defined architecturally.
When I tried to read EL for the first time using gdbstub, I was looking
for CurrentEL, and finally found it accidently under CPSR.
Would that make more sense?
> The thing that *is* defined architecturally is the SPSR_ELx format, which
> is where various bits of PSTATE get saved when reporting an exception up
> to a higher exception level (and which is pretty much the AArch32 CPSR
> format when the lower EL is AArch32). (Note that not *all* of PSTATE
> appears in the SPSR_ELx: for example the SME SM and ZA bits are
> considered part of PSTATE but they aren't saved into SPSR_ELx.)
>
> For convenience, various pieces of software pass around information
> in that SPSR_ELx format. Calling this either "CPSR" or "PSTATE"
> is not really correct, but either is perhaps less confusing than
> calling it SPSR when the context is that of the code running at the
> lower EL rather than the higher.
>
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/include/asm/kgdb.h#n41
> suggests that expanding the existing pstate to 64 bits is probably
> likely to produce problems. Perhaps we should define a pstate_high
> or something for the top 32 bits?
>
It seems we don't expose pstate at all now, and from your answer above,
it would not make sense to expose it directly, as it's not formally
defined. What is exposed by kgdb?
> (I'll see if I can find out if anybody's already looked at this
> for the native debug case.)
>
> thanks
> -- PMM
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 47/82] target/arm: Expand pstate to 64 bits
2025-08-01 16:26 ` Pierrick Bouvier
@ 2025-08-01 16:37 ` Peter Maydell
2025-08-01 16:41 ` Pierrick Bouvier
0 siblings, 1 reply; 188+ messages in thread
From: Peter Maydell @ 2025-08-01 16:37 UTC (permalink / raw)
To: Pierrick Bouvier; +Cc: Richard Henderson, qemu-devel, qemu-arm
On Fri, 1 Aug 2025 at 17:26, Pierrick Bouvier
<pierrick.bouvier@linaro.org> wrote:
>
> On 8/1/25 6:22 AM, Peter Maydell wrote:
> > On Thu, 31 Jul 2025 at 21:34, Pierrick Bouvier
> > <pierrick.bouvier@linaro.org> wrote:
> >>
> >> On 7/27/25 1:02 AM, Richard Henderson wrote:
> >>> diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
> >>> index 64ee9b3b56..3cef47281a 100644
> >>> --- a/target/arm/gdbstub64.c
> >>> +++ b/target/arm/gdbstub64.c
> >>> @@ -47,6 +47,7 @@ int aarch64_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
> >>> case 32:
> >>> return gdb_get_reg64(mem_buf, env->pc);
> >>> case 33:
> >>> + /* pstate is now a 64-bit value; can we simply adjust the xml? */
> >>> return gdb_get_reg32(mem_buf, pstate_read(env));
> >>> }
> >>
> >> If I'm correct, we currently don't expose PSTATE through gdbstub, but
> >> only CPSR. This was a bit confusing for me, considering that CPSR is not
> >> even supposed to exist in Aarch64.
> >> Maybe it's a good opportunity to expose PSTATE instead, which could have
> >> a 64 bits size. This way, we don't break any workflow.
> >
> > Architecturally, PSTATE is simply an abstract bundling together of
> > different information: it is not a particular format of a value,
> > whether 32 or 64 bit or otherwise. (This makes it different to
> > AArch32 CPSR, which really is a guest-visible register.)
> >
>
> I see.
> Then maybe what we really miss are the special registers associated to
> PSTATE (CurrentEL, DAIF, NZCV, ...) which are defined architecturally.
> When I tried to read EL for the first time using gdbstub, I was looking
> for CurrentEL, and finally found it accidently under CPSR.
> Would that make more sense?
I think for backwards-compatibility reasons we should stick
with the current cpsr format for the information that is in it.
We do at least define the fields so you get a nice view of it:
(gdb) print $cpsr
$4 = [ EL=0 BTYPE=0 Z ]
> > The thing that *is* defined architecturally is the SPSR_ELx format, which
> > is where various bits of PSTATE get saved when reporting an exception up
> > to a higher exception level (and which is pretty much the AArch32 CPSR
> > format when the lower EL is AArch32). (Note that not *all* of PSTATE
> > appears in the SPSR_ELx: for example the SME SM and ZA bits are
> > considered part of PSTATE but they aren't saved into SPSR_ELx.)
> >
> > For convenience, various pieces of software pass around information
> > in that SPSR_ELx format. Calling this either "CPSR" or "PSTATE"
> > is not really correct, but either is perhaps less confusing than
> > calling it SPSR when the context is that of the code running at the
> > lower EL rather than the higher.
> >
> > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/include/asm/kgdb.h#n41
> > suggests that expanding the existing pstate to 64 bits is probably
> > likely to produce problems. Perhaps we should define a pstate_high
> > or something for the top 32 bits?
> >
>
> It seems we don't expose pstate at all now, and from your answer above,
> it would not make sense to expose it directly, as it's not formally
> defined. What is exposed by kgdb?
kgdb currently does the same thing we do, and exposes a 32-bit
"cpsr" value.
-- PMM
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 47/82] target/arm: Expand pstate to 64 bits
2025-08-01 16:37 ` Peter Maydell
@ 2025-08-01 16:41 ` Pierrick Bouvier
2025-08-01 16:44 ` Peter Maydell
0 siblings, 1 reply; 188+ messages in thread
From: Pierrick Bouvier @ 2025-08-01 16:41 UTC (permalink / raw)
To: Peter Maydell; +Cc: Richard Henderson, qemu-devel, qemu-arm
On 8/1/25 9:37 AM, Peter Maydell wrote:
> On Fri, 1 Aug 2025 at 17:26, Pierrick Bouvier
> <pierrick.bouvier@linaro.org> wrote:
>>
>> On 8/1/25 6:22 AM, Peter Maydell wrote:
>>> On Thu, 31 Jul 2025 at 21:34, Pierrick Bouvier
>>> <pierrick.bouvier@linaro.org> wrote:
>>>>
>>>> On 7/27/25 1:02 AM, Richard Henderson wrote:
>>>>> diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
>>>>> index 64ee9b3b56..3cef47281a 100644
>>>>> --- a/target/arm/gdbstub64.c
>>>>> +++ b/target/arm/gdbstub64.c
>>>>> @@ -47,6 +47,7 @@ int aarch64_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
>>>>> case 32:
>>>>> return gdb_get_reg64(mem_buf, env->pc);
>>>>> case 33:
>>>>> + /* pstate is now a 64-bit value; can we simply adjust the xml? */
>>>>> return gdb_get_reg32(mem_buf, pstate_read(env));
>>>>> }
>>>>
>>>> If I'm correct, we currently don't expose PSTATE through gdbstub, but
>>>> only CPSR. This was a bit confusing for me, considering that CPSR is not
>>>> even supposed to exist in Aarch64.
>>>> Maybe it's a good opportunity to expose PSTATE instead, which could have
>>>> a 64 bits size. This way, we don't break any workflow.
>>>
>>> Architecturally, PSTATE is simply an abstract bundling together of
>>> different information: it is not a particular format of a value,
>>> whether 32 or 64 bit or otherwise. (This makes it different to
>>> AArch32 CPSR, which really is a guest-visible register.)
>>>
>>
>> I see.
>> Then maybe what we really miss are the special registers associated to
>> PSTATE (CurrentEL, DAIF, NZCV, ...) which are defined architecturally.
>> When I tried to read EL for the first time using gdbstub, I was looking
>> for CurrentEL, and finally found it accidently under CPSR.
>> Would that make more sense?
>
> I think for backwards-compatibility reasons we should stick
> with the current cpsr format for the information that is in it.
Yes, it's here anyway. My proposal was to add new registers.
> We do at least define the fields so you get a nice view of it:
>
> (gdb) print $cpsr
> $4 = [ EL=0 BTYPE=0 Z ]
>
Do you have specific pretty printers installed? On my debian trixie (gdb
16.3), there is no pretty printer for cpsr by default.
>>> The thing that *is* defined architecturally is the SPSR_ELx format, which
>>> is where various bits of PSTATE get saved when reporting an exception up
>>> to a higher exception level (and which is pretty much the AArch32 CPSR
>>> format when the lower EL is AArch32). (Note that not *all* of PSTATE
>>> appears in the SPSR_ELx: for example the SME SM and ZA bits are
>>> considered part of PSTATE but they aren't saved into SPSR_ELx.)
>>>
>>> For convenience, various pieces of software pass around information
>>> in that SPSR_ELx format. Calling this either "CPSR" or "PSTATE"
>>> is not really correct, but either is perhaps less confusing than
>>> calling it SPSR when the context is that of the code running at the
>>> lower EL rather than the higher.
>>>
>>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/include/asm/kgdb.h#n41
>>> suggests that expanding the existing pstate to 64 bits is probably
>>> likely to produce problems. Perhaps we should define a pstate_high
>>> or something for the top 32 bits?
>>>
>>
>> It seems we don't expose pstate at all now, and from your answer above,
>> it would not make sense to expose it directly, as it's not formally
>> defined. What is exposed by kgdb?
>
> kgdb currently does the same thing we do, and exposes a 32-bit
> "cpsr" value.
>
> -- PMM
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 47/82] target/arm: Expand pstate to 64 bits
2025-08-01 16:41 ` Pierrick Bouvier
@ 2025-08-01 16:44 ` Peter Maydell
2025-08-01 16:53 ` Pierrick Bouvier
0 siblings, 1 reply; 188+ messages in thread
From: Peter Maydell @ 2025-08-01 16:44 UTC (permalink / raw)
To: Pierrick Bouvier; +Cc: Richard Henderson, qemu-devel, qemu-arm
On Fri, 1 Aug 2025 at 17:41, Pierrick Bouvier
<pierrick.bouvier@linaro.org> wrote:
>
> On 8/1/25 9:37 AM, Peter Maydell wrote:
> > We do at least define the fields so you get a nice view of it:
> >
> > (gdb) print $cpsr
> > $4 = [ EL=0 BTYPE=0 Z ]
> >
>
> Do you have specific pretty printers installed? On my debian trixie (gdb
> 16.3), there is no pretty printer for cpsr by default.
I'm not aware of having installed any. This is
GNU gdb (Ubuntu 15.0.50.20240403-0ubuntu1) 15.0.50.20240403-git
I was assuming that this was just plain gdb doing something
useful because the xml defines the field names and bitpositions
(at least if your QEMU has commit 63070ce368e1a where Manos
synced our xml to upstream gdb's to add these).
-- PMM
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 47/82] target/arm: Expand pstate to 64 bits
2025-08-01 16:44 ` Peter Maydell
@ 2025-08-01 16:53 ` Pierrick Bouvier
2025-08-01 16:55 ` Pierrick Bouvier
0 siblings, 1 reply; 188+ messages in thread
From: Pierrick Bouvier @ 2025-08-01 16:53 UTC (permalink / raw)
To: Peter Maydell; +Cc: Richard Henderson, qemu-devel, qemu-arm
On 8/1/25 9:44 AM, Peter Maydell wrote:
> On Fri, 1 Aug 2025 at 17:41, Pierrick Bouvier
> <pierrick.bouvier@linaro.org> wrote:
>>
>> On 8/1/25 9:37 AM, Peter Maydell wrote:
>>> We do at least define the fields so you get a nice view of it:
>>>
>>> (gdb) print $cpsr
>>> $4 = [ EL=0 BTYPE=0 Z ]
>>>
>>
>> Do you have specific pretty printers installed? On my debian trixie (gdb
>> 16.3), there is no pretty printer for cpsr by default.
>
> I'm not aware of having installed any. This is
> GNU gdb (Ubuntu 15.0.50.20240403-0ubuntu1) 15.0.50.20240403-git
>
Trying with a ubuntu 24.04 container, I don't see it neither. Maybe
something is missing in my gdbinit.
> I was assuming that this was just plain gdb doing something
> useful because the xml defines the field names and bitpositions
> (at least if your QEMU has commit 63070ce368e1a where Manos
> synced our xml to upstream gdb's to add these).
>
> -- PMM
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 47/82] target/arm: Expand pstate to 64 bits
2025-08-01 16:53 ` Pierrick Bouvier
@ 2025-08-01 16:55 ` Pierrick Bouvier
0 siblings, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-08-01 16:55 UTC (permalink / raw)
To: Peter Maydell; +Cc: Richard Henderson, qemu-devel, qemu-arm
On 8/1/25 9:53 AM, Pierrick Bouvier wrote:
> On 8/1/25 9:44 AM, Peter Maydell wrote:
>> On Fri, 1 Aug 2025 at 17:41, Pierrick Bouvier
>> <pierrick.bouvier@linaro.org> wrote:
>>>
>>> On 8/1/25 9:37 AM, Peter Maydell wrote:
>>>> We do at least define the fields so you get a nice view of it:
>>>>
>>>> (gdb) print $cpsr
>>>> $4 = [ EL=0 BTYPE=0 Z ]
>>>>
>>>
>>> Do you have specific pretty printers installed? On my debian trixie (gdb
>>> 16.3), there is no pretty printer for cpsr by default.
>>
>> I'm not aware of having installed any. This is
>> GNU gdb (Ubuntu 15.0.50.20240403-0ubuntu1) 15.0.50.20240403-git
>>
>
> Trying with a ubuntu 24.04 container, I don't see it neither. Maybe
> something is missing in my gdbinit.
>
My fault, I was using my system wide qemu binary. Using master branch it
works well indeed.
>> I was assuming that this was just plain gdb doing something
>> useful because the xml defines the field names and bitpositions
>> (at least if your QEMU has commit 63070ce368e1a where Manos
>> synced our xml to upstream gdb's to add these).
>>
>> -- PMM
>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 37/82] target/arm: Convert regime_is_user from switch to table
2025-08-01 3:53 ` Richard Henderson
2025-08-01 16:10 ` Pierrick Bouvier
@ 2025-08-01 18:06 ` Peter Maydell
1 sibling, 0 replies; 188+ messages in thread
From: Peter Maydell @ 2025-08-01 18:06 UTC (permalink / raw)
To: Richard Henderson; +Cc: Pierrick Bouvier, qemu-devel, qemu-arm
On Fri, 1 Aug 2025 at 04:54, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> On 7/31/25 07:21, Pierrick Bouvier wrote:
> >> #include "mmuidx-internal.h"
> >> -#define EL(X) ((X << R_MMUIDXINFO_EL_SHIFT) | R_MMUIDXINFO_ELVALID_MASK)
> >> +#define EL(X) ((X << R_MMUIDXINFO_EL_SHIFT) | R_MMUIDXINFO_ELVALID_MASK | \
> >> + ((X == 0) << R_MMUIDXINFO_USER_SHIFT))
> >> #define REL(X) ((X << R_MMUIDXINFO_REL_SHIFT) | R_MMUIDXINFO_RELVALID_MASK)
> >> #define R2 R_MMUIDXINFO_2RANGES_MASK
> >> #define PAN R_MMUIDXINFO_PAN_MASK
> >> +#define USER R_MMUIDXINFO_USER_MASK
> >> const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8] = {
> >> /*
> >> @@ -33,7 +35,7 @@ const uint32_t arm_mmuidx_table[ARM_MMU_IDX_M + 8] = {
> >> [ARMMMUIdx_Stage2_S] = REL(2),
> >> [ARMMMUIdx_Stage2] = REL(2),
> >> - [ARMMMUIdx_Stage1_E0] = REL(1) | R2,
> >> + [ARMMMUIdx_Stage1_E0] = REL(1) | R2 | USER,
> >> [ARMMMUIdx_Stage1_E1] = REL(1) | R2,
> >> [ARMMMUIdx_Stage1_E1_PAN] = REL(1) | R2 | PAN,
> >
> > Maybe I missed something, but what about other entries that were initially treated in the
> > switch?
> > - ARMMMUIdx_E.0_0
> > - ARMMMUIdx_M*User
>
> See the change to EL().
>
> I'm not sure why ARMMMUIdx_Stage1_* is excluded from arm_mmu_idx_to_el(), but I don't
> change that in this patch series.
It's always been that way through various refactorings
of the mmu index, back to commit c1e3781090b9d36 when
the function was added.
In practice we only use arm_mmu_idx_to_el() to get back to
the EL from the MMU index that we put into the TB flags.
So we know it's always one of the "complete translation"
index values, not a Stage1-only, Stage2-only or Phys index.
My guess is I originally put in the assert that enforced
that you don't call it with either a Stage2-only or a
Stage1-only mmuidx because I knew that couldn't happen and
it meant I could implement the idx-to-EL code for the
valid cases as "mmu_idx & 3" and didn't need to add
extra code to handle a Stage1-only index the function
would never see.
thanks
-- PMM
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 47/82] target/arm: Expand pstate to 64 bits
2025-08-01 13:22 ` Peter Maydell
2025-08-01 16:26 ` Pierrick Bouvier
@ 2025-08-01 18:45 ` Manos Pitsidianakis
2025-08-02 3:14 ` Thiago Jung Bauermann
1 sibling, 1 reply; 188+ messages in thread
From: Manos Pitsidianakis @ 2025-08-01 18:45 UTC (permalink / raw)
To: Peter Maydell; +Cc: Pierrick Bouvier, Richard Henderson, qemu-devel, qemu-arm
On Fri, Aug 1, 2025 at 4:33 PM Peter Maydell <peter.maydell@linaro.org> wrote:
>
> On Thu, 31 Jul 2025 at 21:34, Pierrick Bouvier
> <pierrick.bouvier@linaro.org> wrote:
> >
> > On 7/27/25 1:02 AM, Richard Henderson wrote:
> > > diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
> > > index 64ee9b3b56..3cef47281a 100644
> > > --- a/target/arm/gdbstub64.c
> > > +++ b/target/arm/gdbstub64.c
> > > @@ -47,6 +47,7 @@ int aarch64_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
> > > case 32:
> > > return gdb_get_reg64(mem_buf, env->pc);
> > > case 33:
> > > + /* pstate is now a 64-bit value; can we simply adjust the xml? */
> > > return gdb_get_reg32(mem_buf, pstate_read(env));
> > > }
> >
> > If I'm correct, we currently don't expose PSTATE through gdbstub, but
> > only CPSR. This was a bit confusing for me, considering that CPSR is not
> > even supposed to exist in Aarch64.
> > Maybe it's a good opportunity to expose PSTATE instead, which could have
> > a 64 bits size. This way, we don't break any workflow.
>
> Architecturally, PSTATE is simply an abstract bundling together of
> different information: it is not a particular format of a value,
> whether 32 or 64 bit or otherwise. (This makes it different to
> AArch32 CPSR, which really is a guest-visible register.)
>
> The thing that *is* defined architecturally is the SPSR_ELx format, which
> is where various bits of PSTATE get saved when reporting an exception up
> to a higher exception level (and which is pretty much the AArch32 CPSR
> format when the lower EL is AArch32). (Note that not *all* of PSTATE
> appears in the SPSR_ELx: for example the SME SM and ZA bits are
> considered part of PSTATE but they aren't saved into SPSR_ELx.)
>
> For convenience, various pieces of software pass around information
> in that SPSR_ELx format. Calling this either "CPSR" or "PSTATE"
> is not really correct, but either is perhaps less confusing than
> calling it SPSR when the context is that of the code running at the
> lower EL rather than the higher.
>
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/include/asm/kgdb.h#n41
> suggests that expanding the existing pstate to 64 bits is probably
> likely to produce problems. Perhaps we should define a pstate_high
> or something for the top 32 bits?
>
IIUC, this is only a problem if you use the default gdb architecture
register map, but QEMU ships its own as part of gdbstub, so it's free
to change register definition of cspr. Or add a new PSTATE register.
> (I'll see if I can find out if anybody's already looked at this
> for the native debug case.)
>
> thanks
> -- PMM
>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 47/82] target/arm: Expand pstate to 64 bits
2025-08-01 16:12 ` Pierrick Bouvier
@ 2025-08-01 20:19 ` Richard Henderson
0 siblings, 0 replies; 188+ messages in thread
From: Richard Henderson @ 2025-08-01 20:19 UTC (permalink / raw)
To: Pierrick Bouvier, qemu-devel; +Cc: qemu-arm
On 8/2/25 02:12, Pierrick Bouvier wrote:
> My comment was related to vmstate_pstate64. Sorry it was confusing as I left the last
> change concerning helper-a64.c, which was not related at all.
>
> So the comment was that vmstate_cpsr already contains the lower 32 bits of pstate, and
> thus we could save only the upper part in the new field.
That was part laziness. By saving the lower half twice, I can simply do
pstate_write(env, val)
to load the data, rather than
pstate_write(env, (val << 32) | pstate_read(env));
or something, to merge the halves.
r~
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 47/82] target/arm: Expand pstate to 64 bits
2025-07-27 8:02 ` [PATCH 47/82] target/arm: Expand pstate to 64 bits Richard Henderson
2025-07-31 19:13 ` Pierrick Bouvier
@ 2025-08-01 20:22 ` Pierrick Bouvier
1 sibling, 0 replies; 188+ messages in thread
From: Pierrick Bouvier @ 2025-08-01 20:22 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: qemu-arm
On 7/27/25 1:02 AM, Richard Henderson wrote:
> The ARM now defines 36 bits in SPSR_ELx in aarch64 mode, so
> it's time to bite the bullet and extend PSTATE to match.
>
> Most changes are straightforward, adjusting printf formats,
> changing local variable types. More complex is migration,
> where to maintain backward compatibility a new pstate64
> record is introduced, and only when one of the extensions
> that sets bits 32-35 are active.
>
> The fate of gdbstub is left undecided for the moment.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/cpu.h | 8 +++---
> target/arm/tcg/translate.h | 20 ++++++-------
> target/arm/cpu.c | 6 ++--
> target/arm/gdbstub64.c | 1 +
> target/arm/helper.c | 11 ++++----
> target/arm/machine.c | 56 +++++++++++++++++++++++++++++++++++++
> target/arm/tcg/helper-a64.c | 2 +-
> 7 files changed, 81 insertions(+), 23 deletions(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
^ permalink raw reply [flat|nested] 188+ messages in thread
* Re: [PATCH 47/82] target/arm: Expand pstate to 64 bits
2025-08-01 18:45 ` Manos Pitsidianakis
@ 2025-08-02 3:14 ` Thiago Jung Bauermann
0 siblings, 0 replies; 188+ messages in thread
From: Thiago Jung Bauermann @ 2025-08-02 3:14 UTC (permalink / raw)
To: Manos Pitsidianakis
Cc: Peter Maydell, Pierrick Bouvier, Richard Henderson, qemu-devel,
qemu-arm
Manos Pitsidianakis <manos.pitsidianakis@linaro.org> writes:
> On Fri, Aug 1, 2025 at 4:33 PM Peter Maydell <peter.maydell@linaro.org> wrote:
>>
>> On Thu, 31 Jul 2025 at 21:34, Pierrick Bouvier
>> <pierrick.bouvier@linaro.org> wrote:
>> >
>> > On 7/27/25 1:02 AM, Richard Henderson wrote:
>> > > diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
>> > > index 64ee9b3b56..3cef47281a 100644
>> > > --- a/target/arm/gdbstub64.c
>> > > +++ b/target/arm/gdbstub64.c
>> > > @@ -47,6 +47,7 @@ int aarch64_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
>> > > case 32:
>> > > return gdb_get_reg64(mem_buf, env->pc);
>> > > case 33:
>> > > + /* pstate is now a 64-bit value; can we simply adjust the xml? */
>> > > return gdb_get_reg32(mem_buf, pstate_read(env));
>> > > }
>> >
>> > If I'm correct, we currently don't expose PSTATE through gdbstub, but
>> > only CPSR. This was a bit confusing for me, considering that CPSR is not
>> > even supposed to exist in Aarch64.
>> > Maybe it's a good opportunity to expose PSTATE instead, which could have
>> > a 64 bits size. This way, we don't break any workflow.
>>
>> Architecturally, PSTATE is simply an abstract bundling together of
>> different information: it is not a particular format of a value,
>> whether 32 or 64 bit or otherwise. (This makes it different to
>> AArch32 CPSR, which really is a guest-visible register.)
>>
>> The thing that *is* defined architecturally is the SPSR_ELx format, which
>> is where various bits of PSTATE get saved when reporting an exception up
>> to a higher exception level (and which is pretty much the AArch32 CPSR
>> format when the lower EL is AArch32). (Note that not *all* of PSTATE
>> appears in the SPSR_ELx: for example the SME SM and ZA bits are
>> considered part of PSTATE but they aren't saved into SPSR_ELx.)
>>
>> For convenience, various pieces of software pass around information
>> in that SPSR_ELx format. Calling this either "CPSR" or "PSTATE"
>> is not really correct, but either is perhaps less confusing than
>> calling it SPSR when the context is that of the code running at the
>> lower EL rather than the higher.
>>
>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/arm64/include/asm/kgdb.h#n41
>> suggests that expanding the existing pstate to 64 bits is probably
>> likely to produce problems. Perhaps we should define a pstate_high
>> or something for the top 32 bits?
>>
>
> IIUC, this is only a problem if you use the default gdb architecture
> register map, but QEMU ships its own as part of gdbstub, so it's free
> to change register definition of cspr. Or add a new PSTATE register.
That is correct. The kgdb.h comment also mentions this:
* Note that if you are using one of the versions of gdb that supports
* the gdb-7.7 version of the protocol you cannot use kgdb directly
* without providing a custom register description (gdb can load new
* protocol descriptions at runtime).
"providing a custom register description" is the manual procedure the
user can perform that is equivalent to the gdbstub sending its own
register map XML ("target description" in GDB parlance) to GDB, as the
QEMU gdbstub does.
I checked and the only places where GDB hardcodes the CPSR size is in
Linux and FreeBSD specific code, when reading or writing a core file
because in that case the size is defined by the OS.
Note that the CPSR position in the register map is hardcoded, defining
its register number as 33.
--
Thiago
^ permalink raw reply [flat|nested] 188+ messages in thread
end of thread, other threads:[~2025-08-02 3:15 UTC | newest]
Thread overview: 188+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-27 8:01 [PATCH for-10.2 00/82] target/arm: Implement FEAT_GCS Richard Henderson
2025-07-27 8:01 ` [PATCH 01/82] target/arm: Add prot_check parameter to pmsav8_mpu_lookup Richard Henderson
2025-07-30 20:27 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 02/82] target/arm: Add in_prot_check to S1Translate Richard Henderson
2025-07-30 20:27 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 03/82] target/arm: Skip permission check from arm_cpu_get_phys_page_attrs_debug Richard Henderson
2025-07-30 20:28 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 04/82] target/arm: Introduce get_phys_addr_for_at Richard Henderson
2025-07-30 20:29 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 05/82] target/arm: Skip AF and DB updates for AccessType_AT Richard Henderson
2025-07-30 20:31 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 06/82] target/arm: Add prot_check parameter to do_ats_write Richard Henderson
2025-07-30 20:35 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 07/82] target/arm: Fill in HFG[RWI]TR_EL2 bits for Arm v9.5 Richard Henderson
2025-07-30 20:35 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 08/82] target/arm: Remove outdated comment for ZCR_EL12 Richard Henderson
2025-07-30 20:36 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 09/82] target/arm: Implement FEAT_ATS1A Richard Henderson
2025-07-30 20:38 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 10/82] target/arm: Add isar feature test for FEAT_S1PIE, FEAT_S2PIE Richard Henderson
2025-07-30 20:38 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 11/82] target/arm: Enable TCR2_ELx.PIE Richard Henderson
2025-07-30 20:39 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 12/82] target/arm: Implement PIR_ELx, PIRE0_ELx, S2PIR_EL2 registers Richard Henderson
2025-07-30 20:41 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 13/82] target/arm: Force HPD for stage2 translations Richard Henderson
2025-07-30 20:42 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 14/82] target/arm: Cache NV1 early in get_phys_addr_lpae Richard Henderson
2025-07-30 20:43 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 15/82] target/arm: Populate PIE in aa64_va_parameters Richard Henderson
2025-07-30 20:45 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 16/82] target/arm: Implement get_S1prot_indirect Richard Henderson
2025-07-31 21:15 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 17/82] target/arm: Implement get_S2prot_indirect Richard Henderson
2025-07-31 21:13 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 18/82] target/arm: Do not migrate env->exception Richard Henderson
2025-07-30 20:46 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 19/82] target/arm: Expand CPUARMState.exception.syndrome to 64 bits Richard Henderson
2025-07-30 20:47 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 20/82] target/arm: Expand syndrome parameter to raise_exception* Richard Henderson
2025-07-30 20:47 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 21/82] target/arm: Implement dirtybit check for PIE Richard Henderson
2025-07-30 20:50 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 22/82] target/arm: Enable FEAT_S1PIE and FEAT_S2PIE on -cpu max Richard Henderson
2025-07-30 20:50 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 23/82] include/hw/core/cpu: Introduce MMUIdxMap Richard Henderson
2025-07-30 20:52 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 24/82] include/hw/core/cpu: Introduce cpu_tlb_fast Richard Henderson
2025-07-30 20:53 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 25/82] include/hw/core/cpu: Invert the indexing into CPUTLBDescFast Richard Henderson
2025-07-30 21:00 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 26/82] target/hppa: Adjust mmu indexes to begin with 0 Richard Henderson
2025-07-30 21:03 ` Pierrick Bouvier
2025-07-27 8:01 ` [PATCH 27/82] include/exec/memopidx: Adjust for 32 mmu indexes Richard Henderson
2025-07-30 21:03 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 28/82] include/hw/core/cpu: Widen MMUIdxMap Richard Henderson
2025-07-30 21:07 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 29/82] target/arm: Split out mmuidx.h from cpu.h Richard Henderson
2025-07-30 21:07 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 30/82] target/arm: Convert arm_mmu_idx_to_el from switch to table Richard Henderson
2025-07-30 21:10 ` Pierrick Bouvier
2025-07-30 21:12 ` Pierrick Bouvier
2025-07-30 21:31 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 31/82] target/arm: Remove unused env argument from regime_el Richard Henderson
2025-07-30 21:13 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 32/82] target/arm: Convert regime_el from switch to table Richard Henderson
2025-07-30 21:15 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 33/82] target/arm: Convert regime_has_2_ranges " Richard Henderson
2025-07-30 21:16 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 34/82] target/arm: Remove unused env argument from regime_is_pan Richard Henderson
2025-07-30 21:17 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 35/82] target/arm: Convert regime_is_pan from switch to table Richard Henderson
2025-07-30 21:17 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 36/82] target/arm: Remove unused env argument from regime_is_user Richard Henderson
2025-07-30 21:18 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 37/82] target/arm: Convert regime_is_user from switch to table Richard Henderson
2025-07-30 21:21 ` Pierrick Bouvier
2025-08-01 3:53 ` Richard Henderson
2025-08-01 16:10 ` Pierrick Bouvier
2025-08-01 18:06 ` Peter Maydell
2025-07-27 8:02 ` [PATCH 38/82] target/arm: Convert arm_mmu_idx_is_stage1_of_2 " Richard Henderson
2025-07-30 21:23 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 39/82] target/arm: Convert regime_is_stage2 " Richard Henderson
2025-07-30 21:23 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 40/82] target/arm: Introduce mmu indexes for GCS Richard Henderson
2025-07-30 21:28 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 41/82] target/arm: Introduce regime_to_gcs Richard Henderson
2025-07-30 21:33 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 42/82] target/arm: Support page protections for GCS mmu indexes Richard Henderson
2025-07-31 18:40 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 43/82] target/arm: Implement gcs bit for data abort Richard Henderson
2025-07-31 18:41 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 44/82] target/arm: Add GCS cpregs Richard Henderson
2025-07-31 18:45 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 45/82] target/arm: Add GCS enable and trap levels to DisasContext Richard Henderson
2025-07-31 18:54 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 46/82] target/arm: Implement FEAT_CHK Richard Henderson
2025-07-29 16:01 ` Gustavo Romero
2025-07-29 17:21 ` Richard Henderson
2025-07-31 18:59 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 47/82] target/arm: Expand pstate to 64 bits Richard Henderson
2025-07-31 19:13 ` Pierrick Bouvier
2025-08-01 4:24 ` Richard Henderson
2025-08-01 12:35 ` Manos Pitsidianakis
2025-08-01 4:29 ` Richard Henderson
2025-08-01 16:12 ` Pierrick Bouvier
2025-08-01 20:19 ` Richard Henderson
2025-08-01 13:22 ` Peter Maydell
2025-08-01 16:26 ` Pierrick Bouvier
2025-08-01 16:37 ` Peter Maydell
2025-08-01 16:41 ` Pierrick Bouvier
2025-08-01 16:44 ` Peter Maydell
2025-08-01 16:53 ` Pierrick Bouvier
2025-08-01 16:55 ` Pierrick Bouvier
2025-08-01 18:45 ` Manos Pitsidianakis
2025-08-02 3:14 ` Thiago Jung Bauermann
2025-08-01 20:22 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 48/82] target/arm: Add syndrome data for EC_GCS Richard Henderson
2025-07-31 19:35 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 49/82] target/arm: Implement EXLOCKException for ELR_ELx and SPSR_ELx Richard Henderson
2025-07-31 20:53 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 50/82] target/arm: Split {arm,core}_user_mem_index Richard Henderson
2025-07-31 21:06 ` Pierrick Bouvier
2025-07-31 21:24 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 51/82] target/arm: Introduce delay_exception{_el} Richard Henderson
2025-07-31 21:09 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 52/82] target/arm: Emit HSTR trap exception out of line Richard Henderson
2025-07-31 21:10 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 53/82] target/arm: Emit v7m LTPSIZE " Richard Henderson
2025-07-31 21:10 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 54/82] target/arm: Implement GCSSTR, GCSSTTR Richard Henderson
2025-07-31 21:25 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 55/82] target/arm: Implement GCSB Richard Henderson
2025-07-31 21:27 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 56/82] target/arm: Implement GCSPUSHM Richard Henderson
2025-07-31 21:33 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 57/82] target/arm: Implement GCSPOPM Richard Henderson
2025-07-31 21:34 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 58/82] target/arm: Implement GCSPUSHX Richard Henderson
2025-07-31 21:36 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 59/82] target/arm: Implement GCSPOPX Richard Henderson
2025-07-31 21:37 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 60/82] target/arm: Implement GCSPOPCX Richard Henderson
2025-07-31 21:38 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 61/82] target/arm: Implement GCSSS1 Richard Henderson
2025-07-31 21:43 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 62/82] target/arm: Implement GCSSS2 Richard Henderson
2025-07-31 21:45 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 63/82] target/arm: Add gcs record for BL Richard Henderson
2025-07-31 21:45 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 64/82] target/arm: Add gcs record for BLR Richard Henderson
2025-07-31 21:46 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 65/82] target/arm: Add gcs record for BLR with PAuth Richard Henderson
2025-07-31 21:46 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 66/82] target/arm: Load gcs record for RET Richard Henderson
2025-07-31 21:47 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 67/82] target/arm: Load gcs record for RET with PAuth Richard Henderson
2025-07-31 21:48 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 68/82] target/arm: Copy EXLOCKEn to EXLOCK on exception to the same EL Richard Henderson
2025-07-31 21:48 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 69/82] target/arm: Implement EXLOCK check during exception return Richard Henderson
2025-07-31 21:49 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 70/82] target/arm: Enable FEAT_GCS with -cpu max Richard Henderson
2025-07-31 21:49 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 71/82] linux-user/aarch64: Implement prctls for GCS Richard Henderson
2025-07-31 21:53 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 72/82] linux-user/aarch64: Allocate new gcs stack on clone Richard Henderson
2025-07-31 21:54 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 73/82] linux-user/aarch64: Release gcs stack on thread exit Richard Henderson
2025-07-31 21:54 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 74/82] linux-user/aarch64: Implement map_shadow_stack syscall Richard Henderson
2025-07-31 21:55 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 75/82] target/arm: Enable GCSPR_EL0 for read in user-mode Richard Henderson
2025-07-31 21:56 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 76/82] linux-user/aarch64: Inject SIGSEGV for GCS faults Richard Henderson
2025-07-31 21:56 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 77/82] linux-user/aarch64: Generate GCS signal records Richard Henderson
2025-07-31 21:57 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 78/82] linux-user: Change exported get_elf_hwcap to abi_ulong Richard Henderson
2025-07-31 21:58 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 79/82] linux-user/aarch64: Enable GCS in HWCAP Richard Henderson
2025-07-31 21:58 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 80/82] tests/tcg/aarch64: Add gcsstr Richard Henderson
2025-07-31 22:05 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 81/82] tests/tcg/aarch64: Add gcspushm Richard Henderson
2025-07-31 22:11 ` Pierrick Bouvier
2025-07-27 8:02 ` [PATCH 82/82] tests/tcg/aarch64: Add gcsss Richard Henderson
2025-07-31 22:14 ` Pierrick Bouvier
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).