fault.c 15.1 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 *  arch/s390/mm/fault.c
 *
 *  S390 version
 *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
 *    Author(s): Hartmut Penner (hp@de.ibm.com)
 *               Ulrich Weigand (uweigand@de.ibm.com)
 *
 *  Derived from "arch/i386/mm/fault.c"
 *    Copyright (C) 1995  Linus Torvalds
 */

#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/smp.h>
23
#include <linux/kdebug.h>
L
Linus Torvalds 已提交
24 25 26 27 28
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/module.h>
#include <linux/hardirq.h>
M
Michael Grundy 已提交
29
#include <linux/kprobes.h>
30
#include <linux/uaccess.h>
L
Linus Torvalds 已提交
31 32 33

#include <asm/system.h>
#include <asm/pgtable.h>
H
Heiko Carstens 已提交
34
#include <asm/s390_ext.h>
M
Martin Schwidefsky 已提交
35
#include <asm/mmu_context.h>
L
Linus Torvalds 已提交
36

37
#ifndef CONFIG_64BIT
L
Linus Torvalds 已提交
38 39 40 41
#define __FAIL_ADDR_MASK 0x7ffff000
#define __FIXUP_MASK 0x7fffffff
#define __SUBCODE_MASK 0x0200
#define __PF_RES_FIELD 0ULL
42
#else /* CONFIG_64BIT */
L
Linus Torvalds 已提交
43 44 45 46
#define __FAIL_ADDR_MASK -4096L
#define __FIXUP_MASK ~0L
#define __SUBCODE_MASK 0x0600
#define __PF_RES_FIELD 0x8000000000000000ULL
47
#endif /* CONFIG_64BIT */
L
Linus Torvalds 已提交
48 49 50 51 52 53 54

#ifdef CONFIG_SYSCTL
extern int sysctl_userprocess_debug;
#endif

extern void die(const char *,struct pt_regs *,long);

M
Michael Grundy 已提交
55
#ifdef CONFIG_KPROBES
56 57
static inline int notify_page_fault(struct pt_regs *regs, long err)
{
58 59 60 61 62 63 64 65 66 67 68
	int ret = 0;

	/* kprobe_running() needs smp_processor_id() */
	if (!user_mode(regs)) {
		preempt_disable();
		if (kprobe_running() && kprobe_fault_handler(regs, 14))
			ret = 1;
		preempt_enable();
	}

	return ret;
M
Michael Grundy 已提交
69 70
}
#else
71
static inline int notify_page_fault(struct pt_regs *regs, long err)
M
Michael Grundy 已提交
72
{
73
	return 0;
M
Michael Grundy 已提交
74 75 76
}
#endif

L
Linus Torvalds 已提交
77 78 79

/*
 * Unlock any spinlocks which will prevent us from getting the
80
 * message out.
L
Linus Torvalds 已提交
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
 */
void bust_spinlocks(int yes)
{
	if (yes) {
		oops_in_progress = 1;
	} else {
		int loglevel_save = console_loglevel;
		console_unblank();
		oops_in_progress = 0;
		/*
		 * OK, the message is on the console.  Now we call printk()
		 * without oops_in_progress set so that printk will give klogd
		 * a poke.  Hold onto your hats...
		 */
		console_loglevel = 15;
		printk(" ");
		console_loglevel = loglevel_save;
	}
}

/*
102 103 104
 * Returns the address space associated with the fault.
 * Returns 0 for kernel space, 1 for user space and
 * 2 for code execution in user space with noexec=on.
L
Linus Torvalds 已提交
105
 */
106
static inline int check_space(struct task_struct *tsk)
L
Linus Torvalds 已提交
107 108
{
	/*
109 110
	 * The lowest two bits of S390_lowcore.trans_exc_code
	 * indicate which paging table was used.
L
Linus Torvalds 已提交
111
	 */
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
	int desc = S390_lowcore.trans_exc_code & 3;

	if (desc == 3)	/* Home Segment Table Descriptor */
		return switch_amode == 0;
	if (desc == 2)	/* Secondary Segment Table Descriptor */
		return tsk->thread.mm_segment.ar4;
#ifdef CONFIG_S390_SWITCH_AMODE
	if (unlikely(desc == 1)) { /* STD determined via access register */
		/* %a0 always indicates primary space. */
		if (S390_lowcore.exc_access_id != 0) {
			save_access_regs(tsk->thread.acrs);
			/*
			 * An alet of 0 indicates primary space.
			 * An alet of 1 indicates secondary space.
			 * Any other alet values generate an
			 * alen-translation exception.
			 */
			if (tsk->thread.acrs[S390_lowcore.exc_access_id])
				return tsk->thread.mm_segment.ar4;
		}
	}
#endif
	/* Primary Segment Table Descriptor */
	return switch_amode << s390_noexec;
L
Linus Torvalds 已提交
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
}

