Commit 416716ed authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'powerpc-4.1-4' of git://git.kernel.org/pub/scm/linux/kernel/git/mpe/linux

Pull powerpc fixes from Michael Ellerman:

 - THP/hugetlb fixes from Aneesh.

 - MCE fix from Daniel.

 - TOC fix from Anton.

* tag 'powerpc-4.1-4' of git://git.kernel.org/pub/scm/linux/kernel/git/mpe/linux:
  powerpc: Align TOC to 256 bytes
  powerpc/mce: fix off by one errors in mce event handling
  powerpc/mm: Return NULL for not present hugetlb page
  powerpc/thp: Serialize pmd clear against a linux page table walk.
parents 68465bb0 5e95235c
...@@ -73,7 +73,7 @@ void save_mce_event(struct pt_regs *regs, long handled, ...@@ -73,7 +73,7 @@ void save_mce_event(struct pt_regs *regs, long handled,
uint64_t nip, uint64_t addr) uint64_t nip, uint64_t addr)
{ {
uint64_t srr1; uint64_t srr1;
int index = __this_cpu_inc_return(mce_nest_count); int index = __this_cpu_inc_return(mce_nest_count) - 1;
struct machine_check_event *mce = this_cpu_ptr(&mce_event[index]); struct machine_check_event *mce = this_cpu_ptr(&mce_event[index]);
/* /*
...@@ -184,7 +184,7 @@ void machine_check_queue_event(void) ...@@ -184,7 +184,7 @@ void machine_check_queue_event(void)
if (!get_mce_event(&evt, MCE_EVENT_RELEASE)) if (!get_mce_event(&evt, MCE_EVENT_RELEASE))
return; return;
index = __this_cpu_inc_return(mce_queue_count); index = __this_cpu_inc_return(mce_queue_count) - 1;
/* If queue is full, just return for now. */ /* If queue is full, just return for now. */
if (index >= MAX_MC_EVT) { if (index >= MAX_MC_EVT) {
__this_cpu_dec(mce_queue_count); __this_cpu_dec(mce_queue_count);
......
...@@ -213,6 +213,7 @@ SECTIONS ...@@ -213,6 +213,7 @@ SECTIONS
*(.opd) *(.opd)
} }
. = ALIGN(256);
.got : AT(ADDR(.got) - LOAD_OFFSET) { .got : AT(ADDR(.got) - LOAD_OFFSET) {
__toc_start = .; __toc_start = .;
#ifndef CONFIG_RELOCATABLE #ifndef CONFIG_RELOCATABLE
......
...@@ -689,27 +689,34 @@ void hugetlb_free_pgd_range(struct mmu_gather *tlb, ...@@ -689,27 +689,34 @@ void hugetlb_free_pgd_range(struct mmu_gather *tlb,
struct page * struct page *
follow_huge_addr(struct mm_struct *mm, unsigned long address, int write) follow_huge_addr(struct mm_struct *mm, unsigned long address, int write)
{ {
pte_t *ptep; pte_t *ptep, pte;
struct page *page;
unsigned shift; unsigned shift;
unsigned long mask, flags; unsigned long mask, flags;
struct page *page = ERR_PTR(-EINVAL);
local_irq_save(flags);
ptep = find_linux_pte_or_hugepte(mm->pgd, address, &shift);
if (!ptep)
goto no_page;
pte = READ_ONCE(*ptep);
/* /*
* Verify it is a huge page else bail.
* Transparent hugepages are handled by generic code. We can skip them * Transparent hugepages are handled by generic code. We can skip them
* here. * here.
*/ */
local_irq_save(flags); if (!shift || pmd_trans_huge(__pmd(pte_val(pte))))
ptep = find_linux_pte_or_hugepte(mm->pgd, address, &shift); goto no_page;
/* Verify it is a huge page else bail. */ if (!pte_present(pte)) {
if (!ptep || !shift || pmd_trans_huge(*(pmd_t *)ptep)) { page = NULL;
local_irq_restore(flags); goto no_page;
return ERR_PTR(-EINVAL);
} }
mask = (1UL << shift) - 1; mask = (1UL << shift) - 1;
page = pte_page(*ptep); page = pte_page(pte);
if (page) if (page)
page += (address & mask) / PAGE_SIZE; page += (address & mask) / PAGE_SIZE;
no_page:
local_irq_restore(flags); local_irq_restore(flags);
return page; return page;
} }
......
...@@ -839,6 +839,17 @@ pmd_t pmdp_get_and_clear(struct mm_struct *mm, ...@@ -839,6 +839,17 @@ pmd_t pmdp_get_and_clear(struct mm_struct *mm,
* hash fault look at them. * hash fault look at them.
*/ */
memset(pgtable, 0, PTE_FRAG_SIZE); memset(pgtable, 0, PTE_FRAG_SIZE);
/*
* Serialize against find_linux_pte_or_hugepte which does lock-less
* lookup in page tables with local interrupts disabled. For huge pages
* it casts pmd_t to pte_t. Since format of pte_t is different from
* pmd_t we want to prevent transit from pmd pointing to page table
* to pmd pointing to huge page (and back) while interrupts are disabled.
* We clear pmd to possibly replace it with page table pointer in
* different code paths. So make sure we wait for the parallel
* find_linux_pte_or_hugepage to finish.
*/
kick_all_cpus_sync();
return old_pmd; return old_pmd;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment