MIPS: KVM: Allow ULRI to restrict UserLocal register
authorJames Hogan <james.hogan@imgtec.com>
Wed, 15 Jun 2016 18:29:54 +0000 (19:29 +0100)
committerPaolo Bonzini <pbonzini@redhat.com>
Wed, 15 Jun 2016 21:58:35 +0000 (23:58 +0200)
The ULRI bit in Config3 specifies whether the UserLocal register is
implemented, but it is assumed to always be set. Now that the Config
registers can be modified by userland, allow Config3.ULRI to be cleared
and check ULRI before allowing the corresponding bit to be set in
HWREna.

In fact any HWREna bits corresponding to unimplemented RDHWR registers
should read as zero and be ignored on write, so we actually prevent
other unimplemented bits being set too.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Krčmář <rkrcmar@redhat.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-mips@linux-mips.org
Cc: kvm@vger.kernel.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/mips/kvm/emulate.c

index 892f36f56d32e60975ba2b0d97af6f7a50e1f4c6..84f435bf74bd38aca6f5ff5b77a4ed37b6aa0c60 100644 (file)
@@ -921,8 +921,8 @@ unsigned int kvm_mips_config1_wrmask(struct kvm_vcpu *vcpu)
  */
 unsigned int kvm_mips_config3_wrmask(struct kvm_vcpu *vcpu)
 {
-       /* Config4 is optional */
-       unsigned int mask = MIPS_CONF_M;
+       /* Config4 and ULRI are optional */
+       unsigned int mask = MIPS_CONF_M | MIPS_CONF3_ULRI;
 
        /* Permit MSA to be present if MSA is supported */
        if (kvm_mips_guest_can_have_msa(&vcpu->arch))
@@ -1229,6 +1229,16 @@ enum emulation_result kvm_mips_emulate_CP0(union mips_instruction inst,
                                        else
                                                kvm_mips_count_enable_cause(vcpu);
                                }
+                       } else if ((rd == MIPS_CP0_HWRENA) && (sel == 0)) {
+                               u32 mask = MIPS_HWRENA_CPUNUM |
+                                          MIPS_HWRENA_SYNCISTEP |
+                                          MIPS_HWRENA_CC |
+                                          MIPS_HWRENA_CCRES;
+
+                               if (kvm_read_c0_guest_config3(cop0) &
+                                   MIPS_CONF3_ULRI)
+                                       mask |= MIPS_HWRENA_ULR;
+                               cop0->reg[rd][sel] = vcpu->arch.gprs[rt] & mask;
                        } else {
                                cop0->reg[rd][sel] = vcpu->arch.gprs[rt];
 #ifdef CONFIG_KVM_MIPS_DYN_TRANS