Skip to content

Commit 494e5b6

Browse files
hikerockiesdavem330
authored andcommitted
sparc: Resolve conflict between sparc v9 and M7 on usage of bit 9 of TTE
sparc: Resolve conflict between sparc v9 and M7 on usage of bit 9 of TTE Bit 9 of TTE is CV (Cacheable in V-cache) on sparc v9 processor while the same bit 9 is MCDE (Memory Corruption Detection Enable) on M7 processor. This creates a conflicting usage of the same bit. Kernel sets TTE.cv bit on all pages for sun4v architecture which works well for sparc v9 but enables memory corruption detection on M7 processor which is not the intent. This patch adds code to determine if kernel is running on M7 processor and takes steps to not enable memory corruption detection in TTE erroneously. Signed-off-by: Khalid Aziz <khalid.aziz@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent f0c1a11 commit 494e5b6

File tree

6 files changed

+104
-22
lines changed

6 files changed

+104
-22
lines changed

arch/sparc/include/asm/pgtable_64.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,12 +308,26 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t prot)
308308
" sllx %1, 32, %1\n"
309309
" or %0, %1, %0\n"
310310
" .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"
311322
: "=r" (mask), "=r" (tmp)
312323
: "i" (_PAGE_PADDR_4U | _PAGE_MODIFIED_4U | _PAGE_ACCESSED_4U |
313324
_PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U |
314325
_PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4U),
315326
"i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V |
316327
_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 |
317331
_PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4V));
318332

319333
return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask));
@@ -342,9 +356,15 @@ static inline pgprot_t pgprot_noncached(pgprot_t prot)
342356
" andn %0, %4, %0\n"
343357
" or %0, %5, %0\n"
344358
" .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"
345364
: "=r" (val)
346365
: "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));
348368

349369
return __pgprot(val);
350370
}

arch/sparc/include/asm/trap_block.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ struct sun4v_2insn_patch_entry {
7979
};
8080
extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch,
8181
__sun4v_2insn_patch_end;
82+
extern struct sun4v_2insn_patch_entry __sun_m7_2insn_patch,
83+
__sun_m7_2insn_patch_end;
8284

8385

8486
#endif /* !(__ASSEMBLY__) */

arch/sparc/kernel/entry.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *,
6969
struct sun4v_1insn_patch_entry *);
7070
void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *,
7171
struct sun4v_2insn_patch_entry *);
72+
void sun_m7_patch_2insn_range(struct sun4v_2insn_patch_entry *,
73+
struct sun4v_2insn_patch_entry *);
7274
extern unsigned int dcache_parity_tl1_occurred;
7375
extern unsigned int icache_parity_tl1_occurred;
7476

arch/sparc/kernel/setup_64.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,24 @@ void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *start,
255255
}
256256
}
257257

258+
void 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+
258276
static void __init sun4v_patch(void)
259277
{
260278
extern void sun4v_hvapi_init(void);
@@ -267,6 +285,9 @@ static void __init sun4v_patch(void)
267285

268286
sun4v_patch_2insn_range(&__sun4v_2insn_patch,
269287
&__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);
270291

271292
sun4v_hvapi_init();
272293
}

arch/sparc/kernel/vmlinux.lds.S

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,11 @@ SECTIONS
138138
*(.pause_3insn_patch)
139139
__pause_3insn_patch_end = .;
140140
}
141+
.sun_m7_2insn_patch : {
142+
__sun_m7_2insn_patch = .;
143+
*(.sun_m7_2insn_patch)
144+
__sun_m7_2insn_patch_end = .;
145+
}
141146
PERCPU_SECTION(SMP_CACHE_BYTES)
142147

143148
. = ALIGN(PAGE_SIZE);

arch/sparc/mm/init_64.c

Lines changed: 53 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#include "init_64.h"
5555

5656
unsigned long kern_linear_pte_xor[4] __read_mostly;
57+
static unsigned long page_cache4v_flag;
5758

