]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/i386/i386/locore.s
Merge llvm trunk r321414 to contrib/llvm.
[FreeBSD/FreeBSD.git] / sys / i386 / i386 / locore.s
1 /*-
2  * Copyright (c) 1990 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * William Jolitz.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  *      from: @(#)locore.s      7.3 (Berkeley) 5/13/91
33  * $FreeBSD$
34  *
35  *              originally from: locore.s, by William F. Jolitz
36  *
37  *              Substantially rewritten by David Greenman, Rod Grimes,
38  *                      Bruce Evans, Wolfgang Solfrank, Poul-Henning Kamp
39  *                      and many others.
40  */
41
42 #include "opt_bootp.h"
43 #include "opt_compat.h"
44 #include "opt_nfsroot.h"
45 #include "opt_pmap.h"
46
47 #include <sys/syscall.h>
48 #include <sys/reboot.h>
49
50 #include <machine/asmacros.h>
51 #include <machine/cputypes.h>
52 #include <machine/psl.h>
53 #include <machine/pmap.h>
54 #include <machine/specialreg.h>
55
56 #include "assym.s"
57
58 /*
59  *      XXX
60  *
61  * Note: This version greatly munged to avoid various assembler errors
62  * that may be fixed in newer versions of gas. Perhaps newer versions
63  * will have more pleasant appearance.
64  */
65
66 /*
67  * PTmap is recursive pagemap at top of virtual address space.
68  * Within PTmap, the page directory can be found (third indirection).
69  */
70         .globl  PTmap,PTD,PTDpde
71         .set    PTmap,(PTDPTDI << PDRSHIFT)
72         .set    PTD,PTmap + (PTDPTDI * PAGE_SIZE)
73         .set    PTDpde,PTD + (PTDPTDI * PDESIZE)
74
75 /*
76  * Compiled KERNBASE location and the kernel load address
77  */
78         .globl  kernbase
79         .set    kernbase,KERNBASE
80         .globl  kernload
81         .set    kernload,KERNLOAD
82
83 /*
84  * Globals
85  */
86         .data
87         ALIGN_DATA                      /* just to be sure */
88
89         .space  0x2000                  /* space for tmpstk - temporary stack */
90 tmpstk:
91
92         .globl  bootinfo
93 bootinfo:       .space  BOOTINFO_SIZE   /* bootinfo that we can handle */
94
95                 .globl KERNend
96 KERNend:        .long   0               /* phys addr end of kernel (just after bss) */
97 physfree:       .long   0               /* phys addr of next free page */
98
99         .globl  IdlePTD
100 IdlePTD:        .long   0               /* phys addr of kernel PTD */
101
102 #if defined(PAE) || defined(PAE_TABLES)
103         .globl  IdlePDPT
104 IdlePDPT:       .long   0               /* phys addr of kernel PDPT */
105 #endif
106
107         .globl  KPTmap
108 KPTmap:         .long   0               /* address of kernel page tables */
109
110         .globl  KPTphys
111 KPTphys:        .long   0               /* phys addr of kernel page tables */
112
113         .globl  proc0kstack
114 proc0kstack:    .long   0               /* address of proc 0 kstack space */
115 p0kpa:          .long   0               /* phys addr of proc0's STACK */
116
117 vm86phystk:     .long   0               /* PA of vm86/bios stack */
118
119         .globl  vm86paddr, vm86pa
120 vm86paddr:      .long   0               /* address of vm86 region */
121 vm86pa:         .long   0               /* phys addr of vm86 region */
122
123 /**********************************************************************
124  *
125  * Some handy macros
126  *
127  */
128
129 #define R(foo) ((foo)-KERNBASE)
130
131 #define ALLOCPAGES(foo) \
132         movl    R(physfree), %esi ; \
133         movl    $((foo)*PAGE_SIZE), %eax ; \
134         addl    %esi, %eax ; \
135         movl    %eax, R(physfree) ; \
136         movl    %esi, %edi ; \
137         movl    $((foo)*PAGE_SIZE),%ecx ; \
138         xorl    %eax,%eax ; \
139         cld ; \
140         rep ; \
141         stosb
142
143 /*
144  * fillkpt
145  *      eax = page frame address
146  *      ebx = index into page table
147  *      ecx = how many pages to map
148  *      base = base address of page dir/table
149  *      prot = protection bits
150  */
151 #define fillkpt(base, prot)               \
152         shll    $PTESHIFT,%ebx          ; \
153         addl    base,%ebx               ; \
154         orl     $PG_V,%eax              ; \
155         orl     prot,%eax               ; \
156 1:      movl    %eax,(%ebx)             ; \
157         addl    $PAGE_SIZE,%eax         ; /* increment physical address */ \
158         addl    $PTESIZE,%ebx           ; /* next pte */ \
159         loop    1b
160
161 /*
162  * fillkptphys(prot)
163  *      eax = physical address
164  *      ecx = how many pages to map
165  *      prot = protection bits
166  */
167 #define fillkptphys(prot)                 \
168         movl    %eax, %ebx              ; \
169         shrl    $PAGE_SHIFT, %ebx       ; \
170         fillkpt(R(KPTphys), prot)
171
172         .text
173 /**********************************************************************
174  *
175  * This is where the bootblocks start us, set the ball rolling...
176  *
177  */
178 NON_GPROF_ENTRY(btext)
179
180 /* Tell the bios to warmboot next time */
181         movw    $0x1234,0x472
182
183 /* Set up a real frame in case the double return in newboot is executed. */
184         pushl   %ebp
185         movl    %esp, %ebp
186
187 /* Don't trust what the BIOS gives for eflags. */
188         pushl   $PSL_KERNEL
189         popfl
190
191 /*
192  * Don't trust what the BIOS gives for %fs and %gs.  Trust the bootstrap
193  * to set %cs, %ds, %es and %ss.
194  */
195         mov     %ds, %ax
196         mov     %ax, %fs
197         mov     %ax, %gs
198
199 /*
200  * Clear the bss.  Not all boot programs do it, and it is our job anyway.
201  *
202  * XXX we don't check that there is memory for our bss and page tables
203  * before using it.
204  *
205  * Note: we must be careful to not overwrite an active gdt or idt.  They
206  * inactive from now until we switch to new ones, since we don't load any
207  * more segment registers or permit interrupts until after the switch.
208  */
209         movl    $R(end),%ecx
210         movl    $R(edata),%edi
211         subl    %edi,%ecx
212         xorl    %eax,%eax
213         cld
214         rep
215         stosb
216
217         call    recover_bootinfo
218
219 /* Get onto a stack that we can trust. */
220 /*
221  * XXX this step is delayed in case recover_bootinfo needs to return via
222  * the old stack, but it need not be, since recover_bootinfo actually
223  * returns via the old frame.
224  */
225         movl    $R(tmpstk),%esp
226
227         call    identify_cpu
228         call    create_pagetables
229
230 /*
231  * If the CPU has support for VME, turn it on.
232  */ 
233         testl   $CPUID_VME, R(cpu_feature)
234         jz      1f
235         movl    %cr4, %eax
236         orl     $CR4_VME, %eax
237         movl    %eax, %cr4
238 1:
239
240 /* Now enable paging */
241 #if defined(PAE) || defined(PAE_TABLES)
242         movl    R(IdlePDPT), %eax
243         movl    %eax, %cr3
244         movl    %cr4, %edx
245         orl     $CR4_PAE, %edx
246         movl    %edx, %cr4
247 #else
248         movl    R(IdlePTD), %eax
249         movl    %eax,%cr3               /* load ptd addr into mmu */
250 #endif
251         movl    %cr0,%edx               /* get control word */
252         orl     $CR0_PE|CR0_PG,%edx     /* enable paging */
253         movl    %edx,%cr0               /* and let's page NOW! */
254
255         pushl   $begin                  /* jump to high virtualized address */
256         ret
257
258 begin:
259         /*
260          * Now running relocated at KERNBASE where the system is linked to run.
261          *
262          * Remove the lowest part of the double mapping of low memory to get
263          * some null pointer checks.
264          */
265         movl    $0,PTD
266         movl    %eax,%cr3               /* invalidate TLB */
267
268         /* set up bootstrap stack */
269         movl    proc0kstack,%eax        /* location of in-kernel stack */
270
271         /*
272          * Only use bottom page for init386().  init386() calculates the
273          * PCB + FPU save area size and returns the true top of stack.
274          */
275         leal    PAGE_SIZE(%eax),%esp
276
277         xorl    %ebp,%ebp               /* mark end of frames */
278
279         pushl   physfree                /* value of first for init386(first) */
280         call    init386                 /* wire 386 chip for unix operation */
281
282         /*
283          * Clean up the stack in a way that db_numargs() understands, so
284          * that backtraces in ddb don't underrun the stack.  Traps for
285          * inaccessible memory are more fatal than usual this early.
286          */
287         addl    $4,%esp
288
289         /* Switch to true top of stack. */
290         movl    %eax,%esp
291
292         call    mi_startup              /* autoconfiguration, mountroot etc */
293         /* NOTREACHED */
294         addl    $0,%esp                 /* for db_numargs() again */
295
296 /*
297  * Signal trampoline, copied to top of user stack
298  */
299 NON_GPROF_ENTRY(sigcode)
300         calll   *SIGF_HANDLER(%esp)
301         leal    SIGF_UC(%esp),%eax      /* get ucontext */
302         pushl   %eax
303         testl   $PSL_VM,UC_EFLAGS(%eax)
304         jne     1f
305         mov     UC_GS(%eax),%gs         /* restore %gs */
306 1:
307         movl    $SYS_sigreturn,%eax
308         pushl   %eax                    /* junk to fake return addr. */
309         int     $0x80                   /* enter kernel with args */
310                                         /* on stack */
311 1:
312         jmp     1b
313
314 #ifdef COMPAT_FREEBSD4
315         ALIGN_TEXT
316 freebsd4_sigcode:
317         calll   *SIGF_HANDLER(%esp)
318         leal    SIGF_UC4(%esp),%eax     /* get ucontext */
319         pushl   %eax
320         testl   $PSL_VM,UC4_EFLAGS(%eax)
321         jne     1f
322         mov     UC4_GS(%eax),%gs        /* restore %gs */
323 1:
324         movl    $344,%eax               /* 4.x SYS_sigreturn */
325         pushl   %eax                    /* junk to fake return addr. */
326         int     $0x80                   /* enter kernel with args */
327                                         /* on stack */
328 1:
329         jmp     1b
330 #endif
331
332 #ifdef COMPAT_43
333         ALIGN_TEXT
334 osigcode:
335         call    *SIGF_HANDLER(%esp)     /* call signal handler */
336         lea     SIGF_SC(%esp),%eax      /* get sigcontext */
337         pushl   %eax
338         testl   $PSL_VM,SC_PS(%eax)
339         jne     9f
340         mov     SC_GS(%eax),%gs         /* restore %gs */
341 9:
342         movl    $103,%eax               /* 3.x SYS_sigreturn */
343         pushl   %eax                    /* junk to fake return addr. */
344         int     $0x80                   /* enter kernel with args */
345 0:      jmp     0b
346 #endif /* COMPAT_43 */
347
348         ALIGN_TEXT
349 esigcode:
350
351         .data
352         .globl  szsigcode
353 szsigcode:
354         .long   esigcode-sigcode
355 #ifdef COMPAT_FREEBSD4
356         .globl  szfreebsd4_sigcode
357 szfreebsd4_sigcode:
358         .long   esigcode-freebsd4_sigcode
359 #endif
360 #ifdef COMPAT_43
361         .globl  szosigcode
362 szosigcode:
363         .long   esigcode-osigcode
364 #endif
365         .text
366
367 /**********************************************************************
368  *
369  * Recover the bootinfo passed to us from the boot program
370  *
371  */
372 recover_bootinfo:
373         /*
374          * This code is called in different ways depending on what loaded
375          * and started the kernel.  This is used to detect how we get the
376          * arguments from the other code and what we do with them.
377          *
378          * Old disk boot blocks:
379          *      (*btext)(howto, bootdev, cyloffset, esym);
380          *      [return address == 0, and can NOT be returned to]
381          *      [cyloffset was not supported by the FreeBSD boot code
382          *       and always passed in as 0]
383          *      [esym is also known as total in the boot code, and
384          *       was never properly supported by the FreeBSD boot code]
385          *
386          * Old diskless netboot code:
387          *      (*btext)(0,0,0,0,&nfsdiskless,0,0,0);
388          *      [return address != 0, and can NOT be returned to]
389          *      If we are being booted by this code it will NOT work,
390          *      so we are just going to halt if we find this case.
391          *
392          * New uniform boot code:
393          *      (*btext)(howto, bootdev, 0, 0, 0, &bootinfo)
394          *      [return address != 0, and can be returned to]
395          *
396          * There may seem to be a lot of wasted arguments in here, but
397          * that is so the newer boot code can still load very old kernels
398          * and old boot code can load new kernels.
399          */
400
401         /*
402          * The old style disk boot blocks fake a frame on the stack and
403          * did an lret to get here.  The frame on the stack has a return
404          * address of 0.
405          */
406         cmpl    $0,4(%ebp)
407         je      olddiskboot
408
409         /*
410          * We have some form of return address, so this is either the
411          * old diskless netboot code, or the new uniform code.  That can
412          * be detected by looking at the 5th argument, if it is 0
413          * we are being booted by the new uniform boot code.
414          */
415         cmpl    $0,24(%ebp)
416         je      newboot
417
418         /*
419          * Seems we have been loaded by the old diskless boot code, we
420          * don't stand a chance of running as the diskless structure
421          * changed considerably between the two, so just halt.
422          */
423          hlt
424
425         /*
426          * We have been loaded by the new uniform boot code.
427          * Let's check the bootinfo version, and if we do not understand
428          * it we return to the loader with a status of 1 to indicate this error
429          */
430 newboot:
431         movl    28(%ebp),%ebx           /* &bootinfo.version */
432         movl    BI_VERSION(%ebx),%eax
433         cmpl    $1,%eax                 /* We only understand version 1 */
434         je      1f
435         movl    $1,%eax                 /* Return status */
436         leave
437         /*
438          * XXX this returns to our caller's caller (as is required) since
439          * we didn't set up a frame and our caller did.
440          */
441         ret
442
443 1:
444         /*
445          * If we have a kernelname copy it in
446          */
447         movl    BI_KERNELNAME(%ebx),%esi
448         cmpl    $0,%esi
449         je      2f                      /* No kernelname */
450         movl    $MAXPATHLEN,%ecx        /* Brute force!!! */
451         movl    $R(kernelname),%edi
452         cmpb    $'/',(%esi)             /* Make sure it starts with a slash */
453         je      1f
454         movb    $'/',(%edi)
455         incl    %edi
456         decl    %ecx
457 1:
458         cld
459         rep
460         movsb
461
462 2:
463         /*
464          * Determine the size of the boot loader's copy of the bootinfo
465          * struct.  This is impossible to do properly because old versions
466          * of the struct don't contain a size field and there are 2 old
467          * versions with the same version number.
468          */
469         movl    $BI_ENDCOMMON,%ecx      /* prepare for sizeless version */
470         testl   $RB_BOOTINFO,8(%ebp)    /* bi_size (and bootinfo) valid? */
471         je      got_bi_size             /* no, sizeless version */
472         movl    BI_SIZE(%ebx),%ecx
473 got_bi_size:
474
475         /*
476          * Copy the common part of the bootinfo struct
477          */
478         movl    %ebx,%esi
479         movl    $R(bootinfo),%edi
480         cmpl    $BOOTINFO_SIZE,%ecx
481         jbe     got_common_bi_size
482         movl    $BOOTINFO_SIZE,%ecx
483 got_common_bi_size:
484         cld
485         rep
486         movsb
487
488 #ifdef NFS_ROOT
489 #ifndef BOOTP_NFSV3
490         /*
491          * If we have a nfs_diskless structure copy it in
492          */
493         movl    BI_NFS_DISKLESS(%ebx),%esi
494         cmpl    $0,%esi
495         je      olddiskboot
496         movl    $R(nfs_diskless),%edi
497         movl    $NFSDISKLESS_SIZE,%ecx
498         cld
499         rep
500         movsb
501         movl    $R(nfs_diskless_valid),%edi
502         movl    $1,(%edi)
503 #endif
504 #endif
505
506         /*
507          * The old style disk boot.
508          *      (*btext)(howto, bootdev, cyloffset, esym);
509          * Note that the newer boot code just falls into here to pick
510          * up howto and bootdev, cyloffset and esym are no longer used
511          */
512 olddiskboot:
513         movl    8(%ebp),%eax
514         movl    %eax,R(boothowto)
515         movl    12(%ebp),%eax
516         movl    %eax,R(bootdev)
517
518         ret
519
520
521 /**********************************************************************
522  *
523  * Identify the CPU and initialize anything special about it
524  *
525  */
526 identify_cpu:
527
528         /* Try to toggle alignment check flag; does not exist on 386. */
529         pushfl
530         popl    %eax
531         movl    %eax,%ecx
532         orl     $PSL_AC,%eax
533         pushl   %eax
534         popfl
535         pushfl
536         popl    %eax
537         xorl    %ecx,%eax
538         andl    $PSL_AC,%eax
539         pushl   %ecx
540         popfl
541
542         testl   %eax,%eax
543         jnz     try486
544
545         /* NexGen CPU does not have aligment check flag. */
546         pushfl
547         movl    $0x5555, %eax
548         xorl    %edx, %edx
549         movl    $2, %ecx
550         clc
551         divl    %ecx
552         jz      trynexgen
553         popfl
554         movl    $CPU_386,R(cpu)
555         jmp     3f
556
557 trynexgen:
558         popfl
559         movl    $CPU_NX586,R(cpu)
560         movl    $0x4778654e,R(cpu_vendor)       # store vendor string
561         movl    $0x72446e65,R(cpu_vendor+4)
562         movl    $0x6e657669,R(cpu_vendor+8)
563         movl    $0,R(cpu_vendor+12)
564         jmp     3f
565
566 try486: /* Try to toggle identification flag; does not exist on early 486s. */
567         pushfl
568         popl    %eax
569         movl    %eax,%ecx
570         xorl    $PSL_ID,%eax
571         pushl   %eax
572         popfl
573         pushfl
574         popl    %eax
575         xorl    %ecx,%eax
576         andl    $PSL_ID,%eax
577         pushl   %ecx
578         popfl
579
580         testl   %eax,%eax
581         jnz     trycpuid
582         movl    $CPU_486,R(cpu)
583
584         /*
585          * Check Cyrix CPU
586          * Cyrix CPUs do not change the undefined flags following
587          * execution of the divide instruction which divides 5 by 2.
588          *
589          * Note: CPUID is enabled on M2, so it passes another way.
590          */
591         pushfl
592         movl    $0x5555, %eax
593         xorl    %edx, %edx
594         movl    $2, %ecx
595         clc
596         divl    %ecx
597         jnc     trycyrix
598         popfl
599         jmp     3f              /* You may use Intel CPU. */
600
601 trycyrix:
602         popfl
603         /*
604          * IBM Bluelighting CPU also doesn't change the undefined flags.
605          * Because IBM doesn't disclose the information for Bluelighting
606          * CPU, we couldn't distinguish it from Cyrix's (including IBM
607          * brand of Cyrix CPUs).
608          */
609         movl    $0x69727943,R(cpu_vendor)       # store vendor string
610         movl    $0x736e4978,R(cpu_vendor+4)
611         movl    $0x64616574,R(cpu_vendor+8)
612         jmp     3f
613
614 trycpuid:       /* Use the `cpuid' instruction. */
615         xorl    %eax,%eax
616         cpuid                                   # cpuid 0
617         movl    %eax,R(cpu_high)                # highest capability
618         movl    %ebx,R(cpu_vendor)              # store vendor string
619         movl    %edx,R(cpu_vendor+4)
620         movl    %ecx,R(cpu_vendor+8)
621         movb    $0,R(cpu_vendor+12)
622
623         movl    $1,%eax
624         cpuid                                   # cpuid 1
625         movl    %eax,R(cpu_id)                  # store cpu_id
626         movl    %ebx,R(cpu_procinfo)            # store cpu_procinfo
627         movl    %edx,R(cpu_feature)             # store cpu_feature
628         movl    %ecx,R(cpu_feature2)            # store cpu_feature2
629         rorl    $8,%eax                         # extract family type
630         andl    $15,%eax
631         cmpl    $5,%eax
632         jae     1f
633
634         /* less than Pentium; must be 486 */
635         movl    $CPU_486,R(cpu)
636         jmp     3f
637 1:
638         /* a Pentium? */
639         cmpl    $5,%eax
640         jne     2f
641         movl    $CPU_586,R(cpu)
642         jmp     3f
643 2:
644         /* Greater than Pentium...call it a Pentium Pro */
645         movl    $CPU_686,R(cpu)
646 3:
647         ret
648
649
650 /**********************************************************************
651  *
652  * Create the first page directory and its page tables.
653  *
654  */
655
656 create_pagetables:
657
658 /* Find end of kernel image (rounded up to a page boundary). */
659         movl    $R(_end),%esi
660
661 /* Include symbols, if any. */
662         movl    R(bootinfo+BI_ESYMTAB),%edi
663         testl   %edi,%edi
664         je      over_symalloc
665         movl    %edi,%esi
666         movl    $KERNBASE,%edi
667         addl    %edi,R(bootinfo+BI_SYMTAB)
668         addl    %edi,R(bootinfo+BI_ESYMTAB)
669 over_symalloc:
670
671 /* If we are told where the end of the kernel space is, believe it. */
672         movl    R(bootinfo+BI_KERNEND),%edi
673         testl   %edi,%edi
674         je      no_kernend
675         movl    %edi,%esi
676 no_kernend:
677
678         addl    $PDRMASK,%esi           /* Play conservative for now, and */
679         andl    $~PDRMASK,%esi          /* ... round up to PDR boundary */
680         movl    %esi,R(KERNend)         /* save end of kernel */
681         movl    %esi,R(physfree)        /* next free page is at end of kernel */
682
683 /* Allocate Kernel Page Tables */
684         ALLOCPAGES(NKPT)
685         movl    %esi,R(KPTphys)
686         addl    $(KERNBASE-(KPTDI<<(PDRSHIFT-PAGE_SHIFT+PTESHIFT))),%esi
687         movl    %esi,R(KPTmap)
688
689 /* Allocate Page Table Directory */
690 #if defined(PAE) || defined(PAE_TABLES)
691         /* XXX only need 32 bytes (easier for now) */
692         ALLOCPAGES(1)
693         movl    %esi,R(IdlePDPT)
694 #endif
695         ALLOCPAGES(NPGPTD)
696         movl    %esi,R(IdlePTD)
697
698 /* Allocate KSTACK */
699         ALLOCPAGES(TD0_KSTACK_PAGES)
700         movl    %esi,R(p0kpa)
701         addl    $KERNBASE, %esi
702         movl    %esi, R(proc0kstack)
703
704         ALLOCPAGES(1)                   /* vm86/bios stack */
705         movl    %esi,R(vm86phystk)
706
707         ALLOCPAGES(3)                   /* pgtable + ext + IOPAGES */
708         movl    %esi,R(vm86pa)
709         addl    $KERNBASE, %esi
710         movl    %esi, R(vm86paddr)
711
712 /*
713  * Enable PSE and PGE.
714  */
715 #ifndef DISABLE_PSE
716         testl   $CPUID_PSE, R(cpu_feature)
717         jz      1f
718         movl    $PG_PS, R(pseflag)
719         movl    %cr4, %eax
720         orl     $CR4_PSE, %eax
721         movl    %eax, %cr4
722 1:
723 #endif
724 #ifndef DISABLE_PG_G
725         testl   $CPUID_PGE, R(cpu_feature)
726         jz      2f
727         movl    $PG_G, R(pgeflag)
728         movl    %cr4, %eax
729         orl     $CR4_PGE, %eax
730         movl    %eax, %cr4
731 2:
732 #endif
733
734 /*
735  * Initialize page table pages mapping physical address zero through the
736  * (physical) end of the kernel.  Many of these pages must be reserved,
737  * and we reserve them all and map them linearly for convenience.  We do
738  * this even if we've enabled PSE above; we'll just switch the corresponding
739  * kernel PDEs before we turn on paging.
740  *
741  * XXX: We waste some pages here in the PSE case!
742  *
743  * This and all other page table entries allow read and write access for
744  * various reasons.  Kernel mappings never have any access restrictions.
745  */
746         xorl    %eax, %eax
747         movl    R(KERNend),%ecx
748         shrl    $PAGE_SHIFT,%ecx
749         fillkptphys($PG_RW)
750
751 /* Map page table pages. */
752         movl    R(KPTphys),%eax
753         movl    $NKPT,%ecx
754         fillkptphys($PG_RW)
755
756 /* Map page directory. */
757 #if defined(PAE) || defined(PAE_TABLES)
758         movl    R(IdlePDPT), %eax
759         movl    $1, %ecx
760         fillkptphys($PG_RW)
761 #endif
762
763         movl    R(IdlePTD), %eax
764         movl    $NPGPTD, %ecx
765         fillkptphys($PG_RW)
766
767 /* Map proc0's KSTACK in the physical way ... */
768         movl    R(p0kpa), %eax
769         movl    $(TD0_KSTACK_PAGES), %ecx
770         fillkptphys($PG_RW)
771
772 /* Map ISA hole */
773         movl    $ISA_HOLE_START, %eax
774         movl    $ISA_HOLE_LENGTH>>PAGE_SHIFT, %ecx
775         fillkptphys($PG_RW)
776
777 /* Map space for the vm86 region */
778         movl    R(vm86phystk), %eax
779         movl    $4, %ecx
780         fillkptphys($PG_RW)
781
782 /* Map page 0 into the vm86 page table */
783         movl    $0, %eax
784         movl    $0, %ebx
785         movl    $1, %ecx
786         fillkpt(R(vm86pa), $PG_RW|PG_U)
787
788 /* ...likewise for the ISA hole */
789         movl    $ISA_HOLE_START, %eax
790         movl    $ISA_HOLE_START>>PAGE_SHIFT, %ebx
791         movl    $ISA_HOLE_LENGTH>>PAGE_SHIFT, %ecx
792         fillkpt(R(vm86pa), $PG_RW|PG_U)
793
794 /*
795  * Create an identity mapping for low physical memory, including the kernel.
796  * This is only used to map the 2 instructions for jumping to 'begin' in
797  * locore (we map everything to avoid having to determine where these
798  * instructions are).  ACPI resume will transiently restore the first PDE in
799  * this mapping (and depend on this PDE's page table created here not being
800  * destroyed).  See pmap_bootstrap() for more details.
801  *
802  * Note:  There are errata concerning large pages and physical address zero,
803  * so a PG_PS mapping should not be used for PDE 0.  Our double mapping
804  * avoids this automatically by not using PG_PS for PDE #KPDI so that PAT
805  * bits can be set at the page level for i/o pages below 1 MB.
806  */
807         movl    R(KPTphys), %eax
808         xorl    %ebx, %ebx
809         movl    $NKPT, %ecx
810         fillkpt(R(IdlePTD), $PG_RW)
811
812 /*
813  * Install PDEs for PTs covering enough kva to bootstrap.  Then for the PSE
814  * case, replace the PDEs whose coverage is strictly within the kernel
815  * (between KERNLOAD (rounded up) and KERNend) by large-page PDEs.
816  */
817         movl    R(KPTphys), %eax
818         movl    $KPTDI, %ebx
819         movl    $NKPT, %ecx
820         fillkpt(R(IdlePTD), $PG_RW)
821         cmpl    $0,R(pseflag)
822         je      done_pde
823
824         movl    R(KERNend), %ecx
825         movl    $(KERNLOAD + PDRMASK) & ~PDRMASK, %eax
826         subl    %eax, %ecx
827         shrl    $PDRSHIFT, %ecx
828         movl    $KPTDI + ((KERNLOAD + PDRMASK) >> PDRSHIFT), %ebx
829         shll    $PDESHIFT, %ebx
830         addl    R(IdlePTD), %ebx
831         orl     $(PG_V|PG_RW|PG_PS), %eax
832 1:      movl    %eax, (%ebx)
833         addl    $(1 << PDRSHIFT), %eax
834         addl    $PDESIZE, %ebx
835         loop    1b
836
837 done_pde:
838 /* install a pde recursively mapping page directory as a page table */
839         movl    R(IdlePTD), %eax
840         movl    $PTDPTDI, %ebx
841         movl    $NPGPTD,%ecx
842         fillkpt(R(IdlePTD), $PG_RW)
843
844 #if defined(PAE) || defined(PAE_TABLES)
845         movl    R(IdlePTD), %eax
846         xorl    %ebx, %ebx
847         movl    $NPGPTD, %ecx
848         fillkpt(R(IdlePDPT), $0x0)
849 #endif
850
851         ret
852
853 #ifdef XENHVM
854 /* Xen Hypercall page */
855         .text
856 .p2align PAGE_SHIFT, 0x90       /* Hypercall_page needs to be PAGE aligned */
857
858 NON_GPROF_ENTRY(hypercall_page)
859         .skip   0x1000, 0x90    /* Fill with "nop"s */
860 #endif