diff --git a/cpu-defs.h b/cpu-defs.h
index 47c1d85..2e94585 100644
--- a/cpu-defs.h
+++ b/cpu-defs.h
@@ -111,6 +111,8 @@ typedef struct CPUTLBEntry {
     /* The meaning of the MMU modes is defined in the target code. */   \
     CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE];                  \
     target_phys_addr_t iotlb[NB_MMU_MODES][CPU_TLB_SIZE];               \
+    target_ulong tlb_flush_addr;                                        \
+    target_ulong tlb_flush_mask;
 
 #else
 
diff --git a/exec-all.h b/exec-all.h
index 56e7977..37da2f5 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -96,17 +96,9 @@ void tb_invalidate_page_range(target_ulong start, target_ulong end);
 void tlb_flush_page(CPUState *env, target_ulong addr);
 void tlb_flush(CPUState *env, int flush_global);
 #if !defined(CONFIG_USER_ONLY)
-int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
-                      target_phys_addr_t paddr, int prot,
-                      int mmu_idx, int is_softmmu);
-static inline int tlb_set_page(CPUState *env1, target_ulong vaddr,
-                               target_phys_addr_t paddr, int prot,
-                               int mmu_idx, int is_softmmu)
-{
-    if (prot & PAGE_READ)
-        prot |= PAGE_EXEC;
-    return tlb_set_page_exec(env1, vaddr, paddr, prot, mmu_idx, is_softmmu);
-}
+void tlb_set_page(CPUState *env, target_ulong vaddr,
+                  target_phys_addr_t paddr, int prot,
+                  int mmu_idx, target_ulong size);
 #endif
 
 #define CODE_GEN_ALIGN           16 /* must be >= of the size of a icache line */
diff --git a/exec.c b/exec.c
index b0b6056..14767b7 100644
--- a/exec.c
+++ b/exec.c
@@ -1918,6 +1918,8 @@ void tlb_flush(CPUState *env, int flush_global)
 
     memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
 
+    env->tlb_flush_addr = -1;
+    env->tlb_flush_mask = 0;
     tlb_flush_count++;
 }
 
@@ -1941,6 +1943,16 @@ void tlb_flush_page(CPUState *env, target_ulong addr)
 #if defined(DEBUG_TLB)
     printf("tlb_flush_page: " TARGET_FMT_lx "\n", addr);
 #endif
+    /* Check if we need to flush due to large pages.  */
+    if ((addr & env->tlb_flush_mask) == env->tlb_flush_addr) {
+#if defined(DEBUG_TLB)
+        printf("tlb_flush_page: forced full flush ("
+               TARGET_FMT_lx "/" TARGET_FMT_lx ")\n",
+               env->tlb_flush_addr, env->tlb_flush_mask);
+#endif
+        tlb_flush(env, 1);
+        return;
+    }
     /* must reset current TB so that interrupts cannot modify the
        links while we are modifying them */
     env->current_tb = NULL;
@@ -2090,13 +2102,35 @@ static inline void tlb_set_dirty(CPUState *env, target_ulong vaddr)
         tlb_set_dirty1(&env->tlb_table[mmu_idx][i], vaddr);
 }
 
