All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] *** SUBJECT HERE ***
@ 2013-10-28 10:34 ` Bharat Bhushan
  0 siblings, 0 replies; 12+ messages in thread
From: Bharat Bhushan @ 2013-10-28 10:22 UTC (permalink / raw)
  To: paulus, agraf, kvm-ppc, kvm, scottwood; +Cc: Bharat Bhushan

From: Bharat Bhushan <bharat.bhushan@freescale.com>

v1->v2
 - Removed _PAGE_BUSY loop as suggested by PaulS.
 - Added check for PAGE_SPLITTING

kvm: powerpc: use cache attributes from linux pte
 - 1st Patch fixes a bug in booke (detail in patch)
 - 2nd patch is renaming the linux_pte_lookup_function() just for clarity.
   There is not functional change.
 - 3nd Patch adds a Linux pte lookup function.
 - 4th Patch uses the above defined function and setup TLB.wimg accordingly


Bharat Bhushan (4):
  kvm: booke: clear host tlb reference flag on guest tlb invalidation
  kvm: book3s: rename lookup_linux_pte() to
    lookup_linux_pte_and_update()
  kvm: powerpc: define a linux pte lookup function
  kvm: powerpc: use caching attributes as per linux pte

 arch/powerpc/include/asm/kvm_host.h |    2 +-
 arch/powerpc/include/asm/pgtable.h  |   27 +++++++++++++++++
 arch/powerpc/kvm/book3s_hv_rm_mmu.c |    8 +++--
 arch/powerpc/kvm/booke.c            |    1 +
 arch/powerpc/kvm/e500.h             |    8 +++--
 arch/powerpc/kvm/e500_mmu_host.c    |   55 +++++++++++++++++++---------------
 6 files changed, 70 insertions(+), 31 deletions(-)

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/4 v2] kvm: booke: clear host tlb reference flag on guest tlb invalidation
  2013-10-28 10:34 ` Bharat Bhushan
@ 2013-10-28 10:34   ` Bharat Bhushan
  -1 siblings, 0 replies; 12+ messages in thread
From: Bharat Bhushan @ 2013-10-28 10:22 UTC (permalink / raw)
  To: paulus, agraf, kvm-ppc, kvm, scottwood; +Cc: Bharat Bhushan, Bharat Bhushan

On booke, "struct tlbe_ref" contains host tlb mapping information
(pfn: for guest-pfn to pfn, flags: attribute associated with this mapping)
for a guest tlb entry. So when a guest creates a TLB entry then
"struct tlbe_ref" is set to point to valid "pfn" and set attributes in
"flags" field of the above said structure. When a guest TLB entry is
invalidated then flags field of corresponding "struct tlbe_ref" is
updated to point that this is no more valid, also we selectively clear
some other attribute bits, example: if E500_TLB_BITMAP was set then we clear
E500_TLB_BITMAP, if E500_TLB_TLB0 is set then we clear this.

Ideally we should clear complete "flags" as this entry is invalid and does not
have anything to re-used. The other part of the problem is that when we use
the same entry again then also we do not clear (started doing or-ing etc).

So far it was working because the selectively clearing mentioned above
actually clears "flags" what was set during TLB mapping. But the problem
starts coming when we add more attributes to this then we need to selectively
clear them and which is not needed.

Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com>
---
v1->v2
 -- No Change

 arch/powerpc/kvm/e500_mmu_host.c |   16 ++++++++--------
 1 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c
index 8f0d532..59e05f2 100644
--- a/arch/powerpc/kvm/e500_mmu_host.c
+++ b/arch/powerpc/kvm/e500_mmu_host.c
@@ -230,15 +230,15 @@ void inval_gtlbe_on_host(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel,
 		ref->flags &= ~(E500_TLB_TLB0 | E500_TLB_VALID);
 	}
 
-	/* Already invalidated in between */
-	if (!(ref->flags & E500_TLB_VALID))
-		return;
-
-	/* Guest tlbe is backed by at most one host tlbe per shadow pid. */
-	kvmppc_e500_tlbil_one(vcpu_e500, gtlbe);
+	/*
+	 * If TLB entry is still valid then it's a TLB0 entry, and thus
+	 * backed by at most one host tlbe per shadow pid
+	 */
+	if (ref->flags & E500_TLB_VALID)
+		kvmppc_e500_tlbil_one(vcpu_e500, gtlbe);
 
 	/* Mark the TLB as not backed by the host anymore */
-	ref->flags &= ~E500_TLB_VALID;
+	ref->flags = 0;
 }
 
 static inline int tlbe_is_writable(struct kvm_book3e_206_tlb_entry *tlbe)
@@ -251,7 +251,7 @@ static inline void kvmppc_e500_ref_setup(struct tlbe_ref *ref,
 					 pfn_t pfn)
 {
 	ref->pfn = pfn;
-	ref->flags |= E500_TLB_VALID;
+	ref->flags = E500_TLB_VALID;
 
 	/* Mark the page accessed */
 	kvm_set_pfn_accessed(pfn);
-- 
1.7.0.4



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/4 v2] kvm: book3s: rename lookup_linux_pte() to lookup_linux_pte_and_update()
  2013-10-28 10:34 ` Bharat Bhushan
@ 2013-10-28 10:34   ` Bharat Bhushan
  -1 siblings, 0 replies; 12+ messages in thread
From: Bharat Bhushan @ 2013-10-28 10:22 UTC (permalink / raw)
  To: paulus, agraf, kvm-ppc, kvm, scottwood; +Cc: Bharat Bhushan, Bharat Bhushan

lookup_linux_pte() is doing more than lookup, updating the pte,
so for clarity it is renamed to lookup_linux_pte_and_update()

Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com>
---
v1->v2
 -- No Change

 arch/powerpc/kvm/book3s_hv_rm_mmu.c |    8 +++++---
 1 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index 45e30d6..1743ddd 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -134,7 +134,7 @@ static void remove_revmap_chain(struct kvm *kvm, long pte_index,
 	unlock_rmap(rmap);
 }
 
-static pte_t lookup_linux_pte(pgd_t *pgdir, unsigned long hva,
+static pte_t lookup_linux_pte_and_update(pgd_t *pgdir, unsigned long hva,
 			      int writing, unsigned long *pte_sizep)
 {
 	pte_t *ptep;
@@ -231,7 +231,8 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
 
 		/* Look up the Linux PTE for the backing page */
 		pte_size = psize;
-		pte = lookup_linux_pte(pgdir, hva, writing, &pte_size);
+		pte = lookup_linux_pte_and_update(pgdir, hva, writing,
+						  &pte_size);
 		if (pte_present(pte)) {
 			if (writing && !pte_write(pte))
 				/* make the actual HPTE be read-only */
@@ -667,7 +668,8 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
 			memslot = __gfn_to_memslot(kvm_memslots(kvm), gfn);
 			if (memslot) {
 				hva = __gfn_to_hva_memslot(memslot, gfn);
-				pte = lookup_linux_pte(pgdir, hva, 1, &psize);
+				pte = lookup_linux_pte_and_update(pgdir, hva,
+								  1, &psize);
 				if (pte_present(pte) && !pte_write(pte))
 					r = hpte_make_readonly(r);
 			}
-- 
1.7.0.4



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/4 v2] kvm: powerpc: define a linux pte lookup function
  2013-10-28 10:34 ` Bharat Bhushan
@ 2013-10-28 10:34   ` Bharat Bhushan
  -1 siblings, 0 replies; 12+ messages in thread
From: Bharat Bhushan @ 2013-10-28 10:22 UTC (permalink / raw)
  To: paulus, agraf, kvm-ppc, kvm, scottwood; +Cc: Bharat Bhushan, Bharat Bhushan

We need to search linux "pte" to get "pte" attributes for
setting TLB in KVM.
This patch defines a linux_pte_lookup() function for same.

Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com>
---
v1->v2
 -- removed _PAGE_BUSY and _PAGE_PRESENT as suggested by PaulS
 -- Added _PAGE_SPLITTING 

 arch/powerpc/include/asm/pgtable.h |   27 +++++++++++++++++++++++++++
 1 files changed, 27 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h
index 7d6eacf..a7151df 100644
--- a/arch/powerpc/include/asm/pgtable.h
+++ b/arch/powerpc/include/asm/pgtable.h
@@ -223,6 +223,33 @@ extern int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr,
 #endif
 pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea,
 				 unsigned *shift);
+
+static inline pte_t lookup_linux_pte(pgd_t *pgdir, unsigned long hva,
+				     unsigned long *pte_sizep)
+{
+	pte_t *ptep;
+	unsigned long ps = *pte_sizep;
+	unsigned int shift;
+
+	ptep = find_linux_pte_or_hugepte(pgdir, hva, &shift);
+	if (!ptep)
+		return __pte(0);
+	if (shift)
+		*pte_sizep = 1ul << shift;
+	else
+		*pte_sizep = PAGE_SIZE;
+
+	if (ps > *pte_sizep)
+		return __pte(0);
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+	/* If hugepage and is trans splitting return None */
+	if (unlikely(hugepage && pmd_trans_splitting(pte_pmd(*ptep))))
+		return __pte(0);
+#endif
+
+	return pte_val(*ptep);;
+}
 #endif /* __ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
-- 
1.7.0.4



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 4/4 v2] kvm: powerpc: use caching attributes as per linux pte
  2013-10-28 10:34 ` Bharat Bhushan
