Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5d868627 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull arm64 fixes from Catalin Marinas:

 - Build fix when !CONFIG_UID16 (the patch is touching generic files but
   it only affects arm64 builds; submitted by Arnd Bergmann)

 - EFI fixes to deal with early_memremap() returning NULL and correctly
   mapping run-time regions

 - Fix CPUID register extraction of unsigned fields (not to be
   sign-extended)

 - ASID allocator fix to deal with long-running tasks over multiple
   generation roll-overs

 - Revert support for marking page ranges as contiguous PTEs (it leads
   to TLB conflicts and requires additional non-trivial kernel changes)

 - Proper early_alloc() failure check

 - Disable KASan for 48-bit VA and 16KB page configuration (the pgd is
   larger than the KASan shadow memory)

 - Update the fault_info table (original descriptions based on early
   engineering spec)

* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
  arm64: efi: fix initcall return values
  arm64: efi: deal with NULL return value of early_memremap()
  arm64: debug: Treat the BRPs/WRPs as unsigned
  arm64: cpufeature: Track unsigned fields
  arm64: cpufeature: Add helpers for extracting unsigned values
  Revert "arm64: Mark kernel page ranges contiguous"
  arm64: mm: keep reserved ASIDs in sync with mm after multiple rollovers
  arm64: KASAN depends on !(ARM64_16K_PAGES && ARM64_VA_BITS_48)
  arm64: efi: correctly map runtime regions
  arm64: mm: fix fault_info table xFSC decoding
  arm64: fix building without CONFIG_UID16
  arm64: early_alloc: Fix check for allocation failure
parents 5a44ed0d 66362c9a
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -49,7 +49,7 @@ config ARM64
	select HAVE_ARCH_AUDITSYSCALL
	select HAVE_ARCH_AUDITSYSCALL
	select HAVE_ARCH_BITREVERSE
	select HAVE_ARCH_BITREVERSE
	select HAVE_ARCH_JUMP_LABEL
	select HAVE_ARCH_JUMP_LABEL
	select HAVE_ARCH_KASAN if SPARSEMEM_VMEMMAP
	select HAVE_ARCH_KASAN if SPARSEMEM_VMEMMAP && !(ARM64_16K_PAGES && ARM64_VA_BITS_48)
	select HAVE_ARCH_KGDB
	select HAVE_ARCH_KGDB
	select HAVE_ARCH_SECCOMP_FILTER
	select HAVE_ARCH_SECCOMP_FILTER
	select HAVE_ARCH_TRACEHOOK
	select HAVE_ARCH_TRACEHOOK