-/* add a new TLB entry. At most one entry for a given virtual address
-   is permitted. Return 0 if OK or 2 if the page could not be mapped
-   (can only happen in non SOFTMMU mode for I/O pages or pages
-   conflicting with the host address space). */
-int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
-                      target_phys_addr_t paddr, int prot,
-                      int mmu_idx, int is_softmmu)
+/* Our TLB does not support large pages, so remember the area covered by
+   large pages and trigger a full TLB flush if these are invalidated.  */
+static void tlb_add_large_page(CPUState *env, target_ulong vaddr,
+                               target_ulong size)
+{
+    target_ulong mask = ~(size - 1);
+
+    if (env->tlb_flush_addr == (target_ulong)-1) {
+        env->tlb_flush_addr = vaddr & mask;
+        env->tlb_flush_mask = mask;
+        return;
+    }
+    /* Extend the existing region to include the new page.
+       This is a compromise between unnecessary flushes and the cost
+       of maintaining a full variable size TLB.  */
+    mask &= env->tlb_flush_mask;
+    while (((env->tlb_flush_addr ^ vaddr) & mask) != 0) {
+        mask <<= 1;
+    }
+    env->tlb_flush_addr &= mask;
+    env->tlb_flush_mask = mask;
+}
+
+/* Add a new TLB entry. At most one entry for a given virtual address
+   is permitted. Only a single TARGET_PAGE_SIZE region is mapped, the
+   supplied size is only used by tlb_flush_page.  */
+void tlb_set_page(CPUState *env, target_ulong vaddr,
+                  target_phys_addr_t paddr, int prot,
+                  int mmu_idx, target_ulong size)
 {
     PhysPageDesc *p;
     unsigned long pd;
@@ -2104,11 +2138,14 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
     target_ulong address;
     target_ulong code_address;
     target_phys_addr_t addend;
-    int ret;
     CPUTLBEntry *te;
     CPUWatchpoint *wp;
     target_phys_addr_t iotlb;
 
+    assert(size >= TARGET_PAGE_SIZE);
+    if (size != TARGET_PAGE_SIZE) {
+        tlb_add_large_page(env, vaddr, size);
+    }
     p = phys_page_find(paddr >> TARGET_PAGE_BITS);
     if (!p) {
         pd = IO_MEM_UNASSIGNED;
@@ -2120,7 +2157,6 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
            vaddr, (int)paddr, prot, mmu_idx, is_softmmu, pd);
 #endif
 
-    ret = 0;
     address = vaddr;
     if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
         /* IO memory case (romd handled later) */
@@ -2190,7 +2226,6 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
     } else {
         te->addr_write = -1;
     }
-    return ret;
 }
 
 #else
diff --git a/hw/alpha_palcode.c b/hw/alpha_palcode.c
index c1220ad..6293d10 100644
--- a/hw/alpha_palcode.c
+++ b/hw/alpha_palcode.c
@@ -1003,11 +1003,14 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
         /* No fault */
         page_size = 1ULL << zbits;
         address &= ~(page_size - 1);
+        /* FIXME: page_size should probably be passed to tlb_set_page,
+           and this loop removed.   */
         for (end = physical + page_size; physical < end; physical += 0x1000) {
-            ret = tlb_set_page(env, address, physical, prot,
-                               mmu_idx, is_softmmu);
+            tlb_set_page(env, address, physical, prot, mmu_idx,
+                         TARGET_PAGE_SIZE);
             address += 0x1000;
         }
