Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 34 additions & 9 deletions arch/x86_64/src/common/x86_64_syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@

#include "x86_64_internal.h"

/****************************************************************************
* Pre-processor Definitions
****************************************************************************/

/* Red zone the System V AMD64 ABI reserves below the user stack pointer */

#define X86_64_ABI_RED_ZONE 128

/****************************************************************************
* Private Types
****************************************************************************/
Expand Down Expand Up @@ -247,16 +255,24 @@ uint64_t *x86_64_syscall(uint64_t *regs)
{
uint64_t usp;

/* Copy "info" into user stack */
/* Save the kernel stack pointer to restore on handler
* return
*/

usp = rtcb->xcp.saved_ursp - 8;
rtcb->xcp.kstkptr = (uintptr_t *)regs[REG_RSP];

/* Create a frame for info and copy the kernel info */
/* Create a 16 byte aligned frame for info below the red
* zone of the interrupted user code
*/

usp = usp - sizeof(siginfo_t);
usp = (rtcb->xcp.saved_ursp - X86_64_ABI_RED_ZONE -
sizeof(siginfo_t)) & ~0x0f;
memcpy((void *)usp, (void *)regs[REG_RSI], sizeof(siginfo_t));

/* Now set the updated SP and user copy of "info" to RSI */
/* Set the new SP and the user copy of "info" to RSI.
* The naked trampoline is entered with SP 16 byte
* aligned; its call provides the return address slot.
*/

regs[REG_RSP] = usp;
regs[REG_RSI] = usp;
Expand Down Expand Up @@ -290,12 +306,21 @@ uint64_t *x86_64_syscall(uint64_t *regs)
DEBUGASSERT(rtcb->xcp.sigreturn != 0);

regs[REG_RCX] = rtcb->xcp.sigreturn;
regs[REG_RSP] = rtcb->xcp.saved_rsp;
rtcb->xcp.sigreturn = 0;

/* For kernel mode, we should be already on a correct kernel stack
* which was recovered in x86_64_syscall_entry.
*/
#ifdef CONFIG_ARCH_KERNEL_STACK
if (rtcb->xcp.kstack != NULL)
{
/* Return to the kernel stack saved at dispatch */

regs[REG_RSP] = (uint64_t)rtcb->xcp.kstkptr;
rtcb->xcp.kstkptr = rtcb->xcp.ktopstk;
}
else
#endif
{
regs[REG_RSP] = rtcb->xcp.saved_rsp;
}

break;
}
Expand Down
21 changes: 19 additions & 2 deletions arch/x86_64/src/intel64/intel64_schedulesigaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@

void up_schedule_sigaction(struct tcb_s *tcb)
{
uint64_t sp = tcb->xcp.regs[REG_RSP];

sinfo("tcb=%p, rtcb=%p current_regs=%p\n", tcb,
this_task(), this_task()->xcp.regs);

Expand All @@ -83,14 +85,29 @@ void up_schedule_sigaction(struct tcb_s *tcb)
*/

tcb->xcp.saved_rip = tcb->xcp.regs[REG_RIP];
tcb->xcp.saved_rsp = tcb->xcp.regs[REG_RSP];
tcb->xcp.saved_rsp = sp;
tcb->xcp.saved_rflags = tcb->xcp.regs[REG_RFLAGS];

/* Then set up to vector to the trampoline with interrupts
* disabled
*/

tcb->xcp.regs[REG_RIP] = (uint64_t)x86_64_sigdeliver;
tcb->xcp.regs[REG_RSP] = tcb->xcp.regs[REG_RSP] - 8;
tcb->xcp.regs[REG_RFLAGS] = 0;

#ifdef CONFIG_ARCH_KERNEL_STACK
/* Run the trampoline on the thread kernel stack when the thread was
* interrupted in user mode: the signal handler runs on the user
* stack and would overwrite the trampoline frame there.
*/

if (tcb->xcp.kstack != NULL &&
(sp < (uint64_t)tcb->xcp.kstack || sp > (uint64_t)tcb->xcp.ktopstk))
{
tcb->xcp.saved_ursp = sp;
sp = (uint64_t)tcb->xcp.ktopstk;
}
#endif

tcb->xcp.regs[REG_RSP] = sp - 8;
}
Loading