aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Hogan <james.hogan@imgtec.com>2014-12-02 10:48:24 -0500
committerJames Hogan <james.hogan@imgtec.com>2015-03-27 17:25:21 -0400
commitab86bd600400357ffa0dfdb1797f587476d01352 (patch)
tree265d24436dc03ac0e1ff2fa3a1652feb3346b6ff
parentc2537ed9fb8e17d713e5e67fcede047699d25814 (diff)
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
-rw-r--r--Documentation/virtual/kvm/api.txt12
-rw-r--r--arch/mips/include/uapi/asm/kvm.h12
-rw-r--r--arch/mips/kvm/mips.c65
3 files changed, 86 insertions, 3 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index a1e9bfa5fe9e..62809871814b 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1981,8 +1981,11 @@ registers, find a list below:
1981 MIPS | KVM_REG_MIPS_COUNT_HZ | 64 1981 MIPS | KVM_REG_MIPS_COUNT_HZ | 64
1982 MIPS | KVM_REG_MIPS_FPR_32(0..31) | 32 1982 MIPS | KVM_REG_MIPS_FPR_32(0..31) | 32
1983 MIPS | KVM_REG_MIPS_FPR_64(0..31) | 64 1983 MIPS | KVM_REG_MIPS_FPR_64(0..31) | 64
1984 MIPS | KVM_REG_MIPS_VEC_128(0..31) | 128
1984 MIPS | KVM_REG_MIPS_FCR_IR | 32 1985 MIPS | KVM_REG_MIPS_FCR_IR | 32
1985 MIPS | KVM_REG_MIPS_FCR_CSR | 32 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
1987ARM registers are mapped using the lower 32 bits. The upper 16 of that 1990ARM registers are mapped using the lower 32 bits. The upper 16 of that
1988is the register group type, or coprocessor number: 1991is the register group type, or coprocessor number:
@@ -2040,14 +2043,21 @@ MIPS FPU registers (see KVM_REG_MIPS_FPR_{32,64}() above) have the following
2040id bit patterns depending on the size of the register being accessed. They are 2043id bit patterns depending on the size of the register being accessed. They are
2041always accessed according to the current guest FPU mode (Status.FR and 2044always accessed according to the current guest FPU mode (Status.FR and
2042Config5.FRE), i.e. as the guest would see them, and they become unpredictable 2045Config5.FRE), i.e. as the guest would see them, and they become unpredictable
2043if the guest FPU mode is changed: 2046if the guest FPU mode is changed. MIPS SIMD Architecture (MSA) vector
2047registers (see KVM_REG_MIPS_VEC_128() above) have similar patterns as they
2048overlap the FPU registers:
2044 0x7020 0000 0003 00 <0:3> <reg:5> (32-bit FPU registers) 2049 0x7020 0000 0003 00 <0:3> <reg:5> (32-bit FPU registers)
2045 0x7030 0000 0003 00 <0:3> <reg:5> (64-bit FPU registers) 2050 0x7030 0000 0003 00 <0:3> <reg:5> (64-bit FPU registers)
2051 0x7040 0000 0003 00 <0:3> <reg:5> (128-bit MSA vector registers)
2046 2052
2047MIPS FPU control registers (see KVM_REG_MIPS_FCR_{IR,CSR} above) have the 2053MIPS FPU control registers (see KVM_REG_MIPS_FCR_{IR,CSR} above) have the
2048following id bit patterns: 2054following id bit patterns:
2049 0x7020 0000 0003 01 <0:3> <reg:5> 2055 0x7020 0000 0003 01 <0:3> <reg:5>
2050 2056
2057MIPS MSA control registers (see KVM_REG_MIPS_MSA_{IR,CSR} above) have the
2058following id bit patterns:
2059 0x7020 0000 0003 02 <0:3> <reg:5>
2060
2051 2061
20524.69 KVM_GET_ONE_REG 20624.69 KVM_GET_ONE_REG
2053 2063
diff --git a/arch/mips/include/uapi/asm/kvm.h b/arch/mips/include/uapi/asm/kvm.h
index 401e6a6f8bb8..6985eb59b085 100644
--- a/arch/mips/include/uapi/asm/kvm.h
+++ b/arch/mips/include/uapi/asm/kvm.h
@@ -58,7 +58,7 @@ struct kvm_fpu {
58 * 58 *
59 * Register set = 2: KVM specific registers (see definitions below). 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 * Other sets registers may be added in the future. Each set would 63 * Other sets registers may be added in the future. Each set would
64 * have its own identifier in bits[31..16]. 64 * have its own identifier in bits[31..16].
@@ -148,7 +148,7 @@ struct kvm_fpu {
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 * bits[15..8] - Register subset (see definitions below). 153 * bits[15..8] - Register subset (see definitions below).
154 * bits[7..5] - Must be zero. 154 * bits[7..5] - Must be zero.
@@ -157,12 +157,14 @@ struct kvm_fpu {
157 157
158#define KVM_REG_MIPS_FPR (KVM_REG_MIPS_FPU | 0x0000000000000000ULL) 158#define KVM_REG_MIPS_FPR (KVM_REG_MIPS_FPU | 0x0000000000000000ULL)
159#define KVM_REG_MIPS_FCR (KVM_REG_MIPS_FPU | 0x0000000000000100ULL) 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 * KVM_REG_MIPS_FPR - Floating point / Vector registers. 163 * KVM_REG_MIPS_FPR - Floating point / Vector registers.
163 */ 164 */
164#define KVM_REG_MIPS_FPR_32(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U32 | (n)) 165#define KVM_REG_MIPS_FPR_32(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U32 | (n))
165#define KVM_REG_MIPS_FPR_64(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U64 | (n)) 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 * KVM_REG_MIPS_FCR - Floating point control registers. 170 * KVM_REG_MIPS_FCR - Floating point control registers.
@@ -170,6 +172,12 @@ struct kvm_fpu {
170#define KVM_REG_MIPS_FCR_IR (KVM_REG_MIPS_FCR | KVM_REG_SIZE_U32 | 0) 172#define KVM_REG_MIPS_FCR_IR (KVM_REG_MIPS_FCR | KVM_REG_SIZE_U32 | 0)
171#define KVM_REG_MIPS_FCR_CSR (KVM_REG_MIPS_FCR | KVM_REG_SIZE_U32 | 31) 173#define KVM_REG_MIPS_FCR_CSR (KVM_REG_MIPS_FCR | KVM_REG_SIZE_U32 | 31)
172 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)
180
173 181
174/* 182/*
175 * KVM MIPS specific structures and definitions 183 * KVM MIPS specific structures and definitions
diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
index e02c7e5a12ff..35d3146895f1 100644
--- a/arch/mips/kvm/mips.c
+++ b/arch/mips/kvm/mips.c
@@ -531,6 +531,7 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu,
531 struct mips_fpu_struct *fpu = &vcpu->arch.fpu; 531 struct mips_fpu_struct *fpu = &vcpu->arch.fpu;
532 int ret; 532 int ret;
533 s64 v; 533 s64 v;
534 s64 vs[2];
534 unsigned int idx; 535 unsigned int idx;
535 536
536 switch (reg->id) { 537 switch (reg->id) {
@@ -579,6 +580,35 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu,
579 v = fpu->fcr31; 580 v = fpu->fcr31;
580 break; 581 break;
581 582
583 /* MIPS SIMD Architecture (MSA) registers */
584 case KVM_REG_MIPS_VEC_128(0) ... KVM_REG_MIPS_VEC_128(31):
585 if (!kvm_mips_guest_has_msa(&vcpu->arch))
586 return -EINVAL;
587 /* Can't access MSA registers in FR=0 mode */
588 if (!(kvm_read_c0_guest_status(cop0) & ST0_FR))
589 return -EINVAL;
590 idx = reg->id - KVM_REG_MIPS_VEC_128(0);
591#ifdef CONFIG_CPU_LITTLE_ENDIAN
592 /* least significant byte first */
593 vs[0] = get_fpr64(&fpu->fpr[idx], 0);
594 vs[1] = get_fpr64(&fpu->fpr[idx], 1);
595#else
596 /* most significant byte first */
597 vs[0] = get_fpr64(&fpu->fpr[idx], 1);
598 vs[1] = get_fpr64(&fpu->fpr[idx], 0);
599#endif
600 break;
601 case KVM_REG_MIPS_MSA_IR:
602 if (!kvm_mips_guest_has_msa(&vcpu->arch))
603 return -EINVAL;
604 v = boot_cpu_data.msa_id;
605 break;
606 case KVM_REG_MIPS_MSA_CSR:
607 if (!kvm_mips_guest_has_msa(&vcpu->arch))
608 return -EINVAL;
609 v = fpu->msacsr;
610 break;
611
582 /* Co-processor 0 registers */ 612 /* Co-processor 0 registers */
583 case KVM_REG_MIPS_CP0_INDEX: 613 case KVM_REG_MIPS_CP0_INDEX:
584 v = (long)kvm_read_c0_guest_index(cop0); 614 v = (long)kvm_read_c0_guest_index(cop0);
@@ -664,6 +694,10 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu,
664 u32 v32 = (u32)v; 694 u32 v32 = (u32)v;
665 695
666 return put_user(v32, uaddr32); 696 return put_user(v32, uaddr32);
697 } else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U128) {
698 void __user *uaddr = (void __user *)(long)reg->addr;
699
700 return copy_to_user(uaddr, vs, 16);
667 } else { 701 } else {
668 return -EINVAL; 702 return -EINVAL;
669 } 703 }
@@ -675,6 +709,7 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu,
675 struct mips_coproc *cop0 = vcpu->arch.cop0; 709 struct mips_coproc *cop0 = vcpu->arch.cop0;
676 struct mips_fpu_struct *fpu = &vcpu->arch.fpu; 710 struct mips_fpu_struct *fpu = &vcpu->arch.fpu;
677 s64 v; 711 s64 v;
712 s64 vs[2];
678 unsigned int idx; 713 unsigned int idx;
679 714
680 if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U64) { 715 if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U64) {
@@ -689,6 +724,10 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu,
689 if (get_user(v32, uaddr32) != 0) 724 if (get_user(v32, uaddr32) != 0)
690 return -EFAULT; 725 return -EFAULT;
691 v = (s64)v32; 726 v = (s64)v32;
727 } else if ((reg->id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U128) {
728 void __user *uaddr = (void __user *)(long)reg->addr;
729
730 return copy_from_user(vs, uaddr, 16);
692 } else { 731 } else {
693 return -EINVAL; 732 return -EINVAL;
694 } 733 }
@@ -742,6 +781,32 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu,
742 fpu->fcr31 = v; 781 fpu->fcr31 = v;
743 break; 782 break;
744 783
784 /* MIPS SIMD Architecture (MSA) registers */
785 case KVM_REG_MIPS_VEC_128(0) ... KVM_REG_MIPS_VEC_128(31):
786 if (!kvm_mips_guest_has_msa(&vcpu->arch))
787 return -EINVAL;
788 idx = reg->id - KVM_REG_MIPS_VEC_128(0);
789#ifdef CONFIG_CPU_LITTLE_ENDIAN
790 /* least significant byte first */
791 set_fpr64(&fpu->fpr[idx], 0, vs[0]);
792 set_fpr64(&fpu->fpr[idx], 1, vs[1]);
793#else
794 /* most significant byte first */
795 set_fpr64(&fpu->fpr[idx], 1, vs[0]);
796 set_fpr64(&fpu->fpr[idx], 0, vs[1]);
797#endif
798 break;
799 case KVM_REG_MIPS_MSA_IR:
800 if (!kvm_mips_guest_has_msa(&vcpu->arch))
801 return -EINVAL;
802 /* Read-only */
803 break;
804 case KVM_REG_MIPS_MSA_CSR:
805 if (!kvm_mips_guest_has_msa(&vcpu->arch))
806 return -EINVAL;
807 fpu->msacsr = v;
808 break;
809
745 /* Co-processor 0 registers */ 810 /* Co-processor 0 registers */
746 case KVM_REG_MIPS_CP0_INDEX: 811 case KVM_REG_MIPS_CP0_INDEX:
747 kvm_write_c0_guest_index(cop0, v); 812 kvm_write_c0_guest_index(cop0, v);