+        ret = 0;
         break;
 #if 0
     case 1:
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 1a181ac..18e22b1 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -894,7 +894,8 @@ static uint32_t get_level1_table_address(CPUState *env, uint32_t address)
 }
 
 static int get_phys_addr_v5(CPUState *env, uint32_t address, int access_type,
-			    int is_user, uint32_t *phys_ptr, int *prot)
+			    int is_user, uint32_t *phys_ptr, int *prot,
+                            target_ulong *page_size)
 {
     int code;
     uint32_t table;
@@ -927,6 +928,7 @@ static int get_phys_addr_v5(CPUState *env, uint32_t address, int access_type,
         phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);
         ap = (desc >> 10) & 3;
         code = 13;
+        *page_size = 1024 * 1024;
     } else {
         /* Lookup l2 entry.  */
 	if (type == 1) {
@@ -944,10 +946,12 @@ static int get_phys_addr_v5(CPUState *env, uint32_t address, int access_type,
         case 1: /* 64k page.  */
             phys_addr = (desc & 0xffff0000) | (address & 0xffff);
             ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
+            *page_size = 0x10000;
             break;
         case 2: /* 4k page.  */
             phys_addr = (desc & 0xfffff000) | (address & 0xfff);
             ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
+            *page_size = 0x1000;
             break;
         case 3: /* 1k page.  */
 	    if (type == 1) {
@@ -962,6 +966,7 @@ static int get_phys_addr_v5(CPUState *env, uint32_t address, int access_type,
 		phys_addr = (desc & 0xfffffc00) | (address & 0x3ff);
 	    }
             ap = (desc >> 4) & 3;
+            *page_size = 0x400;
             break;
         default:
             /* Never happens, but compiler isn't smart enough to tell.  */
@@ -981,7 +986,8 @@ do_fault:
 }
 
 static int get_phys_addr_v6(CPUState *env, uint32_t address, int access_type,
-			    int is_user, uint32_t *phys_ptr, int *prot)
+			    int is_user, uint32_t *phys_ptr, int *prot,
+                            target_ulong *page_size)
 {
     int code;
     uint32_t table;
@@ -1021,9 +1027,11 @@ static int get_phys_addr_v6(CPUState *env, uint32_t address, int access_type,
         if (desc & (1 << 18)) {
             /* Supersection.  */
             phys_addr = (desc & 0xff000000) | (address & 0x00ffffff);
+            *page_size = 0x1000000;
         } else {
             /* Section.  */
             phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);
+            *page_size = 0x100000;
         }
         ap = ((desc >> 10) & 3) | ((desc >> 13) & 4);
         xn = desc & (1 << 4);
@@ -1040,10 +1048,12 @@ static int get_phys_addr_v6(CPUState *env, uint32_t address, int access_type,
         case 1: /* 64k page.  */
             phys_addr = (desc & 0xffff0000) | (address & 0xffff);
             xn = desc & (1 << 15);
+            *page_size = 0x10000;
             break;
         case 2: case 3: /* 4k page.  */
             phys_addr = (desc & 0xfffff000) | (address & 0xfff);
             xn = desc & 1;
+            *page_size = 0x1000;
             break;
         default:
             /* Never happens, but compiler isn't smart enough to tell.  */
@@ -1132,7 +1142,8 @@ static int get_phys_addr_mpu(CPUState *env, uint32_t address, int access_type,
 
 static inline int get_phys_addr(CPUState *env, uint32_t address,
                                 int access_type, int is_user,
-                                uint32_t *phys_ptr, int *prot)
+                                uint32_t *phys_ptr, int *prot,
+                                target_ulong *page_size)
 {
     /* Fast Context Switch Extension.  */
     if (address < 0x02000000)
@@ -1142,16 +1153,18 @@ static inline int get_phys_addr(CPUState *env, uint32_t address,
         /* MMU/MPU disabled.  */
         *phys_ptr = address;
         *prot = PAGE_READ | PAGE_WRITE;
+        *page_size = TARGET_PAGE_SIZE;
         return 0;
     } else if (arm_feature(env, ARM_FEATURE_MPU)) {
+        *page_size = TARGET_PAGE_SIZE;
 	return get_phys_addr_mpu(env, address, access_type, is_user, phys_ptr,
 				 prot);
     } else if (env->cp15.c1_sys & (1 << 23)) {
         return get_phys_addr_v6(env, address, access_type, is_user, phys_ptr,
-                                prot);
+                                prot, page_size);
     } else {
         return get_phys_addr_v5(env, address, access_type, is_user, phys_ptr,
-                                prot);
+                                prot, page_size);
     }
 }
 
@@ -1159,17 +1172,20 @@ int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address,
                               int access_type, int mmu_idx, int is_softmmu)
 {
     uint32_t phys_addr;
+    target_ulong page_size;
     int prot;
     int ret, is_user;
 
     is_user = mmu_idx == MMU_USER_IDX;
-    ret = get_phys_addr(env, address, access_type, is_user, &phys_addr, &prot);
+    ret = get_phys_addr(env, address, access_type, is_user, &phys_addr, &prot,
+                        &page_size);
     if (ret == 0) {
         /* Map a single [sub]page.  */
         phys_addr &= ~(uint32_t)0x3ff;
         address &= ~(uint32_t)0x3ff;
-        return tlb_set_page (env, address, phys_addr, prot, mmu_idx,
-                             is_softmmu);
+        tlb_set_page (env, address, phys_addr, prot | PAGE_EXEC, mmu_idx,
+                      page_size);
+        return 0;
     }
 
     if (access_type == 2) {
@@ -1189,10 +1205,11 @@ int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address,
 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 {
     uint32_t phys_addr;
+    target_ulong page_size;
     int prot;
     int ret;
 
-    ret = get_phys_addr(env, addr, 0, 0, &phys_addr, &prot);
+    ret = get_phys_addr(env, addr, 0, 0, &phys_addr, &prot, &page_size);
 
     if (ret != 0)
         return -1;
@@ -1406,18 +1423,7 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
             tlb_flush(env, 0);
             break;
         case 1: /* Invalidate single TLB entry.  */
-#if 0
-            /* ??? This is wrong for large pages and sections.  */
-            /* As an ugly hack to make linux work we always flush a 4K
-               pages.  */
-            val &= 0xfffff000;
-            tlb_flush_page(env, val);
-            tlb_flush_page(env, val + 0x400);
-            tlb_flush_page(env, val + 0x800);
-            tlb_flush_page(env, val + 0xc00);
-#else
-            tlb_flush(env, 1);
-#endif
+            tlb_flush_page(env, val & TARGET_PAGE_MASK);
             break;
         case 2: /* Invalidate on ASID.  */
             tlb_flush(env, val == 0);
diff --git a/target-cris/helper.c b/target-cris/helper.c
index b101dc5..fcdcf97 100644
--- a/target-cris/helper.c
+++ b/target-cris/helper.c
@@ -100,8 +100,9 @@ int cpu_cris_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
 		 */
 		phy = res.phy & ~0x80000000;
 		prot = res.prot;
-		r = tlb_set_page(env, address & TARGET_PAGE_MASK,
-				 phy, prot, mmu_idx, is_softmmu);
+		tlb_set_page(env, address & TARGET_PAGE_MASK, phy,
+                             prot | PAGE_EXEC, mmu_idx, TARGET_PAGE_SIZE);
+                r = 0;
 	}
 	if (r > 0)
 		D_LOG("%s returns %d irqreq=%x addr=%x"
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 05758f9..35ab720 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -531,14 +531,13 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
    -1 = cannot handle fault
    0  = nothing more to do
    1  = generate PF fault
-   2  = soft MMU activation required for this block
 */
 int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
                              int is_write1, int mmu_idx, int is_softmmu)
 {
     uint64_t ptep, pte;
     target_ulong pde_addr, pte_addr;
-    int error_code, is_dirty, prot, page_size, ret, is_write, is_user;
+    int error_code, is_dirty, prot, page_size, is_write, is_user;
     target_phys_addr_t paddr;
     uint32_t page_offset;
     target_ulong vaddr, virt_addr;
@@ -799,8 +798,8 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
     paddr = (pte & TARGET_PAGE_MASK) + page_offset;
     vaddr = virt_addr + page_offset;
 
-    ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
-    return ret;
+    tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
+    return 0;
  do_fault_protect:
     error_code = PG_ERROR_P_MASK;
  do_fault:
diff --git a/target-m68k/helper.c b/target-m68k/helper.c
index 5d52bd3..2dfd48f 100644
--- a/target-m68k/helper.c
+++ b/target-m68k/helper.c
@@ -368,8 +368,9 @@ int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
     int prot;
 
     address &= TARGET_PAGE_MASK;
-    prot = PAGE_READ | PAGE_WRITE;
-    return tlb_set_page(env, address, address, prot, mmu_idx, is_softmmu);
+    prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+    tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
+    return 0;
 }
 
 /* Notify CPU of a pending interrupt.  Prioritization and vectoring should
diff --git a/target-microblaze/helper.c b/target-microblaze/helper.c
index d99840c..5230b52 100644
--- a/target-microblaze/helper.c
+++ b/target-microblaze/helper.c
@@ -76,8 +76,8 @@ int cpu_mb_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
 
             DMMU(qemu_log("MMU map mmu=%d v=%x p=%x prot=%x\n",
                      mmu_idx, vaddr, paddr, lu.prot));
-            r = tlb_set_page(env, vaddr,
-                             paddr, lu.prot, mmu_idx, is_softmmu);
+            tlb_set_page(env, vaddr, paddr, lu.prot, mmu_idx, TARGET_PAGE_SIZE);
+            r = 0;
         } else {
             env->sregs[SR_EAR] = address;
             DMMU(qemu_log("mmu=%d miss v=%x\n", mmu_idx, address));
@@ -107,7 +107,8 @@ int cpu_mb_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
         /* MMU disabled or not available.  */
         address &= TARGET_PAGE_MASK;
         prot = PAGE_BITS;
-        r = tlb_set_page(env, address, address, prot, mmu_idx, is_softmmu);
+        tlb_set_page(env, address, address, prot, mmu_idx, TARGET_PAGE_SIZE);
+        r = 0;
     }
     return r;
 }
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 933c7bc..8102f03 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -296,9 +296,10 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
     qemu_log("%s address=" TARGET_FMT_lx " ret %d physical " TARGET_FMT_plx " prot %d\n",
               __func__, address, ret, physical, prot);
     if (ret == TLBRET_MATCH) {
-       ret = tlb_set_page(env, address & TARGET_PAGE_MASK,
-                          physical & TARGET_PAGE_MASK, prot,
-                          mmu_idx, is_softmmu);
+       tlb_set_page(env, address & TARGET_PAGE_MASK,
+                    physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
+                    mmu_idx, TARGET_PAGE_SIZE);
+       ret = 0;
     } else if (ret < 0)
 #endif
     {
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index fc54d71..c28223b 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -1410,9 +1410,10 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
     }
     ret = get_physical_address(env, &ctx, address, rw, access_type);
     if (ret == 0) {
-        ret = tlb_set_page_exec(env, address & TARGET_PAGE_MASK,
-                                ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
-                                mmu_idx, is_softmmu);
+        tlb_set_page(env, address & TARGET_PAGE_MASK,
+                     ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
+                     mmu_idx, TARGET_PAGE_SIZE);
+        ret = 0;
     } else if (ret < 0) {
         LOG_MMU_STATE(env);
         if (access_type == ACCESS_CODE) {
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index b97d1ff..ba0c052 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -69,10 +69,11 @@ int cpu_s390x_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
     /* XXX: implement mmu */
 
     phys = address;
-    prot = PAGE_READ | PAGE_WRITE;
+    prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
 
-    return tlb_set_page(env, address & TARGET_PAGE_MASK,
-                        phys & TARGET_PAGE_MASK, prot,
-                        mmu_idx, is_softmmu);
+    tlb_set_page(env, address & TARGET_PAGE_MASK,
+                 phys & TARGET_PAGE_MASK, prot,
+                 mmu_idx, TARGET_PAGE_SIZE);
+    return 0;
 }
 #endif /* CONFIG_USER_ONLY */
diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index 486be5d..6c3f896 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -470,7 +470,8 @@ int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
     address &= TARGET_PAGE_MASK;
     physical &= TARGET_PAGE_MASK;
 
-    return tlb_set_page(env, address, physical, prot, mmu_idx, is_softmmu);
+    tlb_set_page(env, address, physical, prot, mmu_idx, TARGET_PAGE_SIZE);
+    return 0;
 }
 
 target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 976eb43..1f0f7d4 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -102,7 +102,8 @@ static const int perm_table[2][8] = {
 
 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
                                 int *prot, int *access_index,
-                                target_ulong address, int rw, int mmu_idx)
+                                target_ulong address, int rw, int mmu_idx,
+                                target_ulong *page_size)
 {
     int access_perms = 0;
     target_phys_addr_t pde_ptr;
@@ -113,6 +114,7 @@ static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
     is_user = mmu_idx == MMU_USER_IDX;
 
     if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
+        *page_size = TARGET_PAGE_SIZE;
         // Boot mode: instruction fetches are taken from PROM
         if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) {
             *physical = env->prom_addr | (address & 0x7ffffULL);
@@ -175,13 +177,16 @@ static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
                     page_offset = (address & TARGET_PAGE_MASK) &
                         (TARGET_PAGE_SIZE - 1);
                 }
