aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-i386
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2006-09-26 04:52:39 -0400
committerAndi Kleen <andi@basil.nowhere.org>2006-09-26 04:52:39 -0400
commit78be3706b21a232310590fe00258b224177ac05f (patch)
tree57dbe444e57241613067145b04c0e15c98278cd6 /include/asm-i386
parent0da5db313317e3195482d3e660a1074857374a89 (diff)
[PATCH] i386: Allow a kernel not to be in ring 0
We allow for the fact that the guest kernel may not run in ring 0. This requires some abstraction in a few places when setting %cs or checking privilege level (user vs kernel). This is Chris' [RFC PATCH 15/33] move segment checks to subarch, except rather than using #define USER_MODE_MASK which depends on a config option, we use Zach's more flexible approach of assuming ring 3 == userspace. I also used "get_kernel_rpl()" over "get_kernel_cs()" because I think it reads better in the code... 1) Remove the hardcoded 3 and introduce #define SEGMENT_RPL_MASK 3 2) Add a get_kernel_rpl() macro, and don't assume it's zero. And: Clean up of patch for letting kernel run other than ring 0: a. Add some comments about the SEGMENT_IS_*_CODE() macros. b. Add a USER_RPL macro. (Code was comparing a value to a mask in some places and to the magic number 3 in other places.) c. Add macros for table indicator field and use them. d. Change the entry.S tests for LDT stack segment to use the macros Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: Zachary Amsden <zach@vmware.com> Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Andi Kleen <ak@suse.de>
Diffstat (limited to 'include/asm-i386')
-rw-r--r--include/asm-i386/ptrace.h5
-rw-r--r--include/asm-i386/segment.h17
2 files changed, 20 insertions, 2 deletions
diff --git a/include/asm-i386/ptrace.h b/include/asm-i386/ptrace.h
index 30a442ec2059..21bb91679c82 100644
--- a/include/asm-i386/ptrace.h
+++ b/include/asm-i386/ptrace.h
@@ -60,6 +60,7 @@ struct pt_regs {
60#ifdef __KERNEL__ 60#ifdef __KERNEL__
61 61
62#include <asm/vm86.h> 62#include <asm/vm86.h>
63#include <asm/segment.h>
63 64
64struct task_struct; 65struct task_struct;
65extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code); 66extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code);
@@ -73,11 +74,11 @@ extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int erro
73 */ 74 */
74static inline int user_mode(struct pt_regs *regs) 75static inline int user_mode(struct pt_regs *regs)
75{ 76{
76 return (regs->xcs & 3) != 0; 77 return (regs->xcs & SEGMENT_RPL_MASK) == USER_RPL;
77} 78}
78static inline int user_mode_vm(struct pt_regs *regs) 79static inline int user_mode_vm(struct pt_regs *regs)
79{ 80{
80 return ((regs->xcs & 3) | (regs->eflags & VM_MASK)) != 0; 81 return ((regs->xcs & SEGMENT_RPL_MASK) | (regs->eflags & VM_MASK)) >= USER_RPL;
81} 82}
82#define instruction_pointer(regs) ((regs)->eip) 83#define instruction_pointer(regs) ((regs)->eip)
83extern unsigned long profile_pc(struct pt_regs *regs); 84extern unsigned long profile_pc(struct pt_regs *regs);
diff --git a/include/asm-i386/segment.h b/include/asm-i386/segment.h
index faf995307b9e..b7ab59685ba7 100644
--- a/include/asm-i386/segment.h
+++ b/include/asm-i386/segment.h
@@ -83,6 +83,11 @@
83 83
84#define GDT_SIZE (GDT_ENTRIES * 8) 84#define GDT_SIZE (GDT_ENTRIES * 8)
85 85
86/* Matches __KERNEL_CS and __USER_CS (they must be 2 entries apart) */
87#define SEGMENT_IS_FLAT_CODE(x) (((x) & 0xec) == GDT_ENTRY_KERNEL_CS * 8)
88/* Matches PNP_CS32 and PNP_CS16 (they must be consecutive) */
89#define SEGMENT_IS_PNP_CODE(x) (((x) & 0xf4) == GDT_ENTRY_PNPBIOS_BASE * 8)
90
86/* Simple and small GDT entries for booting only */ 91/* Simple and small GDT entries for booting only */
87 92
88#define GDT_ENTRY_BOOT_CS 2 93#define GDT_ENTRY_BOOT_CS 2
@@ -112,4 +117,16 @@
112 */ 117 */
113#define IDT_ENTRIES 256 118#define IDT_ENTRIES 256
114 119
120/* Bottom two bits of selector give the ring privilege level */
121#define SEGMENT_RPL_MASK 0x3
122/* Bit 2 is table indicator (LDT/GDT) */
123#define SEGMENT_TI_MASK 0x4
124
125/* User mode is privilege level 3 */
126#define USER_RPL 0x3
127/* LDT segment has TI set, GDT has it cleared */
128#define SEGMENT_LDT 0x4
129#define SEGMENT_GDT 0x0
130
131#define get_kernel_rpl() 0
115#endif 132#endif