[USER] User mode code execution
This commit is contained in:
parent
f63afbb3b1
commit
4f76557b73
@ -6,12 +6,14 @@
|
|||||||
#include <process.h>
|
#include <process.h>
|
||||||
#include <cpu.h>
|
#include <cpu.h>
|
||||||
#include <timer.h>
|
#include <timer.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
void thread_function()
|
void thread_function()
|
||||||
{
|
{
|
||||||
|
int i = 0;
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,10 +32,18 @@ int kmain(uint64_t multiboot_magic, void *multiboot_data)
|
|||||||
pit_init();
|
pit_init();
|
||||||
|
|
||||||
process_t *p1 = process_spawn(0);
|
process_t *p1 = process_spawn(0);
|
||||||
thread_t *t1 = new_thread(thread_function);
|
uint64_t addr = 0x200000;
|
||||||
process_attach(p1, t1);
|
thread_t *th = new_thread((void *)addr, 1);
|
||||||
|
|
||||||
scheduler_insert(t1);
|
uintptr_t page = pmm_alloc();
|
||||||
|
// Write thread code to address
|
||||||
|
vmm_set_page(p1->P4, addr, page, PAGE_PRESENT | PAGE_WRITE | PAGE_USER);
|
||||||
|
memcpy(P2V(page), thread_function, PAGE_SIZE);
|
||||||
|
// Map a user stack space
|
||||||
|
vmm_set_page(p1->P4, USERSPACE_TOP-PAGE_SIZE, pmm_alloc(), PAGE_PRESENT | PAGE_WRITE | PAGE_USER);
|
||||||
|
|
||||||
|
process_attach(p1, th);
|
||||||
|
scheduler_insert(th);
|
||||||
|
|
||||||
asm("sti");
|
asm("sti");
|
||||||
debug_info("BOOT COMPLETE\n");
|
debug_info("BOOT COMPLETE\n");
|
||||||
|
@ -66,6 +66,14 @@
|
|||||||
#define INT_APIC_ERROR 0x45
|
#define INT_APIC_ERROR 0x45
|
||||||
#define INT_APIC_SPUR 0xFF
|
#define INT_APIC_SPUR 0xFF
|
||||||
|
|
||||||
|
|
||||||
|
#define RFLAGS_IOPL (3<<12)
|
||||||
|
#define RFLAGS_IOPL1 (1<<12)
|
||||||
|
#define RFLAGS_IOPL2 (2<<12)
|
||||||
|
#define RFLAGS_IOPL3 (3<<12)
|
||||||
|
#define RFLAGS_INT (1<<9)
|
||||||
|
#define REG_OFFSET_RFLAGS 152
|
||||||
|
|
||||||
#ifndef __ASSEMBLER__
|
#ifndef __ASSEMBLER__
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <apic.h>
|
#include <apic.h>
|
||||||
@ -116,13 +124,13 @@ typedef struct registers_st
|
|||||||
uint64_t r14;
|
uint64_t r14;
|
||||||
uint64_t r15;
|
uint64_t r15;
|
||||||
|
|
||||||
uint64_t int_no;
|
uint64_t int_no; //120
|
||||||
uint64_t err_code;
|
uint64_t err_code; //128
|
||||||
uint64_t rip;
|
uint64_t rip; //136
|
||||||
uint64_t cs;
|
uint64_t cs; //144
|
||||||
uint64_t rflags;
|
uint64_t rflags; //152
|
||||||
uint64_t rsp;
|
uint64_t rsp; //160
|
||||||
uint64_t ss;
|
uint64_t ss; //168
|
||||||
}registers_t;
|
}registers_t;
|
||||||
|
|
||||||
typedef registers_t *(*int_handler_t)(registers_t *);
|
typedef registers_t *(*int_handler_t)(registers_t *);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#define USERSPACE_TOP 0x0000800000000000
|
||||||
#define KERNEL_OFFSET 0xFFFFFF8000000000
|
#define KERNEL_OFFSET 0xFFFFFF8000000000
|
||||||
#define KERNEL_HEAP_S 0xFFFFFFC000000000
|
#define KERNEL_HEAP_S 0xFFFFFFC000000000
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ typedef struct thread_stack_st
|
|||||||
#define get_current_thread() (get_cpu()->current_thread)
|
#define get_current_thread() (get_cpu()->current_thread)
|
||||||
#define set_current_thread(new) (get_cpu()->current_thread = (new))
|
#define set_current_thread(new) (get_cpu()->current_thread = (new))
|
||||||
|
|
||||||
thread_t *new_thread(void (*func)(void));
|
thread_t *new_thread(void (*func)(void), int user);
|
||||||
void switch_thread(thread_t *old, thread_t *new);
|
void switch_thread(thread_t *old, thread_t *new);
|
||||||
void free_thread(thread_t *th);
|
void free_thread(thread_t *th);
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include <int.h>
|
||||||
.intel_syntax noprefix
|
.intel_syntax noprefix
|
||||||
|
|
||||||
.extern int_handler
|
.extern int_handler
|
||||||
@ -21,13 +22,33 @@ isr_common:
|
|||||||
push rcx
|
push rcx
|
||||||
push rbx
|
push rbx
|
||||||
push rax
|
push rax
|
||||||
|
|
||||||
|
# Clear RFLAGS
|
||||||
|
pushq 0
|
||||||
|
popf
|
||||||
|
|
||||||
|
# Check stored RFLAGS to see if we came here from user mode
|
||||||
|
mov rax, [rsp + REG_OFFSET_RFLAGS]
|
||||||
|
and rax, RFLAGS_IOPL
|
||||||
|
jz .kernel_mode
|
||||||
|
swapgs
|
||||||
|
|
||||||
|
.kernel_mode:
|
||||||
mov rdi, rsp
|
mov rdi, rsp
|
||||||
call int_handler
|
call int_handler
|
||||||
mov rdi, rax
|
mov rdi, rax
|
||||||
|
|
||||||
isr_return:
|
isr_return:
|
||||||
// Return and restore stack
|
|
||||||
mov rsp, rdi
|
mov rsp, rdi
|
||||||
|
|
||||||
|
# Check stored RFLAGS to see if we are going into user mode
|
||||||
|
mov rax, [rsp + REG_OFFSET_RFLAGS]
|
||||||
|
and rax, RFLAGS_IOPL
|
||||||
|
jz .kernel_return
|
||||||
|
swapgs
|
||||||
|
|
||||||
|
.kernel_return:
|
||||||
|
// Return and restore stack
|
||||||
pop rax
|
pop rax
|
||||||
pop rbx
|
pop rbx
|
||||||
pop rcx
|
pop rcx
|
||||||
|
@ -105,5 +105,5 @@ void scheduler_init()
|
|||||||
LIST_HEAD_INIT(ready_queue);
|
LIST_HEAD_INIT(ready_queue);
|
||||||
scheduler_started = 1;
|
scheduler_started = 1;
|
||||||
}
|
}
|
||||||
get_cpu()->scheduler = new_thread(scheduler);
|
get_cpu()->scheduler = new_thread(scheduler, 0);
|
||||||
}
|
}
|
||||||
|
@ -8,21 +8,30 @@
|
|||||||
|
|
||||||
uint64_t tid = 1;
|
uint64_t tid = 1;
|
||||||
|
|
||||||
thread_t *new_thread(void (*func)(void))
|
thread_t *new_thread(void (*func)(void), int user)
|
||||||
{
|
{
|
||||||
// Set up original stack of thread
|
// Set up original stack of thread
|
||||||
thread_stack_t *stack = kcalloc(1, sizeof(thread_stack_t));
|
thread_stack_t *stack = kcalloc(1, sizeof(thread_stack_t));
|
||||||
thread_t *th = &stack->tcb;
|
thread_t *th = &stack->tcb;
|
||||||
|
|
||||||
stack->thread = (uint64_t)th;
|
stack->thread = (uint64_t)th;
|
||||||
stack->function_address = (uint64_t)isr_return;
|
|
||||||
stack->RBP = (uint64_t)&stack->zero_frame;
|
stack->RBP = (uint64_t)&stack->zero_frame;
|
||||||
|
|
||||||
th->r.rip = (uint64_t)func;
|
|
||||||
th->r.rflags = RFLAGS_IF;
|
th->r.rflags = RFLAGS_IF;
|
||||||
th->r.cs = 0x8;
|
if(user)
|
||||||
th->r.ss = 0x10;
|
{
|
||||||
th->r.rsp = (uint64_t)&th->stack_pointer;
|
stack->function_address = (uint64_t)isr_return;
|
||||||
|
th->r.rip = (uint64_t)func;
|
||||||
|
th->r.cs = SEG_UCODE|3;
|
||||||
|
th->r.ss = SEG_UDATA|3;
|
||||||
|
th->r.rflags |= RFLAGS_IOPL3;
|
||||||
|
th->r.rsp = USERSPACE_TOP;
|
||||||
|
} else {
|
||||||
|
stack->function_address = (uint64_t)func;
|
||||||
|
th->r.cs = SEG_KCODE;
|
||||||
|
th->r.ss = SEG_KDATA;
|
||||||
|
th->r.rsp = (uint64_t)&th->stack_pointer;
|
||||||
|
}
|
||||||
|
|
||||||
th->tid = tid++;
|
th->tid = tid++;
|
||||||
th->state = THREAD_STATE_READY;
|
th->state = THREAD_STATE_READY;
|
||||||
@ -37,6 +46,8 @@ thread_t *new_thread(void (*func)(void))
|
|||||||
void switch_thread(thread_t *old, thread_t *new)
|
void switch_thread(thread_t *old, thread_t *new)
|
||||||
{
|
{
|
||||||
set_current_thread(new);
|
set_current_thread(new);
|
||||||
|
get_cpu()->tss.rsp0 = (uint64_t)&new->stack_pointer;
|
||||||
|
get_cpu()->kernel_stack = &new->stack_pointer;
|
||||||
|
|
||||||
uint64_t *old_stack = (old)?&old->stack_pointer:0;
|
uint64_t *old_stack = (old)?&old->stack_pointer:0;
|
||||||
swtch(old_stack, &new->stack_pointer);
|
swtch(old_stack, &new->stack_pointer);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user