+                *page_size = TARGET_PAGE_SIZE;
                 break;
             case 2: /* L2 PTE */
                 page_offset = address & 0x3ffff;
+                *page_size = 0x40000;
             }
             break;
         case 2: /* L1 PTE */
             page_offset = address & 0xffffff;
+            *page_size = 0x1000000;
         }
     }
 
@@ -220,10 +225,11 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
 {
     target_phys_addr_t paddr;
     target_ulong vaddr;
-    int error_code = 0, prot, ret = 0, access_index;
+    target_ulong page_size;
+    int error_code = 0, prot, access_index;
 
     error_code = get_physical_address(env, &paddr, &prot, &access_index,
-                                      address, rw, mmu_idx);
+                                      address, rw, mmu_idx, &page_size);
     if (error_code == 0) {
         vaddr = address & TARGET_PAGE_MASK;
         paddr &= TARGET_PAGE_MASK;
@@ -231,8 +237,8 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
         printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
                TARGET_FMT_lx "\n", address, paddr, vaddr);
 #endif
-        ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
-        return ret;
+        tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
+        return 0;
     }
 
     if (env->mmuregs[3]) /* Fault status register */
@@ -247,8 +253,8 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
         // switching to normal mode.
         vaddr = address & TARGET_PAGE_MASK;
         prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
