Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Paul Mackerras and committed by
Alexander Graf
a8bd19ef a136a8bd

+149
+11
Documentation/virtual/kvm/api.txt
··· 1759 1759 PPC | KVM_REG_PPC_PMC6 | 32 1760 1760 PPC | KVM_REG_PPC_PMC7 | 32 1761 1761 PPC | KVM_REG_PPC_PMC8 | 32 1762 + PPC | KVM_REG_PPC_FPR0 | 64 1763 + ... 1764 + PPC | KVM_REG_PPC_FPR31 | 64 1765 + PPC | KVM_REG_PPC_VR0 | 128 1766 + ... 1767 + PPC | KVM_REG_PPC_VR31 | 128 1768 + PPC | KVM_REG_PPC_VSR0 | 128 1769 + ... 1770 + PPC | KVM_REG_PPC_VSR31 | 128 1771 + PPC | KVM_REG_PPC_FPSCR | 64 1772 + PPC | KVM_REG_PPC_VSCR | 32 1762 1773 1763 1774 4.69 KVM_GET_ONE_REG 1764 1775
+20
arch/powerpc/include/asm/kvm.h
··· 360 360 #define KVM_REG_PPC_PMC7 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1e) 361 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 383 #endif /* __LINUX_KVM_POWERPC_H */
+2
arch/powerpc/include/asm/kvm_ppc.h
··· 200 200 union kvmppc_one_reg { 201 201 u32 wval; 202 202 u64 dval; 203 + vector128 vval; 204 + u64 vsxval[2]; 203 205 }; 204 206 205 207 #define one_reg_size(id) \
+48
arch/powerpc/kvm/book3s.c
··· 490 490 int r; 491 491 union kvmppc_one_reg val; 492 492 int size; 493 + long int i; 493 494 494 495 size = one_reg_size(reg->id); 495 496 if (size > sizeof(val)) ··· 507 506 case KVM_REG_PPC_DSISR: 508 507 val = get_reg_val(reg->id, vcpu->arch.shared->dsisr); 509 508 break; 509 + case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31: 510 + i = reg->id - KVM_REG_PPC_FPR0; 511 + val = get_reg_val(reg->id, vcpu->arch.fpr[i]); 512 + break; 513 + case KVM_REG_PPC_FPSCR: 514 + val = get_reg_val(reg->id, vcpu->arch.fpscr); 515 + break; 516 + #ifdef CONFIG_ALTIVEC 517 + case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31: 518 + if (!cpu_has_feature(CPU_FTR_ALTIVEC)) { 519 + r = -ENXIO; 520 + break; 521 + } 522 + val.vval = vcpu->arch.vr[reg->id - KVM_REG_PPC_VR0]; 523 + break; 524 + case KVM_REG_PPC_VSCR: 525 + if (!cpu_has_feature(CPU_FTR_ALTIVEC)) { 526 + r = -ENXIO; 527 + break; 528 + } 529 + val = get_reg_val(reg->id, vcpu->arch.vscr.u[3]); 530 + break; 531 + #endif /* CONFIG_ALTIVEC */ 510 532 default: 511 533 r = -EINVAL; 512 534 break; ··· 549 525 int r; 550 526 union kvmppc_one_reg val; 551 527 int size; 528 + long int i; 552 529 553 530 size = one_reg_size(reg->id); 554 531 if (size > sizeof(val)) ··· 569 544 case KVM_REG_PPC_DSISR: 570 545 vcpu->arch.shared->dsisr = set_reg_val(reg->id, val); 571 546 break; 547 + case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31: 548 + i = reg->id - KVM_REG_PPC_FPR0; 549 + vcpu->arch.fpr[i] = set_reg_val(reg->id, val); 550 + break; 551 + case KVM_REG_PPC_FPSCR: 552 + vcpu->arch.fpscr = set_reg_val(reg->id, val); 553 + break; 554 + #ifdef CONFIG_ALTIVEC 555 + case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31: 556 + if (!cpu_has_feature(CPU_FTR_ALTIVEC)) { 557 + r = -ENXIO; 558 + break; 559 + } 560 + vcpu->arch.vr[reg->id - KVM_REG_PPC_VR0] = val.vval; 561 + break; 562 + case KVM_REG_PPC_VSCR: 563 + if (!cpu_has_feature(CPU_FTR_ALTIVEC)) { 564 + r = -ENXIO; 565 + break; 566 + } 567 + vcpu->arch.vscr.u[3] = set_reg_val(reg->id, val); 568 + break; 569 + #endif /* CONFIG_ALTIVEC */ 572 570 default: 573 571 r = -EINVAL; 574 572 break;
+42
arch/powerpc/kvm/book3s_hv.c
··· 579 579 i = id - KVM_REG_PPC_PMC1; 580 580 *val = get_reg_val(id, vcpu->arch.pmc[i]); 581 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 603 default: 583 604 r = -EINVAL; 584 605 break; ··· 645 624 i = id - KVM_REG_PPC_PMC1; 646 625 vcpu->arch.pmc[i] = set_reg_val(id, *val); 647 626 break; 627 + #ifdef CONFIG_VSX 628 + case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31: 629 + if (cpu_has_feature(CPU_FTR_VSX)) { 630 + /* VSX => FP reg i is stored in arch.vsr[2*i] */ 631 + long int i = id - KVM_REG_PPC_FPR0; 632 + vcpu->arch.vsr[2 * i] = set_reg_val(id, *val); 633 + } else { 634 + /* let generic code handle it */ 635 + r = -EINVAL; 636 + } 637 + break; 638 + case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31: 639 + if (cpu_has_feature(CPU_FTR_VSX)) { 640 + long int i = id - KVM_REG_PPC_VSR0; 641 + vcpu->arch.vsr[2 * i] = val->vsxval[0]; 642 + vcpu->arch.vsr[2 * i + 1] = val->vsxval[1]; 643 + } else { 644 + r = -ENXIO; 645 + } 646 + break; 647 + #endif /* CONFIG_VSX */ 648 648 default: 649 649 r = -EINVAL; 650 650 break;
+26
arch/powerpc/kvm/book3s_pr.c
··· 953 953 case KVM_REG_PPC_HIOR: 954 954 *val = get_reg_val(id, to_book3s(vcpu)->hior); 955 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 969 default: 957 970 r = -EINVAL; 958 971 break; ··· 983 970 to_book3s(vcpu)->hior = set_reg_val(id, *val); 984 971 to_book3s(vcpu)->hior_explicit = true; 985 972 break; 973 + #ifdef CONFIG_VSX 974 + case KVM_REG_PPC_VSR0 ... KVM_REG_PPC_VSR31: { 975 + long int i = id - KVM_REG_PPC_VSR0; 976 + 977 + if (!cpu_has_feature(CPU_FTR_VSX)) { 978 + r = -ENXIO; 979 + break; 980 + } 981 + vcpu->arch.fpr[i] = val->vsxval[0]; 982 + vcpu->arch.vsr[i] = val->vsxval[1]; 983 + break; 984 + } 985 + #endif /* CONFIG_VSX */ 986 986 default: 987 987 r = -EINVAL; 988 988 break;