diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1994-11-28 11:59:19 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1994-11-28 11:59:19 +0000 |
commit | 1513ff9b7899ab588401c89db0e99903dbf5f886 (patch) | |
tree | f69cc81a940a502ea23d664c3ffb2d215a479667 /arch/i386 |
Import of Linus's Linux 1.1.68
Diffstat (limited to 'arch/i386')
-rw-r--r-- | arch/i386/Makefile | 107 | ||||
-rw-r--r-- | arch/i386/boot/bootsect.S | 460 | ||||
-rw-r--r-- | arch/i386/boot/head.S | 349 | ||||
-rw-r--r-- | arch/i386/boot/setup.S | 1011 | ||||
-rw-r--r-- | arch/i386/config.in | 219 | ||||
-rw-r--r-- | arch/i386/entry.S | 545 |
6 files changed, 2691 insertions, 0 deletions
diff --git a/arch/i386/Makefile b/arch/i386/Makefile new file mode 100644 index 000000000..1b878067a --- /dev/null +++ b/arch/i386/Makefile @@ -0,0 +1,107 @@ +# +# i386/Makefile +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 1994 by Linus Torvalds +# + +AS86 =as86 -0 -a +LD86 =ld86 -0 +AS =as +LD =ld +HOSTCC =gcc -I$(TOPDIR)/include +CC =gcc -D__KERNEL__ -I$(TOPDIR)/include +MAKE =make +CPP =$(CC) -E +AR =ar +STRIP =strip + +ifdef CONFIG_M486 +CFLAGS := $(CFLAGS) -m486 +else +CFLAGS := $(CFLAGS) -m386 +endif + +zBoot/zSystem: zBoot/*.c zBoot/*.S tools/zSystem + $(MAKE) -C zBoot + +zImage: $(CONFIGURE) boot/bootsect boot/setup zBoot/zSystem tools/build + tools/build boot/bootsect boot/setup zBoot/zSystem $(ROOT_DEV) > zImage + sync + +zdisk: zImage + dd bs=8192 if=zImage of=/dev/fd0 + +zlilo: $(CONFIGURE) zImage + if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi + if [ -f $(INSTALL_PATH)/zSystem.map ]; then mv $(INSTALL_PATH)/zSystem.map $(INSTALL_PATH)/zSystem.old; fi + cat zImage > $(INSTALL_PATH)/vmlinuz + cp zSystem.map $(INSTALL_PATH)/ + if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi + +# +# Set these to indicate how to link it.. +# +# -zmagic: +# +#LOWLDFLAGS = -Ttext 0x1000 +#HIGHLDFLAGS = -Ttext 0x100000 +# +# -qmagic (we need to remove the 32 byte header for bootup purposes) +# +LOWLDFLAGS =-qmagic -Ttext 0xfe0 +HIGHLDFLAGS =-qmagic -Ttext 0xfffe0 + +tools/system: boot/head.o init/main.o tools/version.o linuxsubdirs + $(LD) $(LOWLDFLAGS) boot/head.o init/main.o tools/version.o \ + $(ARCHIVES) \ + $(FILESYSTEMS) \ + $(DRIVERS) \ + $(LIBS) \ + -o tools/system + nm tools/zSystem | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | \ + sort > System.map + +boot/setup: boot/setup.o + $(LD86) -s -o $@ $< + +boot/setup.o: boot/setup.s + $(AS86) -o $@ $< + +boot/setup.s: boot/setup.S $(CONFIGURE) include/linux/config.h Makefile + $(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@ + +boot/bootsect: boot/bootsect.o + $(LD86) -s -o $@ $< + +boot/bootsect.o: boot/bootsect.s + $(AS86) -o $@ $< + +boot/bootsect.s: boot/bootsect.S $(CONFIGURE) include/linux/config.h Makefile + $(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@ + +tools/zSystem: boot/head.o init/main.o tools/version.o linuxsubdirs + $(LD) $(HIGHLDFLAGS) boot/head.o init/main.o tools/version.o \ + $(ARCHIVES) \ + $(FILESYSTEMS) \ + $(DRIVERS) \ + $(LIBS) \ + -o tools/zSystem + nm tools/zSystem | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | \ + sort > zSystem.map + +# +# Leave these dummy entries for now to tell people that they are going away.. +# +lilo: + @echo + @echo Uncompressed kernel images no longer supported. Use + @echo \"make zlilo\" instead. + @echo + @exit 1 + +archclean: + rm -f boot/bootsect boot/setup diff --git a/arch/i386/boot/bootsect.S b/arch/i386/boot/bootsect.S new file mode 100644 index 000000000..f6a0d3158 --- /dev/null +++ b/arch/i386/boot/bootsect.S @@ -0,0 +1,460 @@ +! +! SYS_SIZE is the number of clicks (16 bytes) to be loaded. +! 0x7F00 is 0x7F000 bytes = 508kB, more than enough for current +! versions of linux which compress the kernel +! +#include <linux/config.h> +SYSSIZE = DEF_SYSSIZE +! +! bootsect.s Copyright (C) 1991, 1992 Linus Torvalds +! modified by Drew Eckhardt +! modified by Bruce Evans (bde) +! +! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves +! itself out of the way to address 0x90000, and jumps there. +! +! bde - should not jump blindly, there may be systems with only 512K low +! memory. Use int 0x12 to get the top of memory, etc. +! +! It then loads 'setup' directly after itself (0x90200), and the system +! at 0x10000, using BIOS interrupts. +! +! NOTE! currently system is at most (8*65536-4096) bytes long. This should +! be no problem, even in the future. I want to keep it simple. This 508 kB +! kernel size should be enough, especially as this doesn't contain the +! buffer cache as in minix (and especially now that the kernel is +! compressed :-) +! +! The loader has been made as simple as possible, and continuous +! read errors will result in a unbreakable loop. Reboot by hand. It +! loads pretty fast by getting whole tracks at a time whenever possible. + +.text + +SETUPSECS = 4 ! nr of setup-sectors +BOOTSEG = 0x07C0 ! original address of boot-sector +INITSEG = DEF_INITSEG ! we move boot here - out of the way +SETUPSEG = DEF_SETUPSEG ! setup starts here +SYSSEG = DEF_SYSSEG ! system loaded at 0x10000 (65536). + +! ROOT_DEV & SWAP_DEV are now written by "build". +ROOT_DEV = 0 +SWAP_DEV = 0 +#ifndef SVGA_MODE +#define SVGA_MODE ASK_VGA +#endif +#ifndef RAMDISK +#define RAMDISK 0 +#endif +#ifndef CONFIG_ROOT_RDONLY +#define CONFIG_ROOT_RDONLY 0 +#endif + +! ld86 requires an entry symbol. This may as well be the usual one. +.globl _main +_main: +#if 0 /* hook for debugger, harmless unless BIOS is fussy (old HP) */ + int 3 +#endif + mov ax,#BOOTSEG + mov ds,ax + mov ax,#INITSEG + mov es,ax + mov cx,#256 + sub si,si + sub di,di + cld + rep + movsw + jmpi go,INITSEG + +! ax and es already contain INITSEG + +go: mov di,#0x4000-12 ! 0x4000 is arbitrary value >= length of + ! bootsect + length of setup + room for stack + ! 12 is disk parm size + +! bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde). We +! wouldn't have to worry about this if we checked the top of memory. Also +! my BIOS can be configured to put the wini drive tables in high memory +! instead of in the vector table. The old stack might have clobbered the +! drive table. + + mov ds,ax + mov ss,ax ! put stack at INITSEG:0x4000-12. + mov sp,di +/* + * Many BIOS's default disk parameter tables will not + * recognize multi-sector reads beyond the maximum sector number + * specified in the default diskette parameter tables - this may + * mean 7 sectors in some cases. + * + * Since single sector reads are slow and out of the question, + * we must take care of this by creating new parameter tables + * (for the first disk) in RAM. We will set the maximum sector + * count to 36 - the most we will encounter on an ED 2.88. + * + * High doesn't hurt. Low does. + * + * Segments are as follows: ds=es=ss=cs - INITSEG, + * fs = 0, gs is unused. + */ + +! cx contains 0 from rep movsw above + + mov fs,cx + mov bx,#0x78 ! fs:bx is parameter table address + push ds + seg fs + lds si,(bx) ! ds:si is source + + mov cl,#6 ! copy 12 bytes + cld + push di + + rep + movsw + + pop di + pop ds + + movb 4(di),*36 ! patch sector count + + seg fs + mov (bx),di + seg fs + mov 2(bx),es + +! load the setup-sectors directly after the bootblock. +! Note that 'es' is already set up. +! Also cx is 0 from rep movsw above. + +load_setup: + xor ah,ah ! reset FDC + xor dl,dl + int 0x13 + + xor dx, dx ! drive 0, head 0 + mov cl,#0x02 ! sector 2, track 0 + mov bx,#0x0200 ! address = 512, in INITSEG + mov ah,#0x02 ! service 2, nr of sectors + mov al,setup_sects ! (assume all on head 0, track 0) + int 0x13 ! read it + jnc ok_load_setup ! ok - continue + + push ax ! dump error code + call print_nl + mov bp, sp + call print_hex + pop ax + + jmp load_setup + +ok_load_setup: + +! Get disk drive parameters, specifically nr of sectors/track + +#if 0 + +! bde - the Phoenix BIOS manual says function 0x08 only works for fixed +! disks. It doesn't work for one of my BIOS's (1987 Award). It was +! fatal not to check the error code. + + xor dl,dl + mov ah,#0x08 ! AH=8 is get drive parameters + int 0x13 + xor ch,ch +#else + +! It seems that there is no BIOS call to get the number of sectors. Guess +! 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read, +! 15 if sector 15 can be read. Otherwise guess 9. + + mov si,#disksizes ! table of sizes to try + +probe_loop: + lodsb + cbw ! extend to word + mov sectors, ax + cmp si,#disksizes+4 + jae got_sectors ! if all else fails, try 9 + xchg ax, cx ! cx = track and sector + xor dx, dx ! drive 0, head 0 + xor bl, bl + mov bh,setup_sects + inc bh + shl bh,#1 ! address after setup (es = cs) + mov ax,#0x0201 ! service 2, 1 sector + int 0x13 + jc probe_loop ! try next value + +#endif + +got_sectors: + +! Restore es + + mov ax,#INITSEG + mov es,ax + +! Print some inane message + + mov ah,#0x03 ! read cursor pos + xor bh,bh + int 0x10 + + mov cx,#9 + mov bx,#0x0007 ! page 0, attribute 7 (normal) + mov bp,#msg1 + mov ax,#0x1301 ! write string, move cursor + int 0x10 + +! ok, we've written the message, now +! we want to load the system (at 0x10000) + + mov ax,#SYSSEG + mov es,ax ! segment of 0x010000 + call read_it + call kill_motor + call print_nl + +! After that we check which root-device to use. If the device is +! defined (!= 0), nothing is done and the given device is used. +! Otherwise, one of /dev/fd0H2880 (2,32) or /dev/PS0 (2,28) or /dev/at0 (2,8), +! depending on the number of sectors we pretend to know we have. + + seg cs + mov ax,root_dev + or ax,ax + jne root_defined + seg cs + mov bx,sectors + mov ax,#0x0208 ! /dev/ps0 - 1.2Mb + cmp bx,#15 + je root_defined + mov al,#0x1c ! /dev/PS0 - 1.44Mb + cmp bx,#18 + je root_defined + mov al,#0x20 ! /dev/fd0H2880 - 2.88Mb + cmp bx,#36 + je root_defined + mov al,#0 ! /dev/fd0 - autodetect +root_defined: + seg cs + mov root_dev,ax + +! after that (everything loaded), we jump to +! the setup-routine loaded directly after +! the bootblock: + + jmpi 0,SETUPSEG + +! This routine loads the system at address 0x10000, making sure +! no 64kB boundaries are crossed. We try to load it as fast as +! possible, loading whole tracks whenever we can. +! +! in: es - starting address segment (normally 0x1000) +! +sread: .word 0 ! sectors read of current track +head: .word 0 ! current head +track: .word 0 ! current track + +read_it: + mov al,setup_sects + inc al + mov sread,al + mov ax,es + test ax,#0x0fff +die: jne die ! es must be at 64kB boundary + xor bx,bx ! bx is starting address within segment +rp_read: + mov ax,es + sub ax,#SYSSEG + cmp ax,syssize ! have we loaded all yet? + jbe ok1_read + ret +ok1_read: + mov ax,sectors + sub ax,sread + mov cx,ax + shl cx,#9 + add cx,bx + jnc ok2_read + je ok2_read + xor ax,ax + sub ax,bx + shr ax,#9 +ok2_read: + call read_track + mov cx,ax + add ax,sread + cmp ax,sectors + jne ok3_read + mov ax,#1 + sub ax,head + jne ok4_read + inc track +ok4_read: + mov head,ax + xor ax,ax +ok3_read: + mov sread,ax + shl cx,#9 + add bx,cx + jnc rp_read + mov ax,es + add ah,#0x10 + mov es,ax + xor bx,bx + jmp rp_read + +read_track: + pusha + pusha + mov ax, #0xe2e ! loading... message 2e = . + mov bx, #7 + int 0x10 + popa + + mov dx,track + mov cx,sread + inc cx + mov ch,dl + mov dx,head + mov dh,dl + and dx,#0x0100 + mov ah,#2 + + push dx ! save for error dump + push cx + push bx + push ax + + int 0x13 + jc bad_rt + add sp, #8 + popa + ret + +bad_rt: push ax ! save error code + call print_all ! ah = error, al = read + + + xor ah,ah + xor dl,dl + int 0x13 + + + add sp, #10 + popa + jmp read_track + +/* + * print_all is for debugging purposes. + * It will print out all of the registers. The assumption is that this is + * called from a routine, with a stack frame like + * dx + * cx + * bx + * ax + * error + * ret <- sp + * +*/ + +print_all: + mov cx, #5 ! error code + 4 registers + mov bp, sp + +print_loop: + push cx ! save count left + call print_nl ! nl for readability + + cmp cl, #5 + jae no_reg ! see if register name is needed + + mov ax, #0xe05 + 'A - 1 + sub al, cl + int 0x10 + + mov al, #'X + int 0x10 + + mov al, #': + int 0x10 + +no_reg: + add bp, #2 ! next register + call print_hex ! print it + pop cx + loop print_loop + ret + +print_nl: + mov ax, #0xe0d ! CR + int 0x10 + mov al, #0xa ! LF + int 0x10 + ret + +/* + * print_hex is for debugging purposes, and prints the word + * pointed to by ss:bp in hexadecimal. +*/ + +print_hex: + mov cx, #4 ! 4 hex digits + mov dx, (bp) ! load word into dx +print_digit: + rol dx, #4 ! rotate so that lowest 4 bits are used + mov ax, #0xe0f ! ah = request, al = mask for nybble + and al, dl + add al, #0x90 ! convert al to ascii hex (four instructions) + daa + adc al, #0x40 + daa + int 0x10 + loop print_digit + ret + + +/* + * This procedure turns off the floppy drive motor, so + * that we enter the kernel in a known state, and + * don't have to worry about it later. + */ +kill_motor: + push dx + mov dx,#0x3f2 + xor al, al + outb + pop dx + ret + +sectors: + .word 0 + +disksizes: + .byte 36,18,15,9 + +msg1: + .byte 13,10 + .ascii "Loading" + +.org 497 +setup_sects: + .byte SETUPSECS +root_flags: + .word CONFIG_ROOT_RDONLY +syssize: + .word SYSSIZE +swap_dev: + .word SWAP_DEV +ram_size: + .word RAMDISK +vid_mode: + .word SVGA_MODE +root_dev: + .word ROOT_DEV +boot_flag: + .word 0xAA55 diff --git a/arch/i386/boot/head.S b/arch/i386/boot/head.S new file mode 100644 index 000000000..896c62f18 --- /dev/null +++ b/arch/i386/boot/head.S @@ -0,0 +1,349 @@ +/* + * linux/boot/head.S + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* + * head.S contains the 32-bit startup code. + */ + +.text +.globl _idt,_gdt, +.globl _swapper_pg_dir,_pg0 +.globl _empty_bad_page +.globl _empty_bad_page_table +.globl _empty_zero_page +.globl _floppy_track_buffer + +#define __ASSEMBLY__ +#include <linux/tasks.h> +#include <linux/fd.h> +#include <asm/segment.h> + +#define CL_MAGIC_ADDR 0x90020 +#define CL_MAGIC 0xA33F +#define CL_BASE_ADDR 0x90000 +#define CL_OFFSET 0x90022 + +/* + * swapper_pg_dir is the main page directory, address 0x00001000 (or at + * address 0x00101000 for a compressed boot). + */ +startup_32: + cld + movl $(KERNEL_DS),%eax + mov %ax,%ds + mov %ax,%es + mov %ax,%fs + mov %ax,%gs + lss _stack_start,%esp +/* + * Clear BSS first so that there are no surprises... + */ + xorl %eax,%eax + movl $__edata,%edi + movl $__end,%ecx + subl %edi,%ecx + cld + rep + stosb +/* + * start system 32-bit setup. We need to re-do some of the things done + * in 16-bit mode for the "real" operations. + */ + call setup_idt + xorl %eax,%eax +1: incl %eax # check that A20 really IS enabled + movl %eax,0x000000 # loop forever if it isn't + cmpl %eax,0x100000 + je 1b +/* + * Initialize eflags. Some BIOS's leave bits like NT set. This would + * confuse the debugger if this code is traced. + * XXX - best to initialize before switching to protected mode. + */ + pushl $0 + popfl +/* + * Copy bootup parameters out of the way. First 2kB of + * _empty_zero_page is for boot parameters, second 2kB + * is for the command line. + */ + movl $0x90000,%esi + movl $_empty_zero_page,%edi + movl $512,%ecx + cld + rep + movsl + xorl %eax,%eax + movl $512,%ecx + rep + stosl + cmpw $(CL_MAGIC),CL_MAGIC_ADDR + jne 1f + movl $_empty_zero_page+2048,%edi + movzwl CL_OFFSET,%esi + addl $(CL_BASE_ADDR),%esi + movl $2048,%ecx + rep + movsb +1: +/* check if it is 486 or 386. */ +/* + * 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 + * we don't need to preserve eflags. + */ + movl %esp,%edi # save stack pointer + andl $0xfffffffc,%esp # align stack to avoid AC fault + movl $3,_x86 + pushfl # push EFLAGS + popl %eax # get EFLAGS + movl %eax,%ecx # save original EFLAGS + xorl $0x40000,%eax # flip AC bit in EFLAGS + pushl %eax # copy to EFLAGS + popfl # set EFLAGS + pushfl # get new EFLAGS + popl %eax # put it in eax + xorl %ecx,%eax # change in flags + andl $0x40000,%eax # check if AC bit changed + je is386 + movl $4,_x86 + movl %ecx,%eax + xorl $0x200000,%eax # check ID flag + pushl %eax + popfl # if we are on a straight 486DX, SX, or + pushfl # 487SX we can't change it + popl %eax + xorl %ecx,%eax + andl $0x200000,%eax + je is486 +isnew: pushl %ecx # restore original EFLAGS + popfl + movl $1, %eax # Use the CPUID instruction to + .byte 0x0f, 0xa2 # check the processor type + andl $0xf00, %eax # Set _x86 with the family + shrl $8, %eax # returned. + movl %eax, _x86 + movl %edi,%esp # restore esp + movl %cr0,%eax # 486+ + andl $0x80000011,%eax # Save PG,PE,ET + orl $0x50022,%eax # set AM, WP, NE and MP + jmp 2f +is486: pushl %ecx # restore original EFLAGS + popfl + movl %edi,%esp # restore esp + movl %cr0,%eax # 486 + andl $0x80000011,%eax # Save PG,PE,ET + orl $0x50022,%eax # set AM, WP, NE and MP + jmp 2f +is386: pushl %ecx # restore original EFLAGS + popfl + movl %edi,%esp # restore esp + movl %cr0,%eax # 386 + andl $0x80000011,%eax # Save PG,PE,ET + orl $2,%eax # set MP +2: movl %eax,%cr0 + call check_x87 + call setup_paging + lgdt gdt_descr + lidt idt_descr + ljmp $(KERNEL_CS),$1f +1: movl $(KERNEL_DS),%eax # reload all the segment registers + mov %ax,%ds # after changing gdt. + mov %ax,%es + mov %ax,%fs + mov %ax,%gs + lss _stack_start,%esp + xorl %eax,%eax + lldt %ax + pushl %eax # These are the parameters to main :-) + pushl %eax + pushl %eax + cld # gcc2 wants the direction flag cleared at all times + call _start_kernel +L6: + jmp L6 # main should never return here, but + # just in case, we know what happens. + +/* + * We depend on ET to be correct. This checks for 287/387. + */ +check_x87: + movl $0,_hard_math + clts + fninit + fstsw %ax + cmpb $0,%al + je 1f + movl %cr0,%eax /* no coprocessor: have to set bits */ + xorl $4,%eax /* set EM */ + movl %eax,%cr0 + ret +.align 2 +1: movl $1,_hard_math + .byte 0xDB,0xE4 /* fsetpm for 287, ignored by 387 */ + ret + +/* + * setup_idt + * + * sets up a idt with 256 entries pointing to + * ignore_int, interrupt gates. It doesn't actually load + * idt - that can be done only after paging has been enabled + * and the kernel moved to 0xC0000000. Interrupts + * are enabled elsewhere, when we can be relatively + * sure everything is ok. + */ +setup_idt: + lea ignore_int,%edx + movl $(KERNEL_CS << 16),%eax + movw %dx,%ax /* selector = 0x0010 = cs */ + movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ + + lea _idt,%edi + mov $256,%ecx +rp_sidt: + movl %eax,(%edi) + movl %edx,4(%edi) + addl $8,%edi + dec %ecx + jne rp_sidt + ret + + +/* + * Setup_paging + * + * This routine sets up paging by setting the page bit + * in cr0. The page tables are set up, identity-mapping + * the first 4MB. The rest are initialized later. + * + * (ref: added support for up to 32mb, 17Apr92) -- Rik Faith + * (ref: update, 25Sept92) -- croutons@crunchy.uucp + * (ref: 92.10.11 - Linus Torvalds. Corrected 16M limit - no upper memory limit) + */ +.align 2 +setup_paging: + movl $1024*2,%ecx /* 2 pages - swapper_pg_dir+1 page table */ + xorl %eax,%eax + movl $_swapper_pg_dir,%edi /* swapper_pg_dir is at 0x1000 */ + cld;rep;stosl +/* Identity-map the kernel in low 4MB memory for ease of transition */ + movl $_pg0+7,_swapper_pg_dir /* set present bit/user r/w */ +/* But the real place is at 0xC0000000 */ + movl $_pg0+7,_swapper_pg_dir+3072 /* set present bit/user r/w */ + movl $_pg0+4092,%edi + movl $0x03ff007,%eax /* 4Mb - 4096 + 7 (r/w user,p) */ + std +1: stosl /* fill the page backwards - more efficient :-) */ + subl $0x1000,%eax + jge 1b + cld + movl $_swapper_pg_dir,%eax + movl %eax,%cr3 /* cr3 - page directory start */ + movl %cr0,%eax + orl $0x80000000,%eax + movl %eax,%cr0 /* set paging (PG) bit */ + ret /* this also flushes the prefetch-queue */ + +/* + * page 0 is made non-existent, so that kernel NULL pointer references get + * caught. Thus the swapper page directory has been moved to 0x1000 + * + * XXX Actually, the swapper page directory is at 0x1000 plus 1 megabyte, + * with the introduction of the compressed boot code. Theoretically, + * the original design of overlaying the startup code with the swapper + * 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..... + */ +.org 0x1000 +_swapper_pg_dir: +/* + * The page tables are initialized to only 4MB here - the final page + * tables are set up later depending on memory size. + */ +.org 0x2000 +_pg0: + +.org 0x3000 +_empty_bad_page: + +.org 0x4000 +_empty_bad_page_table: + +.org 0x5000 +_empty_zero_page: + +.org 0x6000 +/* + * floppy_track_buffer is used to buffer one track of floppy data: it + * has to be separate from the tmp_floppy area, as otherwise a single- + * sector read/write can mess it up. It can contain one full cylinder (sic) of + * data (36*2*512 bytes). + */ +_floppy_track_buffer: + .fill 512*2*MAX_BUFFER_SECTORS,1,0 + +/* This is the default interrupt "handler" :-) */ +int_msg: + .asciz "Unknown interrupt\n" +.align 2 +ignore_int: + cld + pushl %eax + pushl %ecx + pushl %edx + push %ds + push %es + push %fs + movl $(KERNEL_DS),%eax + mov %ax,%ds + mov %ax,%es + mov %ax,%fs + pushl $int_msg + call _printk + popl %eax + pop %fs + pop %es + pop %ds + popl %edx + popl %ecx + popl %eax + iret + +/* + * The interrupt descriptor table has room for 256 idt's + */ +.align 4 +.word 0 +idt_descr: + .word 256*8-1 # idt contains 256 entries + .long 0xc0000000+_idt + +.align 4 +_idt: + .fill 256,8,0 # idt is uninitialized + +.align 4 +.word 0 +gdt_descr: + .word (8+2*NR_TASKS)*8-1 + .long 0xc0000000+_gdt + +/* + * This gdt setup gives the kernel a 1GB address space at virtual + * address 0xC0000000 - space enough for expansion, I hope. + */ +.align 4 +_gdt: + .quad 0x0000000000000000 /* NULL descriptor */ + .quad 0x0000000000000000 /* not used */ + .quad 0xc0c39a000000ffff /* 0x10 kernel 1GB code at 0xC0000000 */ + .quad 0xc0c392000000ffff /* 0x18 kernel 1GB data at 0xC0000000 */ + .quad 0x00cbfa000000ffff /* 0x23 user 3GB code at 0x00000000 */ + .quad 0x00cbf2000000ffff /* 0x2b user 3GB data at 0x00000000 */ + .quad 0x0000000000000000 /* not used */ + .quad 0x0000000000000000 /* not used */ + .fill 2*NR_TASKS,8,0 /* space for LDT's and TSS's etc */ diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S new file mode 100644 index 000000000..d4f56ef2a --- /dev/null +++ b/arch/i386/boot/setup.S @@ -0,0 +1,1011 @@ +! +! setup.S Copyright (C) 1991, 1992 Linus Torvalds +! +! setup.s is responsible for getting the system data from the BIOS, +! and putting them into the appropriate places in system memory. +! both setup.s and system has been loaded by the bootblock. +! +! This code asks the bios for memory/disk/other parameters, and +! puts them in a "safe" place: 0x90000-0x901FF, ie where the +! boot-block used to be. It is then up to the protected mode +! system to read them from there before the area is overwritten +! for buffer-blocks. +! +! Move PS/2 aux init code to psaux.c +! (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92 +! +! some changes and additional features by Christoph Niemann, +! March 1993/June 1994 (Christoph.Niemann@linux.org) +! + +! NOTE! These had better be the same as in bootsect.s! +#define __ASSEMBLY__ +#include <linux/config.h> +#include <asm/segment.h> + +#ifndef SVGA_MODE +#define SVGA_MODE ASK_VGA +#endif + +! Signature words to ensure LILO loaded us right +#define SIG1 0xAA55 +#define SIG2 0x5A5A + +INITSEG = DEF_INITSEG ! we move boot here - out of the way +SYSSEG = DEF_SYSSEG ! system loaded at 0x10000 (65536). +SETUPSEG = DEF_SETUPSEG ! this is the current segment + +.globl begtext, begdata, begbss, endtext, enddata, endbss +.text +begtext: +.data +begdata: +.bss +begbss: +.text + +entry start +start: +! Bootlin depends on this being done early + mov ax,#0x01500 + mov dl,#0x81 + int 0x13 + +! Check signature at end of setup + mov ax,#SETUPSEG + mov ds,ax + cmp setup_sig1,#SIG1 + jne bad_sig + cmp setup_sig2,#SIG2 + jne bad_sig + jmp good_sig1 + +! Routine to print asciiz-string at DS:SI + +prtstr: lodsb + and al,al + jz fin + call prnt1 + jmp prtstr +fin: ret + +! Part of above routine, this one just prints ascii al + +prnt1: push ax + push cx + xor bh,bh + mov cx,#0x01 + mov ah,#0x0e + int 0x10 + pop cx + pop ax + ret + +beep: mov al,#0x07 + jmp prnt1 + +no_sig_mess: .ascii "No setup signature found ..." + db 0x00 +start_sys_seg: .word SYSSEG + +good_sig1: + jmp good_sig + +! We now have to find the rest of the setup code/data +bad_sig: + mov ax,#INITSEG + mov ds,ax + xor bh,bh + mov bl,[497] ! get setup sects from boot sector + sub bx,#4 ! LILO loads 4 sectors of setup + shl bx,#8 ! convert to words + mov cx,bx + shr bx,#3 ! convert to segment + add bx,#SYSSEG + seg cs + mov start_sys_seg,bx + +! Move rest of setup code/data to here + mov di,#2048 ! four sectors loaded by LILO + sub si,si + mov ax,#SETUPSEG + mov es,ax + mov ax,#SYSSEG + mov ds,ax + rep + movsw + + mov ax,#SETUPSEG + mov ds,ax + cmp setup_sig1,#SIG1 + jne no_sig + cmp setup_sig2,#SIG2 + jne no_sig + jmp good_sig + +no_sig: + lea si,no_sig_mess + call prtstr +no_sig_loop: + jmp no_sig_loop + +good_sig: + mov ax,#INITSEG + mov ds,ax + +! Get memory size (extended mem, kB) + + mov ah,#0x88 + int 0x15 + mov [2],ax + +! set the keyboard repeat rate to the max + + mov ax,#0x0305 + xor bx,bx ! clear bx + int 0x16 + +! check for EGA/VGA and some config parameters + + mov ah,#0x12 + mov bl,#0x10 + int 0x10 + mov [8],ax + mov [10],bx + mov [12],cx + mov ax,#0x5019 + cmp bl,#0x10 + je novga + mov ax,#0x1a00 ! Added check for EGA/VGA discrimination + int 0x10 + mov bx,ax + mov ax,#0x5019 + cmp bl,#0x1a ! 1a means VGA, anything else EGA or lower + jne novga + call chsvga +novga: mov [14],ax + mov ah,#0x03 ! read cursor pos + xor bh,bh ! clear bh + int 0x10 ! save it in known place, con_init fetches + mov [0],dx ! it from 0x90000. + +! Get video-card data: + + mov ah,#0x0f + int 0x10 + mov [4],bx ! bh = display page + mov [6],ax ! al = video mode, ah = window width + +! Get hd0 data + + xor ax,ax ! clear ax + mov ds,ax + lds si,[4*0x41] + mov ax,#INITSEG + push ax + mov es,ax + mov di,#0x0080 + mov cx,#0x10 + push cx + cld + rep + movsb + +! Get hd1 data + + xor ax,ax ! clear ax + mov ds,ax + lds si,[4*0x46] + pop cx + pop es + mov di,#0x0090 + rep + movsb + +! Check that there IS a hd1 :-) + + mov ax,#0x01500 + mov dl,#0x81 + int 0x13 + jc no_disk1 + cmp ah,#3 + je is_disk1 +no_disk1: + mov ax,#INITSEG + mov es,ax + mov di,#0x0090 + mov cx,#0x10 + xor ax,ax ! clear ax + cld + rep + stosb +is_disk1: + +! check for PS/2 pointing device + + mov ax,#INITSEG + mov ds,ax + mov [0x1ff],#0 ! default is no pointing device + int 0x11 ! int 0x11: equipment determination + test al,#0x04 ! check if pointing device installed + jz no_psmouse + mov [0x1ff],#0xaa ! device present +no_psmouse: +! now we want to move to protected mode ... + + cli ! no interrupts allowed ! + mov al,#0x80 ! disable NMI for the bootup sequence + out #0x70,al + +! first we move the system to its rightful place + + mov ax,#0x100 ! start of destination segment + seg cs + mov bx,start_sys_seg ! start of source segment + cld ! 'direction'=0, movs moves forward +do_move: + mov es,ax ! destination segment + inc ah ! instead of add ax,#0x100 + cmp ax,#0x9000 + jz end_move + mov ds,bx ! source segment + add bx,#0x100 + sub di,di + sub si,si + mov cx,#0x800 + rep + movsw + jmp do_move + +! then we load the segment descriptors + +end_move: + mov ax,#SETUPSEG ! right, forgot this at first. didn't work :-) + mov ds,ax + lidt idt_48 ! load idt with 0,0 + lgdt gdt_48 ! load gdt with whatever appropriate + +! that was painless, now we enable A20 + + call empty_8042 + mov al,#0xD1 ! command write + out #0x64,al + call empty_8042 + mov al,#0xDF ! A20 on + out #0x60,al + call empty_8042 + +! make sure any possible coprocessor is properly reset.. + + xor ax,ax + out #0xf0,al + call delay + out #0xf1,al + call delay + +! well, that went ok, I hope. Now we have to reprogram the interrupts :-( +! we put them right after the intel-reserved hardware interrupts, at +! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really +! messed this up with the original PC, and they haven't been able to +! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f, +! which is used for the internal hardware interrupts as well. We just +! have to reprogram the 8259's, and it isn't fun. + + mov al,#0x11 ! initialization sequence + out #0x20,al ! send it to 8259A-1 + call delay + out #0xA0,al ! and to 8259A-2 + call delay + mov al,#0x20 ! start of hardware int's (0x20) + out #0x21,al + call delay + mov al,#0x28 ! start of hardware int's 2 (0x28) + out #0xA1,al + call delay + mov al,#0x04 ! 8259-1 is master + out #0x21,al + call delay + mov al,#0x02 ! 8259-2 is slave + out #0xA1,al + call delay + mov al,#0x01 ! 8086 mode for both + out #0x21,al + call delay + out #0xA1,al + call delay + mov al,#0xFF ! mask off all interrupts for now + out #0xA1,al + call delay + mov al,#0xFB ! mask all irq's but irq2 which + out #0x21,al ! is cascaded + +! well, that certainly wasn't fun :-(. Hopefully it works, and we don't +! need no steenking BIOS anyway (except for the initial loading :-). +! The BIOS-routine wants lots of unnecessary data, and it's less +! "interesting" anyway. This is how REAL programmers do it. +! +! Well, now's the time to actually move into protected mode. To make +! things as simple as possible, we do no register set-up or anything, +! we let the gnu-compiled 32-bit programs do that. We just jump to +! absolute address 0x00000, in 32-bit protected mode. +! +! Note that the short jump isn't strictly needed, although there are +! reasons why it might be a good idea. It won't hurt in any case. +! + xor ax,ax + inc ax ! protected mode (PE) bit + lmsw ax ! This is it! + jmp flush_instr +flush_instr: + jmpi 0x1000,KERNEL_CS ! jmp offset 1000 of segment 0x10 (cs) + +! This routine checks that the keyboard command queue is empty +! (after emptying the output buffers) +! +! No timeout is used - if this hangs there is something wrong with +! the machine, and we probably couldn't proceed anyway. +empty_8042: + call delay + in al,#0x64 ! 8042 status port + test al,#1 ! output buffer? + jz no_output + call delay + in al,#0x60 ! read it + jmp empty_8042 +no_output: + test al,#2 ! is input buffer full? + jnz empty_8042 ! yes - loop + ret +! +! Read a key and return the (US-)ascii code in al, scan code in ah +! +getkey: + xor ah,ah + int 0x16 + ret + +! +! Read a key with a timeout of 30 seconds. The cmos clock is used to get +! the time. +! +getkt: + call gettime + add al,#30 ! wait 30 seconds + cmp al,#60 + jl lminute + sub al,#60 +lminute: + mov cl,al +again: mov ah,#0x01 + int 0x16 + jnz getkey ! key pressed, so get it + call gettime + cmp al,cl + jne again + mov al,#0x20 ! timeout, return default char `space' + ret + +! +! Flush the keyboard buffer +! +flush: mov ah,#0x01 + int 0x16 + jz empty + xor ah,ah + int 0x16 + jmp flush +empty: ret + +! +! Read the cmos clock. Return the seconds in al +! +gettime: + push cx + mov ah,#0x02 + int 0x1a + mov al,dh ! dh contains the seconds + and al,#0x0f + mov ah,dh + mov cl,#0x04 + shr ah,cl + aad + pop cx + ret + +! +! Delay is needed after doing i/o +! +delay: + .word 0x00eb ! jmp $+2 + ret + +! Routine trying to recognize type of SVGA-board present (if any) +! and if it recognize one gives the choices of resolution it offers. +! If one is found the resolution chosen is given by al,ah (rows,cols). + +chsvga: cld + push ds + push cs + mov ax,[0x01fa] + pop ds + mov modesave,ax + mov ax,#0xc000 + mov es,ax + mov ax,modesave + cmp ax,#NORMAL_VGA + je defvga + cmp ax,#EXTENDED_VGA + je vga50 + cmp ax,#ASK_VGA + jne svga + lea si,msg1 + call prtstr + call flush +nokey: call getkt + cmp al,#0x0d ! enter ? + je svga ! yes - svga selection + cmp al,#0x20 ! space ? + je defvga ! no - repeat + call beep + jmp nokey +defvga: mov ax,#0x5019 + pop ds + ret +/* extended vga mode: 80x50 */ +vga50: + mov ax,#0x1112 + xor bl,bl + int 0x10 ! use 8x8 font set (50 lines on VGA) + mov ax,#0x1200 + mov bl,#0x20 + int 0x10 ! use alternate print screen + mov ax,#0x1201 + mov bl,#0x34 + int 0x10 ! turn off cursor emulation + mov ah,#0x01 + mov cx,#0x0607 + int 0x10 ! turn on cursor (scan lines 6 to 7) + pop ds + mov ax,#0x5032 ! return 80x50 + ret +/* extended vga mode: 80x28 */ +vga28: + pop ax ! clean the stack + mov ax,#0x1111 + xor bl,bl + int 0x10 ! use 9x14 fontset (28 lines on VGA) + mov ah, #0x01 + mov cx,#0x0b0c + int 0x10 ! turn on cursor (scan lines 11 to 12) + pop ds + mov ax,#0x501c ! return 80x28 + ret +/* svga modes */ +! +! test for presence of an S3 VGA chip. The algorithm was taken +! from the SuperProbe package of XFree86 1.2.1 +! report bugs to Christoph.Niemann@linux.org +! +svga: cld + mov cx,#0x0f35 ! we store some constants in cl/ch + mov dx,#0x03d4 + movb al,#0x38 + call inidx + mov bh,al ! store current value of CRT-register 0x38 + mov ax,#0x0038 + call outidx ! disable writing to special regs + movb al,cl ! check whether we can write special reg 0x35 + call inidx + movb bl,al ! save the current value of CRT reg 0x35 + andb al,#0xf0 ! clear bits 0-3 + movb ah,al + movb al,cl ! and write it to CRT reg 0x35 + call outidx + call inidx ! now read it back + andb al,ch ! clear the upper 4 bits + jz s3_2 ! the first test failed. But we have a + movb ah,bl ! second chance + mov al,cl + call outidx + jmp s3_1 ! do the other tests +s3_2: mov ax,cx ! load ah with 0xf and al with 0x35 + orb ah,bl ! set the upper 4 bits of ah with the orig value + call outidx ! write ... + call inidx ! ... and reread + andb al,cl ! turn off the upper 4 bits + push ax + movb ah,bl ! restore old value in register 0x35 + movb al,cl + call outidx + pop ax + cmp al,ch ! setting lower 4 bits was successful => bad + je no_s3 ! writing is allowed => this is not an S3 +s3_1: mov ax,#0x4838 ! allow writing to special regs by putting + call outidx ! magic number into CRT-register 0x38 + movb al,cl ! check whether we can write special reg 0x35 + call inidx + movb bl,al + andb al,#0xf0 + movb ah,al + movb al,cl + call outidx + call inidx + andb al,ch + jnz no_s3 ! no, we can't write => no S3 + mov ax,cx + orb ah,bl + call outidx + call inidx + andb al,ch + push ax + movb ah,bl ! restore old value in register 0x35 + movb al,cl + call outidx + pop ax + cmp al,ch + jne no_s31 ! writing not possible => no S3 + movb al,#0x30 + call inidx ! now get the S3 id ... + lea di,idS3 + mov cx,#0x10 + repne + scasb + je no_s31 + lea si,dsc_S3 ! table of descriptions of video modes for BIOS + lea di,mo_S3 ! table of sizes of video modes for my BIOS + movb ah,bh + movb al,#0x38 + call outidx ! restore old value of CRT register 0x38 + br selmod ! go ask for video mode +no_s3: movb al,#0x35 ! restore CRT register 0x35 + movb ah,bl + call outidx +no_s31: movb ah,bh + movb al,#0x38 + call outidx ! restore old value of CRT register 0x38 + + lea si,idati ! Check ATI 'clues' + mov di,#0x31 + mov cx,#0x09 + repe + cmpsb + jne noati + lea si,dscati + lea di,moati + br selmod +noati: mov ax,#0x200f ! Check Ahead 'clues' + mov dx,#0x3ce + out dx,ax + inc dx + in al,dx + cmp al,#0x20 + je isahed + cmp al,#0x21 + jne noahed +isahed: lea si,dscahead + lea di,moahead + br selmod +noahed: mov dx,#0x3c3 ! Check Chips & Tech. 'clues' + in al,dx + or al,#0x10 + out dx,al + mov dx,#0x104 + in al,dx + mov bl,al + mov dx,#0x3c3 + in al,dx + and al,#0xef + out dx,al + cmp bl,[idcandt] + jne nocant + lea si,dsccandt + lea di,mocandt + br selmod +nocant: mov dx,#0x3d4 ! Check Cirrus 'clues' + mov al,#0x0c + out dx,al + inc dx + in al,dx + mov bl,al + xor al,al + out dx,al + dec dx + mov al,#0x1f + out dx,al + inc dx + in al,dx + mov bh,al + xor ah,ah + shl al,#4 + mov cx,ax + mov al,bh + shr al,#4 + add cx,ax + shl cx,#8 + add cx,#6 + mov ax,cx + mov dx,#0x3c4 + out dx,ax + inc dx + in al,dx + and al,al + jnz nocirr + mov al,bh + out dx,al + in al,dx + cmp al,#0x01 + jne nocirr + call rst3d4 + lea si,dsccirrus + lea di,mocirrus + br selmod +rst3d4: mov dx,#0x3d4 + mov al,bl + xor ah,ah + shl ax,#8 + add ax,#0x0c + out dx,ax + ret +nocirr: call rst3d4 ! Check Everex 'clues' + mov ax,#0x7000 + xor bx,bx + int 0x10 + cmp al,#0x70 + jne noevrx + shr dx,#4 + cmp dx,#0x678 + je istrid + cmp dx,#0x236 + je istrid + lea si,dsceverex + lea di,moeverex + br selmod +istrid: lea cx,ev2tri + jmp cx +noevrx: lea si,idgenoa ! Check Genoa 'clues' + xor ax,ax + seg es + mov al,[0x37] + mov di,ax + mov cx,#0x04 + dec si + dec di +l1: inc si + inc di + mov al,(si) + test al,al + jz l2 + seg es + cmp al,(di) +l2: loope l1 + cmp cx,#0x00 + jne nogen + lea si,dscgenoa + lea di,mogenoa + br selmod +nogen: cld + lea si,idoakvga + mov di,#0x08 + mov cx,#0x08 + repe + cmpsb + jne nooak + lea si,dscoakvga + lea di,mooakvga + br selmod +nooak: cld + lea si,idparadise ! Check Paradise 'clues' + mov di,#0x7d + mov cx,#0x04 + repe + cmpsb + jne nopara + lea si,dscparadise + lea di,moparadise + br selmod +nopara: mov dx,#0x3c4 ! Check Trident 'clues' + mov al,#0x0e + out dx,al + inc dx + in al,dx + xchg ah,al + xor al,al + out dx,al + in al,dx + xchg al,ah + mov bl,al ! Strange thing ... in the book this wasn't + and bl,#0x02 ! necessary but it worked on my card which + jz setb2 ! is a trident. Without it the screen goes + and al,#0xfd ! blurred ... + jmp clrb2 ! +setb2: or al,#0x02 ! +clrb2: out dx,al + and ah,#0x0f + cmp ah,#0x02 + jne notrid +ev2tri: lea si,dsctrident + lea di,motrident + jmp selmod +notrid: mov dx,#0x3cd ! Check Tseng 'clues' + in al,dx ! Could things be this simple ! :-) + mov bl,al + mov al,#0x55 + out dx,al + in al,dx + mov ah,al + mov al,bl + out dx,al + cmp ah,#0x55 + jne notsen + lea si,dsctseng + lea di,motseng + jmp selmod +notsen: mov dx,#0x3cc ! Check Video7 'clues' + in al,dx + mov dx,#0x3b4 + and al,#0x01 + jz even7 + mov dx,#0x3d4 +even7: mov al,#0x0c + out dx,al + inc dx + in al,dx + mov bl,al + mov al,#0x55 + out dx,al + in al,dx + dec dx + mov al,#0x1f + out dx,al + inc dx + in al,dx + mov bh,al + dec dx + mov al,#0x0c + out dx,al + inc dx + mov al,bl + out dx,al + mov al,#0x55 + xor al,#0xea + cmp al,bh + jne novid7 + lea si,dscvideo7 + lea di,movideo7 + jmp selmod +novid7: lea si,dsunknown + lea di,mounknown +selmod: xor cx,cx + mov cl,(di) + mov ax,modesave + cmp ax,#ASK_VGA + je askmod + cmp ax,#NORMAL_VGA + je askmod + cmp al,cl + jl gotmode + push si + lea si,msg4 + call prtstr + pop si +askmod: push si + lea si,msg2 + call prtstr + pop si + push si + push cx +tbl: pop bx + push bx + mov al,bl + sub al,cl + call modepr + lodsw + xchg al,ah + call dprnt + xchg ah,al + push ax + mov al,#0x78 + call prnt1 + pop ax + call dprnt + push si + lea si,crlf ! print CR+LF + call prtstr + pop si + loop tbl + pop cx + lea si,msg3 + call prtstr + pop si + add cl,#0x30 + jmp nonum +nonumb: call beep +nonum: call getkey + cmp al,#0x30 ! ascii `0' + jb nonumb + cmp al,#0x3a ! ascii `9' + jbe number + cmp al,#0x61 ! ascii `a' + jb nonumb + cmp al,#0x7a ! ascii `z' + ja nonumb + sub al,#0x27 + cmp al,cl + jae nonumb + sub al,#0x30 + jmp gotmode +number: cmp al,cl + jae nonumb + sub al,#0x30 +gotmode: xor ah,ah + or al,al + beq vga50 + push ax + dec ax + beq vga28 + add di,ax + mov al,(di) + int 0x10 + pop ax + shl ax,#1 + add si,ax + lodsw + pop ds + ret + +! Routine to write al into a VGA-register that is +! accessed via an index register +! +! dx contains the address of the index register +! al contains the index +! ah contains the value to write to the data register (dx + 1) +! +! no registers are changed + +outidx: out dx,al + push ax + mov al,ah + inc dx + out dx,al + dec dx + pop ax + ret +inidx: out dx,al + inc dx + in al,dx + dec dx + ret + +! Routine to print a decimal value on screen, the value to be +! printed is put in al (i.e 0-255). + +dprnt: push ax + push cx + xor ah,ah ! Clear ah + mov cl,#0x0a + idiv cl + cmp al,#0x09 + jbe lt100 + call dprnt + jmp skip10 +lt100: add al,#0x30 + call prnt1 +skip10: mov al,ah + add al,#0x30 + call prnt1 + pop cx + pop ax + ret + +! +! Routine to print the mode number key on screen. Mode numbers +! 0-9 print the ascii values `0' to '9', 10-35 are represented by +! the letters `a' to `z'. This routine prints some spaces around the +! mode no. +! + +modepr: push ax + cmp al,#0x0a + jb digit ! Here is no check for number > 35 + add al,#0x27 +digit: add al,#0x30 + mov modenr, al + push si + lea si, modestring + call prtstr + pop si + pop ax + ret + +gdt: + .word 0,0,0,0 ! dummy + + .word 0,0,0,0 ! unused + + .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb) + .word 0x0000 ! base address=0 + .word 0x9A00 ! code read/exec + .word 0x00C0 ! granularity=4096, 386 + + .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb) + .word 0x0000 ! base address=0 + .word 0x9200 ! data read/write + .word 0x00C0 ! granularity=4096, 386 + +idt_48: + .word 0 ! idt limit=0 + .word 0,0 ! idt base=0L + +gdt_48: + .word 0x800 ! gdt limit=2048, 256 GDT entries + .word 512+gdt,0x9 ! gdt base = 0X9xxxx + +msg1: .ascii "Press <RETURN> to see SVGA-modes available, <SPACE> to continue or wait 30 secs." + db 0x0d, 0x0a, 0x0a, 0x00 +msg2: .ascii "Mode: COLSxROWS:" + db 0x0d, 0x0a, 0x0a, 0x00 +msg3: db 0x0d, 0x0a + .ascii "Choose mode by pressing the corresponding number or letter." +crlf: db 0x0d, 0x0a, 0x00 +msg4: .ascii "You passed an undefined mode number to setup. Please choose a new mode." + db 0x0d, 0x0a, 0x0a, 0x07, 0x00 +modestring: .ascii " " +modenr: db 0x00 ! mode number + .ascii ": " + db 0x00 + +idati: .ascii "761295520" +idcandt: .byte 0xa5 +idgenoa: .byte 0x77, 0x00, 0x99, 0x66 +idparadise: .ascii "VGA=" +idoakvga: .ascii "OAK VGA " +idS3: .byte 0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95 + .byte 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0 + +! Manufacturer: Numofmodes+2: Mode: +! Number of modes is the number of chip-specific svga modes plus the extended +! modes available on any vga (currently 2) + +moati: .byte 0x06, 0x23, 0x33, 0x22, 0x21 +moahead: .byte 0x07, 0x22, 0x23, 0x24, 0x2f, 0x34 +mocandt: .byte 0x04, 0x60, 0x61 +mocirrus: .byte 0x06, 0x1f, 0x20, 0x22, 0x31 +moeverex: .byte 0x0c, 0x03, 0x04, 0x07, 0x08, 0x0a, 0x0b, 0x16, 0x18, 0x21, 0x40 +mogenoa: .byte 0x0c, 0x58, 0x5a, 0x60, 0x61, 0x62, 0x63, 0x64, 0x72, 0x74, 0x78 +moparadise: .byte 0x04, 0x55, 0x54 +motrident: .byte 0x09, 0x50, 0x51, 0x52, 0x57, 0x58, 0x59, 0x5a +motseng: .byte 0x07, 0x26, 0x2a, 0x23, 0x24, 0x22 +movideo7: .byte 0x08, 0x40, 0x43, 0x44, 0x41, 0x42, 0x45 +mooakvga: .byte 0x08, 0x00, 0x07, 0x4e, 0x4f, 0x50, 0x51 +mo_S3: .byte 0x04, 0x54, 0x55 +mounknown: .byte 0x02 + +! msb = Cols lsb = Rows: +! The first two modes are standard vga modes available on any vga. +! mode 0 is 80x50 and mode 1 is 80x28 + +dscati: .word 0x5032, 0x501c, 0x8419, 0x842c, 0x641e, 0x6419 +dscahead: .word 0x5032, 0x501c, 0x842c, 0x8419, 0x841c, 0xa032, 0x5042 +dsccandt: .word 0x5032, 0x501c, 0x8419, 0x8432 +dsccirrus: .word 0x5032, 0x501c, 0x8419, 0x842c, 0x841e, 0x6425 +dsceverex: .word 0x5032, 0x501c, 0x5022, 0x503c, 0x642b, 0x644b, 0x8419, 0x842c, 0x501e, 0x641b, 0xa040, 0x841e +dscgenoa: .word 0x5032, 0x501c, 0x5020, 0x642a, 0x8419, 0x841d, 0x8420, 0x842c, 0x843c, 0x503c, 0x5042, 0x644b +dscparadise: .word 0x5032, 0x501c, 0x8419, 0x842c +dsctrident: .word 0x5032, 0x501c, 0x501e, 0x502b, 0x503c, 0x8419, 0x841e, 0x842b, 0x843c +dsctseng: .word 0x5032, 0x501c, 0x503c, 0x6428, 0x8419, 0x841c, 0x842c +dscvideo7: .word 0x5032, 0x501c, 0x502b, 0x503c, 0x643c, 0x8419, 0x842c, 0x841c +dscoakvga: .word 0x5032, 0x501c, 0x2819, 0x5019, 0x503c, 0x843c, 0x8419, 0x842b +dsc_S3: .word 0x5032, 0x501c, 0x842b, 0x8419 +dsunknown: .word 0x5032, 0x501c +modesave: .word SVGA_MODE + +! This must be last +setup_sig1: .word SIG1 +setup_sig2: .word SIG2 + +.text +endtext: +.data +enddata: +.bss +endbss: diff --git a/arch/i386/config.in b/arch/i386/config.in new file mode 100644 index 000000000..2c4bc4ba5 --- /dev/null +++ b/arch/i386/config.in @@ -0,0 +1,219 @@ +# +# For a description of the syntax of this configuration file, +# see the Configure script. +# + +comment 'General setup' + +bool 'Kernel math emulation' CONFIG_MATH_EMULATION n +bool 'Normal floppy disk support' CONFIG_BLK_DEV_FD y +bool 'Normal harddisk support' CONFIG_BLK_DEV_HD y +bool 'XT harddisk support' CONFIG_BLK_DEV_XD n +bool 'Networking support' CONFIG_NET y +bool 'Limit memory to low 16MB' CONFIG_MAX_16M n +bool 'System V IPC' CONFIG_SYSVIPC y +bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF y +bool 'Use -m486 flag for 486-specific optimizations' CONFIG_M486 y + +if [ "$CONFIG_NET" = "y" ]; then +comment 'Networking options' +bool 'TCP/IP networking' CONFIG_INET y +if [ "$CONFIG_INET" "=" "y" ]; then +bool 'IP forwarding/gatewaying' CONFIG_IP_FORWARD n +comment '(it is safe to leave these untouched)' +bool 'PC/TCP compatibility mode' CONFIG_INET_PCTCP n +bool 'Reverse ARP' CONFIG_INET_RARP n +bool 'Assume subnets are local' CONFIG_INET_SNARL y +bool 'Disable NAGLE algorithm (normally enabled)' CONFIG_TCP_NAGLE_OFF n +fi +bool 'The IPX protocol' CONFIG_IPX n +#bool 'Amateur Radio AX.25 Level 2' CONFIG_AX25 n +fi + +comment 'SCSI support' + +bool 'SCSI support?' CONFIG_SCSI n + +if [ "$CONFIG_SCSI" = "n" ]; then + +comment 'Skipping SCSI configuration options...' + +else + +comment 'SCSI support type (disk, tape, CDrom)' + +bool 'Scsi disk support' CONFIG_BLK_DEV_SD y +bool 'Scsi tape support' CONFIG_CHR_DEV_ST n +bool 'Scsi CDROM support' CONFIG_BLK_DEV_SR n +bool 'Scsi generic support' CONFIG_CHR_DEV_SG n + +comment 'SCSI low-level drivers' + +bool 'Adaptec AHA152X support' CONFIG_SCSI_AHA152X n +bool 'Adaptec AHA1542 support' CONFIG_SCSI_AHA1542 y +bool 'Adaptec AHA1740 support' CONFIG_SCSI_AHA1740 n +bool 'Adaptec AHA274X/284X support' CONFIG_SCSI_AHA274X n +bool 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC n +bool 'UltraStor 14F/34F support' CONFIG_SCSI_U14_34F n +bool 'Future Domain 16xx SCSI support' CONFIG_SCSI_FUTURE_DOMAIN n +bool 'Generic NCR5380 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 n +bool 'NCR53c7,8xx SCSI support' CONFIG_SCSI_NCR53C7xx n +bool 'Always IN2000 SCSI support (test release)' CONFIG_SCSI_IN2000 n +bool 'PAS16 SCSI support' CONFIG_SCSI_PAS16 n +bool 'QLOGIC SCSI support' CONFIG_SCSI_QLOGIC n +bool 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE n +bool 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 n +bool 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR n +bool '7000FASST SCSI support' CONFIG_SCSI_7000FASST n +bool 'EISA EATA support' CONFIG_SCSI_EATA n +#bool 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG n +fi + + +if [ "$CONFIG_NET" = "y" ]; then + +comment 'Network device support' + +bool 'Network device support?' CONFIG_NETDEVICES y +if [ "$CONFIG_NETDEVICES" = "n" ]; then + +comment 'Skipping network driver configuration options...' + +else +bool 'Dummy net driver support' CONFIG_DUMMY n +bool 'SLIP (serial line) support' CONFIG_SLIP n +if [ "$CONFIG_SLIP" = "y" ]; then + bool ' CSLIP compressed headers' SL_COMPRESSED y +# bool ' SLIP debugging on' SL_DUMP y +fi +bool 'PPP (point-to-point) support' CONFIG_PPP n +bool 'PLIP (parallel port) support' CONFIG_PLIP n +bool 'Load balancing support (experimental)' CONFIG_SLAVE_BALANCING n +bool 'Do you want to be offered ALPHA test drivers' CONFIG_NET_ALPHA n +bool 'Western Digital/SMC cards' CONFIG_NET_VENDOR_SMC n +if [ "$CONFIG_NET_VENDOR_SMC" = "y" ]; then + bool 'WD80*3 support' CONFIG_WD80x3 n + bool 'SMC Ultra support' CONFIG_ULTRA n +fi +bool '3COM cards' CONFIG_NET_VENDOR_3COM y +if [ "$CONFIG_NET_VENDOR_3COM" = "y" ]; then + bool '3c501 support' CONFIG_EL1 n + bool '3c503 support' CONFIG_EL2 n + if [ "$CONFIG_NET_ALPHA" = "y" ]; then + bool '3c505 support' CONFIG_ELPLUS n + bool '3c507 support' CONFIG_EL16 n + fi + bool '3c509/3c579 support' CONFIG_EL3 y +fi +bool 'Other ISA cards' CONFIG_NET_ISA n +if [ "$CONFIG_NET_ISA" = "y" ]; then + bool 'AT1500 and NE2100 (LANCE and PCnet-ISA) support' CONFIG_LANCE n + bool 'Cabletron E21xx support (not recommended)' CONFIG_E2100 n + bool 'DEPCA support' CONFIG_DEPCA n + bool 'EtherWorks 3 support' CONFIG_EWRK3 n + if [ "$CONFIG_NET_ALPHA" = "y" ]; then + bool 'EtherExpress support' CONFIG_EEXPRESS n + bool 'AT1700 support' CONFIG_AT1700 n + bool 'NI5210 support' CONFIG_NI52 n + bool 'NI6510 support' CONFIG_NI65 n + fi + bool 'HP PCLAN support' CONFIG_HPLAN n + bool 'HP PCLAN PLUS support' CONFIG_HPLAN_PLUS n + bool 'NE2000/NE1000 support' CONFIG_NE2000 y + bool 'SK_G16 support' CONFIG_SK_G16 n +fi +bool 'EISA and on board controllers' CONFIG_NET_EISA n + if [ "$CONFIG_NET_ALPHA" = "y" ]; then + bool 'Ansel Communications EISA 3200 support' CONFIG_AC3200 n + fi + bool 'Apricot Xen-II on board ethernet' CONFIG_APRICOT n +bool 'Pocket and portable adaptors' CONFIG_NET_POCKET n +if [ "$CONFIG_NET_POCKET" = "y" ]; then + bool 'D-Link DE600 pocket adaptor support' CONFIG_DE600 n + bool 'D-Link DE620 pocket adaptor support' CONFIG_DE620 n + bool 'AT-LAN-TEC/RealTek pocket adaptor support' CONFIG_ATP n + bool 'Zenith Z-Note support' CONFIG_ZNET n +fi +fi +fi + +comment 'CD-ROM drivers' + +bool 'Sony CDU31A/CDU33A CDROM driver support' CONFIG_CDU31A n +bool 'Mitsumi CDROM driver support' CONFIG_MCD n +bool 'Matsushita/Panasonic CDROM driver support' CONFIG_SBPCD n +if [ "$CONFIG_SBPCD" = "y" ]; then + bool 'Matsushita/Panasonic second CDROM controller support' CONFIG_SBPCD2 n + if [ "$CONFIG_SBPCD2" = "y" ]; then + bool 'Matsushita/Panasonic third CDROM controller support' CONFIG_SBPCD3 n + if [ "$CONFIG_SBPCD3" = "y" ]; then + bool 'Matsushita/Panasonic fourth CDROM controller support' CONFIG_SBPCD4 n + fi + fi +fi + +comment 'Filesystems' + +bool 'Standard (minix) fs support' CONFIG_MINIX_FS y +bool 'Extended fs support' CONFIG_EXT_FS n +bool 'Second extended fs support' CONFIG_EXT2_FS y +bool 'xiafs filesystem support' CONFIG_XIA_FS n +bool 'msdos fs support' CONFIG_MSDOS_FS y +if [ "$CONFIG_MSDOS_FS" = "y" ]; then +bool 'umsdos: Unix like fs on top of std MSDOS FAT fs' CONFIG_UMSDOS_FS n +fi +bool '/proc filesystem support' CONFIG_PROC_FS y +if [ "$CONFIG_INET" = "y" ]; then +bool 'NFS filesystem support' CONFIG_NFS_FS y +fi +if [ "$CONFIG_BLK_DEV_SR" = "y" -o "$CONFIG_CDU31A" = "y" -o "$CONFIG_MCD" = "y" -o "$CONFIG_SBPCD" = "y" -o "$CONFIG_BLK_DEV_IDECD" = "y" ]; then + bool 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS y +else + bool 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS n +fi +bool 'OS/2 HPFS filesystem support (read only)' CONFIG_HPFS_FS n +bool 'System V and Coherent filesystem support' CONFIG_SYSV_FS n + +comment 'character devices' + +bool 'Parallel printer support' CONFIG_PRINTER n +bool 'Logitech busmouse support' CONFIG_BUSMOUSE n +bool 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE n +if [ "$CONFIG_PSMOUSE" = "y" ]; then +bool 'C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE y +fi +bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n +bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n +bool 'Selection (cut and paste for virtual consoles)' CONFIG_SELECTION n + +bool 'QIC-02 tape support' CONFIG_QIC02_TAPE n +if [ "$CONFIG_QIC02_TAPE" = "y" ]; then +bool 'Do you want runtime configuration for QIC-02' CONFIG_QIC02_DYNCONF y +if [ "$CONFIG_QIC02_DYNCONF" != "y" ]; then + +comment '>>> Edit configuration parameters in ./include/linux/tpqic02.h!' + +else + +comment '>>> Setting runtime QIC-02 configuration is done with qic02conf' +comment '>>> Which is available from ftp://ftp.funet.fi/pub/OS/Linux/BETA/QIC-02/' + +fi +fi + +bool 'QIC-117 tape support' CONFIG_FTAPE n +if [ "$CONFIG_FTAPE" = "y" ]; then +int ' number of ftape buffers' NR_FTAPE_BUFFERS 3 +fi + +comment 'Sound' + +bool 'Sound card support' CONFIG_SOUND n + +comment 'Kernel hacking' + +#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC n +bool 'Kernel profiling support' CONFIG_PROFILE n +if [ "$CONFIG_SCSI" = "y" ]; then +bool 'Verbose scsi error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS y +fi diff --git a/arch/i386/entry.S b/arch/i386/entry.S new file mode 100644 index 000000000..d7008a74b --- /dev/null +++ b/arch/i386/entry.S @@ -0,0 +1,545 @@ +/* + * linux/arch/i386/entry.S + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* + * entry.S contains the system-call and fault low-level handling routines. + * This also contains the timer-interrupt handler, as well as all interrupts + * and faults that can result in a task-switch. + * + * NOTE: This code handles signal-recognition, which happens every time + * after a timer-interrupt and after each system call. + * + * I changed all the .align's to 4 (16 byte alignment), as that's faster + * on a 486. + * + * Stack layout in 'ret_from_system_call': + * ptrace needs to have all regs on the stack. + * if the order here is changed, it needs to be + * updated in fork.c:copy_process, signal.c:do_signal, + * ptrace.c and ptrace.h + * + * 0(%esp) - %ebx + * 4(%esp) - %ecx + * 8(%esp) - %edx + * C(%esp) - %esi + * 10(%esp) - %edi + * 14(%esp) - %ebp + * 18(%esp) - %eax + * 1C(%esp) - %ds + * 20(%esp) - %es + * 24(%esp) - %fs + * 28(%esp) - %gs + * 2C(%esp) - orig_eax + * 30(%esp) - %eip + * 34(%esp) - %cs + * 38(%esp) - %eflags + * 3C(%esp) - %oldesp + * 40(%esp) - %oldss + */ + +#define __ASSEMBLY__ +#include <linux/sys.h> +#include <asm/segment.h> + +EBX = 0x00 +ECX = 0x04 +EDX = 0x08 +ESI = 0x0C +EDI = 0x10 +EBP = 0x14 +EAX = 0x18 +DS = 0x1C +ES = 0x20 +FS = 0x24 +GS = 0x28 +ORIG_EAX = 0x2C +EIP = 0x30 +CS = 0x34 +EFLAGS = 0x38 +OLDESP = 0x3C +OLDSS = 0x40 + +CF_MASK = 0x00000001 +IF_MASK = 0x00000200 +NT_MASK = 0x00004000 +VM_MASK = 0x00020000 + +/* + * these are offsets into the task-struct. + */ +state = 0 +counter = 4 +priority = 8 +signal = 12 +blocked = 16 +flags = 20 +errno = 24 +dbgreg6 = 52 +dbgreg7 = 56 +exec_domain = 60 + +ENOSYS = 38 + +.globl _system_call,_lcall7 +.globl _device_not_available, _coprocessor_error +.globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op +.globl _double_fault,_coprocessor_segment_overrun +.globl _invalid_TSS,_segment_not_present,_stack_segment +.globl _general_protection,_reserved +.globl _alignment_check,_page_fault +.globl ret_from_sys_call, _sys_call_table + +#define SAVE_ALL \ + cld; \ + push %gs; \ + push %fs; \ + push %es; \ + push %ds; \ + pushl %eax; \ + pushl %ebp; \ + pushl %edi; \ + pushl %esi; \ + pushl %edx; \ + pushl %ecx; \ + pushl %ebx; \ + movl $(KERNEL_DS),%edx; \ + mov %dx,%ds; \ + mov %dx,%es; \ + movl $(USER_DS),%edx; \ + mov %dx,%fs; + +#define RESTORE_ALL \ + cmpw $(KERNEL_CS),CS(%esp); \ + je 1f; \ + movl _current,%eax; \ + movl dbgreg7(%eax),%ebx; \ + movl %ebx,%db7; \ +1: popl %ebx; \ + popl %ecx; \ + popl %edx; \ + popl %esi; \ + popl %edi; \ + popl %ebp; \ + popl %eax; \ + pop %ds; \ + pop %es; \ + pop %fs; \ + pop %gs; \ + addl $4,%esp; \ + iret + +.align 4 +_lcall7: + pushfl # We get a different stack layout with call gates, + pushl %eax # which has to be cleaned up later.. + SAVE_ALL + movl EIP(%esp),%eax # due to call gates, this is eflags, not eip.. + movl CS(%esp),%edx # this is eip.. + movl EFLAGS(%esp),%ecx # and this is cs.. + movl %eax,EFLAGS(%esp) # + movl %edx,EIP(%esp) # Now we move them to their "normal" places + movl %ecx,CS(%esp) # + movl %esp,%eax + movl _current,%edx + pushl %eax + movl exec_domain(%edx),%edx # Get the execution domain + movl 4(%edx),%edx # Get the lcall7 handler for the domain + call *%edx + popl %eax + jmp ret_from_sys_call + +.align 4 +handle_bottom_half: + pushfl + incl _intr_count + sti + call _do_bottom_half + popfl + decl _intr_count + jmp 9f +.align 4 +reschedule: + pushl $ret_from_sys_call + jmp _schedule +.align 4 +_system_call: + pushl %eax # save orig_eax + SAVE_ALL + movl $-ENOSYS,EAX(%esp) + cmpl $(NR_syscalls),%eax + jae ret_from_sys_call + movl _sys_call_table(,%eax,4),%eax + testl %eax,%eax + je ret_from_sys_call + movl _current,%ebx + andl $~CF_MASK,EFLAGS(%esp) # clear carry - assume no errors + movl $0,errno(%ebx) + movl %db6,%edx + movl %edx,dbgreg6(%ebx) # save current hardware debugging status + testb $0x20,flags(%ebx) # PF_TRACESYS + jne 1f + call *%eax + movl %eax,EAX(%esp) # save the return value + movl errno(%ebx),%edx + negl %edx + je ret_from_sys_call + movl %edx,EAX(%esp) + orl $(CF_MASK),EFLAGS(%esp) # set carry to indicate error + jmp ret_from_sys_call +.align 4 +1: call _syscall_trace + movl ORIG_EAX(%esp),%eax + call _sys_call_table(,%eax,4) + movl %eax,EAX(%esp) # save the return value + movl _current,%eax + movl errno(%eax),%edx + negl %edx + je 1f + movl %edx,EAX(%esp) + orl $(CF_MASK),EFLAGS(%esp) # set carry to indicate error +1: call _syscall_trace + + .align 4,0x90 +ret_from_sys_call: + cmpl $0,_intr_count + jne 2f +9: movl _bh_mask,%eax + andl _bh_active,%eax + jne handle_bottom_half + movl EFLAGS(%esp),%eax # check VM86 flag: CS/SS are + testl $(VM_MASK),%eax # different then + jne 1f + cmpw $(KERNEL_CS),CS(%esp) # was old code segment supervisor ? + je 2f +1: sti + orl $(IF_MASK),%eax # these just try to make sure + andl $~NT_MASK,%eax # the program doesn't do anything + movl %eax,EFLAGS(%esp) # stupid + cmpl $0,_need_resched + jne reschedule + movl _current,%eax + cmpl _task,%eax # task[0] cannot have signals + je 2f + cmpl $0,state(%eax) # state + jne reschedule + cmpl $0,counter(%eax) # counter + je reschedule + movl blocked(%eax),%ecx + movl %ecx,%ebx # save blocked in %ebx for signal handling + notl %ecx + andl signal(%eax),%ecx + jne signal_return +2: RESTORE_ALL +.align 4 +signal_return: + movl %esp,%ecx + pushl %ecx + testl $(VM_MASK),EFLAGS(%ecx) + jne v86_signal_return + pushl %ebx + call _do_signal + popl %ebx + popl %ebx + RESTORE_ALL +.align 4 +v86_signal_return: + call _save_v86_state + movl %eax,%esp + pushl %eax + pushl %ebx + call _do_signal + popl %ebx + popl %ebx + RESTORE_ALL + +.align 4 +_divide_error: + pushl $0 # no error code + pushl $_do_divide_error +.align 4,0x90 +error_code: + push %fs + push %es + push %ds + pushl %eax + pushl %ebp + pushl %edi + pushl %esi + pushl %edx + pushl %ecx + pushl %ebx + movl $0,%eax + movl %eax,%db7 # disable hardware debugging... + cld + movl $-1, %eax + xchgl %eax, ORIG_EAX(%esp) # orig_eax (get the error code. ) + xorl %ebx,%ebx # zero ebx + mov %gs,%bx # get the lower order bits of gs + xchgl %ebx, GS(%esp) # get the address and save gs. + pushl %eax # push the error code + lea 4(%esp),%edx + pushl %edx + movl $(KERNEL_DS),%edx + mov %dx,%ds + mov %dx,%es + movl $(USER_DS),%edx + mov %dx,%fs + pushl %eax + movl _current,%eax + movl %db6,%edx + movl %edx,dbgreg6(%eax) # save current hardware debugging status + popl %eax + call *%ebx + addl $8,%esp + jmp ret_from_sys_call + +.align 4 +_coprocessor_error: + pushl $0 + pushl $_do_coprocessor_error + jmp error_code + +.align 4 +_device_not_available: + pushl $-1 # mark this as an int + SAVE_ALL + pushl $ret_from_sys_call + movl %cr0,%eax + testl $0x4,%eax # EM (math emulation bit) + je _math_state_restore + pushl $0 # temporary storage for ORIG_EIP + call _math_emulate + addl $4,%esp + ret + +.align 4 +_debug: + pushl $0 + pushl $_do_debug + jmp error_code + +.align 4 +_nmi: + pushl $0 + pushl $_do_nmi + jmp error_code + +.align 4 +_int3: + pushl $0 + pushl $_do_int3 + jmp error_code + +.align 4 +_overflow: + pushl $0 + pushl $_do_overflow + jmp error_code + +.align 4 +_bounds: + pushl $0 + pushl $_do_bounds + jmp error_code + +.align 4 +_invalid_op: + pushl $0 + pushl $_do_invalid_op + jmp error_code + +.align 4 +_coprocessor_segment_overrun: + pushl $0 + pushl $_do_coprocessor_segment_overrun + jmp error_code + +.align 4 +_reserved: + pushl $0 + pushl $_do_reserved + jmp error_code + +.align 4 +_double_fault: + pushl $_do_double_fault + jmp error_code + +.align 4 +_invalid_TSS: + pushl $_do_invalid_TSS + jmp error_code + +.align 4 +_segment_not_present: + pushl $_do_segment_not_present + jmp error_code + +.align 4 +_stack_segment: + pushl $_do_stack_segment + jmp error_code + +.align 4 +_general_protection: + pushl $_do_general_protection + jmp error_code + +.align 4 +_alignment_check: + pushl $_do_alignment_check + jmp error_code + +.align 4 +_page_fault: + pushl $_do_page_fault + jmp error_code + +.data +.align 4 +_sys_call_table: + .long _sys_setup /* 0 */ + .long _sys_exit + .long _sys_fork + .long _sys_read + .long _sys_write + .long _sys_open /* 5 */ + .long _sys_close + .long _sys_waitpid + .long _sys_creat + .long _sys_link + .long _sys_unlink /* 10 */ + .long _sys_execve + .long _sys_chdir + .long _sys_time + .long _sys_mknod + .long _sys_chmod /* 15 */ + .long _sys_chown + .long _sys_break + .long _sys_stat + .long _sys_lseek + .long _sys_getpid /* 20 */ + .long _sys_mount + .long _sys_umount + .long _sys_setuid + .long _sys_getuid + .long _sys_stime /* 25 */ + .long _sys_ptrace + .long _sys_alarm + .long _sys_fstat + .long _sys_pause + .long _sys_utime /* 30 */ + .long _sys_stty + .long _sys_gtty + .long _sys_access + .long _sys_nice + .long _sys_ftime /* 35 */ + .long _sys_sync + .long _sys_kill + .long _sys_rename + .long _sys_mkdir + .long _sys_rmdir /* 40 */ + .long _sys_dup + .long _sys_pipe + .long _sys_times + .long _sys_prof + .long _sys_brk /* 45 */ + .long _sys_setgid + .long _sys_getgid + .long _sys_signal + .long _sys_geteuid + .long _sys_getegid /* 50 */ + .long _sys_acct + .long _sys_phys + .long _sys_lock + .long _sys_ioctl + .long _sys_fcntl /* 55 */ + .long _sys_mpx + .long _sys_setpgid + .long _sys_ulimit + .long _sys_olduname + .long _sys_umask /* 60 */ + .long _sys_chroot + .long _sys_ustat + .long _sys_dup2 + .long _sys_getppid + .long _sys_getpgrp /* 65 */ + .long _sys_setsid + .long _sys_sigaction + .long _sys_sgetmask + .long _sys_ssetmask + .long _sys_setreuid /* 70 */ + .long _sys_setregid + .long _sys_sigsuspend + .long _sys_sigpending + .long _sys_sethostname + .long _sys_setrlimit /* 75 */ + .long _sys_getrlimit + .long _sys_getrusage + .long _sys_gettimeofday + .long _sys_settimeofday + .long _sys_getgroups /* 80 */ + .long _sys_setgroups + .long _sys_select + .long _sys_symlink + .long _sys_lstat + .long _sys_readlink /* 85 */ + .long _sys_uselib + .long _sys_swapon + .long _sys_reboot + .long _sys_readdir + .long _sys_mmap /* 90 */ + .long _sys_munmap + .long _sys_truncate + .long _sys_ftruncate + .long _sys_fchmod + .long _sys_fchown /* 95 */ + .long _sys_getpriority + .long _sys_setpriority + .long _sys_profil + .long _sys_statfs + .long _sys_fstatfs /* 100 */ + .long _sys_ioperm + .long _sys_socketcall + .long _sys_syslog + .long _sys_setitimer + .long _sys_getitimer /* 105 */ + .long _sys_newstat + .long _sys_newlstat + .long _sys_newfstat + .long _sys_uname + .long _sys_iopl /* 110 */ + .long _sys_vhangup + .long _sys_idle + .long _sys_vm86 + .long _sys_wait4 + .long _sys_swapoff /* 115 */ + .long _sys_sysinfo + .long _sys_ipc + .long _sys_fsync + .long _sys_sigreturn + .long _sys_clone /* 120 */ + .long _sys_setdomainname + .long _sys_newuname + .long _sys_modify_ldt + .long _sys_adjtimex + .long _sys_mprotect /* 125 */ + .long _sys_sigprocmask + .long _sys_create_module + .long _sys_init_module + .long _sys_delete_module + .long _sys_get_kernel_syms /* 130 */ + .long _sys_quotactl + .long _sys_getpgid + .long _sys_fchdir + .long _sys_bdflush + .long _sys_sysfs /* 135 */ + .long _sys_personality + .long 0 /* for afs_syscall */ + .long _sys_setfsuid + .long _sys_setfsgid + .long _sys_llseek /* 140 */ + .space (NR_syscalls-140)*4 |