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

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
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#ifndef _ASM_TILE_PROCESSOR_H #ifndef _ASM_TILE_PROCESSOR_H
#define _ASM_TILE_PROCESSOR_H #define _ASM_TILE_PROCESSOR_H
#include <arch/chip.h>
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
/* /*
...@@ -25,7 +27,6 @@ ...@@ -25,7 +27,6 @@
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/percpu.h> #include <asm/percpu.h>
#include <arch/chip.h>
#include <arch/spr_def.h> #include <arch/spr_def.h>
struct task_struct; struct task_struct;
...@@ -347,7 +348,6 @@ extern int kdata_huge; ...@@ -347,7 +348,6 @@ extern int kdata_huge;
/* /*
* Provide symbolic constants for PLs. * Provide symbolic constants for PLs.
* Note that assembly code assumes that USER_PL is zero.
*/ */
#define USER_PL 0 #define USER_PL 0
#if CONFIG_KERNEL_PL == 2 #if CONFIG_KERNEL_PL == 2
......
...@@ -39,7 +39,7 @@ typedef unsigned long pt_reg_t; ...@@ -39,7 +39,7 @@ typedef unsigned long pt_reg_t;
#define user_stack_pointer(regs) ((regs)->sp) #define user_stack_pointer(regs) ((regs)->sp)
/* Does the process account for user or for system time? */ /* 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. */ /* Fill in a struct pt_regs with the current kernel registers. */
struct pt_regs *get_pt_regs(struct pt_regs *); struct pt_regs *get_pt_regs(struct pt_regs *);
......
...@@ -34,6 +34,16 @@ ...@@ -34,6 +34,16 @@
#define PTREGS_OFFSET_SYSCALL PTREGS_OFFSET_REG(TREG_SYSCALL_NR) #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 .macro push_reg reg, ptr=sp, delta=-8
{ {
...@@ -308,7 +318,7 @@ intvec_\vecname: ...@@ -308,7 +318,7 @@ intvec_\vecname:
*/ */
{ {
blbs sp, 2f 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 .ifc \vecnum, INT_DOUBLE_FAULT
...@@ -641,11 +651,12 @@ intvec_\vecname: ...@@ -641,11 +651,12 @@ intvec_\vecname:
/* /*
* If we will be returning to the kernel, we will need to * If we will be returning to the kernel, we will need to
* reset the interrupt masks to the state they had before. * 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 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) PTREGS_PTR(r21, PTREGS_OFFSET_FLAGS)
} }
beqzt r32, 1f /* zero if from user space */ beqzt r32, 1f /* zero if from user space */
...@@ -812,7 +823,7 @@ STD_ENTRY(interrupt_return) ...@@ -812,7 +823,7 @@ STD_ENTRY(interrupt_return)
PTREGS_PTR(r29, PTREGS_OFFSET_EX1) PTREGS_PTR(r29, PTREGS_OFFSET_EX1)
} }
ld r29, r29 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 beqzt r29, .Lresume_userspace
move r29, sp move r29, sp
...@@ -936,7 +947,7 @@ STD_ENTRY(interrupt_return) ...@@ -936,7 +947,7 @@ STD_ENTRY(interrupt_return)
PTREGS_PTR(r32, PTREGS_OFFSET_FLAGS) PTREGS_PTR(r32, PTREGS_OFFSET_FLAGS)
} }
{ {
andi r0, r0, SPR_EX_CONTEXT_1_1__PL_MASK IS_KERNEL_EX1(r0, r0)
ld r32, r32 ld r32, r32
} }
bnez r0, 1f bnez r0, 1f
...@@ -1007,7 +1018,7 @@ STD_ENTRY(interrupt_return) ...@@ -1007,7 +1018,7 @@ STD_ENTRY(interrupt_return)
pop_reg r21, sp, PTREGS_OFFSET_REG(31) - PTREGS_OFFSET_PC pop_reg r21, sp, PTREGS_OFFSET_REG(31) - PTREGS_OFFSET_PC
{ {
mtspr SPR_EX_CONTEXT_K_1, lr 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 mtspr SPR_EX_CONTEXT_K_0, r21
......
...@@ -103,7 +103,7 @@ static struct pt_regs *valid_fault_handler(struct KBacktraceIterator* kbt) ...@@ -103,7 +103,7 @@ static struct pt_regs *valid_fault_handler(struct KBacktraceIterator* kbt)
p->sp >= sp) { p->sp >= sp) {
if (kbt->verbose) if (kbt->verbose)
pr_err(" <%s while in kernel mode>\n", fault); 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) { p->sp < PAGE_OFFSET && p->sp != 0) {
if (kbt->verbose) if (kbt->verbose)
pr_err(" <%s while in user mode>\n", fault); pr_err(" <%s while in user mode>\n", fault);
......
...@@ -283,7 +283,7 @@ static int handle_page_fault(struct pt_regs *regs, ...@@ -283,7 +283,7 @@ static int handle_page_fault(struct pt_regs *regs,
flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
(write ? FAULT_FLAG_WRITE : 0)); (write ? FAULT_FLAG_WRITE : 0));
is_kernel_mode = (EX1_PL(regs->ex1) != USER_PL); is_kernel_mode = !user_mode(regs);
tsk = validate_current(); tsk = validate_current();
...@@ -824,7 +824,7 @@ void do_page_fault(struct pt_regs *regs, int fault_num, ...@@ -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 CHIP_HAS_TILE_DMA() || CHIP_HAS_SN_PROC()
if (EX1_PL(regs->ex1) != USER_PL) { if (!user_mode(regs)) {
struct async_tlb *async; struct async_tlb *async;
switch (fault_num) { switch (fault_num) {
#if CHIP_HAS_TILE_DMA() #if CHIP_HAS_TILE_DMA()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment