#if 1
kernel_task("ide/1", disk_task_entry, (void *)1);
- // kernel_task("user", user_task_entry, NULL);
+ kernel_task("user", user_task_entry, NULL);
kernel_task("tskA", taskA_entry, NULL);
kernel_task("tskB", taskB_entry, NULL);
kernel_task("tskC", taskC_entry, NULL);
printk("RING3 ENTRY %x page %x pgd inx %u pt inx %u\n", mod_start, text_at, pgd_index, pt_index);
- LoadCR3(current->cr3);
+ set_cr3(current->cr3);
asm("sysexit;" ::"d"(mod_start), "c"(mod_start + PAGE_SIZE - 4));
#endif
#include <system.h>
#include <types.h>
-#define __ring3text__ __attribute__((__section__(".ring3.text")))
-
-int ring3_sysctest();
-void __ring3text__ __attribute__((__aligned__(PAGE_SIZE))) ring3_entry() {
+#define RING3_ENTRY __attribute__((__section__(".ring3.entry")))
+void RING3_ENTRY __attribute__((__aligned__(PAGE_SIZE))) ring3_entry() {
while (1) {
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处
+ // EDI = 用户态返回地址
+ // EBP = 用户态栈
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;"
- "movl $200, %%ebx;"
- "pushl %%ebp;"
- "movl %%esp, %%ebp;"
+ "nop;"
+ "nop;"
+ "pusha;"
+ "call get_eip;"
+ "get_eip:"
+ "popl %%edi;" // 获得EIP的值,注意此时EIP的位置为这条pop指令的地址
+ // 反汇编后计算了一下需要加8个字节才能跳到sysenter下一个指令
+ "addl $8, %%edi;"
+ "movl %%esp, %%ebp;"
"sysenter;"
- "sysexit_return_address:"
- : "=a"(__sysc_ret__)
- : "a"(SYSC_WAIT), "c"(ring3_entry));
-
- for (int i = 10000000; i > 0; i--) {
- for (int j = 1; j > 0; j--) {
- asm("nop;nop;nop;");
- }
- }
+ "popa;"
+ "nop;"
+ "nop;"
+ :"=a"(__sysc_ret__)
+ :"a"(SYSC_WAIT)
+ );
}
}
+void flush_tlb() {
+ asm volatile("movl %%cr3, %%eax;"
+ "movl %%eax, %%cr3;"
+ :
+ :
+ : "eax");
+}
+
void user_task_entry() {
current->priority = 7;
- unsigned long ring3_text_page = va2pa(ring3_entry);
- unsigned long ring3_bss_page = (unsigned long)page2pa(alloc_one_page(0));
-
- unsigned long *pt_text_page = (unsigned long *)page2va(alloc_one_page(0));
- unsigned long *pt_bss_page = (unsigned long *)page2va(alloc_one_page(0));
+ // ring3只占用一个page,页的起始位置放的是代码,页的末尾当栈用
+ // ring3的地址直接是物理地址
+ extern unsigned long ring3_page_addr;
+ extern unsigned long ring3_page_end;
+ unsigned long ring3_text_page =(unsigned long) &ring3_page_addr; // 不在内核空间的物理地址
+ unsigned long ring3_stack_top = (unsigned long) &ring3_page_end; // 不在内核空间的物理地址
- unsigned long *p = (unsigned long *)(pa2va(current->cr3));
+ unsigned long ring3_page_vaddr = 0x08000000; // 指定的ring3的虚拟地址
+ unsigned long ring3_stack_top_vaddr = ring3_page_vaddr + (ring3_stack_top - ring3_text_page);
+ int npte = get_npte(ring3_page_vaddr);
+ int npde = get_npde(ring3_page_vaddr);
- printd("page dir : %x %x %x %x\n", p, pt_text_page, ring3_text_page);
- printd("pt bss page %x %x\n", pt_bss_page, ring3_bss_page);
+ // 分配一个页表在用户空间对这页进行映射
+ pte_t *pgt = (pte_t *)page2va(alloc_one_page(0));
- // text: 0x0800_0000
- // bss: 0x3000_0000
- unsigned long text_at = 0x08000000;
- unsigned long bbs_at = 0x30000000;
+ memset(pgt, 0, PAGE_SIZE);
+ pgt[npte] = (pte_t)(ring3_text_page | PAGE_P | PAGE_US | PAGE_WR);
- 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 | PAGE_P | PAGE_WR | PAGE_US;
+ // 把这个页表映射到页目录
+ pde_t *pgd = pa2va(get_pgd());
+ pgd[npde] = (pde_t)(((unsigned long)va2pa(pgt)) | PAGE_P | PAGE_US | PAGE_WR);
- //
- LoadCR3(current->cr3);
+ // 到此完成了 ring3_page_vaddr -> ring3_text_page的映射
+ // 刷新tlb
+ flush_tlb();
- // 现在要准备返回用户态
- // eip --> edx
- // esp --> ecx
- asm volatile("sysexit;" ::"d"(0x08000000), "c"(0x30000000 + PAGE_SIZE - 100));
+ // 现在准备返回用户态
+ asm volatile("sysexit;" ::"d"(ring3_page_vaddr), "c"(ring3_stack_top_vaddr - 0x10));
}
return i;
}
-void reboot() { syscall1(SYSC_REBOOT, 0); }
+// void reboot() { syscall1(SYSC_REBOOT, 0); }
-void poweroff() { syscall1(SYSC_REBOOT, 1); }
+// void poweroff() { syscall1(SYSC_REBOOT, 1); }
-int systest() { return syscall0(SYSC_TEST); }
+// int systest() { return syscall0(SYSC_TEST); }
-int sysdebug(unsigned int v) { return syscall1(SYSC_DEBUG, v); }
+// int sysdebug(unsigned int v) { return syscall1(SYSC_DEBUG, v); }
-int pause(unsigned long tick) { return syscall1(SYSC_PAUSE, tick); }
+// int pause(unsigned long tick) { return syscall1(SYSC_PAUSE, tick); }
int vsprintf(char *buf, const char *fmt, char *args);
int sprintf(char *str, const char *fmtstr, ...) {