Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 332379
b: refs/heads/master
c: 75077af
h: refs/heads/master
i:
  332377: 017d6a0
  332375: e12d898
v: v3
  • Loading branch information
Gerald Schaefer authored and Linus Torvalds committed Oct 9, 2012
1 parent 95b9a5e commit cd13d7b
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8e72033f2a489b6c98c4e3c7cc281b1afd6cb85c
refs/heads/master: 75077afbec1ac89178c1542b23a70d0f960b0aaf
13 changes: 13 additions & 0 deletions trunk/arch/s390/include/asm/pgtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,8 @@ extern struct page *vmemmap;

#define _SEGMENT_ENTRY_LARGE 0x400 /* STE-format control, large page */
#define _SEGMENT_ENTRY_CO 0x100 /* change-recording override */
#define _SEGMENT_ENTRY_SPLIT_BIT 0 /* THP splitting bit number */
#define _SEGMENT_ENTRY_SPLIT (1UL << _SEGMENT_ENTRY_SPLIT_BIT)

/* Page status table bits for virtualization */
#define RCP_ACC_BITS 0xf000000000000000UL
Expand Down Expand Up @@ -506,6 +508,10 @@ static inline int pmd_bad(pmd_t pmd)
return (pmd_val(pmd) & mask) != _SEGMENT_ENTRY;
}

#define __HAVE_ARCH_PMDP_SPLITTING_FLUSH
extern void pmdp_splitting_flush(struct vm_area_struct *vma,
unsigned long addr, pmd_t *pmdp);

static inline int pte_none(pte_t pte)
{
return (pte_val(pte) & _PAGE_INVALID) && !(pte_val(pte) & _PAGE_SWT);
Expand Down Expand Up @@ -1159,6 +1165,13 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
#define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address)
#define pte_unmap(pte) do { } while (0)

#ifdef CONFIG_TRANSPARENT_HUGEPAGE
static inline int pmd_trans_splitting(pmd_t pmd)
{
return pmd_val(pmd) & _SEGMENT_ENTRY_SPLIT;
}
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */

/*
* 31 bit swap entry format:
* A page-table entry has some bits we have to treat in a special way.
Expand Down
11 changes: 10 additions & 1 deletion trunk/arch/s390/mm/gup.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,16 @@ static inline int gup_pmd_range(pud_t *pudp, pud_t pud, unsigned long addr,
pmd = *pmdp;
barrier();
next = pmd_addr_end(addr, end);
if (pmd_none(pmd))
/*
* The pmd_trans_splitting() check below explains why
* pmdp_splitting_flush() has to serialize with
* smp_call_function() against our disabled IRQs, to stop
* this gup-fast code from running while we set the
* splitting bit in the pmd. Returning zero will take
* the slow path that will call wait_split_huge_page()
* if the pmd is still in splitting state.
*/
if (pmd_none(pmd) || pmd_trans_splitting(pmd))
return 0;
if (unlikely(pmd_huge(pmd))) {
if (!gup_huge_pmd(pmdp, pmd, addr, next,
Expand Down
18 changes: 18 additions & 0 deletions trunk/arch/s390/mm/pgtable.c
Original file line number Diff line number Diff line change
Expand Up @@ -866,3 +866,21 @@ bool kernel_page_present(struct page *page)
return cc == 0;
}
#endif /* CONFIG_HIBERNATION && CONFIG_DEBUG_PAGEALLOC */

#ifdef CONFIG_TRANSPARENT_HUGEPAGE
static void pmdp_splitting_flush_sync(void *arg)
{
/* Simply deliver the interrupt */
}

void pmdp_splitting_flush(struct vm_area_struct *vma, unsigned long address,
pmd_t *pmdp)
{
VM_BUG_ON(address & ~HPAGE_PMD_MASK);
if (!test_and_set_bit(_SEGMENT_ENTRY_SPLIT_BIT,
(unsigned long *) pmdp)) {
/* need to serialize against gup-fast (IRQ disabled) */
smp_call_function(pmdp_splitting_flush_sync, NULL, 1);
}
}
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */

0 comments on commit cd13d7b

Please sign in to comment.