From 3375d22835694cf5b6c3da534e64e7669e376390 Mon Sep 17 00:00:00 2001 From: Michal Orzel Date: Tue, 25 Aug 2026 08:23:28 +0200 Subject: [PATCH] xen/arm: traps: report level 0 faults in panic_PAR() decode_fsc() derives the fault level from the low two bits of the FSC, so level 0 is a valid output: FSC_FLT_TRANS is 0x04, i.e. "translation fault, level 0 or translation table base register". This is reachable on arm64 because xen_pgtable is the zeroeth-level root, but fsc_level_str() has no case for it and prints " (level invalid)" instead. At the time the function was created Xen used only three levels. Add the missing case. On arm32 the zeroeth level does not exist but FSC 0 denotes address size fault at translation table base register. While at it, make decode_fsc() decode also address size faults. Signed-off-by: Michal Orzel Reviewed-by: Oleksandr Tyshchenko (cherry picked from commit 4e1f58ea1a20d8a831ad72aa30eafa618dfae750) --- xen/arch/arm/include/asm/processor.h | 2 ++ xen/arch/arm/traps.c | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/xen/arch/arm/include/asm/processor.h b/xen/arch/arm/include/asm/processor.h index a3753c317f..509040a1cd 100644 --- a/xen/arch/arm/include/asm/processor.h +++ b/xen/arch/arm/include/asm/processor.h @@ -521,6 +521,7 @@ extern register_t __cpu_logical_map[]; /* * 543210 BIT * 00XXLL -- XX Fault Level LL + * ..00LL -- Address Size Fault LL * ..01LL -- Translation Fault LL * ..10LL -- Access Fault LL * ..11LL -- Permission Fault LL @@ -534,6 +535,7 @@ extern register_t __cpu_logical_map[]; #define FSC_TYPE_OTH (_AC(0x02,U)<<4) #define FSC_TYPE_IMPL (_AC(0x03,U)<<4) +#define FSC_FLT_ADDR_SIZE (0x00) #define FSC_FLT_TRANS (0x04) #define FSC_FLT_ACCESS (0x08) #define FSC_FLT_PERM (0x0c) diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c index 0c01f37ad6..344aa21b98 100644 --- a/xen/arch/arm/traps.c +++ b/xen/arch/arm/traps.c @@ -307,6 +307,10 @@ static const char *decode_fsc(uint32_t fsc, int *level) switch ( fsc & 0x3f ) { + case FSC_FLT_ADDR_SIZE ... FSC_FLT_ADDR_SIZE + 3: + msg = "Address size fault"; + *level = fsc & FSC_LL_MASK; + break; case FSC_FLT_TRANS ... FSC_FLT_TRANS + 3: msg = "Translation fault"; *level = fsc & FSC_LL_MASK; @@ -363,6 +367,7 @@ static const char *fsc_level_str(int level) switch ( level ) { case -1: return ""; + case 0: return " at level 0 or TTBR"; case 1: return " at level 1"; case 2: return " at level 2"; case 3: return " at level 3";