OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [i386/] [kernel/] [head.S] - Diff between revs 1765 and 1782

Only display areas with differences | Details | Blame | View Log

Rev 1765 Rev 1782
/*
/*
 *  linux/arch/i386/head.S
 *  linux/arch/i386/head.S
 *
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *  Copyright (C) 1991, 1992  Linus Torvalds
 */
 */
/*
/*
 *  head.S contains the 32-bit startup code.
 *  head.S contains the 32-bit startup code.
 */
 */
.text
.text
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define CL_MAGIC_ADDR   0x90020
#define CL_MAGIC_ADDR   0x90020
#define CL_MAGIC        0xA33F
#define CL_MAGIC        0xA33F
#define CL_BASE_ADDR    0x90000
#define CL_BASE_ADDR    0x90000
#define CL_OFFSET       0x90022
#define CL_OFFSET       0x90022
/*
/*
 * swapper_pg_dir is the main page directory, address 0x00001000 (or at
 * swapper_pg_dir is the main page directory, address 0x00001000 (or at
 * address 0x00101000 for a compressed boot).
 * address 0x00101000 for a compressed boot).
 */
 */
ENTRY(stext)
ENTRY(stext)
ENTRY(_stext)
ENTRY(_stext)
startup_32:
startup_32:
        cld
        cld
        movl $(KERNEL_DS),%eax
        movl $(KERNEL_DS),%eax
        mov %ax,%ds
        mov %ax,%ds
        mov %ax,%es
        mov %ax,%es
        mov %ax,%fs
        mov %ax,%fs
        mov %ax,%gs
        mov %ax,%gs
#ifdef __SMP__
#ifdef __SMP__
        orw  %bx,%bx
        orw  %bx,%bx
        jz  1f                          /* Initial CPU cleans BSS */
        jz  1f                          /* Initial CPU cleans BSS */
/*
/*
 *      Set up the stack
 *      Set up the stack
 */
 */
        mov %ax,%ss
        mov %ax,%ss
        xorl %eax,%eax
        xorl %eax,%eax
        movw %cx, %ax
        movw %cx, %ax
        movl %eax,%esp
        movl %eax,%esp
        pushl $0
        pushl $0
        popfl
        popfl
        jmp checkCPUtype
        jmp checkCPUtype
1:
1:
        lss stack_start,%esp
        lss stack_start,%esp
#endif __SMP__
#endif __SMP__
/*
/*
 * Clear BSS first so that there are no surprises...
 * Clear BSS first so that there are no surprises...
 */
 */
        xorl %eax,%eax
        xorl %eax,%eax
        movl $ SYMBOL_NAME(_edata),%edi
        movl $ SYMBOL_NAME(_edata),%edi
        movl $ SYMBOL_NAME(_end),%ecx
        movl $ SYMBOL_NAME(_end),%ecx
        subl %edi,%ecx
        subl %edi,%ecx
        cld
        cld
        rep
        rep
        stosb
        stosb
/*
/*
 * start system 32-bit setup. We need to re-do some of the things done
 * start system 32-bit setup. We need to re-do some of the things done
 * in 16-bit mode for the "real" operations.
 * in 16-bit mode for the "real" operations.
 */
 */
        call setup_idt
        call setup_idt
        xorl %eax,%eax
        xorl %eax,%eax
1:      incl %eax               # check that A20 really IS enabled
1:      incl %eax               # check that A20 really IS enabled
        movl %eax,0x000000      # loop forever if it isn't
        movl %eax,0x000000      # loop forever if it isn't
        cmpl %eax,0x100000
        cmpl %eax,0x100000
        je 1b
        je 1b
/*
/*
 * Initialize eflags.  Some BIOS's leave bits like NT set.  This would
 * Initialize eflags.  Some BIOS's leave bits like NT set.  This would
 * confuse the debugger if this code is traced.
 * confuse the debugger if this code is traced.
 * XXX - best to initialize before switching to protected mode.
 * XXX - best to initialize before switching to protected mode.
 */
 */
        pushl $0
        pushl $0
        popfl
        popfl
