aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2012-09-25 16:32:30 -0400
committerAlexander Graf <agraf@suse.de>2012-10-05 17:38:54 -0400
commita8bd19ef4dd49f0eef86a4a8eb43d60f967236b8 (patch)
tree29a4c8141e1e68d20c832b5d05e064e5ad83f028 /arch/powerpc/kvm
parenta136a8bdc02fc14625ac45ee846cc646fc46597e (diff)
KVM: PPC: Book3S: Get/set guest FP regs using the GET/SET_ONE_REG interface
This enables userspace to get and set all the guest floating-point state using the KVM_[GS]ET_ONE_REG ioctls. The floating-point state includes all of the traditional floating-point registers and the FPSCR (floating point status/control register), all the VMX/Altivec vector registers and the VSCR (vector status/control register), and on POWER7, the vector-scalar registers (note that each FP register is the high-order half of the corresponding VSR). Most of these are implemented in common Book 3S code, except for VSX on POWER7. Because HV and PR differ in how they store the FP and VSX registers on POWER7, the code for these cases is not common. On POWER7, the FP registers are the upper halves of the VSX registers vsr0 - vsr31. PR KVM stores vsr0 - vsr31 in two halves, with the upper halves in the arch.fpr[] array and the lower halves in the arch.vsr[] array, whereas HV KVM on POWER7 stores the whole VSX register in arch.vsr[]. Signed-off-by: Paul Mackerras <paulus@samba.org> [agraf: fix whitespace, vsx compilation] Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc/kvm')
-rw-r--r--arch/powerpc/kvm/book3s.c48
-rw-r--r--arch/powerpc/kvm/book3s_hv.c42
-rw-r--r--arch/powerpc/kvm/book3s_pr.c26
3 files changed, 116 insertions, 0 deletions
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index a5af28fc3a8f..a4b645285240 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -490,6 +490,7 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
490 int r; 490 int r;
491 union kvmppc_one_reg val; 491 union kvmppc_one_reg val;
492 int size; 492 int size;
493 long int i;
493 494
494 size = one_reg_size(reg->id); 495 size = one_reg_size(reg->id);
495 if (size > sizeof(val)) 496 if (size > sizeof(val))
@@ -506,6 +507,29 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
506 case KVM_REG_PPC_DSISR: 507 case KVM_REG_PPC_DSISR:
507 val = get_reg_val(reg->id, vcpu->arch.shared->dsisr); 508 val = get_reg_val(reg->id, vcpu->arch.shared->dsisr);
508 break; 509 break;
510 case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
511 i = reg->id - KVM_REG_PPC_FPR0;
512 val = get_reg_val(reg->id, vcpu->arch.fpr[i]);
513 break;
514 case KVM_REG_PPC_FPSCR:
515 val = get_reg_val(reg->id, vcpu->arch.fpscr);
516 break;
517#ifdef CONFIG_ALTIVEC
518 case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31:
519 if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
520 r = -ENXIO;
521 break;
522 }
523 val.vval = vcpu->arch.vr[reg->id - KVM_REG_PPC_VR0];
524 break;
525 case KVM_REG_PPC_VSCR:
526 if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
527 r = -ENXIO;
528 break;
529 }
530 val = get_reg_val(reg->id, vcpu->arch.vscr.u[3]);
531 break;
532#endif /* CONFIG_ALTIVEC */
509 default: 533 default:
510 r = -EINVAL; 534 r = -EINVAL;
511 break; 535 break;
@@ -525,6 +549,7 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
525 int r; 549 int r;
526 union kvmppc_one_reg val; 550 union kvmppc_one_reg val;
527 int size; 551 int size;
552 long int i;
528 553
529 size = one_reg_size(reg->id); 554 size = one_reg_size(reg->id);
530 if (size > sizeof(val)) 555 if (size > sizeof(val))
@@ -544,6 +569,29 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
544 case KVM_REG_PPC_DSISR: 569 case KVM_REG_PPC_DSISR:
545 vcpu->arch.shared->dsisr = set_reg_val(reg->id, val); 570 vcpu->arch.shared->dsisr = set_reg_val(reg->id, val);
546 break; 571 break;
572 case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
573 i = reg->id - KVM_REG_PPC_FPR0;
574 vcpu->arch.fpr[i] = set_reg_val(reg->id, val);
575 break;
576 case KVM_REG_PPC_FPSCR:
577 vcpu->arch.fpscr = set_reg_val(reg->id, val);
578 break;
579#ifdef CONFIG_ALTIVEC
580 case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31:
581 if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
582 r = -ENXIO;
583 break;
584 }
585 vcpu->arch.vr[reg->id - KVM_REG_PPC_VR0] = val.vval;
586 break;
587 case KVM_REG_PPC_VSCR:
588 if (!cpu_has_feature(CPU_FTR_ALTIVEC)) {
589 r = -ENXIO;
590 break;
591 }
592 vcpu->arch.vscr.u[3] = set_reg_val(reg->id, val);
593 break;
594#endif /* CONFIG_ALTIVEC */
547 default: 595 default:
548 r = -EINVAL; 596 r = -EINVAL;
549 break; 597 break;
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 1cc6b77fa63d..94ec0e30969d 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -579,6 +579,27 @@ int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)
579 i = id - KVM_REG_PPC_PMC1; 579 i = id - KVM_REG_PPC_PMC1;
580 *val = get_reg_val(id, vcpu->arch.pmc[i]); 580 *val = get_reg_val(id, vcpu->arch.pmc[i]);
581 break; 581 break;
582#ifdef CONFIG_VSX
583 case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
584 if (cpu_has_feature(CPU_FTR_VSX)) {
585 /* VSX => FP reg i is stored in arch.vsr[2*i] */
586 long int i = id - KVM_REG_PPC_FPR0;
587 *val = get_reg_val(id, vcpu->arch.vsr[2 * i]);
588 } else {
589 /* let generic code handle it */
590 r = -EINVAL;
591 }
592 break;
593 case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31:
594 if (cpu_has_feature(CPU_FTR_VSX)) {
595 long int i = id - KVM_REG_PPC_VSR0;
596 val->vsxval[0] = vcpu->arch.vsr[2 * i];
597 val->vsxval[1] = vcpu->arch.vsr[2 * i + 1];
598 } else {
599 r = -ENXIO;
600 }
601 break;
602#endif /* CONFIG_VSX */
582 default: 603 default:
583 r = -EINVAL; 604 r = -EINVAL;
584 break; 605 break;
@@ -624,6 +645,27 @@ int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)
624 i = id - KVM_REG_PPC_PMC1; 645 i = id - KVM_REG_PPC_PMC1;
625 vcpu->arch.pmc[i] = set_reg_val(id, *val); 646 vcpu->arch.pmc[i] = set_reg_val(id, *val);
626 break; 647 break;
648#ifdef CONFIG_VSX
649 case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31:
650 if (cpu_has_feature(CPU_FTR_VSX)) {
651 /* VSX => FP reg i is stored in arch.vsr[2*i] */
652 long int i = id - KVM_REG_PPC_FPR0;
653 vcpu->arch.vsr[2 * i] = set_reg_val(id, *val);
654 } else {
655 /* let generic code handle it */
656 r = -EINVAL;
657 }
658 break;
659 case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31:
660 if (cpu_has_feature(CPU_FTR_VSX)) {
661 long int i = id - KVM_REG_PPC_VSR0;
662 vcpu->arch.vsr[2 * i] = val->vsxval[0];
663 vcpu->arch.vsr[2 * i + 1] = val->vsxval[1];
664 } else {
665 r = -ENXIO;
666 }
667 break;
668#endif /* CONFIG_VSX */
627 default: 669 default:
628 r = -EINVAL; 670 r = -EINVAL;
629 break; 671 break;
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index c81109f3a376..b853696b6d8e 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -953,6 +953,19 @@ int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)
953 case KVM_REG_PPC_HIOR: 953 case KVM_REG_PPC_HIOR:
954 *val = get_reg_val(id, to_book3s(vcpu)->hior); 954 *val = get_reg_val(id, to_book3s(vcpu)->hior);
955 break; 955 break;
956#ifdef CONFIG_VSX
957 case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31: {
958 long int i = id - KVM_REG_PPC_VSR0;
959
960 if (!cpu_has_feature(CPU_FTR_VSX)) {
961 r = -ENXIO;
962 break;
963 }
964 val->vsxval[0] = vcpu->arch.fpr[i];
965 val->vsxval[1] = vcpu->arch.vsr[i];
966 break;
967 }
968#endif /* CONFIG_VSX */
956 default: 969 default:
957 r = -EINVAL; 970 r = -EINVAL;
958 break; 971 break;
@@ -970,6 +983,19 @@ int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val)
970 to_book3s(vcpu)->hior = set_reg_val(id, *val); 983 to_book3s(vcpu)->hior = set_reg_val(id, *val);
971 to_book3s(vcpu)->hior_explicit = true; 984 to_book3s(vcpu)->hior_explicit = true;
972 break; 985 break;
986#ifdef CONFIG_VSX
987 case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31: {
988 long int i = id - KVM_REG_PPC_VSR0;
989
990 if (!cpu_has_feature(CPU_FTR_VSX)) {
991 r = -ENXIO;
992 break;
993 }
994 vcpu->arch.fpr[i] = val->vsxval[0];
995 vcpu->arch.vsr[i] = val->vsxval[1];
996 break;
997 }
998#endif /* CONFIG_VSX */
973 default: 999 default:
974 r = -EINVAL; 1000 r = -EINVAL;
975 break; 1001 break;