2023-08-04 16:27:43

by Tianyu Lan

[permalink] [raw]
Subject: [PATCH V4 0/9] x86/hyperv: Add AMD sev-snp enlightened guest support on hyperv

From: Tianyu Lan <[email protected]>

Hyper-V provides two modes for running SEV-SNP VMs:

1) In vTOM mode with a paravisor (see Section 15.36.8 of [1])
2) In "fully enlightened" mode with normal "C" bit control
over page encryption, and no paravisor

For #1, the paravisor runs in VMPL 0, while Linux runs in VMPL 2
(see Section 15.36.7 of [1]). The paravisor is typically provided
by Hyper-V and handles most of the SNP-related functionality. As
such, most of the SNP functionality in the Linux guest is bypassed.
The guest operates in vTOM mode, where encryption is enabled by default.
The guest must still request page transitions between private and shared,
but there is relatively less SNP machinery required in the guest. Support
for this mode of operation first went upstream in the 5.15 kernel.

For #2, this patch set provides the initial support. The existing
SEV-SNP machinery in the kernel is fully used, but Hyper-V specific
updates are required to properly share Hyper-V communication pages
between the guest and host and to start APs at boot time.

In either mode, Hyper-V requires that the guest implement the SEV-SNP
Restricted Interrupt Injection feature (see Section 15.36.16 of [1],
and Section 5 of [2]). Without this feature, the guest is subject to
attack by a compromised hypervisor that can inject any exception at
any time, such as injecting an interrupt while the guest has interrupts
disabled. In vTOM mode, Restricted Interrupt Injection is implemented
by the paravisor, so no Linux guest changes are required. But in fully
enlightened mode, the Linux guest must provide the implementation.

This patch set is derived from an earlier patch set that includes both
the Hyper-V specific changes and Restricted Interrupt Injection support.[3]
But it is now limited to only the Hyper-V specific changes. The Restricted
Interrupt Injection support will come later in a separate patch set.


[1] https://www.amd.com/system/files/TechDocs/24593.pdf
[2] https://www.amd.com/system/files/TechDocs/56421-guest-hypervisor-communication-block-standardization.pdf
[3] https://lore.kernel.org/lkml/[email protected]/

Change since v3:
* Fix fossil comment

Change since v2:
* Update Change log.
* Rework Hyper-V hypercall implementation.

Change since v1:
* vTOM case uses paravisor_present flag and
HV_ISOLATION_TYPE_SNP type.
* Rework some patches' change log
* Fix some comments in the patches

Tianyu Lan (9):
x86/hyperv: Add sev-snp enlightened guest static key
x86/hyperv: Set Virtual Trust Level in VMBus init message
x86/hyperv: Mark Hyper-V vp assist page unencrypted in SEV-SNP
enlightened guest
drivers: hv: Mark percpu hvcall input arg page unencrypted in SEV-SNP
enlightened guest
x86/hyperv: Use vmmcall to implement Hyper-V hypercall in sev-snp
enlightened guest
clocksource: hyper-v: Mark hyperv tsc page unencrypted in sev-snp
enlightened guest
x86/hyperv: Add smp support for SEV-SNP guest
x86/hyperv: Add hyperv-specific handling for VMMCALL under SEV-ES
x86/hyperv: Initialize cpu and memory for SEV-SNP enlightened guest

arch/x86/hyperv/hv_init.c | 52 +++++++-
arch/x86/hyperv/ivm.c | 199 +++++++++++++++++++++++++++++
arch/x86/include/asm/hyperv-tlfs.h | 7 +
arch/x86/include/asm/mshyperv.h | 56 ++++++--
arch/x86/kernel/cpu/mshyperv.c | 42 +++++-
drivers/clocksource/hyperv_timer.c | 2 +-
drivers/hv/connection.c | 1 +
drivers/hv/hv.c | 57 ++++++++-
drivers/hv/hv_common.c | 19 +++
include/asm-generic/hyperv-tlfs.h | 1 +
include/asm-generic/mshyperv.h | 13 +-
include/linux/hyperv.h | 4 +-
12 files changed, 426 insertions(+), 27 deletions(-)

--
2.25.1



2023-08-04 16:32:05

by Tianyu Lan

[permalink] [raw]
Subject: [PATCH V4 1/9] x86/hyperv: Add sev-snp enlightened guest static key

From: Tianyu Lan <[email protected]>