/*
/*
 * Copy bootup parameters out of the way. First 2kB of
 * Copy bootup parameters out of the way. First 2kB of
 * _empty_zero_page is for boot parameters, second 2kB
 * _empty_zero_page is for boot parameters, second 2kB
 * is for the command line.
 * is for the command line.
 */
 */
        movl $0x90000,%esi
        movl $0x90000,%esi
        movl $ SYMBOL_NAME(empty_zero_page),%edi
        movl $ SYMBOL_NAME(empty_zero_page),%edi
        movl $512,%ecx
        movl $512,%ecx
        cld
        cld
        rep
        rep
        movsl
        movsl
        xorl %eax,%eax
        xorl %eax,%eax
        movl $512,%ecx
        movl $512,%ecx
        rep
        rep
        stosl
        stosl
        cmpw $(CL_MAGIC),CL_MAGIC_ADDR
        cmpw $(CL_MAGIC),CL_MAGIC_ADDR
        jne 1f
        jne 1f
        movl $ SYMBOL_NAME(empty_zero_page)+2048,%edi
        movl $ SYMBOL_NAME(empty_zero_page)+2048,%edi
        movzwl CL_OFFSET,%esi
        movzwl CL_OFFSET,%esi
        addl $(CL_BASE_ADDR),%esi
        addl $(CL_BASE_ADDR),%esi
        movl $2048,%ecx
        movl $2048,%ecx
        rep
        rep
        movsb
        movsb
1:
1:
#ifdef __SMP__
#ifdef __SMP__
checkCPUtype:
checkCPUtype:
#endif
#endif
/* check Processor type: 386, 486, 6x86(L) or CPUID capable processor */
/* check Processor type: 386, 486, 6x86(L) or CPUID capable processor */
/*
/*
 * XXX - this does a lot of unnecessary setup.  Alignment checks don't
 * XXX - this does a lot of unnecessary setup.  Alignment checks don't
 * apply at our cpl of 0 and the stack ought to be aligned already, and
 * apply at our cpl of 0 and the stack ought to be aligned already, and
 * we don't need to preserve eflags.
 * we don't need to preserve eflags.
 */
 */
        movl $3, SYMBOL_NAME(x86)
        movl $3, SYMBOL_NAME(x86)
        pushfl                  # push EFLAGS
        pushfl                  # push EFLAGS
        popl %eax               # get EFLAGS
        popl %eax               # get EFLAGS
        movl %eax,%ecx          # save original EFLAGS in ecx
        movl %eax,%ecx          # save original EFLAGS in ecx
        xorl $0x40000,%eax      # flip AC bit in EFLAGS
        xorl $0x40000,%eax      # flip AC bit in EFLAGS
        pushl %eax              # copy to EFLAGS
        pushl %eax              # copy to EFLAGS
        popfl                   # set EFLAGS
        popfl                   # set EFLAGS
        pushfl                  # get new EFLAGS
        pushfl                  # get new EFLAGS
        popl %eax               # put it in eax
        popl %eax               # put it in eax
        xorl %ecx,%eax          # change in flags
        xorl %ecx,%eax          # change in flags
        andl $0x40000,%eax      # check if AC bit changed
        andl $0x40000,%eax      # check if AC bit changed
        je is386
        je is386
        movl $4,SYMBOL_NAME(x86)
        movl $4,SYMBOL_NAME(x86)
        movl %ecx,%eax
        movl %ecx,%eax
        xorl $0x200000,%eax     # check ID flag
        xorl $0x200000,%eax     # check ID flag
        pushl %eax
        pushl %eax
        popfl                   # if we are on a straight 486DX, SX, or
        popfl                   # if we are on a straight 486DX, SX, or
        pushfl                  # 487SX we can't change it
        pushfl                  # 487SX we can't change it
        popl %eax               # Also if we are on a Cyrix 6x86(L)
        popl %eax               # Also if we are on a Cyrix 6x86(L)
        xorl %ecx,%eax          # OTOH 6x86MXs and MIIs check OK
        xorl %ecx,%eax          # OTOH 6x86MXs and MIIs check OK
        andl $0x200000,%eax
        andl $0x200000,%eax
        je is486x
        je is486x
isnew:  pushl %ecx              # restore original EFLAGS
isnew:  pushl %ecx              # restore original EFLAGS
        popfl
        popfl
        incl SYMBOL_NAME(have_cpuid)    # we have CPUID
        incl SYMBOL_NAME(have_cpuid)    # we have CPUID
        /*
        /*
         *      Technically we should use CPUID 0 to see if we have CPUID 1!
         *      Technically we should use CPUID 0 to see if we have CPUID 1!
         */
         */
        /* get processor type */
        /* get processor type */
        movl $1, %eax           # Use the CPUID instruction to
        movl $1, %eax           # Use the CPUID instruction to
#ifdef GAS_KNOWS_CPUID
#ifdef GAS_KNOWS_CPUID
        cpuid                   # check the processor type
        cpuid                   # check the processor type
