Commit 977674c0 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus

Pull MIPS fixes from Ralf Baechle:
 "Lantiq:
    - Fix adding xbar resoures causing a panic

  Loongson3:
    - Some Loongson 3A don't identify themselves as having an FTLB so
      hardwire that knowledge into CPU probing.
    - Handle Loongson 3 TLB peculiarities in the fast path of the RDHWR
      emulation.
    - Fix invalid FTLB entries with huge page on VTLB+FTLB platforms
    - Add missing calculation of S-cache and V-cache cache-way size

  Ralink:
    - Fix typos in rt3883 pinctrl data

  Generic:
    - Force o32 fp64 support on 32bit MIPS64r6 kernels
    - Yet another build fix after the linux/sched.h changes
    - Wire up statx system call
    - Fix stack unwinding after introduction of IRQ stack
    - Fix spinlock code to build even for microMIPS with recent binutils

  SMP-CPS:
    - Fix retrieval of VPE mask on big endian CPUs"

* 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus:
  MIPS: IRQ Stack: Unwind IRQ stack onto task stack
  MIPS: c-r4k: Fix Loongson-3's vcache/scache waysize calculation
  MIPS: Flush wrong invalid FTLB entry for huge page
  MIPS: Check TLB before handle_ri_rdhwr() for Loongson-3
  MIPS: Add MIPS_CPU_FTLB for Loongson-3A R2
  MIPS: Lantiq: fix missing xbar kernel panic
  MIPS: smp-cps: Fix retrieval of VPE mask on big endian CPUs
  MIPS: Wire up statx system call
  MIPS: Include asm/ptrace.h now linux/sched.h doesn't
  MIPS: ralink: Fix typos in rt3883 pinctrl
  MIPS: End spinlocks with .insn
  MIPS: Force o32 fp64 support on 32bit MIPS64r6 kernels
parents 4691f4a6 db8466c5
...@@ -1531,7 +1531,7 @@ config CPU_MIPS64_R6 ...@@ -1531,7 +1531,7 @@ config CPU_MIPS64_R6
select CPU_SUPPORTS_HIGHMEM select CPU_SUPPORTS_HIGHMEM
select CPU_SUPPORTS_MSA select CPU_SUPPORTS_MSA
select GENERIC_CSUM select GENERIC_CSUM
select MIPS_O32_FP64_SUPPORT if MIPS32_O32 select MIPS_O32_FP64_SUPPORT if 32BIT || MIPS32_O32
select HAVE_KVM select HAVE_KVM
help help
Choose this option to build a kernel for release 6 or later of the Choose this option to build a kernel for release 6 or later of the
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <asm/cpu-features.h> #include <asm/cpu-features.h>
#include <asm/fpu_emulator.h> #include <asm/fpu_emulator.h>
#include <asm/hazards.h> #include <asm/hazards.h>
#include <asm/ptrace.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/current.h> #include <asm/current.h>
#include <asm/msa.h> #include <asm/msa.h>
......
...@@ -18,9 +18,24 @@ ...@@ -18,9 +18,24 @@
#include <irq.h> #include <irq.h>
#define IRQ_STACK_SIZE THREAD_SIZE #define IRQ_STACK_SIZE THREAD_SIZE
#define IRQ_STACK_START (IRQ_STACK_SIZE - sizeof(unsigned long))
extern void *irq_stack[NR_CPUS]; extern void *irq_stack[NR_CPUS];
/*
* The highest address on the IRQ stack contains a dummy frame put down in
* genex.S (handle_int & except_vec_vi_handler) which is structured as follows:
*
* top ------------
* | task sp | <- irq_stack[cpu] + IRQ_STACK_START
* ------------
* | | <- First frame of IRQ context
* ------------
*
* task sp holds a copy of the task stack pointer where the struct pt_regs
* from exception entry can be found.
*/
static inline bool on_irq_stack(int cpu, unsigned long sp) static inline bool on_irq_stack(int cpu, unsigned long sp)
{ {
unsigned long low = (unsigned long)irq_stack[cpu]; unsigned long low = (unsigned long)irq_stack[cpu];
......
...@@ -127,7 +127,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock) ...@@ -127,7 +127,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
" andi %[ticket], %[ticket], 0xffff \n" " andi %[ticket], %[ticket], 0xffff \n"
" bne %[ticket], %[my_ticket], 4f \n" " bne %[ticket], %[my_ticket], 4f \n"
" subu %[ticket], %[my_ticket], %[ticket] \n" " subu %[ticket], %[my_ticket], %[ticket] \n"
"2: \n" "2: .insn \n"
" .subsection 2 \n" " .subsection 2 \n"
"4: andi %[ticket], %[ticket], 0xffff \n" "4: andi %[ticket], %[ticket], 0xffff \n"
" sll %[ticket], 5 \n" " sll %[ticket], 5 \n"
...@@ -202,7 +202,7 @@ static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock) ...@@ -202,7 +202,7 @@ static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock)
" sc %[ticket], %[ticket_ptr] \n" " sc %[ticket], %[ticket_ptr] \n"
" beqz %[ticket], 1b \n" " beqz %[ticket], 1b \n"
" li %[ticket], 1 \n" " li %[ticket], 1 \n"
"2: \n" "2: .insn \n"
" .subsection 2 \n" " .subsection 2 \n"
"3: b 2b \n" "3: b 2b \n"
" li %[ticket], 0 \n" " li %[ticket], 0 \n"
...@@ -382,7 +382,7 @@ static inline int arch_read_trylock(arch_rwlock_t *rw) ...@@ -382,7 +382,7 @@ static inline int arch_read_trylock(arch_rwlock_t *rw)
" .set reorder \n" " .set reorder \n"
__WEAK_LLSC_MB __WEAK_LLSC_MB
" li %2, 1 \n" " li %2, 1 \n"
"2: \n" "2: .insn \n"
: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret) : "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp), "=&r" (ret)
: GCC_OFF_SMALL_ASM() (rw->lock) : GCC_OFF_SMALL_ASM() (rw->lock)
: "memory"); : "memory");
...@@ -422,7 +422,7 @@ static inline int arch_write_trylock(arch_rwlock_t *rw) ...@@ -422,7 +422,7 @@ static inline int arch_write_trylock(arch_rwlock_t *rw)
" lui %1, 0x8000 \n" " lui %1, 0x8000 \n"
" sc %1, %0 \n" " sc %1, %0 \n"
" li %2, 1 \n" " li %2, 1 \n"
"2: \n" "2: .insn \n"
: "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp), : "=" GCC_OFF_SMALL_ASM() (rw->lock), "=&r" (tmp),
"=&r" (ret) "=&r" (ret)
: GCC_OFF_SMALL_ASM() (rw->lock) : GCC_OFF_SMALL_ASM() (rw->lock)
......
...@@ -386,17 +386,18 @@ ...@@ -386,17 +386,18 @@
#define __NR_pkey_mprotect (__NR_Linux + 363) #define __NR_pkey_mprotect (__NR_Linux + 363)
#define __NR_pkey_alloc (__NR_Linux + 364) #define __NR_pkey_alloc (__NR_Linux + 364)
#define __NR_pkey_free (__NR_Linux + 365) #define __NR_pkey_free (__NR_Linux + 365)
#define __NR_statx (__NR_Linux + 366)
/* /*
* Offset of the last Linux o32 flavoured syscall * Offset of the last Linux o32 flavoured syscall
*/ */
#define __NR_Linux_syscalls 365 #define __NR_Linux_syscalls 366
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
#define __NR_O32_Linux 4000 #define __NR_O32_Linux 4000
#define __NR_O32_Linux_syscalls 365 #define __NR_O32_Linux_syscalls 366
#if _MIPS_SIM == _MIPS_SIM_ABI64 #if _MIPS_SIM == _MIPS_SIM_ABI64
...@@ -730,16 +731,17 @@ ...@@ -730,16 +731,17 @@
#define __NR_pkey_mprotect (__NR_Linux + 323) #define __NR_pkey_mprotect (__NR_Linux + 323)
#define __NR_pkey_alloc (__NR_Linux + 324) #define __NR_pkey_alloc (__NR_Linux + 324)
#define __NR_pkey_free (__NR_Linux + 325) #define __NR_pkey_free (__NR_Linux + 325)
#define __NR_statx (__NR_Linux + 326)
/* /*
* Offset of the last Linux 64-bit flavoured syscall * Offset of the last Linux 64-bit flavoured syscall
*/ */
#define __NR_Linux_syscalls 325 #define __NR_Linux_syscalls 326
#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
#define __NR_64_Linux 5000 #define __NR_64_Linux 5000
#define __NR_64_Linux_syscalls 325 #define __NR_64_Linux_syscalls 326
#if _MIPS_SIM == _MIPS_SIM_NABI32 #if _MIPS_SIM == _MIPS_SIM_NABI32
...@@ -1077,15 +1079,16 @@ ...@@ -1077,15 +1079,16 @@
#define __NR_pkey_mprotect (__NR_Linux + 327) #define __NR_pkey_mprotect (__NR_Linux + 327)
#define __NR_pkey_alloc (__NR_Linux + 328) #define __NR_pkey_alloc (__NR_Linux + 328)
#define __NR_pkey_free (__NR_Linux + 329) #define __NR_pkey_free (__NR_Linux + 329)
#define __NR_statx (__NR_Linux + 330)
/* /*
* Offset of the last N32 flavoured syscall * Offset of the last N32 flavoured syscall
*/ */
#define __NR_Linux_syscalls 329 #define __NR_Linux_syscalls 330
#endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */ #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
#define __NR_N32_Linux 6000 #define __NR_N32_Linux 6000
#define __NR_N32_Linux_syscalls 329 #define __NR_N32_Linux_syscalls 330
#endif /* _UAPI_ASM_UNISTD_H */ #endif /* _UAPI_ASM_UNISTD_H */
...@@ -102,6 +102,7 @@ void output_thread_info_defines(void) ...@@ -102,6 +102,7 @@ void output_thread_info_defines(void)
DEFINE(_THREAD_SIZE, THREAD_SIZE); DEFINE(_THREAD_SIZE, THREAD_SIZE);
DEFINE(_THREAD_MASK, THREAD_MASK); DEFINE(_THREAD_MASK, THREAD_MASK);
DEFINE(_IRQ_STACK_SIZE, IRQ_STACK_SIZE); DEFINE(_IRQ_STACK_SIZE, IRQ_STACK_SIZE);
DEFINE(_IRQ_STACK_START, IRQ_STACK_START);
BLANK(); BLANK();
} }
......
...@@ -361,7 +361,7 @@ LEAF(mips_cps_get_bootcfg) ...@@ -361,7 +361,7 @@ LEAF(mips_cps_get_bootcfg)
END(mips_cps_get_bootcfg) END(mips_cps_get_bootcfg)
LEAF(mips_cps_boot_vpes) LEAF(mips_cps_boot_vpes)
PTR_L ta2, COREBOOTCFG_VPEMASK(a0) lw ta2, COREBOOTCFG_VPEMASK(a0)
PTR_L ta3, COREBOOTCFG_VPECONFIG(a0) PTR_L ta3, COREBOOTCFG_VPECONFIG(a0)
#if defined(CONFIG_CPU_MIPSR6) #if defined(CONFIG_CPU_MIPSR6)
......
...@@ -1824,7 +1824,7 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu) ...@@ -1824,7 +1824,7 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
} }
decode_configs(c); decode_configs(c);
c->options |= MIPS_CPU_TLBINV | MIPS_CPU_LDPTE; c->options |= MIPS_CPU_FTLB | MIPS_CPU_TLBINV | MIPS_CPU_LDPTE;
c->writecombine = _CACHE_UNCACHED_ACCELERATED; c->writecombine = _CACHE_UNCACHED_ACCELERATED;
break; break;
default: default:
......
...@@ -215,9 +215,11 @@ NESTED(handle_int, PT_SIZE, sp) ...@@ -215,9 +215,11 @@ NESTED(handle_int, PT_SIZE, sp)
beq t0, t1, 2f beq t0, t1, 2f
/* Switch to IRQ stack */ /* Switch to IRQ stack */
li t1, _IRQ_STACK_SIZE li t1, _IRQ_STACK_START
PTR_ADD sp, t0, t1 PTR_ADD sp, t0, t1
/* Save task's sp on IRQ stack so that unwinding can follow it */
LONG_S s1, 0(sp)
2: 2:
jal plat_irq_dispatch jal plat_irq_dispatch
...@@ -325,9 +327,11 @@ NESTED(except_vec_vi_handler, 0, sp) ...@@ -325,9 +327,11 @@ NESTED(except_vec_vi_handler, 0, sp)
beq t0, t1, 2f beq t0, t1, 2f
/* Switch to IRQ stack */ /* Switch to IRQ stack */
li t1, _IRQ_STACK_SIZE li t1, _IRQ_STACK_START
PTR_ADD sp, t0, t1 PTR_ADD sp, t0, t1
/* Save task's sp on IRQ stack so that unwinding can follow it */
LONG_S s1, 0(sp)
2: 2:
jalr v0 jalr v0
...@@ -519,7 +523,7 @@ NESTED(nmi_handler, PT_SIZE, sp) ...@@ -519,7 +523,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
BUILD_HANDLER reserved reserved sti verbose /* others */ BUILD_HANDLER reserved reserved sti verbose /* others */
.align 5 .align 5
LEAF(handle_ri_rdhwr_vivt) LEAF(handle_ri_rdhwr_tlbp)
.set push .set push
.set noat .set noat
.set noreorder .set noreorder
...@@ -538,7 +542,7 @@ NESTED(nmi_handler, PT_SIZE, sp) ...@@ -538,7 +542,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
.set pop .set pop
bltz k1, handle_ri /* slow path */ bltz k1, handle_ri /* slow path */
/* fall thru */ /* fall thru */
END(handle_ri_rdhwr_vivt) END(handle_ri_rdhwr_tlbp)
LEAF(handle_ri_rdhwr) LEAF(handle_ri_rdhwr)
.set push .set push
......
...@@ -488,31 +488,52 @@ unsigned long notrace unwind_stack_by_address(unsigned long stack_page, ...@@ -488,31 +488,52 @@ unsigned long notrace unwind_stack_by_address(unsigned long stack_page,
unsigned long pc, unsigned long pc,
unsigned long *ra) unsigned long *ra)
{ {
unsigned long low, high, irq_stack_high;
struct mips_frame_info info; struct mips_frame_info info;
unsigned long size, ofs; unsigned long size, ofs;
struct pt_regs *regs;
int leaf; int leaf;
extern void ret_from_irq(void);
extern void ret_from_exception(void);
if (!stack_page) if (!stack_page)
return 0; return 0;
/* /*
* If we reached the bottom of interrupt context, * IRQ stacks start at IRQ_STACK_START
* return saved pc in pt_regs. * task stacks at THREAD_SIZE - 32
*/ */
if (pc == (unsigned long)ret_from_irq || low = stack_page;
pc == (unsigned long)ret_from_exception) { if (!preemptible() && on_irq_stack(raw_smp_processor_id(), *sp)) {
struct pt_regs *regs; high = stack_page + IRQ_STACK_START;
if (*sp >= stack_page && irq_stack_high = high;
*sp + sizeof(*regs) <= stack_page + THREAD_SIZE - 32) { } else {
regs = (struct pt_regs *)*sp; high = stack_page + THREAD_SIZE - 32;
pc = regs->cp0_epc; irq_stack_high = 0;
if (!user_mode(regs) && __kernel_text_address(pc)) { }
*sp = regs->regs[29];
*ra = regs->regs[31]; /*
return pc; * If we reached the top of the interrupt stack, start unwinding
} * the interrupted task stack.
*/
if (unlikely(*sp == irq_stack_high)) {
unsigned long task_sp = *(unsigned long *)*sp;
/*
* Check that the pointer saved in the IRQ stack head points to
* something within the stack of the current task
*/
if (!object_is_on_stack((void *)task_sp))
return 0;
/*
* Follow pointer to tasks kernel stack frame where interrupted
* state was saved.
*/
regs = (struct pt_regs *)task_sp;
pc = regs->cp0_epc;
if (!user_mode(regs) && __kernel_text_address(pc)) {
*sp = regs->regs[29];
*ra = regs->regs[31];
return pc;
} }
return 0; return 0;
} }
...@@ -533,8 +554,7 @@ unsigned long notrace unwind_stack_by_address(unsigned long stack_page, ...@@ -533,8 +554,7 @@ unsigned long notrace unwind_stack_by_address(unsigned long stack_page,
if (leaf < 0) if (leaf < 0)
return 0; return 0;
if (*sp < stack_page || if (*sp < low || *sp + info.frame_size > high)
*sp + info.frame_size > stack_page + THREAD_SIZE - 32)
return 0; return 0;
if (leaf) if (leaf)
......
...@@ -600,3 +600,4 @@ EXPORT(sys_call_table) ...@@ -600,3 +600,4 @@ EXPORT(sys_call_table)
PTR sys_pkey_mprotect PTR sys_pkey_mprotect
PTR sys_pkey_alloc PTR sys_pkey_alloc
PTR sys_pkey_free /* 4365 */ PTR sys_pkey_free /* 4365 */
PTR sys_statx
...@@ -438,4 +438,5 @@ EXPORT(sys_call_table) ...@@ -438,4 +438,5 @@ EXPORT(sys_call_table)
PTR sys_pkey_mprotect PTR sys_pkey_mprotect
PTR sys_pkey_alloc PTR sys_pkey_alloc
PTR sys_pkey_free /* 5325 */ PTR sys_pkey_free /* 5325 */
PTR sys_statx
.size sys_call_table,.-sys_call_table .size sys_call_table,.-sys_call_table
...@@ -433,4 +433,5 @@ EXPORT(sysn32_call_table) ...@@ -433,4 +433,5 @@ EXPORT(sysn32_call_table)
PTR sys_pkey_mprotect PTR sys_pkey_mprotect
PTR sys_pkey_alloc PTR sys_pkey_alloc
PTR sys_pkey_free PTR sys_pkey_free
PTR sys_statx /* 6330 */
.size sysn32_call_table,.-sysn32_call_table .size sysn32_call_table,.-sysn32_call_table
...@@ -588,4 +588,5 @@ EXPORT(sys32_call_table) ...@@ -588,4 +588,5 @@ EXPORT(sys32_call_table)
PTR sys_pkey_mprotect PTR sys_pkey_mprotect
PTR sys_pkey_alloc PTR sys_pkey_alloc
PTR sys_pkey_free /* 4365 */ PTR sys_pkey_free /* 4365 */
PTR sys_statx
.size sys32_call_table,.-sys32_call_table .size sys32_call_table,.-sys32_call_table
...@@ -83,7 +83,7 @@ extern asmlinkage void handle_dbe(void); ...@@ -83,7 +83,7 @@ extern asmlinkage void handle_dbe(void);
extern asmlinkage void handle_sys(void); extern asmlinkage void handle_sys(void);
extern asmlinkage void handle_bp(void); extern asmlinkage void handle_bp(void);
extern asmlinkage void handle_ri(void); extern asmlinkage void handle_ri(void);
extern asmlinkage void handle_ri_rdhwr_vivt(void); extern asmlinkage void handle_ri_rdhwr_tlbp(void);
extern asmlinkage void handle_ri_rdhwr(void); extern asmlinkage void handle_ri_rdhwr(void);
extern asmlinkage void handle_cpu(void); extern asmlinkage void handle_cpu(void);
extern asmlinkage void handle_ov(void); extern asmlinkage void handle_ov(void);
...@@ -2408,9 +2408,18 @@ void __init trap_init(void) ...@@ -2408,9 +2408,18 @@ void __init trap_init(void)
set_except_vector(EXCCODE_SYS, handle_sys); set_except_vector(EXCCODE_SYS, handle_sys);
set_except_vector(EXCCODE_BP, handle_bp); set_except_vector(EXCCODE_BP, handle_bp);
set_except_vector(EXCCODE_RI, rdhwr_noopt ? handle_ri :
(cpu_has_vtag_icache ? if (rdhwr_noopt)
handle_ri_rdhwr_vivt : handle_ri_rdhwr)); set_except_vector(EXCCODE_RI, handle_ri);
else {
if (cpu_has_vtag_icache)
set_except_vector(EXCCODE_RI, handle_ri_rdhwr_tlbp);
else if (current_cpu_type() == CPU_LOONGSON3)
set_except_vector(EXCCODE_RI, handle_ri_rdhwr_tlbp);
else
set_except_vector(EXCCODE_RI, handle_ri_rdhwr);
}
set_except_vector(EXCCODE_CPU, handle_cpu); set_except_vector(EXCCODE_CPU, handle_cpu);
set_except_vector(EXCCODE_OV, handle_ov); set_except_vector(EXCCODE_OV, handle_ov);
set_except_vector(EXCCODE_TR, handle_tr); set_except_vector(EXCCODE_TR, handle_tr);
......
...@@ -467,7 +467,7 @@ void __init ltq_soc_init(void) ...@@ -467,7 +467,7 @@ void __init ltq_soc_init(void)
if (!np_xbar) if (!np_xbar)
panic("Failed to load xbar nodes from devicetree"); panic("Failed to load xbar nodes from devicetree");
if (of_address_to_resource(np_pmu, 0, &res_xbar)) if (of_address_to_resource(np_xbar, 0, &res_xbar))
panic("Failed to get xbar resources"); panic("Failed to get xbar resources");
if (!request_mem_region(res_xbar.start, resource_size(&res_xbar), if (!request_mem_region(res_xbar.start, resource_size(&res_xbar),
res_xbar.name)) res_xbar.name))
......
...@@ -1562,6 +1562,7 @@ static void probe_vcache(void) ...@@ -1562,6 +1562,7 @@ static void probe_vcache(void)
vcache_size = c->vcache.sets * c->vcache.ways * c->vcache.linesz; vcache_size = c->vcache.sets * c->vcache.ways * c->vcache.linesz;
c->vcache.waybit = 0; c->vcache.waybit = 0;
c->vcache.waysize = vcache_size / c->vcache.ways;
pr_info("Unified victim cache %ldkB %s, linesize %d bytes.\n", pr_info("Unified victim cache %ldkB %s, linesize %d bytes.\n",
vcache_size >> 10, way_string[c->vcache.ways], c->vcache.linesz); vcache_size >> 10, way_string[c->vcache.ways], c->vcache.linesz);
...@@ -1664,6 +1665,7 @@ static void __init loongson3_sc_init(void) ...@@ -1664,6 +1665,7 @@ static void __init loongson3_sc_init(void)
/* Loongson-3 has 4 cores, 1MB scache for each. scaches are shared */ /* Loongson-3 has 4 cores, 1MB scache for each. scaches are shared */
scache_size *= 4; scache_size *= 4;
c->scache.waybit = 0; c->scache.waybit = 0;
c->scache.waysize = scache_size / c->scache.ways;
pr_info("Unified secondary cache %ldkB %s, linesize %d bytes.\n", pr_info("Unified secondary cache %ldkB %s, linesize %d bytes.\n",
scache_size >> 10, way_string[c->scache.ways], c->scache.linesz); scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
if (scache_size) if (scache_size)
......
...@@ -760,7 +760,8 @@ static void build_huge_update_entries(u32 **p, unsigned int pte, ...@@ -760,7 +760,8 @@ static void build_huge_update_entries(u32 **p, unsigned int pte,
static void build_huge_handler_tail(u32 **p, struct uasm_reloc **r, static void build_huge_handler_tail(u32 **p, struct uasm_reloc **r,
struct uasm_label **l, struct uasm_label **l,
unsigned int pte, unsigned int pte,
unsigned int ptr) unsigned int ptr,
unsigned int flush)
{ {
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
UASM_i_SC(p, pte, 0, ptr); UASM_i_SC(p, pte, 0, ptr);
...@@ -769,6 +770,22 @@ static void build_huge_handler_tail(u32 **p, struct uasm_reloc **r, ...@@ -769,6 +770,22 @@ static void build_huge_handler_tail(u32 **p, struct uasm_reloc **r,
#else #else
UASM_i_SW(p, pte, 0, ptr); UASM_i_SW(p, pte, 0, ptr);
#endif #endif
if (cpu_has_ftlb && flush) {
BUG_ON(!cpu_has_tlbinv);
UASM_i_MFC0(p, ptr, C0_ENTRYHI);
uasm_i_ori(p, ptr, ptr, MIPS_ENTRYHI_EHINV);
UASM_i_MTC0(p, ptr, C0_ENTRYHI);
build_tlb_write_entry(p, l, r, tlb_indexed);
uasm_i_xori(p, ptr, ptr, MIPS_ENTRYHI_EHINV);
UASM_i_MTC0(p, ptr, C0_ENTRYHI);
build_huge_update_entries(p, pte, ptr);
build_huge_tlb_write_entry(p, l, r, pte, tlb_random, 0);
return;
}
build_huge_update_entries(p, pte, ptr); build_huge_update_entries(p, pte, ptr);
build_huge_tlb_write_entry(p, l, r, pte, tlb_indexed, 0); build_huge_tlb_write_entry(p, l, r, pte, tlb_indexed, 0);
} }
...@@ -2199,7 +2216,7 @@ static void build_r4000_tlb_load_handler(void) ...@@ -2199,7 +2216,7 @@ static void build_r4000_tlb_load_handler(void)
uasm_l_tlbl_goaround2(&l, p); uasm_l_tlbl_goaround2(&l, p);
} }
uasm_i_ori(&p, wr.r1, wr.r1, (_PAGE_ACCESSED | _PAGE_VALID)); uasm_i_ori(&p, wr.r1, wr.r1, (_PAGE_ACCESSED | _PAGE_VALID));
build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2); build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2, 1);
#endif #endif
uasm_l_nopage_tlbl(&l, p); uasm_l_nopage_tlbl(&l, p);
...@@ -2254,7 +2271,7 @@ static void build_r4000_tlb_store_handler(void) ...@@ -2254,7 +2271,7 @@ static void build_r4000_tlb_store_handler(void)
build_tlb_probe_entry(&p); build_tlb_probe_entry(&p);
uasm_i_ori(&p, wr.r1, wr.r1, uasm_i_ori(&p, wr.r1, wr.r1,
_PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY); _PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY);
build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2); build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2, 1);
#endif #endif
uasm_l_nopage_tlbs(&l, p); uasm_l_nopage_tlbs(&l, p);
...@@ -2310,7 +2327,7 @@ static void build_r4000_tlb_modify_handler(void) ...@@ -2310,7 +2327,7 @@ static void build_r4000_tlb_modify_handler(void)
build_tlb_probe_entry(&p); build_tlb_probe_entry(&p);
uasm_i_ori(&p, wr.r1, wr.r1, uasm_i_ori(&p, wr.r1, wr.r1,
_PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY); _PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID | _PAGE_DIRTY);
build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2); build_huge_handler_tail(&p, &r, &l, wr.r1, wr.r2, 0);
#endif #endif
uasm_l_nopage_tlbm(&l, p); uasm_l_nopage_tlbm(&l, p);
......
...@@ -35,7 +35,7 @@ static struct rt2880_pmx_func uartlite_func[] = { FUNC("uartlite", 0, 15, 2) }; ...@@ -35,7 +35,7 @@ static struct rt2880_pmx_func uartlite_func[] = { FUNC("uartlite", 0, 15, 2) };
static struct rt2880_pmx_func jtag_func[] = { FUNC("jtag", 0, 17, 5) }; static struct rt2880_pmx_func jtag_func[] = { FUNC("jtag", 0, 17, 5) };
static struct rt2880_pmx_func mdio_func[] = { FUNC("mdio", 0, 22, 2) }; static struct rt2880_pmx_func mdio_func[] = { FUNC("mdio", 0, 22, 2) };
static struct rt2880_pmx_func lna_a_func[] = { FUNC("lna a", 0, 32, 3) }; static struct rt2880_pmx_func lna_a_func[] = { FUNC("lna a", 0, 32, 3) };
static struct rt2880_pmx_func lna_g_func[] = { FUNC("lna a", 0, 35, 3) }; static struct rt2880_pmx_func lna_g_func[] = { FUNC("lna g", 0, 35, 3) };
static struct rt2880_pmx_func pci_func[] = { static struct rt2880_pmx_func pci_func[] = {
FUNC("pci-dev", 0, 40, 32), FUNC("pci-dev", 0, 40, 32),
FUNC("pci-host2", 1, 40, 32), FUNC("pci-host2", 1, 40, 32),
...@@ -43,7 +43,7 @@ static struct rt2880_pmx_func pci_func[] = { ...@@ -43,7 +43,7 @@ static struct rt2880_pmx_func pci_func[] = {
FUNC("pci-fnc", 3, 40, 32) FUNC("pci-fnc", 3, 40, 32)
}; };
static struct rt2880_pmx_func ge1_func[] = { FUNC("ge1", 0, 72, 12) }; static struct rt2880_pmx_func ge1_func[] = { FUNC("ge1", 0, 72, 12) };
static struct rt2880_pmx_func ge2_func[] = { FUNC("ge1", 0, 84, 12) }; static struct rt2880_pmx_func ge2_func[] = { FUNC("ge2", 0, 84, 12) };
static struct rt2880_pmx_group rt3883_pinmux_data[] = { static struct rt2880_pmx_group rt3883_pinmux_data[] = {
GRP("i2c", i2c_func, 1, RT3883_GPIO_MODE_I2C), GRP("i2c", i2c_func, 1, RT3883_GPIO_MODE_I2C),
......
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