Mercurial > hg > Members > taiki > elilo
changeset 10:28550dbb2579
add new files
author | taiki |
---|---|
date | Tue, 26 Mar 2013 18:15:35 +0900 |
parents | 5910e0636c2e |
children | 6eb39a8c991f |
files | x86_64/elilo_kernel.o x86_64/pgtable_flags.h x86_64/ready_kernel.c x86_64/registers.h |
diffstat | 4 files changed, 498 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/x86_64/pgtable_flags.h Tue Mar 26 18:15:35 2013 +0900 @@ -0,0 +1,43 @@ +#ifndef PGTABLE_FLAGS +#define PGTABLE_FLAGS + +#define ENABLE 1 +#define DISABLE 0 + +#define PML4_SIZE 512 +#define PDPTE_SIZE 512 + +typedef struct _pml4_t { + UINT64 p:1; // 0 Present + UINT64 r_w:1; // 1 Read/Write + UINT64 u_s:1; // 2 User/Supervisor + UINT64 pwt:1; // 3 Page-level write-throuph + UINT64 pcd:1; // 4 Page-level cache disable + UINT64 a:1; // 5 Accessed + UINT64 ignored1:1; // 6 ignored + UINT64 ps:1; // 7 Reserved. must be 0 + UINT64 ignored2:4; // 11-8 ignored + UINT64 paddr :40;// 13-x (x-1)-50 include reserved + UINT64 ignored3:11; // 62-52 ignored + UINT64 xd:1; // 63 execute-disable +} pml4_t; + +typedef struct _pdpte_t { + UINT64 p:1; // 0 Present; must be 1 to map + UINT64 r_w:1; // 1 Read/write + UINT64 u_s :1; // 2 User/Supervisor + UINT64 pwt:1; // 3 Page-level write-through + UINT64 pcd:1; // 4 Page-level cache disable + UINT64 a:1; // 5 Accessed + UINT64 d:1; // 6 Dirty + UINT64 ps:1; // 7 Page size + UINT64 g :1; // 8 Global + UINT64 ignored1:3; // 9-11 ignored + UINT64 pat:1; // 12 has page directory + UINT64 reserved1 :17; // 13-29 Reserved. must be 0 + UINT64 paddr: 22; // 30-51 include reserved + UINT64 ignored :11; // 52-62 + UINT64 xd:1; // 63 execute-disable +} pdpte_t; + +#endif /* PGTABLE_FLAGS */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/x86_64/ready_kernel.c Tue Mar 26 18:15:35 2013 +0900 @@ -0,0 +1,389 @@ +#include <efi.h> +#include <efilib.h> + +#include "elilo.h" +#include "pgtable_flags.h" +#include "sysdeps.h" +#include "registers.h" + +#define ALIGN_4K 12 /* use 4KB aligned */ + +#define MEMCPY(to, from, cnt) { \ + UINT8 *t = (UINT8 *)(to); \ + UINT8 *f = (UINT8 *)(from); \ + UINTN n = cnt; \ + if (t && f && n && (t<f)) { \ + while (n--) { \ + *t++ = *f++; \ + } \ + } else if (t && f && n && (t>f)) { \ + t += n; \ + f += n; \ + while (n--) { \ + *t-- = *f--; \ + } \ + } \ +} + +#define MEMSET(ptr, size, val) { \ + UINT8 *p = (UINT8 *)(ptr); \ + UINTN n = (UINTN)(size); \ + UINT8 v = (UINT8)(val); \ + if (p && n) { \ + while (n--) { \ + *p++ = v; \ + } \ + } \ +} + +/* +VOID +enable_efer_flags() +{ + + asm volatile ("movl %0, %%ecx \n\t rdmsr \n\t btsl %1, %%eax\n\t wrmsr " :: "r"(msr_efer) ,"r"(efer_flg)); +} + +disable_efer_flags() +{ + asm volatile ("movl %0, %%ecx \n\t rdmsr \n\t btsl %1, %%eax\n\t wrmsr " :: "r"(msr_efer) ,"r"(efer_flg)); +} +*/ + + +extern pml4_t *pml4; +extern pdpte_t *pdpte; + +VOID +cpuid(UINTN *eax, UINTN *ebx, UINTN *ecx, UINTN *edx) +{ + asm volatile ("cpuid" : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) + : "0" (*eax), "2" (*ecx) : "memory"); +} + +INTN +enable_cr4_pae() +{ + cr4_t cr4; + MEMSET(&cr4, sizeof(UINT64), 0); + + asm volatile("mov %%cr4,%0\n\t" : "=r" (cr4)); + + cr4.pae = ENABLE; + cr4.pcide = DISABLE; + + asm volatile("mov %0,%%cr4": : "r" (cr4)); + //asm volatile("movq %%rax, %%cr4"::"a"(cr4_flag)); + return 0; +} + +UINTN +insert_addr_to_cr3(UINT64 addr) +{ + cr3_t cr3; + MEMSET(&cr3, sizeof(UINT64), 0); + + // asm volatile ("movq %0, %%rax \n\tmovq %%rax, %%cr3" :: "m"(addr) ); + + /* write cr3 */ + Print(L"Read cr3.\n"); + asm volatile("mov %%cr3,%0\n\t" : "=r" (cr3)); + Print(L"Getting cr3 is %lx pwt:%d, pcd:%d pdb 0x%lx\n addr:%lx \n", cr3, cr3.pwt, cr3.pcd, cr3.pdb, addr); + Print(L"%lx\n", cr3); + //addr = addr >> ALIGN_4K; + //cr3.pdb = addr; + Print(L"Write addr:%lx to cr3 / cr3.pdb: %lx.\n", addr, cr3.pdb); + asm volatile("mov %0,%%cr3": : "r" (cr3)); + Print(L"Written cr3.\n"); + return 0; +} + +INTN +disable_paging_cr0() +{ + cr0_t cr0; + MEMSET(&cr0, sizeof(UINT64), 0); + + asm volatile("mov %%cr0,%0\n\t" : "=r" (cr0)); + + cr0.pg = DISABLE; + + asm volatile("mov %0,%%cr0": : "r" (cr0)); + // asm volatile("movl %0, %%eax \n\t movq %%rax, %%cr0"::"m"(cr0_flag)); + return 0; +} + +INTN +enable_paging_cr0() +{ + cr0_t cr0; + MEMSET(&cr0, sizeof(UINT64), 0); + + asm volatile("mov %%cr0,%0\n\t" : "=r" (cr0)); + Print(L"Register cr0 : %lx \n", cr0); + cr0.pg = ENABLE; + asm volatile("mov %0,%%cr0": : "r" (cr0)); + // asm volatile("movl %0, %%eax \n\t movq %%rax, %%cr0"::"m"(cr0_flag)); + return 0; +} + +VOID +init_pgtable_value(VOID *addr, UINT32 size, UINT64 value) +{ + if (addr == NULL) { + Print(L"addr is not using.\n"); + return; + } + + UINT64 *tmp = (UINT64 *)addr; + + while(size--) { + *tmp++ = value; + } +} + +#define PML4_START 0x00101000 +#define PDPTE_START PML4_START + PML4_SIZE + +/* alloc pages use how many pages for 4KiB */ +#define PGCNT_BYTE 4096 + +/* PDPTE indicate original page is 1GB */ +#define ORIG_PAGE_SIZE 1048576 + + +/* init_pgtable() + * init pagetable. use IA-32e page table + * This function initialize PML4 and PDPTE + */ +UINT64 +init_pgtable() +{ + pml4 = (pml4_t *)PML4_START; + UINTN pml4_size = PML4_SIZE * sizeof(pml4_t) / PGCNT_BYTE; + Print(L"allocate pml4 ::%lx", pml4); + pml4 = (pml4_t *)alloc_pages(pml4_size, EfiLoaderData, AllocateAddress, pml4); + if (pml4 == NULL) { + Print(L"can not allocate pml4.\n"); + return -1; + } + + pdpte = (pdpte_t *)PDPTE_START; + Print(L"allocate pdpte ::%lx", pdpte); + UINTN pdpte_size = PDPTE_SIZE * PML4_SIZE * sizeof(pdpte_t) / PGCNT_BYTE; + pdpte = (pdpte_t *)alloc_pages(pdpte_size , EfiLoaderData, AllocateAddress, pdpte); + Print(L"pdpte :%lx", pdpte); + + if (pdpte == NULL) { + Print(L"can not allocate pdpte.\n"); + return -1; + } + + init_pgtable_value((VOID *)pml4, PML4_SIZE * sizeof(pml4_t), 0); + init_pgtable_value((VOID *)pdpte, PDPTE_SIZE * PML4_SIZE * sizeof(pdpte_t), 0); + + UINT64 orig_addr_start = PDPTE_START + (PDPTE_SIZE * PML4_SIZE * sizeof(UINT64)); + UINTN i = 0; + for (; i<PML4_SIZE ;i++) { + UINT64 tmp_pdpte_addr = (UINT64)&pdpte[PDPTE_SIZE * i]; + tmp_pdpte_addr = tmp_pdpte_addr >> ALIGN_4K; + pml4[i].paddr = tmp_pdpte_addr; + pml4[i].p = ENABLE; + UINTN j = 0; + for (;j < PDPTE_SIZE; j++) { + pdpte[(PDPTE_SIZE * i) + j].p = ENABLE; + pdpte[(PDPTE_SIZE * i) + j].ps = ENABLE; + pdpte[(PDPTE_SIZE * i) + j].paddr = orig_addr_start + (PDPTE_SIZE * i + j * ORIG_PAGE_SIZE) * sizeof(UINT64); + } + } + + return (UINT64)pml4; +} + +VOID +stop_kernel() +{ + Print(L"stop\n"); + while(1) { + } +} + +typedef struct _estatus { + unsigned long long estart; + unsigned long esize; + unsigned int etype; + int merge; +} estatus_t; + +enum MAP_DATA { + MAP_MAX = 128 +}; + + +static VOID +fill_memory_map(struct e820entry *map, + UINTN *nr_map, + UINT64 start, + UINT64 size, + UINT64 type, + estatus_t *est) +{ + UINTN x = *nr_map; + if ((x > 0) && + (map[x-1].addr + map[x-1].size == start) && + (map[x-1].type == type)) { + est->estart = map[x-1].addr; + est->esize = map[x-1].size; + est->etype = map[x-1].type; + est->merge++; + return; + } + + if (x<MAP_MAX) { + map[x].addr = start; + map[x].size = size; + map[x].type = type; + (*nr_map)++; + est->merge=0; + return; + } + + if ((est->etype != type) || (est->estart + est->esize) != start) { + est->merge = 0; + est->estart = start; + est->esize = size; + est->etype = type; + } + + est->estart += est->esize; + est->esize += size; + est->merge++; + + return; +} + +VOID +set_memory_map(mmap_desc_t *mmapd) +{ + UINTN nr_map; + UINT64 start, end, size, type; + nr_map = mmapd->map_size/mmapd->desc_size; + estatus_t *est; + struct e820entry *map; + + UINTN i; + for (i=0; i <nr_map ;i++) { + EFI_MEMORY_DESCRIPTOR p = mmapd->md[i]; + switch (p.Type) { + case EfiReservedMemoryType: + Print(L"| reserved memory."); + break; + case EfiLoaderCode: + Print(L"| loader code."); + break; + case EfiLoaderData: + Print(L"| loader data."); + break; + case EfiBootServicesCode: + Print(L"| boot services code."); + break; + case EfiBootServicesData: + Print(L"| boot services data."); + break; + case EfiConventionalMemory: + Print(L"| conventional memory."); + break; + case EfiUnusableMemory: + Print(L"| unusable memory."); + break; + case EfiACPIReclaimMemory: + Print(L"| ACPI reclaim memory."); + break; + case EfiACPIMemoryNVS: + Print(L"| ACPI memory NVS."); + break; + case EfiMemoryMappedIO: + Print(L"| memory mapped IO."); + break; + case EfiMemoryMappedIOPortSpace: + Print(L"| memory mapped IO port space."); + break; + case EfiPalCode: + Print(L"| pal code. "); + break; + case EfiMaxMemoryType: + Print(L"| max memory type."); + break; + } + } + return; +} + + +EFI_STATUS +start_elilo_kernel(EFI_HANDLE image) +{ + Print(L"Start original ELILO kernel.\n"); + close_devices(); + + /* + mmap_desc_t mmapd; + get_memmap(&mmapd); + set_memory_map(&mmapd); + */ + + UINTN map_size, cookie, size, version; + map_size = EFI_PAGE_SIZE * 2; + EFI_MEMORY_DESCRIPTOR *md; + + EFI_STATUS status = uefi_call_wrapper(BS->AllocatePool, 3, EfiLoaderData, map_size, &md); + if (EFI_ERROR(status)) { + Print(L"error 'allocate pool' %r \n", status); + } + + status = uefi_call_wrapper(BS->GetMemoryMap, 5, &map_size, md, &cookie, &size, &version); + if (EFI_ERROR(status)) { + Print(L"error 'get memory map' %r \n", status); + } + + status = uefi_call_wrapper(BS->ExitBootServices, 2, image, cookie); + if (EFI_ERROR(status)) { + Print(L"error 'exit boot services' %r \n", status); + } + + asm volatile ("cli"::); + + MEMSET(gdt_addr.base, gdt_addr.limit, 0); + MEMCPY(gdt_addr.base, init_gdt, sizeof_init_gdt); + + asm volatile ( "lidt %0" : : "m" (idt_addr) ); + asm volatile ( "lgdt %0" : : "m" (gdt_addr) ); + + UINTN eax = 0, ebx = 0, ecx = 0, edx = 0; + eax = 0x80000008; + cpuid(&eax, &ebx, &ecx, &edx); + Print(L"eax %x\n", eax); + eax &= PHYADDR_WIDTH; + Print(L"use pagetable wise %d\n", eax); + + Print(L"disable cr0...\n"); + disable_paging_cr0(); + + Print(L"init pagetable...\n"); + init_pgtable(); + + UINT64 addr = PML4_START; + Print(L"insert addr %lx to cr3...\n", addr); + insert_addr_to_cr3(addr); + + Print(L"enable paging cr0...\n"); + enable_cr4_pae(); + enable_paging_cr0(); + + Print(L"finish to initialize...\n"); + + asm volatile ("hlt" : : ); + + Print(L"finish internal kernel\n"); + return EFI_SUCCESS; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/x86_64/registers.h Tue Mar 26 18:15:35 2013 +0900 @@ -0,0 +1,66 @@ +#ifndef REGISTERS +#define REGISTERS + +typedef struct _cr3_t { + UINT64 ignored1:3; + UINT64 pwt:1; /* page-level write through */ + UINT64 pcd:1; /* page-level cache disable */ + UINT64 ignored2:7; + UINT64 pdb:40; /* page directory base */ + UINT64 reserved :12; +} cr3_t; +#define PHYADDR_WIDTH 127 + +typedef struct _cr4_t { + UINT64 vme:1; + UINT64 pvi:1; + UINT64 tsd:1; + UINT64 de:1; + UINT64 pse:1; // page size extensions + UINT64 pae:1; // physical address extension + UINT64 mce:1; + UINT64 pge:1; + UINT64 pce:1; + UINT64 osfxsr:1; + UINT64 osxmmexcept:1; + UINT64 ignored2 :2; + UINT64 vmxe: 1; + UINT64 smxe: 1; + UINT64 ignored3: 1; + UINT64 fsgsbase: 1; + UINT64 pcide: 1; + UINT64 osxsave: 1; + UINT64 ignored4: 1; + UINT64 smep: 1; + UINT64 reserved:43; +} cr4_t; + +typedef struct _cr0_t { + UINT64 pe :1; + UINT64 mp :1; + UINT64 em :1; + UINT64 ts :1; + UINT64 et :1; + UINT64 ne :1; + UINT64 ignored1 :10; + UINT64 wp :1; + UINT64 ignored2 :1; + UINT64 am :1; + UINT64 ignored3 :10; + UINT64 nw :1; + UINT64 cd :1; + UINT64 pg :1; /* pageing */ +} cr0_t; + +typedef struct _efer_t { + UINT64 syscall_enable :1; + UINT64 reserved1:7; + UINT64 ia32e_enable :1; + UINT64 reserved2 :1; + UINT64 ia32e_active :1; + UINT64 edb_enable :1; + UINT64 reserved3 :52; +} efer_t; + + +#endif /* REGISTERS */