Introduce static key isolation_type_en_snp for enlightened
sev-snp guest check.

Reviewed-by: Michael Kelley <[email protected]>
Signed-off-by: Tianyu Lan <[email protected]>
---
arch/x86/hyperv/ivm.c | 11 +++++++++++
arch/x86/include/asm/mshyperv.h | 3 +++
arch/x86/kernel/cpu/mshyperv.c | 9 +++++++--
drivers/hv/hv_common.c | 6 ++++++
include/asm-generic/mshyperv.h | 12 +++++++++---
5 files changed, 36 insertions(+), 5 deletions(-)

diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c
index 14f46ad2ca64..b2b5cb19fac9 100644
--- a/arch/x86/hyperv/ivm.c
+++ b/arch/x86/hyperv/ivm.c
@@ -413,3 +413,14 @@ bool hv_isolation_type_snp(void)
{
return static_branch_unlikely(&isolation_type_snp);
}
+
+DEFINE_STATIC_KEY_FALSE(isolation_type_en_snp);
+/*
+ * hv_isolation_type_en_snp - Check system runs in the AMD SEV-SNP based
+ * isolation enlightened VM.
+ */
+bool hv_isolation_type_en_snp(void)
+{
+ return static_branch_unlikely(&isolation_type_en_snp);
+}
+
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 88d9ef98e087..2fa38e9f6207 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -26,6 +26,7 @@
union hv_ghcb;

DECLARE_STATIC_KEY_FALSE(isolation_type_snp);
+DECLARE_STATIC_KEY_FALSE(isolation_type_en_snp);

typedef int (*hyperv_fill_flush_list_func)(
struct hv_guest_mapping_flush_list *flush,
@@ -45,6 +46,8 @@ extern void *hv_hypercall_pg;

extern u64 hv_current_partition_id;

+extern bool hv_isolation_type_en_snp(void);
+
extern union hv_ghcb * __percpu *hv_ghcb_pg;

int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages);
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index c7969e806c64..5398fb2f4d39 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -402,8 +402,12 @@ static void __init ms_hyperv_init_platform(void)
pr_info("Hyper-V: Isolation Config: Group A 0x%x, Group B 0x%x\n",
ms_hyperv.isolation_config_a, ms_hyperv.isolation_config_b);

- if (hv_get_isolation_type() == HV_ISOLATION_TYPE_SNP)
+
+ if (cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) {
+ static_branch_enable(&isolation_type_en_snp);
+ } else if (hv_get_isolation_type() == HV_ISOLATION_TYPE_SNP) {
static_branch_enable(&isolation_type_snp);
+ }
}

