Skip to content

Commit

Permalink
usermode: support int 80h syscalls
Browse files Browse the repository at this point in the history
From usermode's perspective it works the same as syscall.

Signed-off-by: Johannes Wikner <[email protected]>
Signed-off-by: Pawel Wieczorkiewicz <[email protected]>
  • Loading branch information
sktt committed Aug 30, 2023
1 parent eec2373 commit e9b57fd
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 4 deletions.
18 changes: 18 additions & 0 deletions arch/x86/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,24 @@ ENTRY(sysenter_handler_entry)

SYSEXIT
END_FUNC(sysenter_handler_entry)

ENTRY(int80_handler_entry)
SAVE_ALL_REGS
syscall_from_usermode

MASK_USER_FLAGS

cmp $SYSCALL_EXIT, %_ASM_AX
jz syscall_exit

mov %_ASM_DI, %_ASM_CX
mov %_ASM_AX, %_ASM_DI
call syscall_handler

syscall_to_usermode
RESTORE_ALL_REGS
IRET
END_FUNC(int80_handler_entry)
GLOBAL(end_usermode_helpers)

SECTION(.text.user, "ax", 16)
Expand Down
26 changes: 23 additions & 3 deletions common/usermode.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <pagetable.h>
#include <percpu.h>
#include <processor.h>
#include <traps.h>
#include <usermode.h>

extern char exception_handlers[], end_exception_handlers[];
Expand Down Expand Up @@ -111,6 +112,25 @@ void init_usermode(percpu_t *percpu) {

init_syscall();
init_sysenter(percpu);
set_intr_gate(&percpu->idt[SYSCALL_INT], __KERN_CS, _ul(int80_handler_entry),
GATE_DPL3, GATE_PRESENT, 0);
}

static inline long __user_text _int80(long syscall_nr, long arg1, long arg2, long arg3,
long arg4, long arg5) {
register long return_code asm(STR(_ASM_AX));
register long _arg4 asm("r8") = arg4;
register long _arg5 asm("r9") = arg5;

/* clang-format off */
asm volatile(
"int $" STR(SYSCALL_INT) "\n"
: "=a"(return_code)
: "0"(syscall_nr), "S"(arg1), "d"(arg2), "D" (arg3), "r"(_arg4), "r"(_arg5)
);
/* clang-format on */

return return_code;
}

static inline long __user_text _syscall(long syscall_nr, long arg1, long arg2, long arg3,
Expand Down Expand Up @@ -156,7 +176,7 @@ static inline long __user_text _sysenter(long syscall_nr, long arg1, long arg2,
static __user_data syscall_mode_t sc_mode = SYSCALL_MODE_SYSCALL;

bool __user_text syscall_mode(syscall_mode_t mode) {
if (mode > SYSCALL_MODE_INT) {
if (mode > SYSCALL_MODE_INT80) {
return false;
}
sc_mode = mode;
Expand All @@ -171,8 +191,8 @@ static long __user_text syscall(long syscall_nr, long arg1, long arg2, long arg3
return _syscall(syscall_nr, arg1, arg2, arg3, arg4, arg5);
case SYSCALL_MODE_SYSENTER:
return _sysenter(syscall_nr, arg1, arg2, arg3, arg4, arg5);
case SYSCALL_MODE_INT:
// unimplemented
case SYSCALL_MODE_INT80:
return _int80(syscall_nr, arg1, arg2, arg3, arg4, arg5);
default:
UNREACHABLE();
}
Expand Down
2 changes: 2 additions & 0 deletions include/arch/x86/traps.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@

#define MAX_INT 256

#define SYSCALL_INT 0x80

#ifndef __ASSEMBLY__
#include <cpu.h>

Expand Down
3 changes: 2 additions & 1 deletion include/usermode.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
enum syscall_mode {
SYSCALL_MODE_SYSCALL, // use SYSCALL
SYSCALL_MODE_SYSENTER, // use SYSENTER
SYSCALL_MODE_INT, // TODO: use INT $SYSVEC
SYSCALL_MODE_INT80, // use INT 0x80
};
typedef enum syscall_mode syscall_mode_t;

Expand All @@ -57,6 +57,7 @@ static inline bool enter_from_usermode(uint16_t cs) {
extern unsigned long enter_usermode(task_func_t fn, void *fn_arg, void *user_stack);
extern void syscall_handler_entry(void);
extern void sysenter_handler_entry(void);
extern void int80_handler_entry(void);

extern void init_usermode(percpu_t *percpu);

Expand Down

0 comments on commit e9b57fd

Please sign in to comment.