diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sparc64/kernel/ktlb.S | 29 | ||||
-rw-r--r-- | arch/sparc64/mm/init.c | 82 |
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 | |||
162 | 1: ldx [%g5], %g2 | ||
138 | 163 | ||
139 | .globl kvmap_linear_patch | 164 | .globl kvmap_linear_patch |
140 | kvmap_linear_patch: | 165 | kvmap_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 | ||
46 | extern void device_scan(void); | 46 | extern 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 | |||
53 | unsigned 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 | */ | ||
59 | unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)]; | ||
60 | |||
48 | #define MAX_BANKS 32 | 61 | #define MAX_BANKS 32 |
49 | 62 | ||
50 | static struct linux_prom64_registers pavail[MAX_BANKS] __initdata; | 63 | static struct linux_prom64_registers pavail[MAX_BANKS] __initdata; |
@@ -119,7 +132,6 @@ unsigned long phys_base __read_mostly; | |||
119 | unsigned long kern_base __read_mostly; | 132 | unsigned long kern_base __read_mostly; |
120 | unsigned long kern_size __read_mostly; | 133 | unsigned long kern_size __read_mostly; |
121 | unsigned long pfn_base __read_mostly; | 134 | unsigned long pfn_base __read_mostly; |
122 | unsigned 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". */ |
125 | DEFINE_SPINLOCK(ctx_alloc_lock); | 137 | DEFINE_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 | ||
893 | static struct linux_prom64_registers pall[MAX_BANKS] __initdata; | ||
894 | static int pall_ents __initdata; | ||
895 | |||
881 | #ifdef CONFIG_DEBUG_PAGEALLOC | 896 | #ifdef CONFIG_DEBUG_PAGEALLOC |
882 | static unsigned long kernel_map_range(unsigned long pstart, unsigned long pend, pgprot_t prot) | 897 | static 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 | ||
936 | static struct linux_prom64_registers pall[MAX_BANKS] __initdata; | ||
937 | static int pall_ents __initdata; | ||
938 | |||
939 | extern unsigned int kvmap_linear_patch[1]; | 951 | extern unsigned int kvmap_linear_patch[1]; |
952 | #endif /* CONFIG_DEBUG_PAGEALLOC */ | ||
953 | |||
954 | static 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 | ||
941 | static void __init kernel_physical_mapping_init(void) | 980 | static 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 | ||
965 | void kernel_map_pages(struct page *page, int numpages, int enable) | 1015 | void 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); |