if (hv_max_functions_eax >= HYPERV_CPUID_NESTED_FEATURES) {
@@ -473,7 +477,8 @@ static void __init ms_hyperv_init_platform(void)

#if IS_ENABLED(CONFIG_HYPERV)
if ((hv_get_isolation_type() == HV_ISOLATION_TYPE_VBS) ||
- (hv_get_isolation_type() == HV_ISOLATION_TYPE_SNP))
+ ((hv_get_isolation_type() == HV_ISOLATION_TYPE_SNP) &&
+ ms_hyperv.paravisor_present))
hv_vtom_init();
/*
* Setup the hook to get control post apic initialization.
diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
index 542a1d53b303..4b4aa53c34c2 100644
--- a/drivers/hv/hv_common.c
+++ b/drivers/hv/hv_common.c
@@ -502,6 +502,12 @@ bool __weak hv_isolation_type_snp(void)
}
EXPORT_SYMBOL_GPL(hv_isolation_type_snp);

+bool __weak hv_isolation_type_en_snp(void)
+{
+ return false;
+}
+EXPORT_SYMBOL_GPL(hv_isolation_type_en_snp);
+
void __weak hv_setup_vmbus_handler(void (*handler)(void))
{
}
diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
index 402a8c1c202d..6b5c41f90398 100644
--- a/include/asm-generic/mshyperv.h
+++ b/include/asm-generic/mshyperv.h
@@ -36,15 +36,21 @@ struct ms_hyperv_info {
u32 nested_features;
u32 max_vp_index;
u32 max_lp_index;
- u32 isolation_config_a;
+ union {
+ u32 isolation_config_a;
+ struct {
+ u32 paravisor_present : 1;
+ u32 reserved_a1 : 31;
+ };
+ };
union {
u32 isolation_config_b;
struct {
u32 cvm_type : 4;
- u32 reserved1 : 1;
+ u32 reserved_b1 : 1;
u32 shared_gpa_boundary_active : 1;
u32 shared_gpa_boundary_bits : 6;
- u32 reserved2 : 20;
+ u32 reserved_b2 : 20;
};
};
u64 shared_gpa_boundary;
--
2.25.1


2023-08-04 16:34:09

by Tianyu Lan

[permalink] [raw]
Subject: [PATCH V4 9/9] x86/hyperv: Initialize cpu and memory for SEV-SNP enlightened guest

From: Tianyu Lan <[email protected]>

Hyper-V enlightened guest doesn't have boot loader support.
Boot Linux kernel directly from hypervisor with data (kernel
image, initrd and parameter page) and memory for boot up that
is initialized via AMD SEV PSP protocol (Please reference
Section 4.5 Launching a Guest of [1]).

Kernel needs to read processor and memory info from EN_SEV_
SNP_PROCESSOR/MEM_INFO_ADDR address which are populated by
Hyper-V. The data is prepared by hypervisor via SNP_
LAUNCH_UPDATE with page type SNP_PAGE_TYPE_UNMEASURED and
Initialize smp cpu related ops, validate system memory and
add them into e820 table.

[1]: https://www.amd.com/system/files/TechDocs/56860.pdf
Reviewed-by: Michael Kelley <[email protected]>
Signed-off-by: Tianyu Lan <[email protected]>
---
Change since v2:
* Update change log.
---
arch/x86/hyperv/ivm.c | 88 +++++++++++++++++++++++++++++++++
arch/x86/include/asm/mshyperv.h | 17 +++++++
arch/x86/kernel/cpu/mshyperv.c | 3 ++
3 files changed, 108 insertions(+)

diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c
index ee08a0cd6da3..e86b2a54cdfd 100644
--- a/arch/x86/hyperv/ivm.c
+++ b/arch/x86/hyperv/ivm.c
@@ -67,6 +67,8 @@ union hv_ghcb {

static u16 hv_ghcb_version __ro_after_init;

+static u32 processor_count;
+
u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size)
{
union hv_ghcb *hv_ghcb;
@@ -457,6 +459,92 @@ int hv_snp_boot_ap(int cpu, unsigned long start_ip)
return ret;
}

+static __init void hv_snp_get_smp_config(unsigned int early)
+{
+ /*
+ * The "early" parameter can be true only if old-style AMD
+ * Opteron NUMA detection is enabled, which should never be
+ * the case for an SEV-SNP guest. See CONFIG_AMD_NUMA.
+ * For safety, just do nothing if "early" is true.
+ */
+ if (early)
+ return;
+
+ /*
+ * There is no firmware and ACPI MADT table support in
+ * in the Hyper-V SEV-SNP enlightened guest. Set smp
+ * related config variable here.
+ */
+ while (num_processors < processor_count) {
+ early_per_cpu(x86_cpu_to_apicid, num_processors) = num_processors;
+ early_per_cpu(x86_bios_cpu_apicid, num_processors) = num_processors;
+ physid_set(num_processors, phys_cpu_present_map);
+ set_cpu_possible(num_processors, true);
+ set_cpu_present(num_processors, true);
+ num_processors++;
+ }
+}
+
+__init void hv_sev_init_mem_and_cpu(void)
+{
+ struct memory_map_entry *entry;
+ struct e820_entry *e820_entry;
+ u64 e820_end;
+ u64 ram_end;
+ u64 page;
+
+ /*
+ * Hyper-V enlightened snp guest boots kernel
+ * directly without bootloader. So roms, bios
+ * regions and reserve resources are not available.
+ * Set these callback to NULL.
+ */
+ x86_platform.legacy.rtc = 0;
+ x86_platform.legacy.reserve_bios_regions = 0;
+ x86_platform.set_wallclock = set_rtc_noop;
+ x86_platform.get_wallclock = get_rtc_noop;
+ x86_init.resources.probe_roms = x86_init_noop;
+ x86_init.resources.reserve_resources = x86_init_noop;
+ x86_init.mpparse.find_smp_config = x86_init_noop;
+ x86_init.mpparse.get_smp_config = hv_snp_get_smp_config;
+
+ /*
+ * Hyper-V SEV-SNP enlightened guest doesn't support ioapic
+ * and legacy APIC page read/write.
+ */
+ disable_ioapic_support();
+
+ /* Get processor and mem info. */
+ processor_count = *(u32 *)__va(EN_SEV_SNP_PROCESSOR_INFO_ADDR);
+ entry = (struct memory_map_entry *)__va(EN_SEV_SNP_MEM_INFO_ADDR);
+
+ /*
+ * There is no bootloader/EFI firmware in the SEV SNP guest.
+ * E820 table in the memory just describes memory for kernel,
+ * ACPI table, cmdline, boot params and ramdisk. The dynamic
+ * data(e.g, vcpu number and the rest memory layout) needs to
+ * be read from EN_SEV_SNP_PROCESSOR_INFO_ADDR.
+ */
+ for (; entry->numpages != 0; entry++) {
+ e820_entry = &e820_table->entries[
+ e820_table->nr_entries - 1];
+ e820_end = e820_entry->addr + e820_entry->size;
+ ram_end = (entry->starting_gpn +
+ entry->numpages) * PAGE_SIZE;
+
+ if (e820_end < entry->starting_gpn * PAGE_SIZE)
+ e820_end = entry->starting_gpn * PAGE_SIZE;
+
+ if (e820_end < ram_end) {
+ pr_info("Hyper-V: add e820 entry [mem %#018Lx-%#018Lx]\n", e820_end, ram_end - 1);
+ e820__range_add(e820_end, ram_end - e820_end,
+ E820_TYPE_RAM);
+ for (page = e820_end; page < ram_end; page += PAGE_SIZE)
+ pvalidate((unsigned long)__va(page), RMP_PG_SIZE_4K, true);
+ }
+ }
+}
+
void __init hv_vtom_init(void)
{
/*
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 5173c3524873..c8f33a7af90e 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -57,6 +57,21 @@ extern union hv_ghcb * __percpu *hv_ghcb_pg;
#define HV_AP_INIT_GPAT_DEFAULT 0x0007040600070406ULL
#define HV_AP_SEGMENT_LIMIT 0xffffffff

+/*
+ * Hyper-V puts processor and memory layout info
+ * to this address in SEV-SNP enlightened guest.
+ */
+#define EN_SEV_SNP_PROCESSOR_INFO_ADDR 0x802000
+#define EN_SEV_SNP_MEM_INFO_ADDR 0x802018
+
+struct memory_map_entry {
+ u64 starting_gpn;
+ u64 numpages;
+ u16 type;
+ u16 flags;
+ u32 reserved;
+};
+
int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages);
int hv_call_add_logical_proc(int node, u32 lp_index, u32 acpi_id);
int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags);
@@ -242,6 +257,7 @@ bool hv_ghcb_negotiate_protocol(void);
void __noreturn hv_ghcb_terminate(unsigned int set, unsigned int reason);
void hv_vtom_init(void);
int hv_snp_boot_ap(int cpu, unsigned long start_ip);
+void hv_sev_init_mem_and_cpu(void);
#else
static inline void hv_ghcb_msr_write(u64 msr, u64 value) {}
static inline void hv_ghcb_msr_read(u64 msr, u64 *value) {}
@@ -249,6 +265,7 @@ static inline bool hv_ghcb_negotiate_protocol(void) { return false; }
static inline void hv_ghcb_terminate(unsigned int set, unsigned int reason) {}
static inline void hv_vtom_init(void) {}
static int hv_snp_boot_ap(int cpu, unsigned long start_ip) {}
+static inline void hv_sev_init_mem_and_cpu(void) {}
#endif