#else
#else
        .byte 0x0f, 0xa2        # check the processor type
        .byte 0x0f, 0xa2        # check the processor type
#endif
#endif
        movb %al, %cl           # save reg for future use
        movb %al, %cl           # save reg for future use
        andb $0x0f,%ah          # mask processor family
        andb $0x0f,%ah          # mask processor family
        movb %ah,SYMBOL_NAME(x86)
        movb %ah,SYMBOL_NAME(x86)
        andb $0xf0, %al         # mask model
        andb $0xf0, %al         # mask model
        shrb $4, %al
        shrb $4, %al
        movb %al,SYMBOL_NAME(x86_model)
        movb %al,SYMBOL_NAME(x86_model)
        andb $0x0f, %cl         # mask mask revision
        andb $0x0f, %cl         # mask mask revision
        movb %cl,SYMBOL_NAME(x86_mask)
        movb %cl,SYMBOL_NAME(x86_mask)
        movl %edx,SYMBOL_NAME(x86_capability)
        movl %edx,SYMBOL_NAME(x86_capability)
        /* get vendor info */
        /* get vendor info */
        xorl %eax, %eax                 # call CPUID with 0 -> return vendor ID
        xorl %eax, %eax                 # call CPUID with 0 -> return vendor ID
#ifdef GAS_KNOWS_CPUID
#ifdef GAS_KNOWS_CPUID
        cpuid
        cpuid
#else
#else
        .byte 0x0f, 0xa2                # CPUID
        .byte 0x0f, 0xa2                # CPUID
#endif
#endif
        movl %ebx,SYMBOL_NAME(x86_vendor_id)    # lo 4 chars
        movl %ebx,SYMBOL_NAME(x86_vendor_id)    # lo 4 chars
        movl %edx,SYMBOL_NAME(x86_vendor_id)+4  # next 4 chars
        movl %edx,SYMBOL_NAME(x86_vendor_id)+4  # next 4 chars
        movl %ecx,SYMBOL_NAME(x86_vendor_id)+8  # last 4 chars
        movl %ecx,SYMBOL_NAME(x86_vendor_id)+8  # last 4 chars
        movl %cr0,%eax          # 486+
        movl %cr0,%eax          # 486+
        andl $0x80000011,%eax   # Save PG,PE,ET
        andl $0x80000011,%eax   # Save PG,PE,ET
        orl $0x50022,%eax       # set AM, WP, NE and MP
        orl $0x50022,%eax       # set AM, WP, NE and MP
        jmp 2f
        jmp 2f
/* Now we test if we have a Cyrix 6x86(L). We didn't test before to avoid
/* Now we test if we have a Cyrix 6x86(L). We didn't test before to avoid
 * clobbering the new BX chipset used with the Pentium II, which has a register
 * clobbering the new BX chipset used with the Pentium II, which has a register
 * at the same addresses as those used to access the Cyrix special configuration
 * at the same addresses as those used to access the Cyrix special configuration
 * registers (CCRs).
 * registers (CCRs).
 */
 */
        /*
        /*
         * A Cyrix/IBM 6x86(L) preserves flags after dividing 5 by 2
         * A Cyrix/IBM 6x86(L) preserves flags after dividing 5 by 2
         * (and it _must_ be 5 divided by 2) while other CPUs change
         * (and it _must_ be 5 divided by 2) while other CPUs change
         * them in undefined ways. We need to know this since we may
         * them in undefined ways. We need to know this since we may
         * need to enable the CPUID instruction at least.
         * need to enable the CPUID instruction at least.
         * We couldn't use this test before since the PPro and PII behave
         * We couldn't use this test before since the PPro and PII behave
         * like Cyrix chips in this respect.
         * like Cyrix chips in this respect.
         */
         */
is486x: xor %ax,%ax
is486x: xor %ax,%ax
        sahf
        sahf
        movb $5,%ax
        movb $5,%ax
        movb $2,%bx
        movb $2,%bx
        div %bl
        div %bl
        lahf
        lahf
        cmpb $2,%ah
        cmpb $2,%ah
        jne ncyrix
        jne ncyrix
        /*
        /*
         * N.B. The pattern of accesses to 0x22 and 0x23 is *essential*
         * N.B. The pattern of accesses to 0x22 and 0x23 is *essential*
         *      so do not try to "optimize" it! For the same reason we
         *      so do not try to "optimize" it! For the same reason we
         *      do all this with interrupts off.
         *      do all this with interrupts off.
         */
         */
