Commit 7ac63f6b authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'x86-vmware-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 vmware updates from Ingo Molnar:
 "This updates the VMWARE guest driver with support for VMCALL/VMMCALL
  based hypercalls"

* 'x86-vmware-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  input/vmmouse: Update the backdoor call with support for new instructions
  drm/vmwgfx: Update the backdoor call with support for new instructions
  x86/vmware: Add a header file for hypercall definitions
  x86/vmware: Update platform detection code for VMCALL/VMMCALL hypercalls
parents e2bddc20 f7b15c74
...@@ -17193,6 +17193,7 @@ M: "VMware, Inc." <pv-drivers@vmware.com> ...@@ -17193,6 +17193,7 @@ M: "VMware, Inc." <pv-drivers@vmware.com>
L: virtualization@lists.linux-foundation.org L: virtualization@lists.linux-foundation.org
S: Supported S: Supported
F: arch/x86/kernel/cpu/vmware.c F: arch/x86/kernel/cpu/vmware.c
F: arch/x86/include/asm/vmware.h
VMWARE PVRDMA DRIVER VMWARE PVRDMA DRIVER
M: Adit Ranadive <aditr@vmware.com> M: Adit Ranadive <aditr@vmware.com>
......
...@@ -231,6 +231,8 @@ ...@@ -231,6 +231,8 @@
#define X86_FEATURE_VMMCALL ( 8*32+15) /* Prefer VMMCALL to VMCALL */ #define X86_FEATURE_VMMCALL ( 8*32+15) /* Prefer VMMCALL to VMCALL */
#define X86_FEATURE_XENPV ( 8*32+16) /* "" Xen paravirtual guest */ #define X86_FEATURE_XENPV ( 8*32+16) /* "" Xen paravirtual guest */
#define X86_FEATURE_EPT_AD ( 8*32+17) /* Intel Extended Page Table access-dirty bit */ #define X86_FEATURE_EPT_AD ( 8*32+17) /* Intel Extended Page Table access-dirty bit */
#define X86_FEATURE_VMCALL ( 8*32+18) /* "" Hypervisor supports the VMCALL instruction */
#define X86_FEATURE_VMW_VMMCALL ( 8*32+19) /* "" VMware prefers VMMCALL hypercall instruction */
/* Intel-defined CPU features, CPUID level 0x00000007:0 (EBX), word 9 */ /* Intel-defined CPU features, CPUID level 0x00000007:0 (EBX), word 9 */
#define X86_FEATURE_FSGSBASE ( 9*32+ 0) /* RDFSBASE, WRFSBASE, RDGSBASE, WRGSBASE instructions*/ #define X86_FEATURE_FSGSBASE ( 9*32+ 0) /* RDFSBASE, WRFSBASE, RDGSBASE, WRGSBASE instructions*/
......
/* SPDX-License-Identifier: GPL-2.0 or MIT */
#ifndef _ASM_X86_VMWARE_H
#define _ASM_X86_VMWARE_H
#include <asm/cpufeatures.h>
#include <asm/alternative.h>
/*
* The hypercall definitions differ in the low word of the %edx argument
* in the following way: the old port base interface uses the port
* number to distinguish between high- and low bandwidth versions.
*
* The new vmcall interface instead uses a set of flags to select
* bandwidth mode and transfer direction. The flags should be loaded
* into %dx by any user and are automatically replaced by the port
* number if the VMWARE_HYPERVISOR_PORT method is used.
*
* In short, new driver code should strictly use the new definition of
* %dx content.
*/
/* Old port-based version */
#define VMWARE_HYPERVISOR_PORT "0x5658"
#define VMWARE_HYPERVISOR_PORT_HB "0x5659"
/* Current vmcall / vmmcall version */
#define VMWARE_HYPERVISOR_HB BIT(0)
#define VMWARE_HYPERVISOR_OUT BIT(1)
/* The low bandwidth call. The low word of edx is presumed clear. */
#define VMWARE_HYPERCALL \
ALTERNATIVE_2("movw $" VMWARE_HYPERVISOR_PORT ", %%dx; inl (%%dx)", \
"vmcall", X86_FEATURE_VMCALL, \
"vmmcall", X86_FEATURE_VMW_VMMCALL)
/*
* The high bandwidth out call. The low word of edx is presumed to have the
* HB and OUT bits set.
*/
#define VMWARE_HYPERCALL_HB_OUT \
ALTERNATIVE_2("movw $" VMWARE_HYPERVISOR_PORT_HB ", %%dx; rep outsb", \
"vmcall", X86_FEATURE_VMCALL, \
"vmmcall", X86_FEATURE_VMW_VMMCALL)
/*
* The high bandwidth in call. The low word of edx is presumed to have the
* HB bit set.
*/
#define VMWARE_HYPERCALL_HB_IN \
ALTERNATIVE_2("movw $" VMWARE_HYPERVISOR_PORT_HB ", %%dx; rep insb", \
"vmcall", X86_FEATURE_VMCALL, \
"vmmcall", X86_FEATURE_VMW_VMMCALL)
#endif
...@@ -30,34 +30,69 @@ ...@@ -30,34 +30,69 @@
#include <asm/hypervisor.h> #include <asm/hypervisor.h>
#include <asm/timer.h> #include <asm/timer.h>
#include <asm/apic.h> #include <asm/apic.h>
#include <asm/vmware.h>
#undef pr_fmt #undef pr_fmt
#define pr_fmt(fmt) "vmware: " fmt #define pr_fmt(fmt) "vmware: " fmt
#define CPUID_VMWARE_INFO_LEAF 0x40000000 #define CPUID_VMWARE_INFO_LEAF 0x40000000
#define CPUID_VMWARE_FEATURES_LEAF 0x40000010
#define CPUID_VMWARE_FEATURES_ECX_VMMCALL BIT(0)
#define CPUID_VMWARE_FEATURES_ECX_VMCALL BIT(1)
#define VMWARE_HYPERVISOR_MAGIC 0x564D5868 #define VMWARE_HYPERVISOR_MAGIC 0x564D5868
#define VMWARE_HYPERVISOR_PORT 0x5658
#define VMWARE_PORT_CMD_GETVERSION 10 #define VMWARE_CMD_GETVERSION 10
#define VMWARE_PORT_CMD_GETHZ 45 #define VMWARE_CMD_GETHZ 45
#define VMWARE_PORT_CMD_GETVCPU_INFO 68 #define VMWARE_CMD_GETVCPU_INFO 68
#define VMWARE_PORT_CMD_LEGACY_X2APIC 3 #define VMWARE_CMD_LEGACY_X2APIC 3
#define VMWARE_PORT_CMD_VCPU_RESERVED 31 #define VMWARE_CMD_VCPU_RESERVED 31
#define VMWARE_PORT(cmd, eax, ebx, ecx, edx) \ #define VMWARE_PORT(cmd, eax, ebx, ecx, edx) \
__asm__("inl (%%dx)" : \ __asm__("inl (%%dx)" : \
"=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) : \ "=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) : \
"0"(VMWARE_HYPERVISOR_MAGIC), \ "a"(VMWARE_HYPERVISOR_MAGIC), \
"1"(VMWARE_PORT_CMD_##cmd), \ "c"(VMWARE_CMD_##cmd), \
"2"(VMWARE_HYPERVISOR_PORT), "3"(UINT_MAX) : \ "d"(VMWARE_HYPERVISOR_PORT), "b"(UINT_MAX) : \
"memory"); "memory")
#define VMWARE_VMCALL(cmd, eax, ebx, ecx, edx) \
__asm__("vmcall" : \
"=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) : \
"a"(VMWARE_HYPERVISOR_MAGIC), \
"c"(VMWARE_CMD_##cmd), \
"d"(0), "b"(UINT_MAX) : \
"memory")
#define VMWARE_VMMCALL(cmd, eax, ebx, ecx, edx) \
__asm__("vmmcall" : \
"=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) : \
"a"(VMWARE_HYPERVISOR_MAGIC), \
"c"(VMWARE_CMD_##cmd), \
"d"(0), "b"(UINT_MAX) : \
"memory")
#define VMWARE_CMD(cmd, eax, ebx, ecx, edx) do { \
switch (vmware_hypercall_mode) { \
case CPUID_VMWARE_FEATURES_ECX_VMCALL: \
VMWARE_VMCALL(cmd, eax, ebx, ecx, edx); \
break; \
case CPUID_VMWARE_FEATURES_ECX_VMMCALL: \
VMWARE_VMMCALL(cmd, eax, ebx, ecx, edx); \
break; \
default: \
VMWARE_PORT(cmd, eax, ebx, ecx, edx); \
break; \
} \
} while (0)
static unsigned long vmware_tsc_khz __ro_after_init; static unsigned long vmware_tsc_khz __ro_after_init;
static u8 vmware_hypercall_mode __ro_after_init;
static inline int __vmware_platform(void) static inline int __vmware_platform(void)
{ {
uint32_t eax, ebx, ecx, edx; uint32_t eax, ebx, ecx, edx;
VMWARE_PORT(GETVERSION, eax, ebx, ecx, edx); VMWARE_CMD(GETVERSION, eax, ebx, ecx, edx);
return eax != (uint32_t)-1 && ebx == VMWARE_HYPERVISOR_MAGIC; return eax != (uint32_t)-1 && ebx == VMWARE_HYPERVISOR_MAGIC;
} }
...@@ -129,6 +164,10 @@ static void __init vmware_set_capabilities(void) ...@@ -129,6 +164,10 @@ static void __init vmware_set_capabilities(void)
{ {
setup_force_cpu_cap(X86_FEATURE_CONSTANT_TSC); setup_force_cpu_cap(X86_FEATURE_CONSTANT_TSC);
setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE); setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE);
if (vmware_hypercall_mode == CPUID_VMWARE_FEATURES_ECX_VMCALL)
setup_force_cpu_cap(X86_FEATURE_VMCALL);
else if (vmware_hypercall_mode == CPUID_VMWARE_FEATURES_ECX_VMMCALL)
setup_force_cpu_cap(X86_FEATURE_VMW_VMMCALL);
} }
static void __init vmware_platform_setup(void) static void __init vmware_platform_setup(void)
...@@ -136,7 +175,7 @@ static void __init vmware_platform_setup(void) ...@@ -136,7 +175,7 @@ static void __init vmware_platform_setup(void)
uint32_t eax, ebx, ecx, edx; uint32_t eax, ebx, ecx, edx;
uint64_t lpj, tsc_khz; uint64_t lpj, tsc_khz;
VMWARE_PORT(GETHZ, eax, ebx, ecx, edx); VMWARE_CMD(GETHZ, eax, ebx, ecx, edx);
if (ebx != UINT_MAX) { if (ebx != UINT_MAX) {
lpj = tsc_khz = eax | (((uint64_t)ebx) << 32); lpj = tsc_khz = eax | (((uint64_t)ebx) << 32);
...@@ -174,10 +213,21 @@ static void __init vmware_platform_setup(void) ...@@ -174,10 +213,21 @@ static void __init vmware_platform_setup(void)
vmware_set_capabilities(); vmware_set_capabilities();
} }
static u8 vmware_select_hypercall(void)
{
int eax, ebx, ecx, edx;
cpuid(CPUID_VMWARE_FEATURES_LEAF, &eax, &ebx, &ecx, &edx);
return (ecx & (CPUID_VMWARE_FEATURES_ECX_VMMCALL |
CPUID_VMWARE_FEATURES_ECX_VMCALL));
}
/* /*
* While checking the dmi string information, just checking the product * While checking the dmi string information, just checking the product
* serial key should be enough, as this will always have a VMware * serial key should be enough, as this will always have a VMware
* specific string when running under VMware hypervisor. * specific string when running under VMware hypervisor.
* If !boot_cpu_has(X86_FEATURE_HYPERVISOR), vmware_hypercall_mode
* intentionally defaults to 0.
*/ */
static uint32_t __init vmware_platform(void) static uint32_t __init vmware_platform(void)
{ {
...@@ -187,8 +237,16 @@ static uint32_t __init vmware_platform(void) ...@@ -187,8 +237,16 @@ static uint32_t __init vmware_platform(void)
cpuid(CPUID_VMWARE_INFO_LEAF, &eax, &hyper_vendor_id[0], cpuid(CPUID_VMWARE_INFO_LEAF, &eax, &hyper_vendor_id[0],
&hyper_vendor_id[1], &hyper_vendor_id[2]); &hyper_vendor_id[1], &hyper_vendor_id[2]);
if (!memcmp(hyper_vendor_id, "VMwareVMware", 12)) if (!memcmp(hyper_vendor_id, "VMwareVMware", 12)) {
if (eax >= CPUID_VMWARE_FEATURES_LEAF)
vmware_hypercall_mode =
vmware_select_hypercall();
pr_info("hypercall mode: 0x%02x\n",
(unsigned int) vmware_hypercall_mode);
return CPUID_VMWARE_INFO_LEAF; return CPUID_VMWARE_INFO_LEAF;
}
} else if (dmi_available && dmi_name_in_serial("VMware") && } else if (dmi_available && dmi_name_in_serial("VMware") &&
__vmware_platform()) __vmware_platform())
return 1; return 1;
...@@ -200,9 +258,9 @@ static uint32_t __init vmware_platform(void) ...@@ -200,9 +258,9 @@ static uint32_t __init vmware_platform(void)
static bool __init vmware_legacy_x2apic_available(void) static bool __init vmware_legacy_x2apic_available(void)
{ {
uint32_t eax, ebx, ecx, edx; uint32_t eax, ebx, ecx, edx;
VMWARE_PORT(GETVCPU_INFO, eax, ebx, ecx, edx); VMWARE_CMD(GETVCPU_INFO, eax, ebx, ecx, edx);
return (eax & (1 << VMWARE_PORT_CMD_VCPU_RESERVED)) == 0 && return (eax & (1 << VMWARE_CMD_VCPU_RESERVED)) == 0 &&
(eax & (1 << VMWARE_PORT_CMD_LEGACY_X2APIC)) != 0; (eax & (1 << VMWARE_CMD_LEGACY_X2APIC)) != 0;
} }
const __initconst struct hypervisor_x86 x86_hyper_vmware = { const __initconst struct hypervisor_x86 x86_hyper_vmware = {
......
...@@ -46,8 +46,6 @@ ...@@ -46,8 +46,6 @@
#define RETRIES 3 #define RETRIES 3
#define VMW_HYPERVISOR_MAGIC 0x564D5868 #define VMW_HYPERVISOR_MAGIC 0x564D5868
#define VMW_HYPERVISOR_PORT 0x5658
#define VMW_HYPERVISOR_HB_PORT 0x5659
#define VMW_PORT_CMD_MSG 30 #define VMW_PORT_CMD_MSG 30
#define VMW_PORT_CMD_HB_MSG 0 #define VMW_PORT_CMD_HB_MSG 0
...@@ -93,7 +91,7 @@ static int vmw_open_channel(struct rpc_channel *channel, unsigned int protocol) ...@@ -93,7 +91,7 @@ static int vmw_open_channel(struct rpc_channel *channel, unsigned int protocol)
VMW_PORT(VMW_PORT_CMD_OPEN_CHANNEL, VMW_PORT(VMW_PORT_CMD_OPEN_CHANNEL,
(protocol | GUESTMSG_FLAG_COOKIE), si, di, (protocol | GUESTMSG_FLAG_COOKIE), si, di,
VMW_HYPERVISOR_PORT, 0,
VMW_HYPERVISOR_MAGIC, VMW_HYPERVISOR_MAGIC,
eax, ebx, ecx, edx, si, di); eax, ebx, ecx, edx, si, di);
...@@ -126,7 +124,7 @@ static int vmw_close_channel(struct rpc_channel *channel) ...@@ -126,7 +124,7 @@ static int vmw_close_channel(struct rpc_channel *channel)
VMW_PORT(VMW_PORT_CMD_CLOSE_CHANNEL, VMW_PORT(VMW_PORT_CMD_CLOSE_CHANNEL,
0, si, di, 0, si, di,
(VMW_HYPERVISOR_PORT | (channel->channel_id << 16)), channel->channel_id << 16,
VMW_HYPERVISOR_MAGIC, VMW_HYPERVISOR_MAGIC,
eax, ebx, ecx, edx, si, di); eax, ebx, ecx, edx, si, di);
...@@ -160,7 +158,8 @@ static unsigned long vmw_port_hb_out(struct rpc_channel *channel, ...@@ -160,7 +158,8 @@ static unsigned long vmw_port_hb_out(struct rpc_channel *channel,
VMW_PORT_HB_OUT( VMW_PORT_HB_OUT(
(MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG, (MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG,
msg_len, si, di, msg_len, si, di,
VMW_HYPERVISOR_HB_PORT | (channel->channel_id << 16), VMWARE_HYPERVISOR_HB | (channel->channel_id << 16) |
VMWARE_HYPERVISOR_OUT,
VMW_HYPERVISOR_MAGIC, bp, VMW_HYPERVISOR_MAGIC, bp,
eax, ebx, ecx, edx, si, di); eax, ebx, ecx, edx, si, di);
...@@ -181,7 +180,7 @@ static unsigned long vmw_port_hb_out(struct rpc_channel *channel, ...@@ -181,7 +180,7 @@ static unsigned long vmw_port_hb_out(struct rpc_channel *channel,
VMW_PORT(VMW_PORT_CMD_MSG | (MSG_TYPE_SENDPAYLOAD << 16), VMW_PORT(VMW_PORT_CMD_MSG | (MSG_TYPE_SENDPAYLOAD << 16),
word, si, di, word, si, di,
VMW_HYPERVISOR_PORT | (channel->channel_id << 16), channel->channel_id << 16,
VMW_HYPERVISOR_MAGIC, VMW_HYPERVISOR_MAGIC,
eax, ebx, ecx, edx, si, di); eax, ebx, ecx, edx, si, di);
} }
...@@ -213,7 +212,7 @@ static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply, ...@@ -213,7 +212,7 @@ static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply,
VMW_PORT_HB_IN( VMW_PORT_HB_IN(
(MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG, (MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG,
reply_len, si, di, reply_len, si, di,
VMW_HYPERVISOR_HB_PORT | (channel->channel_id << 16), VMWARE_HYPERVISOR_HB | (channel->channel_id << 16),
VMW_HYPERVISOR_MAGIC, bp, VMW_HYPERVISOR_MAGIC, bp,
eax, ebx, ecx, edx, si, di); eax, ebx, ecx, edx, si, di);
...@@ -230,7 +229,7 @@ static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply, ...@@ -230,7 +229,7 @@ static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply,
VMW_PORT(VMW_PORT_CMD_MSG | (MSG_TYPE_RECVPAYLOAD << 16), VMW_PORT(VMW_PORT_CMD_MSG | (MSG_TYPE_RECVPAYLOAD << 16),
MESSAGE_STATUS_SUCCESS, si, di, MESSAGE_STATUS_SUCCESS, si, di,
VMW_HYPERVISOR_PORT | (channel->channel_id << 16), channel->channel_id << 16,
VMW_HYPERVISOR_MAGIC, VMW_HYPERVISOR_MAGIC,
eax, ebx, ecx, edx, si, di); eax, ebx, ecx, edx, si, di);
...@@ -269,7 +268,7 @@ static int vmw_send_msg(struct rpc_channel *channel, const char *msg) ...@@ -269,7 +268,7 @@ static int vmw_send_msg(struct rpc_channel *channel, const char *msg)
VMW_PORT(VMW_PORT_CMD_SENDSIZE, VMW_PORT(VMW_PORT_CMD_SENDSIZE,
msg_len, si, di, msg_len, si, di,
VMW_HYPERVISOR_PORT | (channel->channel_id << 16), channel->channel_id << 16,
VMW_HYPERVISOR_MAGIC, VMW_HYPERVISOR_MAGIC,
eax, ebx, ecx, edx, si, di); eax, ebx, ecx, edx, si, di);
...@@ -327,7 +326,7 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg, ...@@ -327,7 +326,7 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
VMW_PORT(VMW_PORT_CMD_RECVSIZE, VMW_PORT(VMW_PORT_CMD_RECVSIZE,
0, si, di, 0, si, di,
(VMW_HYPERVISOR_PORT | (channel->channel_id << 16)), channel->channel_id << 16,
VMW_HYPERVISOR_MAGIC, VMW_HYPERVISOR_MAGIC,
eax, ebx, ecx, edx, si, di); eax, ebx, ecx, edx, si, di);
...@@ -371,7 +370,7 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg, ...@@ -371,7 +370,7 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
VMW_PORT(VMW_PORT_CMD_RECVSTATUS, VMW_PORT(VMW_PORT_CMD_RECVSTATUS,
MESSAGE_STATUS_SUCCESS, si, di, MESSAGE_STATUS_SUCCESS, si, di,
(VMW_HYPERVISOR_PORT | (channel->channel_id << 16)), channel->channel_id << 16,
VMW_HYPERVISOR_MAGIC, VMW_HYPERVISOR_MAGIC,
eax, ebx, ecx, edx, si, di); eax, ebx, ecx, edx, si, di);
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#ifndef _VMWGFX_MSG_H #ifndef _VMWGFX_MSG_H
#define _VMWGFX_MSG_H #define _VMWGFX_MSG_H
#include <asm/vmware.h>
/** /**
* Hypervisor-specific bi-directional communication channel. Should never * Hypervisor-specific bi-directional communication channel. Should never
...@@ -44,7 +45,7 @@ ...@@ -44,7 +45,7 @@
* @in_ebx: [IN] Message Len, through EBX * @in_ebx: [IN] Message Len, through EBX
* @in_si: [IN] Input argument through SI, set to 0 if not used * @in_si: [IN] Input argument through SI, set to 0 if not used
* @in_di: [IN] Input argument through DI, set ot 0 if not used * @in_di: [IN] Input argument through DI, set ot 0 if not used
* @port_num: [IN] port number + [channel id] * @flags: [IN] hypercall flags + [channel id]
* @magic: [IN] hypervisor magic value * @magic: [IN] hypervisor magic value
* @eax: [OUT] value of EAX register * @eax: [OUT] value of EAX register
* @ebx: [OUT] e.g. status from an HB message status command * @ebx: [OUT] e.g. status from an HB message status command
...@@ -54,10 +55,10 @@ ...@@ -54,10 +55,10 @@
* @di: [OUT] * @di: [OUT]
*/ */
#define VMW_PORT(cmd, in_ebx, in_si, in_di, \ #define VMW_PORT(cmd, in_ebx, in_si, in_di, \
port_num, magic, \ flags, magic, \
eax, ebx, ecx, edx, si, di) \ eax, ebx, ecx, edx, si, di) \
({ \ ({ \
asm volatile ("inl %%dx, %%eax;" : \ asm volatile (VMWARE_HYPERCALL : \
"=a"(eax), \ "=a"(eax), \
"=b"(ebx), \ "=b"(ebx), \
"=c"(ecx), \ "=c"(ecx), \
...@@ -67,7 +68,7 @@ ...@@ -67,7 +68,7 @@
"a"(magic), \ "a"(magic), \
"b"(in_ebx), \ "b"(in_ebx), \
"c"(cmd), \ "c"(cmd), \
"d"(port_num), \ "d"(flags), \
"S"(in_si), \ "S"(in_si), \
"D"(in_di) : \ "D"(in_di) : \
"memory"); \ "memory"); \
...@@ -85,7 +86,7 @@ ...@@ -85,7 +86,7 @@
* @in_ecx: [IN] Message Len, through ECX * @in_ecx: [IN] Message Len, through ECX
* @in_si: [IN] Input argument through SI, set to 0 if not used * @in_si: [IN] Input argument through SI, set to 0 if not used
* @in_di: [IN] Input argument through DI, set to 0 if not used * @in_di: [IN] Input argument through DI, set to 0 if not used
* @port_num: [IN] port number + [channel id] * @flags: [IN] hypercall flags + [channel id]
* @magic: [IN] hypervisor magic value * @magic: [IN] hypervisor magic value
* @bp: [IN] * @bp: [IN]
* @eax: [OUT] value of EAX register * @eax: [OUT] value of EAX register
...@@ -98,12 +99,12 @@ ...@@ -98,12 +99,12 @@
#ifdef __x86_64__ #ifdef __x86_64__
#define VMW_PORT_HB_OUT(cmd, in_ecx, in_si, in_di, \ #define VMW_PORT_HB_OUT(cmd, in_ecx, in_si, in_di, \
port_num, magic, bp, \ flags, magic, bp, \
eax, ebx, ecx, edx, si, di) \ eax, ebx, ecx, edx, si, di) \
({ \ ({ \
asm volatile ("push %%rbp;" \ asm volatile ("push %%rbp;" \
"mov %12, %%rbp;" \ "mov %12, %%rbp;" \
"rep outsb;" \ VMWARE_HYPERCALL_HB_OUT \
"pop %%rbp;" : \ "pop %%rbp;" : \
"=a"(eax), \ "=a"(eax), \
"=b"(ebx), \ "=b"(ebx), \
...@@ -114,7 +115,7 @@ ...@@ -114,7 +115,7 @@
"a"(magic), \ "a"(magic), \
"b"(cmd), \ "b"(cmd), \
"c"(in_ecx), \ "c"(in_ecx), \
"d"(port_num), \ "d"(flags), \
"S"(in_si), \ "S"(in_si), \
"D"(in_di), \ "D"(in_di), \
"r"(bp) : \ "r"(bp) : \
...@@ -123,12 +124,12 @@ ...@@ -123,12 +124,12 @@
#define VMW_PORT_HB_IN(cmd, in_ecx, in_si, in_di, \ #define VMW_PORT_HB_IN(cmd, in_ecx, in_si, in_di, \
port_num, magic, bp, \ flags, magic, bp, \
eax, ebx, ecx, edx, si, di) \ eax, ebx, ecx, edx, si, di) \
({ \ ({ \
asm volatile ("push %%rbp;" \ asm volatile ("push %%rbp;" \
"mov %12, %%rbp;" \ "mov %12, %%rbp;" \
"rep insb;" \ VMWARE_HYPERCALL_HB_IN \
"pop %%rbp" : \ "pop %%rbp" : \
"=a"(eax), \ "=a"(eax), \
"=b"(ebx), \ "=b"(ebx), \
...@@ -139,7 +140,7 @@ ...@@ -139,7 +140,7 @@
"a"(magic), \ "a"(magic), \
"b"(cmd), \ "b"(cmd), \
"c"(in_ecx), \ "c"(in_ecx), \
"d"(port_num), \ "d"(flags), \
"S"(in_si), \ "S"(in_si), \
"D"(in_di), \ "D"(in_di), \
"r"(bp) : \ "r"(bp) : \
...@@ -157,13 +158,13 @@ ...@@ -157,13 +158,13 @@
* just pushed it. * just pushed it.
*/ */
#define VMW_PORT_HB_OUT(cmd, in_ecx, in_si, in_di, \ #define VMW_PORT_HB_OUT(cmd, in_ecx, in_si, in_di, \
port_num, magic, bp, \ flags, magic, bp, \
eax, ebx, ecx, edx, si, di) \ eax, ebx, ecx, edx, si, di) \
({ \ ({ \
asm volatile ("push %12;" \ asm volatile ("push %12;" \
"push %%ebp;" \ "push %%ebp;" \
"mov 0x04(%%esp), %%ebp;" \ "mov 0x04(%%esp), %%ebp;" \
"rep outsb;" \ VMWARE_HYPERCALL_HB_OUT \
"pop %%ebp;" \ "pop %%ebp;" \
"add $0x04, %%esp;" : \ "add $0x04, %%esp;" : \
"=a"(eax), \ "=a"(eax), \
...@@ -175,7 +176,7 @@ ...@@ -175,7 +176,7 @@
"a"(magic), \ "a"(magic), \
"b"(cmd), \ "b"(cmd), \
"c"(in_ecx), \ "c"(in_ecx), \
"d"(port_num), \ "d"(flags), \
"S"(in_si), \ "S"(in_si), \
"D"(in_di), \ "D"(in_di), \
"m"(bp) : \ "m"(bp) : \
...@@ -184,13 +185,13 @@ ...@@ -184,13 +185,13 @@
#define VMW_PORT_HB_IN(cmd, in_ecx, in_si, in_di, \ #define VMW_PORT_HB_IN(cmd, in_ecx, in_si, in_di, \
port_num, magic, bp, \ flags, magic, bp, \
eax, ebx, ecx, edx, si, di) \ eax, ebx, ecx, edx, si, di) \
({ \ ({ \
asm volatile ("push %12;" \ asm volatile ("push %12;" \
"push %%ebp;" \ "push %%ebp;" \
"mov 0x04(%%esp), %%ebp;" \ "mov 0x04(%%esp), %%ebp;" \
"rep insb;" \ VMWARE_HYPERCALL_HB_IN \
"pop %%ebp;" \ "pop %%ebp;" \
"add $0x04, %%esp;" : \ "add $0x04, %%esp;" : \
"=a"(eax), \ "=a"(eax), \
...@@ -202,7 +203,7 @@ ...@@ -202,7 +203,7 @@
"a"(magic), \ "a"(magic), \
"b"(cmd), \ "b"(cmd), \
"c"(in_ecx), \ "c"(in_ecx), \
"d"(port_num), \ "d"(flags), \
"S"(in_si), \ "S"(in_si), \
"D"(in_di), \ "D"(in_di), \
"m"(bp) : \ "m"(bp) : \
......
...@@ -16,12 +16,12 @@ ...@@ -16,12 +16,12 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
#include <asm/hypervisor.h> #include <asm/hypervisor.h>
#include <asm/vmware.h>
#include "psmouse.h" #include "psmouse.h"
#include "vmmouse.h" #include "vmmouse.h"
#define VMMOUSE_PROTO_MAGIC 0x564D5868U #define VMMOUSE_PROTO_MAGIC 0x564D5868U
#define VMMOUSE_PROTO_PORT 0x5658
/* /*
* Main commands supported by the vmmouse hypervisor port. * Main commands supported by the vmmouse hypervisor port.
...@@ -84,7 +84,7 @@ struct vmmouse_data { ...@@ -84,7 +84,7 @@ struct vmmouse_data {
#define VMMOUSE_CMD(cmd, in1, out1, out2, out3, out4) \ #define VMMOUSE_CMD(cmd, in1, out1, out2, out3, out4) \
({ \ ({ \
unsigned long __dummy1, __dummy2; \ unsigned long __dummy1, __dummy2; \
__asm__ __volatile__ ("inl %%dx" : \ __asm__ __volatile__ (VMWARE_HYPERCALL : \
"=a"(out1), \ "=a"(out1), \
"=b"(out2), \ "=b"(out2), \
"=c"(out3), \ "=c"(out3), \
...@@ -94,7 +94,7 @@ struct vmmouse_data { ...@@ -94,7 +94,7 @@ struct vmmouse_data {
"a"(VMMOUSE_PROTO_MAGIC), \ "a"(VMMOUSE_PROTO_MAGIC), \
"b"(in1), \ "b"(in1), \
"c"(VMMOUSE_PROTO_CMD_##cmd), \ "c"(VMMOUSE_PROTO_CMD_##cmd), \
"d"(VMMOUSE_PROTO_PORT) : \ "d"(0) : \
"memory"); \ "memory"); \
}) })
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment