diff options
Diffstat (limited to 'arch/sparc/mm/init_64.c')
| -rw-r--r-- | arch/sparc/mm/init_64.c | 74 | 
1 files changed, 53 insertions, 21 deletions
| 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 @@  #include "init_64.h"  unsigned long kern_linear_pte_xor[4] __read_mostly; +static unsigned long page_cache4v_flag;  /* A bitmap, two bits for every 256MB of physical memory.  These two   * bits determine what page size we use for kernel linear @@ -1909,11 +1910,24 @@ static void __init sun4u_linear_pte_xor_finalize(void)  static void __init sun4v_linear_pte_xor_finalize(void)  { +	unsigned long pagecv_flag; + +	/* Bit 9 of TTE is no longer CV bit on M7 processor and it instead +	 * enables MCD error. Do not set bit 9 on M7 processor. +	 */ +	switch (sun4v_chip_type) { +	case SUN4V_CHIP_SPARC_M7: +		pagecv_flag = 0x00; +		break; +	default: +		pagecv_flag = _PAGE_CV_4V; +		break; +	}  #ifndef CONFIG_DEBUG_PAGEALLOC  	if (cpu_pgsz_mask & HV_PGSZ_MASK_256MB) {  		kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZ256MB_4V) ^  			PAGE_OFFSET; -		kern_linear_pte_xor[1] |= (_PAGE_CP_4V | _PAGE_CV_4V | +		kern_linear_pte_xor[1] |= (_PAGE_CP_4V | pagecv_flag |  					   _PAGE_P_4V | _PAGE_W_4V);  	} else {  		kern_linear_pte_xor[1] = kern_linear_pte_xor[0]; @@ -1922,7 +1936,7 @@ static void __init sun4v_linear_pte_xor_finalize(void)  	if (cpu_pgsz_mask & HV_PGSZ_MASK_2GB) {  		kern_linear_pte_xor[2] = (_PAGE_VALID | _PAGE_SZ2GB_4V) ^  			PAGE_OFFSET; -		kern_linear_pte_xor[2] |= (_PAGE_CP_4V | _PAGE_CV_4V | +		kern_linear_pte_xor[2] |= (_PAGE_CP_4V | pagecv_flag |  					   _PAGE_P_4V | _PAGE_W_4V);  	} else {  		kern_linear_pte_xor[2] = kern_linear_pte_xor[1]; @@ -1931,7 +1945,7 @@ static void __init sun4v_linear_pte_xor_finalize(void)  	if (cpu_pgsz_mask & HV_PGSZ_MASK_16GB) {  		kern_linear_pte_xor[3] = (_PAGE_VALID | _PAGE_SZ16GB_4V) ^  			PAGE_OFFSET; -		kern_linear_pte_xor[3] |= (_PAGE_CP_4V | _PAGE_CV_4V | +		kern_linear_pte_xor[3] |= (_PAGE_CP_4V | pagecv_flag |  					   _PAGE_P_4V | _PAGE_W_4V);  	} else {  		kern_linear_pte_xor[3] = kern_linear_pte_xor[2]; @@ -1958,6 +1972,13 @@ static phys_addr_t __init available_memory(void)  	return available;  } +#define _PAGE_CACHE_4U	(_PAGE_CP_4U | _PAGE_CV_4U) +#define _PAGE_CACHE_4V	(_PAGE_CP_4V | _PAGE_CV_4V) +#define __DIRTY_BITS_4U	 (_PAGE_MODIFIED_4U | _PAGE_WRITE_4U | _PAGE_W_4U) +#define __DIRTY_BITS_4V	 (_PAGE_MODIFIED_4V | _PAGE_WRITE_4V | _PAGE_W_4V) +#define __ACCESS_BITS_4U (_PAGE_ACCESSED_4U | _PAGE_READ_4U | _PAGE_R) +#define __ACCESS_BITS_4V (_PAGE_ACCESSED_4V | _PAGE_READ_4V | _PAGE_R) +  /* We need to exclude reserved regions. This exclusion will include   * vmlinux and initrd. To be more precise the initrd size could be used to   * compute a new lower limit because it is freed later during initialization. @@ -2034,6 +2055,25 @@ void __init paging_init(void)  	memset(swapper_4m_tsb, 0x40, sizeof(swapper_4m_tsb));  #endif +	/* TTE.cv bit on sparc v9 occupies the same position as TTE.mcde +	 * bit on M7 processor. This is a conflicting usage of the same +	 * bit. Enabling TTE.cv on M7 would turn on Memory Corruption +	 * Detection error on all pages and this will lead to problems +	 * later. Kernel does not run with MCD enabled and hence rest +	 * of the required steps to fully configure memory corruption +	 * detection are not taken. We need to ensure TTE.mcde is not +	 * set on M7 processor. Compute the value of cacheability +	 * flag for use later taking this into consideration. +	 */ +	switch (sun4v_chip_type) { +	case SUN4V_CHIP_SPARC_M7: +		page_cache4v_flag = _PAGE_CP_4V; +		break; +	default: +		page_cache4v_flag = _PAGE_CACHE_4V; +		break; +	} +  	if (tlb_type == hypervisor)  		sun4v_pgprot_init();  	else @@ -2274,13 +2314,6 @@ void free_initrd_mem(unsigned long start, unsigned long end)  }  #endif -#define _PAGE_CACHE_4U	(_PAGE_CP_4U | _PAGE_CV_4U) -#define _PAGE_CACHE_4V	(_PAGE_CP_4V | _PAGE_CV_4V) -#define __DIRTY_BITS_4U	 (_PAGE_MODIFIED_4U | _PAGE_WRITE_4U | _PAGE_W_4U) -#define __DIRTY_BITS_4V	 (_PAGE_MODIFIED_4V | _PAGE_WRITE_4V | _PAGE_W_4V) -#define __ACCESS_BITS_4U (_PAGE_ACCESSED_4U | _PAGE_READ_4U | _PAGE_R) -#define __ACCESS_BITS_4V (_PAGE_ACCESSED_4V | _PAGE_READ_4V | _PAGE_R) -  pgprot_t PAGE_KERNEL __read_mostly;  EXPORT_SYMBOL(PAGE_KERNEL); @@ -2312,8 +2345,7 @@ int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,  		    _PAGE_P_4U | _PAGE_W_4U);  	if (tlb_type == hypervisor)  		pte_base = (_PAGE_VALID | _PAGE_SZ4MB_4V | -			    _PAGE_CP_4V | _PAGE_CV_4V | -			    _PAGE_P_4V | _PAGE_W_4V); +			    page_cache4v_flag | _PAGE_P_4V | _PAGE_W_4V);  	pte_base |= _PAGE_PMD_HUGE; @@ -2450,14 +2482,14 @@ static void __init sun4v_pgprot_init(void)  	int i;  	PAGE_KERNEL = __pgprot (_PAGE_PRESENT_4V | _PAGE_VALID | -				_PAGE_CACHE_4V | _PAGE_P_4V | +				page_cache4v_flag | _PAGE_P_4V |  				__ACCESS_BITS_4V | __DIRTY_BITS_4V |  				_PAGE_EXEC_4V);  	PAGE_KERNEL_LOCKED = PAGE_KERNEL;  	_PAGE_IE = _PAGE_IE_4V;  	_PAGE_E = _PAGE_E_4V; -	_PAGE_CACHE = _PAGE_CACHE_4V; +	_PAGE_CACHE = page_cache4v_flag;  #ifdef CONFIG_DEBUG_PAGEALLOC  	kern_linear_pte_xor[0] = _PAGE_VALID ^ PAGE_OFFSET; @@ -2465,8 +2497,8 @@ static void __init sun4v_pgprot_init(void)  	kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZ4MB_4V) ^  		PAGE_OFFSET;  #endif -	kern_linear_pte_xor[0] |= (_PAGE_CP_4V | _PAGE_CV_4V | -				   _PAGE_P_4V | _PAGE_W_4V); +	kern_linear_pte_xor[0] |= (page_cache4v_flag | _PAGE_P_4V | +				   _PAGE_W_4V);  	for (i = 1; i < 4; i++)  		kern_linear_pte_xor[i] = kern_linear_pte_xor[0]; @@ -2479,12 +2511,12 @@ static void __init sun4v_pgprot_init(void)  			     _PAGE_SZ4MB_4V | _PAGE_SZ512K_4V |  			     _PAGE_SZ64K_4V | _PAGE_SZ8K_4V); -	page_none = _PAGE_PRESENT_4V | _PAGE_ACCESSED_4V | _PAGE_CACHE_4V; -	page_shared = (_PAGE_VALID | _PAGE_PRESENT_4V | _PAGE_CACHE_4V | +	page_none = _PAGE_PRESENT_4V | _PAGE_ACCESSED_4V | page_cache4v_flag; +	page_shared = (_PAGE_VALID | _PAGE_PRESENT_4V | page_cache4v_flag |  		       __ACCESS_BITS_4V | _PAGE_WRITE_4V | _PAGE_EXEC_4V); -	page_copy   = (_PAGE_VALID | _PAGE_PRESENT_4V | _PAGE_CACHE_4V | +	page_copy   = (_PAGE_VALID | _PAGE_PRESENT_4V | page_cache4v_flag |  		       __ACCESS_BITS_4V | _PAGE_EXEC_4V); -	page_readonly = (_PAGE_VALID | _PAGE_PRESENT_4V | _PAGE_CACHE_4V | +	page_readonly = (_PAGE_VALID | _PAGE_PRESENT_4V | page_cache4v_flag |  			 __ACCESS_BITS_4V | _PAGE_EXEC_4V);  	page_exec_bit = _PAGE_EXEC_4V; @@ -2542,7 +2574,7 @@ static unsigned long kern_large_tte(unsigned long paddr)  	       _PAGE_EXEC_4U | _PAGE_L_4U | _PAGE_W_4U);  	if (tlb_type == hypervisor)  		val = (_PAGE_VALID | _PAGE_SZ4MB_4V | -		       _PAGE_CP_4V | _PAGE_CV_4V | _PAGE_P_4V | +		       page_cache4v_flag | _PAGE_P_4V |  		       _PAGE_EXEC_4V | _PAGE_W_4V);  	return val | paddr; |