Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc
Browse files Browse the repository at this point in the history
Pull sparc updates from David Miller:

 1) Double spin lock bug in sunhv serial driver, from Dan Carpenter.

 2) Use correct RSS estimate when determining whether to grow the huge
    TSB or not, from Mike Kravetz.

 3) Don't use full three level page tables for hugepages, PMD level is
    sufficient.  From Nitin Gupta.

 4) Mask out extraneous bits from TSB_TAG_ACCESS register, we only want
    the address bits.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc:
  sparc64: Trim page tables for 8M hugepages
  sparc64 mm: Fix base TSB sizing when hugetlb pages are used
  sparc: serial: sunhv: fix a double lock bug
  sparc32: off by ones in BUG_ON()
  sparc: Don't leak context bits into thread->fault_address
  • Loading branch information
Linus Torvalds committed Jul 29, 2016
2 parents 9d3bc3d + 7bc3777 commit 86505fc
Show file tree
Hide file tree
Showing 14 changed files with 173 additions and 94 deletions.
12 changes: 4 additions & 8 deletions arch/sparc/include/asm/hugetlb.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,6 @@ static inline int prepare_hugepage_range(struct file *file,
return 0;
}

static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb,
unsigned long addr, unsigned long end,
unsigned long floor,
unsigned long ceiling)
{
free_pgd_range(tlb, addr, end, floor, ceiling);
}

static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
unsigned long addr, pte_t *ptep)
{
Expand Down Expand Up @@ -82,4 +74,8 @@ static inline void arch_clear_hugepage_flags(struct page *page)
{
}

void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
unsigned long end, unsigned long floor,
unsigned long ceiling);

