|
@@ -1447,7 +1447,51 @@ static inline void ept_sync_context(u64 eptp)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static __always_inline unsigned long vmcs_readl(unsigned long field)
|
|
|
+static __always_inline void vmcs_check16(unsigned long field)
|
|
|
+{
|
|
|
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6001) == 0x2000,
|
|
|
+ "16-bit accessor invalid for 64-bit field");
|
|
|
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6001) == 0x2001,
|
|
|
+ "16-bit accessor invalid for 64-bit high field");
|
|
|
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x4000,
|
|
|
+ "16-bit accessor invalid for 32-bit high field");
|
|
|
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x6000,
|
|
|
+ "16-bit accessor invalid for natural width field");
|
|
|
+}
|
|
|
+
|
|
|
+static __always_inline void vmcs_check32(unsigned long field)
|
|
|
+{
|
|
|
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0,
|
|
|
+ "32-bit accessor invalid for 16-bit field");
|
|
|
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x6000,
|
|
|
+ "32-bit accessor invalid for natural width field");
|
|
|
+}
|
|
|
+
|
|
|
+static __always_inline void vmcs_check64(unsigned long field)
|
|
|
+{
|
|
|
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0,
|
|
|
+ "64-bit accessor invalid for 16-bit field");
|
|
|
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6001) == 0x2001,
|
|
|
+ "64-bit accessor invalid for 64-bit high field");
|
|
|
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x4000,
|
|
|
+ "64-bit accessor invalid for 32-bit field");
|
|
|
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x6000,
|
|
|
+ "64-bit accessor invalid for natural width field");
|
|
|
+}
|
|
|
+
|
|
|
+static __always_inline void vmcs_checkl(unsigned long field)
|
|
|
+{
|
|
|
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0,
|
|
|
+ "Natural width accessor invalid for 16-bit field");
|
|
|
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6001) == 0x2000,
|
|
|
+ "Natural width accessor invalid for 64-bit field");
|
|
|
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6001) == 0x2001,
|
|
|
+ "Natural width accessor invalid for 64-bit high field");
|
|
|
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x4000,
|
|
|
+ "Natural width accessor invalid for 32-bit field");
|
|
|
+}
|
|
|
+
|
|
|
+static __always_inline unsigned long __vmcs_readl(unsigned long field)
|
|
|
{
|
|
|
unsigned long value;
|
|
|
|
|
@@ -1458,23 +1502,32 @@ static __always_inline unsigned long vmcs_readl(unsigned long field)
|
|
|
|
|
|
static __always_inline u16 vmcs_read16(unsigned long field)
|
|
|
{
|
|
|
- return vmcs_readl(field);
|
|
|
+ vmcs_check16(field);
|
|
|
+ return __vmcs_readl(field);
|
|
|
}
|
|
|
|
|
|
static __always_inline u32 vmcs_read32(unsigned long field)
|
|
|
{
|
|
|
- return vmcs_readl(field);
|
|
|
+ vmcs_check32(field);
|
|
|
+ return __vmcs_readl(field);
|
|
|
}
|
|
|
|
|
|
static __always_inline u64 vmcs_read64(unsigned long field)
|
|
|
{
|
|
|
+ vmcs_check64(field);
|
|
|
#ifdef CONFIG_X86_64
|
|
|
- return vmcs_readl(field);
|
|
|
+ return __vmcs_readl(field);
|
|
|
#else
|
|
|
- return vmcs_readl(field) | ((u64)vmcs_readl(field+1) << 32);
|
|
|
+ return __vmcs_readl(field) | ((u64)__vmcs_readl(field+1) << 32);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
+static __always_inline unsigned long vmcs_readl(unsigned long field)
|
|
|
+{
|
|
|
+ vmcs_checkl(field);
|
|
|
+ return __vmcs_readl(field);
|
|
|
+}
|
|
|
+
|
|
|
static noinline void vmwrite_error(unsigned long field, unsigned long value)
|
|
|
{
|
|
|
printk(KERN_ERR "vmwrite error: reg %lx value %lx (err %d)\n",
|
|
@@ -1482,7 +1535,7 @@ static noinline void vmwrite_error(unsigned long field, unsigned long value)
|
|
|
dump_stack();
|
|
|
}
|
|
|
|
|
|
-static void vmcs_writel(unsigned long field, unsigned long value)
|
|
|
+static __always_inline void __vmcs_writel(unsigned long field, unsigned long value)
|
|
|
{
|
|
|
u8 error;
|
|
|
|
|
@@ -1492,33 +1545,46 @@ static void vmcs_writel(unsigned long field, unsigned long value)
|
|
|
vmwrite_error(field, value);
|
|
|
}
|
|
|
|
|
|
-static void vmcs_write16(unsigned long field, u16 value)
|
|
|
+static __always_inline void vmcs_write16(unsigned long field, u16 value)
|
|
|
{
|
|
|
- vmcs_writel(field, value);
|
|
|
+ vmcs_check16(field);
|
|
|
+ __vmcs_writel(field, value);
|
|
|
}
|
|
|
|
|
|
-static void vmcs_write32(unsigned long field, u32 value)
|
|
|
+static __always_inline void vmcs_write32(unsigned long field, u32 value)
|
|
|
{
|
|
|
- vmcs_writel(field, value);
|
|
|
+ vmcs_check32(field);
|
|
|
+ __vmcs_writel(field, value);
|
|
|
}
|
|
|
|
|
|
-static void vmcs_write64(unsigned long field, u64 value)
|
|
|
+static __always_inline void vmcs_write64(unsigned long field, u64 value)
|
|
|
{
|
|
|
- vmcs_writel(field, value);
|
|
|
+ vmcs_check64(field);
|
|
|
+ __vmcs_writel(field, value);
|
|
|
#ifndef CONFIG_X86_64
|
|
|
asm volatile ("");
|
|
|
- vmcs_writel(field+1, value >> 32);
|
|
|
+ __vmcs_writel(field+1, value >> 32);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
-static void vmcs_clear_bits(unsigned long field, u32 mask)
|
|
|
+static __always_inline void vmcs_writel(unsigned long field, unsigned long value)
|
|
|
+{
|
|
|
+ vmcs_checkl(field);
|
|
|
+ __vmcs_writel(field, value);
|
|
|
+}
|
|
|
+
|
|
|
+static __always_inline void vmcs_clear_bits(unsigned long field, u32 mask)
|
|
|
{
|
|
|
- vmcs_writel(field, vmcs_readl(field) & ~mask);
|
|
|
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x2000,
|
|
|
+ "vmcs_clear_bits does not support 64-bit fields");
|
|
|
+ __vmcs_writel(field, __vmcs_readl(field) & ~mask);
|
|
|
}
|
|
|
|
|
|
-static void vmcs_set_bits(unsigned long field, u32 mask)
|
|
|
+static __always_inline void vmcs_set_bits(unsigned long field, u32 mask)
|
|
|
{
|
|
|
- vmcs_writel(field, vmcs_readl(field) | mask);
|
|
|
+ BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x2000,
|
|
|
+ "vmcs_set_bits does not support 64-bit fields");
|
|
|
+ __vmcs_writel(field, __vmcs_readl(field) | mask);
|
|
|
}
|
|
|
|
|
|
static inline void vm_entry_controls_init(struct vcpu_vmx *vmx, u32 val)
|