浏览代码

x86: introduce vsmp paravirt helpers

Signed-off-by: Glauber Costa <gcosta@redhat.com>
Signed-off-by: Ravikiran Thirumalai <kiran@scalemp.com>
Acked-by: Shai Fultheim <shai@scalemp.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Glauber Costa 17 年之前
父节点
当前提交
96597fd2be
共有 2 个文件被更改,包括 58 次插入1 次删除
  1. 2 1
      arch/x86/Kconfig
  2. 56 0
      arch/x86/kernel/vsmp_64.c

+ 2 - 1
arch/x86/Kconfig

@@ -328,7 +328,8 @@ config X86_RDC321X
 config X86_VSMP
 config X86_VSMP
 	bool "Support for ScaleMP vSMP"
 	bool "Support for ScaleMP vSMP"
 	depends on X86_64 && PCI
 	depends on X86_64 && PCI
-	 help
+	select PARAVIRT
+	help
 	  Support for ScaleMP vSMP systems.  Say 'Y' here if this kernel is
 	  Support for ScaleMP vSMP systems.  Say 'Y' here if this kernel is
 	  supposed to run on these EM64T-based machines.  Only choose this option
 	  supposed to run on these EM64T-based machines.  Only choose this option
 	  if you have one of these machines.
 	  if you have one of these machines.

+ 56 - 0
arch/x86/kernel/vsmp_64.c

@@ -8,6 +8,8 @@
  *
  *
  * Ravikiran Thirumalai <kiran@scalemp.com>,
  * Ravikiran Thirumalai <kiran@scalemp.com>,
  * Shai Fultheim <shai@scalemp.com>
  * Shai Fultheim <shai@scalemp.com>
+ * Paravirt ops integration: Glauber de Oliveira Costa <gcosta@redhat.com>,
+ *			     Ravikiran Thirumalai <kiran@scalemp.com>
  */
  */
 
 
 #include <linux/init.h>
 #include <linux/init.h>
@@ -15,6 +17,60 @@
 #include <linux/pci_regs.h>
 #include <linux/pci_regs.h>
 #include <asm/pci-direct.h>
 #include <asm/pci-direct.h>
 #include <asm/io.h>
 #include <asm/io.h>
+#include <asm/paravirt.h>
+
+/*
+ * Interrupt control on vSMPowered systems:
+ * ~AC is a shadow of IF.  If IF is 'on' AC should be 'off'
+ * and vice versa.
+ */
+
+static unsigned long vsmp_save_fl(void)
+{
+	unsigned long flags = native_save_fl();
+
+	if (!(flags & X86_EFLAGS_IF) || (flags & X86_EFLAGS_AC))
+		flags &= ~X86_EFLAGS_IF;
+	return flags;
+}
+
+static void vsmp_restore_fl(unsigned long flags)
+{
+	if (flags & X86_EFLAGS_IF)
+		flags &= ~X86_EFLAGS_AC;
+	else
+		flags |= X86_EFLAGS_AC;
+	native_restore_fl(flags);
+}
+
+static void vsmp_irq_disable(void)
+{
+	unsigned long flags = native_save_fl();
+
+	native_restore_fl((flags & ~X86_EFLAGS_IF) | X86_EFLAGS_AC);
+}
+
+static void vsmp_irq_enable(void)
+{
+	unsigned long flags = native_save_fl();
+
+	native_restore_fl((flags | X86_EFLAGS_IF) & (~X86_EFLAGS_AC));
+}
+
+static unsigned __init vsmp_patch(u8 type, u16 clobbers, void *ibuf,
+				  unsigned long addr, unsigned len)
+{
+	switch (type) {
+	case PARAVIRT_PATCH(pv_irq_ops.irq_enable):
+	case PARAVIRT_PATCH(pv_irq_ops.irq_disable):
+	case PARAVIRT_PATCH(pv_irq_ops.save_fl):
+	case PARAVIRT_PATCH(pv_irq_ops.restore_fl):
+		return paravirt_patch_default(type, clobbers, ibuf, addr, len);
+	default:
+		return native_patch(type, clobbers, ibuf, addr, len);
+	}
+
+}
 
 
 void __init vsmp_init(void)
 void __init vsmp_init(void)
 {
 {