mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge branch 'next' of https://github.com/kvm-x86/linux.git
This commit is contained in:
@@ -639,27 +639,24 @@ static void kvmppc_set_pvr_pr(struct kvm_vcpu *vcpu, u32 pvr)
|
||||
*/
|
||||
static void kvmppc_patch_dcbz(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte)
|
||||
{
|
||||
struct kvm_host_map map;
|
||||
u64 hpage_offset;
|
||||
u32 *page;
|
||||
int i, r;
|
||||
int i;
|
||||
|
||||
r = kvm_vcpu_map(vcpu, pte->raddr >> PAGE_SHIFT, &map);
|
||||
if (r)
|
||||
CLASS(kvm_vcpu_map_local, m)(vcpu, pte->raddr >> PAGE_SHIFT);
|
||||
if (m.ret)
|
||||
return;
|
||||
|
||||
hpage_offset = pte->raddr & ~PAGE_MASK;
|
||||
hpage_offset &= ~0xFFFULL;
|
||||
hpage_offset /= 4;
|
||||
|
||||
page = map.hva;
|
||||
page = m.map.hva;
|
||||
|
||||
/* patch dcbz into reserved instruction, so we trap */
|
||||
for (i=hpage_offset; i < hpage_offset + (HW_PAGE_SIZE / 4); i++)
|
||||
if ((be32_to_cpu(page[i]) & 0xff0007ff) == INS_DCBZ)
|
||||
page[i] &= cpu_to_be32(0xfffffff7);
|
||||
|
||||
kvm_vcpu_unmap(vcpu, &map);
|
||||
}
|
||||
|
||||
static bool kvmppc_visible_gpa(struct kvm_vcpu *vcpu, gpa_t gpa)
|
||||
|
||||
@@ -136,8 +136,12 @@
|
||||
#define X86_FEATURE_HYPERVISOR ( 4*32+31) /* "hypervisor" Running on a hypervisor */
|
||||
|
||||
/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
|
||||
#define X86_FEATURE_SM2 ( 5*32+ 0) /* "sm2" SM2 algorithm */
|
||||
#define X86_FEATURE_SM2_EN ( 5*32+ 1) /* "sm2_en" SM2 enabled */
|
||||
#define X86_FEATURE_XSTORE ( 5*32+ 2) /* "rng" RNG present (xstore) */
|
||||
#define X86_FEATURE_XSTORE_EN ( 5*32+ 3) /* "rng_en" RNG enabled */
|
||||
#define X86_FEATURE_CCS ( 5*32+ 4) /* "ccs" SM3 + SM4 instructions */
|
||||
#define X86_FEATURE_CCS_EN ( 5*32+ 5) /* "ccs_en" CCS enabled */
|
||||
#define X86_FEATURE_XCRYPT ( 5*32+ 6) /* "ace" on-CPU crypto (xcrypt) */
|
||||
#define X86_FEATURE_XCRYPT_EN ( 5*32+ 7) /* "ace_en" on-CPU crypto enabled */
|
||||
#define X86_FEATURE_ACE2 ( 5*32+ 8) /* "ace2" Advanced Cryptography Engine v2 */
|
||||
@@ -146,6 +150,12 @@
|
||||
#define X86_FEATURE_PHE_EN ( 5*32+11) /* "phe_en" PHE enabled */
|
||||
#define X86_FEATURE_PMM ( 5*32+12) /* "pmm" PadLock Montgomery Multiplier */
|
||||
#define X86_FEATURE_PMM_EN ( 5*32+13) /* "pmm_en" PMM enabled */
|
||||
#define X86_FEATURE_RNG2 ( 5*32+22) /* "rng2" RNG v2 */
|
||||
#define X86_FEATURE_RNG2_EN ( 5*32+23) /* "rng2_en" RNG2 enabled */
|
||||
#define X86_FEATURE_PHE2 ( 5*32+25) /* "phe2" PadLock Hash Engine v2 */
|
||||
#define X86_FEATURE_PHE2_EN ( 5*32+26) /* "phe2_en" PHE2 enabled */
|
||||
#define X86_FEATURE_RSA ( 5*32+27) /* "rsa" Big-number arithmetic */
|
||||
#define X86_FEATURE_RSA_EN ( 5*32+28) /* "rsa_en" RSA enabled */
|
||||
|
||||
/* More extended AMD flags: CPUID level 0x80000001, ECX, word 6 */
|
||||
#define X86_FEATURE_LAHF_LM ( 6*32+ 0) /* "lahf_lm" LAHF/SAHF in long mode */
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#if !defined(KVM_X86_NESTED_OP) || \
|
||||
!defined(KVM_X86_NESTED_OP_OPTIONAL) || \
|
||||
!defined(KVM_X86_NESTED_OP_OPTIONAL_RET0)
|
||||
#error Missing one or more KVM_X86_NESTED_OP #defines
|
||||
#else
|
||||
/*
|
||||
* KVM_X86_NESTED_OP() and KVM_X86_NESTED_OP_OPTIONAL() are used to help
|
||||
* generate both DECLARE/DEFINE_STATIC_CALL() invocations and
|
||||
* "static_call_update()" calls.
|
||||
*
|
||||
* KVM_X86_NESTED_OP_OPTIONAL() can be used for those functions that can have
|
||||
* a NULL definition. KVM_X86_NESTED_OP_OPTIONAL_RET0() can be used likewise
|
||||
* to make a definition optional, but in this case the default will
|
||||
* be __static_call_return0.
|
||||
*/
|
||||
KVM_X86_NESTED_OP(leave_nested)
|
||||
KVM_X86_NESTED_OP(is_exception_vmexit)
|
||||
KVM_X86_NESTED_OP(check_events)
|
||||
KVM_X86_NESTED_OP_OPTIONAL_RET0(has_events)
|
||||
KVM_X86_NESTED_OP(triple_fault)
|
||||
KVM_X86_NESTED_OP(get_state)
|
||||
KVM_X86_NESTED_OP(set_state)
|
||||
KVM_X86_NESTED_OP(get_nested_state_pages)
|
||||
KVM_X86_NESTED_OP_OPTIONAL_RET0(write_log_dirty)
|
||||
KVM_X86_NESTED_OP(translate_nested_gpa)
|
||||
#ifdef CONFIG_KVM_HYPERV
|
||||
KVM_X86_NESTED_OP_OPTIONAL(enable_evmcs)
|
||||
KVM_X86_NESTED_OP_OPTIONAL_RET0(get_evmcs_version)
|
||||
KVM_X86_NESTED_OP(hv_inject_synthetic_vmexit_post_tlb_flush)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#undef KVM_X86_NESTED_OP
|
||||
#undef KVM_X86_NESTED_OP_OPTIONAL
|
||||
#undef KVM_X86_NESTED_OP_OPTIONAL_RET0
|
||||
@@ -110,7 +110,7 @@ KVM_X86_OP(handle_exit_irqoff)
|
||||
KVM_X86_OP_OPTIONAL(update_cpu_dirty_logging)
|
||||
KVM_X86_OP_OPTIONAL(vcpu_blocking)
|
||||
KVM_X86_OP_OPTIONAL(vcpu_unblocking)
|
||||
KVM_X86_OP_OPTIONAL(pi_update_irte)
|
||||
KVM_X86_OP(pi_update_irte)
|
||||
KVM_X86_OP_OPTIONAL(pi_start_bypass)
|
||||
KVM_X86_OP_OPTIONAL(apicv_pre_state_restore)
|
||||
KVM_X86_OP_OPTIONAL(apicv_post_state_restore)
|
||||
@@ -134,6 +134,7 @@ KVM_X86_OP_OPTIONAL(mem_enc_unregister_region)
|
||||
KVM_X86_OP_OPTIONAL(vm_copy_enc_context_from)
|
||||
KVM_X86_OP_OPTIONAL(vm_move_enc_context_from)
|
||||
KVM_X86_OP_OPTIONAL(guest_memory_reclaimed)
|
||||
KVM_X86_OP_OPTIONAL(reload_vmsa)
|
||||
KVM_X86_OP(get_feature_msr)
|
||||
KVM_X86_OP(check_emulate_instruction)
|
||||
KVM_X86_OP(apic_init_signal_blocked)
|
||||
@@ -145,9 +146,16 @@ KVM_X86_OP(vcpu_deliver_sipi_vector)
|
||||
KVM_X86_OP_OPTIONAL_RET0(vcpu_get_apicv_inhibit_reasons);
|
||||
KVM_X86_OP_OPTIONAL(get_untagged_addr)
|
||||
KVM_X86_OP_OPTIONAL(alloc_apic_backing_page)
|
||||
KVM_X86_OP_OPTIONAL_RET0(gmem_prepare)
|
||||
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_CONVERT
|
||||
KVM_X86_OP_OPTIONAL_RET0(gmem_make_private)
|
||||
#endif
|
||||
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM
|
||||
KVM_X86_OP_OPTIONAL(gmem_make_shared)
|
||||
#endif
|
||||
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
|
||||
KVM_X86_OP_OPTIONAL(gmem_invalidate_range)
|
||||
#endif
|
||||
KVM_X86_OP_OPTIONAL_RET0(gmem_max_mapping_level)
|
||||
KVM_X86_OP_OPTIONAL(gmem_invalidate)
|
||||
#endif
|
||||
|
||||
#undef KVM_X86_OP
|
||||
|
||||
+31
-192
@@ -122,27 +122,11 @@
|
||||
KVM_ARCH_REQ_FLAGS(31, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
|
||||
#define KVM_REQ_HV_TLB_FLUSH \
|
||||
KVM_ARCH_REQ_FLAGS(32, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
|
||||
#define KVM_REQ_VMSA_PAGE_RELOAD \
|
||||
KVM_ARCH_REQ_FLAGS(33, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
|
||||
#define KVM_REQ_UPDATE_PROTECTED_GUEST_STATE \
|
||||
KVM_ARCH_REQ_FLAGS(34, KVM_REQUEST_WAIT)
|
||||
|
||||
#define CR0_RESERVED_BITS \
|
||||
(~(unsigned long)(X86_CR0_PE | X86_CR0_MP | X86_CR0_EM | X86_CR0_TS \
|
||||
| X86_CR0_ET | X86_CR0_NE | X86_CR0_WP | X86_CR0_AM \
|
||||
| X86_CR0_NW | X86_CR0_CD | X86_CR0_PG))
|
||||
|
||||
#define CR4_RESERVED_BITS \
|
||||
(~(unsigned long)(X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD | X86_CR4_DE\
|
||||
| X86_CR4_PSE | X86_CR4_PAE | X86_CR4_MCE \
|
||||
| X86_CR4_PGE | X86_CR4_PCE | X86_CR4_OSFXSR | X86_CR4_PCIDE \
|
||||
| X86_CR4_OSXSAVE | X86_CR4_SMEP | X86_CR4_FSGSBASE \
|
||||
| X86_CR4_OSXMMEXCPT | X86_CR4_LA57 | X86_CR4_VMXE \
|
||||
| X86_CR4_SMAP | X86_CR4_PKE | X86_CR4_UMIP \
|
||||
| X86_CR4_LAM_SUP | X86_CR4_CET))
|
||||
|
||||
#define CR8_RESERVED_BITS (~(unsigned long)X86_CR8_TPR)
|
||||
|
||||
|
||||
|
||||
#define INVALID_PAGE (~(hpa_t)0)
|
||||
#define VALID_PAGE(x) ((x) != INVALID_PAGE)
|
||||
|
||||
@@ -230,37 +214,6 @@ enum x86_intercept_stage;
|
||||
|
||||
#define KVM_NR_DB_REGS 4
|
||||
|
||||
#define DR6_BUS_LOCK (1 << 11)
|
||||
#define DR6_BD (1 << 13)
|
||||
#define DR6_BS (1 << 14)
|
||||
#define DR6_BT (1 << 15)
|
||||
#define DR6_RTM (1 << 16)
|
||||
/*
|
||||
* DR6_ACTIVE_LOW combines fixed-1 and active-low bits.
|
||||
* We can regard all the bits in DR6_FIXED_1 as active_low bits;
|
||||
* they will never be 0 for now, but when they are defined
|
||||
* in the future it will require no code change.
|
||||
*
|
||||
* DR6_ACTIVE_LOW is also used as the init/reset value for DR6.
|
||||
*/
|
||||
#define DR6_ACTIVE_LOW 0xffff0ff0
|
||||
#define DR6_VOLATILE 0x0001e80f
|
||||
#define DR6_FIXED_1 (DR6_ACTIVE_LOW & ~DR6_VOLATILE)
|
||||
|
||||
#define DR7_BP_EN_MASK 0x000000ff
|
||||
#define DR7_GE (1 << 9)
|
||||
#define DR7_GD (1 << 13)
|
||||
#define DR7_VOLATILE 0xffff2bff
|
||||
|
||||
#define KVM_GUESTDBG_VALID_MASK \
|
||||
(KVM_GUESTDBG_ENABLE | \
|
||||
KVM_GUESTDBG_SINGLESTEP | \
|
||||
KVM_GUESTDBG_USE_HW_BP | \
|
||||
KVM_GUESTDBG_USE_SW_BP | \
|
||||
KVM_GUESTDBG_INJECT_BP | \
|
||||
KVM_GUESTDBG_INJECT_DB | \
|
||||
KVM_GUESTDBG_BLOCKIRQ)
|
||||
|
||||
#define PFERR_PRESENT_MASK BIT(0)
|
||||
#define PFERR_WRITE_MASK BIT(1)
|
||||
#define PFERR_USER_MASK BIT(2)
|
||||
@@ -290,19 +243,11 @@ enum x86_intercept_stage;
|
||||
#define PFERR_PRIVATE_ACCESS BIT_ULL(49)
|
||||
#define PFERR_SYNTHETIC_MASK (PFERR_IMPLICIT_ACCESS | PFERR_PRIVATE_ACCESS)
|
||||
|
||||
/* apic attention bits */
|
||||
#define KVM_APIC_CHECK_VAPIC 0
|
||||
/*
|
||||
* The following bit is set with PV-EOI, unset on EOI.
|
||||
* We detect PV-EOI changes by guest by comparing
|
||||
* this bit with PV-EOI in guest memory.
|
||||
* See the implementation in apic_update_pv_eoi.
|
||||
*/
|
||||
#define KVM_APIC_PV_EOI_PENDING 1
|
||||
|
||||
struct kvm_kernel_irqfd;
|
||||
struct kvm_kernel_irq_routing_entry;
|
||||
|
||||
struct kvm_apic_map;
|
||||
|
||||
struct kvm_x86_msr_filter;
|
||||
struct kvm_x86_pmu_event_filter;
|
||||
|
||||
@@ -329,6 +274,8 @@ struct kvm_caps {
|
||||
u64 supported_xss;
|
||||
u64 supported_perf_cap;
|
||||
|
||||
u64 supported_efer_bits;
|
||||
|
||||
u64 supported_quirks;
|
||||
u64 inapplicable_quirks;
|
||||
};
|
||||
@@ -705,95 +652,6 @@ struct kvm_mtrr {
|
||||
u64 deftype;
|
||||
};
|
||||
|
||||
/* Hyper-V SynIC timer */
|
||||
struct kvm_vcpu_hv_stimer {
|
||||
struct hrtimer timer;
|
||||
int index;
|
||||
union hv_stimer_config config;
|
||||
u64 count;
|
||||
u64 exp_time;
|
||||
struct hv_message msg;
|
||||
bool msg_pending;
|
||||
};
|
||||
|
||||
/* Hyper-V synthetic interrupt controller (SynIC)*/
|
||||
struct kvm_vcpu_hv_synic {
|
||||
u64 version;
|
||||
u64 control;
|
||||
u64 msg_page;
|
||||
u64 evt_page;
|
||||
atomic64_t sint[HV_SYNIC_SINT_COUNT];
|
||||
atomic_t sint_to_gsi[HV_SYNIC_SINT_COUNT];
|
||||
DECLARE_BITMAP(auto_eoi_bitmap, 256);
|
||||
DECLARE_BITMAP(vec_bitmap, 256);
|
||||
bool active;
|
||||
bool dont_zero_synic_pages;
|
||||
};
|
||||
|
||||
/* The maximum number of entries on the TLB flush fifo. */
|
||||
#define KVM_HV_TLB_FLUSH_FIFO_SIZE (16)
|
||||
/*
|
||||
* Note: the following 'magic' entry is made up by KVM to avoid putting
|
||||
* anything besides GVA on the TLB flush fifo. It is theoretically possible
|
||||
* to observe a request to flush 4095 PFNs starting from 0xfffffffffffff000
|
||||
* which will look identical. KVM's action to 'flush everything' instead of
|
||||
* flushing these particular addresses is, however, fully legitimate as
|
||||
* flushing more than requested is always OK.
|
||||
*/
|
||||
#define KVM_HV_TLB_FLUSHALL_ENTRY ((u64)-1)
|
||||
|
||||
enum hv_tlb_flush_fifos {
|
||||
HV_L1_TLB_FLUSH_FIFO,
|
||||
HV_L2_TLB_FLUSH_FIFO,
|
||||
HV_NR_TLB_FLUSH_FIFOS,
|
||||
};
|
||||
|
||||
struct kvm_vcpu_hv_tlb_flush_fifo {
|
||||
spinlock_t write_lock;
|
||||
DECLARE_KFIFO(entries, u64, KVM_HV_TLB_FLUSH_FIFO_SIZE);
|
||||
};
|
||||
|
||||
/* Hyper-V per vcpu emulation context */
|
||||
struct kvm_vcpu_hv {
|
||||
struct kvm_vcpu *vcpu;
|
||||
u32 vp_index;
|
||||
u64 hv_vapic;
|
||||
s64 runtime_offset;
|
||||
struct kvm_vcpu_hv_synic synic;
|
||||
struct kvm_hyperv_exit exit;
|
||||
struct kvm_vcpu_hv_stimer stimer[HV_SYNIC_STIMER_COUNT];
|
||||
DECLARE_BITMAP(stimer_pending_bitmap, HV_SYNIC_STIMER_COUNT);
|
||||
bool enforce_cpuid;
|
||||
struct {
|
||||
u32 features_eax; /* HYPERV_CPUID_FEATURES.EAX */
|
||||
u32 features_ebx; /* HYPERV_CPUID_FEATURES.EBX */
|
||||
u32 features_edx; /* HYPERV_CPUID_FEATURES.EDX */
|
||||
u32 enlightenments_eax; /* HYPERV_CPUID_ENLIGHTMENT_INFO.EAX */
|
||||
u32 enlightenments_ebx; /* HYPERV_CPUID_ENLIGHTMENT_INFO.EBX */
|
||||
u32 syndbg_cap_eax; /* HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES.EAX */
|
||||
u32 nested_eax; /* HYPERV_CPUID_NESTED_FEATURES.EAX */
|
||||
u32 nested_ebx; /* HYPERV_CPUID_NESTED_FEATURES.EBX */
|
||||
} cpuid_cache;
|
||||
|
||||
struct kvm_vcpu_hv_tlb_flush_fifo tlb_flush_fifo[HV_NR_TLB_FLUSH_FIFOS];
|
||||
|
||||
/*
|
||||
* Preallocated buffers for handling hypercalls that pass sparse vCPU
|
||||
* sets (for high vCPU counts, they're too large to comfortably fit on
|
||||
* the stack).
|
||||
*/
|
||||
u64 sparse_banks[HV_MAX_SPARSE_VCPU_BANKS];
|
||||
DECLARE_BITMAP(vcpu_mask, KVM_MAX_VCPUS);
|
||||
|
||||
struct hv_vp_assist_page vp_assist_page;
|
||||
|
||||
struct {
|
||||
u64 pa_page_gpa;
|
||||
u64 vm_id;
|
||||
u32 vp_id;
|
||||
} nested;
|
||||
};
|
||||
|
||||
struct kvm_hypervisor_cpuid {
|
||||
u32 base;
|
||||
u32 limit;
|
||||
@@ -824,6 +682,8 @@ struct kvm_vcpu_xen {
|
||||
};
|
||||
#endif
|
||||
|
||||
struct kvm_vcpu_hv;
|
||||
|
||||
struct kvm_queued_exception {
|
||||
bool pending;
|
||||
bool injected;
|
||||
@@ -1181,39 +1041,6 @@ struct kvm_arch_memory_slot {
|
||||
unsigned short *gfn_write_track;
|
||||
};
|
||||
|
||||
/*
|
||||
* Track the mode of the optimized logical map, as the rules for decoding the
|
||||
* destination vary per mode. Enabling the optimized logical map requires all
|
||||
* software-enabled local APIs to be in the same mode, each addressable APIC to
|
||||
* be mapped to only one MDA, and each MDA to map to at most one APIC.
|
||||
*/
|
||||
enum kvm_apic_logical_mode {
|
||||
/* All local APICs are software disabled. */
|
||||
KVM_APIC_MODE_SW_DISABLED,
|
||||
/* All software enabled local APICs in xAPIC cluster addressing mode. */
|
||||
KVM_APIC_MODE_XAPIC_CLUSTER,
|
||||
/* All software enabled local APICs in xAPIC flat addressing mode. */
|
||||
KVM_APIC_MODE_XAPIC_FLAT,
|
||||
/* All software enabled local APICs in x2APIC mode. */
|
||||
KVM_APIC_MODE_X2APIC,
|
||||
/*
|
||||
* Optimized map disabled, e.g. not all local APICs in the same logical
|
||||
* mode, same logical ID assigned to multiple APICs, etc.
|
||||
*/
|
||||
KVM_APIC_MODE_MAP_DISABLED,
|
||||
};
|
||||
|
||||
struct kvm_apic_map {
|
||||
struct rcu_head rcu;
|
||||
enum kvm_apic_logical_mode logical_mode;
|
||||
u32 max_apic_id;
|
||||
union {
|
||||
struct kvm_lapic *xapic_flat_map[8];
|
||||
struct kvm_lapic *xapic_cluster_map[16][4];
|
||||
};
|
||||
struct kvm_lapic *phys_map[];
|
||||
};
|
||||
|
||||
/* Hyper-V synthetic debugger (SynDbg)*/
|
||||
struct kvm_hv_syndbg {
|
||||
struct {
|
||||
@@ -1842,8 +1669,6 @@ struct kvm_x86_ops {
|
||||
|
||||
void (*update_cpu_dirty_logging)(struct kvm_vcpu *vcpu);
|
||||
|
||||
const struct kvm_x86_nested_ops *nested_ops;
|
||||
|
||||
void (*vcpu_blocking)(struct kvm_vcpu *vcpu);
|
||||
void (*vcpu_unblocking)(struct kvm_vcpu *vcpu);
|
||||
|
||||
@@ -1878,6 +1703,7 @@ struct kvm_x86_ops {
|
||||
int (*vm_copy_enc_context_from)(struct kvm *kvm, unsigned int source_fd);
|
||||
int (*vm_move_enc_context_from)(struct kvm *kvm, unsigned int source_fd);
|
||||
void (*guest_memory_reclaimed)(struct kvm *kvm);
|
||||
void (*reload_vmsa)(struct kvm_vcpu *vcpu);
|
||||
|
||||
int (*get_feature_msr)(u32 msr, u64 *data);
|
||||
|
||||
@@ -1900,12 +1726,22 @@ struct kvm_x86_ops {
|
||||
|
||||
gva_t (*get_untagged_addr)(struct kvm_vcpu *vcpu, gva_t gva, unsigned int flags);
|
||||
void *(*alloc_apic_backing_page)(struct kvm_vcpu *vcpu);
|
||||
int (*gmem_prepare)(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_order);
|
||||
void (*gmem_invalidate)(kvm_pfn_t start, kvm_pfn_t end);
|
||||
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_CONVERT
|
||||
int (*gmem_make_private)(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,
|
||||
kvm_pfn_t nr_pages);
|
||||
#endif
|
||||
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_RECLAIM
|
||||
void (*gmem_make_shared)(kvm_pfn_t pfn, kvm_pfn_t nr_pages);
|
||||
#endif
|
||||
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
|
||||
void (*gmem_invalidate_range)(struct kvm *kvm, struct kvm_gfn_range *range);
|
||||
#endif
|
||||
int (*gmem_max_mapping_level)(struct kvm *kvm, kvm_pfn_t pfn, bool is_private);
|
||||
};
|
||||
|
||||
struct kvm_x86_nested_ops {
|
||||
bool enabled;
|
||||
|
||||
void (*leave_nested)(struct kvm_vcpu *vcpu);
|
||||
bool (*is_exception_vmexit)(struct kvm_vcpu *vcpu, u8 vector,
|
||||
u32 error_code);
|
||||
@@ -1937,6 +1773,7 @@ struct kvm_x86_init_ops {
|
||||
|
||||
struct kvm_x86_ops *runtime_ops;
|
||||
struct kvm_pmu_ops *pmu_ops;
|
||||
struct kvm_x86_nested_ops *nested_ops;
|
||||
};
|
||||
|
||||
struct kvm_arch_async_pf {
|
||||
@@ -1952,6 +1789,7 @@ extern bool __read_mostly enable_apicv;
|
||||
extern bool __read_mostly enable_ipiv;
|
||||
extern bool __read_mostly enable_device_posted_irqs;
|
||||
extern struct kvm_x86_ops kvm_x86_ops;
|
||||
extern struct kvm_x86_nested_ops kvm_nested_ops __read_mostly;
|
||||
|
||||
#define kvm_x86_call(func) static_call(kvm_x86_##func)
|
||||
|
||||
@@ -1961,6 +1799,14 @@ extern struct kvm_x86_ops kvm_x86_ops;
|
||||
#define KVM_X86_OP_OPTIONAL_RET0 KVM_X86_OP
|
||||
#include <asm/kvm-x86-ops.h>
|
||||
|
||||
#define kvm_nested_call(func) static_call(kvm_x86_nested_##func)
|
||||
|
||||
#define KVM_X86_NESTED_OP(func) \
|
||||
DECLARE_STATIC_CALL(kvm_x86_nested_##func, *(((struct kvm_x86_nested_ops *)0)->func));
|
||||
#define KVM_X86_NESTED_OP_OPTIONAL KVM_X86_NESTED_OP
|
||||
#define KVM_X86_NESTED_OP_OPTIONAL_RET0 KVM_X86_NESTED_OP
|
||||
#include <asm/kvm-x86-nested-ops.h>
|
||||
|
||||
#define __KVM_HAVE_ARCH_VM_ALLOC
|
||||
static inline struct kvm *kvm_arch_alloc_vm(void)
|
||||
{
|
||||
@@ -2019,13 +1865,6 @@ static inline unsigned long read_msr(unsigned long msr)
|
||||
}
|
||||
#endif
|
||||
|
||||
enum {
|
||||
TASK_SWITCH_CALL = 0,
|
||||
TASK_SWITCH_IRET = 1,
|
||||
TASK_SWITCH_JMP = 2,
|
||||
TASK_SWITCH_GATE = 3,
|
||||
};
|
||||
|
||||
#define HF_GUEST_MASK (1 << 0) /* VCPU is in guest-mode */
|
||||
|
||||
#ifdef CONFIG_KVM_SMM
|
||||
|
||||
@@ -160,7 +160,8 @@ config KVM_AMD_SEV
|
||||
depends on CRYPTO_DEV_SP_PSP && !(KVM_AMD=y && CRYPTO_DEV_CCP_DD=m)
|
||||
select ARCH_HAS_CC_PLATFORM
|
||||
select KVM_GENERIC_MEMORY_ATTRIBUTES
|
||||
select HAVE_KVM_ARCH_GMEM_PREPARE
|
||||
select HAVE_KVM_ARCH_GMEM_CONVERT
|
||||
select HAVE_KVM_ARCH_GMEM_RECLAIM
|
||||
select HAVE_KVM_ARCH_GMEM_INVALIDATE
|
||||
select HAVE_KVM_ARCH_GMEM_POPULATE
|
||||
help
|
||||
|
||||
+18
-4
@@ -370,7 +370,7 @@ static u32 cpuid_get_reg_unsafe(struct kvm_cpuid_entry2 *entry, u32 reg)
|
||||
}
|
||||
}
|
||||
|
||||
static int cpuid_func_emulated(struct kvm_cpuid_entry2 *entry, u32 func,
|
||||
static int cpuid_func_emulated(struct kvm_cpuid_entry2 *entry, u32 func, u32 index,
|
||||
bool include_partially_emulated);
|
||||
|
||||
void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
|
||||
@@ -400,7 +400,7 @@ void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
|
||||
if (!entry)
|
||||
continue;
|
||||
|
||||
cpuid_func_emulated(&emulated, cpuid.function, true);
|
||||
cpuid_func_emulated(&emulated, cpuid.function, cpuid.index, true);
|
||||
|
||||
/*
|
||||
* A vCPU has a feature if it's supported by KVM and is enabled
|
||||
@@ -1273,8 +1273,12 @@ void kvm_initialize_cpu_caps(void)
|
||||
kvm_cpu_cap_set(X86_FEATURE_NULL_SEL_CLR_BASE);
|
||||
|
||||
kvm_cpu_cap_init(CPUID_C000_0001_EDX,
|
||||
F(SM2),
|
||||
F(SM2_EN),
|
||||
F(XSTORE),
|
||||
F(XSTORE_EN),
|
||||
F(CCS),
|
||||
F(CCS_EN),
|
||||
F(XCRYPT),
|
||||
F(XCRYPT_EN),
|
||||
F(ACE2),
|
||||
@@ -1283,6 +1287,12 @@ void kvm_initialize_cpu_caps(void)
|
||||
F(PHE_EN),
|
||||
F(PMM),
|
||||
F(PMM_EN),
|
||||
F(RNG2),
|
||||
F(RNG2_EN),
|
||||
F(PHE2),
|
||||
F(PHE2_EN),
|
||||
F(RSA),
|
||||
F(RSA_EN),
|
||||
);
|
||||
|
||||
/*
|
||||
@@ -1369,11 +1379,15 @@ static struct kvm_cpuid_entry2 *do_host_cpuid(struct kvm_cpuid_array *array,
|
||||
return entry;
|
||||
}
|
||||
|
||||
static int cpuid_func_emulated(struct kvm_cpuid_entry2 *entry, u32 func,
|
||||
static int cpuid_func_emulated(struct kvm_cpuid_entry2 *entry, u32 func, u32 index,
|
||||
bool include_partially_emulated)
|
||||
{
|
||||
memset(entry, 0, sizeof(*entry));
|
||||
|
||||
/* KVM doesn't currently emulate any non-zero indices. */
|
||||
if (cpuid_function_is_indexed(func) && index)
|
||||
return 0;
|
||||
|
||||
entry->function = func;
|
||||
entry->index = 0;
|
||||
entry->flags = 0;
|
||||
@@ -1411,7 +1425,7 @@ static int __do_cpuid_func_emulated(struct kvm_cpuid_array *array, u32 func)
|
||||
if (array->nent >= array->maxnent)
|
||||
return -E2BIG;
|
||||
|
||||
array->nent += cpuid_func_emulated(&array->entries[array->nent], func, false);
|
||||
array->nent += cpuid_func_emulated(&array->entries[array->nent], func, 0, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+37
-12
@@ -3280,8 +3280,12 @@ static int em_dr_write(struct x86_emulate_ctxt *ctxt)
|
||||
else
|
||||
val = ctxt->src.val & ~0U;
|
||||
|
||||
/* #UD condition is already handled. */
|
||||
if (ctxt->ops->set_dr(ctxt, ctxt->modrm_reg, val) < 0)
|
||||
/*
|
||||
* A #GP due to an illegal value should be impossible at this point, as
|
||||
* such #GPs have priority over MOV DR intercepts on SVM, i.e. KVM must
|
||||
* manually check the value *before* emulating the write.
|
||||
*/
|
||||
if (WARN_ON_ONCE(ctxt->ops->set_dr(ctxt, ctxt->modrm_reg, val)))
|
||||
return emulate_gp(ctxt, 0);
|
||||
|
||||
/* Disable writeback. */
|
||||
@@ -3816,31 +3820,53 @@ static int check_cr_access(struct x86_emulate_ctxt *ctxt)
|
||||
|
||||
static int check_dr_read(struct x86_emulate_ctxt *ctxt)
|
||||
{
|
||||
bool is_intel = ctxt->ops->guest_cpuid_is_intel_compatible(ctxt);
|
||||
int dr = ctxt->modrm_reg;
|
||||
u64 cr4;
|
||||
|
||||
if (dr > 7)
|
||||
return emulate_ud(ctxt);
|
||||
|
||||
cr4 = ctxt->ops->get_cr(ctxt, 4);
|
||||
if ((cr4 & X86_CR4_DE) && (dr == 4 || dr == 5))
|
||||
if ((dr == 4 || dr == 5) && (ctxt->ops->get_cr(ctxt, 4) & X86_CR4_DE))
|
||||
return emulate_ud(ctxt);
|
||||
|
||||
/* Intel CPUs prioritize the DR7.GD=1 #DB over the CPL>0 #GP. */
|
||||
if (!is_intel && ctxt->ops->cpl(ctxt))
|
||||
return emulate_gp(ctxt, 0);
|
||||
|
||||
if (ctxt->ops->get_effective_dr7(ctxt) & DR7_GD)
|
||||
return emulate_db(ctxt, DR6_BD);
|
||||
|
||||
if (is_intel && ctxt->ops->cpl(ctxt))
|
||||
return emulate_gp(ctxt, 0);
|
||||
|
||||
return X86EMUL_CONTINUE;
|
||||
}
|
||||
|
||||
static int check_dr_write(struct x86_emulate_ctxt *ctxt)
|
||||
{
|
||||
u64 new_val = ctxt->src.val64;
|
||||
int dr = ctxt->modrm_reg;
|
||||
int rc;
|
||||
|
||||
if ((dr == 6 || dr == 7) && (new_val & 0xffffffff00000000ULL))
|
||||
return emulate_gp(ctxt, 0);
|
||||
rc = check_dr_read(ctxt);
|
||||
if (rc != X86EMUL_CONTINUE)
|
||||
return rc;
|
||||
|
||||
return check_dr_read(ctxt);
|
||||
switch (ctxt->modrm_reg) {
|
||||
case 4:
|
||||
case 6:
|
||||
if (!kvm_dr6_valid(new_val))
|
||||
return emulate_gp(ctxt, 0);
|
||||
break;
|
||||
case 5:
|
||||
case 7:
|
||||
if (!kvm_dr7_valid(new_val))
|
||||
return emulate_gp(ctxt, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return X86EMUL_CONTINUE;
|
||||
}
|
||||
|
||||
static int check_svme(struct x86_emulate_ctxt *ctxt)
|
||||
@@ -4349,11 +4375,10 @@ static const struct opcode twobyte_table[256] = {
|
||||
D(ImplicitOps | ModRM | SrcMem | NoAccess), /* NOP + 7 * reserved NOP */
|
||||
/* 0x20 - 0x2F */
|
||||
DIP(ModRM | DstMem | Priv | Op3264 | NoMod, cr_read, check_cr_access),
|
||||
DIP(ModRM | DstMem | Priv | Op3264 | NoMod, dr_read, check_dr_read),
|
||||
DIP(ModRM | DstMem | Op3264 | NoMod, dr_read, check_dr_read),
|
||||
IIP(ModRM | SrcMem | Priv | Op3264 | NoMod, em_cr_write, cr_write,
|
||||
check_cr_access),
|
||||
IIP(ModRM | SrcMem | Priv | Op3264 | NoMod, em_dr_write, dr_write,
|
||||
check_dr_write),
|
||||
IIP(ModRM | SrcMem | Op3264 | NoMod, em_dr_write, dr_write, check_dr_write),
|
||||
N, N, N, N,
|
||||
GP(ModRM | DstReg | SrcMem | Mov | Sse | Avx, &pfx_0f_28_0f_29),
|
||||
GP(ModRM | DstMem | SrcReg | Mov | Sse | Avx, &pfx_0f_28_0f_29),
|
||||
|
||||
+55
-40
@@ -206,14 +206,20 @@ static struct kvm_vcpu *get_vcpu_by_vpidx(struct kvm *kvm, u32 vpidx)
|
||||
|
||||
static struct kvm_vcpu_hv_synic *synic_get(struct kvm *kvm, u32 vpidx)
|
||||
{
|
||||
struct kvm_vcpu *vcpu;
|
||||
struct kvm_vcpu_hv_synic *synic;
|
||||
struct kvm_vcpu_hv *hv_vcpu;
|
||||
struct kvm_vcpu *vcpu;
|
||||
|
||||
vcpu = get_vcpu_by_vpidx(kvm, vpidx);
|
||||
if (!vcpu || !to_hv_vcpu(vcpu))
|
||||
if (!vcpu)
|
||||
return NULL;
|
||||
synic = to_hv_synic(vcpu);
|
||||
return (synic->active) ? synic : NULL;
|
||||
|
||||
hv_vcpu = to_hv_vcpu_safe(vcpu);
|
||||
if (!hv_vcpu)
|
||||
return NULL;
|
||||
|
||||
synic = &hv_vcpu->synic;
|
||||
return READ_ONCE(synic->active) ? synic : NULL;
|
||||
}
|
||||
|
||||
static void kvm_hv_notify_acked_sint(struct kvm_vcpu *vcpu, u32 sint)
|
||||
@@ -593,8 +599,7 @@ static void stimer_mark_pending(struct kvm_vcpu_hv_stimer *stimer,
|
||||
{
|
||||
struct kvm_vcpu *vcpu = hv_stimer_to_vcpu(stimer);
|
||||
|
||||
set_bit(stimer->index,
|
||||
to_hv_vcpu(vcpu)->stimer_pending_bitmap);
|
||||
set_bit(stimer->index, vcpu->arch.hyperv->stimer_pending_bitmap);
|
||||
kvm_make_request(KVM_REQ_HV_STIMER, vcpu);
|
||||
if (vcpu_kick)
|
||||
kvm_vcpu_kick(vcpu);
|
||||
@@ -608,8 +613,7 @@ static void stimer_cleanup(struct kvm_vcpu_hv_stimer *stimer)
|
||||
stimer->index);
|
||||
|
||||
hrtimer_cancel(&stimer->timer);
|
||||
clear_bit(stimer->index,
|
||||
to_hv_vcpu(vcpu)->stimer_pending_bitmap);
|
||||
clear_bit(stimer->index, vcpu->arch.hyperv->stimer_pending_bitmap);
|
||||
stimer->msg_pending = false;
|
||||
stimer->exp_time = 0;
|
||||
}
|
||||
@@ -626,6 +630,18 @@ static enum hrtimer_restart stimer_timer_callback(struct hrtimer *timer)
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate a stimer expiry given in 100ns reference ticks into an
|
||||
* an absolute deadline. Saturates on overflow.
|
||||
*/
|
||||
static ktime_t stimer_add_delta(ktime_t now, u64 delta_100ns)
|
||||
{
|
||||
if (delta_100ns >= KTIME_MAX / 100)
|
||||
return KTIME_MAX;
|
||||
|
||||
return ktime_add_safe(now, 100 * delta_100ns);
|
||||
}
|
||||
|
||||
/*
|
||||
* stimer_start() assumptions:
|
||||
* a) stimer->count is not equal to 0
|
||||
@@ -635,6 +651,7 @@ static int stimer_start(struct kvm_vcpu_hv_stimer *stimer)
|
||||
{
|
||||
u64 time_now;
|
||||
ktime_t ktime_now;
|
||||
ktime_t deadline;
|
||||
|
||||
time_now = get_time_ref_counter(hv_stimer_to_vcpu(stimer)->kvm);
|
||||
ktime_now = ktime_get();
|
||||
@@ -657,10 +674,8 @@ static int stimer_start(struct kvm_vcpu_hv_stimer *stimer)
|
||||
stimer->index,
|
||||
time_now, stimer->exp_time);
|
||||
|
||||
hrtimer_start(&stimer->timer,
|
||||
ktime_add_ns(ktime_now,
|
||||
100 * (stimer->exp_time - time_now)),
|
||||
HRTIMER_MODE_ABS);
|
||||
deadline = stimer_add_delta(ktime_now, stimer->exp_time - time_now);
|
||||
hrtimer_start(&stimer->timer, deadline, HRTIMER_MODE_ABS);
|
||||
return 0;
|
||||
}
|
||||
stimer->exp_time = stimer->count;
|
||||
@@ -679,9 +694,9 @@ static int stimer_start(struct kvm_vcpu_hv_stimer *stimer)
|
||||
stimer->index,
|
||||
time_now, stimer->count);
|
||||
|
||||
hrtimer_start(&stimer->timer,
|
||||
ktime_add_ns(ktime_now, 100 * (stimer->count - time_now)),
|
||||
HRTIMER_MODE_ABS);
|
||||
deadline = stimer_add_delta(ktime_now, stimer->count - time_now);
|
||||
hrtimer_start(&stimer->timer, deadline, HRTIMER_MODE_ABS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -972,7 +987,6 @@ int kvm_hv_vcpu_init(struct kvm_vcpu *vcpu)
|
||||
if (!hv_vcpu)
|
||||
return -ENOMEM;
|
||||
|
||||
vcpu->arch.hyperv = hv_vcpu;
|
||||
hv_vcpu->vcpu = vcpu;
|
||||
|
||||
synic_init(&hv_vcpu->synic);
|
||||
@@ -988,6 +1002,14 @@ int kvm_hv_vcpu_init(struct kvm_vcpu *vcpu)
|
||||
spin_lock_init(&hv_vcpu->tlb_flush_fifo[i].write_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure the structure is fully initialized before it's visible to
|
||||
* other tasks, as much of the state can be legally accessed without
|
||||
* holding vcpu->mutex.
|
||||
*
|
||||
* Pairs with the smp_load_acquire() in to_hv_vcpu_safe().
|
||||
*/
|
||||
smp_store_release(&vcpu->arch.hyperv, hv_vcpu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1002,7 +1024,7 @@ int kvm_hv_activate_synic(struct kvm_vcpu *vcpu, bool dont_zero_synic_pages)
|
||||
|
||||
synic = to_hv_synic(vcpu);
|
||||
|
||||
synic->active = true;
|
||||
WRITE_ONCE(synic->active, true);
|
||||
synic->dont_zero_synic_pages = dont_zero_synic_pages;
|
||||
synic->control = HV_SYNIC_CONTROL_ENABLE;
|
||||
return 0;
|
||||
@@ -1935,14 +1957,14 @@ static int kvm_hv_get_tlb_flush_entries(struct kvm *kvm, struct kvm_hv_hcall *hc
|
||||
return kvm_hv_get_hc_data(kvm, hc, hc->rep_cnt, hc->rep_cnt, entries);
|
||||
}
|
||||
|
||||
static void hv_tlb_flush_enqueue(struct kvm_vcpu *vcpu,
|
||||
struct kvm_vcpu_hv_tlb_flush_fifo *tlb_flush_fifo,
|
||||
u64 *entries, int count)
|
||||
static void hv_tlb_flush_enqueue(struct kvm_vcpu *vcpu, u64 *entries, int count,
|
||||
bool is_guest_mode)
|
||||
{
|
||||
struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu);
|
||||
struct kvm_vcpu_hv_tlb_flush_fifo *tlb_flush_fifo;
|
||||
u64 flush_all_entry = KVM_HV_TLB_FLUSHALL_ENTRY;
|
||||
|
||||
if (!hv_vcpu)
|
||||
tlb_flush_fifo = kvm_hv_get_tlb_flush_fifo(vcpu, is_guest_mode);
|
||||
if (!tlb_flush_fifo)
|
||||
return;
|
||||
|
||||
spin_lock(&tlb_flush_fifo->write_lock);
|
||||
@@ -1970,15 +1992,16 @@ out_unlock:
|
||||
int kvm_hv_vcpu_flush_tlb(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_vcpu_hv_tlb_flush_fifo *tlb_flush_fifo;
|
||||
struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu);
|
||||
u64 entries[KVM_HV_TLB_FLUSH_FIFO_SIZE];
|
||||
int i, j, count;
|
||||
gva_t gva;
|
||||
|
||||
if (!tdp_enabled || !hv_vcpu)
|
||||
if (!tdp_enabled)
|
||||
return -EINVAL;
|
||||
|
||||
tlb_flush_fifo = kvm_hv_get_tlb_flush_fifo(vcpu, is_guest_mode(vcpu));
|
||||
if (!tlb_flush_fifo)
|
||||
return -EINVAL;
|
||||
|
||||
count = kfifo_out(&tlb_flush_fifo->entries, entries, KVM_HV_TLB_FLUSH_FIFO_SIZE);
|
||||
|
||||
@@ -2017,7 +2040,6 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
|
||||
struct kvm *kvm = vcpu->kvm;
|
||||
struct hv_tlb_flush_ex flush_ex;
|
||||
struct hv_tlb_flush flush;
|
||||
struct kvm_vcpu_hv_tlb_flush_fifo *tlb_flush_fifo;
|
||||
/*
|
||||
* Normally, there can be no more than 'KVM_HV_TLB_FLUSH_FIFO_SIZE'
|
||||
* entries on the TLB flush fifo. The last entry, however, needs to be
|
||||
@@ -2144,11 +2166,8 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
|
||||
* analyze it here, flush TLB regardless of the specified address space.
|
||||
*/
|
||||
if (all_cpus && !is_guest_mode(vcpu)) {
|
||||
kvm_for_each_vcpu(i, v, kvm) {
|
||||
tlb_flush_fifo = kvm_hv_get_tlb_flush_fifo(v, false);
|
||||
hv_tlb_flush_enqueue(v, tlb_flush_fifo,
|
||||
tlb_flush_entries, hc->rep_cnt);
|
||||
}
|
||||
kvm_for_each_vcpu(i, v, kvm)
|
||||
hv_tlb_flush_enqueue(v, tlb_flush_entries, hc->rep_cnt, false);
|
||||
|
||||
kvm_make_all_cpus_request(kvm, KVM_REQ_HV_TLB_FLUSH);
|
||||
} else if (!is_guest_mode(vcpu)) {
|
||||
@@ -2158,9 +2177,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
|
||||
v = kvm_get_vcpu(kvm, i);
|
||||
if (!v)
|
||||
continue;
|
||||
tlb_flush_fifo = kvm_hv_get_tlb_flush_fifo(v, false);
|
||||
hv_tlb_flush_enqueue(v, tlb_flush_fifo,
|
||||
tlb_flush_entries, hc->rep_cnt);
|
||||
hv_tlb_flush_enqueue(v, tlb_flush_entries, hc->rep_cnt, false);
|
||||
}
|
||||
|
||||
kvm_make_vcpus_request_mask(kvm, KVM_REQ_HV_TLB_FLUSH, vcpu_mask);
|
||||
@@ -2170,7 +2187,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
|
||||
bitmap_zero(vcpu_mask, KVM_MAX_VCPUS);
|
||||
|
||||
kvm_for_each_vcpu(i, v, kvm) {
|
||||
hv_v = to_hv_vcpu(v);
|
||||
hv_v = to_hv_vcpu_safe(v);
|
||||
|
||||
/*
|
||||
* The following check races with nested vCPUs entering/exiting
|
||||
@@ -2191,9 +2208,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
|
||||
continue;
|
||||
|
||||
__set_bit(i, vcpu_mask);
|
||||
tlb_flush_fifo = kvm_hv_get_tlb_flush_fifo(v, true);
|
||||
hv_tlb_flush_enqueue(v, tlb_flush_fifo,
|
||||
tlb_flush_entries, hc->rep_cnt);
|
||||
hv_tlb_flush_enqueue(v, tlb_flush_entries, hc->rep_cnt, true);
|
||||
}
|
||||
|
||||
kvm_make_vcpus_request_mask(kvm, KVM_REQ_HV_TLB_FLUSH, vcpu_mask);
|
||||
@@ -2406,7 +2421,7 @@ static int kvm_hv_hypercall_complete(struct kvm_vcpu *vcpu, u64 result)
|
||||
ret = kvm_skip_emulated_instruction(vcpu);
|
||||
|
||||
if (tlb_lock_count)
|
||||
kvm_x86_ops.nested_ops->hv_inject_synthetic_vmexit_post_tlb_flush(vcpu);
|
||||
kvm_nested_call(hv_inject_synthetic_vmexit_post_tlb_flush)(vcpu);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -2787,8 +2802,8 @@ int kvm_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid,
|
||||
};
|
||||
int i, nent = ARRAY_SIZE(cpuid_entries);
|
||||
|
||||
if (kvm_x86_ops.nested_ops->get_evmcs_version)
|
||||
evmcs_ver = kvm_x86_ops.nested_ops->get_evmcs_version(vcpu);
|
||||
if (kvm_nested_ops.enabled)
|
||||
evmcs_ver = kvm_nested_call(get_evmcs_version)(vcpu);
|
||||
|
||||
if (cpuid->nent < nent)
|
||||
return -E2BIG;
|
||||
|
||||
+113
-4
@@ -27,6 +27,96 @@
|
||||
|
||||
#ifdef CONFIG_KVM_HYPERV
|
||||
|
||||
|
||||
/* Hyper-V SynIC timer */
|
||||
struct kvm_vcpu_hv_stimer {
|
||||
struct hrtimer timer;
|
||||
int index;
|
||||
union hv_stimer_config config;
|
||||
u64 count;
|
||||
u64 exp_time;
|
||||
struct hv_message msg;
|
||||
bool msg_pending;
|
||||
};
|
||||
|
||||
/* Hyper-V synthetic interrupt controller (SynIC)*/
|
||||
struct kvm_vcpu_hv_synic {
|
||||
u64 version;
|
||||
u64 control;
|
||||
u64 msg_page;
|
||||
u64 evt_page;
|
||||
atomic64_t sint[HV_SYNIC_SINT_COUNT];
|
||||
atomic_t sint_to_gsi[HV_SYNIC_SINT_COUNT];
|
||||
DECLARE_BITMAP(auto_eoi_bitmap, 256);
|
||||
DECLARE_BITMAP(vec_bitmap, 256);
|
||||
bool active;
|
||||
bool dont_zero_synic_pages;
|
||||
};
|
||||
|
||||
/* The maximum number of entries on the TLB flush fifo. */
|
||||
#define KVM_HV_TLB_FLUSH_FIFO_SIZE (16)
|
||||
/*
|
||||
* Note: the following 'magic' entry is made up by KVM to avoid putting
|
||||
* anything besides GVA on the TLB flush fifo. It is theoretically possible
|
||||
* to observe a request to flush 4095 PFNs starting from 0xfffffffffffff000
|
||||
* which will look identical. KVM's action to 'flush everything' instead of
|
||||
* flushing these particular addresses is, however, fully legitimate as
|
||||
* flushing more than requested is always OK.
|
||||
*/
|
||||
#define KVM_HV_TLB_FLUSHALL_ENTRY ((u64)-1)
|
||||
|
||||
enum hv_tlb_flush_fifos {
|
||||
HV_L1_TLB_FLUSH_FIFO,
|
||||
HV_L2_TLB_FLUSH_FIFO,
|
||||
HV_NR_TLB_FLUSH_FIFOS,
|
||||
};
|
||||
|
||||
struct kvm_vcpu_hv_tlb_flush_fifo {
|
||||
spinlock_t write_lock;
|
||||
DECLARE_KFIFO(entries, u64, KVM_HV_TLB_FLUSH_FIFO_SIZE);
|
||||
};
|
||||
|
||||
/* Hyper-V per vcpu emulation context */
|
||||
struct kvm_vcpu_hv {
|
||||
struct kvm_vcpu *vcpu;
|
||||
u32 vp_index;
|
||||
u64 hv_vapic;
|
||||
s64 runtime_offset;
|
||||
struct kvm_vcpu_hv_synic synic;
|
||||
struct kvm_hyperv_exit exit;
|
||||
struct kvm_vcpu_hv_stimer stimer[HV_SYNIC_STIMER_COUNT];
|
||||
DECLARE_BITMAP(stimer_pending_bitmap, HV_SYNIC_STIMER_COUNT);
|
||||
bool enforce_cpuid;
|
||||
struct {
|
||||
u32 features_eax; /* HYPERV_CPUID_FEATURES.EAX */
|
||||
u32 features_ebx; /* HYPERV_CPUID_FEATURES.EBX */
|
||||
u32 features_edx; /* HYPERV_CPUID_FEATURES.EDX */
|
||||
u32 enlightenments_eax; /* HYPERV_CPUID_ENLIGHTMENT_INFO.EAX */
|
||||
u32 enlightenments_ebx; /* HYPERV_CPUID_ENLIGHTMENT_INFO.EBX */
|
||||
u32 syndbg_cap_eax; /* HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES.EAX */
|
||||
u32 nested_eax; /* HYPERV_CPUID_NESTED_FEATURES.EAX */
|
||||
u32 nested_ebx; /* HYPERV_CPUID_NESTED_FEATURES.EBX */
|
||||
} cpuid_cache;
|
||||
|
||||
struct kvm_vcpu_hv_tlb_flush_fifo tlb_flush_fifo[HV_NR_TLB_FLUSH_FIFOS];
|
||||
|
||||
/*
|
||||
* Preallocated buffers for handling hypercalls that pass sparse vCPU
|
||||
* sets (for high vCPU counts, they're too large to comfortably fit on
|
||||
* the stack).
|
||||
*/
|
||||
u64 sparse_banks[HV_MAX_SPARSE_VCPU_BANKS];
|
||||
DECLARE_BITMAP(vcpu_mask, KVM_MAX_VCPUS);
|
||||
|
||||
struct hv_vp_assist_page vp_assist_page;
|
||||
|
||||
struct {
|
||||
u64 pa_page_gpa;
|
||||
u64 vm_id;
|
||||
u32 vp_id;
|
||||
} nested;
|
||||
};
|
||||
|
||||
/* "Hv#1" signature */
|
||||
#define HYPERV_CPUID_SIGNATURE_EAX 0x31237648
|
||||
|
||||
@@ -62,8 +152,22 @@ static inline struct kvm_hv *to_kvm_hv(struct kvm *kvm)
|
||||
return &kvm->arch.hyperv;
|
||||
}
|
||||
|
||||
static inline struct kvm_vcpu_hv *to_hv_vcpu_safe(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
/*
|
||||
* Ensure the HyperV structure is fully initialized when accessing it
|
||||
* without holding vcpu->mutex (or some other guarantee that KVM can't
|
||||
* concurrently instantiate the structure).
|
||||
*
|
||||
* Pairs with the smp_store_release() in kvm_hv_vcpu_init().
|
||||
*/
|
||||
return smp_load_acquire(&vcpu->arch.hyperv);
|
||||
}
|
||||
|
||||
static inline struct kvm_vcpu_hv *to_hv_vcpu(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
kvm_lockdep_assert_vcpu_is_locked_or_unreachable(vcpu);
|
||||
|
||||
return vcpu->arch.hyperv;
|
||||
}
|
||||
|
||||
@@ -88,7 +192,7 @@ static inline struct kvm_hv_syndbg *to_hv_syndbg(struct kvm_vcpu *vcpu)
|
||||
|
||||
static inline u32 kvm_hv_get_vpindex(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu);
|
||||
struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu_safe(vcpu);
|
||||
|
||||
return hv_vcpu ? hv_vcpu->vp_index : vcpu->vcpu_idx;
|
||||
}
|
||||
@@ -142,7 +246,7 @@ static inline struct kvm_vcpu *hv_stimer_to_vcpu(struct kvm_vcpu_hv_stimer *stim
|
||||
|
||||
static inline bool kvm_hv_has_stimer_pending(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu);
|
||||
struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu_safe(vcpu);
|
||||
|
||||
if (!hv_vcpu)
|
||||
return false;
|
||||
@@ -198,10 +302,13 @@ int kvm_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid,
|
||||
static inline struct kvm_vcpu_hv_tlb_flush_fifo *kvm_hv_get_tlb_flush_fifo(struct kvm_vcpu *vcpu,
|
||||
bool is_guest_mode)
|
||||
{
|
||||
struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu);
|
||||
struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu_safe(vcpu);
|
||||
int i = is_guest_mode ? HV_L2_TLB_FLUSH_FIFO :
|
||||
HV_L1_TLB_FLUSH_FIFO;
|
||||
|
||||
if (!hv_vcpu)
|
||||
return NULL;
|
||||
|
||||
return &hv_vcpu->tlb_flush_fifo[i];
|
||||
}
|
||||
|
||||
@@ -209,10 +316,12 @@ static inline void kvm_hv_vcpu_purge_flush_tlb(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_vcpu_hv_tlb_flush_fifo *tlb_flush_fifo;
|
||||
|
||||
if (!to_hv_vcpu(vcpu) || !kvm_check_request(KVM_REQ_HV_TLB_FLUSH, vcpu))
|
||||
if (!kvm_check_request(KVM_REQ_HV_TLB_FLUSH, vcpu))
|
||||
return;
|
||||
|
||||
tlb_flush_fifo = kvm_hv_get_tlb_flush_fifo(vcpu, is_guest_mode(vcpu));
|
||||
if (!tlb_flush_fifo)
|
||||
return;
|
||||
|
||||
kfifo_reset_out(&tlb_flush_fifo->entries);
|
||||
}
|
||||
|
||||
@@ -118,6 +118,26 @@ int kvm_cpu_has_extint(struct kvm_vcpu *v);
|
||||
int kvm_cpu_get_extint(struct kvm_vcpu *v);
|
||||
int kvm_cpu_get_interrupt(struct kvm_vcpu *v);
|
||||
|
||||
static inline void kvm_warn_on_lost_irq(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
/*
|
||||
* WARN if an IRQ was lost between detecting the IRQ and grabbing the
|
||||
* IRQ for injection, unless it's possible the lost IRQ was due to one
|
||||
* of the exceptional cases below.
|
||||
*
|
||||
* If the VM has an in-kernel PIC, the ExtINT handling that's routed
|
||||
* through KVM's virtual PIC is tracked per-VM, not per-vCPU. If
|
||||
* another vCPU grabs the IRQ, or deasserts the interrupt (which is
|
||||
* level-triggered), then it's both expected and "fine" for an IRQ
|
||||
* seemingly be "lost" from this vCPU's perspective.
|
||||
*
|
||||
* Similarly, Xen's event channel isn't entirely within KVM's control,
|
||||
* e.g. Xen emulation can be disabled entirely per-VM, or the guest
|
||||
* can desassert an IRQ by writing to shared memory.
|
||||
*/
|
||||
WARN_ON_ONCE(!pic_in_kernel(vcpu->kvm) && !IS_ENABLED(CONFIG_KVM_XEN));
|
||||
}
|
||||
|
||||
void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu);
|
||||
void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu);
|
||||
void kvm_apic_nmi_wd_deliver(struct kvm_vcpu *vcpu);
|
||||
|
||||
+11
-2
@@ -75,6 +75,16 @@ module_param(lapic_timer_advance, bool, 0444);
|
||||
/* step-by-step approximation to mitigate fluctuation */
|
||||
#define LAPIC_TIMER_ADVANCE_ADJUST_STEP 8
|
||||
|
||||
/* apic attention bits */
|
||||
#define KVM_APIC_CHECK_VAPIC 0
|
||||
/*
|
||||
* The following bit is set with PV-EOI, unset on EOI.
|
||||
* We detect PV-EOI changes by guest by comparing
|
||||
* this bit with PV-EOI in guest memory.
|
||||
* See the implementation in apic_update_pv_eoi.
|
||||
*/
|
||||
#define KVM_APIC_PV_EOI_PENDING 1
|
||||
|
||||
static bool __read_mostly vector_hashing_enabled = true;
|
||||
module_param_named(vector_hashing, vector_hashing_enabled, bool, 0444);
|
||||
|
||||
@@ -1487,8 +1497,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_ERR "TODO: unsupported delivery mode %x\n",
|
||||
delivery_mode);
|
||||
WARN_ON_ONCE(1);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -32,6 +32,39 @@ enum lapic_mode {
|
||||
LAPIC_MODE_X2APIC = MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE,
|
||||
};
|
||||
|
||||
/*
|
||||
* Track the mode of the optimized logical map, as the rules for decoding the
|
||||
* destination vary per mode. Enabling the optimized logical map requires all
|
||||
* software-enabled local APIs to be in the same mode, each addressable APIC to
|
||||
* be mapped to only one MDA, and each MDA to map to at most one APIC.
|
||||
*/
|
||||
enum kvm_apic_logical_mode {
|
||||
/* All local APICs are software disabled. */
|
||||
KVM_APIC_MODE_SW_DISABLED,
|
||||
/* All software enabled local APICs in xAPIC cluster addressing mode. */
|
||||
KVM_APIC_MODE_XAPIC_CLUSTER,
|
||||
/* All software enabled local APICs in xAPIC flat addressing mode. */
|
||||
KVM_APIC_MODE_XAPIC_FLAT,
|
||||
/* All software enabled local APICs in x2APIC mode. */
|
||||
KVM_APIC_MODE_X2APIC,
|
||||
/*
|
||||
* Optimized map disabled, e.g. not all local APICs in the same logical
|
||||
* mode, same logical ID assigned to multiple APICs, etc.
|
||||
*/
|
||||
KVM_APIC_MODE_MAP_DISABLED,
|
||||
};
|
||||
|
||||
struct kvm_apic_map {
|
||||
struct rcu_head rcu;
|
||||
enum kvm_apic_logical_mode logical_mode;
|
||||
u32 max_apic_id;
|
||||
union {
|
||||
struct kvm_lapic *xapic_flat_map[8];
|
||||
struct kvm_lapic *xapic_cluster_map[16][4];
|
||||
};
|
||||
struct kvm_lapic *phys_map[];
|
||||
};
|
||||
|
||||
enum lapic_lvt_entry {
|
||||
LVT_TIMER,
|
||||
LVT_THERMAL_MONITOR,
|
||||
|
||||
+5
-6
@@ -6,14 +6,14 @@
|
||||
#include "regs.h"
|
||||
#include "cpuid.h"
|
||||
|
||||
extern bool tdp_enabled;
|
||||
extern bool __read_mostly tdp_enabled;
|
||||
#ifdef CONFIG_X86_64
|
||||
extern bool tdp_mmu_enabled;
|
||||
extern bool __read_mostly tdp_mmu_enabled;
|
||||
#else
|
||||
#define tdp_mmu_enabled false
|
||||
#endif
|
||||
extern bool __read_mostly enable_mmio_caching;
|
||||
extern bool eager_page_split;
|
||||
extern bool __read_mostly eager_page_split;
|
||||
|
||||
#define KVM_MEMSLOT_PAGES_TO_MMU_PAGES_RATIO 50
|
||||
#define KVM_MIN_ALLOC_MMU_PAGES 64UL
|
||||
@@ -385,9 +385,8 @@ static inline gpa_t kvm_translate_gpa(struct kvm_vcpu *vcpu,
|
||||
{
|
||||
if (!mmu_is_nested(vcpu) || w == &vcpu->arch.ngpa_walk)
|
||||
return gpa;
|
||||
return kvm_x86_ops.nested_ops->translate_nested_gpa(vcpu, gpa, access,
|
||||
exception,
|
||||
pte_access);
|
||||
return kvm_nested_call(translate_nested_gpa)(vcpu, gpa, access,
|
||||
exception, pte_access);
|
||||
}
|
||||
|
||||
static inline bool kvm_has_mirrored_tdp(const struct kvm *kvm)
|
||||
|
||||
+77
-57
@@ -105,7 +105,7 @@ module_param_named(flush_on_reuse, force_flush_and_sync_on_reuse, bool, 0644);
|
||||
* 2. while doing 1. it walks guest-physical to host-physical
|
||||
* If the hardware supports that we don't need to do shadow paging.
|
||||
*/
|
||||
bool tdp_enabled = false;
|
||||
bool __read_mostly tdp_enabled = false;
|
||||
|
||||
static bool __ro_after_init tdp_mmu_allowed;
|
||||
|
||||
@@ -1248,18 +1248,9 @@ struct rmap_iterator {
|
||||
int pos; /* index of the sptep */
|
||||
};
|
||||
|
||||
/*
|
||||
* Iteration must be started by this function. This should also be used after
|
||||
* removing/dropping sptes from the rmap link because in such cases the
|
||||
* information in the iterator may not be valid.
|
||||
*
|
||||
* Returns sptep if found, NULL otherwise.
|
||||
*/
|
||||
static u64 *rmap_get_first(struct kvm_rmap_head *rmap_head,
|
||||
struct rmap_iterator *iter)
|
||||
static u64 *__rmap_get_first(unsigned long rmap_val,
|
||||
struct rmap_iterator *iter)
|
||||
{
|
||||
unsigned long rmap_val = kvm_rmap_get(rmap_head);
|
||||
|
||||
if (!rmap_val)
|
||||
return NULL;
|
||||
|
||||
@@ -1273,6 +1264,19 @@ static u64 *rmap_get_first(struct kvm_rmap_head *rmap_head,
|
||||
return iter->desc->sptes[iter->pos];
|
||||
}
|
||||
|
||||
/*
|
||||
* Iteration must be started by this function. This should also be used after
|
||||
* removing/dropping sptes from the rmap link because in such cases the
|
||||
* information in the iterator may not be valid.
|
||||
*
|
||||
* Returns sptep if found, NULL otherwise.
|
||||
*/
|
||||
static u64 *rmap_get_first(struct kvm_rmap_head *rmap_head,
|
||||
struct rmap_iterator *iter)
|
||||
{
|
||||
return __rmap_get_first(kvm_rmap_get(rmap_head), iter);
|
||||
}
|
||||
|
||||
/*
|
||||
* Must be used with a valid iterator: e.g. after rmap_get_first().
|
||||
*
|
||||
@@ -1307,8 +1311,9 @@ static u64 *rmap_get_next(struct rmap_iterator *iter)
|
||||
__for_each_rmap_spte(_rmap_head_, _iter_, _sptep_) \
|
||||
if (!WARN_ON_ONCE(!is_shadow_present_pte(*(_sptep_)))) \
|
||||
|
||||
#define for_each_rmap_spte_lockless(_rmap_head_, _iter_, _sptep_, _spte_) \
|
||||
__for_each_rmap_spte(_rmap_head_, _iter_, _sptep_) \
|
||||
#define for_each_rmap_spte_lockless(_rmap_val_, _iter_, _sptep_, _spte_) \
|
||||
for (_sptep_ = __rmap_get_first(_rmap_val_, _iter_); \
|
||||
_sptep_; _sptep_ = rmap_get_next(_iter_)) \
|
||||
if (is_shadow_present_pte(_spte_ = mmu_spte_get_lockless(sptep)))
|
||||
|
||||
static void drop_spte(struct kvm *kvm, u64 *sptep)
|
||||
@@ -1734,11 +1739,11 @@ static bool kvm_rmap_age_gfn_range(struct kvm *kvm,
|
||||
struct kvm_rmap_head *rmap_head;
|
||||
struct rmap_iterator iter;
|
||||
unsigned long rmap_val;
|
||||
u64 old_spte, new_spte;
|
||||
bool young = false;
|
||||
u64 *sptep;
|
||||
gfn_t gfn;
|
||||
int level;
|
||||
u64 spte;
|
||||
|
||||
for (level = PG_LEVEL_4K; level <= KVM_MAX_HUGEPAGE_LEVEL; level++) {
|
||||
for (gfn = range->start; gfn < range->end;
|
||||
@@ -1746,8 +1751,8 @@ static bool kvm_rmap_age_gfn_range(struct kvm *kvm,
|
||||
rmap_head = gfn_to_rmap(gfn, level, range->slot);
|
||||
rmap_val = kvm_rmap_lock_readonly(rmap_head);
|
||||
|
||||
for_each_rmap_spte_lockless(rmap_head, &iter, sptep, spte) {
|
||||
if (!is_accessed_spte(spte))
|
||||
for_each_rmap_spte_lockless(rmap_val, &iter, sptep, old_spte) {
|
||||
if (!is_accessed_spte(old_spte))
|
||||
continue;
|
||||
|
||||
if (test_only) {
|
||||
@@ -1755,17 +1760,18 @@ static bool kvm_rmap_age_gfn_range(struct kvm *kvm,
|
||||
return true;
|
||||
}
|
||||
|
||||
if (spte_ad_enabled(spte))
|
||||
clear_bit((ffs(shadow_accessed_mask) - 1),
|
||||
(unsigned long *)sptep);
|
||||
if (spte_ad_enabled(old_spte))
|
||||
new_spte = old_spte & ~shadow_accessed_mask;
|
||||
else
|
||||
/*
|
||||
* If the following cmpxchg fails, the
|
||||
* spte is being concurrently modified
|
||||
* and should most likely stay young.
|
||||
*/
|
||||
cmpxchg64(sptep, spte,
|
||||
mark_spte_for_access_track(spte));
|
||||
new_spte = mark_spte_for_access_track(old_spte);
|
||||
|
||||
/*
|
||||
* Don't bother retrying if the CMPXCHG fails,
|
||||
* i.e. if another CPU modified the SPTE. The
|
||||
* SPTE is either being zapped or is likely
|
||||
* still in-use, i.e. is still young.
|
||||
*/
|
||||
cmpxchg64(sptep, old_spte, new_spte);
|
||||
young = true;
|
||||
}
|
||||
|
||||
@@ -6944,20 +6950,11 @@ restart:
|
||||
kvm_mmu_commit_zap_page(kvm, &invalid_list);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fast invalidate all shadow pages and use lock-break technique
|
||||
* to zap obsolete pages.
|
||||
*
|
||||
* It's required when memslot is being deleted or VM is being
|
||||
* destroyed, in these cases, we should ensure that KVM MMU does
|
||||
* not use any resource of the being-deleted slot or all slots
|
||||
* after calling the function.
|
||||
*/
|
||||
static void kvm_mmu_zap_all_fast(struct kvm *kvm)
|
||||
static void __kvm_mmu_zap_all_fast_front_half(struct kvm *kvm)
|
||||
{
|
||||
lockdep_assert_held(&kvm->slots_lock);
|
||||
lockdep_assert_held_write(&kvm->mmu_lock);
|
||||
|
||||
write_lock(&kvm->mmu_lock);
|
||||
trace_kvm_mmu_zap_all_fast(kvm);
|
||||
|
||||
/*
|
||||
@@ -6994,8 +6991,12 @@ static void kvm_mmu_zap_all_fast(struct kvm *kvm)
|
||||
kvm_make_all_cpus_request(kvm, KVM_REQ_MMU_FREE_OBSOLETE_ROOTS);
|
||||
|
||||
kvm_zap_obsolete_pages(kvm);
|
||||
}
|
||||
|
||||
write_unlock(&kvm->mmu_lock);
|
||||
static void __kvm_mmu_zap_all_fast_back_half(struct kvm *kvm)
|
||||
{
|
||||
lockdep_assert_held(&kvm->slots_lock);
|
||||
lockdep_assert_not_held(&kvm->mmu_lock);
|
||||
|
||||
/*
|
||||
* Zap the invalidated TDP MMU roots, all SPTEs must be dropped before
|
||||
@@ -7009,6 +7010,24 @@ static void kvm_mmu_zap_all_fast(struct kvm *kvm)
|
||||
kvm_tdp_mmu_zap_invalidated_roots(kvm, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fast invalidate all shadow pages and use lock-break technique
|
||||
* to zap obsolete pages.
|
||||
*
|
||||
* It's required when memslot is being deleted or VM is being
|
||||
* destroyed, in these cases, we should ensure that KVM MMU does
|
||||
* not use any resource of the being-deleted slot or all slots
|
||||
* after calling the function.
|
||||
*/
|
||||
static void kvm_mmu_zap_all_fast(struct kvm *kvm)
|
||||
{
|
||||
write_lock(&kvm->mmu_lock);
|
||||
__kvm_mmu_zap_all_fast_front_half(kvm);
|
||||
write_unlock(&kvm->mmu_lock);
|
||||
|
||||
__kvm_mmu_zap_all_fast_back_half(kvm);
|
||||
}
|
||||
|
||||
int kvm_mmu_init_vm(struct kvm *kvm)
|
||||
{
|
||||
int r, i;
|
||||
@@ -7583,8 +7602,8 @@ out_flush:
|
||||
kvm_mmu_remote_flush_or_zap(kvm, &invalid_list, flush);
|
||||
}
|
||||
|
||||
static void kvm_mmu_zap_memslot(struct kvm *kvm,
|
||||
struct kvm_memory_slot *slot)
|
||||
void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
|
||||
struct kvm_memory_slot *slot)
|
||||
{
|
||||
struct kvm_gfn_range range = {
|
||||
.slot = slot,
|
||||
@@ -7593,27 +7612,28 @@ static void kvm_mmu_zap_memslot(struct kvm *kvm,
|
||||
.may_block = true,
|
||||
.attr_filter = KVM_FILTER_PRIVATE | KVM_FILTER_SHARED,
|
||||
};
|
||||
bool zap_all = kvm->arch.vm_type == KVM_X86_DEFAULT_VM &&
|
||||
kvm_check_has_quirk(kvm, KVM_X86_QUIRK_SLOT_ZAP_ALL);
|
||||
bool flush;
|
||||
|
||||
write_lock(&kvm->mmu_lock);
|
||||
flush = kvm_unmap_gfn_range(kvm, &range);
|
||||
kvm_mmu_zap_memslot_pages_and_flush(kvm, slot, flush);
|
||||
|
||||
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
|
||||
if (slot->gmem.file)
|
||||
kvm_arch_gmem_invalidate_range(kvm, &range);
|
||||
#endif
|
||||
|
||||
if (zap_all) {
|
||||
__kvm_mmu_zap_all_fast_front_half(kvm);
|
||||
} else {
|
||||
flush = kvm_unmap_gfn_range(kvm, &range);
|
||||
kvm_mmu_zap_memslot_pages_and_flush(kvm, slot, flush);
|
||||
}
|
||||
|
||||
write_unlock(&kvm->mmu_lock);
|
||||
}
|
||||
|
||||
static inline bool kvm_memslot_flush_zap_all(struct kvm *kvm)
|
||||
{
|
||||
return kvm->arch.vm_type == KVM_X86_DEFAULT_VM &&
|
||||
kvm_check_has_quirk(kvm, KVM_X86_QUIRK_SLOT_ZAP_ALL);
|
||||
}
|
||||
|
||||
void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
|
||||
struct kvm_memory_slot *slot)
|
||||
{
|
||||
if (kvm_memslot_flush_zap_all(kvm))
|
||||
kvm_mmu_zap_all_fast(kvm);
|
||||
else
|
||||
kvm_mmu_zap_memslot(kvm, slot);
|
||||
if (zap_all)
|
||||
__kvm_mmu_zap_all_fast_back_half(kvm);
|
||||
}
|
||||
|
||||
void kvm_mmu_invalidate_mmio_sptes(struct kvm *kvm, u64 gen)
|
||||
|
||||
@@ -235,7 +235,7 @@ static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu,
|
||||
!(pte & PT_GUEST_DIRTY_MASK)) {
|
||||
trace_kvm_mmu_set_dirty_bit(table_gfn, index, sizeof(pte));
|
||||
#if PTTYPE == PTTYPE_EPT
|
||||
if (kvm_x86_ops.nested_ops->write_log_dirty(vcpu, addr))
|
||||
if (kvm_nested_call(write_log_dirty)(vcpu, addr))
|
||||
return -EINVAL;
|
||||
#endif
|
||||
pte |= PT_GUEST_DIRTY_MASK;
|
||||
|
||||
@@ -19,6 +19,13 @@ static inline u64 kvm_tdp_mmu_read_spte(tdp_ptep_t sptep)
|
||||
return READ_ONCE(*rcu_dereference(sptep));
|
||||
}
|
||||
|
||||
/*
|
||||
* WARNING! mmu_lock must be held for write when using the "write atomic" or
|
||||
* "clear bits atomic" APIs, otherwise KVM could overwrite the "wrong" old SPTE
|
||||
* value, i.e. clobber an update from a different CPU. The only exception is
|
||||
* when KVM is freezing a leaf SPTE for removal, in which case KVM doesn't care
|
||||
* about the exact old SPTE value (KVM will react to the actual old value).
|
||||
*/
|
||||
static inline u64 kvm_tdp_mmu_write_spte_atomic(tdp_ptep_t sptep, u64 new_spte)
|
||||
{
|
||||
KVM_MMU_WARN_ON(is_ept_ve_possible(new_spte));
|
||||
|
||||
@@ -1335,19 +1335,17 @@ static void kvm_tdp_mmu_age_spte(struct kvm *kvm, struct tdp_iter *iter)
|
||||
if (WARN_ON_ONCE(is_mirror_sptep(iter->sptep)))
|
||||
return;
|
||||
|
||||
if (spte_ad_enabled(iter->old_spte)) {
|
||||
iter->old_spte = tdp_mmu_clear_spte_bits_atomic(iter->sptep,
|
||||
shadow_accessed_mask);
|
||||
if (spte_ad_enabled(iter->old_spte))
|
||||
new_spte = iter->old_spte & ~shadow_accessed_mask;
|
||||
} else {
|
||||
else
|
||||
new_spte = mark_spte_for_access_track(iter->old_spte);
|
||||
/*
|
||||
* It is safe for the following cmpxchg to fail. Leave the
|
||||
* Accessed bit set, as the spte is most likely young anyway.
|
||||
*/
|
||||
if (__tdp_mmu_set_spte_atomic(kvm, iter, new_spte))
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't bother retrying if another CPU modified the SPTE, the SPTE is
|
||||
* either being zapped or is likely still in-use, i.e. is still young.
|
||||
*/
|
||||
if (__tdp_mmu_set_spte_atomic(kvm, iter, new_spte))
|
||||
return;
|
||||
|
||||
trace_kvm_tdp_mmu_spte_changed(iter->as_id, iter->gfn, iter->level,
|
||||
iter->old_spte, new_spte);
|
||||
|
||||
+2
-19
@@ -19,17 +19,6 @@ bool __read_mostly report_ignored_msrs = true;
|
||||
module_param(report_ignored_msrs, bool, 0644);
|
||||
EXPORT_SYMBOL_FOR_KVM_INTERNAL(report_ignored_msrs);
|
||||
|
||||
/* EFER defaults:
|
||||
* - enable syscall per default because its emulated by KVM
|
||||
* - enable LME and LMA per default on 64 bit KVM
|
||||
*/
|
||||
#ifdef CONFIG_X86_64
|
||||
static
|
||||
u64 __read_mostly efer_reserved_bits = ~((u64)(EFER_SCE | EFER_LME | EFER_LMA));
|
||||
#else
|
||||
static u64 __read_mostly efer_reserved_bits = ~((u64)EFER_SCE);
|
||||
#endif
|
||||
|
||||
#define MAX_IO_MSRS 256
|
||||
|
||||
struct msr_bitmap_range {
|
||||
@@ -614,7 +603,7 @@ static bool __kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer)
|
||||
}
|
||||
bool kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer)
|
||||
{
|
||||
if (efer & efer_reserved_bits)
|
||||
if (efer & ~kvm_caps.supported_efer_bits)
|
||||
return false;
|
||||
|
||||
return __kvm_valid_efer(vcpu, efer);
|
||||
@@ -627,7 +616,7 @@ static int set_efer(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
||||
u64 efer = msr_info->data;
|
||||
int r;
|
||||
|
||||
if (efer & efer_reserved_bits)
|
||||
if (efer & ~kvm_caps.supported_efer_bits)
|
||||
return 1;
|
||||
|
||||
if (!msr_info->host_initiated) {
|
||||
@@ -658,12 +647,6 @@ static int set_efer(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kvm_enable_efer_bits(u64 mask)
|
||||
{
|
||||
efer_reserved_bits &= ~mask;
|
||||
}
|
||||
EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_enable_efer_bits);
|
||||
|
||||
bool kvm_msr_allowed(struct kvm_vcpu *vcpu, u32 index, u32 type)
|
||||
{
|
||||
struct kvm_x86_msr_filter *msr_filter;
|
||||
|
||||
+2
-3
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef ARCH_X86_KVM_MSR_H
|
||||
#define ARCH_X86_KVM_MSR_H
|
||||
#ifndef ARCH_X86_KVM_MSRS_H
|
||||
#define ARCH_X86_KVM_MSRS_H
|
||||
|
||||
#include <linux/kvm_host.h>
|
||||
#include <linux/user-return-notifier.h>
|
||||
@@ -58,7 +58,6 @@ int kvm_get_set_one_reg(struct kvm_vcpu *vcpu, unsigned int ioctl,
|
||||
int kvm_get_reg_list(struct kvm_vcpu *vcpu,
|
||||
struct kvm_reg_list __user *user_list);
|
||||
|
||||
void kvm_enable_efer_bits(u64);
|
||||
bool kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer);
|
||||
int kvm_emulate_msr_read(struct kvm_vcpu *vcpu, u32 index, u64 *data);
|
||||
int kvm_emulate_msr_write(struct kvm_vcpu *vcpu, u32 index, u64 data);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user