- Add VZ specific VM Exit reasons to the traces. - Add top level handler for Guest Exit exceptions. Signed-off-by: Sanjay Lal <sanjayl@xxxxxxxxxxx> --- arch/mips/kvm/kvm_mips.c | 73 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 20 deletions(-) diff --git a/arch/mips/kvm/kvm_mips.c b/arch/mips/kvm/kvm_mips.c index e0dad02..cad9112 100644 --- a/arch/mips/kvm/kvm_mips.c +++ b/arch/mips/kvm/kvm_mips.c @@ -18,6 +18,9 @@ #include <asm/page.h> #include <asm/cacheflush.h> #include <asm/mmu_context.h> +#ifdef CONFIG_KVM_MIPS_VZ +#include <asm/mipsvzregs.h> +#endif #include <linux/kvm_host.h> @@ -47,6 +50,21 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { { "resvd_inst", VCPU_STAT(resvd_inst_exits) }, { "break_inst", VCPU_STAT(break_inst_exits) }, { "flush_dcache", VCPU_STAT(flush_dcache_exits) }, +#ifdef CONFIG_KVM_MIPS_VZ + { "hypervisor_gpsi", VCPU_STAT(hypervisor_gpsi_exits) }, + { "hypervisor_gpsi_cp0", VCPU_STAT(hypervisor_gpsi_cp0_exits) }, + { "hypervisor_gpsi_cache", VCPU_STAT(hypervisor_gpsi_cache_exits) }, + { "hypervisor_gsfc", VCPU_STAT(hypervisor_gsfc_exits) }, + { "hypervisor_gsfc_cp0_status", VCPU_STAT(hypervisor_gsfc_cp0_status_exits) }, + { "hypervisor_gsfc_cp0_cause", VCPU_STAT(hypervisor_gsfc_cp0_cause_exits) }, + { "hypervisor_gsfc_cp0_intctl", VCPU_STAT(hypervisor_gsfc_cp0_intctl_exits) }, + { "hypervisor_hc", VCPU_STAT(hypervisor_hc_exits) }, + { "hypervisor_grr", VCPU_STAT(hypervisor_grr_exits) }, + { "hypervisor_gva", VCPU_STAT(hypervisor_gva_exits) }, + { "hypervisor_ghfc", VCPU_STAT(hypervisor_ghfc_exits) }, + { "hypervisor_gpa", VCPU_STAT(hypervisor_gpa_exits) }, + { "hypervisor_resv", VCPU_STAT(hypervisor_resv_exits) }, +#endif { "halt_wakeup", VCPU_STAT(halt_wakeup) }, {NULL} }; @@ -57,6 +75,9 @@ static int kvm_mips_reset_vcpu(struct kvm_vcpu *vcpu) for_each_possible_cpu(i) { vcpu->arch.guest_kernel_asid[i] = 0; vcpu->arch.guest_user_asid[i] = 0; +#ifdef CONFIG_KVM_MIPS_VZ + vcpu->arch.vzguestid[i] = 0; +#endif } return 0; } @@ -106,7 +127,7 @@ void kvm_arch_check_processor_compat(void *rtn) static void kvm_mips_init_tlbs(struct kvm *kvm) { - unsigned long wired; + ulong wired; /* Add a wired entry to the TLB, it is used to map the commpage to the Guest kernel */ wired = read_c0_wired(); @@ -209,19 +230,19 @@ int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages) } int kvm_arch_prepare_memory_region(struct kvm *kvm, - struct kvm_memory_slot *memslot, - struct kvm_userspace_memory_region *mem, - enum kvm_mr_change change) + struct kvm_memory_slot *memslot, + struct kvm_userspace_memory_region *mem, + enum kvm_mr_change change) { return 0; } void kvm_arch_commit_memory_region(struct kvm *kvm, - struct kvm_userspace_memory_region *mem, - const struct kvm_memory_slot *old, - enum kvm_mr_change change) + struct kvm_userspace_memory_region *mem, + const struct kvm_memory_slot *old, + enum kvm_mr_change change) { - unsigned long npages = 0; + ulong npages = 0; int i, err = 0; kvm_debug("%s: kvm: %p slot: %d, GPA: %llx, size: %llx, QVA: %llx\n", @@ -236,7 +257,7 @@ void kvm_arch_commit_memory_region(struct kvm *kvm, if (npages) { kvm->arch.guest_pmap_npages = npages; kvm->arch.guest_pmap = - kzalloc(npages * sizeof(unsigned long), GFP_KERNEL); + kzalloc(npages * sizeof(ulong), GFP_KERNEL); if (!kvm->arch.guest_pmap) { kvm_err("Failed to allocate guest PMAP"); @@ -345,7 +366,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id) mips32_GuestExceptionEnd - mips32_GuestException); /* Invalidate the icache for these ranges */ - mips32_SyncICache((unsigned long) gebase, ALIGN(size, PAGE_SIZE)); + mips32_SyncICache((ulong) gebase, ALIGN(size, PAGE_SIZE)); /* Allocate comm page for guest kernel, a TLB will be reserved for mapping GVA @ 0xFFFF8000 to this page */ vcpu->arch.kseg0_commpage = kzalloc(PAGE_SIZE << 1, GFP_KERNEL); @@ -376,6 +397,12 @@ out: return ERR_PTR(err); } +int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) +{ + return 0; +} + + void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu) { hrtimer_cancel(&vcpu->arch.comparecount_timer); @@ -527,7 +554,7 @@ out: int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log) { struct kvm_memory_slot *memslot; - unsigned long ga, ga_end; + ulong ga, ga_end; int is_dirty = 0; int r; unsigned long n; @@ -602,11 +629,6 @@ kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) return -ENOTSUPP; } -int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) -{ - return 0; -} - int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) { return -ENOTSUPP; @@ -630,6 +652,11 @@ int kvm_dev_ioctl_check_extension(long ext) case KVM_CAP_COALESCED_MMIO: r = KVM_COALESCED_MMIO_PAGE_OFFSET; break; +#ifdef CONFIG_KVM_MIPS_VZ + case KVM_CAP_MIPS_VZ_ASE: + r = cpu_has_vz; + break; +#endif default: r = 0; break; @@ -721,7 +748,7 @@ enum hrtimer_restart kvm_mips_comparecount_wakeup(struct hrtimer *timer) struct kvm_vcpu *vcpu; vcpu = container_of(timer, struct kvm_vcpu, arch.comparecount_timer); - kvm_mips_comparecount_func((unsigned long) vcpu); + kvm_mips_comparecount_func((ulong) vcpu); hrtimer_forward_now(&vcpu->arch.comparecount_timer, ktime_set(0, MS_TO_NS(10))); return HRTIMER_RESTART; @@ -776,14 +803,13 @@ int kvm_mips_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu) { uint32_t cause = vcpu->arch.host_cp0_cause; uint32_t exccode = (cause >> CAUSEB_EXCCODE) & 0x1f; - uint32_t __user *opc = (uint32_t __user *) vcpu->arch.pc; - unsigned long badvaddr = vcpu->arch.host_cp0_badvaddr; + uint32_t *opc = (uint32_t *) vcpu->arch.pc; + ulong badvaddr = vcpu->arch.host_cp0_badvaddr; enum emulation_result er = EMULATE_DONE; int ret = RESUME_GUEST; /* Set a default exit reason */ run->exit_reason = KVM_EXIT_UNKNOWN; - run->ready_for_interrupt_injection = 1; /* Set the appropriate status bits based on host CPU features, before we hit the scheduler */ kvm_mips_set_c0_status(); @@ -887,6 +913,13 @@ int kvm_mips_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu) ret = kvm_mips_callbacks->handle_break(vcpu); break; +#ifdef CONFIG_KVM_MIPS_VZ + case T_GUEST_EXIT: + /* defer exit accounting to handler */ + ret = kvm_mips_callbacks->handle_guest_exit(vcpu); + break; + +#endif default: kvm_err ("Exception Code: %d, not yet handled, @ PC: %p, inst: 0x%08x BadVaddr: %#lx Status: %#lx\n", -- 1.7.11.3