feat: add support for process to conduct Intel x87 and MMX related task.
authorMinep <zelong56@gmail.com>
Sat, 17 Sep 2022 17:25:59 +0000 (18:25 +0100)
committerMinep <zelong56@gmail.com>
Sat, 17 Sep 2022 17:25:59 +0000 (18:25 +0100)
lunaix-os/arch/x86/boot.S
lunaix-os/includes/lunaix/process.h
lunaix-os/kernel/asm/x86/interrupt.S
lunaix-os/kernel/process/sched.c
lunaix-os/kernel/process/signal.c

index 9c86bbc6bed8081695dcb00a58b33b100403b73e..938db876514333b8a8f0dec1b1d598590b51f80d 100644 (file)
         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
 
         /* 进入高半核! */
index c7b925ef59651532d3da80ab6a6f0fbc68fe0f28..c014443089bb557b35991bb7f1968c3873123a7b 100644 (file)
@@ -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 ---- */
 
index 17236f8f9fb4805d67cb6b9bbb9e875f5d6ab190..14bafb68263a87826888c70ae3adbf5f7d2d8594 100644 (file)
 
         # 保存用户栈顶指针。这是因为我们允许系统调用内进行上下文切换,而这样一来,我们就失去了用户栈的信息,
         # 这样一来,就无法设置信号上下文。这主要是为了实现了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
 
         movl 56(%esp), %eax
         movl %eax, (debug_resv + 4)
 #endif
+        movl (__current), %eax
+        movl 92(%eax), %eax
+        fxrstor (%eax)
 
         popl %eax
         popl %ebx
         # 注意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
 
index 3ee0e7666c32eafe97c3436ac1c2a9ccc103f64b..4e3f290c4ca61e36699988c9f77f899d567c3bf7 100644 (file)
@@ -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)
index 5d09d9b6efa59bb02df9faabb3d0c7111d5ce9d2..9a9a34999dc86b19bf461b713c897b13357424c2 100644 (file)
@@ -1,3 +1,4 @@
+#include <klibc/string.h>
 #include <lunaix/lunistd.h>
 #include <lunaix/lxsignal.h>
 #include <lunaix/process.h>
@@ -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();