On 6/3/26 11:26, Jim MacArthur wrote:
+ const uint64_t BW_STRIDE_SHIFT = 40;
...
+ switch (bw_stride_field) {
+ case 0b00000:
+ case 0b00010:
+ case 0b00100:
+ case 0b00110:
+ case 0b00111:
+ case 0b01000:
+ case 0b01001:
+ case 0b01010:
+ case 0b10000:
+ bw_stride = 1ULL << (bw_stride_field + BW_STRIDE_SHIFT);
BW_STRIDE_SHIFT should be 39 not 40.
Everything else is correct.
However, we can simplify:
bw_mask = bw_stride - bw_size;
contains the bits [gpcbwu:gpcbwl]. Then...
+ /*
+ * 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.
+ */
if (bw_addr & ~bw_mask)
tests both conditions and...
+ uint64_t bw_size_mask = MAKE_64BIT_MASK(0, bw_size_field +
+ BW_SIZE_SHIFT);
+
+ if (bw_addr & bw_size_mask) {
+ goto fault_walk;
+ }
+
+ if (bw_addr >= bw_stride) {
+ goto fault_walk;
+ }
+ }
+
/* Note this field is read-only and fixed at reset. */
l0gptsz = 30 + FIELD_EX64(gpccr, GPCCR, L0GPTSZ);
@@ -431,6 +494,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_stride_mask = MAKE_64BIT_MASK(0, bw_stride);
+ uint64_t effective_address = paddress & bw_stride_mask;
+
+ if (effective_address >= bw_addr &&
+ effective_address < bw_addr + bw_size) {
+ return true;
+ }
if ((paddress & bw_mask) == bw_addr) {
return true;
}
is exactly the check in PAWithinGPCBypassWindow.
r~