123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767 |
- /* #defines because ljmp wants a number, probably gas bug */
- /* .equ KERN_CODE_SEG,_pmcs-_gdt */
- #define KERN_CODE_SEG 0x08
- .equ KERN_DATA_SEG,_pmds-_gdt
- /* .equ REAL_CODE_SEG,_rmcs-_gdt */
- #define REAL_CODE_SEG 0x18
- .equ REAL_DATA_SEG,_rmds-_gdt
- .equ FLAT_CODE_SEG,_pmcs2-_gdt
- .equ FLAT_DATA_SEG,_pmds2-_gdt
- .equ CR0_PE,1
- #ifdef CONFIG_X86_64
- .equ LM_CODE_SEG, _lmcs-_gdt
- .equ LM_DATA_SEG, _lmds-_gdt
- #endif
-
- .equ MSR_K6_EFER, 0xC0000080
- .equ EFER_LME, 0x00000100
- .equ X86_CR4_PAE, 0x00000020
- .equ CR0_PG, 0x80000000
-
- #ifdef GAS291
- #define DATA32 data32;
- #define ADDR32 addr32;
- #define LJMPI(x) ljmp x
- #else
- #define DATA32 data32
- #define ADDR32 addr32
- /* newer GAS295 require #define LJMPI(x) ljmp *x */
- #define LJMPI(x) ljmp x
- #endif
-
- #define BOCHSBP xchgw %bx, %bx
-
- #include "callbacks.h"
- #define NUM_PUSHA_REGS (8)
- #define NUM_SEG_REGS (6)
-
- /*
- * NOTE: if you write a subroutine that is called from C code (gcc/egcs),
- * then you only have to take care of %ebx, %esi, %edi and %ebp. These
- * registers must not be altered under any circumstance. All other registers
- * may be clobbered without any negative side effects. If you don't follow
- * this rule then you'll run into strange effects that only occur on some
- * gcc versions (because the register allocator may use different registers).
- *
- * All the data32 prefixes for the ljmp instructions are necessary, because
- * the assembler emits code with a relocation address of 0. This means that
- * all destinations are initially negative, which the assembler doesn't grok,
- * because for some reason negative numbers don't fit into 16 bits. The addr32
- * prefixes are there for the same reasons, because otherwise the memory
- * references are only 16 bit wide. Theoretically they are all superfluous.
- * One last note about prefixes: the data32 prefixes on all call _real_to_prot
- * instructions could be removed if the _real_to_prot function is changed to
- * deal correctly with 16 bit return addresses. I tried it, but failed.
- */
-
- /**************************************************************************
- * START
- *
- * This file is no longer enterered from the top. init.S will jump to
- * either _in_call or _rm_in_call, depending on the processor mode
- * when init.S was entered.
- **************************************************************************/
- .text
- .arch i386
- .code32
-
- /**************************************************************************
- _IN_CALL - make a call in to Etherboot.
- **************************************************************************/
-
- /* There are two 32-bit entry points: _in_call and _in_call_far, for
- * near calls and far calls respectively. Both should be called with
- * flat physical addresses. They will result in a call to the C
- * routine in_call(); see there for API details.
- *
- * Note that this routine makes fairly heavy use of the stack and no
- * use of fixed data areas. This is because it must be re-entrant;
- * there may be more than one concurrent call in to Etherboot.
- */
-
- #define IC_OFFSET_VA_LIST_PTR ( 0 )
- #define IC_OFFSET_VA_LIST_PTR_E ( IC_OFFSET_VA_LIST_PTR + 4 )
- #define IC_OFFSET_REGISTERS ( IC_OFFSET_VA_LIST_PTR_E )
- #define IC_OFFSET_REGISTERS_E ( IC_OFFSET_REGISTERS + ( NUM_PUSHA_REGS * 4 ) )
- #define IC_OFFSET_SEG_REGS ( IC_OFFSET_REGISTERS_E )
- #define IC_OFFSET_SEG_REGS_E ( IC_OFFSET_SEG_REGS + ( NUM_SEG_REGS * 2 ) )
- #define IC_OFFSET_GDT ( IC_OFFSET_SEG_REGS_E )
- #define IC_OFFSET_GDT_E ( IC_OFFSET_GDT + 8 )
- #define IC_OFFSET_FLAGS ( IC_OFFSET_GDT_E )
- #define IC_OFFSET_FLAGS_E ( IC_OFFSET_FLAGS + 4 )
- #define IC_OFFSET_RETADDR ( IC_OFFSET_FLAGS_E )
- #define IC_OFFSET_RETADDR_E ( IC_OFFSET_RETADDR + 8 )
- #define IC_OFFSET_ORIG_STACK ( IC_OFFSET_RETADDR )
- #define IC_OFFSET_OPCODE ( IC_OFFSET_ORIG_STACK + 8 )
- #define IC_OFFSET_OPCODE_E ( IC_OFFSET_OPCODE + 4 )
- #define IC_OFFSET_VA_LIST ( IC_OFFSET_OPCODE_E )
-
- .code32
- .globl _in_call
- .globl _in_call_far
- _in_call:
- /* Expand to far return address */
- pushl %eax /* Store %eax */
- xorl %eax, %eax
- movw %cs, %ax
- xchgl %eax, 4(%esp) /* 4(%esp) = %cs, %eax = ret addr */
- xchgl %eax, 0(%esp) /* 0(%esp) = ret addr, restore %eax */
- _in_call_far:
- /* Store flags */
- pushfl
- /* Store the GDT */
- subl $8, %esp
- sgdt 0(%esp)
- /* Store segment register values */
- pushw %gs
- pushw %fs
- pushw %es
- pushw %ds
- pushw %ss
- pushw %cs
- /* Store general-purpose register values */
- pushal
- /* Replace %esp in store with physical %esp value on entry */
- leal (IC_OFFSET_ORIG_STACK - IC_OFFSET_REGISTERS)(%esp), %eax
- movl %eax, (IC_OFFSET_REGISTERS - IC_OFFSET_REGISTERS + 12)(%esp)
- /* Store va_list pointer (physical address) */
- leal (IC_OFFSET_VA_LIST - IC_OFFSET_VA_LIST_PTR_E)(%esp), %eax
- pushl %eax
- /* IC_OFFSET_*(%esp) are now valid */
-
- /* Switch to virtual addresses */
- call _phys_to_virt
-
- /* Fixup the va_list pointer */
- movl virt_offset, %ebp
- subl %ebp, IC_OFFSET_VA_LIST_PTR(%esp)
-
- /* Check opcode for EB_USE_INTERNAL_STACK flag */
- movl IC_OFFSET_OPCODE(%esp), %eax
- testl $EB_USE_INTERNAL_STACK, %eax
- je 2f
- /* Use internal stack flag set */
- /* Check %esp is not already in internal stack range */
- leal _stack, %esi /* %esi = bottom of internal stack */
- leal _estack, %edi /* %edi = top of internal stack */
- cmpl %esi, %esp
- jb 1f
- cmpl %edi, %esp
- jbe 2f
- 1: /* %esp not currently in internal stack range */
- movl %esp, %esi /* %esi = original stack */
- movl $IC_OFFSET_OPCODE_E, %ecx /* %ecx = length to transfer */
- subl %ecx, %edi /* %edi = internal stack pos */
- movl %edi, %esp /* = new %esp */
- rep movsb /* Copy data to internal stack */
- 2:
-
- /* Call to C code */
- call i386_in_call
-
- /* Set %eax (return code from C) in registers structure on
- * stack, so that we return it to the caller.
- */
- movl %eax, (IC_OFFSET_REGISTERS + 28)(%esp)
-
- /* Calculate physical continuation address */
- movl virt_offset, %ebp
- movzwl (IC_OFFSET_SEG_REGS + 0)(%esp), %eax /* %cs */
- movzwl (IC_OFFSET_SEG_REGS + 2)(%esp), %ebx /* %ss */
- pushl %eax /* Continuation segment */
- leal 1f(%ebp), %eax
- pushl %eax /* Continuation offset */
-
- /* Restore caller's GDT */
- cli /* Temporarily disable interrupts */
- lgdt (8+IC_OFFSET_GDT)(%esp)
- /* Reset %ss and adjust %esp */
- movw %bx, %ss
- addl %ebp, %esp
- lret /* Reload %cs:eip, flush prefetch */
- 1:
-
- /* Skip va_list ptr */
- popl %eax
- /* Reload general-purpose registers to be returned */
- popal
- /* Reload segment registers as passed in from caller */
- popw %gs
- popw %fs
- popw %es
- popw %ds
- addl $(4+8), %esp /* Skip %cs, %ss and GDT (already reloaded) */
- /* Restore flags (including revert of interrupt status) */
- popfl
-
- /* Restore physical %esp from entry. It will only be
- * different if EB_USE_INTERNAL_STACK was specified.
- */
- movl ( 12 + IC_OFFSET_REGISTERS - IC_OFFSET_RETADDR )(%esp), %esp
-
- /* Check for EB_SKIP_OPCODE */
- pushfl
- testl $EB_SKIP_OPCODE, 12(%esp)
- jnz 1f
- /* Normal return */
- popfl
- lret
- 1: /* Return and skip opcode */
- popfl
- lret $4
-
- /**************************************************************************
- RELOCATE_TO - relocate etherboot to the specified address
- **************************************************************************/
- .globl relocate_to
- relocate_to:
- /* Save the callee save registers */
- pushl %ebp
- pushl %esi
- pushl %edi
-
- /* Compute the virtual destination address */
- movl 16(%esp), %edi # dest
- subl virt_offset, %edi
-
-
- /* Compute the new value of virt_offset */
- movl 16(%esp), %ebp # virt_offset
- subl $_text, %ebp
-
- /* Fixup the gdt */
- pushl $_pmcs
- pushl %ebp # virt_offset
- call set_seg_base
- addl $8, %esp
-
- /* Fixup gdtarg */
- leal _gdt(%ebp), %eax
- movl %eax, gdtarg +2
-
- /* Fixup virt_offset */
- movl %ebp, virt_offset
-
- /* Load the move parameters */
- movl $_text, %esi
- movl $_end, %ecx
- subl %esi, %ecx
-
- /* Move etherboot uses %esi, %edi, %ecx */
- rep
- movsb
-
- /* Reload the gdt */
- cs
- lgdt gdtarg
-
- /* Reload %cs */
- ljmp $KERN_CODE_SEG, $1f
- 1:
- /* reload other segment registers */
- movl $KERN_DATA_SEG, %eax
- movl %eax,%ds
- movl %eax,%es
- movl %eax,%ss
- movl %eax,%fs
- movl %eax,%gs
-
- /* Restore the callee save registers */
- popl %edi
- popl %esi
- popl %ebp
-
- /* return */
- ret
-
- /**************************************************************************
- XSTART32 - Transfer control to the kernel just loaded
- **************************************************************************/
- .globl xstart32
- xstart32:
- /* Save the callee save registers */
- movl %ebp, os_regs + 32
- movl %esi, os_regs + 36
- movl %edi, os_regs + 40
- movl %ebx, os_regs + 44
-
- /* save the return address */
- popl %eax
- movl %eax, os_regs + 48
-
- /* save the stack pointer */
- movl %esp, os_regs + 52
-
- /* Get the new destination address */
- popl %ecx
-
- /* Store the physical address of xend on the stack */
- movl $xend32, %ebx
- addl virt_offset, %ebx
- pushl %ebx
-
- /* Store the destination address on the stack */
- pushl $FLAT_CODE_SEG
- pushl %ecx
-
- /* Cache virt_offset */
- movl virt_offset, %ebp
-
- /* Switch to using physical addresses */
- call _virt_to_phys
-
- /* Save the target stack pointer */
- movl %esp, os_regs + 12(%ebp)
- leal os_regs(%ebp), %esp
-
- /* Store the pointer to os_regs */
- movl %esp, os_regs_ptr(%ebp)
-
- /* Load my new registers */
- popal
- movl (-32 + 12)(%esp), %esp
-
- /* Jump to the new kernel
- * The lret switches to a flat code segment
- */
- lret
-
- .balign 4
- .globl xend32
- xend32:
- /* Fixup %eflags */
- nop
- cli
- cld
-
- /* Load %esp with &os_regs + virt_offset */
- .byte 0xbc /* movl $0, %esp */
- os_regs_ptr:
- .long 0
-
- /* Save the result registers */
- addl $32, %esp
- pushal
-
- /* Compute virt_offset */
- movl %esp, %ebp
- subl $os_regs, %ebp
-
- /* Load the stack pointer */
- movl 52(%esp), %esp
-
- /* Enable the virtual addresses */
- leal _phys_to_virt(%ebp), %eax
- call *%eax
-
- /* Restore the callee save registers */
- movl os_regs + 32, %ebp
- movl os_regs + 36, %esi
- movl os_regs + 40, %edi
- movl os_regs + 44, %ebx
- movl os_regs + 48, %edx
- movl os_regs + 52, %esp
-
- /* Get the C return value */
- movl os_regs + 28, %eax
-
- jmpl *%edx
-
- #ifdef CONFIG_X86_64
- .arch sledgehammer
- /**************************************************************************
- XSTART_lm - Transfer control to the kernel just loaded in long mode
- **************************************************************************/
- .globl xstart_lm
- xstart_lm:
- /* Save the callee save registers */
- pushl %ebp
- pushl %esi
- pushl %edi
- pushl %ebx
-
- /* Cache virt_offset && (virt_offset & 0xfffff000) */
- movl virt_offset, %ebp
- movl %ebp, %ebx
- andl $0xfffff000, %ebx
-
- /* Switch to using physical addresses */
- call _virt_to_phys
-
- /* Initialize the page tables */
- /* Level 4 */
- leal 0x23 + pgt_level3(%ebx), %eax
- leal pgt_level4(%ebx), %edi
- movl %eax, (%edi)
-
- /* Level 3 */
- leal 0x23 + pgt_level2(%ebx), %eax
- leal pgt_level3(%ebx), %edi
- movl %eax, 0x00(%edi)
- addl $4096, %eax
- movl %eax, 0x08(%edi)
- addl $4096, %eax
- movl %eax, 0x10(%edi)
- addl $4096, %eax
- movl %eax, 0x18(%edi)
-
- /* Level 2 */
- movl $0xe3, %eax
- leal pgt_level2(%ebx), %edi
- leal 16384(%edi), %esi
- pgt_level2_loop:
- movl %eax, (%edi)
- addl $8, %edi
- addl $0x200000, %eax
- cmp %esi, %edi
- jne pgt_level2_loop
-
- /* Point at the x86_64 page tables */
- leal pgt_level4(%ebx), %edi
- movl %edi, %cr3
-
-
- /* Setup for the return from 64bit mode */
- /* 64bit align the stack */
- movl %esp, %ebx /* original stack pointer + 16 */
- andl $0xfffffff8, %esp
-
- /* Save original stack pointer + 16 */
- pushl %ebx
-
- /* Save virt_offset */
- pushl %ebp
-
- /* Setup for the jmp to 64bit long mode */
- leal start_lm(%ebp), %eax
- movl %eax, 0x00 + start_lm_addr(%ebp)
- movl $LM_CODE_SEG, %eax
- movl %eax, 0x04 + start_lm_addr(%ebp)
-
- /* Setup for the jump out of 64bit long mode */
- leal end_lm(%ebp), %eax
- movl %eax, 0x00 + end_lm_addr(%ebp)
- movl $FLAT_CODE_SEG, %eax
- movl %eax, 0x04 + end_lm_addr(%ebp)
-
- /* Enable PAE mode */
- movl %cr4, %eax
- orl $X86_CR4_PAE, %eax
- movl %eax, %cr4
-
- /* Enable long mode */
- movl $MSR_K6_EFER, %ecx
- rdmsr
- orl $EFER_LME, %eax
- wrmsr
-
- /* Start paging, entering 32bit compatiblity mode */
- movl %cr0, %eax
- orl $CR0_PG, %eax
- movl %eax, %cr0
-
- /* Enter 64bit long mode */
- ljmp *start_lm_addr(%ebp)
- .code64
- start_lm:
- /* Load 64bit data segments */
- movl $LM_DATA_SEG, %eax
- movl %eax, %ds
- movl %eax, %es
- movl %eax, %ss
-
- andq $0xffffffff, %rbx
- /* Get the address to jump to */
- movl 20(%rbx), %edx
- andq $0xffffffff, %rdx
-
- /* Get the argument pointer */
- movl 24(%rbx), %ebx
- andq $0xffffffff, %rbx
-
- /* Jump to the 64bit code */
- call *%rdx
-
- /* Preserve the result */
- movl %eax, %edx
-
- /* Fixup %eflags */
- cli
- cld
-
- /* Switch to 32bit compatibility mode */
- ljmp *end_lm_addr(%rip)
-
- .code32
- end_lm:
- /* Disable paging */
- movl %cr0, %eax
- andl $~CR0_PG, %eax
- movl %eax, %cr0
-
- /* Disable long mode */
- movl $MSR_K6_EFER, %ecx
- rdmsr
- andl $~EFER_LME, %eax
- wrmsr
-
- /* Disable PAE */
- movl %cr4, %eax
- andl $~X86_CR4_PAE, %eax
- movl %eax, %cr4
-
- /* Compute virt_offset */
- popl %ebp
-
- /* Compute the original stack pointer + 16 */
- popl %ebx
- movl %ebx, %esp
-
- /* Enable the virtual addresses */
- leal _phys_to_virt(%ebp), %eax
- call *%eax
-
- /* Restore the callee save registers */
- popl %ebx
- popl %esi
- popl %edi
- popl %ebp
-
- /* Get the C return value */
- movl %edx, %eax
-
- /* Return */
- ret
-
- .arch i386
- #endif /* CONFIG_X86_64 */
-
- /**************************************************************************
- SETJMP - Save stack context for non-local goto
- **************************************************************************/
- .globl setjmp
- setjmp:
- movl 4(%esp),%ecx /* jmpbuf */
- movl 0(%esp),%edx /* return address */
- movl %edx,0(%ecx)
- movl %ebx,4(%ecx)
- movl %esp,8(%ecx)
- movl %ebp,12(%ecx)
- movl %esi,16(%ecx)
- movl %edi,20(%ecx)
- movl $0,%eax
- ret
-
- /**************************************************************************
- LONGJMP - Non-local jump to a saved stack context
- **************************************************************************/
- .globl longjmp
- longjmp:
- movl 4(%esp),%edx /* jumpbuf */
- movl 8(%esp),%eax /* result */
- movl 0(%edx),%ecx
- movl 4(%edx),%ebx
- movl 8(%edx),%esp
- movl 12(%edx),%ebp
- movl 16(%edx),%esi
- movl 20(%edx),%edi
- cmpl $0,%eax
- jne 1f
- movl $1,%eax
- 1: movl %ecx,0(%esp)
- ret
-
- /**************************************************************************
- _VIRT_TO_PHYS - Transition from virtual to physical addresses
- Preserves all preservable registers and flags
- **************************************************************************/
- .globl _virt_to_phys
- _virt_to_phys:
- pushfl
- pushl %ebp
- pushl %eax
- movl virt_offset, %ebp /* Load virt_offset */
- addl %ebp, 12(%esp) /* Adjust the return address */
-
- /* reload the code segment */
- pushl $FLAT_CODE_SEG
- leal 1f(%ebp), %eax
- pushl %eax
- lret
-
- 1:
- /* reload other segment registers */
- movl $FLAT_DATA_SEG, %eax
- movl %eax, %ds
- movl %eax, %es
- movl %eax, %ss
- addl %ebp, %esp /* Adjust the stack pointer */
- movl %eax, %fs
- movl %eax, %gs
-
- popl %eax
- popl %ebp
- popfl
- ret
-
-
- /**************************************************************************
- _PHYS_TO_VIRT - Transition from using physical to virtual addresses
- Preserves all preservable registers and flags
- **************************************************************************/
- .globl _phys_to_virt
- _phys_to_virt:
- pushfl
- pushl %ebp
- pushl %eax
-
- call 1f
- 1: popl %ebp
- subl $1b, %ebp
- movl %ebp, virt_offset(%ebp)
-
- /* Fixup the gdt */
- leal _pmcs(%ebp), %eax
- pushl %eax
- pushl %ebp
- call set_seg_base
- addl $8, %esp
-
- /* Fixup gdtarg */
- leal _gdt(%ebp), %eax
- movl %eax, (gdtarg+2)(%ebp)
-
- /* Load the global descriptor table */
- cli
- lgdt %cs:gdtarg(%ebp)
- ljmp $KERN_CODE_SEG, $1f
- 1:
- /* reload other segment regsters */
- movl $KERN_DATA_SEG, %eax
- movl %eax, %ds
- movl %eax, %es
- movl %eax, %ss
- subl %ebp, %esp /* Adjust the stack pointer */
- movl %eax, %fs
- movl %eax, %gs
-
- subl %ebp, 12(%esp) /* Adjust the return address */
- popl %eax
- popl %ebp
- popfl
- ret
-
-
- /**************************************************************************
- SET_SEG_BASE - Set the base address of a segment register
- **************************************************************************/
- .globl set_seg_base
- set_seg_base:
- pushl %eax
- pushl %ebx
- movl 12(%esp), %eax /* %eax = base address */
- movl 16(%esp), %ebx /* %ebx = &code_descriptor */
- movw %ax, (0+2)(%ebx) /* CS base bits 0-15 */
- movw %ax, (8+2)(%ebx) /* DS base bits 0-15 */
- shrl $16, %eax
- movb %al, (0+4)(%ebx) /* CS base bits 16-23 */
- movb %al, (8+4)(%ebx) /* DS base bits 16-23 */
- movb %ah, (0+7)(%ebx) /* CS base bits 24-31 */
- movb %ah, (8+7)(%ebx) /* DS base bits 24-31 */
- popl %ebx
- popl %eax
- ret
-
- /**************************************************************************
- GLOBAL DESCRIPTOR TABLE
- **************************************************************************/
- .data
- .align 4
-
- .globl _gdt
- .globl gdtarg
- _gdt:
- gdtarg:
- .word _gdt_end - _gdt - 1 /* limit */
- .long _gdt /* addr */
- .word 0
-
- .globl _pmcs
- _pmcs:
- /* 32 bit protected mode code segment */
- .word 0xffff,0
- .byte 0,0x9f,0xcf,0
-
- _pmds:
- /* 32 bit protected mode data segment */
- .word 0xffff,0
- .byte 0,0x93,0xcf,0
-
- _rmcs:
- /* 16 bit real mode code segment */
- .word 0xffff,(0&0xffff)
- .byte (0>>16),0x9b,0x00,(0>>24)
-
- _rmds:
- /* 16 bit real mode data segment */
- .word 0xffff,(0&0xffff)
- .byte (0>>16),0x93,0x00,(0>>24)
-
- _pmcs2:
- /* 32 bit protected mode code segment, base 0 */
- .word 0xffff,0
- .byte 0,0x9f,0xcf,0
-
- _pmds2:
- /* 32 bit protected mode data segment, base 0 */
- .word 0xffff,0
- .byte 0,0x93,0xcf,0
-
- #ifdef CONFIG_X86_64
- _lmcs:
- /* 64bit long mode code segment, base 0 */
- .word 0xffff, 0
- .byte 0x00, 0x9f, 0xaf , 0x00
- _lmds:
- /* 64bit long mode data segment, base 0 */
- .word 0xffff, 0
- .byte 0x00, 0x93, 0xcf, 0x00
- #endif
- _gdt_end:
-
- /* The initial register contents */
- .balign 4
- .globl initial_regs
- initial_regs:
- .fill 8, 4, 0
-
- /* The virtual address offset */
- .globl virt_offset
- virt_offset:
- .long 0
-
- .section ".stack"
- .p2align 3
- /* allocate a 4K stack in the stack segment */
- .globl _stack
- _stack:
- .space 4096
- .globl _estack
- _estack:
- #ifdef CONFIG_X86_64
- .section ".bss"
- .p2align 12
- /* Include a dummy space in case we are loaded badly aligned */
- .space 4096
- /* Reserve enough space for a page table convering 4GB with 2MB pages */
- pgt_level4:
- .space 4096
- pgt_level3:
- .space 4096
- pgt_level2:
- .space 16384
- start_lm_addr:
- .space 8
- end_lm_addr:
- .space 8
- #endif
|