diff -purN -X /home/mbligh/.diff.exclude 110-config_hz/arch/i386/Kconfig 112-config_page_offset/arch/i386/Kconfig
--- 110-config_hz/arch/i386/Kconfig	2003-12-02 14:53:47.000000000 -0800
+++ 112-config_page_offset/arch/i386/Kconfig	2003-12-02 14:53:57.000000000 -0800
@@ -682,6 +682,44 @@ config HIGHMEM64G
 
 endchoice
 
+choice
+	help
+	  On i386, a process can only virtually address 4GB of memory.  This
+	  lets you select how much of that virtual space you would like to 
+	  devoted to userspace, and how much to the kernel.
+
+	  Some userspace programs would like to address as much as possible and 
+	  have few demands of the kernel other than it get out of the way.  These
+	  users may opt to use the 3.5GB option to give their userspace program 
+	  as much room as possible.  Due to alignment issues imposed by PAE, 
+	  the "3.5GB" option is unavailable if "64GB" high memory support is 
+	  enabled.
+
+	  Other users (especially those who use PAE) may be running out of
+	  ZONE_NORMAL memory.  Those users may benefit from increasing the
+	  kernel's virtual address space size by taking it away from userspace, 
+	  which may not need all of its space.  An indicator that this is 
+	  happening is when /proc/Meminfo's "LowFree:" is a small percentage of
+	  "LowTotal:" while "HighFree:" is very large.
+
+	  If unsure, say "3GB"
+	prompt "User address space size"
+        default 1GB
+	
+config	05GB
+	bool "3.5 GB"
+	depends on !HIGHMEM64G
+	
+config	1GB
+	bool "3 GB"
+	
+config	2GB
+	bool "2 GB"
+	
+config	3GB
+	bool "1 GB"
+endchoice
+
 config HIGHMEM
 	bool
 	depends on HIGHMEM64G || HIGHMEM4G
diff -purN -X /home/mbligh/.diff.exclude 110-config_hz/arch/i386/Makefile 112-config_page_offset/arch/i386/Makefile
--- 110-config_hz/arch/i386/Makefile	2003-12-02 14:53:24.000000000 -0800
+++ 112-config_page_offset/arch/i386/Makefile	2003-12-02 14:53:57.000000000 -0800
@@ -101,6 +101,7 @@ drivers-$(CONFIG_PM)			+= arch/i386/powe
 
 CFLAGS += $(mflags-y)
 AFLAGS += $(mflags-y)
+AFLAGS_vmlinux.lds.o += -include $(TOPDIR)/include/asm-i386/page.h
 
 boot := arch/i386/boot
 
diff -purN -X /home/mbligh/.diff.exclude 110-config_hz/arch/i386/kernel/vmlinux.lds.S 112-config_page_offset/arch/i386/kernel/vmlinux.lds.S
--- 110-config_hz/arch/i386/kernel/vmlinux.lds.S	2003-10-01 11:40:41.000000000 -0700
+++ 112-config_page_offset/arch/i386/kernel/vmlinux.lds.S	2003-12-02 14:53:57.000000000 -0800
@@ -10,7 +10,7 @@ ENTRY(startup_32)
 jiffies = jiffies_64;
 SECTIONS
 {
-  . = 0xC0000000 + 0x100000;
+  . = __PAGE_OFFSET + 0x100000;
   /* read-only */
   _text = .;			/* Text and read-only data */
   .text : {
diff -purN -X /home/mbligh/.diff.exclude 110-config_hz/include/asm-i386/page.h 112-config_page_offset/include/asm-i386/page.h
--- 110-config_hz/include/asm-i386/page.h	2003-04-09 11:48:05.000000000 -0700
+++ 112-config_page_offset/include/asm-i386/page.h	2003-12-02 14:53:57.000000000 -0800
@@ -115,9 +115,26 @@ static __inline__ int get_order(unsigned
 #endif /* __ASSEMBLY__ */
 
 #ifdef __ASSEMBLY__
-#define __PAGE_OFFSET		(0xC0000000)
+#include <linux/config.h>
+#ifdef CONFIG_05GB
+#define __PAGE_OFFSET          (0xE0000000)
+#elif defined(CONFIG_1GB)
+#define __PAGE_OFFSET          (0xC0000000)
+#elif defined(CONFIG_2GB)
+#define __PAGE_OFFSET          (0x80000000)
+#elif defined(CONFIG_3GB)
+#define __PAGE_OFFSET          (0x40000000)
+#endif
 #else
-#define __PAGE_OFFSET		(0xC0000000UL)
+#ifdef CONFIG_05GB
+#define __PAGE_OFFSET          (0xE0000000UL)
+#elif defined(CONFIG_1GB)
+#define __PAGE_OFFSET          (0xC0000000UL)
+#elif defined(CONFIG_2GB)
+#define __PAGE_OFFSET          (0x80000000UL)
+#elif defined(CONFIG_3GB)
+#define __PAGE_OFFSET          (0x40000000UL)
+#endif
 #endif
 
 
diff -purN -X /home/mbligh/.diff.exclude 110-config_hz/include/asm-i386/processor.h 112-config_page_offset/include/asm-i386/processor.h
--- 110-config_hz/include/asm-i386/processor.h	2003-10-21 11:16:11.000000000 -0700
+++ 112-config_page_offset/include/asm-i386/processor.h	2003-12-02 14:53:57.000000000 -0800
@@ -299,7 +299,11 @@ extern unsigned int mca_pentium_flag;
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
+#ifdef CONFIG_05GB
+#define TASK_UNMAPPED_BASE	(PAGE_ALIGN(TASK_SIZE / 16))
+#else
 #define TASK_UNMAPPED_BASE	(PAGE_ALIGN(TASK_SIZE / 3))
+#endif
 
 /*
  * Size of io_bitmap, covering ports 0 to 0x3ff.
diff -purN -X /home/mbligh/.diff.exclude 110-config_hz/mm/memory.c 112-config_page_offset/mm/memory.c
--- 110-config_hz/mm/memory.c	2003-11-24 16:12:33.000000000 -0800
+++ 112-config_page_offset/mm/memory.c	2003-12-02 14:53:57.000000000 -0800
@@ -109,8 +109,7 @@ static inline void free_one_pmd(struct m
 
 static inline void free_one_pgd(struct mmu_gather *tlb, pgd_t * dir)
 {
-	int j;
-	pmd_t * pmd;
+	pmd_t * pmd, * md, * emd;
 
 	if (pgd_none(*dir))
 		return;
@@ -121,8 +120,21 @@ static inline void free_one_pgd(struct m
 	}
 	pmd = pmd_offset(dir, 0);
 	pgd_clear(dir);
-	for (j = 0; j < PTRS_PER_PMD ; j++)
-		free_one_pmd(tlb, pmd+j);
+	/*
+	 * Beware if changing the loop below.  It once used int j,
+	 * 	for (j = 0; j < PTRS_PER_PMD; j++)
+	 * 		free_one_pmd(pmd+j);
+	 * but some older i386 compilers (e.g. egcs-2.91.66, gcc-2.95.3)
+	 * terminated the loop with a _signed_ address comparison
+	 * using "jle", when configured for HIGHMEM64GB (X86_PAE).
+	 * If also configured for 3GB of kernel virtual address space,
+	 * if page at physical 0x3ffff000 virtual 0x7ffff000 is used as
+	 * a pmd, when that mm exits the loop goes on to free "entries"
+	 * found at 0x80000000 onwards.  The loop below compiles instead
+	 * to be terminated by unsigned address comparison using "jb".
+	 */
+	for (md = pmd, emd = pmd + PTRS_PER_PMD; md < emd; md++)
+		free_one_pmd(tlb,md);
 	pmd_free_tlb(tlb, pmd);
 }