mirror of
https://github.com/hermitcore/libhermit.git
synced 2025-03-09 00:00:03 +01:00
add basic support to save / restore the user thread context
- currently, signal handling is ignored!
This commit is contained in:
parent
5c8b3d97e3
commit
6a7ae04d2e
6 changed files with 222 additions and 3 deletions
|
@ -114,7 +114,39 @@ typedef unsigned short wchar_t;
|
|||
typedef wchar_t wint_t;
|
||||
#endif
|
||||
|
||||
/// This defines what the stack looks like after the task context is saved.
|
||||
/// This defines registers, which are saved for a "user-level" context swicth
|
||||
typedef struct mregs {
|
||||
/// R15 register
|
||||
uint64_t r15;
|
||||
/// R14 register
|
||||
uint64_t r14;
|
||||
/// R13 register
|
||||
uint64_t r13;
|
||||
/// R12 register
|
||||
uint64_t r12;
|
||||
/// R9 register
|
||||
uint64_t r9;
|
||||
/// R8 register
|
||||
uint64_t r8;
|
||||
/// RDI register
|
||||
uint64_t rdi;
|
||||
/// RSI register
|
||||
uint64_t rsi;
|
||||
/// RBP register
|
||||
uint64_t rbp;
|
||||
/// RBX register
|
||||
uint64_t rbx;
|
||||
/// RDX register
|
||||
uint64_t rdx;
|
||||
/// RCX register
|
||||
uint64_t rcx;
|
||||
/// RSP register
|
||||
uint64_t rsp;
|
||||
/// RIP
|
||||
uint64_t rip;
|
||||
} mregs_t;
|
||||
|
||||
/// This defines what the stack looks like after the task context is saved
|
||||
struct state {
|
||||
/// GS register
|
||||
uint64_t gs;
|
||||
|
@ -165,6 +197,12 @@ struct state {
|
|||
uint64_t ss;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
void *ss_sp; /* Stack base or pointer. */
|
||||
int ss_flags; /* Flags. */
|
||||
size_t ss_size; /* Stack size. */
|
||||
} stack_t;
|
||||
|
||||
const int32_t is_single_kernel(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
C_source := irq.c idt.c isrs.c gdt.c processor.c timer.c tasks.c apic.c pci.c vga.c uart.c
|
||||
C_source := irq.c idt.c isrs.c gdt.c processor.c timer.c tasks.c apic.c pci.c vga.c uart.c syscall.c
|
||||
ASM_source := entry.asm string.asm
|
||||
MODULE := arch_x86_kernel
|
||||
|
||||
|
|
|
@ -493,6 +493,79 @@ isrsyscall:
|
|||
o64 sysret
|
||||
%endif
|
||||
|
||||
extern save_fpu_state
|
||||
global getcontext
|
||||
align 64
|
||||
getcontext:
|
||||
cli
|
||||
; save general purpose regsiters
|
||||
mov QWORD [rdi + 0x00], r15
|
||||
mov QWORD [rdi + 0x08], r14
|
||||
mov QWORD [rdi + 0x10], r13
|
||||
mov QWORD [rdi + 0x18], r12
|
||||
mov QWORD [rdi + 0x20], r9
|
||||
mov QWORD [rdi + 0x28], r8
|
||||
mov QWORD [rdi + 0x30], rdi
|
||||
mov QWORD [rdi + 0x38], rsi
|
||||
mov QWORD [rdi + 0x40], rbp
|
||||
mov QWORD [rdi + 0x48], rbx
|
||||
mov QWORD [rdi + 0x50], rdx
|
||||
mov QWORD [rdi + 0x58], rcx
|
||||
lea rax, [rsp + 0x08]
|
||||
mov QWORD [rdi + 0x60], rax
|
||||
mov rax, QWORD [rsp]
|
||||
mov QWORD [rdi + 0x68], rax
|
||||
; restore FPU state
|
||||
add rdi, 0x80
|
||||
call [save_fpu_state]
|
||||
sub rdi, 0x80
|
||||
xor rax, rax
|
||||
sti
|
||||
ret
|
||||
|
||||
extern restore_fpu_state
|
||||
global setcontext
|
||||
align 64
|
||||
setcontext:
|
||||
cli
|
||||
; restore FPU state
|
||||
add rdi, 0x80
|
||||
call [restore_fpu_state]
|
||||
sub rdi, 0x80
|
||||
; restore general purpose registers
|
||||
mov r15, QWORD [rdi + 0x00]
|
||||
mov r14, QWORD [rdi + 0x08]
|
||||
mov r13, QWORD [rdi + 0x10]
|
||||
mov r12, QWORD [rdi + 0x18]
|
||||
mov r9, QWORD [rdi + 0x20]
|
||||
mov r8, QWORD [rdi + 0x28]
|
||||
mov rdi, QWORD [rdi + 0x30]
|
||||
mov rsi, QWORD [rdi + 0x38]
|
||||
mov rbp, QWORD [rdi + 0x40]
|
||||
mov rbx, QWORD [rdi + 0x48]
|
||||
mov rdx, QWORD [rdi + 0x50]
|
||||
mov rcx, QWORD [rdi + 0x58]
|
||||
mov rsp, QWORD [rdi + 0x60]
|
||||
push QWORD [rdi + 0x68]
|
||||
xor rax, rax
|
||||
sti
|
||||
ret
|
||||
|
||||
global __startcontext
|
||||
align 64
|
||||
__startcontext:
|
||||
mov rsp, rbx
|
||||
pop rdi
|
||||
cmp rdi, 0
|
||||
je Lno_context
|
||||
|
||||
call setcontext
|
||||
|
||||
Lno_context:
|
||||
extern exit
|
||||
call exit
|
||||
jmp $
|
||||
|
||||
global switch_context
|
||||
align 64
|
||||
switch_context:
|
||||
|
|
98
hermit/arch/x86/kernel/syscall.c
Normal file
98
hermit/arch/x86/kernel/syscall.c
Normal file
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Stefan Lankes, RWTH Aachen University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <hermit/stddef.h>
|
||||
#include <hermit/stdio.h>
|
||||
#include <hermit/tasks.h>
|
||||
#include <hermit/errno.h>
|
||||
#include <hermit/syscall.h>
|
||||
|
||||
void __startcontext(void);
|
||||
|
||||
void makecontext(ucontext_t *ucp, void (*func)(), int argc, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (BUILTIN_EXPECT(!ucp, 0))
|
||||
return;
|
||||
|
||||
//kprintf("sys_makecontext %p, func %p, stack 0x%zx, task %d\n", ucp, func, ucp->uc_stack.ss_sp, per_core(current_task)->id);
|
||||
|
||||
size_t* stack = (size_t*) (ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
|
||||
stack -= (argc > 6 ? argc - 6 : 0) + 1;
|
||||
uint32_t idx = (argc > 6 ? argc - 6 : 0) + 1;
|
||||
|
||||
/* Align stack and reserve space for trampoline address. */
|
||||
stack = (size_t*) ((((size_t) stack) & ~0xFULL) - 0x8);
|
||||
|
||||
/* Setup context */
|
||||
ucp->uc_mregs.rip = (size_t) func;
|
||||
ucp->uc_mregs.rbx = (size_t) &stack[idx];
|
||||
ucp->uc_mregs.rsp = (size_t) stack;
|
||||
|
||||
stack[0] = (size_t) &__startcontext;
|
||||
stack[idx] = (size_t) ucp->uc_link; // link to the next context
|
||||
|
||||
va_start(ap, argc);
|
||||
for (int i = 0; i < argc; i++)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
ucp->uc_mregs.rdi = va_arg(ap, size_t);
|
||||
break;
|
||||
case 1:
|
||||
ucp->uc_mregs.rsi = va_arg(ap, size_t);
|
||||
break;
|
||||
case 2:
|
||||
ucp->uc_mregs.rdx = va_arg(ap, size_t);
|
||||
break;
|
||||
case 3:
|
||||
ucp->uc_mregs.rcx = va_arg(ap, size_t);
|
||||
break;
|
||||
case 4:
|
||||
ucp->uc_mregs.r8 = va_arg(ap, size_t);
|
||||
break;
|
||||
case 5:
|
||||
ucp->uc_mregs.r9 = va_arg(ap, size_t);
|
||||
break;
|
||||
default:
|
||||
/* copy value on stack */
|
||||
stack[i - 5] = va_arg(ap, size_t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
int swapcontext(ucontext_t *oucp, const ucontext_t *ucp)
|
||||
{
|
||||
//TODO: implementation is missing
|
||||
|
||||
kprintf("WARNING: sys_swapcontext is currently not implemented: %p <=> %p\n", oucp, ucp);
|
||||
return -ENOSYS;
|
||||
}
|
|
@ -93,6 +93,16 @@ void sys_yield(void);
|
|||
int sys_kill(tid_t dest, int signum);
|
||||
int sys_signal(signal_handler_t handler);
|
||||
|
||||
typedef struct ucontext {
|
||||
mregs_t uc_mregs;
|
||||
union fpu_state uc_fpu;
|
||||
struct ucontext *uc_link;
|
||||
stack_t uc_stack;
|
||||
} ucontext_t;
|
||||
|
||||
void makecontext(ucontext_t *ucp, void (*func)(), int argc, ...);
|
||||
int swapcontext(ucontext_t *oucp, const ucontext_t *ucp);
|
||||
|
||||
#define __NR_exit 0
|
||||
#define __NR_write 1
|
||||
#define __NR_open 2
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit d3539f7d58c1ae43acdd4e67b845103dfcae36c7
|
||||
Subproject commit ba4dae88bdc2fda079fc96cf70e7b238282229ca
|
Loading…
Add table
Reference in a new issue