- Fix kernel panic on specific Qualcomm platform due to broken erratum

workaround
 - Revert contiguous bit support due to TLB conflict aborts in simulation
 - Don't treat all CPU ID register fields as 4-bit quantities
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABCgAGBQJYsHbpAAoJELescNyEwWM03xgH/jPZwxdS0UL1WftjqE7VXBI2
 5STwLBXB8cBr527QHBY7VCbtEQZAFnij7vJ8Eqe6nA8SMDbC1RTJ2ZkiPq0rKjVg
 pVJEdd3jEcRb3HNam90tOBTjlsyuR5Eagj0RI07j+YgsKhCxVTf6wu7z2StKhbuk
 o8P3fbV9JA9c68JR2MR7Z2GFe2pZW0vbRrKoSx6CdoCU8Wod46BUq+P+BoeVR+vZ
 593ERXnDi9tzoWFLyJYobO0PVuoipjX4e6+NxX+hPRKck6gJByainhnl63gGil9L
 vavJ2r3GK4pO5qAsusx6eXQksyR9lX5tGPk7XgJi+M+WMd4Moe+/zNXd4NADGww=
 =aG7Y
 -----END PGP SIGNATURE-----

Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux

Pull arm64 fixes from Will Deacon:
 "The main fix here addresses a kernel panic triggered on Qualcomm
  QDF2400 due to incorrect register usage in an erratum workaround
  introduced during the merge window.

  Summary:

   - Fix kernel panic on specific Qualcomm platform due to broken
     erratum workaround

   - Revert contiguous bit support due to TLB conflict aborts in
     simulation

   - Don't treat all CPU ID register fields as 4-bit quantities"

* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
  arm64/cpufeature: check correct field width when updating sys_val
  Revert "arm64: mm: set the contiguous bit for kernel mappings where appropriate"
  arm64: Avoid clobbering mm in erratum workaround on QDF2400
This commit is contained in:
Linus Torvalds 2017-03-01 10:32:30 -08:00
commit 6053dc9814
3 changed files with 15 additions and 35 deletions

View File

@ -184,16 +184,22 @@ static inline u64 arm64_ftr_reg_user_value(const struct arm64_ftr_reg *reg)
} }
static inline int __attribute_const__ static inline int __attribute_const__
cpuid_feature_extract_field(u64 features, int field, bool sign) cpuid_feature_extract_field_width(u64 features, int field, int width, bool sign)
{ {
return (sign) ? return (sign) ?
cpuid_feature_extract_signed_field(features, field) : cpuid_feature_extract_signed_field_width(features, field, width) :
cpuid_feature_extract_unsigned_field(features, field); cpuid_feature_extract_unsigned_field_width(features, field, width);
}
static inline int __attribute_const__
cpuid_feature_extract_field(u64 features, int field, bool sign)
{
return cpuid_feature_extract_field_width(features, field, 4, sign);
} }
static inline s64 arm64_ftr_value(const struct arm64_ftr_bits *ftrp, u64 val) static inline s64 arm64_ftr_value(const struct arm64_ftr_bits *ftrp, u64 val)
{ {
return (s64)cpuid_feature_extract_field(val, ftrp->shift, ftrp->sign); return (s64)cpuid_feature_extract_field_width(val, ftrp->shift, ftrp->width, ftrp->sign);
} }
static inline bool id_aa64mmfr0_mixed_endian_el0(u64 mmfr0) static inline bool id_aa64mmfr0_mixed_endian_el0(u64 mmfr0)

View File

@ -109,10 +109,8 @@ static bool pgattr_change_is_safe(u64 old, u64 new)
static void alloc_init_pte(pmd_t *pmd, unsigned long addr, static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
unsigned long end, unsigned long pfn, unsigned long end, unsigned long pfn,
pgprot_t prot, pgprot_t prot,
phys_addr_t (*pgtable_alloc)(void), phys_addr_t (*pgtable_alloc)(void))
bool page_mappings_only)
{ {
pgprot_t __prot = prot;
pte_t *pte; pte_t *pte;
BUG_ON(pmd_sect(*pmd)); BUG_ON(pmd_sect(*pmd));
@ -130,18 +128,7 @@ static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
do { do {
pte_t old_pte = *pte; pte_t old_pte = *pte;
/* set_pte(pte, pfn_pte(pfn, prot));
* Set the contiguous bit for the subsequent group of PTEs if
* its size and alignment are appropriate.
*/
if (((addr | PFN_PHYS(pfn)) & ~CONT_PTE_MASK) == 0) {
if (end - addr >= CONT_PTE_SIZE && !page_mappings_only)
__prot = __pgprot(pgprot_val(prot) | PTE_CONT);
else
__prot = prot;
}
set_pte(pte, pfn_pte(pfn, __prot));
pfn++; pfn++;
/* /*
@ -160,7 +147,6 @@ static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end,
phys_addr_t (*pgtable_alloc)(void), phys_addr_t (*pgtable_alloc)(void),
bool page_mappings_only) bool page_mappings_only)
{ {
pgprot_t __prot = prot;
pmd_t *pmd; pmd_t *pmd;
unsigned long next; unsigned long next;
@ -187,18 +173,7 @@ static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end,
/* try section mapping first */ /* try section mapping first */
if (((addr | next | phys) & ~SECTION_MASK) == 0 && if (((addr | next | phys) & ~SECTION_MASK) == 0 &&
!page_mappings_only) { !page_mappings_only) {
/* pmd_set_huge(pmd, phys, prot);
* Set the contiguous bit for the subsequent group of
* PMDs if its size and alignment are appropriate.
*/
if (((addr | phys) & ~CONT_PMD_MASK) == 0) {
if (end - addr >= CONT_PMD_SIZE)
__prot = __pgprot(pgprot_val(prot) |
PTE_CONT);
else
__prot = prot;
}
pmd_set_huge(pmd, phys, __prot);
/* /*
* After the PMD entry has been populated once, we * After the PMD entry has been populated once, we
@ -208,8 +183,7 @@ static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end,
pmd_val(*pmd))); pmd_val(*pmd)));
} else { } else {
alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys), alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys),
prot, pgtable_alloc, prot, pgtable_alloc);
page_mappings_only);
BUG_ON(pmd_val(old_pmd) != 0 && BUG_ON(pmd_val(old_pmd) != 0 &&
pmd_val(old_pmd) != pmd_val(*pmd)); pmd_val(old_pmd) != pmd_val(*pmd));

View File

@ -138,7 +138,7 @@ ENDPROC(cpu_do_resume)
* - pgd_phys - physical address of new TTB * - pgd_phys - physical address of new TTB
*/ */
ENTRY(cpu_do_switch_mm) ENTRY(cpu_do_switch_mm)
pre_ttbr0_update_workaround x0, x1, x2 pre_ttbr0_update_workaround x0, x2, x3
mmid x1, x1 // get mm->context.id mmid x1, x1 // get mm->context.id
bfi x0, x1, #48, #16 // set the ASID bfi x0, x1, #48, #16 // set the ASID
msr ttbr0_el1, x0 // set TTBR0 msr ttbr0_el1, x0 // set TTBR0