/* When lazy mode is turned off reset the per-cpu lazy mode variable and then * issue the do-nothing hypercall to flush any stored calls. */ static void lguest_leave_lazy_mode(void) { paravirt_leave_lazy(paravirt_get_lazy_mode()); hcall(LHCALL_FLUSH_ASYNC, 0, 0, 0); }
void paravirt_leave_lazy_cpu(void) { paravirt_leave_lazy(PARAVIRT_LAZY_CPU); }
void paravirt_leave_lazy_mmu(void) { paravirt_leave_lazy(PARAVIRT_LAZY_MMU); }
/* When lazy mode is turned off reset the per-cpu lazy mode variable and then * issue the do-nothing hypercall to flush any stored calls. */ static void lguest_leave_lazy_mode(void) { paravirt_leave_lazy(paravirt_get_lazy_mode()); kvm_hypercall0(LHCALL_FLUSH_ASYNC); }
void xen_leave_lazy(void) { paravirt_leave_lazy(paravirt_get_lazy_mode()); xen_mc_flush(); }
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) { struct kvm_para_state *state = kvm_para_state(); paravirt_enter_lazy_mmu(); state->mode = paravirt_get_lazy_mode(); } static void kvm_leave_lazy_mmu(void) { struct kvm_para_state *state = kvm_para_state(); mmu_queue_flush(state); paravirt_leave_lazy(paravirt_get_lazy_mode()); state->mode = paravirt_get_lazy_mode(); } static void paravirt_ops_setup(void) { pv_info.name = "KVM"; pv_info.paravirt_enabled = 1; 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; } } void __init kvm_guest_init(void) { if (!kvm_para_available()) return; paravirt_ops_setup(); }