extern bool hv_isolation_type_snp(void);
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index 29e836b950e1..ba9a3a65f664 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -539,6 +539,9 @@ static void __init ms_hyperv_init_platform(void)
if (!(ms_hyperv.features & HV_ACCESS_TSC_INVARIANT))
mark_tsc_unstable("running on Hyper-V");

+ if (hv_isolation_type_en_snp())
+ hv_sev_init_mem_and_cpu();
+
hardlockup_detector_disable();
}

--
2.25.1


2023-08-04 16:36:27

by Tianyu Lan

[permalink] [raw]
Subject: [PATCH V4 2/9] x86/hyperv: Set Virtual Trust Level in VMBus init message

From: Tianyu Lan <[email protected]>

SEV-SNP guests on Hyper-V can run at multiple Virtual Trust
Levels (VTL). During boot, get the VTL at which we're running
using the GET_VP_REGISTERs hypercall, and save the value
for future use. Then during VMBus initialization, set the VTL
with the saved value as required in the VMBus init message.

Reviewed-by: Michael Kelley <[email protected]>
Signed-off-by: Tianyu Lan <[email protected]>
---
* Change since v2:
Update the change log.
---
arch/x86/hyperv/hv_init.c | 36 ++++++++++++++++++++++++++++++
arch/x86/include/asm/hyperv-tlfs.h | 7 ++++++
drivers/hv/connection.c | 1 +
include/asm-generic/mshyperv.h | 1 +
include/linux/hyperv.h | 4 ++--
5 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index 6c04b52f139b..1ba367a9686e 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -378,6 +378,40 @@ static void __init hv_get_partition_id(void)
local_irq_restore(flags);
}