#define setCx86(reg, val) \
#define setCx86(reg, val) \
        movb reg,%ax;   \
        movb reg,%ax;   \
        outb %ax,$0x22; \
        outb %ax,$0x22; \
        movb val,%ax;   \
        movb val,%ax;   \
        outb %ax,$0x23
        outb %ax,$0x23
#define getCx86(reg) \
#define getCx86(reg) \
        movb reg,%ax;   \
        movb reg,%ax;   \
        outb %ax,$0x22; \
        outb %ax,$0x22; \
        inb $0x23,%ax
        inb $0x23,%ax
        cli
        cli
        getCx86($0xc3)          # get CCR3
        getCx86($0xc3)          # get CCR3
        movb %ax,%cx            # Save old value
        movb %ax,%cx            # Save old value
        movb %ax,%bx
        movb %ax,%bx
        andb $0x0f,%bx          # Enable access to all config registers
        andb $0x0f,%bx          # Enable access to all config registers
        orb $0x10,%bx           # by setting bit 4
        orb $0x10,%bx           # by setting bit 4
        setCx86($0xc3,%bx)
        setCx86($0xc3,%bx)
        getCx86($0xfe)          # DIR0 : let's check this is a 6x86(L)
        getCx86($0xfe)          # DIR0 : let's check this is a 6x86(L)
        andb $0xf0,%ax          # should be 3xh
        andb $0xf0,%ax          # should be 3xh
        cmpb $0x30,%ax          #
        cmpb $0x30,%ax          #
        jne n6x86
        jne n6x86
        getCx86($0xe8)          # now we can get CCR4
        getCx86($0xe8)          # now we can get CCR4
        orb $0x80,%ax           # and set bit 7 (CPUIDEN)
        orb $0x80,%ax           # and set bit 7 (CPUIDEN)
        movb %ax,%bx            # to enable CPUID execution
        movb %ax,%bx            # to enable CPUID execution
        setCx86($0xe8,%bx)
        setCx86($0xe8,%bx)
        getCx86($0xe9)          # CCR5 : we reset the SLOP bit
        getCx86($0xe9)          # CCR5 : we reset the SLOP bit
        andb $0xfd,%ax          # so that udelay calculation
        andb $0xfd,%ax          # so that udelay calculation
        movb %ax,%bx            # is correct on 6x86(L) CPUs
        movb %ax,%bx            # is correct on 6x86(L) CPUs
        setCx86($0xe9,%bx)
        setCx86($0xe9,%bx)
        setCx86($0xc3,%cx)      # Restore old CCR3
        setCx86($0xc3,%cx)      # Restore old CCR3
        sti
        sti
        jmp isnew               # We enabled CPUID now
        jmp isnew               # We enabled CPUID now
n6x86:  setCx86($0xc3,%cx)      # Restore old CCR3
n6x86:  setCx86($0xc3,%cx)      # Restore old CCR3
        sti
        sti
ncyrix: pushl %ecx              # restore original EFLAGS
ncyrix: pushl %ecx              # restore original EFLAGS
        popfl
        popfl
        movl %cr0,%eax          # 486
        movl %cr0,%eax          # 486
        andl $0x80000011,%eax   # Save PG,PE,ET
        andl $0x80000011,%eax   # Save PG,PE,ET
        orl $0x50022,%eax       # set AM, WP, NE and MP
        orl $0x50022,%eax       # set AM, WP, NE and MP
        jmp 2f
        jmp 2f
is386:  pushl %ecx              # restore original EFLAGS
is386:  pushl %ecx              # restore original EFLAGS
        popfl
        popfl
        movl %cr0,%eax          # 386
        movl %cr0,%eax          # 386
        andl $0x80000011,%eax   # Save PG,PE,ET
        andl $0x80000011,%eax   # Save PG,PE,ET
        orl $2,%eax             # set MP
        orl $2,%eax             # set MP
2:      movl %eax,%cr0
2:      movl %eax,%cr0
        call check_x87
        call check_x87
#ifdef __SMP__
#ifdef __SMP__
        movb ready,%al
        movb ready,%al
        orb %al,%al
        orb %al,%al
        jz 3f
        jz 3f
        movl $ SYMBOL_NAME(swapper_pg_dir), %eax
        movl $ SYMBOL_NAME(swapper_pg_dir), %eax
        movl %eax, %cr3
        movl %eax, %cr3
