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: Chris Metcalf <cmetcalf@tilera.com>
This commit is contained in:
parent
309272f99f
commit
051168df52
5 changed files with 23 additions and 12 deletions
|
@ -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 @@
|
||||||
#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;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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;
|
||||||
#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 @@
|
||||||
|
|
||||||
#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:
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
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:
|
||||||
/*
|
/*
|
||||||
* 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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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,
|
||||||
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
#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()
|
||||||
|
|
Loading…
Reference in a new issue