diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/include/asm/kvm.h | 20 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_ppc.h | 2 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s.c | 48 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_hv.c | 42 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_pr.c | 26 |
5 files changed, 138 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/kvm.h b/arch/powerpc/include/asm/kvm.h index 9557576a532..1466975129c 100644 --- a/arch/powerpc/include/asm/kvm.h +++ b/arch/powerpc/include/asm/kvm.h | |||
@@ -360,4 +360,24 @@ struct kvm_book3e_206_tlb_params { | |||
360 | #define KVM_REG_PPC_PMC7 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1e) | 360 | #define KVM_REG_PPC_PMC7 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1e) |
361 | #define KVM_REG_PPC_PMC8 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1f) | 361 | #define KVM_REG_PPC_PMC8 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1f) |
362 | 362 | ||
363 | /* 32 floating-point registers */ | ||
364 | #define KVM_REG_PPC_FPR0 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x20) | ||
365 | #define KVM_REG_PPC_FPR(n) (KVM_REG_PPC_FPR0 + (n)) | ||
366 | #define KVM_REG_PPC_FPR31 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x3f) | ||
367 | |||
368 | /* 32 VMX/Altivec vector registers */ | ||
369 | #define KVM_REG_PPC_VR0 (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x40) | ||
370 | #define KVM_REG_PPC_VR(n) (KVM_REG_PPC_VR0 + (n)) | ||
371 | #define KVM_REG_PPC_VR31 (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x5f) | ||
372 | |||
373 | /* 32 double-width FP registers for VSX */ | ||
374 | /* High-order halves overlap with FP regs */ | ||
375 | #define KVM_REG_PPC_VSR0 (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x60) | ||
376 | #define KVM_REG_PPC_VSR(n) (KVM_REG_PPC_VSR0 + (n)) | ||
377 | #define KVM_REG_PPC_VSR31 (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x7f) | ||
378 | |||
379 | /* FP and vector status/control registers */ | ||
380 | #define KVM_REG_PPC_FPSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x80) | ||
381 | #define KVM_REG_PPC_VSCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x81) | ||
382 | |||
363 | #endif /* __LINUX_KVM_POWERPC_H */ | 383 | #endif /* __LINUX_KVM_POWERPC_H */ |
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index 709f0ddae1f..51604a16c8a 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h | |||
@@ -200,6 +200,8 @@ static inline u32 kvmppc_set_field(u64 inst, int msb, int lsb, int value) | |||
200 | union kvmppc_one_reg { | 200 | union kvmppc_one_reg { |
201 | u32 wval; | 201 | u32 wval; |
202 | u64 dval; | 202 | u64 dval; |
203 | vector128 vval; | ||
204 | u64 vsxval[2]; | ||
203 | }; | 205 | }; |
204 | 206 | ||
205 | #define one_reg_size(id) \ | 207 | #define one_reg_size(id) \ |
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c index a5af28fc3a8..a4b64528524 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 1cc6b77fa63..94ec0e30969 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 c81109f3a37..b853696b6d8 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; |