+20 −2
Original line number Original line Diff line number Diff line
@@ -47,7 +47,11 @@ enum ftr_type {
#define FTR_STRICT	true	/* SANITY check strict matching required */
#define FTR_STRICT	true	/* SANITY check strict matching required */
#define FTR_NONSTRICT	false	/* SANITY check ignored */
#define FTR_NONSTRICT	false	/* SANITY check ignored */


#define FTR_SIGNED	true	/* Value should be treated as signed */
#define FTR_UNSIGNED	false	/* Value should be treated as unsigned */

struct arm64_ftr_bits {
struct arm64_ftr_bits {
	bool		sign;	/* Value is signed ? */
	bool		strict;	/* CPU Sanity check: strict matching required ? */
	bool		strict;	/* CPU Sanity check: strict matching required ? */
	enum ftr_type	type;
	enum ftr_type	type;
	u8		shift;
	u8		shift;
@@ -124,6 +128,18 @@ cpuid_feature_extract_field(u64 features, int field)
	return cpuid_feature_extract_field_width(features, field, 4);
	return cpuid_feature_extract_field_width(features, field, 4);
}
}


static inline unsigned int __attribute_const__
cpuid_feature_extract_unsigned_field_width(u64 features, int field, int width)
{
	return (u64)(features << (64 - width - field)) >> (64 - width);
}

static inline unsigned int __attribute_const__
cpuid_feature_extract_unsigned_field(u64 features, int field)
{
	return cpuid_feature_extract_unsigned_field_width(features, field, 4);
}

static inline u64 arm64_ftr_mask(struct arm64_ftr_bits *ftrp)
static inline u64 arm64_ftr_mask(struct arm64_ftr_bits *ftrp)
{
{
	return (u64)GENMASK(ftrp->shift + ftrp->width - 1, ftrp->shift);
	return (u64)GENMASK(ftrp->shift + ftrp->width - 1, ftrp->shift);
@@ -131,7 +147,9 @@ static inline u64 arm64_ftr_mask(struct arm64_ftr_bits *ftrp)


static inline s64 arm64_ftr_value(struct arm64_ftr_bits *ftrp, u64 val)
static inline s64 arm64_ftr_value(struct arm64_ftr_bits *ftrp, u64 val)
{
{
	return cpuid_feature_extract_field_width(val, ftrp->shift, ftrp->width);
	return ftrp->sign ?
		cpuid_feature_extract_field_width(val, ftrp->shift, ftrp->width) :
		cpuid_feature_extract_unsigned_field_width(val, ftrp->shift, ftrp->width);
}
}


static inline bool id_aa64mmfr0_mixed_endian_el0(u64 mmfr0)
static inline bool id_aa64mmfr0_mixed_endian_el0(u64 mmfr0)
+4 −2
Original line number Original line Diff line number Diff line
@@ -138,16 +138,18 @@ extern struct pmu perf_ops_bp;
/* Determine number of BRP registers available. */
/* Determine number of BRP registers available. */
static inline int get_num_brps(void)
static inline int get_num_brps(void)
{
{
	u64 dfr0 = read_system_reg(SYS_ID_AA64DFR0_EL1);
	return 1 +
	return 1 +
		cpuid_feature_extract_field(read_system_reg(SYS_ID_AA64DFR0_EL1),
		cpuid_feature_extract_unsigned_field(dfr0,
						ID_AA64DFR0_BRPS_SHIFT);
						ID_AA64DFR0_BRPS_SHIFT);
}
}


/* Determine number of WRP registers available. */
/* Determine number of WRP registers available. */
static inline int get_num_wrps(void)
static inline int get_num_wrps(void)
{
{
	u64 dfr0 = read_system_reg(SYS_ID_AA64DFR0_EL1);
	return 1 +
	return 1 +
		cpuid_feature_extract_field(read_system_reg(SYS_ID_AA64DFR0_EL1),
		cpuid_feature_extract_unsigned_field(dfr0,
						ID_AA64DFR0_WRPS_SHIFT);
						ID_AA64DFR0_WRPS_SHIFT);
}
}


+23 −14
Original line number Original line Diff line number Diff line
@@ -44,8 +44,9 @@ unsigned int compat_elf_hwcap2 __read_mostly;


DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);


#define ARM64_FTR_BITS(STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL) \
#define __ARM64_FTR_BITS(SIGNED, STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL) \
	{						\
	{						\
		.sign = SIGNED,				\
		.strict = STRICT,			\
		.strict = STRICT,			\
		.type = TYPE,				\
		.type = TYPE,				\
		.shift = SHIFT,				\
		.shift = SHIFT,				\
@@ -53,6 +54,14 @@ DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
		.safe_val = SAFE_VAL,			\
		.safe_val = SAFE_VAL,			\
	}
	}


/* Define a feature with signed values */
#define ARM64_FTR_BITS(STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL) \
	__ARM64_FTR_BITS(FTR_SIGNED, STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL)

/* Define a feature with unsigned value */
#define U_ARM64_FTR_BITS(STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL) \
	__ARM64_FTR_BITS(FTR_UNSIGNED, STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL)

#define ARM64_FTR_END					\
#define ARM64_FTR_END					\
	{						\
	{						\
		.width = 0,				\
		.width = 0,				\
@@ -99,7 +108,7 @@ static struct arm64_ftr_bits ftr_id_aa64mmfr0[] = {
	 * Differing PARange is fine as long as all peripherals and memory are mapped
	 * Differing PARange is fine as long as all peripherals and memory are mapped
	 * within the minimum PARange of all CPUs
	 * within the minimum PARange of all CPUs
	 */
	 */
	ARM64_FTR_BITS(FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_PARANGE_SHIFT, 4, 0),
	U_ARM64_FTR_BITS(FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_PARANGE_SHIFT, 4, 0),
	ARM64_FTR_END,
	ARM64_FTR_END,
};
};


@@ -115,18 +124,18 @@ static struct arm64_ftr_bits ftr_id_aa64mmfr1[] = {
};
};


static struct arm64_ftr_bits ftr_ctr[] = {
static struct arm64_ftr_bits ftr_ctr[] = {
	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 31, 1, 1),	/* RAO */
	U_ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 31, 1, 1),	/* RAO */
	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 28, 3, 0),
	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 28, 3, 0),
	ARM64_FTR_BITS(FTR_STRICT, FTR_HIGHER_SAFE, 24, 4, 0),	/* CWG */
	U_ARM64_FTR_BITS(FTR_STRICT, FTR_HIGHER_SAFE, 24, 4, 0),	/* CWG */
	ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 20, 4, 0),	/* ERG */
	U_ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 20, 4, 0),	/* ERG */
	ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 16, 4, 1),	/* DminLine */
	U_ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 16, 4, 1),	/* DminLine */
	/*
	/*
	 * Linux can handle differing I-cache policies. Userspace JITs will
	 * Linux can handle differing I-cache policies. Userspace JITs will
	 * make use of *minLine
	 * make use of *minLine
	 */
	 */
	ARM64_FTR_BITS(FTR_NONSTRICT, FTR_EXACT, 14, 2, 0),	/* L1Ip */
	U_ARM64_FTR_BITS(FTR_NONSTRICT, FTR_EXACT, 14, 2, 0),	/* L1Ip */
	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 4, 10, 0),	/* RAZ */
	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 4, 10, 0),	/* RAZ */
	ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 0, 4, 0),	/* IminLine */
	U_ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 0, 4, 0),	/* IminLine */
	ARM64_FTR_END,
	ARM64_FTR_END,
};
};


