version 1.90, 2009/11/25 14:28:50 |
version 1.96, 2012/02/24 08:06:07 |
Line 201 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 201 __KERNEL_RCSID(0, "$NetBSD$"); |
|
.globl _C_LABEL(esym) |
.globl _C_LABEL(esym) |
.globl _C_LABEL(eblob) |
.globl _C_LABEL(eblob) |
.globl _C_LABEL(atdevbase) |
.globl _C_LABEL(atdevbase) |
.globl _C_LABEL(proc0uarea),_C_LABEL(PDPpaddr) |
.globl _C_LABEL(lwp0uarea),_C_LABEL(PDPpaddr) |
.globl _C_LABEL(gdt) |
.globl _C_LABEL(gdt) |
.globl _C_LABEL(idt) |
.globl _C_LABEL(idt) |
.globl _C_LABEL(lapic_tpr) |
.globl _C_LABEL(lapic_tpr) |
Line 232 _C_LABEL(lapic_tpr): |
|
Line 232 _C_LABEL(lapic_tpr): |
|
_C_LABEL(cpu): .long 0 # are we 80486, Pentium, or.. |
_C_LABEL(cpu): .long 0 # are we 80486, Pentium, or.. |
_C_LABEL(cpuid_level): .long 0 |
_C_LABEL(cpuid_level): .long 0 |
_C_LABEL(atdevbase): .long 0 # location of start of iomem in virtual |
_C_LABEL(atdevbase): .long 0 # location of start of iomem in virtual |
_C_LABEL(proc0uarea): .long 0 |
_C_LABEL(lwp0uarea): .long 0 |
_C_LABEL(PDPpaddr): .long 0 # paddr of PDP, for libkvm |
_C_LABEL(PDPpaddr): .long 0 # paddr of PDP, for libkvm |
_C_LABEL(tablesize): .long 0 |
_C_LABEL(tablesize): .long 0 |
|
|
.space 512 |
.space 512 |
tmpstk: |
tmpstk: |
|
#ifdef XEN |
|
.align PAGE_SIZE, 0x0 # Align on page boundary |
|
_C_LABEL(tmpgdt): |
|
.space PAGE_SIZE # Xen expects a page |
|
#endif /* XEN */ |
|
.globl tmpgdt |
#ifndef XEN |
#ifndef XEN |
#define _RELOC(x) ((x) - KERNBASE) |
#define _RELOC(x) ((x) - KERNBASE) |
#else |
#else |
Line 482 try586: /* Use the `cpuid' instruction. |
|
Line 487 try586: /* Use the `cpuid' instruction. |
|
movl $_RELOC(tmpstk),%esp # bootstrap stack end location |
movl $_RELOC(tmpstk),%esp # bootstrap stack end location |
|
|
/* |
/* |
* Virtual address space of kernel: |
* Virtual address space of kernel, without PAE. The page dir is 1 page long. |
* |
* |
* text | data | bss | [syms] | [blobs] | page dir | proc0 kstack | L1 ptp |
* text | data | bss | [syms] | [blobs] | page dir | proc0 kstack | L1 ptp |
* 0 1 2 3 |
* 0 1 2 3 |
|
* |
|
* Virtual address space of kernel, with PAE. We need 4 pages for the page dir |
|
* and 1 page for the L3. |
|
* text | data | bss | [syms] | [blobs] | L3 | page dir | proc0 kstack | L1 ptp |
|
* 0 1 5 6 7 |
*/ |
*/ |
|
#ifndef PAE |
#define PROC0_PDIR_OFF 0 |
#define PROC0_PDIR_OFF 0 |
#define PROC0_STK_OFF (PROC0_PDIR_OFF + PAGE_SIZE) |
#else |
|
#define PROC0_L3_OFF 0 |
|
#define PROC0_PDIR_OFF 1 * PAGE_SIZE |
|
#endif |
|
|
|
#define PROC0_STK_OFF (PROC0_PDIR_OFF + PDP_SIZE * PAGE_SIZE) |
#define PROC0_PTP1_OFF (PROC0_STK_OFF + UPAGES * PAGE_SIZE) |
#define PROC0_PTP1_OFF (PROC0_STK_OFF + UPAGES * PAGE_SIZE) |
|
|
/* |
/* |
* fillkpt |
* fillkpt - Fill in a kernel page table |
* eax = pte (page frame | control | status) |
* eax = pte (page frame | control | status) |
* ebx = page table address |
* ebx = page table address |
* ecx = number of pages to map |
* ecx = number of pages to map |
|
* |
|
* For PAE, each entry is 8 bytes long: we must set the 4 upper bytes to 0. |
|
* This is done by the first instruction of fillkpt. In the non-PAE case, this |
|
* instruction just clears the page table entry. |
*/ |
*/ |
|
|
#define fillkpt \ |
#define fillkpt \ |
1: movl %eax,(%ebx) ; /* store phys addr */ \ |
1: movl $0,(PDE_SIZE-4)(%ebx) ; /* clear bits */ \ |
addl $4,%ebx ; /* next pte/pde */ \ |
movl %eax,(%ebx) ; /* store phys addr */ \ |
addl $PAGE_SIZE,%eax ; /* next phys page */ \ |
addl $PDE_SIZE,%ebx ; /* next pte/pde */ \ |
loop 1b ; \ |
addl $PAGE_SIZE,%eax ; /* next phys page */ \ |
|
loop 1b ; |
|
|
/* Find end of kernel image. */ |
/* Find end of kernel image. */ |
movl $RELOC(end),%edi |
movl $RELOC(end),%edi |
Line 538 try586: /* Use the `cpuid' instruction. |
|
Line 557 try586: /* Use the `cpuid' instruction. |
|
incl %eax /* one more ptp for VAs stolen by bootstrap */ |
incl %eax /* one more ptp for VAs stolen by bootstrap */ |
1: movl %eax,RELOC(nkptp)+1*4 |
1: movl %eax,RELOC(nkptp)+1*4 |
|
|
/* tablesize = (1 + UPAGES + nkptp) << PGSHIFT; */ |
/* tablesize = (PDP_SIZE + UPAGES + nkptp) << PGSHIFT; */ |
addl $(1+UPAGES),%eax |
addl $(PDP_SIZE+UPAGES),%eax |
|
#ifdef PAE |
|
incl %eax /* one more page for the L3 PD */ |
|
shll $PGSHIFT+1,%eax /* PTP tables are twice larger with PAE */ |
|
#else |
shll $PGSHIFT,%eax |
shll $PGSHIFT,%eax |
|
#endif |
movl %eax,RELOC(tablesize) |
movl %eax,RELOC(tablesize) |
|
|
/* ensure that nkptp covers bootstrap tables */ |
/* ensure that nkptp covers bootstrap tables */ |
Line 578 try586: /* Use the `cpuid' instruction. |
|
Line 602 try586: /* Use the `cpuid' instruction. |
|
*/ |
*/ |
movl $_RELOC(KERNTEXTOFF),%eax |
movl $_RELOC(KERNTEXTOFF),%eax |
movl %eax,%ecx |
movl %eax,%ecx |
shrl $(PGSHIFT-2),%ecx /* ((n >> PGSHIFT) << 2) for # pdes */ |
shrl $(PGSHIFT-2),%ecx /* ((n >> PGSHIFT) << 2) for # pdes */ |
|
#ifdef PAE |
|
shll $1,%ecx /* pdes are twice larger with PAE */ |
|
#endif |
addl %ecx,%ebx |
addl %ecx,%ebx |
|
|
/* Map the kernel text read-only. */ |
/* Map the kernel text read-only. */ |
Line 605 try586: /* Use the `cpuid' instruction. |
|
Line 632 try586: /* Use the `cpuid' instruction. |
|
* Construct a page table directory. |
* Construct a page table directory. |
*/ |
*/ |
/* Set up top level entries for identity mapping */ |
/* Set up top level entries for identity mapping */ |
leal (PROC0_PDIR_OFF)(%esi),%ebx |
leal (PROC0_PDIR_OFF)(%esi),%ebx |
leal (PROC0_PTP1_OFF)(%esi),%eax |
leal (PROC0_PTP1_OFF)(%esi),%eax |
orl $(PG_V|PG_KW), %eax |
orl $(PG_V|PG_KW), %eax |
movl RELOC(nkptp)+1*4,%ecx |
movl RELOC(nkptp)+1*4,%ecx |
fillkpt |
fillkpt |
|
|
/* Set up top level entries for actual kernel mapping */ |
/* Set up top level entries for actual kernel mapping */ |
leal (PROC0_PDIR_OFF + L2_SLOT_KERNBASE*4)(%esi),%ebx |
leal (PROC0_PDIR_OFF + L2_SLOT_KERNBASE*PDE_SIZE)(%esi),%ebx |
leal (PROC0_PTP1_OFF)(%esi),%eax |
leal (PROC0_PTP1_OFF)(%esi),%eax |
orl $(PG_V|PG_KW), %eax |
orl $(PG_V|PG_KW), %eax |
movl RELOC(nkptp)+1*4,%ecx |
movl RELOC(nkptp)+1*4,%ecx |
fillkpt |
fillkpt |
|
|
/* Install a PDE recursively mapping page directory as a page table! */ |
/* Install a PDE recursively mapping page directory as a page table! */ |
leal (PROC0_PDIR_OFF + PDIR_SLOT_PTE*4)(%esi),%ebx |
leal (PROC0_PDIR_OFF + PDIR_SLOT_PTE*PDE_SIZE)(%esi),%ebx |
leal (PROC0_PDIR_OFF)(%esi),%eax |
leal (PROC0_PDIR_OFF)(%esi),%eax |
orl $(PG_V|PG_KW),%eax |
orl $(PG_V|PG_KW),%eax |
movl %eax,(%ebx) |
movl $PDP_SIZE,%ecx |
|
fillkpt |
|
|
|
#ifdef PAE |
|
/* Fill in proc0 L3 page with entries pointing to the page dirs */ |
|
leal (PROC0_L3_OFF)(%esi),%ebx |
|
leal (PROC0_PDIR_OFF)(%esi),%eax |
|
orl $(PG_V),%eax |
|
movl $PDP_SIZE,%ecx |
|
fillkpt |
|
|
|
/* Enable PAE mode */ |
|
movl %cr4,%eax |
|
orl $CR4_PAE,%eax |
|
movl %eax,%cr4 |
|
#endif |
|
|
/* Save phys. addr of PDP, for libkvm. */ |
/* Save phys. addr of PDP, for libkvm. */ |
movl %esi,RELOC(PDPpaddr) |
leal (PROC0_PDIR_OFF)(%esi),%eax |
|
movl %eax,RELOC(PDPpaddr) |
|
|
/* |
/* |
* Startup checklist: |
* Startup checklist: |
* 1. Load %cr3 with pointer to PDIR. |
* 1. Load %cr3 with pointer to PDIR (or L3 PD page for PAE). |
*/ |
*/ |
movl %esi,%eax # phys address of ptd in proc 0 |
movl %esi,%eax # phys address of ptd in proc 0 |
movl %eax,%cr3 # load ptd addr into mmu |
movl %eax,%cr3 # load ptd addr into mmu |
|
|
/* |
/* |
* 2. Enable paging and the rest of it. |
* 2. Enable paging and the rest of it. |
*/ |
*/ |
|
|
* memory, remove it. |
* memory, remove it. |
*/ |
*/ |
movl _C_LABEL(nkptp)+1*4,%ecx |
movl _C_LABEL(nkptp)+1*4,%ecx |
leal (PROC0_PDIR_OFF)(%esi),%ebx # old, phys address of PDIR |
leal (PROC0_PDIR_OFF)(%esi),%ebx # old, phys address of PDIR |
addl $(KERNBASE), %ebx # new, virtual address of PDIR |
addl $(KERNBASE), %ebx # new, virtual address of PDIR |
1: movl $0,(%ebx) |
1: movl $0,(PDE_SIZE-4)(%ebx) # Upper bits (for PAE) |
addl $4,%ebx |
movl $0,(%ebx) |
|
addl $PDE_SIZE,%ebx |
loop 1b |
loop 1b |
|
|
/* Relocate atdevbase. */ |
/* Relocate atdevbase. */ |
|
|
|
|
/* Set up bootstrap stack. */ |
/* Set up bootstrap stack. */ |
leal (PROC0_STK_OFF+KERNBASE)(%esi),%eax |
leal (PROC0_STK_OFF+KERNBASE)(%esi),%eax |
movl %eax,_C_LABEL(proc0uarea) |
movl %eax,_C_LABEL(lwp0uarea) |
leal (KSTACK_SIZE-FRAMESIZE)(%eax),%esp |
leal (KSTACK_SIZE-FRAMESIZE)(%eax),%esp |
movl %esi,(KSTACK_SIZE+PCB_CR3)(%eax) # pcb->pcb_cr3 |
movl %esi,(KSTACK_SIZE+PCB_CR3)(%eax) # pcb->pcb_cr3 |
xorl %ebp,%ebp # mark end of frames |
xorl %ebp,%ebp # mark end of frames |
|
|
movl _C_LABEL(tablesize),%eax |
movl _C_LABEL(tablesize),%eax |
addl %esi,%eax # skip past stack and page tables |
addl %esi,%eax # skip past stack and page tables |
|
|
|
#ifdef PAE |
|
pushl $0 # init386() expects a 64 bits paddr_t with PAE |
|
#endif |
pushl %eax |
pushl %eax |
call _C_LABEL(init386) # wire 386 chip for unix operation |
call _C_LABEL(init386) # wire 386 chip for unix operation |
addl $4+NGDT*8,%esp # pop temporary gdt |
addl $PDE_SIZE,%esp # pop paddr_t |
|
addl $NGDT*8,%esp # pop temporary gdt |
|
|
#ifdef SAFARI_FIFO_HACK |
#ifdef SAFARI_FIFO_HACK |
movb $5,%al |
movb $5,%al |
|
|
cpuid |
cpuid |
movl %eax,RELOC(cpuid_level) |
movl %eax,RELOC(cpuid_level) |
|
|
|
/* |
|
* Use a temp page. We'll re- add it to uvm(9) once we're |
|
* done using it. |
|
*/ |
|
movl $RELOC(tmpgdt), %eax |
|
pushl %eax # start of temporary gdt |
|
call _C_LABEL(initgdt) |
|
addl $4,%esp |
|
|
call xen_pmap_bootstrap |
call xen_pmap_bootstrap |
|
|
/* |
/* |
* First avail returned by xen_pmap_bootstrap in %eax |
* First avail returned by xen_pmap_bootstrap in %eax |
*/ |
*/ |
movl %eax, %esi; |
movl %eax, %esi; |
movl %esi, _C_LABEL(proc0uarea) |
movl %esi, _C_LABEL(lwp0uarea) |
|
|
#define PROC0PDIR ((0) * PAGE_SIZE) |
|
#define PROC0STACK ((1) * PAGE_SIZE) |
|
|
|
/* Set up bootstrap stack. */ |
/* Set up bootstrap stack. */ |
leal (KSTACK_SIZE-FRAMESIZE)(%eax),%esp |
leal (KSTACK_SIZE-FRAMESIZE)(%eax),%esp |
|
|
|
|
addl $USPACE, %esi |
addl $USPACE, %esi |
subl $KERNBASE, %esi #init386 want a physical address |
subl $KERNBASE, %esi #init386 want a physical address |
|
|
|
#ifdef PAE |
|
pushl $0 # init386() expects a 64 bits paddr_t with PAE |
|
#endif |
pushl %esi |
pushl %esi |
call _C_LABEL(init386) # wire 386 chip for unix operation |
call _C_LABEL(init386) # wire 386 chip for unix operation |
addl $4,%esp |
addl $PDE_SIZE,%esp # pop paddr_t |
call _C_LABEL(main) |
call _C_LABEL(main) |
|
|
#if defined(XEN) && !defined(XEN_COMPAT_030001) |
#if defined(XEN) && !defined(XEN_COMPAT_030001) |
Line 931 ENTRY(cpu_switchto) |
|
Line 989 ENTRY(cpu_switchto) |
|
jz 1f |
jz 1f |
|
|
/* Save old context. */ |
/* Save old context. */ |
movl L_ADDR(%esi),%eax |
movl L_PCB(%esi),%eax |
movl %esp,PCB_ESP(%eax) |
movl %esp,PCB_ESP(%eax) |
movl %ebp,PCB_EBP(%eax) |
movl %ebp,PCB_EBP(%eax) |
|
|
/* Switch to newlwp's stack. */ |
/* Switch to newlwp's stack. */ |
1: movl L_ADDR(%edi),%ebx |
1: movl L_PCB(%edi),%ebx |
movl PCB_EBP(%ebx),%ebp |
movl PCB_EBP(%ebx),%ebp |
movl PCB_ESP(%ebx),%esp |
movl PCB_ESP(%ebx),%esp |
|
|
Line 979 ENTRY(cpu_switchto) |
|
Line 1037 ENTRY(cpu_switchto) |
|
/* Switch I/O bitmap */ |
/* Switch I/O bitmap */ |
movl PCB_IOMAP(%ebx),%eax |
movl PCB_IOMAP(%ebx),%eax |
orl %eax,%eax |
orl %eax,%eax |
jnz,pn .Lcopy_iobitmap |
jnz .Lcopy_iobitmap |
movl $(IOMAP_INVALOFF << 16),CPUVAR(IOBASE) |
movl $(IOMAP_INVALOFF << 16),CPUVAR(IOBASE) |
.Liobitmap_done: |
.Liobitmap_done: |
|
|
|
|
#endif |
#endif |
1: |
1: |
#endif /* DIAGNOSTIC */ |
#endif /* DIAGNOSTIC */ |
incl CPUVAR(NSYSCALL) # count it atomically |
addl $1,CPUVAR(NSYSCALL) # count it atomically |
|
adcl $0,CPUVAR(NSYSCALL)+4 # count it atomically |
movl CPUVAR(CURLWP),%edi |
movl CPUVAR(CURLWP),%edi |
movl L_PROC(%edi),%edx |
movl L_PROC(%edi),%edx |
movl %esp,L_MD_REGS(%edi) # save pointer to frame |
movl %esp,L_MD_REGS(%edi) # save pointer to frame |