Skip to content

Commit 20c89a5

Browse files
Tianyu Lanliuw
authored andcommitted
x86/hyperv: Add ghcb hvcall support for SNP VM
hyperv provides ghcb hvcall to handle VMBus HVCALL_SIGNAL_EVENT and HVCALL_POST_MESSAGE msg in SNP Isolation VM. Add such support. Reviewed-by: Michael Kelley <[email protected]> Signed-off-by: Tianyu Lan <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Wei Liu <[email protected]>
1 parent faff440 commit 20c89a5

File tree

5 files changed

+94
-2
lines changed

5 files changed

+94
-2
lines changed

arch/x86/hyperv/ivm.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,85 @@
1919
#include <asm/hypervisor.h>
2020

2121
#ifdef CONFIG_AMD_MEM_ENCRYPT
22+
23+
#define GHCB_USAGE_HYPERV_CALL 1
24+
2225
union hv_ghcb {
2326
struct ghcb ghcb;
27+
struct {
28+
u64 hypercalldata[509];
29+
u64 outputgpa;
30+
union {
31+
union {
32+
struct {
33+
u32 callcode : 16;
34+
u32 isfast : 1;
35+
u32 reserved1 : 14;
36+
u32 isnested : 1;
37+
u32 countofelements : 12;
38+
u32 reserved2 : 4;
39+
u32 repstartindex : 12;
40+
u32 reserved3 : 4;
41+
};
42+
u64 asuint64;
43+
} hypercallinput;
44+
union {
45+
struct {
46+
u16 callstatus;
47+
u16 reserved1;
48+
u32 elementsprocessed : 12;
49+
u32 reserved2 : 20;
50+
};
51+
u64 asunit64;
52+
} hypercalloutput;
53+
};
54+
u64 reserved2;
55+
} hypercall;
2456
} __packed __aligned(HV_HYP_PAGE_SIZE);
2557

58+
u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size)
59+
{
60+
union hv_ghcb *hv_ghcb;
61+
void **ghcb_base;
62+
unsigned long flags;
63+
u64 status;
64+
65+
if (!hv_ghcb_pg)
66+
return -EFAULT;
67+
68+
WARN_ON(in_nmi());
69+
70+
local_irq_save(flags);
71+
ghcb_base = (void **)this_cpu_ptr(hv_ghcb_pg);
72+
hv_ghcb = (union hv_ghcb *)*ghcb_base;
73+
if (!hv_ghcb) {
74+
local_irq_restore(flags);
75+
return -EFAULT;
76+
}
77+
78+
hv_ghcb->ghcb.protocol_version = GHCB_PROTOCOL_MAX;
79+
hv_ghcb->ghcb.ghcb_usage = GHCB_USAGE_HYPERV_CALL;
80+
81+
hv_ghcb->hypercall.outputgpa = (u64)output;
82+
hv_ghcb->hypercall.hypercallinput.asuint64 = 0;
83+
hv_ghcb->hypercall.hypercallinput.callcode = control;
84+
85+
if (input_size)
86+
memcpy(hv_ghcb->hypercall.hypercalldata, input, input_size);
87+
88+
VMGEXIT();
89+
90+
hv_ghcb->ghcb.ghcb_usage = 0xffffffff;
91+
memset(hv_ghcb->ghcb.save.valid_bitmap, 0,
92+
sizeof(hv_ghcb->ghcb.save.valid_bitmap));
93+
94+
status = hv_ghcb->hypercall.hypercalloutput.callstatus;
95+
96+
local_irq_restore(flags);
97+
98+
return status;
99+
}
100+
26101
void hv_ghcb_msr_write(u64 msr, u64 value)
27102
{
28103
union hv_ghcb *hv_ghcb;

drivers/hv/connection.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,10 @@ void vmbus_set_event(struct vmbus_channel *channel)
447447

448448
++channel->sig_events;
449449

450-
hv_do_fast_hypercall8(HVCALL_SIGNAL_EVENT, channel->sig_event);
450+
if (hv_isolation_type_snp())
451+
hv_ghcb_hypercall(HVCALL_SIGNAL_EVENT, &channel->sig_event,
452+
NULL, sizeof(channel->sig_event));
453+
else
454+
hv_do_fast_hypercall8(HVCALL_SIGNAL_EVENT, channel->sig_event);
451455
}
452456
EXPORT_SYMBOL_GPL(vmbus_set_event);

drivers/hv/hv.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,13 @@ int hv_post_message(union hv_connection_id connection_id,
9898
aligned_msg->payload_size = payload_size;
9999
memcpy((void *)aligned_msg->payload, payload, payload_size);
100100

101-
status = hv_do_hypercall(HVCALL_POST_MESSAGE, aligned_msg, NULL);
101+
if (hv_isolation_type_snp())
102+
status = hv_ghcb_hypercall(HVCALL_POST_MESSAGE,
103+
(void *)aligned_msg, NULL,
104+
sizeof(*aligned_msg));
105+
else
106+
status = hv_do_hypercall(HVCALL_POST_MESSAGE,
107+
aligned_msg, NULL);
102108

103109
/* Preemption must remain disabled until after the hypercall
104110
* so some other thread can't get scheduled onto this cpu and

drivers/hv/hv_common.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,3 +289,9 @@ void __weak hyperv_cleanup(void)
289289
{
290290
}
291291
EXPORT_SYMBOL_GPL(hyperv_cleanup);
292+
293+
u64 __weak hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size)
294+
{
295+
return HV_STATUS_INVALID_PARAMETER;
296+
}
297+
EXPORT_SYMBOL_GPL(hv_ghcb_hypercall);

include/asm-generic/mshyperv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ bool hv_is_hibernation_supported(void);
266266
enum hv_isolation_type hv_get_isolation_type(void);
267267
bool hv_is_isolation_supported(void);
268268
bool hv_isolation_type_snp(void);
269+
u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size);
269270
void hyperv_cleanup(void);
270271
bool hv_query_ext_cap(u64 cap_query);
271272
#else /* CONFIG_HYPERV */

0 commit comments

Comments
 (0)