@ 2013-10-28 10:34   ` Bharat Bhushan
  -1 siblings, 0 replies; 12+ messages in thread
From: Bharat Bhushan @ 2013-10-28 10:22 UTC (permalink / raw)
  To: paulus, agraf, kvm-ppc, kvm, scottwood; +Cc: Bharat Bhushan, Bharat Bhushan

KVM uses same WIM tlb attributes as the corresponding qemu pte.
For this we now search the linux pte for the requested page and
get these cache caching/coherency attributes from pte.

Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com>
---
v1->v2
 -- No Change

 arch/powerpc/include/asm/kvm_host.h |    2 +-
 arch/powerpc/kvm/booke.c            |    1 +
 arch/powerpc/kvm/e500.h             |    8 ++++--
 arch/powerpc/kvm/e500_mmu_host.c    |   39 ++++++++++++++++++++--------------
 4 files changed, 30 insertions(+), 20 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index ac40013..dd57029 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -550,6 +550,7 @@ struct kvm_vcpu_arch {
 #endif
 	gpa_t paddr_accessed;
 	gva_t vaddr_accessed;
+	pgd_t *pgdir;
 
 	u8 io_gpr; /* GPR used as IO source/target */
 	u8 mmio_is_bigendian;
@@ -607,7 +608,6 @@ struct kvm_vcpu_arch {
 	struct list_head run_list;
 	struct task_struct *run_task;
 	struct kvm_run *kvm_run;
-	pgd_t *pgdir;
 
 	spinlock_t vpa_update_lock;
 	struct kvmppc_vpa vpa;
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 8b6a790..76e8797 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -727,6 +727,7 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 	thread.debug = current->thread.debug;
 	current->thread.debug = vcpu->arch.shadow_dbg_reg;
 
+	vcpu->arch.pgdir = current->mm->pgd;
 	kvmppc_fix_ee_before_entry();
 
 	ret = __kvmppc_vcpu_run(kvm_run, vcpu);
diff --git a/arch/powerpc/kvm/e500.h b/arch/powerpc/kvm/e500.h
index 4fd9650..a326178 100644
--- a/arch/powerpc/kvm/e500.h
+++ b/arch/powerpc/kvm/e500.h
@@ -31,11 +31,13 @@ enum vcpu_ftr {
 #define E500_TLB_NUM   2
 
 /* entry is mapped somewhere in host TLB */
-#define E500_TLB_VALID		(1 << 0)
+#define E500_TLB_VALID		(1 << 31)
 /* TLB1 entry is mapped by host TLB1, tracked by bitmaps */
-#define E500_TLB_BITMAP		(1 << 1)
+#define E500_TLB_BITMAP		(1 << 30)
 /* TLB1 entry is mapped by host TLB0 */
-#define E500_TLB_TLB0		(1 << 2)
+#define E500_TLB_TLB0		(1 << 29)
+/* bits [6-5] MAS2_X1 and MAS2_X0 and [4-0] bits for WIMGE */
+#define E500_TLB_MAS2_ATTR	(0x7f)
 
 struct tlbe_ref {
 	pfn_t pfn;		/* valid only for TLB0, except briefly */
diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c
index 59e05f2..31faf48 100644
--- a/arch/powerpc/kvm/e500_mmu_host.c
+++ b/arch/powerpc/kvm/e500_mmu_host.c
@@ -64,15 +64,6 @@ static inline u32 e500_shadow_mas3_attrib(u32 mas3, int usermode)
 	return mas3;
 }
 
-static inline u32 e500_shadow_mas2_attrib(u32 mas2, int usermode)
-{
-#ifdef CONFIG_SMP
-	return (mas2 & MAS2_ATTRIB_MASK) | MAS2_M;
-#else
-	return mas2 & MAS2_ATTRIB_MASK;
-#endif
-}
-
 /*
  * writing shadow tlb entry to host TLB
  */
@@ -248,11 +239,14 @@ static inline int tlbe_is_writable(struct kvm_book3e_206_tlb_entry *tlbe)
 
 static inline void kvmppc_e500_ref_setup(struct tlbe_ref *ref,
 					 struct kvm_book3e_206_tlb_entry *gtlbe,
-					 pfn_t pfn)
+					 pfn_t pfn, unsigned int wimg)
 {
 	ref->pfn = pfn;
 	ref->flags = E500_TLB_VALID;
 
+	/* Use guest supplied MAS2_G and MAS2_E */
+	ref->flags |= (gtlbe->mas2 & MAS2_ATTRIB_MASK) | wimg;
+
 	/* Mark the page accessed */
 	kvm_set_pfn_accessed(pfn);
 
@@ -315,8 +309,7 @@ static void kvmppc_e500_setup_stlbe(
 
 	/* Force IPROT=0 for all guest mappings. */
 	stlbe->mas1 = MAS1_TSIZE(tsize) | get_tlb_sts(gtlbe) | MAS1_VALID;
-	stlbe->mas2 = (gvaddr & MAS2_EPN) |
-		      e500_shadow_mas2_attrib(gtlbe->mas2, pr);
+	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);
 
@@ -335,6 +328,10 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
 	unsigned long hva;
 	int pfnmap = 0;
 	int tsize = BOOK3E_PAGESZ_4K;
+	unsigned long tsize_pages = 0;
+	pte_t pte;
+	unsigned int wimg = 0;
+	pgd_t *pgdir;
 
 	/*
 	 * Translate guest physical to true physical, acquiring
@@ -397,7 +394,7 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
 			 */
 
 			for (; tsize > BOOK3E_PAGESZ_4K; tsize -= 2) {
-				unsigned long gfn_start, gfn_end, tsize_pages;
+				unsigned long gfn_start, gfn_end;
 				tsize_pages = 1 << (tsize - 2);
 
 				gfn_start = gfn & ~(tsize_pages - 1);
@@ -439,9 +436,9 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
 	}
 
 	if (likely(!pfnmap)) {
-		unsigned long tsize_pages = 1 << (tsize + 10 - PAGE_SHIFT);
+		tsize_pages = 1 << (tsize + 10 - PAGE_SHIFT);
 		pfn = gfn_to_pfn_memslot(slot, gfn);
-		if (is_error_noslot_pfn(pfn)) {
+		if (is_error_noslot_pfn(pfn) && printk_ratelimit()) {
 			printk(KERN_ERR "Couldn't get real page for gfn %lx!\n",
 					(long)gfn);
 			return -EINVAL;
@@ -452,7 +449,17 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
 		gvaddr &= ~((tsize_pages << PAGE_SHIFT) - 1);
 	}
 
-	kvmppc_e500_ref_setup(ref, gtlbe, pfn);
+
+	pgdir = vcpu_e500->vcpu.arch.pgdir;
+	pte = lookup_linux_pte(pgdir, hva, &tsize_pages);
+	if (pte_present(pte))
+		wimg = (pte >> PTE_WIMGE_SHIFT) & MAS2_WIMGE_MASK;
+	else if (printk_ratelimit()) {
+		printk(KERN_ERR "%s: pte not present: gfn %lx, pfn %lx\n",
+				__func__, (long)gfn, pfn);
+		return -EINVAL;
+	}
+	kvmppc_e500_ref_setup(ref, gtlbe, pfn, wimg);
 
 	kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize,
 				ref, gvaddr, stlbe);
-- 
1.7.0.4



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 0/4] *** SUBJECT HERE ***
@ 2013-10-28 10:34 ` Bharat Bhushan
  0 siblings, 0 replies; 12+ messages in thread
