Commit 9f42f674 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull arm64 fixes from Will Deacon:
 "A pair of arm64 fixes for -rc3. The straightforward one is a fix to
  our firmware calling stub, which accidentally started corrupting the
  link register on machines with SVE. Since these machines don't really
  exist yet, it wasn't spotted in -next.

  The other fix is a revert-and-a-bit of a patch originally intended to
  allow PTE-level huge mappings for the VMAP area on 32-bit PPC 8xx. A
  side-effect of this change was that our pXd_set_huge() implementations
  could be replaced with generic dummy functions depending on the levels
  of page-table being used, which in turn broke the boot if we fail to
  create the linear mapping as a result of using these functions to
  operate on the pgd. Huge thanks to Michael Ellerman for modifying the
  revert so as not to regress PPC 8xx in terms of functionality.

  Anyway, that's the background and it's also available in the commit
  message along with Link tags pointing at all of the fun.

  Summary:

   - Fix hang when issuing SMC on SVE-capable system due to
     clobbered LR

   - Fix boot failure due to missing block mappings with folded
     page-table"

* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
  Revert "mm/pgtable: add stubs for {pmd/pub}_{set/clear}_huge"
  arm64: smccc: Save lr before calling __arm_smccc_sve_check()
parents 7c14e4d6 d8a71905
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -32,20 +32,23 @@ SYM_FUNC_END(__arm_smccc_sve_check)
EXPORT_SYMBOL(__arm_smccc_sve_check)

	.macro SMCCC instr
	stp     x29, x30, [sp, #-16]!
	mov	x29, sp
alternative_if ARM64_SVE
	bl	__arm_smccc_sve_check
alternative_else_nop_endif
	\instr	#0
	ldr	x4, [sp]
	ldr	x4, [sp, #16]
	stp	x0, x1, [x4, #ARM_SMCCC_RES_X0_OFFS]
	stp	x2, x3, [x4, #ARM_SMCCC_RES_X2_OFFS]
	ldr	x4, [sp, #8]
	ldr	x4, [sp, #24]
	cbz	x4, 1f /* no quirk structure */
	ldr	x9, [x4, #ARM_SMCCC_QUIRK_ID_OFFS]
	cmp	x9, #ARM_SMCCC_QUIRK_QCOM_A6
	b.ne	1f
	str	x6, [x4, ARM_SMCCC_QUIRK_STATE_OFFS]
1:	ret
1:	ldp     x29, x30, [sp], #16
	ret
	.endm

/*
+8 −12
Original line number Diff line number Diff line
@@ -1339,7 +1339,6 @@ void *__init fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
	return dt_virt;
}

#if CONFIG_PGTABLE_LEVELS > 3
int pud_set_huge(pud_t *pudp, phys_addr_t phys, pgprot_t prot)
{
	pud_t new_pud = pfn_pud(__phys_to_pfn(phys), mk_pud_sect_prot(prot));
@@ -1354,16 +1353,6 @@ int pud_set_huge(pud_t *pudp, phys_addr_t phys, pgprot_t prot)
	return 1;
}

int pud_clear_huge(pud_t *pudp)
{
	if (!pud_sect(READ_ONCE(*pudp)))
		return 0;
	pud_clear(pudp);
	return 1;
}
#endif

#if CONFIG_PGTABLE_LEVELS > 2
int pmd_set_huge(pmd_t *pmdp, phys_addr_t phys, pgprot_t prot)
{
	pmd_t new_pmd = pfn_pmd(__phys_to_pfn(phys), mk_pmd_sect_prot(prot));
@@ -1378,6 +1367,14 @@ int pmd_set_huge(pmd_t *pmdp, phys_addr_t phys, pgprot_t prot)
	return 1;
}

int pud_clear_huge(pud_t *pudp)
{
	if (!pud_sect(READ_ONCE(*pudp)))
		return 0;
	pud_clear(pudp);
	return 1;
}

int pmd_clear_huge(pmd_t *pmdp)
{
	if (!pmd_sect(READ_ONCE(*pmdp)))
@@ -1385,7 +1382,6 @@ int pmd_clear_huge(pmd_t *pmdp)
	pmd_clear(pmdp);
	return 1;
}
#endif

int pmd_free_pte_page(pmd_t *pmdp, unsigned long addr)
{
+10 −0
Original line number Diff line number Diff line
@@ -240,3 +240,13 @@ void __init setup_kuap(bool disabled)
	mtspr(SPRN_MD_AP, MD_APG_KUAP);
}
#endif

int pud_clear_huge(pud_t *pud)
{
	 return 0;
}

int pmd_clear_huge(pmd_t *pmd)
{
	 return 0;
}
+15 −19
Original line number Diff line number Diff line
@@ -682,7 +682,6 @@ int p4d_clear_huge(p4d_t *p4d)
}
#endif

#if CONFIG_PGTABLE_LEVELS > 3
/**
 * pud_set_huge - setup kernel PUD mapping
 *
@@ -721,23 +720,6 @@ int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot)
	return 1;
}

/**
 * pud_clear_huge - clear kernel PUD mapping when it is set
 *
 * Returns 1 on success and 0 on failure (no PUD map is found).
 */
int pud_clear_huge(pud_t *pud)
{
	if (pud_large(*pud)) {
		pud_clear(pud);
		return 1;
	}

	return 0;
}
#endif

#if CONFIG_PGTABLE_LEVELS > 2
/**
 * pmd_set_huge - setup kernel PMD mapping
 *
@@ -768,6 +750,21 @@ int pmd_set_huge(pmd_t *pmd, phys_addr_t addr, pgprot_t prot)
	return 1;
}

/**
 * pud_clear_huge - clear kernel PUD mapping when it is set
 *
 * Returns 1 on success and 0 on failure (no PUD map is found).
 */
int pud_clear_huge(pud_t *pud)
{
	if (pud_large(*pud)) {
		pud_clear(pud);
		return 1;
	}

	return 0;
}

/**
 * pmd_clear_huge - clear kernel PMD mapping when it is set
 *
@@ -782,7 +779,6 @@ int pmd_clear_huge(pmd_t *pmd)

	return 0;
}
#endif

#ifdef CONFIG_X86_64
/**
+1 −25
Original line number Diff line number Diff line
@@ -1397,34 +1397,10 @@ static inline int p4d_clear_huge(p4d_t *p4d)
}
#endif /* !__PAGETABLE_P4D_FOLDED */

#ifndef __PAGETABLE_PUD_FOLDED
int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot);
int pud_clear_huge(pud_t *pud);
#else
static inline int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot)
{
	return 0;
}
static inline int pud_clear_huge(pud_t *pud)
{
	return 0;
}
#endif /* !__PAGETABLE_PUD_FOLDED */

#ifndef __PAGETABLE_PMD_FOLDED
int pmd_set_huge(pmd_t *pmd, phys_addr_t addr, pgprot_t prot);
int pud_clear_huge(pud_t *pud);
int pmd_clear_huge(pmd_t *pmd);
#else
static inline int pmd_set_huge(pmd_t *pmd, phys_addr_t addr, pgprot_t prot)
{
	return 0;
}
static inline int pmd_clear_huge(pmd_t *pmd)
{
	return 0;
}
#endif /* !__PAGETABLE_PMD_FOLDED */

int p4d_free_pud_page(p4d_t *p4d, unsigned long addr);
int pud_free_pmd_page(pud_t *pud, unsigned long addr);
int pmd_free_pte_page(pmd_t *pmd, unsigned long addr);