#ifdef GAS_KNOWS_CR4
#ifdef GAS_KNOWS_CR4
        movl %cr4,%eax
        movl %cr4,%eax
        orl $16,%eax
        orl $16,%eax
        movl %eax,%cr4
        movl %eax,%cr4
#else
#else
        .byte 0x0f,0x20,0xe0
        .byte 0x0f,0x20,0xe0
        orl $16,%eax
        orl $16,%eax
        .byte 0x0f,0x22,0xe0
        .byte 0x0f,0x22,0xe0
#endif
#endif
        movl %cr0, %eax
        movl %cr0, %eax
        orl $0x80000000, %eax
        orl $0x80000000, %eax
        movl %eax, %cr0
        movl %eax, %cr0
        jmp 4f
        jmp 4f
#endif
#endif
3:
3:
        call setup_paging
        call setup_paging
#ifdef __SMP__
#ifdef __SMP__
        incb ready
        incb ready
#endif
#endif
4:
4:
        lgdt gdt_descr
        lgdt gdt_descr
        lidt idt_descr
        lidt idt_descr
        ljmp $(KERNEL_CS),$1f
        ljmp $(KERNEL_CS),$1f
1:      movl $(KERNEL_DS),%eax  # reload all the segment registers
1:      movl $(KERNEL_DS),%eax  # reload all the segment registers
        mov %ax,%ds             # after changing gdt.
        mov %ax,%ds             # after changing gdt.
        mov %ax,%es
        mov %ax,%es
        mov %ax,%fs
        mov %ax,%fs
        mov %ax,%gs
        mov %ax,%gs
#ifdef __SMP__
#ifdef __SMP__
        movl $(KERNEL_DS), %eax
        movl $(KERNEL_DS), %eax
        mov  %ax,%ss            # Reload the stack pointer (segment only)
        mov  %ax,%ss            # Reload the stack pointer (segment only)
#else
#else
        lss stack_start,%esp    # Load processor stack
        lss stack_start,%esp    # Load processor stack
#endif
#endif
        xorl %eax,%eax
        xorl %eax,%eax
        lldt %ax
        lldt %ax
        pushl %eax              # These are the parameters to main :-)
        pushl %eax              # These are the parameters to main :-)
        pushl %eax
        pushl %eax
        pushl %eax
        pushl %eax
        cld                     # gcc2 wants the direction flag cleared at all times
        cld                     # gcc2 wants the direction flag cleared at all times
        call SYMBOL_NAME(start_kernel)
        call SYMBOL_NAME(start_kernel)
L6:
L6:
        jmp L6                  # main should never return here, but
        jmp L6                  # main should never return here, but
                                # just in case, we know what happens.
                                # just in case, we know what happens.
#ifdef __SMP__
#ifdef __SMP__
ready:  .byte 0
ready:  .byte 0
#endif
#endif
/*
/*
 * We depend on ET to be correct. This checks for 287/387.
 * We depend on ET to be correct. This checks for 287/387.
 */
 */
check_x87:
check_x87:
        movb $0,SYMBOL_NAME(hard_math)
        movb $0,SYMBOL_NAME(hard_math)
        clts
        clts
        fninit
        fninit
        fstsw %ax
        fstsw %ax
        cmpb $0,%al
        cmpb $0,%al
        je 1f
        je 1f
        movl %cr0,%eax          /* no coprocessor: have to set bits */
        movl %cr0,%eax          /* no coprocessor: have to set bits */
        xorl $4,%eax            /* set EM */
        xorl $4,%eax            /* set EM */
        movl %eax,%cr0
        movl %eax,%cr0
        ret
        ret
        ALIGN
        ALIGN
1:      movb $1,SYMBOL_NAME(hard_math)
1:      movb $1,SYMBOL_NAME(hard_math)
        .byte 0xDB,0xE4         /* fsetpm for 287, ignored by 387 */
        .byte 0xDB,0xE4         /* fsetpm for 287, ignored by 387 */
        ret
        ret
/*
/*
 *  setup_idt
 *  setup_idt
 *
 *
 *  sets up a idt with 256 entries pointing to
 *  sets up a idt with 256 entries pointing to
 *  ignore_int, interrupt gates. It doesn't actually load
 *  ignore_int, interrupt gates. It doesn't actually load
 *  idt - that can be done only after paging has been enabled
 *  idt - that can be done only after paging has been enabled
 *  and the kernel moved to PAGE_OFFSET. Interrupts
 *  and the kernel moved to PAGE_OFFSET. Interrupts
 *  are enabled elsewhere, when we can be relatively
 *  are enabled elsewhere, when we can be relatively
 *  sure everything is ok.
 *  sure everything is ok.
 */
 */
setup_idt:
setup_idt:
        lea ignore_int,%edx
        lea ignore_int,%edx
        movl $(KERNEL_CS << 16),%eax
        movl $(KERNEL_CS << 16),%eax
        movw %dx,%ax            /* selector = 0x0010 = cs */
        movw %dx,%ax            /* selector = 0x0010 = cs */
        movw $0x8E00,%dx        /* interrupt gate - dpl=0, present */
        movw $0x8E00,%dx        /* interrupt gate - dpl=0, present */
        lea SYMBOL_NAME(idt),%edi
        lea SYMBOL_NAME(idt),%edi
        mov $256,%ecx
        mov $256,%ecx
rp_sidt:
rp_sidt:
        movl %eax,(%edi)
        movl %eax,(%edi)
        movl %edx,4(%edi)
        movl %edx,4(%edi)
        addl $8,%edi
        addl $8,%edi
        dec %ecx
        dec %ecx
        jne rp_sidt
        jne rp_sidt
        ret
        ret
/*
/*
 * Setup_paging
 * Setup_paging
 *
 *
 * This routine sets up paging by setting the page bit
 * This routine sets up paging by setting the page bit
 * in cr0. The page tables are set up, identity-mapping
 * in cr0. The page tables are set up, identity-mapping
 * the first 4MB.  The rest are initialized later.
 * the first 4MB.  The rest are initialized later.
 *
 *
 * (ref: added support for up to 32mb, 17Apr92)  -- Rik Faith
 * (ref: added support for up to 32mb, 17Apr92)  -- Rik Faith
 * (ref: update, 25Sept92)  -- croutons@crunchy.uucp
 * (ref: update, 25Sept92)  -- croutons@crunchy.uucp
 * (ref: 92.10.11 - Linus Torvalds. Corrected 16M limit - no upper memory limit)
 * (ref: 92.10.11 - Linus Torvalds. Corrected 16M limit - no upper memory limit)
 */
 */
        ALIGN
        ALIGN
setup_paging:
setup_paging:
        movl $1024*2,%ecx               /* 2 pages - swapper_pg_dir+1 page table */
        movl $1024*2,%ecx               /* 2 pages - swapper_pg_dir+1 page table */
        xorl %eax,%eax
        xorl %eax,%eax
        movl $ SYMBOL_NAME(swapper_pg_dir),%edi /* swapper_pg_dir is at 0x1000 */
        movl $ SYMBOL_NAME(swapper_pg_dir),%edi /* swapper_pg_dir is at 0x1000 */
        cld;rep;stosl
        cld;rep;stosl
/* Identity-map the kernel in low 4MB memory for ease of transition */
/* Identity-map the kernel in low 4MB memory for ease of transition */
/* set present bit/user r/w */
/* set present bit/user r/w */
        movl $ SYMBOL_NAME(pg0)+7,SYMBOL_NAME(swapper_pg_dir)
        movl $ SYMBOL_NAME(pg0)+7,SYMBOL_NAME(swapper_pg_dir)
/* But the real place is at PAGE_OFFSET */
/* But the real place is at PAGE_OFFSET */
/* set present bit/user r/w */
/* set present bit/user r/w */
        movl $ SYMBOL_NAME(pg0)+7,SYMBOL_NAME(swapper_pg_dir)+__USER_PGD_PTRS*4
        movl $ SYMBOL_NAME(pg0)+7,SYMBOL_NAME(swapper_pg_dir)+__USER_PGD_PTRS*4
        movl $ SYMBOL_NAME(pg0)+4092,%edi
        movl $ SYMBOL_NAME(pg0)+4092,%edi
        movl $0x03ff007,%eax            /*  4Mb - 4096 + 7 (r/w user,p) */
        movl $0x03ff007,%eax            /*  4Mb - 4096 + 7 (r/w user,p) */
        std
        std
1:      stosl                   /* fill the page backwards - more efficient :-) */
1:      stosl                   /* fill the page backwards - more efficient :-) */
        subl $0x1000,%eax
        subl $0x1000,%eax
        jge 1b
        jge 1b
        cld
        cld
        movl $ SYMBOL_NAME(swapper_pg_dir),%eax
        movl $ SYMBOL_NAME(swapper_pg_dir),%eax
        movl %eax,%cr3                  /* cr3 - page directory start */
        movl %eax,%cr3                  /* cr3 - page directory start */
        movl %cr0,%eax
        movl %cr0,%eax
        orl $0x80000000,%eax
        orl $0x80000000,%eax
        movl %eax,%cr0          /* set paging (PG) bit */
        movl %eax,%cr0          /* set paging (PG) bit */
        ret                     /* this also flushes the prefetch-queue */
        ret                     /* this also flushes the prefetch-queue */
