public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] 7/8 Create accessors that allow the i386 kernel to run at CPLs 0-2
@ 2005-08-06  7:21 Zachary Amsden
  2005-08-07  1:14 ` Chris Wright
  0 siblings, 1 reply; 2+ messages in thread
From: Zachary Amsden @ 2005-08-06  7:21 UTC (permalink / raw)
  To: akpm, chrisw, linux-kernel, davej, hpa, Riley, pratap, zach,
	chrisl

[-- Attachment #1: Type: text/plain, Size: 1 bytes --]



[-- Attachment #2: subarch-segment --]
[-- Type: text/plain, Size: 4368 bytes --]

i386 Transparent paravirtualization subarch patch #7.

These changes allow a sub-architecture to change the notion of privilege
by running the kernel at CPL 0, 1, or 2.  The make_kernel_segment() macro
can be redefined by a subarchitecture to change the RPL on kernel segments
to the appropriate value, and the tests user_mode() and user_mode_vm()
may be similarly overridden.

Changes to the assembly code are required to fully support this, and
provided in a separate patch.

Diffs against: 2.6.13-rc4-mm1

Signed-off-by: Zachary Amsden <zach@vmware.com>
Index: linux-2.6.13/arch/i386/kernel/process.c
===================================================================
--- linux-2.6.13.orig/arch/i386/kernel/process.c	2005-08-03 23:37:25.000000000 -0700
+++ linux-2.6.13/arch/i386/kernel/process.c	2005-08-04 10:04:42.000000000 -0700
@@ -356,7 +356,7 @@
 	regs.xes = __USER_DS;
 	regs.orig_eax = -1;
 	regs.eip = (unsigned long) kernel_thread_helper;
-	regs.xcs = __KERNEL_CS;
+	regs.xcs = make_kernel_segment(__KERNEL_CS);
 	regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2;
 
 	/* Ok, create the new process.. */
Index: linux-2.6.13/arch/i386/kernel/traps.c
===================================================================
--- linux-2.6.13.orig/arch/i386/kernel/traps.c	2005-08-03 23:36:46.000000000 -0700
+++ linux-2.6.13/arch/i386/kernel/traps.c	2005-08-04 10:04:42.000000000 -0700
@@ -1025,10 +1025,10 @@
 	memcpy((void *)(stack_bot + iret_frame16_off), &regs->eip, 20);
 	/* fill in the switch pointers */
 	switch16_ptr[0] = (regs->esp & 0xffff0000) | iret_frame16_off;
-	switch16_ptr[1] = __ESPFIX_SS;
+	switch16_ptr[1] = make_kernel_segment(__ESPFIX_SS);
 	switch32_ptr[0] = (unsigned long)stk + sizeof(struct pt_regs) +
 		8 - CPU_16BIT_STACK_SIZE;
-	switch32_ptr[1] = __KERNEL_DS;
+	switch32_ptr[1] = make_kernel_segment(__KERNEL_DS);
 }
 
 fastcall unsigned char * fixup_x86_bogus_stack(unsigned short sp)
Index: linux-2.6.13/include/asm-i386/ptrace.h
===================================================================
--- linux-2.6.13.orig/include/asm-i386/ptrace.h	2005-08-03 23:36:46.000000000 -0700
+++ linux-2.6.13/include/asm-i386/ptrace.h	2005-08-04 10:04:42.000000000 -0700
@@ -57,25 +57,11 @@
 #ifdef __KERNEL__
 
 #include <asm/vm86.h>
+#include <mach_segment.h>
 
 struct task_struct;
 extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code);
 
-/*
- * user_mode_vm(regs) determines whether a register set came from user mode.
- * This is true if V8086 mode was enabled OR if the register set was from
- * protected mode with RPL-3 CS value.  This tricky test checks that with
- * one comparison.  Many places in the kernel can bypass this full check
- * if they have already ruled out V8086 mode, so user_mode(regs) can be used.
- */
-static inline int user_mode(struct pt_regs *regs)
-{
-	return (regs->xcs & 3) != 0;
-}
-static inline int user_mode_vm(struct pt_regs *regs)
-{
-	return ((regs->xcs & 3) | (regs->eflags & VM_MASK)) != 0;
-}
 #define instruction_pointer(regs) ((regs)->eip)
 #if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER)
 extern unsigned long profile_pc(struct pt_regs *regs);
Index: linux-2.6.13/include/asm-i386/mach-default/mach_segment.h
===================================================================
--- linux-2.6.13.orig/include/asm-i386/mach-default/mach_segment.h	2005-08-04 10:04:42.000000000 -0700
+++ linux-2.6.13/include/asm-i386/mach-default/mach_segment.h	2005-08-04 10:05:17.000000000 -0700
@@ -0,0 +1,28 @@
+/*
+ * include/asm-i386/mach-default/mach_segment.h
+ *
+ * user_mode macros moved from include/asm-i386/ptrace.h 08/05
+ */
+
+#ifndef __MACH_SEGMENT_H
+#define __MACH_SEGMENT_H
+
+/*
+ * user_mode_vm(regs) determines whether a register set came from user mode.
+ * This is true if V8086 mode was enabled OR if the register set was from
+ * protected mode with RPL-3 CS value.  This tricky test checks that with
+ * one comparison.  Many places in the kernel can bypass this full check
+ * if they have already ruled out V8086 mode, so user_mode(regs) can be used.
+ */
+static inline int user_mode(struct pt_regs *regs)
+{
+	return (regs->xcs & 3) != 0;
+}
+static inline int user_mode_vm(struct pt_regs *regs)
+{
+	return ((regs->xcs & 3) | (regs->eflags & VM_MASK)) != 0;
+}
+
+#define make_kernel_segment(seg)	(seg)
+
+#endif

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] 7/8 Create accessors that allow the i386 kernel to run at CPLs 0-2
  2005-08-06  7:21 [PATCH] 7/8 Create accessors that allow the i386 kernel to run at CPLs 0-2 Zachary Amsden
@ 2005-08-07  1:14 ` Chris Wright
  0 siblings, 0 replies; 2+ messages in thread
