static uint16 alloc_idle_TSS (int cpu_num) { int i; descriptor *ad = (descriptor *)KERN_GDT; quest_tss *pTSS = (quest_tss *) (&idleTSS[cpu_num]); void idle_task (void); /* Search 2KB GDT for first free entry */ for (i = 1; i < 256; i++) if (!(ad[i].fPresent)) break; if (i == 256) panic ("No free selector for TSS"); ad[i].uLimit0 = sizeof (idleTSS[cpu_num]) - 1; ad[i].uLimit1 = 0; ad[i].pBase0 = (u32) pTSS & 0xFFFF; ad[i].pBase1 = ((u32) pTSS >> 16) & 0xFF; ad[i].pBase2 = (u32) pTSS >> 24; ad[i].uType = 0x09; /* 32-bit tss */ ad[i].uDPL = 0; /* Only let kernel perform task-switching */ ad[i].fPresent = 1; ad[i].f0 = 0; ad[i].fX = 0; ad[i].fGranularity = 0; /* Set granularity of tss in bytes */ u32 *stk = map_virtual_page (alloc_phys_frame () | 3); pTSS->CR3 = (u32) get_pdbr (); pTSS->initial_EIP = (u32) & idle_task; stk[1023] = pTSS->initial_EIP; pTSS->EFLAGS = F_1 | F_IOPL0; pTSS->ESP = (u32) &stk[1023]; pTSS->EBP = pTSS->ESP; /* Return the index into the GDT for the segment */ return i << 3; }
/** * Prints memory info */ void print_meminfo() { printk("Total mem: %d MB\nFree mem: %d MB\n", get_mem_size() / 1024, (get_max_blocks() - get_used_blocks()) * 4 / 1024); printk("Heap size: %d KB Free heap: %d KB\n", get_heap_size() / 1024, (get_heap_size() - get_used_heap()) / 1024); printk("cr0: %x cr2: %x cr3: %x\n", get_cr0(), get_cr2(), get_pdbr()); }
/* Create an address space for boot modules */ static uint16 load_module (multiboot_module * pmm, int mod_num) { uint32 *plPageDirectory = get_phys_addr (pg_dir[mod_num]); uint32 *plPageTable = get_phys_addr (pg_table[mod_num]); void *pStack = get_phys_addr (ul_stack[mod_num]); /* temporarily map pmm->pe in order to read pph->p_memsz */ Elf32_Ehdr *pe, *pe0 = map_virtual_page ((uint) pmm->pe | 3); Elf32_Phdr *pph = (void *) pe0 + pe0->e_phoff; void *pEntry = (void *) pe0->e_entry; int i, c, j; uint32 *stack_virt_addr; uint32 page_count = 1; /* find out how many pages for the module */ for (i = 0; i < pe0->e_phnum; i++) { if (pph->p_type == PT_LOAD) page_count += (pph->p_memsz >> 12); pph = (void *) pph + pe0->e_phentsize; } /* now map the entire module */ pe = map_contiguous_virtual_pages ((uint) pmm->pe | 3, page_count); unmap_virtual_page (pe0); pph = (void *) pe + pe->e_phoff; /* Populate ring 3 page directory with kernel mappings */ memcpy (&plPageDirectory[1023], (void *) (((uint32) get_pdbr ()) + 4092), 4); /* LAPIC/IOAPIC mappings */ memcpy (&plPageDirectory[1019], (void *) (((uint32) get_pdbr ()) + 4076), 4); /* Populate ring 3 page directory with entries for its private address space */ plPageDirectory[0] = (uint32) plPageTable | 7; plPageDirectory[1022] = (uint32) get_phys_addr (kls_pg_table[mod_num]) | 3; kls_pg_table[mod_num][0] = (uint32) get_phys_addr (kl_stack[mod_num]) | 3; /* Walk ELF header */ for (i = 0; i < pe->e_phnum; i++) { if (pph->p_type == PT_LOAD) { /* map pages loaded from file */ c = (pph->p_filesz + 0xFFF) >> 12; /* #pages to load for module */ for (j = 0; j < c; j++) plPageTable[((uint32) pph->p_vaddr >> 12) + j] = (uint32) pmm->pe + (pph->p_offset & 0xFFFFF000) + (j << 12) + 7; /* zero remainder of final page */ memset ((void *) pe + pph->p_offset + pph->p_filesz, 0, (pph->p_memsz - pph->p_filesz) & 0x0FFF); /* map additional zeroed pages */ c = (pph->p_memsz + 0xFFF) >> 12; /* Allocate space for bss section. Use temporary virtual memory for * memset call to clear physical frame(s) */ for (; j <= c; j++) { uint32 page_frame = (uint32) alloc_phys_frame (); void *virt_addr = map_virtual_page (page_frame | 3); memset (virt_addr, 0, 0x1000); plPageTable[((uint32) pph->p_vaddr >> 12) + j] = page_frame + 7; unmap_virtual_page (virt_addr); } } pph = (void *) pph + pe->e_phentsize; }