[知其然不知其所以然-30] How to work around when system can not be woken up
来源:互联网 发布:vb打开资源管理器 编辑:程序博客网 时间:2024/05/16 00:45
So previously we found problems that, the platform react very slow to user input, either
from terminal or from remote. One of my colleagues has found that, it is because this platform
can not be woken up from mwait, more precisely,
Monitored cached line may not wake up from mwait on certainGoldmont based CPUs. This patch will avoid calling current_set_polling_and_test() and thereby not set the TIF_ flag. The result is that we'll always send IPIs for wakeups.
So the comment above is very short, but contains quite a lot of informations.
Let's see the patch:
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.hindex 4a41348..a5ba0ff 100644--- a/arch/x86/include/asm/cpufeatures.h+++ b/arch/x86/include/asm/cpufeatures.h@@ -303,6 +303,7 @@ #define X86_BUG_SYSRET_SS_ATTRS X86_BUG(8) /* SYSRET doesn't fix up SS attrs */ #define X86_BUG_NULL_SEG X86_BUG(9) /* Nulling a selector preserves the base */ #define X86_BUG_SWAPGS_FENCE X86_BUG(10) /* SWAPGS without input dep on GS */+#define X86_BUG_MONITOR X86_BUG(11) /* IPI required to wake up remote cpu */ #ifdef CONFIG_X86_32diff --git a/arch/x86/include/asm/mwait.h b/arch/x86/include/asm/mwait.hindex 0deeb2d..f37f2d8 100644--- a/arch/x86/include/asm/mwait.h+++ b/arch/x86/include/asm/mwait.h@@ -97,7 +97,7 @@ static inline void __sti_mwait(unsigned long eax, unsigned long ecx) */ static inline void mwait_idle_with_hints(unsigned long eax, unsigned long ecx) {- if (!current_set_polling_and_test()) {+ if (static_cpu_has_bug(X86_BUG_MONITOR) || !current_set_polling_and_test()) { if (static_cpu_has_bug(X86_BUG_CLFLUSH_MONITOR)) { mb(); clflush((void *)¤t_thread_info()->flags);diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.cindex 6e2ffbe..a79e8af 100644--- a/arch/x86/kernel/cpu/intel.c+++ b/arch/x86/kernel/cpu/intel.c@@ -509,6 +509,11 @@ static void init_intel(struct cpuinfo_x86 *c) (c->x86_model == 29 || c->x86_model == 46 || c->x86_model == 47)) set_cpu_bug(c, X86_BUG_CLFLUSH_MONITOR); + if (c->x86 == 6 && boot_cpu_has(X86_FEATURE_MWAIT) &&+ ((c->x86_model == 0x5f) || (c->x86_model == 0x5c))) {+ set_cpu_bug(c, X86_BUG_MONITOR);+ pr_warn("BIOS update needed to avoid MONITOR BUG!!, INTERNAL WORKAROUND!!");+ }
there are mainly two methods to wake up a idle task on one cpu,
suppose we have CPU1 running, and CPU2 in idle, task A is migrated
from CPU1 to CPU2, and we need to wake CPU2 up:
1. if CPU2 is at mwait(idle.flag), then CPU1 set the idle.flag with TIF_POLLING_NRFLAG,
thus CPU2 wakes up from mwait, and switch to task A
2. if CPU2 is not in mwait, thus CPU1 has to send a resched ipi to CPU2, thus CPU2 been woken
up by ipi, and then switch to task A at ret_irq:
void wake_up_if_idle(int cpu){ struct rq *rq = cpu_rq(cpu); unsigned long flags; rcu_read_lock(); if (!is_idle_task(rcu_dereference(rq->curr))) goto out; if (set_nr_if_polling(rq->idle)) { trace_sched_wake_idle_without_ipi(cpu); } else { raw_spin_lock_irqsave(&rq->lock, flags); if (is_idle_task(rq->curr)) smp_send_reschedule(cpu); /* Else cpu is not in idle, do nothing here */ raw_spin_unlock_irqrestore(&rq->lock, flags); }out: rcu_read_unlock();}
static void ttwu_queue_remote(struct task_struct *p, int cpu, int wake_flags){ struct rq *rq = cpu_rq(cpu); p->sched_remote_wakeup = !!(wake_flags & WF_MIGRATED); if (llist_add(&p->wake_entry, &cpu_rq(cpu)->wake_list)) { if (!set_nr_if_polling(rq->idle)) smp_send_reschedule(cpu); else trace_sched_wake_idle_without_ipi(cpu); }}
#define TIF_POLLING_NRFLAG 21 /* idle is polling for TIF_NEED_RESCHED */
So for our case, we want the cpu to be in mwait, but we also want the CPU1 to send ipi to wake ip CPU2,
thus we do not set polling mode for CPU2, although it is in mwait, thus CPU1 will find out CPU2 has no
polling mode set, thus to send ipi to wake CPU2 up.
So the problem above is solved very smartly.
- [知其然不知其所以然-30] How to work around when system can not be woken up
- how to solve sourceinsight can not work
- [知其然不知其所以然-33] How to set up mutt
- how to solve ”The MathType DLL can not be found“
- How to work around Android’s 24 MB memory limit
- How to be effective at work?
- your system does not seem to be set up to build kernel modules
- When to work as root & When to Work as a System User
- How can I work around hidesBottomBarWhenPushed acting weird with the iOS 6 SDK?
- android adb driver can not work on WINDOW XP, it take me 1 hour to fix it up
- how-to: resolve crontab does not work
- How to make UITextField move up when keyboard is present
- TextView can not be cast to ViewGroup
- [知其然不知其所以然-25] How to setup systemtap
- How NOT To Evaluate Your Dialogue System
- How to set up Tomcat 6 to work with JSTL 1.2
- how to solve the problem when you have chmod the directory to 777 but the apache still can not write file
- How to work
- ibatis如何返回存储过程中的输出参数
- 开放平台-web实现QQ第三方登录
- MySQL delete/truncate/drop的差别分析
- Java 集合类详解(含类图)
- JS预解析,作用域
- [知其然不知其所以然-30] How to work around when system can not be woken up
- Android 4.4 NotificationManagerService使用详解与原理分析(二)__原理分析
- java回调机制
- java类和对象的思想以及常见类使用实例
- 跑马灯动画点击事件
- MATLAB mex时 出现错误“error LNK2019 无法链接的外部符号”
- HashMap和Hashtable及HashSet的区别
- 计算机网络系统互连模型
- unity的材质竟然可以写shader