/*
 * Send SIGSEGV to task.  This is an external routine
 * to keep the stack usage of do_page_fault small.
 */
static void do_sigsegv(struct pt_regs *regs, unsigned long error_code,
		       int si_code, unsigned long address)
{
	struct siginfo si;

#if defined(CONFIG_SYSCTL) || defined(CONFIG_PROCESS_DEBUG)
#if defined(CONFIG_SYSCTL)
	if (sysctl_userprocess_debug)
#endif
	{
		printk("User process fault: interruption code 0x%lX\n",
		       error_code);
		printk("failing address: %lX\n", address);
		show_regs(regs);
	}
#endif
	si.si_signo = SIGSEGV;
	si.si_code = si_code;
H
Heiko Carstens 已提交
160
	si.si_addr = (void __user *) address;
L
Linus Torvalds 已提交
161 162 163
	force_sig_info(SIGSEGV, &si, current);
}

164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
static void do_no_context(struct pt_regs *regs, unsigned long error_code,
			  unsigned long address)
{
	const struct exception_table_entry *fixup;

	/* Are we prepared to handle this kernel fault?  */
	fixup = search_exception_tables(regs->psw.addr & __FIXUP_MASK);
	if (fixup) {
		regs->psw.addr = fixup->fixup | PSW_ADDR_AMODE;
		return;
	}

	/*
	 * Oops. The kernel tried to access some bad page. We'll have to
	 * terminate things with extreme prejudice.
	 */
	if (check_space(current) == 0)
		printk(KERN_ALERT "Unable to handle kernel pointer dereference"
		       " at virtual kernel address %p\n", (void *)address);
	else
		printk(KERN_ALERT "Unable to handle kernel paging request"
		       " at virtual user address %p\n", (void *)address);

	die("Oops", regs, error_code);
	do_exit(SIGKILL);
}

static void do_low_address(struct pt_regs *regs, unsigned long error_code)
{
	/* Low-address protection hit in kernel mode means
	   NULL pointer write access in kernel mode.  */
	if (regs->psw.mask & PSW_MASK_PSTATE) {
		/* Low-address protection hit in user mode 'cannot happen'. */
		die ("Low-address protection", regs, error_code);
		do_exit(SIGKILL);
	}

	do_no_context(regs, error_code, 0);
}

/*
 * We ran out of memory, or some other thing happened to us that made
 * us unable to handle the page fault gracefully.
 */
static int do_out_of_memory(struct pt_regs *regs, unsigned long error_code,
			    unsigned long address)
{
	struct task_struct *tsk = current;
	struct mm_struct *mm = tsk->mm;

	up_read(&mm->mmap_sem);
215
	if (is_global_init(tsk)) {
216 217 218 219 220 221
		yield();
		down_read(&mm->mmap_sem);
		return 1;
	}
	printk("VM: killing process %s\n", tsk->comm);
	if (regs->psw.mask & PSW_MASK_PSTATE)
222
		do_group_exit(SIGKILL);
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
	do_no_context(regs, error_code, address);
	return 0;
}

static void do_sigbus(struct pt_regs *regs, unsigned long error_code,
		      unsigned long address)
{
	struct task_struct *tsk = current;
	struct mm_struct *mm = tsk->mm;

	up_read(&mm->mmap_sem);
	/*
	 * Send a sigbus, regardless of whether we were in kernel
	 * or user mode.
	 */
	tsk->thread.prot_addr = address;
	tsk->thread.trap_no = error_code;
	force_sig(SIGBUS, tsk);

	/* Kernel mode? Handle exceptions or die */
	if (!(regs->psw.mask & PSW_MASK_PSTATE))
		do_no_context(regs, error_code, address);
}

G
Gerald Schaefer 已提交
247
#ifdef CONFIG_S390_EXEC_PROTECT
248 249 250 251
extern long sys_sigreturn(void);
extern long sys_rt_sigreturn(void);
extern long sys32_sigreturn(void);
extern long sys32_rt_sigreturn(void);
G
Gerald Schaefer 已提交
252

253 254
static int signal_return(struct mm_struct *mm, struct pt_regs *regs,
			 unsigned long address, unsigned long error_code)