From: Bharat Bhushan @ 2013-10-28 10:34 UTC (permalink / raw)
  To: paulus, agraf, kvm-ppc, kvm, scottwood; +Cc: Bharat Bhushan

From: Bharat Bhushan <bharat.bhushan@freescale.com>

v1->v2
 - Removed _PAGE_BUSY loop as suggested by PaulS.
 - Added check for PAGE_SPLITTING

kvm: powerpc: use cache attributes from linux pte
 - 1st Patch fixes a bug in booke (detail in patch)
 - 2nd patch is renaming the linux_pte_lookup_function() just for clarity.
   There is not functional change.
 - 3nd Patch adds a Linux pte lookup function.
 - 4th Patch uses the above defined function and setup TLB.wimg accordingly


Bharat Bhushan (4):
  kvm: booke: clear host tlb reference flag on guest tlb invalidation
  kvm: book3s: rename lookup_linux_pte() to
    lookup_linux_pte_and_update()
  kvm: powerpc: define a linux pte lookup function
  kvm: powerpc: use caching attributes as per linux pte

 arch/powerpc/include/asm/kvm_host.h |    2 +-
 arch/powerpc/include/asm/pgtable.h  |   27 +++++++++++++++++
 arch/powerpc/kvm/book3s_hv_rm_mmu.c |    8 +++--
 arch/powerpc/kvm/booke.c            |    1 +
 arch/powerpc/kvm/e500.h             |    8 +++--
 arch/powerpc/kvm/e500_mmu_host.c    |   55 +++++++++++++++++++---------------
 6 files changed, 70 insertions(+), 31 deletions(-)