@@ -144,12 +153,12 @@ static struct arm64_ftr_bits ftr_id_mmfr0[] = {


static struct arm64_ftr_bits ftr_id_aa64dfr0[] = {
static struct arm64_ftr_bits ftr_id_aa64dfr0[] = {
	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 32, 32, 0),
	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 32, 32, 0),
	ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_CTX_CMPS_SHIFT, 4, 0),
	U_ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_CTX_CMPS_SHIFT, 4, 0),
	ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_WRPS_SHIFT, 4, 0),
	U_ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_WRPS_SHIFT, 4, 0),
	ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_BRPS_SHIFT, 4, 0),
	U_ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_BRPS_SHIFT, 4, 0),
	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64DFR0_PMUVER_SHIFT, 4, 0),
	U_ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64DFR0_PMUVER_SHIFT, 4, 0),
	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64DFR0_TRACEVER_SHIFT, 4, 0),
	U_ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64DFR0_TRACEVER_SHIFT, 4, 0),
	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64DFR0_DEBUGVER_SHIFT, 4, 0x6),
	U_ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64DFR0_DEBUGVER_SHIFT, 4, 0x6),
	ARM64_FTR_END,
	ARM64_FTR_END,
};
};


+20 −13
Original line number Original line Diff line number Diff line
@@ -127,7 +127,11 @@ static int __init uefi_init(void)
	table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables;
	table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables;
	config_tables = early_memremap(efi_to_phys(efi.systab->tables),
	config_tables = early_memremap(efi_to_phys(efi.systab->tables),
				       table_size);
				       table_size);

	if (config_tables == NULL) {
		pr_warn("Unable to map EFI config table array.\n");
		retval = -ENOMEM;
		goto out;
	}
	retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables,
	retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables,
					 sizeof(efi_config_table_64_t), NULL);
					 sizeof(efi_config_table_64_t), NULL);


@@ -209,6 +213,14 @@ void __init efi_init(void)
			 PAGE_ALIGN(params.mmap_size + (params.mmap & ~PAGE_MASK)));
			 PAGE_ALIGN(params.mmap_size + (params.mmap & ~PAGE_MASK)));
	memmap.phys_map = params.mmap;
	memmap.phys_map = params.mmap;
	memmap.map = early_memremap(params.mmap, params.mmap_size);
	memmap.map = early_memremap(params.mmap, params.mmap_size);
	if (memmap.map == NULL) {
		/*
		* If we are booting via UEFI, the UEFI memory map is the only
		* description of memory we have, so there is little point in
		* proceeding if we cannot access it.
		*/
		panic("Unable to map EFI memory map.\n");
	}
	memmap.map_end = memmap.map + params.mmap_size;
	memmap.map_end = memmap.map + params.mmap_size;
	memmap.desc_size = params.desc_size;
	memmap.desc_size = params.desc_size;
	memmap.desc_version = params.desc_ver;
	memmap.desc_version = params.desc_ver;
