]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/i386/i386/locore.s
MFV r318946: 8021 ARC buf data scatter-ization
[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, %eax
245         orl     $CR4_PAE, %eax
246         movl    %eax, %cr4
247 #else
248         movl    R(IdlePTD), %eax
249         movl    %eax,%cr3               /* load ptd addr into mmu */
250 #endif
251         movl    %cr0,%eax               /* get control word */
252         orl     $CR0_PE|CR0_PG,%eax     /* enable paging */
253         movl    %eax,%cr0               /* and let's page NOW! */
254
255         pushl   $begin                  /* jump to high virtualized address */
256         ret
257
258 /* now running relocated at KERNBASE where the system is linked to run */
259 begin:
260         /* set up bootstrap stack */
261         movl    proc0kstack,%eax        /* location of in-kernel stack */
262
263         /*
264          * Only use bottom page for init386().  init386() calculates the
265          * PCB + FPU save area size and returns the true top of stack.
266          */
267         leal    PAGE_SIZE(%eax),%esp
268
269         xorl    %ebp,%ebp               /* mark end of frames */
270
271         pushl   physfree                /* value of first for init386(first) */
272         call    init386                 /* wire 386 chip for unix operation */
273
274         /*
275          * Clean up the stack in a way that db_numargs() understands, so
276          * that backtraces in ddb don't underrun the stack.  Traps for
277          * inaccessible memory are more fatal than usual this early.
278          */
279         addl    $4,%esp
280
281         /* Switch to true top of stack. */
282         movl    %eax,%esp
283
284         call    mi_startup              /* autoconfiguration, mountroot etc */
285         /* NOTREACHED */
286         addl    $0,%esp                 /* for db_numargs() again */
287
288 /*
289  * Signal trampoline, copied to top of user stack
290  */
291 NON_GPROF_ENTRY(sigcode)
292         calll   *SIGF_HANDLER(%esp)
293         leal    SIGF_UC(%esp),%eax      /* get ucontext */
294         pushl   %eax
295         testl   $PSL_VM,UC_EFLAGS(%eax)
296         jne     1f
297         mov     UC_GS(%eax),%gs         /* restore %gs */
298 1:
299         movl    $SYS_sigreturn,%eax
300         pushl   %eax                    /* junk to fake return addr. */
301         int     $0x80                   /* enter kernel with args */
302                                         /* on stack */
303 1:
304         jmp     1b
305
306 #ifdef COMPAT_FREEBSD4
307         ALIGN_TEXT
308 freebsd4_sigcode:
309         calll   *SIGF_HANDLER(%esp)
310         leal    SIGF_UC4(%esp),%eax     /* get ucontext */
311         pushl   %eax
312         testl   $PSL_VM,UC4_EFLAGS(%eax)
313         jne     1f
314         mov     UC4_GS(%eax),%gs        /* restore %gs */
315 1:
316         movl    $344,%eax               /* 4.x SYS_sigreturn */
317         pushl   %eax                    /* junk to fake return addr. */
318         int     $0x80                   /* enter kernel with args */
319                                         /* on stack */
320 1:
321         jmp     1b
322 #endif
323
324 #ifdef COMPAT_43
325         ALIGN_TEXT
326 osigcode:
327         call    *SIGF_HANDLER(%esp)     /* call signal handler */
328         lea     SIGF_SC(%esp),%eax      /* get sigcontext */
329         pushl   %eax
330         testl   $PSL_VM,SC_PS(%eax)
331         jne     9f
332         mov     SC_GS(%eax),%gs         /* restore %gs */
333 9:
334         movl    $103,%eax               /* 3.x SYS_sigreturn */
335         pushl   %eax                    /* junk to fake return addr. */
336         int     $0x80                   /* enter kernel with args */
337 0:      jmp     0b
338 #endif /* COMPAT_43 */
339
340         ALIGN_TEXT
341 esigcode:
342
343         .data
344         .globl  szsigcode
345 szsigcode:
346         .long   esigcode-sigcode
347 #ifdef COMPAT_FREEBSD4
348         .globl  szfreebsd4_sigcode
349 szfreebsd4_sigcode:
350         .long   esigcode-freebsd4_sigcode
351 #endif
352 #ifdef COMPAT_43
353         .globl  szosigcode
354 szosigcode:
355         .long   esigcode-osigcode
356 #endif
357         .text
358
359 /**********************************************************************
360  *
361  * Recover the bootinfo passed to us from the boot program
362  *
363  */
364 recover_bootinfo:
365         /*
366          * This code is called in different ways depending on what loaded
367          * and started the kernel.  This is used to detect how we get the
368          * arguments from the other code and what we do with them.
369          *
370          * Old disk boot blocks:
371          *      (*btext)(howto, bootdev, cyloffset, esym);
372          *      [return address == 0, and can NOT be returned to]
373          *      [cyloffset was not supported by the FreeBSD boot code
374          *       and always passed in as 0]
375          *      [esym is also known as total in the boot code, and
376          *       was never properly supported by the FreeBSD boot code]
377          *
378          * Old diskless netboot code:
379          *      (*btext)(0,0,0,0,&nfsdiskless,0,0,0);
380          *      [return address != 0, and can NOT be returned to]
381          *      If we are being booted by this code it will NOT work,
382          *      so we are just going to halt if we find this case.
383          *
384          * New uniform boot code:
385          *      (*btext)(howto, bootdev, 0, 0, 0, &bootinfo)
386          *      [return address != 0, and can be returned to]
387          *
388          * There may seem to be a lot of wasted arguments in here, but
389          * that is so the newer boot code can still load very old kernels
390          * and old boot code can load new kernels.
391          */
392
393         /*
394          * The old style disk boot blocks fake a frame on the stack and
395          * did an lret to get here.  The frame on the stack has a return
396          * address of 0.
397          */
398         cmpl    $0,4(%ebp)
399         je      olddiskboot
400
401         /*
402          * We have some form of return address, so this is either the
403          * old diskless netboot code, or the new uniform code.  That can
404          * be detected by looking at the 5th argument, if it is 0
405          * we are being booted by the new uniform boot code.
406          */
407         cmpl    $0,24(%ebp)
408         je      newboot
409
410         /*
411          * Seems we have been loaded by the old diskless boot code, we
412          * don't stand a chance of running as the diskless structure
413          * changed considerably between the two, so just halt.
414          */
415          hlt
416
417         /*
418          * We have been loaded by the new uniform boot code.
419          * Let's check the bootinfo version, and if we do not understand
420          * it we return to the loader with a status of 1 to indicate this error
421          */
422 newboot:
423         movl    28(%ebp),%ebx           /* &bootinfo.version */
424         movl    BI_VERSION(%ebx),%eax
425         cmpl    $1,%eax                 /* We only understand version 1 */
426         je      1f
427         movl    $1,%eax                 /* Return status */
428         leave
429         /*
430          * XXX this returns to our caller's caller (as is required) since
431          * we didn't set up a frame and our caller did.
432          */
433         ret
434
435 1:
436         /*
437          * If we have a kernelname copy it in
438          */
439         movl    BI_KERNELNAME(%ebx),%esi
440         cmpl    $0,%esi
441         je      2f                      /* No kernelname */
442         movl    $MAXPATHLEN,%ecx        /* Brute force!!! */
443         movl    $R(kernelname),%edi
444         cmpb    $'/',(%esi)             /* Make sure it starts with a slash */
445         je      1f
446         movb    $'/',(%edi)
447         incl    %edi
448         decl    %ecx
449 1:
450         cld
451         rep
452         movsb
453
454 2:
455         /*
456          * Determine the size of the boot loader's copy of the bootinfo
457          * struct.  This is impossible to do properly because old versions
458          * of the struct don't contain a size field and there are 2 old
459          * versions with the same version number.
460          */
461         movl    $BI_ENDCOMMON,%ecx      /* prepare for sizeless version */
462         testl   $RB_BOOTINFO,8(%ebp)    /* bi_size (and bootinfo) valid? */
463         je      got_bi_size             /* no, sizeless version */
464         movl    BI_SIZE(%ebx),%ecx
465 got_bi_size:
466
467         /*
468          * Copy the common part of the bootinfo struct
469          */
470         movl    %ebx,%esi
471         movl    $R(bootinfo),%edi
472         cmpl    $BOOTINFO_SIZE,%ecx
473         jbe     got_common_bi_size
474         movl    $BOOTINFO_SIZE,%ecx
475 got_common_bi_size:
476         cld
477         rep
478         movsb
479
480 #ifdef NFS_ROOT
481 #ifndef BOOTP_NFSV3
482         /*
483          * If we have a nfs_diskless structure copy it in
484          */
485         movl    BI_NFS_DISKLESS(%ebx),%esi
486         cmpl    $0,%esi
487         je      olddiskboot
488         movl    $R(nfs_diskless),%edi
489         movl    $NFSDISKLESS_SIZE,%ecx
490         cld
491         rep
492         movsb
493         movl    $R(nfs_diskless_valid),%edi
494         movl    $1,(%edi)
495 #endif
496 #endif
497
498         /*
499          * The old style disk boot.
500          *      (*btext)(howto, bootdev, cyloffset, esym);
501          * Note that the newer boot code just falls into here to pick
502          * up howto and bootdev, cyloffset and esym are no longer used
503          */
504 olddiskboot:
505         movl    8(%ebp),%eax
506         movl    %eax,R(boothowto)
507         movl    12(%ebp),%eax
508         movl    %eax,R(bootdev)
509
510         ret
511
512
513 /**********************************************************************
514  *
515  * Identify the CPU and initialize anything special about it
516  *
517  */
518 identify_cpu:
519
520         /* Try to toggle alignment check flag; does not exist on 386. */
521         pushfl
522         popl    %eax
523         movl    %eax,%ecx
524         orl     $PSL_AC,%eax
525         pushl   %eax
526         popfl
527         pushfl
528         popl    %eax
529         xorl    %ecx,%eax
530         andl    $PSL_AC,%eax
531         pushl   %ecx
532         popfl
533
534         testl   %eax,%eax
535         jnz     try486
536
537         /* NexGen CPU does not have aligment check flag. */
538         pushfl
539         movl    $0x5555, %eax
540         xorl    %edx, %edx
541         movl    $2, %ecx
542         clc
543         divl    %ecx
544         jz      trynexgen
545         popfl
546         movl    $CPU_386,R(cpu)
547         jmp     3f
548
549 trynexgen:
550         popfl
551         movl    $CPU_NX586,R(cpu)
552         movl    $0x4778654e,R(cpu_vendor)       # store vendor string
553         movl    $0x72446e65,R(cpu_vendor+4)
554         movl    $0x6e657669,R(cpu_vendor+8)
555         movl    $0,R(cpu_vendor+12)
556         jmp     3f
557
558 try486: /* Try to toggle identification flag; does not exist on early 486s. */
559         pushfl
560         popl    %eax
561         movl    %eax,%ecx
562         xorl    $PSL_ID,%eax
563         pushl   %eax
564         popfl
565         pushfl
566         popl    %eax
567         xorl    %ecx,%eax
568         andl    $PSL_ID,%eax
569         pushl   %ecx
570         popfl
571
572         testl   %eax,%eax
573         jnz     trycpuid
574         movl    $CPU_486,R(cpu)
575
576         /*
577          * Check Cyrix CPU
578          * Cyrix CPUs do not change the undefined flags following
579          * execution of the divide instruction which divides 5 by 2.
580          *
581          * Note: CPUID is enabled on M2, so it passes another way.
582          */
583         pushfl
584         movl    $0x5555, %eax
585         xorl    %edx, %edx
586         movl    $2, %ecx
587         clc
588         divl    %ecx
589         jnc     trycyrix
590         popfl
591         jmp     3f              /* You may use Intel CPU. */
592
593 trycyrix:
594         popfl
595         /*
596          * IBM Bluelighting CPU also doesn't change the undefined flags.
597          * Because IBM doesn't disclose the information for Bluelighting
598          * CPU, we couldn't distinguish it from Cyrix's (including IBM
599          * brand of Cyrix CPUs).
600          */
601         movl    $0x69727943,R(cpu_vendor)       # store vendor string
602         movl    $0x736e4978,R(cpu_vendor+4)
603         movl    $0x64616574,R(cpu_vendor+8)
604         jmp     3f
605
606 trycpuid:       /* Use the `cpuid' instruction. */
607         xorl    %eax,%eax
608         cpuid                                   # cpuid 0
609         movl    %eax,R(cpu_high)                # highest capability
610         movl    %ebx,R(cpu_vendor)              # store vendor string
611         movl    %edx,R(cpu_vendor+4)
612         movl    %ecx,R(cpu_vendor+8)
613         movb    $0,R(cpu_vendor+12)
614
615         movl    $1,%eax
616         cpuid                                   # cpuid 1
617         movl    %eax,R(cpu_id)                  # store cpu_id
618         movl    %ebx,R(cpu_procinfo)            # store cpu_procinfo
619         movl    %edx,R(cpu_feature)             # store cpu_feature
620         movl    %ecx,R(cpu_feature2)            # store cpu_feature2
621         rorl    $8,%eax                         # extract family type
622         andl    $15,%eax
623         cmpl    $5,%eax
624         jae     1f
625
626         /* less than Pentium; must be 486 */
627         movl    $CPU_486,R(cpu)
628         jmp     3f
629 1:
630         /* a Pentium? */
631         cmpl    $5,%eax
632         jne     2f
633         movl    $CPU_586,R(cpu)
634         jmp     3f
635 2:
636         /* Greater than Pentium...call it a Pentium Pro */
637         movl    $CPU_686,R(cpu)
638 3:
639         ret
640
641
642 /**********************************************************************
643  *
644  * Create the first page directory and its page tables.
645  *
646  */
647
648 create_pagetables:
649
650 /* Find end of kernel image (rounded up to a page boundary). */
651         movl    $R(_end),%esi
652
653 /* Include symbols, if any. */
654         movl    R(bootinfo+BI_ESYMTAB),%edi
655         testl   %edi,%edi
656         je      over_symalloc
657         movl    %edi,%esi
658         movl    $KERNBASE,%edi
659         addl    %edi,R(bootinfo+BI_SYMTAB)
660         addl    %edi,R(bootinfo+BI_ESYMTAB)
661 over_symalloc:
662
663 /* If we are told where the end of the kernel space is, believe it. */
664         movl    R(bootinfo+BI_KERNEND),%edi
665         testl   %edi,%edi
666         je      no_kernend
667         movl    %edi,%esi
668 no_kernend:
669
670         addl    $PDRMASK,%esi           /* Play conservative for now, and */
671         andl    $~PDRMASK,%esi          /*   ... wrap to next 4M. */
672         movl    %esi,R(KERNend)         /* save end of kernel */
673         movl    %esi,R(physfree)        /* next free page is at end of kernel */
674
675 /* Allocate Kernel Page Tables */
676         ALLOCPAGES(NKPT)
677         movl    %esi,R(KPTphys)
678         addl    $(KERNBASE-(KPTDI<<(PDRSHIFT-PAGE_SHIFT+PTESHIFT))),%esi
679         movl    %esi,R(KPTmap)
680
681 /* Allocate Page Table Directory */
682 #if defined(PAE) || defined(PAE_TABLES)
683         /* XXX only need 32 bytes (easier for now) */
684         ALLOCPAGES(1)
685         movl    %esi,R(IdlePDPT)
686 #endif
687         ALLOCPAGES(NPGPTD)
688         movl    %esi,R(IdlePTD)
689
690 /* Allocate KSTACK */
691         ALLOCPAGES(TD0_KSTACK_PAGES)
692         movl    %esi,R(p0kpa)
693         addl    $KERNBASE, %esi
694         movl    %esi, R(proc0kstack)
695
696         ALLOCPAGES(1)                   /* vm86/bios stack */
697         movl    %esi,R(vm86phystk)
698
699         ALLOCPAGES(3)                   /* pgtable + ext + IOPAGES */
700         movl    %esi,R(vm86pa)
701         addl    $KERNBASE, %esi
702         movl    %esi, R(vm86paddr)
703
704 /*
705  * Enable PSE and PGE.
706  */
707 #ifndef DISABLE_PSE
708         testl   $CPUID_PSE, R(cpu_feature)
709         jz      1f
710         movl    $PG_PS, R(pseflag)
711         movl    %cr4, %eax
712         orl     $CR4_PSE, %eax
713         movl    %eax, %cr4
714 1:
715 #endif
716 #ifndef DISABLE_PG_G
717         testl   $CPUID_PGE, R(cpu_feature)
718         jz      2f
719         movl    $PG_G, R(pgeflag)
720         movl    %cr4, %eax
721         orl     $CR4_PGE, %eax
722         movl    %eax, %cr4
723 2:
724 #endif
725
726 /*
727  * Initialize page table pages mapping physical address zero through the
728  * end of the kernel.  All of the page table entries allow read and write
729  * access.  Write access to the first physical page is required by bios32
730  * calls, and write access to the first 1 MB of physical memory is required
731  * by ACPI for implementing suspend and resume.  We do this even
732  * if we've enabled PSE above, we'll just switch the corresponding kernel
733  * PDEs before we turn on paging.
734  *
735  * XXX: We waste some pages here in the PSE case!
736  */
737         xorl    %eax, %eax
738         movl    R(KERNend),%ecx
739         shrl    $PAGE_SHIFT,%ecx
740         fillkptphys($PG_RW)
741
742 /* Map page table pages. */
743         movl    R(KPTphys),%eax
744         movl    $NKPT,%ecx
745         fillkptphys($PG_RW)
746
747 /* Map page directory. */
748 #if defined(PAE) || defined(PAE_TABLES)
749         movl    R(IdlePDPT), %eax
750         movl    $1, %ecx
751         fillkptphys($PG_RW)
752 #endif
753
754         movl    R(IdlePTD), %eax
755         movl    $NPGPTD, %ecx
756         fillkptphys($PG_RW)
757
758 /* Map proc0's KSTACK in the physical way ... */
759         movl    R(p0kpa), %eax
760         movl    $(TD0_KSTACK_PAGES), %ecx
761         fillkptphys($PG_RW)
762
763 /* Map ISA hole */
764         movl    $ISA_HOLE_START, %eax
765         movl    $ISA_HOLE_LENGTH>>PAGE_SHIFT, %ecx
766         fillkptphys($PG_RW)
767
768 /* Map space for the vm86 region */
769         movl    R(vm86phystk), %eax
770         movl    $4, %ecx
771         fillkptphys($PG_RW)
772
773 /* Map page 0 into the vm86 page table */
774         movl    $0, %eax
775         movl    $0, %ebx
776         movl    $1, %ecx
777         fillkpt(R(vm86pa), $PG_RW|PG_U)
778
779 /* ...likewise for the ISA hole */
780         movl    $ISA_HOLE_START, %eax
781         movl    $ISA_HOLE_START>>PAGE_SHIFT, %ebx
782         movl    $ISA_HOLE_LENGTH>>PAGE_SHIFT, %ecx
783         fillkpt(R(vm86pa), $PG_RW|PG_U)
784
785 /*
786  * Create an identity mapping for low physical memory, including the kernel.
787  * The part of this mapping that covers the first 1 MB of physical memory
788  * becomes a permanent part of the kernel's address space.  The rest of this
789  * mapping is destroyed in pmap_bootstrap().  Ordinarily, the same page table
790  * pages are shared by the identity mapping and the kernel's native mapping.
791  * However, the permanent identity mapping cannot contain PG_G mappings.
792  * Thus, if the kernel is loaded within the permanent identity mapping, that
793  * page table page must be duplicated and not shared.
794  *
795  * N.B. Due to errata concerning large pages and physical address zero,
796  * a PG_PS mapping is not used.
797  */
798         movl    R(KPTphys), %eax
799         xorl    %ebx, %ebx
800         movl    $NKPT, %ecx
801         fillkpt(R(IdlePTD), $PG_RW)
802 #if KERNLOAD < (1 << PDRSHIFT)
803         testl   $PG_G, R(pgeflag)
804         jz      1f
805         ALLOCPAGES(1)
806         movl    %esi, %edi
807         movl    R(IdlePTD), %eax
808         movl    (%eax), %esi
809         movl    %edi, (%eax)
810         movl    $PAGE_SIZE, %ecx
811         cld
812         rep
813         movsb
814 1:      
815 #endif
816
817 /*
818  * For the non-PSE case, install PDEs for PTs covering the KVA.
819  * For the PSE case, do the same, but clobber the ones corresponding
820  * to the kernel (from btext to KERNend) with 4M (2M for PAE) ('PS')
821  * PDEs immediately after.
822  */
823         movl    R(KPTphys), %eax
824         movl    $KPTDI, %ebx
825         movl    $NKPT, %ecx
826         fillkpt(R(IdlePTD), $PG_RW)
827         cmpl    $0,R(pseflag)
828         je      done_pde
829
830         movl    R(KERNend), %ecx
831         movl    $KERNLOAD, %eax
832         subl    %eax, %ecx
833         shrl    $PDRSHIFT, %ecx
834         movl    $(KPTDI+(KERNLOAD/(1 << PDRSHIFT))), %ebx
835         shll    $PDESHIFT, %ebx
836         addl    R(IdlePTD), %ebx
837         orl     $(PG_V|PG_RW|PG_PS), %eax
838 1:      movl    %eax, (%ebx)
839         addl    $(1 << PDRSHIFT), %eax
840         addl    $PDESIZE, %ebx
841         loop    1b
842
843 done_pde:
844 /* install a pde recursively mapping page directory as a page table */
845         movl    R(IdlePTD), %eax
846         movl    $PTDPTDI, %ebx
847         movl    $NPGPTD,%ecx
848         fillkpt(R(IdlePTD), $PG_RW)
849
850 #if defined(PAE) || defined(PAE_TABLES)
851         movl    R(IdlePTD), %eax
852         xorl    %ebx, %ebx
853         movl    $NPGPTD, %ecx
854         fillkpt(R(IdlePDPT), $0x0)
855 #endif
856
857         ret
858
859 #ifdef XENHVM
860 /* Xen Hypercall page */
861         .text
862 .p2align PAGE_SHIFT, 0x90       /* Hypercall_page needs to be PAGE aligned */
863
864 NON_GPROF_ENTRY(hypercall_page)
865         .skip   0x1000, 0x90    /* Fill with "nop"s */
866 #endif