// Bootstrap processor gets here after setting up the hardware. // Additional processors start here. static void mpmain(void) { cprintf("cpu%d: mpmain\n", cpu()); idtinit(); if(cpu() != mp_bcpu()) lapic_init(cpu()); setupsegs(0); xchg(&cpus[cpu()].booted, 1); cprintf("cpu%d: scheduling\n"); scheduler(); }
/** * Bootstrap processor starts running C code here. */ int main(void) { /** * ld会生成如下几个变量用来标识程序的段 * * _etext(etext) 正文段结束后第一个地址 * _edata(edata) 数据段结束后第一个地址 * _end(end) bss段结束后第一个地址 */ extern char edata[], end[]; // clear BSS memset(edata, 0, end - edata); // collect info about this machine mp_init(); lapic_init(mp_bcpu()); cprintf("\ncpu%d: starting myos\n\n", cpu()); cprintf("Welcome to myos !\n"); pinit(); // process table binit(); // buffer cache pic_init(); // interrupt controller ioapic_init(); // another interrupt controller kinit(); // physical memory allocator tvinit(); // trap vectors fileinit(); // file table iinit(); // inode cache console_init(); // I/O devices & their interrupts ide_init(); // disk if(!ismp) timer_init(); // uniprocessor timer userinit(); // first user process bootothers(); // start other processors // Finish setting up this processor in mpmain. mpmain(); }
void lapic_init(int c) { uint32_t edx; if(!lapic) return; /* Check if APIC is supported */ cpuid(0x01, 0, 0, 0, &edx); if (!(edx & 0x200)) return; if (c == mp_bcpu()){ pte_t *pte; pte = pgdir_walk(boot_pgdir, (void *)lapic, 1); *pte = (physaddr_t)lapic | PTE_W | PTE_P | PTE_PCD; /* Must be Strong Uncacheable */ } // Enable local APIC; set spurious interrupt vector. lapic_write(SVR, ENABLE | (IRQ_OFFSET+IRQ_SPURIOUS)); // The timer repeatedly counts down at bus frequency // from lapic[TICR] and then issues an interrupt. lapic_write(TDCR, X1); lapic_write(TIMER, PERIODIC | (IRQ_OFFSET + IRQ_TIMER)); lapic_write(TICR, 10000000); /* Linux uses if () way -_-, but I'd like IOAPIC to distribute ExtINT */ if (0) {//(c == mp_bcpu()) { lapic_write(LINT0, DLMODE_EXTINT); lapic_write(LINT1, DLMODE_NMI); } else { lapic_write(LINT0, MASKED); lapic_write(LINT1, MASKED); } // Disable performance counter overflow interrupts // on machines that provide that interrupt entry. if(((lapic[VER]>>16) & 0xFF) >= 4) lapic_write(PCINT, MASKED); // Map error interrupt to IRQ_ERROR. lapic_write(ERROR, IRQ_OFFSET+IRQ_ERROR); // Clear error status register (requires back-to-back writes). lapic_write(ESR, 0); lapic_write(ESR, 0); // Ack any outstanding interrupts. lapic_write(EOI, 0); // Send an Init Level De-Assert to synchronise arbitration ID's. lapic_write(ICRHI, 0); lapic_write(ICRLO, BCAST | DLMODE_INIT | LEVEL); while(lapic[ICRLO] & DELIVS) ; // Enable interrupts on the APIC (but not on the processor). lapic_write(TPR, 0); /* 0: Handle all interrupts * 15: Interrupts inhibited * P. Vol.3 9-39 */ //cprintf("CPU %x: lapic_int() success\n", c); }