@@ -227,7 +239,6 @@ static bool __init efi_virtmap_init(void)
	init_new_context(NULL, &efi_mm);
	init_new_context(NULL, &efi_mm);


	for_each_efi_memory_desc(&memmap, md) {
	for_each_efi_memory_desc(&memmap, md) {
		u64 paddr, npages, size;
		pgprot_t prot;
		pgprot_t prot;


		if (!(md->attribute & EFI_MEMORY_RUNTIME))
		if (!(md->attribute & EFI_MEMORY_RUNTIME))
@@ -235,11 +246,6 @@ static bool __init efi_virtmap_init(void)
		if (md->virt_addr == 0)
		if (md->virt_addr == 0)
			return false;
			return false;


		paddr = md->phys_addr;
		npages = md->num_pages;
		memrange_efi_to_native(&paddr, &npages);
		size = npages << PAGE_SHIFT;

		pr_info("  EFI remap 0x%016llx => %p\n",
		pr_info("  EFI remap 0x%016llx => %p\n",
			md->phys_addr, (void *)md->virt_addr);
			md->phys_addr, (void *)md->virt_addr);


@@ -256,7 +262,8 @@ static bool __init efi_virtmap_init(void)
		else
		else
			prot = PAGE_KERNEL;
			prot = PAGE_KERNEL;


		create_pgd_mapping(&efi_mm, paddr, md->virt_addr, size,
		create_pgd_mapping(&efi_mm, md->phys_addr, md->virt_addr,
				   md->num_pages << EFI_PAGE_SHIFT, 
				   __pgprot(pgprot_val(prot) | PTE_NG));
				   __pgprot(pgprot_val(prot) | PTE_NG));
	}
	}
	return true;
	return true;
@@ -273,12 +280,12 @@ static int __init arm64_enable_runtime_services(void)


	if (!efi_enabled(EFI_BOOT)) {
	if (!efi_enabled(EFI_BOOT)) {
		pr_info("EFI services will not be available.\n");
		pr_info("EFI services will not be available.\n");
		return -1;
		return 0;
	}
	}


	if (efi_runtime_disabled()) {
	if (efi_runtime_disabled()) {
		pr_info("EFI runtime services will be disabled.\n");
		pr_info("EFI runtime services will be disabled.\n");
		return -1;
		return 0;
	}
	}


	pr_info("Remapping and enabling EFI services.\n");
	pr_info("Remapping and enabling EFI services.\n");
@@ -288,7 +295,7 @@ static int __init arm64_enable_runtime_services(void)
						   mapsize);
						   mapsize);
	if (!memmap.map) {
	if (!memmap.map) {
		pr_err("Failed to remap EFI memory map\n");
		pr_err("Failed to remap EFI memory map\n");
		return -1;
		return -ENOMEM;
	}
	}
	memmap.map_end = memmap.map + mapsize;
	memmap.map_end = memmap.map + mapsize;
	efi.memmap = &memmap;
	efi.memmap = &memmap;
@@ -297,13 +304,13 @@ static int __init arm64_enable_runtime_services(void)
						   sizeof(efi_system_table_t));
						   sizeof(efi_system_table_t));
	if (!efi.systab) {
	if (!efi.systab) {
		pr_err("Failed to remap EFI System Table\n");
		pr_err("Failed to remap EFI System Table\n");
		return -1;
		return -ENOMEM;
	}
	}
	set_bit(EFI_SYSTEM_TABLES, &efi.flags);
	set_bit(EFI_SYSTEM_TABLES, &efi.flags);


	if (!efi_virtmap_init()) {
	if (!efi_virtmap_init()) {
		pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n");
		pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n");
		return -1;
		return -ENOMEM;
	}
	}


	/* Set up runtime services function pointers */
	/* Set up runtime services function pointers */
Loading