From: Chris Wright @ 2005-08-07  1:14 UTC (permalink / raw)
  To: Zachary Amsden
  Cc: akpm, chrisw, linux-kernel, davej, hpa, Riley, pratap, chrisl

* Zachary Amsden (zach@vmware.com) wrote:
> These changes allow a sub-architecture to change the notion of privilege
> by running the kernel at CPL 0, 1, or 2.  The make_kernel_segment() macro
> can be redefined by a subarchitecture to change the RPL on kernel segments
> to the appropriate value, and the tests user_mode() and user_mode_vm()
> may be similarly overridden.

No issue here, but there's some overlap from my side that needs merging
(note, as with all the others, mine are against 2.6.12, to user_mode(),
for example, has changed since then).  Also note, the segment bit is
still much too heavy handed on my side (looks like you are generally
further along than I am ;-) so I still have some refactoring to do.


--- linux-2.6.12-xen0-arch.orig/include/asm-i386/ptrace.h
+++ linux-2.6.12-xen0-arch/include/asm-i386/ptrace.h
@@ -55,9 +55,9 @@ struct pt_regs {
 #define PTRACE_SET_THREAD_AREA    26
 
 #ifdef __KERNEL__
+#include <mach_ptrace.h>
 struct task_struct;
 extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code);
-#define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs))
 #define instruction_pointer(regs) ((regs)->eip)
 #if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER)
 extern unsigned long profile_pc(struct pt_regs *regs);
--- /dev/null
+++ linux-2.6.12-xen0-arch/include/asm-i386/mach-default/mach_ptrace.h
@@ -0,0 +1,6 @@
+#ifndef __ASM_MACH_PTRACE_H
+#define __ASM_MACH_PTRACE_H
+
+#define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs))
+
+#endif
--- linux-2.6.12-xen0-arch.orig/include/asm-i386/segment.h
+++ linux-2.6.12-xen0-arch/include/asm-i386/segment.h
@@ -1,101 +1,6 @@
 #ifndef _ASM_SEGMENT_H
 #define _ASM_SEGMENT_H
 
