diff --git a/kalloc.c b/kalloc.c
index 9ff32456cc62be1015341e98511d977272895d27..35ea6ed13d58e43d2f0cc410fb9b28e270016188 100644
--- a/kalloc.c
+++ b/kalloc.c
@@ -19,7 +19,6 @@ struct {
 } kmem;
 
 extern char end[]; // first address after kernel loaded from ELF file
-extern uint maxpa;        // Maximum physical address
 static char *newend;
 
 // simple page allocator to get off the ground during entry
@@ -51,7 +50,7 @@ kinit(void)
 
   initlock(&kmem.lock, "kmem");
   p = (char*)PGROUNDUP((uint)newend);
-  for(; p + PGSIZE <= (char*)p2v(maxpa); p += PGSIZE)
+  for(; p + PGSIZE <= (char*)p2v(PHYSTOP); p += PGSIZE)
     kfree(p);
 }
 
@@ -65,7 +64,7 @@ kfree(char *v)
 {
   struct run *r;
 
-  if((uint)v % PGSIZE || v < end || v2p(v) >= maxpa)
+  if((uint)v % PGSIZE || v < end || v2p(v) >= PHYSTOP)
     panic("kfree");
 
   // Fill with junk to catch dangling refs.
diff --git a/memlayout.h b/memlayout.h
index 79429a94ac0aef4cf15659bd6cfc764ffb32b307..ad4fda239e29c5ff3db443757afc456adde230bb 100644
--- a/memlayout.h
+++ b/memlayout.h
@@ -1,6 +1,7 @@
 // Memory layout
 
 #define EXTMEM  0x100000            // Start of extended memory
+#define PHYSTOP 0xE000000           // Top physical memory (too hard to get from E820)
 #define DEVSPACE 0xFE000000         // Other devices are at high addresses
 
 // Key addresses for address space layout (see kmap in vm.c for the layout)
diff --git a/vm.c b/vm.c
index 0011188de1d6367a94ff17f92bf1a93182ba8262..e509a7215de31d50feb8c91d4b3af7544644905c 100644
--- a/vm.c
+++ b/vm.c
@@ -8,7 +8,6 @@
 #include "elf.h"
 
 extern char data[];  // defined in data.S
-uint maxpa;  // max physical address
 pde_t *kpgdir;  // for use in scheduler()
 struct segdesc gdt[NSEGS];
 
@@ -103,11 +102,11 @@ mappages(pde_t *pgdir, void *va, uint size, uint pa, int perm, char* (*alloc)(vo
 //   0..USERTOP      : user memory (text, data, stack, heap), mapped to some unused phys mem
 //   KERNBASE..KERNBASE+EXTMEM: mapped to 0..EXTMEM  (below extended memory)
 //   KERNBASE+EXTMEM..KERNBASE+end : mapped to EXTMEM..end (mapped without write permission)
-//   KERNBASE+end..KERBASE+maxpa     : mapped to end..maxpa (rw data + free memory)
+//   KERNBASE+end..KERBASE+PHYSTOP     : mapped to end..PHYSTOP (rw data + free memory)
 //   0xfe000000..0    : mapped direct (devices such as ioapic)
 //
 // The kernel allocates memory for its heap and for user memory
-// between kernend and the end of physical memory (maxpa).
+// between kernend and the end of physical memory (PHYSTOP).
 // The virtual address space of each user program includes the kernel
 // (which is inaccessible in user mode).  The user program sits in
 // the bottom of the address space, and the kernel at the top at KERNBASE.
@@ -119,7 +118,7 @@ static struct kmap {
 } kmap[] = {
   { P2V(0), 0, 1024*1024, PTE_W},  // First 1Mbyte contains BIOS and some IO devices
   { (void *)KERNLINK, V2P(KERNLINK), V2P(data),  0},  // kernel text, rodata
-  { data, V2P(data), 0,  PTE_W},  // kernel data, memory
+  { data, V2P(data), PHYSTOP,  PTE_W},  // kernel data, memory
   { (void*)DEVSPACE, DEVSPACE, 0, PTE_W},  // more devices
 };
 
@@ -130,17 +129,12 @@ setupkvm(char* (*alloc)(void))
   pde_t *pgdir;
   struct kmap *k;
 
-  if (kmap[2].phys_end == 0) {
-    maxpa = detect_memory();
-    kmap[2].phys_end = maxpa;
-    if (p2v(maxpa) > kmap[3].virt)
-      panic("detect_memory: too much memory");
-
-  }
   if((pgdir = (pde_t*)alloc()) == 0)
     return 0;
   memset(pgdir, 0, PGSIZE);
   k = kmap;
+  if (p2v(PHYSTOP) > (void *) DEVSPACE)
+    panic("PHYSTOP too high");
   for(k = kmap; k < &kmap[NELEM(kmap)]; k++)
     if(mappages(pgdir, k->virt, k->phys_end - k->phys_start, (uint)k->phys_start, 
 		k->perm, alloc) < 0)