Skip to content

Commit 9d5daef

Browse files
committed
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rmk/linux
Pull ARM updates from Russell King: - add dev_is_amba() function to allow conversions during the next cycle - improve PREEMPT_RT performance with VFP - KASAN fixes for vmap stack * tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rmk/linux: ARM: 9431/1: mm: Pair atomic_set_release() with _read_acquire() ARM: 9430/1: entry: Do a dummy read from VMAP shadow ARM: 9429/1: ioremap: Sync PGDs for VMALLOC shadow ARM: 9426/1: vfp: Move sending signals outside of vfp_state_hold()ed section. ARM: 9425/1: vfp: Use vfp_state_hold() in vfp_support_entry(). ARM: 9424/1: vfp: Use vfp_state_hold() in vfp_sync_hwstate(). ARM: 9423/1: vfp: Provide vfp_state_hold() for VFP locking. ARM: 9415/1: amba: Add dev_is_amba() function and export it for modules
2 parents fbb3c22 + 93ee385 commit 9d5daef

File tree

5 files changed

+102
-26
lines changed

5 files changed

+102
-26
lines changed

arch/arm/kernel/entry-armv.S

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <asm/tls.h>
2626
#include <asm/system_info.h>
2727
#include <asm/uaccess-asm.h>
28+
#include <asm/kasan_def.h>
2829

2930
#include "entry-header.S"
3031
#include <asm/probes.h>
@@ -561,6 +562,13 @@ ENTRY(__switch_to)
561562
@ entries covering the vmalloc region.
562563
@
563564
ldr r2, [ip]
565+
#ifdef CONFIG_KASAN_VMALLOC
566+
@ Also dummy read from the KASAN shadow memory for the new stack if we
567+
@ are using KASAN
568+
mov_l r2, KASAN_SHADOW_OFFSET
569+
add r2, r2, ip, lsr #KASAN_SHADOW_SCALE_SHIFT
570+
ldr r2, [r2]
571+
#endif
564572
#endif
565573

566574
@ When CONFIG_THREAD_INFO_IN_TASK=n, the update of SP itself is what

arch/arm/mm/ioremap.c

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
*/
2424
#include <linux/module.h>
2525
#include <linux/errno.h>
26+
#include <linux/kasan.h>
2627
#include <linux/mm.h>
2728
#include <linux/vmalloc.h>
2829
#include <linux/io.h>
@@ -115,16 +116,40 @@ int ioremap_page(unsigned long virt, unsigned long phys,
115116
}
116117
EXPORT_SYMBOL(ioremap_page);
117118

