@@ -71,6 +71,11 @@
#define CAUSEB_DC 27
#define CAUSEF_DC (_ULCAST_(1) << 27)
+/* KVM supports MIPS32R2 and beyond, so ASID_MASK is always 0xFF.
+ * This is to work around the bug introduced by commit d532f3d26716a39dfd4b88d687bd344fbe77e390
+ */
+#define KVM_ASID_MASK(x) ((x) & 0xFF)
+
struct kvm;
struct kvm_run;
struct kvm_vcpu;
@@ -525,16 +525,16 @@ kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc, uint32_t cause,
printk("MTCz, cop0->reg[EBASE]: %#lx\n",
kvm_read_c0_guest_ebase(cop0));
} else if (rd == MIPS_CP0_TLB_HI && sel == 0) {
- uint32_t nasid = ASID_MASK(vcpu->arch.gprs[rt]);
+ uint32_t nasid = KVM_ASID_MASK(vcpu->arch.gprs[rt]);
if ((KSEGX(vcpu->arch.gprs[rt]) != CKSEG0)
&&
- (ASID_MASK(kvm_read_c0_guest_entryhi(cop0))
+ (KVM_ASID_MASK(kvm_read_c0_guest_entryhi(cop0))
!= nasid)) {
kvm_debug
("MTCz, change ASID from %#lx to %#lx\n",
- ASID_MASK(kvm_read_c0_guest_entryhi(cop0)),
- ASID_MASK(vcpu->arch.gprs[rt]));
+ KVM_ASID_MASK(kvm_read_c0_guest_entryhi(cop0)),
+ KVM_ASID_MASK(vcpu->arch.gprs[rt]));
/* Blow away the shadow host TLBs */
kvm_mips_flush_host_tlb(1);
@@ -986,7 +986,7 @@ kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc, uint32_t cause,
* resulting handler will do the right thing
*/
index = kvm_mips_guest_tlb_lookup(vcpu, (va & VPN2_MASK) |
- ASID_MASK(kvm_read_c0_guest_entryhi(cop0)));
+ KVM_ASID_MASK(kvm_read_c0_guest_entryhi(cop0)));
if (index < 0) {
vcpu->arch.host_cp0_entryhi = (va & VPN2_MASK);
@@ -1151,7 +1151,7 @@ kvm_mips_emulate_tlbmiss_ld(unsigned long cause, uint32_t *opc,
struct kvm_vcpu_arch *arch = &vcpu->arch;
enum emulation_result er = EMULATE_DONE;
unsigned long entryhi = (vcpu->arch. host_cp0_badvaddr & VPN2_MASK) |
- ASID_MASK(kvm_read_c0_guest_entryhi(cop0));
+ KVM_ASID_MASK(kvm_read_c0_guest_entryhi(cop0));
if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
/* save old pc */
@@ -1198,7 +1198,7 @@ kvm_mips_emulate_tlbinv_ld(unsigned long cause, uint32_t *opc,
enum emulation_result er = EMULATE_DONE;
unsigned long entryhi =
(vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
- ASID_MASK(kvm_read_c0_guest_entryhi(cop0));
+ KVM_ASID_MASK(kvm_read_c0_guest_entryhi(cop0));
if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
/* save old pc */
@@ -1243,7 +1243,7 @@ kvm_mips_emulate_tlbmiss_st(unsigned long cause, uint32_t *opc,
struct kvm_vcpu_arch *arch = &vcpu->arch;
enum emulation_result er = EMULATE_DONE;
unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
- ASID_MASK(kvm_read_c0_guest_entryhi(cop0));
+ KVM_ASID_MASK(kvm_read_c0_guest_entryhi(cop0));
if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
/* save old pc */
@@ -1287,7 +1287,7 @@ kvm_mips_emulate_tlbinv_st(unsigned long cause, uint32_t *opc,
struct kvm_vcpu_arch *arch = &vcpu->arch;
enum emulation_result er = EMULATE_DONE;
unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
- ASID_MASK(kvm_read_c0_guest_entryhi(cop0));
+ KVM_ASID_MASK(kvm_read_c0_guest_entryhi(cop0));
if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
/* save old pc */
@@ -1356,7 +1356,7 @@ kvm_mips_emulate_tlbmod(unsigned long cause, uint32_t *opc,
{
struct mips_coproc *cop0 = vcpu->arch.cop0;
unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
- ASID_MASK(kvm_read_c0_guest_entryhi(cop0));
+ KVM_ASID_MASK(kvm_read_c0_guest_entryhi(cop0));
struct kvm_vcpu_arch *arch = &vcpu->arch;
enum emulation_result er = EMULATE_DONE;
@@ -1783,7 +1783,7 @@ kvm_mips_handle_tlbmiss(unsigned long cause, uint32_t *opc,
*/
index = kvm_mips_guest_tlb_lookup(vcpu,
(va & VPN2_MASK) |
- ASID_MASK(kvm_read_c0_guest_entryhi
+ KVM_ASID_MASK(kvm_read_c0_guest_entryhi
(vcpu->arch.cop0)));
if (index < 0) {
if (exccode == T_TLB_LD_MISS) {
@@ -54,13 +54,13 @@ EXPORT_SYMBOL(kvm_mips_is_error_pfn);
uint32_t kvm_mips_get_kernel_asid(struct kvm_vcpu *vcpu)
{
- return ASID_MASK(vcpu->arch.guest_kernel_asid[smp_processor_id()]);
+ return KVM_ASID_MASK(vcpu->arch.guest_kernel_asid[smp_processor_id()]);
}
uint32_t kvm_mips_get_user_asid(struct kvm_vcpu *vcpu)
{
- return ASID_MASK(vcpu->arch.guest_user_asid[smp_processor_id()]);
+ return KVM_ASID_MASK(vcpu->arch.guest_user_asid[smp_processor_id()]);
}
inline uint32_t kvm_mips_get_commpage_asid (struct kvm_vcpu *vcpu)
@@ -87,7 +87,7 @@ void kvm_mips_dump_host_tlbs(void)
old_pagemask = read_c0_pagemask();
printk("HOST TLBs:\n");
- printk("ASID: %#lx\n", ASID_MASK(read_c0_entryhi()));
+ printk("ASID: %#lx\n", KVM_ASID_MASK(read_c0_entryhi()));
for (i = 0; i < current_cpu_data.tlbsize; i++) {
write_c0_index(i);
@@ -446,7 +446,7 @@ int kvm_mips_guest_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long entryhi)
for (i = 0; i < KVM_MIPS_GUEST_TLB_SIZE; i++) {
if (((TLB_VPN2(tlb[i]) & ~tlb[i].tlb_mask) == ((entryhi & VPN2_MASK) & ~tlb[i].tlb_mask)) &&
- (TLB_IS_GLOBAL(tlb[i]) || (TLB_ASID(tlb[i]) == ASID_MASK(entryhi)))) {
+ (TLB_IS_GLOBAL(tlb[i]) || (TLB_ASID(tlb[i]) == KVM_ASID_MASK(entryhi)))) {
index = i;
break;
}
@@ -539,7 +539,7 @@ int kvm_mips_host_tlb_inv(struct kvm_vcpu *vcpu, unsigned long va)
#ifdef DEBUG
if (idx > 0) {
kvm_debug("%s: Invalidated entryhi %#lx @ idx %d\n", __func__,
- (va & VPN2_MASK) | (vcpu->arch.asid_map[va & ASID_MASK] & ASID_MASK), idx);
+ (va & VPN2_MASK) | (vcpu->arch.asid_map[va & KVM_ASID_MASK] & KVM_ASID_MASK), idx);
}
#endif
@@ -644,7 +644,7 @@ kvm_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu,
{
unsigned long asid = asid_cache(cpu);
- if (!(ASID_MASK(ASID_INC(asid)))) {
+ if (!KVM_ASID_MASK((asid = ASID_INC(asid)))) {
if (cpu_has_vtag_icache) {
flush_icache_all();
}
@@ -822,7 +822,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
if (!newasid) {
/* If we preempted while the guest was executing, then reload the pre-empted ASID */
if (current->flags & PF_VCPU) {
- write_c0_entryhi(ASID_MASK(vcpu->arch.preempt_entryhi));
+ write_c0_entryhi(KVM_ASID_MASK(vcpu->arch.preempt_entryhi));
ehb();
}
} else {
@@ -834,10 +834,10 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
*/
if (current->flags & PF_VCPU) {
if (KVM_GUEST_KERNEL_MODE(vcpu))
- write_c0_entryhi(ASID_MASK(vcpu->arch.
+ write_c0_entryhi(KVM_ASID_MASK(vcpu->arch.
guest_kernel_asid[cpu]));
else
- write_c0_entryhi(ASID_MASK(vcpu->arch.
+ write_c0_entryhi(KVM_ASID_MASK(vcpu->arch.
guest_user_asid[cpu]));
ehb();
}
@@ -897,7 +897,7 @@ uint32_t kvm_get_inst(uint32_t *opc, struct kvm_vcpu *vcpu)
kvm_mips_guest_tlb_lookup(vcpu,
((unsigned long) opc & VPN2_MASK)
|
- ASID_MASK(kvm_read_c0_guest_entryhi(cop0)));
+ KVM_ASID_MASK(kvm_read_c0_guest_entryhi(cop0)));
if (index < 0) {
kvm_err
("%s: get_user_failed for %p, vcpu: %p, ASID: %#lx\n",
The ASID paramters have default values which are then patched @ runtime as part of the TLB initialization. The fixup does not work since KVM is a kernel module and we end up with the default mask of 0xfc0 instead of the standard ASID mask of 0xff for MIPS32R2 processors. I've posted the issue on the MIPS mailing list and until a solution is found, For now define KVM_ASID_MASK as 0xFF to fix this issue up for Linux 3.10. Signed-off-by: Sanjay Lal <sanjayl@kymasys.com> --- arch/mips/include/asm/kvm_host.h | 5 +++++ arch/mips/kvm/kvm_mips_emul.c | 22 +++++++++++----------- arch/mips/kvm/kvm_tlb.c | 20 ++++++++++---------- 3 files changed, 26 insertions(+), 21 deletions(-)