Annotation of sys/arch/amd64/amd64/cpu.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: cpu.c,v 1.13 2007/08/02 16:40:27 deraadt Exp $ */
2: /* $NetBSD: cpu.c,v 1.1 2003/04/26 18:39:26 fvdl Exp $ */
3:
4: /*-
5: * Copyright (c) 2000 The NetBSD Foundation, Inc.
6: * All rights reserved.
7: *
8: * This code is derived from software contributed to The NetBSD Foundation
9: * by RedBack Networks Inc.
10: *
11: * Author: Bill Sommerfeld
12: *
13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that the following conditions
15: * are met:
16: * 1. Redistributions of source code must retain the above copyright
17: * notice, this list of conditions and the following disclaimer.
18: * 2. Redistributions in binary form must reproduce the above copyright
19: * notice, this list of conditions and the following disclaimer in the
20: * documentation and/or other materials provided with the distribution.
21: * 3. All advertising materials mentioning features or use of this software
22: * must display the following acknowledgement:
23: * This product includes software developed by the NetBSD
24: * Foundation, Inc. and its contributors.
25: * 4. Neither the name of The NetBSD Foundation nor the names of its
26: * contributors may be used to endorse or promote products derived
27: * from this software without specific prior written permission.
28: *
29: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
30: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
31: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
33: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39: * POSSIBILITY OF SUCH DAMAGE.
40: */
41:
42: /*
43: * Copyright (c) 1999 Stefan Grefen
44: *
45: * Redistribution and use in source and binary forms, with or without
46: * modification, are permitted provided that the following conditions
47: * are met:
48: * 1. Redistributions of source code must retain the above copyright
49: * notice, this list of conditions and the following disclaimer.
50: * 2. Redistributions in binary form must reproduce the above copyright
51: * notice, this list of conditions and the following disclaimer in the
52: * documentation and/or other materials provided with the distribution.
53: * 3. All advertising materials mentioning features or use of this software
54: * must display the following acknowledgement:
55: * This product includes software developed by the NetBSD
56: * Foundation, Inc. and its contributors.
57: * 4. Neither the name of The NetBSD Foundation nor the names of its
58: * contributors may be used to endorse or promote products derived
59: * from this software without specific prior written permission.
60: *
61: * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
62: * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
63: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
64: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE
65: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
66: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
67: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
68: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
69: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
70: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
71: * SUCH DAMAGE.
72: */
73:
74: #include "lapic.h"
75: #include "ioapic.h"
76:
77: #include <sys/param.h>
78: #include <sys/proc.h>
79: #include <sys/user.h>
80: #include <sys/systm.h>
81: #include <sys/device.h>
82: #include <sys/malloc.h>
83:
84: #include <uvm/uvm_extern.h>
85:
86: #include <machine/cpu.h>
87: #include <machine/cpufunc.h>
88: #include <machine/cpuvar.h>
89: #include <machine/pmap.h>
90: #include <machine/vmparam.h>
91: #include <machine/mpbiosvar.h>
92: #include <machine/pcb.h>
93: #include <machine/specialreg.h>
94: #include <machine/segments.h>
95: #include <machine/gdt.h>
96: #include <machine/mtrr.h>
97: #include <machine/pio.h>
98:
99: #if NLAPIC > 0
100: #include <machine/apicvar.h>
101: #include <machine/i82489reg.h>
102: #include <machine/i82489var.h>
103: #endif
104:
105: #if NIOAPIC > 0
106: #include <machine/i82093var.h>
107: #endif
108:
109: #include <dev/ic/mc146818reg.h>
110: #include <amd64/isa/nvram.h>
111: #include <dev/isa/isareg.h>
112:
113: int cpu_match(struct device *, void *, void *);
114: void cpu_attach(struct device *, struct device *, void *);
115:
116: struct cpu_softc {
117: struct device sc_dev; /* device tree glue */
118: struct cpu_info *sc_info; /* pointer to CPU info */
119: };
120:
121: #ifdef MULTIPROCESSOR
122: int mp_cpu_start(struct cpu_info *);
123: void mp_cpu_start_cleanup(struct cpu_info *);
124: struct cpu_functions mp_cpu_funcs = { mp_cpu_start, NULL,
125: mp_cpu_start_cleanup };
126: #endif /* MULTIPROCESSOR */
127:
128: struct cfattach cpu_ca = {
129: sizeof(struct cpu_softc), cpu_match, cpu_attach
130: };
131:
132: struct cfdriver cpu_cd = {
133: NULL, "cpu", DV_DULL
134: };
135:
136: /*
137: * Statically-allocated CPU info for the primary CPU (or the only
138: * CPU, on uniprocessors). The CPU info list is initialized to
139: * point at it.
140: */
141: struct cpu_info cpu_info_primary = { 0, &cpu_info_primary };
142:
143: struct cpu_info *cpu_info_list = &cpu_info_primary;
144:
145: u_int32_t cpus_attached = 0;
146:
147: #ifdef MULTIPROCESSOR
148: /*
149: * Array of CPU info structures. Must be statically-allocated because
150: * curproc, etc. are used early.
151: */
152: struct cpu_info *cpu_info[X86_MAXPROCS] = { &cpu_info_primary };
153:
154: u_int32_t cpus_running = 0;
155:
156: void cpu_hatch(void *);
157: static void cpu_boot_secondary(struct cpu_info *ci);
158: static void cpu_start_secondary(struct cpu_info *ci);
159: static void cpu_copy_trampoline(void);
160:
161: /*
162: * Runs once per boot once multiprocessor goo has been detected and
163: * the local APIC on the boot processor has been mapped.
164: *
165: * Called from lapic_boot_init() (from mpbios_scan()).
166: */
167: void
168: cpu_init_first(void)
169: {
170: int cpunum = lapic_cpu_number();
171:
172: if (cpunum != 0) {
173: cpu_info[0] = NULL;
174: cpu_info[cpunum] = &cpu_info_primary;
175: }
176:
177: cpu_copy_trampoline();
178: }
179: #endif
180:
181: int
182: cpu_match(struct device *parent, void *match, void *aux)
183: {
184: struct cfdata *cf = match;
185: struct cpu_attach_args *caa = aux;
186:
187: if (strcmp(caa->caa_name, cf->cf_driver->cd_name) == 0)
188: return 1;
189: return 0;
190: }
191:
192: static void
193: cpu_vm_init(struct cpu_info *ci)
194: {
195: int ncolors = 2, i;
196:
197: for (i = CAI_ICACHE; i <= CAI_L2CACHE; i++) {
198: struct x86_cache_info *cai;
199: int tcolors;
200:
201: cai = &ci->ci_cinfo[i];
202:
203: tcolors = atop(cai->cai_totalsize);
204: switch(cai->cai_associativity) {
205: case 0xff:
206: tcolors = 1; /* fully associative */
207: break;
208: case 0:
209: case 1:
210: break;
211: default:
212: tcolors /= cai->cai_associativity;
213: }
214: ncolors = max(ncolors, tcolors);
215: }
216:
217: #ifdef notyet
218: /*
219: * Knowing the size of the largest cache on this CPU, re-color
220: * our pages.
221: */
222: if (ncolors <= uvmexp.ncolors)
223: return;
224: printf("%s: %d page colors\n", ci->ci_dev->dv_xname, ncolors);
225: uvm_page_recolor(ncolors);
226: #endif
227: }
228:
229:
230: void
231: cpu_attach(struct device *parent, struct device *self, void *aux)
232: {
233: struct cpu_softc *sc = (void *) self;
234: struct cpu_attach_args *caa = aux;
235: struct cpu_info *ci;
236: #if defined(MULTIPROCESSOR)
237: int cpunum = caa->cpu_number;
238: vaddr_t kstack;
239: struct pcb *pcb;
240: #endif
241:
242: /*
243: * If we're an Application Processor, allocate a cpu_info
244: * structure, otherwise use the primary's.
245: */
246: if (caa->cpu_role == CPU_ROLE_AP) {
247: ci = malloc(sizeof(*ci), M_DEVBUF, M_WAITOK);
248: memset(ci, 0, sizeof(*ci));
249: #if defined(MULTIPROCESSOR)
250: if (cpu_info[cpunum] != NULL)
251: panic("cpu at apic id %d already attached?", cpunum);
252: cpu_info[cpunum] = ci;
253: #endif
254: #ifdef TRAPLOG
255: ci->ci_tlog_base = malloc(sizeof(struct tlog),
256: M_DEVBUF, M_WAITOK);
257: #endif
258: } else {
259: ci = &cpu_info_primary;
260: #if defined(MULTIPROCESSOR)
261: if (cpunum != lapic_cpu_number()) {
262: panic("%s: running cpu is at apic %d"
263: " instead of at expected %d",
264: sc->sc_dev.dv_xname, lapic_cpu_number(), cpunum);
265: }
266: #endif
267: }
268:
269: ci->ci_self = ci;
270: sc->sc_info = ci;
271:
272: ci->ci_dev = self;
273: ci->ci_apicid = caa->cpu_number;
274: #ifdef MULTIPROCESSOR
275: ci->ci_cpuid = ci->ci_apicid;
276: #else
277: ci->ci_cpuid = 0; /* False for APs, but they're not used anyway */
278: #endif
279: ci->ci_func = caa->cpu_func;
280:
281: simple_lock_init(&ci->ci_slock);
282:
283: #if defined(MULTIPROCESSOR)
284: /*
285: * Allocate UPAGES contiguous pages for the idle PCB and stack.
286: */
287: kstack = uvm_km_alloc (kernel_map, USPACE);
288: if (kstack == 0) {
289: if (caa->cpu_role != CPU_ROLE_AP) {
290: panic("cpu_attach: unable to allocate idle stack for"
291: " primary");
292: }
293: printf("%s: unable to allocate idle stack\n",
294: sc->sc_dev.dv_xname);
295: return;
296: }
297: pcb = ci->ci_idle_pcb = (struct pcb *) kstack;
298: memset(pcb, 0, USPACE);
299:
300: pcb->pcb_tss.tss_rsp0 = kstack + USPACE - 16;
301: pcb->pcb_rbp = pcb->pcb_rsp = kstack + USPACE - 16;
302: pcb->pcb_tss.tss_ist[0] = kstack + PAGE_SIZE - 16;
303: pcb->pcb_pmap = pmap_kernel();
304: pcb->pcb_cr0 = rcr0();
305: pcb->pcb_cr3 = pcb->pcb_pmap->pm_pdirpa;
306: #endif
307:
308: /* further PCB init done later. */
309:
310: printf(": ");
311:
312: switch (caa->cpu_role) {
313: case CPU_ROLE_SP:
314: printf("(uniprocessor)\n");
315: ci->ci_flags |= CPUF_PRESENT | CPUF_SP | CPUF_PRIMARY;
316: cpu_intr_init(ci);
317: identifycpu(ci);
318: cpu_init(ci);
319: break;
320:
321: case CPU_ROLE_BP:
322: printf("apid %d (boot processor)\n", caa->cpu_number);
323: ci->ci_flags |= CPUF_PRESENT | CPUF_BSP | CPUF_PRIMARY;
324: cpu_intr_init(ci);
325: identifycpu(ci);
326: cpu_init(ci);
327:
328: #if NLAPIC > 0
329: /*
330: * Enable local apic
331: */
332: lapic_enable();
333: lapic_calibrate_timer(ci);
334: #endif
335: #if NIOAPIC > 0
336: ioapic_bsp_id = caa->cpu_number;
337: #endif
338: break;
339:
340: case CPU_ROLE_AP:
341: /*
342: * report on an AP
343: */
344: printf("apid %d (application processor)\n", caa->cpu_number);
345:
346: #if defined(MULTIPROCESSOR)
347: cpu_intr_init(ci);
348: gdt_alloc_cpu(ci);
349: cpu_start_secondary(ci);
350: ncpus++;
351: if (ci->ci_flags & CPUF_PRESENT) {
352: identifycpu(ci);
353: ci->ci_next = cpu_info_list->ci_next;
354: cpu_info_list->ci_next = ci;
355: }
356: #else
357: printf("%s: not started\n", sc->sc_dev.dv_xname);
358: #endif
359: break;
360:
361: default:
362: panic("unknown processor type??");
363: }
364: cpu_vm_init(ci);
365:
366: cpus_attached |= (1 << ci->ci_cpuid);
367:
368: #if defined(MULTIPROCESSOR)
369: if (mp_verbose) {
370: printf("%s: kstack at 0x%lx for %d bytes\n",
371: sc->sc_dev.dv_xname, kstack, USPACE);
372: printf("%s: idle pcb at %p, idle sp at 0x%lx\n",
373: sc->sc_dev.dv_xname, pcb, pcb->pcb_rsp);
374: }
375: #endif
376: }
377:
378: /*
379: * Initialize the processor appropriately.
380: */
381:
382: void
383: cpu_init(struct cpu_info *ci)
384: {
385: /* configure the CPU if needed */
386: if (ci->cpu_setup != NULL)
387: (*ci->cpu_setup)(ci);
388:
389: lcr0(rcr0() | CR0_WP);
390: lcr4(rcr4() | CR4_DEFAULT);
391:
392: #ifdef MTRR
393: if ((ci->ci_flags & CPUF_AP) == 0)
394: i686_mtrr_init_first();
395: mtrr_init_cpu(ci);
396: #endif
397:
398: #ifdef MULTIPROCESSOR
399: ci->ci_flags |= CPUF_RUNNING;
400: cpus_running |= 1 << ci->ci_cpuid;
401: #endif
402: }
403:
404:
405: #ifdef MULTIPROCESSOR
406: void
407: cpu_boot_secondary_processors(void)
408: {
409: struct cpu_info *ci;
410: u_long i;
411:
412: for (i=0; i < X86_MAXPROCS; i++) {
413: ci = cpu_info[i];
414: if (ci == NULL)
415: continue;
416: if (ci->ci_idle_pcb == NULL)
417: continue;
418: if ((ci->ci_flags & CPUF_PRESENT) == 0)
419: continue;
420: if (ci->ci_flags & (CPUF_BSP|CPUF_SP|CPUF_PRIMARY))
421: continue;
422: cpu_boot_secondary(ci);
423: }
424: }
425:
426: void
427: cpu_init_idle_pcbs(void)
428: {
429: struct cpu_info *ci;
430: u_long i;
431:
432: for (i=0; i < X86_MAXPROCS; i++) {
433: ci = cpu_info[i];
434: if (ci == NULL)
435: continue;
436: if (ci->ci_idle_pcb == NULL)
437: continue;
438: if ((ci->ci_flags & CPUF_PRESENT) == 0)
439: continue;
440: x86_64_init_pcb_tss_ldt(ci);
441: }
442: }
443:
444: void
445: cpu_start_secondary(struct cpu_info *ci)
446: {
447: struct pcb *pcb;
448: int i;
449:
450: pcb = ci->ci_idle_pcb;
451:
452: ci->ci_flags |= CPUF_AP;
453:
454: CPU_STARTUP(ci);
455:
456: /*
457: * wait for it to become ready
458: */
459: for (i = 100000; (!(ci->ci_flags & CPUF_PRESENT)) && i>0;i--) {
460: delay(10);
461: }
462: if (! (ci->ci_flags & CPUF_PRESENT)) {
463: printf("%s: failed to become ready\n", ci->ci_dev->dv_xname);
464: #if defined(MPDEBUG) && defined(DDB)
465: printf("dropping into debugger; continue from here to resume boot\n");
466: Debugger();
467: #endif
468: }
469:
470: CPU_START_CLEANUP(ci);
471: }
472:
473: void
474: cpu_boot_secondary(struct cpu_info *ci)
475: {
476: int i;
477:
478: ci->ci_flags |= CPUF_GO; /* XXX atomic */
479:
480: for (i = 100000; (!(ci->ci_flags & CPUF_RUNNING)) && i>0;i--) {
481: delay(10);
482: }
483: if (! (ci->ci_flags & CPUF_RUNNING)) {
484: printf("cpu failed to start\n");
485: #if defined(MPDEBUG) && defined(DDB)
486: printf("dropping into debugger; continue from here to resume boot\n");
487: Debugger();
488: #endif
489: }
490: }
491:
492: /*
493: * The CPU ends up here when its ready to run
494: * This is called from code in mptramp.s; at this point, we are running
495: * in the idle pcb/idle stack of the new cpu. When this function returns,
496: * this processor will enter the idle loop and start looking for work.
497: *
498: * XXX should share some of this with init386 in machdep.c
499: */
500: void
501: cpu_hatch(void *v)
502: {
503: struct cpu_info *ci = (struct cpu_info *)v;
504: int s;
505:
506: cpu_init_msrs(ci);
507:
508: cpu_probe_features(ci);
509: cpu_feature &= ci->ci_feature_flags;
510:
511: #ifdef DEBUG
512: if (ci->ci_flags & CPUF_PRESENT)
513: panic("%s: already running!?", ci->ci_dev->dv_xname);
514: #endif
515:
516: ci->ci_flags |= CPUF_PRESENT;
517:
518: lapic_enable();
519: lapic_initclocks();
520:
521: while ((ci->ci_flags & CPUF_GO) == 0)
522: delay(10);
523: #ifdef DEBUG
524: if (ci->ci_flags & CPUF_RUNNING)
525: panic("%s: already running!?", ci->ci_dev->dv_xname);
526: #endif
527:
528: lcr0(ci->ci_idle_pcb->pcb_cr0);
529: cpu_init_idt();
530: lapic_set_lvt();
531: gdt_init_cpu(ci);
532: fpuinit(ci);
533:
534: lldt(GSYSSEL(GLDT_SEL, SEL_KPL));
535:
536: cpu_init(ci);
537:
538: s = splhigh();
539: lcr8(0);
540: enable_intr();
541:
542: microuptime(&ci->ci_schedstate.spc_runtime);
543: splx(s);
544: }
545:
546: #if defined(DDB)
547:
548: #include <ddb/db_output.h>
549: #include <machine/db_machdep.h>
550:
551: /*
552: * Dump cpu information from ddb.
553: */
554: void
555: cpu_debug_dump(void)
556: {
557: struct cpu_info *ci;
558: CPU_INFO_ITERATOR cii;
559:
560: db_printf("addr dev id flags ipis curproc fpcurproc\n");
561: CPU_INFO_FOREACH(cii, ci) {
562: db_printf("%p %s %u %x %x %10p %10p\n",
563: ci,
564: ci->ci_dev == NULL ? "BOOT" : ci->ci_dev->dv_xname,
565: ci->ci_cpuid,
566: ci->ci_flags, ci->ci_ipis,
567: ci->ci_curproc,
568: ci->ci_fpcurproc);
569: }
570: }
571: #endif
572:
573: static void
574: cpu_copy_trampoline(void)
575: {
576: /*
577: * Copy boot code.
578: */
579: extern u_char cpu_spinup_trampoline[];
580: extern u_char cpu_spinup_trampoline_end[];
581:
582: struct pmap *kmp = pmap_kernel();
583: extern u_int32_t mp_pdirpa;
584: extern vaddr_t lo32_vaddr;
585: extern paddr_t lo32_paddr;
586:
587: pmap_kenter_pa((vaddr_t)MP_TRAMPOLINE, /* virtual */
588: (paddr_t)MP_TRAMPOLINE, /* physical */
589: VM_PROT_ALL); /* protection */
590: memcpy((caddr_t)MP_TRAMPOLINE,
591: cpu_spinup_trampoline,
592: cpu_spinup_trampoline_end-cpu_spinup_trampoline);
593:
594: /*
595: * The initial PML4 pointer must be below 4G, so if the
596: * current one isn't, use a "bounce buffer"
597: * We need to patch this after we copy the trampoline,
598: * the symbol points into the copied trampoline.
599: */
600: if (kmp->pm_pdirpa > 0xffffffff) {
601: memcpy((void *)lo32_vaddr, kmp->pm_pdir, PAGE_SIZE);
602: mp_pdirpa = lo32_paddr;
603: } else
604: mp_pdirpa = kmp->pm_pdirpa;
605: }
606:
607:
608: int
609: mp_cpu_start(struct cpu_info *ci)
610: {
611: #if NLAPIC > 0
612: int error;
613: #endif
614: unsigned short dwordptr[2];
615:
616: /*
617: * "The BSP must initialize CMOS shutdown code to 0Ah ..."
618: */
619:
620: outb(IO_RTC, NVRAM_RESET);
621: outb(IO_RTC+1, NVRAM_RESET_JUMP);
622:
623: /*
624: * "and the warm reset vector (DWORD based at 40:67) to point
625: * to the AP startup code ..."
626: */
627:
628: dwordptr[0] = 0;
629: dwordptr[1] = MP_TRAMPOLINE >> 4;
630:
631: pmap_kenter_pa(0, 0, VM_PROT_READ|VM_PROT_WRITE);
632: memcpy((u_int8_t *) 0x467, dwordptr, 4);
633: pmap_kremove(0, PAGE_SIZE);
634:
635: #if NLAPIC > 0
636: /*
637: * ... prior to executing the following sequence:"
638: */
639:
640: if (ci->ci_flags & CPUF_AP) {
641: if ((error = x86_ipi_init(ci->ci_apicid)) != 0)
642: return error;
643:
644: delay(10000);
645:
646: if (cpu_feature & CPUID_APIC) {
647: if ((error = x86_ipi(MP_TRAMPOLINE/PAGE_SIZE,
648: ci->ci_apicid,
649: LAPIC_DLMODE_STARTUP)) != 0)
650: return error;
651: delay(200);
652:
653: if ((error = x86_ipi(MP_TRAMPOLINE/PAGE_SIZE,
654: ci->ci_apicid,
655: LAPIC_DLMODE_STARTUP)) != 0)
656: return error;
657: delay(200);
658: }
659: }
660: #endif
661: return 0;
662: }
663:
664: void
665: mp_cpu_start_cleanup(struct cpu_info *ci)
666: {
667: /*
668: * Ensure the NVRAM reset byte contains something vaguely sane.
669: */
670:
671: outb(IO_RTC, NVRAM_RESET);
672: outb(IO_RTC+1, NVRAM_RESET_RST);
673: }
674: #endif /* MULTIPROCESSOR */
675:
676: typedef void (vector)(void);
677: extern vector Xsyscall, Xsyscall32;
678:
679: void
680: cpu_init_msrs(struct cpu_info *ci)
681: {
682: wrmsr(MSR_STAR,
683: ((uint64_t)GSEL(GCODE_SEL, SEL_KPL) << 32) |
684: ((uint64_t)LSEL(LSYSRETBASE_SEL, SEL_UPL) << 48));
685: wrmsr(MSR_LSTAR, (uint64_t)Xsyscall);
686: wrmsr(MSR_CSTAR, (uint64_t)Xsyscall32);
687: wrmsr(MSR_SFMASK, PSL_NT|PSL_T|PSL_I|PSL_C);
688:
689: wrmsr(MSR_FSBASE, 0);
690: wrmsr(MSR_GSBASE, (u_int64_t)ci);
691: wrmsr(MSR_KERNELGSBASE, 0);
692:
693: if (cpu_feature & CPUID_NXE)
694: wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_NXE);
695: }
CVSweb