G
Gerald Schaefer 已提交
255
{
256
	u16 instruction;
H
Heiko Carstens 已提交
257 258 259 260
	int rc;
#ifdef CONFIG_COMPAT
	int compat;
#endif
261 262 263 264 265 266 267

	pagefault_disable();
	rc = __get_user(instruction, (u16 __user *) regs->psw.addr);
	pagefault_enable();
	if (rc)
		return -EFAULT;

G
Gerald Schaefer 已提交
268 269 270
	up_read(&mm->mmap_sem);
	clear_tsk_thread_flag(current, TIF_SINGLE_STEP);
#ifdef CONFIG_COMPAT
271 272
	compat = test_tsk_thread_flag(current, TIF_31BIT);
	if (compat && instruction == 0x0a77)
273
		sys32_sigreturn();
274
	else if (compat && instruction == 0x0aad)
275
		sys32_rt_sigreturn();
G
Gerald Schaefer 已提交
276
	else
277 278
#endif
	if (instruction == 0x0a77)
279
		sys_sigreturn();
280
	else if (instruction == 0x0aad)
281
		sys_rt_sigreturn();
G
Gerald Schaefer 已提交
282 283 284 285 286 287 288 289 290
	else {
		current->thread.prot_addr = address;
		current->thread.trap_no = error_code;
		do_sigsegv(regs, error_code, SEGV_MAPERR, address);
	}
	return 0;
}
#endif /* CONFIG_S390_EXEC_PROTECT */

L
Linus Torvalds 已提交
291 292 293 294 295 296 297 298 299 300 301
/*
 * This routine handles page faults.  It determines the address,
 * and the problem, and then passes it off to one of the appropriate
 * routines.
 *
 * error_code:
 *   04       Protection           ->  Write-Protection  (suprression)
 *   10       Segment translation  ->  Not present       (nullification)
 *   11       Page translation     ->  Not present       (nullification)
 *   3b       Region third trans.  ->  Not present       (nullification)
 */
302
static inline void
303
do_exception(struct pt_regs *regs, unsigned long error_code, int write)
L
Linus Torvalds 已提交
304
{
305 306 307 308
	struct task_struct *tsk;
	struct mm_struct *mm;
	struct vm_area_struct *vma;
	unsigned long address;
309
	int space;
310
	int si_code;
N
Nick Piggin 已提交
311
	int fault;
L
Linus Torvalds 已提交
312

313
	if (notify_page_fault(regs, error_code))
M
Michael Grundy 已提交
314 315
		return;

316 317
	tsk = current;
	mm = tsk->mm;
L
Linus Torvalds 已提交
318

319 320
	/* get the failing address and the affected space */
	address = S390_lowcore.trans_exc_code & __FAIL_ADDR_MASK;
321
	space = check_space(tsk);
L
Linus Torvalds 已提交
322 323 324 325 326 327

	/*
	 * Verify that the fault happened in user space, that
	 * we are not in an interrupt and that there is a 
	 * user context.
	 */
328 329
	if (unlikely(space == 0 || in_atomic() || !mm))
		goto no_context;
L
Linus Torvalds 已提交
330 331 332 333 334 335 336 337

	/*
	 * When we get here, the fault happened in the current
	 * task's user address space, so we can switch on the
	 * interrupts again and then search the VMAs
	 */
	local_irq_enable();

338
	down_read(&mm->mmap_sem);
L
Linus Torvalds 已提交
339

340 341 342 343
	si_code = SEGV_MAPERR;
	vma = find_vma(mm, address);
	if (!vma)
		goto bad_area;
G
Gerald Schaefer 已提交
344 345

#ifdef CONFIG_S390_EXEC_PROTECT
346
	if (unlikely((space == 2) && !(vma->vm_flags & VM_EXEC)))
G
Gerald Schaefer 已提交
347 348 349 350 351 352 353 354
		if (!signal_return(mm, regs, address, error_code))
			/*
			 * signal_return() has done an up_read(&mm->mmap_sem)
			 * if it returns 0.
			 */
			return;
#endif

355 356 357 358 359 360
	if (vma->vm_start <= address)
		goto good_area;
	if (!(vma->vm_flags & VM_GROWSDOWN))
		goto bad_area;
	if (expand_stack(vma, address))
		goto bad_area;
L
Linus Torvalds 已提交
361 362 363 364 365 366
/*
 * Ok, we have a good vm_area for this memory access, so
 * we can handle it..
 */
good_area:
	si_code = SEGV_ACCERR;
367
	if (!write) {
L
Linus Torvalds 已提交
368 369 370 371 372 373 374 375 376 377 378 379 380 381
		/* page not present, check vm flags */
		if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
			goto bad_area;
	} else {
		if (!(vma->vm_flags & VM_WRITE))
			goto bad_area;
	}

survive:
	/*
	 * If for any reason at all we couldn't handle the fault,
	 * make sure we exit gracefully rather than endlessly redo
	 * the fault.
	 */
N
Nick Piggin 已提交
382 383 384 385 386 387 388 389 390 391
	fault = handle_mm_fault(mm, vma, address, write);
	if (unlikely(fault & VM_FAULT_ERROR)) {
		if (fault & VM_FAULT_OOM) {
			if (do_out_of_memory(regs, error_code, address))
				goto survive;
			return;
		} else if (fault & VM_FAULT_SIGBUS) {
			do_sigbus(regs, error_code, address);
			return;
		}
L
Linus Torvalds 已提交
392 393
		BUG();
	}
N
Nick Piggin 已提交
394 395 396 397
	if (fault & VM_FAULT_MAJOR)
		tsk->maj_flt++;
	else
		tsk->min_flt++;
L
Linus Torvalds 已提交
398 399 400 401 402 403

        up_read(&mm->mmap_sem);
	/*
	 * The instruction that caused the program check will
	 * be repeated. Don't signal single step via SIGTRAP.
	 */
404
	clear_tsk_thread_flag(tsk, TIF_SINGLE_STEP);
L
Linus Torvalds 已提交
405 406 407 408 409 410 411
        return;

/*
 * Something tried to access memory that isn't in our memory map..
 * Fix it, but check if it's kernel or user first..
 */
bad_area:
412
	up_read(&mm->mmap_sem);
L
Linus Torvalds 已提交
413

414 415 416 417
	/* User mode accesses just cause a SIGSEGV */
	if (regs->psw.mask & PSW_MASK_PSTATE) {
		tsk->thread.prot_addr = address;
		tsk->thread.trap_no = error_code;
L
Linus Torvalds 已提交
418
		do_sigsegv(regs, error_code, si_code, address);
419
		return;
L
Linus Torvalds 已提交
420 421 422
	}

no_context:
423
	do_no_context(regs, error_code, address);
L
Linus Torvalds 已提交
424 425
}

