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

Commit bd0d63f8 authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by Michael Ellerman
Browse files

powerpc/mm: Move page fault VMA access checks to a helper

parent d2e0d2c5
Loading
Loading
Loading
Loading
+33 −24
Original line number Diff line number Diff line
@@ -222,6 +222,37 @@ static bool bad_kernel_fault(bool is_exec, unsigned long error_code,
	return is_exec || (address >= TASK_SIZE);
}

static bool access_error(bool is_write, bool is_exec,
			 struct vm_area_struct *vma)
{
	/*
	 * Allow execution from readable areas if the MMU does not
	 * provide separate controls over reading and executing.
	 *
	 * Note: That code used to not be enabled for 4xx/BookE.
	 * It is now as I/D cache coherency for these is done at
	 * set_pte_at() time and I see no reason why the test
	 * below wouldn't be valid on those processors. This -may-
	 * break programs compiled with a really old ABI though.
	 */
	if (is_exec) {
		return !(vma->vm_flags & VM_EXEC) &&
			(cpu_has_feature(CPU_FTR_NOEXECUTE) ||
			 !(vma->vm_flags & (VM_READ | VM_WRITE)));
	}

	if (is_write) {
		if (unlikely(!(vma->vm_flags & VM_WRITE)))
			return true;
		return false;
	}

	if (unlikely(!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))))
		return true;

	return false;
}

#ifdef CONFIG_PPC_SMLPAR
static inline void cmo_account_page_fault(void)
{
@@ -461,30 +492,8 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,
		return bad_area(regs, address);

good_area:
	if (is_exec) {
		/*
		 * Allow execution from readable areas if the MMU does not
		 * provide separate controls over reading and executing.
		 *
		 * Note: That code used to not be enabled for 4xx/BookE.
		 * It is now as I/D cache coherency for these is done at
		 * set_pte_at() time and I see no reason why the test
		 * below wouldn't be valid on those processors. This -may-
		 * break programs compiled with a really old ABI though.
		 */
		if (unlikely(!(vma->vm_flags & VM_EXEC) &&
			     (cpu_has_feature(CPU_FTR_NOEXECUTE) ||
			      !(vma->vm_flags & (VM_READ | VM_WRITE)))))
			return bad_area(regs, address);
	/* a write */
	} else if (is_write) {
		if (unlikely(!(vma->vm_flags & VM_WRITE)))
	if (unlikely(access_error(is_write, is_exec, vma)))
		return bad_area(regs, address);
	/* a read */
	} else {
		if (unlikely(!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))))
			return bad_area(regs, address);
	}

	/*
	 * If for any reason at all we couldn't handle the fault,