drm/vmwgfx: Use VMware hypercall API
Switch from VMWARE_HYPERCALL macro to vmware_hypercall API. Eliminate arch specific code. drivers/gpu/drm/vmwgfx/vmwgfx_msg_arm64.h: implement arm64 variant of vmware_hypercall. And keep it here until introduction of ARM64 VMWare hypervisor interface. Signed-off-by: Alexey Makhalov <alexey.makhalov@broadcom.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Link: https://lore.kernel.org/r/20240613191650.9913-5-alexey.makhalov@broadcom.com
This commit is contained in:
committed by
Borislav Petkov (AMD)
parent
f0db90b412
commit
90328eaaff
@@ -48,8 +48,6 @@
|
||||
|
||||
#define RETRIES 3
|
||||
|
||||
#define VMW_HYPERVISOR_MAGIC 0x564D5868
|
||||
|
||||
#define VMW_PORT_CMD_MSG 30
|
||||
#define VMW_PORT_CMD_HB_MSG 0
|
||||
#define VMW_PORT_CMD_OPEN_CHANNEL (MSG_TYPE_OPEN << 16 | VMW_PORT_CMD_MSG)
|
||||
@@ -104,20 +102,18 @@ static const char* const mksstat_kern_name_desc[MKSSTAT_KERN_COUNT][2] =
|
||||
*/
|
||||
static int vmw_open_channel(struct rpc_channel *channel, unsigned int protocol)
|
||||
{
|
||||
unsigned long eax, ebx, ecx, edx, si = 0, di = 0;
|
||||
u32 ecx, edx, esi, edi;
|
||||
|
||||
VMW_PORT(VMW_PORT_CMD_OPEN_CHANNEL,
|
||||
(protocol | GUESTMSG_FLAG_COOKIE), si, di,
|
||||
0,
|
||||
VMW_HYPERVISOR_MAGIC,
|
||||
eax, ebx, ecx, edx, si, di);
|
||||
vmware_hypercall6(VMW_PORT_CMD_OPEN_CHANNEL,
|
||||
(protocol | GUESTMSG_FLAG_COOKIE), 0,
|
||||
&ecx, &edx, &esi, &edi);
|
||||
|
||||
if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0)
|
||||
return -EINVAL;
|
||||
|
||||
channel->channel_id = HIGH_WORD(edx);
|
||||
channel->cookie_high = si;
|
||||
channel->cookie_low = di;
|
||||
channel->cookie_high = esi;
|
||||
channel->cookie_low = edi;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -133,17 +129,13 @@ static int vmw_open_channel(struct rpc_channel *channel, unsigned int protocol)
|
||||
*/
|
||||
static int vmw_close_channel(struct rpc_channel *channel)
|
||||
{
|
||||
unsigned long eax, ebx, ecx, edx, si, di;
|
||||
u32 ecx;
|
||||
|
||||
/* Set up additional parameters */
|
||||
si = channel->cookie_high;
|
||||
di = channel->cookie_low;
|
||||
|
||||
VMW_PORT(VMW_PORT_CMD_CLOSE_CHANNEL,
|
||||
0, si, di,
|
||||
channel->channel_id << 16,
|
||||
VMW_HYPERVISOR_MAGIC,
|
||||
eax, ebx, ecx, edx, si, di);
|
||||
vmware_hypercall5(VMW_PORT_CMD_CLOSE_CHANNEL,
|
||||
0, channel->channel_id << 16,
|
||||
channel->cookie_high,
|
||||
channel->cookie_low,
|
||||
&ecx);
|
||||
|
||||
if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0)
|
||||
return -EINVAL;
|
||||
@@ -163,24 +155,18 @@ static int vmw_close_channel(struct rpc_channel *channel)
|
||||
static unsigned long vmw_port_hb_out(struct rpc_channel *channel,
|
||||
const char *msg, bool hb)
|
||||
{
|
||||
unsigned long si, di, eax, ebx, ecx, edx;
|
||||
u32 ebx, ecx;
|
||||
unsigned long msg_len = strlen(msg);
|
||||
|
||||
/* HB port can't access encrypted memory. */
|
||||
if (hb && !cc_platform_has(CC_ATTR_MEM_ENCRYPT)) {
|
||||
unsigned long bp = channel->cookie_high;
|
||||
u32 channel_id = (channel->channel_id << 16);
|
||||
|
||||
si = (uintptr_t) msg;
|
||||
di = channel->cookie_low;
|
||||
|
||||
VMW_PORT_HB_OUT(
|
||||
vmware_hypercall_hb_out(
|
||||
(MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG,
|
||||
msg_len, si, di,
|
||||
VMWARE_HYPERVISOR_HB | channel_id |
|
||||
VMWARE_HYPERVISOR_OUT,
|
||||
VMW_HYPERVISOR_MAGIC, bp,
|
||||
eax, ebx, ecx, edx, si, di);
|
||||
msg_len,
|
||||
channel->channel_id << 16,
|
||||
(uintptr_t) msg, channel->cookie_low,
|
||||
channel->cookie_high,
|
||||
&ebx);
|
||||
|
||||
return ebx;
|
||||
}
|
||||
@@ -194,14 +180,13 @@ static unsigned long vmw_port_hb_out(struct rpc_channel *channel,
|
||||
memcpy(&word, msg, bytes);
|
||||
msg_len -= bytes;
|
||||
msg += bytes;
|
||||
si = channel->cookie_high;
|
||||
di = channel->cookie_low;
|
||||
|
||||
VMW_PORT(VMW_PORT_CMD_MSG | (MSG_TYPE_SENDPAYLOAD << 16),
|
||||
word, si, di,
|
||||
channel->channel_id << 16,
|
||||
VMW_HYPERVISOR_MAGIC,
|
||||
eax, ebx, ecx, edx, si, di);
|
||||
vmware_hypercall5(VMW_PORT_CMD_MSG |
|
||||
(MSG_TYPE_SENDPAYLOAD << 16),
|
||||
word, channel->channel_id << 16,
|
||||
channel->cookie_high,
|
||||
channel->cookie_low,
|
||||
&ecx);
|
||||
}
|
||||
|
||||
return ecx;
|
||||
@@ -220,22 +205,17 @@ static unsigned long vmw_port_hb_out(struct rpc_channel *channel,
|
||||
static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply,
|
||||
unsigned long reply_len, bool hb)
|
||||
{
|
||||
unsigned long si, di, eax, ebx, ecx, edx;
|
||||
u32 ebx, ecx, edx;
|
||||
|
||||
/* HB port can't access encrypted memory */
|
||||
if (hb && !cc_platform_has(CC_ATTR_MEM_ENCRYPT)) {
|
||||
unsigned long bp = channel->cookie_low;
|
||||
u32 channel_id = (channel->channel_id << 16);
|
||||
|
||||
si = channel->cookie_high;
|
||||
di = (uintptr_t) reply;
|
||||
|
||||
VMW_PORT_HB_IN(
|
||||
vmware_hypercall_hb_in(
|
||||
(MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG,
|
||||
reply_len, si, di,
|
||||
VMWARE_HYPERVISOR_HB | channel_id,
|
||||
VMW_HYPERVISOR_MAGIC, bp,
|
||||
eax, ebx, ecx, edx, si, di);
|
||||
reply_len,
|
||||
channel->channel_id << 16,
|
||||
channel->cookie_high,
|
||||
(uintptr_t) reply, channel->cookie_low,
|
||||
&ebx);
|
||||
|
||||
return ebx;
|
||||
}
|
||||
@@ -245,14 +225,13 @@ static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply,
|
||||
while (reply_len) {
|
||||
unsigned int bytes = min_t(unsigned long, reply_len, 4);
|
||||
|
||||
si = channel->cookie_high;
|
||||
di = channel->cookie_low;
|
||||
|
||||
VMW_PORT(VMW_PORT_CMD_MSG | (MSG_TYPE_RECVPAYLOAD << 16),
|
||||
MESSAGE_STATUS_SUCCESS, si, di,
|
||||
channel->channel_id << 16,
|
||||
VMW_HYPERVISOR_MAGIC,
|
||||
eax, ebx, ecx, edx, si, di);
|
||||
vmware_hypercall7(VMW_PORT_CMD_MSG |
|
||||
(MSG_TYPE_RECVPAYLOAD << 16),
|
||||
MESSAGE_STATUS_SUCCESS,
|
||||
channel->channel_id << 16,
|
||||
channel->cookie_high,
|
||||
channel->cookie_low,
|
||||
&ebx, &ecx, &edx);
|
||||
|
||||
if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0)
|
||||
break;
|
||||
@@ -276,22 +255,18 @@ static unsigned long vmw_port_hb_in(struct rpc_channel *channel, char *reply,
|
||||
*/
|
||||
static int vmw_send_msg(struct rpc_channel *channel, const char *msg)
|
||||
{
|
||||
unsigned long eax, ebx, ecx, edx, si, di;
|
||||
u32 ebx, ecx;
|
||||
size_t msg_len = strlen(msg);
|
||||
int retries = 0;
|
||||
|
||||
while (retries < RETRIES) {
|
||||
retries++;
|
||||
|
||||
/* Set up additional parameters */
|
||||
si = channel->cookie_high;
|
||||
di = channel->cookie_low;
|
||||
|
||||
VMW_PORT(VMW_PORT_CMD_SENDSIZE,
|
||||
msg_len, si, di,
|
||||
channel->channel_id << 16,
|
||||
VMW_HYPERVISOR_MAGIC,
|
||||
eax, ebx, ecx, edx, si, di);
|
||||
vmware_hypercall5(VMW_PORT_CMD_SENDSIZE,
|
||||
msg_len, channel->channel_id << 16,
|
||||
channel->cookie_high,
|
||||
channel->cookie_low,
|
||||
&ecx);
|
||||
|
||||
if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) {
|
||||
/* Expected success. Give up. */
|
||||
@@ -329,7 +304,7 @@ STACK_FRAME_NON_STANDARD(vmw_send_msg);
|
||||
static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
|
||||
size_t *msg_len)
|
||||
{
|
||||
unsigned long eax, ebx, ecx, edx, si, di;
|
||||
u32 ebx, ecx, edx;
|
||||
char *reply;
|
||||
size_t reply_len;
|
||||
int retries = 0;
|
||||
@@ -341,15 +316,11 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
|
||||
while (retries < RETRIES) {
|
||||
retries++;
|
||||
|
||||
/* Set up additional parameters */
|
||||
si = channel->cookie_high;
|
||||
di = channel->cookie_low;
|
||||
|
||||
VMW_PORT(VMW_PORT_CMD_RECVSIZE,
|
||||
0, si, di,
|
||||
channel->channel_id << 16,
|
||||
VMW_HYPERVISOR_MAGIC,
|
||||
eax, ebx, ecx, edx, si, di);
|
||||
vmware_hypercall7(VMW_PORT_CMD_RECVSIZE,
|
||||
0, channel->channel_id << 16,
|
||||
channel->cookie_high,
|
||||
channel->cookie_low,
|
||||
&ebx, &ecx, &edx);
|
||||
|
||||
if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) {
|
||||
DRM_ERROR("Failed to get reply size for host message.\n");
|
||||
@@ -384,16 +355,12 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
|
||||
|
||||
reply[reply_len] = '\0';
|
||||
|
||||
|
||||
/* Ack buffer */
|
||||
si = channel->cookie_high;
|
||||
di = channel->cookie_low;
|
||||
|
||||
VMW_PORT(VMW_PORT_CMD_RECVSTATUS,
|
||||
MESSAGE_STATUS_SUCCESS, si, di,
|
||||
channel->channel_id << 16,
|
||||
VMW_HYPERVISOR_MAGIC,
|
||||
eax, ebx, ecx, edx, si, di);
|
||||
vmware_hypercall5(VMW_PORT_CMD_RECVSTATUS,
|
||||
MESSAGE_STATUS_SUCCESS,
|
||||
channel->channel_id << 16,
|
||||
channel->cookie_high,
|
||||
channel->cookie_low,
|
||||
&ecx);
|
||||
|
||||
if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) {
|
||||
kfree(reply);
|
||||
@@ -652,13 +619,7 @@ static inline void reset_ppn_array(PPN64 *arr, size_t size)
|
||||
*/
|
||||
static inline void hypervisor_ppn_reset_all(void)
|
||||
{
|
||||
unsigned long eax, ebx, ecx, edx, si = 0, di = 0;
|
||||
|
||||
VMW_PORT(VMW_PORT_CMD_MKSGS_RESET,
|
||||
0, si, di,
|
||||
0,
|
||||
VMW_HYPERVISOR_MAGIC,
|
||||
eax, ebx, ecx, edx, si, di);
|
||||
vmware_hypercall1(VMW_PORT_CMD_MKSGS_RESET, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -669,13 +630,7 @@ static inline void hypervisor_ppn_reset_all(void)
|
||||
*/
|
||||
static inline void hypervisor_ppn_add(PPN64 pfn)
|
||||
{
|
||||
unsigned long eax, ebx, ecx, edx, si = 0, di = 0;
|
||||
|
||||
VMW_PORT(VMW_PORT_CMD_MKSGS_ADD_PPN,
|
||||
(unsigned long)pfn, si, di,
|
||||
0,
|
||||
VMW_HYPERVISOR_MAGIC,
|
||||
eax, ebx, ecx, edx, si, di);
|
||||
vmware_hypercall1(VMW_PORT_CMD_MKSGS_ADD_PPN, (unsigned long)pfn);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -686,13 +641,7 @@ static inline void hypervisor_ppn_add(PPN64 pfn)
|
||||
*/
|
||||
static inline void hypervisor_ppn_remove(PPN64 pfn)
|
||||
{
|
||||
unsigned long eax, ebx, ecx, edx, si = 0, di = 0;
|
||||
|
||||
VMW_PORT(VMW_PORT_CMD_MKSGS_REMOVE_PPN,
|
||||
(unsigned long)pfn, si, di,
|
||||
0,
|
||||
VMW_HYPERVISOR_MAGIC,
|
||||
eax, ebx, ecx, edx, si, di);
|
||||
vmware_hypercall1(VMW_PORT_CMD_MKSGS_REMOVE_PPN, (unsigned long)pfn);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_VMWGFX_MKSSTATS)
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
#define VMWARE_HYPERVISOR_HB BIT(0)
|
||||
#define VMWARE_HYPERVISOR_OUT BIT(1)
|
||||
|
||||
#define VMWARE_HYPERVISOR_MAGIC 0x564D5868
|
||||
|
||||
#define X86_IO_MAGIC 0x86
|
||||
|
||||
#define X86_IO_W7_SIZE_SHIFT 0
|
||||
@@ -45,86 +47,158 @@
|
||||
#define X86_IO_W7_IMM_SHIFT 5
|
||||
#define X86_IO_W7_IMM_MASK (0xff << X86_IO_W7_IMM_SHIFT)
|
||||
|
||||
static inline void vmw_port(unsigned long cmd, unsigned long in_ebx,
|
||||
unsigned long in_si, unsigned long in_di,
|
||||
unsigned long flags, unsigned long magic,
|
||||
unsigned long *eax, unsigned long *ebx,
|
||||
unsigned long *ecx, unsigned long *edx,
|
||||
unsigned long *si, unsigned long *di)
|
||||
static inline
|
||||
unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1)
|
||||
{
|
||||
register u64 x0 asm("x0") = magic;
|
||||
register u64 x1 asm("x1") = in_ebx;
|
||||
register u64 x0 asm("x0") = VMWARE_HYPERVISOR_MAGIC;
|
||||
register u64 x1 asm("x1") = in1;
|
||||
register u64 x2 asm("x2") = cmd;
|
||||
register u64 x3 asm("x3") = flags | VMWARE_HYPERVISOR_PORT;
|
||||
register u64 x4 asm("x4") = in_si;
|
||||
register u64 x5 asm("x5") = in_di;
|
||||
|
||||
register u64 x3 asm("x3") = VMWARE_HYPERVISOR_PORT;
|
||||
register u64 x7 asm("x7") = ((u64)X86_IO_MAGIC << 32) |
|
||||
X86_IO_W7_WITH |
|
||||
X86_IO_W7_DIR |
|
||||
(2 << X86_IO_W7_SIZE_SHIFT);
|
||||
|
||||
asm volatile("mrs xzr, mdccsr_el0 \n\t"
|
||||
: "+r"(x0), "+r"(x1), "+r"(x2),
|
||||
"+r"(x3), "+r"(x4), "+r"(x5)
|
||||
: "r"(x7)
|
||||
:);
|
||||
*eax = x0;
|
||||
*ebx = x1;
|
||||
*ecx = x2;
|
||||
*edx = x3;
|
||||
*si = x4;
|
||||
*di = x5;
|
||||
asm_inline volatile (
|
||||
"mrs xzr, mdccsr_el0; "
|
||||
: "+r" (x0)
|
||||
: "r" (x1), "r" (x2), "r" (x3), "r" (x7)
|
||||
: "memory");
|
||||
|
||||
return x0;
|
||||
}
|
||||
|
||||
static inline void vmw_port_hb(unsigned long cmd, unsigned long in_ecx,
|
||||
unsigned long in_si, unsigned long in_di,
|
||||
unsigned long flags, unsigned long magic,
|
||||
unsigned long bp, u32 w7dir,
|
||||
unsigned long *eax, unsigned long *ebx,
|
||||
unsigned long *ecx, unsigned long *edx,
|
||||
unsigned long *si, unsigned long *di)
|
||||
static inline
|
||||
unsigned long vmware_hypercall5(unsigned long cmd, unsigned long in1,
|
||||
unsigned long in3, unsigned long in4,
|
||||
unsigned long in5, u32 *out2)
|
||||
{
|
||||
register u64 x0 asm("x0") = magic;
|
||||
register u64 x0 asm("x0") = VMWARE_HYPERVISOR_MAGIC;
|
||||
register u64 x1 asm("x1") = in1;
|
||||
register u64 x2 asm("x2") = cmd;
|
||||
register u64 x3 asm("x3") = in3 | VMWARE_HYPERVISOR_PORT;
|
||||
register u64 x4 asm("x4") = in4;
|
||||
register u64 x5 asm("x5") = in5;
|
||||
register u64 x7 asm("x7") = ((u64)X86_IO_MAGIC << 32) |
|
||||
X86_IO_W7_WITH |
|
||||
X86_IO_W7_DIR |
|
||||
(2 << X86_IO_W7_SIZE_SHIFT);
|
||||
|
||||
asm_inline volatile (
|
||||
"mrs xzr, mdccsr_el0; "
|
||||
: "+r" (x0), "+r" (x2)
|
||||
: "r" (x1), "r" (x3), "r" (x4), "r" (x5), "r" (x7)
|
||||
: "memory");
|
||||
|
||||
*out2 = x2;
|
||||
return x0;
|
||||
}
|
||||
|
||||
static inline
|
||||
unsigned long vmware_hypercall6(unsigned long cmd, unsigned long in1,
|
||||
unsigned long in3, u32 *out2,
|
||||
u32 *out3, u32 *out4, u32 *out5)
|
||||
{
|
||||
register u64 x0 asm("x0") = VMWARE_HYPERVISOR_MAGIC;
|
||||
register u64 x1 asm("x1") = in1;
|
||||
register u64 x2 asm("x2") = cmd;
|
||||
register u64 x3 asm("x3") = in3 | VMWARE_HYPERVISOR_PORT;
|
||||
register u64 x4 asm("x4");
|
||||
register u64 x5 asm("x5");
|
||||
register u64 x7 asm("x7") = ((u64)X86_IO_MAGIC << 32) |
|
||||
X86_IO_W7_WITH |
|
||||
X86_IO_W7_DIR |
|
||||
(2 << X86_IO_W7_SIZE_SHIFT);
|
||||
|
||||
asm_inline volatile (
|
||||
"mrs xzr, mdccsr_el0; "
|
||||
: "+r" (x0), "+r" (x2), "+r" (x3), "=r" (x4), "=r" (x5)
|
||||
: "r" (x1), "r" (x7)
|
||||
: "memory");
|
||||
|
||||
*out2 = x2;
|
||||
*out3 = x3;
|
||||
*out4 = x4;
|
||||
*out5 = x5;
|
||||
return x0;
|
||||
}
|
||||
|
||||
static inline
|
||||
unsigned long vmware_hypercall7(unsigned long cmd, unsigned long in1,
|
||||
unsigned long in3, unsigned long in4,
|
||||
unsigned long in5, u32 *out1,
|
||||
u32 *out2, u32 *out3)
|
||||
{
|
||||
register u64 x0 asm("x0") = VMWARE_HYPERVISOR_MAGIC;
|
||||
register u64 x1 asm("x1") = in1;
|
||||
register u64 x2 asm("x2") = cmd;
|
||||
register u64 x3 asm("x3") = in3 | VMWARE_HYPERVISOR_PORT;
|
||||
register u64 x4 asm("x4") = in4;
|
||||
register u64 x5 asm("x5") = in5;
|
||||
register u64 x7 asm("x7") = ((u64)X86_IO_MAGIC << 32) |
|
||||
X86_IO_W7_WITH |
|
||||
X86_IO_W7_DIR |
|
||||
(2 << X86_IO_W7_SIZE_SHIFT);
|
||||
|
||||
asm_inline volatile (
|
||||
"mrs xzr, mdccsr_el0; "
|
||||
: "+r" (x0), "+r" (x1), "+r" (x2), "+r" (x3)
|
||||
: "r" (x4), "r" (x5), "r" (x7)
|
||||
: "memory");
|
||||
|
||||
*out1 = x1;
|
||||
*out2 = x2;
|
||||
*out3 = x3;
|
||||
return x0;
|
||||
}
|
||||
|
||||
static inline
|
||||
unsigned long vmware_hypercall_hb(unsigned long cmd, unsigned long in2,
|
||||
unsigned long in3, unsigned long in4,
|
||||
unsigned long in5, unsigned long in6,
|
||||
u32 *out1, int dir)
|
||||
{
|
||||
register u64 x0 asm("x0") = VMWARE_HYPERVISOR_MAGIC;
|
||||
register u64 x1 asm("x1") = cmd;
|
||||
register u64 x2 asm("x2") = in_ecx;
|
||||
register u64 x3 asm("x3") = flags | VMWARE_HYPERVISOR_PORT_HB;
|
||||
register u64 x4 asm("x4") = in_si;
|
||||
register u64 x5 asm("x5") = in_di;
|
||||
register u64 x6 asm("x6") = bp;
|
||||
register u64 x2 asm("x2") = in2;
|
||||
register u64 x3 asm("x3") = in3 | VMWARE_HYPERVISOR_PORT_HB;
|
||||
register u64 x4 asm("x4") = in4;
|
||||
register u64 x5 asm("x5") = in5;
|
||||
register u64 x6 asm("x6") = in6;
|
||||
register u64 x7 asm("x7") = ((u64)X86_IO_MAGIC << 32) |
|
||||
X86_IO_W7_STR |
|
||||
X86_IO_W7_WITH |
|
||||
w7dir;
|
||||
dir;
|
||||
|
||||
asm volatile("mrs xzr, mdccsr_el0 \n\t"
|
||||
: "+r"(x0), "+r"(x1), "+r"(x2),
|
||||
"+r"(x3), "+r"(x4), "+r"(x5)
|
||||
: "r"(x6), "r"(x7)
|
||||
:);
|
||||
*eax = x0;
|
||||
*ebx = x1;
|
||||
*ecx = x2;
|
||||
*edx = x3;
|
||||
*si = x4;
|
||||
*di = x5;
|
||||
asm_inline volatile (
|
||||
"mrs xzr, mdccsr_el0; "
|
||||
: "+r" (x0), "+r" (x1)
|
||||
: "r" (x2), "r" (x3), "r" (x4), "r" (x5),
|
||||
"r" (x6), "r" (x7)
|
||||
: "memory");
|
||||
|
||||
*out1 = x1;
|
||||
return x0;
|
||||
}
|
||||
|
||||
#define VMW_PORT(cmd, in_ebx, in_si, in_di, flags, magic, eax, ebx, ecx, edx, \
|
||||
si, di) \
|
||||
vmw_port(cmd, in_ebx, in_si, in_di, flags, magic, &eax, &ebx, &ecx, \
|
||||
&edx, &si, &di)
|
||||
|
||||
#define VMW_PORT_HB_OUT(cmd, in_ecx, in_si, in_di, flags, magic, bp, eax, ebx, \
|
||||
ecx, edx, si, di) \
|
||||
vmw_port_hb(cmd, in_ecx, in_si, in_di, flags, magic, bp, \
|
||||
0, &eax, &ebx, &ecx, &edx, &si, &di)
|
||||
|
||||
#define VMW_PORT_HB_IN(cmd, in_ecx, in_si, in_di, flags, magic, bp, eax, ebx, \
|
||||
ecx, edx, si, di) \
|
||||
vmw_port_hb(cmd, in_ecx, in_si, in_di, flags, magic, bp, \
|
||||
X86_IO_W7_DIR, &eax, &ebx, &ecx, &edx, &si, &di)
|
||||
static inline
|
||||
unsigned long vmware_hypercall_hb_out(unsigned long cmd, unsigned long in2,
|
||||
unsigned long in3, unsigned long in4,
|
||||
unsigned long in5, unsigned long in6,
|
||||
u32 *out1)
|
||||
{
|
||||
return vmware_hypercall_hb(cmd, in2, in3, in4, in5, in6, out1, 0);
|
||||
}
|
||||
|
||||
static inline
|
||||
unsigned long vmware_hypercall_hb_in(unsigned long cmd, unsigned long in2,
|
||||
unsigned long in3, unsigned long in4,
|
||||
unsigned long in5, unsigned long in6,
|
||||
u32 *out1)
|
||||
{
|
||||
return vmware_hypercall_hb(cmd, in2, in3, in4, in5, in6, out1,
|
||||
X86_IO_W7_DIR);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _VMWGFX_MSG_ARM64_H */
|
||||
|
||||
@@ -37,191 +37,6 @@
|
||||
|
||||
#include <asm/vmware.h>
|
||||
|
||||
/**
|
||||
* Hypervisor-specific bi-directional communication channel. Should never
|
||||
* execute on bare metal hardware. The caller must make sure to check for
|
||||
* supported hypervisor before using these macros.
|
||||
*
|
||||
* The last two parameters are both input and output and must be initialized.
|
||||
*
|
||||
* @cmd: [IN] Message Cmd
|
||||
* @in_ebx: [IN] Message Len, through EBX
|
||||
* @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
|
||||
* @flags: [IN] hypercall flags + [channel id]
|
||||
* @magic: [IN] hypervisor magic value
|
||||
* @eax: [OUT] value of EAX register
|
||||
* @ebx: [OUT] e.g. status from an HB message status command
|
||||
* @ecx: [OUT] e.g. status from a non-HB message status command
|
||||
* @edx: [OUT] e.g. channel id
|
||||
* @si: [OUT]
|
||||
* @di: [OUT]
|
||||
*/
|
||||
#define VMW_PORT(cmd, in_ebx, in_si, in_di, \
|
||||
flags, magic, \
|
||||
eax, ebx, ecx, edx, si, di) \
|
||||
({ \
|
||||
asm volatile (VMWARE_HYPERCALL : \
|
||||
"=a"(eax), \
|
||||
"=b"(ebx), \
|
||||
"=c"(ecx), \
|
||||
"=d"(edx), \
|
||||
"=S"(si), \
|
||||
"=D"(di) : \
|
||||
"a"(magic), \
|
||||
"b"(in_ebx), \
|
||||
"c"(cmd), \
|
||||
"d"(flags), \
|
||||
"S"(in_si), \
|
||||
"D"(in_di) : \
|
||||
"memory"); \
|
||||
})
|
||||
|
||||
|
||||
/**
|
||||
* Hypervisor-specific bi-directional communication channel. Should never
|
||||
* execute on bare metal hardware. The caller must make sure to check for
|
||||
* supported hypervisor before using these macros.
|
||||
*
|
||||
* The last 3 parameters are both input and output and must be initialized.
|
||||
*
|
||||
* @cmd: [IN] Message Cmd
|
||||
* @in_ecx: [IN] Message Len, through ECX
|
||||
* @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
|
||||
* @flags: [IN] hypercall flags + [channel id]
|
||||
* @magic: [IN] hypervisor magic value
|
||||
* @bp: [IN]
|
||||
* @eax: [OUT] value of EAX register
|
||||
* @ebx: [OUT] e.g. status from an HB message status command
|
||||
* @ecx: [OUT] e.g. status from a non-HB message status command
|
||||
* @edx: [OUT] e.g. channel id
|
||||
* @si: [OUT]
|
||||
* @di: [OUT]
|
||||
*/
|
||||
#ifdef __x86_64__
|
||||
|
||||
#define VMW_PORT_HB_OUT(cmd, in_ecx, in_si, in_di, \
|
||||
flags, magic, bp, \
|
||||
eax, ebx, ecx, edx, si, di) \
|
||||
({ \
|
||||
asm volatile ( \
|
||||
UNWIND_HINT_SAVE \
|
||||
"push %%rbp;" \
|
||||
UNWIND_HINT_UNDEFINED \
|
||||
"mov %12, %%rbp;" \
|
||||
VMWARE_HYPERCALL_HB_OUT \
|
||||
"pop %%rbp;" \
|
||||
UNWIND_HINT_RESTORE : \
|
||||
"=a"(eax), \
|
||||
"=b"(ebx), \
|
||||
"=c"(ecx), \
|
||||
"=d"(edx), \
|
||||
"=S"(si), \
|
||||
"=D"(di) : \
|
||||
"a"(magic), \
|
||||
"b"(cmd), \
|
||||
"c"(in_ecx), \
|
||||
"d"(flags), \
|
||||
"S"(in_si), \
|
||||
"D"(in_di), \
|
||||
"r"(bp) : \
|
||||
"memory", "cc"); \
|
||||
})
|
||||
|
||||
|
||||
#define VMW_PORT_HB_IN(cmd, in_ecx, in_si, in_di, \
|
||||
flags, magic, bp, \
|
||||
eax, ebx, ecx, edx, si, di) \
|
||||
({ \
|
||||
asm volatile ( \
|
||||
UNWIND_HINT_SAVE \
|
||||
"push %%rbp;" \
|
||||
UNWIND_HINT_UNDEFINED \
|
||||
"mov %12, %%rbp;" \
|
||||
VMWARE_HYPERCALL_HB_IN \
|
||||
"pop %%rbp;" \
|
||||
UNWIND_HINT_RESTORE : \
|
||||
"=a"(eax), \
|
||||
"=b"(ebx), \
|
||||
"=c"(ecx), \
|
||||
"=d"(edx), \
|
||||
"=S"(si), \
|
||||
"=D"(di) : \
|
||||
"a"(magic), \
|
||||
"b"(cmd), \
|
||||
"c"(in_ecx), \
|
||||
"d"(flags), \
|
||||
"S"(in_si), \
|
||||
"D"(in_di), \
|
||||
"r"(bp) : \
|
||||
"memory", "cc"); \
|
||||
})
|
||||
|
||||
#elif defined(__i386__)
|
||||
|
||||
/*
|
||||
* In the 32-bit version of this macro, we store bp in a memory location
|
||||
* because we've ran out of registers.
|
||||
* Now we can't reference that memory location while we've modified
|
||||
* %esp or %ebp, so we first push it on the stack, just before we push
|
||||
* %ebp, and then when we need it we read it from the stack where we
|
||||
* just pushed it.
|
||||
*/
|
||||
#define VMW_PORT_HB_OUT(cmd, in_ecx, in_si, in_di, \
|
||||
flags, magic, bp, \
|
||||
eax, ebx, ecx, edx, si, di) \
|
||||
({ \
|
||||
asm volatile ("push %12;" \
|
||||
"push %%ebp;" \
|
||||
"mov 0x04(%%esp), %%ebp;" \
|
||||
VMWARE_HYPERCALL_HB_OUT \
|
||||
"pop %%ebp;" \
|
||||
"add $0x04, %%esp;" : \
|
||||
"=a"(eax), \
|
||||
"=b"(ebx), \
|
||||
"=c"(ecx), \
|
||||
"=d"(edx), \
|
||||
"=S"(si), \
|
||||
"=D"(di) : \
|
||||
"a"(magic), \
|
||||
"b"(cmd), \
|
||||
"c"(in_ecx), \
|
||||
"d"(flags), \
|
||||
"S"(in_si), \
|
||||
"D"(in_di), \
|
||||
"m"(bp) : \
|
||||
"memory", "cc"); \
|
||||
})
|
||||
|
||||
|
||||
#define VMW_PORT_HB_IN(cmd, in_ecx, in_si, in_di, \
|
||||
flags, magic, bp, \
|
||||
eax, ebx, ecx, edx, si, di) \
|
||||
({ \
|
||||
asm volatile ("push %12;" \
|
||||
"push %%ebp;" \
|
||||
"mov 0x04(%%esp), %%ebp;" \
|
||||
VMWARE_HYPERCALL_HB_IN \
|
||||
"pop %%ebp;" \
|
||||
"add $0x04, %%esp;" : \
|
||||
"=a"(eax), \
|
||||
"=b"(ebx), \
|
||||
"=c"(ecx), \
|
||||
"=d"(edx), \
|
||||
"=S"(si), \
|
||||
"=D"(di) : \
|
||||
"a"(magic), \
|
||||
"b"(cmd), \
|
||||
"c"(in_ecx), \
|
||||
"d"(flags), \
|
||||
"S"(in_si), \
|
||||
"D"(in_di), \
|
||||
"m"(bp) : \
|
||||
"memory", "cc"); \
|
||||
})
|
||||
#endif /* defined(__i386__) */
|
||||
|
||||
#endif /* defined(__i386__) || defined(__x86_64__) */
|
||||
|
||||
#endif /* _VMWGFX_MSG_X86_H */
|
||||
|
||||
Reference in New Issue
Block a user