RPAGE_RSV0..4 PTE bits are currently used for HPTE slot tracking.
We need these bits for memory-protection keys. Luckily these four
bits are relatively easier to move among all the other candidate
bits.
For 64K linux-PTEs backed by 4k HPTEs, these bits are used for
tracking the validity of the slot value stored in the
second-part-of-the-PTE. We device a new mechanism for tracking
the validity without using those bits. The mechanism is
explained in the first patch.
For 64K linux-PTE backed by 64K HPTEs, we simply move the slot
tracking bits to the second-part-of-the-PTE.
The above mechanism is also used to free the bits for hugetlb
linux-PTEs.
For 4k linux-PTE, we have only 3 free bits available. We swizzle
around the bits and release RPAGE_RSV{2,3,4} for memory protection
keys.
Testing:
--------
has survived kernel compilation on multiple platforms
p8 powernv hash-mode, p9 powernv hash-mode, p7 powervm,
p8-powervm, p8-kvm-guest.
History:
-------
This patchset is a spin-off from the memkey patchset.
version v10:
(1) hidx value is rotated by one to save
initialization of the secondary-PTE.
(2) comments are not anymore right justified.
-- comment by mpe
version v9:
(1) rearranged the patch order. First the helper
routines are defined followed by the
patches that make use of the helpers.
version v8:
(1) an additional patch added to free up
RSV{2,3,4} on 4K linux-PTE.
version v7:
(1) GIX bit reset change moved to the second
patch -- noticed by Aneesh.
(2) Separated this patches from memkey patchset
(3) merged a bunch of patches, that used the
helper function, into one.
version v6:
(1) No changes related to PTE.
version v5:
(1) No changes related to PTE.
version v4:
(1) No changes related to PTE.
version v3:
(1) split the patches into smaller consumable
patches.
(2) A bug fix while invalidating a HPTE slot
in __hash_page_4K()
-- noticed by Aneesh
version v2:
(1) fixed a bug in 4k HPTE backed 64k PTE
where page invalidation was not
done correctly, and initialization
of second-part-of-the-PTE was not
done correctly if the PTE was not
yet Hashed with a HPTE.
-- Reported by Aneesh.
version v1: Initial version
Ram Pai (8):
powerpc: introduce pte_set_hidx() helper
powerpc: introduce pte_get_hash_gslot() helper
powerpc: Free up four 64K PTE bits in 4K backed HPTE pages
powerpc: Free up four 64K PTE bits in 64K backed HPTE pages
powerpc: shifted-by-one hidx value
powerpc: Swizzle around 4K PTE bits to free up bit 5 and bit 6
powerpc: use helper functions to get and set hash slots
powerpc: capture the PTE format changes in the dump pte report
arch/powerpc/include/asm/book3s/64/hash-4k.h | 20 ++++
arch/powerpc/include/asm/book3s/64/hash-64k.h | 71 ++++++++++----
arch/powerpc/include/asm/book3s/64/hash.h | 8 +-
arch/powerpc/mm/dump_linuxpagetables.c | 3 +-
arch/powerpc/mm/hash64_4k.c | 14 +--
arch/powerpc/mm/hash64_64k.c | 123 +++++++++++++------------
arch/powerpc/mm/hash_utils_64.c | 35 +++++--
arch/powerpc/mm/hugetlbpage-hash64.c | 16 +--
8 files changed, 175 insertions(+), 115 deletions(-)
Introduce pte_set_hidx().It sets the (H_PAGE_F_SECOND|H_PAGE_F_GIX) bits
at the appropriate location in the PTE of 4K PTE. For 64K PTE, it sets
the bits in the second part of the PTE. Though the implementation for
the former just needs the slot parameter, it does take some additional
parameters to keep the prototype consistent.
This function will be handy as we work towards re-arranging the bits in
the subsequent patches.
Acked-by: Balbir Singh <bsingharora@gmail.com>
Reviewed-by: Aneesh Kumar K.V <redacted>
Signed-off-by: Ram Pai <redacted>
---
arch/powerpc/include/asm/book3s/64/hash-4k.h | 14 ++++++++++++++
arch/powerpc/include/asm/book3s/64/hash-64k.h | 25 +++++++++++++++++++++++++
2 files changed, 39 insertions(+), 0 deletions(-)
@@ -75,6 +77,29 @@ static inline unsigned long __rpte_to_hidx(real_pte_t rpte, unsigned long index)return(pte_val(rpte.pte)>>H_PAGE_F_GIX_SHIFT)&0xf;}+/*+*CommitthehidxandreturnPTEbitsthatneedstobemodified.Thecalleris+*expectedtomodifythePTEbitsaccordinglyandcommitthePTEtomemory.+*/+staticinlineunsignedlongpte_set_hidx(pte_t*ptep,real_pte_trpte,+unsignedintsubpg_index,unsignedlonghidx)+{+unsignedlong*hidxp=(unsignedlong*)(ptep+PTRS_PER_PTE);++rpte.hidx&=~HIDX_BITS(0xfUL,subpg_index);+*hidxp=rpte.hidx|HIDX_BITS(hidx,subpg_index);++/*+*AnyonereadingPTEmustensurehidxbitsarereadafterreadingthe+*PTEbyusingtheread-sidebarriersmp_rmb().__real_pte()canbe+*usedforthat.+*/+smp_wmb();++/* No PTE bits to be modified, return 0x0UL */+return0x0UL;+}+#define __rpte_to_pte(r) ((r).pte)externbool__rpte_sub_valid(real_pte_trpte,unsignedlongindex);/*
Introduce pte_get_hash_gslot()() which returns the global slot number of
the HPTE in the global hash table.
This function will come in handy as we work towards re-arranging the PTE
bits in the later patches.
Reviewed-by: Aneesh Kumar K.V <redacted>
Signed-off-by: Ram Pai <redacted>
---
arch/powerpc/include/asm/book3s/64/hash.h | 3 +++
arch/powerpc/mm/hash_utils_64.c | 18 ++++++++++++++++++
2 files changed, 21 insertions(+), 0 deletions(-)
@@ -167,6 +167,9 @@ static inline int hash__pte_none(pte_t pte)return(pte_val(pte)&~H_PTE_NONE_MASK)==0;}+unsignedlongpte_get_hash_gslot(unsignedlongvpn,unsignedlongshift,+intssize,real_pte_trpte,unsignedintsubpg_index);+/* This low level function performs the actual PTE insertion*SettingthePTEdependsontheMMUtypeandotherfactors.It's*anhorriblemessthatI'mnotgoingtotrytocleanupnowbut
@@ -1591,6 +1591,24 @@ static inline void tm_flush_hash_page(int local)}#endif+/*+*Returntheglobalhashslot,correspondingtothegivenPTE,whichcontains+*theHPTE.+*/+unsignedlongpte_get_hash_gslot(unsignedlongvpn,unsignedlongshift,+intssize,real_pte_trpte,unsignedintsubpg_index)+{+unsignedlonghash,gslot,hidx;++hash=hpt_hash(vpn,shift,ssize);+hidx=__rpte_to_hidx(rpte,subpg_index);+if(hidx&_PTEIDX_SECONDARY)+hash=~hash;+gslot=(hash&htab_hash_mask)*HPTES_PER_GROUP;+gslot+=hidx&_PTEIDX_GROUP_IX;+returngslot;+}+/* WARNING: This is called from hash_low_64.S, if you change this prototype,*donotforgettoupdatetheassemblycallsite!*/
Rearrange 64K PTE bits to free up bits 3, 4, 5 and 6,
in the 4K backed HPTE pages.These bits continue to be used
for 64K backed HPTE pages in this patch, but will be freed
up in the next patch. The bit numbers are big-endian as
defined in the ISA3.0
The patch does the following change to the 4k HTPE backed
64K PTE's format.
H_PAGE_BUSY moves from bit 3 to bit 9 (B bit in the figure
below)
V0 which occupied bit 4 is not used anymore.
V1 which occupied bit 5 is not used anymore.
V2 which occupied bit 6 is not used anymore.
V3 which occupied bit 7 is not used anymore.
Before the patch, the 4k backed 64k PTE format was as follows
0 1 2 3 4 5 6 7 8 9 10...........................63
: : : : : : : : : : : :
v v v v v v v v v v v v
,-,-,-,-,--,--,--,--,-,-,-,-,-,------------------,-,-,-,
|x|x|x|B|V0|V1|V2|V3|x| | |x|x|................|x|x|x|x| <- primary pte
'_'_'_'_'__'__'__'__'_'_'_'_'_'________________'_'_'_'_'
|S|G|I|X|S |G |I |X |S|G|I|X|..................|S|G|I|X| <- secondary pte
'_'_'_'_'__'__'__'__'_'_'_'_'__________________'_'_'_'_'
After the patch, the 4k backed 64k PTE format is as follows
0 1 2 3 4 5 6 7 8 9 10...........................63
: : : : : : : : : : : :
v v v v v v v v v v v v
,-,-,-,-,--,--,--,--,-,-,-,-,-,------------------,-,-,-,
|x|x|x| | | | | |x|B| |x|x|................|.|.|.|.| <- primary pte
'_'_'_'_'__'__'__'__'_'_'_'_'_'________________'_'_'_'_'
|S|G|I|X|S |G |I |X |S|G|I|X|..................|S|G|I|X| <- secondary pte
'_'_'_'_'__'__'__'__'_'_'_'_'__________________'_'_'_'_'
the four bits S,G,I,X (one quadruplet per 4k HPTE) that
cache the hash-bucket slot value, is initialized to
1,1,1,1 indicating -- an invalid slot. If a HPTE gets
cached in a 1111 slot(i.e 7th slot of secondary hash
bucket), it is released immediately. In other words,
even though 1111 is a valid slot value in the hash
bucket, we consider it invalid and release the slot and
the HPTE. This gives us the opportunity to determine
the validity of S,G,I,X bits based on its contents and
not on any of the bits V0,V1,V2 or V3 in the primary PTE
When we release a HPTE cached in the 1111 slot
we also release a legitimate slot in the primary
hash bucket and unmap its corresponding HPTE. This
is to ensure that we do get a HPTE cached in a slot
of the primary hash bucket, the next time we retry.
Though treating 1111 slot as invalid, reduces the
number of available slots in the hash bucket and may
have an effect on the performance, the probabilty of
hitting a 1111 slot is extermely low.
Compared to the current scheme, the above scheme
reduces the number of false hash table updates
significantly and has the added advantage of releasing
four valuable PTE bits for other purpose.
NOTE:even though bits 3, 4, 5, 6, 7 are not used when
the 64K PTE is backed by 4k HPTE, they continue to be
used if the PTE gets backed by 64k HPTE. The next
patch will decouple that aswell, and truely release the
bits.
This idea was jointly developed by Paul Mackerras,
Aneesh, Michael Ellermen and myself.
4K PTE format remains unchanged currently.
The patch does the following code changes
a) PTE flags are split between 64k and 4k header files.
b) __hash_page_4K() is reimplemented to reflect the
above logic.
Acked-by: Balbir Singh <bsingharora@gmail.com>
Reviewed-by: Aneesh Kumar K.V <redacted>
Signed-off-by: Ram Pai <redacted>
---
arch/powerpc/include/asm/book3s/64/hash-4k.h | 2 +
arch/powerpc/include/asm/book3s/64/hash-64k.h | 9 +--
arch/powerpc/include/asm/book3s/64/hash.h | 1 -
arch/powerpc/mm/hash64_64k.c | 102 +++++++++++++------------
arch/powerpc/mm/hash_utils_64.c | 4 +-
5 files changed, 61 insertions(+), 57 deletions(-)
@@ -50,12 +38,11 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,intssize,intsubpg_prot){real_pte_trpte;-unsignedlong*hidxp;unsignedlonghpte_group;unsignedintsubpg_index;-unsignedlongrflags,pa,hidx;+unsignedlongrflags,pa;unsignedlongold_pte,new_pte,subpg_pte;-unsignedlongvpn,hash,slot;+unsignedlongvpn,hash,slot,gslot;unsignedlongshift=mmu_psize_defs[MMU_PAGE_4K].shift;/*
@@ -126,18 +113,14 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,if(__rpte_sub_valid(rpte,subpg_index)){intret;-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,+gslot=pte_get_hash_gslot(vpn,shift,ssize,rpte,+subpg_index);+ret=mmu_hash_ops.hpte_updatepp(gslot,rflags,vpn,MMU_PAGE_4K,MMU_PAGE_4K,ssize,flags);+/*-*ifwefailedbecausetypicallytheHPTEwasn'treallyhere+*IfwefailedbecausetypicallytheHPTEwasn'treallyhere*wetryaninsertion.*/if(ret==-1)
@@ -148,6 +131,14 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,}htab_insert_hpte:++/*+*Initializeallhidxentriestoinvalidvalue,thefirsttime+*thePTEisabouttoallocatea4KHPTE.+*/+if(!(old_pte&H_PAGE_COMBO))+rpte.hidx=INVALID_RPTE_HIDX;+/**handleH_PAGE_4K_PFNcase*/
@@ -172,15 +163,39 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,*Primaryisfull,trythesecondary*/if(unlikely(slot==-1)){+boolsoft_invalid;+hpte_group=((~hash&htab_hash_mask)*HPTES_PER_GROUP)&~0x7UL;slot=mmu_hash_ops.hpte_insert(hpte_group,vpn,pa,rflags,HPTE_V_SECONDARY,MMU_PAGE_4K,MMU_PAGE_4K,ssize);-if(slot==-1){-if(mftb()&0x1)++soft_invalid=hpte_soft_invalid(slot);+if(unlikely(soft_invalid)){+/*+*Wegotavalidslotfromahardwarepointofview.+*butwecannotuseit,becauseweusethisspecial+*value;asdefinedbyhpte_soft_invalid(),totrack+*invalidslots.Wecannotuseit.Soinvalidateit.+*/+gslot=slot&_PTEIDX_GROUP_IX;+mmu_hash_ops.hpte_invalidate(hpte_group+gslot,vpn,+MMU_PAGE_4K,MMU_PAGE_4K,+ssize,0);+}++if(unlikely(slot==-1||soft_invalid)){+/*+*Forsoftinvalidslot,let'sensurethatwereleasea+*slotfromtheprimary,withthehopethatwewill+*acquirethatslotnexttimewetry.Thiswillensure+*thatwedonotgetthesamesoft-invalidslot.+*/+if(soft_invalid||(mftb()&0x1))hpte_group=((hash&htab_hash_mask)*HPTES_PER_GROUP)&~0x7UL;+mmu_hash_ops.hpte_remove(hpte_group);/**FIXME!!Shouldbetrythegroupfromwhichweremoved?
@@ -198,21 +213,10 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,MMU_PAGE_4K,MMU_PAGE_4K,old_pte);return-1;}-/*-*Insertslotnumber&secondarybitinPTEsecondhalf,-*clearH_PAGE_BUSYandsetappropriateHPTEslotbit-*SincewehaveH_PAGE_BUSYsetonptep,wecanbesure-*nobodyisundatinghidx.-*/-hidxp=(unsignedlong*)(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_ptefordetailsonmatchingsmp_rmb()-*/-smp_wmb();++new_pte|=pte_set_hidx(ptep,rpte,subpg_index,slot);+new_pte|=H_PAGE_HASHPTE;+*ptep=__pte(new_pte&~H_PAGE_BUSY);return0;}
Rearrange 64K PTE bits to free up bits 3, 4, 5 and 6
in the 64K backed HPTE pages. This along with the earlier
patch will entirely free up the four bits from 64K PTE.
The bit numbers are big-endian as defined in the ISA3.0
This patch does the following change to 64K PTE backed
by 64K HPTE.
H_PAGE_F_SECOND (S) which occupied bit 4 moves to the
second part of the pte to bit 60.
H_PAGE_F_GIX (G,I,X) which occupied bit 5, 6 and 7 also
moves to the second part of the pte to bit 61,
62, 63, 64 respectively
since bit 7 is now freed up, we move H_PAGE_BUSY (B) from
bit 9 to bit 7.
The second part of the PTE will hold
(H_PAGE_F_SECOND|H_PAGE_F_GIX) at bit 60,61,62,63.
NOTE: None of the bits in the secondary PTE were not used
by 64k-HPTE backed PTE.
Before the patch, the 64K HPTE backed 64k PTE format was
as follows
0 1 2 3 4 5 6 7 8 9 10...........................63
: : : : : : : : : : : :
v v v v v v v v v v v v
,-,-,-,-,--,--,--,--,-,-,-,-,-,------------------,-,-,-,
|x|x|x| |S |G |I |X |x|B| |x|x|................|x|x|x|x| <- primary pte
'_'_'_'_'__'__'__'__'_'_'_'_'_'________________'_'_'_'_'
| | | | | | | | | | | | |..................| | | | | <- secondary pte
'_'_'_'_'__'__'__'__'_'_'_'_'__________________'_'_'_'_'
After the patch, the 64k HPTE backed 64k PTE format is
as follows
0 1 2 3 4 5 6 7 8 9 10...........................63
: : : : : : : : : : : :
v v v v v v v v v v v v
,-,-,-,-,--,--,--,--,-,-,-,-,-,------------------,-,-,-,
|x|x|x| | | | |B |x| | |x|x|................|.|.|.|.| <- primary pte
'_'_'_'_'__'__'__'__'_'_'_'_'_'________________'_'_'_'_'
| | | | | | | | | | | | |..................|S|G|I|X| <- secondary pte
'_'_'_'_'__'__'__'__'_'_'_'_'__________________'_'_'_'_'
The above PTE changes is applicable to hugetlbpages aswell.
The patch does the following code changes:
a) moves the H_PAGE_F_SECOND and H_PAGE_F_GIX to 4k PTE
header since it is no more needed b the 64k PTEs.
b) abstracts out __real_pte() and __rpte_to_hidx() so the
caller need not know the bit location of the slot.
c) moves the slot bits to the secondary pte.
Reviewed-by: Aneesh Kumar K.V <redacted>
Signed-off-by: Ram Pai <redacted>
---
arch/powerpc/include/asm/book3s/64/hash-4k.h | 3 ++
arch/powerpc/include/asm/book3s/64/hash-64k.h | 30 +++++++++++-------------
arch/powerpc/include/asm/book3s/64/hash.h | 3 --
arch/powerpc/mm/hash64_64k.c | 21 ++++++++---------
arch/powerpc/mm/hugetlbpage-hash64.c | 16 +++++--------
5 files changed, 33 insertions(+), 40 deletions(-)
@@ -13,7 +13,7 @@*/#define H_PAGE_COMBO _RPAGE_RPN0 /* this is a combo 4k page */#define H_PAGE_4K_PFN _RPAGE_RPN1 /* PFN is for a single 4k page */-#define H_PAGE_BUSY _RPAGE_RPN42 /* software: PTE & hash are busy */+#define H_PAGE_BUSY _RPAGE_RPN44 /* software: PTE & hash are busy *//**WeneedtodifferentiatebetweenexplicithugepageandTHPhuge
@@ -103,8 +103,8 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,*Onhashinsertfailureweuseoldptevalueandwedon't*wantslotinformationthereifwehaveainsertfailure.*/-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);+old_pte&=~H_PAGE_HASHPTE;+new_pte&=~H_PAGE_HASHPTE;gotohtab_insert_hpte;}/*
@@ -225,6 +225,7 @@ int __hash_page_64K(unsigned long ea, unsigned long access,unsignedlongvsid,pte_t*ptep,unsignedlongtrap,unsignedlongflags,intssize){+real_pte_trpte;unsignedlonghpte_group;unsignedlongrflags,pa;unsignedlongold_pte,new_pte;
@@ -261,6 +262,7 @@ int __hash_page_64K(unsigned long ea, unsigned long access,}while(!pte_xchg(ptep,__pte(old_pte),__pte(new_pte)));rflags=htab_convert_pte_flags(new_pte);+rpte=__real_pte(__pte(old_pte),ptep);if(cpu_has_feature(CPU_FTR_NOEXECUTE)&&!cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
@@ -268,16 +270,13 @@ int __hash_page_64K(unsigned long ea, unsigned long access,vpn=hpt_vpn(ea,vsid,ssize);if(unlikely(old_pte&H_PAGE_HASHPTE)){+unsignedlonggslot;+/**ThereMIGHTbeanHPTEforthispte*/-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,+gslot=pte_get_hash_gslot(vpn,shift,ssize,rpte,0);+if(mmu_hash_ops.hpte_updatepp(gslot,rflags,vpn,MMU_PAGE_64K,MMU_PAGE_64K,ssize,flags)==-1)old_pte&=~_PAGE_HPTEFLAGS;
@@ -326,9 +325,9 @@ 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|=pte_set_hidx(ptep,rpte,0,slot);}*ptep=__pte(new_pte&~H_PAGE_BUSY);return0;
@@ -23,6 +23,7 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,pte_t*ptep,unsignedlongtrap,unsignedlongflags,intssize,unsignedintshift,unsignedintmmu_psize){+real_pte_trpte;unsignedlongvpn;unsignedlongold_pte,new_pte;unsignedlongrflags,pa,sz;
@@ -62,6 +63,7 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,}while(!pte_xchg(ptep,__pte(old_pte),__pte(new_pte)));rflags=htab_convert_pte_flags(new_pte);+rpte=__real_pte(__pte(old_pte),ptep);sz=((1UL)<<shift);if(!cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
@@ -72,15 +74,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 */-unsignedlonghash,slot;+unsignedlonggslot;-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,+gslot=pte_get_hash_gslot(vpn,shift,ssize,rpte,0);+if(mmu_hash_ops.hpte_updatepp(gslot,rflags,vpn,mmu_psize,mmu_psize,ssize,flags)==-1)old_pte&=~_PAGE_HPTEFLAGS;}
@@ -107,8 +104,7 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,return-1;}-new_pte|=(slot<<H_PAGE_F_GIX_SHIFT)&-(H_PAGE_F_SECOND|H_PAGE_F_GIX);+new_pte|=pte_set_hidx(ptep,rpte,0,slot);}/*
0xf is considered invalid hidx value. It indicates absence of a backing
HPTE. A PTE is initialized to 0xf either
a) when it is new it is newly allocated to hold 4k-backing-HPTE
or
b) Any time it gets demoted to a 4k-backing-HPTE
This patch shifts the representation by one-modulo-0xf; i.e hidx 0 is
represented as 1, 1 as 2,... , and 0xf as 0. This convention lets us
initialize the secondary-part of the PTE to all zeroes. PTEs are anyway
zero'd when allocated. We do not have to zero them again; thus saving on
the initialization.
Signed-off-by: Ram Pai <redacted>
---
arch/powerpc/include/asm/book3s/64/hash-64k.h | 14 +++++++++++---
1 files changed, 11 insertions(+), 3 deletions(-)
We need PTE bits 3 ,4, 5, 6 and 57 to support protection-keys,
because these are the bits we want to consolidate on across all
configuration to support protection keys.
Bit 3,4,5 and 6 are currently used on 4K-pte kernels. But bit 9
and 10 are available. Hence we use the two available bits and
free up bit 5 and 6. We will still not be able to free up bit 3
and 4. In the absence of any other free bits, we will have to
stay satisfied with what we have :-(. This means we will not
be able to support 32 protection keys, but only 8. The bit
numbers are big-endian as defined in the ISA3.0
This patch does the following change to 4K PTE.
H_PAGE_F_SECOND (S) which occupied bit 4 moves to bit 7.
H_PAGE_F_GIX (G,I,X) which occupied bit 5, 6 and 7 also moves
to bit 8,9, 10 respectively.
H_PAGE_HASHPTE (H) which occupied bit 8 moves to bit 4.
Before the patch, the 4k PTE format was as follows
0 1 2 3 4 5 6 7 8 9 10....................57.....63
: : : : : : : : : : : : :
v v v v v v v v v v v v v
,-,-,-,-,--,--,--,--,-,-,-,-,-,------------------,-,-,-,
|x|x|x|B|S |G |I |X |H| | |x|x|................| |x|x|x|
'_'_'_'_'__'__'__'__'_'_'_'_'_'________________'_'_'_'_'
After the patch, the 4k PTE format is as follows
0 1 2 3 4 5 6 7 8 9 10....................57.....63
: : : : : : : : : : : : :
v v v v v v v v v v v v v
,-,-,-,-,--,--,--,--,-,-,-,-,-,------------------,-,-,-,
|x|x|x|B|H | | |S |G|I|X|x|x|................| |.|.|.|
'_'_'_'_'__'__'__'__'_'_'_'_'_'________________'_'_'_'_'
The patch has no code changes; just swizzles around bits.
Signed-off-by: Ram Pai <redacted>
---
arch/powerpc/include/asm/book3s/64/hash-4k.h | 7 ++++---
arch/powerpc/include/asm/book3s/64/hash-64k.h | 1 +
arch/powerpc/include/asm/book3s/64/hash.h | 1 -
3 files changed, 5 insertions(+), 4 deletions(-)
@@ -14,6 +14,7 @@#define H_PAGE_COMBO _RPAGE_RPN0 /* this is a combo 4k page */#define H_PAGE_4K_PFN _RPAGE_RPN1 /* PFN is for a single 4k page */#define H_PAGE_BUSY _RPAGE_RPN44 /* software: PTE & hash are busy */+#define H_PAGE_HASHPTE _RPAGE_RPN43 /* PTE has associated HPTE *//**WeneedtodifferentiatebetweenexplicithugepageandTHPhuge
@@ -20,6 +20,7 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,pte_t*ptep,unsignedlongtrap,unsignedlongflags,intssize,intsubpg_prot){+real_pte_trpte;unsignedlonghpte_group;unsignedlongrflags,pa;unsignedlongold_pte,new_pte;
@@ -54,6 +55,7 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,*needtoaddin0x1ifit'saread-onlyuserpage*/rflags=htab_convert_pte_flags(new_pte);+rpte=__real_pte(__pte(old_pte),ptep);if(cpu_has_feature(CPU_FTR_NOEXECUTE)&&!cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
@@ -64,13 +66,10 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,/**ThereMIGHTbeanHPTEforthispte*/-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;+unsignedlonggslot=pte_get_hash_gslot(vpn,shift,ssize,+rpte,0);-if(mmu_hash_ops.hpte_updatepp(slot,rflags,vpn,MMU_PAGE_4K,+if(mmu_hash_ops.hpte_updatepp(gslot,rflags,vpn,MMU_PAGE_4K,MMU_PAGE_4K,ssize,flags)==-1)old_pte&=~_PAGE_HPTEFLAGS;}
@@ -118,8 +117,7 @@ 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);+new_pte|=pte_set_hidx(ptep,rpte,0,slot);}*ptep=__pte(new_pte&~H_PAGE_BUSY);return0;
@@ -1617,23 +1617,18 @@ unsigned long pte_get_hash_gslot(unsigned long vpn, unsigned long shift,voidflush_hash_page(unsignedlongvpn,real_pte_tpte,intpsize,intssize,unsignedlongflags){-unsignedlonghash,index,shift,hidx,slot;+unsignedlongindex,shift,gslot;intlocal=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);+gslot=pte_get_hash_gslot(vpn,shift,ssize,pte,index);+DBG_LOW(" sub %ld: gslot=%lx\n",index,gslot);/**Weusesamebasepagesizeandactualpsize,becausewedon't*usethesefunctionsforhugepage*/-mmu_hash_ops.hpte_invalidate(slot,vpn,psize,psize,+mmu_hash_ops.hpte_invalidate(gslot,vpn,psize,psize,ssize,local);}pte_iterate_hashed_end();
The H_PAGE_F_SECOND,H_PAGE_F_GIX are not in the 64K main-PTE.
capture these changes in the dump pte report.
Reviewed-by: Aneesh Kumar K.V <redacted>
Signed-off-by: Ram Pai <redacted>
---
arch/powerpc/mm/dump_linuxpagetables.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
From: Michael Ellerman <hidden> Date: 2018-01-17 13:30:02
On Mon, 2017-11-06 at 08:50:45 UTC, Ram Pai wrote:
Introduce pte_set_hidx().It sets the (H_PAGE_F_SECOND|H_PAGE_F_GIX) bits
at the appropriate location in the PTE of 4K PTE. For 64K PTE, it sets
the bits in the second part of the PTE. Though the implementation for
the former just needs the slot parameter, it does take some additional
parameters to keep the prototype consistent.
This function will be handy as we work towards re-arranging the bits in
the subsequent patches.
Acked-by: Balbir Singh <bsingharora@gmail.com>
Reviewed-by: Aneesh Kumar K.V <redacted>
Signed-off-by: Ram Pai <redacted>