119+
#ifdef CONFIG_KASAN
120+
static unsigned long arm_kasan_mem_to_shadow(unsigned long addr)
121+
{
122+
return (unsigned long)kasan_mem_to_shadow((void *)addr);
123+
}
124+
#else
125+
static unsigned long arm_kasan_mem_to_shadow(unsigned long addr)
126+
{
127+
return 0;
128+
}
129+
#endif
130+
131+
static void memcpy_pgd(struct mm_struct *mm, unsigned long start,
132+
unsigned long end)
133+
{
134+
end = ALIGN(end, PGDIR_SIZE);
135+
memcpy(pgd_offset(mm, start), pgd_offset_k(start),
136+
sizeof(pgd_t) * (pgd_index(end) - pgd_index(start)));
137+
}
138+
118139
void __check_vmalloc_seq(struct mm_struct *mm)
119140
{
120141
int seq;
121142

122143
do {
123-
seq = atomic_read(&init_mm.context.vmalloc_seq);
124-
memcpy(pgd_offset(mm, VMALLOC_START),
125-
pgd_offset_k(VMALLOC_START),
126-
sizeof(pgd_t) * (pgd_index(VMALLOC_END) -
127-
pgd_index(VMALLOC_START)));
144+
seq = atomic_read_acquire(&init_mm.context.vmalloc_seq);
145+
memcpy_pgd(mm, VMALLOC_START, VMALLOC_END);
146+
if (IS_ENABLED(CONFIG_KASAN_VMALLOC)) {
147+
unsigned long start =
148+
arm_kasan_mem_to_shadow(VMALLOC_START);
149+
unsigned long end =
150+
arm_kasan_mem_to_shadow(VMALLOC_END);
151+
memcpy_pgd(mm, start, end);
152+
}
128153
/*
129154
* Use a store-release so that other CPUs that observe the
130155
* counter's new value are guaranteed to see the results of the

arch/arm/vfp/vfpmodule.c

Lines changed: 53 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,34 @@ extern unsigned int VFP_arch_feroceon __alias(VFP_arch);
5555
*/
5656
union vfp_state *vfp_current_hw_state[NR_CPUS];
5757

58+
/*
59+
* Claim ownership of the VFP unit.
60+
*
61+
* The caller may change VFP registers until vfp_state_release() is called.
62+
*
63+
* local_bh_disable() is used to disable preemption and to disable VFP
64+
* processing in softirq context. On PREEMPT_RT kernels local_bh_disable() is
65+
* not sufficient because it only serializes soft interrupt related sections
66+
* via a local lock, but stays preemptible. Disabling preemption is the right
67+
* choice here as bottom half processing is always in thread context on RT
68+
* kernels so it implicitly prevents bottom half processing as well.
69+
*/
70+
static void vfp_state_hold(void)
71+
{
72+
if (!IS_ENABLED(CONFIG_PREEMPT_RT))
73+
local_bh_disable();
74+
else
75+
preempt_disable();
76+
}
77+
78+
static void vfp_state_release(void)
79+
{
80+
if (!IS_ENABLED(CONFIG_PREEMPT_RT))
81+
local_bh_enable();
82+
else
83+
preempt_enable();
84+
}
85+
5886
/*
5987
* Is 'thread's most up to date state stored in this CPUs hardware?
6088
* Must be called from non-preemptible context.
@@ -240,16 +268,15 @@ static void vfp_panic(char *reason, u32 inst)
240268
/*
241269
* Process bitmask of exception conditions.
242270
*/
243-
static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_regs *regs)
271+
static int vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr)
244272
{
245273
int si_code = 0;
246274

247275
pr_debug("VFP: raising exceptions %08x\n", exceptions);
248276

249277
if (exceptions == VFP_EXCEPTION_ERROR) {
250278
vfp_panic("unhandled bounce", inst);
251-
vfp_raise_sigfpe(FPE_FLTINV, regs);
252-
return;
279+
return FPE_FLTINV;
253280
}
254281

255282
/*
@@ -277,8 +304,7 @@ static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_
277304
RAISE(FPSCR_OFC, FPSCR_OFE, FPE_FLTOVF);
278305
RAISE(FPSCR_IOC, FPSCR_IOE, FPE_FLTINV);
279306

280-
if (si_code)
281-
vfp_raise_sigfpe(si_code, regs);
307+
return si_code;
282308
}
283309

284310
/*
@@ -324,6 +350,8 @@ static u32 vfp_emulate_instruction(u32 inst, u32 fpscr, struct pt_regs *regs)
324350
static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
325351
{
326352
u32 fpscr, orig_fpscr, fpsid, exceptions;
353+
int si_code2 = 0;
354+
int si_code = 0;
327355

328356
pr_debug("VFP: bounce: trigger %08x fpexc %08x\n", trigger, fpexc);
329357

@@ -369,8 +397,8 @@ static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
369397
* unallocated VFP instruction but with FPSCR.IXE set and not
370398
* on VFP subarch 1.
371399
*/
372-
vfp_raise_exceptions(VFP_EXCEPTION_ERROR, trigger, fpscr, regs);
373-
return;
400+
si_code = vfp_raise_exceptions(VFP_EXCEPTION_ERROR, trigger, fpscr);
401+
goto exit;
374402
}
375403

376404
/*
@@ -394,14 +422,14 @@ static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
394422
*/
395423
exceptions = vfp_emulate_instruction(trigger, fpscr, regs);
396424
if (exceptions)
397-
vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs);
425+
si_code2 = vfp_raise_exceptions(exceptions, trigger, orig_fpscr);
398426

399427
/*
400428
* If there isn't a second FP instruction, exit now. Note that
401429
* the FPEXC.FP2V bit is valid only if FPEXC.EX is 1.
402430
*/
403431
if ((fpexc & (FPEXC_EX | FPEXC_FP2V)) != (FPEXC_EX | FPEXC_FP2V))
404-
return;
432+
goto exit;
405433

