Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 190503
b: refs/heads/master
c: 1ec5632
h: refs/heads/master
i:
  190501: 000ebec
  190499: 9400a75
  190495: 33b36c9
v: v3
  • Loading branch information
David Daney authored and Ralf Baechle committed Apr 30, 2010
1 parent ed78efe commit f1e5214
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 24 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: 3be6022c27ace1e3b4ba963e7ffd2e3b60cecd8a
refs/heads/master: 1ec56329ff939aba29291c0dec1a28ceed660162
110 changes: 87 additions & 23 deletions trunk/arch/mips/mm/tlbex.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@
#include <asm/war.h>
#include <asm/uasm.h>

/*
* TLB load/store/modify handlers.
*
* Only the fastpath gets synthesized at runtime, the slowpath for
* do_page_fault remains normal asm.
*/
extern void tlb_do_page_fault_0(void);
extern void tlb_do_page_fault_1(void);


static inline int r45k_bvahwbug(void)
{
/* XXX: We should probe for the presence of this bug, but we don't. */
Expand Down Expand Up @@ -83,6 +93,7 @@ enum label_id {
label_nopage_tlbm,
label_smp_pgtable_change,
label_r3000_write_probe_fail,
label_large_segbits_fault,
#ifdef CONFIG_HUGETLB_PAGE
label_tlb_huge_update,
#endif
Expand All @@ -101,6 +112,7 @@ UASM_L_LA(_nopage_tlbs)
UASM_L_LA(_nopage_tlbm)
UASM_L_LA(_smp_pgtable_change)
UASM_L_LA(_r3000_write_probe_fail)
UASM_L_LA(_large_segbits_fault)
#ifdef CONFIG_HUGETLB_PAGE
UASM_L_LA(_tlb_huge_update)
#endif
Expand Down Expand Up @@ -157,6 +169,10 @@ static u32 tlb_handler[128] __cpuinitdata;
static struct uasm_label labels[128] __cpuinitdata;
static struct uasm_reloc relocs[128] __cpuinitdata;

#ifdef CONFIG_64BIT
static int check_for_high_segbits __cpuinitdata;
#endif

#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
/*
* CONFIG_MIPS_PGD_C0_CONTEXT implies 64 bit and lack of pgd_current,
Expand Down Expand Up @@ -532,7 +548,24 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
* The vmalloc handling is not in the hotpath.
*/
uasm_i_dmfc0(p, tmp, C0_BADVADDR);
uasm_il_bltz(p, r, tmp, label_vmalloc);

if (check_for_high_segbits) {
/*
* The kernel currently implicitely assumes that the
* MIPS SEGBITS parameter for the processor is
* (PGDIR_SHIFT+PGDIR_BITS) or less, and will never
* allocate virtual addresses outside the maximum
* range for SEGBITS = (PGDIR_SHIFT+PGDIR_BITS). But
* that doesn't prevent user code from accessing the
* higher xuseg addresses. Here, we make sure that
* everything but the lower xuseg addresses goes down
* the module_alloc/vmalloc path.
*/
uasm_i_dsrl_safe(p, ptr, tmp, PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3);
uasm_il_bnez(p, r, ptr, label_vmalloc);
} else {
uasm_il_bltz(p, r, tmp, label_vmalloc);
}
/* No uasm_i_nop needed here, since the next insn doesn't touch TMP. */

#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
Expand Down Expand Up @@ -583,28 +616,64 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
#endif
}

enum vmalloc64_mode {not_refill, refill};
/*
* BVADDR is the faulting address, PTR is scratch.
* PTR will hold the pgd for vmalloc.
*/
static void __cpuinit
build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
unsigned int bvaddr, unsigned int ptr)
unsigned int bvaddr, unsigned int ptr,
enum vmalloc64_mode mode)
{
long swpd = (long)swapper_pg_dir;
int single_insn_swpd;
int did_vmalloc_branch = 0;

single_insn_swpd = uasm_in_compat_space_p(swpd) && !uasm_rel_lo(swpd);

uasm_l_vmalloc(l, *p);

if (uasm_in_compat_space_p(swpd) && !uasm_rel_lo(swpd)) {
uasm_il_b(p, r, label_vmalloc_done);
uasm_i_lui(p, ptr, uasm_rel_hi(swpd));
} else {
UASM_i_LA_mostly(p, ptr, swpd);
uasm_il_b(p, r, label_vmalloc_done);
if (uasm_in_compat_space_p(swpd))
uasm_i_addiu(p, ptr, ptr, uasm_rel_lo(swpd));
else
uasm_i_daddiu(p, ptr, ptr, uasm_rel_lo(swpd));
if (mode == refill && check_for_high_segbits) {
if (single_insn_swpd) {
uasm_il_bltz(p, r, bvaddr, label_vmalloc_done);
uasm_i_lui(p, ptr, uasm_rel_hi(swpd));
did_vmalloc_branch = 1;
/* fall through */
} else {
uasm_il_bgez(p, r, bvaddr, label_large_segbits_fault);
}
}
if (!did_vmalloc_branch) {
if (uasm_in_compat_space_p(swpd) && !uasm_rel_lo(swpd)) {
uasm_il_b(p, r, label_vmalloc_done);
uasm_i_lui(p, ptr, uasm_rel_hi(swpd));
} else {
UASM_i_LA_mostly(p, ptr, swpd);
uasm_il_b(p, r, label_vmalloc_done);
if (uasm_in_compat_space_p(swpd))
uasm_i_addiu(p, ptr, ptr, uasm_rel_lo(swpd));
else
uasm_i_daddiu(p, ptr, ptr, uasm_rel_lo(swpd));
}
}
if (mode == refill && check_for_high_segbits) {
uasm_l_large_segbits_fault(l, *p);
/*
* We get here if we are an xsseg address, or if we are
* an xuseg address above (PGDIR_SHIFT+PGDIR_BITS) boundary.
*
* Ignoring xsseg (assume disabled so would generate
* (address errors?), the only remaining possibility
* is the upper xuseg addresses. On processors with
* TLB_SEGBITS <= PGDIR_SHIFT+PGDIR_BITS, these
* addresses would have taken an address error. We try
* to mimic that here by taking a load/istream page
* fault.
*/
UASM_i_LA(p, ptr, (unsigned long)tlb_do_page_fault_0);
uasm_i_jr(p, ptr);
uasm_i_nop(p);
}
}

Expand Down Expand Up @@ -823,7 +892,7 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
#endif

#ifdef CONFIG_64BIT
build_get_pgd_vmalloc64(&p, &l, &r, K0, K1);
build_get_pgd_vmalloc64(&p, &l, &r, K0, K1, refill);
#endif

/*
Expand Down Expand Up @@ -932,15 +1001,6 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
dump_handler((u32 *)ebase, 64);
}

/*
* TLB load/store/modify handlers.
*
* Only the fastpath gets synthesized at runtime, the slowpath for
* do_page_fault remains normal asm.
*/
extern void tlb_do_page_fault_0(void);
extern void tlb_do_page_fault_1(void);

/*
* 128 instructions for the fastpath handler is generous and should
* never be exceeded.
Expand Down Expand Up @@ -1300,7 +1360,7 @@ build_r4000_tlbchange_handler_tail(u32 **p, struct uasm_label **l,
uasm_i_eret(p); /* return from trap */

#ifdef CONFIG_64BIT
build_get_pgd_vmalloc64(p, l, r, tmp, ptr);
build_get_pgd_vmalloc64(p, l, r, tmp, ptr, not_refill);
#endif
}

Expand Down Expand Up @@ -1524,6 +1584,10 @@ void __cpuinit build_tlb_refill_handler(void)
*/
static int run_once = 0;

#ifdef CONFIG_64BIT
check_for_high_segbits = current_cpu_data.vmbits > (PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3);
#endif

switch (current_cpu_type()) {
case CPU_R2000:
case CPU_R3000:
Expand Down

0 comments on commit f1e5214

Please sign in to comment.