aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2006-02-21 23:51:13 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-03-20 04:13:55 -0500
commit9cc3a1ac9a819cadff05ca37bb7f208013a22035 (patch)
tree601fa49272b540b3a3e6cc3728db27c525b73721
parent30c91d576e9ea41c963e7f28643219bda73b0ddc (diff)
[SPARC64]: Make use of Niagara 256MB PTEs for kernel mappings.
We use a bitmap, one bit for every 256MB of memory. If the bit is set we can use a 256MB PTE for linear mappings, else we have to use a 4MB PTE. SUN4V support is there, and we can very easily add support for Panther cpu 256MB PTEs in the future. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--arch/sparc64/kernel/ktlb.S29
-rw-r--r--arch/sparc64/mm/init.c82
2 files changed, 96 insertions, 15 deletions
diff --git a/arch/sparc64/kernel/ktlb.S b/arch/sparc64/kernel/ktlb.S
index 883180be3d59..ae1dac17bc8d 100644
--- a/arch/sparc64/kernel/ktlb.S
+++ b/arch/sparc64/kernel/ktlb.S
@@ -133,8 +133,33 @@ kvmap_dtlb_4v:
133 brgez,pn %g4, kvmap_dtlb_nonlinear 133 brgez,pn %g4, kvmap_dtlb_nonlinear
134 nop 134 nop
135 135
136 sethi %hi(kern_linear_pte_xor), %g2 136 sethi %hi(kpte_linear_bitmap), %g2
137 ldx [%g2 + %lo(kern_linear_pte_xor)], %g2 137 or %g2, %lo(kpte_linear_bitmap), %g2
138
139 /* Clear the PAGE_OFFSET top virtual bits, then shift
140 * down to get a 256MB physical address index.
141 */
142 sllx %g4, 21, %g5
143 mov 1, %g7
144 srlx %g5, 21 + 28, %g5
145
146 /* Don't try this at home kids... this depends upon srlx
147 * only taking the low 6 bits of the shift count in %g5.
148 */
149 sllx %g7, %g5, %g7
150
151 /* Divide by 64 to get the offset into the bitmask. */
152 srlx %g5, 6, %g5
153
154 /* kern_linear_pte_xor[((mask & bit) ? 1 : 0)] */
155 ldx [%g2 + %g5], %g2
156 andcc %g2, %g7, %g0
157 sethi %hi(kern_linear_pte_xor), %g5
158 or %g5, %lo(kern_linear_pte_xor), %g5
159 bne,a,pt %xcc, 1f
160 add %g5, 8, %g5
161
1621: ldx [%g5], %g2
138 163
139 .globl kvmap_linear_patch 164 .globl kvmap_linear_patch
140kvmap_linear_patch: 165kvmap_linear_patch:
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index c7aa4404edca..b5869f00d2d1 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -45,6 +45,19 @@
45 45
46extern void device_scan(void); 46extern void device_scan(void);
47 47
48#define MAX_PHYS_ADDRESS (1UL << 42UL)
49#define KPTE_BITMAP_CHUNK_SZ (256UL * 1024UL * 1024UL)
50#define KPTE_BITMAP_BYTES \
51 ((MAX_PHYS_ADDRESS / KPTE_BITMAP_CHUNK_SZ) / 8)
52
53unsigned long kern_linear_pte_xor[2] __read_mostly;
54
55/* A bitmap, one bit for every 256MB of physical memory. If the bit
56 * is clear, we should use a 4MB page (via kern_linear_pte_xor[0]) else
57 * if set we should use a 256MB page (via kern_linear_pte_xor[1]).
58 */
59unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)];
60
48#define MAX_BANKS 32 61#define MAX_BANKS 32
49 62
50static struct linux_prom64_registers pavail[MAX_BANKS] __initdata; 63static struct linux_prom64_registers pavail[MAX_BANKS] __initdata;
@@ -119,7 +132,6 @@ unsigned long phys_base __read_mostly;
119unsigned long kern_base __read_mostly; 132unsigned long kern_base __read_mostly;
120unsigned long kern_size __read_mostly; 133unsigned long kern_size __read_mostly;
121unsigned long pfn_base __read_mostly; 134unsigned long pfn_base __read_mostly;
122unsigned long kern_linear_pte_xor __read_mostly;
123 135
124/* get_new_mmu_context() uses "cache + 1". */ 136/* get_new_mmu_context() uses "cache + 1". */
125DEFINE_SPINLOCK(ctx_alloc_lock); 137DEFINE_SPINLOCK(ctx_alloc_lock);
@@ -878,6 +890,9 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
878 return end_pfn; 890 return end_pfn;
879} 891}
880 892
893static struct linux_prom64_registers pall[MAX_BANKS] __initdata;
894static int pall_ents __initdata;
895
881#ifdef CONFIG_DEBUG_PAGEALLOC 896#ifdef CONFIG_DEBUG_PAGEALLOC
882static unsigned long kernel_map_range(unsigned long pstart, unsigned long pend, pgprot_t prot) 897static unsigned long kernel_map_range(unsigned long pstart, unsigned long pend, pgprot_t prot)
883{ 898{
@@ -933,14 +948,41 @@ static unsigned long kernel_map_range(unsigned long pstart, unsigned long pend,
933 return alloc_bytes; 948 return alloc_bytes;
934} 949}
935 950
936static struct linux_prom64_registers pall[MAX_BANKS] __initdata;
937static int pall_ents __initdata;
938
939extern unsigned int kvmap_linear_patch[1]; 951extern unsigned int kvmap_linear_patch[1];
952#endif /* CONFIG_DEBUG_PAGEALLOC */
953
954static void __init mark_kpte_bitmap(unsigned long start, unsigned long end)
955{
956 const unsigned long shift_256MB = 28;
957 const unsigned long mask_256MB = ((1UL << shift_256MB) - 1UL);
958 const unsigned long size_256MB = (1UL << shift_256MB);
959
960 while (start < end) {
961 long remains;
962
963 if (start & mask_256MB) {
964 start = (start + size_256MB) & ~mask_256MB;
965 continue;
966 }
967
968 remains = end - start;
969 while (remains >= size_256MB) {
970 unsigned long index = start >> shift_256MB;
971
972 __set_bit(index, kpte_linear_bitmap);
973
974 start += size_256MB;
975 remains -= size_256MB;
976 }
977 }
978}
940 979
941static void __init kernel_physical_mapping_init(void) 980static void __init kernel_physical_mapping_init(void)
942{ 981{
943 unsigned long i, mem_alloced = 0UL; 982 unsigned long i;
983#ifdef CONFIG_DEBUG_PAGEALLOC
984 unsigned long mem_alloced = 0UL;
985#endif
944 986
945 read_obp_memory("reg", &pall[0], &pall_ents); 987 read_obp_memory("reg", &pall[0], &pall_ents);
946 988
@@ -949,10 +991,16 @@ static void __init kernel_physical_mapping_init(void)
949 991
950 phys_start = pall[i].phys_addr; 992 phys_start = pall[i].phys_addr;
951 phys_end = phys_start + pall[i].reg_size; 993 phys_end = phys_start + pall[i].reg_size;
994
995 mark_kpte_bitmap(phys_start, phys_end);
996
997#ifdef CONFIG_DEBUG_PAGEALLOC
952 mem_alloced += kernel_map_range(phys_start, phys_end, 998 mem_alloced += kernel_map_range(phys_start, phys_end,
953 PAGE_KERNEL); 999 PAGE_KERNEL);
1000#endif
954 } 1001 }
955 1002
1003#ifdef CONFIG_DEBUG_PAGEALLOC
956 printk("Allocated %ld bytes for kernel page tables.\n", 1004 printk("Allocated %ld bytes for kernel page tables.\n",
957 mem_alloced); 1005 mem_alloced);
958 1006
@@ -960,8 +1008,10 @@ static void __init kernel_physical_mapping_init(void)
960 flushi(&kvmap_linear_patch[0]); 1008 flushi(&kvmap_linear_patch[0]);
961 1009
962 __flush_tlb_all(); 1010 __flush_tlb_all();
1011#endif
963} 1012}
964 1013
1014#ifdef CONFIG_DEBUG_PAGEALLOC
965void kernel_map_pages(struct page *page, int numpages, int enable) 1015void kernel_map_pages(struct page *page, int numpages, int enable)
966{ 1016{
967 unsigned long phys_start = page_to_pfn(page) << PAGE_SHIFT; 1017 unsigned long phys_start = page_to_pfn(page) << PAGE_SHIFT;
@@ -1172,9 +1222,7 @@ void __init paging_init(void)
1172 pages_avail = 0; 1222 pages_avail = 0;
1173 last_valid_pfn = end_pfn = bootmem_init(&pages_avail); 1223 last_valid_pfn = end_pfn = bootmem_init(&pages_avail);
1174 1224
1175#ifdef CONFIG_DEBUG_PAGEALLOC
1176 kernel_physical_mapping_init(); 1225 kernel_physical_mapping_init();
1177#endif
1178 1226
1179 { 1227 {
1180 unsigned long zones_size[MAX_NR_ZONES]; 1228 unsigned long zones_size[MAX_NR_ZONES];
@@ -1413,10 +1461,13 @@ static void __init sun4u_pgprot_init(void)
1413 pg_iobits = (_PAGE_VALID | _PAGE_PRESENT_4U | __DIRTY_BITS_4U | 1461 pg_iobits = (_PAGE_VALID | _PAGE_PRESENT_4U | __DIRTY_BITS_4U |
1414 __ACCESS_BITS_4U | _PAGE_E_4U); 1462 __ACCESS_BITS_4U | _PAGE_E_4U);
1415 1463
1416 kern_linear_pte_xor = (_PAGE_VALID | _PAGE_SZ4MB_4U) ^ 1464 kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZ4MB_4U) ^
1417 0xfffff80000000000; 1465 0xfffff80000000000;
1418 kern_linear_pte_xor |= (_PAGE_CP_4U | _PAGE_CV_4U | 1466 kern_linear_pte_xor[0] |= (_PAGE_CP_4U | _PAGE_CV_4U |
1419 _PAGE_P_4U | _PAGE_W_4U); 1467 _PAGE_P_4U | _PAGE_W_4U);
1468
1469 /* XXX Should use 256MB on Panther. XXX */
1470 kern_linear_pte_xor[1] = kern_linear_pte_xor[0];
1420 1471
1421 _PAGE_SZBITS = _PAGE_SZBITS_4U; 1472 _PAGE_SZBITS = _PAGE_SZBITS_4U;
1422 _PAGE_ALL_SZ_BITS = (_PAGE_SZ4MB_4U | _PAGE_SZ512K_4U | 1473 _PAGE_ALL_SZ_BITS = (_PAGE_SZ4MB_4U | _PAGE_SZ512K_4U |
@@ -1454,10 +1505,15 @@ static void __init sun4v_pgprot_init(void)
1454 _PAGE_E = _PAGE_E_4V; 1505 _PAGE_E = _PAGE_E_4V;
1455 _PAGE_CACHE = _PAGE_CACHE_4V; 1506 _PAGE_CACHE = _PAGE_CACHE_4V;
1456 1507
1457 kern_linear_pte_xor = (_PAGE_VALID | _PAGE_SZ4MB_4V) ^ 1508 kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZ4MB_4V) ^
1509 0xfffff80000000000;
1510 kern_linear_pte_xor[0] |= (_PAGE_CP_4V | _PAGE_CV_4V |
1511 _PAGE_P_4V | _PAGE_W_4V);
1512
1513 kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZ256MB_4V) ^
1458 0xfffff80000000000; 1514 0xfffff80000000000;
1459 kern_linear_pte_xor |= (_PAGE_CP_4V | _PAGE_CV_4V | 1515 kern_linear_pte_xor[1] |= (_PAGE_CP_4V | _PAGE_CV_4V |
1460 _PAGE_P_4V | _PAGE_W_4V); 1516 _PAGE_P_4V | _PAGE_W_4V);
1461 1517
1462 pg_iobits = (_PAGE_VALID | _PAGE_PRESENT_4V | __DIRTY_BITS_4V | 1518 pg_iobits = (_PAGE_VALID | _PAGE_PRESENT_4V | __DIRTY_BITS_4V |
1463 __ACCESS_BITS_4V | _PAGE_E_4V); 1519 __ACCESS_BITS_4V | _PAGE_E_4V);