-        ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
-        return ret;
+        tlb_set_page(env, vaddr, paddr, prot, mmu_idx, TARGET_PAGE_SIZE);
+        return 0;
     } else {
         if (rw & 2)
             env->exception_index = TT_TFAULT;
@@ -531,10 +537,14 @@ static int get_physical_address_code(CPUState *env,
 
 static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
                                 int *prot, int *access_index,
-                                target_ulong address, int rw, int mmu_idx)
+                                target_ulong address, int rw, int mmu_idx,
+                                target_ulong *page_size)
 {
     int is_user = mmu_idx == MMU_USER_IDX;
 
+    /* ??? We treat everything as a small page, then explicitly flush
+       everything when an entry is evicted.  */
+    *page_size = TARGET_PAGE_SIZE;
     if (rw == 2)
         return get_physical_address_code(env, physical, prot, address,
                                          is_user);
@@ -549,10 +559,11 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
 {
     target_ulong virt_addr, vaddr;
     target_phys_addr_t paddr;
-    int error_code = 0, prot, ret = 0, access_index;
+    target_ulong page_size;
+    int error_code = 0, prot, access_index;
 
     error_code = get_physical_address(env, &paddr, &prot, &access_index,
-                                      address, rw, mmu_idx);
+                                      address, rw, mmu_idx, &page_size);
     if (error_code == 0) {
         virt_addr = address & TARGET_PAGE_MASK;
         vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
@@ -561,8 +572,8 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
         printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64
                "\n", address, paddr, vaddr);
 #endif
-        ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
-        return ret;
+        tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
+        return 0;
     }
     // XXX
     return 1;
@@ -656,12 +667,13 @@ void dump_mmu(CPUState *env)
 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 {
     target_phys_addr_t phys_addr;
+    target_ulong page_size;
     int prot, access_index;
 
     if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2,
-                             MMU_KERNEL_IDX) != 0)
+                             MMU_KERNEL_IDX, &page_size) != 0)
         if (get_physical_address(env, &phys_addr, &prot, &access_index, addr,
-                                 0, MMU_KERNEL_IDX) != 0)
+                                 0, MMU_KERNEL_IDX, &page_size) != 0)
             return -1;
     if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
         return -1;
