Annotation of src/sys/arch/amd64/amd64/locore.S, Revision 1.76.8.2
1.76.8.2! snj 1: /* $NetBSD: locore.S,v 1.76.8.1 2017/04/26 14:51:58 martin Exp $ */
1.1 fvdl 2:
3: /*
4: * Copyright-o-rama!
5: */
6:
7: /*
1.32 bouyer 8: * Copyright (c) 2007 Manuel Bouyer.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29: *
30: */
31:
32: /*
33: * Copyright (c) 2006 Mathieu Ropert <mro@adviseo.fr>
34: *
35: * Permission to use, copy, modify, and distribute this software for any
36: * purpose with or without fee is hereby granted, provided that the above
37: * copyright notice and this permission notice appear in all copies.
38: *
39: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
40: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
41: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
42: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
43: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
44: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
45: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
46: */
47:
48: /*
1.1 fvdl 49: * Copyright (c) 2001 Wasabi Systems, Inc.
50: * All rights reserved.
51: *
52: * Written by Frank van der Linden for Wasabi Systems, Inc.
53: *
54: * Redistribution and use in source and binary forms, with or without
55: * modification, are permitted provided that the following conditions
56: * are met:
57: * 1. Redistributions of source code must retain the above copyright
58: * notice, this list of conditions and the following disclaimer.
59: * 2. Redistributions in binary form must reproduce the above copyright
60: * notice, this list of conditions and the following disclaimer in the
61: * documentation and/or other materials provided with the distribution.
62: * 3. All advertising materials mentioning features or use of this software
63: * must display the following acknowledgement:
64: * This product includes software developed for the NetBSD Project by
65: * Wasabi Systems, Inc.
66: * 4. The name of Wasabi Systems, Inc. may not be used to endorse
67: * or promote products derived from this software without specific prior
68: * written permission.
69: *
70: * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
71: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
72: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
73: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
74: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
75: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
76: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
77: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
78: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
79: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
80: * POSSIBILITY OF SUCH DAMAGE.
81: */
82:
83:
84: /*-
1.41 ad 85: * Copyright (c) 1998, 2000, 2007, 2008 The NetBSD Foundation, Inc.
1.1 fvdl 86: * All rights reserved.
87: *
88: * This code is derived from software contributed to The NetBSD Foundation
89: * by Charles M. Hannum.
90: *
91: * Redistribution and use in source and binary forms, with or without
92: * modification, are permitted provided that the following conditions
93: * are met:
94: * 1. Redistributions of source code must retain the above copyright
95: * notice, this list of conditions and the following disclaimer.
96: * 2. Redistributions in binary form must reproduce the above copyright
97: * notice, this list of conditions and the following disclaimer in the
98: * documentation and/or other materials provided with the distribution.
99: *
100: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
101: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
102: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
103: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
104: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
105: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
106: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
107: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
108: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
109: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
110: * POSSIBILITY OF SUCH DAMAGE.
111: */
112:
113: /*-
114: * Copyright (c) 1990 The Regents of the University of California.
115: * All rights reserved.
116: *
117: * This code is derived from software contributed to Berkeley by
118: * William Jolitz.
119: *
120: * Redistribution and use in source and binary forms, with or without
121: * modification, are permitted provided that the following conditions
122: * are met:
123: * 1. Redistributions of source code must retain the above copyright
124: * notice, this list of conditions and the following disclaimer.
125: * 2. Redistributions in binary form must reproduce the above copyright
126: * notice, this list of conditions and the following disclaimer in the
127: * documentation and/or other materials provided with the distribution.
1.5 agc 128: * 3. Neither the name of the University nor the names of its contributors
1.1 fvdl 129: * may be used to endorse or promote products derived from this software
130: * without specific prior written permission.
131: *
132: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
133: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
134: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
135: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
136: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
137: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
138: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
139: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
140: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
141: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
142: * SUCH DAMAGE.
143: *
144: * @(#)locore.s 7.3 (Berkeley) 5/13/91
145: */
146:
1.34 dsl 147: /*
148: * override user-land alignment before including asm.h
149: */
150: #define ALIGN_DATA .align 8
151: #define ALIGN_TEXT .align 16,0x90
152: #define _ALIGN_TEXT ALIGN_TEXT
153:
154: #include <machine/asm.h>
155:
1.1 fvdl 156: #include "opt_ddb.h"
157: #include "opt_ddbparam.h"
1.51 apb 158: #include "opt_modular.h"
1.1 fvdl 159: #include "opt_realmem.h"
160:
1.12 drochner 161: #include "opt_compat_netbsd.h"
162: #include "opt_compat_netbsd32.h"
163: #include "opt_compat_ibcs2.h"
1.32 bouyer 164: #include "opt_xen.h"
1.12 drochner 165:
1.1 fvdl 166: #include "assym.h"
167: #include "lapic.h"
168: #include "ioapic.h"
1.2 fvdl 169: #include "ksyms.h"
1.1 fvdl 170:
171: #include <sys/errno.h>
172: #include <sys/syscall.h>
173:
174: #include <machine/pte.h>
175: #include <machine/segments.h>
176: #include <machine/specialreg.h>
177: #include <machine/trap.h>
178: #include <machine/bootinfo.h>
179: #include <machine/frameasm.h>
1.44 ad 180: #include <machine/cputypes.h>
1.1 fvdl 181:
182: #if NLAPIC > 0
183: #include <machine/i82489reg.h>
184: #endif
185:
186: /* XXX temporary kluge; these should not be here */
187: /* Get definitions for IOM_BEGIN, IOM_END, and IOM_SIZE */
188: #include <dev/isa/isareg.h>
189:
1.71 uebayasi 190: #define _RELOC(x) ((x) - KERNBASE)
191: #define RELOC(x) _RELOC(_C_LABEL(x))
192:
1.32 bouyer 193: #ifdef XEN
194:
195: /*
1.73 uebayasi 196: * Xen guest identifier and loader selection
1.32 bouyer 197: */
198:
199: .section __xen_guest
200:
1.73 uebayasi 201: .ascii "GUEST_OS=NetBSD,GUEST_VER=4.99"
202: .ascii ",XEN_VER=xen-3.0"
203: .ascii ",LOADER=generic"
1.32 bouyer 204: .ascii ",VIRT_BASE=0xffffffff80000000"
205: .ascii ",ELF_PADDR_OFFSET=0xffffffff80000000"
206: .ascii ",VIRT_ENTRY=0xffffffff80100000"
207: .ascii ",HYPERCALL_PAGE=0x00000101" /* (???+HYPERCALL_PAGE_OFFSET)/PAGE_SIZE) */
1.49 ad 208: #if NKSYMS > 0 || defined(DDB) || defined(MODULAR)
1.33 bouyer 209: .ascii ",BSD_SYMTAB=yes"
1.32 bouyer 210: #endif
1.73 uebayasi 211: .byte 0
1.32 bouyer 212:
213: #endif /* XEN */
1.1 fvdl 214:
215: /*
216: * Initialization
217: */
218: .data
219:
1.73 uebayasi 220: #if NLAPIC > 0
221: .align PAGE_SIZE
1.71 uebayasi 222: .globl _C_LABEL(local_apic)
223: .globl _C_LABEL(lapic_id)
224: .globl _C_LABEL(lapic_tpr)
225:
226: .type _C_LABEL(local_apic), @object
227: LABEL(local_apic)
1.73 uebayasi 228: .space LAPIC_ID
1.71 uebayasi 229: END(local_apic)
230: .type _C_LABEL(lapic_id), @object
231: LABEL(lapic_id)
1.73 uebayasi 232: .long 0x00000000
233: .space LAPIC_TPRI-(LAPIC_ID+4)
1.71 uebayasi 234: END(lapic_id)
235: .type _C_LABEL(lapic_tpr), @object
236: LABEL(lapic_tpr)
1.73 uebayasi 237: .space LAPIC_PPRI-LAPIC_TPRI
1.71 uebayasi 238: END(lapic_tpr)
239: .type _C_LABEL(lapic_ppr), @object
1.1 fvdl 240: _C_LABEL(lapic_ppr):
1.73 uebayasi 241: .space LAPIC_ISR-LAPIC_PPRI
1.71 uebayasi 242: END(lapic_ppr)
243: .type _C_LABEL(lapic_isr), @object
1.1 fvdl 244: _C_LABEL(lapic_isr):
1.73 uebayasi 245: .space PAGE_SIZE-LAPIC_ISR
1.71 uebayasi 246: END(lapic_isr)
1.1 fvdl 247: #endif
248:
1.71 uebayasi 249: .globl _C_LABEL(cpu_id)
250: .globl _C_LABEL(cpu_vendorname)
251: .globl _C_LABEL(cpu_brand_id)
1.57 jym 252: .globl _C_LABEL(cpuid_level)
1.71 uebayasi 253: .globl _C_LABEL(esym)
254: .globl _C_LABEL(eblob)
255: .globl _C_LABEL(boothowto)
256: .globl _C_LABEL(bootinfo)
257: .globl _C_LABEL(atdevbase)
1.54 matt 258: .globl _C_LABEL(PDPpaddr)
1.71 uebayasi 259: .globl _C_LABEL(biosbasemem)
260: .globl _C_LABEL(biosextmem)
261: .globl _C_LABEL(gdtstore)
262: .globl _C_LABEL(cputype)
1.43 ad 263:
1.71 uebayasi 264: .type _C_LABEL(cputype), @object
1.73 uebayasi 265: LABEL(cputype) .long 0 # are we 80486, Pentium, or..
1.71 uebayasi 266: END(cputype)
267: .type _C_LABEL(cpu_id), @object
268: LABEL(cpu_id) .long 0 # saved from `cpuid' instruction
269: END(cpu_id)
270: .type _C_LABEL(cpuid_level), @object
271: LABEL(cpuid_level) .long -1 # max. level accepted by 'cpuid'
1.1 fvdl 272: # instruction
1.71 uebayasi 273: END(cpuid_level)
274: .type _C_LABEL(cpu_vendorname), @object
275: LABEL(cpu_vendorname) .space 16 # vendor string returned by `cpuid'
1.1 fvdl 276: # instruction
1.71 uebayasi 277: END(cpu_vendorname)
278: .type _C_LABEL(cpu_brand_id), @object
279: LABEL(cpu_brand_id) .long 0 # brand ID from 'cpuid' instruction
280: END(cpu_brand_id)
281: .type _C_LABEL(esym), @object
282: LABEL(esym) .quad 0 # ptr to end of syms
283: END(esym)
284: .type _C_LABEL(eblob), @object
285: LABEL(eblob) .quad 0 # ptr to end of modules
286: END(eblob)
287: .type _C_LABEL(atdevbase), @object
288: LABEL(atdevbase) .quad 0 # location of start of iomem in virtual
289: END(atdevbase)
290: .type _C_LABEL(PDPpaddr), @object
291: LABEL(PDPpaddr) .quad 0 # paddr of PTD, for libkvm
292: END(PDPpaddr)
293: .type _C_LABEL(biosbasemem), @object
1.1 fvdl 294: #ifndef REALBASEMEM
1.71 uebayasi 295: LABEL(biosbasemem) .long 0 # base memory reported by BIOS
1.1 fvdl 296: #else
1.71 uebayasi 297: LABEL(biosbasemem) .long REALBASEMEM
1.1 fvdl 298: #endif
1.71 uebayasi 299: END(biosbasemem)
300: .type _C_LABEL(biosextmem), @object
1.1 fvdl 301: #ifndef REALEXTMEM
1.71 uebayasi 302: LABEL(biosextmem) .long 0 # extended memory reported by BIOS
1.1 fvdl 303: #else
1.71 uebayasi 304: LABEL(biosextmem) .long REALEXTMEM
1.1 fvdl 305: #endif
1.71 uebayasi 306: END(biosextmem)
1.1 fvdl 307:
1.32 bouyer 308: #ifndef XEN
1.56 jym 309: .globl gdt64_lo
310: .globl gdt64_hi
1.1 fvdl 311:
1.56 jym 312: #define GDT64_LIMIT gdt64_end-gdt64_start-1
313:
314: /* Temporary gdt64, with base address in low memory */
1.71 uebayasi 315: .type _C_LABEL(gdt64_lo), @object
316: LABEL(gdt64_lo)
1.56 jym 317: .word GDT64_LIMIT
1.1 fvdl 318: .quad _RELOC(gdt64_start)
1.71 uebayasi 319: END(gdt64_lo)
1.1 fvdl 320: .align 64
321:
1.56 jym 322: /* Temporary gdt64, with base address in high memory */
1.71 uebayasi 323: .type _C_LABEL(gdt64_hi), @object
324: LABEL(gdt64_hi)
1.56 jym 325: .word GDT64_LIMIT
326: .quad gdt64_start
1.71 uebayasi 327: END(gdt64_hi)
1.56 jym 328: .align 64
329:
330: #undef GDT64_LIMIT
331:
1.71 uebayasi 332: .type _C_LABEL(gdt64_start), @object
333: _C_LABEL(gdt64_start):
1.1 fvdl 334: .quad 0x0000000000000000 /* always empty */
335: .quad 0x00af9a000000ffff /* kernel CS */
336: .quad 0x00cf92000000ffff /* kernel DS */
1.71 uebayasi 337: END(gdt64_start)
1.1 fvdl 338: gdt64_end:
339:
1.71 uebayasi 340: .type _C_LABEL(farjmp64), @object
341: _C_LABEL(farjmp64):
1.57 jym 342: .long _RELOC(longmode)
1.1 fvdl 343: .word GSEL(GCODE_SEL, SEL_KPL)
1.71 uebayasi 344: END(farjmp64)
1.1 fvdl 345:
1.32 bouyer 346: #endif /* !XEN */
1.71 uebayasi 347:
348: .size tmpstk, tmpstk - .
1.1 fvdl 349: .space 512
350: tmpstk:
351:
352: .globl _C_LABEL(cpu_private)
1.73 uebayasi 353: .comm _C_LABEL(cpu_private),PAGE_SIZE,PAGE_SIZE
1.1 fvdl 354:
355: /*
356: * Some hackage to deal with 64bit symbols in 32 bit mode.
357: * This may not be needed it things are cleaned up a little.
358: */
359:
360:
361: .text
362: .globl _C_LABEL(kernel_text)
363: .set _C_LABEL(kernel_text),KERNTEXTOFF
364:
1.71 uebayasi 365: ENTRY(start)
1.32 bouyer 366: #ifndef XEN
1.71 uebayasi 367: .code32
368: movw $0x1234,0x472 # warm boot
1.1 fvdl 369: /*
370: * Load parameters from stack
371: * (howto, [bootdev], bootinfo, esym, basemem, extmem).
372: */
373: movl 4(%esp),%eax
374: movl %eax,RELOC(boothowto)
375: movl 12(%esp),%eax
376: testl %eax, %eax
377: jz 1f
378: movl (%eax), %ebx /* number of entries */
379: movl $RELOC(bootinfo),%ebp
380: movl %ebp, %edx
381: addl $BOOTINFO_MAXSIZE,%ebp
382: movl %ebx, (%edx)
383: addl $4, %edx
384: 2:
385: testl %ebx, %ebx
386: jz 1f
387: addl $4, %eax
388: movl (%eax), %ecx /* address of entry */
389: pushl %edi
390: pushl %esi
391: pushl %eax
392:
393: movl (%ecx),%eax /* len */
394: movl %edx,%edi
395: addl (%ecx), %edx /* update dest pointer */
396: cmpl %ebp, %edx
397: jg 2f
398: movl %ecx,%esi
399: movl %eax,%ecx
1.43 ad 400: /*
401: * If any modules were loaded, record where they
402: * end. We'll need to skip over them.
403: */
404: cmpl $BTINFO_MODULELIST, 4(%esi)
405: jne 0f
406: pushl 12(%esi) /* endpa */
407: popl RELOC(eblob)
408: addl $KERNBASE_LO, RELOC(eblob)
409: adcl $KERNBASE_HI, RELOC(eblob)+4
410: 0:
1.1 fvdl 411: rep
412: movsb
413: popl %eax
414: popl %esi
415: popl %edi
416: subl $1, %ebx
417: jmp 2b
418: 2: /* cleanup for overflow case */
419: popl %eax
420: popl %esi
421: popl %edi
422: movl $RELOC(bootinfo),%ebp
423: movl %ebp, %edx
424: subl %ebx, (%edx) /* correct number of entries */
425: 1:
426:
1.72 uebayasi 427: movl 16(%esp),%eax
1.1 fvdl 428: testl %eax,%eax
429: jz 1f
430: addl $KERNBASE_LO,%eax
431: 1: movl $RELOC(esym),%ebp
432: movl %eax,(%ebp)
433: movl $KERNBASE_HI,4(%ebp)
434:
435: movl $RELOC(biosextmem),%ebp
436: movl (%ebp),%eax
437: testl %eax,%eax
438: jnz 1f
439: movl 20(%esp),%eax
440: movl %eax,(%ebp)
441: 1:
442: movl $RELOC(biosbasemem),%ebp
443: movl (%ebp),%eax
444: testl %eax,%eax
445: jnz 1f
446: movl 24(%esp),%eax
447: movl %eax,(%ebp)
448: 1:
449:
450: /* First, reset the PSL. */
451: pushl $PSL_MBO
452: popfl
453:
454: xorl %eax,%eax
455: cpuid
456: movl %eax,RELOC(cpuid_level)
1.30 ad 457: movl $RELOC(cpu_vendorname),%ebp
1.1 fvdl 458: movl %ebx,(%ebp)
459: movl %edx,4(%ebp)
460: movl %ecx,8(%ebp)
1.73 uebayasi 461: movl $0, 12(%ebp)
1.1 fvdl 462:
463: movl $1,%eax
464: cpuid
465: movl %eax,RELOC(cpu_id)
466:
467: /* Brand ID is bits 0-7 of %ebx */
468: andl $255,%ebx
469: movl %ebx,RELOC(cpu_brand_id)
470:
471: /*
472: * Finished with old stack; load new %esp now instead of later so we
473: * can trace this code without having to worry about the trace trap
474: * clobbering the memory test or the zeroing of the bss+bootstrap page
475: * tables.
476: *
477: * The boot program should check:
478: * text+data <= &stack_variable - more_space_for_stack
479: * text+data+bss+pad+space_for_page_tables <= end_of_memory
480: * Oops, the gdt is in the carcass of the boot program so clearing
481: * the rest of memory is still not possible.
482: */
483: movl $RELOC(tmpstk),%esp
484:
485: /*
486: * Virtual address space of kernel:
487: *
1.73 uebayasi 488: * text | data | bss | [syms] | page dir | proc0 kstack | L1 ptp | L2 ptp | L3
1.1 fvdl 489: * 0 1 2 3
490: */
491:
492: #if L2_SLOT_KERNBASE > 0
493: #define TABLE_L2_ENTRIES (2 * (NKL2_KIMG_ENTRIES + 1))
494: #else
495: #define TABLE_L2_ENTRIES (NKL2_KIMG_ENTRIES + 1)
496: #endif
497:
498: #if L3_SLOT_KERNBASE > 0
499: #define TABLE_L3_ENTRIES (2 * NKL3_KIMG_ENTRIES)
500: #else
501: #define TABLE_L3_ENTRIES NKL3_KIMG_ENTRIES
502: #endif
503:
504:
505: #define PROC0_PML4_OFF 0
1.73 uebayasi 506: #define PROC0_STK_OFF (PROC0_PML4_OFF + PAGE_SIZE)
507: #define PROC0_PTP3_OFF (PROC0_STK_OFF + UPAGES * PAGE_SIZE)
508: #define PROC0_PTP2_OFF (PROC0_PTP3_OFF + NKL4_KIMG_ENTRIES * PAGE_SIZE)
509: #define PROC0_PTP1_OFF (PROC0_PTP2_OFF + TABLE_L3_ENTRIES * PAGE_SIZE)
1.1 fvdl 510: #define TABLESIZE \
511: ((NKL4_KIMG_ENTRIES + TABLE_L3_ENTRIES + TABLE_L2_ENTRIES + 1 + UPAGES) \
1.73 uebayasi 512: * PAGE_SIZE)
1.1 fvdl 513:
514: #define fillkpt \
1.73 uebayasi 515: 1: movl %eax,(%ebx) ; /* store phys addr */ \
516: movl $0,4(%ebx) ; /* upper 32 bits 0 */ \
517: addl $8,%ebx ; /* next pte/pde */ \
518: addl $PAGE_SIZE,%eax ; /* next phys page */ \
519: loop 1b ;
1.1 fvdl 520:
521: /* Find end of kernel image. */
522: movl $RELOC(end),%edi
1.49 ad 523: #if (NKSYMS || defined(DDB) || defined(MODULAR)) && !defined(SYMTAB_SPACE)
1.1 fvdl 524: /* Save the symbols (if loaded). */
525: movl RELOC(esym),%eax
526: testl %eax,%eax
527: jz 1f
528: subl $KERNBASE_LO,%eax /* XXX */
529: movl %eax,%edi
530: 1:
531: #endif
1.43 ad 532: /* Skip over any modules/blobs. */
533: movl RELOC(eblob),%eax
534: testl %eax,%eax
535: jz 1f
536: subl $KERNBASE_LO,%eax /* XXX */
537: movl %eax,%edi
538: 1:
1.73 uebayasi 539: /* Compute sizes */
1.1 fvdl 540: movl %edi,%esi
1.73 uebayasi 541: addl $PGOFSET,%esi # page align up
1.1 fvdl 542: andl $~PGOFSET,%esi
543:
544: movl %esi,%edi
545: xorl %eax,%eax
546: cld
547: movl $TABLESIZE,%ecx
548: shrl $2,%ecx
549: rep
550: stosl
551:
552: leal (PROC0_PTP1_OFF)(%esi), %ebx
553:
1.73 uebayasi 554: /*
555: * Build initial page tables.
556: */
1.1 fvdl 557: /*
1.72 uebayasi 558: * Compute &__data_start - KERNBASE. This can't be > 4G,
1.29 yamt 559: * or we can't deal with it anyway, since we can't load it in
560: * 32 bit mode. So use the bottom 32 bits.
1.1 fvdl 561: */
1.29 yamt 562: movl $RELOC(__data_start),%edx
1.1 fvdl 563: andl $~PGOFSET,%edx
564:
565: /*
566: * Skip the first MB.
567: */
568: movl $(KERNTEXTOFF_LO - KERNBASE_LO),%eax
569: movl %eax,%ecx
570: shrl $(PGSHIFT-3),%ecx /* ((n >> PGSHIFT) << 3) for # pdes */
571: addl %ecx,%ebx
572:
1.73 uebayasi 573: /* Map the kernel text read-only. */
1.1 fvdl 574: movl %edx,%ecx
575: subl %eax,%ecx
576: shrl $PGSHIFT,%ecx
1.73 uebayasi 577: orl $(PG_V|PG_KR),%eax
1.1 fvdl 578: fillkpt
579:
580: /* Map the data, BSS, and bootstrap tables read-write. */
581: leal (PG_V|PG_KW)(%edx),%eax
582: movl $TABLESIZE,%ecx
1.73 uebayasi 583: addl %esi,%ecx # end of tables
584: subl %edx,%ecx # subtract end of text
1.1 fvdl 585: shrl $PGSHIFT,%ecx
586: fillkpt
587:
588: /* Map ISA I/O mem (later atdevbase) */
1.73 uebayasi 589: movl $(IOM_BEGIN|PG_V|PG_KW/*|PG_N*/),%eax # having these bits set
590: movl $(IOM_SIZE>>PGSHIFT),%ecx # for this many pte s,
1.1 fvdl 591: fillkpt
592:
1.73 uebayasi 593: /*
594: * Construct a page table directory.
595: */
1.1 fvdl 596: /* Set up level 2 pages */
1.73 uebayasi 597: leal (PROC0_PTP2_OFF)(%esi),%ebx
1.1 fvdl 598: leal (PROC0_PTP1_OFF)(%esi),%eax
599: orl $(PG_V|PG_KW), %eax
600: movl $(NKL2_KIMG_ENTRIES+1),%ecx
601: fillkpt
602:
603: #if L2_SLOT_KERNBASE > 0
604: /* If needed, set up level 2 entries for actual kernel mapping */
605: leal (PROC0_PTP2_OFF+ L2_SLOT_KERNBASE*8)(%esi),%ebx
1.73 uebayasi 606: leal (PROC0_PTP1_OFF)(%esi),%eax
607: orl $(PG_V|PG_KW), %eax
608: movl $(NKL2_KIMG_ENTRIES+1),%ecx
1.1 fvdl 609: fillkpt
610: #endif
611:
612: /* Set up level 3 pages */
1.73 uebayasi 613: leal (PROC0_PTP3_OFF)(%esi),%ebx
1.1 fvdl 614: leal (PROC0_PTP2_OFF)(%esi),%eax
615: orl $(PG_V|PG_KW), %eax
616: movl $NKL3_KIMG_ENTRIES,%ecx
617: fillkpt
618:
619: #if L3_SLOT_KERNBASE > 0
620: /* If needed, set up level 3 entries for actual kernel mapping */
621: leal (PROC0_PTP3_OFF+ L3_SLOT_KERNBASE*8)(%esi),%ebx
1.73 uebayasi 622: leal (PROC0_PTP2_OFF)(%esi),%eax
623: orl $(PG_V|PG_KW), %eax
624: movl $NKL3_KIMG_ENTRIES,%ecx
1.1 fvdl 625: fillkpt
626: #endif
627:
628: /* Set up top level entries for identity mapping */
1.73 uebayasi 629: leal (PROC0_PML4_OFF)(%esi),%ebx
1.1 fvdl 630: leal (PROC0_PTP3_OFF)(%esi),%eax
631: orl $(PG_V|PG_KW), %eax
632: movl $NKL4_KIMG_ENTRIES,%ecx
633: fillkpt
634:
635: /* Set up top level entries for actual kernel mapping */
1.73 uebayasi 636: leal (PROC0_PML4_OFF + L4_SLOT_KERNBASE*8)(%esi),%ebx
1.1 fvdl 637: leal (PROC0_PTP3_OFF)(%esi),%eax
638: orl $(PG_V|PG_KW), %eax
639: movl $NKL4_KIMG_ENTRIES,%ecx
640: fillkpt
641:
642: /* Install recursive top level PDE */
1.73 uebayasi 643: leal (PROC0_PML4_OFF + PDIR_SLOT_PTE*8)(%esi),%ebx
644: leal (PROC0_PML4_OFF)(%esi),%eax
1.1 fvdl 645: orl $(PG_V|PG_KW),%eax
646: movl %eax,(%ebx)
647: movl $0, 4(%ebx)
648:
649:
650: /* Save phys. addr of PTD, for libkvm. */
1.29 yamt 651: movl $RELOC(PDPpaddr),%ebp
1.1 fvdl 652: movl %esi,(%ebp)
653: movl $0,4(%ebp)
654:
655: /*
656: * Startup checklist:
657: * 1. Enable PAE (and SSE while here).
658: */
659: movl %cr4,%eax
660: orl $(CR4_PAE|CR4_OSFXSR|CR4_OSXMMEXCPT),%eax
661: movl %eax,%cr4
662:
663: /*
664: * 2. Set Long Mode Enable in EFER. Also enable the
665: * syscall extensions.
666: */
1.73 uebayasi 667: movl $MSR_EFER,%ecx
1.1 fvdl 668: rdmsr
669: xorl %eax,%eax /* XXX */
670: orl $(EFER_LME|EFER_SCE),%eax
671: wrmsr
672:
673: /*
674: * 3. Load %cr3 with pointer to PML4.
675: */
676: movl %esi,%eax
677: movl %eax,%cr3
678:
679: /*
680: * 4. Enable paging and the rest of it.
681: */
682: movl %cr0,%eax
1.68 jym 683: orl $(CR0_PE|CR0_PG|CR0_NE|CR0_TS|CR0_MP|CR0_WP|CR0_AM),%eax
1.1 fvdl 684: movl %eax,%cr0
685: jmp compat
686: compat:
687:
688: /*
689: * 5.
690: * Not quite done yet, we're now in a compatibility segment,
691: * in legacy mode. We must jump to a long mode segment.
692: * Need to set up a temporary GDT with a long mode segment
693: * in it to do that.
694: */
695:
1.56 jym 696: movl $RELOC(gdt64_lo),%eax
1.1 fvdl 697: lgdt (%eax)
698: movl $RELOC(farjmp64),%eax
699: ljmp *(%eax)
700:
701: .code64
702: longmode:
703: /*
704: * 6.
705: * Finally, we're in long mode. However, we're still
706: * in the identity mapped area (could not jump out
707: * of that earlier because it would have been a > 32bit
708: * jump). We can do that now, so here we go.
709: */
710: movabsq $longmode_hi,%rax
711: jmp *%rax
1.56 jym 712:
1.1 fvdl 713: longmode_hi:
1.56 jym 714:
715: /*
716: * We left the identity mapped area. Base address of
717: * the temporary gdt64 should now be in high memory.
718: */
719: movq $RELOC(gdt64_hi),%rax
720: lgdt (%rax)
721:
1.1 fvdl 722: /*
1.73 uebayasi 723: * We have arrived.
1.1 fvdl 724: * There's no need anymore for the identity mapping in low
725: * memory, remove it.
726: */
727: movq $KERNBASE,%r8
728:
729: #if L2_SLOT_KERNBASE > 0
730: movq $(NKL2_KIMG_ENTRIES+1),%rcx
731: leaq (PROC0_PTP2_OFF)(%rsi),%rbx
732: addq %r8, %rbx
733: 1: movq $0,(%rbx)
734: addq $8,%rbx
735: loop 1b
736: #endif
737:
738: #if L3_SLOT_KERNBASE > 0
739: movq $NKL3_KIMG_ENTRIES,%rcx
740: leaq (PROC0_PTP3_OFF)(%rsi),%rbx
741: addq %r8, %rbx
742: 1: movq $0,(%rbx)
743: addq $8,%rbx
744: loop 1b
745: #endif
746:
747: movq $NKL4_KIMG_ENTRIES,%rcx
748: leaq (PROC0_PML4_OFF)(%rsi),%rbx # old, phys address of PML4
1.8 wiz 749: addq %r8, %rbx # new, virtual address of PML4
1.1 fvdl 750: 1: movq $0,(%rbx)
751: addq $8,%rbx
752: loop 1b
753:
754: /* Relocate atdevbase. */
755: movq $(TABLESIZE+KERNBASE),%rdx
756: addq %rsi,%rdx
757: movq %rdx,_C_LABEL(atdevbase)(%rip)
758:
759: /* Set up bootstrap stack. */
760: leaq (PROC0_STK_OFF)(%rsi),%rax
761: addq %r8,%rax
1.55 rmind 762: movq %rax,(_C_LABEL(lwp0)+L_PCB)(%rip) /* XXX L_PCB != uarea */
1.1 fvdl 763: leaq (USPACE-FRAMESIZE)(%rax),%rsp
764: movq %rsi,PCB_CR3(%rax) # pcb->pcb_cr3
1.73 uebayasi 765: xorq %rbp,%rbp # mark end of frames
1.1 fvdl 766:
767: xorw %ax,%ax
768: movw %ax,%gs
769: movw %ax,%fs
770:
771: /* XXX merge these */
1.46 ad 772: leaq (TABLESIZE+IOM_SIZE)(%rsi),%rdi
1.32 bouyer 773:
774: #else /* XEN */
775: /* First, reset the PSL. */
776: pushq $2
777: popfq
778:
779: cld
780:
781: /*
782: * Xen info:
783: * - %rsi -> start_info struct
784: * - %rsp -> stack, *theorically* the last used page
785: * by Xen bootstrap
786: */
787: movq %rsi, %rbx
788:
1.73 uebayasi 789: /* Clear BSS. */
1.32 bouyer 790: xorq %rax,%rax
791: movq $_C_LABEL(__bss_start),%rdi
792: movq $_C_LABEL(_end),%rcx
793: subq %rdi,%rcx
794: rep
795: stosb
796:
797: /* Copy start_info to a safe place */
798: movq %rbx,%rsi
799: movq $_C_LABEL(start_info_union),%rdi
800: movq $64,%rcx
801: rep
802: movsq
803:
804: /*
805: * Memory layout at start of the day:
806: * - Kernel image
807: * - Page frames list
808: * - start_info struct. we copied it, so it can be recycled.
809: * - xenstore
810: * - console
811: * - Xen bootstrap page tables
812: * - kernel stack. provided by Xen
813: * - guaranted 512kB padding
814: *
815: * As we want to rebuild our page tables and place our stack
816: * in proc0 struct, all data starting from after console can be
817: * discarded after we've done a little setup.
818: */
819:
820: /*
821: * We want our own page tables, let's rebuild them
822: * We will reclaim xen space afterward INCLUDING stack
823: * so let's change it to a temporary one
824: */
825:
826: movq $tmpstk, %rax
827: subq $8, %rax
828: movq %rax, %rsp
829:
1.45 bouyer 830: xorl %eax,%eax
831: cpuid
832: movl %eax,_C_LABEL(cpuid_level)
833:
1.67 cherry 834: movq $cpu_info_primary, %rdi
835: movq %rdi, CPU_INFO_SELF(%rdi) /* ci->ci_self = ci */
836: movq $1, %rsi
837: call cpu_init_msrs /* cpu_init_msrs(ci, true); */
838:
1.32 bouyer 839: call xen_pmap_bootstrap
840:
841: /*
842: * First avail returned by xen_pmap_bootstrap in %rax
843: */
844: movq %rax, %rsi
1.55 rmind 845: movq %rsi,(_C_LABEL(lwp0)+L_PCB) /* XXX L_PCB != uarea */
1.32 bouyer 846:
847: /*
848: * Set new stack and clear segments
849: */
850:
851: leaq (USPACE-FRAMESIZE)(%rsi),%rsp
852: xorq %rbp,%rbp
853:
1.63 jym 854: xorw %ax,%ax
1.32 bouyer 855: movw %ax,%gs
856: movw %ax,%fs
857:
858: /*
859: * Set first_avail after proc0
860: */
861:
862: movq %rsi,%rdi
863: addq $USPACE,%rdi
864: subq $KERNBASE,%rdi # init_x86_64 want a physical address
865:
1.73 uebayasi 866: #endif /* XEN */
1.1 fvdl 867: call _C_LABEL(init_x86_64)
868:
869: call _C_LABEL(main)
1.71 uebayasi 870: END(start)
1.1 fvdl 871:
1.73 uebayasi 872: #if defined(XEN)
1.32 bouyer 873: /* space for the hypercall call page */
874: #define HYPERCALL_PAGE_OFFSET 0x1000
875: .org HYPERCALL_PAGE_OFFSET
876: ENTRY(hypercall_page)
877: .skip 0x1000
1.71 uebayasi 878: END(hypercall_page)
1.32 bouyer 879: #endif /* XEN */
1.1 fvdl 880:
881: /*
1.22 yamt 882: * int setjmp(label_t *)
883: *
884: * Used primarily by DDB.
885: */
1.1 fvdl 886: ENTRY(setjmp)
887: /*
888: * Only save registers that must be preserved across function
889: * calls according to the ABI (%rbx, %rsp, %rbp, %r12-%r15)
890: * and %rip.
891: */
892: movq %rdi,%rax
893: movq %rbx,(%rax)
894: movq %rsp,8(%rax)
895: movq %rbp,16(%rax)
896: movq %r12,24(%rax)
897: movq %r13,32(%rax)
898: movq %r14,40(%rax)
899: movq %r15,48(%rax)
900: movq (%rsp),%rdx
901: movq %rdx,56(%rax)
902: xorl %eax,%eax
903: ret
1.71 uebayasi 904: END(setjmp)
1.1 fvdl 905:
1.22 yamt 906: /*
907: * int longjmp(label_t *)
908: *
909: * Used primarily by DDB.
910: */
1.1 fvdl 911: ENTRY(longjmp)
912: movq %rdi,%rax
913: movq (%rax),%rbx
914: movq 8(%rax),%rsp
915: movq 16(%rax),%rbp
916: movq 24(%rax),%r12
917: movq 32(%rax),%r13
918: movq 40(%rax),%r14
919: movq 48(%rax),%r15
920: movq 56(%rax),%rdx
921: movq %rdx,(%rsp)
1.22 yamt 922: movl $1,%eax
1.1 fvdl 923: ret
1.71 uebayasi 924: END(longjmp)
1.1 fvdl 925:
1.73 uebayasi 926: /*
927: * void dumpsys(void)
928: *
929: * Mimic cpu_switchto() for postmortem debugging.
930: */
1.25 yamt 931: ENTRY(dumpsys)
932: # build a fake switch frame.
933: pushq %rbx
934: pushq %r12
935: pushq %r13
936: pushq %r14
937: pushq %r15
938:
939: # save a context.
940: movq $dumppcb, %rax
941: movq %rsp, PCB_RSP(%rax)
942: movq %rbp, PCB_RBP(%rax)
943:
944: call _C_LABEL(dodumpsys)
945:
946: addq $(5*8), %rsp # sizeof(switchframe) - sizeof(%rip)
947: ret
1.71 uebayasi 948: END(dumpsys)
1.25 yamt 949:
1.1 fvdl 950: /*
1.58 chs 951: * struct lwp *cpu_switchto(struct lwp *oldlwp, struct lwp *newlwp,
1.35 ad 952: * bool returning)
1.22 yamt 953: *
954: * 1. if (oldlwp != NULL), save its context.
955: * 2. then, restore context of newlwp.
956: *
957: * Note that the stack frame layout is known to "struct switchframe" in
958: * <machine/frame.h> and to the code in cpu_lwp_fork() which initializes
959: * it for a new lwp.
1.1 fvdl 960: */
1.22 yamt 961: ENTRY(cpu_switchto)
1.1 fvdl 962: pushq %rbx
963: pushq %r12
964: pushq %r13
965: pushq %r14
966: pushq %r15
967:
1.22 yamt 968: movq %rdi,%r13 # oldlwp
969: movq %rsi,%r12 # newlwp
1.1 fvdl 970:
1.22 yamt 971: testq %r13,%r13
972: jz 1f
1.1 fvdl 973:
1.22 yamt 974: /* Save old context. */
1.55 rmind 975: movq L_PCB(%r13),%rax
1.22 yamt 976: movq %rsp,PCB_RSP(%rax)
977: movq %rbp,PCB_RBP(%rax)
978:
979: /* Switch to newlwp's stack. */
1.55 rmind 980: 1: movq L_PCB(%r12),%r14
1.32 bouyer 981: #ifdef XEN /* XXX debug code */
982: cmpq $0, PCB_RSP(%r14)
983: jne 999f
984: callq _C_LABEL(cpu_Debugger);
985: 999:
986: #endif
1.22 yamt 987: movq PCB_RSP(%r14),%rsp
988: movq PCB_RBP(%r14),%rbp
1.1 fvdl 989:
1.39 ad 990: /*
991: * Set curlwp. This must be globally visible in order to permit
992: * non-interlocked mutex release.
993: */
994: movq %r12,%rcx
995: xchgq %rcx,CPUVAR(CURLWP)
1.35 ad 996:
997: /* Skip the rest if returning to a pinned LWP. */
998: testb %dl,%dl
999: jnz 4f
1000:
1.38 yamt 1001: /* Switch ring0 stack */
1002: #ifndef XEN
1003: movq PCB_RSP0(%r14),%rax
1004: movq %rax,CPUVAR(RSP0)
1005: #else
1.32 bouyer 1006: movq %r14, %rdi
1007: callq _C_LABEL(x86_64_switch_context);
1008: #endif
1.1 fvdl 1009:
1.22 yamt 1010: /* Don't bother with the rest if switching to a system process. */
1011: testl $LW_SYSTEM,L_FLAG(%r12)
1012: jnz 4f
1.1 fvdl 1013:
1.22 yamt 1014: /* Is this process using RAS (restartable atomic sequences)? */
1015: movq L_PROC(%r12),%rdi
1016: cmpq $0,P_RASLIST(%rdi)
1017: jne 5f
1.1 fvdl 1018:
1019: /*
1.76 rmind 1020: * Restore cr0 including FPU state (may have CR0_TS set). Note that
1021: * IPL_SCHED prevents from FPU interrupt altering the LWP's saved cr0.
1.1 fvdl 1022: */
1.32 bouyer 1023: 2:
1024: #ifndef XEN
1.75 christos 1025: movl $IPL_HIGH,CPUVAR(ILEVEL)
1026: movl PCB_CR0(%r14),%ecx /* has CR0_TS clear */
1.22 yamt 1027: movq %cr0,%rdx
1.1 fvdl 1028:
1.75 christos 1029: /*
1030: * If our floating point registers are on a different CPU,
1031: * set CR0_TS so we'll trap rather than reuse bogus state.
1032: */
1033: cmpq CPUVAR(FPCURLWP),%r12
1034: je 3f
1035: orq $CR0_TS,%rcx
1036:
1.22 yamt 1037: /* Reloading CR0 is very expensive - avoid if possible. */
1.75 christos 1038: 3: cmpq %rdx,%rcx
1.58 chs 1039: je 6f
1.1 fvdl 1040: movq %rcx,%cr0
1.58 chs 1041:
1.73 uebayasi 1042: 6: testl $PCB_COMPAT32, PCB_FLAGS(%r14)
1.58 chs 1043: jne 32f
1044:
1045: /* Zero out %fs/%gs registers and GDT descriptors. */
1046: xorq %rax, %rax
1047: movw %ax, %fs
1048: CLI(cx)
1.70 dsl 1049: SWAPGS
1.58 chs 1050: movw %ax, %gs
1.70 dsl 1051: SWAPGS
1.58 chs 1052: STI(cx)
1053:
1054: movq CPUVAR(GDT),%rcx
1055: movq %rax, (GUFS_SEL*8)(%rcx)
1056: movq %rax, (GUGS_SEL*8)(%rcx)
1057:
1058: /* Reload 64-bit %fs/%gs MSRs. */
1059: movl $MSR_FSBASE, %ecx
1060: movl PCB_FS(%r14), %eax
1061: movl 4+PCB_FS(%r14), %edx
1062: wrmsr
1063: movl $MSR_KERNELGSBASE, %ecx
1064: movl PCB_GS(%r14), %eax
1065: movl 4+PCB_GS(%r14), %edx
1066: wrmsr
1067: jmp 4f
1068:
1069: 32:
1070: /* Reload %fs/%gs GDT descriptors. */
1071: movq CPUVAR(GDT),%rcx
1072: movq PCB_FS(%r14), %rax
1073: movq %rax, (GUFS_SEL*8)(%rcx)
1074: movq PCB_GS(%r14), %rax
1075: movq %rax, (GUGS_SEL*8)(%rcx)
1076:
1077: /* Reload %fs and %gs */
1078: movq L_MD_REGS(%r12), %rbx
1079: movw TF_FS(%rbx), %fs
1080: CLI(ax)
1.70 dsl 1081: SWAPGS
1.58 chs 1082: movw TF_GS(%rbx), %gs
1.70 dsl 1083: SWAPGS
1.58 chs 1084: STI(ax)
1085:
1086: #else
1087: movq %r12,%rdi
1088: callq _C_LABEL(x86_64_tls_switch)
1.32 bouyer 1089: #endif
1.58 chs 1090:
1.22 yamt 1091: /* Return to the new LWP, returning 'oldlwp' in %rax. */
1092: 4: movq %r13,%rax
1.1 fvdl 1093: popq %r15
1094: popq %r14
1095: popq %r13
1096: popq %r12
1097: popq %rbx
1098: ret
1099:
1.22 yamt 1100: /* Check for restartable atomic sequences (RAS). */
1101: 5: movq L_MD_REGS(%r12),%rbx
1102: movq TF_RIP(%rbx),%rsi
1103: call _C_LABEL(ras_lookup)
1104: cmpq $-1,%rax
1105: je 2b
1106: movq %rax,TF_RIP(%rbx)
1107: jmp 2b
1.71 uebayasi 1108: END(cpu_switchto)
1.1 fvdl 1109:
1110: /*
1.22 yamt 1111: * void savectx(struct pcb *pcb);
1112: *
1.1 fvdl 1113: * Update pcb, saving current processor state.
1114: */
1115: ENTRY(savectx)
1116: /* Save stack pointers. */
1117: movq %rsp,PCB_RSP(%rdi)
1118: movq %rbp,PCB_RBP(%rdi)
1119: ret
1.71 uebayasi 1120: END(savectx)
1.1 fvdl 1121:
1122: IDTVEC(syscall32)
1123: sysret /* go away please */
1.71 uebayasi 1124: IDTVEC_END(syscall32)
1.1 fvdl 1125:
1126: /*
1.22 yamt 1127: * syscall()
1128: *
1.70 dsl 1129: * syscall insn entry.
1130: * This currently isn't much faster, but it can be made faster in the future.
1131: * (Actually we've already saved a few 100 clocks by not loading the trap gate)
1.1 fvdl 1132: */
1133: IDTVEC(syscall)
1.32 bouyer 1134: #ifndef XEN
1.70 dsl 1135: /*
1136: * The user %rip is in %rcx and the user %flags in %r11.
1137: * The kernel %cs and %ss are loaded, but nothing else is.
1138: * The 'swapgs' gives us access to cpu-specific memory where
1139: * we can save a user register and then read the lwps
1140: * kernel stack pointer,
1141: * This code doesn't seem to set %ds, this may not matter since it
1142: * is ignored in 64bit mode, OTOH the syscall instruction sets %ss
1143: * and that is ignored as well.
1144: */
1.1 fvdl 1145: swapgs
1146: movq %r15,CPUVAR(SCRATCH)
1.22 yamt 1147: movq CPUVAR(CURLWP),%r15
1.55 rmind 1148: movq L_PCB(%r15),%r15
1.70 dsl 1149: movq PCB_RSP0(%r15),%r15 /* LWP's kernel stack pointer */
1150:
1151: /* Make stack look like an 'int nn' frame */
1152: #define SP(x) (x)-(TF_SS+8)(%r15)
1153: movq $(LSEL(LUDATA_SEL, SEL_UPL)), SP(TF_SS) /* user %ss */
1154: movq %rsp, SP(TF_RSP) /* User space rsp */
1155:
1156: movq %r11, SP(TF_RFLAGS) /* old rflags from syscall insn */
1157: movq $(LSEL(LUCODE_SEL, SEL_UPL)), SP(TF_CS)
1158: movq %rcx, SP(TF_RIP) /* syscall saves rip in rcx */
1.1 fvdl 1159:
1.70 dsl 1160: leaq SP(0),%rsp /* %rsp now valid after frame */
1.1 fvdl 1161: movq CPUVAR(SCRATCH),%r15
1.70 dsl 1162: #undef SP
1163:
1164: movq $2,TF_ERR(%rsp) /* syscall instruction size */
1165: movq $T_ASTFLT, TF_TRAPNO(%rsp)
1166:
1.59 yamt 1167: movw %es,TF_ES(%rsp)
1.41 ad 1168: sti
1.1 fvdl 1169: INTR_SAVE_GPRS
1.24 fvdl 1170: movw %fs,TF_FS(%rsp)
1171: movw %gs,TF_GS(%rsp)
1.1 fvdl 1172: movw $(LSEL(LUDATA_SEL, SEL_UPL)),TF_DS(%rsp)
1.32 bouyer 1173: #else
1174: /* Xen already switched to kernel stack */
1175: pushq %rsi
1.36 dsl 1176: STI(si)
1.32 bouyer 1177: popq %rsi
1.37 dsl 1178: addq $0x10,%rsp /* gap to match cs:rip */
1179: pushq $2 /* error code */
1.32 bouyer 1180: pushq $T_ASTFLT
1.37 dsl 1181: subq $TF_REGSIZE,%rsp
1.32 bouyer 1182: INTR_SAVE_GPRS
1183: movw %fs,TF_FS(%rsp)
1184: movw %gs,TF_GS(%rsp)
1185: movw %es,TF_ES(%rsp)
1186: movw $(LSEL(LUDATA_SEL, SEL_UPL)),TF_DS(%rsp)
1187: #endif
1.1 fvdl 1188:
1.70 dsl 1189: do_syscall:
1.1 fvdl 1190: movq CPUVAR(CURLWP),%r14
1.64 matt 1191: incq CPUVAR(NSYSCALL) # count it atomically
1.1 fvdl 1192: movq %rsp,L_MD_REGS(%r14) # save pointer to frame
1193: movq L_PROC(%r14),%r15
1.70 dsl 1194: andl $~MDL_IRET,L_MD_FLAGS(%r14) /* Allow sysret return */
1.37 dsl 1195: movq %rsp,%rdi /* Pass frame as arg0 */
1.1 fvdl 1196: call *P_MD_SYSCALL(%r15)
1.29 yamt 1197: .Lsyscall_checkast:
1.70 dsl 1198: /*
1199: * Disable interrupts to avoid new ASTs (etc) being added and
1200: * to ensure we don't take an interrupt with some of the user
1201: * registers loaded.
1202: */
1203: CLI(si)
1.29 yamt 1204: /* Check for ASTs on exit to user mode. */
1.41 ad 1205: movl L_MD_ASTPENDING(%r14), %eax
1206: orl CPUVAR(WANT_PMAPLOAD), %eax
1.29 yamt 1207: jnz 9f
1.1 fvdl 1208: #ifdef DIAGNOSTIC
1209: cmpl $IPL_NONE,CPUVAR(ILEVEL)
1210: jne 3f
1211: #endif
1.70 dsl 1212: testl $(MDL_IRET | MDL_COMPAT32), L_MD_FLAGS(%r14)
1213: INTR_RESTORE_GPRS
1.58 chs 1214: movw TF_ES(%rsp),%es
1.70 dsl 1215: SWAPGS
1216: jnz 2f
1.32 bouyer 1217: #ifndef XEN
1.70 dsl 1218: movq TF_RIP(%rsp), %rcx /* %rip for sysret */
1219: movq TF_RFLAGS(%rsp), %r11 /* %flags for sysret */
1220: movw TF_DS(%rsp), %ds
1221: movq TF_RSP(%rsp), %rsp
1.1 fvdl 1222: sysretq
1.32 bouyer 1223: #else
1.70 dsl 1224: movw TF_DS(%rsp), %ds
1225: addq $TF_RIP, %rsp
1.32 bouyer 1226: pushq $256 /* VGCF_IN_SYSCALL */
1227: jmp HYPERVISOR_iret
1228: #endif
1.1 fvdl 1229:
1.70 dsl 1230: /*
1231: * If the syscall might have modified some registers, or we are a 32bit
1232: * process we must return to user with an 'iret' instruction.
1233: * If the iret faults in kernel (assumed due to illegal register values)
1234: * then a SIGSEGV will be signalled.
1235: */
1236: 2:
1237: movw TF_DS(%rsp), %ds
1238: addq $TF_RIP, %rsp
1239: iretq
1240:
1241: /* Report SPL error */
1.1 fvdl 1242: #ifdef DIAGNOSTIC
1243: 3: movabsq $4f, %rdi
1244: movl TF_RAX(%rsp),%esi
1245: movl TF_RDI(%rsp),%edx
1246: movl %ebx,%ecx
1247: movl CPUVAR(ILEVEL),%r8d
1248: xorq %rax,%rax
1249: call _C_LABEL(printf)
1.35 ad 1250: movl $IPL_NONE,%edi
1251: call _C_LABEL(spllower)
1.29 yamt 1252: jmp .Lsyscall_checkast
1.1 fvdl 1253: 4: .asciz "WARNING: SPL NOT LOWERED ON SYSCALL %d %d EXIT %x %x\n"
1254: #endif
1.70 dsl 1255:
1256: /* AST pending or pmap load needed */
1.41 ad 1257: 9:
1258: cmpl $0, CPUVAR(WANT_PMAPLOAD)
1259: jz 10f
1260: STI(si)
1.29 yamt 1261: call _C_LABEL(do_pmap_load)
1262: jmp .Lsyscall_checkast /* re-check ASTs */
1.41 ad 1263: 10:
1264: CLEAR_ASTPENDING(%r14)
1265: STI(si)
1266: /* Pushed T_ASTFLT into tf_trapno on entry. */
1267: movq %rsp,%rdi
1268: call _C_LABEL(trap)
1269: jmp .Lsyscall_checkast /* re-check ASTs */
1.71 uebayasi 1270: IDTVEC_END(syscall)
1.29 yamt 1271:
1.22 yamt 1272: /*
1273: * void lwp_trampoline(void);
1274: *
1275: * This is a trampoline function pushed run by newly created LWPs
1.70 dsl 1276: * in order to do additional setup in their context.
1.22 yamt 1277: */
1278: NENTRY(lwp_trampoline)
1279: movq %rbp,%rsi
1.41 ad 1280: movq %rbp,%r14 /* for .Lsyscall_checkast */
1.22 yamt 1281: movq %rax,%rdi
1282: xorq %rbp,%rbp
1283: call _C_LABEL(lwp_startup)
1.1 fvdl 1284: movq %r13,%rdi
1285: call *%r12
1.41 ad 1286: jmp .Lsyscall_checkast
1.71 uebayasi 1287: END(lwp_trampoline)
1.1 fvdl 1288:
1289: /*
1.22 yamt 1290: * osyscall()
1291: *
1.1 fvdl 1292: * Trap gate entry for int $80 syscall, also used by sigreturn.
1293: */
1294: IDTVEC(osyscall)
1.32 bouyer 1295: #ifdef XEN
1296: movq (%rsp),%rcx
1297: movq 8(%rsp),%r11
1298: addq $0x10,%rsp
1299: #endif
1.1 fvdl 1300: pushq $2 # size of instruction for restart
1301: pushq $T_ASTFLT # trap # for doing ASTs
1302: INTRENTRY
1.36 dsl 1303: STI(si)
1.70 dsl 1304: jmp do_syscall
1.71 uebayasi 1305: IDTVEC_END(osyscall)
1.26 ad 1306:
1307: /*
1.66 chs 1308: * bool sse2_idlezero_page(void *pg)
1.26 ad 1309: *
1.47 ad 1310: * Zero a page without polluting the cache. Preemption must be
1311: * disabled by the caller. Abort if a preemption is pending.
1.66 chs 1312: * Returns true if the page is zeroed, false if not.
1.26 ad 1313: */
1.47 ad 1314: ENTRY(sse2_idlezero_page)
1315: pushq %rbp
1316: movq %rsp,%rbp
1317: movl $(PAGE_SIZE/64), %ecx
1.26 ad 1318: xorq %rax, %rax
1319: .align 16
1320: 1:
1.50 ad 1321: testl $RESCHED_KPREEMPT, CPUVAR(RESCHED)
1.47 ad 1322: jnz 2f
1.26 ad 1323: movnti %rax, 0(%rdi)
1324: movnti %rax, 8(%rdi)
1325: movnti %rax, 16(%rdi)
1326: movnti %rax, 24(%rdi)
1327: movnti %rax, 32(%rdi)
1328: movnti %rax, 40(%rdi)
1329: movnti %rax, 48(%rdi)
1330: movnti %rax, 56(%rdi)
1.47 ad 1331: addq $64, %rdi
1332: decl %ecx
1.26 ad 1333: jnz 1b
1334: sfence
1.47 ad 1335: incl %eax
1336: popq %rbp
1.26 ad 1337: ret
1.47 ad 1338: 2:
1.26 ad 1339: sfence
1.47 ad 1340: popq %rbp
1.26 ad 1341: ret
1.71 uebayasi 1342: END(sse2_idlezero_page)
1.66 chs 1343:
1344: /*
1345: * void pagezero(vaddr_t va)
1346: *
1347: * Zero a page without polluting the cache.
1348: */
1349:
1350: ENTRY(pagezero)
1351: movq $-PAGE_SIZE,%rdx
1352: subq %rdx,%rdi
1353: xorq %rax,%rax
1354: 1:
1355: movnti %rax,(%rdi,%rdx)
1356: movnti %rax,8(%rdi,%rdx)
1357: movnti %rax,16(%rdi,%rdx)
1358: movnti %rax,24(%rdi,%rdx)
1359: movnti %rax,32(%rdi,%rdx)
1360: movnti %rax,40(%rdi,%rdx)
1361: movnti %rax,48(%rdi,%rdx)
1362: movnti %rax,56(%rdi,%rdx)
1363: addq $64,%rdx
1364: jne 1b
1365: sfence
1366: ret
1.71 uebayasi 1367: END(pagezero)
CVSweb <webmaster@jp.NetBSD.org>