/*
/*
 * page 0 is made non-existent, so that kernel NULL pointer references get
 * page 0 is made non-existent, so that kernel NULL pointer references get
 * caught. Thus the swapper page directory has been moved to 0x1000
 * caught. Thus the swapper page directory has been moved to 0x1000
 *
 *
 * XXX Actually, the swapper page directory is at 0x1000 plus 1 megabyte,
 * XXX Actually, the swapper page directory is at 0x1000 plus 1 megabyte,
 * with the introduction of the compressed boot code.  Theoretically,
 * with the introduction of the compressed boot code.  Theoretically,
 * the original design of overlaying the startup code with the swapper
 * the original design of overlaying the startup code with the swapper
 * page directory is still possible --- it would reduce the size of the kernel
 * page directory is still possible --- it would reduce the size of the kernel
 * by 2-3k.  This would be a good thing to do at some point.....
 * by 2-3k.  This would be a good thing to do at some point.....
 */
 */
.org 0x1000
.org 0x1000
ENTRY(swapper_pg_dir)
ENTRY(swapper_pg_dir)
/*
/*
 * The page tables are initialized to only 4MB here - the final page
 * The page tables are initialized to only 4MB here - the final page
 * tables are set up later depending on memory size.
 * tables are set up later depending on memory size.
 */
 */
.org 0x2000
.org 0x2000
ENTRY(pg0)
ENTRY(pg0)
.org 0x3000
.org 0x3000
ENTRY(empty_bad_page)
ENTRY(empty_bad_page)
.org 0x4000
.org 0x4000
ENTRY(empty_bad_page_table)
ENTRY(empty_bad_page_table)
.org 0x5000
.org 0x5000
ENTRY(empty_zero_page)
ENTRY(empty_zero_page)
.org 0x6000
.org 0x6000
stack_start:
stack_start:
        .long SYMBOL_NAME(init_user_stack)+4096
        .long SYMBOL_NAME(init_user_stack)+4096
        .long KERNEL_DS
        .long KERNEL_DS
/* NOTE: keep the idt short behind the above '.org 0x6000'
/* NOTE: keep the idt short behind the above '.org 0x6000'
         It must fit completely within _one_ page */
         It must fit completely within _one_ page */
ENTRY(idt)
ENTRY(idt)
        .fill 256,8,0           # idt is uninitialized
        .fill 256,8,0           # idt is uninitialized
/* This is the default interrupt "handler" :-) */
/* This is the default interrupt "handler" :-) */
int_msg:
int_msg:
        .asciz "Unknown interrupt\n"
        .asciz "Unknown interrupt\n"
        ALIGN
        ALIGN
ignore_int:
ignore_int:
        cld
        cld
        pushl %eax
        pushl %eax
        pushl %ecx
        pushl %ecx
        pushl %edx
        pushl %edx
        push %ds
        push %ds
        push %es
        push %es
        push %fs
        push %fs
        movl $(KERNEL_DS),%eax
        movl $(KERNEL_DS),%eax
        mov %ax,%ds
        mov %ax,%ds
        mov %ax,%es
        mov %ax,%es
        mov %ax,%fs
        mov %ax,%fs
        pushl $int_msg
        pushl $int_msg
        call SYMBOL_NAME(printk)
        call SYMBOL_NAME(printk)
        popl %eax
        popl %eax
        pop %fs
        pop %fs
        pop %es
        pop %es
        pop %ds
        pop %ds
        popl %edx
        popl %edx
        popl %ecx
        popl %ecx
        popl %eax
        popl %eax
        iret
        iret
/*
/*
 * The interrupt descriptor table has room for 256 idt's
 * The interrupt descriptor table has room for 256 idt's
 */
 */
        ALIGN
        ALIGN
.word 0
.word 0
idt_descr:
idt_descr:
        .word 256*8-1           # idt contains 256 entries
        .word 256*8-1           # idt contains 256 entries
        .long __PAGE_OFFSET+SYMBOL_NAME(idt)
        .long __PAGE_OFFSET+SYMBOL_NAME(idt)
        ALIGN
        ALIGN
