Skip to content

Commit 3fbdc37

Browse files
committed
Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
Pull MIPS fixes from Ralf Baechle: "Another round of MIPS fixes for 4.2. No area does particularly stand out but we have a two unpleasant ones: - Kernel ptes are marked with a global bit which allows the kernel to share kernel TLB entries between all processes. For this to work both entries of an adjacent even/odd pte pair need to have the global bit set. There has been a subtle race in setting the other entry's global bit since ~ 2000 but it take particularly pathological workloads that essentially do mostly vmalloc/vfree to trigger this. This pull request fixes the 64-bit case but leaves the case of 32 bit CPUs with 64 bit ptes unsolved for now. The unfixed cases affect hardware that is not available in the field yet. - Instruction emulation requires loading instructions from user space but the current fast but simplistic approach will fail on pages that are PROT_EXEC but !PROT_READ. For this reason we temporarily do not permit this permission and will map pages with PROT_EXEC | PROT_READ. The remainder of this pull request is more or less across the field and the short log explains them well" * 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: MIPS: Make set_pte() SMP safe. MIPS: Replace add and sub instructions in relocate_kernel.S with addiu MIPS: Flush RPS on kernel entry with EVA Revert "MIPS: BCM63xx: Provide a plat_post_dma_flush hook" MIPS: BMIPS: Delete unused Kconfig symbol MIPS: Export get_c0_perfcount_int() MIPS: show_stack: Fix stack trace with EVA MIPS: do_mcheck: Fix kernel code dump with EVA MIPS: SMP: Don't increment irq_count multiple times for call function IPIs MIPS: Partially disable RIXI support. MIPS: Handle page faults of executable but unreadable pages correctly. MIPS: Malta: Don't reinitialise RTC MIPS: unaligned: Fix build error on big endian R6 kernels MIPS: Fix sched_getaffinity with MT FPAFF enabled MIPS: Fix build with CONFIG_OF=y for non OF-enabled targets CPUFREQ: Loongson2: Fix broken build due to incorrect include.
2 parents af0b315 + 46011e6 commit 3fbdc37

File tree

31 files changed

+130
-62
lines changed

31 files changed

+130
-62
lines changed

arch/mips/Kconfig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,6 @@ config BMIPS_GENERIC
151151
select BCM7120_L2_IRQ
152152
select BRCMSTB_L2_IRQ
153153
select IRQ_MIPS_CPU
154-
select RAW_IRQ_ACCESSORS
155154
select DMA_NONCOHERENT
156155
select SYS_SUPPORTS_32BIT_KERNEL
157156
select SYS_SUPPORTS_LITTLE_ENDIAN

arch/mips/ath79/setup.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ int get_c0_perfcount_int(void)
190190
{
191191
return ATH79_MISC_IRQ(5);
192192
}
193+
EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
193194

194195
unsigned int get_c0_compare_int(void)
195196
{

arch/mips/cavium-octeon/smp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ static irqreturn_t mailbox_interrupt(int irq, void *dev_id)
4242
cvmx_write_csr(CVMX_CIU_MBOX_CLRX(coreid), action);
4343

4444
if (action & SMP_CALL_FUNCTION)
45-
smp_call_function_interrupt();
45+
generic_smp_call_function_interrupt();
4646
if (action & SMP_RESCHEDULE_YOURSELF)
4747
scheduler_ipi();
4848

arch/mips/include/asm/mach-bcm63xx/dma-coherence.h

Lines changed: 0 additions & 10 deletions
This file was deleted.

arch/mips/include/asm/pgtable.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,39 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)
182182
* Make sure the buddy is global too (if it's !none,
183183
* it better already be global)
184184
*/
185+
#ifdef CONFIG_SMP
186+
/*
187+
* For SMP, multiple CPUs can race, so we need to do
188+
* this atomically.
189+
*/
190+
#ifdef CONFIG_64BIT
191+
#define LL_INSN "lld"
192+
#define SC_INSN "scd"
193+
#else /* CONFIG_32BIT */
194+
#define LL_INSN "ll"
195+
#define SC_INSN "sc"
196+
#endif
197+
unsigned long page_global = _PAGE_GLOBAL;
198+
unsigned long tmp;
199+
200+
__asm__ __volatile__ (
201+
" .set push\n"
202+
" .set noreorder\n"
203+
"1: " LL_INSN " %[tmp], %[buddy]\n"
204+
" bnez %[tmp], 2f\n"
205+
" or %[tmp], %[tmp], %[global]\n"
206+
" " SC_INSN " %[tmp], %[buddy]\n"
207+
" beqz %[tmp], 1b\n"
208+
" nop\n"
209+
"2:\n"
210+
" .set pop"
211+
: [buddy] "+m" (buddy->pte),
212+
[tmp] "=&r" (tmp)
213+
: [global] "r" (page_global));
214+
#else /* !CONFIG_SMP */
185215
if (pte_none(*buddy))
186216
pte_val(*buddy) = pte_val(*buddy) | _PAGE_GLOBAL;
217+
#endif /* CONFIG_SMP */
187218
}
188219
#endif
189220
}

