static void parse_initrd(Mbdata *mb) { if(!mb->flags & (1<<3)) kprintf("multiboot header has no modules\n"); int i; struct Mbmod *mods = (struct Mbmod*)VADDR_DIRECT(mb->mods_addr); for(i=0;i<mb->mods_count;i++){ kprintf("mbmod: %d %p %p\n", i, mods[i].start, mods[i].end); } if(mb->mods_count<1) return; initrd_begin = VADDR_DIRECT(mods[0].start); initrd_end = VADDR_DIRECT(mods[0].end); }
// Start additional processor running bootstrap code at addr. // See Appendix B of MultiProcessor Specification. void lapic_ap_start(int apicid, uint32_t addr) { int i; uint16_t *wrv; // "The BSP must initialize CMOS shutdown code to 0AH // and the warm reset vector (DWORD based at 40:67) to point at // the AP startup code prior to the [universal startup algorithm]." outb(IO_RTC, 0xF); // offset 0xF is shutdown code outb(IO_RTC+1, 0x0A); wrv = VADDR_DIRECT(0x40 << 4 | 0x67); wrv[0] = addr & 0xffff; wrv[1] = (addr ^ wrv[0]) >> 4; // "Universal startup algorithm." // Send INIT (level-triggered) interrupt to reset other CPU. lapicw(ICRHI, apicid << 24); lapicw(ICRLO, INIT | LEVEL | ASSERT); microdelay(200); lapicw(ICRLO, INIT | LEVEL); microdelay(100); // should be 10ms, but too slow in Bochs! // Send startup IPI (twice!) to enter bootstrap code. // Regular hardware is supposed to only accept a STARTUP // when it is in the halted state due to an INIT. So the second // should be ignored, but it is part of the official Intel algorithm. // Bochs complains about the second one. Too bad for Bochs. for(i = 0; i < 2; i++){ lapicw(ICRHI, apicid << 24); lapicw(ICRLO, STARTUP | (addr >> 12)); microdelay(200); } }
void cpu_up(int id) { extern char _bootother_start[]; extern uint64_t _bootother_size; extern void (*apstart)(void); char *stack; unsigned char *code = (unsigned char*)VADDR_DIRECT(0x7000); struct cpu *c = per_cpu_ptr(cpus, id); assert(c->id != myid()); assert(c->id == id); memcpy(code, _bootother_start, _bootother_size); stack = (char*)page2kva(alloc_pages_cpu(c, KSTACKPAGE)); assert(stack != NULL); kprintf("LAPIC %d, CODE %p PA: %p, STACK: %p\n", c->hwid, code, PADDR_DIRECT(code), stack); warmreset(PADDR_DIRECT(code)); *(uint32_t*)(code-4) = (uint32_t)PADDR_DIRECT(&apstart); *(uint64_t*)(code-12) = (uint64_t)stack + KSTACKSIZE; *(uint64_t*)(code-20) = (uint64_t)boot_cr3; // bootother.S sets this to 0x0a55face early on *(uint32_t*)(code-64) = 0; bcpuid = c->id; atomic_set(&bsync, 0); lapic_start_ap(c, PADDR_DIRECT(code)); while(atomic_read(&bsync) == 0) nop_pause(); rstrreset(); }
static void rstrreset(void) { volatile uint16_t *wrv; // Paranoid: set warm reset code and vector back to defaults outb(IO_RTC, 0xF); outb(IO_RTC+1, 0); wrv = (uint16_t*)VADDR_DIRECT(0x40<<4 | 0x67); wrv[0] = 0; wrv[1] = 0; }
pmd_t * get_pmd(pgd_t *pgdir, uintptr_t la, bool create) { #if PMXSHIFT == PUXSHIFT return get_pud(pgdir, la, create); #else /* PMXSHIFT == PUXSHIFT */ pud_t *pudp; if ((pudp = get_pud(pgdir, la, create)) == NULL) { return NULL; } if (!(*pudp & PTE_P)) { struct Page *page; if (!create || (page = alloc_page()) == NULL) { return NULL; } set_page_ref(page, 1); uintptr_t pa = page2pa(page); memset(VADDR_DIRECT(pa), 0, PGSIZE); *pudp = pa | PTE_U | PTE_W | PTE_P; } return &((pmd_t *)VADDR_DIRECT(PUD_ADDR(*pudp)))[PMX(la)]; #endif /* PMXSHIFT == PUXSHIFT */ }
static void warmreset(uint32_t addr) { volatile uint16_t *wrv; // "The BSP must initialize CMOS shutdown code to 0AH // and the warm reset vector (DWORD based at 40:67) to point at // the AP startup code prior to the [universal startup algorithm]." outb(IO_RTC, 0xF); // offset 0xF is shutdown code outb(IO_RTC+1, 0x0A); wrv = (uint16_t*)VADDR_DIRECT(0x40<<4 | 0x67); // Warm reset vector wrv[0] = 0; wrv[1] = addr >> 4; }
static void mbmem2e820(Mbdata *mb) { static struct e820map m; if(!(mb->flags & (1<<6))) panic("multiboot header has no memory map"); e820map_addr = &m; uint8_t *p = (uint8_t*) VADDR_DIRECT(mb->mmap_addr); uint8_t *ep = p + mb->mmap_length; int i = 0; while(p<ep){ if(i>=E820MAX) break; struct Mbmem *mbmem = (Mbmem*)p; p += 4 + mbmem->size; m.map[i].addr = mbmem->base; m.map[i].size = mbmem->length; m.map[i].type = mbmem->type; i++; } m.nr_map = i; }
static uint32_t lapicw(int index, uint32_t value) { ((volatile uint32_t *)VADDR_DIRECT(sysconf.lapic_phys))[index] = value; return ((volatile uint32_t *)VADDR_DIRECT(sysconf.lapic_phys))[ID]; }
static uint32_t lapicr(int index) { return ((volatile uint32_t *)VADDR_DIRECT(sysconf.lapic_phys))[index]; }
int kern_init(uint64_t mbmagic, uint64_t mbmem) { extern char edata[], end[]; memset(edata, 0, end - edata); /* percpu variable for CPU0 is preallocated */ percpu_offsets[0] = __percpu_start; cons_init(); // init the console const char *message = "(THU.CST) os is loading ..."; kprintf("%s\n\n", message); if(mbmagic == MULTIBOOT_BOOTLOADER_MAGIC){ kprintf("Multiboot dectected: param %p\n", (void*)mbmem); mbmem2e820((Mbdata*)VADDR_DIRECT(mbmem)); parse_initrd((Mbdata*)VADDR_DIRECT(mbmem)); } print_kerninfo(); /* get_cpu_var not available before tls_init() */ hz_init(); gdt_init(per_cpu_ptr(cpus, 0)); tls_init(per_cpu_ptr(cpus, 0)); acpitables_init(); lapic_init(); numa_init(); pmm_init_numa(); // init physical memory management, numa awared /* map the lapic */ lapic_init_late(); //init the acpi stuff idt_init(); // init interrupt descriptor table pic_init(); // init interrupt controller // acpi_conf_init(); percpu_init(); cpus_init(); #ifdef UCONFIG_ENABLE_IPI ipi_init(); #endif refcache_init(); vmm_init(); // init virtual memory management sched_init(); // init scheduler proc_init(); // init process table sync_init(); // init sync struct /* ext int */ ioapic_init(); acpi_init(); ide_init(); // init ide devices #ifdef UCONFIG_SWAP swap_init(); // init swap #endif fs_init(); // init fs clock_init(); // init clock interrupt mod_init(); trap_init(); //XXX put here? bootaps(); intr_enable(); // enable irq interrupt #ifdef UCONFIG_HAVE_LINUX_DDE36_BASE dde_kit_init(); #endif /* do nothing */ cpu_idle(); // run idle process }