mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 06:31:49 +00:00
Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
Pull MIPS fixes from Ralf Baechle: "More 3.18 fixes for MIPS: - backtraces were not quite working on on 64-bit kernels - loongson needs a different cache coherency setting - Loongson 3 is a MIPS64 R2 version but due to erratum we treat is an older architecture revision. - fix build errors due to undefined references to __node_distances for certain configurations. - fix instruction decodig in the jump label code. - for certain configurations copy_{from,to}_user destroy the content of $3 so that register needs to be marked as clobbed by the calling code. - Hardware Table Walker fixes. - fill the delay slot of the last instruction of memcpy otherwise whatever ends up there randomly might have undesirable effects. - ensure get_user/__get_user always zero the variable to be read even in case of an error" * 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: MIPS: jump_label.c: Handle the microMIPS J instruction encoding MIPS: jump_label.c: Correct the span of the J instruction MIPS: Zero variable read by get_user / __get_user in case of an error. MIPS: lib: memcpy: Restore NOP on delay slot before returning to caller MIPS: tlb-r4k: Add missing HTW stop/start sequences MIPS: asm: uaccess: Add v1 register to clobber list on EVA MIPS: oprofile: Fix backtrace on 64-bit kernel MIPS: Loongson: Set Loongson-3's ISA level to MIPS64R1 MIPS: Loongson: Fix the write-combine CCA value setting MIPS: IP27: Fix __node_distances undefined error MIPS: Loongson3: Fix __node_distances undefined error
This commit is contained in:
commit
e6a588d086
@ -20,9 +20,15 @@
|
|||||||
#define WORD_INSN ".word"
|
#define WORD_INSN ".word"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_CPU_MICROMIPS
|
||||||
|
#define NOP_INSN "nop32"
|
||||||
|
#else
|
||||||
|
#define NOP_INSN "nop"
|
||||||
|
#endif
|
||||||
|
|
||||||
static __always_inline bool arch_static_branch(struct static_key *key)
|
static __always_inline bool arch_static_branch(struct static_key *key)
|
||||||
{
|
{
|
||||||
asm_volatile_goto("1:\tnop\n\t"
|
asm_volatile_goto("1:\t" NOP_INSN "\n\t"
|
||||||
"nop\n\t"
|
"nop\n\t"
|
||||||
".pushsection __jump_table, \"aw\"\n\t"
|
".pushsection __jump_table, \"aw\"\n\t"
|
||||||
WORD_INSN " 1b, %l[l_yes], %0\n\t"
|
WORD_INSN " 1b, %l[l_yes], %0\n\t"
|
||||||
|
@ -41,10 +41,8 @@
|
|||||||
#define cpu_has_mcheck 0
|
#define cpu_has_mcheck 0
|
||||||
#define cpu_has_mdmx 0
|
#define cpu_has_mdmx 0
|
||||||
#define cpu_has_mips16 0
|
#define cpu_has_mips16 0
|
||||||
#define cpu_has_mips32r1 0
|
|
||||||
#define cpu_has_mips32r2 0
|
#define cpu_has_mips32r2 0
|
||||||
#define cpu_has_mips3d 0
|
#define cpu_has_mips3d 0
|
||||||
#define cpu_has_mips64r1 0
|
|
||||||
#define cpu_has_mips64r2 0
|
#define cpu_has_mips64r2 0
|
||||||
#define cpu_has_mipsmt 0
|
#define cpu_has_mipsmt 0
|
||||||
#define cpu_has_prefetch 0
|
#define cpu_has_prefetch 0
|
||||||
|
@ -301,7 +301,8 @@ do { \
|
|||||||
__get_kernel_common((x), size, __gu_ptr); \
|
__get_kernel_common((x), size, __gu_ptr); \
|
||||||
else \
|
else \
|
||||||
__get_user_common((x), size, __gu_ptr); \
|
__get_user_common((x), size, __gu_ptr); \
|
||||||
} \
|
} else \
|
||||||
|
(x) = 0; \
|
||||||
\
|
\
|
||||||
__gu_err; \
|
__gu_err; \
|
||||||
})
|
})
|
||||||
@ -316,6 +317,7 @@ do { \
|
|||||||
" .insn \n" \
|
" .insn \n" \
|
||||||
" .section .fixup,\"ax\" \n" \
|
" .section .fixup,\"ax\" \n" \
|
||||||
"3: li %0, %4 \n" \
|
"3: li %0, %4 \n" \
|
||||||
|
" move %1, $0 \n" \
|
||||||
" j 2b \n" \
|
" j 2b \n" \
|
||||||
" .previous \n" \
|
" .previous \n" \
|
||||||
" .section __ex_table,\"a\" \n" \
|
" .section __ex_table,\"a\" \n" \
|
||||||
@ -630,6 +632,7 @@ do { \
|
|||||||
" .insn \n" \
|
" .insn \n" \
|
||||||
" .section .fixup,\"ax\" \n" \
|
" .section .fixup,\"ax\" \n" \
|
||||||
"3: li %0, %4 \n" \
|
"3: li %0, %4 \n" \
|
||||||
|
" move %1, $0 \n" \
|
||||||
" j 2b \n" \
|
" j 2b \n" \
|
||||||
" .previous \n" \
|
" .previous \n" \
|
||||||
" .section __ex_table,\"a\" \n" \
|
" .section __ex_table,\"a\" \n" \
|
||||||
@ -773,10 +776,11 @@ extern void __put_user_unaligned_unknown(void);
|
|||||||
"jal\t" #destination "\n\t"
|
"jal\t" #destination "\n\t"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_CPU_DADDI_WORKAROUNDS
|
#if defined(CONFIG_CPU_DADDI_WORKAROUNDS) || (defined(CONFIG_EVA) && \
|
||||||
#define DADDI_SCRATCH "$0"
|
defined(CONFIG_CPU_HAS_PREFETCH))
|
||||||
#else
|
|
||||||
#define DADDI_SCRATCH "$3"
|
#define DADDI_SCRATCH "$3"
|
||||||
|
#else
|
||||||
|
#define DADDI_SCRATCH "$0"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern size_t __copy_user(void *__to, const void *__from, size_t __n);
|
extern size_t __copy_user(void *__to, const void *__from, size_t __n);
|
||||||
|
@ -757,31 +757,34 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
|
|||||||
c->cputype = CPU_LOONGSON2;
|
c->cputype = CPU_LOONGSON2;
|
||||||
__cpu_name[cpu] = "ICT Loongson-2";
|
__cpu_name[cpu] = "ICT Loongson-2";
|
||||||
set_elf_platform(cpu, "loongson2e");
|
set_elf_platform(cpu, "loongson2e");
|
||||||
|
set_isa(c, MIPS_CPU_ISA_III);
|
||||||
break;
|
break;
|
||||||
case PRID_REV_LOONGSON2F:
|
case PRID_REV_LOONGSON2F:
|
||||||
c->cputype = CPU_LOONGSON2;
|
c->cputype = CPU_LOONGSON2;
|
||||||
__cpu_name[cpu] = "ICT Loongson-2";
|
__cpu_name[cpu] = "ICT Loongson-2";
|
||||||
set_elf_platform(cpu, "loongson2f");
|
set_elf_platform(cpu, "loongson2f");
|
||||||
|
set_isa(c, MIPS_CPU_ISA_III);
|
||||||
break;
|
break;
|
||||||
case PRID_REV_LOONGSON3A:
|
case PRID_REV_LOONGSON3A:
|
||||||
c->cputype = CPU_LOONGSON3;
|
c->cputype = CPU_LOONGSON3;
|
||||||
c->writecombine = _CACHE_UNCACHED_ACCELERATED;
|
|
||||||
__cpu_name[cpu] = "ICT Loongson-3";
|
__cpu_name[cpu] = "ICT Loongson-3";
|
||||||
set_elf_platform(cpu, "loongson3a");
|
set_elf_platform(cpu, "loongson3a");
|
||||||
|
set_isa(c, MIPS_CPU_ISA_M64R1);
|
||||||
break;
|
break;
|
||||||
case PRID_REV_LOONGSON3B_R1:
|
case PRID_REV_LOONGSON3B_R1:
|
||||||
case PRID_REV_LOONGSON3B_R2:
|
case PRID_REV_LOONGSON3B_R2:
|
||||||
c->cputype = CPU_LOONGSON3;
|
c->cputype = CPU_LOONGSON3;
|
||||||
__cpu_name[cpu] = "ICT Loongson-3";
|
__cpu_name[cpu] = "ICT Loongson-3";
|
||||||
set_elf_platform(cpu, "loongson3b");
|
set_elf_platform(cpu, "loongson3b");
|
||||||
|
set_isa(c, MIPS_CPU_ISA_M64R1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_isa(c, MIPS_CPU_ISA_III);
|
|
||||||
c->options = R4K_OPTS |
|
c->options = R4K_OPTS |
|
||||||
MIPS_CPU_FPU | MIPS_CPU_LLSC |
|
MIPS_CPU_FPU | MIPS_CPU_LLSC |
|
||||||
MIPS_CPU_32FPR;
|
MIPS_CPU_32FPR;
|
||||||
c->tlbsize = 64;
|
c->tlbsize = 64;
|
||||||
|
c->writecombine = _CACHE_UNCACHED_ACCELERATED;
|
||||||
break;
|
break;
|
||||||
case PRID_IMP_LOONGSON_32: /* Loongson-1 */
|
case PRID_IMP_LOONGSON_32: /* Loongson-1 */
|
||||||
decode_configs(c);
|
decode_configs(c);
|
||||||
|
@ -18,31 +18,53 @@
|
|||||||
|
|
||||||
#ifdef HAVE_JUMP_LABEL
|
#ifdef HAVE_JUMP_LABEL
|
||||||
|
|
||||||
#define J_RANGE_MASK ((1ul << 28) - 1)
|
/*
|
||||||
|
* Define parameters for the standard MIPS and the microMIPS jump
|
||||||
|
* instruction encoding respectively:
|
||||||
|
*
|
||||||
|
* - the ISA bit of the target, either 0 or 1 respectively,
|
||||||
|
*
|
||||||
|
* - the amount the jump target address is shifted right to fit in the
|
||||||
|
* immediate field of the machine instruction, either 2 or 1,
|
||||||
|
*
|
||||||
|
* - the mask determining the size of the jump region relative to the
|
||||||
|
* delay-slot instruction, either 256MB or 128MB,
|
||||||
|
*
|
||||||
|
* - the jump target alignment, either 4 or 2 bytes.
|
||||||
|
*/
|
||||||
|
#define J_ISA_BIT IS_ENABLED(CONFIG_CPU_MICROMIPS)
|
||||||
|
#define J_RANGE_SHIFT (2 - J_ISA_BIT)
|
||||||
|
#define J_RANGE_MASK ((1ul << (26 + J_RANGE_SHIFT)) - 1)
|
||||||
|
#define J_ALIGN_MASK ((1ul << J_RANGE_SHIFT) - 1)
|
||||||
|
|
||||||
void arch_jump_label_transform(struct jump_entry *e,
|
void arch_jump_label_transform(struct jump_entry *e,
|
||||||
enum jump_label_type type)
|
enum jump_label_type type)
|
||||||
{
|
{
|
||||||
|
union mips_instruction *insn_p;
|
||||||
union mips_instruction insn;
|
union mips_instruction insn;
|
||||||
union mips_instruction *insn_p =
|
|
||||||
(union mips_instruction *)(unsigned long)e->code;
|
|
||||||
|
|
||||||
/* Jump only works within a 256MB aligned region. */
|
insn_p = (union mips_instruction *)msk_isa16_mode(e->code);
|
||||||
BUG_ON((e->target & ~J_RANGE_MASK) != (e->code & ~J_RANGE_MASK));
|
|
||||||
|
|
||||||
/* Target must have 4 byte alignment. */
|
/* Jump only works within an aligned region its delay slot is in. */
|
||||||
BUG_ON((e->target & 3) != 0);
|
BUG_ON((e->target & ~J_RANGE_MASK) != ((e->code + 4) & ~J_RANGE_MASK));
|
||||||
|
|
||||||
|
/* Target must have the right alignment and ISA must be preserved. */
|
||||||
|
BUG_ON((e->target & J_ALIGN_MASK) != J_ISA_BIT);
|
||||||
|
|
||||||
if (type == JUMP_LABEL_ENABLE) {
|
if (type == JUMP_LABEL_ENABLE) {
|
||||||
insn.j_format.opcode = j_op;
|
insn.j_format.opcode = J_ISA_BIT ? mm_j32_op : j_op;
|
||||||
insn.j_format.target = (e->target & J_RANGE_MASK) >> 2;
|
insn.j_format.target = e->target >> J_RANGE_SHIFT;
|
||||||
} else {
|
} else {
|
||||||
insn.word = 0; /* nop */
|
insn.word = 0; /* nop */
|
||||||
}
|
}
|
||||||
|
|
||||||
get_online_cpus();
|
get_online_cpus();
|
||||||
mutex_lock(&text_mutex);
|
mutex_lock(&text_mutex);
|
||||||
*insn_p = insn;
|
if (IS_ENABLED(CONFIG_CPU_MICROMIPS)) {
|
||||||
|
insn_p->halfword[0] = insn.word >> 16;
|
||||||
|
insn_p->halfword[1] = insn.word;
|
||||||
|
} else
|
||||||
|
*insn_p = insn;
|
||||||
|
|
||||||
flush_icache_range((unsigned long)insn_p,
|
flush_icache_range((unsigned long)insn_p,
|
||||||
(unsigned long)insn_p + sizeof(*insn_p));
|
(unsigned long)insn_p + sizeof(*insn_p));
|
||||||
|
@ -503,6 +503,7 @@
|
|||||||
STOREB(t0, NBYTES-2(dst), .Ls_exc_p1\@)
|
STOREB(t0, NBYTES-2(dst), .Ls_exc_p1\@)
|
||||||
.Ldone\@:
|
.Ldone\@:
|
||||||
jr ra
|
jr ra
|
||||||
|
nop
|
||||||
.if __memcpy == 1
|
.if __memcpy == 1
|
||||||
END(memcpy)
|
END(memcpy)
|
||||||
.set __memcpy, 0
|
.set __memcpy, 0
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
static struct node_data prealloc__node_data[MAX_NUMNODES];
|
static struct node_data prealloc__node_data[MAX_NUMNODES];
|
||||||
unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES];
|
unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES];
|
||||||
|
EXPORT_SYMBOL(__node_distances);
|
||||||
struct node_data *__node_data[MAX_NUMNODES];
|
struct node_data *__node_data[MAX_NUMNODES];
|
||||||
EXPORT_SYMBOL(__node_data);
|
EXPORT_SYMBOL(__node_data);
|
||||||
|
|
||||||
|
@ -299,6 +299,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
|
|||||||
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
|
|
||||||
|
htw_stop();
|
||||||
pid = read_c0_entryhi() & ASID_MASK;
|
pid = read_c0_entryhi() & ASID_MASK;
|
||||||
address &= (PAGE_MASK << 1);
|
address &= (PAGE_MASK << 1);
|
||||||
write_c0_entryhi(address | pid);
|
write_c0_entryhi(address | pid);
|
||||||
@ -346,6 +347,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
|
|||||||
tlb_write_indexed();
|
tlb_write_indexed();
|
||||||
}
|
}
|
||||||
tlbw_use_hazard();
|
tlbw_use_hazard();
|
||||||
|
htw_start();
|
||||||
flush_itlb_vm(vma);
|
flush_itlb_vm(vma);
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
}
|
}
|
||||||
@ -422,6 +424,7 @@ __init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
|
|||||||
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
/* Save old context and create impossible VPN2 value */
|
/* Save old context and create impossible VPN2 value */
|
||||||
|
htw_stop();
|
||||||
old_ctx = read_c0_entryhi();
|
old_ctx = read_c0_entryhi();
|
||||||
old_pagemask = read_c0_pagemask();
|
old_pagemask = read_c0_pagemask();
|
||||||
wired = read_c0_wired();
|
wired = read_c0_wired();
|
||||||
@ -443,6 +446,7 @@ __init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
|
|||||||
|
|
||||||
write_c0_entryhi(old_ctx);
|
write_c0_entryhi(old_ctx);
|
||||||
write_c0_pagemask(old_pagemask);
|
write_c0_pagemask(old_pagemask);
|
||||||
|
htw_start();
|
||||||
out:
|
out:
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -92,7 +92,7 @@ static inline int unwind_user_frame(struct stackframe *old_frame,
|
|||||||
/* This marks the end of the previous function,
|
/* This marks the end of the previous function,
|
||||||
which means we overran. */
|
which means we overran. */
|
||||||
break;
|
break;
|
||||||
stack_size = (unsigned) stack_adjustment;
|
stack_size = (unsigned long) stack_adjustment;
|
||||||
} else if (is_ra_save_ins(&ip)) {
|
} else if (is_ra_save_ins(&ip)) {
|
||||||
int ra_slot = ip.i_format.simmediate;
|
int ra_slot = ip.i_format.simmediate;
|
||||||
if (ra_slot < 0)
|
if (ra_slot < 0)
|
||||||
|
@ -107,6 +107,7 @@ static void router_recurse(klrou_t *router_a, klrou_t *router_b, int depth)
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned char __node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES];
|
unsigned char __node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES];
|
||||||
|
EXPORT_SYMBOL(__node_distances);
|
||||||
|
|
||||||
static int __init compute_node_distance(nasid_t nasid_a, nasid_t nasid_b)
|
static int __init compute_node_distance(nasid_t nasid_a, nasid_t nasid_b)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user