/* * Set up proc0's TSS and LDT. */ void x86_64_proc0_tss_ldt_init(void) { struct pcb *pcb; int x; gdt_init(); cpu_info_primary.ci_curpcb = pcb = &proc0.p_addr->u_pcb; pcb->pcb_flags = 0; pcb->pcb_tss.tss_iobase = (u_int16_t)((caddr_t)pcb->pcb_iomap - (caddr_t)&pcb->pcb_tss); for (x = 0; x < sizeof(pcb->pcb_iomap) / 4; x++) pcb->pcb_iomap[x] = 0xffffffff; pcb->pcb_ldt_sel = pmap_kernel()->pm_ldt_sel = GSYSSEL(GLDT_SEL, SEL_KPL); pcb->pcb_cr0 = rcr0(); pcb->pcb_tss.tss_rsp0 = (u_int64_t)proc0.p_addr + USPACE - 16; pcb->pcb_tss.tss_ist[0] = (u_int64_t)proc0.p_addr + PAGE_SIZE; proc0.p_md.md_regs = (struct trapframe *)pcb->pcb_tss.tss_rsp0 - 1; proc0.p_md.md_tss_sel = tss_alloc(pcb); ltr(proc0.p_md.md_tss_sel); lldt(pcb->pcb_ldt_sel); }
/* * Load appropriate gdt descriptor; we better be running on *ci * (for the most part, this is how a cpu knows who it is). */ void gdt_init_cpu(struct cpu_info *ci) { struct region_descriptor region; set_sys_segment(GDT_ADDR_SYS(ci->ci_gdt, GPROC0_SEL), ci->ci_tss, sizeof (struct x86_64_tss)-1, SDT_SYS386TSS, SEL_KPL, 0); setregion(®ion, ci->ci_gdt, GDT_SIZE - 1); lgdt(®ion); ltr(GSYSSEL(GPROC0_SEL, SEL_KPL)); }
/* * The CPU ends up here when its ready to run * This is called from code in mptramp.s; at this point, we are running * in the idle pcb/idle stack of the new cpu. When this function returns, * this processor will enter the idle loop and start looking for work. * * XXX should share some of this with init386 in machdep.c */ void cpu_hatch(void *v) { struct cpu_info *ci = (struct cpu_info *)v; int s; cpu_init_msrs(ci); cpu_probe_features(ci); cpu_feature &= ci->ci_feature_flags; #ifdef DEBUG if (ci->ci_flags & CPUF_PRESENT) panic("%s: already running!?", ci->ci_dev->dv_xname); #endif ci->ci_flags |= CPUF_PRESENT; lapic_enable(); lapic_initclocks(); while ((ci->ci_flags & CPUF_GO) == 0) delay(10); #ifdef DEBUG if (ci->ci_flags & CPUF_RUNNING) panic("%s: already running!?", ci->ci_dev->dv_xname); #endif lcr0(ci->ci_idle_pcb->pcb_cr0); cpu_init_idt(); lapic_set_lvt(); gdt_init_cpu(ci); fpuinit(ci); lldt(GSYSSEL(GLDT_SEL, SEL_KPL)); cpu_init(ci); s = splhigh(); lcr8(0); enable_intr(); microuptime(&ci->ci_schedstate.spc_runtime); splx(s); SCHED_LOCK(s); cpu_switchto(NULL, sched_chooseproc()); }
void x86_64_init_pcb_tss_ldt(struct cpu_info *ci) { int x; struct pcb *pcb = ci->ci_idle_pcb; pcb->pcb_tss.tss_iobase = (u_int16_t)((caddr_t)pcb->pcb_iomap - (caddr_t)&pcb->pcb_tss); for (x = 0; x < sizeof(pcb->pcb_iomap) / 4; x++) pcb->pcb_iomap[x] = 0xffffffff; /* XXXfvdl pmap_kernel not needed */ pcb->pcb_ldt_sel = pmap_kernel()->pm_ldt_sel = GSYSSEL(GLDT_SEL, SEL_KPL); pcb->pcb_cr0 = rcr0(); ci->ci_idle_tss_sel = tss_alloc(pcb); }