-/*
- * The layout of the per-CPU GDT under Linux:
- *
- *   0 - null
- *   1 - reserved
- *   2 - reserved
- *   3 - reserved
- *
- *   4 - unused			<==== new cacheline
- *   5 - unused
- *
- *  ------- start of TLS (Thread-Local Storage) segments:
- *
- *   6 - TLS segment #1			[ glibc's TLS segment ]
- *   7 - TLS segment #2			[ Wine's %fs Win32 segment ]
- *   8 - TLS segment #3
- *   9 - reserved
- *  10 - reserved
- *  11 - reserved
- *
- *  ------- start of kernel segments:
- *
- *  12 - kernel code segment		<==== new cacheline
- *  13 - kernel data segment
- *  14 - default user CS
- *  15 - default user DS
- *  16 - TSS
- *  17 - LDT
- *  18 - PNPBIOS support (16->32 gate)
- *  19 - PNPBIOS support
- *  20 - PNPBIOS support
- *  21 - PNPBIOS support
- *  22 - PNPBIOS support
- *  23 - APM BIOS support
- *  24 - APM BIOS support
- *  25 - APM BIOS support 
- *
- *  26 - ESPFIX small SS
- *  27 - unused
- *  28 - unused
- *  29 - unused
- *  30 - unused
- *  31 - TSS for double fault handler
- */
-#define GDT_ENTRY_TLS_ENTRIES	3
-#define GDT_ENTRY_TLS_MIN	6
-#define GDT_ENTRY_TLS_MAX 	(GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1)
-
-#define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES * 8)
-
-#define GDT_ENTRY_DEFAULT_USER_CS	14
-#define __USER_CS (GDT_ENTRY_DEFAULT_USER_CS * 8 + 3)
-
-#define GDT_ENTRY_DEFAULT_USER_DS	15
-#define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS * 8 + 3)
-
-#define GDT_ENTRY_KERNEL_BASE	12
-
-#define GDT_ENTRY_KERNEL_CS		(GDT_ENTRY_KERNEL_BASE + 0)
-#define __KERNEL_CS (GDT_ENTRY_KERNEL_CS * 8)
-
-#define GDT_ENTRY_KERNEL_DS		(GDT_ENTRY_KERNEL_BASE + 1)
-#define __KERNEL_DS (GDT_ENTRY_KERNEL_DS * 8)
-
-#define GDT_ENTRY_TSS			(GDT_ENTRY_KERNEL_BASE + 4)
-#define GDT_ENTRY_LDT			(GDT_ENTRY_KERNEL_BASE + 5)
-
-#define GDT_ENTRY_PNPBIOS_BASE		(GDT_ENTRY_KERNEL_BASE + 6)
-#define GDT_ENTRY_APMBIOS_BASE		(GDT_ENTRY_KERNEL_BASE + 11)
-
-#define GDT_ENTRY_ESPFIX_SS		(GDT_ENTRY_KERNEL_BASE + 14)
-#define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS * 8)
-
-#define GDT_ENTRY_DOUBLEFAULT_TSS	31
-
-/*
- * The GDT has 32 entries
- */
-#define GDT_ENTRIES 32
-
-#define GDT_SIZE (GDT_ENTRIES * 8)
-
-/* Simple and small GDT entries for booting only */
-
-#define GDT_ENTRY_BOOT_CS		2
-#define __BOOT_CS	(GDT_ENTRY_BOOT_CS * 8)
-
-#define GDT_ENTRY_BOOT_DS		(GDT_ENTRY_BOOT_CS + 1)
-#define __BOOT_DS	(GDT_ENTRY_BOOT_DS * 8)
-
-/*
- * The interrupt descriptor table has room for 256 idt's,
- * the global descriptor table is dependent on the number
- * of tasks we can have..
- */
-#define IDT_ENTRIES 256
+#include <mach_segment.h>
 
 #endif
