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.
Unified · Split
| @@ -1981,8 +1981,11 @@ registers, find a list below: · 1980 unmodified lines | ||
| 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: |
| @@ -2040,14 +2043,21 @@ MIPS FPU registers (see KVM_REG_MIPS_FPR_{32,64}() above) have the following · 51 unmodified lines | ||
| 2040 | 2043 | id bit patterns depending on the size of the register being accessed. They are |
| 2041 | 2044 | always accessed according to the current guest FPU mode (Status.FR and |
| 2042 | 2045 | 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: | |
| 2044 | 2049 | 0x7020 0000 0003 00 <0:3> <reg:5> (32-bit FPU registers) |
| 2045 | 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 | |
| 2047 | 2053 | MIPS FPU control registers (see KVM_REG_MIPS_FCR_{IR,CSR} above) have the |
| 2048 | 2054 | following id bit patterns: |
| 2049 | 2055 | 0x7020 0000 0003 01 <0:3> <reg:5> |
| 2050 | 2056 | |
| 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 | + | |
| 2051 | 2061 | |
| 2052 | 2062 | 4.69 KVM_GET_ONE_REG |
| 2053 | 2063 | |
| @@ -58,7 +58,7 @@ struct kvm_fpu { · 57 unmodified lines | ||
| 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,7 +148,7 @@ struct kvm_fpu { · 83 unmodified lines | ||
| 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,12 +157,14 @@ struct kvm_fpu { · 2 unmodified lines | ||
| 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. |
| @@ -170,6 +172,12 @@ struct kvm_fpu { · 1 unmodified line | ||
| 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) |
| 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 | 183 | * KVM MIPS specific structures and definitions |
| @@ -531,6 +531,7 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu, · 530 unmodified lines | ||
| 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) { |
| @@ -579,6 +580,35 @@ static int kvm_mips_get_reg(struct kvm_vcpu *vcpu, · 42 unmodified lines | ||
| 579 | 580 | v = fpu->fcr31; |
| 580 | 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 | 612 | /* Co-processor 0 registers */ |
| 583 | 613 | case KVM_REG_MIPS_CP0_INDEX: |
| 584 | 614 | 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 | ||
| 664 | 694 | u32 v32 = (u32)v; |
| 665 | 695 | |
| 666 | 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 | 701 | } else { |
| 668 | 702 | return -EINVAL; |
| 669 | 703 | } |
| @@ -675,6 +709,7 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu, · 5 unmodified lines | ||
| 675 | 709 | struct mips_coproc *cop0 = vcpu->arch.cop0; |
| 676 | 710 | struct mips_fpu_struct *fpu = &vcpu->arch.fpu; |
| 677 | 711 | s64 v; |
| 712 | + s64 vs[2]; | |
| 678 | 713 | unsigned int idx; |
| 679 | 714 | |
| 680 | 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, · 8 unmodified lines | ||
| 689 | 724 | if (get_user(v32, uaddr32) != 0) |
| 690 | 725 | return -EFAULT; |
| 691 | 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 | 731 | } else { |
| 693 | 732 | return -EINVAL; |
| 694 | 733 | } |
| @@ -742,6 +781,32 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu, · 47 unmodified lines | ||
| 742 | 781 | fpu->fcr31 = v; |
| 743 | 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 | 810 | /* Co-processor 0 registers */ |
| 746 | 811 | case KVM_REG_MIPS_CP0_INDEX: |
| 747 | 812 | kvm_write_c0_guest_index(cop0, v); |