diff options
author | James Hogan <james.hogan@imgtec.com> | 2016-11-14 23:59:27 +0000 |
---|---|---|
committer | James Hogan <james.hogan@imgtec.com> | 2017-02-03 15:21:30 +0000 |
commit | 7801bbe1bd907a8f8b136fc184583260508febb6 (patch) | |
tree | 657af8c96b0d433c9fe1297756fa2c80bfddb321 /arch/mips/kvm/trap_emul.c | |
parent | 654229a02456a9af372defb13d1911345360074d (diff) | |
download | blackbird-op-linux-7801bbe1bd907a8f8b136fc184583260508febb6.tar.gz blackbird-op-linux-7801bbe1bd907a8f8b136fc184583260508febb6.zip |
KVM: MIPS/T&E: Implement CP0_EBase register
The CP0_EBase register is a standard feature of MIPS32r2, so we should
always have been implementing it properly. However the register value
was ignored and wasn't exposed to userland.
Fix the emulation of exceptions and interrupts to use the value stored
in guest CP0_EBase, and fix the masks so that the top 3 bits (rather
than the standard 2) are fixed, so that it is always in the guest KSeg0
segment.
Also add CP0_EBASE to the KVM one_reg interface so it can be accessed by
userland, also allowing the CPU number field to be written (which isn't
permitted by the guest).
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
Diffstat (limited to 'arch/mips/kvm/trap_emul.c')
-rw-r--r-- | arch/mips/kvm/trap_emul.c | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/arch/mips/kvm/trap_emul.c b/arch/mips/kvm/trap_emul.c index 08327de4323a..80a681f42bf5 100644 --- a/arch/mips/kvm/trap_emul.c +++ b/arch/mips/kvm/trap_emul.c @@ -653,6 +653,7 @@ static u64 kvm_trap_emul_get_one_regs[] = { KVM_REG_MIPS_CP0_CAUSE, KVM_REG_MIPS_CP0_EPC, KVM_REG_MIPS_CP0_PRID, + KVM_REG_MIPS_CP0_EBASE, KVM_REG_MIPS_CP0_CONFIG, KVM_REG_MIPS_CP0_CONFIG1, KVM_REG_MIPS_CP0_CONFIG2, @@ -735,6 +736,9 @@ static int kvm_trap_emul_get_one_reg(struct kvm_vcpu *vcpu, case KVM_REG_MIPS_CP0_PRID: *v = (long)kvm_read_c0_guest_prid(cop0); break; + case KVM_REG_MIPS_CP0_EBASE: + *v = (long)kvm_read_c0_guest_ebase(cop0); + break; case KVM_REG_MIPS_CP0_CONFIG: *v = (long)kvm_read_c0_guest_config(cop0); break; @@ -837,6 +841,14 @@ static int kvm_trap_emul_set_one_reg(struct kvm_vcpu *vcpu, case KVM_REG_MIPS_CP0_PRID: kvm_write_c0_guest_prid(cop0, v); break; + case KVM_REG_MIPS_CP0_EBASE: + /* + * Allow core number to be written, but the exception base must + * remain in guest KSeg0. + */ + kvm_change_c0_guest_ebase(cop0, 0x1ffff000 | MIPS_EBASE_CPUNUM, + v); + break; case KVM_REG_MIPS_CP0_COUNT: kvm_mips_write_count(vcpu, v); break; |