arch/armv8-m: Add CONTROL register to xcptcontext.
To simplify the interrupt handling in protected mode. Signed-off-by: wangming9 <wangming9@xiaomi.com>
This commit is contained in:
parent
2684642a7a
commit
f8aaed780a
@ -72,8 +72,9 @@
|
|||||||
#define REG_R9 (7) /* R9 */
|
#define REG_R9 (7) /* R9 */
|
||||||
#define REG_R10 (8) /* R10 */
|
#define REG_R10 (8) /* R10 */
|
||||||
#define REG_R11 (9) /* R11 */
|
#define REG_R11 (9) /* R11 */
|
||||||
#define REG_EXC_RETURN (10) /* EXC_RETURN */
|
#define REG_CONTROL (10) /* CONTROL */
|
||||||
#define SW_INT_REGS (11)
|
#define REG_EXC_RETURN (11) /* EXC_RETURN */
|
||||||
|
#define SW_INT_REGS (12)
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_FPU
|
#ifdef CONFIG_ARCH_FPU
|
||||||
|
|
||||||
|
@ -146,6 +146,7 @@
|
|||||||
exception_common:
|
exception_common:
|
||||||
|
|
||||||
mrs r0, ipsr /* R0=exception number */
|
mrs r0, ipsr /* R0=exception number */
|
||||||
|
mrs r12, control /* R12=control */
|
||||||
|
|
||||||
/* Complete the context save */
|
/* Complete the context save */
|
||||||
|
|
||||||
@ -198,7 +199,7 @@ exception_common:
|
|||||||
subne sp, #(4*SW_FPU_REGS)
|
subne sp, #(4*SW_FPU_REGS)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
stmdb sp!, {r2-r11,r14} /* Save the remaining registers plus the SP/PRIMASK values */
|
stmdb sp!, {r2-r12,r14} /* Save the remaining registers plus the SP/PRIMASK values */
|
||||||
|
|
||||||
/* There are two arguments to arm_doirq:
|
/* There are two arguments to arm_doirq:
|
||||||
*
|
*
|
||||||
@ -243,7 +244,7 @@ exception_common:
|
|||||||
* array to use for the interrupt return.
|
* array to use for the interrupt return.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ldmia r0!, {r2-r11,r14} /* Recover R4-R11, r14 + 2 temp values */
|
ldmia r0!, {r2-r12,r14} /* Recover R4-R12, r14 + 2 temp values */
|
||||||
#ifdef CONFIG_ARCH_FPU
|
#ifdef CONFIG_ARCH_FPU
|
||||||
/* Switched-in task including volatile FP registers ? */
|
/* Switched-in task including volatile FP registers ? */
|
||||||
|
|
||||||
@ -260,31 +261,6 @@ exception_common:
|
|||||||
/* The EXC_RETURN value tells us whether we are returning on the MSP or PSP
|
/* The EXC_RETURN value tells us whether we are returning on the MSP or PSP
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef CONFIG_BUILD_PROTECTED
|
|
||||||
/* The EXC_RETURN value will be 0xfffffff9 (privileged thread) or 0xfffffff1
|
|
||||||
* (handler mode) if the stack is on the MSP. It can only be on the PSP if
|
|
||||||
* EXC_RETURN is 0xfffffffd (unprivileged thread)
|
|
||||||
*/
|
|
||||||
|
|
||||||
mrs r2, control /* R2=Contents of the control register */
|
|
||||||
tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */
|
|
||||||
beq 2f /* Branch if privileged */
|
|
||||||
|
|
||||||
orr r2, r2, #1 /* Unprivileged mode */
|
|
||||||
#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
|
|
||||||
msr psplim, r1
|
|
||||||
#endif
|
|
||||||
msr psp, r0 /* R0=The process stack pointer */
|
|
||||||
b 3f
|
|
||||||
2:
|
|
||||||
bic r2, r2, #1 /* Privileged mode */
|
|
||||||
#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
|
|
||||||
msr msplim, r1
|
|
||||||
#endif
|
|
||||||
msr msp, r0 /* R0=The main stack pointer */
|
|
||||||
3:
|
|
||||||
msr control, r2 /* Save the updated control register */
|
|
||||||
#else
|
|
||||||
tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */
|
tst r14, #EXC_RETURN_PROCESS_STACK /* nonzero if context on process stack */
|
||||||
#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
|
#ifdef CONFIG_ARMV8M_STACKCHECK_HARDWARE
|
||||||
itete eq
|
itete eq
|
||||||
@ -295,7 +271,6 @@ exception_common:
|
|||||||
#endif
|
#endif
|
||||||
msreq msp, r0 /* R0=The main stack pointer */
|
msreq msp, r0 /* R0=The main stack pointer */
|
||||||
msrne psp, r0 /* R0=The process stack pointer */
|
msrne psp, r0 /* R0=The process stack pointer */
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Restore the interrupt state */
|
/* Restore the interrupt state */
|
||||||
|
|
||||||
@ -305,6 +280,8 @@ exception_common:
|
|||||||
msr primask, r3 /* Restore interrupts */
|
msr primask, r3 /* Restore interrupts */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
msr control, r12
|
||||||
|
|
||||||
/* Always return with R14 containing the special value that will: (1)
|
/* Always return with R14 containing the special value that will: (1)
|
||||||
* return to thread mode, and (2) select the correct stack.
|
* return to thread mode, and (2) select the correct stack.
|
||||||
*/
|
*/
|
||||||
|
@ -150,6 +150,8 @@ void up_initial_state(struct tcb_s *tcb)
|
|||||||
|
|
||||||
xcp->regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
|
xcp->regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
|
||||||
|
|
||||||
|
xcp->regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_FPU
|
#ifdef CONFIG_ARCH_FPU
|
||||||
xcp->regs[REG_FPSCR] |= ARMV8M_FPSCR_LTPSIZE_NONE;
|
xcp->regs[REG_FPSCR] |= ARMV8M_FPSCR_LTPSIZE_NONE;
|
||||||
#endif /* CONFIG_ARCH_FPU */
|
#endif /* CONFIG_ARCH_FPU */
|
||||||
|
@ -162,6 +162,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
|||||||
#ifdef CONFIG_BUILD_PROTECTED
|
#ifdef CONFIG_BUILD_PROTECTED
|
||||||
CURRENT_REGS[REG_LR] = EXC_RETURN_PRIVTHR;
|
CURRENT_REGS[REG_LR] = EXC_RETURN_PRIVTHR;
|
||||||
CURRENT_REGS[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
|
CURRENT_REGS[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
|
||||||
|
CURRENT_REGS[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,6 +210,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
|||||||
tcb->xcp.regs[REG_XPSR] = ARMV8M_XPSR_T;
|
tcb->xcp.regs[REG_XPSR] = ARMV8M_XPSR_T;
|
||||||
#ifdef CONFIG_BUILD_PROTECTED
|
#ifdef CONFIG_BUILD_PROTECTED
|
||||||
tcb->xcp.regs[REG_LR] = EXC_RETURN_PRIVTHR;
|
tcb->xcp.regs[REG_LR] = EXC_RETURN_PRIVTHR;
|
||||||
|
tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -319,6 +321,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
|||||||
tcb->xcp.regs[REG_XPSR] = ARMV8M_XPSR_T;
|
tcb->xcp.regs[REG_XPSR] = ARMV8M_XPSR_T;
|
||||||
#ifdef CONFIG_BUILD_PROTECTED
|
#ifdef CONFIG_BUILD_PROTECTED
|
||||||
tcb->xcp.regs[REG_LR] = EXC_RETURN_PRIVTHR;
|
tcb->xcp.regs[REG_LR] = EXC_RETURN_PRIVTHR;
|
||||||
|
tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -365,6 +368,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
|||||||
CURRENT_REGS[REG_XPSR] = ARMV8M_XPSR_T;
|
CURRENT_REGS[REG_XPSR] = ARMV8M_XPSR_T;
|
||||||
#ifdef CONFIG_BUILD_PROTECTED
|
#ifdef CONFIG_BUILD_PROTECTED
|
||||||
CURRENT_REGS[REG_LR] = EXC_RETURN_PRIVTHR;
|
CURRENT_REGS[REG_LR] = EXC_RETURN_PRIVTHR;
|
||||||
|
CURRENT_REGS[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -431,6 +435,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
|
|||||||
tcb->xcp.regs[REG_XPSR] = ARMV8M_XPSR_T;
|
tcb->xcp.regs[REG_XPSR] = ARMV8M_XPSR_T;
|
||||||
#ifdef CONFIG_BUILD_PROTECTED
|
#ifdef CONFIG_BUILD_PROTECTED
|
||||||
tcb->xcp.regs[REG_LR] = EXC_RETURN_PRIVTHR;
|
tcb->xcp.regs[REG_LR] = EXC_RETURN_PRIVTHR;
|
||||||
|
tcb->xcp.regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -145,12 +145,8 @@ int arm_svcall(int irq, void *context, void *arg)
|
|||||||
svcinfo(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
svcinfo(" R8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||||
regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11],
|
regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11],
|
||||||
regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]);
|
regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]);
|
||||||
# ifdef REG_EXC_RETURN
|
svcinfo(" PSR: %08x EXC_RETURN: %08x CONTROL: %08x\n",
|
||||||
svcinfo(" PSR: %08x EXC_RETURN: %08x\n",
|
regs[REG_XPSR], regs[REG_EXC_RETURN], regs[REG_CONTROL]);
|
||||||
regs[REG_XPSR], regs[REG_EXC_RETURN]);
|
|
||||||
# else
|
|
||||||
svcinfo(" PSR: %08x\n", regs[REG_XPSR]);
|
|
||||||
# endif
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -276,6 +272,10 @@ int arm_svcall(int irq, void *context, void *arg)
|
|||||||
regs[REG_PC] = (uint32_t)USERSPACE->task_startup & ~1;
|
regs[REG_PC] = (uint32_t)USERSPACE->task_startup & ~1;
|
||||||
regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR;
|
regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR;
|
||||||
|
|
||||||
|
/* Return unprivileged mode */
|
||||||
|
|
||||||
|
regs[REG_CONTROL] = getcontrol() | CONTROL_NPRIV;
|
||||||
|
|
||||||
/* Change the parameter ordering to match the expectation of struct
|
/* Change the parameter ordering to match the expectation of struct
|
||||||
* userpace_s task_startup:
|
* userpace_s task_startup:
|
||||||
*/
|
*/
|
||||||
@ -310,6 +310,10 @@ int arm_svcall(int irq, void *context, void *arg)
|
|||||||
regs[REG_PC] = (uint32_t)regs[REG_R1] & ~1; /* startup */
|
regs[REG_PC] = (uint32_t)regs[REG_R1] & ~1; /* startup */
|
||||||
regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR;
|
regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR;
|
||||||
|
|
||||||
|
/* Return unprivileged mode */
|
||||||
|
|
||||||
|
regs[REG_CONTROL] = getcontrol() | CONTROL_NPRIV;
|
||||||
|
|
||||||
/* Change the parameter ordering to match the expectation of the
|
/* Change the parameter ordering to match the expectation of the
|
||||||
* user space pthread_startup:
|
* user space pthread_startup:
|
||||||
*/
|
*/
|
||||||
@ -351,6 +355,10 @@ int arm_svcall(int irq, void *context, void *arg)
|
|||||||
regs[REG_PC] = (uint32_t)USERSPACE->signal_handler & ~1;
|
regs[REG_PC] = (uint32_t)USERSPACE->signal_handler & ~1;
|
||||||
regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR;
|
regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR;
|
||||||
|
|
||||||
|
/* Return unprivileged mode */
|
||||||
|
|
||||||
|
regs[REG_CONTROL] = getcontrol() | CONTROL_NPRIV;
|
||||||
|
|
||||||
/* Change the parameter ordering to match the expectation of struct
|
/* Change the parameter ordering to match the expectation of struct
|
||||||
* userpace_s signal_handler.
|
* userpace_s signal_handler.
|
||||||
*/
|
*/
|
||||||
@ -383,6 +391,11 @@ int arm_svcall(int irq, void *context, void *arg)
|
|||||||
|
|
||||||
regs[REG_PC] = rtcb->xcp.sigreturn & ~1;
|
regs[REG_PC] = rtcb->xcp.sigreturn & ~1;
|
||||||
regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
|
regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
|
||||||
|
|
||||||
|
/* Return privileged mode */
|
||||||
|
|
||||||
|
regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||||
|
|
||||||
rtcb->xcp.sigreturn = 0;
|
rtcb->xcp.sigreturn = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -418,6 +431,10 @@ int arm_svcall(int irq, void *context, void *arg)
|
|||||||
regs[REG_PC] = (uint32_t)dispatch_syscall & ~1;
|
regs[REG_PC] = (uint32_t)dispatch_syscall & ~1;
|
||||||
regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
|
regs[REG_EXC_RETURN] = EXC_RETURN_PRIVTHR;
|
||||||
|
|
||||||
|
/* Return privileged mode */
|
||||||
|
|
||||||
|
regs[REG_CONTROL] = getcontrol() & ~CONTROL_NPRIV;
|
||||||
|
|
||||||
/* Offset R0 to account for the reserved values */
|
/* Offset R0 to account for the reserved values */
|
||||||
|
|
||||||
regs[REG_R0] -= CONFIG_SYS_RESERVED;
|
regs[REG_R0] -= CONFIG_SYS_RESERVED;
|
||||||
@ -454,12 +471,9 @@ int arm_svcall(int irq, void *context, void *arg)
|
|||||||
CURRENT_REGS[REG_R10], CURRENT_REGS[REG_R11],
|
CURRENT_REGS[REG_R10], CURRENT_REGS[REG_R11],
|
||||||
CURRENT_REGS[REG_R12], CURRENT_REGS[REG_R13],
|
CURRENT_REGS[REG_R12], CURRENT_REGS[REG_R13],
|
||||||
CURRENT_REGS[REG_R14], CURRENT_REGS[REG_R15]);
|
CURRENT_REGS[REG_R14], CURRENT_REGS[REG_R15]);
|
||||||
# ifdef REG_EXC_RETURN
|
svcinfo(" PSR: %08x EXC_RETURN: %08x CONTROL: %08x\n",
|
||||||
svcinfo(" PSR: %08x EXC_RETURN: %08x\n",
|
CURRENT_REGS[REG_XPSR], CURRENT_REGS[REG_EXC_RETURN],
|
||||||
CURRENT_REGS[REG_XPSR], CURRENT_REGS[REG_EXC_RETURN]);
|
CURRENT_REGS[REG_CONTROL]);
|
||||||
# else
|
|
||||||
svcinfo(" PSR: %08x\n", CURRENT_REGS[REG_XPSR]);
|
|
||||||
# endif
|
|
||||||
}
|
}
|
||||||
# ifdef CONFIG_DEBUG_SVCALL
|
# ifdef CONFIG_DEBUG_SVCALL
|
||||||
else
|
else
|
||||||
|
Loading…
Reference in New Issue
Block a user