X86/Hyper-V: Add flush HvFlushGuestPhysicalAddressSpace hypercall support
Hyper-V supports a pv hypercall HvFlushGuestPhysicalAddressSpace to flush nested VM address space mapping in l1 hypervisor and it's to reduce overhead of flushing ept tlb among vcpus. This patch is to implement it. Signed-off-by: Lan Tianyu <Tianyu.Lan@microsoft.com> Acked-by: K. Y. Srinivasan <kys@microsoft.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
3553ae5690
commit
eb914cfe72
@ -1,2 +1,2 @@
|
|||||||
obj-y := hv_init.o mmu.o
|
obj-y := hv_init.o mmu.o nested.o
|
||||||
obj-$(CONFIG_X86_64) += hv_apic.o
|
obj-$(CONFIG_X86_64) += hv_apic.o
|
||||||
|
53
arch/x86/hyperv/nested.c
Normal file
53
arch/x86/hyperv/nested.c
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hyper-V nested virtualization code.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018, Microsoft, Inc.
|
||||||
|
*
|
||||||
|
* Author : Lan Tianyu <Tianyu.Lan@microsoft.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <asm/hyperv-tlfs.h>
|
||||||
|
#include <asm/mshyperv.h>
|
||||||
|
#include <asm/tlbflush.h>
|
||||||
|
|
||||||
|
int hyperv_flush_guest_mapping(u64 as)
|
||||||
|
{
|
||||||
|
struct hv_guest_mapping_flush **flush_pcpu;
|
||||||
|
struct hv_guest_mapping_flush *flush;
|
||||||
|
u64 status;
|
||||||
|
unsigned long flags;
|
||||||
|
int ret = -ENOTSUPP;
|
||||||
|
|
||||||
|
if (!hv_hypercall_pg)
|
||||||
|
goto fault;
|
||||||
|
|
||||||
|
local_irq_save(flags);
|
||||||
|
|
||||||
|
flush_pcpu = (struct hv_guest_mapping_flush **)
|
||||||
|
this_cpu_ptr(hyperv_pcpu_input_arg);
|
||||||
|
|
||||||
|
flush = *flush_pcpu;
|
||||||
|
|
||||||
|
if (unlikely(!flush)) {
|
||||||
|
local_irq_restore(flags);
|
||||||
|
goto fault;
|
||||||
|
}
|
||||||
|
|
||||||
|
flush->address_space = as;
|
||||||
|
flush->flags = 0;
|
||||||
|
|
||||||
|
status = hv_do_hypercall(HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE,
|
||||||
|
flush, NULL);
|
||||||
|
local_irq_restore(flags);
|
||||||
|
|
||||||
|
if (!(status & HV_HYPERCALL_RESULT_MASK))
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
fault:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(hyperv_flush_guest_mapping);
|
@ -309,6 +309,7 @@ struct ms_hyperv_tsc_page {
|
|||||||
#define HV_X64_MSR_REENLIGHTENMENT_CONTROL 0x40000106
|
#define HV_X64_MSR_REENLIGHTENMENT_CONTROL 0x40000106
|
||||||
|
|
||||||
/* Nested features (CPUID 0x4000000A) EAX */
|
/* Nested features (CPUID 0x4000000A) EAX */
|
||||||
|
#define HV_X64_NESTED_GUEST_MAPPING_FLUSH BIT(18)
|
||||||
#define HV_X64_NESTED_MSR_BITMAP BIT(19)
|
#define HV_X64_NESTED_MSR_BITMAP BIT(19)
|
||||||
|
|
||||||
struct hv_reenlightenment_control {
|
struct hv_reenlightenment_control {
|
||||||
@ -350,6 +351,7 @@ struct hv_tsc_emulation_status {
|
|||||||
#define HVCALL_SEND_IPI_EX 0x0015
|
#define HVCALL_SEND_IPI_EX 0x0015
|
||||||
#define HVCALL_POST_MESSAGE 0x005c
|
#define HVCALL_POST_MESSAGE 0x005c
|
||||||
#define HVCALL_SIGNAL_EVENT 0x005d
|
#define HVCALL_SIGNAL_EVENT 0x005d
|
||||||
|
#define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af
|
||||||
|
|
||||||
#define HV_X64_MSR_VP_ASSIST_PAGE_ENABLE 0x00000001
|
#define HV_X64_MSR_VP_ASSIST_PAGE_ENABLE 0x00000001
|
||||||
#define HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT 12
|
#define HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT 12
|
||||||
@ -741,6 +743,12 @@ struct ipi_arg_ex {
|
|||||||
struct hv_vpset vp_set;
|
struct hv_vpset vp_set;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* HvFlushGuestPhysicalAddressSpace hypercalls */
|
||||||
|
struct hv_guest_mapping_flush {
|
||||||
|
u64 address_space;
|
||||||
|
u64 flags;
|
||||||
|
};
|
||||||
|
|
||||||
/* HvFlushVirtualAddressSpace, HvFlushVirtualAddressList hypercalls */
|
/* HvFlushVirtualAddressSpace, HvFlushVirtualAddressList hypercalls */
|
||||||
struct hv_tlb_flush {
|
struct hv_tlb_flush {
|
||||||
u64 address_space;
|
u64 address_space;
|
||||||
|
@ -305,6 +305,7 @@ void hyperv_reenlightenment_intr(struct pt_regs *regs);
|
|||||||
void set_hv_tscchange_cb(void (*cb)(void));
|
void set_hv_tscchange_cb(void (*cb)(void));
|
||||||
void clear_hv_tscchange_cb(void);
|
void clear_hv_tscchange_cb(void);
|
||||||
void hyperv_stop_tsc_emulation(void);
|
void hyperv_stop_tsc_emulation(void);
|
||||||
|
int hyperv_flush_guest_mapping(u64 as);
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
void hv_apic_init(void);
|
void hv_apic_init(void);
|
||||||
@ -324,6 +325,7 @@ static inline struct hv_vp_assist_page *hv_get_vp_assist_page(unsigned int cpu)
|
|||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
static inline int hyperv_flush_guest_mapping(u64 as) { return -1; }
|
||||||
#endif /* CONFIG_HYPERV */
|
#endif /* CONFIG_HYPERV */
|
||||||
|
|
||||||
#ifdef CONFIG_HYPERV_TSCPAGE
|
#ifdef CONFIG_HYPERV_TSCPAGE
|
||||||
|
Loading…
Reference in New Issue
Block a user