+static u8 __init get_vtl(void)
+{
+ u64 control = HV_HYPERCALL_REP_COMP_1 | HVCALL_GET_VP_REGISTERS;
+ struct hv_get_vp_registers_input *input;
+ struct hv_get_vp_registers_output *output;
+ u64 vtl = 0;
+ u64 ret;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ input = *this_cpu_ptr(hyperv_pcpu_input_arg);
+ output = (struct hv_get_vp_registers_output *)input;
+ if (!input) {
+ local_irq_restore(flags);
+ goto done;
+ }
+
+ memset(input, 0, struct_size(input, element, 1));
+ input->header.partitionid = HV_PARTITION_ID_SELF;
+ input->header.vpindex = HV_VP_INDEX_SELF;
+ input->header.inputvtl = 0;
+ input->element[0].name0 = HV_X64_REGISTER_VSM_VP_STATUS;
+
+ ret = hv_do_hypercall(control, input, output);
+ if (hv_result_success(ret))
+ vtl = output->as64.low & HV_X64_VTL_MASK;
+ else
+ pr_err("Hyper-V: failed to get VTL! %lld", ret);
+ local_irq_restore(flags);
+
+done:
+ return vtl;
+}
+
/*
* This function is to be invoked early in the boot sequence after the
* hypervisor has been detected.
@@ -506,6 +540,8 @@ void __init hyperv_init(void)
/* Query the VMs extended capability once, so that it can be cached. */
hv_query_ext_cap(0);

+ /* Find the VTL */
+ ms_hyperv.vtl = get_vtl();
return;

clean_guest_os_id:
diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h
index cea95dcd27c2..4bf0b315b0ce 100644
--- a/arch/x86/include/asm/hyperv-tlfs.h
+++ b/arch/x86/include/asm/hyperv-tlfs.h
@@ -301,6 +301,13 @@ enum hv_isolation_type {
#define HV_X64_MSR_TIME_REF_COUNT HV_REGISTER_TIME_REF_COUNT
#define HV_X64_MSR_REFERENCE_TSC HV_REGISTER_REFERENCE_TSC

+/*
+ * Registers are only accessible via HVCALL_GET_VP_REGISTERS hvcall and
+ * there is not associated MSR address.
+ */
+#define HV_X64_REGISTER_VSM_VP_STATUS 0x000D0003
+#define HV_X64_VTL_MASK GENMASK(3, 0)
+
/* Hyper-V memory host visibility */
enum hv_mem_host_visibility {
VMBUS_PAGE_NOT_VISIBLE = 0,
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
index 5978e9dbc286..02b54f85dc60 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -98,6 +98,7 @@ int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, u32 version)
*/
if (version >= VERSION_WIN10_V5) {
msg->msg_sint = VMBUS_MESSAGE_SINT;
+ msg->msg_vtl = ms_hyperv.vtl;
vmbus_connection.msg_conn_id = VMBUS_MESSAGE_CONNECTION_ID_4;
} else {
msg->interrupt_page = virt_to_phys(vmbus_connection.int_page);
diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
index 6b5c41f90398..f73a044ecaa7 100644
--- a/include/asm-generic/mshyperv.h
+++ b/include/asm-generic/mshyperv.h
@@ -54,6 +54,7 @@ struct ms_hyperv_info {
};
};
u64 shared_gpa_boundary;
+ u8 vtl;
};
extern struct ms_hyperv_info ms_hyperv;
extern bool hv_nested;
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index bfbc37ce223b..1f2bfec4abde 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -665,8 +665,8 @@ struct vmbus_channel_initiate_contact {
u64 interrupt_page;
struct {
u8 msg_sint;
- u8 padding1[3];
- u32 padding2;
+ u8 msg_vtl;
+ u8 reserved[6];
};
};
u64 monitor_page1;
--
2.25.1


