Skip to content

Commit

Permalink
更新用户进程执行
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaoyi1212 committed Nov 11, 2024
1 parent 427a21a commit 85731aa
Show file tree
Hide file tree
Showing 16 changed files with 394 additions and 50 deletions.
Binary file added lib/libelf_parse.a
Binary file not shown.
19 changes: 19 additions & 0 deletions src/boot/asmfunc.asm
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
global gdt_flush,tss_flush,idt_flush,switch_to,copy_page_physical
global asm_syscall_handler

extern syscall

gdt_flush: ; void gdt_flush(uint32_t gdtr);
mov eax, [esp + 4] ; [esp+4]按规定是第一个参数,即gdtr
Expand Down Expand Up @@ -84,3 +87,19 @@ copy_page_physical:
popf ; Pop EFLAGS back.
pop ebx ; Get the original value of EBX back.
ret

asm_syscall_handler:
cli
push ds
push es
push fs
push gs
pusha
call syscall
mov dword [esp+28], eax
popa
pop gs
pop fs
pop es
pop ds
IRETD
22 changes: 5 additions & 17 deletions src/core/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "keyboard.h"
#include "scheduler.h"
#include "krlibc.h"
#include "syscall.h"
#include "shell.h"

extern void* program_break_end;
Expand Down Expand Up @@ -63,29 +64,16 @@ _Noreturn void kernel_main(multiboot_t *multiboot, uint32_t kernel_stack) {
init_pcb();

keyboard_init();
setup_syscall();
create_kernel_thread((void*)setup_shell, NULL, "Shell");
klogf(true,"Enable kernel shell service.\n");

vfs_mkdir("/a");
vfs_mount("/dev/ide0", vfs_open("/a"));

klogf(true,"Kernel load done!\n");
enable_scheduler();
io_sti(); //内核加载完毕, 打开中断以启动进程调度器, 开始运行

// int ret = vfs_mkdir("/dev");
// printk(" vfs ret=%d\n",ret);
// vfs_mount(NULL, vfs_open("/dev"));
// vfs_node_t p = vfs_open("/");
// list_foreach(p->child, i) {
// vfs_node_t c = (vfs_node_t)i->data;
// printk("%s ", c->name);
// }
// printk("\n");

// uint8_t *buf = kmalloc(2048);
// p = vfs_open("/dev/ide_atapi0");
// vfs_read(p,buf,2048,2048);
// for(int i = 0;i<2048;i++) {
// printk("%02x ",buf[i]);
// }

while(1) io_hlt();
}
24 changes: 16 additions & 8 deletions src/core/memory/page.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,13 @@ page_directory_t *clone_directory(page_directory_t *src) {
return dir;
}

page_directory_t *get_current_directory(){
return current_directory;
}

