From: acevest Date: Fri, 5 Nov 2021 06:51:10 +0000 (+0800) Subject: 用新的方式跳转到用户态 X-Git-Url: http://zhaoyanbai.com/repos/FAQ?a=commitdiff_plain;h=2133ea4a6a616b19e1cb5db2133714e665052566;p=kernel.git 用新的方式跳转到用户态 --- diff --git a/.bochsrc b/.bochsrc index a2e7855..dd16352 100644 --- a/.bochsrc +++ b/.bochsrc @@ -1308,4 +1308,4 @@ magic_break: enabled=1 #megs: 32 #megs: 16 #megs: 8 -megs: 32 +megs: 8 diff --git a/include/printk.h b/include/printk.h index a1acab0..30e0108 100644 --- a/include/printk.h +++ b/include/printk.h @@ -37,6 +37,7 @@ enum { MPL_TEST, MPL_DEBUG, MPL_ROOT, + MPL_TASK_0, MPL_TASK_1, MPL_TASK_2, MPL_TASK_3, diff --git a/kernel/init.c b/kernel/init.c index b4434d7..8b36e12 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -25,59 +25,62 @@ char idtr[6] __attribute__((__aligned__(4))); // int debug_wait_queue_get(); #define __ring3text__ __attribute__((__section__(".ring3.text"))) -#define __ring3data__ __attribute__((__section__(".ring3.data"), __aligned__(PAGE_SIZE))) -#define __ring3bss__ __attribute__((__section__(".ring3.bss"), __aligned__(PAGE_SIZE))) -char __ring3data__ ring3_stack[PAGE_SIZE] = {0}; -char __ring3bss__ ring3_bss[PAGE_SIZE + 1234]; int ring3_sysctest(); void __ring3text__ __attribute__((__aligned__(PAGE_SIZE))) ring3_entry() { while (1) { - ring3_sysctest(); + int __sysc_ret__ = 0; + + // 下面这段汇编中的 ring3_entry 和 sysexit_return_address的地址都是内核地址 + // 然而在用户态用的代码地址是从0x08000000开始的 + // 因此为了算了systexit返回的正确地址 + // 需要借助ring3_entry算出sysexit_return_address相对ring3_entry的偏移量 + // 再把这个偏移量加上0x08000000就是正确的sysexit的地址 + + // 必需注意这里的sysexit_return_address并不是sysexit指令返回的地址 + // sysexit指令返回的是编译在内核中的一段代码地址,这个地址已经被设成内核和用户态共享 + // 在内核中的那段代码里会利用存在栈上的sysexit_return_address返回到 + // sysexit_return_address处 + asm volatile( + "leal sysexit_return_address, %%ebx;" + "subl %%ecx, %%ebx;" + "addl $0x08000000, %%ebx;" // 算出sysexit_return_address在用户态的实际地址 + "pushl %%ebx;" // 把这个地址保存在栈上,内核sysexit会返回到一段共享代码上 + // 共享代码会利用保存在栈上的地址返回到sysexit_return_address处 + "pushl $0;" + "pushl $0;" + "pushl %%ebp;" + "movl %%esp, %%ebp;" + "sysenter;" + "sysexit_return_address:" + : "=a"(__sysc_ret__) + : "a"(SYSC_TEST), "c"(ring3_entry)); } } -static int __ring3text__ __volatile__ __ring3_syscall0(int nr) { - int __sysc_ret__ = 0; - extern void sysenter; - asm volatile("leal sysenter, %%ebx;call *%%ebx;" : "=a"(__sysc_ret__) : "a"(nr)); - return __sysc_ret__; -} -int __ring3text__ _ring3_syscall0(int nr) { return __ring3_syscall0(nr); } -int __ring3text__ ring3_sysctest() { return _ring3_syscall0(SYSC_TEST); } - -void user_task_entry() { - // printk("user_task_entry: %08x\n", ring3_entry); - - // unsigned long ring3_text_page = va2pa(alloc_one_page(0)); - // unsigned long ring3_data_page = va2pa(alloc_one_page(0)); - // unsigned long ring3_bss_page = va2pa(alloc_one_page(0)); +void user_task_entry(char *name) { + strcpy(current->name, name); unsigned long ring3_text_page = va2pa(ring3_entry); - unsigned long ring3_data_page = va2pa(ring3_stack); unsigned long ring3_bss_page = va2pa(alloc_one_page(0)); unsigned long *pt_text_page = (unsigned long *)(alloc_one_page(0)); - unsigned long *pt_data_page = (unsigned long *)(alloc_one_page(0)); unsigned long *pt_bss_page = (unsigned long *)(alloc_one_page(0)); + unsigned long *p = (unsigned long *)(pa2va(current->cr3)); printk("page dir : %x %x %x %x\n", p, pt_text_page, ring3_text_page); printk("pt bss page %x %x", pt_bss_page, ring3_bss_page); // text: 0x0800_0000 - // data: 0x2000_0000 // bss: 0x3000_0000 unsigned long text_at = 0x08000000; - unsigned long data_at = 0x20000000; unsigned long bbs_at = 0x30000000; - p[text_at >> 22] = (unsigned long)va2pa(pt_text_page) | PAGE_P | PAGE_WR | PAGE_US; - pt_text_page[0] = ring3_text_page | 7; - p[data_at >> 22] = (unsigned long)va2pa(pt_data_page) | PAGE_P | PAGE_WR | PAGE_US; - pt_data_page[0] = ring3_data_page | 7; + p[text_at >> 22] = (unsigned long)va2pa(pt_text_page) | PAGE_P | PAGE_US; + pt_text_page[0] = ring3_text_page | PAGE_P | PAGE_US; p[bbs_at >> 22] = (unsigned long)va2pa(pt_bss_page) | PAGE_P | PAGE_WR | PAGE_US; - pt_bss_page[0] = ring3_bss_page | 7; + pt_bss_page[0] = ring3_bss_page | PAGE_P | PAGE_WR | PAGE_US; // LoadCR3(current->cr3); @@ -88,10 +91,12 @@ void user_task_entry() { asm volatile("sysexit;" ::"d"(0x08000000), "c"(0x30000000 + PAGE_SIZE - 100)); } -void init_task_entry() { +void init_task_entry(char *name) { int cnt = 0; pid_t id = sysc_getpid(); + strcpy(current->name, name); + // 赋予不同的优先级 current->priority = id * 30; if (current->priority <= 0) { @@ -103,7 +108,7 @@ void init_task_entry() { while (1) { // sysc_test(); - printl(MPL_TASK_1 + id - 1, "task:%d [%08x] weight %d cnt %d", id, current, current->weight, cnt++); + // printl(MPL_TASK_0 + id, "task:%d [%08x] weight %d cnt %d", id, current, current->weight, cnt++); // printl(MPL_TASK_1, "task:%d [%08x] weight %d cnt %d", id, current, current->weight, cnt++); int v = 0; // debug_wait_queue_get(); // printk("task:%d wait queue get %d\n", id, v); @@ -130,6 +135,8 @@ void kernel_task(char *name, void *entry) { regs.fs = SELECTOR_KRNL_DS; regs.gs = SELECTOR_KRNL_DS; + regs.ebx = (unsigned long)name; // 用ebx传递参数 + int pid = do_fork(®s, FORK_KRNL); printk("kernel[%s] task pid is %d\n", name, pid); @@ -145,7 +152,7 @@ void root_task_entry() { int cnt = 0; while (1) { // sysc_test(); - printl(MPL_ROOT, "root:0 [%08x] weight %d cnt %d", current, root_task.weight, cnt++); + // printl(MPL_TASK_0, "root:0 [%08x] weight %d cnt %d", current, root_task.weight, cnt++); // printk("root:0 [%08x] weight %d cnt %d", current, current->weight, cnt++); asm("sti;hlt;"); // asm("nop;nop;nop;"); diff --git a/kernel/sched.c b/kernel/sched.c index 535d464..d458525 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -143,7 +143,7 @@ unsigned long schedule() { unsigned long iflags; irq_save(iflags); - printl(MPL_ROOT, "root:%d [%08x] cnt %u", root_task.pid, &root_task, root_task.cnt); + // printl(MPL_ROOT, "root:%d [%08x] cnt %u", root_task.pid, &root_task, root_task.cnt); float min_ratio = 1.0; @@ -172,8 +172,6 @@ unsigned long schedule() { list_for_each_safe(pos, t, &all_tasks) { p = list_entry(pos, task_union, list); - printl(MPL_ROOT + p->pid, "task:%d [%08x] state %s cnt %u", p->pid, p, task_state(p->state), p->cnt); - if (p->state != TASK_RUNNING) { continue; } @@ -196,6 +194,12 @@ unsigned long schedule() { if (prev != next) { // printk("switch to: %s:%d\n", next->name, next->pid); + + list_for_each_safe(pos, t, &all_tasks) { + p = list_entry(pos, task_union, list); + printl(MPL_TASK_0 + p->pid, "%s%4s:%d [%08x] state %s weight %03d cnt %u", sel == p ? ">" : " ", p->name, + p->pid, p, task_state(p->state), p->weight, p->cnt); + } context_switch(prev, next); } } diff --git a/kernel/syscall.S b/kernel/syscall.S index 906d65c..76b3ad1 100644 --- a/kernel/syscall.S +++ b/kernel/syscall.S @@ -89,7 +89,11 @@ ret_from_fork_krnl: addl $12, %esp popfl addl $8, %esp + + # 用ebx传递参数 + pushl %ebx call *%edx + addl $4, %esp # 还没有实现do_exit #call do_exit @@ -101,18 +105,6 @@ ret_from_fork_krnl: # this page is shared by the kernel and userspace # the reason why i use this method is because of that the user program # no need to pay attention on the return address -.global sysenter -.section .sysenter -.align 0x1000 -sysenter: - pushl %ecx; - pushl %edx; - pushl %ebp; - movl %esp, %ebp; - sysenter; - - - .global sysexit .section .sysexit .align 0x1000 diff --git a/mm/bootmem.c b/mm/bootmem.c index 597a593..bd8a30b 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c @@ -44,7 +44,7 @@ void fast_init_bootmem_bitmap(unsigned long bgn_pfn, unsigned long end_pfn, int u8 data = op == 0 ? 0x00 : 0xFF; // 先设置头部不是从单个字节开始的比特 - unsigned int i = 0; // 这个变更不能放到for循环里定义 + unsigned int i = 0; // 这个变量不能放到for循环里定义 for (i = bgn_pfn; i < end_pfn && (i % 8 != 0); i++) { bit_func(i, bootmem_data.bitmap); } @@ -52,7 +52,7 @@ void fast_init_bootmem_bitmap(unsigned long bgn_pfn, unsigned long end_pfn, int // 算出中间的整字节数 unsigned int bytes = (end_pfn - i) / 8; - // 直接清零 + // 直接清零或设置 memset((char *)(bootmem_data.bitmap) + (i / 8), data, bytes); // 最后设置尾部不是整字节的比特 diff --git a/mm/mm.c b/mm/mm.c index c3907b0..02ca95e 100644 --- a/mm/mm.c +++ b/mm/mm.c @@ -75,9 +75,7 @@ void init_paging() { } // paging for user space - extern void sysenter(); extern void sysexit(); - set_page_shared(sysenter); set_page_shared(sysexit); LoadCR3(va2pa(init_pgd)); diff --git a/scripts/link.ld b/scripts/link.ld index df9ce80..8d8efff 100644 --- a/scripts/link.ld +++ b/scripts/link.ld @@ -29,8 +29,7 @@ SECTIONS boot/multiboot.S.o(.text) *(.multiboot_header) *(.text) - - *(.sysenter) /* last */ + *(.ring3.text); *(.sysexit) /* last */ } etext = .; @@ -50,24 +49,6 @@ SECTIONS ebss = .; - .ring3.text : AT(phys_addr) ALIGN(0x1000) - { - phys_addr = . - kernel_virtual_addr_start; - *(.ring3.text); - } - - .ring3.data : AT(phys_addr) ALIGN(0x1000) - { - phys_addr = . - kernel_virtual_addr_start; - *(.ring3.data); - } - - .ring3.bss : AT(phys_addr) ALIGN(0x1000) - { - phys_addr = . - kernel_virtual_addr_start; - *(.ring3.bss); - } - end = .; _end = .; kernel_end = .;