RE: [PATCH 1/2] KVM: PPC: e500mc: Add support for single threaded vcpus on e6500 core

2014-09-01 Thread mihai.cara...@freescale.com
I abandon this patch, I will send a v2 with a minor fix for 85xx.

Mike

 -Original Message-
 From: Mihai Caraman [mailto:mihai.cara...@freescale.com]
 Sent: Friday, August 29, 2014 8:04 PM
 To: kvm-...@vger.kernel.org
 Cc: kvm@vger.kernel.org; Caraman Mihai Claudiu-B02008
 Subject: [PATCH 1/2] KVM: PPC: e500mc: Add support for single threaded
 vcpus on e6500 core
 
 ePAPR represents hardware threads as cpu node properties in device tree.
 So with existing QEMU, hardware threads are simply exposed as vcpus with
 one hardware thread.
 
 The e6500 core shares TLBs between hardware threads. Without tlb write
 conditional instruction, the Linux kernel uses per core mechanisms to
 protect against duplicate TLB entries.
 
 The guest is unable to detect real siblings threads, so it can't use a
 TLB protection mechanism. An alternative solution is to use the
 hypervisor
 to allocate different lpids to guest's vcpus running simultaneous on real
 siblings threads. On systems with two threads per core this patch halves
 the size of the lpid pool that the allocator sees and use two lpids per
 VM.
 Use even numbers to speedup vcpu lpid computation with consecutive lpids
 per VM: vm1 will use lpids 2 and 3, vm2 lpids 4 and 5, and so on.
 
 Signed-off-by: Mihai Caraman mihai.cara...@freescale.com
 ---
  arch/powerpc/include/asm/kvm_booke.h |  5 +++-
  arch/powerpc/kvm/e500.h  | 20 
  arch/powerpc/kvm/e500_mmu_host.c | 16 ++---
  arch/powerpc/kvm/e500mc.c| 46 ++
 --
  4 files changed, 64 insertions(+), 23 deletions(-)
 
 diff --git a/arch/powerpc/include/asm/kvm_booke.h
 b/arch/powerpc/include/asm/kvm_booke.h
 index f7aa5cc..630134d 100644
 --- a/arch/powerpc/include/asm/kvm_booke.h
 +++ b/arch/powerpc/include/asm/kvm_booke.h
 @@ -23,7 +23,10 @@
  #include linux/types.h
  #include linux/kvm_host.h
 
 -/* LPIDs we support with this build -- runtime limit may be lower */
 +/*
 + * Number of available lpids. Only the low-order 6 bits of LPID rgister
 are
 + * implemented on e500mc+ cores.
 + */
  #define KVMPPC_NR_LPIDS64
 
  #define KVMPPC_INST_EHPRIV   0x7c00021c
 diff --git a/arch/powerpc/kvm/e500.h b/arch/powerpc/kvm/e500.h
 index a326178..7b74453 100644
 --- a/arch/powerpc/kvm/e500.h
 +++ b/arch/powerpc/kvm/e500.h
 @@ -22,6 +22,7 @@
  #include linux/kvm_host.h
  #include asm/mmu-book3e.h
  #include asm/tlb.h
 +#include asm/cputhreads.h
 
  enum vcpu_ftr {
   VCPU_FTR_MMU_V2
 @@ -289,6 +290,25 @@ void kvmppc_e500_tlbil_all(struct kvmppc_vcpu_e500
 *vcpu_e500);
  #define kvmppc_e500_get_tlb_stid(vcpu, gtlbe)   get_tlb_tid(gtlbe)
  #define get_tlbmiss_tid(vcpu)   get_cur_pid(vcpu)
  #define get_tlb_sts(gtlbe)  (gtlbe-mas1  MAS1_TS)
 +
 +/*
 + * This functios should be called with preemtion disabled
 + * and the returned value is valid only in that context
 + */
 +static inline int get_thread_specific_lpid(int vm_lpid)
 +{
 + int vcpu_lpid = vm_lpid;
 +
 + if (threads_per_core == 2)
 + vcpu_lpid |= smp_processor_id()  1;
 +
 + return vcpu_lpid;
 +}
 +
 +static inline int get_lpid(struct kvm_vcpu *vcpu)
 +{
 + return get_thread_specific_lpid(vcpu-kvm-arch.lpid);
 +}
  #else
  unsigned int kvmppc_e500_get_tlb_stid(struct kvm_vcpu *vcpu,
 struct kvm_book3e_206_tlb_entry *gtlbe);
 diff --git a/arch/powerpc/kvm/e500_mmu_host.c
 b/arch/powerpc/kvm/e500_mmu_host.c
 index 08f14bb..5759608 100644
 --- a/arch/powerpc/kvm/e500_mmu_host.c
 +++ b/arch/powerpc/kvm/e500_mmu_host.c
 @@ -69,7 +69,8 @@ static inline u32 e500_shadow_mas3_attrib(u32 mas3, int
 usermode)
   * writing shadow tlb entry to host TLB
   */
  static inline void __write_host_tlbe(struct kvm_book3e_206_tlb_entry
 *stlbe,
 -  uint32_t mas0)
 +  uint32_t mas0,
 +  uint32_t lpid)
  {
   unsigned long flags;
 
 @@ -80,7 +81,7 @@ static inline void __write_host_tlbe(struct
 kvm_book3e_206_tlb_entry *stlbe,
   mtspr(SPRN_MAS3, (u32)stlbe-mas7_3);
   mtspr(SPRN_MAS7, (u32)(stlbe-mas7_3  32));
  #ifdef CONFIG_KVM_BOOKE_HV
 - mtspr(SPRN_MAS8, stlbe-mas8);
 + mtspr(SPRN_MAS8, MAS8_TGS | get_thread_specific_lpid(lpid));
  #endif
   asm volatile(isync; tlbwe : : : memory);
 
 @@ -129,11 +130,12 @@ static inline void write_host_tlbe(struct
 kvmppc_vcpu_e500 *vcpu_e500,
 
   if (tlbsel == 0) {
   mas0 = get_host_mas0(stlbe-mas2);
 - __write_host_tlbe(stlbe, mas0);
 + __write_host_tlbe(stlbe, mas0, vcpu_e500-vcpu.kvm-
 arch.lpid);
   } else {
   __write_host_tlbe(stlbe,
 MAS0_TLBSEL(1) |
 -   MAS0_ESEL(to_htlb1_esel(sesel)));
 +   MAS0_ESEL(to_htlb1_esel(sesel)),
 +   vcpu_e500

RE: [PATCH 1/2] KVM: PPC: e500mc: Add support for single threaded vcpus on e6500 core

2014-09-01 Thread mihai.cara...@freescale.com
I abandon this patch, I will send a v2 with a minor fix for 85xx.

Mike

 -Original Message-
 From: Mihai Caraman [mailto:mihai.cara...@freescale.com]
 Sent: Friday, August 29, 2014 8:04 PM
 To: kvm-ppc@vger.kernel.org
 Cc: k...@vger.kernel.org; Caraman Mihai Claudiu-B02008
 Subject: [PATCH 1/2] KVM: PPC: e500mc: Add support for single threaded
 vcpus on e6500 core
 
 ePAPR represents hardware threads as cpu node properties in device tree.
 So with existing QEMU, hardware threads are simply exposed as vcpus with
 one hardware thread.
 
 The e6500 core shares TLBs between hardware threads. Without tlb write
 conditional instruction, the Linux kernel uses per core mechanisms to
 protect against duplicate TLB entries.
 
 The guest is unable to detect real siblings threads, so it can't use a
 TLB protection mechanism. An alternative solution is to use the
 hypervisor
 to allocate different lpids to guest's vcpus running simultaneous on real
 siblings threads. On systems with two threads per core this patch halves
 the size of the lpid pool that the allocator sees and use two lpids per
 VM.
 Use even numbers to speedup vcpu lpid computation with consecutive lpids
 per VM: vm1 will use lpids 2 and 3, vm2 lpids 4 and 5, and so on.
 
 Signed-off-by: Mihai Caraman mihai.cara...@freescale.com
 ---
  arch/powerpc/include/asm/kvm_booke.h |  5 +++-
  arch/powerpc/kvm/e500.h  | 20 
  arch/powerpc/kvm/e500_mmu_host.c | 16 ++---
  arch/powerpc/kvm/e500mc.c| 46 ++
 --
  4 files changed, 64 insertions(+), 23 deletions(-)
 
 diff --git a/arch/powerpc/include/asm/kvm_booke.h
 b/arch/powerpc/include/asm/kvm_booke.h
 index f7aa5cc..630134d 100644
 --- a/arch/powerpc/include/asm/kvm_booke.h
 +++ b/arch/powerpc/include/asm/kvm_booke.h
 @@ -23,7 +23,10 @@
  #include linux/types.h
  #include linux/kvm_host.h
 
 -/* LPIDs we support with this build -- runtime limit may be lower */
 +/*
 + * Number of available lpids. Only the low-order 6 bits of LPID rgister
 are
 + * implemented on e500mc+ cores.
 + */
  #define KVMPPC_NR_LPIDS64
 
  #define KVMPPC_INST_EHPRIV   0x7c00021c
 diff --git a/arch/powerpc/kvm/e500.h b/arch/powerpc/kvm/e500.h
 index a326178..7b74453 100644
 --- a/arch/powerpc/kvm/e500.h
 +++ b/arch/powerpc/kvm/e500.h
 @@ -22,6 +22,7 @@
  #include linux/kvm_host.h
  #include asm/mmu-book3e.h
  #include asm/tlb.h
 +#include asm/cputhreads.h
 
  enum vcpu_ftr {
   VCPU_FTR_MMU_V2
 @@ -289,6 +290,25 @@ void kvmppc_e500_tlbil_all(struct kvmppc_vcpu_e500
 *vcpu_e500);
  #define kvmppc_e500_get_tlb_stid(vcpu, gtlbe)   get_tlb_tid(gtlbe)
  #define get_tlbmiss_tid(vcpu)   get_cur_pid(vcpu)
  #define get_tlb_sts(gtlbe)  (gtlbe-mas1  MAS1_TS)
 +
 +/*
 + * This functios should be called with preemtion disabled
 + * and the returned value is valid only in that context
 + */
 +static inline int get_thread_specific_lpid(int vm_lpid)
 +{
 + int vcpu_lpid = vm_lpid;
 +
 + if (threads_per_core == 2)
 + vcpu_lpid |= smp_processor_id()  1;
 +
 + return vcpu_lpid;
 +}
 +
 +static inline int get_lpid(struct kvm_vcpu *vcpu)
 +{
 + return get_thread_specific_lpid(vcpu-kvm-arch.lpid);
 +}
  #else
  unsigned int kvmppc_e500_get_tlb_stid(struct kvm_vcpu *vcpu,
 struct kvm_book3e_206_tlb_entry *gtlbe);
 diff --git a/arch/powerpc/kvm/e500_mmu_host.c
 b/arch/powerpc/kvm/e500_mmu_host.c
 index 08f14bb..5759608 100644
 --- a/arch/powerpc/kvm/e500_mmu_host.c
 +++ b/arch/powerpc/kvm/e500_mmu_host.c
 @@ -69,7 +69,8 @@ static inline u32 e500_shadow_mas3_attrib(u32 mas3, int
 usermode)
   * writing shadow tlb entry to host TLB
   */
  static inline void __write_host_tlbe(struct kvm_book3e_206_tlb_entry
 *stlbe,
 -  uint32_t mas0)
 +  uint32_t mas0,
 +  uint32_t lpid)
  {
   unsigned long flags;
 
 @@ -80,7 +81,7 @@ static inline void __write_host_tlbe(struct
 kvm_book3e_206_tlb_entry *stlbe,
   mtspr(SPRN_MAS3, (u32)stlbe-mas7_3);
   mtspr(SPRN_MAS7, (u32)(stlbe-mas7_3  32));
  #ifdef CONFIG_KVM_BOOKE_HV
 - mtspr(SPRN_MAS8, stlbe-mas8);
 + mtspr(SPRN_MAS8, MAS8_TGS | get_thread_specific_lpid(lpid));
  #endif
   asm volatile(isync; tlbwe : : : memory);
 
 @@ -129,11 +130,12 @@ static inline void write_host_tlbe(struct
 kvmppc_vcpu_e500 *vcpu_e500,
 
   if (tlbsel == 0) {
   mas0 = get_host_mas0(stlbe-mas2);
 - __write_host_tlbe(stlbe, mas0);
 + __write_host_tlbe(stlbe, mas0, vcpu_e500-vcpu.kvm-
 arch.lpid);
   } else {
   __write_host_tlbe(stlbe,
 MAS0_TLBSEL(1) |
 -   MAS0_ESEL(to_htlb1_esel(sesel)));
 +   MAS0_ESEL(to_htlb1_esel(sesel)),
 +   vcpu_e500

[PATCH 1/2] KVM: PPC: e500mc: Add support for single threaded vcpus on e6500 core

2014-08-29 Thread Mihai Caraman
ePAPR represents hardware threads as cpu node properties in device tree.
So with existing QEMU, hardware threads are simply exposed as vcpus with
one hardware thread.

The e6500 core shares TLBs between hardware threads. Without tlb write
conditional instruction, the Linux kernel uses per core mechanisms to
protect against duplicate TLB entries.

The guest is unable to detect real siblings threads, so it can't use a
TLB protection mechanism. An alternative solution is to use the hypervisor
to allocate different lpids to guest's vcpus running simultaneous on real
siblings threads. On systems with two threads per core this patch halves
the size of the lpid pool that the allocator sees and use two lpids per VM.
Use even numbers to speedup vcpu lpid computation with consecutive lpids
per VM: vm1 will use lpids 2 and 3, vm2 lpids 4 and 5, and so on.

Signed-off-by: Mihai Caraman mihai.cara...@freescale.com
---
 arch/powerpc/include/asm/kvm_booke.h |  5 +++-
 arch/powerpc/kvm/e500.h  | 20 
 arch/powerpc/kvm/e500_mmu_host.c | 16 ++---
 arch/powerpc/kvm/e500mc.c| 46 ++--
 4 files changed, 64 insertions(+), 23 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_booke.h 
b/arch/powerpc/include/asm/kvm_booke.h
index f7aa5cc..630134d 100644
--- a/arch/powerpc/include/asm/kvm_booke.h
+++ b/arch/powerpc/include/asm/kvm_booke.h
@@ -23,7 +23,10 @@
 #include linux/types.h
 #include linux/kvm_host.h
 
-/* LPIDs we support with this build -- runtime limit may be lower */
+/*
+ * Number of available lpids. Only the low-order 6 bits of LPID rgister are
+ * implemented on e500mc+ cores.
+ */
 #define KVMPPC_NR_LPIDS64
 
 #define KVMPPC_INST_EHPRIV 0x7c00021c
diff --git a/arch/powerpc/kvm/e500.h b/arch/powerpc/kvm/e500.h
index a326178..7b74453 100644
--- a/arch/powerpc/kvm/e500.h
+++ b/arch/powerpc/kvm/e500.h
@@ -22,6 +22,7 @@
 #include linux/kvm_host.h
 #include asm/mmu-book3e.h
 #include asm/tlb.h
+#include asm/cputhreads.h
 
 enum vcpu_ftr {
VCPU_FTR_MMU_V2
@@ -289,6 +290,25 @@ void kvmppc_e500_tlbil_all(struct kvmppc_vcpu_e500 
*vcpu_e500);
 #define kvmppc_e500_get_tlb_stid(vcpu, gtlbe)   get_tlb_tid(gtlbe)
 #define get_tlbmiss_tid(vcpu)   get_cur_pid(vcpu)
 #define get_tlb_sts(gtlbe)  (gtlbe-mas1  MAS1_TS)
+
+/*
+ * This functios should be called with preemtion disabled
+ * and the returned value is valid only in that context
+ */
+static inline int get_thread_specific_lpid(int vm_lpid)
+{
+   int vcpu_lpid = vm_lpid;
+
+   if (threads_per_core == 2)
+   vcpu_lpid |= smp_processor_id()  1;
+
+   return vcpu_lpid;
+}
+
+static inline int get_lpid(struct kvm_vcpu *vcpu)
+{
+   return get_thread_specific_lpid(vcpu-kvm-arch.lpid);
+}
 #else
 unsigned int kvmppc_e500_get_tlb_stid(struct kvm_vcpu *vcpu,
  struct kvm_book3e_206_tlb_entry *gtlbe);
diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c
index 08f14bb..5759608 100644
--- a/arch/powerpc/kvm/e500_mmu_host.c
+++ b/arch/powerpc/kvm/e500_mmu_host.c
@@ -69,7 +69,8 @@ static inline u32 e500_shadow_mas3_attrib(u32 mas3, int 
usermode)
  * writing shadow tlb entry to host TLB
  */
 static inline void __write_host_tlbe(struct kvm_book3e_206_tlb_entry *stlbe,
-uint32_t mas0)
+uint32_t mas0,
+uint32_t lpid)
 {
unsigned long flags;
 
@@ -80,7 +81,7 @@ static inline void __write_host_tlbe(struct 
kvm_book3e_206_tlb_entry *stlbe,
mtspr(SPRN_MAS3, (u32)stlbe-mas7_3);
mtspr(SPRN_MAS7, (u32)(stlbe-mas7_3  32));
 #ifdef CONFIG_KVM_BOOKE_HV
-   mtspr(SPRN_MAS8, stlbe-mas8);
+   mtspr(SPRN_MAS8, MAS8_TGS | get_thread_specific_lpid(lpid));
 #endif
asm volatile(isync; tlbwe : : : memory);
 
@@ -129,11 +130,12 @@ static inline void write_host_tlbe(struct 
kvmppc_vcpu_e500 *vcpu_e500,
 
if (tlbsel == 0) {
mas0 = get_host_mas0(stlbe-mas2);
-   __write_host_tlbe(stlbe, mas0);
+   __write_host_tlbe(stlbe, mas0, vcpu_e500-vcpu.kvm-arch.lpid);
} else {
__write_host_tlbe(stlbe,
  MAS0_TLBSEL(1) |
- MAS0_ESEL(to_htlb1_esel(sesel)));
+ MAS0_ESEL(to_htlb1_esel(sesel)),
+ vcpu_e500-vcpu.kvm-arch.lpid);
}
 }
 
@@ -317,10 +319,6 @@ static void kvmppc_e500_setup_stlbe(
stlbe-mas2 = (gvaddr  MAS2_EPN) | (ref-flags  E500_TLB_MAS2_ATTR);
stlbe-mas7_3 = ((u64)pfn  PAGE_SHIFT) |
e500_shadow_mas3_attrib(gtlbe-mas7_3, pr);
-
-#ifdef CONFIG_KVM_BOOKE_HV
-   stlbe-mas8 = MAS8_TGS | vcpu-kvm-arch.lpid;
-#endif
 }
 
 static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500