2023-08-04 16:43:48

by Tianyu Lan

[permalink] [raw]
Subject: [PATCH V4 5/9] x86/hyperv: Use vmmcall to implement Hyper-V hypercall in sev-snp enlightened guest

From: Tianyu Lan <[email protected]>

In sev-snp enlightened guest, Hyper-V hypercall needs
to use vmmcall to trigger vmexit and notify hypervisor
to handle hypercall request.

Signed-off-by: Tianyu Lan <[email protected]>
---
arch/x86/include/asm/mshyperv.h | 27 ++++++++++++++-------------
1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 2fa38e9f6207..025eda129d99 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -64,12 +64,12 @@ static inline u64 hv_do_hypercall(u64 control, void *input, void *output)
if (!hv_hypercall_pg)
return U64_MAX;

- __asm__ __volatile__("mov %4, %%r8\n"
- CALL_NOSPEC
+ __asm__ __volatile__("mov %[output], %%r8\n"
+ ALTERNATIVE("vmmcall", CALL_NOSPEC, X86_FEATURE_SEV_ES)
: "=a" (hv_status), ASM_CALL_CONSTRAINT,
- "+c" (control), "+d" (input_address)
- : "r" (output_address),
- THUNK_TARGET(hv_hypercall_pg)
+ "+c" (control), "+d" (input_address)
+ : [output] "r" (output_address),
+ THUNK_TARGET(hv_hypercall_pg)
: "cc", "memory", "r8", "r9", "r10", "r11");
#else
u32 input_address_hi = upper_32_bits(input_address);
@@ -105,7 +105,8 @@ static inline u64 _hv_do_fast_hypercall8(u64 control, u64 input1)

#ifdef CONFIG_X86_64
{
- __asm__ __volatile__(CALL_NOSPEC
+ __asm__ __volatile__("mov %[thunk_target], %%r8\n"
+ ALTERNATIVE("vmmcall", CALL_NOSPEC, X86_FEATURE_SEV_ES)
: "=a" (hv_status), ASM_CALL_CONSTRAINT,
"+c" (control), "+d" (input1)
: THUNK_TARGET(hv_hypercall_pg)
@@ -150,13 +151,13 @@ static inline u64 _hv_do_fast_hypercall16(u64 control, u64 input1, u64 input2)

#ifdef CONFIG_X86_64
{
- __asm__ __volatile__("mov %4, %%r8\n"
- CALL_NOSPEC
- : "=a" (hv_status), ASM_CALL_CONSTRAINT,
- "+c" (control), "+d" (input1)
- : "r" (input2),
- THUNK_TARGET(hv_hypercall_pg)
- : "cc", "r8", "r9", "r10", "r11");
+ __asm__ __volatile__("mov %[output], %%r8\n"
+ ALTERNATIVE("vmmcall", CALL_NOSPEC, X86_FEATURE_SEV_ES)
+ : "=a" (hv_status), ASM_CALL_CONSTRAINT,
+ "+c" (control), "+d" (input1)
+ : [output] "r" (input2),
+ THUNK_TARGET(hv_hypercall_pg)
+ : "cc", "r8", "r9", "r10", "r11");
}
#else
{
--
2.25.1


2023-08-05 00:23:25

by Wei Liu

[permalink] [raw]
Subject: Re: [PATCH V4 0/9] x86/hyperv: Add AMD sev-snp enlightened guest support on hyperv

On Fri, Aug 04, 2023 at 11:22:44AM -0400, Tianyu Lan wrote:
> From: Tianyu Lan <[email protected]>
[...]
> Tianyu Lan (9):
> x86/hyperv: Add sev-snp enlightened guest static key
> x86/hyperv: Set Virtual Trust Level in VMBus init message
> x86/hyperv: Mark Hyper-V vp assist page unencrypted in SEV-SNP
> enlightened guest
> drivers: hv: Mark percpu hvcall input arg page unencrypted in SEV-SNP
> enlightened guest
> x86/hyperv: Use vmmcall to implement Hyper-V hypercall in sev-snp
> enlightened guest
> clocksource: hyper-v: Mark hyperv tsc page unencrypted in sev-snp
> enlightened guest
> x86/hyperv: Add smp support for SEV-SNP guest
> x86/hyperv: Add hyperv-specific handling for VMMCALL under SEV-ES

I applied all but the last patch to hyperv-next. Thanks.

> x86/hyperv: Initialize cpu and memory for SEV-SNP enlightened guest


2023-08-06 00:52:31

by Dexuan Cui

[permalink] [raw]
Subject: RE: [PATCH V4 0/9] x86/hyperv: Add AMD sev-snp enlightened guest support on hyperv

> From: Wei Liu <[email protected]>
> Sent: Friday, August 4, 2023 4:35 PM
> To: Tianyu Lan <[email protected]>
> [...]
> On Fri, Aug 04, 2023 at 11:22:44AM -0400, Tianyu Lan wrote:
> > From: Tianyu Lan <[email protected]>
> [...]
> > Tianyu Lan (9):
[...]
> > x86/hyperv: Use vmmcall to implement Hyper-V hypercall in sev-snp ...

Unluckily this commit causes a crash on Intel CPUs (see the below call-trace).

I made a fix here:
https://github.com/dcui/linux/commit/c4db45f6256248435b2a303b264ecbb41320c41d
I guess Wei can squash the fix into Tianyu's commit in the hyperv-next branch?

[ 0.861465] invalid opcode: 0000 [#1] PREEMPT SMP
[ 0.865489] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 6.5.0-rc4-decui-hcl+ #1
[ 0.869194] Hardware name: Microsoft Corporation Virtual Machine/Virtual Machine, BIOS Hyper-V UEFI Release v4.1 04/20/2023
[ 0.875049] RIP: 0010:hv_query_ext_cap+0x7a/0x130
[ 0.879626] Code: 83 72 57 48 c7 c6 00 00 00 80 48 2b 35 0f f2 9d 00 48 01 f0 48 8b 35 5d 3e 3d 01 48 85 f6 74 2a b9 01 80 00 00 31 d2 49 89 c0 <0f> 01 d9 c6 05 d4 f2 20 02 01 66 85 c0 74 aa 48 89 c6 48 c7 c7 20
[ 0.897457] RSP: 0000:ffffffff82803e50 EFLAGS: 00010246
[ 0.900194] RAX: 00000000074f72e0 RBX: 0000000000000000 RCX: 0000000000008001
[ 0.903955] RDX: 0000000000000000 RSI: ffffc90000017000 RDI: 0000000000000000
[ 0.908445] RBP: ffffffff82803e60 R08: 00000000074f72e0 R09: 0000000000000001
[ 0.916354] R10: 0720072007200720 R11: 0720072007200720 R12: 0000000000000000
[ 0.924285] R13: 0000000000000000 R14: 0000000000000000 R15: ffffffff8280edb8
[ 0.929481] FS: 0000000000000000(0000) GS:ffff8880f6800000(0000) knlGS:0000000000000000
[ 0.933589] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 0.936526] CR2: ffff888507fff000 CR3: 0000000006036001 CR4: 00000000000200f0
[ 0.942279] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 0.950573] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[ 0.958417] Call Trace:
[ 0.959827] <TASK>
[ 0.961044] ? show_regs+0x64/0x70
[ 0.962872] ? __die_body+0x20/0x70
[ 0.964741] ? die+0x3e/0x60
[ 0.966273] ? do_trap+0xd7/0x100
[ 0.967922] ? do_error_trap+0x71/0x90
[ 0.970027] ? hv_query_ext_cap+0x7a/0x130
[ 0.974573] ? exc_invalid_op+0x53/0x70
[ 0.978961] ? hv_query_ext_cap+0x7a/0x130
[ 0.983977] ? asm_exc_invalid_op+0x1b/0x20
[ 0.988932] ? hv_query_ext_cap+0x7a/0x130
[ 0.991413] hyperv_init+0x2fe/0x5f0
[ 0.993373] apic_intr_mode_init+0x3e/0x100
[ 0.995655] x86_late_time_init+0x1b/0x30
[ 0.997832] start_kernel+0x617/0xa70
[ 0.999546] x86_64_start_reservations+0x18/0x30
[ 1.003761] x86_64_start_kernel+0xc0/0x110
[ 1.008815] secondary_startup_64_no_verify+0x17e/0x18b
[ Ubuntu
[ *Advanced options for Ubuntu
[ 1.021465] ---[ end trace 0000000000000000 ]---
[ 1.024093] RIP: 0010:hv_query_ext_cap+0x7a/0x130
[ 1.026769] Code: 83 72 57 48 c7 c6 00 00 00 80 48 2b 35 0f f2 9d 00 48 01 f0 48 8b 35 5d 3e 3d 01 48 85 f6 74 2a b9 01 80 00 00 31 d2 49 89 c0 <0f> 01 d9 c6 05 d4 f2 20 02 01 66 85 c0 74 aa 48 89 c6 48 c7 c7 20
[ 1.042358] RSP: 0000:ffffffff82803e50 EFLAGS: 00010246
[ 1.049317] RAX: 00000000074f72e0 RBX: 0000000000000000 RCX: 0000000000008001
[ 1.054740] RDX: 0000000000000000 RSI: ffffc90000017000 RDI: 0000000000000000
[ 1.059058] RBP: ffffffff82803e60 R08: 00000000074f72e0 R09: 0000000000000001
[ 1.062406] R10: 0720072007200720 R11: 0720072007200720 R12: 0000000000000000
[ 1.070915] R13: 0000000000000000 R14: 0000000000000000 R15: ffffffff8280edb8
[ 1.080300] FS: 0000000000000000(0000) GS:ffff8880f6800000(0000) knlGS:0000000000000000
[ 1.086956] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 1.090242] CR2: ffff888507fff000 CR3: 0000000006036001 CR4: 00000000000200f0
[ 1.093949] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 1.101352] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400


2023-08-06 03:23:03

by Dexuan Cui

[permalink] [raw]
Subject: RE: [PATCH V4 0/9] x86/hyperv: Add AMD sev-snp enlightened guest support on hyperv

> From: Dexuan Cui
> Sent: Saturday, August 5, 2023 4:37 PM
> [...]
> > From: Wei Liu <[email protected]>
> > Sent: Friday, August 4, 2023 4:35 PM
> > To: Tianyu Lan <[email protected]>
> > [...]
> > On Fri, Aug 04, 2023 at 11:22:44AM -0400, Tianyu Lan wrote:
> > > From: Tianyu Lan <[email protected]>
> > [...]
> > > Tianyu Lan (9):
> [...]
> > > x86/hyperv: Use vmmcall to implement Hyper-V hypercall in sev-snp ...
>
> Unluckily this commit causes a crash on Intel CPUs (see the below call-trace).
>
> I made a fix here:
> https://github.com/dcui/linux/commit/c4db45f6256248435b2a303b264ecbb
> 41320c41d
> I guess Wei can squash the fix into Tianyu's commit in the hyperv-next
> branch?

I also made a patch to fix the ARM64 build:
https://github.com/dcui/linux/commit/a559709c612de2a212e288ef1a8b0abfabb168e5

2023-08-07 05:21:49

by Wei Liu

[permalink] [raw]
Subject: Re: [PATCH V4 0/9] x86/hyperv: Add AMD sev-snp enlightened guest support on hyperv

On Fri, Aug 04, 2023 at 11:34:36PM +0000, Wei Liu wrote:
> On Fri, Aug 04, 2023 at 11:22:44AM -0400, Tianyu Lan wrote:
> > From: Tianyu Lan <[email protected]>
> [...]
> > Tianyu Lan (9):
> > x86/hyperv: Add sev-snp enlightened guest static key
> > x86/hyperv: Set Virtual Trust Level in VMBus init message
> > x86/hyperv: Mark Hyper-V vp assist page unencrypted in SEV-SNP
> > enlightened guest
> > drivers: hv: Mark percpu hvcall input arg page unencrypted in SEV-SNP
> > enlightened guest
> > x86/hyperv: Use vmmcall to implement Hyper-V hypercall in sev-snp
> > enlightened guest
> > clocksource: hyper-v: Mark hyperv tsc page unencrypted in sev-snp
> > enlightened guest
> > x86/hyperv: Add smp support for SEV-SNP guest
> > x86/hyperv: Add hyperv-specific handling for VMMCALL under SEV-ES
>
> I applied all but the last patch to hyperv-next. Thanks.

This is causing build issues in linux-next. I've reverted this series
from hyperv-next.

>
> > x86/hyperv: Initialize cpu and memory for SEV-SNP enlightened guest
>