aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/mm
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-09-06 21:13:58 -0400
committerDavid S. Miller <davem@davemloft.net>2012-09-06 21:13:58 -0400
commit4f93d21d2563353df813ee049f6489f340389aab (patch)
treed12bf9282a121c9a326bce958bdc9736b005f5cc /arch/sparc/mm
parent699871bc943be418be13208526bc613d68017fab (diff)
sparc64: Support 2GB and 16GB page sizes for kernel linear mappings.
SPARC-T4 supports 2GB pages. So convert kpte_linear_bitmap into an array of 2-bit values which index into kern_linear_pte_xor. Now kern_linear_pte_xor is used for 4 page size aligned regions, 4MB, 256MB, 2GB, and 16GB respectively. Enabling 2GB pages is currently hardcoded using a check against sun4v_chip_type. In the future this will be done more cleanly by interrogating the machine description which is the correct way to determine this kind of thing. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/mm')
-rw-r--r--arch/sparc/mm/init_64.c137
-rw-r--r--arch/sparc/mm/init_64.h4
2 files changed, 112 insertions, 29 deletions
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index d58edf5fefdb..c0fc25be0c51 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -51,18 +51,34 @@
51 51
52#include "init_64.h" 52#include "init_64.h"
53 53
54unsigned long kern_linear_pte_xor[2] __read_mostly; 54unsigned long kern_linear_pte_xor[4] __read_mostly;
55 55
56/* A bitmap, one bit for every 256MB of physical memory. If the bit 56/* A bitmap, two bits for every 256MB of physical memory. These two
57 * is clear, we should use a 4MB page (via kern_linear_pte_xor[0]) else 57 * bits determine what page size we use for kernel linear
58 * if set we should use a 256MB page (via kern_linear_pte_xor[1]). 58 * translations. They form an index into kern_linear_pte_xor[]. The
59 * value in the indexed slot is XOR'd with the TLB miss virtual
60 * address to form the resulting TTE. The mapping is:
61 *
62 * 0 ==> 4MB
63 * 1 ==> 256MB
64 * 2 ==> 2GB
65 * 3 ==> 16GB
66 *
67 * All sun4v chips support 256MB pages. Only SPARC-T4 and later
68 * support 2GB pages, and hopefully future cpus will support the 16GB
69 * pages as well. For slots 2 and 3, we encode a 256MB TTE xor there
70 * if these larger page sizes are not supported by the cpu.
71 *
72 * It would be nice to determine this from the machine description
73 * 'cpu' properties, but we need to have this table setup before the
74 * MDESC is initialized.
59 */ 75 */
60unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)]; 76unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)];
61 77
62#ifndef CONFIG_DEBUG_PAGEALLOC 78#ifndef CONFIG_DEBUG_PAGEALLOC
63/* A special kernel TSB for 4MB and 256MB linear mappings. 79/* A special kernel TSB for 4MB, 256MB, 2GB and 16GB linear mappings.
64 * Space is allocated for this right after the trap table 80 * Space is allocated for this right after the trap table in
65 * in arch/sparc64/kernel/head.S 81 * arch/sparc64/kernel/head.S
66 */ 82 */
67extern struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES]; 83extern struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES];
68#endif 84#endif
@@ -1358,32 +1374,75 @@ static unsigned long __ref kernel_map_range(unsigned long pstart,
1358extern unsigned int kvmap_linear_patch[1]; 1374extern unsigned int kvmap_linear_patch[1];
1359#endif /* CONFIG_DEBUG_PAGEALLOC */ 1375#endif /* CONFIG_DEBUG_PAGEALLOC */
1360 1376
1361static void __init mark_kpte_bitmap(unsigned long start, unsigned long end) 1377static void __init kpte_set_val(unsigned long index, unsigned long val)
1362{ 1378{
1363 const unsigned long shift_256MB = 28; 1379 unsigned long *ptr = kpte_linear_bitmap;
1364 const unsigned long mask_256MB = ((1UL << shift_256MB) - 1UL);
1365 const unsigned long size_256MB = (1UL << shift_256MB);
1366 1380
1367 while (start < end) { 1381 val <<= ((index % (BITS_PER_LONG / 2)) * 2);
1368 long remains; 1382 ptr += (index / (BITS_PER_LONG / 2));
1369 1383
1370 remains = end - start; 1384 *ptr |= val;
1371 if (remains < size_256MB) 1385}
1372 break;
1373 1386
1374 if (start & mask_256MB) { 1387static const unsigned long kpte_shift_min = 28; /* 256MB */
1375 start = (start + size_256MB) & ~mask_256MB; 1388static const unsigned long kpte_shift_max = 34; /* 16GB */
1376 continue; 1389static const unsigned long kpte_shift_incr = 3;
1377 }
1378 1390
1379 while (remains >= size_256MB) { 1391static unsigned long kpte_mark_using_shift(unsigned long start, unsigned long end,
1380 unsigned long index = start >> shift_256MB; 1392 unsigned long shift)
1393{
1394 unsigned long size = (1UL << shift);
1395 unsigned long mask = (size - 1UL);
1396 unsigned long remains = end - start;
1397 unsigned long val;
1381 1398
1382 __set_bit(index, kpte_linear_bitmap); 1399 if (remains < size || (start & mask))
1400 return start;
1383 1401
1384 start += size_256MB; 1402 /* VAL maps:
1385 remains -= size_256MB; 1403 *
1404 * shift 28 --> kern_linear_pte_xor index 1
1405 * shift 31 --> kern_linear_pte_xor index 2
1406 * shift 34 --> kern_linear_pte_xor index 3
1407 */
1408 val = ((shift - kpte_shift_min) / kpte_shift_incr) + 1;
1409
1410 remains &= ~mask;
1411 if (shift != kpte_shift_max)
1412 remains = size;
1413
1414 while (remains) {
1415 unsigned long index = start >> kpte_shift_min;
1416
1417 kpte_set_val(index, val);
1418
1419 start += 1UL << kpte_shift_min;
1420 remains -= 1UL << kpte_shift_min;
1421 }
1422
1423 return start;
1424}
1425
1426static void __init mark_kpte_bitmap(unsigned long start, unsigned long end)
1427{
1428 unsigned long smallest_size, smallest_mask;
1429 unsigned long s;
1430
1431 smallest_size = (1UL << kpte_shift_min);
1432 smallest_mask = (smallest_size - 1UL);
1433
1434 while (start < end) {
1435 unsigned long orig_start = start;
1436
1437 for (s = kpte_shift_max; s >= kpte_shift_min; s -= kpte_shift_incr) {
1438 start = kpte_mark_using_shift(start, end, s);
1439
1440 if (start != orig_start)
1441 break;
1386 } 1442 }
1443
1444 if (start == orig_start)
1445 start = (start + smallest_size) & ~smallest_mask;
1387 } 1446 }
1388} 1447}
1389 1448
@@ -1577,13 +1636,15 @@ static void __init sun4v_ktsb_init(void)
1577 ktsb_descr[0].resv = 0; 1636 ktsb_descr[0].resv = 0;
1578 1637
1579#ifndef CONFIG_DEBUG_PAGEALLOC 1638#ifndef CONFIG_DEBUG_PAGEALLOC
1580 /* Second KTSB for 4MB/256MB mappings. */ 1639 /* Second KTSB for 4MB/256MB/2GB/16GB mappings. */
1581 ktsb_pa = (kern_base + 1640 ktsb_pa = (kern_base +
1582 ((unsigned long)&swapper_4m_tsb[0] - KERNBASE)); 1641 ((unsigned long)&swapper_4m_tsb[0] - KERNBASE));
1583 1642
1584 ktsb_descr[1].pgsz_idx = HV_PGSZ_IDX_4MB; 1643 ktsb_descr[1].pgsz_idx = HV_PGSZ_IDX_4MB;
1585 ktsb_descr[1].pgsz_mask = (HV_PGSZ_MASK_4MB | 1644 ktsb_descr[1].pgsz_mask = (HV_PGSZ_MASK_4MB |
1586 HV_PGSZ_MASK_256MB); 1645 HV_PGSZ_MASK_256MB);
1646 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA4)
1647 ktsb_descr[1].pgsz_mask |= HV_PGSZ_MASK_2GB;
1587 ktsb_descr[1].assoc = 1; 1648 ktsb_descr[1].assoc = 1;
1588 ktsb_descr[1].num_ttes = KERNEL_TSB4M_NENTRIES; 1649 ktsb_descr[1].num_ttes = KERNEL_TSB4M_NENTRIES;
1589 ktsb_descr[1].ctx_idx = 0; 1650 ktsb_descr[1].ctx_idx = 0;
@@ -2110,6 +2171,7 @@ static void __init sun4u_pgprot_init(void)
2110{ 2171{
2111 unsigned long page_none, page_shared, page_copy, page_readonly; 2172 unsigned long page_none, page_shared, page_copy, page_readonly;
2112 unsigned long page_exec_bit; 2173 unsigned long page_exec_bit;
2174 int i;
2113 2175
2114 PAGE_KERNEL = __pgprot (_PAGE_PRESENT_4U | _PAGE_VALID | 2176 PAGE_KERNEL = __pgprot (_PAGE_PRESENT_4U | _PAGE_VALID |
2115 _PAGE_CACHE_4U | _PAGE_P_4U | 2177 _PAGE_CACHE_4U | _PAGE_P_4U |
@@ -2138,7 +2200,8 @@ static void __init sun4u_pgprot_init(void)
2138 _PAGE_P_4U | _PAGE_W_4U); 2200 _PAGE_P_4U | _PAGE_W_4U);
2139 2201
2140 /* XXX Should use 256MB on Panther. XXX */ 2202 /* XXX Should use 256MB on Panther. XXX */
2141 kern_linear_pte_xor[1] = kern_linear_pte_xor[0]; 2203 for (i = 1; i < 4; i++)
2204 kern_linear_pte_xor[i] = kern_linear_pte_xor[0];
2142 2205
2143 _PAGE_SZBITS = _PAGE_SZBITS_4U; 2206 _PAGE_SZBITS = _PAGE_SZBITS_4U;
2144 _PAGE_ALL_SZ_BITS = (_PAGE_SZ4MB_4U | _PAGE_SZ512K_4U | 2207 _PAGE_ALL_SZ_BITS = (_PAGE_SZ4MB_4U | _PAGE_SZ512K_4U |
@@ -2164,6 +2227,7 @@ static void __init sun4v_pgprot_init(void)
2164{ 2227{
2165 unsigned long page_none, page_shared, page_copy, page_readonly; 2228 unsigned long page_none, page_shared, page_copy, page_readonly;
2166 unsigned long page_exec_bit; 2229 unsigned long page_exec_bit;
2230 int i;
2167 2231
2168 PAGE_KERNEL = __pgprot (_PAGE_PRESENT_4V | _PAGE_VALID | 2232 PAGE_KERNEL = __pgprot (_PAGE_PRESENT_4V | _PAGE_VALID |
2169 _PAGE_CACHE_4V | _PAGE_P_4V | 2233 _PAGE_CACHE_4V | _PAGE_P_4V |
@@ -2195,6 +2259,25 @@ static void __init sun4v_pgprot_init(void)
2195 kern_linear_pte_xor[1] |= (_PAGE_CP_4V | _PAGE_CV_4V | 2259 kern_linear_pte_xor[1] |= (_PAGE_CP_4V | _PAGE_CV_4V |
2196 _PAGE_P_4V | _PAGE_W_4V); 2260 _PAGE_P_4V | _PAGE_W_4V);
2197 2261
2262 i = 2;
2263
2264 if (sun4v_chip_type == SUN4V_CHIP_NIAGARA4) {
2265#ifdef CONFIG_DEBUG_PAGEALLOC
2266 kern_linear_pte_xor[2] = (_PAGE_VALID | _PAGE_SZBITS_4V) ^
2267 0xfffff80000000000UL;
2268#else
2269 kern_linear_pte_xor[2] = (_PAGE_VALID | _PAGE_SZ2GB_4V) ^
2270 0xfffff80000000000UL;
2271#endif
2272 kern_linear_pte_xor[2] |= (_PAGE_CP_4V | _PAGE_CV_4V |
2273 _PAGE_P_4V | _PAGE_W_4V);
2274
2275 i = 3;
2276 }
2277
2278 for (; i < 4; i++)
2279 kern_linear_pte_xor[i] = kern_linear_pte_xor[i - 1];
2280
2198 pg_iobits = (_PAGE_VALID | _PAGE_PRESENT_4V | __DIRTY_BITS_4V | 2281 pg_iobits = (_PAGE_VALID | _PAGE_PRESENT_4V | __DIRTY_BITS_4V |
2199 __ACCESS_BITS_4V | _PAGE_E_4V); 2282 __ACCESS_BITS_4V | _PAGE_E_4V);
2200 2283
diff --git a/arch/sparc/mm/init_64.h b/arch/sparc/mm/init_64.h
index 3e1ac8b96cae..0661aa606dec 100644
--- a/arch/sparc/mm/init_64.h
+++ b/arch/sparc/mm/init_64.h
@@ -8,12 +8,12 @@
8#define MAX_PHYS_ADDRESS (1UL << 41UL) 8#define MAX_PHYS_ADDRESS (1UL << 41UL)
9#define KPTE_BITMAP_CHUNK_SZ (256UL * 1024UL * 1024UL) 9#define KPTE_BITMAP_CHUNK_SZ (256UL * 1024UL * 1024UL)
10#define KPTE_BITMAP_BYTES \ 10#define KPTE_BITMAP_BYTES \
11 ((MAX_PHYS_ADDRESS / KPTE_BITMAP_CHUNK_SZ) / 8) 11 ((MAX_PHYS_ADDRESS / KPTE_BITMAP_CHUNK_SZ) / 4)
12#define VALID_ADDR_BITMAP_CHUNK_SZ (4UL * 1024UL * 1024UL) 12#define VALID_ADDR_BITMAP_CHUNK_SZ (4UL * 1024UL * 1024UL)
13#define VALID_ADDR_BITMAP_BYTES \ 13#define VALID_ADDR_BITMAP_BYTES \
14 ((MAX_PHYS_ADDRESS / VALID_ADDR_BITMAP_CHUNK_SZ) / 8) 14 ((MAX_PHYS_ADDRESS / VALID_ADDR_BITMAP_CHUNK_SZ) / 8)
15 15
16extern unsigned long kern_linear_pte_xor[2]; 16extern unsigned long kern_linear_pte_xor[4];
17extern unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)]; 17extern unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)];
18extern unsigned int sparc64_highest_unlocked_tlb_ent; 18extern unsigned int sparc64_highest_unlocked_tlb_ent;
19extern unsigned long sparc64_kern_pri_context; 19extern unsigned long sparc64_kern_pri_context;