426 427
void __kprobes do_protection_exception(struct pt_regs *regs,
				       unsigned long error_code)
L
Linus Torvalds 已提交
428
{
429
	/* Protection exception is supressing, decrement psw address. */
L
Linus Torvalds 已提交
430
	regs->psw.addr -= (error_code >> 16);
431 432 433 434 435 436 437 438 439
	/*
	 * Check for low-address protection.  This needs to be treated
	 * as a special case because the translation exception code
	 * field is not guaranteed to contain valid data in this case.
	 */
	if (unlikely(!(S390_lowcore.trans_exc_code & 4))) {
		do_low_address(regs, error_code);
		return;
	}
L
Linus Torvalds 已提交
440 441 442
	do_exception(regs, 4, 1);
}

443
void __kprobes do_dat_exception(struct pt_regs *regs, unsigned long error_code)
L
Linus Torvalds 已提交
444 445 446 447
{
	do_exception(regs, error_code & 0xff, 0);
}

M
Martin Schwidefsky 已提交
448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
#ifdef CONFIG_64BIT
void __kprobes do_asce_exception(struct pt_regs *regs, unsigned long error_code)
{
	struct mm_struct *mm;
	struct vm_area_struct *vma;
	unsigned long address;
	int space;

	mm = current->mm;
	address = S390_lowcore.trans_exc_code & __FAIL_ADDR_MASK;
	space = check_space(current);

	if (unlikely(space == 0 || in_atomic() || !mm))
		goto no_context;

	local_irq_enable();

	down_read(&mm->mmap_sem);
	vma = find_vma(mm, address);
	up_read(&mm->mmap_sem);

	if (vma) {
		update_mm(mm, current);
		return;
	}

	/* User mode accesses just cause a SIGSEGV */
	if (regs->psw.mask & PSW_MASK_PSTATE) {
		current->thread.prot_addr = address;
		current->thread.trap_no = error_code;
		do_sigsegv(regs, error_code, SEGV_MAPERR, address);
		return;
	}

no_context:
	do_no_context(regs, error_code, address);
}
#endif

L
Linus Torvalds 已提交
487 488 489 490
#ifdef CONFIG_PFAULT 
/*
 * 'pfault' pseudo page faults routines.
 */
H
Heiko Carstens 已提交
491
static ext_int_info_t ext_int_pfault;
L
Linus Torvalds 已提交
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510
static int pfault_disable = 0;

static int __init nopfault(char *str)
{
	pfault_disable = 1;
	return 1;
}

__setup("nopfault", nopfault);