arch/mips/include/asm/smp.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,6 @@ static inline void __cpu_die(unsigned int cpu)
8383
extern void play_dead(void);
8484
#endif
8585

86-
extern asmlinkage void smp_call_function_interrupt(void);
87-
8886
static inline void arch_send_call_function_single_ipi(int cpu)
8987
{
9088
extern struct plat_smp_ops *mp_ops; /* private */

arch/mips/include/asm/stackframe.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,31 @@
152152
.set noreorder
153153
bltz k0, 8f
154154
move k1, sp
155+
#ifdef CONFIG_EVA
156+
/*
157+
* Flush interAptiv's Return Prediction Stack (RPS) by writing
158+
* EntryHi. Toggling Config7.RPS is slower and less portable.
159+
*
160+
* The RPS isn't automatically flushed when exceptions are
161+
* taken, which can result in kernel mode speculative accesses
162+
* to user addresses if the RPS mispredicts. That's harmless
163+
* when user and kernel share the same address space, but with
164+
* EVA the same user segments may be unmapped to kernel mode,
165+
* even containing sensitive MMIO regions or invalid memory.
166+
*
167+
* This can happen when the kernel sets the return address to
168+
* ret_from_* and jr's to the exception handler, which looks
169+
* more like a tail call than a function call. If nested calls
170+
* don't evict the last user address in the RPS, it will
171+
* mispredict the return and fetch from a user controlled
172+
* address into the icache.
173+
*
174+
* More recent EVA-capable cores with MAAR to restrict
175+
* speculative accesses aren't affected.
176+
*/
177+
MFC0 k0, CP0_ENTRYHI
178+
MTC0 k0, CP0_ENTRYHI
179+
#endif
155180
.set reorder
156181
/* Called from user mode, new stack. */
157182
get_saved_sp

arch/mips/kernel/mips-mt-fpaff.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,
154154
unsigned long __user *user_mask_ptr)
155155
{
156156
unsigned int real_len;
157-
cpumask_t mask;
157+
cpumask_t allowed, mask;
158158
int retval;
159159
struct task_struct *p;
160160

@@ -173,7 +173,8 @@ asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,
173173
if (retval)
174174
goto out_unlock;
175175

176-
cpumask_and(&mask, &p->thread.user_cpus_allowed, cpu_possible_mask);
176+
cpumask_or(&allowed, &p->thread.user_cpus_allowed, &p->cpus_allowed);
177+
cpumask_and(&mask, &allowed, cpu_active_mask);
177178

178179
out_unlock:
179180
read_unlock(&tasklist_lock);

arch/mips/kernel/prom.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ char *mips_get_machine_name(void)
3838
return mips_machine_name;
3939
}
4040

41-
#ifdef CONFIG_OF
41+
#ifdef CONFIG_USE_OF
4242
void __init early_init_dt_add_memory_arch(u64 base, u64 size)
4343
{
4444
return add_memory_region(base, size, BOOT_MEM_RAM);

arch/mips/kernel/relocate_kernel.S

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ LEAF(relocate_new_kernel)
2424

2525
process_entry:
2626
PTR_L s2, (s0)
27-
PTR_ADD s0, s0, SZREG
27+
PTR_ADDIU s0, s0, SZREG
2828

2929
/*
3030
* In case of a kdump/crash kernel, the indirection page is not
@@ -61,9 +61,9 @@ copy_word:
6161
/* copy page word by word */
6262
REG_L s5, (s2)
6363
REG_S s5, (s4)
64-
PTR_ADD s4, s4, SZREG
65-
PTR_ADD s2, s2, SZREG
66-
LONG_SUB s6, s6, 1
64+
PTR_ADDIU s4, s4, SZREG
65+
PTR_ADDIU s2, s2, SZREG
66+
LONG_ADDIU s6, s6, -1
6767
beq s6, zero, process_entry
6868
b copy_word
6969
b process_entry

arch/mips/kernel/smp-bmips.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ static irqreturn_t bmips5000_ipi_interrupt(int irq, void *dev_id)
284284
if (action == 0)
285285
scheduler_ipi();
286286
else
287-
smp_call_function_interrupt();
287+
generic_smp_call_function_interrupt();
288288

289289
return IRQ_HANDLED;
290290
}
@@ -336,7 +336,7 @@ static irqreturn_t bmips43xx_ipi_interrupt(int irq, void *dev_id)
336336
if (action & SMP_RESCHEDULE_YOURSELF)
337337
scheduler_ipi();
338338
if (action & SMP_CALL_FUNCTION)
339-
smp_call_function_interrupt();
339+
generic_smp_call_function_interrupt();
340340