--- /dev/null
+++ linux-2.6.12-xen0-arch/include/asm-i386/mach-default/mach_segment.h
@@ -0,0 +1,101 @@
+#ifndef _ASM_MACH_SEGMENT_H
+#define _ASM_MACH_SEGMENT_H
+
+/*
+ * The layout of the per-CPU GDT under Linux:
+ *
+ *   0 - null
+ *   1 - reserved
+ *   2 - reserved
+ *   3 - reserved
+ *
+ *   4 - unused			<==== new cacheline
+ *   5 - unused
+ *
+ *  ------- start of TLS (Thread-Local Storage) segments:
+ *
+ *   6 - TLS segment #1			[ glibc's TLS segment ]
+ *   7 - TLS segment #2			[ Wine's %fs Win32 segment ]
+ *   8 - TLS segment #3
+ *   9 - reserved
+ *  10 - reserved
+ *  11 - reserved
+ *
+ *  ------- start of kernel segments:
+ *
+ *  12 - kernel code segment		<==== new cacheline
+ *  13 - kernel data segment
+ *  14 - default user CS
+ *  15 - default user DS
+ *  16 - TSS
+ *  17 - LDT
+ *  18 - PNPBIOS support (16->32 gate)
+ *  19 - PNPBIOS support
+ *  20 - PNPBIOS support
+ *  21 - PNPBIOS support
+ *  22 - PNPBIOS support
+ *  23 - APM BIOS support
+ *  24 - APM BIOS support
+ *  25 - APM BIOS support 
+ *
+ *  26 - ESPFIX small SS
+ *  27 - unused
+ *  28 - unused
+ *  29 - unused
+ *  30 - unused
+ *  31 - TSS for double fault handler
+ */
+#define GDT_ENTRY_TLS_ENTRIES	3
+#define GDT_ENTRY_TLS_MIN	6
+#define GDT_ENTRY_TLS_MAX 	(GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1)
+
+#define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES * 8)
+
+#define GDT_ENTRY_DEFAULT_USER_CS	14
+#define __USER_CS (GDT_ENTRY_DEFAULT_USER_CS * 8 + 3)
+
+#define GDT_ENTRY_DEFAULT_USER_DS	15
+#define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS * 8 + 3)
+
+#define GDT_ENTRY_KERNEL_BASE	12
+
+#define GDT_ENTRY_KERNEL_CS		(GDT_ENTRY_KERNEL_BASE + 0)
+#define __KERNEL_CS (GDT_ENTRY_KERNEL_CS * 8)
+
+#define GDT_ENTRY_KERNEL_DS		(GDT_ENTRY_KERNEL_BASE + 1)
+#define __KERNEL_DS (GDT_ENTRY_KERNEL_DS * 8)
+
+#define GDT_ENTRY_TSS			(GDT_ENTRY_KERNEL_BASE + 4)
+#define GDT_ENTRY_LDT			(GDT_ENTRY_KERNEL_BASE + 5)
+
+#define GDT_ENTRY_PNPBIOS_BASE		(GDT_ENTRY_KERNEL_BASE + 6)
+#define GDT_ENTRY_APMBIOS_BASE		(GDT_ENTRY_KERNEL_BASE + 11)
+
+#define GDT_ENTRY_ESPFIX_SS		(GDT_ENTRY_KERNEL_BASE + 14)
+#define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS * 8)
+
+#define GDT_ENTRY_DOUBLEFAULT_TSS	31
+
+/*
+ * The GDT has 32 entries
+ */
+#define GDT_ENTRIES 32
+
+#define GDT_SIZE (GDT_ENTRIES * 8)
+
+/* Simple and small GDT entries for booting only */
+
+#define GDT_ENTRY_BOOT_CS		2
+#define __BOOT_CS	(GDT_ENTRY_BOOT_CS * 8)
+
+#define GDT_ENTRY_BOOT_DS		(GDT_ENTRY_BOOT_CS + 1)
+#define __BOOT_DS	(GDT_ENTRY_BOOT_DS * 8)
+
+/*
+ * The interrupt descriptor table has room for 256 idt's,
+ * the global descriptor table is dependent on the number
+ * of tasks we can have..
+ */
+#define IDT_ENTRIES 256
+
+#endif

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2005-08-07  1:17 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-08-06  7:21 [PATCH] 7/8 Create accessors that allow the i386 kernel to run at CPLs 0-2 Zachary Amsden
2005-08-07  1:14 ` Chris Wright

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox