diff options
Diffstat (limited to 'arch/powerpc/kvm/powerpc.c')
-rw-r--r-- | arch/powerpc/kvm/powerpc.c | 88 |
1 files changed, 87 insertions, 1 deletions
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 72a4ad86ee91..2f87a1627f6c 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c | |||
@@ -38,9 +38,56 @@ | |||
38 | 38 | ||
39 | int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) | 39 | int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) |
40 | { | 40 | { |
41 | return !(v->arch.msr & MSR_WE) || !!(v->arch.pending_exceptions); | 41 | return !(v->arch.shared->msr & MSR_WE) || |
42 | !!(v->arch.pending_exceptions); | ||
42 | } | 43 | } |
43 | 44 | ||
45 | int kvmppc_kvm_pv(struct kvm_vcpu *vcpu) | ||
46 | { | ||
47 | int nr = kvmppc_get_gpr(vcpu, 11); | ||
48 | int r; | ||
49 | unsigned long __maybe_unused param1 = kvmppc_get_gpr(vcpu, 3); | ||
50 | unsigned long __maybe_unused param2 = kvmppc_get_gpr(vcpu, 4); | ||
51 | unsigned long __maybe_unused param3 = kvmppc_get_gpr(vcpu, 5); | ||
52 | unsigned long __maybe_unused param4 = kvmppc_get_gpr(vcpu, 6); | ||
53 | unsigned long r2 = 0; | ||
54 | |||
55 | if (!(vcpu->arch.shared->msr & MSR_SF)) { | ||
56 | /* 32 bit mode */ | ||
57 | param1 &= 0xffffffff; | ||
58 | param2 &= 0xffffffff; | ||
59 | param3 &= 0xffffffff; | ||
60 | param4 &= 0xffffffff; | ||
61 | } | ||
62 | |||
63 | switch (nr) { | ||
64 | case HC_VENDOR_KVM | KVM_HC_PPC_MAP_MAGIC_PAGE: | ||
65 | { | ||
66 | vcpu->arch.magic_page_pa = param1; | ||
67 | vcpu->arch.magic_page_ea = param2; | ||
68 | |||
69 | r2 = KVM_MAGIC_FEAT_SR; | ||
70 | |||
71 | r = HC_EV_SUCCESS; | ||
72 | break; | ||
73 | } | ||
74 | case HC_VENDOR_KVM | KVM_HC_FEATURES: | ||
75 | r = HC_EV_SUCCESS; | ||
76 | #if defined(CONFIG_PPC_BOOK3S) /* XXX Missing magic page on BookE */ | ||
77 | r2 |= (1 << KVM_FEATURE_MAGIC_PAGE); | ||
78 | #endif | ||
79 | |||
80 | /* Second return value is in r4 */ | ||
81 | break; | ||
82 | default: | ||
83 | r = HC_EV_UNIMPLEMENTED; | ||
84 | break; | ||
85 | } | ||
86 | |||
87 | kvmppc_set_gpr(vcpu, 4, r2); | ||
88 | |||
89 | return r; | ||
90 | } | ||
44 | 91 | ||
45 | int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu) | 92 | int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu) |
46 | { | 93 | { |
@@ -145,8 +192,10 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
145 | case KVM_CAP_PPC_SEGSTATE: | 192 | case KVM_CAP_PPC_SEGSTATE: |
146 | case KVM_CAP_PPC_PAIRED_SINGLES: | 193 | case KVM_CAP_PPC_PAIRED_SINGLES: |
147 | case KVM_CAP_PPC_UNSET_IRQ: | 194 | case KVM_CAP_PPC_UNSET_IRQ: |
195 | case KVM_CAP_PPC_IRQ_LEVEL: | ||
148 | case KVM_CAP_ENABLE_CAP: | 196 | case KVM_CAP_ENABLE_CAP: |
149 | case KVM_CAP_PPC_OSI: | 197 | case KVM_CAP_PPC_OSI: |
198 | case KVM_CAP_PPC_GET_PVINFO: | ||
150 | r = 1; | 199 | r = 1; |
151 | break; | 200 | break; |
152 | case KVM_CAP_COALESCED_MMIO: | 201 | case KVM_CAP_COALESCED_MMIO: |
@@ -534,16 +583,53 @@ out: | |||
534 | return r; | 583 | return r; |
535 | } | 584 | } |
536 | 585 | ||
586 | static int kvm_vm_ioctl_get_pvinfo(struct kvm_ppc_pvinfo *pvinfo) | ||
587 | { | ||
588 | u32 inst_lis = 0x3c000000; | ||
589 | u32 inst_ori = 0x60000000; | ||
590 | u32 inst_nop = 0x60000000; | ||
591 | u32 inst_sc = 0x44000002; | ||
592 | u32 inst_imm_mask = 0xffff; | ||
593 | |||
594 | /* | ||
595 | * The hypercall to get into KVM from within guest context is as | ||
596 | * follows: | ||
597 | * | ||
598 | * lis r0, r0, KVM_SC_MAGIC_R0@h | ||
599 | * ori r0, KVM_SC_MAGIC_R0@l | ||
600 | * sc | ||
601 | * nop | ||
602 | */ | ||
603 | pvinfo->hcall[0] = inst_lis | ((KVM_SC_MAGIC_R0 >> 16) & inst_imm_mask); | ||
604 | pvinfo->hcall[1] = inst_ori | (KVM_SC_MAGIC_R0 & inst_imm_mask); | ||
605 | pvinfo->hcall[2] = inst_sc; | ||
606 | pvinfo->hcall[3] = inst_nop; | ||
607 | |||
608 | return 0; | ||
609 | } | ||
610 | |||
537 | long kvm_arch_vm_ioctl(struct file *filp, | 611 | long kvm_arch_vm_ioctl(struct file *filp, |
538 | unsigned int ioctl, unsigned long arg) | 612 | unsigned int ioctl, unsigned long arg) |
539 | { | 613 | { |
614 | void __user *argp = (void __user *)arg; | ||
540 | long r; | 615 | long r; |
541 | 616 | ||
542 | switch (ioctl) { | 617 | switch (ioctl) { |
618 | case KVM_PPC_GET_PVINFO: { | ||
619 | struct kvm_ppc_pvinfo pvinfo; | ||
620 | r = kvm_vm_ioctl_get_pvinfo(&pvinfo); | ||
621 | if (copy_to_user(argp, &pvinfo, sizeof(pvinfo))) { | ||
622 | r = -EFAULT; | ||
623 | goto out; | ||
624 | } | ||
625 | |||
626 | break; | ||
627 | } | ||
543 | default: | 628 | default: |
544 | r = -ENOTTY; | 629 | r = -ENOTTY; |
545 | } | 630 | } |
546 | 631 | ||
632 | out: | ||
547 | return r; | 633 | return r; |
548 | } | 634 | } |
549 | 635 | ||