typedef struct {
	__u16 refdiagc;
	__u16 reffcode;
	__u16 refdwlen;
	__u16 refversn;
	__u64 refgaddr;
	__u64 refselmk;
	__u64 refcmpmk;
	__u64 reserved;
511
} __attribute__ ((packed, aligned(8))) pfault_refbk_t;
L
Linus Torvalds 已提交
512 513 514 515 516 517 518 519

int pfault_init(void)
{
	pfault_refbk_t refbk =
		{ 0x258, 0, 5, 2, __LC_CURRENT, 1ULL << 48, 1ULL << 48,
		  __PF_RES_FIELD };
        int rc;

H
Heiko Carstens 已提交
520
	if (!MACHINE_IS_VM || pfault_disable)
L
Linus Torvalds 已提交
521
		return -1;
522 523 524 525
	asm volatile(
		"	diag	%1,%0,0x258\n"
		"0:	j	2f\n"
		"1:	la	%0,8\n"
L
Linus Torvalds 已提交
526
		"2:\n"
527 528
		EX_TABLE(0b,1b)
		: "=d" (rc) : "a" (&refbk), "m" (refbk) : "cc");
L
Linus Torvalds 已提交
529 530 531 532 533 534 535 536 537
        __ctl_set_bit(0, 9);
        return rc;
}

void pfault_fini(void)
{
	pfault_refbk_t refbk =
	{ 0x258, 1, 5, 2, 0ULL, 0ULL, 0ULL, 0ULL };

H
Heiko Carstens 已提交
538
	if (!MACHINE_IS_VM || pfault_disable)
L
Linus Torvalds 已提交
539 540
		return;
	__ctl_clear_bit(0,9);
541 542
	asm volatile(
		"	diag	%0,0,0x258\n"
L
Linus Torvalds 已提交
543
		"0:\n"
544 545
		EX_TABLE(0b,0b)
		: : "a" (&refbk), "m" (refbk) : "cc");
L
Linus Torvalds 已提交
546 547
}

548
static void pfault_interrupt(__u16 error_code)
L
Linus Torvalds 已提交
549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574
{
	struct task_struct *tsk;
	__u16 subcode;

	/*
	 * Get the external interruption subcode & pfault
	 * initial/completion signal bit. VM stores this 
	 * in the 'cpu address' field associated with the
         * external interrupt. 
	 */
	subcode = S390_lowcore.cpu_addr;
	if ((subcode & 0xff00) != __SUBCODE_MASK)
		return;

	/*
	 * Get the token (= address of the task structure of the affected task).
	 */
	tsk = *(struct task_struct **) __LC_PFAULT_INTPARM;

	if (subcode & 0x0080) {
		/* signal bit is set -> a page has been swapped in by VM */
		if (xchg(&tsk->thread.pfault_wait, -1) != 0) {
			/* Initial interrupt was faster than the completion
			 * interrupt. pfault_wait is valid. Set pfault_wait
			 * back to zero and wake up the process. This can
			 * safely be done because the task is still sleeping
575
			 * and can't produce new pfaults. */
L
Linus Torvalds 已提交
576 577
			tsk->thread.pfault_wait = 0;
			wake_up_process(tsk);
578
			put_task_struct(tsk);
L
Linus Torvalds 已提交
579 580 581
		}
	} else {
		/* signal bit not set -> a real page is missing. */
582
		get_task_struct(tsk);
L
Linus Torvalds 已提交
583 584 585 586 587 588 589 590 591
		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
		if (xchg(&tsk->thread.pfault_wait, 1) != 0) {
			/* Completion interrupt was faster than the initial
			 * interrupt (swapped in a -1 for pfault_wait). Set
			 * pfault_wait back to zero and exit. This can be
			 * done safely because tsk is running in kernel 
			 * mode and can't produce new pfaults. */
			tsk->thread.pfault_wait = 0;
			set_task_state(tsk, TASK_RUNNING);
592
			put_task_struct(tsk);
L
Linus Torvalds 已提交
593 594 595 596 597
		} else
			set_tsk_need_resched(tsk);
	}
}

H
Heiko Carstens 已提交
598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
void __init pfault_irq_init(void)
{
	if (!MACHINE_IS_VM)
		return;

	/*
	 * Try to get pfault pseudo page faults going.
	 */
	if (register_early_external_interrupt(0x2603, pfault_interrupt,
					      &ext_int_pfault) != 0)
		panic("Couldn't request external interrupt 0x2603");

	if (pfault_init() == 0)
		return;

	/* Tough luck, no pfault. */
	pfault_disable = 1;
	unregister_early_external_interrupt(0x2603, pfault_interrupt,
					    &ext_int_pfault);
}
#endif