From fa57b4a05aa12d594f40e0894e0ac6f810a7095c Mon Sep 17 00:00:00 2001 From: Minep Date: Sat, 17 Sep 2022 18:25:59 +0100 Subject: [PATCH] feat: add support for process to conduct Intel x87 and MMX related task. --- lunaix-os/arch/x86/boot.S | 10 ++++++++-- lunaix-os/includes/lunaix/process.h | 23 ++++++++++++++--------- lunaix-os/kernel/asm/x86/interrupt.S | 14 +++++++++++--- lunaix-os/kernel/process/sched.c | 3 +++ lunaix-os/kernel/process/signal.c | 10 +++++++--- 5 files changed, 43 insertions(+), 17 deletions(-) diff --git a/lunaix-os/arch/x86/boot.S b/lunaix-os/arch/x86/boot.S index 9c86bbc..938db87 100644 --- a/lunaix-os/arch/x86/boot.S +++ b/lunaix-os/arch/x86/boot.S @@ -77,11 +77,17 @@ andl $0xfffff000, %eax # 有点多余,但写上还算明白一点 movl %eax, %cr3 - /* 开启分页与地址转换 (CR0.PG=1, PG.WP=1) */ movl %cr0, %eax - orl $0x80010000, %eax + orl $0x80010000, %eax /* 开启分页与地址转换 (CR0.PG=1, CR0.WP=1) */ + andl $0xfffffffb, %eax + orl $0x2, %eax /* 启用x87 FPU (CR0.MP=1, CR0.EM=0) */ movl %eax, %cr0 + movl %cr4, %eax + orl $0x600, %eax + movl %eax, %cr4 /* CR4.OSFXSR=1, CR4.OSXMMEXCPT=1 */ + /* x87 FPU 已配置 */ + addl $16, %esp /* 进入高半核! */ diff --git a/lunaix-os/includes/lunaix/process.h b/lunaix-os/includes/lunaix/process.h index c7b925e..c014443 100644 --- a/lunaix-os/includes/lunaix/process.h +++ b/lunaix-os/includes/lunaix/process.h @@ -31,14 +31,18 @@ struct proc_mm struct mm_region regions; }; +struct proc_sigstate +{ + isr_param proc_regs; + char fxstate[512] __attribute__((aligned(16))); +}; + struct proc_sig { void* signal_handler; int sig_num; - isr_param prev_context; -}; - -#define PROC_SIG_SIZE sizeof(struct proc_sig) // size=84 + struct proc_sigstate prev_context; +} __attribute__((packed)); struct proc_info { @@ -50,11 +54,12 @@ struct proc_info /* ---- critical section start ---- */ - pid_t pid; - struct proc_info* parent; - isr_param intr_ctx; // size=76 - uintptr_t ustack_top; - void* page_table; + pid_t pid; // offset = 0 + struct proc_info* parent; // offset = 4 + isr_param intr_ctx; // offset = 8 + uintptr_t ustack_top; // offset = 84 + void* page_table; // offset = 88 + void* fxstate; // offset = 92 /* ---- critical section end ---- */ diff --git a/lunaix-os/kernel/asm/x86/interrupt.S b/lunaix-os/kernel/asm/x86/interrupt.S index 17236f8..14bafb6 100644 --- a/lunaix-os/kernel/asm/x86/interrupt.S +++ b/lunaix-os/kernel/asm/x86/interrupt.S @@ -74,7 +74,12 @@ # 保存用户栈顶指针。这是因为我们允许系统调用内进行上下文切换,而这样一来,我们就失去了用户栈的信息, # 这样一来,就无法设置信号上下文。这主要是为了实现了pause()而做的准备 - movl (__current), %eax + movl (__current), %eax + + # 保存x87FPU的状态 + movl 92(%eax), %ebx + fxsave (%ebx) + movl 68(%esp), %ebx # 取出esp movl %ebx, 84(%eax) # 存入__current->ustack_top @@ -97,6 +102,9 @@ movl 56(%esp), %eax movl %eax, (debug_resv + 4) #endif + movl (__current), %eax + movl 92(%eax), %eax + fxrstor (%eax) popl %eax popl %ebx @@ -168,9 +176,9 @@ # 注意2:handle_signal在调用之前,须确保proc_sig已经写入用户栈! leal 8(%eax), %ebx # arg1 in %eax: addr of proc_sig structure in user stack - pushl $UDATA_SEG # proc_sig->prev_context.ss + pushl $UDATA_SEG # proc_sig->prev_context.proc_regs.ss pushl %eax # esp - pushl 64(%ebx) # proc_sig->prev_context.eflags + pushl 64(%ebx) # proc_sig->prev_context.proc_regs.eflags pushl $UCODE_SEG # cs pushl $sig_wrapper # eip for sig wrapper diff --git a/lunaix-os/kernel/process/sched.c b/lunaix-os/kernel/process/sched.c index 3ee0e76..4e3f290 100644 --- a/lunaix-os/kernel/process/sched.c +++ b/lunaix-os/kernel/process/sched.c @@ -282,6 +282,8 @@ alloc_process() proc->created = clock_systime(); proc->pgid = proc->pid; proc->fdtable = vzalloc(sizeof(struct v_fdtable)); + proc->fxstate = + vzalloc_dma(512); // FXSAVE需要十六位对齐地址,使用DMA块(128位对齐) llist_init_head(&proc->mm.regions.head); llist_init_head(&proc->tasks); @@ -349,6 +351,7 @@ destroy_process(pid_t pid) } vfree(proc->fdtable); + vfree_dma(proc->fxstate); struct mm_region *pos, *n; llist_for_each(pos, n, &proc->mm.regions.head, head) diff --git a/lunaix-os/kernel/process/signal.c b/lunaix-os/kernel/process/signal.c index 5d09d9b..9a9a349 100644 --- a/lunaix-os/kernel/process/signal.c +++ b/lunaix-os/kernel/process/signal.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -22,7 +23,7 @@ void* default_handlers[_SIG_NUM] = { [_SIGINT] = default_sighandler_term, }; -volatile isr_param __temp_save; +volatile struct proc_sigstate __temp_save; // Referenced in kernel/asm/x86/interrupt.S void* signal_dispatch() @@ -79,7 +80,9 @@ signal_dispatch() 解决办法就是先吧intr_ctx拷贝到一个静态分配的区域里,然后再注入到用户栈。 */ - __temp_save = __current->intr_ctx; + __temp_save.proc_regs = __current->intr_ctx; + memcpy(__temp_save.fxstate, __current->fxstate, 512); + sig_ctx->prev_context = __temp_save; sig_ctx->sig_num = sig_selected; @@ -138,7 +141,8 @@ send_single: __DEFINE_LXSYSCALL1(int, sigreturn, struct proc_sig, *sig_ctx) { - __current->intr_ctx = sig_ctx->prev_context; + memcpy(__current->fxstate, sig_ctx->prev_context.fxstate, 512); + __current->intr_ctx = sig_ctx->prev_context.proc_regs; __current->flags &= ~PROC_FINPAUSE; __SIGCLEAR(__current->sig_inprogress, sig_ctx->sig_num); schedule(); -- 2.27.0