void linux_setregs(struct lwp *l, struct exec_package *epp, vaddr_t stack) { struct trapframe *tf; #ifdef USER_LDT pmap_ldt_cleanup(l); #endif fpu_save_area_clear(l, __Linux_NPXCW__); tf = l->l_md.md_regs; tf->tf_gs = 0; tf->tf_fs = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_edi = 0; tf->tf_esi = 0; tf->tf_ebp = 0; tf->tf_ebx = l->l_proc->p_psstrp; tf->tf_edx = 0; tf->tf_ecx = 0; tf->tf_eax = 0; tf->tf_eip = epp->ep_entry; tf->tf_cs = GSEL(GUCODEBIG_SEL, SEL_UPL); tf->tf_eflags = PSL_USERSET; tf->tf_esp = stack; tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL); }
/* * Finish a fork operation, with process p2 nearly set up. * Copy and update the kernel stack and pcb, making the child * ready to run, and marking it so that it can return differently * than the parent. Returns 1 in the child process, 0 in the parent. * We currently double-map the user area so that the stack is at the same * address in each process; in the future we will probably relocate * the frame pointers on the stack after copying. */ void cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize, void (*func)(void *), void *arg) { struct pcb *pcb = &p2->p_addr->u_pcb; struct trapframe *tf; struct switchframe *sf; #if NNPX > 0 npxsave_proc(p1, 1); #endif p2->p_md.md_flags = p1->p_md.md_flags; /* Copy pcb from proc p1 to p2. */ if (p1 == curproc) { /* Sync the PCB before we copy it. */ savectx(curpcb); } #ifdef DIAGNOSTIC else if (p1 != &proc0) panic("cpu_fork: curproc"); #endif *pcb = p1->p_addr->u_pcb; /* * Preset these so that gdt_compact() doesn't get confused if called * during the allocations below. * * Note: pcb_ldt_sel is handled in the pmap_activate() call when * we run the new process. */ p2->p_md.md_tss_sel = GSEL(GNULL_SEL, SEL_KPL); /* Fix up the TSS. */ pcb->pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL); pcb->pcb_tss.tss_esp0 = (int)p2->p_addr + USPACE - 16; p2->p_md.md_tss_sel = tss_alloc(pcb); /* * Copy the trapframe, and arrange for the child to return directly * through rei(). */ p2->p_md.md_regs = tf = (struct trapframe *)pcb->pcb_tss.tss_esp0 - 1; *tf = *p1->p_md.md_regs; /* * If specified, give the child a different stack. */ if (stack != NULL) tf->tf_esp = (u_int)stack + stacksize; sf = (struct switchframe *)tf - 1; sf->sf_ppl = 0; sf->sf_esi = (int)func; sf->sf_ebx = (int)arg; sf->sf_eip = (int)proc_trampoline; pcb->pcb_esp = (int)sf; }
/* * AP cpu's call this to sync up protected mode. * * WARNING! We must ensure that the cpu is sufficiently initialized to * be able to use to the FP for our optimized bzero/bcopy code before * we enter more mainstream C code. * * WARNING! %fs is not set up on entry. This routine sets up %fs. */ void init_secondary(void) { int gsel_tss; int x, myid = bootAP; u_int cr0; struct mdglobaldata *md; struct privatespace *ps; ps = &CPU_prvspace[myid]; gdt_segs[GPRIV_SEL].ssd_base = (int)ps; gdt_segs[GPROC0_SEL].ssd_base = (int) &ps->mdglobaldata.gd_common_tss; ps->mdglobaldata.mi.gd_prvspace = ps; for (x = 0; x < NGDT; x++) { ssdtosd(&gdt_segs[x], &gdt[myid * NGDT + x].sd); } r_gdt.rd_limit = NGDT * sizeof(gdt[0]) - 1; r_gdt.rd_base = (int) &gdt[myid * NGDT]; lgdt(&r_gdt); /* does magic intra-segment return */ lidt(&r_idt); lldt(_default_ldt); mdcpu->gd_currentldt = _default_ldt; gsel_tss = GSEL(GPROC0_SEL, SEL_KPL); gdt[myid * NGDT + GPROC0_SEL].sd.sd_type = SDT_SYS386TSS; md = mdcpu; /* loaded through %fs:0 (mdglobaldata.mi.gd_prvspace)*/ md->gd_common_tss.tss_esp0 = 0; /* not used until after switch */ md->gd_common_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL); md->gd_common_tss.tss_ioopt = (sizeof md->gd_common_tss) << 16; md->gd_tss_gdt = &gdt[myid * NGDT + GPROC0_SEL].sd; md->gd_common_tssd = *md->gd_tss_gdt; ltr(gsel_tss); /* * Set to a known state: * Set by mpboot.s: CR0_PG, CR0_PE * Set by cpu_setregs: CR0_NE, CR0_MP, CR0_TS, CR0_WP, CR0_AM */ cr0 = rcr0(); cr0 &= ~(CR0_CD | CR0_NW | CR0_EM); load_cr0(cr0); pmap_set_opt(); /* PSE/4MB pages, etc */ /* set up CPU registers and state */ cpu_setregs(); /* set up FPU state on the AP */ npxinit(__INITIAL_NPXCW__); /* set up SSE registers */ enable_sse(); }
void cpu_set_tss_gates(struct cpu_info *ci) { struct segment_descriptor sd; ci->ci_doubleflt_stack = (char *)uvm_km_alloc(kernel_map, USPACE); cpu_init_tss(&ci->ci_doubleflt_tss, ci->ci_doubleflt_stack, IDTVEC(tss_trap08)); setsegment(&sd, &ci->ci_doubleflt_tss, sizeof(struct i386tss) - 1, SDT_SYS386TSS, SEL_KPL, 0, 0); ci->ci_gdt[GTRAPTSS_SEL].sd = sd; setgate(&idt[8], NULL, 0, SDT_SYSTASKGT, SEL_KPL, GSEL(GTRAPTSS_SEL, SEL_KPL)); #if defined(DDB) && defined(MULTIPROCESSOR) /* * Set up separate handler for the DDB IPI, so that it doesn't * stomp on a possibly corrupted stack. * * XXX overwriting the gate set in db_machine_init. * Should rearrange the code so that it's set only once. */ ci->ci_ddbipi_stack = (char *)uvm_km_alloc(kernel_map, USPACE); cpu_init_tss(&ci->ci_ddbipi_tss, ci->ci_ddbipi_stack, Xintrddbipi); setsegment(&sd, &ci->ci_ddbipi_tss, sizeof(struct i386tss) - 1, SDT_SYS386TSS, SEL_KPL, 0, 0); ci->ci_gdt[GIPITSS_SEL].sd = sd; setgate(&idt[ddb_vec], NULL, 0, SDT_SYSTASKGT, SEL_KPL, GSEL(GIPITSS_SEL, SEL_KPL)); #endif }
static void init_reg_state(void) { vmm_write_register(HV_X86_RAX, 0); vmm_write_register(HV_X86_RBX, 0); vmm_write_register(HV_X86_RCX, 0); vmm_write_register(HV_X86_RDX, 0); vmm_write_register(HV_X86_RSI, 0); vmm_write_register(HV_X86_RDI, 0); vmm_write_register(HV_X86_R8, 0); vmm_write_register(HV_X86_R9, 0); vmm_write_register(HV_X86_R10, 0); vmm_write_register(HV_X86_R11, 0); vmm_write_register(HV_X86_R12, 0); vmm_write_register(HV_X86_R13, 0); vmm_write_register(HV_X86_R14, 0); vmm_write_register(HV_X86_R15, 0); vmm_write_vmcs(VMCS_GUEST_FS, 0); vmm_write_vmcs(VMCS_GUEST_ES, 0); vmm_write_vmcs(VMCS_GUEST_GS, 0); vmm_write_vmcs(VMCS_GUEST_DS, 0); vmm_write_vmcs(VMCS_GUEST_CS, GSEL(SEG_CODE, 0)); vmm_write_vmcs(VMCS_GUEST_DS, GSEL(SEG_DATA, 0)); vmm_write_vmcs(VMCS_GUEST_FS_BASE, 0); vmm_write_vmcs(VMCS_GUEST_GS_BASE, 0); vmm_write_vmcs(VMCS_GUEST_LDTR, 0); init_fpu(); }
static void linux_buildcontext(struct lwp *l, void *catcher, void *f) { struct trapframe *tf = l->l_md.md_regs; tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_rip = (u_int64_t)catcher; tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL); tf->tf_rflags &= ~PSL_CLEARSIG; tf->tf_rsp = (u_int64_t)f; tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL); }
void linux_setregs(struct lwp *l, struct exec_package *epp, u_long stack) { struct pcb *pcb = &l->l_addr->u_pcb; struct trapframe *tf; /* If we were using the FPU, forget about it. */ if (l->l_addr->u_pcb.pcb_fpcpu != NULL) fpusave_lwp(l, 0); l->l_md.md_flags &= ~MDP_USEDFPU; pcb->pcb_flags = 0; pcb->pcb_savefpu.fp_fxsave.fx_fcw = __NetBSD_NPXCW__; pcb->pcb_savefpu.fp_fxsave.fx_mxcsr = __INITIAL_MXCSR__; pcb->pcb_savefpu.fp_fxsave.fx_mxcsr_mask = __INITIAL_MXCSR_MASK__; pcb->pcb_fs = 0; pcb->pcb_gs = 0; l->l_proc->p_flag &= ~PK_32; tf = l->l_md.md_regs; tf->tf_rax = 0; tf->tf_rbx = 0; tf->tf_rcx = epp->ep_entry; tf->tf_rdx = 0; tf->tf_rsi = 0; tf->tf_rdi = 0; tf->tf_rbp = 0; tf->tf_rsp = stack; tf->tf_r8 = 0; tf->tf_r9 = 0; tf->tf_r10 = 0; tf->tf_r11 = 0; tf->tf_r12 = 0; tf->tf_r13 = 0; tf->tf_r14 = 0; tf->tf_r15 = 0; tf->tf_rip = epp->ep_entry; tf->tf_rflags = PSL_USERSET; tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL); tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_ds = 0; tf->tf_es = 0; tf->tf_fs = 0; tf->tf_gs = 0; return; }
uint64_t vmm_get_host_datasel(void) { return (GSEL(GDATA_SEL, SEL_KPL)); }
/** * @brief Find a free IDT slot and setup the interrupt handler. */ static int vmbus_vector_alloc(void) { int vector; uintptr_t func; struct gate_descriptor *ip; /* * Search backwards form the highest IDT vector available for use * as vmbus channel callback vector. We install 'hv_vmbus_callback' * handler at that vector and use it to interrupt vcpus. */ vector = APIC_SPURIOUS_INT; while (--vector >= APIC_IPI_INTS) { ip = &idt[vector]; func = ((long)ip->gd_hioffset << 16 | ip->gd_looffset); if (func == (uintptr_t)&IDTVEC(rsvd)) { #ifdef __i386__ setidt(vector , IDTVEC(hv_vmbus_callback), SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); #else setidt(vector , IDTVEC(hv_vmbus_callback), SDT_SYSIGT, SEL_KPL, 0); #endif return (vector); } } return (0); }
void cpu_init_tss(struct i386tss *tss, void *stack, void *func) { memset(tss, 0, sizeof *tss); tss->tss_esp0 = tss->tss_esp = (int)((char *)stack + USPACE - 16); tss->tss_ss0 = GSEL(GDATA_SEL, SEL_KPL); tss->__tss_cs = GSEL(GCODE_SEL, SEL_KPL); tss->tss_fs = GSEL(GCPU_SEL, SEL_KPL); tss->tss_gs = tss->__tss_es = tss->__tss_ds = tss->__tss_ss = GSEL(GDATA_SEL, SEL_KPL); tss->tss_cr3 = pmap_kernel()->pm_pdirpa; tss->tss_esp = (int)((char *)stack + USPACE - 16); tss->tss_ldt = 0; tss->__tss_eflags = PSL_MBO | PSL_NT; /* XXX not needed? */ tss->__tss_eip = (int)func; }
int cpu_ptrace(struct thread *td, int req, void *addr, int data) { struct segment_descriptor *sdp, sd; register_t r; int error; switch (req) { case PT_GETXMMREGS: case PT_SETXMMREGS: case PT_GETXSTATE_OLD: case PT_SETXSTATE_OLD: case PT_GETXSTATE_INFO: case PT_GETXSTATE: case PT_SETXSTATE: error = cpu_ptrace_xmm(td, req, addr, data); break; case PT_GETFSBASE: case PT_GETGSBASE: sdp = req == PT_GETFSBASE ? &td->td_pcb->pcb_fsd : &td->td_pcb->pcb_gsd; r = sdp->sd_hibase << 24 | sdp->sd_lobase; error = copyout(&r, addr, sizeof(r)); break; case PT_SETFSBASE: case PT_SETGSBASE: error = copyin(addr, &r, sizeof(r)); if (error != 0) break; fill_based_sd(&sd, r); if (req == PT_SETFSBASE) { td->td_pcb->pcb_fsd = sd; td->td_frame->tf_fs = GSEL(GUFS_SEL, SEL_UPL); } else { td->td_pcb->pcb_gsd = sd; td->td_pcb->pcb_gs = GSEL(GUGS_SEL, SEL_UPL); } break; default: return (EINVAL); } return (error); }
/* * Caller must have pmap locked for both of these functions. */ void ldt_alloc(struct pmap *pmap, union descriptor *ldt, size_t len) { int slot; slot = gdt_get_slot(); setgdt(slot, ldt, len - 1, SDT_SYSLDT, SEL_KPL, 0, 0); pmap->pm_ldt_sel = GSEL(slot, SEL_KPL); }
void idt_vec_set(int vec, void (*function)(void)) { KASSERT(mutex_owned(&cpu_lock) || !mp_online); KASSERT(idt_allocmap[vec] == 1); setgate(&idt[vec], function, 0, SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); }
void idt_vec_set(int vec, void (*function)(void)) { /* * Vector should be allocated, so no locking needed. */ KASSERT(idt_allocmap[vec] == 1); setgate(&idt[vec], function, 0, SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); }
int tss_alloc(const struct i386tss *tss) { int slot; slot = gdt_get_slot(); setgdt(slot, tss, sizeof(struct i386tss) + IOMAPSIZE - 1, SDT_SYS386TSS, SEL_KPL, 0, 0); return GSEL(slot, SEL_KPL); }
int tss_alloc(struct pcb *pcb) { int slot; slot = gdt_get_slot(); setgdt(slot, &pcb->pcb_tss, sizeof(struct pcb) - 1, SDT_SYS386TSS, SEL_KPL, 0, 0); return GSEL(slot, SEL_KPL); }
/* * Caller must have pmap locked for both of these functions. */ void ldt_alloc(struct pmap *pmap, union descriptor *ldt, size_t len) { int slot; slot = gdt_get_slot1(1); cpu_info_primary.ci_gdt[slot].ld.ld_base = (u_int32_t)ldt; cpu_info_primary.ci_gdt[slot].ld.ld_entries = len / sizeof(union descriptor); pmap->pm_ldt_sel = GSEL(slot, SEL_KPL); }
void ldt_alloc(struct pmap *pmap, char *ldt, size_t len) { int slot; struct sys_segment_descriptor *gdt; gdt = (struct sys_segment_descriptor *)&gdtstore[DYNSEL_START]; slot = gdt_get_slot(); set_sys_gdt(&gdt[slot], ldt, len - 1, SDT_SYSLDT, SEL_KPL, 0); pmap->pm_ldt_sel = GSEL(slot, SEL_KPL); }
void kvm86_init() { size_t vmdsize; char *buf; struct kvm86_data *vmd; struct pcb *pcb; paddr_t pa; int i; vmdsize = round_page(sizeof(struct kvm86_data)) + PAGE_SIZE; if ((buf = km_alloc(vmdsize, &kv_any, &kp_zero, &kd_waitok)) == NULL) return; /* first page is stack */ vmd = (struct kvm86_data *)(buf + PAGE_SIZE); pcb = &vmd->pcb; /* * derive pcb and TSS from proc0 * we want to access all IO ports, so we need a full-size * permission bitmap * XXX do we really need the pcb or just the TSS? */ memcpy(pcb, &proc0.p_addr->u_pcb, sizeof(struct pcb)); pcb->pcb_tss.tss_esp0 = (int)vmd; pcb->pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL); for (i = 0; i < sizeof(vmd->iomap) / 4; i++) vmd->iomap[i] = 0; pcb->pcb_tss.tss_ioopt = ((caddr_t)vmd->iomap - (caddr_t)&pcb->pcb_tss) << 16; /* setup TSS descriptor (including our iomap) */ setsegment(&vmd->sd, &pcb->pcb_tss, sizeof(struct pcb) + sizeof(vmd->iomap) - 1, SDT_SYS386TSS, SEL_KPL, 0, 0); /* prepare VM for BIOS calls */ kvm86_mapbios(vmd); if ((bioscallscratchpage = km_alloc(PAGE_SIZE, &kv_any, &kp_dirty, &kd_waitok)) == NULL) return; pmap_extract(pmap_kernel(), (vaddr_t)bioscallscratchpage, &pa); kvm86_map(vmd, pa, BIOSCALLSCRATCHPAGE_VMVA); bioscallvmd = vmd; bioscalltmpva = (vaddr_t)km_alloc(PAGE_SIZE, &kv_any, &kp_none, &kd_waitok); mtx_init(&kvm86_mp_mutex, IPL_IPI); }
void * gdb_cpu_getreg(int regnum, size_t *regsz) { static uint32_t _kcodesel = GSEL(GCODE_SEL, SEL_KPL); static uint32_t _kdatasel = GSEL(GDATA_SEL, SEL_KPL); *regsz = gdb_cpu_regsz(regnum); if (kdb_thread == curthread) { switch (regnum) { case 0: return (&kdb_frame->tf_rax); case 2: return (&kdb_frame->tf_rcx); case 3: return (&kdb_frame->tf_rdx); case 4: return (&kdb_frame->tf_rsi); case 5: return (&kdb_frame->tf_rdi); case 8: return (&kdb_frame->tf_r8); case 9: return (&kdb_frame->tf_r9); case 10: return (&kdb_frame->tf_r10); case 11: return (&kdb_frame->tf_r11); case 17: return (&kdb_frame->tf_rflags); case 18: return (&kdb_frame->tf_cs); case 19: return (&kdb_frame->tf_ss); } } switch (regnum) { case 1: return (&kdb_thrctx->pcb_rbx); case 6: return (&kdb_thrctx->pcb_rbp); case 7: return (&kdb_thrctx->pcb_rsp); case 12: return (&kdb_thrctx->pcb_r12); case 13: return (&kdb_thrctx->pcb_r13); case 14: return (&kdb_thrctx->pcb_r14); case 15: return (&kdb_thrctx->pcb_r15); case 16: return (&kdb_thrctx->pcb_rip); case 18: return (&_kcodesel); case 19: return (&_kdatasel); } return (NULL); }
void * gdb_cpu_getreg(int regnum, size_t *regsz) { static uint32_t _kcodesel = GSEL(GCODE_SEL, SEL_KPL); static uint32_t _kdatasel = GSEL(GDATA_SEL, SEL_KPL); static uint32_t _kprivsel = GSEL(GPRIV_SEL, SEL_KPL); *regsz = gdb_cpu_regsz(regnum); if (kdb_thread == curthread) { switch (regnum) { case 0: return (&kdb_frame->tf_eax); case 1: return (&kdb_frame->tf_ecx); case 2: return (&kdb_frame->tf_edx); case 9: return (&kdb_frame->tf_eflags); case 10: return (&kdb_frame->tf_cs); case 12: return (&kdb_frame->tf_ds); case 13: return (&kdb_frame->tf_es); case 14: return (&kdb_frame->tf_fs); } } switch (regnum) { case 3: return (&kdb_thrctx->pcb_ebx); case 4: return (&kdb_thrctx->pcb_esp); case 5: return (&kdb_thrctx->pcb_ebp); case 6: return (&kdb_thrctx->pcb_esi); case 7: return (&kdb_thrctx->pcb_edi); case 8: return (&kdb_thrctx->pcb_eip); case 10: return (&_kcodesel); case 11: return (&_kdatasel); case 12: return (&_kdatasel); case 13: return (&_kdatasel); case 14: return (&_kprivsel); case 15: return (&kdb_thrctx->pcb_gs); } return (NULL); }
/* * Caller must have pmap locked for both of these functions. */ int ldt_alloc(union descriptor *ldtp, size_t len) { int slot; #ifndef XEN slot = gdt_get_slot(); setgdt(slot, ldtp, len - 1, SDT_SYSLDT, SEL_KPL, 0, 0); #else slot = gdt_get_slot1(1); cpu_info_primary.ci_gdt[slot].ld.ld_base = (uint32_t)ldtp; cpu_info_primary.ci_gdt[slot].ld.ld_entries = len / sizeof(union descriptor); #endif return GSEL(slot, SEL_KPL); }
void linux32_setregs(struct lwp *l, struct exec_package *pack, u_long stack) { struct pcb *pcb = lwp_getpcb(l); struct trapframe *tf; struct proc *p = l->l_proc; /* If we were using the FPU, forget about it. */ if (pcb->pcb_fpcpu != NULL) fpusave_lwp(l, 0); #if defined(USER_LDT) && 0 pmap_ldt_cleanup(p); #endif netbsd32_adjust_limits(p); l->l_md.md_flags &= ~MDL_USEDFPU; l->l_md.md_flags |= MDL_COMPAT32; /* Forces iret not sysret */ pcb->pcb_flags = PCB_COMPAT32; pcb->pcb_savefpu.fp_fxsave.fx_fcw = __Linux_NPXCW__; pcb->pcb_savefpu.fp_fxsave.fx_mxcsr = __INITIAL_MXCSR__; pcb->pcb_savefpu.fp_fxsave.fx_mxcsr_mask = __INITIAL_MXCSR_MASK__; p->p_flag |= PK_32; tf = l->l_md.md_regs; tf->tf_rax = 0; tf->tf_rbx = (u_int32_t)p->p_psstrp; tf->tf_rcx = pack->ep_entry & 0xffffffff; tf->tf_rdx = 0; tf->tf_rsi = 0; tf->tf_rdi = 0; tf->tf_rbp = 0; tf->tf_rsp = stack & 0xffffffff; tf->tf_r8 = 0; tf->tf_r9 = 0; tf->tf_r10 = 0; tf->tf_r11 = 0; tf->tf_r12 = 0; tf->tf_r13 = 0; tf->tf_r14 = 0; tf->tf_r15 = 0; tf->tf_rip = pack->ep_entry & 0xffffffff; tf->tf_rflags = PSL_USERSET; tf->tf_cs = GSEL(GUCODE32_SEL, SEL_UPL); tf->tf_ss = GSEL(GUDATA32_SEL, SEL_UPL); tf->tf_ds = GSEL(GUDATA32_SEL, SEL_UPL); tf->tf_es = GSEL(GUDATA32_SEL, SEL_UPL); cpu_fsgs_zero(l); cpu_fsgs_reload(l, GSEL(GUDATA32_SEL, SEL_UPL), GSEL(GUDATA32_SEL, SEL_UPL)); }
/* * Fill in default interrupt table (in case of spurious interrupt * during configuration of kernel), setup interrupt control unit */ void intr_default_setup(void) { int i; /* icu vectors */ for (i = 0; i < NUM_LEGACY_IRQS; i++) { idt_allocmap[ICU_OFFSET + i] = 1; setgate(&idt[ICU_OFFSET + i], i8259_stubs[i].ist_entry, 0, SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); } /* * Eventually might want to check if it's actually there. */ i8259_default_setup(); }
static u_int16_t pcibios_get_version(void) { struct bios_regs args; if (PCIbios.ventry == 0) { PRVERB(("pcibios: No call entry point\n")); return (0); } args.eax = PCIBIOS_BIOS_PRESENT; if (bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL))) { PRVERB(("pcibios: BIOS_PRESENT call failed\n")); return (0); } if (args.edx != 0x20494350) { PRVERB(("pcibios: BIOS_PRESENT didn't return 'PCI ' in edx\n")); return (0); } return (args.ebx & 0xffff); }
static const struct target_desc * amd64fbsd_read_description (struct target_ops *ops) { #ifdef PT_GETXSTATE_INFO static int xsave_probed; static uint64_t xcr0; #endif struct reg regs; int is64; if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't get registers")); is64 = (regs.r_cs == GSEL (GUCODE_SEL, SEL_UPL)); #ifdef PT_GETXSTATE_INFO if (!xsave_probed) { struct ptrace_xstate_info info; if (ptrace (PT_GETXSTATE_INFO, ptid_get_pid (inferior_ptid), (PTRACE_TYPE_ARG3) &info, sizeof (info)) == 0) { amd64bsd_xsave_len = info.xsave_len; xcr0 = info.xsave_mask; } xsave_probed = 1; } if (amd64bsd_xsave_len != 0) { if (is64) return amd64_target_description (xcr0); else return i386_target_description (xcr0); } #endif if (is64) return tdesc_amd64; else return tdesc_i386; }
void linux32_setregs(struct lwp *l, struct exec_package *pack, u_long stack) { struct pcb *pcb = lwp_getpcb(l); struct trapframe *tf; struct proc *p = l->l_proc; #if defined(USER_LDT) && 0 pmap_ldt_cleanup(l); #endif netbsd32_adjust_limits(p); fpu_save_area_clear(l, __Linux_NPXCW__); l->l_md.md_flags |= MDL_COMPAT32; /* Forces iret not sysret */ pcb->pcb_flags = PCB_COMPAT32; p->p_flag |= PK_32; tf = l->l_md.md_regs; tf->tf_rax = 0; tf->tf_rbx = (u_int32_t)p->p_psstrp; tf->tf_rcx = pack->ep_entry & 0xffffffff; tf->tf_rdx = 0; tf->tf_rsi = 0; tf->tf_rdi = 0; tf->tf_rbp = 0; tf->tf_rsp = stack & 0xffffffff; tf->tf_r8 = 0; tf->tf_r9 = 0; tf->tf_r10 = 0; tf->tf_r11 = 0; tf->tf_r12 = 0; tf->tf_r13 = 0; tf->tf_r14 = 0; tf->tf_r15 = 0; tf->tf_rip = pack->ep_entry & 0xffffffff; tf->tf_rflags = PSL_USERSET; tf->tf_cs = GSEL(GUCODE32_SEL, SEL_UPL); tf->tf_ss = GSEL(GUDATA32_SEL, SEL_UPL); tf->tf_ds = GSEL(GUDATA32_SEL, SEL_UPL); tf->tf_es = GSEL(GUDATA32_SEL, SEL_UPL); cpu_fsgs_zero(l); cpu_fsgs_reload(l, GSEL(GUDATA32_SEL, SEL_UPL), GSEL(GUDATA32_SEL, SEL_UPL)); }
int db_segsize(struct trapframe *tfp) { struct proc_ldt *plp; struct segment_descriptor *sdp; int sel; if (tfp == NULL) return (32); if (tfp->tf_eflags & PSL_VM) return (16); sel = tfp->tf_cs & 0xffff; if (sel == GSEL(GCODE_SEL, SEL_KPL)) return (32); /* Rare cases follow. User mode cases are currently unreachable. */ if (ISLDT(sel)) { plp = curthread->td_proc->p_md.md_ldt; sdp = (plp != NULL) ? &plp->ldt_sd : &ldt[0].sd; } else { sdp = &gdt[PCPU_GET(cpuid) * NGDT].sd; } return (sdp[IDXSEL(sel)].sd_def32 == 0 ? 16 : 32); }
void linux_setregs(struct lwp *l, struct exec_package *epp, u_long stack) { struct pcb *pcb = &l->l_addr->u_pcb; struct trapframe *tf; #if NNPX > 0 /* If we were using the FPU, forget about it. */ if (npxproc == l) npxdrop(); #endif #ifdef USER_LDT pmap_ldt_cleanup(l); #endif l->l_md.md_flags &= ~MDL_USEDFPU; if (i386_use_fxsave) { pcb->pcb_savefpu.sv_xmm.sv_env.en_cw = __Linux_NPXCW__; pcb->pcb_savefpu.sv_xmm.sv_env.en_mxcsr = __INITIAL_MXCSR__; } else pcb->pcb_savefpu.sv_87.sv_env.en_cw = __Linux_NPXCW__; tf = l->l_md.md_regs; tf->tf_gs = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_fs = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_edi = 0; tf->tf_esi = 0; tf->tf_ebp = 0; tf->tf_ebx = (int)l->l_proc->p_psstr; tf->tf_edx = 0; tf->tf_ecx = 0; tf->tf_eax = 0; tf->tf_eip = epp->ep_entry; tf->tf_cs = GSEL(GUCODEBIG_SEL, SEL_UPL); tf->tf_eflags = PSL_USERSET; tf->tf_esp = stack; tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL); }
static void cpu_initialize_context(unsigned int cpu) { /* vcpu_guest_context_t is too large to allocate on the stack. * Hence we allocate statically and protect it with a lock */ vm_page_t m[NPGPTD + 2]; static vcpu_guest_context_t ctxt; vm_offset_t boot_stack; vm_offset_t newPTD; vm_paddr_t ma[NPGPTD]; int i; /* * Page 0,[0-3] PTD * Page 1, [4] boot stack * Page [5] PDPT * */ for (i = 0; i < NPGPTD + 2; i++) { m[i] = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ | VM_ALLOC_WIRED | VM_ALLOC_ZERO); pmap_zero_page(m[i]); } boot_stack = kmem_alloc_nofault(kernel_map, PAGE_SIZE); newPTD = kmem_alloc_nofault(kernel_map, NPGPTD * PAGE_SIZE); ma[0] = VM_PAGE_TO_MACH(m[0])|PG_V; #ifdef PAE pmap_kenter(boot_stack, VM_PAGE_TO_PHYS(m[NPGPTD + 1])); for (i = 0; i < NPGPTD; i++) { ((vm_paddr_t *)boot_stack)[i] = ma[i] = VM_PAGE_TO_MACH(m[i])|PG_V; } #endif /* * Copy cpu0 IdlePTD to new IdlePTD - copying only * kernel mappings */ pmap_qenter(newPTD, m, 4); memcpy((uint8_t *)newPTD + KPTDI*sizeof(vm_paddr_t), (uint8_t *)PTOV(IdlePTD) + KPTDI*sizeof(vm_paddr_t), nkpt*sizeof(vm_paddr_t)); pmap_qremove(newPTD, 4); kmem_free(kernel_map, newPTD, 4 * PAGE_SIZE); /* * map actual idle stack to boot_stack */ pmap_kenter(boot_stack, VM_PAGE_TO_PHYS(m[NPGPTD])); xen_pgdpt_pin(VM_PAGE_TO_MACH(m[NPGPTD + 1])); rw_wlock(&pvh_global_lock); for (i = 0; i < 4; i++) { int pdir = (PTDPTDI + i) / NPDEPG; int curoffset = (PTDPTDI + i) % NPDEPG; xen_queue_pt_update((vm_paddr_t) ((ma[pdir] & ~PG_V) + (curoffset*sizeof(vm_paddr_t))), ma[i]); } PT_UPDATES_FLUSH(); rw_wunlock(&pvh_global_lock); memset(&ctxt, 0, sizeof(ctxt)); ctxt.flags = VGCF_IN_KERNEL; ctxt.user_regs.ds = GSEL(GDATA_SEL, SEL_KPL); ctxt.user_regs.es = GSEL(GDATA_SEL, SEL_KPL); ctxt.user_regs.fs = GSEL(GPRIV_SEL, SEL_KPL); ctxt.user_regs.gs = GSEL(GDATA_SEL, SEL_KPL); ctxt.user_regs.cs = GSEL(GCODE_SEL, SEL_KPL); ctxt.user_regs.ss = GSEL(GDATA_SEL, SEL_KPL); ctxt.user_regs.eip = (unsigned long)init_secondary; ctxt.user_regs.eflags = PSL_KERNEL | 0x1000; /* IOPL_RING1 */ memset(&ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt)); smp_trap_init(ctxt.trap_ctxt); ctxt.ldt_ents = 0; ctxt.gdt_frames[0] = (uint32_t)((uint64_t)vtomach(bootAPgdt) >> PAGE_SHIFT); ctxt.gdt_ents = 512; #ifdef __i386__ ctxt.user_regs.esp = boot_stack + PAGE_SIZE; ctxt.kernel_ss = GSEL(GDATA_SEL, SEL_KPL); ctxt.kernel_sp = boot_stack + PAGE_SIZE; ctxt.event_callback_cs = GSEL(GCODE_SEL, SEL_KPL); ctxt.event_callback_eip = (unsigned long)Xhypervisor_callback; ctxt.failsafe_callback_cs = GSEL(GCODE_SEL, SEL_KPL); ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback; ctxt.ctrlreg[3] = VM_PAGE_TO_MACH(m[NPGPTD + 1]); #else /* __x86_64__ */ ctxt.user_regs.esp = idle->thread.rsp0 - sizeof(struct pt_regs); ctxt.kernel_ss = GSEL(GDATA_SEL, SEL_KPL); ctxt.kernel_sp = idle->thread.rsp0; ctxt.event_callback_eip = (unsigned long)hypervisor_callback; ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback; ctxt.syscall_callback_eip = (unsigned long)system_call; ctxt.ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(init_level4_pgt)); ctxt.gs_base_kernel = (unsigned long)(cpu_pda(cpu)); #endif printf("gdtpfn=%lx pdptpfn=%lx\n", ctxt.gdt_frames[0], ctxt.ctrlreg[3] >> PAGE_SHIFT); PANIC_IF(HYPERVISOR_vcpu_op(VCPUOP_initialise, cpu, &ctxt)); DELAY(3000); PANIC_IF(HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL)); }