diff options
author | David S. Miller <davem@davemloft.net> | 2012-09-06 21:13:58 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-09-06 21:13:58 -0400 |
commit | 4f93d21d2563353df813ee049f6489f340389aab (patch) | |
tree | d12bf9282a121c9a326bce958bdc9736b005f5cc /arch/sparc/mm | |
parent | 699871bc943be418be13208526bc613d68017fab (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.c | 137 | ||||
-rw-r--r-- | arch/sparc/mm/init_64.h | 4 |
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 | ||
54 | unsigned long kern_linear_pte_xor[2] __read_mostly; | 54 | unsigned 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 | */ |
60 | unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)]; | 76 | unsigned 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 | */ |
67 | extern struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES]; | 83 | extern 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, | |||
1358 | extern unsigned int kvmap_linear_patch[1]; | 1374 | extern unsigned int kvmap_linear_patch[1]; |
1359 | #endif /* CONFIG_DEBUG_PAGEALLOC */ | 1375 | #endif /* CONFIG_DEBUG_PAGEALLOC */ |
1360 | 1376 | ||
1361 | static void __init mark_kpte_bitmap(unsigned long start, unsigned long end) | 1377 | static 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) { | 1387 | static const unsigned long kpte_shift_min = 28; /* 256MB */ |
1375 | start = (start + size_256MB) & ~mask_256MB; | 1388 | static const unsigned long kpte_shift_max = 34; /* 16GB */ |
1376 | continue; | 1389 | static const unsigned long kpte_shift_incr = 3; |
1377 | } | ||
1378 | 1390 | ||
1379 | while (remains >= size_256MB) { | 1391 | static 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 | |||
1426 | static 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 | ||
16 | extern unsigned long kern_linear_pte_xor[2]; | 16 | extern unsigned long kern_linear_pte_xor[4]; |
17 | extern unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)]; | 17 | extern unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)]; |
18 | extern unsigned int sparc64_highest_unlocked_tlb_ent; | 18 | extern unsigned int sparc64_highest_unlocked_tlb_ent; |
19 | extern unsigned long sparc64_kern_pri_context; | 19 | extern unsigned long sparc64_kern_pri_context; |