341341
return IRQ_HANDLED;
342342
}

arch/mips/kernel/smp.c

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -192,16 +192,6 @@ asmlinkage void start_secondary(void)
192192
cpu_startup_entry(CPUHP_ONLINE);
193193
}
194194

195-
/*
196-
* Call into both interrupt handlers, as we share the IPI for them
197-
*/
198-
void __irq_entry smp_call_function_interrupt(void)
199-
{
200-
irq_enter();
201-
generic_smp_call_function_interrupt();
202-
irq_exit();
203-
}
204-
205195
static void stop_this_cpu(void *dummy)
206196
{
207197
/*

arch/mips/kernel/traps.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ static void show_stacktrace(struct task_struct *task,
192192
void show_stack(struct task_struct *task, unsigned long *sp)
193193
{
194194
struct pt_regs regs;
195+
mm_segment_t old_fs = get_fs();
195196
if (sp) {
196197
regs.regs[29] = (unsigned long)sp;
197198
regs.regs[31] = 0;
@@ -210,7 +211,13 @@ void show_stack(struct task_struct *task, unsigned long *sp)
210211
prepare_frametrace(&regs);
211212
}
212213
}
214+
/*
215+
* show_stack() deals exclusively with kernel mode, so be sure to access
216+
* the stack in the kernel (not user) address space.
217+
*/
218+
set_fs(KERNEL_DS);
213219
show_stacktrace(task, &regs);
220+
set_fs(old_fs);
214221
}
215222

216223
static void show_code(unsigned int __user *pc)
@@ -1519,6 +1526,7 @@ asmlinkage void do_mcheck(struct pt_regs *regs)
15191526
const int field = 2 * sizeof(unsigned long);
15201527
int multi_match = regs->cp0_status & ST0_TS;
15211528
enum ctx_state prev_state;
1529+
mm_segment_t old_fs = get_fs();
15221530

15231531
prev_state = exception_enter();
15241532
show_regs(regs);
@@ -1540,8 +1548,13 @@ asmlinkage void do_mcheck(struct pt_regs *regs)
15401548
dump_tlb_all();
15411549
}
15421550

1551+
if (!user_mode(regs))
1552+
set_fs(KERNEL_DS);
1553+
15431554
show_code((unsigned int __user *) regs->cp0_epc);
15441555

