arm64: mte: Use Normal Tagged attributes for the linear map
Once user space is given access to tagged memory, the kernel must be able to clear/save/restore tags visible to the user. This is done via the linear mapping, therefore map it as such. The new MT_NORMAL_TAGGED index for MAIR_EL1 is initially mapped as Normal memory and later changed to Normal Tagged via the cpufeature infrastructure. From a mismatched attribute aliases perspective, the Tagged memory is considered a permission and it won't lead to undefined behaviour. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Cc: Will Deacon <will@kernel.org> Cc: Suzuki K Poulose <Suzuki.Poulose@arm.com>
This commit is contained in:
		
							parent
							
								
									c058b1c4a5
								
							
						
					
					
						commit
						0178dc7613
					
				| @ -133,6 +133,7 @@ | ||||
| #define MT_NORMAL_NC		3 | ||||
| #define MT_NORMAL		4 | ||||
| #define MT_NORMAL_WT		5 | ||||
| #define MT_NORMAL_TAGGED	6 | ||||
| 
 | ||||
| /*
 | ||||
|  * Memory types for Stage-2 translation | ||||
|  | ||||
| @ -50,6 +50,7 @@ extern bool arm64_use_ng_mappings; | ||||
| #define PROT_NORMAL_NC		(PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_NC)) | ||||
| #define PROT_NORMAL_WT		(PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_WT)) | ||||
| #define PROT_NORMAL		(PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL)) | ||||
| #define PROT_NORMAL_TAGGED	(PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_WRITE | PTE_ATTRINDX(MT_NORMAL_TAGGED)) | ||||
| 
 | ||||
| #define PROT_SECT_DEVICE_nGnRE	(PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_DEVICE_nGnRE)) | ||||
| #define PROT_SECT_NORMAL	(PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_NORMAL)) | ||||
| @ -59,6 +60,7 @@ extern bool arm64_use_ng_mappings; | ||||
| #define _HYP_PAGE_DEFAULT	_PAGE_DEFAULT | ||||
| 
 | ||||
| #define PAGE_KERNEL		__pgprot(PROT_NORMAL) | ||||
| #define PAGE_KERNEL_TAGGED	__pgprot(PROT_NORMAL_TAGGED) | ||||
| #define PAGE_KERNEL_RO		__pgprot((PROT_NORMAL & ~PTE_WRITE) | PTE_RDONLY) | ||||
| #define PAGE_KERNEL_ROX		__pgprot((PROT_NORMAL & ~(PTE_WRITE | PTE_PXN)) | PTE_RDONLY) | ||||
| #define PAGE_KERNEL_EXEC	__pgprot(PROT_NORMAL & ~PTE_PXN) | ||||
|  | ||||
| @ -169,6 +169,10 @@ static const struct prot_bits pte_bits[] = { | ||||
| 		.mask	= PTE_ATTRINDX_MASK, | ||||
| 		.val	= PTE_ATTRINDX(MT_NORMAL), | ||||
| 		.set	= "MEM/NORMAL", | ||||
| 	}, { | ||||
| 		.mask	= PTE_ATTRINDX_MASK, | ||||
| 		.val	= PTE_ATTRINDX(MT_NORMAL_TAGGED), | ||||
| 		.set	= "MEM/NORMAL-TAGGED", | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -122,7 +122,7 @@ static bool pgattr_change_is_safe(u64 old, u64 new) | ||||
| 	 * The following mapping attributes may be updated in live | ||||
| 	 * kernel mappings without the need for break-before-make. | ||||
| 	 */ | ||||
| 	static const pteval_t mask = PTE_PXN | PTE_RDONLY | PTE_WRITE | PTE_NG; | ||||
| 	pteval_t mask = PTE_PXN | PTE_RDONLY | PTE_WRITE | PTE_NG; | ||||
| 
 | ||||
| 	/* creating or taking down mappings is always safe */ | ||||
| 	if (old == 0 || new == 0) | ||||
| @ -136,6 +136,17 @@ static bool pgattr_change_is_safe(u64 old, u64 new) | ||||
| 	if (old & ~new & PTE_NG) | ||||
| 		return false; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Changing the memory type between Normal and Normal-Tagged is safe | ||||
| 	 * since Tagged is considered a permission attribute from the | ||||
| 	 * mismatched attribute aliases perspective. | ||||
| 	 */ | ||||
| 	if (((old & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL) || | ||||
| 	     (old & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL_TAGGED)) && | ||||
| 	    ((new & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL) || | ||||
| 	     (new & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL_TAGGED))) | ||||
| 		mask |= PTE_ATTRINDX_MASK; | ||||
| 
 | ||||
| 	return ((old ^ new) & ~mask) == 0; | ||||
| } | ||||
| 
 | ||||
| @ -491,7 +502,12 @@ static void __init map_mem(pgd_t *pgdp) | ||||
| 		if (memblock_is_nomap(reg)) | ||||
| 			continue; | ||||
| 
 | ||||
| 		__map_memblock(pgdp, start, end, PAGE_KERNEL, flags); | ||||
| 		/*
 | ||||
| 		 * The linear map must allow allocation tags reading/writing | ||||
| 		 * if MTE is present. Otherwise, it has the same attributes as | ||||
| 		 * PAGE_KERNEL. | ||||
| 		 */ | ||||
| 		__map_memblock(pgdp, start, end, PAGE_KERNEL_TAGGED, flags); | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
|  | ||||
| @ -44,14 +44,18 @@ | ||||
| #define TCR_KASAN_FLAGS 0 | ||||
| #endif | ||||
| 
 | ||||
| /* Default MAIR_EL1 */ | ||||
| /* | ||||
|  * Default MAIR_EL1. MT_NORMAL_TAGGED is initially mapped as Normal memory and | ||||
|  * changed during __cpu_setup to Normal Tagged if the system supports MTE. | ||||
|  */ | ||||
| #define MAIR_EL1_SET							\ | ||||
| 	(MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRnE, MT_DEVICE_nGnRnE) |	\ | ||||
| 	 MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRE, MT_DEVICE_nGnRE) |	\ | ||||
| 	 MAIR_ATTRIDX(MAIR_ATTR_DEVICE_GRE, MT_DEVICE_GRE) |		\ | ||||
| 	 MAIR_ATTRIDX(MAIR_ATTR_NORMAL_NC, MT_NORMAL_NC) |		\ | ||||
| 	 MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL) |			\ | ||||
| 	 MAIR_ATTRIDX(MAIR_ATTR_NORMAL_WT, MT_NORMAL_WT)) | ||||
| 	 MAIR_ATTRIDX(MAIR_ATTR_NORMAL_WT, MT_NORMAL_WT) |		\ | ||||
| 	 MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL_TAGGED)) | ||||
| 
 | ||||
| #ifdef CONFIG_CPU_PM | ||||
| /** | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user