mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-01 10:42:11 +00:00
Merge branches 'fixes' and 'misc' into for-next
This commit is contained in:
commit
6139f79136
@ -25,6 +25,7 @@
|
|||||||
#include <asm/tls.h>
|
#include <asm/tls.h>
|
||||||
#include <asm/system_info.h>
|
#include <asm/system_info.h>
|
||||||
#include <asm/uaccess-asm.h>
|
#include <asm/uaccess-asm.h>
|
||||||
|
#include <asm/kasan_def.h>
|
||||||
|
|
||||||
#include "entry-header.S"
|
#include "entry-header.S"
|
||||||
#include <asm/probes.h>
|
#include <asm/probes.h>
|
||||||
@ -561,6 +562,13 @@ ENTRY(__switch_to)
|
|||||||
@ entries covering the vmalloc region.
|
@ entries covering the vmalloc region.
|
||||||
@
|
@
|
||||||
ldr r2, [ip]
|
ldr r2, [ip]
|
||||||
|
#ifdef CONFIG_KASAN_VMALLOC
|
||||||
|
@ Also dummy read from the KASAN shadow memory for the new stack if we
|
||||||
|
@ are using KASAN
|
||||||
|
mov_l r2, KASAN_SHADOW_OFFSET
|
||||||
|
add r2, r2, ip, lsr #KASAN_SHADOW_SCALE_SHIFT
|
||||||
|
ldr r2, [r2]
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ When CONFIG_THREAD_INFO_IN_TASK=n, the update of SP itself is what
|
@ When CONFIG_THREAD_INFO_IN_TASK=n, the update of SP itself is what
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
|
#include <linux/kasan.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/vmalloc.h>
|
#include <linux/vmalloc.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
@ -115,16 +116,40 @@ int ioremap_page(unsigned long virt, unsigned long phys,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ioremap_page);
|
EXPORT_SYMBOL(ioremap_page);
|
||||||
|
|
||||||
|
#ifdef CONFIG_KASAN
|
||||||
|
static unsigned long arm_kasan_mem_to_shadow(unsigned long addr)
|
||||||
|
{
|
||||||
|
return (unsigned long)kasan_mem_to_shadow((void *)addr);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static unsigned long arm_kasan_mem_to_shadow(unsigned long addr)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void memcpy_pgd(struct mm_struct *mm, unsigned long start,
|
||||||
|
unsigned long end)
|
||||||
|
{
|
||||||
|
end = ALIGN(end, PGDIR_SIZE);
|
||||||
|
memcpy(pgd_offset(mm, start), pgd_offset_k(start),
|
||||||
|
sizeof(pgd_t) * (pgd_index(end) - pgd_index(start)));
|
||||||
|
}
|
||||||
|
|
||||||
void __check_vmalloc_seq(struct mm_struct *mm)
|
void __check_vmalloc_seq(struct mm_struct *mm)
|
||||||
{
|
{
|
||||||
int seq;
|
int seq;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
seq = atomic_read(&init_mm.context.vmalloc_seq);
|
seq = atomic_read_acquire(&init_mm.context.vmalloc_seq);
|
||||||
memcpy(pgd_offset(mm, VMALLOC_START),
|
memcpy_pgd(mm, VMALLOC_START, VMALLOC_END);
|
||||||
pgd_offset_k(VMALLOC_START),
|
if (IS_ENABLED(CONFIG_KASAN_VMALLOC)) {
|
||||||
sizeof(pgd_t) * (pgd_index(VMALLOC_END) -
|
unsigned long start =
|
||||||
pgd_index(VMALLOC_START)));
|
arm_kasan_mem_to_shadow(VMALLOC_START);
|
||||||
|
unsigned long end =
|
||||||
|
arm_kasan_mem_to_shadow(VMALLOC_END);
|
||||||
|
memcpy_pgd(mm, start, end);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Use a store-release so that other CPUs that observe the
|
* Use a store-release so that other CPUs that observe the
|
||||||
* counter's new value are guaranteed to see the results of the
|
* counter's new value are guaranteed to see the results of the
|
||||||
|
@ -55,6 +55,34 @@ extern unsigned int VFP_arch_feroceon __alias(VFP_arch);
|
|||||||
*/
|
*/
|
||||||
union vfp_state *vfp_current_hw_state[NR_CPUS];
|
union vfp_state *vfp_current_hw_state[NR_CPUS];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Claim ownership of the VFP unit.
|
||||||
|
*
|
||||||
|
* The caller may change VFP registers until vfp_state_release() is called.
|
||||||
|
*
|
||||||
|
* local_bh_disable() is used to disable preemption and to disable VFP
|
||||||
|
* processing in softirq context. On PREEMPT_RT kernels local_bh_disable() is
|
||||||
|
* not sufficient because it only serializes soft interrupt related sections
|
||||||
|
* via a local lock, but stays preemptible. Disabling preemption is the right
|
||||||
|
* choice here as bottom half processing is always in thread context on RT
|
||||||
|
* kernels so it implicitly prevents bottom half processing as well.
|
||||||
|
*/
|
||||||
|
static void vfp_state_hold(void)
|
||||||
|
{
|
||||||
|
if (!IS_ENABLED(CONFIG_PREEMPT_RT))
|
||||||
|
local_bh_disable();
|
||||||
|
else
|
||||||
|
preempt_disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vfp_state_release(void)
|
||||||
|
{
|
||||||
|
if (!IS_ENABLED(CONFIG_PREEMPT_RT))
|
||||||
|
local_bh_enable();
|
||||||
|
else
|
||||||
|
preempt_enable();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Is 'thread's most up to date state stored in this CPUs hardware?
|
* Is 'thread's most up to date state stored in this CPUs hardware?
|
||||||
* Must be called from non-preemptible context.
|
* Must be called from non-preemptible context.
|
||||||
@ -240,7 +268,7 @@ static void vfp_panic(char *reason, u32 inst)
|
|||||||
/*
|
/*
|
||||||
* Process bitmask of exception conditions.
|
* Process bitmask of exception conditions.
|
||||||
*/
|
*/
|
||||||
static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_regs *regs)
|
static int vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr)
|
||||||
{
|
{
|
||||||
int si_code = 0;
|
int si_code = 0;
|
||||||
|
|
||||||
@ -248,8 +276,7 @@ static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_
|
|||||||
|
|
||||||
if (exceptions == VFP_EXCEPTION_ERROR) {
|
if (exceptions == VFP_EXCEPTION_ERROR) {
|
||||||
vfp_panic("unhandled bounce", inst);
|
vfp_panic("unhandled bounce", inst);
|
||||||
vfp_raise_sigfpe(FPE_FLTINV, regs);
|
return FPE_FLTINV;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -277,8 +304,7 @@ static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_
|
|||||||
RAISE(FPSCR_OFC, FPSCR_OFE, FPE_FLTOVF);
|
RAISE(FPSCR_OFC, FPSCR_OFE, FPE_FLTOVF);
|
||||||
RAISE(FPSCR_IOC, FPSCR_IOE, FPE_FLTINV);
|
RAISE(FPSCR_IOC, FPSCR_IOE, FPE_FLTINV);
|
||||||
|
|
||||||
if (si_code)
|
return si_code;
|
||||||
vfp_raise_sigfpe(si_code, regs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -324,6 +350,8 @@ static u32 vfp_emulate_instruction(u32 inst, u32 fpscr, struct pt_regs *regs)
|
|||||||
static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
|
static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
u32 fpscr, orig_fpscr, fpsid, exceptions;
|
u32 fpscr, orig_fpscr, fpsid, exceptions;
|
||||||
|
int si_code2 = 0;
|
||||||
|
int si_code = 0;
|
||||||
|
|
||||||
pr_debug("VFP: bounce: trigger %08x fpexc %08x\n", trigger, fpexc);
|
pr_debug("VFP: bounce: trigger %08x fpexc %08x\n", trigger, fpexc);
|
||||||
|
|
||||||
@ -369,8 +397,8 @@ static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
|
|||||||
* unallocated VFP instruction but with FPSCR.IXE set and not
|
* unallocated VFP instruction but with FPSCR.IXE set and not
|
||||||
* on VFP subarch 1.
|
* on VFP subarch 1.
|
||||||
*/
|
*/
|
||||||
vfp_raise_exceptions(VFP_EXCEPTION_ERROR, trigger, fpscr, regs);
|
si_code = vfp_raise_exceptions(VFP_EXCEPTION_ERROR, trigger, fpscr);
|
||||||
return;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -394,14 +422,14 @@ static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
|
|||||||
*/
|
*/
|
||||||
exceptions = vfp_emulate_instruction(trigger, fpscr, regs);
|
exceptions = vfp_emulate_instruction(trigger, fpscr, regs);
|
||||||
if (exceptions)
|
if (exceptions)
|
||||||
vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs);
|
si_code2 = vfp_raise_exceptions(exceptions, trigger, orig_fpscr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If there isn't a second FP instruction, exit now. Note that
|
* If there isn't a second FP instruction, exit now. Note that
|
||||||
* the FPEXC.FP2V bit is valid only if FPEXC.EX is 1.
|
* the FPEXC.FP2V bit is valid only if FPEXC.EX is 1.
|
||||||
*/
|
*/
|
||||||
if ((fpexc & (FPEXC_EX | FPEXC_FP2V)) != (FPEXC_EX | FPEXC_FP2V))
|
if ((fpexc & (FPEXC_EX | FPEXC_FP2V)) != (FPEXC_EX | FPEXC_FP2V))
|
||||||
return;
|
goto exit;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The barrier() here prevents fpinst2 being read
|
* The barrier() here prevents fpinst2 being read
|
||||||
@ -413,7 +441,13 @@ static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
|
|||||||
emulate:
|
emulate:
|
||||||
exceptions = vfp_emulate_instruction(trigger, orig_fpscr, regs);
|
exceptions = vfp_emulate_instruction(trigger, orig_fpscr, regs);
|
||||||
if (exceptions)
|
if (exceptions)
|
||||||
vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs);
|
si_code = vfp_raise_exceptions(exceptions, trigger, orig_fpscr);
|
||||||
|
exit:
|
||||||
|
vfp_state_release();
|
||||||
|
if (si_code2)
|
||||||
|
vfp_raise_sigfpe(si_code2, regs);
|
||||||
|
if (si_code)
|
||||||
|
vfp_raise_sigfpe(si_code, regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vfp_enable(void *unused)
|
static void vfp_enable(void *unused)
|
||||||
@ -512,11 +546,9 @@ static inline void vfp_pm_init(void) { }
|
|||||||
*/
|
*/
|
||||||
void vfp_sync_hwstate(struct thread_info *thread)
|
void vfp_sync_hwstate(struct thread_info *thread)
|
||||||
{
|
{
|
||||||
unsigned int cpu = get_cpu();
|
vfp_state_hold();
|
||||||
|
|
||||||
local_bh_disable();
|
if (vfp_state_in_hw(raw_smp_processor_id(), thread)) {
|
||||||
|
|
||||||
if (vfp_state_in_hw(cpu, thread)) {
|
|
||||||
u32 fpexc = fmrx(FPEXC);
|
u32 fpexc = fmrx(FPEXC);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -527,8 +559,7 @@ void vfp_sync_hwstate(struct thread_info *thread)
|
|||||||
fmxr(FPEXC, fpexc);
|
fmxr(FPEXC, fpexc);
|
||||||
}
|
}
|
||||||
|
|
||||||
local_bh_enable();
|
vfp_state_release();
|
||||||
put_cpu();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure that the thread reloads the hardware VFP state on the next use. */
|
/* 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)
|
|||||||
if (!user_mode(regs))
|
if (!user_mode(regs))
|
||||||
return vfp_kmode_exception(regs, trigger);
|
return vfp_kmode_exception(regs, trigger);
|
||||||
|
|
||||||
local_bh_disable();
|
vfp_state_hold();
|
||||||
fpexc = fmrx(FPEXC);
|
fpexc = fmrx(FPEXC);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -748,6 +779,7 @@ static int vfp_support_entry(struct pt_regs *regs, u32 trigger)
|
|||||||
* replay the instruction that trapped.
|
* replay the instruction that trapped.
|
||||||
*/
|
*/
|
||||||
fmxr(FPEXC, fpexc);
|
fmxr(FPEXC, fpexc);
|
||||||
|
vfp_state_release();
|
||||||
} else {
|
} else {
|
||||||
/* Check for synchronous or asynchronous exceptions */
|
/* Check for synchronous or asynchronous exceptions */
|
||||||
if (!(fpexc & (FPEXC_EX | FPEXC_DEX))) {
|
if (!(fpexc & (FPEXC_EX | FPEXC_DEX))) {
|
||||||
@ -762,17 +794,17 @@ static int vfp_support_entry(struct pt_regs *regs, u32 trigger)
|
|||||||
if (!(fpscr & FPSCR_IXE)) {
|
if (!(fpscr & FPSCR_IXE)) {
|
||||||
if (!(fpscr & FPSCR_LENGTH_MASK)) {
|
if (!(fpscr & FPSCR_LENGTH_MASK)) {
|
||||||
pr_debug("not VFP\n");
|
pr_debug("not VFP\n");
|
||||||
local_bh_enable();
|
vfp_state_release();
|
||||||
return -ENOEXEC;
|
return -ENOEXEC;
|
||||||
}
|
}
|
||||||
fpexc |= FPEXC_DEX;
|
fpexc |= FPEXC_DEX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bounce: regs->ARM_pc += 4;
|
bounce: regs->ARM_pc += 4;
|
||||||
|
/* VFP_bounce() will invoke vfp_state_release() */
|
||||||
VFP_bounce(trigger, fpexc, regs);
|
VFP_bounce(trigger, fpexc, regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
local_bh_enable();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -837,7 +869,7 @@ void kernel_neon_begin(void)
|
|||||||
unsigned int cpu;
|
unsigned int cpu;
|
||||||
u32 fpexc;
|
u32 fpexc;
|
||||||
|
|
||||||
local_bh_disable();
|
vfp_state_hold();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Kernel mode NEON is only allowed outside of hardirq context with
|
* Kernel mode NEON is only allowed outside of hardirq context with
|
||||||
@ -868,7 +900,7 @@ void kernel_neon_end(void)
|
|||||||
{
|
{
|
||||||
/* Disable the NEON/VFP unit. */
|
/* Disable the NEON/VFP unit. */
|
||||||
fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
|
fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
|
||||||
local_bh_enable();
|
vfp_state_release();
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(kernel_neon_end);
|
EXPORT_SYMBOL(kernel_neon_end);
|
||||||
|
|
||||||
|
@ -449,6 +449,12 @@ const struct bus_type amba_bustype = {
|
|||||||
};
|
};
|
||||||
EXPORT_SYMBOL_GPL(amba_bustype);
|
EXPORT_SYMBOL_GPL(amba_bustype);
|
||||||
|
|
||||||
|
bool dev_is_amba(const struct device *dev)
|
||||||
|
{
|
||||||
|
return dev->bus == &amba_bustype;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(dev_is_amba);
|
||||||
|
|
||||||
static int __init amba_init(void)
|
static int __init amba_init(void)
|
||||||
{
|
{
|
||||||
return bus_register(&amba_bustype);
|
return bus_register(&amba_bustype);
|
||||||
|
@ -121,6 +121,7 @@ extern const struct bus_type amba_bustype;
|
|||||||
#ifdef CONFIG_ARM_AMBA
|
#ifdef CONFIG_ARM_AMBA
|
||||||
int __amba_driver_register(struct amba_driver *, struct module *);
|
int __amba_driver_register(struct amba_driver *, struct module *);
|
||||||
void amba_driver_unregister(struct amba_driver *);
|
void amba_driver_unregister(struct amba_driver *);
|
||||||
|
bool dev_is_amba(const struct device *dev);
|
||||||
#else
|
#else
|
||||||
static inline int __amba_driver_register(struct amba_driver *drv,
|
static inline int __amba_driver_register(struct amba_driver *drv,
|
||||||
struct module *owner)
|
struct module *owner)
|
||||||
@ -130,6 +131,10 @@ static inline int __amba_driver_register(struct amba_driver *drv,
|
|||||||
static inline void amba_driver_unregister(struct amba_driver *drv)
|
static inline void amba_driver_unregister(struct amba_driver *drv)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
static inline bool dev_is_amba(const struct device *dev)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct amba_device *amba_device_alloc(const char *, resource_size_t, size_t);
|
struct amba_device *amba_device_alloc(const char *, resource_size_t, size_t);
|
||||||
|
Loading…
Reference in New Issue
Block a user