asp net做网站视频,wordpress怎么注册,宁波seo培训,做高端生活方式的网站背景
开始把core调度器当成了linux的主调度器#xff0c;导致查找网上资料时总觉得对不上#xff0c;最后从linux的rust文档中明白了#xff0c;core调度器是为了解决超线程场景下缓存漏洞#xff08;如mds、L1HF#xff09;而存在的。简单来说就是一个cpu上同时运行两个…背景
开始把core调度器当成了linux的主调度器导致查找网上资料时总觉得对不上最后从linux的rust文档中明白了core调度器是为了解决超线程场景下缓存漏洞如mds、L1HF而存在的。简单来说就是一个cpu上同时运行两个线程时线程1预加载到缓存的数据可以被线程看到。
网上只找到了公开熔断Meltdown和幽灵Spectre漏洞的代码可以参考这个侧信道攻击实践 - 知乎没找到mds和L1HF的POC代码不太理解超线程的漏洞具体怎么实现只能找到非超线程的漏洞原理。
这两种非超线程的漏洞原理是这样都是刷掉所有缓存再通过分支预测和缺页异常访问预先加载出一个字节非法地址的数据将这个数据乘一个cacheline大小作为地址访问从而触发缓存把以这字节数据为index位置的缓存行load上来由于其它cache都刷掉了访问速度肯定没这个快。所以只要访问合法的(0~256)*cache_line地址数据统计触发每个cacheline访问时间中最快的那个index就能知道最初的数据cacheline的index是多少从而窃取一个字节的数据。
linux解决超线程缓存漏洞的方式是让同一个cpu的多个超线程在同一时间段内只能跑一个trust组中的多个task。
实现
在支持超线程时每个超线程存了一个smt_mask (cpu_sibling_map)标记与此超线程相同cpu的其它超线程编号每个超线程有个runqueues其中rq-core绑定了leader同一cpu的第一个编号位置的超线程的runqueue。
用户可以为几个线程指定相同的cookie值sched_core_share_pid从而将它们归为一个trust组同一时间同一个cpu的超线程上只能跑一个trust组的线程。
core调度器的runqueue是以cookie值为key的红黑树用于找相同cookie的task。
当同一trust组中task数比一个cpu的超线程数少时会有一部分超线程强制置为idle状态运行超线程数与idle超线程数分别用core_forceidle_occupation和core_forceidle_count表示force idle的超线程可以偷取其它同cpu的force idle超线程的同一trust组的tasksched_core_balance。
在一个调度周期内每个超线程都可能触发调度pick 下一个task但如果没有发生过新的enqueue或dequeue则不需要重新pick只需要第一个触发的人pick一次然后每个超线程用它pick的结果就可以了。这需要维护三个sequence来实现core-core_task_seq开始选task时的seqcore-core_pick_seq成功选出的task时的seqcore_sched_seq当前超线程的seq。当一次pick完成时所有其它超线程在pick时只需要core_sched_seq赶上leader的core_pick_seq即可不用重选有点像简化版本的Paxos协议但不是多者赢而是先者赢。
启动入口是 migration_init要看完整细节可以从这个地方开始看但与调度相关的函数最重要的是 pick_next_task另外有sched_core_balance让force idle超线程做任务偷取sched_core_tick做统计。
pick_next_task
代码为逻辑代码非真实代码。linux版本v6.6
pick_next_task():// 其它超线程已经pick过任务在这个超线程上还没调度过if (rq-core-core_pick_seq rq-core-core_task_seq rq-core-core_pick_seq ! rq-core_sched_seq rq-core_pick) {put_prev_task(rq, prev);set_next_task(rq, next);goto out}// 从上一个task的级别调度类到最低级别调度类分别调一次balance的hookput_prev_task_balance();// rq-core指向leader的queue, 开始选 taskrq-core-core_task_seq;// 从同cpu所有超线程选出最高优先级的taskfor_each_cpu_wrap(smt_mask) {rq_i-core_pick pick_task(rq_i);if (!max || prio_less(max, p, fi_before))max p;}// 以这个最高优先级task为准找出其它同cpu超线程上可以跑的同一trust组的task。for_each_cpu(i, smt_mask) {p sched_core_find(rq_i, cookie);if (p) {rq-core-core_forceidle_occupation;} else {p idle_sched_class.pick_task(rq_i);rq-core-core_forceidle_count;}}// 选task成功rq-core-core_pick_seq rq-core-core_task_seq;// 标记当前超线程在本轮已经选过了taskrq-core_sched_seq rq-core-core_pick_seq;// 为有cfs类任务的超线程更新vruntime与forceidle_seq// 并对需要切任务的超线程触发调度for_each_cpu(smt_mask) {task_vruntime_update(rq_i, rq_i-core_pick, !!rq-core-core_forceidle_count);resched_curr(rq_i);}// 如果有超线程被forceidle了则在调度时尝试偷一个同cpu其它超线程的同trust组任务执行// 下一个任务与上一个一样则在__schedule-__balance_callbacks处触发// 下一个任务与上一个不一样则在切之后finish_task_switch时触发queue_core_balance();