1556+
set_fs(old_fs);
1557+
15451558
/*
15461559
* Some chips may have other causes of machine check (e.g. SB1
15471560
* graduation timer)

arch/mips/kernel/unaligned.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ do { \
438438
: "memory"); \
439439
} while(0)
440440

441-
#define StoreDW(addr, value, res) \
441+
#define _StoreDW(addr, value, res) \
442442
do { \
443443
__asm__ __volatile__ ( \
444444
".set\tpush\n\t" \

arch/mips/lantiq/irq.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
293293

294294
static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
295295
{
296-
smp_call_function_interrupt();
296+
generic_smp_call_function_interrupt();
297297
return IRQ_HANDLED;
298298
}
299299

@@ -466,6 +466,7 @@ int get_c0_perfcount_int(void)
466466
{
467467
return ltq_perfcount_irq;
468468
}
469+
EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
469470

470471
unsigned int get_c0_compare_int(void)
471472
{

arch/mips/loongson64/loongson-3/smp.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,8 +266,11 @@ void loongson3_ipi_interrupt(struct pt_regs *regs)
266266
if (action & SMP_RESCHEDULE_YOURSELF)
267267
scheduler_ipi();
268268

269-
if (action & SMP_CALL_FUNCTION)
270-
smp_call_function_interrupt();
269+
if (action & SMP_CALL_FUNCTION) {
270+
irq_enter();
271+
generic_smp_call_function_interrupt();
272+
irq_exit();
273+
}
271274

272275
if (action & SMP_ASK_C0COUNT) {
273276
BUG_ON(cpu != 0);

arch/mips/mm/cache.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,18 +160,18 @@ static inline void setup_protection_map(void)
160160
protection_map[1] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC);
161161
protection_map[2] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_NO_READ);
162162
protection_map[3] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC);
163-
protection_map[4] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_READ);
163+
protection_map[4] = __pgprot(_page_cachable_default | _PAGE_PRESENT);
164164
protection_map[5] = __pgprot(_page_cachable_default | _PAGE_PRESENT);
165-
protection_map[6] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_READ);
165+
protection_map[6] = __pgprot(_page_cachable_default | _PAGE_PRESENT);
166166
protection_map[7] = __pgprot(_page_cachable_default | _PAGE_PRESENT);
167167

168168
protection_map[8] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_NO_READ);
169169
protection_map[9] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC);
170170
protection_map[10] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_WRITE | _PAGE_NO_READ);
171171
protection_map[11] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_WRITE);
172-
protection_map[12] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_READ);
172+
protection_map[12] = __pgprot(_page_cachable_default | _PAGE_PRESENT);
173173
protection_map[13] = __pgprot(_page_cachable_default | _PAGE_PRESENT);
174-
protection_map[14] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_WRITE | _PAGE_NO_READ);
174+
protection_map[14] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_WRITE);
175175
protection_map[15] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_WRITE);
176176

177177
} else {

arch/mips/mm/fault.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,8 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
133133
#endif
134134
goto bad_area;
135135
}
136-
if (!(vma->vm_flags & VM_READ)) {
136+
if (!(vma->vm_flags & VM_READ) &&
137+
exception_epc(regs) != address) {
137138
#if 0
138139
pr_notice("Cpu%d[%s:%d:%0*lx:%ld:%0*lx] RI violation\n",
139140
raw_smp_processor_id(),

arch/mips/mti-malta/malta-int.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
222222

223223
static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
224224
{
225-
smp_call_function_interrupt();
225+
generic_smp_call_function_interrupt();
226226

227227
return IRQ_HANDLED;
228228
}

arch/mips/mti-malta/malta-time.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ int get_c0_perfcount_int(void)
154154

155155
return mips_cpu_perf_irq;
156156
}
157+
EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
157158

158159
unsigned int get_c0_compare_int(void)
159160
{
@@ -171,14 +172,17 @@ unsigned int get_c0_compare_int(void)
171172

172173
static void __init init_rtc(void)
173174
{
174-
/* stop the clock whilst setting it up */
175-
CMOS_WRITE(RTC_SET | RTC_24H, RTC_CONTROL);
175+
unsigned char freq, ctrl;
176176

177-
/* 32KHz time base */
178-
CMOS_WRITE(RTC_REF_CLCK_32KHZ, RTC_FREQ_SELECT);
177+
/* Set 32KHz time base if not already set */
178+
freq = CMOS_READ(RTC_FREQ_SELECT);
179+
if ((freq & RTC_DIV_CTL) != RTC_REF_CLCK_32KHZ)
180+
CMOS_WRITE(RTC_REF_CLCK_32KHZ, RTC_FREQ_SELECT);
179181

180-
/* start the clock */
181-
CMOS_WRITE(RTC_24H, RTC_CONTROL);
182+
/* Ensure SET bit is clear so RTC can run */
183+
ctrl = CMOS_READ(RTC_CONTROL);
184+
if (ctrl & RTC_SET)
185+
CMOS_WRITE(ctrl & ~RTC_SET, RTC_CONTROL);
182186
}
183187

184188
void __init plat_time_init(void)

arch/mips/mti-sead3/sead3-time.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ int get_c0_perfcount_int(void)
7777
return MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
7878
return -1;
7979
}
80+
EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
8081

8182
unsigned int get_c0_compare_int(void)
8283
{

arch/mips/netlogic/common/smp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc)
8686
{
8787
clear_c0_eimr(irq);
8888
ack_c0_eirr(irq);
89-
smp_call_function_interrupt();
89+
generic_smp_call_function_interrupt();
9090
set_c0_eimr(irq);
9191
}
9292

arch/mips/paravirt/paravirt-smp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ static irqreturn_t paravirt_reched_interrupt(int irq, void *dev_id)
114114

115115
static irqreturn_t paravirt_function_interrupt(int irq, void *dev_id)
116116
{
117-
smp_call_function_interrupt();
117+
generic_smp_call_function_interrupt();
118118
return IRQ_HANDLED;
119119
}
120120

arch/mips/pistachio/time.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ int get_c0_perfcount_int(void)
2626
{
2727
return gic_get_c0_perfcount_int();
2828
}
29+
EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
2930

3031
int get_c0_fdc_int(void)
3132
{

0 commit comments

Comments
 (0)