#endif /* _ASM_SPARC64_HUGETLB_H */
3 changes: 2 additions & 1 deletion arch/sparc/include/asm/mmu_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ struct tsb_config {
typedef struct {
spinlock_t lock;
unsigned long sparc64_ctx_val;
unsigned long huge_pte_count;
unsigned long hugetlb_pte_count;
unsigned long thp_pte_count;
struct tsb_config tsb_block[MM_NUM_TSBS];
struct hv_tsb_descr tsb_descr[MM_NUM_TSBS];
} mm_context_t;
Expand Down
7 changes: 6 additions & 1 deletion arch/sparc/include/asm/pgtable_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -395,14 +395,19 @@ static inline unsigned long __pte_huge_mask(void)

static inline pte_t pte_mkhuge(pte_t pte)
{
return __pte(pte_val(pte) | __pte_huge_mask());
return __pte(pte_val(pte) | _PAGE_PMD_HUGE | __pte_huge_mask());
}

static inline bool is_hugetlb_pte(pte_t pte)
{
return !!(pte_val(pte) & __pte_huge_mask());
}

static inline bool is_hugetlb_pmd(pmd_t pmd)
{
return !!(pmd_val(pmd) & _PAGE_PMD_HUGE);
}

#ifdef CONFIG_TRANSPARENT_HUGEPAGE
static inline pmd_t pmd_mkhuge(pmd_t pmd)
{
Expand Down
2 changes: 1 addition & 1 deletion arch/sparc/include/asm/tsb.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
* We have to propagate the 4MB bit of the virtual address
* because we are fabricating 8MB pages using 4MB hw pages.
*/
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
#define USER_PGTABLE_CHECK_PMD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, PTE_LABEL) \
brz,pn REG1, FAIL_LABEL; \
sethi %uhi(_PAGE_PMD_HUGE), REG2; \
Expand Down
4 changes: 2 additions & 2 deletions arch/sparc/kernel/dtlb_prot.S
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@

/* PROT ** ICACHE line 2: More real fault processing */
ldxa [%g4] ASI_DMMU, %g5 ! Put tagaccess in %g5
srlx %g5, PAGE_SHIFT, %g5
sllx %g5, PAGE_SHIFT, %g5 ! Clear context ID bits
bgu,pn %xcc, winfix_trampoline ! Yes, perform winfixup
mov FAULT_CODE_DTLB | FAULT_CODE_WRITE, %g4
ba,pt %xcc, sparc64_realfault_common ! Nope, normal fault
nop
nop
nop
nop

/* PROT ** ICACHE line 3: Unused... */
nop
Expand Down
4 changes: 2 additions & 2 deletions arch/sparc/kernel/irq_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ void irq_link(unsigned int irq)

p = &irq_table[irq];
pil = p->pil;
BUG_ON(pil > SUN4D_MAX_IRQ);
BUG_ON(pil >= SUN4D_MAX_IRQ);
p->next = irq_map[pil];
irq_map[pil] = p;

Expand All @@ -182,7 +182,7 @@ void irq_unlink(unsigned int irq)
spin_lock_irqsave(&irq_map_lock, flags);

p = &irq_table[irq];
BUG_ON(p->pil > SUN4D_MAX_IRQ);
BUG_ON(p->pil >= SUN4D_MAX_IRQ);
pnext = &irq_map[p->pil];
while (*pnext != p)
pnext = &(*pnext)->next;
Expand Down
12 changes: 12 additions & 0 deletions arch/sparc/kernel/ktlb.S
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ kvmap_itlb:
mov TLB_TAG_ACCESS, %g4
ldxa [%g4] ASI_IMMU, %g4

/* The kernel executes in context zero, therefore we do not
* need to clear the context ID bits out of %g4 here.
*/

/* sun4v_itlb_miss branches here with the missing virtual
* address already loaded into %g4
*/
Expand Down Expand Up @@ -128,6 +132,10 @@ kvmap_dtlb:
mov TLB_TAG_ACCESS, %g4
ldxa [%g4] ASI_DMMU, %g4

/* The kernel executes in context zero, therefore we do not
* need to clear the context ID bits out of %g4 here.
*/

/* sun4v_dtlb_miss branches here with the missing virtual
* address already loaded into %g4
*/
Expand Down Expand Up @@ -251,6 +259,10 @@ kvmap_dtlb_longpath:
nop
.previous

/* The kernel executes in context zero, therefore we do not
* need to clear the context ID bits out of %g5 here.
*/

be,pt %xcc, sparc64_realfault_common
mov FAULT_CODE_DTLB, %g4
ba,pt %xcc, winfix_trampoline
Expand Down
12 changes: 10 additions & 2 deletions arch/sparc/kernel/tsb.S
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,17 @@
*/
tsb_miss_dtlb:
mov TLB_TAG_ACCESS, %g4
ldxa [%g4] ASI_DMMU, %g4
srlx %g4, PAGE_SHIFT, %g4
ba,pt %xcc, tsb_miss_page_table_walk
ldxa [%g4] ASI_DMMU, %g4
sllx %g4, PAGE_SHIFT, %g4

tsb_miss_itlb:
mov TLB_TAG_ACCESS, %g4
ldxa [%g4] ASI_IMMU, %g4
srlx %g4, PAGE_SHIFT, %g4
ba,pt %xcc, tsb_miss_page_table_walk
ldxa [%g4] ASI_IMMU, %g4
sllx %g4, PAGE_SHIFT, %g4

/* At this point we have:
* %g1 -- PAGE_SIZE TSB entry address
Expand Down Expand Up @@ -284,6 +288,10 @@ tsb_do_dtlb_fault:
nop
.previous

/* Clear context ID bits. */
srlx %g5, PAGE_SHIFT, %g5
sllx %g5, PAGE_SHIFT, %g5

be,pt %xcc, sparc64_realfault_common
mov FAULT_CODE_DTLB, %g4
ba,pt %xcc, winfix_trampoline
Expand Down
10 changes: 5 additions & 5 deletions arch/sparc/mm/fault_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ static unsigned int get_user_insn(unsigned long tpc)
if (pmd_none(*pmdp) || unlikely(pmd_bad(*pmdp)))
goto out_irq_enable;

#ifdef CONFIG_TRANSPARENT_HUGEPAGE
if (pmd_trans_huge(*pmdp)) {
#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
if (is_hugetlb_pmd(*pmdp)) {
pa = pmd_pfn(*pmdp) << PAGE_SHIFT;
pa += tpc & ~HPAGE_MASK;

Expand Down Expand Up @@ -476,14 +476,14 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
up_read(&mm->mmap_sem);

mm_rss = get_mm_rss(mm);
#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
mm_rss -= (mm->context.huge_pte_count * (HPAGE_SIZE / PAGE_SIZE));
#if defined(CONFIG_TRANSPARENT_HUGEPAGE)
mm_rss -= (mm->context.thp_pte_count * (HPAGE_SIZE / PAGE_SIZE));
#endif
if (unlikely(mm_rss >
mm->context.tsb_block[MM_TSB_BASE].tsb_rss_limit))
tsb_grow(mm, MM_TSB_BASE, mm_rss);
#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
mm_rss = mm->context.huge_pte_count;
mm_rss = mm->context.hugetlb_pte_count + mm->context.thp_pte_count;
if (unlikely(mm_rss >
mm->context.tsb_block[MM_TSB_HUGE].tsb_rss_limit)) {
if (mm->context.tsb_block[MM_TSB_HUGE].tsb)
Expand Down
Loading

0 comments on commit 86505fc

Please sign in to comment.