diff options
author | Chris Metcalf <cmetcalf@tilera.com> | 2013-09-03 14:45:52 -0400 |
---|---|---|
committer | Chris Metcalf <cmetcalf@tilera.com> | 2013-09-03 14:45:52 -0400 |
commit | 051168df528fe4456d63f5f65b041c147c26fe97 (patch) | |
tree | 789109ca42db49bf4d8c0c2794cf55659a171a39 | |
parent | 309272f99f3e65b9bb5c49a2901c63a1859172f3 (diff) |
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>
-rw-r--r-- | arch/tile/include/asm/processor.h | 4 | ||||
-rw-r--r-- | arch/tile/include/asm/ptrace.h | 2 | ||||
-rw-r--r-- | arch/tile/kernel/intvec_64.S | 23 | ||||
-rw-r--r-- | arch/tile/kernel/stack.c | 2 | ||||
-rw-r--r-- | arch/tile/mm/fault.c | 4 |
5 files changed, 23 insertions, 12 deletions
diff --git a/arch/tile/include/asm/processor.h b/arch/tile/include/asm/processor.h index 230b830e94d4..c72fcba7016a 100644 --- a/arch/tile/include/asm/processor.h +++ b/arch/tile/include/asm/processor.h | |||
@@ -15,6 +15,8 @@ | |||
15 | #ifndef _ASM_TILE_PROCESSOR_H | 15 | #ifndef _ASM_TILE_PROCESSOR_H |
16 | #define _ASM_TILE_PROCESSOR_H | 16 | #define _ASM_TILE_PROCESSOR_H |
17 | 17 | ||
18 | #include <arch/chip.h> | ||
19 | |||
18 | #ifndef __ASSEMBLY__ | 20 | #ifndef __ASSEMBLY__ |
19 | 21 | ||
20 | /* | 22 | /* |
@@ -25,7 +27,6 @@ | |||
25 | #include <asm/ptrace.h> | 27 | #include <asm/ptrace.h> |
26 | #include <asm/percpu.h> | 28 | #include <asm/percpu.h> |
27 | 29 | ||
28 | #include <arch/chip.h> | ||
29 | #include <arch/spr_def.h> | 30 | #include <arch/spr_def.h> |
30 | 31 | ||
31 | struct task_struct; | 32 | struct task_struct; |
@@ -347,7 +348,6 @@ extern int kdata_huge; | |||
347 | 348 | ||
348 | /* | 349 | /* |
349 | * Provide symbolic constants for PLs. | 350 | * Provide symbolic constants for PLs. |
350 | * Note that assembly code assumes that USER_PL is zero. | ||
351 | */ | 351 | */ |
352 | #define USER_PL 0 | 352 | #define USER_PL 0 |
353 | #if CONFIG_KERNEL_PL == 2 | 353 | #if CONFIG_KERNEL_PL == 2 |
diff --git a/arch/tile/include/asm/ptrace.h b/arch/tile/include/asm/ptrace.h index 0d25c21bcd61..b9620c077abc 100644 --- a/arch/tile/include/asm/ptrace.h +++ b/arch/tile/include/asm/ptrace.h | |||
@@ -39,7 +39,7 @@ typedef unsigned long pt_reg_t; | |||
39 | #define user_stack_pointer(regs) ((regs)->sp) | 39 | #define user_stack_pointer(regs) ((regs)->sp) |
40 | 40 | ||
41 | /* Does the process account for user or for system time? */ | 41 | /* Does the process account for user or for system time? */ |
42 | #define user_mode(regs) (EX1_PL((regs)->ex1) == USER_PL) | 42 | #define user_mode(regs) (EX1_PL((regs)->ex1) < KERNEL_PL) |
43 | 43 | ||
44 | /* Fill in a struct pt_regs with the current kernel registers. */ | 44 | /* Fill in a struct pt_regs with the current kernel registers. */ |
45 | struct pt_regs *get_pt_regs(struct pt_regs *); | 45 | struct pt_regs *get_pt_regs(struct pt_regs *); |
diff --git a/arch/tile/kernel/intvec_64.S b/arch/tile/kernel/intvec_64.S index 3b35bb490d3e..f020f01960cf 100644 --- a/arch/tile/kernel/intvec_64.S +++ b/arch/tile/kernel/intvec_64.S | |||
@@ -34,6 +34,16 @@ | |||
34 | 34 | ||
35 | #define PTREGS_OFFSET_SYSCALL PTREGS_OFFSET_REG(TREG_SYSCALL_NR) | 35 | #define PTREGS_OFFSET_SYSCALL PTREGS_OFFSET_REG(TREG_SYSCALL_NR) |
36 | 36 | ||
37 | #if CONFIG_KERNEL_PL == 1 || CONFIG_KERNEL_PL == 2 | ||
38 | /* | ||
39 | * Set "result" non-zero if ex1 holds the PL of the kernel | ||
40 | * (with or without ICS being set). Note this works only | ||
41 | * because we never find the PL at level 3. | ||
42 | */ | ||
43 | # define IS_KERNEL_EX1(result, ex1) andi result, ex1, CONFIG_KERNEL_PL | ||
44 | #else | ||
45 | # error Recode IS_KERNEL_EX1 for CONFIG_KERNEL_PL | ||
46 | #endif | ||
37 | 47 | ||
38 | .macro push_reg reg, ptr=sp, delta=-8 | 48 | .macro push_reg reg, ptr=sp, delta=-8 |
39 | { | 49 | { |
@@ -308,7 +318,7 @@ intvec_\vecname: | |||
308 | */ | 318 | */ |
309 | { | 319 | { |
310 | blbs sp, 2f | 320 | blbs sp, 2f |
311 | andi r0, r0, SPR_EX_CONTEXT_1_1__PL_MASK /* mask off ICS */ | 321 | IS_KERNEL_EX1(r0, r0) |
312 | } | 322 | } |
313 | 323 | ||
314 | .ifc \vecnum, INT_DOUBLE_FAULT | 324 | .ifc \vecnum, INT_DOUBLE_FAULT |
@@ -641,11 +651,12 @@ intvec_\vecname: | |||
641 | /* | 651 | /* |
642 | * If we will be returning to the kernel, we will need to | 652 | * If we will be returning to the kernel, we will need to |
643 | * reset the interrupt masks to the state they had before. | 653 | * reset the interrupt masks to the state they had before. |
644 | * Set DISABLE_IRQ in flags iff we came from PL1 with irqs disabled. | 654 | * Set DISABLE_IRQ in flags iff we came from kernel pl with |
655 | * irqs disabled. | ||
645 | */ | 656 | */ |
646 | mfspr r32, SPR_EX_CONTEXT_K_1 | 657 | mfspr r32, SPR_EX_CONTEXT_K_1 |
647 | { | 658 | { |
648 | andi r32, r32, SPR_EX_CONTEXT_1_1__PL_MASK /* mask off ICS */ | 659 | IS_KERNEL_EX1(r22, r22) |
649 | PTREGS_PTR(r21, PTREGS_OFFSET_FLAGS) | 660 | PTREGS_PTR(r21, PTREGS_OFFSET_FLAGS) |
650 | } | 661 | } |
651 | beqzt r32, 1f /* zero if from user space */ | 662 | beqzt r32, 1f /* zero if from user space */ |
@@ -812,7 +823,7 @@ STD_ENTRY(interrupt_return) | |||
812 | PTREGS_PTR(r29, PTREGS_OFFSET_EX1) | 823 | PTREGS_PTR(r29, PTREGS_OFFSET_EX1) |
813 | } | 824 | } |
814 | ld r29, r29 | 825 | ld r29, r29 |
815 | andi r29, r29, SPR_EX_CONTEXT_1_1__PL_MASK /* mask off ICS */ | 826 | IS_KERNEL_EX1(r29, r29) |
816 | { | 827 | { |
817 | beqzt r29, .Lresume_userspace | 828 | beqzt r29, .Lresume_userspace |
818 | move r29, sp | 829 | move r29, sp |
@@ -936,7 +947,7 @@ STD_ENTRY(interrupt_return) | |||
936 | PTREGS_PTR(r32, PTREGS_OFFSET_FLAGS) | 947 | PTREGS_PTR(r32, PTREGS_OFFSET_FLAGS) |
937 | } | 948 | } |
938 | { | 949 | { |
939 | andi r0, r0, SPR_EX_CONTEXT_1_1__PL_MASK | 950 | IS_KERNEL_EX1(r0, r0) |
940 | ld r32, r32 | 951 | ld r32, r32 |
941 | } | 952 | } |
942 | bnez r0, 1f | 953 | bnez r0, 1f |
@@ -1007,7 +1018,7 @@ STD_ENTRY(interrupt_return) | |||
1007 | pop_reg r21, sp, PTREGS_OFFSET_REG(31) - PTREGS_OFFSET_PC | 1018 | pop_reg r21, sp, PTREGS_OFFSET_REG(31) - PTREGS_OFFSET_PC |
1008 | { | 1019 | { |
1009 | mtspr SPR_EX_CONTEXT_K_1, lr | 1020 | mtspr SPR_EX_CONTEXT_K_1, lr |
1010 | andi lr, lr, SPR_EX_CONTEXT_1_1__PL_MASK /* mask off ICS */ | 1021 | IS_KERNEL_EX1(lr, lr) |
1011 | } | 1022 | } |
1012 | { | 1023 | { |
1013 | mtspr SPR_EX_CONTEXT_K_0, r21 | 1024 | mtspr SPR_EX_CONTEXT_K_0, r21 |
diff --git a/arch/tile/kernel/stack.c b/arch/tile/kernel/stack.c index 24fd223df65d..362284af3afd 100644 --- a/arch/tile/kernel/stack.c +++ b/arch/tile/kernel/stack.c | |||
@@ -103,7 +103,7 @@ static struct pt_regs *valid_fault_handler(struct KBacktraceIterator* kbt) | |||
103 | p->sp >= sp) { | 103 | p->sp >= sp) { |
104 | if (kbt->verbose) | 104 | if (kbt->verbose) |
105 | pr_err(" <%s while in kernel mode>\n", fault); | 105 | pr_err(" <%s while in kernel mode>\n", fault); |
106 | } else if (EX1_PL(p->ex1) == USER_PL && | 106 | } else if (user_mode(p) && |
107 | p->sp < PAGE_OFFSET && p->sp != 0) { | 107 | p->sp < PAGE_OFFSET && p->sp != 0) { |
108 | if (kbt->verbose) | 108 | if (kbt->verbose) |
109 | pr_err(" <%s while in user mode>\n", fault); | 109 | pr_err(" <%s while in user mode>\n", fault); |
diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c index 64eec3f9584f..39c48cbe0a96 100644 --- a/arch/tile/mm/fault.c +++ b/arch/tile/mm/fault.c | |||
@@ -283,7 +283,7 @@ static int handle_page_fault(struct pt_regs *regs, | |||
283 | flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | | 283 | flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | |
284 | (write ? FAULT_FLAG_WRITE : 0)); | 284 | (write ? FAULT_FLAG_WRITE : 0)); |
285 | 285 | ||
286 | is_kernel_mode = (EX1_PL(regs->ex1) != USER_PL); | 286 | is_kernel_mode = !user_mode(regs); |
287 | 287 | ||
288 | tsk = validate_current(); | 288 | tsk = validate_current(); |
289 | 289 | ||
@@ -824,7 +824,7 @@ void do_page_fault(struct pt_regs *regs, int fault_num, | |||
824 | } | 824 | } |
825 | 825 | ||
826 | #if CHIP_HAS_TILE_DMA() || CHIP_HAS_SN_PROC() | 826 | #if CHIP_HAS_TILE_DMA() || CHIP_HAS_SN_PROC() |
827 | if (EX1_PL(regs->ex1) != USER_PL) { | 827 | if (!user_mode(regs)) { |
828 | struct async_tlb *async; | 828 | struct async_tlb *async; |
829 | switch (fault_num) { | 829 | switch (fault_num) { |
830 | #if CHIP_HAS_TILE_DMA() | 830 | #if CHIP_HAS_TILE_DMA() |