Skip to content

Commit

Permalink
usermode: add exit system call
Browse files Browse the repository at this point in the history
The exit system call has index 0. It is used by usermode_stub() to exit
back to kernel, when user task is finished.

Signed-off-by: Pawel Wieczorkiewicz <[email protected]>
  • Loading branch information
wipawel committed Jul 22, 2022
1 parent c9a195d commit 874ff2f
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 15 deletions.
5 changes: 4 additions & 1 deletion arch/x86/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,10 @@ ENTRY(usermode_stub)
xchg %_ASM_DI, %_ASM_SI
call *%_ASM_SI

int $X86_RET2KERN_INT
/* sys_exit */
mov %_ASM_AX, %_ASM_DI
xor %_ASM_AX, %_ASM_AX
syscall
END_FUNC(usermode_stub)

SECTION(.data.rmode, "aw", 16)
Expand Down
12 changes: 0 additions & 12 deletions arch/x86/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,6 @@ extern void asm_interrupt_handler_uart(void);
extern void asm_interrupt_handler_keyboard(void);
extern void asm_interrupt_handler_timer(void);

static void ret2kern_handler(void) {
/* clang-format off */
asm volatile("mov %%gs:%[sp], %%" STR(_ASM_SP) "\n"
"POPF \n"
:: [ sp ] "m"(ACCESS_ONCE(PERCPU_VAR(usermode_private))));
/* clang-format on */
}

static void init_tss(percpu_t *percpu) {
#if defined(__i386__)
percpu->tss_df.iopb = sizeof(percpu->tss_df);
Expand Down Expand Up @@ -155,10 +147,6 @@ void init_traps(const cpu_t *cpu) {
set_intr_gate(&percpu->idt[X86_EX_DF], __KERN_CS, _ul(entry_DF), GATE_DPL0, GATE_PRESENT, 1);
#endif

/* User mode return to kernel handler */
set_intr_gate(&percpu->idt[X86_RET2KERN_INT], __KERN_CS, _ul(ret2kern_handler), GATE_DPL3, GATE_PRESENT, 0);
/* clang-format on */

set_intr_gate(&percpu->idt[COM1_IRQ0_OFFSET], __KERN_CS,
_ul(asm_interrupt_handler_uart), GATE_DPL0, GATE_PRESENT, 0);
set_intr_gate(&percpu->idt[COM2_IRQ0_OFFSET], __KERN_CS,
Expand Down
61 changes: 61 additions & 0 deletions common/usermode.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,15 @@ static inline long syscall_return(long return_code) {
return ret;
}

static inline void stack_switch(void) {
/* clang-format off */
asm volatile(
"xchg %%gs:%[private], %%" STR(_ASM_SP) "\n"
::[private] "m"(ACCESS_ONCE(PERCPU_VAR(usermode_private)))
);
/* clang-format on */
}

static inline void switch_address_space(const cr3_t *cr3) {
/* clang-format off */
asm volatile(
Expand All @@ -65,7 +74,49 @@ static inline void switch_address_space(const cr3_t *cr3) {
/* clang-format on */
}

static inline void _sys_exit(void) {
/* clang-format off */
asm volatile (
"mov %%" STR(_ASM_DI)", %%gs:%[private]\n"
POPF()
RESTORE_ALL_REGS()
"mov %%gs:%[private], %%" STR(_ASM_AX) "\n"
"ret\n"
:: [ private ] "m"(ACCESS_ONCE(PERCPU_VAR(usermode_private)))
: STR(_ASM_AX)
);
/* clang-format on */
}

void __naked syscall_handler(void) {
register unsigned long syscall_nr asm(STR(_ASM_AX));
register unsigned long param1 asm(STR(_ASM_DI));
(void) param1;
asm volatile(SAVE_CLOBBERED_REGS():::);
switch_address_space(&cr3);
swapgs();
stack_switch();
syscall_save();

switch (syscall_nr) {
case SYSCALL_EXIT:
syscall_restore();
_sys_exit();
UNREACHABLE();

default:
printk("Unknown syscall: %lu\n", syscall_nr);
syscall_return(-1L);
break;
}

syscall_restore();
stack_switch();
swapgs();
switch_address_space(&user_cr3);

asm volatile(RESTORE_CLOBBERED_REGS():::);

sysret();
}

Expand All @@ -92,5 +143,15 @@ static void init_syscall(void) {
void init_usermode(percpu_t *percpu) {
vmap_user_4k(&cr3, virt_to_mfn(&cr3), L1_PROT);
vmap_user_4k(&enter_usermode, virt_to_mfn(&enter_usermode), L1_PROT);
vmap_user_4k(&syscall_handler, virt_to_mfn(&syscall_handler), L1_PROT);

init_syscall();
}

static inline void __user_text sys_exit(unsigned long exit_code) {
asm volatile("syscall" ::"A"(SYSCALL_EXIT), "D"(exit_code) : STR(_ASM_CX), "r11");
}

void __user_text exit(unsigned long exit_code) {
sys_exit(exit_code);
}
2 changes: 0 additions & 2 deletions include/arch/x86/traps.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@

#define MAX_INT 256

#define X86_RET2KERN_INT 32

#ifndef __ASSEMBLY__
#include <cpu.h>

Expand Down
3 changes: 3 additions & 0 deletions include/usermode.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#ifndef KTF_USERMODE_H
#define KTF_USERMODE_H

#define SYSCALL_EXIT 0

#ifndef __ASSEMBLY__
#include <percpu.h>
#include <sched.h>
Expand All @@ -43,6 +45,7 @@ extern void __naked syscall_handler(void);

extern void init_usermode(percpu_t *percpu);

extern void __user_text exit(unsigned long exit_code);
#endif /* __ASSEMBLY__ */

#endif /* KTF_USERMODE_H */

0 comments on commit 874ff2f

Please sign in to comment.