Merge branch 'x86-idle-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 idle updates from Ingo Molnar: "There were two bigger changes in this development cycle: - remove idle notifiers: 32 files changed, 74 insertions(+), 803 deletions(-) These notifiers were of questionable value and the main usecase, the i7300 driver, was essentially unmaintained and can be removed, plus modern power management concepts don't need the callback - so use this golden opportunity and get rid of this opaque and fragile callback from a latency sensitive code path. (Len Brown, Thomas Gleixner) - improve the AMD Erratum 400 workaround that used high overhead MSR polling in the idle loop (Borisla Petkov, Thomas Gleixner)" * 'x86-idle-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86: Remove empty idle.h header x86/amd: Simplify AMD E400 aware idle routine x86/amd: Check for the C1E bug post ACPI subsystem init x86/bugs: Separate AMD E400 erratum and C1E bug x86/cpufeature: Provide helper to set bugs bits x86/idle: Remove enter_idle(), exit_idle() x86: Remove x86_test_and_clear_bit_percpu() x86/idle: Remove is_idle flag x86/idle: Remove idle_notifier i7300_idle: Remove this driver
Este cometimento está contido em:
@@ -48,7 +48,6 @@
|
||||
#include <asm/io_apic.h>
|
||||
#include <asm/desc.h>
|
||||
#include <asm/hpet.h>
|
||||
#include <asm/idle.h>
|
||||
#include <asm/mtrr.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/smp.h>
|
||||
@@ -894,11 +893,13 @@ void __init setup_boot_APIC_clock(void)
|
||||
|
||||
/* Setup the lapic or request the broadcast */
|
||||
setup_APIC_timer();
|
||||
amd_e400_c1e_apic_setup();
|
||||
}
|
||||
|
||||
void setup_secondary_APIC_clock(void)
|
||||
{
|
||||
setup_APIC_timer();
|
||||
amd_e400_c1e_apic_setup();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -48,7 +48,6 @@
|
||||
#include <linux/bootmem.h>
|
||||
|
||||
#include <asm/irqdomain.h>
|
||||
#include <asm/idle.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/cpu.h>
|
||||
|
@@ -20,6 +20,10 @@
|
||||
|
||||
#include "cpu.h"
|
||||
|
||||
static const int amd_erratum_383[];
|
||||
static const int amd_erratum_400[];
|
||||
static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum);
|
||||
|
||||
/*
|
||||
* nodes_per_socket: Stores the number of nodes per socket.
|
||||
* Refer to Fam15h Models 00-0fh BKDG - CPUID Fn8000_001E_ECX
|
||||
@@ -592,11 +596,16 @@ static void early_init_amd(struct cpuinfo_x86 *c)
|
||||
/* F16h erratum 793, CVE-2013-6885 */
|
||||
if (c->x86 == 0x16 && c->x86_model <= 0xf)
|
||||
msr_set_bit(MSR_AMD64_LS_CFG, 15);
|
||||
}
|
||||
|
||||
static const int amd_erratum_383[];
|
||||
static const int amd_erratum_400[];
|
||||
static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum);
|
||||
/*
|
||||
* Check whether the machine is affected by erratum 400. This is
|
||||
* used to select the proper idle routine and to enable the check
|
||||
* whether the machine is affected in arch_post_acpi_init(), which
|
||||
* sets the X86_BUG_AMD_APIC_C1E bug depending on the MSR check.
|
||||
*/
|
||||
if (cpu_has_amd_erratum(c, amd_erratum_400))
|
||||
set_cpu_bug(c, X86_BUG_AMD_E400);
|
||||
}
|
||||
|
||||
static void init_amd_k8(struct cpuinfo_x86 *c)
|
||||
{
|
||||
@@ -777,9 +786,6 @@ static void init_amd(struct cpuinfo_x86 *c)
|
||||
if (c->x86 > 0x11)
|
||||
set_cpu_cap(c, X86_FEATURE_ARAT);
|
||||
|
||||
if (cpu_has_amd_erratum(c, amd_erratum_400))
|
||||
set_cpu_bug(c, X86_BUG_AMD_APIC_C1E);
|
||||
|
||||
rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);
|
||||
|
||||
/* 3DNow or LM implies PREFETCHW */
|
||||
|
@@ -1172,7 +1172,6 @@ void enable_sep_cpu(void)
|
||||
void __init identify_boot_cpu(void)
|
||||
{
|
||||
identify_cpu(&boot_cpu_data);
|
||||
init_amd_e400_c1e_mask();
|
||||
#ifdef CONFIG_X86_32
|
||||
sysenter_setup();
|
||||
enable_sep_cpu();
|
||||
|
@@ -24,7 +24,6 @@
|
||||
|
||||
#include <asm/amd_nb.h>
|
||||
#include <asm/apic.h>
|
||||
#include <asm/idle.h>
|
||||
#include <asm/mce.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/trace/irq_vectors.h>
|
||||
|
@@ -26,7 +26,6 @@
|
||||
|
||||
#include <asm/processor.h>
|
||||
#include <asm/apic.h>
|
||||
#include <asm/idle.h>
|
||||
#include <asm/mce.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/trace/irq_vectors.h>
|
||||
|
@@ -6,7 +6,6 @@
|
||||
|
||||
#include <asm/irq_vectors.h>
|
||||
#include <asm/apic.h>
|
||||
#include <asm/idle.h>
|
||||
#include <asm/mce.h>
|
||||
#include <asm/trace/irq_vectors.h>
|
||||
|
||||
|
@@ -25,7 +25,6 @@
|
||||
#include <asm/hyperv.h>
|
||||
#include <asm/mshyperv.h>
|
||||
#include <asm/desc.h>
|
||||
#include <asm/idle.h>
|
||||
#include <asm/irq_regs.h>
|
||||
#include <asm/i8259.h>
|
||||
#include <asm/apic.h>
|
||||
|
@@ -14,7 +14,6 @@
|
||||
#include <asm/apic.h>
|
||||
#include <asm/io_apic.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/idle.h>
|
||||
#include <asm/mce.h>
|
||||
#include <asm/hw_irq.h>
|
||||
#include <asm/desc.h>
|
||||
|
@@ -16,7 +16,6 @@
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/smp.h>
|
||||
#include <asm/io_apic.h>
|
||||
#include <asm/idle.h>
|
||||
#include <asm/apic.h>
|
||||
|
||||
int sysctl_panic_on_stackoverflow;
|
||||
|
@@ -42,7 +42,6 @@
|
||||
#include <asm/traps.h>
|
||||
#include <asm/desc.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/idle.h>
|
||||
#include <asm/apic.h>
|
||||
#include <asm/apicdef.h>
|
||||
#include <asm/hypervisor.h>
|
||||
@@ -267,13 +266,11 @@ do_async_page_fault(struct pt_regs *regs, unsigned long error_code)
|
||||
case KVM_PV_REASON_PAGE_NOT_PRESENT:
|
||||
/* page is swapped out by the host. */
|
||||
prev_state = exception_enter();
|
||||
exit_idle();
|
||||
kvm_async_pf_task_wait((u32)read_cr2());
|
||||
exception_exit(prev_state);
|
||||
break;
|
||||
case KVM_PV_REASON_PAGE_READY:
|
||||
rcu_irq_enter();
|
||||
exit_idle();
|
||||
kvm_async_pf_task_wake((u32)read_cr2());
|
||||
rcu_irq_exit();
|
||||
break;
|
||||
|
@@ -23,7 +23,6 @@
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/apic.h>
|
||||
#include <asm/syscalls.h>
|
||||
#include <asm/idle.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/mwait.h>
|
||||
#include <asm/fpu/internal.h>
|
||||
@@ -65,23 +64,6 @@ __visible DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, cpu_tss) = {
|
||||
};
|
||||
EXPORT_PER_CPU_SYMBOL(cpu_tss);
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
static DEFINE_PER_CPU(unsigned char, is_idle);
|
||||
static ATOMIC_NOTIFIER_HEAD(idle_notifier);
|
||||
|
||||
void idle_notifier_register(struct notifier_block *n)
|
||||
{
|
||||
atomic_notifier_chain_register(&idle_notifier, n);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(idle_notifier_register);
|
||||
|
||||
void idle_notifier_unregister(struct notifier_block *n)
|
||||
{
|
||||
atomic_notifier_chain_unregister(&idle_notifier, n);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(idle_notifier_unregister);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* this gets called so that we can store lazy state into memory and copy the
|
||||
* current task into the new thread.
|
||||
@@ -251,39 +233,9 @@ static inline void play_dead(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
void enter_idle(void)
|
||||
{
|
||||
this_cpu_write(is_idle, 1);
|
||||
atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL);
|
||||
}
|
||||
|
||||
static void __exit_idle(void)
|
||||
{
|
||||
if (x86_test_and_clear_bit_percpu(0, is_idle) == 0)
|
||||
return;
|
||||
atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL);
|
||||
}
|
||||
|
||||
/* Called from interrupts to signify idle end */
|
||||
void exit_idle(void)
|
||||
{
|
||||
/* idle loop has pid 0 */
|
||||
if (current->pid)
|
||||
return;
|
||||
__exit_idle();
|
||||
}
|
||||
#endif
|
||||
|
||||
void arch_cpu_idle_enter(void)
|
||||
{
|
||||
local_touch_nmi();
|
||||
enter_idle();
|
||||
}
|
||||
|
||||
void arch_cpu_idle_exit(void)
|
||||
{
|
||||
__exit_idle();
|
||||
}
|
||||
|
||||
void arch_cpu_idle_dead(void)
|
||||
@@ -336,59 +288,33 @@ void stop_this_cpu(void *dummy)
|
||||
halt();
|
||||
}
|
||||
|
||||
bool amd_e400_c1e_detected;
|
||||
EXPORT_SYMBOL(amd_e400_c1e_detected);
|
||||
|
||||
static cpumask_var_t amd_e400_c1e_mask;
|
||||
|
||||
void amd_e400_remove_cpu(int cpu)
|
||||
{
|
||||
if (amd_e400_c1e_mask != NULL)
|
||||
cpumask_clear_cpu(cpu, amd_e400_c1e_mask);
|
||||
}
|
||||
|
||||
/*
|
||||
* AMD Erratum 400 aware idle routine. We check for C1E active in the interrupt
|
||||
* pending message MSR. If we detect C1E, then we handle it the same
|
||||
* way as C3 power states (local apic timer and TSC stop)
|
||||
* AMD Erratum 400 aware idle routine. We handle it the same way as C3 power
|
||||
* states (local apic timer and TSC stop).
|
||||
*/
|
||||
static void amd_e400_idle(void)
|
||||
{
|
||||
if (!amd_e400_c1e_detected) {
|
||||
u32 lo, hi;
|
||||
|
||||
rdmsr(MSR_K8_INT_PENDING_MSG, lo, hi);
|
||||
|
||||
if (lo & K8_INTP_C1E_ACTIVE_MASK) {
|
||||
amd_e400_c1e_detected = true;
|
||||
if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
|
||||
mark_tsc_unstable("TSC halt in AMD C1E");
|
||||
pr_info("System has AMD C1E enabled\n");
|
||||
}
|
||||
/*
|
||||
* We cannot use static_cpu_has_bug() here because X86_BUG_AMD_APIC_C1E
|
||||
* gets set after static_cpu_has() places have been converted via
|
||||
* alternatives.
|
||||
*/
|
||||
if (!boot_cpu_has_bug(X86_BUG_AMD_APIC_C1E)) {
|
||||
default_idle();
|
||||
return;
|
||||
}
|
||||
|
||||
if (amd_e400_c1e_detected) {
|
||||
int cpu = smp_processor_id();
|
||||
tick_broadcast_enter();
|
||||
|
||||
if (!cpumask_test_cpu(cpu, amd_e400_c1e_mask)) {
|
||||
cpumask_set_cpu(cpu, amd_e400_c1e_mask);
|
||||
/* Force broadcast so ACPI can not interfere. */
|
||||
tick_broadcast_force();
|
||||
pr_info("Switch to broadcast mode on CPU%d\n", cpu);
|
||||
}
|
||||
tick_broadcast_enter();
|
||||
default_idle();
|
||||
|
||||
default_idle();
|
||||
|
||||
/*
|
||||
* The switch back from broadcast mode needs to be
|
||||
* called with interrupts disabled.
|
||||
*/
|
||||
local_irq_disable();
|
||||
tick_broadcast_exit();
|
||||
local_irq_enable();
|
||||
} else
|
||||
default_idle();
|
||||
/*
|
||||
* The switch back from broadcast mode needs to be called with
|
||||
* interrupts disabled.
|
||||
*/
|
||||
local_irq_disable();
|
||||
tick_broadcast_exit();
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -448,8 +374,7 @@ void select_idle_routine(const struct cpuinfo_x86 *c)
|
||||
if (x86_idle || boot_option_idle_override == IDLE_POLL)
|
||||
return;
|
||||
|
||||
if (cpu_has_bug(c, X86_BUG_AMD_APIC_C1E)) {
|
||||
/* E400: APIC timer interrupt does not wake up CPU from C1e */
|
||||
if (boot_cpu_has_bug(X86_BUG_AMD_E400)) {
|
||||
pr_info("using AMD E400 aware idle routine\n");
|
||||
x86_idle = amd_e400_idle;
|
||||
} else if (prefer_mwait_c1_over_halt(c)) {
|
||||
@@ -459,11 +384,37 @@ void select_idle_routine(const struct cpuinfo_x86 *c)
|
||||
x86_idle = default_idle;
|
||||
}
|
||||
|
||||
void __init init_amd_e400_c1e_mask(void)
|
||||
void amd_e400_c1e_apic_setup(void)
|
||||
{
|
||||
/* If we're using amd_e400_idle, we need to allocate amd_e400_c1e_mask. */
|
||||
if (x86_idle == amd_e400_idle)
|
||||
zalloc_cpumask_var(&amd_e400_c1e_mask, GFP_KERNEL);
|
||||
if (boot_cpu_has_bug(X86_BUG_AMD_APIC_C1E)) {
|
||||
pr_info("Switch to broadcast mode on CPU%d\n", smp_processor_id());
|
||||
local_irq_disable();
|
||||
tick_broadcast_force();
|
||||
local_irq_enable();
|
||||
}
|
||||
}
|
||||
|
||||
void __init arch_post_acpi_subsys_init(void)
|
||||
{
|
||||
u32 lo, hi;
|
||||
|
||||
if (!boot_cpu_has_bug(X86_BUG_AMD_E400))
|
||||
return;
|
||||
|
||||
/*
|
||||
* AMD E400 detection needs to happen after ACPI has been enabled. If
|
||||
* the machine is affected K8_INTP_C1E_ACTIVE_MASK bits are set in
|
||||
* MSR_K8_INT_PENDING_MSG.
|
||||
*/
|
||||
rdmsr(MSR_K8_INT_PENDING_MSG, lo, hi);
|
||||
if (!(lo & K8_INTP_C1E_ACTIVE_MASK))
|
||||
return;
|
||||
|
||||
boot_cpu_set_bug(X86_BUG_AMD_APIC_C1E);
|
||||
|
||||
if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
|
||||
mark_tsc_unstable("TSC halt in AMD C1E");
|
||||
pr_info("System has AMD C1E enabled\n");
|
||||
}
|
||||
|
||||
static int __init idle_setup(char *str)
|
||||
|
@@ -49,7 +49,6 @@
|
||||
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/idle.h>
|
||||
#include <asm/syscalls.h>
|
||||
#include <asm/debugreg.h>
|
||||
#include <asm/switch_to.h>
|
||||
|
@@ -44,7 +44,6 @@
|
||||
#include <asm/desc.h>
|
||||
#include <asm/proto.h>
|
||||
#include <asm/ia32.h>
|
||||
#include <asm/idle.h>
|
||||
#include <asm/syscalls.h>
|
||||
#include <asm/debugreg.h>
|
||||
#include <asm/switch_to.h>
|
||||
|
@@ -58,7 +58,6 @@
|
||||
#include <asm/desc.h>
|
||||
#include <asm/nmi.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/idle.h>
|
||||
#include <asm/realmode.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/numa.h>
|
||||
@@ -1596,7 +1595,6 @@ void play_dead_common(void)
|
||||
{
|
||||
idle_task_exit();
|
||||
reset_lazy_tlbstate();
|
||||
amd_e400_remove_cpu(raw_smp_processor_id());
|
||||
|
||||
/* Ack it */
|
||||
(void)cpu_report_death();
|
||||
|
Criar uma nova questão referindo esta
Bloquear um utilizador