Enable arm64 SError exceptions in the kernel

These are needed to signal to the kernel when a Reliability,
Availability, and Serviceability (RAS) exception has triggered.

Reviewed by:	mhorne
Sponsored by:	The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D31477
This commit is contained in:
Andrew Turner 2021-08-09 16:30:44 +00:00
parent a7fcda1b8c
commit 17b6ee9613
5 changed files with 31 additions and 18 deletions

View File

@ -75,23 +75,25 @@ __FBSDID("$FreeBSD$");
ldr x0, [x18, #(PC_CURTHREAD)]
bl dbg_monitor_enter
msr daifclr, #DAIF_D /* Enable the debug exception */
.endif
/* Unmask debug and SError exceptions */
msr daifclr, #(DAIF_D | DAIF_A)
.else
/*
* Unmask debug and SError exceptions.
* For EL1, debug exceptions are conditionally unmasked in
* do_el1h_sync().
*/
msr daifclr, #(DAIF_A)
.endif
.endm
.macro restore_registers el
.if \el == 1
/*
* Disable interrupts and debug exceptions, x18 may change in the
* interrupt exception handler. For EL0 exceptions, do_ast already
* did this.
* Mask all exceptions, x18 may change in the interrupt exception
* handler.
*/
msr daifset, #(DAIF_D | DAIF_INTR)
.endif
msr daifset, #(DAIF_ALL)
.if \el == 0
ldr x0, [x18, #PC_CURTHREAD]
mov x1, sp
@ -147,8 +149,10 @@ __FBSDID("$FreeBSD$");
/* Make sure the IRQs are enabled before calling ast() */
bic x19, x19, #PSR_I
1:
/* Disable interrupts */
msr daifset, #(DAIF_D | DAIF_INTR)
/*
* Mask interrupts while checking the ast pending flag
*/
msr daifset, #(DAIF_INTR)
/* Read the current thread flags */
ldr x1, [x18, #PC_CURTHREAD] /* Load curthread */

View File

@ -931,6 +931,12 @@ init_proc0(vm_offset_t kstack)
thread0.td_pcb->pcb_vfpcpu = UINT_MAX;
thread0.td_frame = &proc0_tf;
pcpup->pc_curpcb = thread0.td_pcb;
/*
* Unmask SError exceptions. They are used to signal a RAS failure,
* or other hardware error.
*/
serror_enable();
}
typedef struct {

View File

@ -112,7 +112,7 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
/* Setup to release spin count in fork_exit(). */
td2->td_md.md_spinlock_count = 1;
td2->td_md.md_saved_daif = td1->td_md.md_saved_daif & ~DAIF_I_MASKED;
td2->td_md.md_saved_daif = PSR_DAIF_DEFAULT;
}
void
@ -186,7 +186,7 @@ cpu_copy_thread(struct thread *td, struct thread *td0)
/* Setup to release spin count in fork_exit(). */
td->td_md.md_spinlock_count = 1;
td->td_md.md_saved_daif = td0->td_md.md_saved_daif & ~DAIF_I_MASKED;
td->td_md.md_saved_daif = PSR_DAIF_DEFAULT;
}
/*

View File

@ -124,12 +124,6 @@
#define CTR_ILINE_VAL(reg) ((reg) & CTR_ILINE_MASK)
#define CTR_ILINE_SIZE(reg) (4 << (CTR_ILINE_VAL(reg) >> CTR_ILINE_SHIFT))
/* DAIF - Interrupt Mask Bits */
#define DAIF_D_MASKED (1 << 9)
#define DAIF_A_MASKED (1 << 8)
#define DAIF_I_MASKED (1 << 7)
#define DAIF_F_MASKED (1 << 6)
/* DAIFSet/DAIFClear */
#define DAIF_D (1 << 3)
#define DAIF_A (1 << 2)
@ -1078,6 +1072,8 @@
#define PSR_A 0x00000100
#define PSR_D 0x00000200
#define PSR_DAIF (PSR_D | PSR_A | PSR_I | PSR_F)
/* The default DAIF mask. These bits are valid in spsr_el1 and daif */
#define PSR_DAIF_DEFAULT (PSR_F)
#define PSR_IL 0x00100000
#define PSR_SS 0x00200000
#define PSR_V 0x10000000

View File

@ -147,6 +147,13 @@ intr_enable(void)
__asm __volatile("msr daifclr, #(" __XSTRING(DAIF_INTR) ")");
}
static __inline void
serror_enable(void)
{
__asm __volatile("msr daifclr, #(" __XSTRING(DAIF_A) ")");
}
static __inline register_t
get_midr(void)
{