History

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.

James Hogan committed 11 years ago

Commit ab86bd61 parent c2537ed3 files · +86 −3Browse files

Unified · Split

3 files
  1. Documentation/virtual/kvm/api.txt +11 −1
  2. arch/mips/include/uapi/asm/kvm.h +10 −2
  3. arch/mips/kvm/mips.c +65 −0
Documentation/virtual/kvm/api.txt+11−1
@@ -1981,8 +1981,11 @@ registers, find a list below: · 1980 unmodified lines
19811981 MIPS | KVM_REG_MIPS_COUNT_HZ | 64
19821982 MIPS | KVM_REG_MIPS_FPR_32(0..31) | 32
19831983 MIPS | KVM_REG_MIPS_FPR_64(0..31) | 64
1984+ MIPS | KVM_REG_MIPS_VEC_128(0..31) | 128
19841985 MIPS | KVM_REG_MIPS_FCR_IR | 32
19851986 MIPS | KVM_REG_MIPS_FCR_CSR | 32
1987+ MIPS | KVM_REG_MIPS_MSA_IR | 32
1988+ MIPS | KVM_REG_MIPS_MSA_CSR | 32
19861989
19871990 ARM registers are mapped using the lower 32 bits. The upper 16 of that
19881991 is 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 · 51 unmodified lines
20402043 id bit patterns depending on the size of the register being accessed. They are
20412044 always accessed according to the current guest FPU mode (Status.FR and
20422045 Config5.FRE), i.e. as the guest would see them, and they become unpredictable
2043−if the guest FPU mode is changed:
2046+if the guest FPU mode is changed. MIPS SIMD Architecture (MSA) vector
2047+registers (see KVM_REG_MIPS_VEC_128() above) have similar patterns as they
2048+overlap the FPU registers:
20442049 0x7020 0000 0003 00 <0:3> <reg:5> (32-bit FPU registers)
20452050 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)
20462052
20472053 MIPS FPU control registers (see KVM_REG_MIPS_FCR_{IR,CSR} above) have the
20482054 following id bit patterns:
20492055 0x7020 0000 0003 01 <0:3> <reg:5>
20502056
2057+MIPS MSA control registers (see KVM_REG_MIPS_MSA_{IR,CSR} above) have the
2058+following id bit patterns:
2059+ 0x7020 0000 0003 02 <0:3> <reg:5>
2060+
20512061
20522062 4.69 KVM_GET_ONE_REG
20532063
arch/mips/include/uapi/asm/kvm.h+10−2
@@ -58,7 +58,7 @@ struct kvm_fpu { · 57 unmodified lines
5858 *
5959 * Register set = 2: KVM specific registers (see definitions below).
6060 *
61− * Register set = 3: FPU registers (see definitions below).
61+ * Register set = 3: FPU / MSA registers (see definitions below).
6262 *
6363 * Other sets registers may be added in the future. Each set would
6464 * have its own identifier in bits[31..16].
@@ -148,7 +148,7 @@ struct kvm_fpu { · 83 unmodified lines
148148
149149
150150 /*
151− * KVM_REG_MIPS_FPU - Floating Point registers.
151+ * KVM_REG_MIPS_FPU - Floating Point and MIPS SIMD Architecture (MSA) registers.
152152 *
153153 * bits[15..8] - Register subset (see definitions below).
154154 * bits[7..5] - Must be zero.
@@ -157,12 +157,14 @@ struct kvm_fpu { · 2 unmodified lines
157157
158158 #define KVM_REG_MIPS_FPR (KVM_REG_MIPS_FPU | 0x0000000000000000ULL)
159159 #define KVM_REG_MIPS_FCR (KVM_REG_MIPS_FPU | 0x0000000000000100ULL)
160+#define KVM_REG_MIPS_MSACR (KVM_REG_MIPS_FPU | 0x0000000000000200ULL)
160161
161162 /*
162163 * KVM_REG_MIPS_FPR - Floating point / Vector registers.
163164 */
164165 #define KVM_REG_MIPS_FPR_32(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U32 | (n))
165166 #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))
166168
167169 /*
168170 * KVM_REG_MIPS_FCR - Floating point control registers.
@@ -170,6 +172,12 @@ struct kvm_fpu { · 1 unmodified line
170172 #define KVM_REG_MIPS_FCR_IR (KVM_REG_MIPS_FCR | KVM_REG_SIZE_U32 | 0)
171173 #define KVM_REG_MIPS_FCR_CSR (KVM_REG_MIPS_FCR | KVM_REG_SIZE_U32 | 31)
172174
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+
173181
174182 /*
175183 * KVM MIPS specific structures and definitions
arch/mips/kvm/mips.c+65−0
@@ -531,6 +531,7 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu, · 530 unmodified lines
531531 struct mips_fpu_struct *fpu = &vcpu->arch.fpu;
532532 int ret;
533533 s64 v;
534+ s64 vs[2];
534535 unsigned int idx;
535536
536537 switch (reg->id) {
@@ -579,6 +580,35 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu, · 42 unmodified lines
579580 v = fpu->fcr31;
580581 break;
581582
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+
582612 /* Co-processor 0 registers */
583613 case KVM_REG_MIPS_CP0_INDEX:
584614 v = (long)kvm_read_c0_guest_index(cop0);
@@ -664,6 +694,10 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu, · 79 unmodified lines
664694 u32 v32 = (u32)v;
665695
666696 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);
667701 } else {
668702 return -EINVAL;
669703 }
@@ -675,6 +709,7 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu, · 5 unmodified lines
675709 struct mips_coproc *cop0 = vcpu->arch.cop0;
676710 struct mips_fpu_struct *fpu = &vcpu->arch.fpu;
677711 s64 v;
712+ s64 vs[2];
678713 unsigned int idx;
679714
680715 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, · 8 unmodified lines
689724 if (get_user(v32, uaddr32) != 0)
690725 return -EFAULT;
691726 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);
692731 } else {
693732 return -EINVAL;
694733 }
@@ -742,6 +781,32 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu, · 47 unmodified lines
742781 fpu->fcr31 = v;
743782 break;
744783
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+
745810 /* Co-processor 0 registers */
746811 case KVM_REG_MIPS_CP0_INDEX:
747812 kvm_write_c0_guest_index(cop0, v);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t