406434
/*
407435
* The barrier() here prevents fpinst2 being read
@@ -413,7 +441,13 @@ static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
413441
emulate:
414442
exceptions = vfp_emulate_instruction(trigger, orig_fpscr, regs);
415443
if (exceptions)
416-
vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs);
444+
si_code = vfp_raise_exceptions(exceptions, trigger, orig_fpscr);
445+
exit:
446+
vfp_state_release();
447+
if (si_code2)
448+
vfp_raise_sigfpe(si_code2, regs);
449+
if (si_code)
450+
vfp_raise_sigfpe(si_code, regs);
417451
}
418452

419453
static void vfp_enable(void *unused)
@@ -512,11 +546,9 @@ static inline void vfp_pm_init(void) { }
512546
*/
513547
void vfp_sync_hwstate(struct thread_info *thread)
514548
{
515-
unsigned int cpu = get_cpu();
549+
vfp_state_hold();
516550

517-
local_bh_disable();
518-
519-
if (vfp_state_in_hw(cpu, thread)) {
551+
if (vfp_state_in_hw(raw_smp_processor_id(), thread)) {
520552
u32 fpexc = fmrx(FPEXC);
521553

522554
/*
@@ -527,8 +559,7 @@ void vfp_sync_hwstate(struct thread_info *thread)
527559
fmxr(FPEXC, fpexc);
528560
}
529561

530-
local_bh_enable();
531-
put_cpu();
562+
vfp_state_release();
532563
}
533564

534565
/* Ensure that the thread reloads the hardware VFP state on the next use. */
@@ -683,7 +714,7 @@ static int vfp_support_entry(struct pt_regs *regs, u32 trigger)
683714
if (!user_mode(regs))
684715
return vfp_kmode_exception(regs, trigger);
685716

686-
local_bh_disable();
717+
vfp_state_hold();
687718
fpexc = fmrx(FPEXC);
688719

689720
/*
@@ -748,6 +779,7 @@ static int vfp_support_entry(struct pt_regs *regs, u32 trigger)
748779
* replay the instruction that trapped.
749780
*/
750781
fmxr(FPEXC, fpexc);
782+
vfp_state_release();
751783
} else {
752784
/* Check for synchronous or asynchronous exceptions */
753785
if (!(fpexc & (FPEXC_EX | FPEXC_DEX))) {
@@ -762,17 +794,17 @@ static int vfp_support_entry(struct pt_regs *regs, u32 trigger)
762794
if (!(fpscr & FPSCR_IXE)) {
763795
if (!(fpscr & FPSCR_LENGTH_MASK)) {
764796
pr_debug("not VFP\n");
765-
local_bh_enable();
797+
vfp_state_release();
766798
return -ENOEXEC;
767799
}
768800
fpexc |= FPEXC_DEX;
769801
}
770802
}
771803
bounce: regs->ARM_pc += 4;
804+
/* VFP_bounce() will invoke vfp_state_release() */
772805
VFP_bounce(trigger, fpexc, regs);
773806
}
774807

775-
local_bh_enable();
776808
return 0;
777809
}
778810

@@ -837,7 +869,7 @@ void kernel_neon_begin(void)
837869
unsigned int cpu;
838870
u32 fpexc;
839871

840-
local_bh_disable();
872+
vfp_state_hold();
841873

842874
/*
843875
* Kernel mode NEON is only allowed outside of hardirq context with
@@ -868,7 +900,7 @@ void kernel_neon_end(void)
868900
{
869901
/* Disable the NEON/VFP unit. */
870902
fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
871-
local_bh_enable();
903+
vfp_state_release();
872904
}
873905
EXPORT_SYMBOL(kernel_neon_end);
874906

drivers/amba/bus.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,12 @@ const struct bus_type amba_bustype = {
449449
};
450450
EXPORT_SYMBOL_GPL(amba_bustype);
451451

452+
bool dev_is_amba(const struct device *dev)
453+
{
454+
return dev->bus == &amba_bustype;
455+
}
456+
EXPORT_SYMBOL_GPL(dev_is_amba);
457+
452458
static int __init amba_init(void)
453459
{
454460
return bus_register(&amba_bustype);

include/linux/amba/bus.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ extern const struct bus_type amba_bustype;
121121
#ifdef CONFIG_ARM_AMBA
122122
int __amba_driver_register(struct amba_driver *, struct module *);
123123
void amba_driver_unregister(struct amba_driver *);
124+
bool dev_is_amba(const struct device *dev);
124125
#else
125126
static inline int __amba_driver_register(struct amba_driver *drv,
126127
struct module *owner)
@@ -130,6 +131,10 @@ static inline int __amba_driver_register(struct amba_driver *drv,
130131
static inline void amba_driver_unregister(struct amba_driver *drv)
131132
{
132133
}
134+
static inline bool dev_is_amba(const struct device *dev)
135+
{
136+
return false;
137+
}
133138
#endif
134139

135140
struct amba_device *amba_device_alloc(const char *, resource_size_t, size_t);

0 commit comments

Comments
 (0)