| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2 | *  Copyright (C) 1995  Linus Torvalds | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 3 | *  Copyright (C) 2001, 2002 Andi Kleen, SuSE Labs. | 
| Ingo Molnar | f8eeb2e | 2009-02-20 23:13:36 +0100 | [diff] [blame] | 4 | *  Copyright (C) 2008-2009, Red Hat Inc., Ingo Molnar | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5 | */ | 
| Ingo Molnar | a2bcd47 | 2009-03-29 23:47:48 +0200 | [diff] [blame] | 6 | #include <linux/sched.h>		/* test_thread_flag(), ...	*/ | 
|  | 7 | #include <linux/kdebug.h>		/* oops_begin/end, ...		*/ | 
| Linus Torvalds | 4cdf8db | 2016-10-11 23:38:39 -0700 | [diff] [blame] | 8 | #include <linux/extable.h>		/* search_exception_tables	*/ | 
| Ingo Molnar | a2bcd47 | 2009-03-29 23:47:48 +0200 | [diff] [blame] | 9 | #include <linux/bootmem.h>		/* max_low_pfn			*/ | 
| Masami Hiramatsu | 9326638 | 2014-04-17 17:18:14 +0900 | [diff] [blame] | 10 | #include <linux/kprobes.h>		/* NOKPROBE_SYMBOL, ...		*/ | 
| Ingo Molnar | a2bcd47 | 2009-03-29 23:47:48 +0200 | [diff] [blame] | 11 | #include <linux/mmiotrace.h>		/* kmmio_handler, ...		*/ | 
| Ingo Molnar | cdd6c48 | 2009-09-21 12:02:48 +0200 | [diff] [blame] | 12 | #include <linux/perf_event.h>		/* perf_sw_event		*/ | 
| Andi Kleen | f672b49 | 2010-09-27 22:05:55 +0200 | [diff] [blame] | 13 | #include <linux/hugetlb.h>		/* hstate_index_to_shift	*/ | 
| Linus Torvalds | 268bb0c | 2011-05-20 12:50:29 -0700 | [diff] [blame] | 14 | #include <linux/prefetch.h>		/* prefetchw			*/ | 
| Frederic Weisbecker | 56dd947 | 2013-02-24 00:23:25 +0100 | [diff] [blame] | 15 | #include <linux/context_tracking.h>	/* exception_enter(), ...	*/ | 
| David Hildenbrand | 70ffdb9 | 2015-05-11 17:52:11 +0200 | [diff] [blame] | 16 | #include <linux/uaccess.h>		/* faulthandler_disabled()	*/ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 17 |  | 
| Dave Hansen | 019132f | 2016-02-12 13:02:14 -0800 | [diff] [blame] | 18 | #include <asm/cpufeature.h>		/* boot_cpu_has, ...		*/ | 
| Ingo Molnar | a2bcd47 | 2009-03-29 23:47:48 +0200 | [diff] [blame] | 19 | #include <asm/traps.h>			/* dotraplinkage, ...		*/ | 
|  | 20 | #include <asm/pgalloc.h>		/* pgd_*(), ...			*/ | 
| Vegard Nossum | f856129 | 2008-04-04 00:53:23 +0200 | [diff] [blame] | 21 | #include <asm/kmemcheck.h>		/* kmemcheck_*(), ...		*/ | 
| Andy Lutomirski | f40c330 | 2014-05-05 12:19:36 -0700 | [diff] [blame] | 22 | #include <asm/fixmap.h>			/* VSYSCALL_ADDR		*/ | 
|  | 23 | #include <asm/vsyscall.h>		/* emulate_vsyscall		*/ | 
| Brian Gerst | ba3e127 | 2015-07-29 01:41:21 -0400 | [diff] [blame] | 24 | #include <asm/vm86.h>			/* struct vm86			*/ | 
| Dave Hansen | 019132f | 2016-02-12 13:02:14 -0800 | [diff] [blame] | 25 | #include <asm/mmu_context.h>		/* vma_pkey()			*/ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 26 |  | 
| Seiji Aguchi | d34603b | 2013-10-30 16:39:03 -0400 | [diff] [blame] | 27 | #define CREATE_TRACE_POINTS | 
|  | 28 | #include <asm/trace/exceptions.h> | 
|  | 29 |  | 
| Harvey Harrison | 33cb524 | 2008-01-30 13:32:19 +0100 | [diff] [blame] | 30 | /* | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 31 | * Page fault error code bits: | 
|  | 32 | * | 
|  | 33 | *   bit 0 ==	 0: no page found	1: protection fault | 
|  | 34 | *   bit 1 ==	 0: read access		1: write access | 
|  | 35 | *   bit 2 ==	 0: kernel-mode access	1: user-mode access | 
|  | 36 | *   bit 3 ==				1: use of reserved bit detected | 
|  | 37 | *   bit 4 ==				1: fault was an instruction fetch | 
| Dave Hansen | b3ecd51 | 2016-02-12 13:02:07 -0800 | [diff] [blame] | 38 | *   bit 5 ==				1: protection keys block access | 
| Harvey Harrison | 33cb524 | 2008-01-30 13:32:19 +0100 | [diff] [blame] | 39 | */ | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 40 | enum x86_pf_error_code { | 
|  | 41 |  | 
|  | 42 | PF_PROT		=		1 << 0, | 
|  | 43 | PF_WRITE	=		1 << 1, | 
|  | 44 | PF_USER		=		1 << 2, | 
|  | 45 | PF_RSVD		=		1 << 3, | 
|  | 46 | PF_INSTR	=		1 << 4, | 
| Dave Hansen | b3ecd51 | 2016-02-12 13:02:07 -0800 | [diff] [blame] | 47 | PF_PK		=		1 << 5, | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 48 | }; | 
| Andi Kleen | 66c5815 | 2006-01-11 22:44:09 +0100 | [diff] [blame] | 49 |  | 
| Ingo Molnar | b814d41 | 2009-02-20 22:32:10 +0100 | [diff] [blame] | 50 | /* | 
| Ingo Molnar | b319eed | 2009-02-22 10:24:18 +0100 | [diff] [blame] | 51 | * Returns 0 if mmiotrace is disabled, or if the fault is not | 
|  | 52 | * handled by mmiotrace: | 
| Ingo Molnar | b814d41 | 2009-02-20 22:32:10 +0100 | [diff] [blame] | 53 | */ | 
| Masami Hiramatsu | 9326638 | 2014-04-17 17:18:14 +0900 | [diff] [blame] | 54 | static nokprobe_inline int | 
| Masami Hiramatsu | 62c9295 | 2009-08-27 13:23:11 -0400 | [diff] [blame] | 55 | kmmio_fault(struct pt_regs *regs, unsigned long addr) | 
| Pekka Paalanen | 8606978 | 2008-05-12 21:20:56 +0200 | [diff] [blame] | 56 | { | 
| Pekka Paalanen | 0fd0e3d | 2008-05-12 21:20:57 +0200 | [diff] [blame] | 57 | if (unlikely(is_kmmio_active())) | 
|  | 58 | if (kmmio_handler(regs, addr) == 1) | 
|  | 59 | return -1; | 
| Pekka Paalanen | 0fd0e3d | 2008-05-12 21:20:57 +0200 | [diff] [blame] | 60 | return 0; | 
| Pekka Paalanen | 8606978 | 2008-05-12 21:20:56 +0200 | [diff] [blame] | 61 | } | 
|  | 62 |  | 
| Masami Hiramatsu | 9326638 | 2014-04-17 17:18:14 +0900 | [diff] [blame] | 63 | static nokprobe_inline int kprobes_fault(struct pt_regs *regs) | 
| Anil S Keshavamurthy | 1bd858a | 2006-06-26 00:25:25 -0700 | [diff] [blame] | 64 | { | 
| Christoph Hellwig | 74a0b57 | 2007-10-16 01:24:07 -0700 | [diff] [blame] | 65 | int ret = 0; | 
| Anil S Keshavamurthy | 1bd858a | 2006-06-26 00:25:25 -0700 | [diff] [blame] | 66 |  | 
| Christoph Hellwig | 74a0b57 | 2007-10-16 01:24:07 -0700 | [diff] [blame] | 67 | /* kprobe_running() needs smp_processor_id() */ | 
| Andy Lutomirski | f39b6f0 | 2015-03-18 18:33:33 -0700 | [diff] [blame] | 68 | if (kprobes_built_in() && !user_mode(regs)) { | 
| Christoph Hellwig | 74a0b57 | 2007-10-16 01:24:07 -0700 | [diff] [blame] | 69 | preempt_disable(); | 
|  | 70 | if (kprobe_running() && kprobe_fault_handler(regs, 14)) | 
|  | 71 | ret = 1; | 
|  | 72 | preempt_enable(); | 
|  | 73 | } | 
| Anil S Keshavamurthy | 1bd858a | 2006-06-26 00:25:25 -0700 | [diff] [blame] | 74 |  | 
| Christoph Hellwig | 74a0b57 | 2007-10-16 01:24:07 -0700 | [diff] [blame] | 75 | return ret; | 
| Harvey Harrison | 33cb524 | 2008-01-30 13:32:19 +0100 | [diff] [blame] | 76 | } | 
| Anil S Keshavamurthy | 1bd858a | 2006-06-26 00:25:25 -0700 | [diff] [blame] | 77 |  | 
| Harvey Harrison | 1dc85be | 2008-01-30 13:32:35 +0100 | [diff] [blame] | 78 | /* | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 79 | * Prefetch quirks: | 
| Harvey Harrison | 1dc85be | 2008-01-30 13:32:35 +0100 | [diff] [blame] | 80 | * | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 81 | * 32-bit mode: | 
| Harvey Harrison | 1dc85be | 2008-01-30 13:32:35 +0100 | [diff] [blame] | 82 | * | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 83 | *   Sometimes AMD Athlon/Opteron CPUs report invalid exceptions on prefetch. | 
|  | 84 | *   Check that here and ignore it. | 
|  | 85 | * | 
|  | 86 | * 64-bit mode: | 
|  | 87 | * | 
|  | 88 | *   Sometimes the CPU reports invalid exceptions on prefetch. | 
|  | 89 | *   Check that here and ignore it. | 
|  | 90 | * | 
|  | 91 | * Opcode checker based on code by Richard Brunner. | 
| Harvey Harrison | 1dc85be | 2008-01-30 13:32:35 +0100 | [diff] [blame] | 92 | */ | 
| Ingo Molnar | 107a036 | 2009-02-20 20:37:05 +0100 | [diff] [blame] | 93 | static inline int | 
|  | 94 | check_prefetch_opcode(struct pt_regs *regs, unsigned char *instr, | 
|  | 95 | unsigned char opcode, int *prefetch) | 
|  | 96 | { | 
|  | 97 | unsigned char instr_hi = opcode & 0xf0; | 
|  | 98 | unsigned char instr_lo = opcode & 0x0f; | 
|  | 99 |  | 
|  | 100 | switch (instr_hi) { | 
|  | 101 | case 0x20: | 
|  | 102 | case 0x30: | 
|  | 103 | /* | 
|  | 104 | * Values 0x26,0x2E,0x36,0x3E are valid x86 prefixes. | 
|  | 105 | * In X86_64 long mode, the CPU will signal invalid | 
|  | 106 | * opcode if some of these prefixes are present so | 
|  | 107 | * X86_64 will never get here anyway | 
|  | 108 | */ | 
|  | 109 | return ((instr_lo & 7) == 0x6); | 
|  | 110 | #ifdef CONFIG_X86_64 | 
|  | 111 | case 0x40: | 
|  | 112 | /* | 
|  | 113 | * In AMD64 long mode 0x40..0x4F are valid REX prefixes | 
|  | 114 | * Need to figure out under what instruction mode the | 
|  | 115 | * instruction was issued. Could check the LDT for lm, | 
|  | 116 | * but for now it's good enough to assume that long | 
|  | 117 | * mode only uses well known segments or kernel. | 
|  | 118 | */ | 
| Andy Lutomirski | 318f5a2 | 2011-08-03 09:31:53 -0400 | [diff] [blame] | 119 | return (!user_mode(regs) || user_64bit_mode(regs)); | 
| Ingo Molnar | 107a036 | 2009-02-20 20:37:05 +0100 | [diff] [blame] | 120 | #endif | 
|  | 121 | case 0x60: | 
|  | 122 | /* 0x64 thru 0x67 are valid prefixes in all modes. */ | 
|  | 123 | return (instr_lo & 0xC) == 0x4; | 
|  | 124 | case 0xF0: | 
|  | 125 | /* 0xF0, 0xF2, 0xF3 are valid prefixes in all modes. */ | 
|  | 126 | return !instr_lo || (instr_lo>>1) == 1; | 
|  | 127 | case 0x00: | 
|  | 128 | /* Prefetch instruction is 0x0F0D or 0x0F18 */ | 
|  | 129 | if (probe_kernel_address(instr, opcode)) | 
|  | 130 | return 0; | 
|  | 131 |  | 
|  | 132 | *prefetch = (instr_lo == 0xF) && | 
|  | 133 | (opcode == 0x0D || opcode == 0x18); | 
|  | 134 | return 0; | 
|  | 135 | default: | 
|  | 136 | return 0; | 
|  | 137 | } | 
|  | 138 | } | 
|  | 139 |  | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 140 | static int | 
|  | 141 | is_prefetch(struct pt_regs *regs, unsigned long error_code, unsigned long addr) | 
| Harvey Harrison | 33cb524 | 2008-01-30 13:32:19 +0100 | [diff] [blame] | 142 | { | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 143 | unsigned char *max_instr; | 
| Andi Kleen | ab2bf0c | 2006-12-07 02:14:06 +0100 | [diff] [blame] | 144 | unsigned char *instr; | 
| Harvey Harrison | 33cb524 | 2008-01-30 13:32:19 +0100 | [diff] [blame] | 145 | int prefetch = 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 146 |  | 
| Ingo Molnar | 3085354 | 2008-03-27 21:29:09 +0100 | [diff] [blame] | 147 | /* | 
|  | 148 | * If it was a exec (instruction fetch) fault on NX page, then | 
|  | 149 | * do not ignore the fault: | 
|  | 150 | */ | 
| Andi Kleen | 66c5815 | 2006-01-11 22:44:09 +0100 | [diff] [blame] | 151 | if (error_code & PF_INSTR) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 152 | return 0; | 
| Harvey Harrison | 1dc85be | 2008-01-30 13:32:35 +0100 | [diff] [blame] | 153 |  | 
| Ingo Molnar | 107a036 | 2009-02-20 20:37:05 +0100 | [diff] [blame] | 154 | instr = (void *)convert_ip_to_linear(current, regs); | 
| Andi Kleen | f1290ec | 2005-04-16 15:24:59 -0700 | [diff] [blame] | 155 | max_instr = instr + 15; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 156 |  | 
| Andy Lutomirski | d31bf07 | 2015-03-18 18:33:27 -0700 | [diff] [blame] | 157 | if (user_mode(regs) && instr >= (unsigned char *)TASK_SIZE_MAX) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 158 | return 0; | 
|  | 159 |  | 
| Ingo Molnar | 107a036 | 2009-02-20 20:37:05 +0100 | [diff] [blame] | 160 | while (instr < max_instr) { | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 161 | unsigned char opcode; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 162 |  | 
| Andi Kleen | ab2bf0c | 2006-12-07 02:14:06 +0100 | [diff] [blame] | 163 | if (probe_kernel_address(instr, opcode)) | 
| Harvey Harrison | 33cb524 | 2008-01-30 13:32:19 +0100 | [diff] [blame] | 164 | break; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 165 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 166 | instr++; | 
|  | 167 |  | 
| Ingo Molnar | 107a036 | 2009-02-20 20:37:05 +0100 | [diff] [blame] | 168 | if (!check_prefetch_opcode(regs, instr, opcode, &prefetch)) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 169 | break; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 170 | } | 
|  | 171 | return prefetch; | 
|  | 172 | } | 
|  | 173 |  | 
| Dave Hansen | 019132f | 2016-02-12 13:02:14 -0800 | [diff] [blame] | 174 | /* | 
|  | 175 | * A protection key fault means that the PKRU value did not allow | 
|  | 176 | * access to some PTE.  Userspace can figure out what PKRU was | 
|  | 177 | * from the XSAVE state, and this function fills out a field in | 
|  | 178 | * siginfo so userspace can discover which protection key was set | 
|  | 179 | * on the PTE. | 
|  | 180 | * | 
|  | 181 | * If we get here, we know that the hardware signaled a PF_PK | 
|  | 182 | * fault and that there was a VMA once we got in the fault | 
|  | 183 | * handler.  It does *not* guarantee that the VMA we find here | 
|  | 184 | * was the one that we faulted on. | 
|  | 185 | * | 
|  | 186 | * 1. T1   : mprotect_key(foo, PAGE_SIZE, pkey=4); | 
|  | 187 | * 2. T1   : set PKRU to deny access to pkey=4, touches page | 
|  | 188 | * 3. T1   : faults... | 
|  | 189 | * 4.    T2: mprotect_key(foo, PAGE_SIZE, pkey=5); | 
|  | 190 | * 5. T1   : enters fault handler, takes mmap_sem, etc... | 
|  | 191 | * 6. T1   : reaches here, sees vma_pkey(vma)=5, when we really | 
|  | 192 | *	     faulted on a pte with its pkey=4. | 
|  | 193 | */ | 
| Eric W. Biederman | 5ab44e8 | 2018-01-12 14:31:35 -0600 | [diff] [blame] | 194 | static void fill_sig_info_pkey(int si_signo, int si_code, siginfo_t *info, | 
|  | 195 | u32 *pkey) | 
| Dave Hansen | 019132f | 2016-02-12 13:02:14 -0800 | [diff] [blame] | 196 | { | 
|  | 197 | /* This is effectively an #ifdef */ | 
|  | 198 | if (!boot_cpu_has(X86_FEATURE_OSPKE)) | 
|  | 199 | return; | 
|  | 200 |  | 
|  | 201 | /* Fault not from Protection Keys: nothing to do */ | 
| Eric W. Biederman | 5ab44e8 | 2018-01-12 14:31:35 -0600 | [diff] [blame] | 202 | if ((si_code != SEGV_PKUERR) || (si_signo != SIGSEGV)) | 
| Dave Hansen | 019132f | 2016-02-12 13:02:14 -0800 | [diff] [blame] | 203 | return; | 
|  | 204 | /* | 
|  | 205 | * force_sig_info_fault() is called from a number of | 
|  | 206 | * contexts, some of which have a VMA and some of which | 
|  | 207 | * do not.  The PF_PK handing happens after we have a | 
|  | 208 | * valid VMA, so we should never reach this without a | 
|  | 209 | * valid VMA. | 
|  | 210 | */ | 
| Laurent Dufour | 54af98f | 2017-09-04 10:32:15 +0200 | [diff] [blame] | 211 | if (!pkey) { | 
| Dave Hansen | 019132f | 2016-02-12 13:02:14 -0800 | [diff] [blame] | 212 | WARN_ONCE(1, "PKU fault with no VMA passed in"); | 
|  | 213 | info->si_pkey = 0; | 
|  | 214 | return; | 
|  | 215 | } | 
|  | 216 | /* | 
|  | 217 | * si_pkey should be thought of as a strong hint, but not | 
|  | 218 | * absolutely guranteed to be 100% accurate because of | 
|  | 219 | * the race explained above. | 
|  | 220 | */ | 
| Laurent Dufour | 54af98f | 2017-09-04 10:32:15 +0200 | [diff] [blame] | 221 | info->si_pkey = *pkey; | 
| Dave Hansen | 019132f | 2016-02-12 13:02:14 -0800 | [diff] [blame] | 222 | } | 
|  | 223 |  | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 224 | static void | 
|  | 225 | force_sig_info_fault(int si_signo, int si_code, unsigned long address, | 
| Laurent Dufour | 54af98f | 2017-09-04 10:32:15 +0200 | [diff] [blame] | 226 | struct task_struct *tsk, u32 *pkey, int fault) | 
| Harvey Harrison | c4aba4a | 2008-01-30 13:32:35 +0100 | [diff] [blame] | 227 | { | 
| Andi Kleen | f672b49 | 2010-09-27 22:05:55 +0200 | [diff] [blame] | 228 | unsigned lsb = 0; | 
| Harvey Harrison | c4aba4a | 2008-01-30 13:32:35 +0100 | [diff] [blame] | 229 | siginfo_t info; | 
|  | 230 |  | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 231 | info.si_signo	= si_signo; | 
|  | 232 | info.si_errno	= 0; | 
|  | 233 | info.si_code	= si_code; | 
|  | 234 | info.si_addr	= (void __user *)address; | 
| Andi Kleen | f672b49 | 2010-09-27 22:05:55 +0200 | [diff] [blame] | 235 | if (fault & VM_FAULT_HWPOISON_LARGE) | 
|  | 236 | lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault)); | 
|  | 237 | if (fault & VM_FAULT_HWPOISON) | 
|  | 238 | lsb = PAGE_SHIFT; | 
|  | 239 | info.si_addr_lsb = lsb; | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 240 |  | 
| Eric W. Biederman | 5ab44e8 | 2018-01-12 14:31:35 -0600 | [diff] [blame] | 241 | fill_sig_info_pkey(si_signo, si_code, &info, pkey); | 
| Dave Hansen | 019132f | 2016-02-12 13:02:14 -0800 | [diff] [blame] | 242 |  | 
| Harvey Harrison | c4aba4a | 2008-01-30 13:32:35 +0100 | [diff] [blame] | 243 | force_sig_info(si_signo, &info, tsk); | 
|  | 244 | } | 
|  | 245 |  | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 246 | DEFINE_SPINLOCK(pgd_lock); | 
|  | 247 | LIST_HEAD(pgd_list); | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 248 |  | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 249 | #ifdef CONFIG_X86_32 | 
|  | 250 | static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address) | 
|  | 251 | { | 
|  | 252 | unsigned index = pgd_index(address); | 
|  | 253 | pgd_t *pgd_k; | 
|  | 254 | pud_t *pud, *pud_k; | 
|  | 255 | pmd_t *pmd, *pmd_k; | 
|  | 256 |  | 
|  | 257 | pgd += index; | 
|  | 258 | pgd_k = init_mm.pgd + index; | 
|  | 259 |  | 
|  | 260 | if (!pgd_present(*pgd_k)) | 
|  | 261 | return NULL; | 
|  | 262 |  | 
|  | 263 | /* | 
|  | 264 | * set_pgd(pgd, *pgd_k); here would be useless on PAE | 
|  | 265 | * and redundant with the set_pmd() on non-PAE. As would | 
|  | 266 | * set_pud. | 
|  | 267 | */ | 
|  | 268 | pud = pud_offset(pgd, address); | 
|  | 269 | pud_k = pud_offset(pgd_k, address); | 
|  | 270 | if (!pud_present(*pud_k)) | 
|  | 271 | return NULL; | 
|  | 272 |  | 
|  | 273 | pmd = pmd_offset(pud, address); | 
|  | 274 | pmd_k = pmd_offset(pud_k, address); | 
|  | 275 | if (!pmd_present(*pmd_k)) | 
|  | 276 | return NULL; | 
|  | 277 |  | 
| Jeremy Fitzhardinge | b8bcfe9 | 2009-02-17 23:05:19 -0800 | [diff] [blame] | 278 | if (!pmd_present(*pmd)) | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 279 | set_pmd(pmd, *pmd_k); | 
| Jeremy Fitzhardinge | b8bcfe9 | 2009-02-17 23:05:19 -0800 | [diff] [blame] | 280 | else | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 281 | BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k)); | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 282 |  | 
|  | 283 | return pmd_k; | 
| Harvey Harrison | 33cb524 | 2008-01-30 13:32:19 +0100 | [diff] [blame] | 284 | } | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 285 |  | 
|  | 286 | void vmalloc_sync_all(void) | 
|  | 287 | { | 
|  | 288 | unsigned long address; | 
|  | 289 |  | 
|  | 290 | if (SHARED_KERNEL_PMD) | 
|  | 291 | return; | 
|  | 292 |  | 
|  | 293 | for (address = VMALLOC_START & PMD_MASK; | 
| Andy Lutomirski | dc4fac8 | 2016-05-10 14:10:29 -0700 | [diff] [blame] | 294 | address >= TASK_SIZE_MAX && address < FIXADDR_TOP; | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 295 | address += PMD_SIZE) { | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 296 | struct page *page; | 
|  | 297 |  | 
| Andrea Arcangeli | a79e53d | 2011-02-16 15:45:22 -0800 | [diff] [blame] | 298 | spin_lock(&pgd_lock); | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 299 | list_for_each_entry(page, &pgd_list, lru) { | 
| Jeremy Fitzhardinge | 617d34d | 2010-09-21 12:01:51 -0700 | [diff] [blame] | 300 | spinlock_t *pgt_lock; | 
| Borislav Petkov | f01f7c5 | 2010-10-19 22:17:37 +0000 | [diff] [blame] | 301 | pmd_t *ret; | 
| Jeremy Fitzhardinge | 617d34d | 2010-09-21 12:01:51 -0700 | [diff] [blame] | 302 |  | 
| Andrea Arcangeli | a79e53d | 2011-02-16 15:45:22 -0800 | [diff] [blame] | 303 | /* the pgt_lock only for Xen */ | 
| Jeremy Fitzhardinge | 617d34d | 2010-09-21 12:01:51 -0700 | [diff] [blame] | 304 | pgt_lock = &pgd_page_get_mm(page)->page_table_lock; | 
|  | 305 |  | 
|  | 306 | spin_lock(pgt_lock); | 
|  | 307 | ret = vmalloc_sync_one(page_address(page), address); | 
|  | 308 | spin_unlock(pgt_lock); | 
|  | 309 |  | 
|  | 310 | if (!ret) | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 311 | break; | 
|  | 312 | } | 
| Andrea Arcangeli | a79e53d | 2011-02-16 15:45:22 -0800 | [diff] [blame] | 313 | spin_unlock(&pgd_lock); | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 314 | } | 
|  | 315 | } | 
|  | 316 |  | 
|  | 317 | /* | 
|  | 318 | * 32-bit: | 
|  | 319 | * | 
|  | 320 | *   Handle a fault on the vmalloc or module mapping area | 
|  | 321 | */ | 
| Masami Hiramatsu | 9326638 | 2014-04-17 17:18:14 +0900 | [diff] [blame] | 322 | static noinline int vmalloc_fault(unsigned long address) | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 323 | { | 
|  | 324 | unsigned long pgd_paddr; | 
|  | 325 | pmd_t *pmd_k; | 
|  | 326 | pte_t *pte_k; | 
|  | 327 |  | 
|  | 328 | /* Make sure we are in vmalloc area: */ | 
|  | 329 | if (!(address >= VMALLOC_START && address < VMALLOC_END)) | 
|  | 330 | return -1; | 
|  | 331 |  | 
| Frederic Weisbecker | ebc8827 | 2010-09-27 18:50:51 +0200 | [diff] [blame] | 332 | WARN_ON_ONCE(in_nmi()); | 
|  | 333 |  | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 334 | /* | 
|  | 335 | * Synchronize this task's top level page-table | 
|  | 336 | * with the 'reference' page table. | 
|  | 337 | * | 
|  | 338 | * Do _not_ use "current" here. We might be inside | 
|  | 339 | * an interrupt in the middle of a task switch.. | 
|  | 340 | */ | 
|  | 341 | pgd_paddr = read_cr3(); | 
|  | 342 | pmd_k = vmalloc_sync_one(__va(pgd_paddr), address); | 
|  | 343 | if (!pmd_k) | 
|  | 344 | return -1; | 
|  | 345 |  | 
| Toshi Kani | d3b0e98 | 2018-03-13 11:03:46 -0600 | [diff] [blame] | 346 | if (pmd_large(*pmd_k)) | 
| Toshi Kani | f4eafd8 | 2016-02-17 18:16:54 -0700 | [diff] [blame] | 347 | return 0; | 
|  | 348 |  | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 349 | pte_k = pte_offset_kernel(pmd_k, address); | 
|  | 350 | if (!pte_present(*pte_k)) | 
|  | 351 | return -1; | 
|  | 352 |  | 
|  | 353 | return 0; | 
|  | 354 | } | 
| Masami Hiramatsu | 9326638 | 2014-04-17 17:18:14 +0900 | [diff] [blame] | 355 | NOKPROBE_SYMBOL(vmalloc_fault); | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 356 |  | 
|  | 357 | /* | 
|  | 358 | * Did it hit the DOS screen memory VA from vm86 mode? | 
|  | 359 | */ | 
|  | 360 | static inline void | 
|  | 361 | check_v8086_mode(struct pt_regs *regs, unsigned long address, | 
|  | 362 | struct task_struct *tsk) | 
|  | 363 | { | 
| Brian Gerst | 9fda6a0 | 2015-07-29 01:41:16 -0400 | [diff] [blame] | 364 | #ifdef CONFIG_VM86 | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 365 | unsigned long bit; | 
|  | 366 |  | 
| Brian Gerst | 9fda6a0 | 2015-07-29 01:41:16 -0400 | [diff] [blame] | 367 | if (!v8086_mode(regs) || !tsk->thread.vm86) | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 368 | return; | 
|  | 369 |  | 
|  | 370 | bit = (address - 0xA0000) >> PAGE_SHIFT; | 
|  | 371 | if (bit < 32) | 
| Brian Gerst | 9fda6a0 | 2015-07-29 01:41:16 -0400 | [diff] [blame] | 372 | tsk->thread.vm86->screen_bitmap |= 1 << bit; | 
|  | 373 | #endif | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 374 | } | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 375 |  | 
| Akinobu Mita | 087975b | 2009-06-27 15:35:15 +0900 | [diff] [blame] | 376 | static bool low_pfn(unsigned long pfn) | 
|  | 377 | { | 
|  | 378 | return pfn < max_low_pfn; | 
|  | 379 | } | 
|  | 380 |  | 
| Adrian Bunk | cae30f82 | 2008-02-13 23:31:31 +0200 | [diff] [blame] | 381 | static void dump_pagetable(unsigned long address) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 382 | { | 
| Akinobu Mita | 087975b | 2009-06-27 15:35:15 +0900 | [diff] [blame] | 383 | pgd_t *base = __va(read_cr3()); | 
|  | 384 | pgd_t *pgd = &base[pgd_index(address)]; | 
|  | 385 | pmd_t *pmd; | 
|  | 386 | pte_t *pte; | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 387 |  | 
| Harvey Harrison | 1156e09 | 2008-01-30 13:34:10 +0100 | [diff] [blame] | 388 | #ifdef CONFIG_X86_PAE | 
| Akinobu Mita | 087975b | 2009-06-27 15:35:15 +0900 | [diff] [blame] | 389 | printk("*pdpt = %016Lx ", pgd_val(*pgd)); | 
|  | 390 | if (!low_pfn(pgd_val(*pgd) >> PAGE_SHIFT) || !pgd_present(*pgd)) | 
|  | 391 | goto out; | 
| Harvey Harrison | 1156e09 | 2008-01-30 13:34:10 +0100 | [diff] [blame] | 392 | #endif | 
| Akinobu Mita | 087975b | 2009-06-27 15:35:15 +0900 | [diff] [blame] | 393 | pmd = pmd_offset(pud_offset(pgd, address), address); | 
|  | 394 | printk(KERN_CONT "*pde = %0*Lx ", sizeof(*pmd) * 2, (u64)pmd_val(*pmd)); | 
| Harvey Harrison | 1156e09 | 2008-01-30 13:34:10 +0100 | [diff] [blame] | 395 |  | 
|  | 396 | /* | 
|  | 397 | * We must not directly access the pte in the highpte | 
|  | 398 | * case if the page table is located in highmem. | 
|  | 399 | * And let's rather not kmap-atomic the pte, just in case | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 400 | * it's allocated already: | 
| Harvey Harrison | 1156e09 | 2008-01-30 13:34:10 +0100 | [diff] [blame] | 401 | */ | 
| Akinobu Mita | 087975b | 2009-06-27 15:35:15 +0900 | [diff] [blame] | 402 | if (!low_pfn(pmd_pfn(*pmd)) || !pmd_present(*pmd) || pmd_large(*pmd)) | 
|  | 403 | goto out; | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 404 |  | 
| Akinobu Mita | 087975b | 2009-06-27 15:35:15 +0900 | [diff] [blame] | 405 | pte = pte_offset_kernel(pmd, address); | 
|  | 406 | printk("*pte = %0*Lx ", sizeof(*pte) * 2, (u64)pte_val(*pte)); | 
|  | 407 | out: | 
| Harvey Harrison | 1156e09 | 2008-01-30 13:34:10 +0100 | [diff] [blame] | 408 | printk("\n"); | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 409 | } | 
|  | 410 |  | 
|  | 411 | #else /* CONFIG_X86_64: */ | 
|  | 412 |  | 
|  | 413 | void vmalloc_sync_all(void) | 
|  | 414 | { | 
| Yasuaki Ishimatsu | 9661d5b | 2014-08-22 13:27:34 -0700 | [diff] [blame] | 415 | sync_global_pgds(VMALLOC_START & PGDIR_MASK, VMALLOC_END, 0); | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 416 | } | 
|  | 417 |  | 
|  | 418 | /* | 
|  | 419 | * 64-bit: | 
|  | 420 | * | 
|  | 421 | *   Handle a fault on the vmalloc area | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 422 | */ | 
| Masami Hiramatsu | 9326638 | 2014-04-17 17:18:14 +0900 | [diff] [blame] | 423 | static noinline int vmalloc_fault(unsigned long address) | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 424 | { | 
|  | 425 | pgd_t *pgd, *pgd_ref; | 
|  | 426 | pud_t *pud, *pud_ref; | 
|  | 427 | pmd_t *pmd, *pmd_ref; | 
|  | 428 | pte_t *pte, *pte_ref; | 
|  | 429 |  | 
|  | 430 | /* Make sure we are in vmalloc area: */ | 
|  | 431 | if (!(address >= VMALLOC_START && address < VMALLOC_END)) | 
|  | 432 | return -1; | 
|  | 433 |  | 
| Frederic Weisbecker | ebc8827 | 2010-09-27 18:50:51 +0200 | [diff] [blame] | 434 | WARN_ON_ONCE(in_nmi()); | 
|  | 435 |  | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 436 | /* | 
|  | 437 | * Copy kernel mappings over when needed. This can also | 
|  | 438 | * happen within a race in page table update. In the later | 
|  | 439 | * case just flush: | 
|  | 440 | */ | 
| Andy Lutomirski | 46aea38 | 2016-07-14 13:22:54 -0700 | [diff] [blame] | 441 | pgd = (pgd_t *)__va(read_cr3()) + pgd_index(address); | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 442 | pgd_ref = pgd_offset_k(address); | 
|  | 443 | if (pgd_none(*pgd_ref)) | 
|  | 444 | return -1; | 
|  | 445 |  | 
| Samu Kallio | 1160c27 | 2013-03-23 09:36:35 -0400 | [diff] [blame] | 446 | if (pgd_none(*pgd)) { | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 447 | set_pgd(pgd, *pgd_ref); | 
| Samu Kallio | 1160c27 | 2013-03-23 09:36:35 -0400 | [diff] [blame] | 448 | arch_flush_lazy_mmu_mode(); | 
|  | 449 | } else { | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 450 | BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref)); | 
| Samu Kallio | 1160c27 | 2013-03-23 09:36:35 -0400 | [diff] [blame] | 451 | } | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 452 |  | 
|  | 453 | /* | 
|  | 454 | * Below here mismatches are bugs because these lower tables | 
|  | 455 | * are shared: | 
|  | 456 | */ | 
|  | 457 |  | 
|  | 458 | pud = pud_offset(pgd, address); | 
|  | 459 | pud_ref = pud_offset(pgd_ref, address); | 
|  | 460 | if (pud_none(*pud_ref)) | 
|  | 461 | return -1; | 
|  | 462 |  | 
| Toshi Kani | f4eafd8 | 2016-02-17 18:16:54 -0700 | [diff] [blame] | 463 | if (pud_none(*pud) || pud_pfn(*pud) != pud_pfn(*pud_ref)) | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 464 | BUG(); | 
|  | 465 |  | 
| Toshi Kani | d3b0e98 | 2018-03-13 11:03:46 -0600 | [diff] [blame] | 466 | if (pud_large(*pud)) | 
| Toshi Kani | f4eafd8 | 2016-02-17 18:16:54 -0700 | [diff] [blame] | 467 | return 0; | 
|  | 468 |  | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 469 | pmd = pmd_offset(pud, address); | 
|  | 470 | pmd_ref = pmd_offset(pud_ref, address); | 
|  | 471 | if (pmd_none(*pmd_ref)) | 
|  | 472 | return -1; | 
|  | 473 |  | 
| Toshi Kani | f4eafd8 | 2016-02-17 18:16:54 -0700 | [diff] [blame] | 474 | if (pmd_none(*pmd) || pmd_pfn(*pmd) != pmd_pfn(*pmd_ref)) | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 475 | BUG(); | 
|  | 476 |  | 
| Toshi Kani | d3b0e98 | 2018-03-13 11:03:46 -0600 | [diff] [blame] | 477 | if (pmd_large(*pmd)) | 
| Toshi Kani | f4eafd8 | 2016-02-17 18:16:54 -0700 | [diff] [blame] | 478 | return 0; | 
|  | 479 |  | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 480 | pte_ref = pte_offset_kernel(pmd_ref, address); | 
|  | 481 | if (!pte_present(*pte_ref)) | 
|  | 482 | return -1; | 
|  | 483 |  | 
|  | 484 | pte = pte_offset_kernel(pmd, address); | 
|  | 485 |  | 
|  | 486 | /* | 
|  | 487 | * Don't use pte_page here, because the mappings can point | 
|  | 488 | * outside mem_map, and the NUMA hash lookup cannot handle | 
|  | 489 | * that: | 
|  | 490 | */ | 
|  | 491 | if (!pte_present(*pte) || pte_pfn(*pte) != pte_pfn(*pte_ref)) | 
|  | 492 | BUG(); | 
|  | 493 |  | 
|  | 494 | return 0; | 
|  | 495 | } | 
| Masami Hiramatsu | 9326638 | 2014-04-17 17:18:14 +0900 | [diff] [blame] | 496 | NOKPROBE_SYMBOL(vmalloc_fault); | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 497 |  | 
| Jan Beulich | e05139f | 2011-09-28 16:56:51 +0100 | [diff] [blame] | 498 | #ifdef CONFIG_CPU_SUP_AMD | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 499 | static const char errata93_warning[] = | 
| Joe Perches | ad361c9 | 2009-07-06 13:05:40 -0700 | [diff] [blame] | 500 | KERN_ERR | 
|  | 501 | "******* Your BIOS seems to not contain a fix for K8 errata #93\n" | 
|  | 502 | "******* Working around it, but it may cause SEGVs or burn power.\n" | 
|  | 503 | "******* Please consider a BIOS update.\n" | 
|  | 504 | "******* Disabling USB legacy in the BIOS may also help.\n"; | 
| Jan Beulich | e05139f | 2011-09-28 16:56:51 +0100 | [diff] [blame] | 505 | #endif | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 506 |  | 
|  | 507 | /* | 
|  | 508 | * No vm86 mode in 64-bit mode: | 
|  | 509 | */ | 
|  | 510 | static inline void | 
|  | 511 | check_v8086_mode(struct pt_regs *regs, unsigned long address, | 
|  | 512 | struct task_struct *tsk) | 
|  | 513 | { | 
|  | 514 | } | 
|  | 515 |  | 
|  | 516 | static int bad_address(void *p) | 
|  | 517 | { | 
|  | 518 | unsigned long dummy; | 
|  | 519 |  | 
|  | 520 | return probe_kernel_address((unsigned long *)p, dummy); | 
|  | 521 | } | 
|  | 522 |  | 
|  | 523 | static void dump_pagetable(unsigned long address) | 
|  | 524 | { | 
| Akinobu Mita | 087975b | 2009-06-27 15:35:15 +0900 | [diff] [blame] | 525 | pgd_t *base = __va(read_cr3() & PHYSICAL_PAGE_MASK); | 
|  | 526 | pgd_t *pgd = base + pgd_index(address); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 527 | pud_t *pud; | 
|  | 528 | pmd_t *pmd; | 
|  | 529 | pte_t *pte; | 
|  | 530 |  | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 531 | if (bad_address(pgd)) | 
|  | 532 | goto bad; | 
|  | 533 |  | 
| Jan Beulich | d646bce | 2006-02-03 21:51:47 +0100 | [diff] [blame] | 534 | printk("PGD %lx ", pgd_val(*pgd)); | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 535 |  | 
|  | 536 | if (!pgd_present(*pgd)) | 
|  | 537 | goto out; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 538 |  | 
| Andi Kleen | d2ae5b5 | 2006-06-26 13:57:56 +0200 | [diff] [blame] | 539 | pud = pud_offset(pgd, address); | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 540 | if (bad_address(pud)) | 
|  | 541 | goto bad; | 
|  | 542 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 543 | printk("PUD %lx ", pud_val(*pud)); | 
| Andi Kleen | b536022 | 2008-02-04 16:48:09 +0100 | [diff] [blame] | 544 | if (!pud_present(*pud) || pud_large(*pud)) | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 545 | goto out; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 546 |  | 
|  | 547 | pmd = pmd_offset(pud, address); | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 548 | if (bad_address(pmd)) | 
|  | 549 | goto bad; | 
|  | 550 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 551 | printk("PMD %lx ", pmd_val(*pmd)); | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 552 | if (!pmd_present(*pmd) || pmd_large(*pmd)) | 
|  | 553 | goto out; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 554 |  | 
|  | 555 | pte = pte_offset_kernel(pmd, address); | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 556 | if (bad_address(pte)) | 
|  | 557 | goto bad; | 
|  | 558 |  | 
| Harvey Harrison | 33cb524 | 2008-01-30 13:32:19 +0100 | [diff] [blame] | 559 | printk("PTE %lx", pte_val(*pte)); | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 560 | out: | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 561 | printk("\n"); | 
|  | 562 | return; | 
|  | 563 | bad: | 
|  | 564 | printk("BAD\n"); | 
|  | 565 | } | 
|  | 566 |  | 
| Ingo Molnar | f2f13a8 | 2009-02-20 22:50:24 +0100 | [diff] [blame] | 567 | #endif /* CONFIG_X86_64 */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 568 |  | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 569 | /* | 
|  | 570 | * Workaround for K8 erratum #93 & buggy BIOS. | 
|  | 571 | * | 
|  | 572 | * BIOS SMM functions are required to use a specific workaround | 
|  | 573 | * to avoid corruption of the 64bit RIP register on C stepping K8. | 
|  | 574 | * | 
|  | 575 | * A lot of BIOS that didn't get tested properly miss this. | 
|  | 576 | * | 
|  | 577 | * The OS sees this as a page fault with the upper 32bits of RIP cleared. | 
|  | 578 | * Try to work around it here. | 
|  | 579 | * | 
|  | 580 | * Note we only handle faults in kernel here. | 
|  | 581 | * Does nothing on 32-bit. | 
| Harvey Harrison | fdfe8aa | 2008-01-30 13:33:13 +0100 | [diff] [blame] | 582 | */ | 
| Harvey Harrison | 33cb524 | 2008-01-30 13:32:19 +0100 | [diff] [blame] | 583 | static int is_errata93(struct pt_regs *regs, unsigned long address) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 584 | { | 
| Jan Beulich | e05139f | 2011-09-28 16:56:51 +0100 | [diff] [blame] | 585 | #if defined(CONFIG_X86_64) && defined(CONFIG_CPU_SUP_AMD) | 
|  | 586 | if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD | 
|  | 587 | || boot_cpu_data.x86 != 0xf) | 
|  | 588 | return 0; | 
|  | 589 |  | 
| H. Peter Anvin | 65ea5b0 | 2008-01-30 13:30:56 +0100 | [diff] [blame] | 590 | if (address != regs->ip) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 591 | return 0; | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 592 |  | 
| Harvey Harrison | 33cb524 | 2008-01-30 13:32:19 +0100 | [diff] [blame] | 593 | if ((address >> 32) != 0) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 594 | return 0; | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 595 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 596 | address |= 0xffffffffUL << 32; | 
| Harvey Harrison | 33cb524 | 2008-01-30 13:32:19 +0100 | [diff] [blame] | 597 | if ((address >= (u64)_stext && address <= (u64)_etext) || | 
|  | 598 | (address >= MODULES_VADDR && address <= MODULES_END)) { | 
| Ingo Molnar | a454ab3 | 2009-05-03 10:09:03 +0200 | [diff] [blame] | 599 | printk_once(errata93_warning); | 
| H. Peter Anvin | 65ea5b0 | 2008-01-30 13:30:56 +0100 | [diff] [blame] | 600 | regs->ip = address; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 601 | return 1; | 
|  | 602 | } | 
| Harvey Harrison | fdfe8aa | 2008-01-30 13:33:13 +0100 | [diff] [blame] | 603 | #endif | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 604 | return 0; | 
| Harvey Harrison | 33cb524 | 2008-01-30 13:32:19 +0100 | [diff] [blame] | 605 | } | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 606 |  | 
| Harvey Harrison | 35f3266 | 2008-01-30 13:34:09 +0100 | [diff] [blame] | 607 | /* | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 608 | * Work around K8 erratum #100 K8 in compat mode occasionally jumps | 
|  | 609 | * to illegal addresses >4GB. | 
|  | 610 | * | 
|  | 611 | * We catch this in the page fault handler because these addresses | 
|  | 612 | * are not reachable. Just detect this case and return.  Any code | 
| Harvey Harrison | 35f3266 | 2008-01-30 13:34:09 +0100 | [diff] [blame] | 613 | * segment in LDT is compatibility mode. | 
|  | 614 | */ | 
|  | 615 | static int is_errata100(struct pt_regs *regs, unsigned long address) | 
|  | 616 | { | 
|  | 617 | #ifdef CONFIG_X86_64 | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 618 | if ((regs->cs == __USER32_CS || (regs->cs & (1<<2))) && (address >> 32)) | 
| Harvey Harrison | 35f3266 | 2008-01-30 13:34:09 +0100 | [diff] [blame] | 619 | return 1; | 
|  | 620 | #endif | 
|  | 621 | return 0; | 
|  | 622 | } | 
|  | 623 |  | 
| Harvey Harrison | 29caf2f | 2008-01-30 13:34:09 +0100 | [diff] [blame] | 624 | static int is_f00f_bug(struct pt_regs *regs, unsigned long address) | 
|  | 625 | { | 
|  | 626 | #ifdef CONFIG_X86_F00F_BUG | 
|  | 627 | unsigned long nr; | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 628 |  | 
| Harvey Harrison | 29caf2f | 2008-01-30 13:34:09 +0100 | [diff] [blame] | 629 | /* | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 630 | * Pentium F0 0F C7 C8 bug workaround: | 
| Harvey Harrison | 29caf2f | 2008-01-30 13:34:09 +0100 | [diff] [blame] | 631 | */ | 
| Borislav Petkov | e2604b4 | 2013-03-20 15:07:24 +0100 | [diff] [blame] | 632 | if (boot_cpu_has_bug(X86_BUG_F00F)) { | 
| Harvey Harrison | 29caf2f | 2008-01-30 13:34:09 +0100 | [diff] [blame] | 633 | nr = (address - idt_descr.address) >> 3; | 
|  | 634 |  | 
|  | 635 | if (nr == 6) { | 
|  | 636 | do_invalid_op(regs, 0); | 
|  | 637 | return 1; | 
|  | 638 | } | 
|  | 639 | } | 
|  | 640 | #endif | 
|  | 641 | return 0; | 
|  | 642 | } | 
|  | 643 |  | 
| Ingo Molnar | 8f76614 | 2009-02-20 23:00:29 +0100 | [diff] [blame] | 644 | static const char nx_warning[] = KERN_CRIT | 
|  | 645 | "kernel tried to execute NX-protected page - exploit attempt? (uid: %d)\n"; | 
| Jiri Kosina | eff50c3 | 2014-06-10 22:49:31 +0200 | [diff] [blame] | 646 | static const char smep_warning[] = KERN_CRIT | 
|  | 647 | "unable to execute userspace code (SMEP?) (uid: %d)\n"; | 
| Ingo Molnar | 8f76614 | 2009-02-20 23:00:29 +0100 | [diff] [blame] | 648 |  | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 649 | static void | 
|  | 650 | show_fault_oops(struct pt_regs *regs, unsigned long error_code, | 
|  | 651 | unsigned long address) | 
| Harvey Harrison | b3279c7 | 2008-01-30 13:34:10 +0100 | [diff] [blame] | 652 | { | 
| Harvey Harrison | 1156e09 | 2008-01-30 13:34:10 +0100 | [diff] [blame] | 653 | if (!oops_may_print()) | 
|  | 654 | return; | 
|  | 655 |  | 
| Harvey Harrison | 1156e09 | 2008-01-30 13:34:10 +0100 | [diff] [blame] | 656 | if (error_code & PF_INSTR) { | 
| Harvey Harrison | 93809be | 2008-02-01 17:49:43 +0100 | [diff] [blame] | 657 | unsigned int level; | 
| Matt Fleming | 426e34c | 2013-12-06 21:13:04 +0000 | [diff] [blame] | 658 | pgd_t *pgd; | 
|  | 659 | pte_t *pte; | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 660 |  | 
| Matt Fleming | 426e34c | 2013-12-06 21:13:04 +0000 | [diff] [blame] | 661 | pgd = __va(read_cr3() & PHYSICAL_PAGE_MASK); | 
|  | 662 | pgd += pgd_index(address); | 
|  | 663 |  | 
|  | 664 | pte = lookup_address_in_pgd(pgd, address, &level); | 
| Harvey Harrison | 1156e09 | 2008-01-30 13:34:10 +0100 | [diff] [blame] | 665 |  | 
| Ingo Molnar | 8f76614 | 2009-02-20 23:00:29 +0100 | [diff] [blame] | 666 | if (pte && pte_present(*pte) && !pte_exec(*pte)) | 
| Eric W. Biederman | 078de5f | 2012-02-08 07:00:08 -0800 | [diff] [blame] | 667 | printk(nx_warning, from_kuid(&init_user_ns, current_uid())); | 
| Jiri Kosina | eff50c3 | 2014-06-10 22:49:31 +0200 | [diff] [blame] | 668 | if (pte && pte_present(*pte) && pte_exec(*pte) && | 
|  | 669 | (pgd_flags(*pgd) & _PAGE_USER) && | 
| Andy Lutomirski | 1e02ce4 | 2014-10-24 15:58:08 -0700 | [diff] [blame] | 670 | (__read_cr4() & X86_CR4_SMEP)) | 
| Jiri Kosina | eff50c3 | 2014-06-10 22:49:31 +0200 | [diff] [blame] | 671 | printk(smep_warning, from_kuid(&init_user_ns, current_uid())); | 
| Harvey Harrison | 1156e09 | 2008-01-30 13:34:10 +0100 | [diff] [blame] | 672 | } | 
| Harvey Harrison | fd40d6e | 2008-01-30 13:34:11 +0100 | [diff] [blame] | 673 |  | 
| Harvey Harrison | 1156e09 | 2008-01-30 13:34:10 +0100 | [diff] [blame] | 674 | printk(KERN_ALERT "BUG: unable to handle kernel "); | 
|  | 675 | if (address < PAGE_SIZE) | 
|  | 676 | printk(KERN_CONT "NULL pointer dereference"); | 
|  | 677 | else | 
|  | 678 | printk(KERN_CONT "paging request"); | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 679 |  | 
| Vegard Nossum | f294a8c | 2008-07-01 15:38:13 +0200 | [diff] [blame] | 680 | printk(KERN_CONT " at %p\n", (void *) address); | 
| Harvey Harrison | 19f0dda | 2008-01-30 13:34:10 +0100 | [diff] [blame] | 681 | printk(KERN_ALERT "IP:"); | 
| Jiri Slaby | 5f01c98 | 2013-10-25 15:06:58 +0200 | [diff] [blame] | 682 | printk_address(regs->ip); | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 683 |  | 
| Harvey Harrison | b3279c7 | 2008-01-30 13:34:10 +0100 | [diff] [blame] | 684 | dump_pagetable(address); | 
|  | 685 | } | 
|  | 686 |  | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 687 | static noinline void | 
|  | 688 | pgtable_bad(struct pt_regs *regs, unsigned long error_code, | 
|  | 689 | unsigned long address) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 690 | { | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 691 | struct task_struct *tsk; | 
|  | 692 | unsigned long flags; | 
|  | 693 | int sig; | 
|  | 694 |  | 
|  | 695 | flags = oops_begin(); | 
|  | 696 | tsk = current; | 
|  | 697 | sig = SIGKILL; | 
| Jan Beulich | 1209140 | 2005-09-12 18:49:24 +0200 | [diff] [blame] | 698 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 699 | printk(KERN_ALERT "%s: Corrupted page table at address %lx\n", | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 700 | tsk->comm, address); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 701 | dump_pagetable(address); | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 702 |  | 
|  | 703 | tsk->thread.cr2		= address; | 
| Srikar Dronamraju | 51e7dc7 | 2012-03-12 14:55:55 +0530 | [diff] [blame] | 704 | tsk->thread.trap_nr	= X86_TRAP_PF; | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 705 | tsk->thread.error_code	= error_code; | 
|  | 706 |  | 
| Jan Beulich | 22f5991 | 2008-01-30 13:31:23 +0100 | [diff] [blame] | 707 | if (__die("Bad pagetable", regs, error_code)) | 
| Alexander van Heukelum | 874d93d | 2008-10-22 12:00:09 +0200 | [diff] [blame] | 708 | sig = 0; | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 709 |  | 
| Alexander van Heukelum | 874d93d | 2008-10-22 12:00:09 +0200 | [diff] [blame] | 710 | oops_end(flags, regs, sig); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 711 | } | 
|  | 712 |  | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 713 | static noinline void | 
|  | 714 | no_context(struct pt_regs *regs, unsigned long error_code, | 
| Andy Lutomirski | 4fc3490 | 2011-11-07 16:33:40 -0800 | [diff] [blame] | 715 | unsigned long address, int signal, int si_code) | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 716 | { | 
|  | 717 | struct task_struct *tsk = current; | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 718 | unsigned long flags; | 
|  | 719 | int sig; | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 720 |  | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 721 | /* Are we prepared to handle this kernel fault? */ | 
| Tony Luck | 548acf1 | 2016-02-17 10:20:12 -0800 | [diff] [blame] | 722 | if (fixup_exception(regs, X86_TRAP_PF)) { | 
| Peter Zijlstra | c026b35 | 2014-01-10 21:06:03 +0100 | [diff] [blame] | 723 | /* | 
|  | 724 | * Any interrupt that takes a fault gets the fixup. This makes | 
|  | 725 | * the below recursive fault logic only apply to a faults from | 
|  | 726 | * task context. | 
|  | 727 | */ | 
|  | 728 | if (in_interrupt()) | 
|  | 729 | return; | 
|  | 730 |  | 
|  | 731 | /* | 
|  | 732 | * Per the above we're !in_interrupt(), aka. task context. | 
|  | 733 | * | 
|  | 734 | * In this case we need to make sure we're not recursively | 
|  | 735 | * faulting through the emulate_vsyscall() logic. | 
|  | 736 | */ | 
| Ingo Molnar | 2a53ccb | 2016-07-15 10:21:11 +0200 | [diff] [blame] | 737 | if (current->thread.sig_on_uaccess_err && signal) { | 
| Srikar Dronamraju | 51e7dc7 | 2012-03-12 14:55:55 +0530 | [diff] [blame] | 738 | tsk->thread.trap_nr = X86_TRAP_PF; | 
| Andy Lutomirski | 4fc3490 | 2011-11-07 16:33:40 -0800 | [diff] [blame] | 739 | tsk->thread.error_code = error_code | PF_USER; | 
|  | 740 | tsk->thread.cr2 = address; | 
|  | 741 |  | 
|  | 742 | /* XXX: hwpoison faults will set the wrong code. */ | 
| Dave Hansen | 7b2d0db | 2016-02-12 13:02:11 -0800 | [diff] [blame] | 743 | force_sig_info_fault(signal, si_code, address, | 
| Laurent Dufour | 54af98f | 2017-09-04 10:32:15 +0200 | [diff] [blame] | 744 | tsk, NULL, 0); | 
| Andy Lutomirski | 4fc3490 | 2011-11-07 16:33:40 -0800 | [diff] [blame] | 745 | } | 
| Peter Zijlstra | c026b35 | 2014-01-10 21:06:03 +0100 | [diff] [blame] | 746 |  | 
|  | 747 | /* | 
|  | 748 | * Barring that, we can do the fixup and be happy. | 
|  | 749 | */ | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 750 | return; | 
| Andy Lutomirski | 4fc3490 | 2011-11-07 16:33:40 -0800 | [diff] [blame] | 751 | } | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 752 |  | 
| Andy Lutomirski | 6271cfd | 2016-08-30 17:27:57 -0700 | [diff] [blame] | 753 | #ifdef CONFIG_VMAP_STACK | 
|  | 754 | /* | 
|  | 755 | * Stack overflow?  During boot, we can fault near the initial | 
|  | 756 | * stack in the direct map, but that's not an overflow -- check | 
|  | 757 | * that we're in vmalloc space to avoid this. | 
|  | 758 | */ | 
|  | 759 | if (is_vmalloc_addr((void *)address) && | 
|  | 760 | (((unsigned long)tsk->stack - 1 - address < PAGE_SIZE) || | 
|  | 761 | address - ((unsigned long)tsk->stack + THREAD_SIZE) < PAGE_SIZE)) { | 
|  | 762 | register void *__sp asm("rsp"); | 
|  | 763 | unsigned long stack = this_cpu_read(orig_ist.ist[DOUBLEFAULT_STACK]) - sizeof(void *); | 
|  | 764 | /* | 
|  | 765 | * We're likely to be running with very little stack space | 
|  | 766 | * left.  It's plausible that we'd hit this condition but | 
|  | 767 | * double-fault even before we get this far, in which case | 
|  | 768 | * we're fine: the double-fault handler will deal with it. | 
|  | 769 | * | 
|  | 770 | * We don't want to make it all the way into the oops code | 
|  | 771 | * and then double-fault, though, because we're likely to | 
|  | 772 | * break the console driver and lose most of the stack dump. | 
|  | 773 | */ | 
|  | 774 | asm volatile ("movq %[stack], %%rsp\n\t" | 
|  | 775 | "call handle_stack_overflow\n\t" | 
|  | 776 | "1: jmp 1b" | 
|  | 777 | : "+r" (__sp) | 
|  | 778 | : "D" ("kernel stack overflow (page fault)"), | 
|  | 779 | "S" (regs), "d" (address), | 
|  | 780 | [stack] "rm" (stack)); | 
|  | 781 | unreachable(); | 
|  | 782 | } | 
|  | 783 | #endif | 
|  | 784 |  | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 785 | /* | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 786 | * 32-bit: | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 787 | * | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 788 | *   Valid to do another page fault here, because if this fault | 
|  | 789 | *   had been triggered by is_prefetch fixup_exception would have | 
|  | 790 | *   handled it. | 
|  | 791 | * | 
|  | 792 | * 64-bit: | 
|  | 793 | * | 
|  | 794 | *   Hall of shame of CPU/BIOS bugs. | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 795 | */ | 
|  | 796 | if (is_prefetch(regs, error_code, address)) | 
|  | 797 | return; | 
|  | 798 |  | 
|  | 799 | if (is_errata93(regs, address)) | 
|  | 800 | return; | 
|  | 801 |  | 
|  | 802 | /* | 
|  | 803 | * Oops. The kernel tried to access some bad page. We'll have to | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 804 | * terminate things with extreme prejudice: | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 805 | */ | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 806 | flags = oops_begin(); | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 807 |  | 
|  | 808 | show_fault_oops(regs, error_code, address); | 
|  | 809 |  | 
| Aaron Tomlin | a70857e | 2014-09-12 14:16:18 +0100 | [diff] [blame] | 810 | if (task_stack_end_corrupted(tsk)) | 
| Prarit Bhargava | b0f4c4b | 2012-01-26 08:55:34 -0500 | [diff] [blame] | 811 | printk(KERN_EMERG "Thread overran stack, or stack corrupted\n"); | 
| Ingo Molnar | 1980307 | 2009-01-21 10:39:51 +0100 | [diff] [blame] | 812 |  | 
| Ingo Molnar | 1cc9954 | 2009-02-20 23:07:48 +0100 | [diff] [blame] | 813 | tsk->thread.cr2		= address; | 
| Srikar Dronamraju | 51e7dc7 | 2012-03-12 14:55:55 +0530 | [diff] [blame] | 814 | tsk->thread.trap_nr	= X86_TRAP_PF; | 
| Ingo Molnar | 1cc9954 | 2009-02-20 23:07:48 +0100 | [diff] [blame] | 815 | tsk->thread.error_code	= error_code; | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 816 |  | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 817 | sig = SIGKILL; | 
|  | 818 | if (__die("Oops", regs, error_code)) | 
|  | 819 | sig = 0; | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 820 |  | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 821 | /* Executive summary in case the body of the oops scrolled away */ | 
| Prarit Bhargava | b0f4c4b | 2012-01-26 08:55:34 -0500 | [diff] [blame] | 822 | printk(KERN_DEFAULT "CR2: %016lx\n", address); | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 823 |  | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 824 | oops_end(flags, regs, sig); | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 825 | } | 
|  | 826 |  | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 827 | /* | 
|  | 828 | * Print out info about fatal segfaults, if the show_unhandled_signals | 
|  | 829 | * sysctl is set: | 
|  | 830 | */ | 
|  | 831 | static inline void | 
|  | 832 | show_signal_msg(struct pt_regs *regs, unsigned long error_code, | 
|  | 833 | unsigned long address, struct task_struct *tsk) | 
|  | 834 | { | 
|  | 835 | if (!unhandled_signal(tsk, SIGSEGV)) | 
|  | 836 | return; | 
|  | 837 |  | 
|  | 838 | if (!printk_ratelimit()) | 
|  | 839 | return; | 
|  | 840 |  | 
| Roland Dreier | a1a08d1 | 2009-07-11 00:10:04 -0700 | [diff] [blame] | 841 | printk("%s%s[%d]: segfault at %lx ip %p sp %p error %lx", | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 842 | task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG, | 
|  | 843 | tsk->comm, task_pid_nr(tsk), address, | 
|  | 844 | (void *)regs->ip, (void *)regs->sp, error_code); | 
|  | 845 |  | 
|  | 846 | print_vma_addr(KERN_CONT " in ", regs->ip); | 
|  | 847 |  | 
|  | 848 | printk(KERN_CONT "\n"); | 
|  | 849 | } | 
|  | 850 |  | 
|  | 851 | static void | 
|  | 852 | __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code, | 
| Laurent Dufour | 54af98f | 2017-09-04 10:32:15 +0200 | [diff] [blame] | 853 | unsigned long address, u32 *pkey, int si_code) | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 854 | { | 
|  | 855 | struct task_struct *tsk = current; | 
|  | 856 |  | 
|  | 857 | /* User mode accesses just cause a SIGSEGV */ | 
|  | 858 | if (error_code & PF_USER) { | 
|  | 859 | /* | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 860 | * It's possible to have interrupts off here: | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 861 | */ | 
|  | 862 | local_irq_enable(); | 
|  | 863 |  | 
|  | 864 | /* | 
|  | 865 | * Valid to do another page fault here because this one came | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 866 | * from user space: | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 867 | */ | 
|  | 868 | if (is_prefetch(regs, error_code, address)) | 
|  | 869 | return; | 
|  | 870 |  | 
|  | 871 | if (is_errata100(regs, address)) | 
|  | 872 | return; | 
|  | 873 |  | 
| Andy Lutomirski | 3ae3665 | 2011-08-10 11:15:32 -0400 | [diff] [blame] | 874 | #ifdef CONFIG_X86_64 | 
|  | 875 | /* | 
|  | 876 | * Instruction fetch faults in the vsyscall page might need | 
|  | 877 | * emulation. | 
|  | 878 | */ | 
|  | 879 | if (unlikely((error_code & PF_INSTR) && | 
| Andy Lutomirski | f40c330 | 2014-05-05 12:19:36 -0700 | [diff] [blame] | 880 | ((address & ~0xfff) == VSYSCALL_ADDR))) { | 
| Andy Lutomirski | 3ae3665 | 2011-08-10 11:15:32 -0400 | [diff] [blame] | 881 | if (emulate_vsyscall(regs, address)) | 
|  | 882 | return; | 
|  | 883 | } | 
|  | 884 | #endif | 
| Andy Lutomirski | dc4fac8 | 2016-05-10 14:10:29 -0700 | [diff] [blame] | 885 |  | 
|  | 886 | /* | 
|  | 887 | * To avoid leaking information about the kernel page table | 
|  | 888 | * layout, pretend that user-mode accesses to kernel addresses | 
|  | 889 | * are always protection faults. | 
|  | 890 | */ | 
|  | 891 | if (address >= TASK_SIZE_MAX) | 
| Kees Cook | e575a86 | 2013-02-07 09:44:13 -0800 | [diff] [blame] | 892 | error_code |= PF_PROT; | 
| Andy Lutomirski | 3ae3665 | 2011-08-10 11:15:32 -0400 | [diff] [blame] | 893 |  | 
| Kees Cook | e575a86 | 2013-02-07 09:44:13 -0800 | [diff] [blame] | 894 | if (likely(show_unhandled_signals)) | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 895 | show_signal_msg(regs, error_code, address, tsk); | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 896 |  | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 897 | tsk->thread.cr2		= address; | 
| Kees Cook | e575a86 | 2013-02-07 09:44:13 -0800 | [diff] [blame] | 898 | tsk->thread.error_code	= error_code; | 
| Srikar Dronamraju | 51e7dc7 | 2012-03-12 14:55:55 +0530 | [diff] [blame] | 899 | tsk->thread.trap_nr	= X86_TRAP_PF; | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 900 |  | 
| Laurent Dufour | 54af98f | 2017-09-04 10:32:15 +0200 | [diff] [blame] | 901 | force_sig_info_fault(SIGSEGV, si_code, address, tsk, pkey, 0); | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 902 |  | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 903 | return; | 
|  | 904 | } | 
|  | 905 |  | 
|  | 906 | if (is_f00f_bug(regs, address)) | 
|  | 907 | return; | 
|  | 908 |  | 
| Andy Lutomirski | 4fc3490 | 2011-11-07 16:33:40 -0800 | [diff] [blame] | 909 | no_context(regs, error_code, address, SIGSEGV, si_code); | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 910 | } | 
|  | 911 |  | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 912 | static noinline void | 
|  | 913 | bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code, | 
| Laurent Dufour | 54af98f | 2017-09-04 10:32:15 +0200 | [diff] [blame] | 914 | unsigned long address, u32 *pkey) | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 915 | { | 
| Laurent Dufour | 54af98f | 2017-09-04 10:32:15 +0200 | [diff] [blame] | 916 | __bad_area_nosemaphore(regs, error_code, address, pkey, SEGV_MAPERR); | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 917 | } | 
|  | 918 |  | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 919 | static void | 
|  | 920 | __bad_area(struct pt_regs *regs, unsigned long error_code, | 
| Dave Hansen | 7b2d0db | 2016-02-12 13:02:11 -0800 | [diff] [blame] | 921 | unsigned long address,  struct vm_area_struct *vma, int si_code) | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 922 | { | 
|  | 923 | struct mm_struct *mm = current->mm; | 
| Laurent Dufour | 54af98f | 2017-09-04 10:32:15 +0200 | [diff] [blame] | 924 | u32 pkey; | 
|  | 925 |  | 
|  | 926 | if (vma) | 
|  | 927 | pkey = vma_pkey(vma); | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 928 |  | 
|  | 929 | /* | 
|  | 930 | * Something tried to access memory that isn't in our memory map.. | 
|  | 931 | * Fix it, but check if it's kernel or user first.. | 
|  | 932 | */ | 
|  | 933 | up_read(&mm->mmap_sem); | 
|  | 934 |  | 
| Laurent Dufour | 54af98f | 2017-09-04 10:32:15 +0200 | [diff] [blame] | 935 | __bad_area_nosemaphore(regs, error_code, address, | 
|  | 936 | (vma) ? &pkey : NULL, si_code); | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 937 | } | 
|  | 938 |  | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 939 | static noinline void | 
|  | 940 | bad_area(struct pt_regs *regs, unsigned long error_code, unsigned long address) | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 941 | { | 
| Dave Hansen | 7b2d0db | 2016-02-12 13:02:11 -0800 | [diff] [blame] | 942 | __bad_area(regs, error_code, address, NULL, SEGV_MAPERR); | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 943 | } | 
|  | 944 |  | 
| Dave Hansen | 33a709b | 2016-02-12 13:02:19 -0800 | [diff] [blame] | 945 | static inline bool bad_area_access_from_pkeys(unsigned long error_code, | 
|  | 946 | struct vm_area_struct *vma) | 
|  | 947 | { | 
| Dave Hansen | 07f146f | 2016-02-12 13:02:22 -0800 | [diff] [blame] | 948 | /* This code is always called on the current mm */ | 
|  | 949 | bool foreign = false; | 
|  | 950 |  | 
| Dave Hansen | 33a709b | 2016-02-12 13:02:19 -0800 | [diff] [blame] | 951 | if (!boot_cpu_has(X86_FEATURE_OSPKE)) | 
|  | 952 | return false; | 
|  | 953 | if (error_code & PF_PK) | 
|  | 954 | return true; | 
| Dave Hansen | 07f146f | 2016-02-12 13:02:22 -0800 | [diff] [blame] | 955 | /* this checks permission keys on the VMA: */ | 
| Dave Hansen | d61172b | 2016-02-12 13:02:24 -0800 | [diff] [blame] | 956 | if (!arch_vma_access_permitted(vma, (error_code & PF_WRITE), | 
|  | 957 | (error_code & PF_INSTR), foreign)) | 
| Dave Hansen | 07f146f | 2016-02-12 13:02:22 -0800 | [diff] [blame] | 958 | return true; | 
| Dave Hansen | 33a709b | 2016-02-12 13:02:19 -0800 | [diff] [blame] | 959 | return false; | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 960 | } | 
|  | 961 |  | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 962 | static noinline void | 
|  | 963 | bad_area_access_error(struct pt_regs *regs, unsigned long error_code, | 
| Dave Hansen | 7b2d0db | 2016-02-12 13:02:11 -0800 | [diff] [blame] | 964 | unsigned long address, struct vm_area_struct *vma) | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 965 | { | 
| Dave Hansen | 019132f | 2016-02-12 13:02:14 -0800 | [diff] [blame] | 966 | /* | 
|  | 967 | * This OSPKE check is not strictly necessary at runtime. | 
|  | 968 | * But, doing it this way allows compiler optimizations | 
|  | 969 | * if pkeys are compiled out. | 
|  | 970 | */ | 
| Dave Hansen | 33a709b | 2016-02-12 13:02:19 -0800 | [diff] [blame] | 971 | if (bad_area_access_from_pkeys(error_code, vma)) | 
| Dave Hansen | 019132f | 2016-02-12 13:02:14 -0800 | [diff] [blame] | 972 | __bad_area(regs, error_code, address, vma, SEGV_PKUERR); | 
|  | 973 | else | 
|  | 974 | __bad_area(regs, error_code, address, vma, SEGV_ACCERR); | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 975 | } | 
|  | 976 |  | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 977 | static void | 
| Andi Kleen | a6e04aa | 2009-09-16 11:50:09 +0200 | [diff] [blame] | 978 | do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address, | 
| Laurent Dufour | 54af98f | 2017-09-04 10:32:15 +0200 | [diff] [blame] | 979 | u32 *pkey, unsigned int fault) | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 980 | { | 
|  | 981 | struct task_struct *tsk = current; | 
| Andi Kleen | a6e04aa | 2009-09-16 11:50:09 +0200 | [diff] [blame] | 982 | int code = BUS_ADRERR; | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 983 |  | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 984 | /* Kernel mode? Handle exceptions or die: */ | 
| Linus Torvalds | 9605456 | 2010-08-13 09:49:20 -0700 | [diff] [blame] | 985 | if (!(error_code & PF_USER)) { | 
| Andy Lutomirski | 4fc3490 | 2011-11-07 16:33:40 -0800 | [diff] [blame] | 986 | no_context(regs, error_code, address, SIGBUS, BUS_ADRERR); | 
| Linus Torvalds | 9605456 | 2010-08-13 09:49:20 -0700 | [diff] [blame] | 987 | return; | 
|  | 988 | } | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 989 |  | 
| Ingo Molnar | cd1b68f | 2009-02-20 23:39:02 +0100 | [diff] [blame] | 990 | /* User-space => ok to do another page fault: */ | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 991 | if (is_prefetch(regs, error_code, address)) | 
|  | 992 | return; | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 993 |  | 
|  | 994 | tsk->thread.cr2		= address; | 
|  | 995 | tsk->thread.error_code	= error_code; | 
| Srikar Dronamraju | 51e7dc7 | 2012-03-12 14:55:55 +0530 | [diff] [blame] | 996 | tsk->thread.trap_nr	= X86_TRAP_PF; | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 997 |  | 
| Andi Kleen | a6e04aa | 2009-09-16 11:50:09 +0200 | [diff] [blame] | 998 | #ifdef CONFIG_MEMORY_FAILURE | 
| Andi Kleen | f672b49 | 2010-09-27 22:05:55 +0200 | [diff] [blame] | 999 | if (fault & (VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE)) { | 
| Andi Kleen | a6e04aa | 2009-09-16 11:50:09 +0200 | [diff] [blame] | 1000 | printk(KERN_ERR | 
|  | 1001 | "MCE: Killing %s:%d due to hardware memory corruption fault at %lx\n", | 
|  | 1002 | tsk->comm, tsk->pid, address); | 
|  | 1003 | code = BUS_MCEERR_AR; | 
|  | 1004 | } | 
|  | 1005 | #endif | 
| Laurent Dufour | 54af98f | 2017-09-04 10:32:15 +0200 | [diff] [blame] | 1006 | force_sig_info_fault(SIGBUS, code, address, tsk, pkey, fault); | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 1007 | } | 
|  | 1008 |  | 
| Johannes Weiner | 3a13c4d | 2013-09-12 15:13:40 -0700 | [diff] [blame] | 1009 | static noinline void | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1010 | mm_fault_error(struct pt_regs *regs, unsigned long error_code, | 
| Laurent Dufour | 54af98f | 2017-09-04 10:32:15 +0200 | [diff] [blame] | 1011 | unsigned long address, u32 *pkey, unsigned int fault) | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 1012 | { | 
| Johannes Weiner | 3a13c4d | 2013-09-12 15:13:40 -0700 | [diff] [blame] | 1013 | if (fatal_signal_pending(current) && !(error_code & PF_USER)) { | 
| Johannes Weiner | 3a13c4d | 2013-09-12 15:13:40 -0700 | [diff] [blame] | 1014 | no_context(regs, error_code, address, 0, 0); | 
|  | 1015 | return; | 
| KOSAKI Motohiro | b80ef10 | 2011-05-26 17:12:12 +0900 | [diff] [blame] | 1016 | } | 
| KOSAKI Motohiro | b80ef10 | 2011-05-26 17:12:12 +0900 | [diff] [blame] | 1017 |  | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1018 | if (fault & VM_FAULT_OOM) { | 
| Andrey Vagin | f862685 | 2011-03-09 15:22:23 -0800 | [diff] [blame] | 1019 | /* Kernel mode? Handle exceptions or die: */ | 
|  | 1020 | if (!(error_code & PF_USER)) { | 
| Andy Lutomirski | 4fc3490 | 2011-11-07 16:33:40 -0800 | [diff] [blame] | 1021 | no_context(regs, error_code, address, | 
|  | 1022 | SIGSEGV, SEGV_MAPERR); | 
| Johannes Weiner | 3a13c4d | 2013-09-12 15:13:40 -0700 | [diff] [blame] | 1023 | return; | 
| Andrey Vagin | f862685 | 2011-03-09 15:22:23 -0800 | [diff] [blame] | 1024 | } | 
|  | 1025 |  | 
| David Rientjes | c2d23f9 | 2012-12-12 13:52:10 -0800 | [diff] [blame] | 1026 | /* | 
|  | 1027 | * We ran out of memory, call the OOM killer, and return the | 
|  | 1028 | * userspace (which will retry the fault, or kill us if we got | 
|  | 1029 | * oom-killed): | 
|  | 1030 | */ | 
|  | 1031 | pagefault_out_of_memory(); | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1032 | } else { | 
| Andi Kleen | f672b49 | 2010-09-27 22:05:55 +0200 | [diff] [blame] | 1033 | if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON| | 
|  | 1034 | VM_FAULT_HWPOISON_LARGE)) | 
| Laurent Dufour | 54af98f | 2017-09-04 10:32:15 +0200 | [diff] [blame] | 1035 | do_sigbus(regs, error_code, address, pkey, fault); | 
| Linus Torvalds | 33692f2 | 2015-01-29 10:51:32 -0800 | [diff] [blame] | 1036 | else if (fault & VM_FAULT_SIGSEGV) | 
| Laurent Dufour | 54af98f | 2017-09-04 10:32:15 +0200 | [diff] [blame] | 1037 | bad_area_nosemaphore(regs, error_code, address, pkey); | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1038 | else | 
|  | 1039 | BUG(); | 
|  | 1040 | } | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 1041 | } | 
|  | 1042 |  | 
| Thomas Gleixner | d8b57bb | 2008-02-06 22:39:43 +0100 | [diff] [blame] | 1043 | static int spurious_fault_check(unsigned long error_code, pte_t *pte) | 
|  | 1044 | { | 
|  | 1045 | if ((error_code & PF_WRITE) && !pte_write(*pte)) | 
|  | 1046 | return 0; | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1047 |  | 
| Thomas Gleixner | d8b57bb | 2008-02-06 22:39:43 +0100 | [diff] [blame] | 1048 | if ((error_code & PF_INSTR) && !pte_exec(*pte)) | 
|  | 1049 | return 0; | 
| Dave Hansen | b3ecd51 | 2016-02-12 13:02:07 -0800 | [diff] [blame] | 1050 | /* | 
|  | 1051 | * Note: We do not do lazy flushing on protection key | 
|  | 1052 | * changes, so no spurious fault will ever set PF_PK. | 
|  | 1053 | */ | 
|  | 1054 | if ((error_code & PF_PK)) | 
|  | 1055 | return 1; | 
| Thomas Gleixner | d8b57bb | 2008-02-06 22:39:43 +0100 | [diff] [blame] | 1056 |  | 
|  | 1057 | return 1; | 
|  | 1058 | } | 
|  | 1059 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1060 | /* | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1061 | * Handle a spurious fault caused by a stale TLB entry. | 
|  | 1062 | * | 
|  | 1063 | * This allows us to lazily refresh the TLB when increasing the | 
|  | 1064 | * permissions of a kernel page (RO -> RW or NX -> X).  Doing it | 
|  | 1065 | * eagerly is very expensive since that implies doing a full | 
|  | 1066 | * cross-processor TLB flush, even if no stale TLB entries exist | 
|  | 1067 | * on other processors. | 
|  | 1068 | * | 
| David Vrabel | 3166851 | 2014-04-10 18:46:45 +0100 | [diff] [blame] | 1069 | * Spurious faults may only occur if the TLB contains an entry with | 
|  | 1070 | * fewer permission than the page table entry.  Non-present (P = 0) | 
|  | 1071 | * and reserved bit (R = 1) faults are never spurious. | 
|  | 1072 | * | 
| Jeremy Fitzhardinge | 5b727a3 | 2008-01-30 13:34:11 +0100 | [diff] [blame] | 1073 | * There are no security implications to leaving a stale TLB when | 
|  | 1074 | * increasing the permissions on a page. | 
| David Vrabel | 3166851 | 2014-04-10 18:46:45 +0100 | [diff] [blame] | 1075 | * | 
|  | 1076 | * Returns non-zero if a spurious fault was handled, zero otherwise. | 
|  | 1077 | * | 
|  | 1078 | * See Intel Developer's Manual Vol 3 Section 4.10.4.3, bullet 3 | 
|  | 1079 | * (Optional Invalidation). | 
| Jeremy Fitzhardinge | 5b727a3 | 2008-01-30 13:34:11 +0100 | [diff] [blame] | 1080 | */ | 
| Masami Hiramatsu | 9326638 | 2014-04-17 17:18:14 +0900 | [diff] [blame] | 1081 | static noinline int | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1082 | spurious_fault(unsigned long error_code, unsigned long address) | 
| Jeremy Fitzhardinge | 5b727a3 | 2008-01-30 13:34:11 +0100 | [diff] [blame] | 1083 | { | 
|  | 1084 | pgd_t *pgd; | 
|  | 1085 | pud_t *pud; | 
|  | 1086 | pmd_t *pmd; | 
|  | 1087 | pte_t *pte; | 
| Steven Rostedt | 3c3e569 | 2009-02-19 11:46:36 -0500 | [diff] [blame] | 1088 | int ret; | 
| Jeremy Fitzhardinge | 5b727a3 | 2008-01-30 13:34:11 +0100 | [diff] [blame] | 1089 |  | 
| David Vrabel | 3166851 | 2014-04-10 18:46:45 +0100 | [diff] [blame] | 1090 | /* | 
|  | 1091 | * Only writes to RO or instruction fetches from NX may cause | 
|  | 1092 | * spurious faults. | 
|  | 1093 | * | 
|  | 1094 | * These could be from user or supervisor accesses but the TLB | 
|  | 1095 | * is only lazily flushed after a kernel mapping protection | 
|  | 1096 | * change, so user accesses are not expected to cause spurious | 
|  | 1097 | * faults. | 
|  | 1098 | */ | 
|  | 1099 | if (error_code != (PF_WRITE | PF_PROT) | 
|  | 1100 | && error_code != (PF_INSTR | PF_PROT)) | 
| Jeremy Fitzhardinge | 5b727a3 | 2008-01-30 13:34:11 +0100 | [diff] [blame] | 1101 | return 0; | 
|  | 1102 |  | 
|  | 1103 | pgd = init_mm.pgd + pgd_index(address); | 
|  | 1104 | if (!pgd_present(*pgd)) | 
|  | 1105 | return 0; | 
|  | 1106 |  | 
|  | 1107 | pud = pud_offset(pgd, address); | 
|  | 1108 | if (!pud_present(*pud)) | 
|  | 1109 | return 0; | 
|  | 1110 |  | 
| Thomas Gleixner | d8b57bb | 2008-02-06 22:39:43 +0100 | [diff] [blame] | 1111 | if (pud_large(*pud)) | 
|  | 1112 | return spurious_fault_check(error_code, (pte_t *) pud); | 
|  | 1113 |  | 
| Jeremy Fitzhardinge | 5b727a3 | 2008-01-30 13:34:11 +0100 | [diff] [blame] | 1114 | pmd = pmd_offset(pud, address); | 
|  | 1115 | if (!pmd_present(*pmd)) | 
|  | 1116 | return 0; | 
|  | 1117 |  | 
| Thomas Gleixner | d8b57bb | 2008-02-06 22:39:43 +0100 | [diff] [blame] | 1118 | if (pmd_large(*pmd)) | 
|  | 1119 | return spurious_fault_check(error_code, (pte_t *) pmd); | 
|  | 1120 |  | 
| Jeremy Fitzhardinge | 5b727a3 | 2008-01-30 13:34:11 +0100 | [diff] [blame] | 1121 | pte = pte_offset_kernel(pmd, address); | 
| Andrea Arcangeli | 954f857 | 2013-02-22 15:11:49 -0800 | [diff] [blame] | 1122 | if (!pte_present(*pte)) | 
| Jeremy Fitzhardinge | 5b727a3 | 2008-01-30 13:34:11 +0100 | [diff] [blame] | 1123 | return 0; | 
|  | 1124 |  | 
| Steven Rostedt | 3c3e569 | 2009-02-19 11:46:36 -0500 | [diff] [blame] | 1125 | ret = spurious_fault_check(error_code, pte); | 
|  | 1126 | if (!ret) | 
|  | 1127 | return 0; | 
|  | 1128 |  | 
|  | 1129 | /* | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1130 | * Make sure we have permissions in PMD. | 
|  | 1131 | * If not, then there's a bug in the page tables: | 
| Steven Rostedt | 3c3e569 | 2009-02-19 11:46:36 -0500 | [diff] [blame] | 1132 | */ | 
|  | 1133 | ret = spurious_fault_check(error_code, (pte_t *) pmd); | 
|  | 1134 | WARN_ONCE(!ret, "PMD has incorrect permission bits\n"); | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1135 |  | 
| Steven Rostedt | 3c3e569 | 2009-02-19 11:46:36 -0500 | [diff] [blame] | 1136 | return ret; | 
| Jeremy Fitzhardinge | 5b727a3 | 2008-01-30 13:34:11 +0100 | [diff] [blame] | 1137 | } | 
| Masami Hiramatsu | 9326638 | 2014-04-17 17:18:14 +0900 | [diff] [blame] | 1138 | NOKPROBE_SYMBOL(spurious_fault); | 
| Jeremy Fitzhardinge | 5b727a3 | 2008-01-30 13:34:11 +0100 | [diff] [blame] | 1139 |  | 
| Masoud Asgharifard Sharbiani | abd4f75 | 2007-07-22 11:12:28 +0200 | [diff] [blame] | 1140 | int show_unhandled_signals = 1; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1141 |  | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1142 | static inline int | 
| Michel Lespinasse | 68da336 | 2010-10-26 14:21:58 -0700 | [diff] [blame] | 1143 | access_error(unsigned long error_code, struct vm_area_struct *vma) | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 1144 | { | 
| Dave Hansen | 07f146f | 2016-02-12 13:02:22 -0800 | [diff] [blame] | 1145 | /* This is only called for the current mm, so: */ | 
|  | 1146 | bool foreign = false; | 
| Dave Hansen | e8c6226 | 2016-07-29 09:30:10 -0700 | [diff] [blame] | 1147 |  | 
|  | 1148 | /* | 
|  | 1149 | * Read or write was blocked by protection keys.  This is | 
|  | 1150 | * always an unconditional error and can never result in | 
|  | 1151 | * a follow-up action to resolve the fault, like a COW. | 
|  | 1152 | */ | 
|  | 1153 | if (error_code & PF_PK) | 
|  | 1154 | return 1; | 
|  | 1155 |  | 
| Dave Hansen | 33a709b | 2016-02-12 13:02:19 -0800 | [diff] [blame] | 1156 | /* | 
| Dave Hansen | 07f146f | 2016-02-12 13:02:22 -0800 | [diff] [blame] | 1157 | * Make sure to check the VMA so that we do not perform | 
|  | 1158 | * faults just to hit a PF_PK as soon as we fill in a | 
|  | 1159 | * page. | 
|  | 1160 | */ | 
| Dave Hansen | d61172b | 2016-02-12 13:02:24 -0800 | [diff] [blame] | 1161 | if (!arch_vma_access_permitted(vma, (error_code & PF_WRITE), | 
|  | 1162 | (error_code & PF_INSTR), foreign)) | 
| Dave Hansen | 07f146f | 2016-02-12 13:02:22 -0800 | [diff] [blame] | 1163 | return 1; | 
| Dave Hansen | 33a709b | 2016-02-12 13:02:19 -0800 | [diff] [blame] | 1164 |  | 
| Michel Lespinasse | 68da336 | 2010-10-26 14:21:58 -0700 | [diff] [blame] | 1165 | if (error_code & PF_WRITE) { | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1166 | /* write, present and write, not present: */ | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 1167 | if (unlikely(!(vma->vm_flags & VM_WRITE))) | 
|  | 1168 | return 1; | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1169 | return 0; | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 1170 | } | 
|  | 1171 |  | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1172 | /* read, present: */ | 
|  | 1173 | if (unlikely(error_code & PF_PROT)) | 
|  | 1174 | return 1; | 
|  | 1175 |  | 
|  | 1176 | /* read, not present: */ | 
|  | 1177 | if (unlikely(!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))) | 
|  | 1178 | return 1; | 
|  | 1179 |  | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 1180 | return 0; | 
|  | 1181 | } | 
|  | 1182 |  | 
| Hiroshi Shimamoto | 0973a06 | 2009-02-04 15:24:09 -0800 | [diff] [blame] | 1183 | static int fault_in_kernel_space(unsigned long address) | 
|  | 1184 | { | 
| Ingo Molnar | d951734 | 2009-02-20 23:32:28 +0100 | [diff] [blame] | 1185 | return address >= TASK_SIZE_MAX; | 
| Hiroshi Shimamoto | 0973a06 | 2009-02-04 15:24:09 -0800 | [diff] [blame] | 1186 | } | 
|  | 1187 |  | 
| H. Peter Anvin | 40d3cd6 | 2012-09-21 12:43:14 -0700 | [diff] [blame] | 1188 | static inline bool smap_violation(int error_code, struct pt_regs *regs) | 
|  | 1189 | { | 
| H. Peter Anvin | 4640c7e | 2014-02-13 07:46:04 -0800 | [diff] [blame] | 1190 | if (!IS_ENABLED(CONFIG_X86_SMAP)) | 
|  | 1191 | return false; | 
|  | 1192 |  | 
|  | 1193 | if (!static_cpu_has(X86_FEATURE_SMAP)) | 
|  | 1194 | return false; | 
|  | 1195 |  | 
| H. Peter Anvin | 40d3cd6 | 2012-09-21 12:43:14 -0700 | [diff] [blame] | 1196 | if (error_code & PF_USER) | 
|  | 1197 | return false; | 
|  | 1198 |  | 
| Andy Lutomirski | f39b6f0 | 2015-03-18 18:33:33 -0700 | [diff] [blame] | 1199 | if (!user_mode(regs) && (regs->flags & X86_EFLAGS_AC)) | 
| H. Peter Anvin | 40d3cd6 | 2012-09-21 12:43:14 -0700 | [diff] [blame] | 1200 | return false; | 
|  | 1201 |  | 
|  | 1202 | return true; | 
|  | 1203 | } | 
|  | 1204 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1205 | /* | 
|  | 1206 | * This routine handles page faults.  It determines the address, | 
|  | 1207 | * and the problem, and then passes it off to one of the appropriate | 
|  | 1208 | * routines. | 
| Peter Zijlstra | d4078e2 | 2014-03-05 14:07:49 +0100 | [diff] [blame] | 1209 | * | 
|  | 1210 | * This function must have noinline because both callers | 
|  | 1211 | * {,trace_}do_page_fault() have notrace on. Having this an actual function | 
|  | 1212 | * guarantees there's a function trace entry. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1213 | */ | 
| Masami Hiramatsu | 9326638 | 2014-04-17 17:18:14 +0900 | [diff] [blame] | 1214 | static noinline void | 
| Jiri Olsa | 0ac09f9 | 2014-02-28 17:05:26 +0100 | [diff] [blame] | 1215 | __do_page_fault(struct pt_regs *regs, unsigned long error_code, | 
|  | 1216 | unsigned long address) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1217 | { | 
| Harvey Harrison | 33cb524 | 2008-01-30 13:32:19 +0100 | [diff] [blame] | 1218 | struct vm_area_struct *vma; | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1219 | struct task_struct *tsk; | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1220 | struct mm_struct *mm; | 
| Linus Torvalds | 26178ec | 2014-12-15 15:07:33 -0800 | [diff] [blame] | 1221 | int fault, major = 0; | 
| Johannes Weiner | 759496b | 2013-09-12 15:13:39 -0700 | [diff] [blame] | 1222 | unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; | 
| Laurent Dufour | 54af98f | 2017-09-04 10:32:15 +0200 | [diff] [blame] | 1223 | u32 pkey; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1224 |  | 
| Arjan van de Ven | a9ba9a3 | 2006-03-25 16:30:10 +0100 | [diff] [blame] | 1225 | tsk = current; | 
|  | 1226 | mm = tsk->mm; | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1227 |  | 
| Vegard Nossum | f856129 | 2008-04-04 00:53:23 +0200 | [diff] [blame] | 1228 | /* | 
|  | 1229 | * Detect and handle instructions that would cause a page fault for | 
|  | 1230 | * both a tracked kernel page and a userspace page. | 
|  | 1231 | */ | 
|  | 1232 | if (kmemcheck_active(regs)) | 
|  | 1233 | kmemcheck_hide(regs); | 
| Ingo Molnar | 5dfaf90 | 2009-06-16 10:23:32 +0200 | [diff] [blame] | 1234 | prefetchw(&mm->mmap_sem); | 
| Vegard Nossum | f856129 | 2008-04-04 00:53:23 +0200 | [diff] [blame] | 1235 |  | 
| Pekka Paalanen | 0fd0e3d | 2008-05-12 21:20:57 +0200 | [diff] [blame] | 1236 | if (unlikely(kmmio_fault(regs, address))) | 
| Pekka Paalanen | 8606978 | 2008-05-12 21:20:56 +0200 | [diff] [blame] | 1237 | return; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1238 |  | 
|  | 1239 | /* | 
|  | 1240 | * We fault-in kernel-space virtual memory on-demand. The | 
|  | 1241 | * 'reference' page table is init_mm.pgd. | 
|  | 1242 | * | 
|  | 1243 | * NOTE! We MUST NOT take any locks for this case. We may | 
|  | 1244 | * be in an interrupt or a critical region, and should | 
|  | 1245 | * only copy the information from the master page table, | 
|  | 1246 | * nothing more. | 
|  | 1247 | * | 
|  | 1248 | * This verifies that the fault happens in kernel space | 
|  | 1249 | * (error_code & 4) == 0, and that the fault was not a | 
| Jan Beulich | 8b1bde9 | 2006-01-11 22:42:23 +0100 | [diff] [blame] | 1250 | * protection error (error_code & 9) == 0. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1251 | */ | 
| Hiroshi Shimamoto | 0973a06 | 2009-02-04 15:24:09 -0800 | [diff] [blame] | 1252 | if (unlikely(fault_in_kernel_space(address))) { | 
| Vegard Nossum | f856129 | 2008-04-04 00:53:23 +0200 | [diff] [blame] | 1253 | if (!(error_code & (PF_RSVD | PF_USER | PF_PROT))) { | 
|  | 1254 | if (vmalloc_fault(address) >= 0) | 
|  | 1255 | return; | 
|  | 1256 |  | 
|  | 1257 | if (kmemcheck_fault(regs, address, error_code)) | 
|  | 1258 | return; | 
|  | 1259 | } | 
| Jeremy Fitzhardinge | 5b727a3 | 2008-01-30 13:34:11 +0100 | [diff] [blame] | 1260 |  | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1261 | /* Can handle a stale RO->RW TLB: */ | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 1262 | if (spurious_fault(error_code, address)) | 
| Jeremy Fitzhardinge | 5b727a3 | 2008-01-30 13:34:11 +0100 | [diff] [blame] | 1263 | return; | 
|  | 1264 |  | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1265 | /* kprobes don't want to hook the spurious faults: */ | 
| Peter Zijlstra | e00b12e | 2013-10-24 12:52:06 +0200 | [diff] [blame] | 1266 | if (kprobes_fault(regs)) | 
| Masami Hiramatsu | 9be260a | 2009-02-05 17:12:39 -0500 | [diff] [blame] | 1267 | return; | 
| Harvey Harrison | f8c2ee2 | 2008-01-30 13:34:10 +0100 | [diff] [blame] | 1268 | /* | 
|  | 1269 | * Don't take the mm semaphore here. If we fixup a prefetch | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1270 | * fault we could otherwise deadlock: | 
| Harvey Harrison | f8c2ee2 | 2008-01-30 13:34:10 +0100 | [diff] [blame] | 1271 | */ | 
| Dave Hansen | 7b2d0db | 2016-02-12 13:02:11 -0800 | [diff] [blame] | 1272 | bad_area_nosemaphore(regs, error_code, address, NULL); | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1273 |  | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 1274 | return; | 
| Harvey Harrison | f8c2ee2 | 2008-01-30 13:34:10 +0100 | [diff] [blame] | 1275 | } | 
|  | 1276 |  | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1277 | /* kprobes don't want to hook the spurious faults: */ | 
| Peter Zijlstra | e00b12e | 2013-10-24 12:52:06 +0200 | [diff] [blame] | 1278 | if (unlikely(kprobes_fault(regs))) | 
| Masami Hiramatsu | 9be260a | 2009-02-05 17:12:39 -0500 | [diff] [blame] | 1279 | return; | 
| Peter Zijlstra | e00b12e | 2013-10-24 12:52:06 +0200 | [diff] [blame] | 1280 |  | 
|  | 1281 | if (unlikely(error_code & PF_RSVD)) | 
|  | 1282 | pgtable_bad(regs, error_code, address); | 
|  | 1283 |  | 
| H. Peter Anvin | 4640c7e | 2014-02-13 07:46:04 -0800 | [diff] [blame] | 1284 | if (unlikely(smap_violation(error_code, regs))) { | 
| Dave Hansen | 7b2d0db | 2016-02-12 13:02:11 -0800 | [diff] [blame] | 1285 | bad_area_nosemaphore(regs, error_code, address, NULL); | 
| H. Peter Anvin | 4640c7e | 2014-02-13 07:46:04 -0800 | [diff] [blame] | 1286 | return; | 
| Peter Zijlstra | e00b12e | 2013-10-24 12:52:06 +0200 | [diff] [blame] | 1287 | } | 
|  | 1288 |  | 
|  | 1289 | /* | 
|  | 1290 | * If we're in an interrupt, have no user context or are running | 
| David Hildenbrand | 70ffdb9 | 2015-05-11 17:52:11 +0200 | [diff] [blame] | 1291 | * in a region with pagefaults disabled then we must not take the fault | 
| Peter Zijlstra | e00b12e | 2013-10-24 12:52:06 +0200 | [diff] [blame] | 1292 | */ | 
| David Hildenbrand | 70ffdb9 | 2015-05-11 17:52:11 +0200 | [diff] [blame] | 1293 | if (unlikely(faulthandler_disabled() || !mm)) { | 
| Dave Hansen | 7b2d0db | 2016-02-12 13:02:11 -0800 | [diff] [blame] | 1294 | bad_area_nosemaphore(regs, error_code, address, NULL); | 
| Peter Zijlstra | e00b12e | 2013-10-24 12:52:06 +0200 | [diff] [blame] | 1295 | return; | 
|  | 1296 | } | 
|  | 1297 |  | 
| Harvey Harrison | f8c2ee2 | 2008-01-30 13:34:10 +0100 | [diff] [blame] | 1298 | /* | 
| Linus Torvalds | 891cffb | 2008-10-12 13:16:12 -0700 | [diff] [blame] | 1299 | * It's safe to allow irq's after cr2 has been saved and the | 
|  | 1300 | * vmalloc fault has been handled. | 
|  | 1301 | * | 
|  | 1302 | * User-mode registers count as a user access even for any | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1303 | * potential system fault or CPU buglet: | 
| Harvey Harrison | f8c2ee2 | 2008-01-30 13:34:10 +0100 | [diff] [blame] | 1304 | */ | 
| Andy Lutomirski | f39b6f0 | 2015-03-18 18:33:33 -0700 | [diff] [blame] | 1305 | if (user_mode(regs)) { | 
| Linus Torvalds | 891cffb | 2008-10-12 13:16:12 -0700 | [diff] [blame] | 1306 | local_irq_enable(); | 
|  | 1307 | error_code |= PF_USER; | 
| Johannes Weiner | 759496b | 2013-09-12 15:13:39 -0700 | [diff] [blame] | 1308 | flags |= FAULT_FLAG_USER; | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1309 | } else { | 
|  | 1310 | if (regs->flags & X86_EFLAGS_IF) | 
|  | 1311 | local_irq_enable(); | 
|  | 1312 | } | 
| Jan Beulich | 8c914cb | 2006-03-25 16:29:40 +0100 | [diff] [blame] | 1313 |  | 
| Peter Zijlstra | a8b0ca1 | 2011-06-27 14:41:57 +0200 | [diff] [blame] | 1314 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); | 
| Peter Zijlstra | 7dd1fcc | 2009-03-13 12:21:33 +0100 | [diff] [blame] | 1315 |  | 
| Johannes Weiner | 759496b | 2013-09-12 15:13:39 -0700 | [diff] [blame] | 1316 | if (error_code & PF_WRITE) | 
|  | 1317 | flags |= FAULT_FLAG_WRITE; | 
| Dave Hansen | d61172b | 2016-02-12 13:02:24 -0800 | [diff] [blame] | 1318 | if (error_code & PF_INSTR) | 
|  | 1319 | flags |= FAULT_FLAG_INSTRUCTION; | 
| Johannes Weiner | 759496b | 2013-09-12 15:13:39 -0700 | [diff] [blame] | 1320 |  | 
| Ingo Molnar | 3a1dfe6 | 2008-10-13 17:49:02 +0200 | [diff] [blame] | 1321 | /* | 
|  | 1322 | * When running in the kernel we expect faults to occur only to | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1323 | * addresses in user space.  All other faults represent errors in | 
|  | 1324 | * the kernel and should generate an OOPS.  Unfortunately, in the | 
|  | 1325 | * case of an erroneous fault occurring in a code path which already | 
|  | 1326 | * holds mmap_sem we will deadlock attempting to validate the fault | 
|  | 1327 | * against the address space.  Luckily the kernel only validly | 
|  | 1328 | * references user space from well defined areas of code, which are | 
|  | 1329 | * listed in the exceptions table. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1330 | * | 
|  | 1331 | * As the vast majority of faults will be valid we will only perform | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1332 | * the source reference check when there is a possibility of a | 
|  | 1333 | * deadlock. Attempt to lock the address space, if we cannot we then | 
|  | 1334 | * validate the source. If this is invalid we can skip the address | 
|  | 1335 | * space check, thus avoiding the deadlock: | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1336 | */ | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 1337 | if (unlikely(!down_read_trylock(&mm->mmap_sem))) { | 
| Andi Kleen | 66c5815 | 2006-01-11 22:44:09 +0100 | [diff] [blame] | 1338 | if ((error_code & PF_USER) == 0 && | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 1339 | !search_exception_tables(regs->ip)) { | 
| Dave Hansen | 7b2d0db | 2016-02-12 13:02:11 -0800 | [diff] [blame] | 1340 | bad_area_nosemaphore(regs, error_code, address, NULL); | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 1341 | return; | 
|  | 1342 | } | 
| Michel Lespinasse | d065bd8 | 2010-10-26 14:21:57 -0700 | [diff] [blame] | 1343 | retry: | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1344 | down_read(&mm->mmap_sem); | 
| Peter Zijlstra | 0100607 | 2009-01-29 16:02:12 +0100 | [diff] [blame] | 1345 | } else { | 
|  | 1346 | /* | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1347 | * The above down_read_trylock() might have succeeded in | 
|  | 1348 | * which case we'll have missed the might_sleep() from | 
|  | 1349 | * down_read(): | 
| Peter Zijlstra | 0100607 | 2009-01-29 16:02:12 +0100 | [diff] [blame] | 1350 | */ | 
|  | 1351 | might_sleep(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1352 | } | 
|  | 1353 |  | 
|  | 1354 | vma = find_vma(mm, address); | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 1355 | if (unlikely(!vma)) { | 
|  | 1356 | bad_area(regs, error_code, address); | 
|  | 1357 | return; | 
|  | 1358 | } | 
|  | 1359 | if (likely(vma->vm_start <= address)) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1360 | goto good_area; | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 1361 | if (unlikely(!(vma->vm_flags & VM_GROWSDOWN))) { | 
|  | 1362 | bad_area(regs, error_code, address); | 
|  | 1363 | return; | 
|  | 1364 | } | 
| Harvey Harrison | 33cb524 | 2008-01-30 13:32:19 +0100 | [diff] [blame] | 1365 | if (error_code & PF_USER) { | 
| Harvey Harrison | 6f4d368 | 2008-01-30 13:33:13 +0100 | [diff] [blame] | 1366 | /* | 
|  | 1367 | * Accessing the stack below %sp is always a bug. | 
|  | 1368 | * The large cushion allows instructions like enter | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1369 | * and pusha to work. ("enter $65535, $31" pushes | 
| Harvey Harrison | 6f4d368 | 2008-01-30 13:33:13 +0100 | [diff] [blame] | 1370 | * 32 pointers and then decrements %sp by 65535.) | 
| Chuck Ebbert | 03fdc2c | 2006-06-26 13:59:50 +0200 | [diff] [blame] | 1371 | */ | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 1372 | if (unlikely(address + 65536 + 32 * sizeof(unsigned long) < regs->sp)) { | 
|  | 1373 | bad_area(regs, error_code, address); | 
|  | 1374 | return; | 
|  | 1375 | } | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1376 | } | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 1377 | if (unlikely(expand_stack(vma, address))) { | 
|  | 1378 | bad_area(regs, error_code, address); | 
|  | 1379 | return; | 
|  | 1380 | } | 
|  | 1381 |  | 
|  | 1382 | /* | 
|  | 1383 | * Ok, we have a good vm_area for this memory access, so | 
|  | 1384 | * we can handle it.. | 
|  | 1385 | */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1386 | good_area: | 
| Michel Lespinasse | 68da336 | 2010-10-26 14:21:58 -0700 | [diff] [blame] | 1387 | if (unlikely(access_error(error_code, vma))) { | 
| Dave Hansen | 7b2d0db | 2016-02-12 13:02:11 -0800 | [diff] [blame] | 1388 | bad_area_access_error(regs, error_code, address, vma); | 
| Nick Piggin | 92181f1 | 2009-01-20 04:24:26 +0100 | [diff] [blame] | 1389 | return; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1390 | } | 
|  | 1391 |  | 
|  | 1392 | /* | 
|  | 1393 | * If for any reason at all we couldn't handle the fault, | 
|  | 1394 | * make sure we exit gracefully rather than endlessly redo | 
| Paul Cassella | 9a95f3c | 2014-08-06 16:07:24 -0700 | [diff] [blame] | 1395 | * the fault.  Since we never set FAULT_FLAG_RETRY_NOWAIT, if | 
|  | 1396 | * we get VM_FAULT_RETRY back, the mmap_sem has been unlocked. | 
| Vlastimil Babka | d0629c6 | 2017-11-01 08:21:25 +0100 | [diff] [blame] | 1397 | * | 
|  | 1398 | * Note that handle_userfault() may also release and reacquire mmap_sem | 
|  | 1399 | * (and not return with VM_FAULT_RETRY), when returning to userland to | 
|  | 1400 | * repeat the page fault later with a VM_FAULT_NOPAGE retval | 
|  | 1401 | * (potentially after handling any pending signal during the return to | 
|  | 1402 | * userland). The return to userland is identified whenever | 
|  | 1403 | * FAULT_FLAG_USER|FAULT_FLAG_KILLABLE are both set in flags. | 
|  | 1404 | * Thus we have to be careful about not touching vma after handling the | 
|  | 1405 | * fault, so we read the pkey beforehand. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1406 | */ | 
| Vlastimil Babka | d0629c6 | 2017-11-01 08:21:25 +0100 | [diff] [blame] | 1407 | pkey = vma_pkey(vma); | 
| Kirill A. Shutemov | dcddffd | 2016-07-26 15:25:18 -0700 | [diff] [blame] | 1408 | fault = handle_mm_fault(vma, address, flags); | 
| Linus Torvalds | 26178ec | 2014-12-15 15:07:33 -0800 | [diff] [blame] | 1409 | major |= fault & VM_FAULT_MAJOR; | 
| Ingo Molnar | 2d4a716 | 2009-02-20 19:56:40 +0100 | [diff] [blame] | 1410 |  | 
| Johannes Weiner | 3a13c4d | 2013-09-12 15:13:40 -0700 | [diff] [blame] | 1411 | /* | 
| Linus Torvalds | 26178ec | 2014-12-15 15:07:33 -0800 | [diff] [blame] | 1412 | * If we need to retry the mmap_sem has already been released, | 
|  | 1413 | * and if there is a fatal signal pending there is no guarantee | 
|  | 1414 | * that we made any progress. Handle this case first. | 
| Johannes Weiner | 3a13c4d | 2013-09-12 15:13:40 -0700 | [diff] [blame] | 1415 | */ | 
| Linus Torvalds | 26178ec | 2014-12-15 15:07:33 -0800 | [diff] [blame] | 1416 | if (unlikely(fault & VM_FAULT_RETRY)) { | 
|  | 1417 | /* Retry at most once */ | 
|  | 1418 | if (flags & FAULT_FLAG_ALLOW_RETRY) { | 
|  | 1419 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | 
|  | 1420 | flags |= FAULT_FLAG_TRIED; | 
|  | 1421 | if (!fatal_signal_pending(tsk)) | 
|  | 1422 | goto retry; | 
|  | 1423 | } | 
| Johannes Weiner | 3a13c4d | 2013-09-12 15:13:40 -0700 | [diff] [blame] | 1424 |  | 
| Linus Torvalds | 26178ec | 2014-12-15 15:07:33 -0800 | [diff] [blame] | 1425 | /* User mode? Just return to handle the fatal exception */ | 
| Linus Torvalds | cf3c0a1 | 2014-12-17 11:52:37 -0800 | [diff] [blame] | 1426 | if (flags & FAULT_FLAG_USER) | 
| Linus Torvalds | 26178ec | 2014-12-15 15:07:33 -0800 | [diff] [blame] | 1427 | return; | 
|  | 1428 |  | 
|  | 1429 | /* Not returning to user mode? Handle exceptions or die: */ | 
|  | 1430 | no_context(regs, error_code, address, SIGBUS, BUS_ADRERR); | 
|  | 1431 | return; | 
|  | 1432 | } | 
|  | 1433 |  | 
|  | 1434 | up_read(&mm->mmap_sem); | 
| Johannes Weiner | 3a13c4d | 2013-09-12 15:13:40 -0700 | [diff] [blame] | 1435 | if (unlikely(fault & VM_FAULT_ERROR)) { | 
| Laurent Dufour | 54af98f | 2017-09-04 10:32:15 +0200 | [diff] [blame] | 1436 | mm_fault_error(regs, error_code, address, &pkey, fault); | 
| Johannes Weiner | 3a13c4d | 2013-09-12 15:13:40 -0700 | [diff] [blame] | 1437 | return; | 
| KOSAKI Motohiro | 37b23e0 | 2011-05-24 17:11:30 -0700 | [diff] [blame] | 1438 | } | 
|  | 1439 |  | 
|  | 1440 | /* | 
| Linus Torvalds | 26178ec | 2014-12-15 15:07:33 -0800 | [diff] [blame] | 1441 | * Major/minor page fault accounting. If any of the events | 
|  | 1442 | * returned VM_FAULT_MAJOR, we account it as a major fault. | 
| Michel Lespinasse | d065bd8 | 2010-10-26 14:21:57 -0700 | [diff] [blame] | 1443 | */ | 
| Linus Torvalds | 26178ec | 2014-12-15 15:07:33 -0800 | [diff] [blame] | 1444 | if (major) { | 
|  | 1445 | tsk->maj_flt++; | 
|  | 1446 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address); | 
|  | 1447 | } else { | 
|  | 1448 | tsk->min_flt++; | 
|  | 1449 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, address); | 
| Peter Zijlstra | ac17dc8 | 2009-03-13 12:21:34 +0100 | [diff] [blame] | 1450 | } | 
| Harvey Harrison | d729ab3 | 2008-01-30 13:33:23 +0100 | [diff] [blame] | 1451 |  | 
| Ingo Molnar | 8c938f9 | 2009-02-20 22:12:18 +0100 | [diff] [blame] | 1452 | check_v8086_mode(regs, address, tsk); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1453 | } | 
| Masami Hiramatsu | 9326638 | 2014-04-17 17:18:14 +0900 | [diff] [blame] | 1454 | NOKPROBE_SYMBOL(__do_page_fault); | 
| Frederic Weisbecker | 6ba3c97 | 2012-07-11 20:26:35 +0200 | [diff] [blame] | 1455 |  | 
| Masami Hiramatsu | 9326638 | 2014-04-17 17:18:14 +0900 | [diff] [blame] | 1456 | dotraplinkage void notrace | 
| Frederic Weisbecker | 6ba3c97 | 2012-07-11 20:26:35 +0200 | [diff] [blame] | 1457 | do_page_fault(struct pt_regs *regs, unsigned long error_code) | 
|  | 1458 | { | 
| Peter Zijlstra | d4078e2 | 2014-03-05 14:07:49 +0100 | [diff] [blame] | 1459 | unsigned long address = read_cr2(); /* Get the faulting address */ | 
| Frederic Weisbecker | 6c1e025 | 2013-02-24 01:19:14 +0100 | [diff] [blame] | 1460 | enum ctx_state prev_state; | 
| Peter Zijlstra | d4078e2 | 2014-03-05 14:07:49 +0100 | [diff] [blame] | 1461 |  | 
|  | 1462 | /* | 
|  | 1463 | * We must have this function tagged with __kprobes, notrace and call | 
|  | 1464 | * read_cr2() before calling anything else. To avoid calling any kind | 
|  | 1465 | * of tracing machinery before we've observed the CR2 value. | 
|  | 1466 | * | 
|  | 1467 | * exception_{enter,exit}() contain all sorts of tracepoints. | 
|  | 1468 | */ | 
| Frederic Weisbecker | 6c1e025 | 2013-02-24 01:19:14 +0100 | [diff] [blame] | 1469 |  | 
|  | 1470 | prev_state = exception_enter(); | 
| Jiri Olsa | 0ac09f9 | 2014-02-28 17:05:26 +0100 | [diff] [blame] | 1471 | __do_page_fault(regs, error_code, address); | 
| Frederic Weisbecker | 6c1e025 | 2013-02-24 01:19:14 +0100 | [diff] [blame] | 1472 | exception_exit(prev_state); | 
| Frederic Weisbecker | 6ba3c97 | 2012-07-11 20:26:35 +0200 | [diff] [blame] | 1473 | } | 
| Masami Hiramatsu | 9326638 | 2014-04-17 17:18:14 +0900 | [diff] [blame] | 1474 | NOKPROBE_SYMBOL(do_page_fault); | 
| Seiji Aguchi | 25c74b1 | 2013-10-30 16:37:00 -0400 | [diff] [blame] | 1475 |  | 
| Peter Zijlstra | d4078e2 | 2014-03-05 14:07:49 +0100 | [diff] [blame] | 1476 | #ifdef CONFIG_TRACING | 
| Masami Hiramatsu | 9326638 | 2014-04-17 17:18:14 +0900 | [diff] [blame] | 1477 | static nokprobe_inline void | 
|  | 1478 | trace_page_fault_entries(unsigned long address, struct pt_regs *regs, | 
|  | 1479 | unsigned long error_code) | 
| Seiji Aguchi | d34603b | 2013-10-30 16:39:03 -0400 | [diff] [blame] | 1480 | { | 
|  | 1481 | if (user_mode(regs)) | 
| Peter Zijlstra | d4078e2 | 2014-03-05 14:07:49 +0100 | [diff] [blame] | 1482 | trace_page_fault_user(address, regs, error_code); | 
| Seiji Aguchi | d34603b | 2013-10-30 16:39:03 -0400 | [diff] [blame] | 1483 | else | 
| Peter Zijlstra | d4078e2 | 2014-03-05 14:07:49 +0100 | [diff] [blame] | 1484 | trace_page_fault_kernel(address, regs, error_code); | 
| Seiji Aguchi | d34603b | 2013-10-30 16:39:03 -0400 | [diff] [blame] | 1485 | } | 
|  | 1486 |  | 
| Masami Hiramatsu | 9326638 | 2014-04-17 17:18:14 +0900 | [diff] [blame] | 1487 | dotraplinkage void notrace | 
| Seiji Aguchi | 25c74b1 | 2013-10-30 16:37:00 -0400 | [diff] [blame] | 1488 | trace_do_page_fault(struct pt_regs *regs, unsigned long error_code) | 
|  | 1489 | { | 
| Jiri Olsa | 0ac09f9 | 2014-02-28 17:05:26 +0100 | [diff] [blame] | 1490 | /* | 
|  | 1491 | * The exception_enter and tracepoint processing could | 
|  | 1492 | * trigger another page faults (user space callchain | 
|  | 1493 | * reading) and destroy the original cr2 value, so read | 
|  | 1494 | * the faulting address now. | 
|  | 1495 | */ | 
|  | 1496 | unsigned long address = read_cr2(); | 
| Peter Zijlstra | d4078e2 | 2014-03-05 14:07:49 +0100 | [diff] [blame] | 1497 | enum ctx_state prev_state; | 
| Seiji Aguchi | 25c74b1 | 2013-10-30 16:37:00 -0400 | [diff] [blame] | 1498 |  | 
|  | 1499 | prev_state = exception_enter(); | 
| Peter Zijlstra | d4078e2 | 2014-03-05 14:07:49 +0100 | [diff] [blame] | 1500 | trace_page_fault_entries(address, regs, error_code); | 
| Jiri Olsa | 0ac09f9 | 2014-02-28 17:05:26 +0100 | [diff] [blame] | 1501 | __do_page_fault(regs, error_code, address); | 
| Seiji Aguchi | 25c74b1 | 2013-10-30 16:37:00 -0400 | [diff] [blame] | 1502 | exception_exit(prev_state); | 
|  | 1503 | } | 
| Masami Hiramatsu | 9326638 | 2014-04-17 17:18:14 +0900 | [diff] [blame] | 1504 | NOKPROBE_SYMBOL(trace_do_page_fault); | 
| Peter Zijlstra | d4078e2 | 2014-03-05 14:07:49 +0100 | [diff] [blame] | 1505 | #endif /* CONFIG_TRACING */ |