* [PATCH] target/arm: honour CCR.BFHFNMIGN for probed data BusFaults
@ 2026-06-05 3:50 Kyle Fox
2026-06-08 11:23 ` Peter Maydell
2026-06-15 0:08 ` [PATCH v2] " Kyle Fox
0 siblings, 2 replies; 5+ messages in thread
From: Kyle Fox @ 2026-06-05 3:50 UTC (permalink / raw)
To: Peter Maydell; +Cc: Kyle Fox, qemu-arm, qemu-devel
M-profile CCR.BFHFNMIGN lets software executing at a negative execution
priority (in HardFault/NMI, or with FAULTMASK set) suppress precise data
BusFaults caused by load/store instructions: the access completes
returning UNKNOWN data, the fault status is recorded in BFSR/BFAR, but no
BusFault exception is taken. Software uses this to probe for the presence
of a device.
QEMU stored CCR.BFHFNMIGN but never consumed it: arm_cpu_do_transaction_
failed() always raised the external abort, which arm_v7m_cpu_do_interrupt()
pended as a BusFault and then escalated to a HardFault it could not take at
priority -1, aborting the VM with "Lockup: can't escalate 3 to HardFault".
Honour the bit in arm_cpu_do_transaction_failed(): when the access is a
data access from M-profile code at negative priority with BFHFNMIGN set,
record PRECISERR/BFARVALID and BFAR and return without raising, so the
faulting instruction completes instead of re-faulting forever. Instruction
fetches are unaffected, since BFHFNMIGN applies only to data accesses.
This surfaced running the real NXP i.MX 95 System Manager firmware on the
emulated Cortex-M33: its SystemMemoryProbe() (set BFHFNMIGN + FAULTMASK,
do the access, test CFSR.BFARVALID) locked up the VM. With this change the
SM's debug-monitor memory-probe commands run and recover correctly.
Signed-off-by: Kyle Fox <kylefoxaustin.github@gmail.com>
---
Found while bringing up an out-of-tree i.MX 95 machine running the real NXP
System Manager firmware on the emulated Cortex-M33; the change is generic to
any ARMv7-M guest that probes for devices via BusFault suppression. It is
independent of (and posted alongside) a separate PMSAv7 MPU align-down fix
from the same bring-up.
The new path only runs for an M-profile data access at negative priority with
CCR.BFHFNMIGN set - the previously-broken case that aborted the VM. Normal
BusFaults (no BFHFNMIGN, or at non-negative priority) and instruction fetches
are unchanged.
Tested on master: qemu-system-arm builds clean, and the ARMv7-M / MPS2 qtests
pass with no regression -- boot-serial (incl. stm32vldiscovery, Cortex-M3),
the stm32l4x5 suite (Cortex-M4: exti/gpio/rcc/syscfg/usart), microbit,
sse-timer and cmsdk-apb-watchdog.
target/arm/tcg/tlb_helper.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/target/arm/tcg/tlb_helper.c b/target/arm/tcg/tlb_helper.c
index f90765cb59..cbef9cb03e 100644
--- a/target/arm/tcg/tlb_helper.c
+++ b/target/arm/tcg/tlb_helper.c
@@ -10,6 +10,7 @@
#include "helper.h"
#include "internals.h"
#include "cpu-features.h"
+#include "hw/intc/armv7m_nvic.h"
/*
* Returns true if the stage 1 translation regime is using LPAE format page
@@ -318,8 +319,31 @@ void arm_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
MemTxResult response, uintptr_t retaddr)
{
ARMCPU *cpu = ARM_CPU(cs);
+ CPUARMState *env = &cpu->env;
ARMMMUFaultInfo fi = {};
+ /*
+ * For M-profile, CCR.BFHFNMIGN lets software executing at a negative
+ * priority (in HardFault/NMI, or with FAULTMASK set) suppress precise
+ * data BusFaults from load/store instructions: the access completes
+ * returning UNKNOWN data (the store is dropped), the fault status is
+ * recorded in BFSR/BFAR, but no BusFault exception is taken. This is
+ * the mechanism software uses to probe for the presence of a device
+ * (e.g. the NXP System Manager's SystemMemoryProbe). Honour it by
+ * recording the status and returning without raising, so the faulting
+ * instruction completes rather than re-faulting forever. BFHFNMIGN
+ * applies only to data accesses, so instruction fetches are unaffected.
+ */
+ if (arm_feature(env, ARM_FEATURE_M) &&
+ access_type != MMU_INST_FETCH &&
+ (env->v7m.ccr[M_REG_NS] & R_V7M_CCR_BFHFNMIGN_MASK) &&
+ armv7m_nvic_neg_prio_requested(env->nvic, env->v7m.secure)) {
+ env->v7m.cfsr[M_REG_NS] |=
+ (R_V7M_CFSR_PRECISERR_MASK | R_V7M_CFSR_BFARVALID_MASK);
+ env->v7m.bfar = addr;
+ return;
+ }
+
/* now we have a real cpu fault */
cpu_restore_state(cs, retaddr);
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] target/arm: honour CCR.BFHFNMIGN for probed data BusFaults
2026-06-05 3:50 [PATCH] target/arm: honour CCR.BFHFNMIGN for probed data BusFaults Kyle Fox
@ 2026-06-08 11:23 ` Peter Maydell
2026-06-13 5:17 ` kylefoxaustin
2026-06-15 0:08 ` [PATCH v2] " Kyle Fox
1 sibling, 1 reply; 5+ messages in thread
From: Peter Maydell @ 2026-06-08 11:23 UTC (permalink / raw)
To: Kyle Fox; +Cc: qemu-arm, qemu-devel
On Fri, 5 Jun 2026 at 04:50, Kyle Fox <kylefoxaustin.github@gmail.com> wrote:
>
> M-profile CCR.BFHFNMIGN lets software executing at a negative execution
> priority (in HardFault/NMI, or with FAULTMASK set) suppress precise data
> BusFaults caused by load/store instructions: the access completes
> returning UNKNOWN data, the fault status is recorded in BFSR/BFAR, but no
> BusFault exception is taken. Software uses this to probe for the presence
> of a device.
>
> QEMU stored CCR.BFHFNMIGN but never consumed it: arm_cpu_do_transaction_
> failed() always raised the external abort, which arm_v7m_cpu_do_interrupt()
> pended as a BusFault and then escalated to a HardFault it could not take at
> priority -1, aborting the VM with "Lockup: can't escalate 3 to HardFault".
>
> Honour the bit in arm_cpu_do_transaction_failed(): when the access is a
> data access from M-profile code at negative priority with BFHFNMIGN set,
> record PRECISERR/BFARVALID and BFAR and return without raising, so the
> faulting instruction completes instead of re-faulting forever. Instruction
> fetches are unaffected, since BFHFNMIGN applies only to data accesses.
>
> This surfaced running the real NXP i.MX 95 System Manager firmware on the
> emulated Cortex-M33: its SystemMemoryProbe() (set BFHFNMIGN + FAULTMASK,
> do the access, test CFSR.BFARVALID) locked up the VM. With this change the
> SM's debug-monitor memory-probe commands run and recover correctly.
>
> Signed-off-by: Kyle Fox <kylefoxaustin.github@gmail.com>
> ---
> Found while bringing up an out-of-tree i.MX 95 machine running the real NXP
> System Manager firmware on the emulated Cortex-M33; the change is generic to
> any ARMv7-M guest that probes for devices via BusFault suppression. It is
> independent of (and posted alongside) a separate PMSAv7 MPU align-down fix
> from the same bring-up.
>
> The new path only runs for an M-profile data access at negative priority with
> CCR.BFHFNMIGN set - the previously-broken case that aborted the VM. Normal
> BusFaults (no BFHFNMIGN, or at non-negative priority) and instruction fetches
> are unchanged.
>
> Tested on master: qemu-system-arm builds clean, and the ARMv7-M / MPS2 qtests
> pass with no regression -- boot-serial (incl. stm32vldiscovery, Cortex-M3),
> the stm32l4x5 suite (Cortex-M4: exti/gpio/rcc/syscfg/usart), microbit,
> sse-timer and cmsdk-apb-watchdog.
>
> target/arm/tcg/tlb_helper.c | 24 ++++++++++++++++++++++++
> 1 file changed, 24 insertions(+)
>
> diff --git a/target/arm/tcg/tlb_helper.c b/target/arm/tcg/tlb_helper.c
> index f90765cb59..cbef9cb03e 100644
> --- a/target/arm/tcg/tlb_helper.c
> +++ b/target/arm/tcg/tlb_helper.c
> @@ -10,6 +10,7 @@
> #include "helper.h"
> #include "internals.h"
> #include "cpu-features.h"
> +#include "hw/intc/armv7m_nvic.h"
>
> /*
> * Returns true if the stage 1 translation regime is using LPAE format page
> @@ -318,8 +319,31 @@ void arm_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
> MemTxResult response, uintptr_t retaddr)
> {
> ARMCPU *cpu = ARM_CPU(cs);
> + CPUARMState *env = &cpu->env;
> ARMMMUFaultInfo fi = {};
>
> + /*
> + * For M-profile, CCR.BFHFNMIGN lets software executing at a negative
> + * priority (in HardFault/NMI, or with FAULTMASK set) suppress precise
> + * data BusFaults from load/store instructions: the access completes
> + * returning UNKNOWN data (the store is dropped), the fault status is
> + * recorded in BFSR/BFAR, but no BusFault exception is taken. This is
> + * the mechanism software uses to probe for the presence of a device
> + * (e.g. the NXP System Manager's SystemMemoryProbe). Honour it by
> + * recording the status and returning without raising, so the faulting
> + * instruction completes rather than re-faulting forever. BFHFNMIGN
> + * applies only to data accesses, so instruction fetches are unaffected.
> + */
> + if (arm_feature(env, ARM_FEATURE_M) &&
> + access_type != MMU_INST_FETCH &&
> + (env->v7m.ccr[M_REG_NS] & R_V7M_CCR_BFHFNMIGN_MASK) &&
> + armv7m_nvic_neg_prio_requested(env->nvic, env->v7m.secure)) {
> + env->v7m.cfsr[M_REG_NS] |=
> + (R_V7M_CFSR_PRECISERR_MASK | R_V7M_CFSR_BFARVALID_MASK);
> + env->v7m.bfar = addr;
> + return;
> + }
Thanks for this patch. This looks good, but it misses a very
obscure corner case, which is the load of the word from the stack
performed by the SG instruction. In the pseudocode that is an
AccType_NORMAL access, so it should honour BFHFNMIGN. In QEMU
we (for complicated reasons) implement that load manually in
v7m_read_sg_stack_word(), so it doesn't go through the TCG TLB
and this transaction_failed hook. So v7m_read_sg_stack_word()
should check BFHFNMIGN to see if it should pend the ARMV7M_EXCP_BUS.
The other places where we manually pend EXCP_BUS are all ones
which should not or are not required to honour BFHFNMIGN
(vector table loads, stacking and unstacking, which are
AccType_VECTABLE, AccType_STACK, AccType_UNSTACK).
thanks
-- PMM
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] target/arm: honour CCR.BFHFNMIGN for probed data BusFaults
2026-06-08 11:23 ` Peter Maydell
@ 2026-06-13 5:17 ` kylefoxaustin
2026-06-14 15:56 ` Peter Maydell
0 siblings, 1 reply; 5+ messages in thread
From: kylefoxaustin @ 2026-06-13 5:17 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-arm, qemu-devel
[-- Attachment #1: Type: text/plain, Size: 6533 bytes --]
Hi Peter!
Thanks, great catch. You're right that the SG stack-word load is an
AccType_NORMAL access and should honour BFHFNMIGN.
I'm working on v2 to incorporate. Basically v2 adds the check in
v7m_read_sg_stack_word():
on the BusFault path it records BFSR/BFAR as before but, when BFHFNMIGN is
set at negative
execution priority, it completes the access returning UNKNOWN data and
returns true, instead of pending ARMV7M_EXCP_BUS. I left the vector-table,
stacking and unstacking EXCP_BUS sites untouched, per your note that those
are AccType_VECTABLE/STACK/UNSTACK and are not required to honour it.
One question on the register bank: I kept ccr[M_REG_NS] in the new check to
match the expression in the transaction_failed hook from v1, but the nearby
STKOFHFNMIGN code in this file uses ccr[is_secure]. Happy to switch both
sites to [secure] if you think that's more correct here.
v2 follows soon for review.
again many thanks!
-- Kyle
On Mon, Jun 8, 2026 at 6:24 AM Peter Maydell <peter.maydell@linaro.org>
wrote:
> On Fri, 5 Jun 2026 at 04:50, Kyle Fox <kylefoxaustin.github@gmail.com>
> wrote:
> >
> > M-profile CCR.BFHFNMIGN lets software executing at a negative execution
> > priority (in HardFault/NMI, or with FAULTMASK set) suppress precise data
> > BusFaults caused by load/store instructions: the access completes
> > returning UNKNOWN data, the fault status is recorded in BFSR/BFAR, but no
> > BusFault exception is taken. Software uses this to probe for the presence
> > of a device.
> >
> > QEMU stored CCR.BFHFNMIGN but never consumed it: arm_cpu_do_transaction_
> > failed() always raised the external abort, which
> arm_v7m_cpu_do_interrupt()
> > pended as a BusFault and then escalated to a HardFault it could not take
> at
> > priority -1, aborting the VM with "Lockup: can't escalate 3 to
> HardFault".
> >
> > Honour the bit in arm_cpu_do_transaction_failed(): when the access is a
> > data access from M-profile code at negative priority with BFHFNMIGN set,
> > record PRECISERR/BFARVALID and BFAR and return without raising, so the
> > faulting instruction completes instead of re-faulting forever.
> Instruction
> > fetches are unaffected, since BFHFNMIGN applies only to data accesses.
> >
> > This surfaced running the real NXP i.MX 95 System Manager firmware on the
> > emulated Cortex-M33: its SystemMemoryProbe() (set BFHFNMIGN + FAULTMASK,
> > do the access, test CFSR.BFARVALID) locked up the VM. With this change
> the
> > SM's debug-monitor memory-probe commands run and recover correctly.
> >
> > Signed-off-by: Kyle Fox <kylefoxaustin.github@gmail.com>
> > ---
> > Found while bringing up an out-of-tree i.MX 95 machine running the real
> NXP
> > System Manager firmware on the emulated Cortex-M33; the change is
> generic to
> > any ARMv7-M guest that probes for devices via BusFault suppression. It is
> > independent of (and posted alongside) a separate PMSAv7 MPU align-down
> fix
> > from the same bring-up.
> >
> > The new path only runs for an M-profile data access at negative priority
> with
> > CCR.BFHFNMIGN set - the previously-broken case that aborted the VM.
> Normal
> > BusFaults (no BFHFNMIGN, or at non-negative priority) and instruction
> fetches
> > are unchanged.
> >
> > Tested on master: qemu-system-arm builds clean, and the ARMv7-M / MPS2
> qtests
> > pass with no regression -- boot-serial (incl. stm32vldiscovery,
> Cortex-M3),
> > the stm32l4x5 suite (Cortex-M4: exti/gpio/rcc/syscfg/usart), microbit,
> > sse-timer and cmsdk-apb-watchdog.
> >
> > target/arm/tcg/tlb_helper.c | 24 ++++++++++++++++++++++++
> > 1 file changed, 24 insertions(+)
> >
> > diff --git a/target/arm/tcg/tlb_helper.c b/target/arm/tcg/tlb_helper.c
> > index f90765cb59..cbef9cb03e 100644
> > --- a/target/arm/tcg/tlb_helper.c
> > +++ b/target/arm/tcg/tlb_helper.c
> > @@ -10,6 +10,7 @@
> > #include "helper.h"
> > #include "internals.h"
> > #include "cpu-features.h"
> > +#include "hw/intc/armv7m_nvic.h"
> >
> > /*
> > * Returns true if the stage 1 translation regime is using LPAE format
> page
> > @@ -318,8 +319,31 @@ void arm_cpu_do_transaction_failed(CPUState *cs,
> hwaddr physaddr,
> > MemTxResult response, uintptr_t
> retaddr)
> > {
> > ARMCPU *cpu = ARM_CPU(cs);
> > + CPUARMState *env = &cpu->env;
> > ARMMMUFaultInfo fi = {};
> >
> > + /*
> > + * For M-profile, CCR.BFHFNMIGN lets software executing at a
> negative
> > + * priority (in HardFault/NMI, or with FAULTMASK set) suppress
> precise
> > + * data BusFaults from load/store instructions: the access completes
> > + * returning UNKNOWN data (the store is dropped), the fault status
> is
> > + * recorded in BFSR/BFAR, but no BusFault exception is taken. This
> is
> > + * the mechanism software uses to probe for the presence of a device
> > + * (e.g. the NXP System Manager's SystemMemoryProbe). Honour it by
> > + * recording the status and returning without raising, so the
> faulting
> > + * instruction completes rather than re-faulting forever. BFHFNMIGN
> > + * applies only to data accesses, so instruction fetches are
> unaffected.
> > + */
> > + if (arm_feature(env, ARM_FEATURE_M) &&
> > + access_type != MMU_INST_FETCH &&
> > + (env->v7m.ccr[M_REG_NS] & R_V7M_CCR_BFHFNMIGN_MASK) &&
> > + armv7m_nvic_neg_prio_requested(env->nvic, env->v7m.secure)) {
> > + env->v7m.cfsr[M_REG_NS] |=
> > + (R_V7M_CFSR_PRECISERR_MASK | R_V7M_CFSR_BFARVALID_MASK);
> > + env->v7m.bfar = addr;
> > + return;
> > + }
>
> Thanks for this patch. This looks good, but it misses a very
> obscure corner case, which is the load of the word from the stack
> performed by the SG instruction. In the pseudocode that is an
> AccType_NORMAL access, so it should honour BFHFNMIGN. In QEMU
> we (for complicated reasons) implement that load manually in
> v7m_read_sg_stack_word(), so it doesn't go through the TCG TLB
> and this transaction_failed hook. So v7m_read_sg_stack_word()
> should check BFHFNMIGN to see if it should pend the ARMV7M_EXCP_BUS.
>
> The other places where we manually pend EXCP_BUS are all ones
> which should not or are not required to honour BFHFNMIGN
> (vector table loads, stacking and unstacking, which are
> AccType_VECTABLE, AccType_STACK, AccType_UNSTACK).
>
> thanks
> -- PMM
>
[-- Attachment #2: Type: text/html, Size: 7746 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] target/arm: honour CCR.BFHFNMIGN for probed data BusFaults
2026-06-13 5:17 ` kylefoxaustin
@ 2026-06-14 15:56 ` Peter Maydell
0 siblings, 0 replies; 5+ messages in thread
From: Peter Maydell @ 2026-06-14 15:56 UTC (permalink / raw)
To: kylefoxaustin; +Cc: qemu-arm, qemu-devel
On Sat, 13 Jun 2026 at 06:17, kylefoxaustin
<kylefoxaustin.github@gmail.com> wrote:
>
> Hi Peter!
> Thanks, great catch. You're right that the SG stack-word load is an
> AccType_NORMAL access and should honour BFHFNMIGN.
>
> I'm working on v2 to incorporate. Basically v2 adds the check in v7m_read_sg_stack_word():
> on the BusFault path it records BFSR/BFAR as before but, when BFHFNMIGN is set at negative
> execution priority, it completes the access returning UNKNOWN data and
> returns true, instead of pending ARMV7M_EXCP_BUS. I left the vector-table,
> stacking and unstacking EXCP_BUS sites untouched, per your note that those
> are AccType_VECTABLE/STACK/UNSTACK and are not required to honour it.
>
> One question on the register bank: I kept ccr[M_REG_NS] in the new check to
> match the expression in the transaction_failed hook from v1, but the nearby
> STKOFHFNMIGN code in this file uses ccr[is_secure]. Happy to switch both
> sites to [secure] if you think that's more correct here.
The CCR register has some bits which are banked (so have S and NS copies)
but some bits which are not banked (so S and NS see the same thing).
The way we implement that is that for the non-banked bits we store
them in one of the two entries in the v7m.ccr[] array, and code that
uses the bit has to check that one. BFHFNMIGN is one of the non-banked
bits, and we keep it in the NS array entry, and check ccr[M_REG_NS].
STKOFHFNMIGN is banked, so we check ccr[is_secure] to get the banked
bit corresponding to the right securite state.
thanks
-- PMM
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2] target/arm: honour CCR.BFHFNMIGN for probed data BusFaults
2026-06-05 3:50 [PATCH] target/arm: honour CCR.BFHFNMIGN for probed data BusFaults Kyle Fox
2026-06-08 11:23 ` Peter Maydell
@ 2026-06-15 0:08 ` Kyle Fox
1 sibling, 0 replies; 5+ messages in thread
From: Kyle Fox @ 2026-06-15 0:08 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-arm, qemu-devel, Kyle Fox
M-profile CCR.BFHFNMIGN lets software executing at a negative execution
priority (in HardFault/NMI, or with FAULTMASK set) suppress precise data
BusFaults caused by load/store instructions: the access completes
returning UNKNOWN data, the fault status is recorded in BFSR/BFAR, but no
BusFault exception is taken. Software uses this to probe for the presence
of a device.
QEMU stored CCR.BFHFNMIGN but never consumed it: arm_cpu_do_transaction_
failed() always raised the external abort, which arm_v7m_cpu_do_interrupt()
pended as a BusFault and then escalated to a HardFault it could not take at
priority -1, aborting the VM with "Lockup: can't escalate 3 to HardFault".
Honour the bit in arm_cpu_do_transaction_failed(): when the access is a
data access from M-profile code at negative priority with BFHFNMIGN set,
record PRECISERR/BFARVALID and BFAR and return without raising, so the
faulting instruction completes instead of re-faulting forever. Instruction
fetches are unaffected, since BFHFNMIGN applies only to data accesses.
The SG instruction's stack-word load is also an AccType_NORMAL data access
that must honour BFHFNMIGN, but QEMU performs it manually in
v7m_read_sg_stack_word() (outside the TCG TLB, so it never reaches
arm_cpu_do_transaction_failed()). Apply the same suppression there: on a
BusFault, record the status and, when BFHFNMIGN is set at negative
priority, return the UNKNOWN data instead of pending ARMV7M_EXCP_BUS. The
remaining manual EXCP_BUS sites (vector-table loads, stacking, unstacking)
are AccType_VECTABLE/STACK/UNSTACK and are not required to honour the bit,
so they are left unchanged.
This surfaced running the real NXP i.MX 95 System Manager firmware on the
emulated Cortex-M33: its SystemMemoryProbe() (set BFHFNMIGN + FAULTMASK,
do the access, test CFSR.BFARVALID) locked up the VM. With this change the
SM's debug-monitor memory-probe commands run and recover correctly.
Signed-off-by: Kyle Fox <kylefoxaustin.github@gmail.com>
---
v2:
- Also honour BFHFNMIGN for the SG instruction's stack-word load in
v7m_read_sg_stack_word() (an AccType_NORMAL access performed manually,
outside the TCG TLB), per review. The vector-table/stacking/unstacking
EXCP_BUS sites are left unchanged (AccType_VECTABLE/STACK/UNSTACK).
target/arm/tcg/m_helper.c | 12 ++++++++++++
target/arm/tcg/tlb_helper.c | 24 ++++++++++++++++++++++++
2 files changed, 36 insertions(+)
diff --git a/target/arm/tcg/m_helper.c b/target/arm/tcg/m_helper.c
index f2059ed8b03..ba101ecb953 100644
--- a/target/arm/tcg/m_helper.c
+++ b/target/arm/tcg/m_helper.c
@@ -2086,6 +2086,18 @@ static bool v7m_read_sg_stack_word(ARMCPU *cpu, ARMMMUIdx mmu_idx,
env->v7m.cfsr[M_REG_NS] |=
(R_V7M_CFSR_PRECISERR_MASK | R_V7M_CFSR_BFARVALID_MASK);
env->v7m.bfar = addr;
+ /*
+ * The SG instruction's stack-word load is an AccType_NORMAL data
+ * access, so CCR.BFHFNMIGN applies: at negative execution priority
+ * with BFHFNMIGN set, the BusFault is suppressed -- the access
+ * completes returning UNKNOWN data (status recorded above), with no
+ * BusFault exception pended.
+ */
+ if ((env->v7m.ccr[M_REG_NS] & R_V7M_CCR_BFHFNMIGN_MASK) &&
+ armv7m_nvic_neg_prio_requested(env->nvic, env->v7m.secure)) {
+ *spdata = value;
+ return true;
+ }
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_BUS, false);
return false;
}
diff --git a/target/arm/tcg/tlb_helper.c b/target/arm/tcg/tlb_helper.c
index bbe1e70bc43..452688010f5 100644
--- a/target/arm/tcg/tlb_helper.c
+++ b/target/arm/tcg/tlb_helper.c
@@ -10,6 +10,7 @@
#include "helper.h"
#include "internals.h"
#include "cpu-features.h"
+#include "hw/intc/armv7m_nvic.h"
/*
* Returns true if the stage 1 translation regime is using LPAE format page
@@ -318,8 +319,31 @@ void arm_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
MemTxResult response, uintptr_t retaddr)
{
ARMCPU *cpu = ARM_CPU(cs);
+ CPUARMState *env = &cpu->env;
ARMMMUFaultInfo fi = {};
+ /*
+ * For M-profile, CCR.BFHFNMIGN lets software executing at a negative
+ * priority (in HardFault/NMI, or with FAULTMASK set) suppress precise
+ * data BusFaults from load/store instructions: the access completes
+ * returning UNKNOWN data (the store is dropped), the fault status is
+ * recorded in BFSR/BFAR, but no BusFault exception is taken. This is
+ * the mechanism software uses to probe for the presence of a device
+ * (e.g. the NXP System Manager's SystemMemoryProbe). Honour it by
+ * recording the status and returning without raising, so the faulting
+ * instruction completes rather than re-faulting forever. BFHFNMIGN
+ * applies only to data accesses, so instruction fetches are unaffected.
+ */
+ if (arm_feature(env, ARM_FEATURE_M) &&
+ access_type != MMU_INST_FETCH &&
+ (env->v7m.ccr[M_REG_NS] & R_V7M_CCR_BFHFNMIGN_MASK) &&
+ armv7m_nvic_neg_prio_requested(env->nvic, env->v7m.secure)) {
+ env->v7m.cfsr[M_REG_NS] |=
+ (R_V7M_CFSR_PRECISERR_MASK | R_V7M_CFSR_BFARVALID_MASK);
+ env->v7m.bfar = addr;
+ return;
+ }
+
/* now we have a real cpu fault */
cpu_restore_state(cs, retaddr);
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-06-15 0:09 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-05 3:50 [PATCH] target/arm: honour CCR.BFHFNMIGN for probed data BusFaults Kyle Fox
2026-06-08 11:23 ` Peter Maydell
2026-06-13 5:17 ` kylefoxaustin
2026-06-14 15:56 ` Peter Maydell
2026-06-15 0:08 ` [PATCH v2] " Kyle Fox
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.