diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2006-09-26 04:52:39 -0400 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2006-09-26 04:52:39 -0400 |
commit | 78be3706b21a232310590fe00258b224177ac05f (patch) | |
tree | 57dbe444e57241613067145b04c0e15c98278cd6 /arch/i386/kernel/entry.S | |
parent | 0da5db313317e3195482d3e660a1074857374a89 (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 'arch/i386/kernel/entry.S')
-rw-r--r-- | arch/i386/kernel/entry.S | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index 3872fca5c74a..284f2e908ad0 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S | |||
@@ -240,8 +240,9 @@ ret_from_intr: | |||
240 | check_userspace: | 240 | check_userspace: |
241 | movl EFLAGS(%esp), %eax # mix EFLAGS and CS | 241 | movl EFLAGS(%esp), %eax # mix EFLAGS and CS |
242 | movb CS(%esp), %al | 242 | movb CS(%esp), %al |
243 | testl $(VM_MASK | 3), %eax | 243 | andl $(VM_MASK | SEGMENT_RPL_MASK), %eax |
244 | jz resume_kernel | 244 | cmpl $USER_RPL, %eax |
245 | jb resume_kernel # not returning to v8086 or userspace | ||
245 | ENTRY(resume_userspace) | 246 | ENTRY(resume_userspace) |
246 | DISABLE_INTERRUPTS # make sure we don't miss an interrupt | 247 | DISABLE_INTERRUPTS # make sure we don't miss an interrupt |
247 | # setting need_resched or sigpending | 248 | # setting need_resched or sigpending |
@@ -377,8 +378,8 @@ restore_all: | |||
377 | # See comments in process.c:copy_thread() for details. | 378 | # See comments in process.c:copy_thread() for details. |
378 | movb OLDSS(%esp), %ah | 379 | movb OLDSS(%esp), %ah |
379 | movb CS(%esp), %al | 380 | movb CS(%esp), %al |
380 | andl $(VM_MASK | (4 << 8) | 3), %eax | 381 | andl $(VM_MASK | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax |
381 | cmpl $((4 << 8) | 3), %eax | 382 | cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax |
382 | CFI_REMEMBER_STATE | 383 | CFI_REMEMBER_STATE |
383 | je ldt_ss # returning to user-space with LDT SS | 384 | je ldt_ss # returning to user-space with LDT SS |
384 | restore_nocheck: | 385 | restore_nocheck: |