Commit 051168df authored by Chris Metcalf's avatar Chris Metcalf
Browse files

tile: don't assume user privilege is zero



Technically, user privilege is anything less than kernel
privilege.  We modify the existing user_mode() macro to have
this semantic (and use it in a couple of places it wasn't being
used before), and add an IS_KERNEL_EX1() macro to the assembly
code as well.

Signed-off-by: default avatarChris Metcalf <cmetcalf@tilera.com>
parent 309272f9
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
#ifndef _ASM_TILE_PROCESSOR_H
#define _ASM_TILE_PROCESSOR_H

#include <arch/chip.h>

#ifndef __ASSEMBLY__

/*
@@ -25,7 +27,6 @@
#include <asm/ptrace.h>
#include <asm/percpu.h>

#include <arch/chip.h>
#include <arch/spr_def.h>

struct task_struct;
@@ -347,7 +348,6 @@ extern int kdata_huge;

/*
 * Provide symbolic constants for PLs.
 * Note that assembly code assumes that USER_PL is zero.
 */
#define USER_PL 0
#if CONFIG_KERNEL_PL == 2
+1 −1
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ typedef unsigned long pt_reg_t;
#define user_stack_pointer(regs) ((regs)->sp)

/* Does the process account for user or for system time? */
#define user_mode(regs) (EX1_PL((regs)->ex1) == USER_PL)
#define user_mode(regs) (EX1_PL((regs)->ex1) < KERNEL_PL)

/* Fill in a struct pt_regs with the current kernel registers. */
struct pt_regs *get_pt_regs(struct pt_regs *);
+17 −6
Original line number Diff line number Diff line
@@ -34,6 +34,16 @@

#define PTREGS_OFFSET_SYSCALL PTREGS_OFFSET_REG(TREG_SYSCALL_NR)

#if CONFIG_KERNEL_PL == 1 || CONFIG_KERNEL_PL == 2
/*
 * Set "result" non-zero if ex1 holds the PL of the kernel
 * (with or without ICS being set).  Note this works only
 * because we never find the PL at level 3.
 */
# define IS_KERNEL_EX1(result, ex1) andi result, ex1, CONFIG_KERNEL_PL
#else
# error Recode IS_KERNEL_EX1 for CONFIG_KERNEL_PL
#endif

	.macro  push_reg reg, ptr=sp, delta=-8
	{
@@ -308,7 +318,7 @@ intvec_\vecname:
	 */
	{
	 blbs   sp, 2f
	 andi   r0, r0, SPR_EX_CONTEXT_1_1__PL_MASK  /* mask off ICS */
	 IS_KERNEL_EX1(r0, r0)
	}

	.ifc    \vecnum, INT_DOUBLE_FAULT
@@ -641,11 +651,12 @@ intvec_\vecname:
	/*
	 * If we will be returning to the kernel, we will need to
	 * reset the interrupt masks to the state they had before.
	 * Set DISABLE_IRQ in flags iff we came from PL1 with irqs disabled.
	 * Set DISABLE_IRQ in flags iff we came from kernel pl with
	 * irqs disabled.
	 */
	mfspr   r32, SPR_EX_CONTEXT_K_1
	{
	 andi   r32, r32, SPR_EX_CONTEXT_1_1__PL_MASK  /* mask off ICS */
	 IS_KERNEL_EX1(r22, r22)
	 PTREGS_PTR(r21, PTREGS_OFFSET_FLAGS)
	}
	beqzt   r32, 1f       /* zero if from user space */
@@ -812,7 +823,7 @@ STD_ENTRY(interrupt_return)
	 PTREGS_PTR(r29, PTREGS_OFFSET_EX1)
	}
	ld      r29, r29
	andi    r29, r29, SPR_EX_CONTEXT_1_1__PL_MASK  /* mask off ICS */
	IS_KERNEL_EX1(r29, r29)
	{
	 beqzt  r29, .Lresume_userspace
	 move   r29, sp
@@ -936,7 +947,7 @@ STD_ENTRY(interrupt_return)
	 PTREGS_PTR(r32, PTREGS_OFFSET_FLAGS)
	}
	{
	 andi   r0, r0, SPR_EX_CONTEXT_1_1__PL_MASK
	 IS_KERNEL_EX1(r0, r0)
	 ld     r32, r32
	}
	bnez    r0, 1f
@@ -1007,7 +1018,7 @@ STD_ENTRY(interrupt_return)
	pop_reg r21, sp, PTREGS_OFFSET_REG(31) - PTREGS_OFFSET_PC
	{
	 mtspr  SPR_EX_CONTEXT_K_1, lr
	 andi   lr, lr, SPR_EX_CONTEXT_1_1__PL_MASK  /* mask off ICS */
	 IS_KERNEL_EX1(lr, lr)
	}
	{
	 mtspr  SPR_EX_CONTEXT_K_0, r21
+1 −1
Original line number Diff line number Diff line
@@ -103,7 +103,7 @@ static struct pt_regs *valid_fault_handler(struct KBacktraceIterator* kbt)
	    p->sp >= sp) {
		if (kbt->verbose)
			pr_err("  <%s while in kernel mode>\n", fault);
	} else if (EX1_PL(p->ex1) == USER_PL &&
	} else if (user_mode(p) &&
		   p->sp < PAGE_OFFSET && p->sp != 0) {
		if (kbt->verbose)
			pr_err("  <%s while in user mode>\n", fault);
+2 −2
Original line number Diff line number Diff line
@@ -283,7 +283,7 @@ static int handle_page_fault(struct pt_regs *regs,
	flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
		 (write ? FAULT_FLAG_WRITE : 0));

	is_kernel_mode = (EX1_PL(regs->ex1) != USER_PL);
	is_kernel_mode = !user_mode(regs);

	tsk = validate_current();

@@ -824,7 +824,7 @@ void do_page_fault(struct pt_regs *regs, int fault_num,
	}

#if CHIP_HAS_TILE_DMA() || CHIP_HAS_SN_PROC()
	if (EX1_PL(regs->ex1) != USER_PL) {
	if (!user_mode(regs)) {
		struct async_tlb *async;
		switch (fault_num) {
#if CHIP_HAS_TILE_DMA()