forked from Bananymous/banan-os
Kernel/Userspace: Start initial work on userspace and syscalls
This commit is contained in:
parent
af854ec9e1
commit
8b8e3cbbf0
|
@ -58,9 +58,11 @@ kernel/SpinLock.o \
|
||||||
kernel/SSP.o \
|
kernel/SSP.o \
|
||||||
kernel/Storage/ATAController.o \
|
kernel/Storage/ATAController.o \
|
||||||
kernel/Storage/StorageDevice.o \
|
kernel/Storage/StorageDevice.o \
|
||||||
|
kernel/Syscall.o \
|
||||||
kernel/Thread.o \
|
kernel/Thread.o \
|
||||||
kernel/TTY.o \
|
kernel/TTY.o \
|
||||||
kernel/VesaTerminalDriver.o \
|
kernel/VesaTerminalDriver.o \
|
||||||
|
userspace/userspace.o \
|
||||||
icxxabi.o \
|
icxxabi.o \
|
||||||
ubsan.o \
|
ubsan.o \
|
||||||
|
|
||||||
|
@ -109,6 +111,7 @@ always:
|
||||||
mkdir -p $(BUILDDIR)/kernel
|
mkdir -p $(BUILDDIR)/kernel
|
||||||
mkdir -p $(BUILDDIR)/kernel/FS
|
mkdir -p $(BUILDDIR)/kernel/FS
|
||||||
mkdir -p $(BUILDDIR)/kernel/Storage
|
mkdir -p $(BUILDDIR)/kernel/Storage
|
||||||
|
mkdir -p $(BUILDDIR)/userspace
|
||||||
mkdir -p $(BUILDDIR)/font
|
mkdir -p $(BUILDDIR)/font
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|
|
@ -152,6 +152,29 @@ found:
|
||||||
"iret;"
|
"iret;"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
extern "C" void syscall_asm();
|
||||||
|
asm(
|
||||||
|
".global syscall_asm;"
|
||||||
|
"syscall_asm:"
|
||||||
|
"pusha;"
|
||||||
|
"pushw %ds;"
|
||||||
|
"pushw %es;"
|
||||||
|
"pushw %ss;"
|
||||||
|
"pushw %ss;"
|
||||||
|
"popw %ds;"
|
||||||
|
"popw %es;"
|
||||||
|
"pushl %edx;"
|
||||||
|
"pushl %ecx;"
|
||||||
|
"pushl %ebx;"
|
||||||
|
"pushl %eax;"
|
||||||
|
"call cpp_syscall_handler;"
|
||||||
|
"addl $16, %esp;"
|
||||||
|
"popw %es;"
|
||||||
|
"popw %ds;"
|
||||||
|
"popa;"
|
||||||
|
"iret;"
|
||||||
|
);
|
||||||
|
|
||||||
static void flush_idt()
|
static void flush_idt()
|
||||||
{
|
{
|
||||||
asm volatile("lidt %0"::"m"(s_idtr));
|
asm volatile("lidt %0"::"m"(s_idtr));
|
||||||
|
@ -175,6 +198,12 @@ found:
|
||||||
flush_idt();
|
flush_idt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void register_syscall_handler(uint8_t offset, void(*handler)())
|
||||||
|
{
|
||||||
|
register_interrupt_handler(offset, handler);
|
||||||
|
s_idt[offset].DPL = 3;
|
||||||
|
}
|
||||||
|
|
||||||
void initialize()
|
void initialize()
|
||||||
{
|
{
|
||||||
constexpr size_t idt_size = 0x100 * sizeof(GateDescriptor);
|
constexpr size_t idt_size = 0x100 * sizeof(GateDescriptor);
|
||||||
|
@ -219,6 +248,8 @@ found:
|
||||||
REGISTER_HANDLER(0x1E);
|
REGISTER_HANDLER(0x1E);
|
||||||
REGISTER_HANDLER(0x1F);
|
REGISTER_HANDLER(0x1F);
|
||||||
|
|
||||||
|
register_syscall_handler(0x80, syscall_asm);
|
||||||
|
|
||||||
flush_idt();
|
flush_idt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,9 @@ SECTIONS
|
||||||
}
|
}
|
||||||
.rodata BLOCK(4K) : ALIGN(4K)
|
.rodata BLOCK(4K) : ALIGN(4K)
|
||||||
{
|
{
|
||||||
*(.rodata)
|
g_rodata_start = .;
|
||||||
|
*(.rodata.*)
|
||||||
|
g_rodata_end = .;
|
||||||
}
|
}
|
||||||
.data BLOCK(4K) : ALIGN(4K)
|
.data BLOCK(4K) : ALIGN(4K)
|
||||||
{
|
{
|
||||||
|
@ -24,4 +26,13 @@ SECTIONS
|
||||||
}
|
}
|
||||||
|
|
||||||
g_kernel_end = .;
|
g_kernel_end = .;
|
||||||
|
|
||||||
|
. = 0x00A00000;
|
||||||
|
|
||||||
|
g_userspace_start = .;
|
||||||
|
.userspace BLOCK(4K) : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.userspace)
|
||||||
|
}
|
||||||
|
g_userspace_end = .;
|
||||||
}
|
}
|
|
@ -148,6 +148,12 @@ namespace IDT
|
||||||
descriptor.flags = 0x8E;
|
descriptor.flags = 0x8E;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void register_syscall_handler(uint8_t index, void(*handler)())
|
||||||
|
{
|
||||||
|
register_interrupt_handler(index, handler);
|
||||||
|
s_idt[index].flags = 0xEE;
|
||||||
|
}
|
||||||
|
|
||||||
void register_irq_handler(uint8_t irq, void(*handler)())
|
void register_irq_handler(uint8_t irq, void(*handler)())
|
||||||
{
|
{
|
||||||
s_irq_handlers[irq] = handler;
|
s_irq_handlers[irq] = handler;
|
||||||
|
@ -203,6 +209,8 @@ namespace IDT
|
||||||
extern "C" void irq14();
|
extern "C" void irq14();
|
||||||
extern "C" void irq15();
|
extern "C" void irq15();
|
||||||
|
|
||||||
|
extern "C" void syscall_asm();
|
||||||
|
|
||||||
void initialize()
|
void initialize()
|
||||||
{
|
{
|
||||||
s_idt = (GateDescriptor*)kmalloc(0x100 * sizeof(GateDescriptor));
|
s_idt = (GateDescriptor*)kmalloc(0x100 * sizeof(GateDescriptor));
|
||||||
|
@ -262,6 +270,8 @@ namespace IDT
|
||||||
REGISTER_IRQ_HANDLER(14);
|
REGISTER_IRQ_HANDLER(14);
|
||||||
REGISTER_IRQ_HANDLER(15);
|
REGISTER_IRQ_HANDLER(15);
|
||||||
|
|
||||||
|
register_syscall_handler(0x80, syscall_asm);
|
||||||
|
|
||||||
flush_idt();
|
flush_idt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,23 @@
|
||||||
popq %rax
|
popq %rax
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
.macro popaq_no_rax
|
||||||
|
popq %r15
|
||||||
|
popq %r14
|
||||||
|
popq %r13
|
||||||
|
popq %r12
|
||||||
|
popq %r11
|
||||||
|
popq %r10
|
||||||
|
popq %r9
|
||||||
|
popq %r8
|
||||||
|
popq %rsi
|
||||||
|
popq %rdi
|
||||||
|
popq %rbp
|
||||||
|
popq %rdx
|
||||||
|
popq %rcx
|
||||||
|
popq %rbx
|
||||||
|
.endm
|
||||||
|
|
||||||
isr_stub:
|
isr_stub:
|
||||||
pushaq
|
pushaq
|
||||||
|
|
||||||
|
@ -138,3 +155,15 @@ irq 12
|
||||||
irq 13
|
irq 13
|
||||||
irq 14
|
irq 14
|
||||||
irq 15
|
irq 15
|
||||||
|
|
||||||
|
.global syscall_asm
|
||||||
|
syscall_asm:
|
||||||
|
cli
|
||||||
|
pushaq
|
||||||
|
movq %rax, %rdi
|
||||||
|
movq %rbx, %rsi
|
||||||
|
xchgq %rcx, %rdx
|
||||||
|
call cpp_syscall_handler
|
||||||
|
popaq_no_rax
|
||||||
|
addq $8, %rsp
|
||||||
|
iretq
|
|
@ -11,7 +11,9 @@ SECTIONS
|
||||||
}
|
}
|
||||||
.rodata BLOCK(4K) : ALIGN(4K)
|
.rodata BLOCK(4K) : ALIGN(4K)
|
||||||
{
|
{
|
||||||
*(.rodata)
|
g_rodata_start = .;
|
||||||
|
*(.rodata.*)
|
||||||
|
g_rodata_end = .;
|
||||||
}
|
}
|
||||||
.data BLOCK(4K) : ALIGN(4K)
|
.data BLOCK(4K) : ALIGN(4K)
|
||||||
{
|
{
|
||||||
|
@ -22,6 +24,15 @@ SECTIONS
|
||||||
*(COMMON)
|
*(COMMON)
|
||||||
*(.bss)
|
*(.bss)
|
||||||
}
|
}
|
||||||
|
|
||||||
g_kernel_end = .;
|
g_kernel_end = .;
|
||||||
|
|
||||||
|
. = 0x00A00000;
|
||||||
|
|
||||||
|
g_userspace_start = .;
|
||||||
|
.userspace BLOCK(4K) : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.userspace)
|
||||||
|
}
|
||||||
|
g_userspace_end = .;
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define SYS_TEST 0
|
||||||
|
#define SYS_PUTC 1
|
|
@ -0,0 +1,44 @@
|
||||||
|
#include <kernel/Debug.h>
|
||||||
|
#include <kernel/kprint.h>
|
||||||
|
#include <kernel/Syscall.h>
|
||||||
|
|
||||||
|
namespace Kernel
|
||||||
|
{
|
||||||
|
|
||||||
|
int sys_test()
|
||||||
|
{
|
||||||
|
dprintln("hello");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sys_putc(void* ch)
|
||||||
|
{
|
||||||
|
kprint("{}", (char)(uintptr_t)ch);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int cpp_syscall_handler(int syscall, void* arg1, void* arg2, void* arg3)
|
||||||
|
{
|
||||||
|
(void)arg1;
|
||||||
|
(void)arg2;
|
||||||
|
(void)arg3;
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
switch (syscall)
|
||||||
|
{
|
||||||
|
case SYS_TEST:
|
||||||
|
ret = sys_test();
|
||||||
|
break;
|
||||||
|
case SYS_PUTC:
|
||||||
|
ret = sys_putc(arg1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = -1;
|
||||||
|
dprintln("Unknown syscall");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <kernel/Arch.h>
|
||||||
#include <kernel/Debug.h>
|
#include <kernel/Debug.h>
|
||||||
#include <kernel/FS/VirtualFileSystem.h>
|
#include <kernel/FS/VirtualFileSystem.h>
|
||||||
#include <kernel/GDT.h>
|
#include <kernel/GDT.h>
|
||||||
|
@ -14,6 +15,7 @@
|
||||||
#include <kernel/Scheduler.h>
|
#include <kernel/Scheduler.h>
|
||||||
#include <kernel/Serial.h>
|
#include <kernel/Serial.h>
|
||||||
#include <kernel/Shell.h>
|
#include <kernel/Shell.h>
|
||||||
|
#include <kernel/Syscall.h>
|
||||||
#include <kernel/TTY.h>
|
#include <kernel/TTY.h>
|
||||||
#include <kernel/VesaTerminalDriver.h>
|
#include <kernel/VesaTerminalDriver.h>
|
||||||
|
|
||||||
|
@ -75,6 +77,14 @@ namespace BAN::Formatter
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" uintptr_t g_rodata_start;
|
||||||
|
extern "C" uintptr_t g_rodata_end;
|
||||||
|
|
||||||
|
extern "C" uintptr_t g_userspace_start;
|
||||||
|
extern "C" uintptr_t g_userspace_end;
|
||||||
|
|
||||||
|
extern void userspace_entry();
|
||||||
|
|
||||||
extern "C" void kernel_main()
|
extern "C" void kernel_main()
|
||||||
{
|
{
|
||||||
using namespace Kernel;
|
using namespace Kernel;
|
||||||
|
@ -124,6 +134,50 @@ extern "C" void kernel_main()
|
||||||
|
|
||||||
MUST(Scheduler::initialize());
|
MUST(Scheduler::initialize());
|
||||||
Scheduler& scheduler = Scheduler::get();
|
Scheduler& scheduler = Scheduler::get();
|
||||||
|
#if 1
|
||||||
|
MUST(scheduler.add_thread(MUST(Thread::create(
|
||||||
|
[] (void*)
|
||||||
|
{
|
||||||
|
MMU::get().allocate_range((uintptr_t)&g_userspace_start, (uintptr_t)&g_userspace_end - (uintptr_t)&g_userspace_start, MMU::Flags::UserSupervisor | MMU::Flags::Present);
|
||||||
|
MMU::get().allocate_range((uintptr_t)&g_rodata_start, (uintptr_t)&g_rodata_end - (uintptr_t)&g_rodata_start, MMU::Flags::UserSupervisor | MMU::Flags::Present);
|
||||||
|
|
||||||
|
void* userspace_stack = kmalloc(4096, 4096);
|
||||||
|
ASSERT(userspace_stack);
|
||||||
|
MMU::get().allocate_page((uintptr_t)userspace_stack, MMU::Flags::UserSupervisor | MMU::Flags::ReadWrite | MMU::Flags::Present);
|
||||||
|
|
||||||
|
BOCHS_BREAK();
|
||||||
|
|
||||||
|
#if ARCH(x86_64)
|
||||||
|
asm volatile(
|
||||||
|
"pushq %0;"
|
||||||
|
"pushq %1;"
|
||||||
|
"pushfq;"
|
||||||
|
"pushq %2;"
|
||||||
|
"pushq %3;"
|
||||||
|
"iretq;"
|
||||||
|
:: "r"((uintptr_t)0x20 | 3), "r"((uintptr_t)userspace_stack + 4096), "r"((uintptr_t)0x18 | 3), "r"(userspace_entry)
|
||||||
|
);
|
||||||
|
#else
|
||||||
|
asm volatile(
|
||||||
|
"movl %0, %%eax;"
|
||||||
|
"movw %%ax, %%ds;"
|
||||||
|
"movw %%ax, %%es;"
|
||||||
|
"movw %%ax, %%fs;"
|
||||||
|
"movw %%ax, %%gs;"
|
||||||
|
|
||||||
|
"movl %1, %%esp;"
|
||||||
|
"pushl %0;"
|
||||||
|
"pushl %1;"
|
||||||
|
"pushfl;"
|
||||||
|
"pushl %2;"
|
||||||
|
"pushl %3;"
|
||||||
|
"iret;"
|
||||||
|
:: "r"((uintptr_t)0x20 | 3), "r"((uintptr_t)userspace_stack + 4096), "r"((uintptr_t)0x18 | 3), "r"(userspace_entry)
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
))));
|
||||||
|
#else
|
||||||
MUST(scheduler.add_thread(MUST(Thread::create(
|
MUST(scheduler.add_thread(MUST(Thread::create(
|
||||||
[](void* terminal_driver)
|
[](void* terminal_driver)
|
||||||
{
|
{
|
||||||
|
@ -144,6 +198,7 @@ extern "C" void kernel_main()
|
||||||
shell->run();
|
shell->run();
|
||||||
}, tty1
|
}, tty1
|
||||||
))));
|
))));
|
||||||
|
#endif
|
||||||
scheduler.start();
|
scheduler.start();
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
}
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
#include <BAN/Formatter.h>
|
||||||
|
#include <kernel/Syscall.h>
|
||||||
|
|
||||||
|
#define USERSPACE __attribute__((section(".userspace")))
|
||||||
|
|
||||||
|
USERSPACE int syscall(int syscall, void* arg1 = nullptr, void* arg2 = nullptr, void* arg3 = nullptr)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
asm volatile("int $0x80" : "=a"(ret) : "a"(syscall), "b"(arg1), "c"(arg2), "d"(arg3) : "memory");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
USERSPACE void user_putc(char ch)
|
||||||
|
{
|
||||||
|
syscall(SYS_PUTC, (void*)(uintptr_t)ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
USERSPACE void print(const char* str)
|
||||||
|
{
|
||||||
|
while (*str)
|
||||||
|
user_putc(*str++);
|
||||||
|
}
|
||||||
|
|
||||||
|
USERSPACE void userspace_entry()
|
||||||
|
{
|
||||||
|
BAN::Formatter::println(user_putc, "Hello {}!", "World");
|
||||||
|
for (;;);
|
||||||
|
}
|
Loading…
Reference in New Issue