5859
/* A bitmap, two bits for every 256MB of physical memory. These two
5960
* bits determine what page size we use for kernel linear
@@ -1909,11 +1910,24 @@ static void __init sun4u_linear_pte_xor_finalize(void)
19091910

19101911
static void __init sun4v_linear_pte_xor_finalize(void)
19111912
{
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+
}
19121926
#ifndef CONFIG_DEBUG_PAGEALLOC
19131927
if (cpu_pgsz_mask & HV_PGSZ_MASK_256MB) {
19141928
kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZ256MB_4V) ^
19151929
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 |
19171931
_PAGE_P_4V | _PAGE_W_4V);
19181932
} else {
19191933
kern_linear_pte_xor[1] = kern_linear_pte_xor[0];
@@ -1922,7 +1936,7 @@ static void __init sun4v_linear_pte_xor_finalize(void)
19221936
if (cpu_pgsz_mask & HV_PGSZ_MASK_2GB) {
19231937
kern_linear_pte_xor[2] = (_PAGE_VALID | _PAGE_SZ2GB_4V) ^
19241938
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 |
19261940
_PAGE_P_4V | _PAGE_W_4V);
19271941
} else {
19281942
kern_linear_pte_xor[2] = kern_linear_pte_xor[1];
@@ -1931,7 +1945,7 @@ static void __init sun4v_linear_pte_xor_finalize(void)
19311945
if (cpu_pgsz_mask & HV_PGSZ_MASK_16GB) {
19321946
kern_linear_pte_xor[3] = (_PAGE_VALID | _PAGE_SZ16GB_4V) ^
19331947
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 |
19351949
_PAGE_P_4V | _PAGE_W_4V);
19361950
} else {
19371951
kern_linear_pte_xor[3] = kern_linear_pte_xor[2];
@@ -1958,6 +1972,13 @@ static phys_addr_t __init available_memory(void)
19581972
return available;
19591973
}
19601974

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+
19611982
/* We need to exclude reserved regions. This exclusion will include
19621983
* vmlinux and initrd. To be more precise the initrd size could be used to
19631984
* compute a new lower limit because it is freed later during initialization.
@@ -2034,6 +2055,25 @@ void __init paging_init(void)
20342055
memset(swapper_4m_tsb, 0x40, sizeof(swapper_4m_tsb));
20352056
#endif
20362057

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+
20372077
if (tlb_type == hypervisor)
20382078
sun4v_pgprot_init();
20392079
else
@@ -2274,13 +2314,6 @@ void free_initrd_mem(unsigned long start, unsigned long end)
22742314
}
22752315
#endif
22762316

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-
22842317
pgprot_t PAGE_KERNEL __read_mostly;
22852318
EXPORT_SYMBOL(PAGE_KERNEL);
22862319

@@ -2312,8 +2345,7 @@ int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,
23122345
_PAGE_P_4U | _PAGE_W_4U);
23132346
if (tlb_type == hypervisor)
23142347
pte_base = (_PAGE_VALID | _PAGE_SZ4MB_4V |
2315-
_PAGE_CP_4V | _PAGE_CV_4V |
2316-
_PAGE_P_4V | _PAGE_W_4V);
2348+
page_cache4v_flag | _PAGE_P_4V | _PAGE_W_4V);
23172349

23182350
pte_base |= _PAGE_PMD_HUGE;
23192351

@@ -2450,23 +2482,23 @@ static void __init sun4v_pgprot_init(void)
24502482
int i;
24512483

24522484
PAGE_KERNEL = __pgprot (_PAGE_PRESENT_4V | _PAGE_VALID |
2453-
_PAGE_CACHE_4V | _PAGE_P_4V |
2485+
page_cache4v_flag | _PAGE_P_4V |
24542486
__ACCESS_BITS_4V | __DIRTY_BITS_4V |
24552487
_PAGE_EXEC_4V);
24562488
PAGE_KERNEL_LOCKED = PAGE_KERNEL;
24572489

24582490
_PAGE_IE = _PAGE_IE_4V;
24592491
_PAGE_E = _PAGE_E_4V;
2460-
_PAGE_CACHE = _PAGE_CACHE_4V;
2492+
_PAGE_CACHE = page_cache4v_flag;
24612493

24622494
#ifdef CONFIG_DEBUG_PAGEALLOC
24632495
kern_linear_pte_xor[0] = _PAGE_VALID ^ PAGE_OFFSET;
24642496
#else
24652497
kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZ4MB_4V) ^
24662498
PAGE_OFFSET;
24672499
#endif
2468-
kern_linear_pte_xor[0] |= (_PAGE_CP_4V | _PAGE_CV_4V |
2469-
_PAGE_P_4V | _PAGE_W_4V);
2500+
kern_linear_pte_xor[0] |= (page_cache4v_flag | _PAGE_P_4V |
2501+
_PAGE_W_4V);
24702502

24712503
for (i = 1; i < 4; i++)
24722504
kern_linear_pte_xor[i] = kern_linear_pte_xor[0];
@@ -2479,12 +2511,12 @@ static void __init sun4v_pgprot_init(void)
24792511
_PAGE_SZ4MB_4V | _PAGE_SZ512K_4V |
24802512
_PAGE_SZ64K_4V | _PAGE_SZ8K_4V);
24812513

2482-
page_none = _PAGE_PRESENT_4V | _PAGE_ACCESSED_4V | _PAGE_CACHE_4V;
2483-
page_shared = (_PAGE_VALID | _PAGE_PRESENT_4V | _PAGE_CACHE_4V |
2514+
page_none = _PAGE_PRESENT_4V | _PAGE_ACCESSED_4V | page_cache4v_flag;
2515+
page_shared = (_PAGE_VALID | _PAGE_PRESENT_4V | page_cache4v_flag |
24842516
__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 |
24862518
__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 |
24882520
__ACCESS_BITS_4V | _PAGE_EXEC_4V);
24892521

24902522
page_exec_bit = _PAGE_EXEC_4V;
@@ -2542,7 +2574,7 @@ static unsigned long kern_large_tte(unsigned long paddr)
25422574
_PAGE_EXEC_4U | _PAGE_L_4U | _PAGE_W_4U);
25432575
if (tlb_type == hypervisor)
25442576
val = (_PAGE_VALID | _PAGE_SZ4MB_4V |
2545-
_PAGE_CP_4V | _PAGE_CV_4V | _PAGE_P_4V |
2577+
page_cache4v_flag | _PAGE_P_4V |
25462578
_PAGE_EXEC_4V | _PAGE_W_4V);
25472579

25482580
return val | paddr;

0 commit comments

Comments
 (0)