diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-27 14:09:59 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-27 14:09:59 -0500 |
commit | 5d8686276a5acc0a3d8055028a6e9d990c9c4fbd (patch) | |
tree | 633652441a0e598950137357c35f9dcf6bfb6b00 | |
parent | 5a44ed0d30dd0681df44eb085c31b371b7fe84fe (diff) | |
parent | 66362c9afc1d4a806280b9e3646d2d0a26cf83e9 (diff) |
Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
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
-rw-r--r-- | arch/arm64/Kconfig | 2 | ||||
-rw-r--r-- | arch/arm64/include/asm/cpufeature.h | 22 | ||||
-rw-r--r-- | arch/arm64/include/asm/hw_breakpoint.h | 6 | ||||
-rw-r--r-- | arch/arm64/kernel/cpufeature.c | 37 | ||||
-rw-r--r-- | arch/arm64/kernel/efi.c | 33 | ||||
-rw-r--r-- | arch/arm64/mm/context.c | 38 | ||||
-rw-r--r-- | arch/arm64/mm/fault.c | 28 | ||||
-rw-r--r-- | arch/arm64/mm/mmu.c | 77 | ||||
-rw-r--r-- | include/linux/syscalls.h | 2 | ||||
-rw-r--r-- | include/linux/types.h | 2 |
10 files changed, 124 insertions, 123 deletions
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index e55848c1edf4..871f21783866 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig | |||
@@ -49,7 +49,7 @@ config ARM64 | |||
49 | select HAVE_ARCH_AUDITSYSCALL | 49 | select HAVE_ARCH_AUDITSYSCALL |
50 | select HAVE_ARCH_BITREVERSE | 50 | select HAVE_ARCH_BITREVERSE |
51 | select HAVE_ARCH_JUMP_LABEL | 51 | select HAVE_ARCH_JUMP_LABEL |
52 | select HAVE_ARCH_KASAN if SPARSEMEM_VMEMMAP | 52 | select HAVE_ARCH_KASAN if SPARSEMEM_VMEMMAP && !(ARM64_16K_PAGES && ARM64_VA_BITS_48) |
53 | select HAVE_ARCH_KGDB | 53 | select HAVE_ARCH_KGDB |
54 | select HAVE_ARCH_SECCOMP_FILTER | 54 | select HAVE_ARCH_SECCOMP_FILTER |
55 | select HAVE_ARCH_TRACEHOOK | 55 | select HAVE_ARCH_TRACEHOOK |
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index 52722ee73dba..8f271b83f910 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h | |||
@@ -47,8 +47,12 @@ enum ftr_type { | |||
47 | #define FTR_STRICT true /* SANITY check strict matching required */ | 47 | #define FTR_STRICT true /* SANITY check strict matching required */ |
48 | #define FTR_NONSTRICT false /* SANITY check ignored */ | 48 | #define FTR_NONSTRICT false /* SANITY check ignored */ |
49 | 49 | ||
50 | #define FTR_SIGNED true /* Value should be treated as signed */ | ||
51 | #define FTR_UNSIGNED false /* Value should be treated as unsigned */ | ||
52 | |||
50 | struct arm64_ftr_bits { | 53 | struct arm64_ftr_bits { |
51 | bool strict; /* CPU Sanity check: strict matching required ? */ | 54 | bool sign; /* Value is signed ? */ |
55 | bool strict; /* CPU Sanity check: strict matching required ? */ | ||
52 | enum ftr_type type; | 56 | enum ftr_type type; |
53 | u8 shift; | 57 | u8 shift; |
54 | u8 width; | 58 | u8 width; |
@@ -124,6 +128,18 @@ cpuid_feature_extract_field(u64 features, int field) | |||
124 | return cpuid_feature_extract_field_width(features, field, 4); | 128 | return cpuid_feature_extract_field_width(features, field, 4); |
125 | } | 129 | } |
126 | 130 | ||
131 | static inline unsigned int __attribute_const__ | ||
132 | cpuid_feature_extract_unsigned_field_width(u64 features, int field, int width) | ||
133 | { | ||
134 | return (u64)(features << (64 - width - field)) >> (64 - width); | ||
135 | } | ||
136 | |||
137 | static inline unsigned int __attribute_const__ | ||
138 | cpuid_feature_extract_unsigned_field(u64 features, int field) | ||
139 | { | ||
140 | return cpuid_feature_extract_unsigned_field_width(features, field, 4); | ||
141 | } | ||
142 | |||
127 | static inline u64 arm64_ftr_mask(struct arm64_ftr_bits *ftrp) | 143 | static inline u64 arm64_ftr_mask(struct arm64_ftr_bits *ftrp) |
128 | { | 144 | { |
129 | return (u64)GENMASK(ftrp->shift + ftrp->width - 1, ftrp->shift); | 145 | 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) | |||
131 | 147 | ||
132 | static inline s64 arm64_ftr_value(struct arm64_ftr_bits *ftrp, u64 val) | 148 | static inline s64 arm64_ftr_value(struct arm64_ftr_bits *ftrp, u64 val) |
133 | { | 149 | { |
134 | return cpuid_feature_extract_field_width(val, ftrp->shift, ftrp->width); | 150 | return ftrp->sign ? |
151 | cpuid_feature_extract_field_width(val, ftrp->shift, ftrp->width) : | ||
152 | cpuid_feature_extract_unsigned_field_width(val, ftrp->shift, ftrp->width); | ||
135 | } | 153 | } |
136 | 154 | ||
137 | static inline bool id_aa64mmfr0_mixed_endian_el0(u64 mmfr0) | 155 | static inline bool id_aa64mmfr0_mixed_endian_el0(u64 mmfr0) |
diff --git a/arch/arm64/include/asm/hw_breakpoint.h b/arch/arm64/include/asm/hw_breakpoint.h index e54415ec6935..9732908bfc8a 100644 --- a/arch/arm64/include/asm/hw_breakpoint.h +++ b/arch/arm64/include/asm/hw_breakpoint.h | |||
@@ -138,16 +138,18 @@ extern struct pmu perf_ops_bp; | |||
138 | /* Determine number of BRP registers available. */ | 138 | /* Determine number of BRP registers available. */ |
139 | static inline int get_num_brps(void) | 139 | static inline int get_num_brps(void) |
140 | { | 140 | { |
141 | u64 dfr0 = read_system_reg(SYS_ID_AA64DFR0_EL1); | ||
141 | return 1 + | 142 | return 1 + |
142 | cpuid_feature_extract_field(read_system_reg(SYS_ID_AA64DFR0_EL1), | 143 | cpuid_feature_extract_unsigned_field(dfr0, |
143 | ID_AA64DFR0_BRPS_SHIFT); | 144 | ID_AA64DFR0_BRPS_SHIFT); |
144 | } | 145 | } |
145 | 146 | ||
146 | /* Determine number of WRP registers available. */ | 147 | /* Determine number of WRP registers available. */ |
147 | static inline int get_num_wrps(void) | 148 | static inline int get_num_wrps(void) |
148 | { | 149 | { |
150 | u64 dfr0 = read_system_reg(SYS_ID_AA64DFR0_EL1); | ||
149 | return 1 + | 151 | return 1 + |
150 | cpuid_feature_extract_field(read_system_reg(SYS_ID_AA64DFR0_EL1), | 152 | cpuid_feature_extract_unsigned_field(dfr0, |
151 | ID_AA64DFR0_WRPS_SHIFT); | 153 | ID_AA64DFR0_WRPS_SHIFT); |
152 | } | 154 | } |
153 | 155 | ||
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index c8cf89223b5a..0669c63281ea 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c | |||
@@ -44,8 +44,9 @@ unsigned int compat_elf_hwcap2 __read_mostly; | |||
44 | 44 | ||
45 | DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS); | 45 | DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS); |
46 | 46 | ||
47 | #define ARM64_FTR_BITS(STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL) \ | 47 | #define __ARM64_FTR_BITS(SIGNED, STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL) \ |
48 | { \ | 48 | { \ |
49 | .sign = SIGNED, \ | ||
49 | .strict = STRICT, \ | 50 | .strict = STRICT, \ |
50 | .type = TYPE, \ | 51 | .type = TYPE, \ |
51 | .shift = SHIFT, \ | 52 | .shift = SHIFT, \ |
@@ -53,6 +54,14 @@ DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS); | |||
53 | .safe_val = SAFE_VAL, \ | 54 | .safe_val = SAFE_VAL, \ |
54 | } | 55 | } |
55 | 56 | ||
57 | /* Define a feature with signed values */ | ||
58 | #define ARM64_FTR_BITS(STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL) \ | ||
59 | __ARM64_FTR_BITS(FTR_SIGNED, STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL) | ||
60 | |||
61 | /* Define a feature with unsigned value */ | ||
62 | #define U_ARM64_FTR_BITS(STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL) \ | ||
63 | __ARM64_FTR_BITS(FTR_UNSIGNED, STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL) | ||
64 | |||
56 | #define ARM64_FTR_END \ | 65 | #define ARM64_FTR_END \ |
57 | { \ | 66 | { \ |
58 | .width = 0, \ | 67 | .width = 0, \ |
@@ -99,7 +108,7 @@ static struct arm64_ftr_bits ftr_id_aa64mmfr0[] = { | |||
99 | * Differing PARange is fine as long as all peripherals and memory are mapped | 108 | * Differing PARange is fine as long as all peripherals and memory are mapped |
100 | * within the minimum PARange of all CPUs | 109 | * within the minimum PARange of all CPUs |
101 | */ | 110 | */ |
102 | ARM64_FTR_BITS(FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_PARANGE_SHIFT, 4, 0), | 111 | U_ARM64_FTR_BITS(FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_PARANGE_SHIFT, 4, 0), |
103 | ARM64_FTR_END, | 112 | ARM64_FTR_END, |
104 | }; | 113 | }; |
105 | 114 | ||
@@ -115,18 +124,18 @@ static struct arm64_ftr_bits ftr_id_aa64mmfr1[] = { | |||
115 | }; | 124 | }; |
116 | 125 | ||
117 | static struct arm64_ftr_bits ftr_ctr[] = { | 126 | static struct arm64_ftr_bits ftr_ctr[] = { |
118 | ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 31, 1, 1), /* RAO */ | 127 | U_ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 31, 1, 1), /* RAO */ |
119 | ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 28, 3, 0), | 128 | ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 28, 3, 0), |
120 | ARM64_FTR_BITS(FTR_STRICT, FTR_HIGHER_SAFE, 24, 4, 0), /* CWG */ | 129 | U_ARM64_FTR_BITS(FTR_STRICT, FTR_HIGHER_SAFE, 24, 4, 0), /* CWG */ |
121 | ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 20, 4, 0), /* ERG */ | 130 | U_ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 20, 4, 0), /* ERG */ |
122 | ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 16, 4, 1), /* DminLine */ | 131 | U_ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 16, 4, 1), /* DminLine */ |
123 | /* | 132 | /* |
124 | * Linux can handle differing I-cache policies. Userspace JITs will | 133 | * Linux can handle differing I-cache policies. Userspace JITs will |
125 | * make use of *minLine | 134 | * make use of *minLine |
126 | */ | 135 | */ |
127 | ARM64_FTR_BITS(FTR_NONSTRICT, FTR_EXACT, 14, 2, 0), /* L1Ip */ | 136 | U_ARM64_FTR_BITS(FTR_NONSTRICT, FTR_EXACT, 14, 2, 0), /* L1Ip */ |
128 | ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 4, 10, 0), /* RAZ */ | 137 | ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 4, 10, 0), /* RAZ */ |
129 | ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 0, 4, 0), /* IminLine */ | 138 | U_ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, 0, 4, 0), /* IminLine */ |
130 | ARM64_FTR_END, | 139 | ARM64_FTR_END, |
131 | }; | 140 | }; |
132 | 141 | ||
@@ -144,12 +153,12 @@ static struct arm64_ftr_bits ftr_id_mmfr0[] = { | |||
144 | 153 | ||
145 | static struct arm64_ftr_bits ftr_id_aa64dfr0[] = { | 154 | static struct arm64_ftr_bits ftr_id_aa64dfr0[] = { |
146 | ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 32, 32, 0), | 155 | ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 32, 32, 0), |
147 | ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_CTX_CMPS_SHIFT, 4, 0), | 156 | U_ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_CTX_CMPS_SHIFT, 4, 0), |
148 | ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_WRPS_SHIFT, 4, 0), | 157 | U_ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_WRPS_SHIFT, 4, 0), |
149 | ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_BRPS_SHIFT, 4, 0), | 158 | U_ARM64_FTR_BITS(FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_BRPS_SHIFT, 4, 0), |
150 | ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64DFR0_PMUVER_SHIFT, 4, 0), | 159 | U_ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64DFR0_PMUVER_SHIFT, 4, 0), |
151 | ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64DFR0_TRACEVER_SHIFT, 4, 0), | 160 | U_ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64DFR0_TRACEVER_SHIFT, 4, 0), |
152 | ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64DFR0_DEBUGVER_SHIFT, 4, 0x6), | 161 | U_ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64DFR0_DEBUGVER_SHIFT, 4, 0x6), |
153 | ARM64_FTR_END, | 162 | ARM64_FTR_END, |
154 | }; | 163 | }; |
155 | 164 | ||
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index fc5508e0df57..4eeb17198cfa 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c | |||
@@ -127,7 +127,11 @@ static int __init uefi_init(void) | |||
127 | table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables; | 127 | table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables; |
128 | config_tables = early_memremap(efi_to_phys(efi.systab->tables), | 128 | config_tables = early_memremap(efi_to_phys(efi.systab->tables), |
129 | table_size); | 129 | table_size); |
130 | 130 | if (config_tables == NULL) { | |
131 | pr_warn("Unable to map EFI config table array.\n"); | ||
132 | retval = -ENOMEM; | ||
133 | goto out; | ||
134 | } | ||
131 | retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables, | 135 | retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables, |
132 | sizeof(efi_config_table_64_t), NULL); | 136 | sizeof(efi_config_table_64_t), NULL); |
133 | 137 | ||
@@ -209,6 +213,14 @@ void __init efi_init(void) | |||
209 | PAGE_ALIGN(params.mmap_size + (params.mmap & ~PAGE_MASK))); | 213 | PAGE_ALIGN(params.mmap_size + (params.mmap & ~PAGE_MASK))); |
210 | memmap.phys_map = params.mmap; | 214 | memmap.phys_map = params.mmap; |
211 | memmap.map = early_memremap(params.mmap, params.mmap_size); | 215 | memmap.map = early_memremap(params.mmap, params.mmap_size); |
216 | if (memmap.map == NULL) { | ||
217 | /* | ||
218 | * If we are booting via UEFI, the UEFI memory map is the only | ||
219 | * description of memory we have, so there is little point in | ||
220 | * proceeding if we cannot access it. | ||
221 | */ | ||
222 | panic("Unable to map EFI memory map.\n"); | ||
223 | } | ||
212 | memmap.map_end = memmap.map + params.mmap_size; | 224 | memmap.map_end = memmap.map + params.mmap_size; |
213 | memmap.desc_size = params.desc_size; | 225 | memmap.desc_size = params.desc_size; |
214 | memmap.desc_version = params.desc_ver; | 226 | memmap.desc_version = params.desc_ver; |
@@ -227,7 +239,6 @@ static bool __init efi_virtmap_init(void) | |||
227 | init_new_context(NULL, &efi_mm); | 239 | init_new_context(NULL, &efi_mm); |
228 | 240 | ||
229 | for_each_efi_memory_desc(&memmap, md) { | 241 | for_each_efi_memory_desc(&memmap, md) { |
230 | u64 paddr, npages, size; | ||
231 | pgprot_t prot; | 242 | pgprot_t prot; |
232 | 243 | ||
233 | if (!(md->attribute & EFI_MEMORY_RUNTIME)) | 244 | if (!(md->attribute & EFI_MEMORY_RUNTIME)) |
@@ -235,11 +246,6 @@ static bool __init efi_virtmap_init(void) | |||
235 | if (md->virt_addr == 0) | 246 | if (md->virt_addr == 0) |
236 | return false; | 247 | return false; |
237 | 248 | ||
238 | paddr = md->phys_addr; | ||
239 | npages = md->num_pages; | ||
240 | memrange_efi_to_native(&paddr, &npages); | ||
241 | size = npages << PAGE_SHIFT; | ||
242 | |||
243 | pr_info(" EFI remap 0x%016llx => %p\n", | 249 | pr_info(" EFI remap 0x%016llx => %p\n", |
244 | md->phys_addr, (void *)md->virt_addr); | 250 | md->phys_addr, (void *)md->virt_addr); |
245 | 251 | ||
@@ -256,7 +262,8 @@ static bool __init efi_virtmap_init(void) | |||
256 | else | 262 | else |
257 | prot = PAGE_KERNEL; | 263 | prot = PAGE_KERNEL; |
258 | 264 | ||
259 | create_pgd_mapping(&efi_mm, paddr, md->virt_addr, size, | 265 | create_pgd_mapping(&efi_mm, md->phys_addr, md->virt_addr, |
266 | md->num_pages << EFI_PAGE_SHIFT, | ||
260 | __pgprot(pgprot_val(prot) | PTE_NG)); | 267 | __pgprot(pgprot_val(prot) | PTE_NG)); |
261 | } | 268 | } |
262 | return true; | 269 | return true; |
@@ -273,12 +280,12 @@ static int __init arm64_enable_runtime_services(void) | |||
273 | 280 | ||
274 | if (!efi_enabled(EFI_BOOT)) { | 281 | if (!efi_enabled(EFI_BOOT)) { |
275 | pr_info("EFI services will not be available.\n"); | 282 | pr_info("EFI services will not be available.\n"); |
276 | return -1; | 283 | return 0; |
277 | } | 284 | } |
278 | 285 | ||
279 | if (efi_runtime_disabled()) { | 286 | if (efi_runtime_disabled()) { |
280 | pr_info("EFI runtime services will be disabled.\n"); | 287 | pr_info("EFI runtime services will be disabled.\n"); |
281 | return -1; | 288 | return 0; |
282 | } | 289 | } |
283 | 290 | ||
284 | pr_info("Remapping and enabling EFI services.\n"); | 291 | pr_info("Remapping and enabling EFI services.\n"); |
@@ -288,7 +295,7 @@ static int __init arm64_enable_runtime_services(void) | |||
288 | mapsize); | 295 | mapsize); |
289 | if (!memmap.map) { | 296 | if (!memmap.map) { |
290 | pr_err("Failed to remap EFI memory map\n"); | 297 | pr_err("Failed to remap EFI memory map\n"); |
291 | return -1; | 298 | return -ENOMEM; |
292 | } | 299 | } |
293 | memmap.map_end = memmap.map + mapsize; | 300 | memmap.map_end = memmap.map + mapsize; |
294 | efi.memmap = &memmap; | 301 | efi.memmap = &memmap; |
@@ -297,13 +304,13 @@ static int __init arm64_enable_runtime_services(void) | |||
297 | sizeof(efi_system_table_t)); | 304 | sizeof(efi_system_table_t)); |
298 | if (!efi.systab) { | 305 | if (!efi.systab) { |
299 | pr_err("Failed to remap EFI System Table\n"); | 306 | pr_err("Failed to remap EFI System Table\n"); |
300 | return -1; | 307 | return -ENOMEM; |
301 | } | 308 | } |
302 | set_bit(EFI_SYSTEM_TABLES, &efi.flags); | 309 | set_bit(EFI_SYSTEM_TABLES, &efi.flags); |
303 | 310 | ||
304 | if (!efi_virtmap_init()) { | 311 | if (!efi_virtmap_init()) { |
305 | pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n"); | 312 | pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n"); |
306 | return -1; | 313 | return -ENOMEM; |
307 | } | 314 | } |
308 | 315 | ||
309 | /* Set up runtime services function pointers */ | 316 | /* Set up runtime services function pointers */ |
diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c index f636a2639f03..e87f53ff5f58 100644 --- a/arch/arm64/mm/context.c +++ b/arch/arm64/mm/context.c | |||
@@ -76,13 +76,28 @@ static void flush_context(unsigned int cpu) | |||
76 | __flush_icache_all(); | 76 | __flush_icache_all(); |
77 | } | 77 | } |
78 | 78 | ||
79 | static int is_reserved_asid(u64 asid) | 79 | static bool check_update_reserved_asid(u64 asid, u64 newasid) |
80 | { | 80 | { |
81 | int cpu; | 81 | int cpu; |
82 | for_each_possible_cpu(cpu) | 82 | bool hit = false; |
83 | if (per_cpu(reserved_asids, cpu) == asid) | 83 | |
84 | return 1; | 84 | /* |
85 | return 0; | 85 | * Iterate over the set of reserved ASIDs looking for a match. |
86 | * If we find one, then we can update our mm to use newasid | ||
87 | * (i.e. the same ASID in the current generation) but we can't | ||
88 | * exit the loop early, since we need to ensure that all copies | ||
89 | * of the old ASID are updated to reflect the mm. Failure to do | ||
90 | * so could result in us missing the reserved ASID in a future | ||
91 | * generation. | ||
92 | */ | ||
93 | for_each_possible_cpu(cpu) { | ||
94 | if (per_cpu(reserved_asids, cpu) == asid) { | ||
95 | hit = true; | ||
96 | per_cpu(reserved_asids, cpu) = newasid; | ||
97 | } | ||
98 | } | ||
99 | |||
100 | return hit; | ||
86 | } | 101 | } |
87 | 102 | ||
88 | static u64 new_context(struct mm_struct *mm, unsigned int cpu) | 103 | static u64 new_context(struct mm_struct *mm, unsigned int cpu) |
@@ -92,12 +107,14 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu) | |||
92 | u64 generation = atomic64_read(&asid_generation); | 107 | u64 generation = atomic64_read(&asid_generation); |
93 | 108 | ||
94 | if (asid != 0) { | 109 | if (asid != 0) { |
110 | u64 newasid = generation | (asid & ~ASID_MASK); | ||
111 | |||
95 | /* | 112 | /* |
96 | * If our current ASID was active during a rollover, we | 113 | * If our current ASID was active during a rollover, we |
97 | * can continue to use it and this was just a false alarm. | 114 | * can continue to use it and this was just a false alarm. |
98 | */ | 115 | */ |
99 | if (is_reserved_asid(asid)) | 116 | if (check_update_reserved_asid(asid, newasid)) |
100 | return generation | (asid & ~ASID_MASK); | 117 | return newasid; |
101 | 118 | ||
102 | /* | 119 | /* |
103 | * We had a valid ASID in a previous life, so try to re-use | 120 | * We had a valid ASID in a previous life, so try to re-use |
@@ -105,7 +122,7 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu) | |||
105 | */ | 122 | */ |
106 | asid &= ~ASID_MASK; | 123 | asid &= ~ASID_MASK; |
107 | if (!__test_and_set_bit(asid, asid_map)) | 124 | if (!__test_and_set_bit(asid, asid_map)) |
108 | goto bump_gen; | 125 | return newasid; |
109 | } | 126 | } |
110 | 127 | ||
111 | /* | 128 | /* |
@@ -129,10 +146,7 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu) | |||
129 | set_asid: | 146 | set_asid: |
130 | __set_bit(asid, asid_map); | 147 | __set_bit(asid, asid_map); |
131 | cur_idx = asid; | 148 | cur_idx = asid; |
132 | 149 | return asid | generation; | |
133 | bump_gen: | ||
134 | asid |= generation; | ||
135 | return asid; | ||
136 | } | 150 | } |
137 | 151 | ||
138 | void check_and_switch_context(struct mm_struct *mm, unsigned int cpu) | 152 | void check_and_switch_context(struct mm_struct *mm, unsigned int cpu) |
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 19211c4a8911..92ddac1e8ca2 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c | |||
@@ -393,16 +393,16 @@ static struct fault_info { | |||
393 | { do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 1 translation fault" }, | 393 | { do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 1 translation fault" }, |
394 | { do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 2 translation fault" }, | 394 | { do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 2 translation fault" }, |
395 | { do_page_fault, SIGSEGV, SEGV_MAPERR, "level 3 translation fault" }, | 395 | { do_page_fault, SIGSEGV, SEGV_MAPERR, "level 3 translation fault" }, |
396 | { do_bad, SIGBUS, 0, "reserved access flag fault" }, | 396 | { do_bad, SIGBUS, 0, "unknown 8" }, |
397 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 1 access flag fault" }, | 397 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 1 access flag fault" }, |
398 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 access flag fault" }, | 398 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 access flag fault" }, |
399 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 access flag fault" }, | 399 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 access flag fault" }, |
400 | { do_bad, SIGBUS, 0, "reserved permission fault" }, | 400 | { do_bad, SIGBUS, 0, "unknown 12" }, |
401 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 1 permission fault" }, | 401 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 1 permission fault" }, |
402 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 permission fault" }, | 402 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 permission fault" }, |
403 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 permission fault" }, | 403 | { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 permission fault" }, |
404 | { do_bad, SIGBUS, 0, "synchronous external abort" }, | 404 | { do_bad, SIGBUS, 0, "synchronous external abort" }, |
405 | { do_bad, SIGBUS, 0, "asynchronous external abort" }, | 405 | { do_bad, SIGBUS, 0, "unknown 17" }, |
406 | { do_bad, SIGBUS, 0, "unknown 18" }, | 406 | { do_bad, SIGBUS, 0, "unknown 18" }, |
407 | { do_bad, SIGBUS, 0, "unknown 19" }, | 407 | { do_bad, SIGBUS, 0, "unknown 19" }, |
408 | { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" }, | 408 | { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" }, |
@@ -410,16 +410,16 @@ static struct fault_info { | |||
410 | { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" }, | 410 | { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" }, |
411 | { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" }, | 411 | { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" }, |
412 | { do_bad, SIGBUS, 0, "synchronous parity error" }, | 412 | { do_bad, SIGBUS, 0, "synchronous parity error" }, |
413 | { do_bad, SIGBUS, 0, "asynchronous parity error" }, | 413 | { do_bad, SIGBUS, 0, "unknown 25" }, |
414 | { do_bad, SIGBUS, 0, "unknown 26" }, | 414 | { do_bad, SIGBUS, 0, "unknown 26" }, |
415 | { do_bad, SIGBUS, 0, "unknown 27" }, | 415 | { do_bad, SIGBUS, 0, "unknown 27" }, |
416 | { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk" }, | 416 | { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk)" }, |
417 | { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk" }, | 417 | { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk)" }, |
418 | { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk" }, | 418 | { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk)" }, |
419 | { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk" }, | 419 | { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk)" }, |
420 | { do_bad, SIGBUS, 0, "unknown 32" }, | 420 | { do_bad, SIGBUS, 0, "unknown 32" }, |
421 | { do_bad, SIGBUS, BUS_ADRALN, "alignment fault" }, | 421 | { do_bad, SIGBUS, BUS_ADRALN, "alignment fault" }, |
422 | { do_bad, SIGBUS, 0, "debug event" }, | 422 | { do_bad, SIGBUS, 0, "unknown 34" }, |
423 | { do_bad, SIGBUS, 0, "unknown 35" }, | 423 | { do_bad, SIGBUS, 0, "unknown 35" }, |
424 | { do_bad, SIGBUS, 0, "unknown 36" }, | 424 | { do_bad, SIGBUS, 0, "unknown 36" }, |
425 | { do_bad, SIGBUS, 0, "unknown 37" }, | 425 | { do_bad, SIGBUS, 0, "unknown 37" }, |
@@ -433,21 +433,21 @@ static struct fault_info { | |||
433 | { do_bad, SIGBUS, 0, "unknown 45" }, | 433 | { do_bad, SIGBUS, 0, "unknown 45" }, |
434 | { do_bad, SIGBUS, 0, "unknown 46" }, | 434 | { do_bad, SIGBUS, 0, "unknown 46" }, |
435 | { do_bad, SIGBUS, 0, "unknown 47" }, | 435 | { do_bad, SIGBUS, 0, "unknown 47" }, |
436 | { do_bad, SIGBUS, 0, "unknown 48" }, | 436 | { do_bad, SIGBUS, 0, "TLB conflict abort" }, |
437 | { do_bad, SIGBUS, 0, "unknown 49" }, | 437 | { do_bad, SIGBUS, 0, "unknown 49" }, |
438 | { do_bad, SIGBUS, 0, "unknown 50" }, | 438 | { do_bad, SIGBUS, 0, "unknown 50" }, |
439 | { do_bad, SIGBUS, 0, "unknown 51" }, | 439 | { do_bad, SIGBUS, 0, "unknown 51" }, |
440 | { do_bad, SIGBUS, 0, "implementation fault (lockdown abort)" }, | 440 | { do_bad, SIGBUS, 0, "implementation fault (lockdown abort)" }, |
441 | { do_bad, SIGBUS, 0, "unknown 53" }, | 441 | { do_bad, SIGBUS, 0, "implementation fault (unsupported exclusive)" }, |
442 | { do_bad, SIGBUS, 0, "unknown 54" }, | 442 | { do_bad, SIGBUS, 0, "unknown 54" }, |
443 | { do_bad, SIGBUS, 0, "unknown 55" }, | 443 | { do_bad, SIGBUS, 0, "unknown 55" }, |
444 | { do_bad, SIGBUS, 0, "unknown 56" }, | 444 | { do_bad, SIGBUS, 0, "unknown 56" }, |
445 | { do_bad, SIGBUS, 0, "unknown 57" }, | 445 | { do_bad, SIGBUS, 0, "unknown 57" }, |
446 | { do_bad, SIGBUS, 0, "implementation fault (coprocessor abort)" }, | 446 | { do_bad, SIGBUS, 0, "unknown 58" }, |
447 | { do_bad, SIGBUS, 0, "unknown 59" }, | 447 | { do_bad, SIGBUS, 0, "unknown 59" }, |
448 | { do_bad, SIGBUS, 0, "unknown 60" }, | 448 | { do_bad, SIGBUS, 0, "unknown 60" }, |
449 | { do_bad, SIGBUS, 0, "unknown 61" }, | 449 | { do_bad, SIGBUS, 0, "section domain fault" }, |
450 | { do_bad, SIGBUS, 0, "unknown 62" }, | 450 | { do_bad, SIGBUS, 0, "page domain fault" }, |
451 | { do_bad, SIGBUS, 0, "unknown 63" }, | 451 | { do_bad, SIGBUS, 0, "unknown 63" }, |
452 | }; | 452 | }; |
453 | 453 | ||
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index abb66f84d4ac..873e363048c6 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c | |||
@@ -64,8 +64,12 @@ EXPORT_SYMBOL(phys_mem_access_prot); | |||
64 | 64 | ||
65 | static void __init *early_alloc(unsigned long sz) | 65 | static void __init *early_alloc(unsigned long sz) |
66 | { | 66 | { |
67 | void *ptr = __va(memblock_alloc(sz, sz)); | 67 | phys_addr_t phys; |
68 | BUG_ON(!ptr); | 68 | void *ptr; |
69 | |||
70 | phys = memblock_alloc(sz, sz); | ||
71 | BUG_ON(!phys); | ||
72 | ptr = __va(phys); | ||
69 | memset(ptr, 0, sz); | 73 | memset(ptr, 0, sz); |
70 | return ptr; | 74 | return ptr; |
71 | } | 75 | } |
@@ -81,55 +85,19 @@ static void split_pmd(pmd_t *pmd, pte_t *pte) | |||
81 | do { | 85 | do { |
82 | /* | 86 | /* |
83 | * Need to have the least restrictive permissions available | 87 | * Need to have the least restrictive permissions available |
84 | * permissions will be fixed up later. Default the new page | 88 | * permissions will be fixed up later |
85 | * range as contiguous ptes. | ||
86 | */ | 89 | */ |
87 | set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC_CONT)); | 90 | set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC)); |
88 | pfn++; | 91 | pfn++; |
89 | } while (pte++, i++, i < PTRS_PER_PTE); | 92 | } while (pte++, i++, i < PTRS_PER_PTE); |
90 | } | 93 | } |
91 | 94 | ||
92 | /* | ||
93 | * Given a PTE with the CONT bit set, determine where the CONT range | ||
94 | * starts, and clear the entire range of PTE CONT bits. | ||
95 | */ | ||
96 | static void clear_cont_pte_range(pte_t *pte, unsigned long addr) | ||
97 | { | ||
98 | int i; | ||
99 | |||
100 | pte -= CONT_RANGE_OFFSET(addr); | ||
101 | for (i = 0; i < CONT_PTES; i++) { | ||
102 | set_pte(pte, pte_mknoncont(*pte)); | ||
103 | pte++; | ||
104 | } | ||
105 | flush_tlb_all(); | ||
106 | } | ||
107 | |||
108 | /* | ||
109 | * Given a range of PTEs set the pfn and provided page protection flags | ||
110 | */ | ||
111 | static void __populate_init_pte(pte_t *pte, unsigned long addr, | ||
112 | unsigned long end, phys_addr_t phys, | ||
113 | pgprot_t prot) | ||
114 | { | ||
115 | unsigned long pfn = __phys_to_pfn(phys); | ||
116 | |||
117 | do { | ||
118 | /* clear all the bits except the pfn, then apply the prot */ | ||
119 | set_pte(pte, pfn_pte(pfn, prot)); | ||
120 | pte++; | ||
121 | pfn++; | ||
122 | addr += PAGE_SIZE; | ||
123 | } while (addr != end); | ||
124 | } | ||
125 | |||
126 | static void alloc_init_pte(pmd_t *pmd, unsigned long addr, | 95 | static void alloc_init_pte(pmd_t *pmd, unsigned long addr, |
127 | unsigned long end, phys_addr_t phys, | 96 | unsigned long end, unsigned long pfn, |
128 | pgprot_t prot, | 97 | pgprot_t prot, |
129 | void *(*alloc)(unsigned long size)) | 98 | void *(*alloc)(unsigned long size)) |
130 | { | 99 | { |
131 | pte_t *pte; | 100 | pte_t *pte; |
132 | unsigned long next; | ||
133 | 101 | ||
134 | if (pmd_none(*pmd) || pmd_sect(*pmd)) { | 102 | if (pmd_none(*pmd) || pmd_sect(*pmd)) { |
135 | pte = alloc(PTRS_PER_PTE * sizeof(pte_t)); | 103 | pte = alloc(PTRS_PER_PTE * sizeof(pte_t)); |
@@ -142,27 +110,9 @@ static void alloc_init_pte(pmd_t *pmd, unsigned long addr, | |||
142 | 110 | ||
143 | pte = pte_offset_kernel(pmd, addr); | 111 | pte = pte_offset_kernel(pmd, addr); |
144 | do { | 112 | do { |
145 | next = min(end, (addr + CONT_SIZE) & CONT_MASK); | 113 | set_pte(pte, pfn_pte(pfn, prot)); |
146 | if (((addr | next | phys) & ~CONT_MASK) == 0) { | 114 | pfn++; |
147 | /* a block of CONT_PTES */ | 115 | } while (pte++, addr += PAGE_SIZE, addr != end); |
148 | __populate_init_pte(pte, addr, next, phys, | ||
149 | __pgprot(pgprot_val(prot) | PTE_CONT)); | ||
150 | } else { | ||
151 | /* | ||
152 | * If the range being split is already inside of a | ||
153 | * contiguous range but this PTE isn't going to be | ||
154 | * contiguous, then we want to unmark the adjacent | ||
155 | * ranges, then update the portion of the range we | ||
156 | * are interrested in. | ||
157 | */ | ||
158 | clear_cont_pte_range(pte, addr); | ||
159 | __populate_init_pte(pte, addr, next, phys, prot); | ||
160 | } | ||
161 | |||
162 | pte += (next - addr) >> PAGE_SHIFT; | ||
163 | phys += next - addr; | ||
164 | addr = next; | ||
165 | } while (addr != end); | ||
166 | } | 116 | } |
167 | 117 | ||
168 | static void split_pud(pud_t *old_pud, pmd_t *pmd) | 118 | static void split_pud(pud_t *old_pud, pmd_t *pmd) |
@@ -223,7 +173,8 @@ static void alloc_init_pmd(struct mm_struct *mm, pud_t *pud, | |||
223 | } | 173 | } |
224 | } | 174 | } |
225 | } else { | 175 | } else { |
226 | alloc_init_pte(pmd, addr, next, phys, prot, alloc); | 176 | alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys), |
177 | prot, alloc); | ||
227 | } | 178 | } |
228 | phys += next - addr; | 179 | phys += next - addr; |
229 | } while (pmd++, addr = next, addr != end); | 180 | } while (pmd++, addr = next, addr != end); |
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index a156b82dd14c..c2b66a277e98 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h | |||
@@ -524,7 +524,7 @@ asmlinkage long sys_chown(const char __user *filename, | |||
524 | asmlinkage long sys_lchown(const char __user *filename, | 524 | asmlinkage long sys_lchown(const char __user *filename, |
525 | uid_t user, gid_t group); | 525 | uid_t user, gid_t group); |
526 | asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group); | 526 | asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group); |
527 | #ifdef CONFIG_UID16 | 527 | #ifdef CONFIG_HAVE_UID16 |
528 | asmlinkage long sys_chown16(const char __user *filename, | 528 | asmlinkage long sys_chown16(const char __user *filename, |
529 | old_uid_t user, old_gid_t group); | 529 | old_uid_t user, old_gid_t group); |
530 | asmlinkage long sys_lchown16(const char __user *filename, | 530 | asmlinkage long sys_lchown16(const char __user *filename, |
diff --git a/include/linux/types.h b/include/linux/types.h index 70d8500bddf1..70dd3dfde631 100644 --- a/include/linux/types.h +++ b/include/linux/types.h | |||
@@ -35,7 +35,7 @@ typedef __kernel_gid16_t gid16_t; | |||
35 | 35 | ||
36 | typedef unsigned long uintptr_t; | 36 | typedef unsigned long uintptr_t; |
37 | 37 | ||
38 | #ifdef CONFIG_UID16 | 38 | #ifdef CONFIG_HAVE_UID16 |
39 | /* This is defined by include/asm-{arch}/posix_types.h */ | 39 | /* This is defined by include/asm-{arch}/posix_types.h */ |
40 | typedef __kernel_old_uid_t old_uid_t; | 40 | typedef __kernel_old_uid_t old_uid_t; |
41 | typedef __kernel_old_gid_t old_gid_t; | 41 | typedef __kernel_old_gid_t old_gid_t; |