[RFC, PATCH 13/24] i386 Vmi system header

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Fairly straightforward code motion in system.h into the sub-arch
layer.  Affected functionality include control register accessors,
which are virtualizable but with great overhead due to the #GP
cost; wbinvd, and most importantly, halt and interrupt control,
which is non-virtualizable.

Since read_cr4_safe can never fault on a VMI kernel (P5+ processor
is required for VMI), we can omit the fault fixup, which does not
play well with the VMI inline assembler, and just call read_cr4()
directly.

Note that shutdown_halt is unused, but provided in case there is
really a use for it.  See arch/i386/kernel/smp.c for a potential
call site during AP shutdown.

Signed-off-by: Zachary Amsden <[email protected]>

Index: linux-2.6.16-rc5/include/asm-i386/system.h
===================================================================
--- linux-2.6.16-rc5.orig/include/asm-i386/system.h	2006-03-10 12:55:08.000000000 -0800
+++ linux-2.6.16-rc5/include/asm-i386/system.h	2006-03-10 13:03:36.000000000 -0800
@@ -9,6 +9,8 @@
 
 #ifdef __KERNEL__
 
+#include <mach_system.h>
+
 struct task_struct;	/* one of the stranger aspects of C forward declarations.. */
 extern struct task_struct * FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next));
 
@@ -83,69 +85,8 @@ __asm__ __volatile__ ("movw %%dx,%1\n\t"
 #define savesegment(seg, value) \
 	asm volatile("mov %%" #seg ",%0":"=rm" (value))
 
-/*
- * Clear and set 'TS' bit respectively
- */
-#define clts() __asm__ __volatile__ ("clts")
-#define read_cr0() ({ \
-	unsigned int __dummy; \
-	__asm__ __volatile__( \
-		"movl %%cr0,%0\n\t" \
-		:"=r" (__dummy)); \
-	__dummy; \
-})
-#define write_cr0(x) \
-	__asm__ __volatile__("movl %0,%%cr0": :"r" (x));
-
-#define read_cr2() ({ \
-	unsigned int __dummy; \
-	__asm__ __volatile__( \
-		"movl %%cr2,%0\n\t" \
-		:"=r" (__dummy)); \
-	__dummy; \
-})
-#define write_cr2(x) \
-	__asm__ __volatile__("movl %0,%%cr2": :"r" (x));
-
-#define read_cr3() ({ \
-	unsigned int __dummy; \
-	__asm__ ( \
-		"movl %%cr3,%0\n\t" \
-		:"=r" (__dummy)); \
-	__dummy; \
-})
-#define write_cr3(x) \
-	__asm__ __volatile__("movl %0,%%cr3": :"r" (x));
-
-#define read_cr4() ({ \
-	unsigned int __dummy; \
-	__asm__( \
-		"movl %%cr4,%0\n\t" \
-		:"=r" (__dummy)); \
-	__dummy; \
-})
-
-#define read_cr4_safe() ({			      \
-	unsigned int __dummy;			      \
-	/* This could fault if %cr4 does not exist */ \
-	__asm__("1: movl %%cr4, %0		\n"   \
-		"2:				\n"   \
-		".section __ex_table,\"a\"	\n"   \
-		".long 1b,2b			\n"   \
-		".previous			\n"   \
-		: "=r" (__dummy): "0" (0));	      \
-	__dummy;				      \
-})
-
-#define write_cr4(x) \
-	__asm__ __volatile__("movl %0,%%cr4": :"r" (x));
-#define stts() write_cr0(8 | read_cr0())
-
 #endif	/* __KERNEL__ */
 
