summaryrefslogtreecommitdiffstats
path: root/arch/i386
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-01-27 01:05:20 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-01-27 01:05:20 +0000
commit546db14ee74118296f425f3b91634fb767d67290 (patch)
tree22b613a3da8d4bf663eec5e155af01b87fdf9094 /arch/i386
parent1e25e41c4f5474e14452094492dbc169b800e4c8 (diff)
Merge with Linux 2.3.23. The new bootmem stuff has broken various
platforms. At this time I've only verified that IP22 support compiles and IP27 actually works.
Diffstat (limited to 'arch/i386')
-rw-r--r--arch/i386/Makefile4
-rw-r--r--arch/i386/boot/Makefile6
-rw-r--r--arch/i386/boot/bootsect.S12
-rw-r--r--arch/i386/boot/setup.S8
-rw-r--r--arch/i386/boot/video.S4
-rw-r--r--arch/i386/config.in15
-rw-r--r--arch/i386/defconfig24
-rw-r--r--arch/i386/kernel/head.S160
-rw-r--r--arch/i386/kernel/irq.c1
-rw-r--r--arch/i386/kernel/pci-i386.c54
-rw-r--r--arch/i386/kernel/pci-i386.h5
-rw-r--r--arch/i386/kernel/pci-pc.c77
-rw-r--r--arch/i386/kernel/pci-visws.c6
-rw-r--r--arch/i386/kernel/setup.c252
-rw-r--r--arch/i386/kernel/smpboot.c55
-rw-r--r--arch/i386/kernel/traps.c8
-rw-r--r--arch/i386/kernel/visws_apic.c2
-rw-r--r--arch/i386/kernel/vm86.c4
-rw-r--r--arch/i386/lib/Makefile2
-rw-r--r--arch/i386/lib/iodebug.c19
-rw-r--r--arch/i386/mm/Makefile4
-rw-r--r--arch/i386/mm/bigmem.c33
-rw-r--r--arch/i386/mm/fault.c36
-rw-r--r--arch/i386/mm/init.c607
-rw-r--r--arch/i386/mm/ioremap.c21
-rw-r--r--arch/i386/vmlinux.lds (renamed from arch/i386/vmlinux.lds.S)2
26 files changed, 892 insertions, 529 deletions
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index 9978cac9d..37b2371a0 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -84,9 +84,6 @@ MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
vmlinux: arch/i386/vmlinux.lds
-arch/i386/vmlinux.lds: arch/i386/vmlinux.lds.S FORCE
- $(CPP) -C -P -imacros $(HPATH)/asm-i386/page_offset.h -Ui386 arch/i386/vmlinux.lds.S >arch/i386/vmlinux.lds
-
FORCE: ;
.PHONY: zImage bzImage compressed zlilo bzlilo zdisk bzdisk install \
@@ -119,7 +116,6 @@ archclean:
@$(MAKEBOOT) clean
archmrproper:
- rm -f arch/i386/vmlinux.lds
archdep:
@$(MAKEBOOT) dep
diff --git a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile
index 414e51679..de8cdced8 100644
--- a/arch/i386/boot/Makefile
+++ b/arch/i386/boot/Makefile
@@ -51,11 +51,11 @@ bootsect.o: bootsect.s
bootsect.s: bootsect.S Makefile $(BOOT_INCL)
$(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
-bbootsect: bbootsect.o bsetup
- $(LD) -Ttext 0x0 -s -oformat binary $< -R bsetup.o -o $@
+bbootsect: bbootsect.o
+ $(LD) -Ttext 0x0 -s -oformat binary $< -o $@
bbootsect.o: bbootsect.s
- $(AS) -o $@ $<
+ $(AS) --defsym bootsect_kludge=0x220 -o $@ $<
bbootsect.s: bootsect.S Makefile $(BOOT_INCL)
$(CPP) -D__BIG_KERNEL__ -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
diff --git a/arch/i386/boot/bootsect.S b/arch/i386/boot/bootsect.S
index e7327e1e1..58644810e 100644
--- a/arch/i386/boot/bootsect.S
+++ b/arch/i386/boot/bootsect.S
@@ -64,12 +64,12 @@ _start:
movw %ax, %ds
movw $INITSEG, %ax
movw %ax, %es
- movw $128, %cx
+ movw $256, %cx
subw %si, %si
subw %di, %di
cld
rep
- movsl
+ movsw
ljmp $INITSEG, $go
# bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde). We
@@ -105,11 +105,11 @@ go: movw $0x4000-12, %di # 0x4000 is an arbitrary value >=
movw $0x78, %bx # fs:bx is parameter table address
pushw %ds
ldsw %fs:(%bx), %si # ds:si is source
- movb $3, %cl # copy 12 bytes
+ movb $6, %cl # copy 12 bytes
cld
pushw %di # di = 0x4000-12.
rep
- movsl
+ movsw
popw %di
popw %ds
movb $36, 0x4(%di) # patch sector count
@@ -118,7 +118,7 @@ go: movw $0x4000-12, %di # 0x4000 is an arbitrary value >=
# Load the setup-sectors directly after the bootblock.
# Note that 'es' is already set up.
-# Also, cx = 0 from rep movsl above.
+# Also, cx = 0 from rep movsw above.
load_setup:
xorb %ah, %ah # reset FDC
@@ -247,7 +247,7 @@ die: jne die # es must be at 64kB boundary
xorw %bx, %bx # bx is starting address within segment
rp_read:
#ifdef __BIG_KERNEL__
- .word 0x1eff, 0x0220 # lcall *bootsect_kludge in setup.S
+ lcall bootsect_kludge # in setup.S
#else
movw %es, %ax
subw $SYSSEG, %ax
diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S
index 859c7248b..9c450bab8 100644
--- a/arch/i386/boot/setup.S
+++ b/arch/i386/boot/setup.S
@@ -209,14 +209,14 @@ bad_sig:
addw $SYSSEG, %bx
movw %bx, %cs:start_sys_seg
# Move rest of setup code/data to here
- movw $2048, %di # four sectors loaded by LILO
+ movw $4096, %di # four sectors loaded by LILO
subw %si, %si
movw %cs, %ax # aka SETUPSEG
movw %ax, %es
movw $SYSSEG, %ax
movw %ax, %ds
rep
- movsl
+ movsw
movw %cs, %ax # aka SETUPSEG
movw %ax, %ds
cmpw $SIG1, setup_sig1
@@ -532,9 +532,9 @@ do_move:
addw $0x100, %bx
subw %di, %di
subw %si, %si
- movw $0x400, %cx
+ movw $0x800, %cx
rep
- movsl
+ movsw
cmpw %bp, %bx # assume start_sys_seg > 0x200,
# so we will perhaps read one
# page more than needed, but
diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S
index 3052b6838..77d22bef1 100644
--- a/arch/i386/boot/video.S
+++ b/arch/i386/boot/video.S
@@ -1152,7 +1152,7 @@ dosvga: lodsw
pushw %es
movw $0xc000, %bx
movw %bx, %es
- call ax # Call test routine
+ call *%ax # Call test routine
popw %es
popw %di
popw %si
@@ -1741,7 +1741,7 @@ even7: movb $0x0c, %al
cmpb %bh, %al
jne isnot
- movb $VIDEO_FIRST_V7>>8, $svga_prefix # Use special mode switching
+ movb $VIDEO_FIRST_V7>>8, svga_prefix # Use special mode switching
ret
video7_md:
diff --git a/arch/i386/config.in b/arch/i386/config.in
index 9d373d1ed..b8f081e65 100644
--- a/arch/i386/config.in
+++ b/arch/i386/config.in
@@ -42,9 +42,17 @@ if [ "$CONFIG_MK7" = "y" ]; then
define_bool CONFIG_X86_USE_3DNOW y
fi
-choice 'Maximum Physical Memory' \
- "1GB CONFIG_1GB \
- 2GB CONFIG_2GB" 1GB
+choice 'High Memory Support' \
+ "off CONFIG_NOHIGHMEM \
+ 4GB CONFIG_HIGHMEM4G \
+ 64GB CONFIG_HIGHMEM64G" off
+if [ "$CONFIG_HIGHMEM4G" = "y" ]; then
+ define_bool CONFIG_HIGHMEM y
+fi
+if [ "$CONFIG_HIGHMEM64G" = "y" ]; then
+ define_bool CONFIG_HIGHMEM y
+ define_bool CONFIG_X86_PAE y
+fi
bool 'Math emulation' CONFIG_MATH_EMULATION
bool 'MTRR (Memory Type Range Register) support' CONFIG_MTRR
@@ -63,7 +71,6 @@ endmenu
mainmenu_option next_comment
comment 'General setup'
-bool 'BIGMEM support' CONFIG_BIGMEM
bool 'Networking support' CONFIG_NET
bool 'SGI Visual Workstation support' CONFIG_VISWS
if [ "$CONFIG_VISWS" = "y" ]; then
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 49137cda4..8b6370667 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -24,8 +24,9 @@ CONFIG_X86_BSWAP=y
CONFIG_X86_POPAD_OK=y
CONFIG_X86_TSC=y
CONFIG_X86_GOOD_APIC=y
-CONFIG_1GB=y
-# CONFIG_2GB is not set
+CONFIG_NOHIGHMEM=y
+# CONFIG_HIGHMEM4G is not set
+# CONFIG_HIGHMEM64G is not set
# CONFIG_MATH_EMULATION is not set
# CONFIG_MTRR is not set
CONFIG_SMP=y
@@ -40,7 +41,6 @@ CONFIG_MODULES=y
#
# General setup
#
-# CONFIG_BIGMEM is not set
CONFIG_NET=y
# CONFIG_VISWS is not set
CONFIG_X86_IO_APIC=y
@@ -54,10 +54,12 @@ CONFIG_PCI_DIRECT=y
# CONFIG_MCA is not set
#
-# PCMCIA/Cardbus support
+# PCMCIA/CardBus support
#
CONFIG_PCMCIA=y
CONFIG_CARDBUS=y
+CONFIG_I82365=y
+# CONFIG_TCIC is not set
CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
@@ -111,7 +113,7 @@ CONFIG_BLK_DEV_IDEPCI=y
# CONFIG_BLK_DEV_OFFBOARD is not set
# CONFIG_BLK_DEV_AEC6210 is not set
CONFIG_BLK_DEV_PIIX=y
-# CONFIG_BLK_DEV_SIS5513 is not set
+# CONFIG_BLK_DEV_PIIX_TUNING is not set
# CONFIG_IDE_CHIPSETS is not set
# CONFIG_BLK_CPQ_DA is not set
@@ -284,11 +286,19 @@ CONFIG_EEXPRESS_PRO100=y
# CONFIG_WAN is not set
#
-# PCMCIA network devices
+# PCMCIA network device support
#
-CONFIG_PCMCIA_PCNET=y
+CONFIG_NET_PCMCIA=y
# CONFIG_PCMCIA_3C589 is not set
+# CONFIG_PCMCIA_3C574 is not set
+# CONFIG_PCMCIA_FMVJ18X is not set
+CONFIG_PCMCIA_PCNET=y
+# CONFIG_PCMCIA_NMCLAN is not set
+# CONFIG_PCMCIA_SMC91C92 is not set
+# CONFIG_PCMCIA_XIRC2PS is not set
CONFIG_PCMCIA_RAYCS=y
+# CONFIG_PCMCIA_NETWAVE is not set
+# CONFIG_PCMCIA_WAVELAN is not set
CONFIG_PCMCIA_NETCARD=y
#
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index f1aa50586..423308aae 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -367,11 +367,13 @@ SYMBOL_NAME(gdt):
.org 0x1000
ENTRY(swapper_pg_dir)
.long 0x00102007
- .fill __USER_PGD_PTRS-1,4,0
- /* default: 767 entries */
+ .long 0x00103007
+ .fill BOOT_USER_PGD_PTRS-2,4,0
+ /* default: 766 entries */
.long 0x00102007
- /* default: 255 entries */
- .fill __KERNEL_PGD_PTRS-1,4,0
+ .long 0x00103007
+ /* default: 254 entries */
+ .fill BOOT_KERNEL_PGD_PTRS-2,4,0
/*
* The page tables are initialized to only 4MB here - the final page
@@ -509,16 +511,156 @@ ENTRY(pg0)
.long 0x3f0007,0x3f1007,0x3f2007,0x3f3007,0x3f4007,0x3f5007,0x3f6007,0x3f7007
.long 0x3f8007,0x3f9007,0x3fa007,0x3fb007,0x3fc007,0x3fd007,0x3fe007,0x3ff007
-.org 0x3000
-ENTRY(empty_bad_page)
-
+ENTRY(pg1)
+ .long 0x400007,0x001007,0x002007,0x003007,0x004007,0x005007,0x006007,0x007007
+ .long 0x408007,0x009007,0x00a007,0x00b007,0x00c007,0x00d007,0x00e007,0x00f007
+ .long 0x410007,0x011007,0x012007,0x013007,0x014007,0x015007,0x016007,0x017007
+ .long 0x418007,0x019007,0x01a007,0x01b007,0x01c007,0x01d007,0x01e007,0x01f007
+ .long 0x420007,0x021007,0x022007,0x023007,0x024007,0x025007,0x026007,0x027007
+ .long 0x428007,0x029007,0x02a007,0x02b007,0x02c007,0x02d007,0x02e007,0x02f007
+ .long 0x430007,0x031007,0x032007,0x033007,0x034007,0x035007,0x036007,0x037007
+ .long 0x438007,0x039007,0x03a007,0x03b007,0x03c007,0x03d007,0x03e007,0x03f007
+ .long 0x440007,0x041007,0x042007,0x043007,0x044007,0x045007,0x046007,0x047007
+ .long 0x448007,0x049007,0x04a007,0x04b007,0x04c007,0x04d007,0x04e007,0x04f007
+ .long 0x450007,0x051007,0x052007,0x053007,0x054007,0x055007,0x056007,0x057007
+ .long 0x458007,0x059007,0x05a007,0x05b007,0x05c007,0x05d007,0x05e007,0x05f007
+ .long 0x460007,0x061007,0x062007,0x063007,0x064007,0x065007,0x066007,0x067007
+ .long 0x468007,0x069007,0x06a007,0x06b007,0x06c007,0x06d007,0x06e007,0x06f007
+ .long 0x470007,0x071007,0x072007,0x073007,0x074007,0x075007,0x076007,0x077007
+ .long 0x478007,0x079007,0x07a007,0x07b007,0x07c007,0x07d007,0x07e007,0x07f007
+ .long 0x480007,0x081007,0x082007,0x083007,0x084007,0x085007,0x086007,0x087007
+ .long 0x488007,0x089007,0x08a007,0x08b007,0x08c007,0x08d007,0x08e007,0x08f007
+ .long 0x490007,0x091007,0x092007,0x093007,0x094007,0x095007,0x096007,0x097007
+ .long 0x498007,0x099007,0x09a007,0x09b007,0x09c007,0x09d007,0x09e007,0x09f007
+ .long 0x4a0007,0x0a1007,0x0a2007,0x0a3007,0x0a4007,0x0a5007,0x0a6007,0x0a7007
+ .long 0x4a8007,0x0a9007,0x0aa007,0x0ab007,0x0ac007,0x0ad007,0x0ae007,0x0af007
+ .long 0x4b0007,0x0b1007,0x0b2007,0x0b3007,0x0b4007,0x0b5007,0x0b6007,0x0b7007
+ .long 0x4b8007,0x0b9007,0x0ba007,0x0bb007,0x0bc007,0x0bd007,0x0be007,0x0bf007
+ .long 0x4c0007,0x0c1007,0x0c2007,0x0c3007,0x0c4007,0x0c5007,0x0c6007,0x0c7007
+ .long 0x4c8007,0x0c9007,0x0ca007,0x0cb007,0x0cc007,0x0cd007,0x0ce007,0x0cf007
+ .long 0x4d0007,0x0d1007,0x0d2007,0x0d3007,0x0d4007,0x0d5007,0x0d6007,0x0d7007
+ .long 0x4d8007,0x0d9007,0x0da007,0x0db007,0x0dc007,0x0dd007,0x0de007,0x0df007
+ .long 0x4e0007,0x0e1007,0x0e2007,0x0e3007,0x0e4007,0x0e5007,0x0e6007,0x0e7007
+ .long 0x4e8007,0x0e9007,0x0ea007,0x0eb007,0x0ec007,0x0ed007,0x0ee007,0x0ef007
+ .long 0x4f0007,0x0f1007,0x0f2007,0x0f3007,0x0f4007,0x0f5007,0x0f6007,0x0f7007
+ .long 0x4f8007,0x0f9007,0x0fa007,0x0fb007,0x0fc007,0x0fd007,0x0fe007,0x0ff007
+ .long 0x500007,0x001007,0x002007,0x003007,0x004007,0x005007,0x006007,0x007007
+ .long 0x508007,0x009007,0x00a007,0x00b007,0x00c007,0x00d007,0x00e007,0x00f007
+ .long 0x510007,0x011007,0x012007,0x013007,0x014007,0x015007,0x016007,0x017007
+ .long 0x518007,0x019007,0x01a007,0x01b007,0x01c007,0x01d007,0x01e007,0x01f007
+ .long 0x520007,0x021007,0x022007,0x023007,0x024007,0x025007,0x026007,0x027007
+ .long 0x528007,0x029007,0x02a007,0x02b007,0x02c007,0x02d007,0x02e007,0x02f007
+ .long 0x530007,0x031007,0x032007,0x033007,0x034007,0x035007,0x036007,0x037007
+ .long 0x538007,0x039007,0x03a007,0x03b007,0x03c007,0x03d007,0x03e007,0x03f007
+ .long 0x540007,0x041007,0x042007,0x043007,0x044007,0x045007,0x046007,0x047007
+ .long 0x548007,0x049007,0x04a007,0x04b007,0x04c007,0x04d007,0x04e007,0x04f007
+ .long 0x550007,0x051007,0x052007,0x053007,0x054007,0x055007,0x056007,0x057007
+ .long 0x558007,0x059007,0x05a007,0x05b007,0x05c007,0x05d007,0x05e007,0x05f007
+ .long 0x560007,0x061007,0x062007,0x063007,0x064007,0x065007,0x066007,0x067007
+ .long 0x568007,0x069007,0x06a007,0x06b007,0x06c007,0x06d007,0x06e007,0x06f007
+ .long 0x570007,0x071007,0x072007,0x073007,0x074007,0x075007,0x076007,0x077007
+ .long 0x578007,0x079007,0x07a007,0x07b007,0x07c007,0x07d007,0x07e007,0x07f007
+ .long 0x580007,0x081007,0x082007,0x083007,0x084007,0x085007,0x086007,0x087007
+ .long 0x588007,0x089007,0x08a007,0x08b007,0x08c007,0x08d007,0x08e007,0x08f007
+ .long 0x590007,0x091007,0x092007,0x093007,0x094007,0x095007,0x096007,0x097007
+ .long 0x598007,0x099007,0x09a007,0x09b007,0x09c007,0x09d007,0x09e007,0x09f007
+ .long 0x5a0007,0x0a1007,0x0a2007,0x0a3007,0x0a4007,0x0a5007,0x0a6007,0x0a7007
+ .long 0x5a8007,0x0a9007,0x0aa007,0x0ab007,0x0ac007,0x0ad007,0x0ae007,0x0af007
+ .long 0x5b0007,0x0b1007,0x0b2007,0x0b3007,0x0b4007,0x0b5007,0x0b6007,0x0b7007
+ .long 0x5b8007,0x0b9007,0x0ba007,0x0bb007,0x0bc007,0x0bd007,0x0be007,0x0bf007
+ .long 0x5c0007,0x0c1007,0x0c2007,0x0c3007,0x0c4007,0x0c5007,0x0c6007,0x0c7007
+ .long 0x5c8007,0x0c9007,0x0ca007,0x0cb007,0x0cc007,0x0cd007,0x0ce007,0x0cf007
+ .long 0x5d0007,0x0d1007,0x0d2007,0x0d3007,0x0d4007,0x0d5007,0x0d6007,0x0d7007
+ .long 0x5d8007,0x0d9007,0x0da007,0x0db007,0x0dc007,0x0dd007,0x0de007,0x0df007
+ .long 0x5e0007,0x0e1007,0x0e2007,0x0e3007,0x0e4007,0x0e5007,0x0e6007,0x0e7007
+ .long 0x5e8007,0x0e9007,0x0ea007,0x0eb007,0x0ec007,0x0ed007,0x0ee007,0x0ef007
+ .long 0x5f0007,0x0f1007,0x0f2007,0x0f3007,0x0f4007,0x0f5007,0x0f6007,0x0f7007
+ .long 0x5f8007,0x0f9007,0x0fa007,0x0fb007,0x0fc007,0x0fd007,0x0fe007,0x0ff007
+ .long 0x600007,0x001007,0x002007,0x003007,0x004007,0x005007,0x006007,0x007007
+ .long 0x608007,0x009007,0x00a007,0x00b007,0x00c007,0x00d007,0x00e007,0x00f007
+ .long 0x610007,0x011007,0x012007,0x013007,0x014007,0x015007,0x016007,0x017007
+ .long 0x618007,0x019007,0x01a007,0x01b007,0x01c007,0x01d007,0x01e007,0x01f007
+ .long 0x620007,0x021007,0x022007,0x023007,0x024007,0x025007,0x026007,0x027007
+ .long 0x628007,0x029007,0x02a007,0x02b007,0x02c007,0x02d007,0x02e007,0x02f007
+ .long 0x630007,0x031007,0x032007,0x033007,0x034007,0x035007,0x036007,0x037007
+ .long 0x638007,0x039007,0x03a007,0x03b007,0x03c007,0x03d007,0x03e007,0x03f007
+ .long 0x640007,0x041007,0x042007,0x043007,0x044007,0x045007,0x046007,0x047007
+ .long 0x648007,0x049007,0x04a007,0x04b007,0x04c007,0x04d007,0x04e007,0x04f007
+ .long 0x650007,0x051007,0x052007,0x053007,0x054007,0x055007,0x056007,0x057007
+ .long 0x658007,0x059007,0x05a007,0x05b007,0x05c007,0x05d007,0x05e007,0x05f007
+ .long 0x660007,0x061007,0x062007,0x063007,0x064007,0x065007,0x066007,0x067007
+ .long 0x668007,0x069007,0x06a007,0x06b007,0x06c007,0x06d007,0x06e007,0x06f007
+ .long 0x670007,0x071007,0x072007,0x073007,0x074007,0x075007,0x076007,0x077007
+ .long 0x678007,0x079007,0x07a007,0x07b007,0x07c007,0x07d007,0x07e007,0x07f007
+ .long 0x680007,0x081007,0x082007,0x083007,0x084007,0x085007,0x086007,0x087007
+ .long 0x688007,0x089007,0x08a007,0x08b007,0x08c007,0x08d007,0x08e007,0x08f007
+ .long 0x690007,0x091007,0x092007,0x093007,0x094007,0x095007,0x096007,0x097007
+ .long 0x698007,0x099007,0x09a007,0x09b007,0x09c007,0x09d007,0x09e007,0x09f007
+ .long 0x6a0007,0x0a1007,0x0a2007,0x0a3007,0x0a4007,0x0a5007,0x0a6007,0x0a7007
+ .long 0x6a8007,0x0a9007,0x0aa007,0x0ab007,0x0ac007,0x0ad007,0x0ae007,0x0af007
+ .long 0x6b0007,0x0b1007,0x0b2007,0x0b3007,0x0b4007,0x0b5007,0x0b6007,0x0b7007
+ .long 0x6b8007,0x0b9007,0x0ba007,0x0bb007,0x0bc007,0x0bd007,0x0be007,0x0bf007
+ .long 0x6c0007,0x0c1007,0x0c2007,0x0c3007,0x0c4007,0x0c5007,0x0c6007,0x0c7007
+ .long 0x6c8007,0x0c9007,0x0ca007,0x0cb007,0x0cc007,0x0cd007,0x0ce007,0x0cf007
+ .long 0x6d0007,0x0d1007,0x0d2007,0x0d3007,0x0d4007,0x0d5007,0x0d6007,0x0d7007
+ .long 0x6d8007,0x0d9007,0x0da007,0x0db007,0x0dc007,0x0dd007,0x0de007,0x0df007
+ .long 0x6e0007,0x0e1007,0x0e2007,0x0e3007,0x0e4007,0x0e5007,0x0e6007,0x0e7007
+ .long 0x6e8007,0x0e9007,0x0ea007,0x0eb007,0x0ec007,0x0ed007,0x0ee007,0x0ef007
+ .long 0x6f0007,0x0f1007,0x0f2007,0x0f3007,0x0f4007,0x0f5007,0x0f6007,0x0f7007
+ .long 0x6f8007,0x0f9007,0x0fa007,0x0fb007,0x0fc007,0x0fd007,0x0fe007,0x0ff007
+ .long 0x700007,0x001007,0x002007,0x003007,0x004007,0x005007,0x006007,0x007007
+ .long 0x708007,0x009007,0x00a007,0x00b007,0x00c007,0x00d007,0x00e007,0x00f007
+ .long 0x710007,0x011007,0x012007,0x013007,0x014007,0x015007,0x016007,0x017007
+ .long 0x718007,0x019007,0x01a007,0x01b007,0x01c007,0x01d007,0x01e007,0x01f007
+ .long 0x720007,0x021007,0x022007,0x023007,0x024007,0x025007,0x026007,0x027007
+ .long 0x728007,0x029007,0x02a007,0x02b007,0x02c007,0x02d007,0x02e007,0x02f007
+ .long 0x730007,0x031007,0x032007,0x033007,0x034007,0x035007,0x036007,0x037007
+ .long 0x738007,0x039007,0x03a007,0x03b007,0x03c007,0x03d007,0x03e007,0x03f007
+ .long 0x740007,0x041007,0x042007,0x043007,0x044007,0x045007,0x046007,0x047007
+ .long 0x748007,0x049007,0x04a007,0x04b007,0x04c007,0x04d007,0x04e007,0x04f007
+ .long 0x750007,0x051007,0x052007,0x053007,0x054007,0x055007,0x056007,0x057007
+ .long 0x758007,0x059007,0x05a007,0x05b007,0x05c007,0x05d007,0x05e007,0x05f007
+ .long 0x760007,0x061007,0x062007,0x063007,0x064007,0x065007,0x066007,0x067007
+ .long 0x768007,0x069007,0x06a007,0x06b007,0x06c007,0x06d007,0x06e007,0x06f007
+ .long 0x770007,0x071007,0x072007,0x073007,0x074007,0x075007,0x076007,0x077007
+ .long 0x778007,0x079007,0x07a007,0x07b007,0x07c007,0x07d007,0x07e007,0x07f007
+ .long 0x780007,0x081007,0x082007,0x083007,0x084007,0x085007,0x086007,0x087007
+ .long 0x788007,0x089007,0x08a007,0x08b007,0x08c007,0x08d007,0x08e007,0x08f007
+ .long 0x790007,0x091007,0x092007,0x093007,0x094007,0x095007,0x096007,0x097007
+ .long 0x798007,0x099007,0x09a007,0x09b007,0x09c007,0x09d007,0x09e007,0x09f007
+ .long 0x7a0007,0x0a1007,0x0a2007,0x0a3007,0x0a4007,0x0a5007,0x0a6007,0x0a7007
+ .long 0x7a8007,0x0a9007,0x0aa007,0x0ab007,0x0ac007,0x0ad007,0x0ae007,0x0af007
+ .long 0x7b0007,0x0b1007,0x0b2007,0x0b3007,0x0b4007,0x0b5007,0x0b6007,0x0b7007
+ .long 0x7b8007,0x0b9007,0x0ba007,0x0bb007,0x0bc007,0x0bd007,0x0be007,0x0bf007
+ .long 0x7c0007,0x0c1007,0x0c2007,0x0c3007,0x0c4007,0x0c5007,0x0c6007,0x0c7007
+ .long 0x7c8007,0x0c9007,0x0ca007,0x0cb007,0x0cc007,0x0cd007,0x0ce007,0x0cf007
+ .long 0x7d0007,0x0d1007,0x0d2007,0x0d3007,0x0d4007,0x0d5007,0x0d6007,0x0d7007
+ .long 0x7d8007,0x0d9007,0x0da007,0x0db007,0x0dc007,0x0dd007,0x0de007,0x0df007
+ .long 0x7e0007,0x0e1007,0x0e2007,0x0e3007,0x0e4007,0x0e5007,0x0e6007,0x0e7007
+ .long 0x7e8007,0x0e9007,0x0ea007,0x0eb007,0x0ec007,0x0ed007,0x0ee007,0x0ef007
+ .long 0x7f0007,0x0f1007,0x0f2007,0x0f3007,0x0f4007,0x0f5007,0x0f6007,0x0f7007
+ .long 0x7f8007,0x0f9007,0x0fa007,0x0fb007,0x0fc007,0x0fd007,0x0fe007,0x0ff007
.org 0x4000
-ENTRY(empty_bad_page_table)
+ENTRY(empty_zero_page)
.org 0x5000
-ENTRY(empty_zero_page)
+ENTRY(empty_bad_page)
.org 0x6000
+ENTRY(empty_bad_pte_table)
+
+#if CONFIG_X86_PAE
+
+ .org 0x7000
+ ENTRY(empty_bad_pmd_table)
+
+ .org 0x8000
+
+#else
+
+ .org 0x7000
+
+#endif
/*
* This starts the data section. Note that the above is all
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index 8ec329287..75659aac4 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -20,6 +20,7 @@
* Naturally it's not a 1:1 relation, but there are similarities.
*/
+#include <linux/config.h>
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/signal.h>
diff --git a/arch/i386/kernel/pci-i386.c b/arch/i386/kernel/pci-i386.c
index af362611d..8e609ec36 100644
--- a/arch/i386/kernel/pci-i386.c
+++ b/arch/i386/kernel/pci-i386.c
@@ -177,7 +177,7 @@ static int __init pcibios_assign_resource(struct pci_dev *dev, int i)
* (4) Assign new addresses to resources which were either
* not configured at all or misconfigured. If explicitly
* requested by the user, configure expansion ROM address
- * as well. Finally enable the I/O and Memory bits.
+ * as well.
*/
static void __init pcibios_allocate_bus_resources(struct pci_bus *bus)
@@ -252,21 +252,18 @@ static void __init pcibios_allocate_resources(int pass)
static void __init pcibios_assign_resources(void)
{
struct pci_dev *dev;
- u16 cmd, old_cmd;
int idx;
- int fault = 0;
struct resource *r;
for(dev=pci_devices; dev; dev=dev->next) {
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- old_cmd = cmd;
for(idx=0; idx<6; idx++) {
r = &dev->resource[idx];
if (((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && idx < 4) ||
- ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO)))
+ ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO)) ||
+ !dev->class || (dev->class >> 8) == PCI_CLASS_BRIDGE_HOST)
/*
* Don't touch IDE controllers and I/O ports of video cards!
- * Neither enable anything in their command registers.
+ * Also avoid classless devices and host bridges.
*/
continue;
if (!r->start && r->end) {
@@ -275,24 +272,9 @@ static void __init pcibios_assign_resources(void)
* the BIOS forgot to do so or because we have decided the old
* address was unusable for some reason.
*/
- if (pcibios_assign_resource(dev, idx) < 0)
- fault = 1;
- }
- if (r->flags & IORESOURCE_IO)
- cmd |= PCI_COMMAND_IO;
- if (r->flags & IORESOURCE_MEM)
- cmd |= PCI_COMMAND_MEMORY;
- }
-
- if (cmd != old_cmd) {
- if (fault)
- printk("PCI: Not enabling device %s because of resource collisions\n", dev->slot_name);
- else {
- printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd);
- pci_write_config_word(dev, PCI_COMMAND, cmd);
+ pcibios_assign_resource(dev, idx);
}
}
-
if (pci_probe & PCI_ASSIGN_ROMS) {
r = &dev->resource[PCI_ROM_RESOURCE];
r->end -= r->start;
@@ -310,3 +292,29 @@ void __init pcibios_resource_survey(void)
pcibios_allocate_resources(1);
pcibios_assign_resources();
}
+
+int pcibios_enable_resources(struct pci_dev *dev)
+{
+ u16 cmd, old_cmd;
+ int idx;
+ struct resource *r;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ old_cmd = cmd;
+ for(idx=0; idx<6; idx++) {
+ r = &dev->resource[idx];
+ if (!r->start && r->end) {
+ printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name);
+ return -EINVAL;
+ }
+ if (r->flags & IORESOURCE_IO)
+ cmd |= PCI_COMMAND_IO;
+ if (r->flags & IORESOURCE_MEM)
+ cmd |= PCI_COMMAND_MEMORY;
+ }
+ if (cmd != old_cmd) {
+ printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd);
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ }
+ return 0;
+}
diff --git a/arch/i386/kernel/pci-i386.h b/arch/i386/kernel/pci-i386.h
index 41ac2b856..1be988b6c 100644
--- a/arch/i386/kernel/pci-i386.h
+++ b/arch/i386/kernel/pci-i386.h
@@ -18,12 +18,13 @@
#define PCI_NO_SORT 0x100
#define PCI_BIOS_SORT 0x200
#define PCI_NO_CHECKS 0x400
-#define PCI_NO_PEER_FIXUP 0x800
+#define PCI_PEER_FIXUP 0x800
#define PCI_ASSIGN_ROMS 0x1000
-#define PCI_NO_IRQ_SCAN 0x2000
+#define PCI_BIOS_IRQ_SCAN 0x2000
extern unsigned int pci_probe;
/* pci-i386.c */
void pcibios_resource_survey(void);
+int pcibios_enable_resources(struct pci_dev *);
diff --git a/arch/i386/kernel/pci-pc.c b/arch/i386/kernel/pci-pc.c
index 8ce187d3f..61d13af55 100644
--- a/arch/i386/kernel/pci-pc.c
+++ b/arch/i386/kernel/pci-pc.c
@@ -688,7 +688,7 @@ static struct irq_routing_table * __init pcibios_get_irq_routing_table(void)
struct irq_routing_table *rt;
int ret, map;
- if (pci_probe & PCI_NO_IRQ_SCAN)
+ if (!(pci_probe & PCI_BIOS_IRQ_SCAN))
return NULL;
pcibios_irq_page = __get_free_page(GFP_KERNEL);
if (!pcibios_irq_page)
@@ -868,7 +868,30 @@ static void __init pci_fixup_i450nx(struct pci_dev *d)
if (suba < subb)
pci_scan_bus(suba+1, pci_root->ops, NULL); /* Bus B */
}
- pci_probe |= PCI_NO_PEER_FIXUP;
+}
+
+static void __init pci_fixup_rcc(struct pci_dev *d)
+{
+ /*
+ * RCC host bridges -- Find and scan all secondary buses.
+ * Register 0x44 contains first, 0x45 last bus number routed there.
+ */
+ u8 busno;
+ pci_read_config_byte(d, 0x44, &busno);
+ printk("PCI: RCC host bridge: secondary bus %02x\n", busno);
+ pci_scan_bus(busno, pci_root->ops, NULL);
+}
+
+static void __init pci_fixup_compaq(struct pci_dev *d)
+{
+ /*
+ * Compaq host bridges -- Find and scan all secondary buses.
+ * This time registers 0xc8 and 0xc9.
+ */
+ u8 busno;
+ pci_read_config_byte(d, 0xc8, &busno);
+ printk("PCI: Compaq host bridge: secondary bus %02x\n", busno);
+ pci_scan_bus(busno, pci_root->ops, NULL);
}
static void __init pci_fixup_umc_ide(struct pci_dev *d)
@@ -905,6 +928,9 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d)
struct pci_fixup pcibios_fixups[] = {
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_RCC, PCI_DEVICE_ID_RCC_HE, pci_fixup_rcc },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_RCC, PCI_DEVICE_ID_RCC_LE, pci_fixup_rcc },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_6010, pci_fixup_compaq },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide },
{ PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases },
{ 0 }
@@ -919,6 +945,8 @@ extern int skip_ioapic_setup;
#define PIRQ_SIGNATURE (('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24))
#define PIRQ_VERSION 0x0100
+static struct irq_routing_table *pirq_table;
+
/*
* Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table.
*/
@@ -974,7 +1002,6 @@ static void __init pcibios_irq_peer_trick(struct irq_routing_table *rt)
*/
if (busmap[i] && pci_scan_bus(i, pci_root->ops, NULL))
printk("PCI: Discovered primary peer bus %02x [IRQ]\n", i);
- pci_probe |= PCI_NO_PEER_FIXUP;
}
/*
@@ -982,7 +1009,7 @@ static void __init pcibios_irq_peer_trick(struct irq_routing_table *rt)
* table, but unfortunately we have to know the interrupt router chip.
*/
-static char * __init pcibios_lookup_irq(struct pci_dev *dev, struct irq_routing_table *rt, int pin)
+static char *pcibios_lookup_irq(struct pci_dev *dev, struct irq_routing_table *rt, int pin, int assign)
{
struct irq_info *q;
struct pci_dev *router;
@@ -1012,9 +1039,9 @@ static char * __init pcibios_lookup_irq(struct pci_dev *dev, struct irq_routing_
return NULL;
}
DBG(" -> PIRQ %02x, mask %04x", pirq, mask);
- if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
+ if (!assign || (dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
newirq = 0;
- else for(newirq = 15; newirq && !(mask & (1 << newirq)); newirq--)
+ else for(newirq = 13; newirq && !(mask & (1 << newirq)); newirq--)
;
if (!(router = pci_find_slot(rt->rtr_bus, rt->rtr_devfn))) {
DBG(" -> router not found\n");
@@ -1068,7 +1095,7 @@ static void __init pcibios_fixup_irqs(void)
struct pci_dev *dev;
u8 pin;
- rtable = pcibios_find_irq_routing_table();
+ rtable = pirq_table = pcibios_find_irq_routing_table();
#ifdef CONFIG_PCI_BIOS
if (!rtable && pci_bios_present)
rtable = pcibios_get_irq_routing_table();
@@ -1106,7 +1133,7 @@ static void __init pcibios_fixup_irqs(void)
dev->irq = irq;
}
}
- rtable = NULL; /* Avoid IRQ assignment below */
+ pirq_table = NULL; /* Avoid automatic IRQ assignment */
}
#endif
/*
@@ -1114,10 +1141,10 @@ static void __init pcibios_fixup_irqs(void)
*/
if (dev->irq >= NR_IRQS)
dev->irq = 0;
- if (pin && !dev->irq && rtable && rtable->version) {
- char *msg = pcibios_lookup_irq(dev, rtable, pin);
+ if (pin && !dev->irq && pirq_table) {
+ char *msg = pcibios_lookup_irq(dev, pirq_table, pin, 0);
if (msg)
- printk("PCI: Assigned IRQ %d to device %s [%s]\n", dev->irq, dev->slot_name, msg);
+ printk("PCI: Found IRQ %d for device %s [%s]\n", dev->irq, dev->slot_name, msg);
}
}
@@ -1173,7 +1200,7 @@ void __init pcibios_init(void)
pci_scan_bus(0, ops, NULL);
pcibios_fixup_irqs();
- if (!(pci_probe & PCI_NO_PEER_FIXUP))
+ if (pci_probe & PCI_PEER_FIXUP)
pcibios_fixup_peer_bridges();
pcibios_resource_survey();
@@ -1199,8 +1226,8 @@ char * __init pcibios_setup(char *str)
} else if (!strcmp(str, "nosort")) {
pci_probe |= PCI_NO_SORT;
return NULL;
- } else if (!strcmp(str, "noirq")) {
- pci_probe |= PCI_NO_IRQ_SCAN;
+ } else if (!strcmp(str, "biosirq")) {
+ pci_probe |= PCI_BIOS_IRQ_SCAN;
return NULL;
}
#endif
@@ -1214,8 +1241,8 @@ char * __init pcibios_setup(char *str)
return NULL;
}
#endif
- else if (!strcmp(str, "nopeer")) {
- pci_probe |= PCI_NO_PEER_FIXUP;
+ else if (!strcmp(str, "peer")) {
+ pci_probe |= PCI_PEER_FIXUP;
return NULL;
} else if (!strcmp(str, "rom")) {
pci_probe |= PCI_ASSIGN_ROMS;
@@ -1223,3 +1250,21 @@ char * __init pcibios_setup(char *str)
}
return str;
}
+
+int pcibios_enable_device(struct pci_dev *dev)
+{
+ int err;
+
+ if ((err = pcibios_enable_resources(dev)) < 0)
+ return err;
+ if (!dev->irq && pirq_table) {
+ u8 pin;
+ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+ if (pin) {
+ char *msg = pcibios_lookup_irq(dev, pirq_table, pin, 1);
+ if (msg)
+ printk("PCI: Assigned IRQ %d to device %s [%s]\n", dev->irq, dev->slot_name, msg);
+ }
+ }
+ return 0;
+}
diff --git a/arch/i386/kernel/pci-visws.c b/arch/i386/kernel/pci-visws.c
index 31a767a22..8a954ce8b 100644
--- a/arch/i386/kernel/pci-visws.c
+++ b/arch/i386/kernel/pci-visws.c
@@ -14,6 +14,7 @@
#include <asm/smp.h>
#include <asm/lithium.h>
+#include <asm/io.h>
#include "pci-i386.h"
@@ -129,3 +130,8 @@ char * __init pcibios_setup(char *str)
{
return str;
}
+
+int pcibios_enable_device(struct pci_dev *dev)
+{
+ return pcibios_enable_resources(dev);
+}
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 734cfca65..31c77bb1d 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -54,7 +54,8 @@
#ifdef CONFIG_BLK_DEV_RAM
#include <linux/blk.h>
#endif
-#include <linux/bigmem.h>
+#include <linux/highmem.h>
+#include <linux/bootmem.h>
#include <asm/processor.h>
#include <linux/console.h>
#include <asm/uaccess.h>
@@ -401,12 +402,15 @@ void __init add_memory_region(unsigned long start,
} /* add_memory_region */
-#define LOWMEMSIZE() ((*(unsigned short *)__va(0x413)) * 1024)
-
+/*
+ * Do NOT EVER look at the BIOS memory size location.
+ * It does not work on many machines.
+ */
+#define LOWMEMSIZE() (0x9f000)
void __init setup_memory_region(void)
{
-#define E820_DEBUG 0
+#define E820_DEBUG 1
#ifdef E820_DEBUG
int i;
#endif
@@ -432,9 +436,8 @@ void __init setup_memory_region(void)
memcpy(e820.map, E820_MAP, e820.nr_map * sizeof e820.map[0]);
#ifdef E820_DEBUG
for (i=0; i < e820.nr_map; i++) {
- printk("e820: %ld @ %08lx ",
- (unsigned long)(e820.map[i].size),
- (unsigned long)(e820.map[i].addr));
+ printk("e820: %08x @ %08x ", (int)e820.map[i].size,
+ (int)e820.map[i].addr);
switch (e820.map[i].type) {
case E820_RAM: printk("(usable)\n");
break;
@@ -464,48 +467,11 @@ void __init setup_memory_region(void)
} /* setup_memory_region */
-void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p)
+static inline void parse_mem_cmdline (char ** cmdline_p)
{
- unsigned long high_pfn, max_pfn;
char c = ' ', *to = command_line, *from = COMMAND_LINE;
int len = 0;
- int i;
- int usermem=0;
-
-#ifdef CONFIG_VISWS
- visws_get_board_type_and_rev();
-#endif
-
- ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
- drive_info = DRIVE_INFO;
- screen_info = SCREEN_INFO;
- apm_bios_info = APM_BIOS_INFO;
- if( SYS_DESC_TABLE.length != 0 ) {
- MCA_bus = SYS_DESC_TABLE.table[3] &0x2;
- machine_id = SYS_DESC_TABLE.table[0];
- machine_submodel_id = SYS_DESC_TABLE.table[1];
- BIOS_revision = SYS_DESC_TABLE.table[2];
- }
- aux_device_present = AUX_DEVICE_INFO;
-
-#ifdef CONFIG_BLK_DEV_RAM
- rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
- rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
- rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
-#endif
- setup_memory_region();
-
- if (!MOUNT_ROOT_RDONLY)
- root_mountflags &= ~MS_RDONLY;
- init_mm.start_code = (unsigned long) &_text;
- init_mm.end_code = (unsigned long) &_etext;
- init_mm.end_data = (unsigned long) &_edata;
- init_mm.brk = (unsigned long) &_end;
-
- code_resource.start = virt_to_bus(&_text);
- code_resource.end = virt_to_bus(&_etext)-1;
- data_resource.start = virt_to_bus(&_etext);
- data_resource.end = virt_to_bus(&_edata)-1;
+ int usermem = 0;
/* Save unparsed command line copy for /proc/cmdline */
memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
@@ -519,8 +485,9 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigne
* "mem=XXX[KkmM]@XXX[KkmM]" defines a memory region from
* <start> to <start>+<mem>, overriding the bios size.
*/
- if (c == ' ' && *(const unsigned long *)from == *(const unsigned long *)"mem=") {
- if (to != command_line) to--;
+ if (c == ' ' && !memcmp(from, "mem=", 4)) {
+ if (to != command_line)
+ to--;
if (!memcmp(from+4, "nopentium", 9)) {
from += 9+4;
boot_cpu_data.x86_capability &= ~X86_FEATURE_PSE;
@@ -542,7 +509,7 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigne
}
mem_size = memparse(from+4, &from);
if (*from == '@')
- start_at = memparse(from+1,&from);
+ start_at = memparse(from+1, &from);
else {
start_at = HIGH_MEMORY;
mem_size -= HIGH_MEMORY;
@@ -559,54 +526,166 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigne
}
*to = '\0';
*cmdline_p = command_line;
+}
- /* Find the highest page frame number we have available */
- max_pfn = 0;
- for (i=0; i < e820.nr_map; i++) {
- /* RAM? */
- if (e820.map[i].type == E820_RAM) {
- unsigned long end_pfn = (e820.map[i].addr + e820.map[i].size) >> PAGE_SHIFT;
+void __init setup_arch(char **cmdline_p)
+{
+ unsigned long bootmap_size;
+ unsigned long start_pfn, max_pfn, max_low_pfn;
+ int i;
- if (end_pfn > max_pfn)
- max_pfn = end_pfn;
- }
+#ifdef CONFIG_VISWS
+ visws_get_board_type_and_rev();
+#endif
+
+ ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
+ drive_info = DRIVE_INFO;
+ screen_info = SCREEN_INFO;
+ apm_bios_info = APM_BIOS_INFO;
+ if( SYS_DESC_TABLE.length != 0 ) {
+ MCA_bus = SYS_DESC_TABLE.table[3] &0x2;
+ machine_id = SYS_DESC_TABLE.table[0];
+ machine_submodel_id = SYS_DESC_TABLE.table[1];
+ BIOS_revision = SYS_DESC_TABLE.table[2];
}
+ aux_device_present = AUX_DEVICE_INFO;
-/*
- * We can only allocate a limited amount of direct-mapped memory
- */
-#define VMALLOC_RESERVE (128 << 20) /* 128MB for vmalloc and initrd */
-#define MAXMEM ((unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE))
-#define MAXMEM_PFN (MAXMEM >> PAGE_SHIFT)
+#ifdef CONFIG_BLK_DEV_RAM
+ rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
+ rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
+ rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
+#endif
+ setup_memory_region();
+
+ if (!MOUNT_ROOT_RDONLY)
+ root_mountflags &= ~MS_RDONLY;
+ init_mm.start_code = (unsigned long) &_text;
+ init_mm.end_code = (unsigned long) &_etext;
+ init_mm.end_data = (unsigned long) &_edata;
+ init_mm.brk = (unsigned long) &_end;
- high_pfn = MAXMEM_PFN;
- if (max_pfn < high_pfn)
- high_pfn = max_pfn;
+ code_resource.start = virt_to_bus(&_text);
+ code_resource.end = virt_to_bus(&_etext)-1;
+ data_resource.start = virt_to_bus(&_etext);
+ data_resource.end = virt_to_bus(&_edata)-1;
+
+ parse_mem_cmdline(cmdline_p);
+
+#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
+#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
/*
- * But the bigmem stuff may be able to use more of it
- * (but currently only up to about 4GB)
+ * 128MB for vmalloc and initrd
*/
-#ifdef CONFIG_BIGMEM
- #define MAXBIGMEM ((unsigned long)(~(VMALLOC_RESERVE-1)))
- #define MAXBIGMEM_PFN (MAXBIGMEM >> PAGE_SHIFT)
- if (max_pfn > MAX_PFN)
- max_pfn = MAX_PFN;
-
-/* When debugging, make half of "normal" memory be BIGMEM memory instead */
-#ifdef BIGMEM_DEBUG
- high_pfn >>= 1;
-#endif
+#define VMALLOC_RESERVE (unsigned long)(128 << 20)
+#define MAXMEM (unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE)
+#define MAXMEM_PFN PFN_DOWN(MAXMEM)
+
+ /*
+ * partially used pages are not usable - thus
+ * we are rounding upwards:
+ */
+ start_pfn = PFN_UP(__pa(&_end));
- bigmem_start = high_pfn << PAGE_SHIFT;
- bigmem_end = max_pfn << PAGE_SHIFT;
- printk(KERN_NOTICE "%ldMB BIGMEM available.\n", (bigmem_end-bigmem_start) >> 20);
+ /*
+ * Find the highest page frame number we have available
+ */
+ max_pfn = 0;
+ for (i = 0; i < e820.nr_map; i++) {
+ unsigned long curr_pfn;
+ /* RAM? */
+ if (e820.map[i].type != E820_RAM)
+ continue;
+ curr_pfn = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
+ if (curr_pfn > max_pfn)
+ max_pfn = curr_pfn;
+ }
+
+ /*
+ * Determine low and high memory ranges:
+ */
+ max_low_pfn = max_pfn;
+ if (max_low_pfn > MAXMEM_PFN)
+ max_low_pfn = MAXMEM_PFN;
+
+#ifdef CONFIG_HIGHMEM
+ highstart_pfn = highend_pfn = max_pfn;
+ if (max_pfn > MAXMEM_PFN) {
+ highstart_pfn = MAXMEM_PFN;
+ highend_pfn = max_pfn;
+ printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
+ pages_to_mb(highend_pfn - highstart_pfn));
+ }
#endif
+ /*
+ * Initialize the boot-time allocator (with low memory only):
+ */
+ bootmap_size = init_bootmem(start_pfn, max_low_pfn);
+
+ /*
+ * FIXME: what about high memory?
+ */
+ ram_resources[1].end = PFN_PHYS(max_low_pfn);
+
+ /*
+ * Register fully available low RAM pages with the bootmem allocator.
+ */
+ for (i = 0; i < e820.nr_map; i++) {
+ unsigned long curr_pfn, last_pfn, size;
+ /*
+ * Reserve usable low memory
+ */
+ if (e820.map[i].type != E820_RAM)
+ continue;
+ /*
+ * We are rounding up the start address of usable memory:
+ */
+ curr_pfn = PFN_UP(e820.map[i].addr);
+ if (curr_pfn >= max_low_pfn)
+ continue;
+ /*
+ * ... and at the end of the usable range downwards:
+ */
+ last_pfn = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
- ram_resources[1].end = (high_pfn << PAGE_SHIFT)-1;
+ if (last_pfn > max_low_pfn)
+ last_pfn = max_low_pfn;
- *memory_start_p = (unsigned long) &_end;
- *memory_end_p = PAGE_OFFSET + (high_pfn << PAGE_SHIFT);
+ /*
+ * .. finally, did all the rounding and playing
+ * around just make the area go away?
+ */
+ if (last_pfn <= curr_pfn)
+ continue;
+
+ size = last_pfn - curr_pfn;
+ free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
+ }
+ /*
+ * Reserve the bootmem bitmap itself as well. We do this in two
+ * steps (first step was init_bootmem()) because this catches
+ * the (very unlikely) case of us accidentally initializing the
+ * bootmem allocator with an invalid RAM area.
+ */
+ reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(start_pfn) +
+ bootmap_size + PAGE_SIZE-1) - (HIGH_MEMORY));
+
+ /*
+ * reserve physical page 0 - it's a special BIOS page on many boxes,
+ * enabling clean reboots, SMP operation, laptop functions.
+ */
+ reserve_bootmem(0, PAGE_SIZE);
+
+#ifdef __SMP__
+ /*
+ * But first pinch a few for the stack/trampoline stuff
+ * FIXME: Don't need the extra page at 4K, but need to fix
+ * trampoline before removing it. (see the GDT stuff)
+ */
+ reserve_bootmem(PAGE_SIZE, PAGE_SIZE);
+ smp_alloc_memory(); /* AP processor realmode stacks in low memory*/
+#endif
#ifdef __SMP__
/*
@@ -616,10 +695,11 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigne
#endif
#ifdef CONFIG_BLK_DEV_INITRD
+// FIXME needs to do the new bootmem alloc stuff
if (LOADER_TYPE) {
initrd_start = INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
initrd_end = initrd_start+INITRD_SIZE;
- if (initrd_end > memory_end) {
+ if (initrd_end > (max_low_pfn << PAGE_SHIFT)) {
printk("initrd extends beyond end of memory "
"(0x%08lx > 0x%08lx)\ndisabling initrd\n",
initrd_end,memory_end);
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 46335ee8f..4386e8dd0 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -39,6 +39,7 @@
#include <linux/kernel_stat.h>
#include <linux/smp_lock.h>
#include <linux/irq.h>
+#include <linux/bootmem.h>
#include <linux/delay.h>
#include <linux/mc146818rtc.h>
@@ -630,12 +631,15 @@ static unsigned long __init setup_trampoline(void)
* We are called very early to get the low memory for the
* SMP bootup trampoline page.
*/
-unsigned long __init smp_alloc_memory(unsigned long mem_base)
+void __init smp_alloc_memory(void)
{
- if (virt_to_phys((void *)mem_base) >= 0x9F000)
+ trampoline_base = (void *) alloc_bootmem_low_pages(PAGE_SIZE);
+ /*
+ * Has to be in very low memory so we can execute
+ * real-mode AP code.
+ */
+ if (__pa(trampoline_base) >= 0x9F000)
BUG();
- trampoline_base = (void *)mem_base;
- return mem_base + PAGE_SIZE;
}
/*
@@ -804,11 +808,10 @@ void __init setup_local_APIC(void)
apic_write(APIC_DFR, value);
}
-unsigned long __init init_smp_mappings(unsigned long memory_start)
+void __init init_smp_mappings(void)
{
unsigned long apic_phys;
- memory_start = PAGE_ALIGN(memory_start);
if (smp_found_config) {
apic_phys = mp_lapic_addr;
} else {
@@ -818,11 +821,10 @@ unsigned long __init init_smp_mappings(unsigned long memory_start)
* could use the real zero-page, but it's safer
* this way if some buggy code writes to this page ...
*/
- apic_phys = __pa(memory_start);
- memset((void *)memory_start, 0, PAGE_SIZE);
- memory_start += PAGE_SIZE;
+ apic_phys = __pa(alloc_bootmem_pages(PAGE_SIZE));
+ memset((void *)apic_phys, 0, PAGE_SIZE);
}
- set_fixmap(FIX_APIC_BASE,apic_phys);
+ set_fixmap(FIX_APIC_BASE, apic_phys);
dprintk("mapped APIC to %08lx (%08lx)\n", APIC_BASE, apic_phys);
#ifdef CONFIG_X86_IO_APIC
@@ -834,9 +836,8 @@ unsigned long __init init_smp_mappings(unsigned long memory_start)
if (smp_found_config) {
ioapic_phys = mp_ioapics[i].mpc_apicaddr;
} else {
- ioapic_phys = __pa(memory_start);
- memset((void *)memory_start, 0, PAGE_SIZE);
- memory_start += PAGE_SIZE;
+ ioapic_phys = __pa(alloc_bootmem_pages(PAGE_SIZE));
+ memset((void *)ioapic_phys, 0, PAGE_SIZE);
}
set_fixmap(idx,ioapic_phys);
dprintk("mapped IOAPIC to %08lx (%08lx)\n",
@@ -845,8 +846,6 @@ unsigned long __init init_smp_mappings(unsigned long memory_start)
}
}
#endif
-
- return memory_start;
}
/*
@@ -1112,6 +1111,12 @@ int __init start_secondary(void *unused)
smp_callin();
while (!atomic_read(&smp_commenced))
/* nothing */ ;
+ /*
+ * low-memory mappings have been cleared, flush them from
+ * the local TLBs too.
+ */
+ local_flush_tlb();
+
return cpu_idle();
}
@@ -1153,7 +1158,6 @@ static int __init fork_by_hand(void)
static void __init do_boot_cpu(int i)
{
unsigned long cfg;
- pgd_t maincfg;
struct task_struct *idle;
unsigned long send_status, accept_status;
int timeout, num_starts, j;
@@ -1207,9 +1211,6 @@ static void __init do_boot_cpu(int i)
*((volatile unsigned short *) phys_to_virt(0x467)) = start_eip & 0xf;
dprintk("3.\n");
- maincfg=swapper_pg_dir[0];
- ((unsigned long *)swapper_pg_dir)[0]=0x102007;
-
/*
* Be paranoid about clearing APIC errors.
*/
@@ -1367,9 +1368,6 @@ static void __init do_boot_cpu(int i)
cpucount--;
}
- swapper_pg_dir[0]=maincfg;
- local_flush_tlb();
-
/* mark "stuck" area as not stuck */
*((volatile unsigned long *)phys_to_virt(8192)) = 0;
}
@@ -1567,14 +1565,9 @@ void __init smp_boot_cpus(void)
#ifndef CONFIG_VISWS
{
- unsigned long cfg;
-
/*
* Install writable page 0 entry to set BIOS data area.
*/
- cfg = pg0[0];
- /* writeable, present, addr 0 */
- pg0[0] = _PAGE_RW | _PAGE_PRESENT | 0;
local_flush_tlb();
/*
@@ -1584,12 +1577,6 @@ void __init smp_boot_cpus(void)
CMOS_WRITE(0, 0xf);
*((volatile long *) phys_to_virt(0x467)) = 0;
-
- /*
- * Restore old page 0 entry.
- */
- pg0[0] = cfg;
- local_flush_tlb();
}
#endif
@@ -1646,5 +1633,7 @@ smp_done:
*/
if (cpu_has_tsc && cpucount)
synchronize_tsc_bp();
+
+ zap_low_mappings();
}
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index ebd1cd002..f66f2363c 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -581,6 +581,7 @@ asmlinkage void math_emulate(long arg)
#endif /* CONFIG_MATH_EMULATION */
+#ifndef CONFIG_M686
void __init trap_init_f00f_bug(void)
{
unsigned long page;
@@ -596,8 +597,8 @@ void __init trap_init_f00f_bug(void)
pgd = pgd_offset(&init_mm, page);
pmd = pmd_offset(pgd, page);
pte = pte_offset(pmd, page);
- free_page(pte_page(*pte));
- *pte = mk_pte(&idt_table, PAGE_KERNEL_RO);
+ __free_page(pte_page(*pte));
+ *pte = mk_pte_phys(__pa(&idt_table), PAGE_KERNEL_RO);
local_flush_tlb();
/*
@@ -608,6 +609,7 @@ void __init trap_init_f00f_bug(void)
idt = (struct desc_struct *)page;
__asm__ __volatile__("lidt %0": "=m" (idt_descr));
}
+#endif
#define _set_gate(gate_addr,type,dpl,addr) \
do { \
@@ -772,7 +774,7 @@ cobalt_init(void)
#endif
void __init trap_init(void)
{
- if (readl(0x0FFFD9) == 'E' + ('I'<<8) + ('S'<<16) + ('A'<<24))
+ if (isa_readl(0x0FFFD9) == 'E'+('I'<<8)+('S'<<16)+('A'<<24))
EISA_bus = 1;
set_trap_gate(0,&divide_error);
diff --git a/arch/i386/kernel/visws_apic.c b/arch/i386/kernel/visws_apic.c
index de79fe61e..6c767d0eb 100644
--- a/arch/i386/kernel/visws_apic.c
+++ b/arch/i386/kernel/visws_apic.c
@@ -37,7 +37,7 @@
#include <asm/cobalt.h>
-#include "irq.h"
+#include <linux/irq.h>
/*
* This is the PIIX4-based 8259 that is wired up indirectly to Cobalt
diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
index 65dd7e9da..3fd5262ac 100644
--- a/arch/i386/kernel/vm86.c
+++ b/arch/i386/kernel/vm86.c
@@ -102,7 +102,7 @@ static void mark_screen_rdonly(struct task_struct * tsk)
if (pgd_none(*pgd))
return;
if (pgd_bad(*pgd)) {
- printk("vm86: bad pgd entry [%p]:%08lx\n", pgd, pgd_val(*pgd));
+ pgd_ERROR(*pgd);
pgd_clear(pgd);
return;
}
@@ -110,7 +110,7 @@ static void mark_screen_rdonly(struct task_struct * tsk)
if (pmd_none(*pmd))
return;
if (pmd_bad(*pmd)) {
- printk("vm86: bad pmd entry [%p]:%08lx\n", pmd, pmd_val(*pmd));
+ pmd_ERROR(*pmd);
pmd_clear(pmd);
return;
}
diff --git a/arch/i386/lib/Makefile b/arch/i386/lib/Makefile
index 3f7bef4aa..5c824c08c 100644
--- a/arch/i386/lib/Makefile
+++ b/arch/i386/lib/Makefile
@@ -7,7 +7,7 @@
L_TARGET = lib.a
L_OBJS = checksum.o old-checksum.o delay.o \
- usercopy.o getuser.o putuser.o
+ usercopy.o getuser.o putuser.o iodebug.o
ifdef CONFIG_X86_USE_3DNOW
L_OBJS += mmx.o
diff --git a/arch/i386/lib/iodebug.c b/arch/i386/lib/iodebug.c
new file mode 100644
index 000000000..701a07fe7
--- /dev/null
+++ b/arch/i386/lib/iodebug.c
@@ -0,0 +1,19 @@
+#include <asm/io.h>
+
+void * __io_virt_debug(unsigned long x, const char *file, int line)
+{
+ if (x < PAGE_OFFSET) {
+ printk("io mapaddr 0x%05lx not valid at %s:%d!\n", x, file, line);
+ return __va(x);
+ }
+ return (void *)x;
+}
+
+unsigned long __io_phys_debug(unsigned long x, const char *file, int line)
+{
+ if (x < PAGE_OFFSET) {
+ printk("io mapaddr 0x%05lx not valid at %s:%d!\n", x, file, line);
+ return x;
+ }
+ return __pa(x);
+}
diff --git a/arch/i386/mm/Makefile b/arch/i386/mm/Makefile
index d60bc1969..cee7d4e6d 100644
--- a/arch/i386/mm/Makefile
+++ b/arch/i386/mm/Makefile
@@ -10,8 +10,4 @@
O_TARGET := mm.o
O_OBJS := init.o fault.o ioremap.o extable.o
-ifeq ($(CONFIG_BIGMEM),y)
-O_OBJS += bigmem.o
-endif
-
include $(TOPDIR)/Rules.make
diff --git a/arch/i386/mm/bigmem.c b/arch/i386/mm/bigmem.c
deleted file mode 100644
index 8da077927..000000000
--- a/arch/i386/mm/bigmem.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * BIGMEM IA32 code and variables.
- *
- * (C) 1999 Andrea Arcangeli, SuSE GmbH, andrea@suse.de
- * Gerhard Wichert, Siemens AG, Gerhard.Wichert@pdb.siemens.de
- */
-
-#include <linux/mm.h>
-#include <linux/bigmem.h>
-
-unsigned long bigmem_start, bigmem_end;
-
-/* NOTE: fixmap_init alloc all the fixmap pagetables contigous on the
- physical space so we can cache the place of the first one and move
- around without checking the pgd every time. */
-pte_t *kmap_pte;
-pgprot_t kmap_prot;
-
-#define kmap_get_fixmap_pte(vaddr) \
- pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
-
-void __init kmap_init(void)
-{
- unsigned long kmap_vstart;
-
- /* cache the first kmap pte */
- kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
- kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
-
- kmap_prot = PAGE_KERNEL;
- if (boot_cpu_data.x86_capability & X86_FEATURE_PGE)
- pgprot_val(kmap_prot) |= _PAGE_GLOBAL;
-}
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
index 1f7879005..b2a98859b 100644
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -76,6 +76,31 @@ bad_area:
return 0;
}
+static inline void handle_wp_test (void)
+{
+ const unsigned long vaddr = PAGE_OFFSET;
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ /*
+ * make it read/writable temporarily, so that the fault
+ * can be handled.
+ */
+ pgd = swapper_pg_dir + __pgd_offset(vaddr);
+ pmd = pmd_offset(pgd, vaddr);
+ pte = pte_offset(pmd, vaddr);
+ *pte = mk_pte_phys(0, PAGE_KERNEL);
+ local_flush_tlb();
+
+ boot_cpu_data.wp_works_ok = 1;
+ /*
+ * Beware: Black magic here. The printk is needed here to flush
+ * CPU state on certain buggy processors.
+ */
+ printk("Ok");
+}
+
asmlinkage void do_invalid_op(struct pt_regs *, unsigned long);
extern unsigned long idt;
@@ -226,15 +251,8 @@ no_context:
* First we check if it was the bootup rw-test, though..
*/
if (boot_cpu_data.wp_works_ok < 0 &&
- address == PAGE_OFFSET && (error_code & 1)) {
- boot_cpu_data.wp_works_ok = 1;
- pg0[0] = pte_val(mk_pte(PAGE_OFFSET, PAGE_KERNEL));
- local_flush_tlb();
- /*
- * Beware: Black magic here. The printk is needed here to flush
- * CPU state on certain buggy processors.
- */
- printk("Ok");
+ address == PAGE_OFFSET && (error_code & 1)) {
+ handle_wp_test();
return;
}
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index b1140f892..d2089fbd0 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -22,7 +22,9 @@
#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/blk.h>
#endif
-#include <linux/bigmem.h>
+#include <linux/highmem.h>
+#include <linux/pagemap.h>
+#include <linux/bootmem.h>
#include <asm/processor.h>
#include <asm/system.h>
@@ -32,22 +34,81 @@
#include <asm/fixmap.h>
#include <asm/e820.h>
-static unsigned long totalram = 0;
-static unsigned long totalbig = 0;
+unsigned long highstart_pfn, highend_pfn;
+static unsigned long totalram_pages = 0;
+static unsigned long totalhigh_pages = 0;
extern void show_net_buffers(void);
-extern unsigned long init_smp_mappings(unsigned long);
-void __bad_pte_kernel(pmd_t *pmd)
+/*
+ * BAD_PAGE is the page that is used for page faults when linux
+ * is out-of-memory. Older versions of linux just did a
+ * do_exit(), but using this instead means there is less risk
+ * for a process dying in kernel mode, possibly leaving an inode
+ * unused etc..
+ *
+ * BAD_PAGETABLE is the accompanying page-table: it is initialized
+ * to point to BAD_PAGE entries.
+ *
+ * ZERO_PAGE is a special page that is used for zero-initialized
+ * data and COW.
+ */
+
+/*
+ * These are allocated in head.S so that we get proper page alignment.
+ * If you change the size of these then change head.S as well.
+ */
+extern char empty_bad_page[PAGE_SIZE];
+#if CONFIG_X86_PAE
+extern pmd_t empty_bad_pmd_table[PTRS_PER_PMD];
+#endif
+extern pte_t empty_bad_pte_table[PTRS_PER_PTE];
+
+/*
+ * We init them before every return and make them writable-shared.
+ * This guarantees we get out of the kernel in some more or less sane
+ * way.
+ */
+#if CONFIG_X86_PAE
+static pmd_t * get_bad_pmd_table(void)
{
- printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
- pmd_val(*pmd) = _KERNPG_TABLE + __pa(BAD_PAGETABLE);
+ pmd_t v;
+ int i;
+
+ pmd_val(v) = _PAGE_TABLE + __pa(empty_bad_pte_table);
+
+ for (i = 0; i < PAGE_SIZE/sizeof(pmd_t); i++)
+ empty_bad_pmd_table[i] = v;
+
+ return empty_bad_pmd_table;
}
+#endif
-void __bad_pte(pmd_t *pmd)
+static pte_t * get_bad_pte_table(void)
{
- printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
- pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE);
+ pte_t v;
+ int i;
+
+ v = pte_mkdirty(mk_pte_phys(__pa(empty_bad_page), PAGE_SHARED));
+
+ for (i = 0; i < PAGE_SIZE/sizeof(pte_t); i++)
+ empty_bad_pte_table[i] = v;
+
+ return empty_bad_pte_table;
+}
+
+
+
+void __handle_bad_pmd(pmd_t *pmd)
+{
+ pmd_ERROR(*pmd);
+ pmd_val(*pmd) = _PAGE_TABLE + __pa(get_bad_pte_table());
+}
+
+void __handle_bad_pmd_kernel(pmd_t *pmd)
+{
+ pmd_ERROR(*pmd);
+ pmd_val(*pmd) = _KERNPG_TABLE + __pa(get_bad_pte_table());
}
pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long offset)
@@ -57,16 +118,16 @@ pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long offset)
pte = (pte_t *) __get_free_page(GFP_KERNEL);
if (pmd_none(*pmd)) {
if (pte) {
- clear_page((unsigned long)pte);
+ clear_page(pte);
pmd_val(*pmd) = _KERNPG_TABLE + __pa(pte);
return pte + offset;
}
- pmd_val(*pmd) = _KERNPG_TABLE + __pa(BAD_PAGETABLE);
+ pmd_val(*pmd) = _KERNPG_TABLE + __pa(get_bad_pte_table());
return NULL;
}
free_page((unsigned long)pte);
if (pmd_bad(*pmd)) {
- __bad_pte_kernel(pmd);
+ __handle_bad_pmd_kernel(pmd);
return NULL;
}
return (pte_t *) pmd_page(*pmd) + offset;
@@ -79,19 +140,19 @@ pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
pte = (unsigned long) __get_free_page(GFP_KERNEL);
if (pmd_none(*pmd)) {
if (pte) {
- clear_page(pte);
+ clear_page((void *)pte);
pmd_val(*pmd) = _PAGE_TABLE + __pa(pte);
- return (pte_t *)(pte + offset);
+ return (pte_t *)pte + offset;
}
- pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE);
+ pmd_val(*pmd) = _PAGE_TABLE + __pa(get_bad_pte_table());
return NULL;
}
free_page(pte);
if (pmd_bad(*pmd)) {
- __bad_pte(pmd);
+ __handle_bad_pmd(pmd);
return NULL;
}
- return (pte_t *) (pmd_page(*pmd) + offset);
+ return (pte_t *) pmd_page(*pmd) + offset;
}
int do_check_pgt_cache(int low, int high)
@@ -110,52 +171,36 @@ int do_check_pgt_cache(int low, int high)
return freed;
}
-/*
- * BAD_PAGE is the page that is used for page faults when linux
- * is out-of-memory. Older versions of linux just did a
- * do_exit(), but using this instead means there is less risk
- * for a process dying in kernel mode, possibly leaving an inode
- * unused etc..
- *
- * BAD_PAGETABLE is the accompanying page-table: it is initialized
- * to point to BAD_PAGE entries.
- *
- * ZERO_PAGE is a special page that is used for zero-initialized
- * data and COW.
- */
-pte_t * __bad_pagetable(void)
-{
- extern char empty_bad_page_table[PAGE_SIZE];
- int d0, d1;
-
- __asm__ __volatile__("cld ; rep ; stosl"
- : "=&D" (d0), "=&c" (d1)
- : "a" (pte_val(BAD_PAGE)),
- "0" ((long) empty_bad_page_table),
- "1" (PAGE_SIZE/4)
- : "memory");
- return (pte_t *) empty_bad_page_table;
-}
+/* NOTE: fixmap_init alloc all the fixmap pagetables contigous on the
+ physical space so we can cache the place of the first one and move
+ around without checking the pgd every time. */
+
+#if CONFIG_HIGHMEM
+pte_t *kmap_pte;
+pgprot_t kmap_prot;
-pte_t __bad_page(void)
+#define kmap_get_fixmap_pte(vaddr) \
+ pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
+
+void __init kmap_init(void)
{
- extern char empty_bad_page[PAGE_SIZE];
- int d0, d1;
-
- __asm__ __volatile__("cld ; rep ; stosl"
- : "=&D" (d0), "=&c" (d1)
- : "a" (0),
- "0" ((long) empty_bad_page),
- "1" (PAGE_SIZE/4)
- : "memory");
- return pte_mkdirty(mk_pte((unsigned long) empty_bad_page, PAGE_SHARED));
+ unsigned long kmap_vstart;
+
+ /* cache the first kmap pte */
+ kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
+ kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
+
+ kmap_prot = PAGE_KERNEL;
+ if (boot_cpu_data.x86_capability & X86_FEATURE_PGE)
+ pgprot_val(kmap_prot) |= _PAGE_GLOBAL;
}
+#endif
void show_mem(void)
{
- int i,free = 0,total = 0,reserved = 0;
+ int i,free = 0, total = 0, reserved = 0;
int shared = 0, cached = 0;
- int bigmem = 0;
+ int highmem = 0;
printk("Mem-info:\n");
show_free_areas();
@@ -163,8 +208,8 @@ void show_mem(void)
i = max_mapnr;
while (i-- > 0) {
total++;
- if (PageBIGMEM(mem_map+i))
- bigmem++;
+ if (PageHighMem(mem_map+i))
+ highmem++;
if (PageReserved(mem_map+i))
reserved++;
else if (PageSwapCache(mem_map+i))
@@ -174,59 +219,42 @@ void show_mem(void)
else
shared += page_count(mem_map+i) - 1;
}
- printk("%d pages of RAM\n",total);
- printk("%d pages of BIGMEM\n",bigmem);
+ printk("%d pages of RAM\n", total);
+ printk("%d pages of HIGHMEM\n",highmem);
printk("%d reserved pages\n",reserved);
printk("%d pages shared\n",shared);
printk("%d pages swap cached\n",cached);
printk("%ld pages in page table cache\n",pgtable_cache_size);
+ show_buffers();
#ifdef CONFIG_NET
show_net_buffers();
#endif
}
-extern unsigned long free_area_init(unsigned long, unsigned long);
-
/* References to section boundaries */
extern char _text, _etext, _edata, __bss_start, _end;
extern char __init_begin, __init_end;
-/*
- * allocate page table(s) for compile-time fixed mappings
- */
-static unsigned long __init fixmap_init(unsigned long start_mem)
-{
- pgd_t * pg_dir;
- unsigned int idx;
- unsigned long address;
-
- start_mem = PAGE_ALIGN(start_mem);
-
- for (idx=1; idx <= __end_of_fixed_addresses; idx += PTRS_PER_PTE)
- {
- address = __fix_to_virt(__end_of_fixed_addresses-idx);
- pg_dir = swapper_pg_dir + (address >> PGDIR_SHIFT);
- memset((void *)start_mem, 0, PAGE_SIZE);
- pgd_val(*pg_dir) = _PAGE_TABLE | __pa(start_mem);
- start_mem += PAGE_SIZE;
- }
-
- return start_mem;
-}
-
static void set_pte_phys (unsigned long vaddr, unsigned long phys)
{
pgprot_t prot;
- pte_t * pte;
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
- pte = pte_offset(pmd_offset(pgd_offset_k(vaddr), vaddr), vaddr);
+ pgd = swapper_pg_dir + __pgd_offset(vaddr);
+ pmd = pmd_offset(pgd, vaddr);
+ pte = pte_offset(pmd, vaddr);
prot = PAGE_KERNEL;
if (boot_cpu_data.x86_capability & X86_FEATURE_PGE)
pgprot_val(prot) |= _PAGE_GLOBAL;
set_pte(pte, mk_pte_phys(phys, prot));
- local_flush_tlb();
+ /*
+ * It's enough to flush this one mapping.
+ */
+ __flush_tlb_one(vaddr);
}
void set_fixmap (enum fixed_addresses idx, unsigned long phys)
@@ -240,6 +268,123 @@ void set_fixmap (enum fixed_addresses idx, unsigned long phys)
set_pte_phys (address,phys);
}
+static void __init pagetable_init(void)
+{
+ pgd_t *pgd, *pgd_base;
+ pmd_t *pmd;
+ pte_t *pte;
+ int i, j, k;
+ unsigned long vaddr;
+ unsigned long end = (unsigned long)__va(max_low_pfn*PAGE_SIZE);
+
+ pgd_base = swapper_pg_dir;
+
+ vaddr = PAGE_OFFSET;
+ i = __pgd_offset(vaddr);
+ pgd = pgd_base + i;
+
+ for (; (i < PTRS_PER_PGD) && (vaddr <= end); pgd++, i++) {
+ vaddr = i*PGDIR_SIZE;
+#if CONFIG_X86_PAE
+ pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ memset((void*)pmd, 0, PAGE_SIZE);
+ pgd_val(*pgd) = __pa(pmd) + 0x1;
+#else
+ pmd = (pmd_t *)pgd;
+#endif
+ if (pmd != pmd_offset(pgd, 0))
+ BUG();
+ for (j = 0; (j < PTRS_PER_PMD) && (vaddr <= end); pmd++, j++) {
+ vaddr = i*PGDIR_SIZE + j*PMD_SIZE;
+ if (cpu_has_pse) {
+ unsigned long __pe;
+
+ set_in_cr4(X86_CR4_PSE);
+ boot_cpu_data.wp_works_ok = 1;
+ __pe = _KERNPG_TABLE + _PAGE_PSE + __pa(vaddr);
+ /* Make it "global" too if supported */
+ if (cpu_has_pge) {
+ set_in_cr4(X86_CR4_PGE);
+ __pe += _PAGE_GLOBAL;
+ }
+ pmd_val(*pmd) = __pe;
+ continue;
+ }
+
+ pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ memset((void*)pte, 0, PAGE_SIZE);
+ pmd_val(*pmd) = _KERNPG_TABLE + __pa(pte);
+
+ if (pte != pte_offset(pmd, 0))
+ BUG();
+
+ for (k = 0;
+ (k < PTRS_PER_PTE) && (vaddr <= end);
+ pte++, k++) {
+ vaddr = i*PGDIR_SIZE + j*PMD_SIZE + k*PAGE_SIZE;
+ *pte = mk_pte_phys(__pa(vaddr), PAGE_KERNEL);
+ }
+ }
+ }
+
+ /*
+ * Fixed mappings, only the page table structure has to be
+ * created - mappings will be set by set_fixmap():
+ */
+
+ vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
+ i = __pgd_offset(vaddr);
+ j = __pmd_offset(vaddr);
+ pgd = pgd_base + i;
+
+ for ( ; (i < PTRS_PER_PGD) && vaddr; pgd++, i++) {
+#if CONFIG_X86_PAE
+ if (pgd_none(*pgd)) {
+ pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ memset((void*)pmd, 0, PAGE_SIZE);
+ pgd_val(*pgd) = __pa(pmd) + 0x1;
+ if (pmd != pmd_offset(pgd, vaddr))
+ BUG();
+ }
+ pmd = pmd_offset(pgd, vaddr);
+#else
+ pmd = (pmd_t *)pgd;
+#endif
+ for (; (j < PTRS_PER_PMD) && vaddr; pmd++, j++) {
+ if (pmd_none(*pmd)) {
+ pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ memset((void*)pte, 0, PAGE_SIZE);
+ pmd_val(*pmd) = _KERNPG_TABLE + __pa(pte);
+ if (pte != pte_offset(pmd, 0))
+ BUG();
+ }
+ vaddr += PMD_SIZE;
+ }
+ j = 0;
+ }
+
+#if CONFIG_X86_PAE
+ /*
+ * Add low memory identity-mappings - SMP needs it when
+ * starting up on an AP from real-mode. In the non-PAE
+ * case we already have these mappings through head.S.
+ * All user-space mappings are explicitly cleared after
+ * SMP startup.
+ */
+ pgd_base[0] = pgd_base[USER_PTRS_PER_PGD];
+#endif
+}
+
+void __init zap_low_mappings (void)
+{
+ int i;
+ /*
+ * Zap initial low-memory mappings:
+ */
+ for (i = 0; i < USER_PTRS_PER_PGD; i++)
+ pgd_clear(swapper_pg_dir + i);
+}
+
/*
* paging_init() sets up the page tables - note that the first 4MB are
* already mapped by head.S.
@@ -247,89 +392,36 @@ void set_fixmap (enum fixed_addresses idx, unsigned long phys)
* This routines also unmaps the page at virtual kernel address 0, so
* that we can trap those pesky NULL-reference errors in the kernel.
*/
-unsigned long __init paging_init(unsigned long start_mem, unsigned long end_mem)
+void __init paging_init(void)
{
- pgd_t * pg_dir;
- pte_t * pg_table;
- unsigned long tmp;
- unsigned long address;
+ pagetable_init();
-/*
- * Physical page 0 is special; it's not touched by Linux since BIOS
- * and SMM (for laptops with [34]86/SL chips) may need it. It is read
- * and write protected to detect null pointer references in the
- * kernel.
- * It may also hold the MP configuration table when we are booting SMP.
- */
- start_mem = PAGE_ALIGN(start_mem);
- address = PAGE_OFFSET;
- pg_dir = swapper_pg_dir;
- /* unmap the original low memory mappings */
- pgd_val(pg_dir[0]) = 0;
-
- /* Map whole memory from PAGE_OFFSET */
- pg_dir += USER_PGD_PTRS;
- while (address < end_mem) {
- /*
- * If we're running on a Pentium CPU, we can use the 4MB
- * page tables.
- *
- * The page tables we create span up to the next 4MB
- * virtual memory boundary, but that's OK as we won't
- * use that memory anyway.
- */
- if (boot_cpu_data.x86_capability & X86_FEATURE_PSE) {
- unsigned long __pe;
-
- set_in_cr4(X86_CR4_PSE);
- boot_cpu_data.wp_works_ok = 1;
- __pe = _KERNPG_TABLE + _PAGE_4M + __pa(address);
- /* Make it "global" too if supported */
- if (boot_cpu_data.x86_capability & X86_FEATURE_PGE) {
- set_in_cr4(X86_CR4_PGE);
- __pe += _PAGE_GLOBAL;
- }
- pgd_val(*pg_dir) = __pe;
- pg_dir++;
- address += 4*1024*1024;
- continue;
- }
+ __asm__( "movl %%ecx,%%cr3\n" ::"c"(__pa(swapper_pg_dir)));
- /*
- * We're on a [34]86, use normal page tables.
- * pg_table is physical at this point
- */
- pg_table = (pte_t *) (PAGE_MASK & pgd_val(*pg_dir));
- if (!pg_table) {
- pg_table = (pte_t *) __pa(start_mem);
- start_mem += PAGE_SIZE;
- }
+#if CONFIG_X86_PAE
+ /*
+ * We will bail out later - printk doesnt work right now so
+ * the user would just see a hanging kernel.
+ */
+ if (cpu_has_pae)
+ set_in_cr4(X86_CR4_PAE);
+#endif
+
+ __flush_tlb();
- pgd_val(*pg_dir) = _PAGE_TABLE | (unsigned long) pg_table;
- pg_dir++;
-
- /* now change pg_table to kernel virtual addresses */
- pg_table = (pte_t *) __va(pg_table);
- for (tmp = 0 ; tmp < PTRS_PER_PTE ; tmp++,pg_table++) {
- pte_t pte = mk_pte(address, PAGE_KERNEL);
- if (address >= end_mem)
- pte_val(pte) = 0;
- set_pte(pg_table, pte);
- address += PAGE_SIZE;
- }
- }
- start_mem = fixmap_init(start_mem);
#ifdef __SMP__
- start_mem = init_smp_mappings(start_mem);
+ init_smp_mappings();
#endif
- local_flush_tlb();
-#ifndef CONFIG_BIGMEM
- return free_area_init(start_mem, end_mem);
-#else
+#ifdef CONFIG_HIGHMEM
kmap_init(); /* run after fixmap_init */
- return free_area_init(start_mem, bigmem_end + PAGE_OFFSET);
#endif
+#ifdef CONFIG_HIGHMEM
+ free_area_init(highend_pfn);
+#else
+ free_area_init(max_low_pfn);
+#endif
+ return;
}
/*
@@ -340,23 +432,38 @@ unsigned long __init paging_init(unsigned long start_mem, unsigned long end_mem)
void __init test_wp_bit(void)
{
- unsigned char tmp_reg;
- unsigned long old = pg0[0];
+/*
+ * Ok, all PAE-capable CPUs are definitely handling the WP bit right.
+ */
+//#ifndef CONFIG_X86_PAE
+ const unsigned long vaddr = PAGE_OFFSET;
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte, old_pte;
+ char tmp_reg;
printk("Checking if this processor honours the WP bit even in supervisor mode... ");
- pg0[0] = pte_val(mk_pte(PAGE_OFFSET, PAGE_READONLY));
+
+ pgd = swapper_pg_dir + __pgd_offset(vaddr);
+ pmd = pmd_offset(pgd, vaddr);
+ pte = pte_offset(pmd, vaddr);
+ old_pte = *pte;
+ *pte = mk_pte_phys(0, PAGE_READONLY);
local_flush_tlb();
+
__asm__ __volatile__(
"jmp 1f; 1:\n"
"movb %0,%1\n"
"movb %1,%0\n"
"jmp 1f; 1:\n"
- :"=m" (*(char *) __va(0)),
+ :"=m" (*(char *) vaddr),
"=q" (tmp_reg)
:/* no inputs */
:"memory");
- pg0[0] = old;
+
+ *pte = old_pte;
local_flush_tlb();
+
if (boot_cpu_data.wp_works_ok < 0) {
boot_cpu_data.wp_works_ok = 0;
printk("No.\n");
@@ -365,136 +472,95 @@ void __init test_wp_bit(void)
#endif
} else
printk(".\n");
+//#endif
}
-static void __init mem_init_region(unsigned long pfn, unsigned long count, unsigned long start_mem_pfn)
+static inline int page_is_ram (unsigned long pagenr)
{
- printk("memory region: %luk @ %08lx000\n", count << 2, pfn);
+ int i;
- do {
- if (pfn >= max_mapnr)
- break;
+ for (i = 0; i < e820.nr_map; i++) {
+ unsigned long addr, size;
- /* Avoid the kernel mapping between HIGH_MEMORY and "start_mem".. */
- if (pfn < (HIGH_MEMORY >> PAGE_SHIFT) || pfn >= start_mem_pfn)
- clear_bit(PG_reserved, &mem_map[pfn].flags);
-
- pfn++;
- } while (--count > 0);
+ if (e820.map[i].type != E820_RAM) /* not usable memory */
+ continue;
+ addr = (e820.map[i].addr+PAGE_SIZE-1) >> PAGE_SHIFT;
+ size = e820.map[i].size >> PAGE_SHIFT;
+ if ((pagenr >= addr) && (pagenr < addr+size))
+ return 1;
+ }
+ return 0;
}
-void __init mem_init(unsigned long start_mem, unsigned long end_mem)
+void __init mem_init(void)
{
- unsigned long start_low_mem = PAGE_SIZE;
int codepages = 0;
int reservedpages = 0;
int datapages = 0;
int initpages = 0;
- unsigned long tmp;
- int i, avail;
-
- end_mem &= PAGE_MASK;
-#ifdef CONFIG_BIGMEM
- bigmem_start = PAGE_ALIGN(bigmem_start);
- bigmem_end &= PAGE_MASK;
-#endif
- high_memory = (void *) end_mem;
-#ifndef CONFIG_BIGMEM
- max_mapnr = num_physpages = MAP_NR(end_mem);
+#ifdef CONFIG_HIGHMEM
+ int tmp;
+
+ if (!mem_map)
+ BUG();
+ highmem_start_page = mem_map + highstart_pfn;
+ /* cache the highmem_mapnr */
+ highmem_mapnr = highstart_pfn;
+ max_mapnr = num_physpages = highend_pfn;
#else
- max_mapnr = num_physpages = PHYSMAP_NR(bigmem_end);
- /* cache the bigmem_mapnr */
- bigmem_mapnr = PHYSMAP_NR(bigmem_start);
+ max_mapnr = num_physpages = max_low_pfn;
#endif
+ high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
/* clear the zero-page */
memset(empty_zero_page, 0, PAGE_SIZE);
- /* mark usable pages in the mem_map[] */
- start_low_mem = PAGE_ALIGN(start_low_mem)+PAGE_OFFSET;
+ /* this will put all low memory onto the freelists */
+ totalram_pages += free_all_bootmem();
-#ifdef __SMP__
- /*
- * But first pinch a few for the stack/trampoline stuff
- * FIXME: Don't need the extra page at 4K, but need to fix
- * trampoline before removing it. (see the GDT stuff)
- *
- */
- start_low_mem += PAGE_SIZE; /* 32bit startup code */
- start_low_mem = smp_alloc_memory(start_low_mem); /* AP processor stacks */
-#endif
- start_mem = PAGE_ALIGN(start_mem);
+#ifdef CONFIG_HIGHMEM
+ for (tmp = highstart_pfn; tmp < highend_pfn; tmp++) {
+ struct page *page = mem_map + tmp;
- /* walk the whitelist, unreserving good memory
- */
- for (avail = i = 0; i < e820.nr_map; i++) {
- unsigned long start_pfn, end_pfn;
-
- if (e820.map[i].type != E820_RAM) /* not usable memory */
- continue;
-
- start_pfn = (e820.map[i].addr + PAGE_SIZE - 1) >> PAGE_SHIFT;
- end_pfn = (e820.map[i].addr + e820.map[i].size) >> PAGE_SHIFT;
-
- /* We have a certain amount of low memory reserved */
- if (start_pfn < MAP_NR(start_low_mem))
- start_pfn = MAP_NR(start_low_mem);
-
- if (end_pfn <= start_pfn)
- continue;
-
- mem_init_region(start_pfn, end_pfn - start_pfn, MAP_NR(start_mem));
- }
-
- for (tmp = PAGE_OFFSET ; tmp < end_mem ; tmp += PAGE_SIZE) {
- if (tmp >= MAX_DMA_ADDRESS)
- clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags);
- if (PageReserved(mem_map+MAP_NR(tmp))) {
- if (tmp >= (unsigned long) &_text && tmp < (unsigned long) &_edata) {
- if (tmp < (unsigned long) &_etext)
- codepages++;
- else
- datapages++;
- } else if (tmp >= (unsigned long) &__init_begin
- && tmp < (unsigned long) &__init_end)
- initpages++;
- else if (tmp >= (unsigned long) &__bss_start
- && tmp < (unsigned long) start_mem)
- datapages++;
- else
- reservedpages++;
+ if (!page_is_ram(tmp)) {
+ SetPageReserved(page);
continue;
}
- set_page_count(mem_map+MAP_NR(tmp), 1);
- totalram += PAGE_SIZE;
-#ifdef CONFIG_BLK_DEV_INITRD
- if (!initrd_start || (tmp < initrd_start || tmp >= initrd_end))
-#endif
- free_page(tmp);
+ ClearPageReserved(page);
+ set_bit(PG_highmem, &page->flags);
+ atomic_set(&page->count, 1);
+ __free_page(page);
+ totalhigh_pages++;
}
-#ifdef CONFIG_BIGMEM
- for (tmp = bigmem_start; tmp < bigmem_end; tmp += PAGE_SIZE) {
- clear_bit(PG_reserved, &mem_map[PHYSMAP_NR(tmp)].flags);
- set_bit(PG_BIGMEM, &mem_map[PHYSMAP_NR(tmp)].flags);
- atomic_set(&mem_map[PHYSMAP_NR(tmp)].count, 1);
- free_page(tmp + PAGE_OFFSET);
- totalbig += PAGE_SIZE;
- }
- totalram += totalbig;
+ totalram_pages += totalhigh_pages;
#endif
- printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init, %dk bigmem)\n",
+ printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init, %ldk highmem)\n",
(unsigned long) nr_free_pages << (PAGE_SHIFT-10),
max_mapnr << (PAGE_SHIFT-10),
codepages << (PAGE_SHIFT-10),
reservedpages << (PAGE_SHIFT-10),
datapages << (PAGE_SHIFT-10),
initpages << (PAGE_SHIFT-10),
- (int) (totalbig >> 10)
+ (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))
);
+#if CONFIG_X86_PAE
+ if (!cpu_has_pae)
+ panic("cannot execute a PAE-enabled kernel on a PAE-incapable CPU!");
+#endif
if (boot_cpu_data.wp_works_ok < 0)
test_wp_bit();
+ /*
+ * Subtle. SMP is doing it's boot stuff late (because it has to
+ * fork idle threads) - but it also needs low mappings for the
+ * protected-mode entry to work. We zap these entries only after
+ * the WP-bit has been tested.
+ */
+#ifndef CONFIG_SMP
+ zap_low_mappings();
+#endif
+
}
void free_initmem(void)
@@ -503,21 +569,22 @@ void free_initmem(void)
addr = (unsigned long)(&__init_begin);
for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
- mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved);
+ ClearPageReserved(mem_map + MAP_NR(addr));
set_page_count(mem_map+MAP_NR(addr), 1);
free_page(addr);
- totalram += PAGE_SIZE;
+ totalram_pages++;
}
printk ("Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10);
}
void si_meminfo(struct sysinfo *val)
{
- val->totalram = totalram;
+ val->totalram = totalram_pages;
val->sharedram = 0;
- val->freeram = nr_free_pages << PAGE_SHIFT;
- val->bufferram = atomic_read(&buffermem);
- val->totalbig = totalbig;
- val->freebig = nr_free_bigpages << PAGE_SHIFT;
+ val->freeram = nr_free_pages;
+ val->bufferram = atomic_read(&buffermem_pages);
+ val->totalhigh = totalhigh_pages;
+ val->freehigh = nr_free_highpages;
+ val->mem_unit = PAGE_SIZE;
return;
}
diff --git a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c
index 32f3c33fd..d69455310 100644
--- a/arch/i386/mm/ioremap.c
+++ b/arch/i386/mm/ioremap.c
@@ -20,15 +20,19 @@ static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned l
end = address + size;
if (end > PMD_SIZE)
end = PMD_SIZE;
+ if (address >= end)
+ BUG();
do {
- if (!pte_none(*pte))
+ if (!pte_none(*pte)) {
printk("remap_area_pte: page already exists\n");
+ BUG();
+ }
set_pte(pte, mk_pte_phys(phys_addr, __pgprot(_PAGE_PRESENT | _PAGE_RW |
_PAGE_DIRTY | _PAGE_ACCESSED | flags)));
address += PAGE_SIZE;
phys_addr += PAGE_SIZE;
pte++;
- } while (address < end);
+ } while (address && (address < end));
}
static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
@@ -41,6 +45,8 @@ static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned lo
if (end > PGDIR_SIZE)
end = PGDIR_SIZE;
phys_addr -= address;
+ if (address >= end)
+ BUG();
do {
pte_t * pte = pte_alloc_kernel(pmd, address);
if (!pte)
@@ -48,7 +54,7 @@ static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned lo
remap_area_pte(pte, address, end - address, address + phys_addr, flags);
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;
- } while (address < end);
+ } while (address && (address < end));
return 0;
}
@@ -61,8 +67,11 @@ static int remap_area_pages(unsigned long address, unsigned long phys_addr,
phys_addr -= address;
dir = pgd_offset(&init_mm, address);
flush_cache_all();
- while (address < end) {
- pmd_t *pmd = pmd_alloc_kernel(dir, address);
+ if (address >= end)
+ BUG();
+ do {
+ pmd_t *pmd;
+ pmd = pmd_alloc_kernel(dir, address);
if (!pmd)
return -ENOMEM;
if (remap_area_pmd(pmd, address, end - address,
@@ -71,7 +80,7 @@ static int remap_area_pages(unsigned long address, unsigned long phys_addr,
set_pgdir(address, *dir);
address = (address + PGDIR_SIZE) & PGDIR_MASK;
dir++;
- }
+ } while (address && (address < end));
flush_tlb_all();
return 0;
}
diff --git a/arch/i386/vmlinux.lds.S b/arch/i386/vmlinux.lds
index 9a9ff07e7..9624cae47 100644
--- a/arch/i386/vmlinux.lds.S
+++ b/arch/i386/vmlinux.lds
@@ -6,7 +6,7 @@ OUTPUT_ARCH(i386)
ENTRY(_start)
SECTIONS
{
- . = PAGE_OFFSET_RAW + 0x100000;
+ . = 0xC0000000 + 0x100000;
_text = .; /* Text and read-only data */
.text : {
*(.text)