aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sparc/include/asm/pgtable_64.h22
-rw-r--r--arch/sparc/include/asm/trap_block.h2
-rw-r--r--arch/sparc/kernel/entry.h2
-rw-r--r--arch/sparc/kernel/setup_64.c21
-rw-r--r--arch/sparc/kernel/vmlinux.lds.S5
-rw-r--r--arch/sparc/mm/init_64.c74
6 files changed, 104 insertions, 22 deletions
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index dc165ebdf05a..2a52c91d2c8a 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -308,12 +308,26 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t prot)
308 " sllx %1, 32, %1\n" 308 " sllx %1, 32, %1\n"
309 " or %0, %1, %0\n" 309 " or %0, %1, %0\n"
310 " .previous\n" 310 " .previous\n"
311 " .section .sun_m7_2insn_patch, \"ax\"\n"
312 " .word 661b\n"
313 " sethi %%uhi(%4), %1\n"
314 " sethi %%hi(%4), %0\n"
315 " .word 662b\n"
316 " or %1, %%ulo(%4), %1\n"
317 " or %0, %%lo(%4), %0\n"
318 " .word 663b\n"
319 " sllx %1, 32, %1\n"
320 " or %0, %1, %0\n"
321 " .previous\n"
311 : "=r" (mask), "=r" (tmp) 322 : "=r" (mask), "=r" (tmp)
312 : "i" (_PAGE_PADDR_4U | _PAGE_MODIFIED_4U | _PAGE_ACCESSED_4U | 323 : "i" (_PAGE_PADDR_4U | _PAGE_MODIFIED_4U | _PAGE_ACCESSED_4U |
313 _PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U | 324 _PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U |
314 _PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4U), 325 _PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4U),
315 "i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V | 326 "i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V |
316 _PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V | 327 _PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V |
328 _PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4V),
329 "i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V |
330 _PAGE_CP_4V | _PAGE_E_4V |
317 _PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4V)); 331 _PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4V));
318 332
319 return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask)); 333 return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask));
@@ -342,9 +356,15 @@ static inline pgprot_t pgprot_noncached(pgprot_t prot)
342 " andn %0, %4, %0\n" 356 " andn %0, %4, %0\n"
343 " or %0, %5, %0\n" 357 " or %0, %5, %0\n"
344 " .previous\n" 358 " .previous\n"
359 " .section .sun_m7_2insn_patch, \"ax\"\n"
360 " .word 661b\n"
361 " andn %0, %6, %0\n"
362 " or %0, %5, %0\n"
363 " .previous\n"
345 : "=r" (val) 364 : "=r" (val)
346 : "0" (val), "i" (_PAGE_CP_4U | _PAGE_CV_4U), "i" (_PAGE_E_4U), 365 : "0" (val), "i" (_PAGE_CP_4U | _PAGE_CV_4U), "i" (_PAGE_E_4U),
347 "i" (_PAGE_CP_4V | _PAGE_CV_4V), "i" (_PAGE_E_4V)); 366 "i" (_PAGE_CP_4V | _PAGE_CV_4V), "i" (_PAGE_E_4V),
367 "i" (_PAGE_CP_4V));
348 368
349 return __pgprot(val); 369 return __pgprot(val);
350} 370}
diff --git a/arch/sparc/include/asm/trap_block.h b/arch/sparc/include/asm/trap_block.h
index 6fd4436d32f0..ec9c04de3664 100644
--- a/arch/sparc/include/asm/trap_block.h
+++ b/arch/sparc/include/asm/trap_block.h
@@ -79,6 +79,8 @@ struct sun4v_2insn_patch_entry {
79}; 79};
80extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch, 80extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch,
81 __sun4v_2insn_patch_end; 81 __sun4v_2insn_patch_end;
82extern struct sun4v_2insn_patch_entry __sun_m7_2insn_patch,
83 __sun_m7_2insn_patch_end;
82 84
83 85
84#endif /* !(__ASSEMBLY__) */ 86#endif /* !(__ASSEMBLY__) */
diff --git a/arch/sparc/kernel/entry.h b/arch/sparc/kernel/entry.h
index 07cc49e541f4..0f679421b468 100644
--- a/arch/sparc/kernel/entry.h
+++ b/arch/sparc/kernel/entry.h
@@ -69,6 +69,8 @@ void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *,
69 struct sun4v_1insn_patch_entry *); 69 struct sun4v_1insn_patch_entry *);
70void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *, 70void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *,
71 struct sun4v_2insn_patch_entry *); 71 struct sun4v_2insn_patch_entry *);
72void sun_m7_patch_2insn_range(struct sun4v_2insn_patch_entry *,
73 struct sun4v_2insn_patch_entry *);
72extern unsigned int dcache_parity_tl1_occurred; 74extern unsigned int dcache_parity_tl1_occurred;
73extern unsigned int icache_parity_tl1_occurred; 75extern unsigned int icache_parity_tl1_occurred;
74 76
diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c
index c38d19fc27ba..f7b261749383 100644
--- a/arch/sparc/kernel/setup_64.c
+++ b/arch/sparc/kernel/setup_64.c
@@ -255,6 +255,24 @@ void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *start,
255 } 255 }
256} 256}
257 257
258void sun_m7_patch_2insn_range(struct sun4v_2insn_patch_entry *start,
259 struct sun4v_2insn_patch_entry *end)
260{
261 while (start < end) {
262 unsigned long addr = start->addr;
263
264 *(unsigned int *) (addr + 0) = start->insns[0];
265 wmb();
266 __asm__ __volatile__("flush %0" : : "r" (addr + 0));
267
268 *(unsigned int *) (addr + 4) = start->insns[1];
269 wmb();
270 __asm__ __volatile__("flush %0" : : "r" (addr + 4));
271
272 start++;
273 }
274}
275
258static void __init sun4v_patch(void) 276static void __init sun4v_patch(void)
259{ 277{
260 extern void sun4v_hvapi_init(void); 278 extern void sun4v_hvapi_init(void);
@@ -267,6 +285,9 @@ static void __init sun4v_patch(void)
267 285
268 sun4v_patch_2insn_range(&__sun4v_2insn_patch, 286 sun4v_patch_2insn_range(&__sun4v_2insn_patch,
269 &__sun4v_2insn_patch_end); 287 &__sun4v_2insn_patch_end);
288 if (sun4v_chip_type == SUN4V_CHIP_SPARC_M7)
289 sun_m7_patch_2insn_range(&__sun_m7_2insn_patch,
290 &__sun_m7_2insn_patch_end);
270 291
271 sun4v_hvapi_init(); 292 sun4v_hvapi_init();
272} 293}
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index 09243057cb0b..f1a2f688b28a 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -138,6 +138,11 @@ SECTIONS
138 *(.pause_3insn_patch) 138 *(.pause_3insn_patch)
139 __pause_3insn_patch_end = .; 139 __pause_3insn_patch_end = .;
140 } 140 }
141 .sun_m7_2insn_patch : {
142 __sun_m7_2insn_patch = .;
143 *(.sun_m7_2insn_patch)
144 __sun_m7_2insn_patch_end = .;
145 }
141 PERCPU_SECTION(SMP_CACHE_BYTES) 146 PERCPU_SECTION(SMP_CACHE_BYTES)
142 147
143 . = ALIGN(PAGE_SIZE); 148 . = ALIGN(PAGE_SIZE);
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 4ca0d6ba5ec8..559cb744112c 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -54,6 +54,7 @@
54#include "init_64.h" 54#include "init_64.h"
55 55
56unsigned long kern_linear_pte_xor[4] __read_mostly; 56unsigned long kern_linear_pte_xor[4] __read_mostly;
57static unsigned long page_cache4v_flag;
57 58
58/* A bitmap, two bits for every 256MB of physical memory. These two 59/* A bitmap, two bits for every 256MB of physical memory. These two
59 * bits determine what page size we use for kernel linear 60 * bits determine what page size we use for kernel linear
@@ -1909,11 +1910,24 @@ static void __init sun4u_linear_pte_xor_finalize(void)
1909 1910
1910static void __init sun4v_linear_pte_xor_finalize(void) 1911static void __init sun4v_linear_pte_xor_finalize(void)
1911{ 1912{
1913 unsigned long pagecv_flag;
1914
1915 /* Bit 9 of TTE is no longer CV bit on M7 processor and it instead
1916 * enables MCD error. Do not set bit 9 on M7 processor.
1917 */
1918 switch (sun4v_chip_type) {
1919 case SUN4V_CHIP_SPARC_M7:
1920 pagecv_flag = 0x00;
1921 break;
1922 default:
1923 pagecv_flag = _PAGE_CV_4V;
1924 break;
1925 }
1912#ifndef CONFIG_DEBUG_PAGEALLOC 1926#ifndef CONFIG_DEBUG_PAGEALLOC
1913 if (cpu_pgsz_mask & HV_PGSZ_MASK_256MB) { 1927 if (cpu_pgsz_mask & HV_PGSZ_MASK_256MB) {
1914 kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZ256MB_4V) ^ 1928 kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZ256MB_4V) ^
1915 PAGE_OFFSET; 1929 PAGE_OFFSET;
1916 kern_linear_pte_xor[1] |= (_PAGE_CP_4V | _PAGE_CV_4V | 1930 kern_linear_pte_xor[1] |= (_PAGE_CP_4V | pagecv_flag |
1917 _PAGE_P_4V | _PAGE_W_4V); 1931 _PAGE_P_4V | _PAGE_W_4V);
1918 } else { 1932 } else {
1919 kern_linear_pte_xor[1] = kern_linear_pte_xor[0]; 1933 kern_linear_pte_xor[1] = kern_linear_pte_xor[0];
@@ -1922,7 +1936,7 @@ static void __init sun4v_linear_pte_xor_finalize(void)
1922 if (cpu_pgsz_mask & HV_PGSZ_MASK_2GB) { 1936 if (cpu_pgsz_mask & HV_PGSZ_MASK_2GB) {
1923 kern_linear_pte_xor[2] = (_PAGE_VALID | _PAGE_SZ2GB_4V) ^ 1937 kern_linear_pte_xor[2] = (_PAGE_VALID | _PAGE_SZ2GB_4V) ^
1924 PAGE_OFFSET; 1938 PAGE_OFFSET;
1925 kern_linear_pte_xor[2] |= (_PAGE_CP_4V | _PAGE_CV_4V | 1939 kern_linear_pte_xor[2] |= (_PAGE_CP_4V | pagecv_flag |
1926 _PAGE_P_4V | _PAGE_W_4V); 1940 _PAGE_P_4V | _PAGE_W_4V);
1927 } else { 1941 } else {
1928 kern_linear_pte_xor[2] = kern_linear_pte_xor[1]; 1942 kern_linear_pte_xor[2] = kern_linear_pte_xor[1];
@@ -1931,7 +1945,7 @@ static void __init sun4v_linear_pte_xor_finalize(void)
1931 if (cpu_pgsz_mask & HV_PGSZ_MASK_16GB) { 1945 if (cpu_pgsz_mask & HV_PGSZ_MASK_16GB) {
1932 kern_linear_pte_xor[3] = (_PAGE_VALID | _PAGE_SZ16GB_4V) ^ 1946 kern_linear_pte_xor[3] = (_PAGE_VALID | _PAGE_SZ16GB_4V) ^
1933 PAGE_OFFSET; 1947 PAGE_OFFSET;
1934 kern_linear_pte_xor[3] |= (_PAGE_CP_4V | _PAGE_CV_4V | 1948 kern_linear_pte_xor[3] |= (_PAGE_CP_4V | pagecv_flag |
1935 _PAGE_P_4V | _PAGE_W_4V); 1949 _PAGE_P_4V | _PAGE_W_4V);
1936 } else { 1950 } else {
1937 kern_linear_pte_xor[3] = kern_linear_pte_xor[2]; 1951 kern_linear_pte_xor[3] = kern_linear_pte_xor[2];
@@ -1958,6 +1972,13 @@ static phys_addr_t __init available_memory(void)
1958 return available; 1972 return available;
1959} 1973}
1960 1974
1975#define _PAGE_CACHE_4U (_PAGE_CP_4U | _PAGE_CV_4U)
1976#define _PAGE_CACHE_4V (_PAGE_CP_4V | _PAGE_CV_4V)
1977#define __DIRTY_BITS_4U (_PAGE_MODIFIED_4U | _PAGE_WRITE_4U | _PAGE_W_4U)
1978#define __DIRTY_BITS_4V (_PAGE_MODIFIED_4V | _PAGE_WRITE_4V | _PAGE_W_4V)
1979#define __ACCESS_BITS_4U (_PAGE_ACCESSED_4U | _PAGE_READ_4U | _PAGE_R)
1980#define __ACCESS_BITS_4V (_PAGE_ACCESSED_4V | _PAGE_READ_4V | _PAGE_R)
1981
1961/* We need to exclude reserved regions. This exclusion will include 1982/* We need to exclude reserved regions. This exclusion will include
1962 * vmlinux and initrd. To be more precise the initrd size could be used to 1983 * vmlinux and initrd. To be more precise the initrd size could be used to
1963 * compute a new lower limit because it is freed later during initialization. 1984 * compute a new lower limit because it is freed later during initialization.
@@ -2034,6 +2055,25 @@ void __init paging_init(void)
2034 memset(swapper_4m_tsb, 0x40, sizeof(swapper_4m_tsb)); 2055 memset(swapper_4m_tsb, 0x40, sizeof(swapper_4m_tsb));
2035#endif 2056#endif
2036 2057
2058 /* TTE.cv bit on sparc v9 occupies the same position as TTE.mcde
2059 * bit on M7 processor. This is a conflicting usage of the same
2060 * bit. Enabling TTE.cv on M7 would turn on Memory Corruption
2061 * Detection error on all pages and this will lead to problems
2062 * later. Kernel does not run with MCD enabled and hence rest
2063 * of the required steps to fully configure memory corruption
2064 * detection are not taken. We need to ensure TTE.mcde is not
2065 * set on M7 processor. Compute the value of cacheability
2066 * flag for use later taking this into consideration.
2067 */
2068 switch (sun4v_chip_type) {
2069 case SUN4V_CHIP_SPARC_M7:
2070 page_cache4v_flag = _PAGE_CP_4V;
2071 break;
2072 default:
2073 page_cache4v_flag = _PAGE_CACHE_4V;
2074 break;
2075 }
2076
2037 if (tlb_type == hypervisor) 2077 if (tlb_type == hypervisor)
2038 sun4v_pgprot_init(); 2078 sun4v_pgprot_init();
2039 else 2079 else
@@ -2274,13 +2314,6 @@ void free_initrd_mem(unsigned long start, unsigned long end)
2274} 2314}
2275#endif 2315#endif
2276 2316
2277#define _PAGE_CACHE_4U (_PAGE_CP_4U | _PAGE_CV_4U)
2278#define _PAGE_CACHE_4V (_PAGE_CP_4V | _PAGE_CV_4V)
2279#define __DIRTY_BITS_4U (_PAGE_MODIFIED_4U | _PAGE_WRITE_4U | _PAGE_W_4U)
2280#define __DIRTY_BITS_4V (_PAGE_MODIFIED_4V | _PAGE_WRITE_4V | _PAGE_W_4V)
2281#define __ACCESS_BITS_4U (_PAGE_ACCESSED_4U | _PAGE_READ_4U | _PAGE_R)
2282#define __ACCESS_BITS_4V (_PAGE_ACCESSED_4V | _PAGE_READ_4V | _PAGE_R)
2283
2284pgprot_t PAGE_KERNEL __read_mostly; 2317pgprot_t PAGE_KERNEL __read_mostly;
2285EXPORT_SYMBOL(PAGE_KERNEL); 2318EXPORT_SYMBOL(PAGE_KERNEL);
2286 2319
@@ -2312,8 +2345,7 @@ int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,
2312 _PAGE_P_4U | _PAGE_W_4U); 2345 _PAGE_P_4U | _PAGE_W_4U);
2313 if (tlb_type == hypervisor) 2346 if (tlb_type == hypervisor)
2314 pte_base = (_PAGE_VALID | _PAGE_SZ4MB_4V | 2347 pte_base = (_PAGE_VALID | _PAGE_SZ4MB_4V |
2315 _PAGE_CP_4V | _PAGE_CV_4V | 2348 page_cache4v_flag | _PAGE_P_4V | _PAGE_W_4V);
2316 _PAGE_P_4V | _PAGE_W_4V);
2317 2349
2318 pte_base |= _PAGE_PMD_HUGE; 2350 pte_base |= _PAGE_PMD_HUGE;
2319 2351
@@ -2450,14 +2482,14 @@ static void __init sun4v_pgprot_init(void)
2450 int i; 2482 int i;
2451 2483
2452 PAGE_KERNEL = __pgprot (_PAGE_PRESENT_4V | _PAGE_VALID | 2484 PAGE_KERNEL = __pgprot (_PAGE_PRESENT_4V | _PAGE_VALID |
2453 _PAGE_CACHE_4V | _PAGE_P_4V | 2485 page_cache4v_flag | _PAGE_P_4V |
2454 __ACCESS_BITS_4V | __DIRTY_BITS_4V | 2486 __ACCESS_BITS_4V | __DIRTY_BITS_4V |
2455 _PAGE_EXEC_4V); 2487 _PAGE_EXEC_4V);
2456 PAGE_KERNEL_LOCKED = PAGE_KERNEL; 2488 PAGE_KERNEL_LOCKED = PAGE_KERNEL;
2457 2489
2458 _PAGE_IE = _PAGE_IE_4V; 2490 _PAGE_IE = _PAGE_IE_4V;
2459 _PAGE_E = _PAGE_E_4V; 2491 _PAGE_E = _PAGE_E_4V;
2460 _PAGE_CACHE = _PAGE_CACHE_4V; 2492 _PAGE_CACHE = page_cache4v_flag;
2461 2493
2462#ifdef CONFIG_DEBUG_PAGEALLOC 2494#ifdef CONFIG_DEBUG_PAGEALLOC
2463 kern_linear_pte_xor[0] = _PAGE_VALID ^ PAGE_OFFSET; 2495 kern_linear_pte_xor[0] = _PAGE_VALID ^ PAGE_OFFSET;
@@ -2465,8 +2497,8 @@ static void __init sun4v_pgprot_init(void)
2465 kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZ4MB_4V) ^ 2497 kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZ4MB_4V) ^
2466 PAGE_OFFSET; 2498 PAGE_OFFSET;
2467#endif 2499#endif
2468 kern_linear_pte_xor[0] |= (_PAGE_CP_4V | _PAGE_CV_4V | 2500 kern_linear_pte_xor[0] |= (page_cache4v_flag | _PAGE_P_4V |
2469 _PAGE_P_4V | _PAGE_W_4V); 2501 _PAGE_W_4V);
2470 2502
2471 for (i = 1; i < 4; i++) 2503 for (i = 1; i < 4; i++)
2472 kern_linear_pte_xor[i] = kern_linear_pte_xor[0]; 2504 kern_linear_pte_xor[i] = kern_linear_pte_xor[0];
@@ -2479,12 +2511,12 @@ static void __init sun4v_pgprot_init(void)
2479 _PAGE_SZ4MB_4V | _PAGE_SZ512K_4V | 2511 _PAGE_SZ4MB_4V | _PAGE_SZ512K_4V |
2480 _PAGE_SZ64K_4V | _PAGE_SZ8K_4V); 2512 _PAGE_SZ64K_4V | _PAGE_SZ8K_4V);
2481 2513
2482 page_none = _PAGE_PRESENT_4V | _PAGE_ACCESSED_4V | _PAGE_CACHE_4V; 2514 page_none = _PAGE_PRESENT_4V | _PAGE_ACCESSED_4V | page_cache4v_flag;
2483 page_shared = (_PAGE_VALID | _PAGE_PRESENT_4V | _PAGE_CACHE_4V | 2515 page_shared = (_PAGE_VALID | _PAGE_PRESENT_4V | page_cache4v_flag |
2484 __ACCESS_BITS_4V | _PAGE_WRITE_4V | _PAGE_EXEC_4V); 2516 __ACCESS_BITS_4V | _PAGE_WRITE_4V | _PAGE_EXEC_4V);
2485 page_copy = (_PAGE_VALID | _PAGE_PRESENT_4V | _PAGE_CACHE_4V | 2517 page_copy = (_PAGE_VALID | _PAGE_PRESENT_4V | page_cache4v_flag |
2486 __ACCESS_BITS_4V | _PAGE_EXEC_4V); 2518 __ACCESS_BITS_4V | _PAGE_EXEC_4V);
2487 page_readonly = (_PAGE_VALID | _PAGE_PRESENT_4V | _PAGE_CACHE_4V | 2519 page_readonly = (_PAGE_VALID | _PAGE_PRESENT_4V | page_cache4v_flag |
2488 __ACCESS_BITS_4V | _PAGE_EXEC_4V); 2520 __ACCESS_BITS_4V | _PAGE_EXEC_4V);
2489 2521
2490 page_exec_bit = _PAGE_EXEC_4V; 2522 page_exec_bit = _PAGE_EXEC_4V;
@@ -2542,7 +2574,7 @@ static unsigned long kern_large_tte(unsigned long paddr)
2542 _PAGE_EXEC_4U | _PAGE_L_4U | _PAGE_W_4U); 2574 _PAGE_EXEC_4U | _PAGE_L_4U | _PAGE_W_4U);
2543 if (tlb_type == hypervisor) 2575 if (tlb_type == hypervisor)
2544 val = (_PAGE_VALID | _PAGE_SZ4MB_4V | 2576 val = (_PAGE_VALID | _PAGE_SZ4MB_4V |
2545 _PAGE_CP_4V | _PAGE_CV_4V | _PAGE_P_4V | 2577 page_cache4v_flag | _PAGE_P_4V |
2546 _PAGE_EXEC_4V | _PAGE_W_4V); 2578 _PAGE_EXEC_4V | _PAGE_W_4V);
2547 2579
2548 return val | paddr; 2580 return val | paddr;