patch-2.4.20 linux-2.4.20/arch/ppc/mm/ppc_mmu.c
Next file: linux-2.4.20/arch/ppc/platforms/Makefile
Previous file: linux-2.4.20/arch/ppc/mm/mmu_decl.h
Back to the patch index
Back to the overall index
- Lines: 181
- Date:
Thu Nov 28 15:53:11 2002
- Orig file:
linux-2.4.19/arch/ppc/mm/ppc_mmu.c
- Orig date:
Fri Aug 2 17:39:43 2002
diff -urN linux-2.4.19/arch/ppc/mm/ppc_mmu.c linux-2.4.20/arch/ppc/mm/ppc_mmu.c
@@ -51,7 +51,7 @@
u64 word[2];
#else
u32 word[2];
-#endif
+#endif
} BATS[4][2]; /* 4 pairs of IBAT, DBAT */
struct batrange { /* stores address ranges mapped by BATs */
@@ -158,31 +158,13 @@
*/
void __init MMU_init_hw(void)
{
- int Hash_bits, mb, mb2;
- unsigned int hmask;
+ unsigned int hmask, mb, mb2;
+ unsigned int n_hpteg, lg_n_hpteg;
extern unsigned int hash_page_patch_A[];
extern unsigned int hash_page_patch_B[], hash_page_patch_C[];
extern unsigned int flush_hash_patch_A[], flush_hash_patch_B[];
-#ifdef CONFIG_PPC64BRIDGE
- /* The hash table has already been allocated and initialized
- in prom.c */
- Hash_mask = (Hash_size >> 7) - 1;
- hmask = Hash_mask >> 9;
- Hash_bits = __ilog2(Hash_size) - 7;
- mb = 25 - Hash_bits;
- if (Hash_bits > 16)
- Hash_bits = 16;
- mb2 = 25 - Hash_bits;
-
- /* Remove the hash table from the available memory */
- if (Hash)
- reserve_phys_mem(__pa(Hash), Hash_size);
-
-#else /* CONFIG_PPC64BRIDGE */
- unsigned int h;
-
if ((cur_cpu_spec[0]->cpu_features & CPU_FTR_HPTE_TABLE) == 0) {
Hash_size = 0;
Hash_end = 0;
@@ -192,72 +174,78 @@
if ( ppc_md.progress ) ppc_md.progress("hash:enter", 0x105);
+#ifdef CONFIG_PPC64BRIDGE
+#define LG_HPTEG_SIZE 7 /* 128 bytes per HPTEG */
+#define SDR1_LOW_BITS (lg_n_hpteg - 11)
+#define MIN_N_HPTEG 2048 /* min 256kB hash table */
+#else
+#define LG_HPTEG_SIZE 6 /* 64 bytes per HPTEG */
+#define SDR1_LOW_BITS ((n_hpteg - 1) >> 10)
+#define MIN_N_HPTEG 1024 /* min 64kB hash table */
+#endif
+
/*
- * Allow 64k of hash table for every 16MB of memory,
- * up to a maximum of 2MB.
+ * Allow 1 HPTE (1/8 HPTEG) for each page of memory.
+ * This is less than the recommended amount, but then
+ * Linux ain't AIX.
*/
- for (h = 64<<10; h < total_memory / 256 && h < (2<<20); h *= 2)
- ;
- Hash_size = h;
- Hash_mask = (h >> 6) - 1;
- hmask = Hash_mask >> 10;
- Hash_bits = __ilog2(h) - 6;
- mb = 26 - Hash_bits;
- if (Hash_bits > 16)
- Hash_bits = 16;
- mb2 = 26 - Hash_bits;
+ n_hpteg = total_memory / (PAGE_SIZE * 8);
+ if (n_hpteg < MIN_N_HPTEG)
+ n_hpteg = MIN_N_HPTEG;
+ lg_n_hpteg = __ilog2(n_hpteg);
+ if (n_hpteg & (n_hpteg - 1)) {
+ ++lg_n_hpteg; /* round up if not power of 2 */
+ n_hpteg = 1 << lg_n_hpteg;
+ }
+ Hash_size = n_hpteg << LG_HPTEG_SIZE;
+ /*
+ * Find some memory for the hash table.
+ */
if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322);
- /* Find some memory for the hash table. */
- if ( Hash_size ) {
- Hash = mem_pieces_find(Hash_size, Hash_size);
- cacheable_memzero(Hash, Hash_size);
- _SDR1 = __pa(Hash) | (Hash_mask >> 10);
- } else
- Hash = 0;
-#endif /* CONFIG_PPC64BRIDGE */
+ Hash = mem_pieces_find(Hash_size, Hash_size);
+ cacheable_memzero(Hash, Hash_size);
+ _SDR1 = __pa(Hash) | SDR1_LOW_BITS;
+ Hash_end = (PTE *) ((unsigned long)Hash + Hash_size);
printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n",
total_memory >> 20, Hash_size >> 10, Hash);
- if (Hash_size) {
- if ( ppc_md.progress ) ppc_md.progress("hash:patch", 0x345);
- Hash_end = (PTE *) ((unsigned long)Hash + Hash_size);
-
- /*
- * Patch up the instructions in hashtable.S:create_hpte
- */
- hash_page_patch_A[0] = (hash_page_patch_A[0] & ~0xffff)
- | ((unsigned int)(Hash) >> 16);
- hash_page_patch_A[1] = (hash_page_patch_A[1] & ~0x7c0)
- | (mb << 6);
- hash_page_patch_A[2] = (hash_page_patch_A[2] & ~0x7c0)
- | (mb2 << 6);
- hash_page_patch_B[0] = (hash_page_patch_B[0] & ~0xffff)
- | hmask;
- hash_page_patch_C[0] = (hash_page_patch_C[0] & ~0xffff)
- | hmask;
- /*
- * Ensure that the locations we've patched have been written
- * out from the data cache and invalidated in the instruction
- * cache, on those machines with split caches.
- */
- flush_icache_range((unsigned long) &hash_page_patch_A[0],
- (unsigned long) &hash_page_patch_C[1]);
- /*
- * Patch up the instructions in hashtable.S:flush_hash_page
- */
- flush_hash_patch_A[0] = (flush_hash_patch_A[0] & ~0xffff)
- | ((unsigned int)(Hash) >> 16);
- flush_hash_patch_A[1] = (flush_hash_patch_A[1] & ~0x7c0)
- | (mb << 6);
- flush_hash_patch_A[2] = (flush_hash_patch_A[2] & ~0x7c0)
- | (mb2 << 6);
- flush_hash_patch_B[0] = (flush_hash_patch_B[0] & ~0xffff)
- | hmask;
- flush_icache_range((unsigned long) &flush_hash_patch_A[0],
- (unsigned long) &flush_hash_patch_B[1]);
- }
-
+
+ /*
+ * Patch up the instructions in hashtable.S:create_hpte
+ */
+ if ( ppc_md.progress ) ppc_md.progress("hash:patch", 0x345);
+ Hash_mask = n_hpteg - 1;
+ hmask = Hash_mask >> (16 - LG_HPTEG_SIZE);
+ mb2 = mb = 32 - LG_HPTEG_SIZE - lg_n_hpteg;
+ if (lg_n_hpteg > 16)
+ mb2 = 16 - LG_HPTEG_SIZE;
+ hash_page_patch_A[0] = (hash_page_patch_A[0] & ~0xffff)
+ | ((unsigned int)(Hash) >> 16);
+ hash_page_patch_A[1] = (hash_page_patch_A[1] & ~0x7c0) | (mb << 6);
+ hash_page_patch_A[2] = (hash_page_patch_A[2] & ~0x7c0) | (mb2 << 6);
+ hash_page_patch_B[0] = (hash_page_patch_B[0] & ~0xffff) | hmask;
+ hash_page_patch_C[0] = (hash_page_patch_C[0] & ~0xffff) | hmask;
+
+ /*
+ * Ensure that the locations we've patched have been written
+ * out from the data cache and invalidated in the instruction
+ * cache, on those machines with split caches.
+ */
+ flush_icache_range((unsigned long) &hash_page_patch_A[0],
+ (unsigned long) &hash_page_patch_C[1]);
+
+ /*
+ * Patch up the instructions in hashtable.S:flush_hash_page
+ */
+ flush_hash_patch_A[0] = (flush_hash_patch_A[0] & ~0xffff)
+ | ((unsigned int)(Hash) >> 16);
+ flush_hash_patch_A[1] = (flush_hash_patch_A[1] & ~0x7c0) | (mb << 6);
+ flush_hash_patch_A[2] = (flush_hash_patch_A[2] & ~0x7c0) | (mb2 << 6);
+ flush_hash_patch_B[0] = (flush_hash_patch_B[0] & ~0xffff) | hmask;
+ flush_icache_range((unsigned long) &flush_hash_patch_A[0],
+ (unsigned long) &flush_hash_patch_B[1]);
+
if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)