^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/4 v2] kvm: booke: clear host tlb reference flag on guest tlb invalidation
@ 2013-10-28 10:34   ` Bharat Bhushan
  0 siblings, 0 replies; 12+ messages in thread
From: Bharat Bhushan @ 2013-10-28 10:34 UTC (permalink / raw)
  To: paulus, agraf, kvm-ppc, kvm, scottwood; +Cc: Bharat Bhushan, Bharat Bhushan

On booke, "struct tlbe_ref" contains host tlb mapping information
(pfn: for guest-pfn to pfn, flags: attribute associated with this mapping)
for a guest tlb entry. So when a guest creates a TLB entry then
"struct tlbe_ref" is set to point to valid "pfn" and set attributes in
"flags" field of the above said structure. When a guest TLB entry is
invalidated then flags field of corresponding "struct tlbe_ref" is
updated to point that this is no more valid, also we selectively clear
some other attribute bits, example: if E500_TLB_BITMAP was set then we clear
E500_TLB_BITMAP, if E500_TLB_TLB0 is set then we clear this.

Ideally we should clear complete "flags" as this entry is invalid and does not
have anything to re-used. The other part of the problem is that when we use
the same entry again then also we do not clear (started doing or-ing etc).

So far it was working because the selectively clearing mentioned above
actually clears "flags" what was set during TLB mapping. But the problem
starts coming when we add more attributes to this then we need to selectively
clear them and which is not needed.

Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com>
---
v1->v2
 -- No Change

 arch/powerpc/kvm/e500_mmu_host.c |   16 ++++++++--------
 1 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c
index 8f0d532..59e05f2 100644
--- a/arch/powerpc/kvm/e500_mmu_host.c
+++ b/arch/powerpc/kvm/e500_mmu_host.c
@@ -230,15 +230,15 @@ void inval_gtlbe_on_host(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel,
 		ref->flags &= ~(E500_TLB_TLB0 | E500_TLB_VALID);
 	}
 
-	/* Already invalidated in between */
-	if (!(ref->flags & E500_TLB_VALID))
-		return;
-
-	/* Guest tlbe is backed by at most one host tlbe per shadow pid. */
-	kvmppc_e500_tlbil_one(vcpu_e500, gtlbe);
+	/*
+	 * If TLB entry is still valid then it's a TLB0 entry, and thus
+	 * backed by at most one host tlbe per shadow pid
+	 */
+	if (ref->flags & E500_TLB_VALID)
+		kvmppc_e500_tlbil_one(vcpu_e500, gtlbe);
 
 	/* Mark the TLB as not backed by the host anymore */
-	ref->flags &= ~E500_TLB_VALID;
+	ref->flags = 0;
 }
 
 static inline int tlbe_is_writable(struct kvm_book3e_206_tlb_entry *tlbe)
@@ -251,7 +251,7 @@ static inline void kvmppc_e500_ref_setup(struct tlbe_ref *ref,
 					 pfn_t pfn)
 {
 	ref->pfn = pfn;
-	ref->flags |= E500_TLB_VALID;
+	ref->flags = E500_TLB_VALID;
 
 	/* Mark the page accessed */
 	kvm_set_pfn_accessed(pfn);
-- 
1.7.0.4



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/4 v2] kvm: book3s: rename lookup_linux_pte() to lookup_linux_pte_and_update()
@ 2013-10-28 10:34   ` Bharat Bhushan
  0 siblings, 0 replies; 12+ messages in thread
From: Bharat Bhushan @ 2013-10-28 10:34 UTC (permalink / raw)
  To: paulus, agraf, kvm-ppc, kvm, scottwood; +Cc: Bharat Bhushan, Bharat Bhushan

lookup_linux_pte() is doing more than lookup, updating the pte,
so for clarity it is renamed to lookup_linux_pte_and_update()

Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com>
---
v1->v2
 -- No Change

 arch/powerpc/kvm/book3s_hv_rm_mmu.c |    8 +++++---
 1 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index 45e30d6..1743ddd 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -134,7 +134,7 @@ static void remove_revmap_chain(struct kvm *kvm, long pte_index,
 	unlock_rmap(rmap);
 }
 
