diff options
Diffstat (limited to 'arch/powerpc/kvm/powerpc.c')
-rw-r--r-- | arch/powerpc/kvm/powerpc.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index fecfe043458d..6a53a3f86dae 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c | |||
@@ -191,6 +191,7 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
191 | case KVM_CAP_PPC_UNSET_IRQ: | 191 | case KVM_CAP_PPC_UNSET_IRQ: |
192 | case KVM_CAP_ENABLE_CAP: | 192 | case KVM_CAP_ENABLE_CAP: |
193 | case KVM_CAP_PPC_OSI: | 193 | case KVM_CAP_PPC_OSI: |
194 | case KVM_CAP_PPC_GET_PVINFO: | ||
194 | r = 1; | 195 | r = 1; |
195 | break; | 196 | break; |
196 | case KVM_CAP_COALESCED_MMIO: | 197 | case KVM_CAP_COALESCED_MMIO: |
@@ -578,16 +579,53 @@ out: | |||
578 | return r; | 579 | return r; |
579 | } | 580 | } |
580 | 581 | ||
582 | static int kvm_vm_ioctl_get_pvinfo(struct kvm_ppc_pvinfo *pvinfo) | ||
583 | { | ||
584 | u32 inst_lis = 0x3c000000; | ||
585 | u32 inst_ori = 0x60000000; | ||
586 | u32 inst_nop = 0x60000000; | ||
587 | u32 inst_sc = 0x44000002; | ||
588 | u32 inst_imm_mask = 0xffff; | ||
589 | |||
590 | /* | ||
591 | * The hypercall to get into KVM from within guest context is as | ||
592 | * follows: | ||
593 | * | ||
594 | * lis r0, r0, KVM_SC_MAGIC_R0@h | ||
595 | * ori r0, KVM_SC_MAGIC_R0@l | ||
596 | * sc | ||
597 | * nop | ||
598 | */ | ||
599 | pvinfo->hcall[0] = inst_lis | ((KVM_SC_MAGIC_R0 >> 16) & inst_imm_mask); | ||
600 | pvinfo->hcall[1] = inst_ori | (KVM_SC_MAGIC_R0 & inst_imm_mask); | ||
601 | pvinfo->hcall[2] = inst_sc; | ||
602 | pvinfo->hcall[3] = inst_nop; | ||
603 | |||
604 | return 0; | ||
605 | } | ||
606 | |||
581 | long kvm_arch_vm_ioctl(struct file *filp, | 607 | long kvm_arch_vm_ioctl(struct file *filp, |
582 | unsigned int ioctl, unsigned long arg) | 608 | unsigned int ioctl, unsigned long arg) |
583 | { | 609 | { |
610 | void __user *argp = (void __user *)arg; | ||
584 | long r; | 611 | long r; |
585 | 612 | ||
586 | switch (ioctl) { | 613 | switch (ioctl) { |
614 | case KVM_PPC_GET_PVINFO: { | ||
615 | struct kvm_ppc_pvinfo pvinfo; | ||
616 | r = kvm_vm_ioctl_get_pvinfo(&pvinfo); | ||
617 | if (copy_to_user(argp, &pvinfo, sizeof(pvinfo))) { | ||
618 | r = -EFAULT; | ||
619 | goto out; | ||
620 | } | ||
621 | |||
622 | break; | ||
623 | } | ||
587 | default: | 624 | default: |
588 | r = -ENOTTY; | 625 | r = -ENOTTY; |
589 | } | 626 | } |
590 | 627 | ||
628 | out: | ||
591 | return r; | 629 | return r; |
592 | } | 630 | } |
593 | 631 | ||