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

MIPS: KVM: Expose MSA registers

Add KVM register numbers for the MIPS SIMD Architecture (MSA) registers,
and implement access to them with the KVM_GET_ONE_REG / KVM_SET_ONE_REG
ioctls when the MSA capability is enabled (exposed in a later patch) and
present in the guest according to its Config3.MSAP bit.

The MSA vector registers use the same register numbers as the FPU
registers except with a different size (128bits). Since MSA depends on
Status.FR=1, these registers are inaccessible when Status.FR=0. These
registers are returned as a single native endian 128bit value, rather
than least significant half first with each 64-bit half native endian as
the kernel uses internally.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Gleb Natapov <gleb@kernel.org>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: linux-mips@linux-mips.org
Cc: kvm@vger.kernel.org
Cc: linux-api@vger.kernel.org
Cc: linux-doc@vger.kernel.org

+86 -3
+11 -1
Documentation/virtual/kvm/api.txt
··· 1981 1981 MIPS | KVM_REG_MIPS_COUNT_HZ | 64 1982 1982 MIPS | KVM_REG_MIPS_FPR_32(0..31) | 32 1983 1983 MIPS | KVM_REG_MIPS_FPR_64(0..31) | 64 1984 + MIPS | KVM_REG_MIPS_VEC_128(0..31) | 128 1984 1985 MIPS | KVM_REG_MIPS_FCR_IR | 32 1985 1986 MIPS | KVM_REG_MIPS_FCR_CSR | 32 1987 + MIPS | KVM_REG_MIPS_MSA_IR | 32 1988 + MIPS | KVM_REG_MIPS_MSA_CSR | 32 1986 1989 1987 1990 ARM registers are mapped using the lower 32 bits. The upper 16 of that 1988 1991 is the register group type, or coprocessor number: ··· 2043 2040 id bit patterns depending on the size of the register being accessed. They are 2044 2041 always accessed according to the current guest FPU mode (Status.FR and 2045 2042 Config5.FRE), i.e. as the guest would see them, and they become unpredictable 2046 - if the guest FPU mode is changed: 2043 + if the guest FPU mode is changed. MIPS SIMD Architecture (MSA) vector 2044 + registers (see KVM_REG_MIPS_VEC_128() above) have similar patterns as they 2045 + overlap the FPU registers: 2047 2046 0x7020 0000 0003 00 <0:3> <reg:5> (32-bit FPU registers) 2048 2047 0x7030 0000 0003 00 <0:3> <reg:5> (64-bit FPU registers) 2048 + 0x7040 0000 0003 00 <0:3> <reg:5> (128-bit MSA vector registers) 2049 2049 2050 2050 MIPS FPU control registers (see KVM_REG_MIPS_FCR_{IR,CSR} above) have the 2051 2051 following id bit patterns: 2052 2052 0x7020 0000 0003 01 <0:3> <reg:5> 2053 + 2054 + MIPS MSA control registers (see KVM_REG_MIPS_MSA_{IR,CSR} above) have the 2055 + following id bit patterns: 2056 + 0x7020 0000 0003 02 <0:3> <reg:5> 2053 2057 2054 2058 2055 2059 4.69 KVM_GET_ONE_REG
+10 -2
arch/mips/include/uapi/asm/kvm.h
··· 58 58 * 59 59 * Register set = 2: KVM specific registers (see definitions below). 60 60 * 61 - * Register set = 3: FPU registers (see definitions below). 61 + * Register set = 3: FPU / MSA registers (see definitions below). 62 62 * 63 63 * Other sets registers may be added in the future. Each set would 64 64 * have its own identifier in bits[31..16]. ··· 148 148 149 149 150 150 /* 151 - * KVM_REG_MIPS_FPU - Floating Point registers. 151 + * KVM_REG_MIPS_FPU - Floating Point and MIPS SIMD Architecture (MSA) registers. 152 152 * 153 153 * bits[15..8] - Register subset (see definitions below). 154 154 * bits[7..5] - Must be zero. ··· 157 157 158 158 #define KVM_REG_MIPS_FPR (KVM_REG_MIPS_FPU | 0x0000000000000000ULL) 159 159 #define KVM_REG_MIPS_FCR (KVM_REG_MIPS_FPU | 0x0000000000000100ULL) 160 + #define KVM_REG_MIPS_MSACR (KVM_REG_MIPS_FPU | 0x0000000000000200ULL) 160 161 161 162 /* 162 163 * KVM_REG_MIPS_FPR - Floating point / Vector registers. 163 164 */ 164 165 #define KVM_REG_MIPS_FPR_32(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U32 | (n)) 165 166 #define KVM_REG_MIPS_FPR_64(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U64 | (n)) 167 + #define KVM_REG_MIPS_VEC_128(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U128 | (n)) 166 168 167 169 /* 168 170 * KVM_REG_MIPS_FCR - Floating point control registers. 169 171 */ 170 172 #define KVM_REG_MIPS_FCR_IR (KVM_REG_MIPS_FCR | KVM_REG_SIZE_U32 | 0) 171 173 #define KVM_REG_MIPS_FCR_CSR (KVM_REG_MIPS_FCR | KVM_REG_SIZE_U32 | 31) 174 + 175 + /* 176 + * KVM_REG_MIPS_MSACR - MIPS SIMD Architecture (MSA) control registers. 177 + */ 178 + #define KVM_REG_MIPS_MSA_IR (KVM_REG_MIPS_MSACR | KVM_REG_SIZE_U32 | 0) 179 + #define KVM_REG_MIPS_MSA_CSR (KVM_REG_MIPS_MSACR | KVM_REG_SIZE_U32 | 1) 172 180 173 181 174 182 /*
+65
arch/mips/kvm/mips.c
··· 531 531 struct mips_fpu_struct *fpu = &vcpu->arch.fpu; 532 532 int ret; 533 533 s64 v; 534 + s64 vs[2]; 534 535 unsigned int idx; 535 536 536 537 switch (reg->id) { ··· 578 577 if (!kvm_mips_guest_has_fpu(&vcpu->arch)) 579 578 return -EINVAL; 580 579 v = fpu->fcr31; 580 + break; 581 + 582 + /* MIPS SIMD Architecture (MSA) registers */ 583 + case KVM_REG_MIPS_VEC_128(0) ... KVM_REG_MIPS_VEC_128(31): 584 + if (!kvm_mips_guest_has_msa(&vcpu->arch)) 585 + return -EINVAL; 586 + /* Can't access MSA registers in FR=0 mode */ 587 + if (!(kvm_read_c0_guest_status(cop0) & ST0_FR)) 588 + return -EINVAL; 589 + idx = reg->id - KVM_REG_MIPS_VEC_128(0); 590 + #ifdef CONFIG_CPU_LITTLE_ENDIAN 591 + /* least significant byte first */ 592 + vs[0] = get_fpr64(&fpu->fpr[idx], 0); 593 + vs[1] = get_fpr64(&fpu->fpr[idx], 1); 594 + #else 595 + /* most significant byte first */ 596 + vs[0] = get_fpr64(&fpu->fpr[idx], 1); 597 + vs[1] = get_fpr64(&fpu->fpr[idx], 0); 598 + #endif 599 + break; 600 + case KVM_REG_MIPS_MSA_IR: 601 + if (!kvm_mips_guest_has_msa(&vcpu->arch)) 602 + return -EINVAL; 603 + v = boot_cpu_data.msa_id; 604 + break; 605 + case KVM_REG_MIPS_MSA_CSR: 606 + if (!kvm_mips_guest_has_msa(&vcpu->arch)) 607 + return -EINVAL; 608 + v = fpu->msacsr; 581 609 break; 582 610 583 611 /* Co-processor 0 registers */ ··· 694 664 u32 v32 = (u32)v; 695 665 696 666 return put_user(v32, uaddr32); 667 + } else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U128) { 668 + void __user *uaddr = (void __user *)(long)reg->addr; 669 + 670 + return copy_to_user(uaddr, vs, 16); 697 671 } else { 698 672 return -EINVAL; 699 673 } ··· 709 675 struct mips_coproc *cop0 = vcpu->arch.cop0; 710 676 struct mips_fpu_struct *fpu = &vcpu->arch.fpu; 711 677 s64 v; 678 + s64 vs[2]; 712 679 unsigned int idx; 713 680 714 681 if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U64) { ··· 724 689 if (get_user(v32, uaddr32) != 0) 725 690 return -EFAULT; 726 691 v = (s64)v32; 692 + } else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U128) { 693 + void __user *uaddr = (void __user *)(long)reg->addr; 694 + 695 + return copy_from_user(vs, uaddr, 16); 727 696 } else { 728 697 return -EINVAL; 729 698 } ··· 779 740 if (!kvm_mips_guest_has_fpu(&vcpu->arch)) 780 741 return -EINVAL; 781 742 fpu->fcr31 = v; 743 + break; 744 + 745 + /* MIPS SIMD Architecture (MSA) registers */ 746 + case KVM_REG_MIPS_VEC_128(0) ... KVM_REG_MIPS_VEC_128(31): 747 + if (!kvm_mips_guest_has_msa(&vcpu->arch)) 748 + return -EINVAL; 749 + idx = reg->id - KVM_REG_MIPS_VEC_128(0); 750 + #ifdef CONFIG_CPU_LITTLE_ENDIAN 751 + /* least significant byte first */ 752 + set_fpr64(&fpu->fpr[idx], 0, vs[0]); 753 + set_fpr64(&fpu->fpr[idx], 1, vs[1]); 754 + #else 755 + /* most significant byte first */ 756 + set_fpr64(&fpu->fpr[idx], 1, vs[0]); 757 + set_fpr64(&fpu->fpr[idx], 0, vs[1]); 758 + #endif 759 + break; 760 + case KVM_REG_MIPS_MSA_IR: 761 + if (!kvm_mips_guest_has_msa(&vcpu->arch)) 762 + return -EINVAL; 763 + /* Read-only */ 764 + break; 765 + case KVM_REG_MIPS_MSA_CSR: 766 + if (!kvm_mips_guest_has_msa(&vcpu->arch)) 767 + return -EINVAL; 768 + fpu->msacsr = v; 782 769 break; 783 770 784 771 /* Co-processor 0 registers */