-static pte_t lookup_linux_pte(pgd_t *pgdir, unsigned long hva,
+static pte_t lookup_linux_pte_and_update(pgd_t *pgdir, unsigned long hva,
 			      int writing, unsigned long *pte_sizep)
 {
 	pte_t *ptep;
@@ -231,7 +231,8 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
 
 		/* Look up the Linux PTE for the backing page */
 		pte_size = psize;
-		pte = lookup_linux_pte(pgdir, hva, writing, &pte_size);
+		pte = lookup_linux_pte_and_update(pgdir, hva, writing,
+						  &pte_size);
 		if (pte_present(pte)) {
 			if (writing && !pte_write(pte))
 				/* make the actual HPTE be read-only */
@@ -667,7 +668,8 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
 			memslot = __gfn_to_memslot(kvm_memslots(kvm), gfn);
 			if (memslot) {
 				hva = __gfn_to_hva_memslot(memslot, gfn);
-				pte = lookup_linux_pte(pgdir, hva, 1, &psize);
+				pte = lookup_linux_pte_and_update(pgdir, hva,
+								  1, &psize);
 				if (pte_present(pte) && !pte_write(pte))
 					r = hpte_make_readonly(r);
 			}
-- 
1.7.0.4



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/4 v2] kvm: powerpc: define a linux pte lookup function
@ 2013-10-28 10:34   ` Bharat Bhushan
  0 siblings, 0 replies; 12+ messages in thread
From: Bharat Bhushan @ 2013-10-28 10:34 UTC (permalink / raw)
  To: paulus, agraf, kvm-ppc, kvm, scottwood; +Cc: Bharat Bhushan, Bharat Bhushan

We need to search linux "pte" to get "pte" attributes for
setting TLB in KVM.
This patch defines a linux_pte_lookup() function for same.

Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com>
---
v1->v2
 -- removed _PAGE_BUSY and _PAGE_PRESENT as suggested by PaulS
 -- Added _PAGE_SPLITTING 

 arch/powerpc/include/asm/pgtable.h |   27 +++++++++++++++++++++++++++
 1 files changed, 27 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h
index 7d6eacf..a7151df 100644
--- a/arch/powerpc/include/asm/pgtable.h
+++ b/arch/powerpc/include/asm/pgtable.h
@@ -223,6 +223,33 @@ extern int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr,
 #endif
 pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea,
 				 unsigned *shift);
+
+static inline pte_t lookup_linux_pte(pgd_t *pgdir, unsigned long hva,
+				     unsigned long *pte_sizep)
+{
+	pte_t *ptep;
+	unsigned long ps = *pte_sizep;
+	unsigned int shift;
+
+	ptep = find_linux_pte_or_hugepte(pgdir, hva, &shift);
+	if (!ptep)
+		return __pte(0);
+	if (shift)
+		*pte_sizep = 1ul << shift;
+	else
+		*pte_sizep = PAGE_SIZE;
+
+	if (ps > *pte_sizep)
+		return __pte(0);
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+	/* If hugepage and is trans splitting return None */
+	if (unlikely(hugepage && pmd_trans_splitting(pte_pmd(*ptep))))
+		return __pte(0);
+#endif
+
+	return pte_val(*ptep);;
+}
 #endif /* __ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
-- 
1.7.0.4



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 4/4 v2] kvm: powerpc: use caching attributes as per linux pte
@ 2013-10-28 10:34   ` Bharat Bhushan
  0 siblings, 0 replies; 12+ messages in thread
From: Bharat Bhushan @ 2013-10-28 10:34 UTC (permalink / raw)
  To: paulus, agraf, kvm-ppc, kvm, scottwood; +Cc: Bharat Bhushan, Bharat Bhushan

KVM uses same WIM tlb attributes as the corresponding qemu pte.
For this we now search the linux pte for the requested page and
get these cache caching/coherency attributes from pte.

Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com>
---
v1->v2
 -- No Change

 arch/powerpc/include/asm/kvm_host.h |    2 +-
 arch/powerpc/kvm/booke.c            |    1 +
 arch/powerpc/kvm/e500.h             |    8 ++++--
 arch/powerpc/kvm/e500_mmu_host.c    |   39 ++++++++++++++++++++--------------
 4 files changed, 30 insertions(+), 20 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index ac40013..dd57029 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -550,6 +550,7 @@ struct kvm_vcpu_arch {
 #endif
 	gpa_t paddr_accessed;
 	gva_t vaddr_accessed;
+	pgd_t *pgdir;
 
 	u8 io_gpr; /* GPR used as IO source/target */
 	u8 mmio_is_bigendian;
@@ -607,7 +608,6 @@ struct kvm_vcpu_arch {
 	struct list_head run_list;
 	struct task_struct *run_task;
 	struct kvm_run *kvm_run;
-	pgd_t *pgdir;
 
 	spinlock_t vpa_update_lock;
 	struct kvmppc_vpa vpa;
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 8b6a790..76e8797 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -727,6 +727,7 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 	thread.debug = current->thread.debug;
 	current->thread.debug = vcpu->arch.shadow_dbg_reg;
 
+	vcpu->arch.pgdir = current->mm->pgd;
 	kvmppc_fix_ee_before_entry();
 
 	ret = __kvmppc_vcpu_run(kvm_run, vcpu);
diff --git a/arch/powerpc/kvm/e500.h b/arch/powerpc/kvm/e500.h
index 4fd9650..a326178 100644
--- a/arch/powerpc/kvm/e500.h
+++ b/arch/powerpc/kvm/e500.h
@@ -31,11 +31,13 @@ enum vcpu_ftr {
 #define E500_TLB_NUM   2
 
 /* entry is mapped somewhere in host TLB */
-#define E500_TLB_VALID		(1 << 0)
+#define E500_TLB_VALID		(1 << 31)
 /* TLB1 entry is mapped by host TLB1, tracked by bitmaps */
-#define E500_TLB_BITMAP		(1 << 1)
+#define E500_TLB_BITMAP		(1 << 30)
 /* TLB1 entry is mapped by host TLB0 */
-#define E500_TLB_TLB0		(1 << 2)
+#define E500_TLB_TLB0		(1 << 29)
+/* bits [6-5] MAS2_X1 and MAS2_X0 and [4-0] bits for WIMGE */
+#define E500_TLB_MAS2_ATTR	(0x7f)
 
 struct tlbe_ref {
 	pfn_t pfn;		/* valid only for TLB0, except briefly */
diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c
index 59e05f2..31faf48 100644
--- a/arch/powerpc/kvm/e500_mmu_host.c
+++ b/arch/powerpc/kvm/e500_mmu_host.c
@@ -64,15 +64,6 @@ static inline u32 e500_shadow_mas3_attrib(u32 mas3, int usermode)
 	return mas3;
 }
 
-static inline u32 e500_shadow_mas2_attrib(u32 mas2, int usermode)
-{
-#ifdef CONFIG_SMP
-	return (mas2 & MAS2_ATTRIB_MASK) | MAS2_M;
-#else
-	return mas2 & MAS2_ATTRIB_MASK;
-#endif
-}
-
 /*
  * writing shadow tlb entry to host TLB
  */
@@ -248,11 +239,14 @@ static inline int tlbe_is_writable(struct kvm_book3e_206_tlb_entry *tlbe)
 
 static inline void kvmppc_e500_ref_setup(struct tlbe_ref *ref,
 					 struct kvm_book3e_206_tlb_entry *gtlbe,
-					 pfn_t pfn)
+					 pfn_t pfn, unsigned int wimg)
 {
 	ref->pfn = pfn;
 	ref->flags = E500_TLB_VALID;
 
+	/* Use guest supplied MAS2_G and MAS2_E */
+	ref->flags |= (gtlbe->mas2 & MAS2_ATTRIB_MASK) | wimg;
+
 	/* Mark the page accessed */
 	kvm_set_pfn_accessed(pfn);
 
@@ -315,8 +309,7 @@ static void kvmppc_e500_setup_stlbe(
 
 	/* Force IPROT=0 for all guest mappings. */
 	stlbe->mas1 = MAS1_TSIZE(tsize) | get_tlb_sts(gtlbe) | MAS1_VALID;
-	stlbe->mas2 = (gvaddr & MAS2_EPN) |
-		      e500_shadow_mas2_attrib(gtlbe->mas2, pr);
+	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);
 
@@ -335,6 +328,10 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
 	unsigned long hva;
 	int pfnmap = 0;
 	int tsize = BOOK3E_PAGESZ_4K;
+	unsigned long tsize_pages = 0;
+	pte_t pte;
+	unsigned int wimg = 0;
+	pgd_t *pgdir;
 
 	/*
 	 * Translate guest physical to true physical, acquiring
@@ -397,7 +394,7 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
 			 */
 
 			for (; tsize > BOOK3E_PAGESZ_4K; tsize -= 2) {
-				unsigned long gfn_start, gfn_end, tsize_pages;
+				unsigned long gfn_start, gfn_end;
 				tsize_pages = 1 << (tsize - 2);
 
 				gfn_start = gfn & ~(tsize_pages - 1);
@@ -439,9 +436,9 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
 	}
 
 	if (likely(!pfnmap)) {
-		unsigned long tsize_pages = 1 << (tsize + 10 - PAGE_SHIFT);
+		tsize_pages = 1 << (tsize + 10 - PAGE_SHIFT);
 		pfn = gfn_to_pfn_memslot(slot, gfn);
-		if (is_error_noslot_pfn(pfn)) {
+		if (is_error_noslot_pfn(pfn) && printk_ratelimit()) {
 			printk(KERN_ERR "Couldn't get real page for gfn %lx!\n",
 					(long)gfn);
 			return -EINVAL;
@@ -452,7 +449,17 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
 		gvaddr &= ~((tsize_pages << PAGE_SHIFT) - 1);
 	}
 
-	kvmppc_e500_ref_setup(ref, gtlbe, pfn);
+
+	pgdir = vcpu_e500->vcpu.arch.pgdir;
+	pte = lookup_linux_pte(pgdir, hva, &tsize_pages);
+	if (pte_present(pte))
+		wimg = (pte >> PTE_WIMGE_SHIFT) & MAS2_WIMGE_MASK;
+	else if (printk_ratelimit()) {
+		printk(KERN_ERR "%s: pte not present: gfn %lx, pfn %lx\n",
+				__func__, (long)gfn, pfn);
+		return -EINVAL;
+	}
+	kvmppc_e500_ref_setup(ref, gtlbe, pfn, wimg);
 
 	kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize,
 				ref, gvaddr, stlbe);
-- 
1.7.0.4



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 3/4 v2] kvm: powerpc: define a linux pte lookup function
  2013-10-28 10:34   ` Bharat Bhushan
@ 2013-11-07  1:54     ` Scott Wood
  -1 siblings, 0 replies; 12+ messages in thread
From: Scott Wood @ 2013-11-07  1:54 UTC (permalink / raw)
  To: Bharat Bhushan; +Cc: paulus, agraf, kvm-ppc, kvm, Bharat Bhushan

On Mon, 2013-10-28 at 15:52 +0530, Bharat Bhushan wrote:
> We need to search linux "pte" to get "pte" attributes for
> setting TLB in KVM.
> This patch defines a linux_pte_lookup() function for same.
> 
> Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com>
> ---
> v1->v2
>  -- removed _PAGE_BUSY and _PAGE_PRESENT as suggested by PaulS
>  -- Added _PAGE_SPLITTING 
> 
>  arch/powerpc/include/asm/pgtable.h |   27 +++++++++++++++++++++++++++
>  1 files changed, 27 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h
> index 7d6eacf..a7151df 100644
> --- a/arch/powerpc/include/asm/pgtable.h
> +++ b/arch/powerpc/include/asm/pgtable.h
> @@ -223,6 +223,33 @@ extern int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr,
>  #endif
>  pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea,
>  				 unsigned *shift);
> +
> +static inline pte_t lookup_linux_pte(pgd_t *pgdir, unsigned long hva,
> +				     unsigned long *pte_sizep)
> +{
> +	pte_t *ptep;
> +	unsigned long ps = *pte_sizep;
> +	unsigned int shift;
> +
> +	ptep = find_linux_pte_or_hugepte(pgdir, hva, &shift);
> +	if (!ptep)
> +		return __pte(0);
> +	if (shift)
> +		*pte_sizep = 1ul << shift;
> +	else
> +		*pte_sizep = PAGE_SIZE;
> +
> +	if (ps > *pte_sizep)
> +		return __pte(0);
> +
> +#ifdef CONFIG_TRANSPARENT_HUGEPAGE
> +	/* If hugepage and is trans splitting return None */
> +	if (unlikely(hugepage && pmd_trans_splitting(pte_pmd(*ptep))))
> +		return __pte(0);
> +#endif
> +
> +	return pte_val(*ptep);;
> +}

s/;;/;/

I'd still rather see lookup_linux_ptep and then the caller can decide
what to do with it.  Currently that CONFIG_TRANSPARENT_HUGEPAGE code
will be completely untested since we don't call this except on booke.  
In fact, it doesn't even look like it compiles -- where is "hugepage"
defined?

-Scott

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 3/4 v2] kvm: powerpc: define a linux pte lookup function
@ 2013-11-07  1:54     ` Scott Wood
  0 siblings, 0 replies; 12+ messages in thread
From: Scott Wood @ 2013-11-07  1:54 UTC (permalink / raw)
  To: Bharat Bhushan; +Cc: paulus, agraf, kvm-ppc, kvm, Bharat Bhushan

On Mon, 2013-10-28 at 15:52 +0530, Bharat Bhushan wrote:
> We need to search linux "pte" to get "pte" attributes for
> setting TLB in KVM.
> This patch defines a linux_pte_lookup() function for same.
> 
> Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com>
> ---
> v1->v2
>  -- removed _PAGE_BUSY and _PAGE_PRESENT as suggested by PaulS
>  -- Added _PAGE_SPLITTING 
> 
>  arch/powerpc/include/asm/pgtable.h |   27 +++++++++++++++++++++++++++
>  1 files changed, 27 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h
> index 7d6eacf..a7151df 100644
> --- a/arch/powerpc/include/asm/pgtable.h
> +++ b/arch/powerpc/include/asm/pgtable.h
> @@ -223,6 +223,33 @@ extern int gup_hugepte(pte_t *ptep, unsigned long sz, unsigned long addr,
>  #endif
>  pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea,
>  				 unsigned *shift);
> +
> +static inline pte_t lookup_linux_pte(pgd_t *pgdir, unsigned long hva,
> +				     unsigned long *pte_sizep)
> +{
> +	pte_t *ptep;
> +	unsigned long ps = *pte_sizep;
> +	unsigned int shift;
> +
> +	ptep = find_linux_pte_or_hugepte(pgdir, hva, &shift);
> +	if (!ptep)
> +		return __pte(0);
> +	if (shift)
> +		*pte_sizep = 1ul << shift;
> +	else
> +		*pte_sizep = PAGE_SIZE;
> +
> +	if (ps > *pte_sizep)
> +		return __pte(0);
> +
> +#ifdef CONFIG_TRANSPARENT_HUGEPAGE
> +	/* If hugepage and is trans splitting return None */
> +	if (unlikely(hugepage && pmd_trans_splitting(pte_pmd(*ptep))))
> +		return __pte(0);
> +#endif
> +
> +	return pte_val(*ptep);;
> +}

s/;;/;/

I'd still rather see lookup_linux_ptep and then the caller can decide
what to do with it.  Currently that CONFIG_TRANSPARENT_HUGEPAGE code
will be completely untested since we don't call this except on booke.  
In fact, it doesn't even look like it compiles -- where is "hugepage"
defined?

-Scott




^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2013-11-07  1:54 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-10-28 10:22 [PATCH 0/4] *** SUBJECT HERE *** Bharat Bhushan
2013-10-28 10:34 ` Bharat Bhushan
2013-10-28 10:22 ` [PATCH 1/4 v2] kvm: booke: clear host tlb reference flag on guest tlb invalidation Bharat Bhushan
2013-10-28 10:34   ` Bharat Bhushan
2013-10-28 10:22 ` [PATCH 2/4 v2] kvm: book3s: rename lookup_linux_pte() to lookup_linux_pte_and_update() Bharat Bhushan
2013-10-28 10:34   ` Bharat Bhushan
2013-10-28 10:22 ` [PATCH 3/4 v2] kvm: powerpc: define a linux pte lookup function Bharat Bhushan
2013-10-28 10:34   ` Bharat Bhushan
2013-11-07  1:54   ` Scott Wood
2013-11-07  1:54     ` Scott Wood
2013-10-28 10:22 ` [PATCH 4/4 v2] kvm: powerpc: use caching attributes as per linux pte Bharat Bhushan
2013-10-28 10:34   ` Bharat Bhushan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.