mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 14:53:58 -04:00
Merge tag 'mips_4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux
Pull MIPS updates from Paul Burton:
"Here are the main MIPS changes for 4.19.
An overview of the general architecture changes:
- Massive DMA ops refactoring from Christoph Hellwig (huzzah for
deleting crufty code!).
- We introduce NT_MIPS_DSP & NT_MIPS_FP_MODE ELF notes &
corresponding regsets to expose DSP ASE & floating point mode state
respectively, both for live debugging & core dumps.
- We better optimize our code by hard-coding cpu_has_* macros at
compile time where their values are known due to the ISA revision
that the kernel build is targeting.
- The EJTAG exception handler now better handles SMP systems, where
it was previously possible for CPUs to clobber a register value
saved by another CPU.
- Our implementation of memset() gained a couple of fixes for MIPSr6
systems to return correct values in some cases where stores fault.
- We now implement ioremap_wc() using the uncached-accelerated cache
coherency attribute where supported, which is detected during boot,
and fall back to plain uncached access where necessary. The
MIPS-specific (and unused in tree) ioremap_uncached_accelerated() &
ioremap_cacheable_cow() are removed.
- The prctl(PR_SET_FP_MODE, ...) syscall is better supported for SMP
systems by reworking the way we ensure remote CPUs that may be
running threads within the affected process switch mode.
- Systems using the MIPS Coherence Manager will now set the
MIPS_IC_SNOOPS_REMOTE flag to avoid some unnecessary cache
maintenance overhead when flushing the icache.
- A few fixes were made for building with clang/LLVM, which now
sucessfully builds kernels for many of our platforms.
- Miscellaneous cleanups all over.
And some platform-specific changes:
- ar7 gained stubs for a few clock API functions to fix build
failures for some drivers.
- ath79 gained support for a few new SoCs, a few fixes & better
gpio-keys support.
- Ci20 now exposes its SPI bus using the spi-gpio driver.
- The generic platform can now auto-detect a suitable value for
PHYS_OFFSET based upon the memory map described by the device tree,
allowing us to avoid wasting memory on page book-keeping for
systems where RAM starts at a non-zero physical address.
- Ingenic systems using the jz4740 platform code now link their
vmlinuz higher to allow for kernels of a realistic size.
- Loongson32 now builds the kernel targeting MIPSr1 rather than
MIPSr2 to avoid CPU errata.
- Loongson64 gains a couple of fixes, a workaround for a write
buffering issue & support for the Loongson 3A R3.1 CPU.
- Malta now uses the piix4-poweroff driver to handle powering down.
- Microsemi Ocelot gained support for its SPI bus & NOR flash, its
second MDIO bus and can now be supported by a FIT/.itb image.
- Octeon saw a bunch of header cleanups which remove a lot of
duplicate or unused code"
* tag 'mips_4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux: (123 commits)
MIPS: Remove remnants of UASM_ISA
MIPS: netlogic: xlr: Remove erroneous check in nlm_fmn_send()
MIPS: VDSO: Force link endianness
MIPS: Always specify -EB or -EL when using clang
MIPS: Use dins to simplify __write_64bit_c0_split()
MIPS: Use read-write output operand in __write_64bit_c0_split()
MIPS: Avoid using array as parameter to write_c0_kpgd()
MIPS: vdso: Allow clang's --target flag in VDSO cflags
MIPS: genvdso: Remove GOT checks
MIPS: Remove obsolete MIPS checks for DST node "chosen@0"
MIPS: generic: Remove input symbols from defconfig
MIPS: Delete unused code in linux32.c
MIPS: Remove unused sys_32_mmap2
MIPS: Remove nabi_no_regargs
mips: dts: mscc: enable spi and NOR flash support on ocelot PCB123
mips: dts: mscc: Add spi on Ocelot
MIPS: Loongson: Merge load addresses
MIPS: Loongson: Set Loongson32 to MIPS32R1
MIPS: mscc: ocelot: add interrupt controller properties to GPIO controller
MIPS: generic: Select MIPS_AUTO_PFN_OFFSET
...
This commit is contained in:
@@ -30,6 +30,7 @@
|
||||
#include <linux/random.h>
|
||||
#include <linux/prctl.h>
|
||||
#include <linux/nmi.h>
|
||||
#include <linux/cpu.h>
|
||||
|
||||
#include <asm/asm.h>
|
||||
#include <asm/bootinfo.h>
|
||||
@@ -706,19 +707,25 @@ int mips_get_process_fp_mode(struct task_struct *task)
|
||||
return value;
|
||||
}
|
||||
|
||||
static void prepare_for_fp_mode_switch(void *info)
|
||||
static long prepare_for_fp_mode_switch(void *unused)
|
||||
{
|
||||
struct mm_struct *mm = info;
|
||||
|
||||
if (current->mm == mm)
|
||||
lose_fpu(1);
|
||||
/*
|
||||
* This is icky, but we use this to simply ensure that all CPUs have
|
||||
* context switched, regardless of whether they were previously running
|
||||
* kernel or user code. This ensures that no CPU currently has its FPU
|
||||
* enabled, or is about to attempt to enable it through any path other
|
||||
* than enable_restore_fp_context() which will wait appropriately for
|
||||
* fp_mode_switching to be zero.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mips_set_process_fp_mode(struct task_struct *task, unsigned int value)
|
||||
{
|
||||
const unsigned int known_bits = PR_FP_MODE_FR | PR_FP_MODE_FRE;
|
||||
struct task_struct *t;
|
||||
int max_users;
|
||||
struct cpumask process_cpus;
|
||||
int cpu;
|
||||
|
||||
/* If nothing to change, return right away, successfully. */
|
||||
if (value == mips_get_process_fp_mode(task))
|
||||
@@ -751,35 +758,7 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value)
|
||||
if (!(value & PR_FP_MODE_FR) && raw_cpu_has_fpu && cpu_has_mips_r6)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Proceed with the mode switch */
|
||||
preempt_disable();
|
||||
|
||||
/* Save FP & vector context, then disable FPU & MSA */
|
||||
if (task->signal == current->signal)
|
||||
lose_fpu(1);
|
||||
|
||||
/* Prevent any threads from obtaining live FP context */
|
||||
atomic_set(&task->mm->context.fp_mode_switching, 1);
|
||||
smp_mb__after_atomic();
|
||||
|
||||
/*
|
||||
* If there are multiple online CPUs then force any which are running
|
||||
* threads in this process to lose their FPU context, which they can't
|
||||
* regain until fp_mode_switching is cleared later.
|
||||
*/
|
||||
if (num_online_cpus() > 1) {
|
||||
/* No need to send an IPI for the local CPU */
|
||||
max_users = (task->mm == current->mm) ? 1 : 0;
|
||||
|
||||
if (atomic_read(¤t->mm->mm_users) > max_users)
|
||||
smp_call_function(prepare_for_fp_mode_switch,
|
||||
(void *)current->mm, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* There are now no threads of the process with live FP context, so it
|
||||
* is safe to proceed with the FP mode switch.
|
||||
*/
|
||||
/* Indicate the new FP mode in each thread */
|
||||
for_each_thread(task, t) {
|
||||
/* Update desired FP register width */
|
||||
if (value & PR_FP_MODE_FR) {
|
||||
@@ -796,9 +775,34 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value)
|
||||
clear_tsk_thread_flag(t, TIF_HYBRID_FPREGS);
|
||||
}
|
||||
|
||||
/* Allow threads to use FP again */
|
||||
atomic_set(&task->mm->context.fp_mode_switching, 0);
|
||||
preempt_enable();
|
||||
/*
|
||||
* We need to ensure that all threads in the process have switched mode
|
||||
* before returning, in order to allow userland to not worry about
|
||||
* races. We can do this by forcing all CPUs that any thread in the
|
||||
* process may be running on to schedule something else - in this case
|
||||
* prepare_for_fp_mode_switch().
|
||||
*
|
||||
* We begin by generating a mask of all CPUs that any thread in the
|
||||
* process may be running on.
|
||||
*/
|
||||
cpumask_clear(&process_cpus);
|
||||
for_each_thread(task, t)
|
||||
cpumask_set_cpu(task_cpu(t), &process_cpus);
|
||||
|
||||
/*
|
||||
* Now we schedule prepare_for_fp_mode_switch() on each of those CPUs.
|
||||
*
|
||||
* The CPUs may have rescheduled already since we switched mode or
|
||||
* generated the cpumask, but that doesn't matter. If the task in this
|
||||
* process is scheduled out then our scheduling
|
||||
* prepare_for_fp_mode_switch() will simply be redundant. If it's
|
||||
* scheduled in then it will already have picked up the new FP mode
|
||||
* whilst doing so.
|
||||
*/
|
||||
get_online_cpus();
|
||||
for_each_cpu_and(cpu, &process_cpus, cpu_online_mask)
|
||||
work_on_cpu(cpu, prepare_for_fp_mode_switch, NULL);
|
||||
put_online_cpus();
|
||||
|
||||
wake_up_var(&task->mm->context.fp_mode_switching);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user