* [RFC PATCH 00/17] Remove slot tracking from linux page table
@ 2017-08-02 5:39 Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 01/17] powerpc/mm: Update native_hpte_find to return hash pte Aneesh Kumar K.V
` (16 more replies)
0 siblings, 17 replies; 19+ messages in thread
From: Aneesh Kumar K.V @ 2017-08-02 5:39 UTC (permalink / raw)
To: benh, paulus, mpe, Anton Blanchard; +Cc: linuxppc-dev, Aneesh Kumar K.V
Hi,
This patch series removes hash pte slot tracking in linux page table.
This free up 4 bits from linux page table and brings the hash and radix
linux page table closer. The series also attempt remove __real_pte_t
because without slot tracking 4k subpage and 64k page , pte formats
are similar.
However not tracking slot implies we search the hash group during invalidate
and updatepp operations. That involves searching max 16 slots to find the
matching hash page table entry. W.r.t subpages, since we don't track the
validity of slots, when invalidating 64K page, we ends up calling invalidate
for all subpages irrespective of whether we have taken a subpage
fault or not.
W.r.t THP, we skip the above and still track slots in level deposited page table.
The patch series do have an impact, hence i am sending this as an RFC series
before doing further measurements with kvm. On baremetal a kernel build gives.
Without patch:
/usr/bin/time -p make vmlinux modules > /dev/null
real 270.70
user 280.23
sys 57.99
With patch
/usr/bin/time -p make vmlinux modules > /dev/null
real 272.97
user 281.32
sys 61.46
That is 6% impact on system time: The real time impact is within the runtime
variance.
Let me know if you think we should continue with this approach.
-aneesh
Aneesh Kumar K.V (17):
powerpc/mm: Update native_hpte_find to return hash pte
powerpc/pseries: Update hpte find helper to take hash value
powerpc/ps3/mm: Add helper for finding hash pte slot using hash value
powerpc/mm: Add hash invalidate callback
powerpc/mm: use hash_invalidate for __kernel_map_pages()
powerpc/mm: Switch flush_hash_range to not use slot
powerpc/mm: Add hash updatepp callback
powerpc/mm/hash: Don't track hash pte slot number in linux page table.
powerpc/mm: Remove unused flag arg in global_invalidates
powerpc/mm: Add new firmware feature HASH API
powerpc/kvm/hash: Implement HASH_REMOVE hcall
powerpc/kvm/hash: Implement HASH_PROTECT hcall
powerpc/kvm/hash: Implement HASH_BULK_REMOVE hcall
powerpc/mm/pseries: Use HASH_PROTECT hcall in guest
powerpc/mm/pseries: Use HASH_REMOVE hcall in guest
powerpc/mm/pseries: Move slot based bulk remove to helper
powerpc/mm/pseries: Use HASH_BULK_REMOVE hcall in guest
arch/powerpc/include/asm/book3s/64/hash-4k.h | 16 +-
arch/powerpc/include/asm/book3s/64/hash-64k.h | 44 +--
arch/powerpc/include/asm/book3s/64/hash.h | 5 +-
arch/powerpc/include/asm/book3s/64/mmu-hash.h | 12 +
arch/powerpc/include/asm/book3s/64/pgtable.h | 26 --
arch/powerpc/include/asm/book3s/64/tlbflush-hash.h | 3 +-
arch/powerpc/include/asm/firmware.h | 3 +-
arch/powerpc/include/asm/hvcall.h | 5 +-
arch/powerpc/include/asm/pgtable-be-types.h | 10 -
arch/powerpc/include/asm/pgtable-types.h | 9 -
arch/powerpc/include/asm/plpar_wrappers.h | 23 ++
arch/powerpc/kvm/book3s_hv.c | 3 +
arch/powerpc/kvm/book3s_hv_rm_mmu.c | 306 ++++++++++++++++++---
arch/powerpc/kvm/book3s_hv_rmhandlers.S | 4 +
arch/powerpc/kvm/powerpc.c | 4 +
arch/powerpc/mm/dump_linuxpagetables.c | 10 -
arch/powerpc/mm/hash64_4k.c | 9 +-
arch/powerpc/mm/hash64_64k.c | 108 ++------
arch/powerpc/mm/hash_native_64.c | 172 ++++++++----
arch/powerpc/mm/hash_utils_64.c | 65 +----
arch/powerpc/mm/hugetlbpage-hash64.c | 13 +-
arch/powerpc/mm/tlb_hash64.c | 9 +-
arch/powerpc/platforms/ps3/htab.c | 88 ++++++
arch/powerpc/platforms/pseries/firmware.c | 1 +
arch/powerpc/platforms/pseries/lpar.c | 193 ++++++++++---
include/uapi/linux/kvm.h | 1 +
26 files changed, 736 insertions(+), 406 deletions(-)
--
2.13.3
^ permalink raw reply [flat|nested] 19+ messages in thread
* [RFC PATCH 01/17] powerpc/mm: Update native_hpte_find to return hash pte
2017-08-02 5:39 [RFC PATCH 00/17] Remove slot tracking from linux page table Aneesh Kumar K.V
@ 2017-08-02 5:40 ` Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 02/17] powerpc/pseries: Update hpte find helper to take hash value Aneesh Kumar K.V
` (15 subsequent siblings)
16 siblings, 0 replies; 19+ messages in thread
From: Aneesh Kumar K.V @ 2017-08-02 5:40 UTC (permalink / raw)
To: benh, paulus, mpe, Anton Blanchard; +Cc: linuxppc-dev, Aneesh Kumar K.V
The helper now also does a secondary hash search so that we can use this in other
functions.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/powerpc/mm/hash_native_64.c | 70 +++++++++++++++++++++++-----------------
1 file changed, 40 insertions(+), 30 deletions(-)
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index 3848af167df9..4b3f6d66e7f0 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -351,32 +351,44 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
return ret;
}
-static long native_hpte_find(unsigned long vpn, int psize, int ssize)
+/* returns a locked hash pte */
+struct hash_pte *native_hpte_find(unsigned long hash, unsigned long vpn,
+ unsigned long bpsize, unsigned long ssize)
{
+ int i;
+ unsigned long hpte_v;
struct hash_pte *hptep;
- unsigned long hash;
- unsigned long i;
- long slot;
- unsigned long want_v, hpte_v;
-
- hash = hpt_hash(vpn, mmu_psize_defs[psize].shift, ssize);
- want_v = hpte_encode_avpn(vpn, psize, ssize);
+ unsigned long want_v, slot;
+ bool secondary_search = false;
- /* Bolted mappings are only ever in the primary group */
+ want_v = hpte_encode_avpn(vpn, bpsize, ssize);
slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
- for (i = 0; i < HPTES_PER_GROUP; i++) {
- hptep = htab_address + slot;
+
+ /*
+ * search for hpte in the primary group
+ */
+search_again:
+ hptep = htab_address + slot;
+ for (i = 0; i < HPTES_PER_GROUP; i++, hptep++) {
+ /*
+ * FIXME!! Should we check locklessly check first ?
+ */
+ native_lock_hpte(hptep);
hpte_v = be64_to_cpu(hptep->v);
if (cpu_has_feature(CPU_FTR_ARCH_300))
hpte_v = hpte_new_to_old_v(hpte_v, be64_to_cpu(hptep->r));
-
- if (HPTE_V_COMPARE(hpte_v, want_v) && (hpte_v & HPTE_V_VALID))
- /* HPTE matches */
- return slot;
- ++slot;
+ if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID))
+ native_unlock_hpte(hptep);
+ else
+ return hptep;
}
-
- return -1;
+ if (!secondary_search) {
+ /* Search for hpte in the secondary group */
+ slot = (~hash & htab_hash_mask) * HPTES_PER_GROUP;
+ secondary_search = true;
+ goto search_again;
+ }
+ return NULL;
}
/*
@@ -389,23 +401,22 @@ static long native_hpte_find(unsigned long vpn, int psize, int ssize)
static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
int psize, int ssize)
{
- unsigned long vpn;
- unsigned long vsid;
- long slot;
+ unsigned long hash;
+ unsigned long vpn, vsid;
struct hash_pte *hptep;
vsid = get_kernel_vsid(ea, ssize);
vpn = hpt_vpn(ea, vsid, ssize);
-
- slot = native_hpte_find(vpn, psize, ssize);
- if (slot == -1)
+ hash = hpt_hash(vpn, mmu_psize_defs[psize].shift, ssize);
+ hptep = native_hpte_find(hash, vpn, psize, ssize);
+ if (!hptep)
panic("could not find page to bolt\n");
- hptep = htab_address + slot;
/* Update the HPTE */
hptep->r = cpu_to_be64((be64_to_cpu(hptep->r) &
~(HPTE_R_PPP | HPTE_R_N)) |
(newpp & (HPTE_R_PPP | HPTE_R_N)));
+ native_unlock_hpte(hptep);
/*
* Ensure it is out of the tlb too. Bolted entries base and
* actual page size will be same.
@@ -422,18 +433,17 @@ static int native_hpte_removebolted(unsigned long ea, int psize, int ssize)
{
unsigned long vpn;
unsigned long vsid;
- long slot;
+ unsigned long hash;
struct hash_pte *hptep;
vsid = get_kernel_vsid(ea, ssize);
vpn = hpt_vpn(ea, vsid, ssize);
+ hash = hpt_hash(vpn, mmu_psize_defs[psize].shift, ssize);
- slot = native_hpte_find(vpn, psize, ssize);
- if (slot == -1)
+ hptep = native_hpte_find(hash, vpn, psize, ssize);
+ if (!hptep)
return -ENOENT;
- hptep = htab_address + slot;
-
VM_WARN_ON(!(be64_to_cpu(hptep->v) & HPTE_V_BOLTED));
/* Invalidate the hpte */
--
2.13.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 02/17] powerpc/pseries: Update hpte find helper to take hash value
2017-08-02 5:39 [RFC PATCH 00/17] Remove slot tracking from linux page table Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 01/17] powerpc/mm: Update native_hpte_find to return hash pte Aneesh Kumar K.V
@ 2017-08-02 5:40 ` Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 03/17] powerpc/ps3/mm: Add helper for finding hash pte slot using " Aneesh Kumar K.V
` (14 subsequent siblings)
16 siblings, 0 replies; 19+ messages in thread
From: Aneesh Kumar K.V @ 2017-08-02 5:40 UTC (permalink / raw)
To: benh, paulus, mpe, Anton Blanchard; +Cc: linuxppc-dev, Aneesh Kumar K.V
The helper now also does secondary hash search so that we can use this in other
functions.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/powerpc/platforms/pseries/lpar.c | 28 +++++++++++++++++-----------
1 file changed, 17 insertions(+), 11 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 495ba4e7336d..edab68d9f9f3 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -328,15 +328,21 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot,
return 0;
}
-static long __pSeries_lpar_hpte_find(unsigned long want_v, unsigned long hpte_group)
+static long __pSeries_lpar_hpte_find(unsigned long hash, unsigned long want_v)
{
long lpar_rc;
unsigned long i, j;
+ unsigned long hpte_group;
+ bool secondary_search = false;
struct {
unsigned long pteh;
unsigned long ptel;
} ptes[4];
+ /* first check primary */
+ hpte_group = (hash & htab_hash_mask) * HPTES_PER_GROUP;
+
+search_again:
for (i = 0; i < HPTES_PER_GROUP; i += 4, hpte_group += 4) {
lpar_rc = plpar_pte_read_4(0, hpte_group, (void *)ptes);
@@ -346,31 +352,31 @@ static long __pSeries_lpar_hpte_find(unsigned long want_v, unsigned long hpte_gr
for (j = 0; j < 4; j++) {
if (HPTE_V_COMPARE(ptes[j].pteh, want_v) &&
(ptes[j].pteh & HPTE_V_VALID))
- return i + j;
+ return hpte_group + j;
}
}
-
+ if (!secondary_search) {
+ hpte_group = (~hash & htab_hash_mask) * HPTES_PER_GROUP;
+ secondary_search = true;
+ goto search_again;
+ }
return -1;
}
static long pSeries_lpar_hpte_find(unsigned long vpn, int psize, int ssize)
{
long slot;
- unsigned long hash;
- unsigned long want_v;
- unsigned long hpte_group;
+ unsigned long hash, want_v;
hash = hpt_hash(vpn, mmu_psize_defs[psize].shift, ssize);
want_v = hpte_encode_avpn(vpn, psize, ssize);
-
- /* Bolted entries are always in the primary group */
- hpte_group = (hash & htab_hash_mask) * HPTES_PER_GROUP;
- slot = __pSeries_lpar_hpte_find(want_v, hpte_group);
+ slot = __pSeries_lpar_hpte_find(hash, want_v);
if (slot < 0)
return -1;
- return hpte_group + slot;
+ return slot;
}
+
static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
unsigned long ea,
int psize, int ssize)
--
2.13.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 03/17] powerpc/ps3/mm: Add helper for finding hash pte slot using hash value
2017-08-02 5:39 [RFC PATCH 00/17] Remove slot tracking from linux page table Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 01/17] powerpc/mm: Update native_hpte_find to return hash pte Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 02/17] powerpc/pseries: Update hpte find helper to take hash value Aneesh Kumar K.V
@ 2017-08-02 5:40 ` Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 04/17] powerpc/mm: Add hash invalidate callback Aneesh Kumar K.V
` (13 subsequent siblings)
16 siblings, 0 replies; 19+ messages in thread
From: Aneesh Kumar K.V @ 2017-08-02 5:40 UTC (permalink / raw)
To: benh, paulus, mpe, Anton Blanchard; +Cc: linuxppc-dev, Aneesh Kumar K.V
We will use this in later patch.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/powerpc/platforms/ps3/htab.c | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c
index cc2b281a3766..255b7a33fefe 100644
--- a/arch/powerpc/platforms/ps3/htab.c
+++ b/arch/powerpc/platforms/ps3/htab.c
@@ -193,6 +193,43 @@ static void ps3_hpte_clear(void)
ps3_mm_vas_destroy();
}
+static long ps3_hpte_find(unsigned long hash, unsigned long want_v)
+{
+ unsigned long i, j, result;
+ unsigned long hpte_group;
+ bool secondary_search = false;
+ u64 hpte_v_array[4], hpte_rs;
+
+
+ /* first check primary */
+ hpte_group = (hash & htab_hash_mask) * HPTES_PER_GROUP;
+
+search_again:
+ for (i = 0; i < HPTES_PER_GROUP; i += 4, hpte_group += 4) {
+
+ result = lv1_read_htab_entries(PS3_LPAR_VAS_ID_CURRENT,
+ hpte_group & ~0x3UL, &hpte_v_array[0],
+ &hpte_v_array[1], &hpte_v_array[2],
+ &hpte_v_array[3], &hpte_rs);
+ /* ignore failures ? */
+ if (result)
+ continue;
+
+ for (j = 0; j < 4; j++) {
+ if (HPTE_V_COMPARE(hpte_v_array[j], want_v) &&
+ (hpte_v_array[j] & HPTE_V_VALID)) {
+ return hpte_group + j;
+ }
+ }
+ }
+ if (!secondary_search) {
+ hpte_group = (~hash & htab_hash_mask) * HPTES_PER_GROUP;
+ secondary_search = true;
+ goto search_again;
+ }
+ return -1;
+}
+
void __init ps3_hpte_init(unsigned long htab_size)
{
mmu_hash_ops.hpte_invalidate = ps3_hpte_invalidate;
--
2.13.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 04/17] powerpc/mm: Add hash invalidate callback
2017-08-02 5:39 [RFC PATCH 00/17] Remove slot tracking from linux page table Aneesh Kumar K.V
` (2 preceding siblings ...)
2017-08-02 5:40 ` [RFC PATCH 03/17] powerpc/ps3/mm: Add helper for finding hash pte slot using " Aneesh Kumar K.V
@ 2017-08-02 5:40 ` Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 05/17] powerpc/mm: use hash_invalidate for __kernel_map_pages() Aneesh Kumar K.V
` (12 subsequent siblings)
16 siblings, 0 replies; 19+ messages in thread
From: Aneesh Kumar K.V @ 2017-08-02 5:40 UTC (permalink / raw)
To: benh, paulus, mpe, Anton Blanchard; +Cc: linuxppc-dev, Aneesh Kumar K.V
Add hash based invalidate callback and use that in flush_hash_page.
Note: In a later patch, we will drop the slot tracking completely. At that point
we will also loose the __rpte_sub_valid() check in
pte_iterate_hashed_subpages(). That means we call the invalidate for all
subpages irrespective of whether we took a hash fault on that or not.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/book3s/64/mmu-hash.h | 4 ++++
arch/powerpc/mm/hash_native_64.c | 27 +++++++++++++++++++++++++++
arch/powerpc/mm/hash_utils_64.c | 11 +++--------
arch/powerpc/platforms/ps3/htab.c | 22 ++++++++++++++++++++++
arch/powerpc/platforms/pseries/lpar.c | 26 ++++++++++++++++++++++++++
5 files changed, 82 insertions(+), 8 deletions(-)
diff --git a/arch/powerpc/include/asm/book3s/64/mmu-hash.h b/arch/powerpc/include/asm/book3s/64/mmu-hash.h
index f9cce40a4035..7e1fcae472f0 100644
--- a/arch/powerpc/include/asm/book3s/64/mmu-hash.h
+++ b/arch/powerpc/include/asm/book3s/64/mmu-hash.h
@@ -135,6 +135,10 @@ struct mmu_hash_ops {
unsigned long vpn,
int bpsize, int apsize,
int ssize, int local);
+ void (*hash_invalidate)(unsigned long hash,
+ unsigned long vpn,
+ int bpsize, int apsize,
+ int ssize, int local);
long (*hpte_updatepp)(unsigned long slot,
unsigned long newpp,
unsigned long vpn,
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index 4b3f6d66e7f0..ce25e125dd06 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -492,6 +492,32 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long vpn,
local_irq_restore(flags);
}
+static void native_hash_invalidate(unsigned long hash, unsigned long vpn,
+ int bpsize, int apsize, int ssize, int local)
+{
+ unsigned long flags;
+ struct hash_pte *hptep;
+
+ DBG_LOW(" invalidate(vpn=%016lx, hash: %lx)\n", vpn, hash);
+ local_irq_save(flags);
+ hptep = native_hpte_find(hash, vpn, bpsize, ssize);
+ if (hptep) {
+ /*
+ * Invalidate the hpte. NOTE: this also unlocks it
+ */
+ hptep->v = 0;
+ }
+ /*
+ * We need to invalidate the TLB always because hpte_remove doesn't do
+ * a tlb invalidate. If a hash bucket gets full, we "evict" a more/less
+ * random entry from it. When we do that we don't invalidate the TLB
+ * (hpte_remove) because we assume the old translation is still
+ * technically "valid".
+ */
+ tlbie(vpn, bpsize, apsize, ssize, local);
+ local_irq_restore(flags);
+}
+
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
static void native_hugepage_invalidate(unsigned long vsid,
unsigned long addr,
@@ -771,6 +797,7 @@ static int native_register_proc_table(unsigned long base, unsigned long page_siz
void __init hpte_init_native(void)
{
mmu_hash_ops.hpte_invalidate = native_hpte_invalidate;
+ mmu_hash_ops.hash_invalidate = native_hash_invalidate;
mmu_hash_ops.hpte_updatepp = native_hpte_updatepp;
mmu_hash_ops.hpte_updateboltedpp = native_hpte_updateboltedpp;
mmu_hash_ops.hpte_removebolted = native_hpte_removebolted;
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index ff3c9522a2b3..a02570b4cfed 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -1598,23 +1598,18 @@ static inline void tm_flush_hash_page(int local)
void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, int ssize,
unsigned long flags)
{
- unsigned long hash, index, shift, hidx, slot;
+ unsigned long hash, index, shift;
int local = flags & HPTE_LOCAL_UPDATE;
DBG_LOW("flush_hash_page(vpn=%016lx)\n", vpn);
pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) {
hash = hpt_hash(vpn, shift, ssize);
- hidx = __rpte_to_hidx(pte, index);
- if (hidx & _PTEIDX_SECONDARY)
- hash = ~hash;
- slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
- slot += hidx & _PTEIDX_GROUP_IX;
- DBG_LOW(" sub %ld: hash=%lx, hidx=%lx\n", index, slot, hidx);
+ DBG_LOW(" sub %ld: hash=%lx\n", index, hash);
/*
* We use same base page size and actual psize, because we don't
* use these functions for hugepage
*/
- mmu_hash_ops.hpte_invalidate(slot, vpn, psize, psize,
+ mmu_hash_ops.hash_invalidate(hash, vpn, psize, psize,
ssize, local);
} pte_iterate_hashed_end();
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c
index 255b7a33fefe..813c2f77f75d 100644
--- a/arch/powerpc/platforms/ps3/htab.c
+++ b/arch/powerpc/platforms/ps3/htab.c
@@ -230,9 +230,31 @@ static long ps3_hpte_find(unsigned long hash, unsigned long want_v)
return -1;
}
+static void ps3_hash_invalidate(unsigned long hash, unsigned long vpn,
+ int psize, int apsize, int ssize, int local)
+{
+ long slot;
+ unsigned long flags;
+ unsigned long want_v;
+
+ want_v = hpte_encode_avpn(vpn, psize, ssize);
+
+ spin_lock_irqsave(&ps3_htab_lock, flags);
+ slot = ps3_hpte_find(hash, want_v);
+ if (slot < 0)
+ /* HPTE not found */
+ goto err_out;
+ /* invalidate the entry */
+ lv1_write_htab_entry(PS3_LPAR_VAS_ID_CURRENT, slot, 0, 0);
+err_out:
+ spin_unlock_irqrestore(&ps3_htab_lock, flags);
+ return;
+}
+
void __init ps3_hpte_init(unsigned long htab_size)
{
mmu_hash_ops.hpte_invalidate = ps3_hpte_invalidate;
+ mmu_hash_ops.hash_invalidate = ps3_hash_invalidate;
mmu_hash_ops.hpte_updatepp = ps3_hpte_updatepp;
mmu_hash_ops.hpte_updateboltedpp = ps3_hpte_updateboltedpp;
mmu_hash_ops.hpte_insert = ps3_hpte_insert;
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index edab68d9f9f3..e366252e0e93 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -419,6 +419,31 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long vpn,
BUG_ON(lpar_rc != H_SUCCESS);
}
+static void pSeries_lpar_hash_invalidate(unsigned long hash, unsigned long vpn,
+ int psize, int apsize,
+ int ssize, int local)
+{
+ long slot;
+ unsigned long want_v;
+ unsigned long lpar_rc;
+ unsigned long dummy1, dummy2;
+
+ pr_devel(" inval : hash=%lx, vpn=%016lx, psize: %d, local: %d\n",
+ hash, vpn, psize, local);
+
+ want_v = hpte_encode_avpn(vpn, psize, ssize);
+ slot = __pSeries_lpar_hpte_find(hash, want_v);
+ if (slot < 0)
+ /* HPTE not found */
+ return;
+ lpar_rc = plpar_pte_remove(H_AVPN, slot, want_v, &dummy1, &dummy2);
+ if (lpar_rc == H_NOT_FOUND)
+ return;
+
+ BUG_ON(lpar_rc != H_SUCCESS);
+}
+
+
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
/*
* Limit iterations holding pSeries_lpar_tlbie_lock to 3. We also need
@@ -758,6 +783,7 @@ static int pseries_lpar_register_process_table(unsigned long base,
void __init hpte_init_pseries(void)
{
mmu_hash_ops.hpte_invalidate = pSeries_lpar_hpte_invalidate;
+ mmu_hash_ops.hash_invalidate = pSeries_lpar_hash_invalidate;
mmu_hash_ops.hpte_updatepp = pSeries_lpar_hpte_updatepp;
mmu_hash_ops.hpte_updateboltedpp = pSeries_lpar_hpte_updateboltedpp;
mmu_hash_ops.hpte_insert = pSeries_lpar_hpte_insert;
--
2.13.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 05/17] powerpc/mm: use hash_invalidate for __kernel_map_pages()
2017-08-02 5:39 [RFC PATCH 00/17] Remove slot tracking from linux page table Aneesh Kumar K.V
` (3 preceding siblings ...)
2017-08-02 5:40 ` [RFC PATCH 04/17] powerpc/mm: Add hash invalidate callback Aneesh Kumar K.V
@ 2017-08-02 5:40 ` Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 06/17] powerpc/mm: Switch flush_hash_range to not use slot Aneesh Kumar K.V
` (11 subsequent siblings)
16 siblings, 0 replies; 19+ messages in thread
From: Aneesh Kumar K.V @ 2017-08-02 5:40 UTC (permalink / raw)
To: benh, paulus, mpe, Anton Blanchard; +Cc: linuxppc-dev, Aneesh Kumar K.V
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/powerpc/mm/hash_utils_64.c | 32 +++++---------------------------
1 file changed, 5 insertions(+), 27 deletions(-)
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index a02570b4cfed..66f12b48f838 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -118,11 +118,6 @@ EXPORT_SYMBOL_GPL(mmu_slb_size);
#ifdef CONFIG_PPC_64K_PAGES
int mmu_ci_restrictions;
#endif
-#ifdef CONFIG_DEBUG_PAGEALLOC
-static u8 *linear_map_hash_slots;
-static unsigned long linear_map_hash_count;
-static DEFINE_SPINLOCK(linear_map_hash_lock);
-#endif /* CONFIG_DEBUG_PAGEALLOC */
struct mmu_hash_ops mmu_hash_ops;
EXPORT_SYMBOL(mmu_hash_ops);
@@ -1746,7 +1741,7 @@ long hpte_insert_repeating(unsigned long hash, unsigned long vpn,
}
#ifdef CONFIG_DEBUG_PAGEALLOC
-static void kernel_map_linear_page(unsigned long vaddr, unsigned long lmi)
+static void kernel_map_linear_page(unsigned long vaddr)
{
unsigned long hash;
unsigned long vsid = get_kernel_vsid(vaddr, mmu_kernel_ssize);
@@ -1763,12 +1758,7 @@ static void kernel_map_linear_page(unsigned long vaddr, unsigned long lmi)
ret = hpte_insert_repeating(hash, vpn, __pa(vaddr), mode,
HPTE_V_BOLTED,
mmu_linear_psize, mmu_kernel_ssize);
-
BUG_ON (ret < 0);
- spin_lock(&linear_map_hash_lock);
- BUG_ON(linear_map_hash_slots[lmi] & 0x80);
- linear_map_hash_slots[lmi] = ret | 0x80;
- spin_unlock(&linear_map_hash_lock);
}
static void kernel_unmap_linear_page(unsigned long vaddr, unsigned long lmi)
@@ -1778,35 +1768,23 @@ static void kernel_unmap_linear_page(unsigned long vaddr, unsigned long lmi)
unsigned long vpn = hpt_vpn(vaddr, vsid, mmu_kernel_ssize);
hash = hpt_hash(vpn, PAGE_SHIFT, mmu_kernel_ssize);
- spin_lock(&linear_map_hash_lock);
- BUG_ON(!(linear_map_hash_slots[lmi] & 0x80));
- hidx = linear_map_hash_slots[lmi] & 0x7f;
- linear_map_hash_slots[lmi] = 0;
- spin_unlock(&linear_map_hash_lock);
- if (hidx & _PTEIDX_SECONDARY)
- hash = ~hash;
- slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
- slot += hidx & _PTEIDX_GROUP_IX;
- mmu_hash_ops.hpte_invalidate(slot, vpn, mmu_linear_psize,
+ mmu_hash_ops.hash_invalidate(hash, vpn, mmu_linear_psize,
mmu_linear_psize,
mmu_kernel_ssize, 0);
}
void __kernel_map_pages(struct page *page, int numpages, int enable)
{
- unsigned long flags, vaddr, lmi;
+ unsigned long flags, vaddr;
int i;
local_irq_save(flags);
for (i = 0; i < numpages; i++, page++) {
vaddr = (unsigned long)page_address(page);
- lmi = __pa(vaddr) >> PAGE_SHIFT;
- if (lmi >= linear_map_hash_count)
- continue;
if (enable)
- kernel_map_linear_page(vaddr, lmi);
+ kernel_map_linear_page(vaddr);
else
- kernel_unmap_linear_page(vaddr, lmi);
+ kernel_unmap_linear_page(vaddr);
}
local_irq_restore(flags);
}
--
2.13.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 06/17] powerpc/mm: Switch flush_hash_range to not use slot
2017-08-02 5:39 [RFC PATCH 00/17] Remove slot tracking from linux page table Aneesh Kumar K.V
` (4 preceding siblings ...)
2017-08-02 5:40 ` [RFC PATCH 05/17] powerpc/mm: use hash_invalidate for __kernel_map_pages() Aneesh Kumar K.V
@ 2017-08-02 5:40 ` Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 07/17] powerpc/mm: Add hash updatepp callback Aneesh Kumar K.V
` (10 subsequent siblings)
16 siblings, 0 replies; 19+ messages in thread
From: Aneesh Kumar K.V @ 2017-08-02 5:40 UTC (permalink / raw)
To: benh, paulus, mpe, Anton Blanchard; +Cc: linuxppc-dev, Aneesh Kumar K.V
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/powerpc/mm/hash_native_64.c | 28 ++++++++--------------------
arch/powerpc/platforms/pseries/lpar.c | 13 ++++---------
2 files changed, 12 insertions(+), 29 deletions(-)
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index ce25e125dd06..c3fdd684a287 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -702,10 +702,8 @@ static void native_hpte_clear(void)
static void native_flush_hash_range(unsigned long number, int local)
{
unsigned long vpn;
- unsigned long hash, index, hidx, shift, slot;
+ unsigned long hash, index, shift;
struct hash_pte *hptep;
- unsigned long hpte_v;
- unsigned long want_v;
unsigned long flags;
real_pte_t pte;
struct ppc64_tlb_batch *batch = this_cpu_ptr(&ppc64_tlb_batch);
@@ -725,23 +723,13 @@ static void native_flush_hash_range(unsigned long number, int local)
pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) {
hash = hpt_hash(vpn, shift, ssize);
- hidx = __rpte_to_hidx(pte, index);
- if (hidx & _PTEIDX_SECONDARY)
- hash = ~hash;
- slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
- slot += hidx & _PTEIDX_GROUP_IX;
- hptep = htab_address + slot;
- want_v = hpte_encode_avpn(vpn, psize, ssize);
- native_lock_hpte(hptep);
- hpte_v = be64_to_cpu(hptep->v);
- if (cpu_has_feature(CPU_FTR_ARCH_300))
- hpte_v = hpte_new_to_old_v(hpte_v,
- be64_to_cpu(hptep->r));
- if (!HPTE_V_COMPARE(hpte_v, want_v) ||
- !(hpte_v & HPTE_V_VALID))
- native_unlock_hpte(hptep);
- else
- hptep->v = 0;
+ hptep = native_hpte_find(hash, vpn, psize, ssize);
+ if (!hptep)
+ continue;
+ /*
+ * Invalidate the hpte. NOTE: this also unlocks it
+ */
+ hptep->v = 0;
} pte_iterate_hashed_end();
}
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index e366252e0e93..ad7838171bb0 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -580,14 +580,14 @@ static int pSeries_lpar_hpte_removebolted(unsigned long ea,
static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
{
unsigned long vpn;
- unsigned long i, pix, rc;
+ unsigned long i, rc;
unsigned long flags = 0;
struct ppc64_tlb_batch *batch = this_cpu_ptr(&ppc64_tlb_batch);
int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
unsigned long param[PLPAR_HCALL9_BUFSIZE];
- unsigned long hash, index, shift, hidx, slot;
+ unsigned long index, shift, slot;
real_pte_t pte;
- int psize, ssize;
+ int psize, ssize, pix;
if (lock_tlbie)
spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags);
@@ -599,12 +599,7 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
vpn = batch->vpn[i];
pte = batch->pte[i];
pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) {
- hash = hpt_hash(vpn, shift, ssize);
- hidx = __rpte_to_hidx(pte, index);
- if (hidx & _PTEIDX_SECONDARY)
- hash = ~hash;
- slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
- slot += hidx & _PTEIDX_GROUP_IX;
+ slot = pSeries_lpar_hpte_find(vpn, psize, ssize);
if (!firmware_has_feature(FW_FEATURE_BULK_REMOVE)) {
/*
* lpar doesn't use the passed actual page size
--
2.13.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 07/17] powerpc/mm: Add hash updatepp callback
2017-08-02 5:39 [RFC PATCH 00/17] Remove slot tracking from linux page table Aneesh Kumar K.V
` (5 preceding siblings ...)
2017-08-02 5:40 ` [RFC PATCH 06/17] powerpc/mm: Switch flush_hash_range to not use slot Aneesh Kumar K.V
@ 2017-08-02 5:40 ` Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 08/17] powerpc/mm/hash: Don't track hash pte slot number in linux page table Aneesh Kumar K.V
` (9 subsequent siblings)
16 siblings, 0 replies; 19+ messages in thread
From: Aneesh Kumar K.V @ 2017-08-02 5:40 UTC (permalink / raw)
To: benh, paulus, mpe, Anton Blanchard; +Cc: linuxppc-dev, Aneesh Kumar K.V
Add hash based updatepp callback and use that during hash pte fault.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/book3s/64/mmu-hash.h | 6 +++++
arch/powerpc/mm/hash64_4k.c | 7 +----
arch/powerpc/mm/hash64_64k.c | 17 +++---------
arch/powerpc/mm/hash_native_64.c | 37 +++++++++++++++++++++++++++
arch/powerpc/mm/hugetlbpage-hash64.c | 9 ++-----
arch/powerpc/platforms/ps3/htab.c | 29 +++++++++++++++++++++
arch/powerpc/platforms/pseries/lpar.c | 31 ++++++++++++++++++++++
7 files changed, 109 insertions(+), 27 deletions(-)
diff --git a/arch/powerpc/include/asm/book3s/64/mmu-hash.h b/arch/powerpc/include/asm/book3s/64/mmu-hash.h
index 7e1fcae472f0..a784d4ac4fb1 100644
--- a/arch/powerpc/include/asm/book3s/64/mmu-hash.h
+++ b/arch/powerpc/include/asm/book3s/64/mmu-hash.h
@@ -144,6 +144,12 @@ struct mmu_hash_ops {
unsigned long vpn,
int bpsize, int apsize,
int ssize, unsigned long flags);
+ long (*hash_updatepp)(unsigned long hash,
+ unsigned long newpp,
+ unsigned long vpn,
+ int bpsize, int apsize,
+ int ssize, unsigned long flags);
+
void (*hpte_updateboltedpp)(unsigned long newpp,
unsigned long ea,
int psize, int ssize);
diff --git a/arch/powerpc/mm/hash64_4k.c b/arch/powerpc/mm/hash64_4k.c
index 6fa450c12d6d..d262d814ca55 100644
--- a/arch/powerpc/mm/hash64_4k.c
+++ b/arch/powerpc/mm/hash64_4k.c
@@ -65,12 +65,7 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
* There MIGHT be an HPTE for this pte
*/
hash = hpt_hash(vpn, shift, ssize);
- if (old_pte & H_PAGE_F_SECOND)
- hash = ~hash;
- slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
- slot += (old_pte & H_PAGE_F_GIX) >> H_PAGE_F_GIX_SHIFT;
-
- if (mmu_hash_ops.hpte_updatepp(slot, rflags, vpn, MMU_PAGE_4K,
+ if (mmu_hash_ops.hash_updatepp(hash, rflags, vpn, MMU_PAGE_4K,
MMU_PAGE_4K, ssize, flags) == -1)
old_pte &= ~_PAGE_HPTEFLAGS;
}
diff --git a/arch/powerpc/mm/hash64_64k.c b/arch/powerpc/mm/hash64_64k.c
index 1a68cb19b0e3..2b72f2c5ed10 100644
--- a/arch/powerpc/mm/hash64_64k.c
+++ b/arch/powerpc/mm/hash64_64k.c
@@ -127,17 +127,11 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
int ret;
hash = hpt_hash(vpn, shift, ssize);
- hidx = __rpte_to_hidx(rpte, subpg_index);
- if (hidx & _PTEIDX_SECONDARY)
- hash = ~hash;
- slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
- slot += hidx & _PTEIDX_GROUP_IX;
-
- ret = mmu_hash_ops.hpte_updatepp(slot, rflags, vpn,
+ ret = mmu_hash_ops.hash_updatepp(hash, rflags, vpn,
MMU_PAGE_4K, MMU_PAGE_4K,
ssize, flags);
/*
- *if we failed because typically the HPTE wasn't really here
+ * if we failed because typically the HPTE wasn't really here
* we try an insertion.
*/
if (ret == -1)
@@ -268,12 +262,7 @@ int __hash_page_64K(unsigned long ea, unsigned long access,
* There MIGHT be an HPTE for this pte
*/
hash = hpt_hash(vpn, shift, ssize);
- if (old_pte & H_PAGE_F_SECOND)
- hash = ~hash;
- slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
- slot += (old_pte & H_PAGE_F_GIX) >> H_PAGE_F_GIX_SHIFT;
-
- if (mmu_hash_ops.hpte_updatepp(slot, rflags, vpn, MMU_PAGE_64K,
+ if (mmu_hash_ops.hash_updatepp(hash, rflags, vpn, MMU_PAGE_64K,
MMU_PAGE_64K, ssize,
flags) == -1)
old_pte &= ~_PAGE_HPTEFLAGS;
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index c3fdd684a287..2eaded4680ae 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -391,6 +391,42 @@ struct hash_pte *native_hpte_find(unsigned long hash, unsigned long vpn,
return NULL;
}
+static long native_hash_updatepp(unsigned long hash, unsigned long newpp,
+ unsigned long vpn, int bpsize,
+ int apsize, int ssize, unsigned long flags)
+{
+ int ret = 0;
+ struct hash_pte *hptep;
+ int local = 0;
+
+
+ DBG_LOW(" update(vpn=%016lx, newpp=%lx)", vpn, newpp);
+
+ hptep = native_hpte_find(hash, vpn, bpsize, ssize);
+ if (hptep) {
+ DBG_LOW(" -> hit\n");
+ /* Update the HPTE */
+ hptep->r = cpu_to_be64((be64_to_cpu(hptep->r) &
+ ~(HPTE_R_PPP | HPTE_R_N)) |
+ (newpp & (HPTE_R_PPP | HPTE_R_N |
+ HPTE_R_C)));
+ native_unlock_hpte(hptep);
+ } else {
+ DBG_LOW(" -> miss\n");
+ ret = -1;
+ }
+ /*
+ * Ensure it is out of the tlb too if it is not a nohpte fault
+ */
+ if (!(flags & HPTE_NOHPTE_UPDATE)) {
+ if (flags & HPTE_LOCAL_UPDATE)
+ local = 1;
+ tlbie(vpn, bpsize, apsize, ssize, local);
+ }
+ return ret;
+}
+
+
/*
* Update the page protection bits. Intended to be used to create
* guard pages for kernel data structures on pages which are bolted
@@ -787,6 +823,7 @@ void __init hpte_init_native(void)
mmu_hash_ops.hpte_invalidate = native_hpte_invalidate;
mmu_hash_ops.hash_invalidate = native_hash_invalidate;
mmu_hash_ops.hpte_updatepp = native_hpte_updatepp;
+ mmu_hash_ops.hash_updatepp = native_hash_updatepp;
mmu_hash_ops.hpte_updateboltedpp = native_hpte_updateboltedpp;
mmu_hash_ops.hpte_removebolted = native_hpte_removebolted;
mmu_hash_ops.hpte_insert = native_hpte_insert;
diff --git a/arch/powerpc/mm/hugetlbpage-hash64.c b/arch/powerpc/mm/hugetlbpage-hash64.c
index a84bb44497f9..4eb8c9d2f452 100644
--- a/arch/powerpc/mm/hugetlbpage-hash64.c
+++ b/arch/powerpc/mm/hugetlbpage-hash64.c
@@ -71,15 +71,10 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
/* Check if pte already has an hpte (case 2) */
if (unlikely(old_pte & H_PAGE_HASHPTE)) {
/* There MIGHT be an HPTE for this pte */
- unsigned long hash, slot;
+ unsigned long hash;
hash = hpt_hash(vpn, shift, ssize);
- if (old_pte & H_PAGE_F_SECOND)
- hash = ~hash;
- slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
- slot += (old_pte & H_PAGE_F_GIX) >> H_PAGE_F_GIX_SHIFT;
-
- if (mmu_hash_ops.hpte_updatepp(slot, rflags, vpn, mmu_psize,
+ if (mmu_hash_ops.hash_updatepp(hash, rflags, vpn, mmu_psize,
mmu_psize, ssize, flags) == -1)
old_pte &= ~_PAGE_HPTEFLAGS;
}
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c
index 813c2f77f75d..4e82f7cbd124 100644
--- a/arch/powerpc/platforms/ps3/htab.c
+++ b/arch/powerpc/platforms/ps3/htab.c
@@ -251,11 +251,40 @@ static void ps3_hash_invalidate(unsigned long hash, unsigned long vpn,
return;
}
+static long ps3_hash_updatepp(unsigned long hash,
+ unsigned long newpp, unsigned long vpn,
+ int psize, int apsize, int ssize,
+ unsigned long inv_flags)
+{
+ long slot;
+ unsigned long flags;
+ unsigned long want_v;
+
+ want_v = hpte_encode_avpn(vpn, psize, ssize);
+ spin_lock_irqsave(&ps3_htab_lock, flags);
+
+ slot = ps3_hpte_find(hash, want_v);
+ if (slot < 0)
+ goto err_out;
+ /*
+ * entry found, just invalidate it
+ */
+ lv1_write_htab_entry(PS3_LPAR_VAS_ID_CURRENT, slot, 0, 0);
+ /*
+ * We just invalidate instead of updating pp. Hence
+ * return -1;
+ */
+err_out:
+ spin_unlock_irqrestore(&ps3_htab_lock, flags);
+ return -1;
+}
+
void __init ps3_hpte_init(unsigned long htab_size)
{
mmu_hash_ops.hpte_invalidate = ps3_hpte_invalidate;
mmu_hash_ops.hash_invalidate = ps3_hash_invalidate;
mmu_hash_ops.hpte_updatepp = ps3_hpte_updatepp;
+ mmu_hash_ops.hash_updatepp = ps3_hash_updatepp;
mmu_hash_ops.hpte_updateboltedpp = ps3_hpte_updateboltedpp;
mmu_hash_ops.hpte_insert = ps3_hpte_insert;
mmu_hash_ops.hpte_remove = ps3_hpte_remove;
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index ad7838171bb0..f4970bae5909 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -376,6 +376,36 @@ static long pSeries_lpar_hpte_find(unsigned long vpn, int psize, int ssize)
return slot;
}
+static long pSeries_lpar_hash_updatepp(unsigned long hash,
+ unsigned long newpp,
+ unsigned long vpn,
+ int psize, int apsize,
+ int ssize, unsigned long inv_flags)
+{
+ long slot;
+ unsigned long lpar_rc;
+ unsigned long flags = (newpp & 7) | H_AVPN;
+ unsigned long want_v;
+
+ want_v = hpte_encode_avpn(vpn, psize, ssize);
+
+ pr_devel(" update: avpnv=%016lx, hash=%016lx, f=%lx, psize: %d ...",
+ want_v, hash, flags, psize);
+
+ slot = __pSeries_lpar_hpte_find(hash, want_v);
+ if (slot < 0)
+ return -1;
+
+ lpar_rc = plpar_pte_protect(flags, slot, want_v);
+ if (lpar_rc == H_NOT_FOUND) {
+ pr_devel("not found !\n");
+ return -1;
+ }
+ pr_devel("ok\n");
+ BUG_ON(lpar_rc != H_SUCCESS);
+
+ return 0;
+}
static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
unsigned long ea,
@@ -780,6 +810,7 @@ void __init hpte_init_pseries(void)
mmu_hash_ops.hpte_invalidate = pSeries_lpar_hpte_invalidate;
mmu_hash_ops.hash_invalidate = pSeries_lpar_hash_invalidate;
mmu_hash_ops.hpte_updatepp = pSeries_lpar_hpte_updatepp;
+ mmu_hash_ops.hash_updatepp = pSeries_lpar_hash_updatepp;
mmu_hash_ops.hpte_updateboltedpp = pSeries_lpar_hpte_updateboltedpp;
mmu_hash_ops.hpte_insert = pSeries_lpar_hpte_insert;
mmu_hash_ops.hpte_remove = pSeries_lpar_hpte_remove;
--
2.13.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 08/17] powerpc/mm/hash: Don't track hash pte slot number in linux page table.
2017-08-02 5:39 [RFC PATCH 00/17] Remove slot tracking from linux page table Aneesh Kumar K.V
` (6 preceding siblings ...)
2017-08-02 5:40 ` [RFC PATCH 07/17] powerpc/mm: Add hash updatepp callback Aneesh Kumar K.V
@ 2017-08-02 5:40 ` Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 09/17] powerpc/mm: Remove unused flag arg in global_invalidates Aneesh Kumar K.V
` (8 subsequent siblings)
16 siblings, 0 replies; 19+ messages in thread
From: Aneesh Kumar K.V @ 2017-08-02 5:40 UTC (permalink / raw)
To: benh, paulus, mpe, Anton Blanchard; +Cc: linuxppc-dev, Aneesh Kumar K.V
Now that we have updated all MMU hash operations to work with hash value instead
of slot, remove slot tracking completely. We also remove real_pte because
without slot tracking 4k, 64k and 64k subpages all have similar pte format.
One of the side effect of this is, we now don't track whether we have taken
a fault on 4k subpages on a 64k page config. That means a invalidate will try
to invalidate all the 4k subpages.
To minimize the impact from above THP still track the slot details. With THP we
have 4096 subpages and we want to avoid calling invalidate on all. For THP we
don't track slot details as part of linux page table, but are tracked in the
deposited page table
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/book3s/64/hash-4k.h | 16 +++-
arch/powerpc/include/asm/book3s/64/hash-64k.h | 44 +---------
arch/powerpc/include/asm/book3s/64/hash.h | 5 +-
arch/powerpc/include/asm/book3s/64/pgtable.h | 26 ------
arch/powerpc/include/asm/book3s/64/tlbflush-hash.h | 3 +-
arch/powerpc/include/asm/pgtable-be-types.h | 10 ---
arch/powerpc/include/asm/pgtable-types.h | 9 --
arch/powerpc/mm/dump_linuxpagetables.c | 10 ---
arch/powerpc/mm/hash64_4k.c | 2 -
arch/powerpc/mm/hash64_64k.c | 95 +++++-----------------
arch/powerpc/mm/hash_native_64.c | 12 +--
arch/powerpc/mm/hash_utils_64.c | 22 +----
arch/powerpc/mm/hugetlbpage-hash64.c | 4 -
arch/powerpc/mm/tlb_hash64.c | 9 +-
arch/powerpc/platforms/pseries/lpar.c | 4 +-
15 files changed, 50 insertions(+), 221 deletions(-)
diff --git a/arch/powerpc/include/asm/book3s/64/hash-4k.h b/arch/powerpc/include/asm/book3s/64/hash-4k.h
index 0c4e470571ca..d65dcb5826ff 100644
--- a/arch/powerpc/include/asm/book3s/64/hash-4k.h
+++ b/arch/powerpc/include/asm/book3s/64/hash-4k.h
@@ -17,8 +17,7 @@
#define H_PGD_TABLE_SIZE (sizeof(pgd_t) << H_PGD_INDEX_SIZE)
/* PTE flags to conserve for HPTE identification */
-#define _PAGE_HPTEFLAGS (H_PAGE_BUSY | H_PAGE_HASHPTE | \
- H_PAGE_F_SECOND | H_PAGE_F_GIX)
+#define _PAGE_HPTEFLAGS (H_PAGE_BUSY | H_PAGE_HASHPTE)
/*
* Not supported by 4k linux page size
*/
@@ -27,6 +26,19 @@
#define H_PAGE_COMBO 0x0
#define H_PTE_FRAG_NR 0
#define H_PTE_FRAG_SIZE_SHIFT 0
+
+#define pte_iterate_hashed_subpages(vpn, psize, index, shift) \
+ do { \
+ index = 0; \
+ shift = mmu_psize_defs[psize].shift; \
+
+#define pte_iterate_hashed_end() } while(0)
+/*
+ * We expect this to be called only for user addresses or kernel virtual
+ * addresses other than the linear mapping.
+ */
+#define pte_pagesize_index(mm, addr, pte) MMU_PAGE_4K
+
/*
* On all 4K setups, remap_4k_pfn() equates to remap_pfn_range()
*/
diff --git a/arch/powerpc/include/asm/book3s/64/hash-64k.h b/arch/powerpc/include/asm/book3s/64/hash-64k.h
index 9732837aaae8..ab36323b8a3e 100644
--- a/arch/powerpc/include/asm/book3s/64/hash-64k.h
+++ b/arch/powerpc/include/asm/book3s/64/hash-64k.h
@@ -25,8 +25,7 @@
#define H_PAGE_COMBO_VALID (H_PAGE_F_GIX | H_PAGE_F_SECOND)
/* PTE flags to conserve for HPTE identification */
-#define _PAGE_HPTEFLAGS (H_PAGE_BUSY | H_PAGE_F_SECOND | \
- H_PAGE_F_GIX | H_PAGE_HASHPTE | H_PAGE_COMBO)
+#define _PAGE_HPTEFLAGS (H_PAGE_BUSY | H_PAGE_HASHPTE | H_PAGE_COMBO)
/*
* we support 16 fragments per PTE page of 64K size.
*/
@@ -40,55 +39,16 @@
#ifndef __ASSEMBLY__
#include <asm/errno.h>
-
-/*
- * With 64K pages on hash table, we have a special PTE format that
- * uses a second "half" of the page table to encode sub-page information
- * in order to deal with 64K made of 4K HW pages. Thus we override the
- * generic accessors and iterators here
- */
-#define __real_pte __real_pte
-static inline real_pte_t __real_pte(pte_t pte, pte_t *ptep)
-{
- real_pte_t rpte;
- unsigned long *hidxp;
-
- rpte.pte = pte;
- rpte.hidx = 0;
- if (pte_val(pte) & H_PAGE_COMBO) {
- /*
- * Make sure we order the hidx load against the H_PAGE_COMBO
- * check. The store side ordering is done in __hash_page_4K
- */
- smp_rmb();
- hidxp = (unsigned long *)(ptep + PTRS_PER_PTE);
- rpte.hidx = *hidxp;
- }
- return rpte;
-}
-
-static inline unsigned long __rpte_to_hidx(real_pte_t rpte, unsigned long index)
-{
- if ((pte_val(rpte.pte) & H_PAGE_COMBO))
- return (rpte.hidx >> (index<<2)) & 0xf;
- return (pte_val(rpte.pte) >> H_PAGE_F_GIX_SHIFT) & 0xf;
-}
-
-#define __rpte_to_pte(r) ((r).pte)
-extern bool __rpte_sub_valid(real_pte_t rpte, unsigned long index);
/*
* Trick: we set __end to va + 64k, which happens works for
* a 16M page as well as we want only one iteration
*/
-#define pte_iterate_hashed_subpages(rpte, psize, vpn, index, shift) \
+#define pte_iterate_hashed_subpages(vpn, psize, index, shift) \
do { \
unsigned long __end = vpn + (1UL << (PAGE_SHIFT - VPN_SHIFT)); \
- unsigned __split = (psize == MMU_PAGE_4K || \
- psize == MMU_PAGE_64K_AP); \
shift = mmu_psize_defs[psize].shift; \
for (index = 0; vpn < __end; index++, \
vpn += (1L << (shift - VPN_SHIFT))) { \
- if (!__split || __rpte_sub_valid(rpte, index)) \
do {
#define pte_iterate_hashed_end() } while(0); } } while(0)
diff --git a/arch/powerpc/include/asm/book3s/64/hash.h b/arch/powerpc/include/asm/book3s/64/hash.h
index 36fc7bfe9e11..4b7035f0344d 100644
--- a/arch/powerpc/include/asm/book3s/64/hash.h
+++ b/arch/powerpc/include/asm/book3s/64/hash.h
@@ -8,11 +8,8 @@
*
*/
#define H_PTE_NONE_MASK _PAGE_HPTEFLAGS
-#define H_PAGE_F_GIX_SHIFT 56
#define H_PAGE_BUSY _RPAGE_RSV1 /* software: PTE & hash are busy */
-#define H_PAGE_F_SECOND _RPAGE_RSV2 /* HPTE is in 2ndary HPTEG */
-#define H_PAGE_F_GIX (_RPAGE_RSV3 | _RPAGE_RSV4 | _RPAGE_RPN44)
-#define H_PAGE_HASHPTE _RPAGE_RPN43 /* PTE has associated HPTE */
+#define H_PAGE_HASHPTE _RPAGE_RSV2 /* PTE has associated HPTE */
#ifdef CONFIG_PPC_64K_PAGES
#include <asm/book3s/64/hash-64k.h>
diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h
index f349f5388af6..ce9cb2a2198c 100644
--- a/arch/powerpc/include/asm/book3s/64/pgtable.h
+++ b/arch/powerpc/include/asm/book3s/64/pgtable.h
@@ -315,32 +315,6 @@ extern unsigned long pci_io_base;
#ifndef __ASSEMBLY__
-/*
- * This is the default implementation of various PTE accessors, it's
- * used in all cases except Book3S with 64K pages where we have a
- * concept of sub-pages
- */
-#ifndef __real_pte
-
-#define __real_pte(e,p) ((real_pte_t){(e)})
-#define __rpte_to_pte(r) ((r).pte)
-#define __rpte_to_hidx(r,index) (pte_val(__rpte_to_pte(r)) >> H_PAGE_F_GIX_SHIFT)
-
-#define pte_iterate_hashed_subpages(rpte, psize, va, index, shift) \
- do { \
- index = 0; \
- shift = mmu_psize_defs[psize].shift; \
-
-#define pte_iterate_hashed_end() } while(0)
-
-/*
- * We expect this to be called only for user addresses or kernel virtual
- * addresses other than the linear mapping.
- */
-#define pte_pagesize_index(mm, addr, pte) MMU_PAGE_4K
-
-#endif /* __real_pte */
-
static inline unsigned long pte_update(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, unsigned long clr,
unsigned long set, int huge)
diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h b/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h
index 2f6373144e2c..d9d409b03ce4 100644
--- a/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h
+++ b/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h
@@ -14,7 +14,6 @@ struct ppc64_tlb_batch {
int active;
unsigned long index;
struct mm_struct *mm;
- real_pte_t pte[PPC64_TLB_BATCH_NR];
unsigned long vpn[PPC64_TLB_BATCH_NR];
unsigned int psize;
int ssize;
@@ -51,7 +50,7 @@ static inline void arch_leave_lazy_mmu_mode(void)
#define arch_flush_lazy_mmu_mode() do {} while (0)
-extern void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize,
+extern void flush_hash_page(unsigned long vpn, int psize,
int ssize, unsigned long flags);
extern void flush_hash_range(unsigned long number, int local);
extern void flush_hash_hugepage(unsigned long vsid, unsigned long addr,
diff --git a/arch/powerpc/include/asm/pgtable-be-types.h b/arch/powerpc/include/asm/pgtable-be-types.h
index 9c0f5db5cf46..dc56a214d38a 100644
--- a/arch/powerpc/include/asm/pgtable-be-types.h
+++ b/arch/powerpc/include/asm/pgtable-be-types.h
@@ -72,16 +72,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#define pgprot_val(x) ((x).pgprot)
#define __pgprot(x) ((pgprot_t) { (x) })
-/*
- * With hash config 64k pages additionally define a bigger "real PTE" type that
- * gathers the "second half" part of the PTE for pseudo 64k pages
- */
-#if defined(CONFIG_PPC_64K_PAGES) && defined(CONFIG_PPC_STD_MMU_64)
-typedef struct { pte_t pte; unsigned long hidx; } real_pte_t;
-#else
-typedef struct { pte_t pte; } real_pte_t;
-#endif
-
static inline bool pte_xchg(pte_t *ptep, pte_t old, pte_t new)
{
unsigned long *p = (unsigned long *)ptep;
diff --git a/arch/powerpc/include/asm/pgtable-types.h b/arch/powerpc/include/asm/pgtable-types.h
index 8bd3b13fe2fb..f19e4ad6bb1f 100644
--- a/arch/powerpc/include/asm/pgtable-types.h
+++ b/arch/powerpc/include/asm/pgtable-types.h
@@ -45,15 +45,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#define pgprot_val(x) ((x).pgprot)
#define __pgprot(x) ((pgprot_t) { (x) })
-/*
- * With hash config 64k pages additionally define a bigger "real PTE" type that
- * gathers the "second half" part of the PTE for pseudo 64k pages
- */
-#if defined(CONFIG_PPC_64K_PAGES) && defined(CONFIG_PPC_STD_MMU_64)
-typedef struct { pte_t pte; unsigned long hidx; } real_pte_t;
-#else
-typedef struct { pte_t pte; } real_pte_t;
-#endif
#ifdef CONFIG_PPC_STD_MMU_64
#include <asm/cmpxchg.h>
diff --git a/arch/powerpc/mm/dump_linuxpagetables.c b/arch/powerpc/mm/dump_linuxpagetables.c
index 44fe4833910f..5554df9b77ae 100644
--- a/arch/powerpc/mm/dump_linuxpagetables.c
+++ b/arch/powerpc/mm/dump_linuxpagetables.c
@@ -214,16 +214,6 @@ static const struct flag_info flag_array[] = {
.set = "4K_pfn",
}, {
#endif
- .mask = H_PAGE_F_GIX,
- .val = H_PAGE_F_GIX,
- .set = "f_gix",
- .is_val = true,
- .shift = H_PAGE_F_GIX_SHIFT,
- }, {
- .mask = H_PAGE_F_SECOND,
- .val = H_PAGE_F_SECOND,
- .set = "f_second",
- }, {
#endif
.mask = _PAGE_SPECIAL,
.val = _PAGE_SPECIAL,
diff --git a/arch/powerpc/mm/hash64_4k.c b/arch/powerpc/mm/hash64_4k.c
index d262d814ca55..88e2346ab597 100644
--- a/arch/powerpc/mm/hash64_4k.c
+++ b/arch/powerpc/mm/hash64_4k.c
@@ -113,8 +113,6 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
return -1;
}
new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | H_PAGE_HASHPTE;
- new_pte |= (slot << H_PAGE_F_GIX_SHIFT) &
- (H_PAGE_F_SECOND | H_PAGE_F_GIX);
}
*ptep = __pte(new_pte & ~H_PAGE_BUSY);
return 0;
diff --git a/arch/powerpc/mm/hash64_64k.c b/arch/powerpc/mm/hash64_64k.c
index 2b72f2c5ed10..7325ed8cfe09 100644
--- a/arch/powerpc/mm/hash64_64k.c
+++ b/arch/powerpc/mm/hash64_64k.c
@@ -15,45 +15,15 @@
#include <linux/mm.h>
#include <asm/machdep.h>
#include <asm/mmu.h>
-/*
- * index from 0 - 15
- */
-bool __rpte_sub_valid(real_pte_t rpte, unsigned long index)
-{
- unsigned long g_idx;
- unsigned long ptev = pte_val(rpte.pte);
-
- g_idx = (ptev & H_PAGE_COMBO_VALID) >> H_PAGE_F_GIX_SHIFT;
- index = index >> 2;
- if (g_idx & (0x1 << index))
- return true;
- else
- return false;
-}
-/*
- * index from 0 - 15
- */
-static unsigned long mark_subptegroup_valid(unsigned long ptev, unsigned long index)
-{
- unsigned long g_idx;
-
- if (!(ptev & H_PAGE_COMBO))
- return ptev;
- index = index >> 2;
- g_idx = 0x1 << index;
-
- return ptev | (g_idx << H_PAGE_F_GIX_SHIFT);
-}
int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
pte_t *ptep, unsigned long trap, unsigned long flags,
int ssize, int subpg_prot)
{
- real_pte_t rpte;
- unsigned long *hidxp;
+ int ret;
unsigned long hpte_group;
unsigned int subpg_index;
- unsigned long rflags, pa, hidx;
+ unsigned long rflags, pa;
unsigned long old_pte, new_pte, subpg_pte;
unsigned long vpn, hash, slot;
unsigned long shift = mmu_psize_defs[MMU_PAGE_4K].shift;
@@ -99,7 +69,6 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
subpg_index = (ea & (PAGE_SIZE - 1)) >> shift;
vpn = hpt_vpn(ea, vsid, ssize);
- rpte = __real_pte(__pte(old_pte), ptep);
/*
*None of the sub 4k page is hashed
*/
@@ -110,37 +79,31 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
* as a 64k HW page, and invalidate the 64k HPTE if so.
*/
if (!(old_pte & H_PAGE_COMBO)) {
- flush_hash_page(vpn, rpte, MMU_PAGE_64K, ssize, flags);
- /*
- * clear the old slot details from the old and new pte.
- * On hash insert failure we use old pte value and we don't
- * want slot information there if we have a insert failure.
- */
- old_pte &= ~(H_PAGE_HASHPTE | H_PAGE_F_GIX | H_PAGE_F_SECOND);
- new_pte &= ~(H_PAGE_HASHPTE | H_PAGE_F_GIX | H_PAGE_F_SECOND);
+ flush_hash_page(vpn, MMU_PAGE_64K, ssize, flags);
+ old_pte &= ~H_PAGE_HASHPTE;
+ new_pte &= ~H_PAGE_HASHPTE;
goto htab_insert_hpte;
}
/*
- * Check for sub page valid and update
+ * We are not tracking the validty of 4k entries seperately. Hence
+ * If H_PAGE_HASHPTE is set, we always try an update.
*/
- if (__rpte_sub_valid(rpte, subpg_index)) {
- int ret;
-
- hash = hpt_hash(vpn, shift, ssize);
- ret = mmu_hash_ops.hash_updatepp(hash, rflags, vpn,
- MMU_PAGE_4K, MMU_PAGE_4K,
- ssize, flags);
- /*
- * if we failed because typically the HPTE wasn't really here
- * we try an insertion.
- */
- if (ret == -1)
- goto htab_insert_hpte;
-
+ hash = hpt_hash(vpn, shift, ssize);
+ ret = mmu_hash_ops.hash_updatepp(hash, rflags, vpn,
+ MMU_PAGE_4K, MMU_PAGE_4K,
+ ssize, flags);
+ /*
+ * if we failed because typically the HPTE wasn't really here
+ * we try an insertion.
+ */
+ if (ret != -1) {
*ptep = __pte(new_pte & ~H_PAGE_BUSY);
return 0;
}
-
+ /*
+ * updatepp failed, hash table doesn't have an entry for this,
+ * insert a new entry
+ */
htab_insert_hpte:
/*
* handle H_PAGE_4K_PFN case
@@ -192,21 +155,7 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
MMU_PAGE_4K, MMU_PAGE_4K, old_pte);
return -1;
}
- /*
- * Insert slot number & secondary bit in PTE second half,
- * clear H_PAGE_BUSY and set appropriate HPTE slot bit
- * Since we have H_PAGE_BUSY set on ptep, we can be sure
- * nobody is undating hidx.
- */
- hidxp = (unsigned long *)(ptep + PTRS_PER_PTE);
- rpte.hidx &= ~(0xfUL << (subpg_index << 2));
- *hidxp = rpte.hidx | (slot << (subpg_index << 2));
- new_pte = mark_subptegroup_valid(new_pte, subpg_index);
new_pte |= H_PAGE_HASHPTE;
- /*
- * check __real_pte for details on matching smp_rmb()
- */
- smp_wmb();
*ptep = __pte(new_pte & ~H_PAGE_BUSY);
return 0;
}
@@ -311,9 +260,7 @@ int __hash_page_64K(unsigned long ea, unsigned long access,
MMU_PAGE_64K, MMU_PAGE_64K, old_pte);
return -1;
}
- new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | H_PAGE_HASHPTE;
- new_pte |= (slot << H_PAGE_F_GIX_SHIFT) &
- (H_PAGE_F_SECOND | H_PAGE_F_GIX);
+ new_pte = new_pte | H_PAGE_HASHPTE;
}
*ptep = __pte(new_pte & ~H_PAGE_BUSY);
return 0;
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index 2eaded4680ae..f24ff28e9fab 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -741,7 +741,6 @@ static void native_flush_hash_range(unsigned long number, int local)
unsigned long hash, index, shift;
struct hash_pte *hptep;
unsigned long flags;
- real_pte_t pte;
struct ppc64_tlb_batch *batch = this_cpu_ptr(&ppc64_tlb_batch);
unsigned long psize = batch->psize;
int ssize = batch->ssize;
@@ -755,9 +754,8 @@ static void native_flush_hash_range(unsigned long number, int local)
for (i = 0; i < number; i++) {
vpn = batch->vpn[i];
- pte = batch->pte[i];
- pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) {
+ pte_iterate_hashed_subpages(vpn, psize, index, shift) {
hash = hpt_hash(vpn, shift, ssize);
hptep = native_hpte_find(hash, vpn, psize, ssize);
if (!hptep)
@@ -773,10 +771,8 @@ static void native_flush_hash_range(unsigned long number, int local)
asm volatile("ptesync":::"memory");
for (i = 0; i < number; i++) {
vpn = batch->vpn[i];
- pte = batch->pte[i];
- pte_iterate_hashed_subpages(pte, psize,
- vpn, index, shift) {
+ pte_iterate_hashed_subpages(vpn, psize, index, shift) {
__tlbiel(vpn, psize, psize, ssize);
} pte_iterate_hashed_end();
}
@@ -790,10 +786,8 @@ static void native_flush_hash_range(unsigned long number, int local)
asm volatile("ptesync":::"memory");
for (i = 0; i < number; i++) {
vpn = batch->vpn[i];
- pte = batch->pte[i];
- pte_iterate_hashed_subpages(pte, psize,
- vpn, index, shift) {
+ pte_iterate_hashed_subpages(vpn, psize, index, shift) {
__tlbie(vpn, psize, psize, ssize);
} pte_iterate_hashed_end();
}
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 66f12b48f838..36a8c2dcb820 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -973,21 +973,8 @@ void __init hash__early_init_devtree(void)
void __init hash__early_init_mmu(void)
{
- /*
- * We have code in __hash_page_64K() and elsewhere, which assumes it can
- * do the following:
- * new_pte |= (slot << H_PAGE_F_GIX_SHIFT) & (H_PAGE_F_SECOND | H_PAGE_F_GIX);
- *
- * Where the slot number is between 0-15, and values of 8-15 indicate
- * the secondary bucket. For that code to work H_PAGE_F_SECOND and
- * H_PAGE_F_GIX must occupy four contiguous bits in the PTE, and
- * H_PAGE_F_SECOND must be placed above H_PAGE_F_GIX. Assert that here
- * with a BUILD_BUG_ON().
- */
- BUILD_BUG_ON(H_PAGE_F_SECOND != (1ul << (H_PAGE_F_GIX_SHIFT + 3)));
htab_init_page_sizes();
-
/*
* initialize page table size
*/
@@ -1590,14 +1577,13 @@ static inline void tm_flush_hash_page(int local)
/* WARNING: This is called from hash_low_64.S, if you change this prototype,
* do not forget to update the assembly call site !
*/
-void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, int ssize,
- unsigned long flags)
+void flush_hash_page(unsigned long vpn, int psize, int ssize, unsigned long flags)
{
unsigned long hash, index, shift;
int local = flags & HPTE_LOCAL_UPDATE;
DBG_LOW("flush_hash_page(vpn=%016lx)\n", vpn);
- pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) {
+ pte_iterate_hashed_subpages(vpn, psize, index, shift) {
hash = hpt_hash(vpn, shift, ssize);
DBG_LOW(" sub %ld: hash=%lx\n", index, hash);
/*
@@ -1679,8 +1665,8 @@ void flush_hash_range(unsigned long number, int local)
this_cpu_ptr(&ppc64_tlb_batch);
for (i = 0; i < number; i++)
- flush_hash_page(batch->vpn[i], batch->pte[i],
- batch->psize, batch->ssize, local);
+ flush_hash_page(batch->vpn[i], batch->psize,
+ batch->ssize, local);
}
}
diff --git a/arch/powerpc/mm/hugetlbpage-hash64.c b/arch/powerpc/mm/hugetlbpage-hash64.c
index 4eb8c9d2f452..8aff8d17d91c 100644
--- a/arch/powerpc/mm/hugetlbpage-hash64.c
+++ b/arch/powerpc/mm/hugetlbpage-hash64.c
@@ -100,11 +100,7 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
mmu_psize, mmu_psize, old_pte);
return -1;
}
-
- new_pte |= (slot << H_PAGE_F_GIX_SHIFT) &
- (H_PAGE_F_SECOND | H_PAGE_F_GIX);
}
-
/*
* No need to use ldarx/stdcx here
*/
diff --git a/arch/powerpc/mm/tlb_hash64.c b/arch/powerpc/mm/tlb_hash64.c
index 71cb2742bd16..8cb61f0c9608 100644
--- a/arch/powerpc/mm/tlb_hash64.c
+++ b/arch/powerpc/mm/tlb_hash64.c
@@ -50,7 +50,6 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
unsigned long vsid;
unsigned int psize;
int ssize;
- real_pte_t rpte;
int i;
i = batch->index;
@@ -91,14 +90,13 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
}
WARN_ON(vsid == 0);
vpn = hpt_vpn(addr, vsid, ssize);
- rpte = __real_pte(__pte(pte), ptep);
/*
* Check if we have an active batch on this CPU. If not, just
* flush now and return.
*/
if (!batch->active) {
- flush_hash_page(vpn, rpte, psize, ssize, mm_is_thread_local(mm));
+ flush_hash_page(vpn, psize, ssize, mm_is_thread_local(mm));
put_cpu_var(ppc64_tlb_batch);
return;
}
@@ -123,7 +121,6 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
batch->psize = psize;
batch->ssize = ssize;
}
- batch->pte[i] = rpte;
batch->vpn[i] = vpn;
batch->index = ++i;
if (i >= PPC64_TLB_BATCH_NR)
@@ -148,8 +145,8 @@ void __flush_tlb_pending(struct ppc64_tlb_batch *batch)
if (cpumask_equal(mm_cpumask(batch->mm), tmp))
local = 1;
if (i == 1)
- flush_hash_page(batch->vpn[0], batch->pte[0],
- batch->psize, batch->ssize, local);
+ flush_hash_page(batch->vpn[0], batch->psize,
+ batch->ssize, local);
else
flush_hash_range(i, local);
batch->index = 0;
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index f4970bae5909..e28e62f6afba 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -616,7 +616,6 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
unsigned long param[PLPAR_HCALL9_BUFSIZE];
unsigned long index, shift, slot;
- real_pte_t pte;
int psize, ssize, pix;
if (lock_tlbie)
@@ -627,8 +626,7 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
pix = 0;
for (i = 0; i < number; i++) {
vpn = batch->vpn[i];
- pte = batch->pte[i];
- pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) {
+ pte_iterate_hashed_subpages(vpn, psize, index, shift) {
slot = pSeries_lpar_hpte_find(vpn, psize, ssize);
if (!firmware_has_feature(FW_FEATURE_BULK_REMOVE)) {
/*
--
2.13.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 09/17] powerpc/mm: Remove unused flag arg in global_invalidates
2017-08-02 5:39 [RFC PATCH 00/17] Remove slot tracking from linux page table Aneesh Kumar K.V
` (7 preceding siblings ...)
2017-08-02 5:40 ` [RFC PATCH 08/17] powerpc/mm/hash: Don't track hash pte slot number in linux page table Aneesh Kumar K.V
@ 2017-08-02 5:40 ` Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 10/17] powerpc/mm: Add new firmware feature HASH API Aneesh Kumar K.V
` (7 subsequent siblings)
16 siblings, 0 replies; 19+ messages in thread
From: Aneesh Kumar K.V @ 2017-08-02 5:40 UTC (permalink / raw)
To: benh, paulus, mpe, Anton Blanchard; +Cc: linuxppc-dev, Aneesh Kumar K.V
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/powerpc/kvm/book3s_hv_rm_mmu.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index fedb0139524c..5abaed27708b 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -42,7 +42,7 @@ static void *real_vmalloc_addr(void *x)
}
/* Return 1 if we need to do a global tlbie, 0 if we can use tlbiel */
-static int global_invalidates(struct kvm *kvm, unsigned long flags)
+static int global_invalidates(struct kvm *kvm)
{
int global;
int cpu;
@@ -499,7 +499,7 @@ long kvmppc_do_h_remove(struct kvm *kvm, unsigned long flags,
if (v & HPTE_V_VALID) {
hpte[0] &= ~cpu_to_be64(HPTE_V_VALID);
rb = compute_tlbie_rb(v, pte_r, pte_index);
- do_tlbies(kvm, &rb, 1, global_invalidates(kvm, flags), true);
+ do_tlbies(kvm, &rb, 1, global_invalidates(kvm), true);
/*
* The reference (R) and change (C) bits in a HPT
* entry can be set by hardware at any time up until
@@ -549,7 +549,7 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
if (kvm_is_radix(kvm))
return H_FUNCTION;
- global = global_invalidates(kvm, 0);
+ global = global_invalidates(kvm);
for (i = 0; i < 4 && ret == H_SUCCESS; ) {
n = 0;
for (; i < 4; ++i) {
@@ -709,8 +709,7 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
rb = compute_tlbie_rb(v, r, pte_index);
hpte[0] = cpu_to_be64((pte_v & ~HPTE_V_VALID) |
HPTE_V_ABSENT);
- do_tlbies(kvm, &rb, 1, global_invalidates(kvm, flags),
- true);
+ do_tlbies(kvm, &rb, 1, global_invalidates(kvm), true);
/* Don't lose R/C bit updates done by hardware */
r |= be64_to_cpu(hpte[1]) & (HPTE_R_R | HPTE_R_C);
hpte[1] = cpu_to_be64(r);
--
2.13.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 10/17] powerpc/mm: Add new firmware feature HASH API
2017-08-02 5:39 [RFC PATCH 00/17] Remove slot tracking from linux page table Aneesh Kumar K.V
` (8 preceding siblings ...)
2017-08-02 5:40 ` [RFC PATCH 09/17] powerpc/mm: Remove unused flag arg in global_invalidates Aneesh Kumar K.V
@ 2017-08-02 5:40 ` Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 11/17] powerpc/kvm/hash: Implement HASH_REMOVE hcall Aneesh Kumar K.V
` (6 subsequent siblings)
16 siblings, 0 replies; 19+ messages in thread
From: Aneesh Kumar K.V @ 2017-08-02 5:40 UTC (permalink / raw)
To: benh, paulus, mpe, Anton Blanchard; +Cc: linuxppc-dev, Aneesh Kumar K.V
We will use this feature to check whether hypervisor implements hash based
remove and protect hcalls
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/firmware.h | 3 ++-
arch/powerpc/kvm/powerpc.c | 4 ++++
arch/powerpc/platforms/pseries/firmware.c | 1 +
include/uapi/linux/kvm.h | 1 +
4 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/include/asm/firmware.h b/arch/powerpc/include/asm/firmware.h
index 8645897472b1..152d704ac3c3 100644
--- a/arch/powerpc/include/asm/firmware.h
+++ b/arch/powerpc/include/asm/firmware.h
@@ -51,6 +51,7 @@
#define FW_FEATURE_BEST_ENERGY ASM_CONST(0x0000000080000000)
#define FW_FEATURE_TYPE1_AFFINITY ASM_CONST(0x0000000100000000)
#define FW_FEATURE_PRRN ASM_CONST(0x0000000200000000)
+#define FW_FEATURE_HASH_API ASM_CONST(0x0000000400000000)
#ifndef __ASSEMBLY__
@@ -67,7 +68,7 @@ enum {
FW_FEATURE_CMO | FW_FEATURE_VPHN | FW_FEATURE_XCMO |
FW_FEATURE_SET_MODE | FW_FEATURE_BEST_ENERGY |
FW_FEATURE_TYPE1_AFFINITY | FW_FEATURE_PRRN |
- FW_FEATURE_HPT_RESIZE,
+ FW_FEATURE_HPT_RESIZE | FW_FEATURE_HASH_API,
FW_FEATURE_PSERIES_ALWAYS = 0,
FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL,
FW_FEATURE_POWERNV_ALWAYS = 0,
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 1a75c0b5f4ca..bd551edfa155 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -632,6 +632,10 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
/* Disable this on POWER9 until code handles new HPTE format */
r = !!hv_enabled && !cpu_has_feature(CPU_FTR_ARCH_300);
break;
+ case KVM_CAP_SPAPR_HASH_API:
+ /* Only enable for HV kvm */
+ r = is_kvmppc_hv_enabled(kvm);
+ break;
#endif
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
case KVM_CAP_PPC_FWNMI:
diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c
index 63cc82ad58ac..32081d4406e8 100644
--- a/arch/powerpc/platforms/pseries/firmware.c
+++ b/arch/powerpc/platforms/pseries/firmware.c
@@ -65,6 +65,7 @@ hypertas_fw_features_table[] = {
{FW_FEATURE_SET_MODE, "hcall-set-mode"},
{FW_FEATURE_BEST_ENERGY, "hcall-best-energy-1*"},
{FW_FEATURE_HPT_RESIZE, "hcall-hpt-resize"},
+ {FW_FEATURE_HASH_API, "hcall-hash-api"},
};
/* Build up the firmware features bitmask using the contents of
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 6cd63c18708a..698b202b4c53 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -929,6 +929,7 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_PPC_SMT_POSSIBLE 147
#define KVM_CAP_HYPERV_SYNIC2 148
#define KVM_CAP_HYPERV_VP_INDEX 149
+#define KVM_CAP_SPAPR_HASH_API 150
#ifdef KVM_CAP_IRQ_ROUTING
--
2.13.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 11/17] powerpc/kvm/hash: Implement HASH_REMOVE hcall
2017-08-02 5:39 [RFC PATCH 00/17] Remove slot tracking from linux page table Aneesh Kumar K.V
` (9 preceding siblings ...)
2017-08-02 5:40 ` [RFC PATCH 10/17] powerpc/mm: Add new firmware feature HASH API Aneesh Kumar K.V
@ 2017-08-02 5:40 ` Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 12/17] powerpc/kvm/hash: Implement HASH_PROTECT hcall Aneesh Kumar K.V
` (5 subsequent siblings)
16 siblings, 0 replies; 19+ messages in thread
From: Aneesh Kumar K.V @ 2017-08-02 5:40 UTC (permalink / raw)
To: benh, paulus, mpe, Anton Blanchard; +Cc: linuxppc-dev, Aneesh Kumar K.V
This is equivalent to H_REMOVE hcall, but then takes hash value as the arg
instead of hashpte slot number. We will use this later to speed up invalidate
operation in guest. Instead of finding slot number using H_READ4 hcall, we can
use hash value directly using this hcall.
Only support flag value for the operation is H_AVPN.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/hvcall.h | 3 +-
arch/powerpc/include/asm/plpar_wrappers.h | 16 ++++
arch/powerpc/kvm/book3s_hv.c | 1 +
arch/powerpc/kvm/book3s_hv_rm_mmu.c | 134 ++++++++++++++++++++++++++----
arch/powerpc/kvm/book3s_hv_rmhandlers.S | 2 +
5 files changed, 138 insertions(+), 18 deletions(-)
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index 57d38b504ff7..6a09e91889cf 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -280,7 +280,8 @@
#define H_RESIZE_HPT_COMMIT 0x370
#define H_REGISTER_PROC_TBL 0x37C
#define H_SIGNAL_SYS_RESET 0x380
-#define MAX_HCALL_OPCODE H_SIGNAL_SYS_RESET
+#define H_HASH_REMOVE 0x384
+#define MAX_HCALL_OPCODE H_HASH_REMOVE
/* H_VIOCTL functions */
#define H_GET_VIOA_DUMP_SIZE 0x01
diff --git a/arch/powerpc/include/asm/plpar_wrappers.h b/arch/powerpc/include/asm/plpar_wrappers.h
index c7b164836bc3..8160fea9b5bc 100644
--- a/arch/powerpc/include/asm/plpar_wrappers.h
+++ b/arch/powerpc/include/asm/plpar_wrappers.h
@@ -124,6 +124,22 @@ static inline long plpar_pte_remove(unsigned long flags, unsigned long ptex,
return rc;
}
+static inline long plpar_pte_hash_remove(unsigned long flags, unsigned long hash,
+ unsigned long avpn, unsigned long *old_pteh_ret,
+ unsigned long *old_ptel_ret)
+{
+ long rc;
+ unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+ rc = plpar_hcall(H_HASH_REMOVE, retbuf, flags, hash, avpn);
+
+ *old_pteh_ret = retbuf[0];
+ *old_ptel_ret = retbuf[1];
+
+ return rc;
+}
+
+
/* plpar_pte_remove_raw can be called in real mode. It calls plpar_hcall_raw */
static inline long plpar_pte_remove_raw(unsigned long flags, unsigned long ptex,
unsigned long avpn, unsigned long *old_pteh_ret,
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 0b436df746fc..86c66af38637 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -4144,6 +4144,7 @@ static unsigned int default_hcall_list[] = {
H_XIRR,
H_XIRR_X,
#endif
+ H_HASH_REMOVE,
0
};
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index 5abaed27708b..85fedb72469b 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -465,34 +465,21 @@ static void do_tlbies(struct kvm *kvm, unsigned long *rbvalues,
}
}
-long kvmppc_do_h_remove(struct kvm *kvm, unsigned long flags,
- unsigned long pte_index, unsigned long avpn,
- unsigned long *hpret)
+static long __kvmppc_do_hash_remove(struct kvm *kvm, __be64 *hpte,
+ unsigned long pte_index,
+ unsigned long *hpret)
{
- __be64 *hpte;
+
unsigned long v, r, rb;
struct revmap_entry *rev;
u64 pte, orig_pte, pte_r;
- if (kvm_is_radix(kvm))
- return H_FUNCTION;
- if (pte_index >= kvmppc_hpt_npte(&kvm->arch.hpt))
- return H_PARAMETER;
- hpte = (__be64 *)(kvm->arch.hpt.virt + (pte_index << 4));
- while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
- cpu_relax();
pte = orig_pte = be64_to_cpu(hpte[0]);
pte_r = be64_to_cpu(hpte[1]);
if (cpu_has_feature(CPU_FTR_ARCH_300)) {
pte = hpte_new_to_old_v(pte, pte_r);
pte_r = hpte_new_to_old_r(pte_r);
}
- if ((pte & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
- ((flags & H_AVPN) && (pte & ~0x7fUL) != avpn) ||
- ((flags & H_ANDCOND) && (pte & avpn) != 0)) {
- __unlock_hpte(hpte, orig_pte);
- return H_NOT_FOUND;
- }
rev = real_vmalloc_addr(&kvm->arch.hpt.rev[pte_index]);
v = pte & ~HPTE_V_HVLOCK;
@@ -525,6 +512,35 @@ long kvmppc_do_h_remove(struct kvm *kvm, unsigned long flags,
hpret[1] = r;
return H_SUCCESS;
}
+
+long kvmppc_do_h_remove(struct kvm *kvm, unsigned long flags,
+ unsigned long pte_index, unsigned long avpn,
+ unsigned long *hpret)
+{
+ __be64 *hpte;
+ u64 pte, orig_pte, pte_r;
+
+ if (kvm_is_radix(kvm))
+ return H_FUNCTION;
+ if (pte_index >= kvmppc_hpt_npte(&kvm->arch.hpt))
+ return H_PARAMETER;
+ hpte = (__be64 *)(kvm->arch.hpt.virt + (pte_index << 4));
+ while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
+ cpu_relax();
+ pte = orig_pte = be64_to_cpu(hpte[0]);
+ pte_r = be64_to_cpu(hpte[1]);
+ if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+ pte = hpte_new_to_old_v(pte, pte_r);
+ pte_r = hpte_new_to_old_r(pte_r);
+ }
+ if ((pte & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
+ ((flags & H_AVPN) && (pte & ~0x7fUL) != avpn) ||
+ ((flags & H_ANDCOND) && (pte & avpn) != 0)) {
+ __unlock_hpte(hpte, orig_pte);
+ return H_NOT_FOUND;
+ }
+ return __kvmppc_do_hash_remove(kvm, hpte, pte_index, hpret);
+}
EXPORT_SYMBOL_GPL(kvmppc_do_h_remove);
long kvmppc_h_remove(struct kvm_vcpu *vcpu, unsigned long flags,
@@ -534,6 +550,90 @@ long kvmppc_h_remove(struct kvm_vcpu *vcpu, unsigned long flags,
&vcpu->arch.gpr[4]);
}
+/* return locked hpte */
+static __be64 *kvmppc_find_hpte_slot(struct kvm *kvm, unsigned long hash,
+ unsigned long avpn, unsigned long *pte_index)
+{
+ int i;
+ __be64 *hpte;
+ unsigned long slot;
+ u64 pte_v, orig_pte, pte_r;
+ bool secondary_search = false;
+
+ /*
+ * search for the hpte in primary group
+ */
+ slot = ((hash & kvmppc_hpt_mask(&kvm->arch.hpt)) * HPTES_PER_GROUP) & ~0x7UL;
+
+search_again:
+ hpte = (__be64 *)(kvm->arch.hpt.virt + (slot << 4));
+ for (i = 0; i < HPTES_PER_GROUP; i++ , hpte += 2) {
+ /* lockless search */
+ pte_v = orig_pte = be64_to_cpu(hpte[0]);
+ pte_r = be64_to_cpu(hpte[1]);
+ if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+ pte_v = hpte_new_to_old_v(pte_v, pte_r);
+ pte_r = hpte_new_to_old_r(pte_r);
+ }
+ if ((pte_v & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0)
+ continue;
+
+ if ((pte_v & ~0x7FUL) == avpn) {
+ while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
+ cpu_relax();
+ pte_v = orig_pte = be64_to_cpu(hpte[0]);
+ pte_r = be64_to_cpu(hpte[1]);
+ if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+ pte_v = hpte_new_to_old_v(pte_v, pte_r);
+ pte_r = hpte_new_to_old_r(pte_r);
+ }
+ if ((pte_v & ~0x7FUL) != avpn) {
+ /* unlock and continue */
+ __unlock_hpte(hpte, orig_pte);
+ continue;
+ }
+ *pte_index = slot + i;
+ return hpte;
+ }
+ }
+ if (!secondary_search) {
+ secondary_search = true;
+ slot = ((~hash & kvmppc_hpt_mask(&kvm->arch.hpt)) * HPTES_PER_GROUP) & ~0x7UL;
+ goto search_again;
+ }
+ return NULL;
+}
+
+/* Only support H_AVPN flag, which is must */
+long kvmppc_do_h_hash_remove(struct kvm *kvm, unsigned long flags,
+ unsigned long hash, unsigned long avpn,
+ unsigned long *hpret)
+{
+ __be64 *hpte;
+ unsigned long pte_index;
+
+
+ if (kvm_is_radix(kvm))
+ return H_FUNCTION;
+
+ if ((flags & H_AVPN) != H_AVPN)
+ return H_PARAMETER;
+
+ hpte = kvmppc_find_hpte_slot(kvm, hash, avpn, &pte_index);
+ if (!hpte)
+ return H_NOT_FOUND;
+
+ return __kvmppc_do_hash_remove(kvm, hpte, pte_index, hpret);
+}
+EXPORT_SYMBOL_GPL(kvmppc_do_h_hash_remove);
+
+long kvmppc_h_hash_remove(struct kvm_vcpu *vcpu, unsigned long flags,
+ unsigned long hash, unsigned long avpn)
+{
+ return kvmppc_do_h_hash_remove(vcpu->kvm, flags, hash, avpn,
+ &vcpu->arch.gpr[4]);
+}
+
long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
{
struct kvm *kvm = vcpu->kvm;
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index c22516a77f9f..988a4f7385cc 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -2319,6 +2319,8 @@ hcall_real_table:
.long 0 /* 0x2fc - H_XIRR_X*/
#endif
.long DOTSYM(kvmppc_h_random) - hcall_real_table
+ .space ((H_HASH_REMOVE - 4) - H_RANDOM), 0
+ .long DOTSYM(kvmppc_h_hash_remove) - hcall_real_table
.globl hcall_real_table_end
hcall_real_table_end:
--
2.13.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 12/17] powerpc/kvm/hash: Implement HASH_PROTECT hcall
2017-08-02 5:39 [RFC PATCH 00/17] Remove slot tracking from linux page table Aneesh Kumar K.V
` (10 preceding siblings ...)
2017-08-02 5:40 ` [RFC PATCH 11/17] powerpc/kvm/hash: Implement HASH_REMOVE hcall Aneesh Kumar K.V
@ 2017-08-02 5:40 ` Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 13/17] powerpc/kvm/hash: Implement HASH_BULK_REMOVE hcall Aneesh Kumar K.V
` (4 subsequent siblings)
16 siblings, 0 replies; 19+ messages in thread
From: Aneesh Kumar K.V @ 2017-08-02 5:40 UTC (permalink / raw)
To: benh, paulus, mpe, Anton Blanchard; +Cc: linuxppc-dev, Aneesh Kumar K.V
This is equivalent to H_PROTECT hcall, but then takes hash value as the arg
instead of hashpte slot number. We will use this later to speed up invalidate
operation in guest. Instead of finding slot number using H_READ4 hcall, we can
use hash value directly using this hcall.
H_AVPN flag value is needed. Otherwise will return error.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/hvcall.h | 3 +-
arch/powerpc/include/asm/plpar_wrappers.h | 7 +++
arch/powerpc/kvm/book3s_hv.c | 1 +
arch/powerpc/kvm/book3s_hv_rm_mmu.c | 74 ++++++++++++++++++++++---------
arch/powerpc/kvm/book3s_hv_rmhandlers.S | 1 +
5 files changed, 63 insertions(+), 23 deletions(-)
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index 6a09e91889cf..c234be675774 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -281,7 +281,8 @@
#define H_REGISTER_PROC_TBL 0x37C
#define H_SIGNAL_SYS_RESET 0x380
#define H_HASH_REMOVE 0x384
-#define MAX_HCALL_OPCODE H_HASH_REMOVE
+#define H_HASH_PROTECT 0x388
+#define MAX_HCALL_OPCODE H_HASH_PROTECT
/* H_VIOCTL functions */
#define H_GET_VIOA_DUMP_SIZE 0x01
diff --git a/arch/powerpc/include/asm/plpar_wrappers.h b/arch/powerpc/include/asm/plpar_wrappers.h
index 8160fea9b5bc..27e30ca6105d 100644
--- a/arch/powerpc/include/asm/plpar_wrappers.h
+++ b/arch/powerpc/include/asm/plpar_wrappers.h
@@ -226,6 +226,13 @@ static inline long plpar_pte_protect(unsigned long flags, unsigned long ptex,
return plpar_hcall_norets(H_PROTECT, flags, ptex, avpn);
}
+static inline long plpar_pte_hash_protect(unsigned long flags,
+ unsigned long hash,
+ unsigned long avpn)
+{
+ return plpar_hcall_norets(H_HASH_PROTECT, flags, hash, avpn);
+}
+
static inline long plpar_resize_hpt_prepare(unsigned long flags,
unsigned long shift)
{
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 86c66af38637..d7be56339d53 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -4144,6 +4144,7 @@ static unsigned int default_hcall_list[] = {
H_XIRR,
H_XIRR_X,
#endif
+ H_HASH_PROTECT,
H_HASH_REMOVE,
0
};
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index 85fedb72469b..2aa507614819 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -752,33 +752,14 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
return ret;
}
-long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
- unsigned long pte_index, unsigned long avpn,
- unsigned long va)
+long __kvmppc_do_hash_protect(struct kvm *kvm, __be64 *hpte,
+ unsigned long flags, unsigned long pte_index)
{
- struct kvm *kvm = vcpu->kvm;
- __be64 *hpte;
+ u64 pte_v, pte_r;
struct revmap_entry *rev;
unsigned long v, r, rb, mask, bits;
- u64 pte_v, pte_r;
-
- if (kvm_is_radix(kvm))
- return H_FUNCTION;
- if (pte_index >= kvmppc_hpt_npte(&kvm->arch.hpt))
- return H_PARAMETER;
- hpte = (__be64 *)(kvm->arch.hpt.virt + (pte_index << 4));
- while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
- cpu_relax();
v = pte_v = be64_to_cpu(hpte[0]);
- if (cpu_has_feature(CPU_FTR_ARCH_300))
- v = hpte_new_to_old_v(v, be64_to_cpu(hpte[1]));
- if ((v & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
- ((flags & H_AVPN) && (v & ~0x7fUL) != avpn)) {
- __unlock_hpte(hpte, pte_v);
- return H_NOT_FOUND;
- }
-
pte_r = be64_to_cpu(hpte[1]);
bits = (flags << 55) & HPTE_R_PP0;
bits |= (flags << 48) & HPTE_R_KEY_HI;
@@ -823,6 +804,55 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
return H_SUCCESS;
}
+long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
+ unsigned long pte_index, unsigned long avpn,
+ unsigned long va)
+{
+ __be64 *hpte;
+ u64 v, pte_v;
+ struct kvm *kvm = vcpu->kvm;
+
+ if (kvm_is_radix(kvm))
+ return H_FUNCTION;
+ if (pte_index >= kvmppc_hpt_npte(&kvm->arch.hpt))
+ return H_PARAMETER;
+
+ hpte = (__be64 *)(kvm->arch.hpt.virt + (pte_index << 4));
+ while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
+ cpu_relax();
+ v = pte_v = be64_to_cpu(hpte[0]);
+ if (cpu_has_feature(CPU_FTR_ARCH_300))
+ v = hpte_new_to_old_v(v, be64_to_cpu(hpte[1]));
+ if ((v & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
+ ((flags & H_AVPN) && (v & ~0x7fUL) != avpn)) {
+ __unlock_hpte(hpte, pte_v);
+ return H_NOT_FOUND;
+ }
+ return __kvmppc_do_hash_protect(kvm, hpte, flags, pte_index);
+}
+
+/* H_AVPN flag is must */
+long kvmppc_h_hash_protect(struct kvm_vcpu *vcpu, unsigned long flags,
+ unsigned long hash, unsigned long avpn,
+ unsigned long va)
+{
+ __be64 *hpte;
+ unsigned long pte_index;
+ struct kvm *kvm = vcpu->kvm;
+
+ if (kvm_is_radix(kvm))
+ return H_FUNCTION;
+
+ if (!(flags & H_AVPN))
+ return H_PARAMETER;
+
+ hpte = kvmppc_find_hpte_slot(kvm, hash, avpn, &pte_index);
+ if (!hpte)
+ return H_NOT_FOUND;
+
+ return __kvmppc_do_hash_protect(kvm, hpte, flags, pte_index);
+}
+
long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags,
unsigned long pte_index)
{
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 988a4f7385cc..3ca9c3fb3320 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -2321,6 +2321,7 @@ hcall_real_table:
.long DOTSYM(kvmppc_h_random) - hcall_real_table
.space ((H_HASH_REMOVE - 4) - H_RANDOM), 0
.long DOTSYM(kvmppc_h_hash_remove) - hcall_real_table
+ .long DOTSYM(kvmppc_h_hash_protect) - hcall_real_table
.globl hcall_real_table_end
hcall_real_table_end:
--
2.13.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 13/17] powerpc/kvm/hash: Implement HASH_BULK_REMOVE hcall
2017-08-02 5:39 [RFC PATCH 00/17] Remove slot tracking from linux page table Aneesh Kumar K.V
` (11 preceding siblings ...)
2017-08-02 5:40 ` [RFC PATCH 12/17] powerpc/kvm/hash: Implement HASH_PROTECT hcall Aneesh Kumar K.V
@ 2017-08-02 5:40 ` Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 14/17] powerpc/mm/pseries: Use HASH_PROTECT hcall in guest Aneesh Kumar K.V
` (3 subsequent siblings)
16 siblings, 0 replies; 19+ messages in thread
From: Aneesh Kumar K.V @ 2017-08-02 5:40 UTC (permalink / raw)
To: benh, paulus, mpe, Anton Blanchard; +Cc: linuxppc-dev, Aneesh Kumar K.V
This is equivalent to H_BULK_REMOVE hcall, but then takes hash value as the arg
instead of hashpte slot number. We will use this later to speed up bulk remove
operation in guest. Instead of finding slot number using H_READ4 hcall, we can
use hash value directly using this hcall.
only support H_AVPN operation
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/book3s/64/mmu-hash.h | 2 +
arch/powerpc/include/asm/hvcall.h | 3 +-
arch/powerpc/kvm/book3s_hv.c | 1 +
arch/powerpc/kvm/book3s_hv_rm_mmu.c | 95 +++++++++++++++++++++++++++
arch/powerpc/kvm/book3s_hv_rmhandlers.S | 1 +
5 files changed, 101 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/include/asm/book3s/64/mmu-hash.h b/arch/powerpc/include/asm/book3s/64/mmu-hash.h
index a784d4ac4fb1..946d02d02822 100644
--- a/arch/powerpc/include/asm/book3s/64/mmu-hash.h
+++ b/arch/powerpc/include/asm/book3s/64/mmu-hash.h
@@ -68,6 +68,8 @@
*/
#define HPTES_PER_GROUP 8
+/* ISA defines max HTAB SIZE bits 46 */
+#define MAX_HTAB_MASK ((1UL << 46) - 1)
#define HPTE_V_SSIZE_SHIFT 62
#define HPTE_V_AVPN_SHIFT 7
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index c234be675774..17366e5a2897 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -282,7 +282,8 @@
#define H_SIGNAL_SYS_RESET 0x380
#define H_HASH_REMOVE 0x384
#define H_HASH_PROTECT 0x388
-#define MAX_HCALL_OPCODE H_HASH_PROTECT
+#define H_HASH_BULK_REMOVE 0x38C
+#define MAX_HCALL_OPCODE H_HASH_BULK_REMOVE
/* H_VIOCTL functions */
#define H_GET_VIOA_DUMP_SIZE 0x01
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index d7be56339d53..01cfea8c684f 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -4146,6 +4146,7 @@ static unsigned int default_hcall_list[] = {
#endif
H_HASH_PROTECT,
H_HASH_REMOVE,
+ H_HASH_BULK_REMOVE,
0
};
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index 2aa507614819..e6820a84daca 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -752,6 +752,101 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
return ret;
}
+long kvmppc_h_hash_bulk_remove(struct kvm_vcpu *vcpu)
+{
+ struct kvm *kvm = vcpu->kvm;
+ unsigned long *args = &vcpu->arch.gpr[4];
+ __be64 *hp, *hptes[4];
+ unsigned long tlbrb[4];
+ long int i, j, k, n, pte_index[4];
+ unsigned long flags, req, hash, rcbits;
+ int global;
+ long int ret = H_SUCCESS;
+ struct revmap_entry *rev, *revs[4];
+ u64 hp0, hp1;
+
+ if (kvm_is_radix(kvm))
+ return H_FUNCTION;
+
+ global = global_invalidates(kvm);
+ for (i = 0; i < 4 && ret == H_SUCCESS; ) {
+ n = 0;
+ for (; i < 4; ++i) {
+ j = i * 2;
+ hash = args[j];
+ flags = hash >> 56;
+ hash &= ((1ul << 56) - 1);
+ req = flags >> 6;
+ flags &= 3;
+ if (req == 3) { /* no more requests */
+ i = 4;
+ break;
+ }
+ /* only support avpn flag */
+ if (req != 1 || flags != 2) {
+ /* parameter error */
+ args[j] = ((0xa0 | flags) << 56) + hash;
+ ret = H_PARAMETER;
+ break;
+ }
+ /*
+ * We wait here to take lock for all hash values
+ * FIXME!! will that deadlock ?
+ */
+ hp = kvmppc_find_hpte_slot(kvm, hash,
+ args[j + 1], &pte_index[n]);
+ if (!hp) {
+ args[j] = ((0x90 | flags) << 56) + hash;
+ continue;
+ }
+ hp0 = be64_to_cpu(hp[0]);
+ hp1 = be64_to_cpu(hp[1]);
+ if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+ hp0 = hpte_new_to_old_v(hp0, hp1);
+ hp1 = hpte_new_to_old_r(hp1);
+ }
+ args[j] = ((0x80 | flags) << 56) + hash;
+ rev = real_vmalloc_addr(&kvm->arch.hpt.rev[pte_index[n]]);
+ note_hpte_modification(kvm, rev);
+
+ if (!(hp0 & HPTE_V_VALID)) {
+ /* insert R and C bits from PTE */
+ rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C);
+ args[j] |= rcbits << (56 - 5);
+ hp[0] = 0;
+ if (is_mmio_hpte(hp0, hp1))
+ atomic64_inc(&kvm->arch.mmio_update);
+ continue;
+ }
+ /* leave it locked */
+ hp[0] &= ~cpu_to_be64(HPTE_V_VALID);
+ tlbrb[n] = compute_tlbie_rb(hp0, hp1, pte_index[n]);
+ hptes[n] = hp;
+ revs[n] = rev;
+ ++n;
+ }
+
+ if (!n)
+ break;
+
+ /* Now that we've collected a batch, do the tlbies */
+ do_tlbies(kvm, tlbrb, n, global, true);
+
+ /* Read PTE low words after tlbie to get final R/C values */
+ for (k = 0; k < n; ++k) {
+ hp = hptes[k];
+ rev = revs[k];
+ remove_revmap_chain(kvm, pte_index[k], rev,
+ be64_to_cpu(hp[0]), be64_to_cpu(hp[1]));
+ rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C);
+ args[j] |= rcbits << (56 - 5);
+ __unlock_hpte(hp, 0);
+ }
+ }
+
+ return ret;
+}
+
long __kvmppc_do_hash_protect(struct kvm *kvm, __be64 *hpte,
unsigned long flags, unsigned long pte_index)
{
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 3ca9c3fb3320..cc6ddf0cfa0c 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -2322,6 +2322,7 @@ hcall_real_table:
.space ((H_HASH_REMOVE - 4) - H_RANDOM), 0
.long DOTSYM(kvmppc_h_hash_remove) - hcall_real_table
.long DOTSYM(kvmppc_h_hash_protect) - hcall_real_table
+ .long DOTSYM(kvmppc_h_hash_bulk_remove) - hcall_real_table
.globl hcall_real_table_end
hcall_real_table_end:
--
2.13.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 14/17] powerpc/mm/pseries: Use HASH_PROTECT hcall in guest
2017-08-02 5:39 [RFC PATCH 00/17] Remove slot tracking from linux page table Aneesh Kumar K.V
` (12 preceding siblings ...)
2017-08-02 5:40 ` [RFC PATCH 13/17] powerpc/kvm/hash: Implement HASH_BULK_REMOVE hcall Aneesh Kumar K.V
@ 2017-08-02 5:40 ` Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 15/17] powerpc/mm/pseries: Use HASH_REMOVE " Aneesh Kumar K.V
` (2 subsequent siblings)
16 siblings, 0 replies; 19+ messages in thread
From: Aneesh Kumar K.V @ 2017-08-02 5:40 UTC (permalink / raw)
To: benh, paulus, mpe, Anton Blanchard; +Cc: linuxppc-dev, Aneesh Kumar K.V
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/powerpc/platforms/pseries/lpar.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index e28e62f6afba..bfab61d17f6d 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -388,15 +388,20 @@ static long pSeries_lpar_hash_updatepp(unsigned long hash,
unsigned long want_v;
want_v = hpte_encode_avpn(vpn, psize, ssize);
-
pr_devel(" update: avpnv=%016lx, hash=%016lx, f=%lx, psize: %d ...",
want_v, hash, flags, psize);
+ if (firmware_has_feature(FW_FEATURE_HASH_API)) {
+ lpar_rc = plpar_pte_hash_protect(flags, hash, want_v);
+ goto err_out;
+ }
slot = __pSeries_lpar_hpte_find(hash, want_v);
if (slot < 0)
return -1;
lpar_rc = plpar_pte_protect(flags, slot, want_v);
+
+err_out:
if (lpar_rc == H_NOT_FOUND) {
pr_devel("not found !\n");
return -1;
--
2.13.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 15/17] powerpc/mm/pseries: Use HASH_REMOVE hcall in guest
2017-08-02 5:39 [RFC PATCH 00/17] Remove slot tracking from linux page table Aneesh Kumar K.V
` (13 preceding siblings ...)
2017-08-02 5:40 ` [RFC PATCH 14/17] powerpc/mm/pseries: Use HASH_PROTECT hcall in guest Aneesh Kumar K.V
@ 2017-08-02 5:40 ` Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 16/17] powerpc/mm/pseries: Move slot based bulk remove to helper Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 17/17] powerpc/mm/pseries: Use HASH_BULK_REMOVE hcall in guest Aneesh Kumar K.V
16 siblings, 0 replies; 19+ messages in thread
From: Aneesh Kumar K.V @ 2017-08-02 5:40 UTC (permalink / raw)
To: benh, paulus, mpe, Anton Blanchard; +Cc: linuxppc-dev, Aneesh Kumar K.V
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/powerpc/platforms/pseries/lpar.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index bfab61d17f6d..04a9618f3b79 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -454,6 +454,27 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long vpn,
BUG_ON(lpar_rc != H_SUCCESS);
}
+static void __pseries_lpar_hash_invalidate(unsigned long hash, unsigned long vpn,
+ int psize, int apsize,
+ int ssize, int local)
+{
+ unsigned long want_v;
+ unsigned long lpar_rc;
+ unsigned long dummy1, dummy2;
+
+ pr_devel(" inval : hash=%lx, vpn=%016lx, psize: %d, local: %d\n",
+ hash, vpn, psize, local);
+
+ want_v = hpte_encode_avpn(vpn, psize, ssize);
+ lpar_rc = plpar_pte_hash_remove(H_AVPN, hash, want_v, &dummy1, &dummy2);
+ if (lpar_rc == H_NOT_FOUND)
+ return;
+
+ BUG_ON(lpar_rc != H_SUCCESS);
+
+}
+
+
static void pSeries_lpar_hash_invalidate(unsigned long hash, unsigned long vpn,
int psize, int apsize,
int ssize, int local)
@@ -466,6 +487,9 @@ static void pSeries_lpar_hash_invalidate(unsigned long hash, unsigned long vpn,
pr_devel(" inval : hash=%lx, vpn=%016lx, psize: %d, local: %d\n",
hash, vpn, psize, local);
+ if (firmware_has_feature(FW_FEATURE_HASH_API))
+ return __pseries_lpar_hash_invalidate(hash, vpn, psize,
+ apsize, ssize, local);
want_v = hpte_encode_avpn(vpn, psize, ssize);
slot = __pSeries_lpar_hpte_find(hash, want_v);
if (slot < 0)
--
2.13.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 16/17] powerpc/mm/pseries: Move slot based bulk remove to helper
2017-08-02 5:39 [RFC PATCH 00/17] Remove slot tracking from linux page table Aneesh Kumar K.V
` (14 preceding siblings ...)
2017-08-02 5:40 ` [RFC PATCH 15/17] powerpc/mm/pseries: Use HASH_REMOVE " Aneesh Kumar K.V
@ 2017-08-02 5:40 ` Aneesh Kumar K.V
2017-08-02 12:50 ` Segher Boessenkool
2017-08-02 5:40 ` [RFC PATCH 17/17] powerpc/mm/pseries: Use HASH_BULK_REMOVE hcall in guest Aneesh Kumar K.V
16 siblings, 1 reply; 19+ messages in thread
From: Aneesh Kumar K.V @ 2017-08-02 5:40 UTC (permalink / raw)
To: benh, paulus, mpe, Anton Blanchard; +Cc: linuxppc-dev, Aneesh Kumar K.V
---
arch/powerpc/platforms/pseries/lpar.c | 51 +++++++++++++++++++++--------------
1 file changed, 31 insertions(+), 20 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 04a9618f3b79..436ec1e725d3 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -632,6 +632,34 @@ static int pSeries_lpar_hpte_removebolted(unsigned long ea,
return 0;
}
+static int plpar_bluk_remove(unsigned long *param, int index, unsigned long slot,
+ unsigned long vpn, unsigned long psize,
+ unsigned long ssize, int local)
+{
+ unsigned long rc;
+ if (!firmware_has_feature(FW_FEATURE_BULK_REMOVE)) {
+ /*
+ * lpar doesn't use the passed actual page size
+ */
+ pSeries_lpar_hpte_invalidate(slot, vpn, psize,
+ 0, ssize, local);
+ } else {
+ param[index] = HBR_REQUEST | HBR_AVPN | slot;
+ param[index+1] = hpte_encode_avpn(vpn, psize,
+ ssize);
+ index += 2;
+ if (index == 8) {
+ rc = plpar_hcall9(H_BULK_REMOVE, param,
+ param[0], param[1], param[2],
+ param[3], param[4], param[5],
+ param[6], param[7]);
+ BUG_ON(rc != H_SUCCESS);
+ index = 0;
+ }
+ }
+ return index;
+}
+
/*
* Take a spinlock around flushes to avoid bouncing the hypervisor tlbie
* lock.
@@ -657,29 +685,12 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
vpn = batch->vpn[i];
pte_iterate_hashed_subpages(vpn, psize, index, shift) {
slot = pSeries_lpar_hpte_find(vpn, psize, ssize);
- if (!firmware_has_feature(FW_FEATURE_BULK_REMOVE)) {
- /*
- * lpar doesn't use the passed actual page size
- */
- pSeries_lpar_hpte_invalidate(slot, vpn, psize,
- 0, ssize, local);
- } else {
- param[pix] = HBR_REQUEST | HBR_AVPN | slot;
- param[pix+1] = hpte_encode_avpn(vpn, psize,
- ssize);
- pix += 2;
- if (pix == 8) {
- rc = plpar_hcall9(H_BULK_REMOVE, param,
- param[0], param[1], param[2],
- param[3], param[4], param[5],
- param[6], param[7]);
- BUG_ON(rc != H_SUCCESS);
- pix = 0;
- }
- }
+ pix = plpar_bluk_remove(param, pix, slot, vpn,
+ psize, ssize, local);
} pte_iterate_hashed_end();
}
if (pix) {
+ /* We have a flush pending */
param[pix] = HBR_END;
rc = plpar_hcall9(H_BULK_REMOVE, param, param[0], param[1],
param[2], param[3], param[4], param[5],
--
2.13.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH 17/17] powerpc/mm/pseries: Use HASH_BULK_REMOVE hcall in guest
2017-08-02 5:39 [RFC PATCH 00/17] Remove slot tracking from linux page table Aneesh Kumar K.V
` (15 preceding siblings ...)
2017-08-02 5:40 ` [RFC PATCH 16/17] powerpc/mm/pseries: Move slot based bulk remove to helper Aneesh Kumar K.V
@ 2017-08-02 5:40 ` Aneesh Kumar K.V
16 siblings, 0 replies; 19+ messages in thread
From: Aneesh Kumar K.V @ 2017-08-02 5:40 UTC (permalink / raw)
To: benh, paulus, mpe, Anton Blanchard; +Cc: linuxppc-dev, Aneesh Kumar K.V
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/powerpc/platforms/pseries/lpar.c | 35 ++++++++++++++++++++++++++++++-----
1 file changed, 30 insertions(+), 5 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 436ec1e725d3..0275b357dca0 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -672,7 +672,7 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
struct ppc64_tlb_batch *batch = this_cpu_ptr(&ppc64_tlb_batch);
int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
unsigned long param[PLPAR_HCALL9_BUFSIZE];
- unsigned long index, shift, slot;
+ unsigned long index, shift;
int psize, ssize, pix;
if (lock_tlbie)
@@ -684,15 +684,40 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
for (i = 0; i < number; i++) {
vpn = batch->vpn[i];
pte_iterate_hashed_subpages(vpn, psize, index, shift) {
- slot = pSeries_lpar_hpte_find(vpn, psize, ssize);
- pix = plpar_bluk_remove(param, pix, slot, vpn,
- psize, ssize, local);
+ if (!firmware_has_feature(FW_FEATURE_HASH_API)) {
+ unsigned long slot;
+ slot = pSeries_lpar_hpte_find(vpn, psize, ssize);
+ pix = plpar_bluk_remove(param, pix, slot, vpn,
+ psize, ssize, local);
+ } else {
+ unsigned long hash;
+ hash = hpt_hash(vpn, mmu_psize_defs[psize].shift, ssize);
+ /* trim the top bits, we overload them below */
+ hash &= MAX_HTAB_MASK;
+ param[pix] = HBR_REQUEST | HBR_AVPN | hash;
+ param[pix+1] = hpte_encode_avpn(vpn, psize, ssize);
+ pix += 2;
+ if (pix == 8) {
+ rc = plpar_hcall9(H_HASH_BULK_REMOVE, param,
+ param[0], param[1], param[2],
+ param[3], param[4], param[5],
+ param[6], param[7]);
+ BUG_ON(rc != H_SUCCESS);
+ pix = 0;
+ }
+ }
} pte_iterate_hashed_end();
}
if (pix) {
+ unsigned long hcall;
+
/* We have a flush pending */
param[pix] = HBR_END;
- rc = plpar_hcall9(H_BULK_REMOVE, param, param[0], param[1],
+ if (!firmware_has_feature(FW_FEATURE_HASH_API))
+ hcall = H_BULK_REMOVE;
+ else
+ hcall = H_HASH_BULK_REMOVE;
+ rc = plpar_hcall9(hcall, param, param[0], param[1],
param[2], param[3], param[4], param[5],
param[6], param[7]);
BUG_ON(rc != H_SUCCESS);
--
2.13.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [RFC PATCH 16/17] powerpc/mm/pseries: Move slot based bulk remove to helper
2017-08-02 5:40 ` [RFC PATCH 16/17] powerpc/mm/pseries: Move slot based bulk remove to helper Aneesh Kumar K.V
@ 2017-08-02 12:50 ` Segher Boessenkool
0 siblings, 0 replies; 19+ messages in thread
From: Segher Boessenkool @ 2017-08-02 12:50 UTC (permalink / raw)
To: Aneesh Kumar K.V; +Cc: benh, paulus, mpe, Anton Blanchard, linuxppc-dev
Hi Aneesh,
On Wed, Aug 02, 2017 at 11:10:15AM +0530, Aneesh Kumar K.V wrote:
> +static int plpar_bluk_remove(unsigned long *param, int index, unsigned long slot,
s/bluk/bulk/ :-)
Segher
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2017-08-02 12:51 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-08-02 5:39 [RFC PATCH 00/17] Remove slot tracking from linux page table Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 01/17] powerpc/mm: Update native_hpte_find to return hash pte Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 02/17] powerpc/pseries: Update hpte find helper to take hash value Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 03/17] powerpc/ps3/mm: Add helper for finding hash pte slot using " Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 04/17] powerpc/mm: Add hash invalidate callback Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 05/17] powerpc/mm: use hash_invalidate for __kernel_map_pages() Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 06/17] powerpc/mm: Switch flush_hash_range to not use slot Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 07/17] powerpc/mm: Add hash updatepp callback Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 08/17] powerpc/mm/hash: Don't track hash pte slot number in linux page table Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 09/17] powerpc/mm: Remove unused flag arg in global_invalidates Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 10/17] powerpc/mm: Add new firmware feature HASH API Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 11/17] powerpc/kvm/hash: Implement HASH_REMOVE hcall Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 12/17] powerpc/kvm/hash: Implement HASH_PROTECT hcall Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 13/17] powerpc/kvm/hash: Implement HASH_BULK_REMOVE hcall Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 14/17] powerpc/mm/pseries: Use HASH_PROTECT hcall in guest Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 15/17] powerpc/mm/pseries: Use HASH_REMOVE " Aneesh Kumar K.V
2017-08-02 5:40 ` [RFC PATCH 16/17] powerpc/mm/pseries: Move slot based bulk remove to helper Aneesh Kumar K.V
2017-08-02 12:50 ` Segher Boessenkool
2017-08-02 5:40 ` [RFC PATCH 17/17] powerpc/mm/pseries: Use HASH_BULK_REMOVE hcall in guest Aneesh Kumar K.V
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).