// Set up CPU's kernel segment descriptors. // Run once at boot time on each CPU. void seginit(void) { struct cpu *c; // Map virtual addresses to linear addresses using identity map. // Cannot share a CODE descriptor for both kernel and user // because it would have to have DPL_USR, but the CPU forbids // an interrupt from CPL=0 to DPL=3. c = &cpus[cpunum()]; c->gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, 0); c->gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0); c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, DPL_USER); c->gdt[SEG_UDATA] = SEG(STA_W, 0, 0xffffffff, DPL_USER); // Map cpu, and curproc c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 8, 0); lgdt(c->gdt, sizeof(c->gdt)); loadgs(SEG_KCPU << 3); // Initialize cpu-local storage. cpu = c; proc = 0; }
// Set up CPU's segment descriptors and task state for a given process. // If p==0, set up for "idle" state for when scheduler() is running. void setupsegs(struct proc *p) { struct cpu *c; pushcli(); c = &cpus[cpu()]; c->ts.ss0 = SEG_KDATA << 3; if(p) c->ts.esp0 = (uint)(p->kstack + KSTACKSIZE); else c->ts.esp0 = 0xffffffff; c->gdt[0] = SEG_NULL; c->gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0x100000 + 64*1024-1, 0); c->gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0); c->gdt[SEG_TSS] = SEG16(STS_T32A, (uint)&c->ts, sizeof(c->ts)-1, 0); c->gdt[SEG_TSS].s = 0; if(p){ c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, (uint)p->mem, p->sz-1, DPL_USER); c->gdt[SEG_UDATA] = SEG(STA_W, (uint)p->mem, p->sz-1, DPL_USER); } else { c->gdt[SEG_UCODE] = SEG_NULL; c->gdt[SEG_UDATA] = SEG_NULL; } lgdt(c->gdt, sizeof(c->gdt)); ltr(SEG_TSS << 3); popcli(); }
/* * 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) { #ifndef XEN struct region_descriptor region; size_t max_len; max_len = MAXGDTSIZ * sizeof(gdt[0]); setregion(®ion, ci->ci_gdt, max_len - 1); lgdt(®ion); #else size_t len = gdt_size[0] * sizeof(gdt[0]); unsigned long frames[len >> PAGE_SHIFT]; vaddr_t va; pt_entry_t *ptp; int f; for (va = (vaddr_t)ci->ci_gdt, f = 0; va < (vaddr_t)ci->ci_gdt + len; va += PAGE_SIZE, f++) { KASSERT(va >= VM_MIN_KERNEL_ADDRESS); ptp = kvtopte(va); frames[f] = *ptp >> PAGE_SHIFT; pmap_pte_clearbits(ptp, PG_RW); } /* printk("loading gdt %x, %d entries, %d pages", */ /* frames[0] << PAGE_SHIFT, gdt_size[0], len >> PAGE_SHIFT); */ if (HYPERVISOR_set_gdt(frames, gdt_size[0])) panic("HYPERVISOR_set_gdt failed!\n"); lgdt_finish(); #endif }
/* * 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(); }
/* * 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; setregion(®ion, ci->ci_gdt, MAXGDTSIZ - 1); lgdt(®ion); }
void seginit(void) { codedesc(&cpu->gdt[SEG_KCODE], KERN_DPL); datadesc(&cpu->gdt[SEG_KDATA], KERN_DPL); datadesc(&cpu->gdt[SEG_UDATA], USER_DPL); codedesc(&cpu->gdt[SEG_UCODE], USER_DPL); lgdt(cpu->gdt, sizeof(cpu->gdt)); }
void gdt_reload_cpu(struct cpu_info *ci) { struct region_descriptor region; size_t max_len; max_len = MAXGDTSIZ * sizeof(gdt[0]); setregion(®ion, ci->ci_gdt, max_len - 1); lgdt(®ion); }
static void update_gdtr() { gdtr.addr = gdt; lgdt(gdtr); // Quitamos el identity map de los primeros 4MB del espacio de direcciones // virtual void *vaddr = (void *) 0x00000000; kernel_pd[PDI(vaddr)] = 0; invalidate_tlb_pages(vaddr,TABLE_TOTAL_ENTRIES); }
/* * 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)); }
void set_up_temp_gdt() { temp_gdt[0] = set_seg_null; //NULL seg temp_gdt[1] = set_seg(STA_X|STA_R, 0x0, 0xFFFFFFFF, 0); //code seg temp_gdt[2] = set_seg(STA_W, 0x0, 0xFFFFFFFF, 0); //data seg temp_gdt[3] = set_seg_real_mode(STA_X|STA_R, 0x10000, 0xFFFF, 0); //normal code seg temp_gdt[4] = set_seg_real_mode(STA_W, 0x0, 0xFFFF, 0); //normal data seg sda.lim = sizeof(temp_gdt)*3-1; sda.base = (uint32_t)temp_gdt - KERNEL_BASE_ADDR; lgdt(&sda); }
// Set up CPU's kernel segment descriptors. // Run once at boot time on each CPU. void ksegment(void) { struct cpu *c; c = &cpus[cpunum()]; c->gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0x100000 + 64*1024-1, 0); c->gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0); c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 8, 0); lgdt(c->gdt, sizeof(c->gdt)); loadgs(SEG_KCPU << 3); // Initialize cpu-local storage. cpu = c; proc = 0; }
/* gdt_init - initialize the default GDT and TSS */ static void gdt_init(void) { // set boot kernel stack and default SS0 load_rsp0((uintptr_t) bootstacktop); ts.ts_ss0 = KERNEL_DS; // initialize the TSS filed of the gdt gdt[SEG_TSS] = SEGTSS(STS_T32A, (uintptr_t) & ts, sizeof(ts), DPL_KERNEL); // reload all segment registers lgdt(&gdt_pd); // load the TSS ltr(GD_TSS); }
/* * Initialize the GDT subsystem. Called from autoconf(). */ void gdt_init() { size_t max_len, min_len; struct region_descriptor region; max_len = MAXGDTSIZ * sizeof(union descriptor); min_len = MINGDTSIZ * sizeof(union descriptor); gdt_size = MINGDTSIZ; dynamic_gdt = (union descriptor *)uvm_km_valloc(kernel_map, max_len); uvm_map_pageable(kernel_map, (vaddr_t)dynamic_gdt, (vaddr_t)dynamic_gdt + min_len, FALSE, FALSE); bcopy(gdt, dynamic_gdt, NGDT * sizeof(union descriptor)); setregion(®ion, dynamic_gdt, max_len - 1); lgdt(®ion); }
/* * AP cpu's call this to sync up protected mode. * * WARNING! %gs is not set up on entry. This routine sets up %gs. */ void init_secondary(void) { int gsel_tss; int x, myid = bootAP; u_int64_t msr, cr0; struct mdglobaldata *md; struct privatespace *ps; ps = &CPU_prvspace[myid]; gdt_segs[GPROC0_SEL].ssd_base = (long) &ps->mdglobaldata.gd_common_tss; ps->mdglobaldata.mi.gd_prvspace = ps; /* We fill the 32-bit segment descriptors */ for (x = 0; x < NGDT; x++) { if (x != GPROC0_SEL && x != (GPROC0_SEL + 1)) ssdtosd(&gdt_segs[x], &gdt[myid * NGDT + x]); } /* And now a 64-bit one */ ssdtosyssd(&gdt_segs[GPROC0_SEL], (struct system_segment_descriptor *)&gdt[myid * NGDT + GPROC0_SEL]); r_gdt.rd_limit = NGDT * sizeof(gdt[0]) - 1; r_gdt.rd_base = (long) &gdt[myid * NGDT]; lgdt(&r_gdt); /* does magic intra-segment return */ /* lgdt() destroys the GSBASE value, so we load GSBASE after lgdt() */ wrmsr(MSR_FSBASE, 0); /* User value */ wrmsr(MSR_GSBASE, (u_int64_t)ps); wrmsr(MSR_KGSBASE, 0); /* XXX User value while we're in the kernel */ lidt(&r_idt_arr[mdcpu->mi.gd_cpuid]); #if 0 lldt(_default_ldt); mdcpu->gd_currentldt = _default_ldt; #endif gsel_tss = GSEL(GPROC0_SEL, SEL_KPL); gdt[myid * NGDT + GPROC0_SEL].sd_type = SDT_SYSTSS; md = mdcpu; /* loaded through %gs:0 (mdglobaldata.mi.gd_prvspace)*/ md->gd_common_tss.tss_rsp0 = 0; /* not used until after switch */ #if 0 /* JG XXX */ md->gd_common_tss.tss_ioopt = (sizeof md->gd_common_tss) << 16; #endif md->gd_tss_gdt = &gdt[myid * NGDT + GPROC0_SEL]; md->gd_common_tssd = *md->gd_tss_gdt; /* double fault stack */ md->gd_common_tss.tss_ist1 = (long)&md->mi.gd_prvspace->idlestack[ sizeof(md->mi.gd_prvspace->idlestack)]; 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); /* Set up the fast syscall stuff */ msr = rdmsr(MSR_EFER) | EFER_SCE; wrmsr(MSR_EFER, msr); wrmsr(MSR_LSTAR, (u_int64_t)IDTVEC(fast_syscall)); wrmsr(MSR_CSTAR, (u_int64_t)IDTVEC(fast_syscall32)); msr = ((u_int64_t)GSEL(GCODE_SEL, SEL_KPL) << 32) | ((u_int64_t)GSEL(GUCODE32_SEL, SEL_UPL) << 48); wrmsr(MSR_STAR, msr); wrmsr(MSR_SF_MASK, PSL_NT|PSL_T|PSL_I|PSL_C|PSL_D|PSL_IOPL); pmap_set_opt(); /* PSE/4MB pages, etc */ pmap_init_pat(); /* Page Attribute Table */ /* set up CPU registers and state */ cpu_setregs(); /* set up SSE/NX registers */ initializecpu(myid); /* set up FPU state on the AP */ npxinit(__INITIAL_FPUCW__); /* disable the APIC, just to be SURE */ lapic->svr &= ~APIC_SVR_ENABLE; }
void init_x86_64(paddr_t first_avail) { extern void consinit(void); extern struct extent *iomem_ex; struct region_descriptor region; struct mem_segment_descriptor *ldt_segp; int x, first16q, ist; u_int64_t seg_start, seg_end; u_int64_t seg_start1, seg_end1; cpu_init_msrs(&cpu_info_primary); proc0.p_addr = proc0paddr; cpu_info_primary.ci_curpcb = &proc0.p_addr->u_pcb; x86_bus_space_init(); consinit(); /* XXX SHOULD NOT BE DONE HERE */ /* * Initailize PAGE_SIZE-dependent variables. */ uvm_setpagesize(); #if 0 uvmexp.ncolors = 2; #endif /* * Boot arguments are in a single page specified by /boot. * * We require the "new" vector form, as well as memory ranges * to be given in bytes rather than KB. * * locore copies the data into bootinfo[] for us. */ if ((bootapiver & (BAPIV_VECTOR | BAPIV_BMEMMAP)) == (BAPIV_VECTOR | BAPIV_BMEMMAP)) { if (bootinfo_size >= sizeof(bootinfo)) panic("boot args too big"); getbootinfo(bootinfo, bootinfo_size); } else panic("invalid /boot"); avail_start = PAGE_SIZE; /* BIOS leaves data in low memory */ /* and VM system doesn't work with phys 0 */ #ifdef MULTIPROCESSOR if (avail_start < MP_TRAMPOLINE + PAGE_SIZE) avail_start = MP_TRAMPOLINE + PAGE_SIZE; #endif /* * Call pmap initialization to make new kernel address space. * We must do this before loading pages into the VM system. */ pmap_bootstrap(VM_MIN_KERNEL_ADDRESS, IOM_END + trunc_page(KBTOB(biosextmem))); if (avail_start != PAGE_SIZE) pmap_prealloc_lowmem_ptps(); if (mem_cluster_cnt == 0) { /* * Allocate the physical addresses used by RAM from the iomem * extent map. This is done before the addresses are * page rounded just to make sure we get them all. */ if (extent_alloc_region(iomem_ex, 0, KBTOB(biosbasemem), EX_NOWAIT)) { /* XXX What should we do? */ printf("WARNING: CAN'T ALLOCATE BASE MEMORY FROM " "IOMEM EXTENT MAP!\n"); } mem_clusters[0].start = 0; mem_clusters[0].size = trunc_page(KBTOB(biosbasemem)); physmem += atop(mem_clusters[0].size); if (extent_alloc_region(iomem_ex, IOM_END, KBTOB(biosextmem), EX_NOWAIT)) { /* XXX What should we do? */ printf("WARNING: CAN'T ALLOCATE EXTENDED MEMORY FROM " "IOMEM EXTENT MAP!\n"); } #if 0 #if NISADMA > 0 /* * Some motherboards/BIOSes remap the 384K of RAM that would * normally be covered by the ISA hole to the end of memory * so that it can be used. However, on a 16M system, this * would cause bounce buffers to be allocated and used. * This is not desirable behaviour, as more than 384K of * bounce buffers might be allocated. As a work-around, * we round memory down to the nearest 1M boundary if * we're using any isadma devices and the remapped memory * is what puts us over 16M. */ if (biosextmem > (15*1024) && biosextmem < (16*1024)) { char pbuf[9]; format_bytes(pbuf, sizeof(pbuf), biosextmem - (15*1024)); printf("Warning: ignoring %s of remapped memory\n", pbuf); biosextmem = (15*1024); } #endif #endif mem_clusters[1].start = IOM_END; mem_clusters[1].size = trunc_page(KBTOB(biosextmem)); physmem += atop(mem_clusters[1].size); mem_cluster_cnt = 2; avail_end = IOM_END + trunc_page(KBTOB(biosextmem)); } /* * If we have 16M of RAM or less, just put it all on * the default free list. Otherwise, put the first * 16M of RAM on a lower priority free list (so that * all of the ISA DMA'able memory won't be eaten up * first-off). */ if (avail_end <= (16 * 1024 * 1024)) first16q = VM_FREELIST_DEFAULT; else first16q = VM_FREELIST_FIRST16; /* Make sure the end of the space used by the kernel is rounded. */ first_avail = round_page(first_avail); kern_end = KERNBASE + first_avail; /* * Now, load the memory clusters (which have already been * rounded and truncated) into the VM system. * * NOTE: WE ASSUME THAT MEMORY STARTS AT 0 AND THAT THE KERNEL * IS LOADED AT IOM_END (1M). */ for (x = 0; x < mem_cluster_cnt; x++) { seg_start = mem_clusters[x].start; seg_end = mem_clusters[x].start + mem_clusters[x].size; seg_start1 = 0; seg_end1 = 0; if (seg_start > 0xffffffffULL) { printf("skipping %lld bytes of memory above 4GB\n", seg_end - seg_start); continue; } if (seg_end > 0x100000000ULL) { printf("skipping %lld bytes of memory above 4GB\n", seg_end - 0x100000000ULL); seg_end = 0x100000000ULL; } /* * Skip memory before our available starting point. */ if (seg_end <= avail_start) continue; if (avail_start >= seg_start && avail_start < seg_end) { if (seg_start != 0) panic("init_x86_64: memory doesn't start at 0"); seg_start = avail_start; if (seg_start == seg_end) continue; } /* * If this segment contains the kernel, split it * in two, around the kernel. */ if (seg_start <= IOM_END && first_avail <= seg_end) { seg_start1 = first_avail; seg_end1 = seg_end; seg_end = IOM_END; } /* First hunk */ if (seg_start != seg_end) { if (seg_start <= (16 * 1024 * 1024) && first16q != VM_FREELIST_DEFAULT) { u_int64_t tmp; if (seg_end > (16 * 1024 * 1024)) tmp = (16 * 1024 * 1024); else tmp = seg_end; #if DEBUG_MEMLOAD printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n", (unsigned long long)seg_start, (unsigned long long)tmp, atop(seg_start), atop(tmp)); #endif uvm_page_physload(atop(seg_start), atop(tmp), atop(seg_start), atop(tmp), first16q); seg_start = tmp; } if (seg_start != seg_end) { #if DEBUG_MEMLOAD printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n", (unsigned long long)seg_start, (unsigned long long)seg_end, atop(seg_start), atop(seg_end)); #endif uvm_page_physload(atop(seg_start), atop(seg_end), atop(seg_start), atop(seg_end), VM_FREELIST_DEFAULT); } } /* Second hunk */ if (seg_start1 != seg_end1) { if (seg_start1 <= (16 * 1024 * 1024) && first16q != VM_FREELIST_DEFAULT) { u_int64_t tmp; if (seg_end1 > (16 * 1024 * 1024)) tmp = (16 * 1024 * 1024); else tmp = seg_end1; #if DEBUG_MEMLOAD printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n", (unsigned long long)seg_start1, (unsigned long long)tmp, atop(seg_start1), atop(tmp)); #endif uvm_page_physload(atop(seg_start1), atop(tmp), atop(seg_start1), atop(tmp), first16q); seg_start1 = tmp; } if (seg_start1 != seg_end1) { #if DEBUG_MEMLOAD printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n", (unsigned long long)seg_start1, (unsigned long long)seg_end1, atop(seg_start1), atop(seg_end1)); #endif uvm_page_physload(atop(seg_start1), atop(seg_end1), atop(seg_start1), atop(seg_end1), VM_FREELIST_DEFAULT); } } } /* * Steal memory for the message buffer (at end of core). */ { struct vm_physseg *vps = NULL; psize_t sz = round_page(MSGBUFSIZE); psize_t reqsz = sz; for (x = 0; x < vm_nphysseg; x++) { vps = &vm_physmem[x]; if (ptoa(vps->avail_end) == avail_end) break; } if (x == vm_nphysseg) panic("init_x86_64: can't find end of memory"); /* Shrink so it'll fit in the last segment. */ if ((vps->avail_end - vps->avail_start) < atop(sz)) sz = ptoa(vps->avail_end - vps->avail_start); vps->avail_end -= atop(sz); vps->end -= atop(sz); msgbuf_paddr = ptoa(vps->avail_end); /* Remove the last segment if it now has no pages. */ if (vps->start == vps->end) { for (vm_nphysseg--; x < vm_nphysseg; x++) vm_physmem[x] = vm_physmem[x + 1]; } /* Now find where the new avail_end is. */ for (avail_end = 0, x = 0; x < vm_nphysseg; x++) if (vm_physmem[x].avail_end > avail_end) avail_end = vm_physmem[x].avail_end; avail_end = ptoa(avail_end); /* Warn if the message buffer had to be shrunk. */ if (sz != reqsz) printf("WARNING: %ld bytes not available for msgbuf " "in last cluster (%ld used)\n", reqsz, sz); } /* * XXXfvdl todo: acpi wakeup code. */ pmap_growkernel(VM_MIN_KERNEL_ADDRESS + 32 * 1024 * 1024); pmap_kenter_pa(idt_vaddr, idt_paddr, VM_PROT_READ|VM_PROT_WRITE); pmap_kenter_pa(idt_vaddr + PAGE_SIZE, idt_paddr + PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE); pmap_kenter_pa(lo32_vaddr, lo32_paddr, VM_PROT_READ|VM_PROT_WRITE); idt = (struct gate_descriptor *)idt_vaddr; gdtstore = (char *)(idt + NIDT); ldtstore = gdtstore + DYNSEL_START; /* make gdt gates and memory segments */ set_mem_segment(GDT_ADDR_MEM(gdtstore, GCODE_SEL), 0, 0xfffff, SDT_MEMERA, SEL_KPL, 1, 0, 1); set_mem_segment(GDT_ADDR_MEM(gdtstore, GDATA_SEL), 0, 0xfffff, SDT_MEMRWA, SEL_KPL, 1, 0, 1); set_sys_segment(GDT_ADDR_SYS(gdtstore, GLDT_SEL), ldtstore, LDT_SIZE - 1, SDT_SYSLDT, SEL_KPL, 0); set_mem_segment(GDT_ADDR_MEM(gdtstore, GUCODE_SEL), 0, atop(VM_MAXUSER_ADDRESS) - 1, SDT_MEMERA, SEL_UPL, 1, 0, 1); set_mem_segment(GDT_ADDR_MEM(gdtstore, GUDATA_SEL), 0, atop(VM_MAXUSER_ADDRESS) - 1, SDT_MEMRWA, SEL_UPL, 1, 0, 1); /* make ldt gates and memory segments */ setgate((struct gate_descriptor *)(ldtstore + LSYS5CALLS_SEL), &IDTVEC(oosyscall), 0, SDT_SYS386CGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); *(struct mem_segment_descriptor *)(ldtstore + LUCODE_SEL) = *GDT_ADDR_MEM(gdtstore, GUCODE_SEL); *(struct mem_segment_descriptor *)(ldtstore + LUDATA_SEL) = *GDT_ADDR_MEM(gdtstore, GUDATA_SEL); /* * 32 bit GDT entries. */ set_mem_segment(GDT_ADDR_MEM(gdtstore, GUCODE32_SEL), 0, atop(VM_MAXUSER_ADDRESS) - 1, SDT_MEMERA, SEL_UPL, 1, 1, 0); set_mem_segment(GDT_ADDR_MEM(gdtstore, GUDATA32_SEL), 0, atop(VM_MAXUSER_ADDRESS) - 1, SDT_MEMRWA, SEL_UPL, 1, 1, 0); /* * 32 bit LDT entries. */ ldt_segp = (struct mem_segment_descriptor *)(ldtstore + LUCODE32_SEL); set_mem_segment(ldt_segp, 0, atop(VM_MAXUSER_ADDRESS32) - 1, SDT_MEMERA, SEL_UPL, 1, 1, 0); ldt_segp = (struct mem_segment_descriptor *)(ldtstore + LUDATA32_SEL); set_mem_segment(ldt_segp, 0, atop(VM_MAXUSER_ADDRESS32) - 1, SDT_MEMRWA, SEL_UPL, 1, 1, 0); /* * Other entries. */ memcpy((struct gate_descriptor *)(ldtstore + LSOL26CALLS_SEL), (struct gate_descriptor *)(ldtstore + LSYS5CALLS_SEL), sizeof (struct gate_descriptor)); memcpy((struct gate_descriptor *)(ldtstore + LBSDICALLS_SEL), (struct gate_descriptor *)(ldtstore + LSYS5CALLS_SEL), sizeof (struct gate_descriptor)); /* exceptions */ for (x = 0; x < 32; x++) { ist = (x == 8) ? 1 : 0; setgate(&idt[x], IDTVEC(exceptions)[x], ist, SDT_SYS386IGT, (x == 3 || x == 4) ? SEL_UPL : SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); idt_allocmap[x] = 1; } /* new-style interrupt gate for syscalls */ setgate(&idt[128], &IDTVEC(osyscall), 0, SDT_SYS386IGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); idt_allocmap[128] = 1; setregion(®ion, gdtstore, DYNSEL_START - 1); lgdt(®ion); cpu_init_idt(); #ifdef DDB db_machine_init(); ddb_init(); if (boothowto & RB_KDB) Debugger(); #endif #ifdef KGDB kgdb_port_init(); if (boothowto & RB_KDB) { kgdb_debug_init = 1; kgdb_connect(1); } #endif intr_default_setup(); softintr_init(); splraise(IPL_IPI); enable_intr(); /* Make sure maxproc is sane */ if (maxproc > cpu_maxproc()) maxproc = cpu_maxproc(); }
int vm_seg_init(void) { lgdt((uint)global_descriptor_table, GDT_SIZE); return 0; }