1
0
Fork 0
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:
Stefan Lankes 2016-09-10 09:59:18 +02:00
parent 5c8b3d97e3
commit 6a7ae04d2e
6 changed files with 222 additions and 3 deletions

View file

@ -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

View file

@ -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

View file

@ -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:

View 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;
}

View file

@ -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