void page_fault(registers_t *regs) {
io_cli();
disable_scheduler();
uint32_t faulting_address;
__asm__ volatile("mov %%cr2, %0" : "=r" (faulting_address)); //

Expand All @@ -180,32 +185,35 @@ void page_fault(registers_t *regs) {
int reserved = regs->err_code & 0x8; // 写入CPU保留位
int id = regs->err_code & 0x10; // 由取指引起

printk("[ERROR]: Page fault |");
printk("[ERROR]: Page fault [PID: %d |Level: %d] |",get_current_proc()->pid,get_current_proc()->task_level);
if (present) {
printk("Type: present;\n\taddress: %x \n", faulting_address);
printk("Type: present | address: %x \n", faulting_address);
} else if (rw) {
printk("Type: read-only;\n\taddress: %x\n", faulting_address);
printk("Type: read-only | address: %x\n", faulting_address);
} else if (us) {
printk("Type: user-mode;\n\taddres: %x\n", faulting_address);
printk("Type: user-mode | addres: %x\n", faulting_address);
} else if (reserved) {
printk("Type: reserved;\n\taddress: %x\n", faulting_address);
printk("Type: reserved | address: %x\n", faulting_address);
} else if (id) {
printk("Type: decode address;\n\taddress: %x\n", faulting_address);
printk("Type: decode address | address: %x\n", faulting_address);
}

// 多进程相关, 未实现多进程的OS可将以下代码全部替换为 while(1)

if(get_current_proc()->task_level == TASK_KERNEL_LEVEL){
klogf(false,"Kernel Error Panic.\n");
while (1) io_hlt();
} else if(get_current_proc()->task_level == TASK_APPLICATION_LEVEL){
kill_proc(get_current_proc());
while (1) io_hlt();
} else if(get_current_proc()->task_level == TASK_SYSTEM_SERVICE_LEVEL){
//TODO 蓝屏处理程序待实现
klogf(false,"System service error. ==Kernel Panic==\n");
while (1) io_hlt();
}



enable_scheduler();
io_sti();
}

void page_init(multiboot_t *multiboot){
Expand Down
77 changes: 77 additions & 0 deletions src/core/syscall.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#include "syscall.h"
#include "io.h"
#include "pcb.h"
#include "scheduler.h"
#include "description_table.h"
#include "klog.h"
#include "keyboard.h"

static uint32_t syscall_putc(uint32_t ebx,uint32_t ecx,uint32_t edx,uint32_t esi,uint32_t edi){
get_current_proc()->tty->putchar(get_current_proc()->tty,(int)ebx);
return 0;
}

static uint32_t syscall_print(uint32_t ebx,uint32_t ecx,uint32_t edx,uint32_t esi,uint32_t edi){
get_current_proc()->tty->print(get_current_proc()->tty, (const char *) ebx);
return 0;
}

static uint32_t syscall_getch(uint32_t ebx,uint32_t ecx,uint32_t edx,uint32_t esi,uint32_t edi){
io_sti();
return kernel_getch();
}

static uint32_t syscall_sbrk(uint32_t ebx,uint32_t ecx,uint32_t edx,uint32_t esi,uint32_t edi){
return (uint32_t) NULL;
}

static uint32_t syscall_free(uint32_t ebx,uint32_t ecx,uint32_t edx,uint32_t esi,uint32_t edi){
return 0;
}

static uint32_t syscall_exit(uint32_t ebx,uint32_t ecx,uint32_t edx,uint32_t esi,uint32_t edi){
int exit_code = ebx;
pcb_t *pcb = get_current_proc();
kill_proc(pcb);
printk("Process exit, code: %d\n",exit_code);
while (1);
/*
* 将该进程流程阻塞, 等待调度器下一次调度
* (因为这时有关该进程的所有上下文信息以及内存都已经被释放, 如果iret返回后则会直接发生#PF错误, 故插入死循环阻塞)
*/
return 0;
}

syscall_t syscall_handlers[MAX_SYSCALLS] = {
[SYSCALL_PUTC] = syscall_putc,
[SYSCALL_PRINT] = syscall_print,
[SYSCALL_GETCH] = syscall_getch,
[SYSCALL_SBRK] = syscall_sbrk,
[SYSCALL_FREE] = syscall_free,
[SYSCALL_EXIT] = syscall_exit,
};

size_t syscall() { //由 asmfunc.c/asm_syscall_handler调用
io_cli();
// disable_scheduler();
volatile size_t eax, ebx, ecx, edx, esi, edi;
__asm__("mov %%eax, %0\n\t" : "=r"(eax));
__asm__("mov %%ebx, %0\n\t" : "=r"(ebx));
__asm__("mov %%ecx, %0\n\t" : "=r"(ecx));
__asm__("mov %%edx, %0\n\t" : "=r"(edx));
__asm__("mov %%esi, %0\n\t" : "=r"(esi));
__asm__("mov %%edi, %0\n\t" : "=r"(edi));
if (0 <= eax && eax < MAX_SYSCALLS && syscall_handlers[eax] != NULL) {
eax = ((syscall_t)syscall_handlers[eax])(ebx, ecx, edx, esi, edi);
} else {
eax = -1;
}
enable_scheduler();
io_sti();
return eax;
}

void setup_syscall(){
idt_use_reg(31, (uint32_t) asm_syscall_handler);
klogf(true,"Register syscall interrupt service.\n");
}
55 changes: 44 additions & 11 deletions src/core/task/pcb.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "krlibc.h"
#include "io.h"
#include "description_table.h"
#include "elf_util.h"

extern pcb_t *current_pcb;
extern pcb_t *running_proc_head;
Expand All @@ -30,8 +31,8 @@ static void add_task(pcb_t *new_task){ //添加进程至调度链

static void switch_to_user_mode(uint32_t func) {
io_cli();
uint32_t esp = (uint32_t )current_pcb->user_stack + STACK_SIZE;
current_pcb->context.eflags = (0 << 12 | 0b10 | 1 << 9);
uint32_t esp = (uint32_t )get_current_proc()->user_stack + STACK_SIZE;
get_current_proc()->context.eflags = (0 << 12 | 0b10 | 1 << 9);
intr_frame_t iframe;
iframe.edi = 1;
iframe.esi = 2;
Expand Down Expand Up @@ -68,27 +69,56 @@ _Noreturn static void process_exit(){
while (1);
}

int create_user_proc(uint32_t _user_start,char *args,char* name){ //创建用户进程
int create_user_process(const char* path,const char* cmdline,char* name,uint8_t level){
vfs_node_t exefile = vfs_open(path);
if(exefile == NULL) return -1;



pcb_t *new_task = kmalloc(STACK_SIZE);
memset(new_task, 0, sizeof(pcb_t));

new_task->task_level = TASK_APPLICATION_LEVEL;
new_task->task_level = level;
strcpy(new_task->name,name);
strcpy(new_task->cmdline,cmdline);
new_task->pid = now_pid++;
new_task->program_break = program_break;
new_task->program_break_end = program_break_end;
new_task->pgd_dir = kernel_directory;
new_task->pgd_dir = clone_directory(kernel_directory);
new_task->cpu_clock = 0;
new_task->tty = &default_tty;
new_task->tty = default_tty_alloc();
new_task->cpu_clock = 0;

new_task->exe_file = exefile;
new_task->kernel_stack = new_task;

for (uint32_t i = 0xb2000000 - STACK_SIZE; i < 0xb2000000; i+= PAGE_SIZE) {
alloc_frame(get_page(i,1,new_task->pgd_dir),0,1);
}
new_task->user_stack = (void*)0xb2000000 - STACK_SIZE;

page_directory_t *cur_dir = get_current_proc()->pgd_dir;
disable_scheduler();
io_sti();
switch_page_directory(new_task->pgd_dir);
uint8_t *data = kmalloc(exefile->size);
if(vfs_read(exefile,data,0,exefile->size) == -1){
vfs_close(exefile);
return -1;
}
uint32_t _start = elf_load(exefile->size,data);
switch_page_directory(cur_dir);
io_cli();
enable_scheduler();

if(_start == 0){
free_tty(new_task->tty);
kfree(new_task);
vfs_close(exefile);
return -1;
}

uint32_t *stack_top = (uint32_t * )((uint32_t) new_task + STACK_SIZE);
*(--stack_top) = (uint32_t) _user_start;
*(--stack_top) = (uint32_t) _start;
*(--stack_top) = (uint32_t) process_exit;
*(--stack_top) = (uint32_t) switch_to_user_mode;

new_task->context.esp = (uint32_t) new_task + STACK_SIZE - sizeof(uint32_t) * 3;
new_task->context.eflags = 0x200;

Expand All @@ -97,6 +127,7 @@ int create_user_proc(uint32_t _user_start,char *args,char* name){ //创建用户
return new_task->pid;
}


int create_kernel_thread(int (*_start)(void* arg),void *args,char* name){ //创建内核进程 (内核线程)
io_cli();
pcb_t *new_task = kmalloc(STACK_SIZE);
Expand Down Expand Up @@ -138,6 +169,8 @@ void kill_proc(pcb_t *pcb){

if(pcb->task_level == TASK_KERNEL_LEVEL){

} else{
vfs_close(pcb->exe_file);
}

free_tty(pcb->tty);
Expand Down
1 change: 1 addition & 0 deletions src/driver/tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ tty_t* default_tty_alloc(){
}

void free_tty(tty_t *tty){
kfree(tty->fifo->buf);
kfree(tty->fifo);
kfree(tty);
}
Expand Down
38 changes: 38 additions & 0 deletions src/include/elf_parse.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#pragma once

#include "ctypes.h"

typedef enum ElfParseResult_Tag {
EntryPoint,
InvalidElfData,
ElfContainsNoSegments,
FailedToGetSegmentData,
AllocFunctionNotProvided,
} ElfParseResult_Tag;

typedef struct ElfParseResult {
ElfParseResult_Tag tag;
union {
struct {
size_t entry_point;
};
};
} ElfParseResult;

typedef struct ElfSegment {
size_t address;
size_t size;
const uint8_t *data;
} ElfSegment;

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

struct ElfParseResult parse_elf(const uint8_t *elf_data,
size_t elf_size,
void (*mapping_callback)(struct ElfSegment segment));

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
5 changes: 5 additions & 0 deletions src/include/elf_util.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

#include "elf_parse.h"

uint32_t elf_load(size_t elf_size,uint8_t *elf_data);
2 changes: 1 addition & 1 deletion src/include/krlibc.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#define KERNEL_NAME "CP_Kernel-i386-0.4.0"
#define KERNEL_NAME "CP_Kernel-i386-0.4.1"

#define KHEAP_INITIAL_SIZE 0xf00000
#define STACK_SIZE 32768
Expand Down
2 changes: 2 additions & 0 deletions src/include/page.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ typedef struct page_directory {
uint32_t physicalAddr;
}__attribute__((packed)) page_directory_t;

page_directory_t *get_current_directory();
page_directory_t *clone_directory(page_directory_t *src);
void alloc_frame_line(page_t *page, uint32_t line,int is_kernel, int is_writable);
void alloc_frame(page_t *page, int is_kernel, int is_writable);
void free_frame(page_t *page);
Expand Down
Loading

0 comments on commit 85731aa

Please sign in to comment.