More VRQ code.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@15623 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
Giovanni Di Sirio 2022-05-11 09:27:20 +00:00
parent a3d8eb7e71
commit 3fcb8c47c3
3 changed files with 42 additions and 24 deletions

View File

@ -723,7 +723,7 @@ struct port_context {
* @param[in] tp pointer to the thread * @param[in] tp pointer to the thread
* @param[in] addr new address * @param[in] addr new address
*/ */
#define __port_syscall_set_u_psp(tp, addr) (tp)->ctx.syscall.u_psp = (addr) #define __port_syscall_set_u_psp(tp, addr) (tp)->ctx.syscall.u_psp = (uint32_t)(addr)
/** /**
* @brief Updates the stored system PSP address. * @brief Updates the stored system PSP address.
@ -731,7 +731,7 @@ struct port_context {
* @param[in] tp pointer to the thread * @param[in] tp pointer to the thread
* @param[in] addr new address * @param[in] addr new address
*/ */
#define __port_syscall_set_s_psp(tp, addr) (tp)->ctx.syscall.u_ssp = (addr) #define __port_syscall_set_s_psp(tp, addr) (tp)->ctx.syscall.s_psp = (uint32_t)(addr)
/** /**
* @brief Returns the user PSP address. * @brief Returns the user PSP address.

View File

@ -52,20 +52,29 @@
/*===========================================================================*/ /*===========================================================================*/
__STATIC_FORCEINLINE void vfq_makectx(sb_class_t *sbp, __STATIC_FORCEINLINE void vfq_makectx(sb_class_t *sbp,
struct port_extctx *ectxp, struct port_extctx *newctxp,
uint32_t active_mask) { uint32_t active_mask) {
uint32_t irqn = __CLZ(active_mask); uint32_t irqn = __CLZ(active_mask);
sbp->vrq_wtmask &= ~(1U << irqn); sbp->vrq_wtmask &= ~(1U << irqn);
/* Building the return context.*/ /* Building the return context.*/
ectxp->r0 = irqn; newctxp->r0 = irqn;
ectxp->pc = sbp->sbhp->hdr_vfq; /* TODO validate or let it eventually crash? */ newctxp->pc = sbp->sbhp->hdr_vfq; /* TODO validate or let it eventually crash? */
ectxp->xpsr = 0x01000000U; newctxp->xpsr = 0x01000000U;
#if CORTEX_USE_FPU == TRUE #if CORTEX_USE_FPU == TRUE
ectxp->fpscr = FPU->FPDSCR; newctxp->fpscr = FPU->FPDSCR;
#endif #endif
} }
/**
* @brief Used as a known privileged address.
*/
static void vfq_privileged_code(void) {
while (true) {
}
}
/*===========================================================================*/ /*===========================================================================*/
/* Module exported functions. */ /* Module exported functions. */
/*===========================================================================*/ /*===========================================================================*/
@ -77,14 +86,10 @@ __STATIC_FORCEINLINE void vfq_makectx(sb_class_t *sbp,
* *
* @param[in] sbp pointer to a @p sb_class_t structure * @param[in] sbp pointer to a @p sb_class_t structure
* @param[in] vmask mask of VRQs to be activated * @param[in] vmask mask of VRQs to be activated
* @return The operation status.
* @retval false if the activation has succeeded.
* @retval true in case of sandbox stack overflow.
* *
* @special * @special
*/ */
bool sbVRQTriggerFromISR(sb_class_t *sbp, sb_vrqmask_t vmask) { void sbVRQTriggerFromISR(sb_class_t *sbp, sb_vrqmask_t vmask) {
struct port_extctx *ectxp;
chSysLockFromISR(); chSysLockFromISR();
@ -96,47 +101,57 @@ bool sbVRQTriggerFromISR(sb_class_t *sbp, sb_vrqmask_t vmask) {
sb_vrqmask_t active_mask = sbp->vrq_wtmask & sbp->vrq_enmask; sb_vrqmask_t active_mask = sbp->vrq_wtmask & sbp->vrq_enmask;
if (active_mask != 0U) { if (active_mask != 0U) {
struct port_extctx *ectxp, *newctxp;
/* This IRQ could have preempted the sandbox itself or some other thread, /* This IRQ could have preempted the sandbox itself or some other thread,
handling is different.*/ handling is different.*/
if (sbp->tp->state == CH_STATE_CURRENT) { if (sbp->tp->state == CH_STATE_CURRENT) {
/* Sandbox case, getting the current exception frame.*/ /* Sandbox case, getting the current exception frame.*/
ectxp = (struct port_extctx *)__get_PSP() - 1; ectxp = (struct port_extctx *)__get_PSP();
newctxp = ectxp - 1;
/* Checking if the new frame is within the sandbox else failure.*/ /* Checking if the new frame is within the sandbox else failure.*/
if (!sb_is_valid_write_range(sbp, if (!sb_is_valid_write_range(sbp,
(void *)ectxp, (void *)newctxp,
sizeof (struct port_extctx))) { sizeof (struct port_extctx))) {
/* Making the sandbox return on a privileged address, this
will cause a fault and sandbox termination.*/
chSysUnlockFromISR(); chSysUnlockFromISR();
ectxp->pc = (uint32_t)vfq_privileged_code;
return true; return;
} }
} }
else { else {
ectxp = sbp->tp->ctx.sp - 1; /* Other thread case, getting the pointer from the context switch
structure.*/
ectxp = sbp->tp->ctx.sp;
newctxp = ectxp - 1;
/* Checking if the new frame is within the sandbox else failure.*/ /* Checking if the new frame is within the sandbox else failure.*/
if (!sb_is_valid_write_range(sbp, if (!sb_is_valid_write_range(sbp,
(void *)ectxp, (void *)newctxp,
sizeof (struct port_extctx))) { sizeof (struct port_extctx))) {
/* Making the sandbox return on a privileged address, this
will cause a fault and sandbox termination.*/
chSysUnlockFromISR(); chSysUnlockFromISR();
ectxp->pc = (uint32_t)vfq_privileged_code;
return true; return;
} }
/* Preventing leakage of information, clearing all register values, those /* Preventing leakage of information, clearing all register values, those
would come from outside the sandbox.*/ would come from outside the sandbox.*/
memset((void *)ectxp, 0, sizeof (struct port_extctx)); memset((void *)newctxp, 0, sizeof (struct port_extctx));
} }
/* Building the return context.*/ /* Building the return context.*/
vfq_makectx(sbp, ectxp, active_mask); vfq_makectx(sbp, newctxp, active_mask);
__port_syscall_set_u_psp(sbp->tp, newctxp);
} }
} }
chSysUnlockFromISR(); chSysUnlockFromISR();
return false; return;
} }
void sb_vrq_disable(struct port_extctx *ectxp) { void sb_vrq_disable(struct port_extctx *ectxp) {
@ -169,6 +184,7 @@ void sb_vrq_enable(struct port_extctx *ectxp) {
/* Building the return context.*/ /* Building the return context.*/
vfq_makectx(sbp, ectxp, active_mask); vfq_makectx(sbp, ectxp, active_mask);
__port_syscall_set_u_psp(sbp->tp, ectxp);
} }
} }
} }
@ -202,6 +218,8 @@ void sb_vrq_return(struct port_extctx *ectxp) {
/* Discarding the return current context, returning on the previous one.*/ /* Discarding the return current context, returning on the previous one.*/
ectxp++; ectxp++;
} }
__port_syscall_set_u_psp(sbp->tp, ectxp);
} }
#endif /* SB_CFG_ENABLE_VRQ == TRUE */ #endif /* SB_CFG_ENABLE_VRQ == TRUE */

View File

@ -65,7 +65,7 @@
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
bool sbVRQTriggerFromISR(sb_class_t *sbp, sb_vrqmask_t vmask); void sbVRQTriggerFromISR(sb_class_t *sbp, sb_vrqmask_t vmask);
void sb_vrq_disable(struct port_extctx *ectxp); void sb_vrq_disable(struct port_extctx *ectxp);
void sb_vrq_enable(struct port_extctx *ectxp); void sb_vrq_enable(struct port_extctx *ectxp);
void sb_vrq_getisr(struct port_extctx *ectxp); void sb_vrq_getisr(struct port_extctx *ectxp);