Skip to contentSkip to conversation

KVM: PPC: Book3S HV: Correct tlbie usage

PATCH Applied Paul Mackerras 3 participants 4 messages Jul 8, 2013 – Jul 17, 2013

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/2 KVM: PPC: Book3S HV: Correct tlbie usage

This corrects the usage of the tlbie (TLB invalidate entry) instruction in HV KVM. The tlbie instruction changed between PPC970 and POWER7. On the PPC970, the bit to select large vs. small page is in the instruction, not in the RB register value. This changes the code to use the correct form on PPC970.

On POWER7 we were calculating the AVAL (Abbreviated Virtual Address, Lower) field of the RB value incorrectly for 64k pages. This fixes it.

Since we now have several cases to handle for the tlbie instruction, this factors out the code to do a sequence of tlbies into a new function, do_tlbies(), and calls that from the various places where the code was doing tlbie instructions inline. It also makes kvmppc_h_bulk_remove() use the same global_invalidates() function for determining whether to do local or global TLB invalidations as is used in other places, for consistency, and also to make sure that kvm->arch.need_tlb_flush gets updated properly.

---
 arch/powerpc/include/asm/kvm_book3s_64.h |   2 +-
 arch/powerpc/kvm/book3s_hv_rm_mmu.c      | 139 ++++++++++++++++++-------------
 2 files changed, 82 insertions(+), 59 deletions(-)
arch/powerpc/include/asm/kvm_book3s_64.h +1 -1
index 9c1ff33..dc6b84a 100644
@@ -100,7 +100,7 @@ static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
 			/* (masks depend on page size) */
 			rb |= 0x1000;		/* page encoding in LP field */
 			rb |= (va_low & 0x7f) << 16; /* 7b of VA in AVA/LP field */
-			rb |= (va_low & 0xfe);	/* AVAL field (P7 doesn't seem to care) */
+			rb |= ((va_low << 4) & 0xf0);	/* AVAL field (P7 doesn't seem to care) */
 		}
 	} else {
 		/* 4kB page */
arch/powerpc/kvm/book3s_hv_rm_mmu.c +81 -58

184 lines not on this page · raw message

Signature · 1 line
1.8.3.1
#1 lore raw

PATCH 2/2 KVM: PPC: Book3S HV: Allow negative offsets to real-mode hcall handlers

The table of offsets to real-mode hcall handlers in book3s_hv_rmhandlers.S can contain negative values, if some of the handlers end up before the table in the vmlinux binary. Thus we need to use a sign-extending load to read the values in the table rather than a zero-extending load. Without this, the host crashes when the guest does one of the hcalls with negative offsets, due to jumping to a bogus address.

---
 arch/powerpc/kvm/book3s_hv_rmhandlers.S | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/kvm/book3s_hv_rmhandlers.S +1 -1
index b02f91e..60dce5b 100644
@@ -1381,7 +1381,7 @@ hcall_try_real_mode:
 	cmpldi	r3,hcall_real_table_end - hcall_real_table
 	bge	guest_exit_cont
 	LOAD_REG_ADDR(r4, hcall_real_table)
-	lwzx	r3,r3,r4
+	lwax	r3,r3,r4
 	cmpwi	r3,0
 	beq	guest_exit_cont
 	add	r3,r3,r4
Signature · 1 line
1.8.3.1
#2 lore raw
In reply to Paul Mackerras
Quoted 18 lines · Paul Mackerras

This corrects the usage of the tlbie (TLB invalidate entry) instruction in HV KVM. The tlbie instruction changed between PPC970 and POWER7. On the PPC970, the bit to select large vs. small page is in the instruction, not in the RB register value. This changes the code to use the correct form on PPC970.

On POWER7 we were calculating the AVAL (Abbreviated Virtual Address, Lower) field of the RB value incorrectly for 64k pages. This fixes it.

Since we now have several cases to handle for the tlbie instruction, this factors out the code to do a sequence of tlbies into a new function, do_tlbies(), and calls that from the various places where the code was doing tlbie instructions inline. It also makes kvmppc_h_bulk_remove() use the same global_invalidates() function for determining whether to do local or global TLB invalidations as is used in other places, for consistency, and also to make sure that kvm->arch.need_tlb_flush gets updated properly.

Quoted 2 lines

Thanks, applied both to kvm-ppc-queue.

Alex

#3 lore raw
In reply to Paul Mackerras
Quoted 5 lines · Paul Mackerras

This corrects the usage of the tlbie (TLB invalidate entry) instruction in HV KVM. The tlbie instruction changed between PPC970 and POWER7. On the PPC970, the bit to select large vs. small page is in the instruction, not in the RB register value. This changes the code to use the correct form on PPC970.

I guess we need a similar fix for __tlbiel ?

Quoted 30 lines

On POWER7 we were calculating the AVAL (Abbreviated Virtual Address, Lower) field of the RB value incorrectly for 64k pages. This fixes it.

Since we now have several cases to handle for the tlbie instruction, this factors out the code to do a sequence of tlbies into a new function, do_tlbies(), and calls that from the various places where the code was doing tlbie instructions inline. It also makes kvmppc_h_bulk_remove() use the same global_invalidates() function for determining whether to do local or global TLB invalidations as is used in other places, for consistency, and also to make sure that kvm->arch.need_tlb_flush gets updated properly.

---
 arch/powerpc/include/asm/kvm_book3s_64.h |   2 +-
 arch/powerpc/kvm/book3s_hv_rm_mmu.c      | 139 ++++++++++++++++++-------------
 2 files changed, 82 insertions(+), 59 deletions(-)
arch/powerpc/include/asm/kvm_book3s_64.h +1 -1
index 9c1ff33..dc6b84a 100644
@@ -100,7 +100,7 @@ static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
 			/* (masks depend on page size) */
 			rb |= 0x1000;		/* page encoding in LP field */
 			rb |= (va_low & 0x7f) << 16; /* 7b of VA in AVA/LP field */
-			rb |= (va_low & 0xfe);	/* AVAL field (P7 doesn't seem to care) */
+			rb |= ((va_low << 4) & 0xf0);	/* AVAL field
Quoted 1 line

(P7 doesn't seem to care) */

Can you explain this more ? Why shift by 4 ? and what about the three bits ('e' part of 0xfe) ?

arch/powerpc/kvm/book3s_hv_rm_mmu.c static inline int try_lock_tlbie(unsigned int *lock) · line 387

Quoted 11 lines
arch/powerpc/include/asm/kvm_book3s_64.h +0 -0
 		}
 	} else {
 		/* 4kB page */
arch/powerpc/kvm/book3s_hv_rm_mmu.c +0 -0
index 6dcbb49..105b00f 100644
@@ -385,6 +385,80 @@ static inline int try_lock_tlbie(unsigned int *lock)
 	return old == 0;
 }
 

-aneesh