You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'kvm-updates/3.3' of git://git.kernel.org/pub/scm/virt/kvm/kvm
* 'kvm-updates/3.3' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (74 commits) KVM: PPC: Whitespace fix for kvm.h KVM: Fix whitespace in kvm_para.h KVM: PPC: annotate kvm_rma_init as __init KVM: x86 emulator: implement RDPMC (0F 33) KVM: x86 emulator: fix RDPMC privilege check KVM: Expose the architectural performance monitoring CPUID leaf KVM: VMX: Intercept RDPMC KVM: SVM: Intercept RDPMC KVM: Add generic RDPMC support KVM: Expose a version 2 architectural PMU to a guests KVM: Expose kvm_lapic_local_deliver() KVM: x86 emulator: Use opcode::execute for Group 9 instruction KVM: x86 emulator: Use opcode::execute for Group 4/5 instructions KVM: x86 emulator: Use opcode::execute for Group 1A instruction KVM: ensure that debugfs entries have been created KVM: drop bsp_vcpu pointer from kvm struct KVM: x86: Consolidate PIT legacy test KVM: x86: Do not rely on implicit inclusions KVM: Make KVM_INTEL depend on CPU_SUP_INTEL KVM: Use memdup_user instead of kmalloc/copy_from_user ...
This commit is contained in:
@@ -350,15 +350,6 @@ Who: anybody or Florian Mickler <florian@mickler.org>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: KVM paravirt mmu host support
|
||||
When: January 2011
|
||||
Why: The paravirt mmu host support is slower than non-paravirt mmu, both
|
||||
on newer and older hardware. It is already not exposed to the guest,
|
||||
and kept only for live migration purposes.
|
||||
Who: Avi Kivity <avi@redhat.com>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: iwlwifi 50XX module parameters
|
||||
When: 3.0
|
||||
Why: The "..50" modules parameters were used to configure 5000 series and
|
||||
|
||||
@@ -1178,9 +1178,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
kvm.ignore_msrs=[KVM] Ignore guest accesses to unhandled MSRs.
|
||||
Default is 0 (don't ignore, but inject #GP)
|
||||
|
||||
kvm.oos_shadow= [KVM] Disable out-of-sync shadow paging.
|
||||
Default is 1 (enabled)
|
||||
|
||||
kvm.mmu_audit= [KVM] This is a R/W parameter which allows audit
|
||||
KVM MMU at runtime.
|
||||
Default is 0 (off)
|
||||
|
||||
@@ -1466,6 +1466,31 @@ is supported; 2 if the processor requires all virtual machines to have
|
||||
an RMA, or 1 if the processor can use an RMA but doesn't require it,
|
||||
because it supports the Virtual RMA (VRMA) facility.
|
||||
|
||||
4.64 KVM_NMI
|
||||
|
||||
Capability: KVM_CAP_USER_NMI
|
||||
Architectures: x86
|
||||
Type: vcpu ioctl
|
||||
Parameters: none
|
||||
Returns: 0 on success, -1 on error
|
||||
|
||||
Queues an NMI on the thread's vcpu. Note this is well defined only
|
||||
when KVM_CREATE_IRQCHIP has not been called, since this is an interface
|
||||
between the virtual cpu core and virtual local APIC. After KVM_CREATE_IRQCHIP
|
||||
has been called, this interface is completely emulated within the kernel.
|
||||
|
||||
To use this to emulate the LINT1 input with KVM_CREATE_IRQCHIP, use the
|
||||
following algorithm:
|
||||
|
||||
- pause the vpcu
|
||||
- read the local APIC's state (KVM_GET_LAPIC)
|
||||
- check whether changing LINT1 will queue an NMI (see the LVT entry for LINT1)
|
||||
- if so, issue KVM_NMI
|
||||
- resume the vcpu
|
||||
|
||||
Some guests configure the LINT1 NMI input to cause a panic, aiding in
|
||||
debugging.
|
||||
|
||||
5. The kvm_run structure
|
||||
|
||||
Application code obtains a pointer to the kvm_run structure by
|
||||
|
||||
@@ -774,13 +774,13 @@ struct kvm *kvm_arch_alloc_vm(void)
|
||||
return kvm;
|
||||
}
|
||||
|
||||
struct kvm_io_range {
|
||||
struct kvm_ia64_io_range {
|
||||
unsigned long start;
|
||||
unsigned long size;
|
||||
unsigned long type;
|
||||
};
|
||||
|
||||
static const struct kvm_io_range io_ranges[] = {
|
||||
static const struct kvm_ia64_io_range io_ranges[] = {
|
||||
{VGA_IO_START, VGA_IO_SIZE, GPFN_FRAME_BUFFER},
|
||||
{MMIO_START, MMIO_SIZE, GPFN_LOW_MMIO},
|
||||
{LEGACY_IO_START, LEGACY_IO_SIZE, GPFN_LEGACY_IO},
|
||||
@@ -1366,14 +1366,12 @@ static void kvm_release_vm_pages(struct kvm *kvm)
|
||||
{
|
||||
struct kvm_memslots *slots;
|
||||
struct kvm_memory_slot *memslot;
|
||||
int i, j;
|
||||
int j;
|
||||
unsigned long base_gfn;
|
||||
|
||||
slots = kvm_memslots(kvm);
|
||||
for (i = 0; i < slots->nmemslots; i++) {
|
||||
memslot = &slots->memslots[i];
|
||||
kvm_for_each_memslot(memslot, slots) {
|
||||
base_gfn = memslot->base_gfn;
|
||||
|
||||
for (j = 0; j < memslot->npages; j++) {
|
||||
if (memslot->rmap[j])
|
||||
put_page((struct page *)memslot->rmap[j]);
|
||||
@@ -1820,7 +1818,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
|
||||
if (log->slot >= KVM_MEMORY_SLOTS)
|
||||
goto out;
|
||||
|
||||
memslot = &kvm->memslots->memslots[log->slot];
|
||||
memslot = id_to_memslot(kvm->memslots, log->slot);
|
||||
r = -ENOENT;
|
||||
if (!memslot->dirty_bitmap)
|
||||
goto out;
|
||||
|
||||
@@ -170,8 +170,8 @@ struct kvm_sregs {
|
||||
} ppc64;
|
||||
struct {
|
||||
__u32 sr[16];
|
||||
__u64 ibat[8];
|
||||
__u64 dbat[8];
|
||||
__u64 ibat[8];
|
||||
__u64 dbat[8];
|
||||
} ppc32;
|
||||
} s;
|
||||
struct {
|
||||
|
||||
@@ -498,7 +498,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
|
||||
|
||||
/* If nothing is dirty, don't bother messing with page tables. */
|
||||
if (is_dirty) {
|
||||
memslot = &kvm->memslots->memslots[log->slot];
|
||||
memslot = id_to_memslot(kvm->memslots, log->slot);
|
||||
|
||||
ga = memslot->base_gfn << PAGE_SHIFT;
|
||||
ga_end = ga + (memslot->npages << PAGE_SHIFT);
|
||||
|
||||
@@ -86,7 +86,7 @@ static inline int lpcr_rmls(unsigned long rma_size)
|
||||
* to allocate contiguous physical memory for the real memory
|
||||
* areas for guests.
|
||||
*/
|
||||
void kvm_rma_init(void)
|
||||
void __init kvm_rma_init(void)
|
||||
{
|
||||
unsigned long i;
|
||||
unsigned long j, npages;
|
||||
|
||||
@@ -197,7 +197,10 @@
|
||||
|
||||
/* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */
|
||||
#define X86_FEATURE_FSGSBASE (9*32+ 0) /* {RD/WR}{FS/GS}BASE instructions*/
|
||||
#define X86_FEATURE_BMI1 (9*32+ 3) /* 1st group bit manipulation extensions */
|
||||
#define X86_FEATURE_AVX2 (9*32+ 5) /* AVX2 instructions */
|
||||
#define X86_FEATURE_SMEP (9*32+ 7) /* Supervisor Mode Execution Protection */
|
||||
#define X86_FEATURE_BMI2 (9*32+ 8) /* 2nd group bit manipulation extensions */
|
||||
#define X86_FEATURE_ERMS (9*32+ 9) /* Enhanced REP MOVSB/STOSB */
|
||||
|
||||
#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
|
||||
|
||||
@@ -181,6 +181,7 @@ struct x86_emulate_ops {
|
||||
int (*set_dr)(struct x86_emulate_ctxt *ctxt, int dr, ulong value);
|
||||
int (*set_msr)(struct x86_emulate_ctxt *ctxt, u32 msr_index, u64 data);
|
||||
int (*get_msr)(struct x86_emulate_ctxt *ctxt, u32 msr_index, u64 *pdata);
|
||||
int (*read_pmc)(struct x86_emulate_ctxt *ctxt, u32 pmc, u64 *pdata);
|
||||
void (*halt)(struct x86_emulate_ctxt *ctxt);
|
||||
void (*wbinvd)(struct x86_emulate_ctxt *ctxt);
|
||||
int (*fix_hypercall)(struct x86_emulate_ctxt *ctxt);
|
||||
@@ -364,6 +365,7 @@ enum x86_intercept {
|
||||
#endif
|
||||
|
||||
int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len);
|
||||
bool x86_page_table_writing_insn(struct x86_emulate_ctxt *ctxt);
|
||||
#define EMULATION_FAILED -1
|
||||
#define EMULATION_OK 0
|
||||
#define EMULATION_RESTART 1
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
#include <linux/mmu_notifier.h>
|
||||
#include <linux/tracepoint.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/irq_work.h>
|
||||
|
||||
#include <linux/kvm.h>
|
||||
#include <linux/kvm_para.h>
|
||||
#include <linux/kvm_types.h>
|
||||
#include <linux/perf_event.h>
|
||||
|
||||
#include <asm/pvclock-abi.h>
|
||||
#include <asm/desc.h>
|
||||
@@ -31,6 +33,8 @@
|
||||
#define KVM_MEMORY_SLOTS 32
|
||||
/* memory slots that does not exposed to userspace */
|
||||
#define KVM_PRIVATE_MEM_SLOTS 4
|
||||
#define KVM_MEM_SLOTS_NUM (KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS)
|
||||
|
||||
#define KVM_MMIO_SIZE 16
|
||||
|
||||
#define KVM_PIO_PAGE_OFFSET 1
|
||||
@@ -228,7 +232,7 @@ struct kvm_mmu_page {
|
||||
* One bit set per slot which has memory
|
||||
* in this shadow page.
|
||||
*/
|
||||
DECLARE_BITMAP(slot_bitmap, KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS);
|
||||
DECLARE_BITMAP(slot_bitmap, KVM_MEM_SLOTS_NUM);
|
||||
bool unsync;
|
||||
int root_count; /* Currently serving as active root */
|
||||
unsigned int unsync_children;
|
||||
@@ -239,14 +243,9 @@ struct kvm_mmu_page {
|
||||
int clear_spte_count;
|
||||
#endif
|
||||
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
int write_flooding_count;
|
||||
|
||||
struct kvm_pv_mmu_op_buffer {
|
||||
void *ptr;
|
||||
unsigned len;
|
||||
unsigned processed;
|
||||
char buf[512] __aligned(sizeof(long));
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
|
||||
struct kvm_pio_request {
|
||||
@@ -294,6 +293,37 @@ struct kvm_mmu {
|
||||
u64 pdptrs[4]; /* pae */
|
||||
};
|
||||
|
||||
enum pmc_type {
|
||||
KVM_PMC_GP = 0,
|
||||
KVM_PMC_FIXED,
|
||||
};
|
||||
|
||||
struct kvm_pmc {
|
||||
enum pmc_type type;
|
||||
u8 idx;
|
||||
u64 counter;
|
||||
u64 eventsel;
|
||||
struct perf_event *perf_event;
|
||||
struct kvm_vcpu *vcpu;
|
||||
};
|
||||
|
||||
struct kvm_pmu {
|
||||
unsigned nr_arch_gp_counters;
|
||||
unsigned nr_arch_fixed_counters;
|
||||
unsigned available_event_types;
|
||||
u64 fixed_ctr_ctrl;
|
||||
u64 global_ctrl;
|
||||
u64 global_status;
|
||||
u64 global_ovf_ctrl;
|
||||
u64 counter_bitmask[2];
|
||||
u64 global_ctrl_mask;
|
||||
u8 version;
|
||||
struct kvm_pmc gp_counters[X86_PMC_MAX_GENERIC];
|
||||
struct kvm_pmc fixed_counters[X86_PMC_MAX_FIXED];
|
||||
struct irq_work irq_work;
|
||||
u64 reprogram_pmi;
|
||||
};
|
||||
|
||||
struct kvm_vcpu_arch {
|
||||
/*
|
||||
* rip and regs accesses must go through
|
||||
@@ -345,19 +375,10 @@ struct kvm_vcpu_arch {
|
||||
*/
|
||||
struct kvm_mmu *walk_mmu;
|
||||
|
||||
/* only needed in kvm_pv_mmu_op() path, but it's hot so
|
||||
* put it here to avoid allocation */
|
||||
struct kvm_pv_mmu_op_buffer mmu_op_buffer;
|
||||
|
||||
struct kvm_mmu_memory_cache mmu_pte_list_desc_cache;
|
||||
struct kvm_mmu_memory_cache mmu_page_cache;
|
||||
struct kvm_mmu_memory_cache mmu_page_header_cache;
|
||||
|
||||
gfn_t last_pt_write_gfn;
|
||||
int last_pt_write_count;
|
||||
u64 *last_pte_updated;
|
||||
gfn_t last_pte_gfn;
|
||||
|
||||
struct fpu guest_fpu;
|
||||
u64 xcr0;
|
||||
|
||||
@@ -436,6 +457,8 @@ struct kvm_vcpu_arch {
|
||||
unsigned access;
|
||||
gfn_t mmio_gfn;
|
||||
|
||||
struct kvm_pmu pmu;
|
||||
|
||||
/* used for guest single stepping over the given code position */
|
||||
unsigned long singlestep_rip;
|
||||
|
||||
@@ -444,6 +467,9 @@ struct kvm_vcpu_arch {
|
||||
|
||||
cpumask_var_t wbinvd_dirty_mask;
|
||||
|
||||
unsigned long last_retry_eip;
|
||||
unsigned long last_retry_addr;
|
||||
|
||||
struct {
|
||||
bool halted;
|
||||
gfn_t gfns[roundup_pow_of_two(ASYNC_PF_PER_VCPU)];
|
||||
@@ -459,7 +485,6 @@ struct kvm_arch {
|
||||
unsigned int n_requested_mmu_pages;
|
||||
unsigned int n_max_mmu_pages;
|
||||
unsigned int indirect_shadow_pages;
|
||||
atomic_t invlpg_counter;
|
||||
struct hlist_head mmu_page_hash[KVM_NUM_MMU_PAGES];
|
||||
/*
|
||||
* Hash table of struct kvm_mmu_page.
|
||||
@@ -660,6 +685,8 @@ void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask,
|
||||
|
||||
int kvm_mmu_reset_context(struct kvm_vcpu *vcpu);
|
||||
void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot);
|
||||
int kvm_mmu_rmap_write_protect(struct kvm *kvm, u64 gfn,
|
||||
struct kvm_memory_slot *slot);
|
||||
void kvm_mmu_zap_all(struct kvm *kvm);
|
||||
unsigned int kvm_mmu_calculate_mmu_pages(struct kvm *kvm);
|
||||
void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned int kvm_nr_mmu_pages);
|
||||
@@ -668,8 +695,6 @@ int load_pdptrs(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, unsigned long cr3);
|
||||
|
||||
int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
|
||||
const void *val, int bytes);
|
||||
int kvm_pv_mmu_op(struct kvm_vcpu *vcpu, unsigned long bytes,
|
||||
gpa_t addr, unsigned long *ret);
|
||||
u8 kvm_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn);
|
||||
|
||||
extern bool tdp_enabled;
|
||||
@@ -692,6 +717,7 @@ enum emulation_result {
|
||||
#define EMULTYPE_NO_DECODE (1 << 0)
|
||||
#define EMULTYPE_TRAP_UD (1 << 1)
|
||||
#define EMULTYPE_SKIP (1 << 2)
|
||||
#define EMULTYPE_RETRY (1 << 3)
|
||||
int x86_emulate_instruction(struct kvm_vcpu *vcpu, unsigned long cr2,
|
||||
int emulation_type, void *insn, int insn_len);
|
||||
|
||||
@@ -734,6 +760,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data);
|
||||
|
||||
unsigned long kvm_get_rflags(struct kvm_vcpu *vcpu);
|
||||
void kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags);
|
||||
bool kvm_rdpmc(struct kvm_vcpu *vcpu);
|
||||
|
||||
void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr);
|
||||
void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code);
|
||||
@@ -754,13 +781,14 @@ int fx_init(struct kvm_vcpu *vcpu);
|
||||
|
||||
void kvm_mmu_flush_tlb(struct kvm_vcpu *vcpu);
|
||||
void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
|
||||
const u8 *new, int bytes,
|
||||
bool guest_initiated);
|
||||
const u8 *new, int bytes);
|
||||
int kvm_mmu_unprotect_page(struct kvm *kvm, gfn_t gfn);
|
||||
int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva);
|
||||
void __kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu);
|
||||
int kvm_mmu_load(struct kvm_vcpu *vcpu);
|
||||
void kvm_mmu_unload(struct kvm_vcpu *vcpu);
|
||||
void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu);
|
||||
gpa_t translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa, u32 access);
|
||||
gpa_t kvm_mmu_gva_to_gpa_read(struct kvm_vcpu *vcpu, gva_t gva,
|
||||
struct x86_exception *exception);
|
||||
gpa_t kvm_mmu_gva_to_gpa_fetch(struct kvm_vcpu *vcpu, gva_t gva,
|
||||
@@ -782,6 +810,11 @@ void kvm_disable_tdp(void);
|
||||
int complete_pio(struct kvm_vcpu *vcpu);
|
||||
bool kvm_check_iopl(struct kvm_vcpu *vcpu);
|
||||
|
||||
static inline gpa_t translate_gpa(struct kvm_vcpu *vcpu, gpa_t gpa, u32 access)
|
||||
{
|
||||
return gpa;
|
||||
}
|
||||
|
||||
static inline struct kvm_mmu_page *page_header(hpa_t shadow_page)
|
||||
{
|
||||
struct page *page = pfn_to_page(shadow_page >> PAGE_SHIFT);
|
||||
@@ -894,4 +927,17 @@ extern bool kvm_find_async_pf_gfn(struct kvm_vcpu *vcpu, gfn_t gfn);
|
||||
|
||||
void kvm_complete_insn_gp(struct kvm_vcpu *vcpu, int err);
|
||||
|
||||
int kvm_is_in_guest(void);
|
||||
|
||||
void kvm_pmu_init(struct kvm_vcpu *vcpu);
|
||||
void kvm_pmu_destroy(struct kvm_vcpu *vcpu);
|
||||
void kvm_pmu_reset(struct kvm_vcpu *vcpu);
|
||||
void kvm_pmu_cpuid_update(struct kvm_vcpu *vcpu);
|
||||
bool kvm_pmu_msr(struct kvm_vcpu *vcpu, u32 msr);
|
||||
int kvm_pmu_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *data);
|
||||
int kvm_pmu_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data);
|
||||
int kvm_pmu_read_pmc(struct kvm_vcpu *vcpu, unsigned pmc, u64 *data);
|
||||
void kvm_handle_pmu_event(struct kvm_vcpu *vcpu);
|
||||
void kvm_deliver_pmi(struct kvm_vcpu *vcpu);
|
||||
|
||||
#endif /* _ASM_X86_KVM_HOST_H */
|
||||
|
||||
@@ -39,8 +39,6 @@
|
||||
#include <asm/desc.h>
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
#define MMU_QUEUE_SIZE 1024
|
||||
|
||||
static int kvmapf = 1;
|
||||
|
||||
static int parse_no_kvmapf(char *arg)
|
||||
@@ -60,21 +58,10 @@ static int parse_no_stealacc(char *arg)
|
||||
|
||||
early_param("no-steal-acc", parse_no_stealacc);
|
||||
|
||||
struct kvm_para_state {
|
||||
u8 mmu_queue[MMU_QUEUE_SIZE];
|
||||
int mmu_queue_len;
|
||||
};
|
||||
|
||||
static DEFINE_PER_CPU(struct kvm_para_state, para_state);
|
||||
static DEFINE_PER_CPU(struct kvm_vcpu_pv_apf_data, apf_reason) __aligned(64);
|
||||
static DEFINE_PER_CPU(struct kvm_steal_time, steal_time) __aligned(64);
|
||||
static int has_steal_clock = 0;
|
||||
|
||||
static struct kvm_para_state *kvm_para_state(void)
|
||||
{
|
||||
return &per_cpu(para_state, raw_smp_processor_id());
|
||||
}
|
||||
|
||||
/*
|
||||
* No need for any "IO delay" on KVM
|
||||
*/
|
||||
@@ -271,151 +258,6 @@ do_async_page_fault(struct pt_regs *regs, unsigned long error_code)
|
||||
}
|
||||
}
|
||||
|
||||
static void kvm_mmu_op(void *buffer, unsigned len)
|
||||
{
|
||||
int r;
|
||||
unsigned long a1, a2;
|
||||
|
||||
do {
|
||||
a1 = __pa(buffer);
|
||||
a2 = 0; /* on i386 __pa() always returns <4G */
|
||||
r = kvm_hypercall3(KVM_HC_MMU_OP, len, a1, a2);
|
||||
buffer += r;
|
||||
len -= r;
|
||||
} while (len);
|
||||
}
|
||||
|
||||
static void mmu_queue_flush(struct kvm_para_state *state)
|
||||
{
|
||||
if (state->mmu_queue_len) {
|
||||
kvm_mmu_op(state->mmu_queue, state->mmu_queue_len);
|
||||
state->mmu_queue_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void kvm_deferred_mmu_op(void *buffer, int len)
|
||||
{
|
||||
struct kvm_para_state *state = kvm_para_state();
|
||||
|
||||
if (paravirt_get_lazy_mode() != PARAVIRT_LAZY_MMU) {
|
||||
kvm_mmu_op(buffer, len);
|
||||
return;
|
||||
}
|
||||
if (state->mmu_queue_len + len > sizeof state->mmu_queue)
|
||||
mmu_queue_flush(state);
|
||||
memcpy(state->mmu_queue + state->mmu_queue_len, buffer, len);
|
||||
state->mmu_queue_len += len;
|
||||
}
|
||||
|
||||
static void kvm_mmu_write(void *dest, u64 val)
|
||||
{
|
||||
__u64 pte_phys;
|
||||
struct kvm_mmu_op_write_pte wpte;
|
||||
|
||||
#ifdef CONFIG_HIGHPTE
|
||||
struct page *page;
|
||||
unsigned long dst = (unsigned long) dest;
|
||||
|
||||
page = kmap_atomic_to_page(dest);
|
||||
pte_phys = page_to_pfn(page);
|
||||
pte_phys <<= PAGE_SHIFT;
|
||||
pte_phys += (dst & ~(PAGE_MASK));
|
||||
#else
|
||||
pte_phys = (unsigned long)__pa(dest);
|
||||
#endif
|
||||
wpte.header.op = KVM_MMU_OP_WRITE_PTE;
|
||||
wpte.pte_val = val;
|
||||
wpte.pte_phys = pte_phys;
|
||||
|
||||
kvm_deferred_mmu_op(&wpte, sizeof wpte);
|
||||
}
|
||||
|
||||
/*
|
||||
* We only need to hook operations that are MMU writes. We hook these so that
|
||||
* we can use lazy MMU mode to batch these operations. We could probably
|
||||
* improve the performance of the host code if we used some of the information
|
||||
* here to simplify processing of batched writes.
|
||||
*/
|
||||
static void kvm_set_pte(pte_t *ptep, pte_t pte)
|
||||
{
|
||||
kvm_mmu_write(ptep, pte_val(pte));
|
||||
}
|
||||
|
||||
static void kvm_set_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t pte)
|
||||
{
|
||||
kvm_mmu_write(ptep, pte_val(pte));
|
||||
}
|
||||
|
||||
static void kvm_set_pmd(pmd_t *pmdp, pmd_t pmd)
|
||||
{
|
||||
kvm_mmu_write(pmdp, pmd_val(pmd));
|
||||
}
|
||||
|
||||
#if PAGETABLE_LEVELS >= 3
|
||||
#ifdef CONFIG_X86_PAE
|
||||
static void kvm_set_pte_atomic(pte_t *ptep, pte_t pte)
|
||||
{
|
||||
kvm_mmu_write(ptep, pte_val(pte));
|
||||
}
|
||||
|
||||
static void kvm_pte_clear(struct mm_struct *mm,
|
||||
unsigned long addr, pte_t *ptep)
|
||||
{
|
||||
kvm_mmu_write(ptep, 0);
|
||||
}
|
||||
|
||||
static void kvm_pmd_clear(pmd_t *pmdp)
|
||||
{
|
||||
kvm_mmu_write(pmdp, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void kvm_set_pud(pud_t *pudp, pud_t pud)
|
||||
{
|
||||
kvm_mmu_write(pudp, pud_val(pud));
|
||||
}
|
||||
|
||||
#if PAGETABLE_LEVELS == 4
|
||||
static void kvm_set_pgd(pgd_t *pgdp, pgd_t pgd)
|
||||
{
|
||||
kvm_mmu_write(pgdp, pgd_val(pgd));
|
||||
}
|
||||
#endif
|
||||
#endif /* PAGETABLE_LEVELS >= 3 */
|
||||
|
||||
static void kvm_flush_tlb(void)
|
||||
{
|
||||
struct kvm_mmu_op_flush_tlb ftlb = {
|
||||
.header.op = KVM_MMU_OP_FLUSH_TLB,
|
||||
};
|
||||
|
||||
kvm_deferred_mmu_op(&ftlb, sizeof ftlb);
|
||||
}
|
||||
|
||||
static void kvm_release_pt(unsigned long pfn)
|
||||
{
|
||||
struct kvm_mmu_op_release_pt rpt = {
|
||||
.header.op = KVM_MMU_OP_RELEASE_PT,
|
||||
.pt_phys = (u64)pfn << PAGE_SHIFT,
|
||||
};
|
||||
|
||||
kvm_mmu_op(&rpt, sizeof rpt);
|
||||
}
|
||||
|
||||
static void kvm_enter_lazy_mmu(void)
|
||||
{
|
||||
paravirt_enter_lazy_mmu();
|
||||
}
|
||||
|
||||
static void kvm_leave_lazy_mmu(void)
|
||||
{
|
||||
struct kvm_para_state *state = kvm_para_state();
|
||||
|
||||
mmu_queue_flush(state);
|
||||
paravirt_leave_lazy_mmu();
|
||||
}
|
||||
|
||||
static void __init paravirt_ops_setup(void)
|
||||
{
|
||||
pv_info.name = "KVM";
|
||||
@@ -424,29 +266,6 @@ static void __init paravirt_ops_setup(void)
|
||||
if (kvm_para_has_feature(KVM_FEATURE_NOP_IO_DELAY))
|
||||
pv_cpu_ops.io_delay = kvm_io_delay;
|
||||
|
||||
if (kvm_para_has_feature(KVM_FEATURE_MMU_OP)) {
|
||||
pv_mmu_ops.set_pte = kvm_set_pte;
|
||||
pv_mmu_ops.set_pte_at = kvm_set_pte_at;
|
||||
pv_mmu_ops.set_pmd = kvm_set_pmd;
|
||||
#if PAGETABLE_LEVELS >= 3
|
||||
#ifdef CONFIG_X86_PAE
|
||||
pv_mmu_ops.set_pte_atomic = kvm_set_pte_atomic;
|
||||
pv_mmu_ops.pte_clear = kvm_pte_clear;
|
||||
pv_mmu_ops.pmd_clear = kvm_pmd_clear;
|
||||
#endif
|
||||
pv_mmu_ops.set_pud = kvm_set_pud;
|
||||
#if PAGETABLE_LEVELS == 4
|
||||
pv_mmu_ops.set_pgd = kvm_set_pgd;
|
||||
#endif
|
||||
#endif
|
||||
pv_mmu_ops.flush_tlb_user = kvm_flush_tlb;
|
||||
pv_mmu_ops.release_pte = kvm_release_pt;
|
||||
pv_mmu_ops.release_pmd = kvm_release_pt;
|
||||
pv_mmu_ops.release_pud = kvm_release_pt;
|
||||
|
||||
pv_mmu_ops.lazy_mode.enter = kvm_enter_lazy_mmu;
|
||||
pv_mmu_ops.lazy_mode.leave = kvm_leave_lazy_mmu;
|
||||
}
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
no_timer_check = 1;
|
||||
#endif
|
||||
|
||||
@@ -35,6 +35,7 @@ config KVM
|
||||
select KVM_MMIO
|
||||
select TASKSTATS
|
||||
select TASK_DELAY_ACCT
|
||||
select PERF_EVENTS
|
||||
---help---
|
||||
Support hosting fully virtualized guest machines using hardware
|
||||
virtualization extensions. You will need a fairly recent
|
||||
@@ -52,6 +53,8 @@ config KVM
|
||||
config KVM_INTEL
|
||||
tristate "KVM for Intel processors support"
|
||||
depends on KVM
|
||||
# for perf_guest_get_msrs():
|
||||
depends on CPU_SUP_INTEL
|
||||
---help---
|
||||
Provides support for KVM on Intel processors equipped with the VT
|
||||
extensions.
|
||||
|
||||
@@ -12,7 +12,7 @@ kvm-$(CONFIG_IOMMU_API) += $(addprefix ../../../virt/kvm/, iommu.o)
|
||||
kvm-$(CONFIG_KVM_ASYNC_PF) += $(addprefix ../../../virt/kvm/, async_pf.o)
|
||||
|
||||
kvm-y += x86.o mmu.o emulate.o i8259.o irq.o lapic.o \
|
||||
i8254.o timer.o
|
||||
i8254.o timer.o cpuid.o pmu.o
|
||||
kvm-intel-y += vmx.o
|
||||
kvm-amd-y += svm.o
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,46 @@
|
||||
#ifndef ARCH_X86_KVM_CPUID_H
|
||||
#define ARCH_X86_KVM_CPUID_H
|
||||
|
||||
#include "x86.h"
|
||||
|
||||
void kvm_update_cpuid(struct kvm_vcpu *vcpu);
|
||||
struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu,
|
||||
u32 function, u32 index);
|
||||
int kvm_dev_ioctl_get_supported_cpuid(struct kvm_cpuid2 *cpuid,
|
||||
struct kvm_cpuid_entry2 __user *entries);
|
||||
int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
|
||||
struct kvm_cpuid *cpuid,
|
||||
struct kvm_cpuid_entry __user *entries);
|
||||
int kvm_vcpu_ioctl_set_cpuid2(struct kvm_vcpu *vcpu,
|
||||
struct kvm_cpuid2 *cpuid,
|
||||
struct kvm_cpuid_entry2 __user *entries);
|
||||
int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu,
|
||||
struct kvm_cpuid2 *cpuid,
|
||||
struct kvm_cpuid_entry2 __user *entries);
|
||||
|
||||
|
||||
static inline bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_cpuid_entry2 *best;
|
||||
|
||||
best = kvm_find_cpuid_entry(vcpu, 1, 0);
|
||||
return best && (best->ecx & bit(X86_FEATURE_XSAVE));
|
||||
}
|
||||
|
||||
static inline bool guest_cpuid_has_smep(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_cpuid_entry2 *best;
|
||||
|
||||
best = kvm_find_cpuid_entry(vcpu, 7, 0);
|
||||
return best && (best->ebx & bit(X86_FEATURE_SMEP));
|
||||
}
|
||||
|
||||
static inline bool guest_cpuid_has_fsgsbase(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_cpuid_entry2 *best;
|
||||
|
||||
best = kvm_find_cpuid_entry(vcpu, 7, 0);
|
||||
return best && (best->ebx & bit(X86_FEATURE_FSGSBASE));
|
||||
}
|
||||
|
||||
#endif
|
||||
+226
-210
File diff suppressed because it is too large
Load Diff
@@ -344,7 +344,7 @@ static void create_pit_timer(struct kvm *kvm, u32 val, int is_period)
|
||||
struct kvm_timer *pt = &ps->pit_timer;
|
||||
s64 interval;
|
||||
|
||||
if (!irqchip_in_kernel(kvm))
|
||||
if (!irqchip_in_kernel(kvm) || ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)
|
||||
return;
|
||||
|
||||
interval = muldiv64(val, NSEC_PER_SEC, KVM_PIT_FREQ);
|
||||
@@ -397,15 +397,11 @@ static void pit_load_count(struct kvm *kvm, int channel, u32 val)
|
||||
case 1:
|
||||
/* FIXME: enhance mode 4 precision */
|
||||
case 4:
|
||||
if (!(ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)) {
|
||||
create_pit_timer(kvm, val, 0);
|
||||
}
|
||||
create_pit_timer(kvm, val, 0);
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
if (!(ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)){
|
||||
create_pit_timer(kvm, val, 1);
|
||||
}
|
||||
create_pit_timer(kvm, val, 1);
|
||||
break;
|
||||
default:
|
||||
destroy_pit_timer(kvm->arch.vpit);
|
||||
|
||||
+16
-8
@@ -262,9 +262,10 @@ int kvm_pic_read_irq(struct kvm *kvm)
|
||||
|
||||
void kvm_pic_reset(struct kvm_kpic_state *s)
|
||||
{
|
||||
int irq;
|
||||
struct kvm_vcpu *vcpu0 = s->pics_state->kvm->bsp_vcpu;
|
||||
int irq, i;
|
||||
struct kvm_vcpu *vcpu;
|
||||
u8 irr = s->irr, isr = s->imr;
|
||||
bool found = false;
|
||||
|
||||
s->last_irr = 0;
|
||||
s->irr = 0;
|
||||
@@ -281,12 +282,19 @@ void kvm_pic_reset(struct kvm_kpic_state *s)
|
||||
s->special_fully_nested_mode = 0;
|
||||
s->init4 = 0;
|
||||
|
||||
for (irq = 0; irq < PIC_NUM_PINS/2; irq++) {
|
||||
if (vcpu0 && kvm_apic_accept_pic_intr(vcpu0))
|
||||
if (irr & (1 << irq) || isr & (1 << irq)) {
|
||||
pic_clear_isr(s, irq);
|
||||
}
|
||||
}
|
||||
kvm_for_each_vcpu(i, vcpu, s->pics_state->kvm)
|
||||
if (kvm_apic_accept_pic_intr(vcpu)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (!found)
|
||||
return;
|
||||
|
||||
for (irq = 0; irq < PIC_NUM_PINS/2; irq++)
|
||||
if (irr & (1 << irq) || isr & (1 << irq))
|
||||
pic_clear_isr(s, irq);
|
||||
}
|
||||
|
||||
static void pic_ioport_write(void *opaque, u32 addr, u32 val)
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "irq.h"
|
||||
#include "trace.h"
|
||||
#include "x86.h"
|
||||
#include "cpuid.h"
|
||||
|
||||
#ifndef CONFIG_X86_64
|
||||
#define mod_64(x, y) ((x) - (y) * div64_u64(x, y))
|
||||
@@ -1120,7 +1121,7 @@ int apic_has_pending_timer(struct kvm_vcpu *vcpu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_apic_local_deliver(struct kvm_lapic *apic, int lvt_type)
|
||||
int kvm_apic_local_deliver(struct kvm_lapic *apic, int lvt_type)
|
||||
{
|
||||
u32 reg = apic_get_reg(apic, lvt_type);
|
||||
int vector, mode, trig_mode;
|
||||
|
||||
@@ -34,6 +34,7 @@ void kvm_apic_set_version(struct kvm_vcpu *vcpu);
|
||||
int kvm_apic_match_physical_addr(struct kvm_lapic *apic, u16 dest);
|
||||
int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
|
||||
int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq);
|
||||
int kvm_apic_local_deliver(struct kvm_lapic *apic, int lvt_type);
|
||||
|
||||
u64 kvm_get_apic_base(struct kvm_vcpu *vcpu);
|
||||
void kvm_set_apic_base(struct kvm_vcpu *vcpu, 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