From mboxrd@z Thu Jan 1 00:00:00 1970 Received: with ECARTIS (v1.0.0; list linux-mips); Mon, 18 Apr 2016 15:01:19 +0200 (CEST) Received: from mailapp01.imgtec.com ([195.59.15.196]:53471 "EHLO imgpgp01.kl.imgtec.org" rhost-flags-OK-OK-OK-FAIL) by eddie.linux-mips.org with ESMTP id S27026276AbcDRNBO0FvPF (ORCPT ); Mon, 18 Apr 2016 15:01:14 +0200 Received: from imgpgp01.kl.imgtec.org (imgpgp01.kl.imgtec.org [127.0.0.1]) by imgpgp01.kl.imgtec.org (PGP Universal) with ESMTP id F351441F8E0B; Mon, 18 Apr 2016 14:01:08 +0100 (BST) Received: from mailapp01.imgtec.com ([10.100.180.242]) by imgpgp01.kl.imgtec.org (PGP Universal service); Mon, 18 Apr 2016 14:01:08 +0100 X-PGP-Universal: processed; by imgpgp01.kl.imgtec.org on Mon, 18 Apr 2016 14:01:08 +0100 Received: from HHMAIL01.hh.imgtec.org (unknown [10.100.10.19]) by Websense Email with ESMTPS id 7C1D22B39B094; Mon, 18 Apr 2016 14:01:05 +0100 (IST) Received: from LEMAIL01.le.imgtec.org (192.168.152.62) by HHMAIL01.hh.imgtec.org (10.100.10.19) with Microsoft SMTP Server (TLS) id 14.3.266.1; Mon, 18 Apr 2016 14:01:08 +0100 Received: from localhost (192.168.154.110) by LEMAIL01.le.imgtec.org (192.168.152.62) with Microsoft SMTP Server (TLS) id 14.3.266.1; Mon, 18 Apr 2016 14:01:08 +0100 Date: Mon, 18 Apr 2016 14:01:08 +0100 From: James Hogan To: Paul Burton CC: , Ralf Baechle , "# v4 . 1+" , David Daney , "Huacai Chen" , "Maciej W. Rozycki" , "Paul Gortmaker" , Aneesh Kumar K.V , , "Peter Zijlstra (Intel)" , David Hildenbrand , Andrew Morton , "Jerome Marchand" , Markos Chandras , Alex Smith , "Kirill A. Shutemov" Subject: Re: [PATCH v2 07/13] MIPS: mm: Fix MIPS32 36b physical addressing (alchemy, netlogic) Message-ID: <20160418130107.GO7859@jhogan-linux.le.imgtec.org> References: <1460972133-16973-1-git-send-email-paul.burton@imgtec.com> <1460972133-16973-8-git-send-email-paul.burton@imgtec.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="5PFZVUeDPxlnBcQp" Content-Disposition: inline In-Reply-To: <1460972133-16973-8-git-send-email-paul.burton@imgtec.com> User-Agent: Mutt/1.5.23 (2014-03-12) X-Originating-IP: [192.168.154.110] X-ESG-ENCRYPT-TAG: ebfc6934 Return-Path: X-Envelope-To: <"|/home/ecartis/ecartis -s linux-mips"> (uid 0) X-Orcpt: rfc822;linux-mips@linux-mips.org Original-Recipient: rfc822;linux-mips@linux-mips.org X-archive-position: 53061 X-ecartis-version: Ecartis v1.0.0 Sender: linux-mips-bounce@linux-mips.org Errors-to: linux-mips-bounce@linux-mips.org X-original-sender: james.hogan@imgtec.com Precedence: bulk List-help: List-unsubscribe: List-software: Ecartis version 1.0.0 List-Id: linux-mips X-List-ID: linux-mips List-subscribe: List-owner: List-post: List-archive: X-list: linux-mips --5PFZVUeDPxlnBcQp Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Mon, Apr 18, 2016 at 10:35:27AM +0100, Paul Burton wrote: > There are 2 distinct cases in which a kernel for a MIPS32 CPU > (CONFIG_CPU_MIPS32=3Dy) may use 64 bit physical addresses > (CONFIG_PHYS_ADDR_T_64BIT=3Dy): >=20 > - 36 bit physical addressing as used by RMI Alchemy & Netlogic XLP/XLR > CPUs. >=20 > - MIPS32r5 eXtended Physical Addressing (XPA). >=20 > These 2 cases are distinct in that they require different behaviour from > the kernel - the EntryLo registers have different formats. Until Linux > v4.1 we only supported the first case, with code conditional upon the 2 > aforementioned Kconfig variables being set. Commit c5b367835cfc ("MIPS: > Add support for XPA.") added support for the second case, but did so by > modifying the code that existed for the first case rather than treating > the 2 cases as distinct. Since the EntryLo registers have different > formats this breaks the 36 bit Alchemy/XLP/XLR case. Fix this by > splitting the 2 cases, with XPA cases now being conditional upon > CONFIG_XPA and the non-XPA case matching the code as it existed prior to > commit c5b367835cfc ("MIPS: Add support for XPA."). >=20 > Signed-off-by: Paul Burton > Reported-by: Manuel Lauss > Tested-by: Manuel Lauss > Fixes: c5b367835cfc ("MIPS: Add support for XPA.") > Cc: # v4.1+ Reviewed-by: James Hogan Thanks James >=20 > --- >=20 > Changes in v2: > - Catch some extra pte_low manipulations (thanks James!). >=20 > arch/mips/include/asm/pgtable-32.h | 27 +++++++++++++++-- > arch/mips/include/asm/pgtable-bits.h | 29 +++++++++++++++--- > arch/mips/include/asm/pgtable.h | 57 ++++++++++++++++++++++++++++++= +----- > arch/mips/mm/init.c | 4 ++- > arch/mips/mm/tlbex.c | 35 ++++++++++++++-------- > 5 files changed, 125 insertions(+), 27 deletions(-) >=20 > diff --git a/arch/mips/include/asm/pgtable-32.h b/arch/mips/include/asm/p= gtable-32.h > index 181bd8e..d21f3da 100644 > --- a/arch/mips/include/asm/pgtable-32.h > +++ b/arch/mips/include/asm/pgtable-32.h > @@ -103,7 +103,7 @@ static inline void pmd_clear(pmd_t *pmdp) > pmd_val(*pmdp) =3D ((unsigned long) invalid_pte_table); > } > =20 > -#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) > +#if defined(CONFIG_XPA) > =20 > #define pte_pfn(x) (((unsigned long)((x).pte_high >> _PFN_SHIFT)) | (un= signed long)((x).pte_low << _PAGE_PRESENT_SHIFT)) > static inline pte_t > @@ -118,6 +118,20 @@ pfn_pte(unsigned long pfn, pgprot_t prot) > return pte; > } > =20 > +#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) > + > +#define pte_pfn(x) ((unsigned long)((x).pte_high >> 6)) > + > +static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot) > +{ > + pte_t pte; > + > + pte.pte_high =3D (pfn << 6) | (pgprot_val(prot) & 0x3f); > + pte.pte_low =3D pgprot_val(prot); > + > + return pte; > +} > + > #else > =20 > #ifdef CONFIG_CPU_VR41XX > @@ -166,7 +180,7 @@ pfn_pte(unsigned long pfn, pgprot_t prot) > =20 > #else > =20 > -#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) > +#if defined(CONFIG_XPA) > =20 > /* Swap entries must have VALID and GLOBAL bits cleared. */ > #define __swp_type(x) (((x).val >> 4) & 0x1f) > @@ -175,6 +189,15 @@ pfn_pte(unsigned long pfn, pgprot_t prot) > #define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_high }) > #define __swp_entry_to_pte(x) ((pte_t) { 0, (x).val }) > =20 > +#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) > + > +/* Swap entries must have VALID and GLOBAL bits cleared. */ > +#define __swp_type(x) (((x).val >> 2) & 0x1f) > +#define __swp_offset(x) ((x).val >> 7) > +#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 2) | ((of= fset) << 7) }) > +#define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_high }) > +#define __swp_entry_to_pte(x) ((pte_t) { 0, (x).val }) > + > #else > /* > * Constraints: > diff --git a/arch/mips/include/asm/pgtable-bits.h b/arch/mips/include/asm= /pgtable-bits.h > index 5bc663d..58e8bf8 100644 > --- a/arch/mips/include/asm/pgtable-bits.h > +++ b/arch/mips/include/asm/pgtable-bits.h > @@ -32,11 +32,11 @@ > * unpredictable things. The code (when it is written) to deal with > * this problem will be in the update_mmu_cache() code for the r4k. > */ > -#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) > +#if defined(CONFIG_XPA) > =20 > /* > - * Page table bit offsets used for 64 bit physical addressing on MIPS32, > - * for example with Alchemy, Netlogic XLP/XLR or XPA. > + * Page table bit offsets used for 64 bit physical addressing on > + * MIPS32r5 with XPA. > */ > enum pgtable_bits { > /* Used by TLB hardware (placed in EntryLo*) */ > @@ -59,6 +59,27 @@ enum pgtable_bits { > */ > #define _PFNX_MASK 0xffffff > =20 > +#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) > + > +/* > + * Page table bit offsets used for 36 bit physical addressing on MIPS32, > + * for example with Alchemy or Netlogic XLP/XLR. > + */ > +enum pgtable_bits { > + /* Used by TLB hardware (placed in EntryLo*) */ > + _PAGE_GLOBAL_SHIFT, > + _PAGE_VALID_SHIFT, > + _PAGE_DIRTY_SHIFT, > + _CACHE_SHIFT, > + > + /* Used only by software (masked out before writing EntryLo*) */ > + _PAGE_PRESENT_SHIFT =3D _CACHE_SHIFT + 3, > + _PAGE_NO_READ_SHIFT, > + _PAGE_WRITE_SHIFT, > + _PAGE_ACCESSED_SHIFT, > + _PAGE_MODIFIED_SHIFT, > +}; > + > #elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) > =20 > /* Page table bits used for r3k systems */ > @@ -116,7 +137,7 @@ enum pgtable_bits { > #endif > =20 > /* Used by TLB hardware (placed in EntryLo*) */ > -#if (defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)) > +#if defined(CONFIG_XPA) > # define _PAGE_NO_EXEC (1 << _PAGE_NO_EXEC_SHIFT) > #elif defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) > # define _PAGE_NO_EXEC (cpu_has_rixi ? (1 << _PAGE_NO_EXEC_SHIFT) : 0) > diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgta= ble.h > index 1459ee9..3822d7d 100644 > --- a/arch/mips/include/asm/pgtable.h > +++ b/arch/mips/include/asm/pgtable.h > @@ -130,7 +130,12 @@ do { \ > =20 > #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) > =20 > -#define pte_none(pte) (!(((pte).pte_high) & ~_PAGE_GLOBAL)) > +#ifdef CONFIG_XPA > +# define pte_none(pte) (!(((pte).pte_high) & ~_PAGE_GLOBAL)) > +#else > +# define pte_none(pte) (!(((pte).pte_low | (pte).pte_high) & ~_PAGE_GLO= BAL)) > +#endif > + > #define pte_present(pte) ((pte).pte_low & _PAGE_PRESENT) > =20 > static inline void set_pte(pte_t *ptep, pte_t pte) > @@ -139,14 +144,21 @@ static inline void set_pte(pte_t *ptep, pte_t pte) > smp_wmb(); > ptep->pte_low =3D pte.pte_low; > =20 > +#ifdef CONFIG_XPA > if (pte.pte_high & _PAGE_GLOBAL) { > +#else > + if (pte.pte_low & _PAGE_GLOBAL) { > +#endif > pte_t *buddy =3D ptep_buddy(ptep); > /* > * Make sure the buddy is global too (if it's !none, > * it better already be global) > */ > - if (pte_none(*buddy)) > + if (pte_none(*buddy)) { > + if (!config_enabled(CONFIG_XPA)) > + buddy->pte_low |=3D _PAGE_GLOBAL; > buddy->pte_high |=3D _PAGE_GLOBAL; > + } > } > } > #define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval) > @@ -157,8 +169,13 @@ static inline void pte_clear(struct mm_struct *mm, u= nsigned long addr, pte_t *pt > =20 > htw_stop(); > /* Preserve global status for the pair */ > - if (ptep_buddy(ptep)->pte_high & _PAGE_GLOBAL) > - null.pte_high =3D _PAGE_GLOBAL; > + if (config_enabled(CONFIG_XPA)) { > + if (ptep_buddy(ptep)->pte_high & _PAGE_GLOBAL) > + null.pte_high =3D _PAGE_GLOBAL; > + } else { > + if (ptep_buddy(ptep)->pte_low & _PAGE_GLOBAL) > + null.pte_low =3D null.pte_high =3D _PAGE_GLOBAL; > + } > =20 > set_pte_at(mm, addr, ptep, null); > htw_start(); > @@ -271,6 +288,8 @@ static inline int pte_young(pte_t pte) { return pte.p= te_low & _PAGE_ACCESSED; } > static inline pte_t pte_wrprotect(pte_t pte) > { > pte.pte_low &=3D ~_PAGE_WRITE; > + if (!config_enabled(CONFIG_XPA)) > + pte.pte_low &=3D ~_PAGE_SILENT_WRITE; > pte.pte_high &=3D ~_PAGE_SILENT_WRITE; > return pte; > } > @@ -278,6 +297,8 @@ static inline pte_t pte_wrprotect(pte_t pte) > static inline pte_t pte_mkclean(pte_t pte) > { > pte.pte_low &=3D ~_PAGE_MODIFIED; > + if (!config_enabled(CONFIG_XPA)) > + pte.pte_low &=3D ~_PAGE_SILENT_WRITE; > pte.pte_high &=3D ~_PAGE_SILENT_WRITE; > return pte; > } > @@ -285,6 +306,8 @@ static inline pte_t pte_mkclean(pte_t pte) > static inline pte_t pte_mkold(pte_t pte) > { > pte.pte_low &=3D ~_PAGE_ACCESSED; > + if (!config_enabled(CONFIG_XPA)) > + pte.pte_low &=3D ~_PAGE_SILENT_READ; > pte.pte_high &=3D ~_PAGE_SILENT_READ; > return pte; > } > @@ -292,24 +315,33 @@ static inline pte_t pte_mkold(pte_t pte) > static inline pte_t pte_mkwrite(pte_t pte) > { > pte.pte_low |=3D _PAGE_WRITE; > - if (pte.pte_low & _PAGE_MODIFIED) > + if (pte.pte_low & _PAGE_MODIFIED) { > + if (!config_enabled(CONFIG_XPA)) > + pte.pte_low |=3D _PAGE_SILENT_WRITE; > pte.pte_high |=3D _PAGE_SILENT_WRITE; > + } > return pte; > } > =20 > static inline pte_t pte_mkdirty(pte_t pte) > { > pte.pte_low |=3D _PAGE_MODIFIED; > - if (pte.pte_low & _PAGE_WRITE) > + if (pte.pte_low & _PAGE_WRITE) { > + if (!config_enabled(CONFIG_XPA)) > + pte.pte_low |=3D _PAGE_SILENT_WRITE; > pte.pte_high |=3D _PAGE_SILENT_WRITE; > + } > return pte; > } > =20 > static inline pte_t pte_mkyoung(pte_t pte) > { > pte.pte_low |=3D _PAGE_ACCESSED; > - if (!(pte.pte_low & _PAGE_NO_READ)) > + if (!(pte.pte_low & _PAGE_NO_READ)) { > + if (!config_enabled(CONFIG_XPA)) > + pte.pte_low |=3D _PAGE_SILENT_READ; > pte.pte_high |=3D _PAGE_SILENT_READ; > + } > return pte; > } > #else > @@ -407,7 +439,7 @@ static inline pgprot_t pgprot_writecombine(pgprot_t _= prot) > */ > #define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) > =20 > -#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) > +#if defined(CONFIG_XPA) > static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) > { > pte.pte_low &=3D (_PAGE_MODIFIED | _PAGE_ACCESSED | _PFNX_MASK); > @@ -416,6 +448,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t n= ewprot) > pte.pte_high |=3D pgprot_val(newprot) & ~_PFN_MASK; > return pte; > } > +#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) > +static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) > +{ > + pte.pte_low &=3D _PAGE_CHG_MASK; > + pte.pte_high &=3D (_PFN_MASK | _CACHE_MASK); > + pte.pte_low |=3D pgprot_val(newprot); > + pte.pte_high |=3D pgprot_val(newprot) & ~(_PFN_MASK | _CACHE_MASK); > + return pte; > +} > #else > static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) > { > diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c > index 7e5fa09..0e57893 100644 > --- a/arch/mips/mm/init.c > +++ b/arch/mips/mm/init.c > @@ -98,8 +98,10 @@ static void *__kmap_pgprot(struct page *page, unsigned= long addr, pgprot_t prot) > idx +=3D in_interrupt() ? FIX_N_COLOURS : 0; > vaddr =3D __fix_to_virt(FIX_CMAP_END - idx); > pte =3D mk_pte(page, prot); > -#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) > +#if defined(CONFIG_XPA) > entrylo =3D pte_to_entrylo(pte.pte_high); > +#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) > + entrylo =3D pte.pte_high; > #else > entrylo =3D pte_to_entrylo(pte_val(pte)); > #endif > diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c > index 7e3272f..ceaee32 100644 > --- a/arch/mips/mm/tlbex.c > +++ b/arch/mips/mm/tlbex.c > @@ -1003,25 +1003,21 @@ static void build_get_ptep(u32 **p, unsigned int = tmp, unsigned int ptr) > =20 > static void build_update_entries(u32 **p, unsigned int tmp, unsigned int= ptep) > { > - /* > - * 64bit address support (36bit on a 32bit CPU) in a 32bit > - * Kernel is a special case. Only a few CPUs use it. > - */ > - if (config_enabled(CONFIG_PHYS_ADDR_T_64BIT) && !cpu_has_64bits) { > + if (config_enabled(CONFIG_XPA)) { > int pte_off_even =3D sizeof(pte_t) / 2; > int pte_off_odd =3D pte_off_even + sizeof(pte_t); > -#ifdef CONFIG_XPA > const int scratch =3D 1; /* Our extra working register */ > =20 > uasm_i_addu(p, scratch, 0, ptep); > -#endif > + > uasm_i_lw(p, tmp, pte_off_even, ptep); /* even pte */ > - uasm_i_lw(p, ptep, pte_off_odd, ptep); /* odd pte */ > UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL)); > - UASM_i_ROTR(p, ptep, ptep, ilog2(_PAGE_GLOBAL)); > UASM_i_MTC0(p, tmp, C0_ENTRYLO0); > + > + uasm_i_lw(p, ptep, pte_off_odd, ptep); /* odd pte */ > + UASM_i_ROTR(p, ptep, ptep, ilog2(_PAGE_GLOBAL)); > UASM_i_MTC0(p, ptep, C0_ENTRYLO1); > -#ifdef CONFIG_XPA > + > uasm_i_lw(p, tmp, 0, scratch); > uasm_i_lw(p, ptep, sizeof(pte_t), scratch); > uasm_i_lui(p, scratch, 0xff); > @@ -1030,7 +1026,22 @@ static void build_update_entries(u32 **p, unsigned= int tmp, unsigned int ptep) > uasm_i_and(p, ptep, scratch, ptep); > uasm_i_mthc0(p, tmp, C0_ENTRYLO0); > uasm_i_mthc0(p, ptep, C0_ENTRYLO1); > -#endif > + return; > + } > + > + /* > + * 64bit address support (36bit on a 32bit CPU) in a 32bit > + * Kernel is a special case. Only a few CPUs use it. > + */ > + if (config_enabled(CONFIG_PHYS_ADDR_T_64BIT) && !cpu_has_64bits) { > + int pte_off_even =3D sizeof(pte_t) / 2; > + int pte_off_odd =3D pte_off_even + sizeof(pte_t); > + > + uasm_i_lw(p, tmp, pte_off_even, ptep); /* even pte */ > + UASM_i_MTC0(p, tmp, C0_ENTRYLO0); > + > + uasm_i_lw(p, ptep, pte_off_odd, ptep); /* odd pte */ > + UASM_i_MTC0(p, ptep, C0_ENTRYLO1); > return; > } > =20 > @@ -1524,7 +1535,7 @@ iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned in= t pte, unsigned int ptr, > #ifdef CONFIG_PHYS_ADDR_T_64BIT > unsigned int hwmode =3D mode & (_PAGE_VALID | _PAGE_DIRTY); > =20 > - if (!cpu_has_64bits) { > + if (config_enabled(CONFIG_XPA) && !cpu_has_64bits) { > const int scratch =3D 1; /* Our extra working register */ > =20 > uasm_i_lui(p, scratch, (mode >> 16)); > --=20 > 2.8.0 >=20 --5PFZVUeDPxlnBcQp Content-Type: application/pgp-signature; name="signature.asc" Content-Description: Digital signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAEBCAAGBQJXFNqTAAoJEGwLaZPeOHZ6ryQQALjjK05LpTVdrj8PbUQQh7C/ joXUZRVOx7WJIBBQ49se12z6Pc1Y8mpfbazczCla+mP7K/CITTbT/v8CKewJ8DuG OkLcI5gTx0ejKG/yqE0fNhVgxe7XiPndLemf8dt6WXWumdxzByGhWv8ZlmZm1H4D Mw1Dk8TPyCC1tQgLa9WXJhZIYiG/bYpiMb1qF17c2mCWkEpSKsl5aigFZCiKaELx Od1gofjWJB2CDtMLxCcckTvG3E7M926IsseGvsc3gKiCuOlb9Z6VMAHRCvWzJ9t4 ax0aNJfyrOn1kTJLwyRnBcwf4N5qPyk8mDX59VzGdttqL8j+or/9YLye9HS2cE5l OlFRubi+0cUI7Piw4s6DUhlQNISX5WMQ8IlbO+st2K0ddOJXAtPXK/TPRupUwDA2 WP4HOOgpthbi9108qXPXJzUpKg/9XwtYJ8AoHa/NiEbf1oIX+JQoy97EuDClfbff YYZLDxhm6aDzQasUFrObwreu06n7vjRIuquX4uq/J0iwB80+p3+ILtAW/osKQ/87 3UQtJ7l5P9Cz97Ea/4nxkolaWAs+krBdWhFL8hozfmCrc/eLNcL5GWSyTlHuglBW XQVAYItMOu5Q9kiT+Vd6pcoxp/FCgEXWQCQ6TbZFlfNCsLBVkgU0+DH7fi+IvgiR CsmB2atHlgFDa5Zy93De =+bUA -----END PGP SIGNATURE----- --5PFZVUeDPxlnBcQp-- From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailapp01.imgtec.com ([195.59.15.196]:53471 "EHLO imgpgp01.kl.imgtec.org" rhost-flags-OK-OK-OK-FAIL) by eddie.linux-mips.org with ESMTP id S27026276AbcDRNBO0FvPF (ORCPT ); Mon, 18 Apr 2016 15:01:14 +0200 Date: Mon, 18 Apr 2016 14:01:08 +0100 From: James Hogan Subject: Re: [PATCH v2 07/13] MIPS: mm: Fix MIPS32 36b physical addressing (alchemy, netlogic) Message-ID: <20160418130107.GO7859@jhogan-linux.le.imgtec.org> References: <1460972133-16973-1-git-send-email-paul.burton@imgtec.com> <1460972133-16973-8-git-send-email-paul.burton@imgtec.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="5PFZVUeDPxlnBcQp" Content-Disposition: inline In-Reply-To: <1460972133-16973-8-git-send-email-paul.burton@imgtec.com> Return-Path: Sender: linux-mips-bounce@linux-mips.org Errors-to: linux-mips-bounce@linux-mips.org List-help: List-unsubscribe: List-software: Ecartis version 1.0.0 List-subscribe: List-owner: List-post: List-archive: To: Paul Burton Cc: linux-mips@linux-mips.org, Ralf Baechle , "# v4 . 1+" , David Daney , Huacai Chen , "Maciej W. Rozycki" , Paul Gortmaker , "Aneesh Kumar K.V" , linux-kernel@vger.kernel.org, "Peter Zijlstra (Intel)" , David Hildenbrand , Andrew Morton , Jerome Marchand , Markos Chandras , Alex Smith , "Kirill A. Shutemov" Message-ID: <20160418130108.imxrdDvkH7QryWcHd3hkb9yY2gwXBJ9r9n4yABVUpRc@z> --5PFZVUeDPxlnBcQp Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Mon, Apr 18, 2016 at 10:35:27AM +0100, Paul Burton wrote: > There are 2 distinct cases in which a kernel for a MIPS32 CPU > (CONFIG_CPU_MIPS32=3Dy) may use 64 bit physical addresses > (CONFIG_PHYS_ADDR_T_64BIT=3Dy): >=20 > - 36 bit physical addressing as used by RMI Alchemy & Netlogic XLP/XLR > CPUs. >=20 > - MIPS32r5 eXtended Physical Addressing (XPA). >=20 > These 2 cases are distinct in that they require different behaviour from > the kernel - the EntryLo registers have different formats. Until Linux > v4.1 we only supported the first case, with code conditional upon the 2 > aforementioned Kconfig variables being set. Commit c5b367835cfc ("MIPS: > Add support for XPA.") added support for the second case, but did so by > modifying the code that existed for the first case rather than treating > the 2 cases as distinct. Since the EntryLo registers have different > formats this breaks the 36 bit Alchemy/XLP/XLR case. Fix this by > splitting the 2 cases, with XPA cases now being conditional upon > CONFIG_XPA and the non-XPA case matching the code as it existed prior to > commit c5b367835cfc ("MIPS: Add support for XPA."). >=20 > Signed-off-by: Paul Burton > Reported-by: Manuel Lauss > Tested-by: Manuel Lauss > Fixes: c5b367835cfc ("MIPS: Add support for XPA.") > Cc: # v4.1+ Reviewed-by: James Hogan Thanks James >=20 > --- >=20 > Changes in v2: > - Catch some extra pte_low manipulations (thanks James!). >=20 > arch/mips/include/asm/pgtable-32.h | 27 +++++++++++++++-- > arch/mips/include/asm/pgtable-bits.h | 29 +++++++++++++++--- > arch/mips/include/asm/pgtable.h | 57 ++++++++++++++++++++++++++++++= +----- > arch/mips/mm/init.c | 4 ++- > arch/mips/mm/tlbex.c | 35 ++++++++++++++-------- > 5 files changed, 125 insertions(+), 27 deletions(-) >=20 > diff --git a/arch/mips/include/asm/pgtable-32.h b/arch/mips/include/asm/p= gtable-32.h > index 181bd8e..d21f3da 100644 > --- a/arch/mips/include/asm/pgtable-32.h > +++ b/arch/mips/include/asm/pgtable-32.h > @@ -103,7 +103,7 @@ static inline void pmd_clear(pmd_t *pmdp) > pmd_val(*pmdp) =3D ((unsigned long) invalid_pte_table); > } > =20 > -#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) > +#if defined(CONFIG_XPA) > =20 > #define pte_pfn(x) (((unsigned long)((x).pte_high >> _PFN_SHIFT)) | (un= signed long)((x).pte_low << _PAGE_PRESENT_SHIFT)) > static inline pte_t > @@ -118,6 +118,20 @@ pfn_pte(unsigned long pfn, pgprot_t prot) > return pte; > } > =20 > +#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) > + > +#define pte_pfn(x) ((unsigned long)((x).pte_high >> 6)) > + > +static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot) > +{ > + pte_t pte; > + > + pte.pte_high =3D (pfn << 6) | (pgprot_val(prot) & 0x3f); > + pte.pte_low =3D pgprot_val(prot); > + > + return pte; > +} > + > #else > =20 > #ifdef CONFIG_CPU_VR41XX > @@ -166,7 +180,7 @@ pfn_pte(unsigned long pfn, pgprot_t prot) > =20 > #else > =20 > -#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) > +#if defined(CONFIG_XPA) > =20 > /* Swap entries must have VALID and GLOBAL bits cleared. */ > #define __swp_type(x) (((x).val >> 4) & 0x1f) > @@ -175,6 +189,15 @@ pfn_pte(unsigned long pfn, pgprot_t prot) > #define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_high }) > #define __swp_entry_to_pte(x) ((pte_t) { 0, (x).val }) > =20 > +#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) > + > +/* Swap entries must have VALID and GLOBAL bits cleared. */ > +#define __swp_type(x) (((x).val >> 2) & 0x1f) > +#define __swp_offset(x) ((x).val >> 7) > +#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 2) | ((of= fset) << 7) }) > +#define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_high }) > +#define __swp_entry_to_pte(x) ((pte_t) { 0, (x).val }) > + > #else > /* > * Constraints: > diff --git a/arch/mips/include/asm/pgtable-bits.h b/arch/mips/include/asm= /pgtable-bits.h > index 5bc663d..58e8bf8 100644 > --- a/arch/mips/include/asm/pgtable-bits.h > +++ b/arch/mips/include/asm/pgtable-bits.h > @@ -32,11 +32,11 @@ > * unpredictable things. The code (when it is written) to deal with > * this problem will be in the update_mmu_cache() code for the r4k. > */ > -#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) > +#if defined(CONFIG_XPA) > =20 > /* > - * Page table bit offsets used for 64 bit physical addressing on MIPS32, > - * for example with Alchemy, Netlogic XLP/XLR or XPA. > + * Page table bit offsets used for 64 bit physical addressing on > + * MIPS32r5 with XPA. > */ > enum pgtable_bits { > /* Used by TLB hardware (placed in EntryLo*) */ > @@ -59,6 +59,27 @@ enum pgtable_bits { > */ > #define _PFNX_MASK 0xffffff > =20 > +#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) > + > +/* > + * Page table bit offsets used for 36 bit physical addressing on MIPS32, > + * for example with Alchemy or Netlogic XLP/XLR. > + */ > +enum pgtable_bits { > + /* Used by TLB hardware (placed in EntryLo*) */ > + _PAGE_GLOBAL_SHIFT, > + _PAGE_VALID_SHIFT, > + _PAGE_DIRTY_SHIFT, > + _CACHE_SHIFT, > + > + /* Used only by software (masked out before writing EntryLo*) */ > + _PAGE_PRESENT_SHIFT =3D _CACHE_SHIFT + 3, > + _PAGE_NO_READ_SHIFT, > + _PAGE_WRITE_SHIFT, > + _PAGE_ACCESSED_SHIFT, > + _PAGE_MODIFIED_SHIFT, > +}; > + > #elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) > =20 > /* Page table bits used for r3k systems */ > @@ -116,7 +137,7 @@ enum pgtable_bits { > #endif > =20 > /* Used by TLB hardware (placed in EntryLo*) */ > -#if (defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)) > +#if defined(CONFIG_XPA) > # define _PAGE_NO_EXEC (1 << _PAGE_NO_EXEC_SHIFT) > #elif defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) > # define _PAGE_NO_EXEC (cpu_has_rixi ? (1 << _PAGE_NO_EXEC_SHIFT) : 0) > diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgta= ble.h > index 1459ee9..3822d7d 100644 > --- a/arch/mips/include/asm/pgtable.h > +++ b/arch/mips/include/asm/pgtable.h > @@ -130,7 +130,12 @@ do { \ > =20 > #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) > =20 > -#define pte_none(pte) (!(((pte).pte_high) & ~_PAGE_GLOBAL)) > +#ifdef CONFIG_XPA > +# define pte_none(pte) (!(((pte).pte_high) & ~_PAGE_GLOBAL)) > +#else > +# define pte_none(pte) (!(((pte).pte_low | (pte).pte_high) & ~_PAGE_GLO= BAL)) > +#endif > + > #define pte_present(pte) ((pte).pte_low & _PAGE_PRESENT) > =20 > static inline void set_pte(pte_t *ptep, pte_t pte) > @@ -139,14 +144,21 @@ static inline void set_pte(pte_t *ptep, pte_t pte) > smp_wmb(); > ptep->pte_low =3D pte.pte_low; > =20 > +#ifdef CONFIG_XPA > if (pte.pte_high & _PAGE_GLOBAL) { > +#else > + if (pte.pte_low & _PAGE_GLOBAL) { > +#endif > pte_t *buddy =3D ptep_buddy(ptep); > /* > * Make sure the buddy is global too (if it's !none, > * it better already be global) > */ > - if (pte_none(*buddy)) > + if (pte_none(*buddy)) { > + if (!config_enabled(CONFIG_XPA)) > + buddy->pte_low |=3D _PAGE_GLOBAL; > buddy->pte_high |=3D _PAGE_GLOBAL; > + } > } > } > #define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval) > @@ -157,8 +169,13 @@ static inline void pte_clear(struct mm_struct *mm, u= nsigned long addr, pte_t *pt > =20 > htw_stop(); > /* Preserve global status for the pair */ > - if (ptep_buddy(ptep)->pte_high & _PAGE_GLOBAL) > - null.pte_high =3D _PAGE_GLOBAL; > + if (config_enabled(CONFIG_XPA)) { > + if (ptep_buddy(ptep)->pte_high & _PAGE_GLOBAL) > + null.pte_high =3D _PAGE_GLOBAL; > + } else { > + if (ptep_buddy(ptep)->pte_low & _PAGE_GLOBAL) > + null.pte_low =3D null.pte_high =3D _PAGE_GLOBAL; > + } > =20 > set_pte_at(mm, addr, ptep, null); > htw_start(); > @@ -271,6 +288,8 @@ static inline int pte_young(pte_t pte) { return pte.p= te_low & _PAGE_ACCESSED; } > static inline pte_t pte_wrprotect(pte_t pte) > { > pte.pte_low &=3D ~_PAGE_WRITE; > + if (!config_enabled(CONFIG_XPA)) > + pte.pte_low &=3D ~_PAGE_SILENT_WRITE; > pte.pte_high &=3D ~_PAGE_SILENT_WRITE; > return pte; > } > @@ -278,6 +297,8 @@ static inline pte_t pte_wrprotect(pte_t pte) > static inline pte_t pte_mkclean(pte_t pte) > { > pte.pte_low &=3D ~_PAGE_MODIFIED; > + if (!config_enabled(CONFIG_XPA)) > + pte.pte_low &=3D ~_PAGE_SILENT_WRITE; > pte.pte_high &=3D ~_PAGE_SILENT_WRITE; > return pte; > } > @@ -285,6 +306,8 @@ static inline pte_t pte_mkclean(pte_t pte) > static inline pte_t pte_mkold(pte_t pte) > { > pte.pte_low &=3D ~_PAGE_ACCESSED; > + if (!config_enabled(CONFIG_XPA)) > + pte.pte_low &=3D ~_PAGE_SILENT_READ; > pte.pte_high &=3D ~_PAGE_SILENT_READ; > return pte; > } > @@ -292,24 +315,33 @@ static inline pte_t pte_mkold(pte_t pte) > static inline pte_t pte_mkwrite(pte_t pte) > { > pte.pte_low |=3D _PAGE_WRITE; > - if (pte.pte_low & _PAGE_MODIFIED) > + if (pte.pte_low & _PAGE_MODIFIED) { > + if (!config_enabled(CONFIG_XPA)) > + pte.pte_low |=3D _PAGE_SILENT_WRITE; > pte.pte_high |=3D _PAGE_SILENT_WRITE; > + } > return pte; > } > =20 > static inline pte_t pte_mkdirty(pte_t pte) > { > pte.pte_low |=3D _PAGE_MODIFIED; > - if (pte.pte_low & _PAGE_WRITE) > + if (pte.pte_low & _PAGE_WRITE) { > + if (!config_enabled(CONFIG_XPA)) > + pte.pte_low |=3D _PAGE_SILENT_WRITE; > pte.pte_high |=3D _PAGE_SILENT_WRITE; > + } > return pte; > } > =20 > static inline pte_t pte_mkyoung(pte_t pte) > { > pte.pte_low |=3D _PAGE_ACCESSED; > - if (!(pte.pte_low & _PAGE_NO_READ)) > + if (!(pte.pte_low & _PAGE_NO_READ)) { > + if (!config_enabled(CONFIG_XPA)) > + pte.pte_low |=3D _PAGE_SILENT_READ; > pte.pte_high |=3D _PAGE_SILENT_READ; > + } > return pte; > } > #else > @@ -407,7 +439,7 @@ static inline pgprot_t pgprot_writecombine(pgprot_t _= prot) > */ > #define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) > =20 > -#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) > +#if defined(CONFIG_XPA) > static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) > { > pte.pte_low &=3D (_PAGE_MODIFIED | _PAGE_ACCESSED | _PFNX_MASK); > @@ -416,6 +448,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t n= ewprot) > pte.pte_high |=3D pgprot_val(newprot) & ~_PFN_MASK; > return pte; > } > +#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) > +static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) > +{ > + pte.pte_low &=3D _PAGE_CHG_MASK; > + pte.pte_high &=3D (_PFN_MASK | _CACHE_MASK); > + pte.pte_low |=3D pgprot_val(newprot); > + pte.pte_high |=3D pgprot_val(newprot) & ~(_PFN_MASK | _CACHE_MASK); > + return pte; > +} > #else > static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) > { > diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c > index 7e5fa09..0e57893 100644 > --- a/arch/mips/mm/init.c > +++ b/arch/mips/mm/init.c > @@ -98,8 +98,10 @@ static void *__kmap_pgprot(struct page *page, unsigned= long addr, pgprot_t prot) > idx +=3D in_interrupt() ? FIX_N_COLOURS : 0; > vaddr =3D __fix_to_virt(FIX_CMAP_END - idx); > pte =3D mk_pte(page, prot); > -#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) > +#if defined(CONFIG_XPA) > entrylo =3D pte_to_entrylo(pte.pte_high); > +#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) > + entrylo =3D pte.pte_high; > #else > entrylo =3D pte_to_entrylo(pte_val(pte)); > #endif > diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c > index 7e3272f..ceaee32 100644 > --- a/arch/mips/mm/tlbex.c > +++ b/arch/mips/mm/tlbex.c > @@ -1003,25 +1003,21 @@ static void build_get_ptep(u32 **p, unsigned int = tmp, unsigned int ptr) > =20 > static void build_update_entries(u32 **p, unsigned int tmp, unsigned int= ptep) > { > - /* > - * 64bit address support (36bit on a 32bit CPU) in a 32bit > - * Kernel is a special case. Only a few CPUs use it. > - */ > - if (config_enabled(CONFIG_PHYS_ADDR_T_64BIT) && !cpu_has_64bits) { > + if (config_enabled(CONFIG_XPA)) { > int pte_off_even =3D sizeof(pte_t) / 2; > int pte_off_odd =3D pte_off_even + sizeof(pte_t); > -#ifdef CONFIG_XPA > const int scratch =3D 1; /* Our extra working register */ > =20 > uasm_i_addu(p, scratch, 0, ptep); > -#endif > + > uasm_i_lw(p, tmp, pte_off_even, ptep); /* even pte */ > - uasm_i_lw(p, ptep, pte_off_odd, ptep); /* odd pte */ > UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL)); > - UASM_i_ROTR(p, ptep, ptep, ilog2(_PAGE_GLOBAL)); > UASM_i_MTC0(p, tmp, C0_ENTRYLO0); > + > + uasm_i_lw(p, ptep, pte_off_odd, ptep); /* odd pte */ > + UASM_i_ROTR(p, ptep, ptep, ilog2(_PAGE_GLOBAL)); > UASM_i_MTC0(p, ptep, C0_ENTRYLO1); > -#ifdef CONFIG_XPA > + > uasm_i_lw(p, tmp, 0, scratch); > uasm_i_lw(p, ptep, sizeof(pte_t), scratch); > uasm_i_lui(p, scratch, 0xff); > @@ -1030,7 +1026,22 @@ static void build_update_entries(u32 **p, unsigned= int tmp, unsigned int ptep) > uasm_i_and(p, ptep, scratch, ptep); > uasm_i_mthc0(p, tmp, C0_ENTRYLO0); > uasm_i_mthc0(p, ptep, C0_ENTRYLO1); > -#endif > + return; > + } > + > + /* > + * 64bit address support (36bit on a 32bit CPU) in a 32bit > + * Kernel is a special case. Only a few CPUs use it. > + */ > + if (config_enabled(CONFIG_PHYS_ADDR_T_64BIT) && !cpu_has_64bits) { > + int pte_off_even =3D sizeof(pte_t) / 2; > + int pte_off_odd =3D pte_off_even + sizeof(pte_t); > + > + uasm_i_lw(p, tmp, pte_off_even, ptep); /* even pte */ > + UASM_i_MTC0(p, tmp, C0_ENTRYLO0); > + > + uasm_i_lw(p, ptep, pte_off_odd, ptep); /* odd pte */ > + UASM_i_MTC0(p, ptep, C0_ENTRYLO1); > return; > } > =20 > @@ -1524,7 +1535,7 @@ iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned in= t pte, unsigned int ptr, > #ifdef CONFIG_PHYS_ADDR_T_64BIT > unsigned int hwmode =3D mode & (_PAGE_VALID | _PAGE_DIRTY); > =20 > - if (!cpu_has_64bits) { > + if (config_enabled(CONFIG_XPA) && !cpu_has_64bits) { > const int scratch =3D 1; /* Our extra working register */ > =20 > uasm_i_lui(p, scratch, (mode >> 16)); > --=20 > 2.8.0 >=20 --5PFZVUeDPxlnBcQp Content-Type: application/pgp-signature; name="signature.asc" Content-Description: Digital signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAEBCAAGBQJXFNqTAAoJEGwLaZPeOHZ6ryQQALjjK05LpTVdrj8PbUQQh7C/ joXUZRVOx7WJIBBQ49se12z6Pc1Y8mpfbazczCla+mP7K/CITTbT/v8CKewJ8DuG OkLcI5gTx0ejKG/yqE0fNhVgxe7XiPndLemf8dt6WXWumdxzByGhWv8ZlmZm1H4D Mw1Dk8TPyCC1tQgLa9WXJhZIYiG/bYpiMb1qF17c2mCWkEpSKsl5aigFZCiKaELx Od1gofjWJB2CDtMLxCcckTvG3E7M926IsseGvsc3gKiCuOlb9Z6VMAHRCvWzJ9t4 ax0aNJfyrOn1kTJLwyRnBcwf4N5qPyk8mDX59VzGdttqL8j+or/9YLye9HS2cE5l OlFRubi+0cUI7Piw4s6DUhlQNISX5WMQ8IlbO+st2K0ddOJXAtPXK/TPRupUwDA2 WP4HOOgpthbi9108qXPXJzUpKg/9XwtYJ8AoHa/NiEbf1oIX+JQoy97EuDClfbff YYZLDxhm6aDzQasUFrObwreu06n7vjRIuquX4uq/J0iwB80+p3+ILtAW/osKQ/87 3UQtJ7l5P9Cz97Ea/4nxkolaWAs+krBdWhFL8hozfmCrc/eLNcL5GWSyTlHuglBW XQVAYItMOu5Q9kiT+Vd6pcoxp/FCgEXWQCQ6TbZFlfNCsLBVkgU0+DH7fi+IvgiR CsmB2atHlgFDa5Zy93De =+bUA -----END PGP SIGNATURE----- --5PFZVUeDPxlnBcQp--