mirror of
https://github.com/ukui/kernel.git
synced 2026-03-09 10:07:04 -07:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
This commit is contained in:
@@ -363,6 +363,7 @@ out:
|
||||
putname(pname);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bpf_obj_get_user);
|
||||
|
||||
static void bpf_evict_inode(struct inode *inode)
|
||||
{
|
||||
|
||||
@@ -704,6 +704,10 @@ static void mark_reg_read(const struct bpf_verifier_state *state, u32 regno)
|
||||
{
|
||||
struct bpf_verifier_state *parent = state->parent;
|
||||
|
||||
if (regno == BPF_REG_FP)
|
||||
/* We don't need to worry about FP liveness because it's read-only */
|
||||
return;
|
||||
|
||||
while (parent) {
|
||||
/* if read wasn't screened by an earlier write ... */
|
||||
if (state->regs[regno].live & REG_LIVE_WRITTEN)
|
||||
@@ -2402,6 +2406,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
|
||||
* copy register state to dest reg
|
||||
*/
|
||||
regs[insn->dst_reg] = regs[insn->src_reg];
|
||||
regs[insn->dst_reg].live |= REG_LIVE_WRITTEN;
|
||||
} else {
|
||||
/* R1 = (u32) R2 */
|
||||
if (is_pointer_value(env, insn->src_reg)) {
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <linux/lockdep.h>
|
||||
#include <linux/tick.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/nmi.h>
|
||||
#include <linux/smpboot.h>
|
||||
#include <linux/relay.h>
|
||||
#include <linux/slab.h>
|
||||
@@ -897,6 +898,11 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen,
|
||||
|
||||
out:
|
||||
cpus_write_unlock();
|
||||
/*
|
||||
* Do post unplug cleanup. This is still protected against
|
||||
* concurrent CPU hotplug via cpu_add_remove_lock.
|
||||
*/
|
||||
lockup_detector_cleanup();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
+8
-17
@@ -344,39 +344,30 @@ EXPORT_SYMBOL_GPL(smpboot_unregister_percpu_thread);
|
||||
* by the client, but only by calling this function.
|
||||
* This function can only be called on a registered smp_hotplug_thread.
|
||||
*/
|
||||
int smpboot_update_cpumask_percpu_thread(struct smp_hotplug_thread *plug_thread,
|
||||
const struct cpumask *new)
|
||||
void smpboot_update_cpumask_percpu_thread(struct smp_hotplug_thread *plug_thread,
|
||||
const struct cpumask *new)
|
||||
{
|
||||
struct cpumask *old = plug_thread->cpumask;
|
||||
cpumask_var_t tmp;
|
||||
static struct cpumask tmp;
|
||||
unsigned int cpu;
|
||||
|
||||
if (!alloc_cpumask_var(&tmp, GFP_KERNEL))
|
||||
return -ENOMEM;
|
||||
|
||||
get_online_cpus();
|
||||
lockdep_assert_cpus_held();
|
||||
mutex_lock(&smpboot_threads_lock);
|
||||
|
||||
/* Park threads that were exclusively enabled on the old mask. */
|
||||
cpumask_andnot(tmp, old, new);
|
||||
for_each_cpu_and(cpu, tmp, cpu_online_mask)
|
||||
cpumask_andnot(&tmp, old, new);
|
||||
for_each_cpu_and(cpu, &tmp, cpu_online_mask)
|
||||
smpboot_park_thread(plug_thread, cpu);
|
||||
|
||||
/* Unpark threads that are exclusively enabled on the new mask. */
|
||||
cpumask_andnot(tmp, new, old);
|
||||
for_each_cpu_and(cpu, tmp, cpu_online_mask)
|
||||
cpumask_andnot(&tmp, new, old);
|
||||
for_each_cpu_and(cpu, &tmp, cpu_online_mask)
|
||||
smpboot_unpark_thread(plug_thread, cpu);
|
||||
|
||||
cpumask_copy(old, new);
|
||||
|
||||
mutex_unlock(&smpboot_threads_lock);
|
||||
put_online_cpus();
|
||||
|
||||
free_cpumask_var(tmp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(smpboot_update_cpumask_percpu_thread);
|
||||
|
||||
static DEFINE_PER_CPU(atomic_t, cpu_hotplug_state) = ATOMIC_INIT(CPU_POST_DEAD);
|
||||
|
||||
|
||||
+9
-13
@@ -872,9 +872,9 @@ static struct ctl_table kern_table[] = {
|
||||
#if defined(CONFIG_LOCKUP_DETECTOR)
|
||||
{
|
||||
.procname = "watchdog",
|
||||
.data = &watchdog_user_enabled,
|
||||
.maxlen = sizeof (int),
|
||||
.mode = 0644,
|
||||
.data = &watchdog_user_enabled,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_watchdog,
|
||||
.extra1 = &zero,
|
||||
.extra2 = &one,
|
||||
@@ -890,16 +890,12 @@ static struct ctl_table kern_table[] = {
|
||||
},
|
||||
{
|
||||
.procname = "nmi_watchdog",
|
||||
.data = &nmi_watchdog_enabled,
|
||||
.maxlen = sizeof (int),
|
||||
.mode = 0644,
|
||||
.data = &nmi_watchdog_user_enabled,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = NMI_WATCHDOG_SYSCTL_PERM,
|
||||
.proc_handler = proc_nmi_watchdog,
|
||||
.extra1 = &zero,
|
||||
#if defined(CONFIG_HAVE_NMI_WATCHDOG) || defined(CONFIG_HARDLOCKUP_DETECTOR)
|
||||
.extra2 = &one,
|
||||
#else
|
||||
.extra2 = &zero,
|
||||
#endif
|
||||
},
|
||||
{
|
||||
.procname = "watchdog_cpumask",
|
||||
@@ -911,9 +907,9 @@ static struct ctl_table kern_table[] = {
|
||||
#ifdef CONFIG_SOFTLOCKUP_DETECTOR
|
||||
{
|
||||
.procname = "soft_watchdog",
|
||||
.data = &soft_watchdog_enabled,
|
||||
.maxlen = sizeof (int),
|
||||
.mode = 0644,
|
||||
.data = &soft_watchdog_user_enabled,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_soft_watchdog,
|
||||
.extra1 = &zero,
|
||||
.extra2 = &one,
|
||||
|
||||
+250
-417
File diff suppressed because it is too large
Load Diff
+115
-89
@@ -21,8 +21,10 @@
|
||||
static DEFINE_PER_CPU(bool, hard_watchdog_warn);
|
||||
static DEFINE_PER_CPU(bool, watchdog_nmi_touch);
|
||||
static DEFINE_PER_CPU(struct perf_event *, watchdog_ev);
|
||||
static struct cpumask dead_events_mask;
|
||||
|
||||
static unsigned long hardlockup_allcpu_dumped;
|
||||
static unsigned int watchdog_cpus;
|
||||
|
||||
void arch_touch_nmi_watchdog(void)
|
||||
{
|
||||
@@ -103,15 +105,12 @@ static struct perf_event_attr wd_hw_attr = {
|
||||
|
||||
/* Callback function for perf event subsystem */
|
||||
static void watchdog_overflow_callback(struct perf_event *event,
|
||||
struct perf_sample_data *data,
|
||||
struct pt_regs *regs)
|
||||
struct perf_sample_data *data,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
/* Ensure the watchdog never gets throttled */
|
||||
event->hw.interrupts = 0;
|
||||
|
||||
if (atomic_read(&watchdog_park_in_progress) != 0)
|
||||
return;
|
||||
|
||||
if (__this_cpu_read(watchdog_nmi_touch) == true) {
|
||||
__this_cpu_write(watchdog_nmi_touch, false);
|
||||
return;
|
||||
@@ -160,104 +159,131 @@ static void watchdog_overflow_callback(struct perf_event *event,
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* People like the simple clean cpu node info on boot.
|
||||
* Reduce the watchdog noise by only printing messages
|
||||
* that are different from what cpu0 displayed.
|
||||
*/
|
||||
static unsigned long firstcpu_err;
|
||||
static atomic_t watchdog_cpus;
|
||||
|
||||
int watchdog_nmi_enable(unsigned int cpu)
|
||||
static int hardlockup_detector_event_create(void)
|
||||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
struct perf_event_attr *wd_attr;
|
||||
struct perf_event *event = per_cpu(watchdog_ev, cpu);
|
||||
int firstcpu = 0;
|
||||
|
||||
/* nothing to do if the hard lockup detector is disabled */
|
||||
if (!(watchdog_enabled & NMI_WATCHDOG_ENABLED))
|
||||
goto out;
|
||||
|
||||
/* is it already setup and enabled? */
|
||||
if (event && event->state > PERF_EVENT_STATE_OFF)
|
||||
goto out;
|
||||
|
||||
/* it is setup but not enabled */
|
||||
if (event != NULL)
|
||||
goto out_enable;
|
||||
|
||||
if (atomic_inc_return(&watchdog_cpus) == 1)
|
||||
firstcpu = 1;
|
||||
struct perf_event *evt;
|
||||
|
||||
wd_attr = &wd_hw_attr;
|
||||
wd_attr->sample_period = hw_nmi_get_sample_period(watchdog_thresh);
|
||||
|
||||
/* Try to register using hardware perf events */
|
||||
event = perf_event_create_kernel_counter(wd_attr, cpu, NULL, watchdog_overflow_callback, NULL);
|
||||
|
||||
/* save the first cpu's error for future comparision */
|
||||
if (firstcpu && IS_ERR(event))
|
||||
firstcpu_err = PTR_ERR(event);
|
||||
|
||||
if (!IS_ERR(event)) {
|
||||
/* only print for the first cpu initialized */
|
||||
if (firstcpu || firstcpu_err)
|
||||
pr_info("enabled on all CPUs, permanently consumes one hw-PMU counter.\n");
|
||||
goto out_save;
|
||||
evt = perf_event_create_kernel_counter(wd_attr, cpu, NULL,
|
||||
watchdog_overflow_callback, NULL);
|
||||
if (IS_ERR(evt)) {
|
||||
pr_info("Perf event create on CPU %d failed with %ld\n", cpu,
|
||||
PTR_ERR(evt));
|
||||
return PTR_ERR(evt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable the hard lockup detector if _any_ CPU fails to set up
|
||||
* set up the hardware perf event. The watchdog() function checks
|
||||
* the NMI_WATCHDOG_ENABLED bit periodically.
|
||||
*
|
||||
* The barriers are for syncing up watchdog_enabled across all the
|
||||
* cpus, as clear_bit() does not use barriers.
|
||||
*/
|
||||
smp_mb__before_atomic();
|
||||
clear_bit(NMI_WATCHDOG_ENABLED_BIT, &watchdog_enabled);
|
||||
smp_mb__after_atomic();
|
||||
|
||||
/* skip displaying the same error again */
|
||||
if (!firstcpu && (PTR_ERR(event) == firstcpu_err))
|
||||
return PTR_ERR(event);
|
||||
|
||||
/* vary the KERN level based on the returned errno */
|
||||
if (PTR_ERR(event) == -EOPNOTSUPP)
|
||||
pr_info("disabled (cpu%i): not supported (no LAPIC?)\n", cpu);
|
||||
else if (PTR_ERR(event) == -ENOENT)
|
||||
pr_warn("disabled (cpu%i): hardware events not enabled\n",
|
||||
cpu);
|
||||
else
|
||||
pr_err("disabled (cpu%i): unable to create perf event: %ld\n",
|
||||
cpu, PTR_ERR(event));
|
||||
|
||||
pr_info("Shutting down hard lockup detector on all cpus\n");
|
||||
|
||||
return PTR_ERR(event);
|
||||
|
||||
/* success path */
|
||||
out_save:
|
||||
per_cpu(watchdog_ev, cpu) = event;
|
||||
out_enable:
|
||||
perf_event_enable(per_cpu(watchdog_ev, cpu));
|
||||
out:
|
||||
this_cpu_write(watchdog_ev, evt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void watchdog_nmi_disable(unsigned int cpu)
|
||||
/**
|
||||
* hardlockup_detector_perf_enable - Enable the local event
|
||||
*/
|
||||
void hardlockup_detector_perf_enable(void)
|
||||
{
|
||||
struct perf_event *event = per_cpu(watchdog_ev, cpu);
|
||||
if (hardlockup_detector_event_create())
|
||||
return;
|
||||
|
||||
if (!watchdog_cpus++)
|
||||
pr_info("Enabled. Permanently consumes one hw-PMU counter.\n");
|
||||
|
||||
perf_event_enable(this_cpu_read(watchdog_ev));
|
||||
}
|
||||
|
||||
/**
|
||||
* hardlockup_detector_perf_disable - Disable the local event
|
||||
*/
|
||||
void hardlockup_detector_perf_disable(void)
|
||||
{
|
||||
struct perf_event *event = this_cpu_read(watchdog_ev);
|
||||
|
||||
if (event) {
|
||||
perf_event_disable(event);
|
||||
per_cpu(watchdog_ev, cpu) = NULL;
|
||||
|
||||
/* should be in cleanup, but blocks oprofile */
|
||||
perf_event_release_kernel(event);
|
||||
|
||||
/* watchdog_nmi_enable() expects this to be zero initially. */
|
||||
if (atomic_dec_and_test(&watchdog_cpus))
|
||||
firstcpu_err = 0;
|
||||
cpumask_set_cpu(smp_processor_id(), &dead_events_mask);
|
||||
watchdog_cpus--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* hardlockup_detector_perf_cleanup - Cleanup disabled events and destroy them
|
||||
*
|
||||
* Called from lockup_detector_cleanup(). Serialized by the caller.
|
||||
*/
|
||||
void hardlockup_detector_perf_cleanup(void)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
for_each_cpu(cpu, &dead_events_mask) {
|
||||
struct perf_event *event = per_cpu(watchdog_ev, cpu);
|
||||
|
||||
/*
|
||||
* Required because for_each_cpu() reports unconditionally
|
||||
* CPU0 as set on UP kernels. Sigh.
|
||||
*/
|
||||
if (event)
|
||||
perf_event_release_kernel(event);
|
||||
per_cpu(watchdog_ev, cpu) = NULL;
|
||||
}
|
||||
cpumask_clear(&dead_events_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* hardlockup_detector_perf_stop - Globally stop watchdog events
|
||||
*
|
||||
* Special interface for x86 to handle the perf HT bug.
|
||||
*/
|
||||
void __init hardlockup_detector_perf_stop(void)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
lockdep_assert_cpus_held();
|
||||
|
||||
for_each_online_cpu(cpu) {
|
||||
struct perf_event *event = per_cpu(watchdog_ev, cpu);
|
||||
|
||||
if (event)
|
||||
perf_event_disable(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* hardlockup_detector_perf_restart - Globally restart watchdog events
|
||||
*
|
||||
* Special interface for x86 to handle the perf HT bug.
|
||||
*/
|
||||
void __init hardlockup_detector_perf_restart(void)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
lockdep_assert_cpus_held();
|
||||
|
||||
if (!(watchdog_enabled & NMI_WATCHDOG_ENABLED))
|
||||
return;
|
||||
|
||||
for_each_online_cpu(cpu) {
|
||||
struct perf_event *event = per_cpu(watchdog_ev, cpu);
|
||||
|
||||
if (event)
|
||||
perf_event_enable(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* hardlockup_detector_perf_init - Probe whether NMI event is available at all
|
||||
*/
|
||||
int __init hardlockup_detector_perf_init(void)
|
||||
{
|
||||
int ret = hardlockup_detector_event_create();
|
||||
|
||||
if (ret) {
|
||||
pr_info("Perf NMI watchdog permanently disabled\n");
|
||||
} else {
|
||||
perf_event_release_kernel(this_cpu_read(watchdog_ev));
|
||||
this_cpu_write(watchdog_ev, NULL);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user