From 9f407c493c33928e0f19b834699d9694036ca42e Mon Sep 17 00:00:00 2001 From: John Hodge Date: Fri, 14 May 2010 20:54:59 +0800 Subject: [PATCH] More work on x86_64 port, near compiling now --- Kernel/Makefile.BuildNum | 2 +- Kernel/arch/x86/proc.asm | 5 +- Kernel/arch/x86/proc.c | 4 +- Kernel/arch/x86_64/desctab.asm | 156 ++++++++++++++++++++++-------- Kernel/arch/x86_64/include/arch.h | 33 +++---- Kernel/arch/x86_64/include/proc.h | 13 ++- Kernel/arch/x86_64/mm_phys.c | 38 +++++++- Kernel/arch/x86_64/mm_virt.c | 58 +++++++++++ Kernel/arch/x86_64/proc.c | 9 +- Kernel/arch/x86_64/start64.asm | 49 ++++++++++ 10 files changed, 284 insertions(+), 83 deletions(-) diff --git a/Kernel/Makefile.BuildNum b/Kernel/Makefile.BuildNum index efeefa47..70cc0b33 100644 --- a/Kernel/Makefile.BuildNum +++ b/Kernel/Makefile.BuildNum @@ -1 +1 @@ -BUILD_NUM = 2158 +BUILD_NUM = 2159 diff --git a/Kernel/arch/x86/proc.asm b/Kernel/arch/x86/proc.asm index b1843c78..d905c249 100644 --- a/Kernel/arch/x86/proc.asm +++ b/Kernel/arch/x86/proc.asm @@ -74,13 +74,12 @@ SpawnTask: ; ; Calls a user fault handler ; -[global Proc_AlterUserReturnAddr] +[global Proc_ReturnToUser] [extern Proc_GetCurThread] -Proc_AlterUserReturnAddr: +Proc_ReturnToUser: ; EBP is the handler to use call Proc_GetCurThread - xchg bx, bx ; EAX is the current thread mov ebx, eax diff --git a/Kernel/arch/x86/proc.c b/Kernel/arch/x86/proc.c index 2451cd0b..45c5a561 100644 --- a/Kernel/arch/x86/proc.c +++ b/Kernel/arch/x86/proc.c @@ -39,7 +39,7 @@ extern tThread *Threads_GetNextToRun(int CPU); extern void Threads_Dump(); extern tThread *Threads_CloneTCB(Uint *Err, Uint Flags); extern void Isr8(); // Double Fault -extern void Proc_AlterUserReturnAddr(); +extern void Proc_ReturnToUser(); // === PROTOTYPES === void ArchThreads_Init(); @@ -703,7 +703,7 @@ void Proc_CallFaultHandler(tThread *Thread) { // Rewinds the stack and calls the user function // Never returns - __asm__ __volatile__ ("mov %0, %%ebp;\n\tcall Proc_AlterUserReturnAddr" :: "r"(Thread->FaultHandler)); + __asm__ __volatile__ ("mov %0, %%ebp;\n\tcall Proc_ReturnToUser" :: "r"(Thread->FaultHandler)); for(;;); } diff --git a/Kernel/arch/x86_64/desctab.asm b/Kernel/arch/x86_64/desctab.asm index aec7656c..de606ea6 100644 --- a/Kernel/arch/x86_64/desctab.asm +++ b/Kernel/arch/x86_64/desctab.asm @@ -3,49 +3,12 @@ ; [BITS 64] -MM_LOCALAPIC equ 0xFFFFFD0000000000 - -[section .text] -Desctab_Init: - ; Install IRQ Handlers - -[section .data] -gIDT: - times 256 dw 0x00080000, 0x00008E00, 0, 0 ; 64-bit Interrupt Gate, CS = 0x8, IST0 - -%macro DEFERR 1 -Isr%1: - push 0 - push %1 - jmp ErrorCommon -%endmacro -%macro DEFERRNO 1 -Isr%1: - push %1 - jmp ErrorCommon -%endmacro - -%macro DEFIRQ 1 -Irq%1: - push 0 - push %1 - jmp IrqCommon -%endmacro +%define NUM_IRQ_CALLBACKS 4 -%macro PUSH_EX 1-* - %rep %0 - push %1 - %rotate 1 - %endrep -%endmacro -%macro POP_EX 1-* - %rep %0 - %rotate -1 - pop %1 - %endrep -%endmacro +MM_LOCALAPIC equ 0xFFFFFD0000000000 %macro PUSH_GPR 0 + mov [rsp-0x60], rsp mov [rsp-0x08], r15 mov [rsp-0x10], r14 mov [rsp-0x18], r13 @@ -57,7 +20,6 @@ Irq%1: mov [rsp-0x48], rdi mov [rsp-0x50], rsi mov [rsp-0x58], rbp - mov [rsp-0x60], rsp mov [rsp-0x68], rbx mov [rsp-0x70], rdx mov [rsp-0x78], rcx @@ -72,8 +34,8 @@ Irq%1: mov r12, [rsp-0x20] mov r11, [rsp-0x28] mov r10, [rsp-0x30] - mov r9, [rsp-0x38] - mov r8, [rsp-0x40] + mov r9, [rsp-0x38] + mov r8, [rsp-0x40] mov rdi, [rsp-0x48] mov rsi, [rsp-0x50] mov rbp, [rsp-0x58] @@ -84,6 +46,107 @@ Irq%1: mov rax, [rsp-0x80] %endmacro +[section .text] +Desctab_Init: + ; Install IRQ Handlers + ret + +; int IRQ_AddHandler(int IRQ, void (*Handler)(int IRQ)) +; Return Values: +; 0 on Success +; -1 on an invalid IRQ Number +; -2 when no slots are avaliable +[global IRQ_AddHandler] +IRQ_AddHandler: + ; RDI - IRQ Number + ; RSI - Callback + + cmp rdi, 16 + jb .numOK + xor rax, rax + dec rax + jmp .ret +.numOK: + + mov rax, rdi + shr rax, 3+2 + mov rcx, gaIRQ_Handlers + add rax, rcx + + ; Find a free callback slot + %rep NUM_IRQ_CALLBACKS + mov rdx, [rax] + test rdx, rdx + jz .assign + add rax, 8 + %endrep + ; None found, return -2 + xor rax, rax + dec rax + dec rax + jmp .ret + + ; Assign the IRQ Callback +.assign: + mov [rax], rsi + xor rax, rax + +.ret: + ret + +%macro DEFERR 1 +Isr%1: + push 0 + push %1 + jmp ErrorCommon +%endmacro +%macro DEFERRNO 1 +Isr%1: + push %1 + jmp ErrorCommon +%endmacro + +%macro DEFIRQ 1 +Irq%1: + push 0 + push %1 + jmp IrqCommon +%endmacro + +IrqCommon: + PUSH_GPR + + mov rbx, [rsp+16*8] ; Calculate address + shr rbx, 3+2 ; *8*4 + mov rax, gaIRQ_Handlers + add rbx, rax + + %assign i 0 + %rep NUM_IRQ_CALLBACKS + mov rax, [rbx] + test rax, rax + mov rdi, [rsp+16*8] ; Get IRQ number + jz .skip.%[i] + call rax ; 2 Bytes (Op and Mod/RM) +.skip.%[i]: + add rbx, 8 + %assign i i+1 + %endrep + + mov rdi, [rsp+16*8] ; Get IRQ number + cmp rdi, 8 + mov al, 0x20 + jb .skipAckSecondary + mov dx, 0x00A0 + out dx, al +.skipAckSecondary: + mov dx, 0x0020 + out dx, al + + POP_GPR + add rsp, 16 + iret + [extern Proc_Scheduler] SchedulerIRQ: ; TODO: Find Current CPU @@ -100,3 +163,10 @@ SchedulerIRQ: ;POP_FPU POP_GPR iret + +[section .data] +gIDT: + times 256 dw 0x00080000, 0x00008E00, 0, 0 ; 64-bit Interrupt Gate, CS = 0x8, IST0 + +gaIRQ_Handlers: + times 16*NUM_IRQ_CALLBACKS dq 0 diff --git a/Kernel/arch/x86_64/include/arch.h b/Kernel/arch/x86_64/include/arch.h index 22c551fc..0dc99277 100644 --- a/Kernel/arch/x86_64/include/arch.h +++ b/Kernel/arch/x86_64/include/arch.h @@ -44,25 +44,24 @@ typedef volatile int tSpinlock; // TODO: Fix this structure typedef struct sSyscallRegs { - Uint Arg4, Arg5; // RDI, RSI - Uint Arg6; // RBP - Uint Resvd2[1]; // Kernel RSP union { - Uint Arg1; - Uint Error; - }; // RBX - union { - Uint Arg3; - Uint RetHi; // High 64 bits of ret - }; // RDX - Uint Arg2; // RCX - union { - Uint Num; - Uint Return; + Uint Num; + Uint Return; }; // RAX - Uint Resvd3[5]; // Int, Err, rip, CS, ... - Uint StackPointer; // RSP - Uint Resvd4[1]; // SS + Uint Arg4; // RCX + Uint Arg3; // RDX + Uint Error; // RBX + Uint Resvd1[2]; // Kernel RSP, RBP + Uint Arg2; // RSI + Uint Arg1; // RDI + Uint Arg5; // R8 + Uint Arg6; // R9 + Uint Resvd2[6]; // R10 - R15 + Uint Resvd3[5]; // IntNum, ErrCode, RIP, CS, RFLAGS + + Uint Resvd4[5]; // Int, Err, rip, CS, ... + Uint StackPointer; // RSP + Uint Resvd5[1]; // SS } tSyscallRegs; #endif diff --git a/Kernel/arch/x86_64/include/proc.h b/Kernel/arch/x86_64/include/proc.h index d78019de..8217c68d 100644 --- a/Kernel/arch/x86_64/include/proc.h +++ b/Kernel/arch/x86_64/include/proc.h @@ -11,14 +11,13 @@ // Register Structure // TODO: Rebuild once IDT code is done typedef struct { - Uint ds, es, fs, gs; - Uint r15, r14, r13, r12; - Uint r11, r10, r9, r8; - Uint rdi, rsi, rbp, krsp; - Uint rbx, rdx, rcx, rax; + Uint rax, rcx, rdx, rbx; + Uint krsp, rbp, rsi, rdi; + Uint r8, r9, r10, r11; + Uint r12, r13, r14, r15; Uint int_num, err_code; - Uint eip, cs; - Uint eflags, esp, ss; + Uint rip, cs; + Uint rflags, rsp, ss; } tRegs; /** diff --git a/Kernel/arch/x86_64/mm_phys.c b/Kernel/arch/x86_64/mm_phys.c index 3535fbca..dd8ddf66 100644 --- a/Kernel/arch/x86_64/mm_phys.c +++ b/Kernel/arch/x86_64/mm_phys.c @@ -4,6 +4,7 @@ * Physical Memory Manager */ #include +#include //#include enum eMMPhys_Ranges @@ -28,8 +29,33 @@ Uint64 giPhysRangeLast[NUM_MM_PHYS_RANGES]; // Last free page in each range Uint64 giMaxPhysPage = 0; // Maximum Physical page // === CODE === -void MM_InitPhys() +void MM_InitPhys(tMBoot_Info *MBoot) { + tMBoot_MMapEnt *mmapStart; + tMBoot_MMapEnt *ent; + Uint64 maxAddr = 0; + + // Scan the physical memory map + mmapStart = (void *)( KERNEL_BASE | MBoot->MMapAddr ); + ent = mmapStart; + while( (Uint)ent < (Uint)mmapStart + MBoot->MMapLength ) + { + // Adjust for the size of the entry + ent->Size += 4; + + // If entry is RAM and is above `maxAddr`, change `maxAddr` + if(ent->Type == 1 && ent->Base + ent->Length > maxAddr) + maxAddr = ent->Base + ent->Length; + // Go to next entry + ent = (tMBoot_MMapEnt *)( (Uint)ent + ent->Size ); + } + + if(maxAddr == 0) { + giMaxPhysPage = (MBoot->HighMem >> 2) + 256; // HighMem is a kByte value + } + else { + giMaxPhysPage = maxAddr >> 12; + } } /** @@ -162,9 +188,12 @@ tPAddr MM_AllocPhys(void) return MM_AllocPhysRange(1, -1); } +/** + * \brief Reference a physical page + */ void MM_RefPhys(tPAddr PAddr) { - if( PAddr > giMaxPhysPage ) return ; + if( PAddr >> 12 > giMaxPhysPage ) return ; gaiPageReferences[ PAddr >> 12 ] ++; gaPrimaryBitmap[PAddr >> 18] |= 1 << ((PAddr>>12) & 63); @@ -172,9 +201,12 @@ void MM_RefPhys(tPAddr PAddr) gaSuperBitmap[PAddr >> 24] |= 1 << ((PAddr >> 18) & 64); } +/** + * \brief Dereference a physical page + */ void MM_DerefPhys(tPAddr PAddr) { - if( PAddr > giMaxPhysPage ) return ; + if( PAddr >> 12 > giMaxPhysPage ) return ; gaiPageReferences[ PAddr >> 12 ] --; if( gaiPageReferences[ PAddr >> 12 ] ) { diff --git a/Kernel/arch/x86_64/mm_virt.c b/Kernel/arch/x86_64/mm_virt.c index 41075757..4cce4854 100644 --- a/Kernel/arch/x86_64/mm_virt.c +++ b/Kernel/arch/x86_64/mm_virt.c @@ -76,6 +76,18 @@ int MM_Map(tVAddr VAddr, tPAddr PAddr) return 1; } +void MM_Unmap(tVAddr VAddr) +{ + // Check PML4 + if( !(PAGEMAPLVL4(VAddr >> 39) & 1) ) return ; + // Check PDP + if( !(PAGEDIRPTR(VAddr >> 30) & 1) ) return ; + // Check Page Dir + if( !(PAGEDIR(VAddr >> 21) & 1) ) return ; + + PAGETABLE(VAddr >> 12) = 0; +} + /** * \brief Allocate a block of memory at the specified virtual address */ @@ -95,6 +107,18 @@ tPAddr MM_Allocate(tVAddr VAddr) return ret; } +void MM_Deallocate(tVAddr VAddr) +{ + tPAddr phys; + + phys = MM_GetPhysAddr(VAddr); + if(!phys) return ; + + MM_Unmap(VAddr); + + MM_DerefPhys(phys); +} + /** * \brief Get the physical address of a virtual location */ @@ -179,6 +203,9 @@ void MM_SetFlags(tVAddr VAddr, Uint Flags, Uint Mask) } } +/** + * \brief Get the flags applied to a page + */ Uint MM_GetFlags(tVAddr VAddr) { tPAddr *ent; @@ -208,3 +235,34 @@ Uint MM_GetFlags(tVAddr VAddr) return ret; } + +// --- Hardware Mappings --- +/** + * \brief Map a range of hardware pages + */ +tVAddr MM_MapHWPages(tPAddr PAddr, Uint Number) +{ + Log_KernelPanic("MM", "TODO: Implement MM_MapHWPages"); + return 0; +} + +/** + * \brief Free a range of hardware pages + */ +void MM_UnmapHWPages(tVAddr VAddr, Uint Number) +{ + Log_KernelPanic("MM", "TODO: Implement MM_UnmapHWPages"); +} + +// --- Tempory Mappings --- +tVAddr MM_MapTemp(tPAddr PAddr) +{ + Log_KernelPanic("MM", "TODO: Implement MM_MapTemp"); + return 0; +} + +void MM_FreeTemp(tVAddr VAddr) +{ + Log_KernelPanic("MM", "TODO: Implement MM_FreeTemp"); + return ; +} diff --git a/Kernel/arch/x86_64/proc.c b/Kernel/arch/x86_64/proc.c index b30eb224..038cc612 100644 --- a/Kernel/arch/x86_64/proc.c +++ b/Kernel/arch/x86_64/proc.c @@ -38,7 +38,7 @@ extern tThread *gDeleteThreads; extern tThread *Threads_GetNextToRun(int CPU); extern void Threads_Dump(); extern tThread *Threads_CloneTCB(Uint *Err, Uint Flags); -extern void Proc_AlterUserReturnAddr(); +extern void Proc_ReturnToUser(); // === PROTOTYPES === void ArchThreads_Init(); @@ -640,11 +640,6 @@ int Proc_Demote(Uint *Err, int Dest, tRegs *Regs) // Change the Segment Registers Regs->cs = (((Dest+1)<<4) | Dest) - 8; Regs->ss = ((Dest+1)<<4) | Dest; - // Check if the GP Segs are GDT, then change them - if(!(Regs->ds & 4)) Regs->ds = ((Dest+1)<<4) | Dest; - if(!(Regs->es & 4)) Regs->es = ((Dest+1)<<4) | Dest; - if(!(Regs->fs & 4)) Regs->fs = ((Dest+1)<<4) | Dest; - if(!(Regs->gs & 4)) Regs->gs = ((Dest+1)<<4) | Dest; return 0; } @@ -657,7 +652,7 @@ void Proc_CallFaultHandler(tThread *Thread) { // Rewinds the stack and calls the user function // Never returns - __asm__ __volatile__ ("mov %0, %%rbp;\n\tcall Proc_AlterUserReturnAddr" :: "r"(Thread->FaultHandler)); + __asm__ __volatile__ ("mov %0, %%rbp;\n\tcall Proc_ReturnToUser" :: "r"(Thread->FaultHandler)); for(;;); } diff --git a/Kernel/arch/x86_64/start64.asm b/Kernel/arch/x86_64/start64.asm index beb22e5a..c1f1e58b 100644 --- a/Kernel/arch/x86_64/start64.asm +++ b/Kernel/arch/x86_64/start64.asm @@ -15,7 +15,56 @@ GetRIP: mov rax, [rsp] ret +KSTACK_USERSTATE_SIZE equ (4+8+1+5)*4 ; SRegs, GPRegs, CPU, IRET +[global Proc_ReturnToUser] +[extern Proc_GetCurThread] +Proc_ReturnToUser: + ; RBP is the handler to use + + call Proc_GetCurThread + + ; EAX is the current thread + mov rbx, rax + mov rax, [rbx+40] ; Get Kernel Stack + sub rax, KSTACK_USERSTATE_SIZE + + ; + ; NOTE: This can cause corruption if the signal happens while the user + ; has called a kernel operation. + ; Good thing this can only be called on a user fault. + ; + + ; Get and alter User SP + mov rcx, [rax+KSTACK_USERSTATE_SIZE-3*8] + mov rdx, [rbx+60] ; Get Signal Number + mov [rcx-8], rdx + mov QWORD [rcx-16], User_Syscall_RetAndExit + sub rcx, 16 + + ; Restore Segment Registers + mov ax, 0x23 + mov ds, ax + mov es, ax + + push 0x23 ; SS + push rcx ; RSP + push 0x202 ; RFLAGS (IF and Rsvd) + push 0x1B ; CS + push rbp ; RIP + + iret + +[section .usertext] +User_Syscall_RetAndExit: + mov rdi, rax + jmp User_Syscall_Exit +User_Syscall_Exit: + xor rax, rax + ; RDI: Return Value + int 0xAC + [section .bss] [global gInitialKernelStack] resd 1024*1 ; 1 Page gInitialKernelStack: + -- 2.20.1