@@ -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",
- Add VZ specific VM Exit reasons to the traces. - Add top level handler for Guest Exit exceptions. Signed-off-by: Sanjay Lal <sanjayl@kymasys.com> --- arch/mips/kvm/kvm_mips.c | 73 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 20 deletions(-)