* [PATCH 0/5] target/arm: Add aarch64 GPC3 bypass windows
@ 2026-05-28 15:34 Jim MacArthur
2026-05-28 15:34 ` [PATCH 1/5] target/arm/cpu-features.h: x-rme now means GPC3 Jim MacArthur
` (4 more replies)
0 siblings, 5 replies; 12+ messages in thread
From: Jim MacArthur @ 2026-05-28 15:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, qemu-arm, Jim MacArthur
Adds the GPC bypass windows defined in D9.2 of the Arm ARM. D9.8 (the
APAS instruction) is not implemented yet.
A large part of this is testing. To test GPC effectively, we need to
check that memory accesses are causing exceptions, or not causing exceptions
as appropriate. For some tests, boot.S is altered to record certain
exceptions and continue executing the test. An alternative would be
to use gdbstub to break on locations inside the vector table and continue,
but this requires significant coordination between the C test binary and
Python test driver, so has been avoided for now.
Signed-off-by: Jim MacArthur <jim.macarthur@linaro.org>
---
Jim MacArthur (5):
target/arm/cpu-features.h: x-rme now means GPC3
target/arm: Setup new registers for GPC3
target/arm/ptw.c: Add Granule Bypass Windows
tests/tcg/aarch64/system: Alternative boot object for exception logging
tests/tcg/aarch64/system/gpc-test.c: Basic test for granule protection check
target/arm/cpu-features.h | 5 +
target/arm/cpu.h | 7 ++
target/arm/helper.c | 19 ++++
target/arm/ptw.c | 50 ++++++++++
target/arm/tcg/cpu64.c | 4 +-
tests/tcg/aarch64/Makefile.softmmu-target | 22 +++-
tests/tcg/aarch64/system/boot.S | 62 ++++++++++++
tests/tcg/aarch64/system/boot.h | 14 +++
tests/tcg/aarch64/system/gpc-test.c | 160 ++++++++++++++++++++++++++++++
9 files changed, 336 insertions(+), 7 deletions(-)
---
base-commit: 2db91528542672cf0db78b3f2cc0e22b36302b38
change-id: 20260528-jmac-gpc3b-187f9d7cf0dd
Best regards,
--
Jim MacArthur <jim.macarthur@linaro.org>
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/5] target/arm/cpu-features.h: x-rme now means GPC3
2026-05-28 15:34 [PATCH 0/5] target/arm: Add aarch64 GPC3 bypass windows Jim MacArthur
@ 2026-05-28 15:34 ` Jim MacArthur
2026-05-28 18:03 ` Richard Henderson
2026-05-28 15:34 ` [PATCH 2/5] target/arm: Setup new registers for GPC3 Jim MacArthur
` (3 subsequent siblings)
4 siblings, 1 reply; 12+ messages in thread
From: Jim MacArthur @ 2026-05-28 15:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, qemu-arm, Jim MacArthur
Signed-off-by: Jim MacArthur <jim.macarthur@linaro.org>
---
target/arm/cpu-features.h | 5 +++++
target/arm/tcg/cpu64.c | 4 ++--
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index f9c979d20b..6819d5f6a7 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -1138,6 +1138,11 @@ static inline bool isar_feature_aa64_rme_gpc2(const ARMISARegisters *id)
return FIELD_EX64_IDREG(id, ID_AA64PFR0, RME) >= 2;
}
+static inline bool isar_feature_aa64_rme_gpc3(const ARMISARegisters *id)
+{
+ return FIELD_EX64_IDREG(id, ID_AA64PFR0, RME) >= 3;
+}
+
static inline bool isar_feature_aa64_dit(const ARMISARegisters *id)
{
return FIELD_EX64_IDREG(id, ID_AA64PFR0, DIT) != 0;
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index a377f67b9c..53f0ea0404 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -159,8 +159,8 @@ static void cpu_arm_set_rme(Object *obj, bool value, Error **errp)
{
ARMCPU *cpu = ARM_CPU(obj);
- /* Enable FEAT_RME_GPC2 */
- FIELD_DP64_IDREG(&cpu->isar, ID_AA64PFR0, RME, value ? 2 : 0);
+ /* Enable FEAT_RME_GPC3 */
+ FIELD_DP64_IDREG(&cpu->isar, ID_AA64PFR0, RME, value ? 3 : 0);
}
static void cpu_max_set_l0gptsz(Object *obj, Visitor *v, const char *name,
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/5] target/arm: Setup new registers for GPC3
2026-05-28 15:34 [PATCH 0/5] target/arm: Add aarch64 GPC3 bypass windows Jim MacArthur
2026-05-28 15:34 ` [PATCH 1/5] target/arm/cpu-features.h: x-rme now means GPC3 Jim MacArthur
@ 2026-05-28 15:34 ` Jim MacArthur
2026-05-28 18:14 ` Richard Henderson
2026-05-28 18:25 ` Richard Henderson
2026-05-28 15:34 ` [PATCH 3/5] target/arm/ptw.c: Add Granule Bypass Windows Jim MacArthur
` (2 subsequent siblings)
4 siblings, 2 replies; 12+ messages in thread
From: Jim MacArthur @ 2026-05-28 15:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, qemu-arm, Jim MacArthur
Adds GPCBW_EL3. A custom write function is necessary to flush TLBs
when this register is written. Also allows write to the GPCBW bit of
GPCCR_EL3.
Signed-off-by: Jim MacArthur <jim.macarthur@linaro.org>
---
target/arm/cpu.h | 7 +++++++
target/arm/helper.c | 19 +++++++++++++++++++
2 files changed, 26 insertions(+)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 85552b573c..9944dc9727 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -546,6 +546,7 @@ typedef struct CPUArchState {
/* RME registers */
uint64_t gpccr_el3;
uint64_t gptbr_el3;
+ uint64_t gpcbw_el3;
uint64_t mfar_el3;
/* NV2 register */
@@ -1228,6 +1229,8 @@ void arm_v7m_cpu_do_interrupt(CPUState *cpu);
typedef struct ARMGranuleProtectionConfig {
/* GPCCR_EL3 */
uint64_t gpccr;
+ /* GPCBW_EL3 */
+ uint64_t gpcbw;
/* GPTBR_EL3 */
uint64_t gptbr;
/* ID_AA64MMFR0_EL1.PARange */
@@ -2098,6 +2101,10 @@ FIELD(GPCCR, NA6, 27, 1)
FIELD(GPCCR, NA7, 28, 1)
FIELD(GPCCR, GPCBW, 29, 1)
+FIELD(GPCBW, BWSIZE, 37, 2)
+FIELD(GPCBW, BWSTRIDE, 32, 5)
+FIELD(GPCBW, BWADDR, 0, 25)
+
FIELD(MFAR, FPA, 12, 40)
FIELD(MFAR, NSE, 62, 1)
FIELD(MFAR, NS, 63, 1)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 34487eeaa3..12453fe39f 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -4990,6 +4990,10 @@ static void gpccr_write(CPUARMState *env, const ARMCPRegInfo *ri,
R_GPCCR_SPAD_MASK | R_GPCCR_NSPAD_MASK | R_GPCCR_RLPAD_MASK;
}
+ if (cpu_isar_feature(aa64_rme_gpc3 , env_archcpu(env))) {
+ rw_mask |= R_GPCCR_GPCBW_MASK;
+ }
+
env->cp15.gpccr_el3 = (value & rw_mask) | (env->cp15.gpccr_el3 & ~rw_mask);
}
@@ -4999,11 +5003,26 @@ static void gpccr_reset(CPUARMState *env, const ARMCPRegInfo *ri)
env_archcpu(env)->reset_l0gptsz);
}
+static void gpcbw_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ uint64_t rw_mask = R_GPCBW_BWADDR_MASK | R_GPCBW_BWSTRIDE_MASK |
+ R_GPCBW_BWSIZE_MASK;
+ ARMCPU *cpu = env_archcpu(env);
+ tlb_flush_by_mmuidx(CPU(cpu), alle1_tlbmask(env));
+
+ env->cp15.gpcbw_el3 = (value & rw_mask) | (env->cp15.gpcbw_el3 & ~rw_mask);
+}
+
static const ARMCPRegInfo rme_reginfo[] = {
{ .name = "GPCCR_EL3", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 6, .crn = 2, .crm = 1, .opc2 = 6,
.access = PL3_RW, .writefn = gpccr_write, .resetfn = gpccr_reset,
.fieldoffset = offsetof(CPUARMState, cp15.gpccr_el3) },
+ { .name = "GPCBW_EL3", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 6, .crn = 2, .crm = 1, .opc2 = 5,
+ .access = PL3_RW, .writefn = gpcbw_write,
+ .fieldoffset = offsetof(CPUARMState, cp15.gpcbw_el3) },
{ .name = "GPTBR_EL3", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 6, .crn = 2, .crm = 1, .opc2 = 4,
.access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.gptbr_el3) },
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 3/5] target/arm/ptw.c: Add Granule Bypass Windows
2026-05-28 15:34 [PATCH 0/5] target/arm: Add aarch64 GPC3 bypass windows Jim MacArthur
2026-05-28 15:34 ` [PATCH 1/5] target/arm/cpu-features.h: x-rme now means GPC3 Jim MacArthur
2026-05-28 15:34 ` [PATCH 2/5] target/arm: Setup new registers for GPC3 Jim MacArthur
@ 2026-05-28 15:34 ` Jim MacArthur
2026-05-28 18:52 ` Richard Henderson
2026-05-28 15:34 ` [PATCH 4/5] tests/tcg/aarch64/system: Alternative boot object for exception logging Jim MacArthur
2026-05-28 15:34 ` [PATCH 5/5] tests/tcg/aarch64/system/gpc-test.c: Basic test for granule protection check Jim MacArthur
4 siblings, 1 reply; 12+ messages in thread
From: Jim MacArthur @ 2026-05-28 15:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, qemu-arm, Jim MacArthur
Signed-off-by: Jim MacArthur <jim.macarthur@linaro.org>
---
target/arm/ptw.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 0a5201763a..46568cc5cb 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -341,11 +341,21 @@ bool arm_granule_protection_check(ARMGranuleProtectionConfig config,
.space = ARMSS_Root,
};
const uint64_t gpccr = config.gpccr;
+ const uint64_t gpcbw = config.gpcbw;
unsigned pps, pgs, l0gptsz, level = 0;
uint64_t tableaddr, pps_mask, align, entry, index;
MemTxResult result;
int gpi;
+ const uint64_t BW_ADDR_SHIFT = 30;
+ const uint64_t BW_SIZE_SHIFT = 30;
+ const uint64_t BW_STRIDE_SHIFT = 40;
+
+ uint64_t bw_start = FIELD_EX64(gpcbw, GPCBW, BWADDR) << BW_ADDR_SHIFT;
+ uint64_t bw_size_field = FIELD_EX64(gpcbw, GPCBW, BWSIZE);
+ uint64_t bw_stride_mask = -1L << (FIELD_EX64(gpcbw, GPCBW, BWSTRIDE) +
+ BW_STRIDE_SHIFT + 1);
+
/*
* We assume Granule Protection Check is enabled when
* calling this function (GPCCR.GPC == 1).
@@ -383,6 +393,28 @@ bool arm_granule_protection_check(ARMGranuleProtectionConfig config,
goto fault_walk;
}
+ /* At this point, GPCCR_EL3 is valid */
+
+ /*
+ * GPC Priority 1 (R_GMGRR):
+ * If GPCCR_EL3.GPCBW is 1 and the configuration GPCBW
+ * is invalid, the access fails as GPT walk fault at level 0.
+ */
+ if (FIELD_EX64(gpccr, GPCCR, GPCBW)) {
+ /*
+ * GPCBW is invalid if the base address is:
+ * not aligned to the size programmed in BWSIZE, or
+ * greater than or equal to the stride value configured by BWSTRIDE.
+ */
+ uint64_t bw_size_mask = -1L << (bw_size_field + 31);
+ if (bw_start & bw_size_mask) {
+ goto fault_walk;
+ }
+ if (bw_start & bw_stride_mask) {
+ goto fault_walk;
+ }
+ }
+
switch (FIELD_EX64(gpccr, GPCCR, PGS)) {
case 0b00: /* 4KB */
pgs = 12;
@@ -431,6 +463,23 @@ bool arm_granule_protection_check(ARMGranuleProtectionConfig config,
goto fault_fail;
}
+ /*
+ * Bypass window check.
+ * I_JJLRM: Granule Protection Table (GPT) lookups can be skipped
+ * in portions of the memory map by using GPC bypass windows.
+ * I_XNHTX: The GPC bypass window check (...) is performed
+ * immediately after priority 3.
+ */
+ if (FIELD_EX64(gpccr, GPCCR, GPCBW)) {
+ uint64_t bw_size = 1 << (bw_size_field + BW_SIZE_SHIFT);
+ uint64_t effective_address = paddress & bw_stride_mask;
+
+ if (effective_address >= bw_start &&
+ effective_address < (bw_start + bw_size)) {
+ return true;
+ }
+ }
+
/* GPC Priority 4: the base address of GPTBR_EL3 exceeds PPS. */
tableaddr = config.gptbr << 12;
if (tableaddr & ~pps_mask) {
@@ -3817,6 +3866,7 @@ static bool get_phys_addr_gpc(CPUARMState *env, S1Translate *ptw,
};
struct ARMGranuleProtectionConfig config = {
.gpccr = env->cp15.gpccr_el3,
+ .gpcbw = env->cp15.gpcbw_el3,
.gptbr = env->cp15.gptbr_el3,
.parange = FIELD_EX64_IDREG(&cpu->isar, ID_AA64MMFR0, PARANGE),
.support_sel2 = cpu_isar_feature(aa64_sel2, cpu),
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 4/5] tests/tcg/aarch64/system: Alternative boot object for exception logging
2026-05-28 15:34 [PATCH 0/5] target/arm: Add aarch64 GPC3 bypass windows Jim MacArthur
` (2 preceding siblings ...)
2026-05-28 15:34 ` [PATCH 3/5] target/arm/ptw.c: Add Granule Bypass Windows Jim MacArthur
@ 2026-05-28 15:34 ` Jim MacArthur
2026-05-28 15:34 ` [PATCH 5/5] tests/tcg/aarch64/system/gpc-test.c: Basic test for granule protection check Jim MacArthur
4 siblings, 0 replies; 12+ messages in thread
From: Jim MacArthur @ 2026-05-28 15:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, qemu-arm, Jim MacArthur
This allows us to record information about exceptions using a small
area of memory, and continue with the test so it can verify exceptions
have been taken where expected.
ALT_VECTOR_TABLE is added to switch this on, and altboot.o
is built from boot.S with this flag. Since boot.o is created for multiple
test targets, we have to build a separate object and selectively link this
new altboot.o into particular test binaries.
Signed-off-by: Jim MacArthur <jim.macarthur@linaro.org>
---
tests/tcg/aarch64/Makefile.softmmu-target | 11 ++++--
tests/tcg/aarch64/system/boot.S | 62 +++++++++++++++++++++++++++++++
tests/tcg/aarch64/system/boot.h | 14 +++++++
3 files changed, 83 insertions(+), 4 deletions(-)
diff --git a/tests/tcg/aarch64/Makefile.softmmu-target b/tests/tcg/aarch64/Makefile.softmmu-target
index f7a7d2b800..47b32968fb 100644
--- a/tests/tcg/aarch64/Makefile.softmmu-target
+++ b/tests/tcg/aarch64/Makefile.softmmu-target
@@ -25,7 +25,7 @@ LDFLAGS=-Wl,-T$(LINK_SCRIPT)
TESTS+=$(AARCH64_TESTS) $(MULTIARCH_TESTS)
EXTRA_RUNS+=$(MULTIARCH_RUNS)
CFLAGS+=-nostdlib -ggdb -O0 $(MINILIB_INC)
-LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
+LDFLAGS+=-static -nostdlib $(MINILIB_OBJS) -lgcc
config-cc.mak: Makefile
$(quiet-@)( \
@@ -36,17 +36,20 @@ config-cc.mak: Makefile
# building head blobs
.PRECIOUS: $(CRT_OBJS)
+altboot.o: $(CRT_PATH)/boot.S
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -DALT_VECTOR_TABLE -x assembler-with-cpp -Wa,--noexecstack -c $< -o $@
+
%.o: $(CRT_PATH)/%.S
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -x assembler-with-cpp -Wa,--noexecstack -c $< -o $@
# Build and link the tests
%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
- $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS) boot.o
memory: CFLAGS+=-DCHECK_UNALIGNED=1
memory-sve: memory.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
- $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS) boot.o
memory-sve: CFLAGS+=-DCHECK_UNALIGNED=1 -march=armv8.1-a+sve -O3
@@ -107,7 +110,7 @@ QEMU_MTE_ENABLED_MACHINE=-M virt,mte=on -cpu max -display none
QEMU_OPTS_WITH_MTE_ON = $(QEMU_MTE_ENABLED_MACHINE) $(QEMU_BASE_ARGS) -kernel
mte: CFLAGS+=-march=armv8.5-a+memtag
mte: mte.S $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
- $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS) boot.o
run-mte: QEMU_OPTS=$(QEMU_OPTS_WITH_MTE_ON)
run-mte: mte
diff --git a/tests/tcg/aarch64/system/boot.S b/tests/tcg/aarch64/system/boot.S
index 8bfa4e4efc..225ae76388 100644
--- a/tests/tcg/aarch64/system/boot.S
+++ b/tests/tcg/aarch64/system/boot.S
@@ -60,6 +60,40 @@ curr_sp0_irq:
curr_sp0_fiq:
curr_sp0_serror:
curr_spx_sync:
+#ifdef ALT_VECTOR_TABLE
+ sub sp, sp, #16
+ stp x0, x1, [sp, #0]
+ mrs x0, ESR_EL3
+ lsr x0, x0, #26
+ and x0, x0, #0x3f
+ cmp x0, #37
+ beq data_fault
+ cmp x0, #30
+ beq gpc_fault
+ b generic_exception
+
+data_fault:
+ mrs x0, FAR_EL3
+ adrp x1, exception_log
+ str x0, [x1]
+ ldr x0, =0x1001
+ str x0, [x1, #8]
+ b skip_return
+gpc_fault:
+ mrs x0, FAR_EL3
+ adrp x1, exception_log
+ str x0, [x1]
+ ldr x0, =0x1002
+ str x0, [x1, #8]
+ /* Fall through */
+skip_return:
+ mrs x0, ELR_EL3
+ add x0, x0, #4 /* Skip faulting instruction */
+ msr ELR_EL3, x0
+ ldp x0, x1, [sp, #0]
+ add sp, sp, #16
+ eret
+#endif
curr_spx_irq:
curr_spx_fiq:
curr_spx_serror:
@@ -71,6 +105,7 @@ lower_a32_sync:
lower_a32_irq:
lower_a32_fiq:
lower_a32_serror:
+generic_exception:
adr x1, .unexp_excp
exit_msg:
mov x0, SYS_WRITE0
@@ -404,6 +439,33 @@ ttb_stage2:
.space 4096, 0
.align 12
+ .global realms_gpt0
+ /* GPT stage 0 table */
+realms_gpt0:
+ .space 4096, 0
+ .align 17
+ .global realms_gpt1
+ /* GPT stage 1 table, initialised to all 0xFF (full access) */
+realms_gpt1:
+ .space 524288, 0xFF
+#ifdef ALT_VECTOR_TABLE
+ .align 8
+ .global exception_log
+ .global exception_fault_address
+ .global exception_type_code
+exception_log:
+ /*
+ *These fields record details of the last exception, if ALT_VECTOR_TABLE
+ * is defined.
+ */
+exception_fault_address:
+ /* The contents of FAR_EL3 when an exception is taken. */
+ .space 8, 0
+exception_type_code:
+ /* A generic code indicating what type of exception occurred. */
+ .space 8, 0
+#endif
+ .align 12
system_stack:
.space 4096, 0
system_stack_end:
diff --git a/tests/tcg/aarch64/system/boot.h b/tests/tcg/aarch64/system/boot.h
new file mode 100644
index 0000000000..cb9ab6c1b9
--- /dev/null
+++ b/tests/tcg/aarch64/system/boot.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ *
+ *
+ * Copyright (c) 2026 Linaro Ltd
+ *
+ */
+
+
+/* Global variables exported in boot.S */
+extern volatile uint64_t exception_fault_address; /* Updated by ISR */
+extern volatile uint64_t exception_type_code; /* Updated by ISR */
+extern uint64_t realms_gpt0[];
+extern uint64_t realms_gpt1[];
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 5/5] tests/tcg/aarch64/system/gpc-test.c: Basic test for granule protection check
2026-05-28 15:34 [PATCH 0/5] target/arm: Add aarch64 GPC3 bypass windows Jim MacArthur
` (3 preceding siblings ...)
2026-05-28 15:34 ` [PATCH 4/5] tests/tcg/aarch64/system: Alternative boot object for exception logging Jim MacArthur
@ 2026-05-28 15:34 ` Jim MacArthur
4 siblings, 0 replies; 12+ messages in thread
From: Jim MacArthur @ 2026-05-28 15:34 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Maydell, qemu-arm, Jim MacArthur
* Sets up granule protection tables
* Enables GPC and bypass windows
* Performs memory accesses in the protected region to
check for allowed and disallowed reads.
Signed-off-by: Jim MacArthur <jim.macarthur@linaro.org>
---
tests/tcg/aarch64/Makefile.softmmu-target | 11 +-
tests/tcg/aarch64/system/gpc-test.c | 160 ++++++++++++++++++++++++++++++
2 files changed, 170 insertions(+), 1 deletion(-)
diff --git a/tests/tcg/aarch64/Makefile.softmmu-target b/tests/tcg/aarch64/Makefile.softmmu-target
index 47b32968fb..d76ca52e63 100644
--- a/tests/tcg/aarch64/Makefile.softmmu-target
+++ b/tests/tcg/aarch64/Makefile.softmmu-target
@@ -53,7 +53,10 @@ memory-sve: memory.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
memory-sve: CFLAGS+=-DCHECK_UNALIGNED=1 -march=armv8.1-a+sve -O3
-TESTS+=memory-sve
+gpc-test: gpc-test.c $(LINK_SCRIPT) altboot.o $(MINILIB_OBJS)
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS) altboot.o
+
+TESTS+=memory-sve gpc-test
# Running
QEMU_BASE_MACHINE=-M virt -cpu max -display none
@@ -74,6 +77,12 @@ QEMU_EL2_MACHINE=-machine virt,virtualization=on,gic-version=2 -cpu cortex-a57 -
QEMU_EL2_BASE_ARGS=-semihosting-config enable=on,target=native,chardev=output,arg="2"
run-vtimer: QEMU_OPTS=$(QEMU_EL2_MACHINE) $(QEMU_EL2_BASE_ARGS) -kernel
+# gpc tests need EL3 and RME
+QEMU_EL3_MACHINE=-machine virt,virtualization=on,secure=on,gic-version=3 -cpu max,x-rme=on
+QEMU_EL3_BASE_ARGS=-semihosting-config enable=on,target=native,chardev=output,arg="3"
+run-gpc-test: QEMU_OPTS=$(QEMU_EL3_MACHINE) $(QEMU_EL3_BASE_ARGS) -kernel
+run-gpc3-test: QEMU_OPTS=$(QEMU_EL3_MACHINE) $(QEMU_EL3_BASE_ARGS) -kernel
+
# Simple Record/Replay Test
.PHONY: memory-record
run-memory-record: memory-record memory
diff --git a/tests/tcg/aarch64/system/gpc-test.c b/tests/tcg/aarch64/system/gpc-test.c
new file mode 100644
index 0000000000..06b25d2787
--- /dev/null
+++ b/tests/tcg/aarch64/system/gpc-test.c
@@ -0,0 +1,160 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ *
+ *
+ * Copyright (c) 2026 Linaro Ltd
+ *
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <minilib.h>
+#include "boot.h"
+
+#define ID_AA64PFR0_EL1 "S3_0_C0_C4_0"
+
+#define GPTBR_EL3 "S3_6_C2_C1_4"
+#define GPCBW_EL3 "S3_6_C2_C1_5"
+#define GPCCR_EL3 "S3_6_C2_C1_6"
+#define VBAR_EL3 "S3_6_C12_C0_0"
+
+#define get_sys_reg(register_name, dest) \
+ asm("mrs %[reg], " register_name "\n\t" : [reg] "=r" (dest))
+#define set_sys_reg(register_name, value) \
+ asm("msr " register_name ", %[reg]\n\r" : : [reg] "r" (value))
+
+const uint32_t gpc_granule_size = 4096;
+const uint32_t gpis_per_64_bits = 16;
+
+int main(uint64_t sp)
+{
+ uint64_t out;
+ uint64_t pfr0;
+ uint64_t gpt_base;
+ uint64_t rme_status;
+ uint64_t currentel_raw;
+ uint64_t currentel;
+ uint64_t gpcbw;
+ uint64_t gpt_table0_addr = (uint64_t) realms_gpt0;
+ uint64_t gpt_table1_addr = (uint64_t) realms_gpt1;
+
+ /* Mask is FNG1, FNG0, and A2 */
+ const uint64_t feature_mask = (1ULL << 18 | 1ULL << 17 | 1ULL << 16);
+ const uint64_t in = feature_mask;
+
+ get_sys_reg("CurrentEL", currentel_raw);
+ currentel = (currentel_raw >> 2) & 0x3;
+
+ if (currentel < 3) {
+ ml_printf("FAIL: Test must be run at EL3 (it is %d)\n", currentel);
+ return 1;
+ }
+
+ get_sys_reg(ID_AA64PFR0_EL1, pfr0);
+
+ /* rme_status is 1 for RME, 2 for RME + GPC2, 3 for RME+GPC3 */
+ rme_status = (pfr0 >> 52) & 0xF;
+ ml_printf("RME is %ld\n", rme_status);
+ if (rme_status < 1) {
+ ml_printf("SKIP: System does not support GPC (RME=%ld)\n", rme_status);
+ return 0;
+ }
+
+ /* Configure the level 0 table for the first 4GB of memory */
+ realms_gpt0[0] = gpt_table1_addr | 0x3; /* Covers GB 0; table descriptor */
+ realms_gpt0[1] = 0xf1; /* Covers GB 1; full access */
+ realms_gpt0[2] = 0xf1; /* Covers GB 2; full access */
+ realms_gpt0[3] = 0xf1; /* Covers GB 3; full access */
+
+ /* Pick a random location to read inside the first 1GB. */
+ uint64_t fault_location = 0x10202008;
+ uint32_t gpi_index = fault_location / gpc_granule_size;
+ realms_gpt1[gpi_index / gpis_per_64_bits] = 0;
+
+ gpt_base = gpt_table0_addr >> 12;
+ set_sys_reg(GPTBR_EL3, gpt_base);
+
+ /*
+ * Default values:
+ * PPS=0: GPC table 0 protects 4GB.
+ * RLPAD=0: Realm physical address spaces are normal
+ * NSPAD=0: Non-secure physical address spaces are normal
+ * SPAD=0: Secure physical address spaces are normal
+ * IRGN=0: Inner non-cacheable
+ * ORGN=0: Outer non-cacheable
+ * PGS=0: Physical granule size is 4KB.
+ * GPCP=0: All GPC faults reported
+ * TBGPCP=0: Trace buffer rejects trace
+ * L0GPTSZ=0: Each entry in table 0 protects 1GB.
+ * APPSAA=0: Accesses above 4GB must be to Non-secure PAs
+ * GPCBW=0: Bypass windows disabled.
+ * NA6, NA7, NSP, SA, NSO are all reserved values for GPI.
+ */
+ uint64_t gpccr = 0;
+
+ /* Switch on granule protection check */
+ gpccr |= 1 << 16; /* GPC enabled. */
+ gpccr |= 0b10 << 12; /* SH = Outer shareable */
+ set_sys_reg(GPCCR_EL3, gpccr);
+
+ /* Access some memory outside the GPC forbidden region */
+ uint64_t x = *(unsigned int *) (fault_location + 4096 * 16);
+ ml_printf("Fault address: %lx\n", exception_fault_address);
+ if (exception_fault_address != 0) {
+ ml_printf("FAIL: Memory access was blocked by GPC, "
+ "and should not have been\n");
+ return 1;
+ }
+
+ /* Access the GPC forbidden region */
+ x = *(unsigned int *) fault_location;
+
+ ml_printf("Fault address: %lx\n", exception_fault_address);
+ if (exception_fault_address != fault_location) {
+ ml_printf("FAIL: Memory access was not blocked by GPC, "
+ "and should have been\n");
+ return 1;
+ }
+
+ /* Clear the exception record */
+ exception_fault_address = 0;
+
+ /* Enable bypass windows */
+ gpccr |= 1 << 29; /* GPC Bypass windows enabled */
+ set_sys_reg(GPCCR_EL3, gpccr);
+
+ gpcbw = 0; /* Base 0GB, Size 1GB, Stride 1TB */
+ set_sys_reg(GPCBW_EL3, gpcbw);
+ ml_printf("GPCBW configured\n");
+
+ /* Access the GPC forbidden region again */
+ x = *(unsigned int *) fault_location;
+
+ ml_printf("Fault address: %lx\n", exception_fault_address);
+ if (exception_fault_address != 0) {
+ ml_printf("FAIL: [3] Memory access was blocked by GPC, "
+ "and should have been allowed by bypass window. code=%lx\n",
+ exception_type_code);
+ return 1;
+ }
+
+ /* Clear the exception record */
+ exception_fault_address = 0;
+ /* Reconfigure GPCBW to 1GB start */
+ gpcbw = 1; /* Base 1GB, Size 1GB, Stride 1TB */
+ set_sys_reg(GPCBW_EL3, gpcbw);
+ ml_printf("GPCBW reconfigured for 1GB start\n");
+
+ /* Access the GPC forbidden region again */
+ x = *(unsigned int *) fault_location;
+
+ ml_printf("Fault address: %lx\n", exception_fault_address);
+ if (exception_fault_address != fault_location) {
+ ml_printf("FAIL: [4] Memory access was allowed by GPC, "
+ "and should not have been allowed by bypass window. log=%lx\n",
+ exception_type_code);
+ return 1;
+ }
+
+ return 0;
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 1/5] target/arm/cpu-features.h: x-rme now means GPC3
2026-05-28 15:34 ` [PATCH 1/5] target/arm/cpu-features.h: x-rme now means GPC3 Jim MacArthur
@ 2026-05-28 18:03 ` Richard Henderson
0 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2026-05-28 18:03 UTC (permalink / raw)
To: qemu-devel
On 5/28/26 08:34, Jim MacArthur wrote:
> Signed-off-by: Jim MacArthur <jim.macarthur@linaro.org>
> ---
> target/arm/cpu-features.h | 5 +++++
> target/arm/tcg/cpu64.c | 4 ++--
> 2 files changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
> index f9c979d20b..6819d5f6a7 100644
> --- a/target/arm/cpu-features.h
> +++ b/target/arm/cpu-features.h
> @@ -1138,6 +1138,11 @@ static inline bool isar_feature_aa64_rme_gpc2(const ARMISARegisters *id)
> return FIELD_EX64_IDREG(id, ID_AA64PFR0, RME) >= 2;
> }
>
> +static inline bool isar_feature_aa64_rme_gpc3(const ARMISARegisters *id)
> +{
> + return FIELD_EX64_IDREG(id, ID_AA64PFR0, RME) >= 3;
> +}
> +
> static inline bool isar_feature_aa64_dit(const ARMISARegisters *id)
> {
> return FIELD_EX64_IDREG(id, ID_AA64PFR0, DIT) != 0;
This hunk is ok.
> diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
> index a377f67b9c..53f0ea0404 100644
> --- a/target/arm/tcg/cpu64.c
> +++ b/target/arm/tcg/cpu64.c
> @@ -159,8 +159,8 @@ static void cpu_arm_set_rme(Object *obj, bool value, Error **errp)
> {
> ARMCPU *cpu = ARM_CPU(obj);
>
> - /* Enable FEAT_RME_GPC2 */
> - FIELD_DP64_IDREG(&cpu->isar, ID_AA64PFR0, RME, value ? 2 : 0);
> + /* Enable FEAT_RME_GPC3 */
> + FIELD_DP64_IDREG(&cpu->isar, ID_AA64PFR0, RME, value ? 3 : 0);
> }
This hunk has to go last, once the implementation is complete.
r~
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/5] target/arm: Setup new registers for GPC3
2026-05-28 15:34 ` [PATCH 2/5] target/arm: Setup new registers for GPC3 Jim MacArthur
@ 2026-05-28 18:14 ` Richard Henderson
2026-05-28 18:25 ` Richard Henderson
1 sibling, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2026-05-28 18:14 UTC (permalink / raw)
To: qemu-devel
On 5/28/26 08:34, Jim MacArthur wrote:
> Adds GPCBW_EL3. A custom write function is necessary to flush TLBs
> when this register is written. Also allows write to the GPCBW bit of
> GPCCR_EL3.
>
> Signed-off-by: Jim MacArthur <jim.macarthur@linaro.org>
> ---
> target/arm/cpu.h | 7 +++++++
> target/arm/helper.c | 19 +++++++++++++++++++
> 2 files changed, 26 insertions(+)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 85552b573c..9944dc9727 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -546,6 +546,7 @@ typedef struct CPUArchState {
> /* RME registers */
> uint64_t gpccr_el3;
> uint64_t gptbr_el3;
> + uint64_t gpcbw_el3;
> uint64_t mfar_el3;
>
> /* NV2 register */
> @@ -1228,6 +1229,8 @@ void arm_v7m_cpu_do_interrupt(CPUState *cpu);
> typedef struct ARMGranuleProtectionConfig {
> /* GPCCR_EL3 */
> uint64_t gpccr;
> + /* GPCBW_EL3 */
> + uint64_t gpcbw;
> /* GPTBR_EL3 */
> uint64_t gptbr;
> /* ID_AA64MMFR0_EL1.PARange */
> @@ -2098,6 +2101,10 @@ FIELD(GPCCR, NA6, 27, 1)
> FIELD(GPCCR, NA7, 28, 1)
> FIELD(GPCCR, GPCBW, 29, 1)
>
> +FIELD(GPCBW, BWSIZE, 37, 2)
> +FIELD(GPCBW, BWSTRIDE, 32, 5)
> +FIELD(GPCBW, BWADDR, 0, 25)
> +
> FIELD(MFAR, FPA, 12, 40)
> FIELD(MFAR, NSE, 62, 1)
> FIELD(MFAR, NS, 63, 1)
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 34487eeaa3..12453fe39f 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -4990,6 +4990,10 @@ static void gpccr_write(CPUARMState *env, const ARMCPRegInfo *ri,
> R_GPCCR_SPAD_MASK | R_GPCCR_NSPAD_MASK | R_GPCCR_RLPAD_MASK;
> }
>
> + if (cpu_isar_feature(aa64_rme_gpc3 , env_archcpu(env))) {
> + rw_mask |= R_GPCCR_GPCBW_MASK;
> + }
> +
> env->cp15.gpccr_el3 = (value & rw_mask) | (env->cp15.gpccr_el3 & ~rw_mask);
> }
>
> @@ -4999,11 +5003,26 @@ static void gpccr_reset(CPUARMState *env, const ARMCPRegInfo *ri)
> env_archcpu(env)->reset_l0gptsz);
> }
>
> +static void gpcbw_write(CPUARMState *env, const ARMCPRegInfo *ri,
> + uint64_t value)
> +{
> + uint64_t rw_mask = R_GPCBW_BWADDR_MASK | R_GPCBW_BWSTRIDE_MASK |
> + R_GPCBW_BWSIZE_MASK;
> + ARMCPU *cpu = env_archcpu(env);
> + tlb_flush_by_mmuidx(CPU(cpu), alle1_tlbmask(env));
> +
> + env->cp15.gpcbw_el3 = (value & rw_mask) | (env->cp15.gpcbw_el3 & ~rw_mask);
There's no need to merge, because all other fields are RES0.
Just value & rw_mask is sufficient.
This is true for GPCCR too, fwiw, but fixing that as a separate patch.
r~
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/5] target/arm: Setup new registers for GPC3
2026-05-28 15:34 ` [PATCH 2/5] target/arm: Setup new registers for GPC3 Jim MacArthur
2026-05-28 18:14 ` Richard Henderson
@ 2026-05-28 18:25 ` Richard Henderson
1 sibling, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2026-05-28 18:25 UTC (permalink / raw)
To: qemu-devel
On 5/28/26 08:34, Jim MacArthur wrote:
> +static void gpcbw_write(CPUARMState *env, const ARMCPRegInfo *ri,
> + uint64_t value)
> +{
> + uint64_t rw_mask = R_GPCBW_BWADDR_MASK | R_GPCBW_BWSTRIDE_MASK |
> + R_GPCBW_BWSIZE_MASK;
> + ARMCPU *cpu = env_archcpu(env);
> + tlb_flush_by_mmuidx(CPU(cpu), alle1_tlbmask(env));
The GPT affects all EL, so this must flush all tlb, not just EL1.
r~
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/5] target/arm/ptw.c: Add Granule Bypass Windows
2026-05-28 15:34 ` [PATCH 3/5] target/arm/ptw.c: Add Granule Bypass Windows Jim MacArthur
@ 2026-05-28 18:52 ` Richard Henderson
2026-05-29 16:44 ` Jim MacArthur
0 siblings, 1 reply; 12+ messages in thread
From: Richard Henderson @ 2026-05-28 18:52 UTC (permalink / raw)
To: Jim MacArthur, qemu-devel; +Cc: Peter Maydell, qemu-arm
On 5/28/26 08:34, Jim MacArthur wrote:
> Signed-off-by: Jim MacArthur <jim.macarthur@linaro.org>
> ---
> target/arm/ptw.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 50 insertions(+)
>
> diff --git a/target/arm/ptw.c b/target/arm/ptw.c
> index 0a5201763a..46568cc5cb 100644
> --- a/target/arm/ptw.c
> +++ b/target/arm/ptw.c
> @@ -341,11 +341,21 @@ bool arm_granule_protection_check(ARMGranuleProtectionConfig config,
> .space = ARMSS_Root,
> };
> const uint64_t gpccr = config.gpccr;
> + const uint64_t gpcbw = config.gpcbw;
> unsigned pps, pgs, l0gptsz, level = 0;
> uint64_t tableaddr, pps_mask, align, entry, index;
> MemTxResult result;
> int gpi;
>
> + const uint64_t BW_ADDR_SHIFT = 30;
> + const uint64_t BW_SIZE_SHIFT = 30;
> + const uint64_t BW_STRIDE_SHIFT = 40;
> +
> + uint64_t bw_start = FIELD_EX64(gpcbw, GPCBW, BWADDR) << BW_ADDR_SHIFT;
> + uint64_t bw_size_field = FIELD_EX64(gpcbw, GPCBW, BWSIZE);
> + uint64_t bw_stride_mask = -1L << (FIELD_EX64(gpcbw, GPCBW, BWSTRIDE) +
> + BW_STRIDE_SHIFT + 1);
This appears to be the inverse of what you wanted, setting high bits instead of setting
low bits.
Never "L", always LL or ULL; but here you certainly want MAKE_64BIT_MASK.
> +
> /*
> * We assume Granule Protection Check is enabled when
> * calling this function (GPCCR.GPC == 1).
> @@ -383,6 +393,28 @@ bool arm_granule_protection_check(ARMGranuleProtectionConfig config,
> goto fault_walk;
> }
>
> + /* At this point, GPCCR_EL3 is valid */
Not true, because you added the new block before validating PGS...
> +
> + /*
> + * GPC Priority 1 (R_GMGRR):
> + * If GPCCR_EL3.GPCBW is 1 and the configuration GPCBW
> + * is invalid, the access fails as GPT walk fault at level 0.
> + */
> + if (FIELD_EX64(gpccr, GPCCR, GPCBW)) {
> + /*
> + * GPCBW is invalid if the base address is:
> + * not aligned to the size programmed in BWSIZE, or
> + * greater than or equal to the stride value configured by BWSTRIDE.
> + */
> + uint64_t bw_size_mask = -1L << (bw_size_field + 31);
> + if (bw_start & bw_size_mask) {
> + goto fault_walk;
> + }
> + if (bw_start & bw_stride_mask) {
> + goto fault_walk;
> + }
> + }
> +
> switch (FIELD_EX64(gpccr, GPCCR, PGS)) {
... here.
None of the checks you're adding are correct:
- Missing size and stride validation,
- Alignment check vs size is incorrect; you wanted
bw_start & MAKE_64BIT_MASK(0, bw_size + BW_ADDR_SHIFT)
- Check vs stride is incorrect; you wanted bw_stride <= bw_addr.
See GPCRegistersConsistent().
> @@ -431,6 +463,23 @@ bool arm_granule_protection_check(ARMGranuleProtectionConfig config,
> goto fault_fail;
> }
>
> + /*
> + * Bypass window check.
> + * I_JJLRM: Granule Protection Table (GPT) lookups can be skipped
> + * in portions of the memory map by using GPC bypass windows.
> + * I_XNHTX: The GPC bypass window check (...) is performed
> + * immediately after priority 3.
> + */
> + if (FIELD_EX64(gpccr, GPCCR, GPCBW)) {
> + uint64_t bw_size = 1 << (bw_size_field + BW_SIZE_SHIFT);
> + uint64_t effective_address = paddress & bw_stride_mask;
> +
> + if (effective_address >= bw_start &&
> + effective_address < (bw_start + bw_size)) {
No need for extra ().
r~
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/5] target/arm/ptw.c: Add Granule Bypass Windows
2026-05-28 18:52 ` Richard Henderson
@ 2026-05-29 16:44 ` Jim MacArthur
2026-05-29 17:11 ` Richard Henderson
0 siblings, 1 reply; 12+ messages in thread
From: Jim MacArthur @ 2026-05-29 16:44 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-arm, qemu-devel
On Thu, May 28, 2026 at 11:52:09AM -0700, Richard Henderson wrote:
> On 5/28/26 08:34, Jim MacArthur wrote:
> > + /*
> > + * GPC Priority 1 (R_GMGRR):
> > + * If GPCCR_EL3.GPCBW is 1 and the configuration GPCBW
> > + * is invalid, the access fails as GPT walk fault at level 0.
> > + */
> > + if (FIELD_EX64(gpccr, GPCCR, GPCBW)) {
> > + /*
> > + * GPCBW is invalid if the base address is:
> > + * not aligned to the size programmed in BWSIZE, or
> > + * greater than or equal to the stride value configured by BWSTRIDE.
> > + */
> > + uint64_t bw_size_mask = -1L << (bw_size_field + 31);
> > + if (bw_start & bw_size_mask) {
> > + goto fault_walk;
> > + }
> > + if (bw_start & bw_stride_mask) {
> > + goto fault_walk;
> > + }
> > + }
> > +
> > switch (FIELD_EX64(gpccr, GPCCR, PGS)) {
>
> ... here.
>
> None of the checks you're adding are correct:
> - Missing size and stride validation,
> - Alignment check vs size is incorrect; you wanted
>
> bw_start & MAKE_64BIT_MASK(0, bw_size + BW_ADDR_SHIFT)
>
> - Check vs stride is incorrect; you wanted bw_stride <= bw_addr.
>
> See GPCRegistersConsistent().
Thanks for the review Richard; the bw_size_mask check was indeed wrong.
On bw_stride_mask: it was intended to keep the high bits in bw_stride_mask
hence this bitwise comparison should have been equivalent to
bw_stride <= bw_addr; in fact the other use of bw_stride_mask was incorrect.
However, since both Arm and Intel GCC produce roughly the same code for both
I will replace it with the more readable arithmetic operation.
On size and stride validation: there are reserved values for these fields,
but the ARM does not say explicitly (that I can see) that they make GPCBW
/invalid/, so it wasn't clear to me that we should fault on these.
Jim
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 3/5] target/arm/ptw.c: Add Granule Bypass Windows
2026-05-29 16:44 ` Jim MacArthur
@ 2026-05-29 17:11 ` Richard Henderson
0 siblings, 0 replies; 12+ messages in thread
From: Richard Henderson @ 2026-05-29 17:11 UTC (permalink / raw)
To: Jim MacArthur; +Cc: qemu-arm, qemu-devel
On 5/29/26 09:44, Jim MacArthur wrote:
> On size and stride validation: there are reserved values for these fields,
> but the ARM does not say explicitly (that I can see) that they make GPCBW
> /invalid/, so it wasn't clear to me that we should fault on these.
It's right there in the pseudocode for GPCRegistersConsistant.
r~
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-05-29 17:11 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-28 15:34 [PATCH 0/5] target/arm: Add aarch64 GPC3 bypass windows Jim MacArthur
2026-05-28 15:34 ` [PATCH 1/5] target/arm/cpu-features.h: x-rme now means GPC3 Jim MacArthur
2026-05-28 18:03 ` Richard Henderson
2026-05-28 15:34 ` [PATCH 2/5] target/arm: Setup new registers for GPC3 Jim MacArthur
2026-05-28 18:14 ` Richard Henderson
2026-05-28 18:25 ` Richard Henderson
2026-05-28 15:34 ` [PATCH 3/5] target/arm/ptw.c: Add Granule Bypass Windows Jim MacArthur
2026-05-28 18:52 ` Richard Henderson
2026-05-29 16:44 ` Jim MacArthur
2026-05-29 17:11 ` Richard Henderson
2026-05-28 15:34 ` [PATCH 4/5] tests/tcg/aarch64/system: Alternative boot object for exception logging Jim MacArthur
2026-05-28 15:34 ` [PATCH 5/5] tests/tcg/aarch64/system/gpc-test.c: Basic test for granule protection check Jim MacArthur
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.