.word 0
.word 0
gdt_descr:
gdt_descr:
#ifdef CONFIG_APM
#ifdef CONFIG_APM
        .word (11+2*NR_TASKS)*8-1
        .word (11+2*NR_TASKS)*8-1
#else
#else
        .word (8+2*NR_TASKS)*8-1
        .word (8+2*NR_TASKS)*8-1
#endif
#endif
        .long __PAGE_OFFSET+SYMBOL_NAME(gdt)
        .long __PAGE_OFFSET+SYMBOL_NAME(gdt)
/*
/*
 * This gdt setup gives the kernel a 1GB address space at virtual
 * This gdt setup gives the kernel a 1GB address space at virtual
 * address PAGE_OFFSET - space enough for expansion, I hope.
 * address PAGE_OFFSET - space enough for expansion, I hope.
 */
 */
#define upper_seg(type,dpl,base,limit) \
#define upper_seg(type,dpl,base,limit) \
        ((base) & 0xff000000) | \
        ((base) & 0xff000000) | \
        (((base) & 0x00ff0000)>>16) | \
        (((base) & 0x00ff0000)>>16) | \
        (((limit)>>12) & 0xf0000) | \
        (((limit)>>12) & 0xf0000) | \
        ((dpl)<<13) | \
        ((dpl)<<13) | \
        (0x00c09000) | \
        (0x00c09000) | \
        ((type)<<8)
        ((type)<<8)
#define lower_seg(type,dpl,base,limit) \
#define lower_seg(type,dpl,base,limit) \
        (((base) & 0x0000ffff)<<16) | \
        (((base) & 0x0000ffff)<<16) | \
        (((limit)>>12) & 0x0ffff)
        (((limit)>>12) & 0x0ffff)
#define x86_seg(type,dpl,base,limit) \
#define x86_seg(type,dpl,base,limit) \
        .long lower_seg(type,dpl,base,limit); \
        .long lower_seg(type,dpl,base,limit); \
        .long upper_seg(type,dpl,base,limit)
        .long upper_seg(type,dpl,base,limit)
ENTRY(gdt)
ENTRY(gdt)
        .quad 0x0000000000000000        /* NULL descriptor */
        .quad 0x0000000000000000        /* NULL descriptor */
        .quad 0x0000000000000000        /* not used */
        .quad 0x0000000000000000        /* not used */
        /* 0x10 kernel 1GB code at 0xC0000000: */
        /* 0x10 kernel 1GB code at 0xC0000000: */
        x86_seg(0xa,0,__PAGE_OFFSET,0xffffffff-__PAGE_OFFSET)
        x86_seg(0xa,0,__PAGE_OFFSET,0xffffffff-__PAGE_OFFSET)
        /* 0x18 kernel 1GB data at 0xC0000000: */
        /* 0x18 kernel 1GB data at 0xC0000000: */
        x86_seg(0x2,0,__PAGE_OFFSET,0xffffffff-__PAGE_OFFSET)
        x86_seg(0x2,0,__PAGE_OFFSET,0xffffffff-__PAGE_OFFSET)
        /* 0x23 user 3GB code at 0x00000000: */
        /* 0x23 user 3GB code at 0x00000000: */
        x86_seg(0xa,3,0,__PAGE_OFFSET-1)
        x86_seg(0xa,3,0,__PAGE_OFFSET-1)
        /* 0x2b user 3GB data at 0x00000000: */
        /* 0x2b user 3GB data at 0x00000000: */
        x86_seg(0x2,3,0,__PAGE_OFFSET-1)
        x86_seg(0x2,3,0,__PAGE_OFFSET-1)
        .quad 0x0000000000000000        /* not used */
        .quad 0x0000000000000000        /* not used */
        .quad 0x0000000000000000        /* not used */
        .quad 0x0000000000000000        /* not used */
        .fill 2*NR_TASKS,8,0            /* space for LDT's and TSS's etc */
        .fill 2*NR_TASKS,8,0            /* space for LDT's and TSS's etc */
#ifdef CONFIG_APM
#ifdef CONFIG_APM
        .quad 0x00c09a0000000000        /* APM CS    code */
        .quad 0x00c09a0000000000        /* APM CS    code */
        .quad 0x00809a0000000000        /* APM CS 16 code (16 bit) */
        .quad 0x00809a0000000000        /* APM CS 16 code (16 bit) */
        .quad 0x00c0920000000000        /* APM DS    data */
        .quad 0x00c0920000000000        /* APM DS    data */
#endif
#endif
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.