-#define wbinvd() \
-	__asm__ __volatile__ ("wbinvd": : :"memory");
-
 static inline unsigned long get_limit(unsigned long segment)
 {
 	unsigned long __limit;
@@ -518,16 +459,7 @@ struct alt_instr { 
 
 #define set_wmb(var, value) do { var = value; wmb(); } while (0)
 
-/* interrupt control.. */
-#define local_save_flags(x)	do { typecheck(unsigned long,x); __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */); } while (0)
-#define local_irq_restore(x) 	do { typecheck(unsigned long,x); __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory", "cc"); } while (0)
-#define local_irq_disable() 	__asm__ __volatile__("cli": : :"memory")
-#define local_irq_enable()	__asm__ __volatile__("sti": : :"memory")
-/* used in the idle loop; sti takes one instruction cycle to complete */
-#define safe_halt()		__asm__ __volatile__("sti; hlt": : :"memory")
-/* used when interrupts are already enabled or to shutdown the processor */
-#define halt()			__asm__ __volatile__("hlt": : :"memory")
-
+#define local_irq_save(x) do { typecheck(unsigned long,x); local_save_flags(x); local_irq_disable(); } while (0)
 #define irqs_disabled()			\
 ({					\
 	unsigned long flags;		\
@@ -535,9 +467,6 @@ struct alt_instr { 
 	!(flags & (1<<9));		\
 })
 
-/* For spinlocks etc */
-#define local_irq_save(x)	__asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (x): /* no input */ :"memory")
-
 /*
  * disable hlt during certain critical i/o operations
  */
Index: linux-2.6.16-rc5/include/asm-i386/mach-vmi/mach_system.h
===================================================================
--- linux-2.6.16-rc5.orig/include/asm-i386/mach-vmi/mach_system.h	2006-03-10 13:03:36.000000000 -0800
+++ linux-2.6.16-rc5/include/asm-i386/mach-vmi/mach_system.h	2006-03-10 13:03:36.000000000 -0800
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2005, VMware, Inc.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Send feedback to [email protected]
+ *
+ */
+
+
+#ifndef _MACH_SYSTEM_H
+#define _MACH_SYSTEM_H
+
+#include <vmi.h>
+
+static inline void write_cr0(const u32 val)
+{
+	vmi_wrap_call(
+		SetCR0, "mov %0, %%cr0",
+		VMI_NO_OUTPUT,
+		1, VMI_IREG1(val),
+		VMI_CLOBBER_EXTENDED(ZERO_RETURNS, "memory"));
+}
+
+static inline void write_cr2(const u32 val)
+{
+	vmi_wrap_call(
+		SetCR2, "mov %0, %%cr2",
+		VMI_NO_OUTPUT,
+		1, VMI_IREG1(val),
+		VMI_CLOBBER_EXTENDED(ZERO_RETURNS, "memory"));
+}
+
+static inline void write_cr3(const u32 val)
+{
+	vmi_wrap_call(
+		SetCR3, "mov %0, %%cr3",
+		VMI_NO_OUTPUT,
+		1, VMI_IREG1(val),
+		VMI_CLOBBER_EXTENDED(ZERO_RETURNS, "memory"));
+}
+
+static inline void write_cr4(const u32 val)
+{
+	vmi_wrap_call(
+		SetCR4, "mov %0, %%cr4",
+		VMI_NO_OUTPUT,
+		1, VMI_IREG1(val),
+		VMI_CLOBBER_EXTENDED(ZERO_RETURNS, "memory"));
+}
+
+static inline u32 read_cr0(void)
+{
+	u32 ret;
+	vmi_wrap_call(
+		GetCR0, "mov %%cr0, %%eax",
+		VMI_OREG1(ret),
+		0, VMI_NO_INPUT,
+		VMI_CLOBBER(ONE_RETURN));
+	return ret;
+}
+
+static inline u32 read_cr2(void)
+{
+	u32 ret;
+	vmi_wrap_call(
+		GetCR2, "mov %%cr2, %%eax",
+		VMI_OREG1(ret),
+		0, VMI_NO_INPUT,
+		VMI_CLOBBER(ONE_RETURN));
+	return ret;
+}
+
+static inline u32 read_cr3(void)
+{
+	u32 ret;
+	vmi_wrap_call(
+		GetCR3, "mov %%cr3, %%eax",
+		VMI_OREG1(ret),
+		0, VMI_NO_INPUT,
+		VMI_CLOBBER(ONE_RETURN));
+	return ret;
+}
+
+static inline u32 read_cr4(void)
+{
+	u32 ret;
+	vmi_wrap_call(
+		GetCR4, "mov %%cr4, %%eax",
+		VMI_OREG1(ret),
+		0, VMI_NO_INPUT,
+		VMI_CLOBBER(ONE_RETURN));
+	return ret;
+}
+
+#define read_cr4_safe() read_cr4()
+#define load_cr3(pgdir) write_cr3(__pa(pgdir))
+
+static inline void clts(void)
+{
+	vmi_wrap_call(
+		CLTS, "clts",
+		VMI_NO_OUTPUT,
+		0, VMI_NO_INPUT,
+		VMI_CLOBBER(ZERO_RETURNS));
+}
+
+static inline void wbinvd(void)
+{
+	vmi_wrap_call(
+		WBINVD, "wbinvd",
+		VMI_NO_OUTPUT,
+		0, VMI_NO_INPUT,
+		VMI_CLOBBER_EXTENDED(ZERO_RETURNS, "memory"));
+}
+
+/* 
+ * For EnableInterrupts, DisableInterrupts, GetInterruptMask, SetInterruptMask,
+ * only flags are clobbered by these calls, since they have assembler call
+ * convention.  We can get better C code by indicating only "cc" clobber.
+ * Both setting and disabling interrupts must use memory clobber as well, to
+ * prevent GCC from reordering memory access around them.
+ */
+static inline void local_irq_disable(void)
+{
+	vmi_wrap_call(
+		DisableInterrupts, "cli",
+		VMI_NO_OUTPUT,
+		0, VMI_NO_INPUT,
+		XCONC("cc", "memory"));
+}
+
+static inline void local_irq_enable(void)
+{
+	vmi_wrap_call(
+		EnableInterrupts, "sti",
+		VMI_NO_OUTPUT,
+		0, VMI_NO_INPUT,
+		XCONC("cc", "memory"));
+}
+
+static inline void local_irq_restore(const unsigned long flags)
+{
+	vmi_wrap_call(
+		SetInterruptMask, "pushl %0; popfl",
+		VMI_NO_OUTPUT,
+		1, VMI_IREG1 (flags),
+		XCONC("cc", "memory"));
+}
+
+static inline unsigned long vmi_get_flags(void)
+{
+	unsigned long ret;
+	vmi_wrap_call(
+		GetInterruptMask, "pushfl; popl %%eax",
+		VMI_OREG1 (ret),
+		0, VMI_NO_INPUT,
+		"cc");
+	return ret;
+}
+
+#define local_save_flags(x)     do { typecheck(unsigned long,x); (x) = vmi_get_flags(); } while (0)
+
+static inline void vmi_reboot(int how)
+{
+	vmi_wrap_call(
+		Reboot, "",
+		VMI_NO_OUTPUT,
+		1, VMI_IREG1(how),
+		"memory"); /* only memory clobber for better code */
+}
+
+static inline void safe_halt(void)
+{
+	vmi_wrap_call(
+		Halt, "sti; hlt",
+		VMI_NO_OUTPUT,
+		0, VMI_NO_INPUT,
+		VMI_CLOBBER(ZERO_RETURNS));
+}
+
+/* By default, halt is assumed safe, but we can drop the sti */
+static inline void halt(void)
+{
+	vmi_wrap_call(
+		Halt, "hlt",
+		VMI_NO_OUTPUT,
+		0, VMI_NO_INPUT,
+		VMI_CLOBBER(ZERO_RETURNS));
+}
+
+static inline void shutdown_halt(void)
+{
+	vmi_wrap_call(
+		Shutdown, "cli; hlt",
+		VMI_NO_OUTPUT,
+		0, VMI_NO_INPUT,
+		"memory"); /* only memory clobber for better code */
+}
+
+#endif
Index: linux-2.6.16-rc5/include/asm-i386/mach-default/mach_system.h
===================================================================
--- linux-2.6.16-rc5.orig/include/asm-i386/mach-default/mach_system.h	2006-03-10 13:03:36.000000000 -0800
+++ linux-2.6.16-rc5/include/asm-i386/mach-default/mach_system.h	2006-03-10 16:00:38.000000000 -0800
@@ -0,0 +1,80 @@
+#ifndef _MACH_SYSTEM_H
+#define _MACH_SYSTEM_H
+
+#define clts() __asm__ __volatile__ ("clts")
+#define read_cr0() ({ \
+	unsigned int __dummy; \
+	__asm__  __volatile__( \
+		"movl %%cr0,%0\n\t" \
+		:"=r" (__dummy)); \
+	__dummy; \
+})
+
+#define write_cr0(x) \
+	__asm__ __volatile__("movl %0,%%cr0": :"r" (x));
+
+#define read_cr2() ({ \
+        unsigned int __dummy; \
+        __asm__  __volatile__( \
+                "movl %%cr2,%0\n\t" \
+                :"=r" (__dummy)); \
+        __dummy; \
+})
+#define write_cr2(x) \
+	__asm__  __volatile__("movl %0,%%cr2": :"r" (x));
+
+#define read_cr3() ({ \
+        unsigned int __dummy; \
+        __asm__( \
+                "movl %%cr3,%0\n\t" \
+                :"=r" (__dummy)); \
+        __dummy; \
+})
+#define write_cr3(x) \
+	__asm__ __volatile__("movl %0,%%cr3": :"r" (x));
+
+#define read_cr4() ({ \
+	unsigned int __dummy; \
+	__asm__( \
+		"movl %%cr4,%0\n\t" \
+		:"=r" (__dummy)); \
+	__dummy; \
+})
+
+#define read_cr4_safe() ({			      \
+	unsigned int __dummy;			      \
+	/* This could fault if %cr4 does not exist */ \
+	__asm__("1: movl %%cr4, %0		\n"   \
+		"2:				\n"   \
+		".section __ex_table,\"a\"	\n"   \
+		".long 1b,2b			\n"   \
+		".previous			\n"   \
+		: "=r" (__dummy): "0" (0));	      \
+	__dummy;				      \
+})
+
+#define write_cr4(x) \
+	__asm__ __volatile__("movl %0,%%cr4": :"r" (x));
+
+#define wbinvd() \
+	__asm__ __volatile__ ("wbinvd": : :"memory");
+
+/* interrupt control.. */
+#define local_save_flags(x)     do { typecheck(unsigned long,x); __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */); } while (0)
+
+/* For spinlocks etc */
+#define local_irq_restore(x)    do { typecheck(unsigned long,x); __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory", "cc"); } while (0)
+
+#define local_irq_disable()     __asm__ __volatile__("cli": : :"memory")
+#define local_irq_enable()      __asm__ __volatile__("sti": : :"memory")
+
+/* used in the idle loop; sti holds off interrupts for 1 instruction */
+#define safe_halt()             __asm__ __volatile__("sti; hlt": : :"memory")
+
+/* force shutdown of the processor; used when IRQs are disabled */
+#define shutdown_halt()		__asm__ __volatile__("hlt": : :"memory")
+
+/* halt until interrupted */
+#define halt()			__asm__ __volatile__("hlt")
+
+#endif
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux