-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.xml
567 lines (527 loc) · 119 KB
/
index.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Tbus – Tbus</title>
<link>/</link>
<description>Recent content on Tbus</description>
<generator>Hugo -- gohugo.io</generator>
<atom:link href="/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>Blog: Hugo构建</title>
<link>/blog/2022/07/20/hugo%E6%9E%84%E5%BB%BA/</link>
<pubDate>Wed, 20 Jul 2022 00:00:00 +0000</pubDate>
<guid>/blog/2022/07/20/hugo%E6%9E%84%E5%BB%BA/</guid>
<description>
<h2 id="clone-博客仓库">Clone 博客仓库</h2>
<blockquote>
<p>将博客clone到本地
尽量使用ssh地址
并再github上配置好公钥</p>
</blockquote>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>git clone [email protected]:TbusOS/blog.git
</span></span></code></pre></div><h2 id="增加一个md文档">增加一个md文档</h2>
<blockquote>
<p>在目录 content\zh\blog\build-environment 下按照已经有的文档写一篇文档</p>
<p><strong>目前博客类的文章都放在这个目录</strong></p>
<p>如果需要不同分类也可以按照blog这个目录下的文档复制一份进行修改</p>
<p>文章的Header按照已有的文章格式写下以下字段</p>
</blockquote>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#204a87;font-weight:bold">linkTitle</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#4e9a06">&#34;&#34;</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#8f5902;font-style:italic"># 链接地址</span><span style="color:#f8f8f8;text-decoration:underline">
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">author</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#4e9a06">&#34;Liulf&#34;</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#8f5902;font-style:italic"># 作者</span><span style="color:#f8f8f8;text-decoration:underline">
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">categories</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">[</span><span style="color:#4e9a06">&#34;docs&#34;</span><span style="color:#000;font-weight:bold">]</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#8f5902;font-style:italic"># 分类</span><span style="color:#f8f8f8;text-decoration:underline">
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">tags</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">[</span><span style="color:#4e9a06">&#34;blog&#34;</span><span style="color:#000;font-weight:bold">,</span><span style="color:#4e9a06">&#34;markdown&#34;</span><span style="color:#000;font-weight:bold">,</span><span style="color:#4e9a06">&#34;typora&#34;</span><span style="color:#000;font-weight:bold">]</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#8f5902;font-style:italic"># tags 分类</span><span style="color:#f8f8f8;text-decoration:underline">
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">title</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#4e9a06">&#34;Hugo构建&#34;</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#8f5902;font-style:italic"># 标题</span><span style="color:#f8f8f8;text-decoration:underline">
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">date</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">2022-07-20</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#8f5902;font-style:italic"># 创建日期</span><span style="color:#f8f8f8;text-decoration:underline">
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">weight</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#0000cf;font-weight:bold">3</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#8f5902;font-style:italic"># (这个是文章的顺序)</span><span style="color:#f8f8f8;text-decoration:underline">
</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">description</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#8f5902;font-style:italic"># 文章描述</span><span style="color:#f8f8f8;text-decoration:underline">
</span></span></span></code></pre></div><p>写完文章后提交到仓库即可</p>
<h2 id="提交文档">提交文档</h2>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>git add .
</span></span><span style="display:flex;"><span>git pus
</span></span></code></pre></div><ul>
<li>提交到github后会博客会自动构建大概需要50秒稍微等待一下</li>
<li>访问<a href="https://tbusos.github.io/">Tbus (tbusos.github.io)</a>刷新一下查看是否更新成功</li>
<li>如果没有更新请联系Liulf</li>
</ul>
<hr>
<p>至此完成一个完整的博客提交流程</p>
</description>
</item>
<item>
<title>Blog: typora PicGo</title>
<link>/blog/2022/07/20/typora-picgo/</link>
<pubDate>Wed, 20 Jul 2022 00:00:00 +0000</pubDate>
<guid>/blog/2022/07/20/typora-picgo/</guid>
<description>
<h2 id="1-typora-设置">1. Typora 设置</h2>
<p>设置完成后点击下载PicGo下载PicGo</p>
<p><img src="https://raw.githubusercontent.com/gitliulf/picture/main/1658280424709.png" alt="1658280424709"></p>
<h2 id="2-picgo设置">2. PicGo设置</h2>
<ul>
<li>安装github-plus插件</li>
</ul>
<p><img src="https://raw.githubusercontent.com/TbusOS/TbusBlogDoc/master/blog/pictures.assets/1658283204030.png" alt="1658283204030"></p>
<ul>
<li>去github创建一个Token用于上传图片使用,这一步一定要记下token最好存在</li>
</ul>
<p><img src="https://raw.githubusercontent.com/TbusOS/TbusBlogDoc/master/blog/pictures.assets/1658283319167.png" alt="1658283319167"></p>
<ul>
<li>创建Token至少选择以下权限</li>
</ul>
<p><img src="https://raw.githubusercontent.com/TbusOS/TbusBlogDoc/master/blog/pictures.assets/1658283463904.png" alt=""></p>
<ul>
<li>然后再回到PicGo进行一下设置一下</li>
<li>设置完以后可以在上传区上传一个图片测试</li>
</ul>
<p><img src="https://raw.githubusercontent.com/TbusOS/TbusBlogDoc/master/blog/pictures.assets/1658283059013.png" alt=""></p>
<h2 id="在typora中添加图片将自动上传到github">在Typora中添加图片将自动上传到github</h2>
<p><img src="https://raw.githubusercontent.com/TbusOS/TbusBlogDoc/master/blog/pictures.assets/1658283928561.png" alt="1658283928561"></p>
</description>
</item>
<item>
<title>Blog: 关于Tbus</title>
<link>/blog/2022/07/20/%E5%85%B3%E4%BA%8Etbus/</link>
<pubDate>Wed, 20 Jul 2022 00:00:00 +0000</pubDate>
<guid>/blog/2022/07/20/%E5%85%B3%E4%BA%8Etbus/</guid>
<description>
<p><img src="https://mmbiz.qpic.cn/mmbiz_jpg/gBMHA1sBRwljzLrHicWkpD3YCFBdnIiaduKLqpO7vXP1NXdic0GyFrfvFJ20VovaaZOmhkuH02QKdMdq5hJWvntkw/640?wx_fmt=jpeg&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p>
<p>TBUS是什么车?这是去哪里的车?我要怎么样才可以上这辆车?</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/gBMHA1sBRwljzLrHicWkpD3YCFBdnIiadus8iaDXhZOO9Fic3b5kLb7Biaicw4IykGAo7GkCsucNllqtia6OE6GAX2zSQ/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p>
<p>我们TBUS团队</p>
<p>我们是一个专注于技术学习与分享的团体,目前团队的正式成员涵盖国内顶尖IT技术人员</p>
<p>在这里我们边学习技术边做一些有趣的项目(小游戏,火车售票系统,聊天系统等),这些项目在Linux这个平台上实现。</p>
<p>这不是外包,也不是什么孵化器项目,完全是我们自己的意愿去做,我们想要成立的是一个团队,不是部门也不是其他,最主要是能够有一个学习的氛围,希望能够吸引更多人来这里面学习。</p>
<p>团队名称“TBUS”的构思源自我们团队成员 寓意如下:</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_jpg/gBMHA1sBRwmT4bSymyKaN3VhZ0SlmfbMCn4XNJYk5zZCaZMwdlBHdVY78xhjuEWy6MOdEB5Tqu8dUenXBuYnzg/640?wx_fmt=jpeg&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片">Technology(技术)</p>
<hr>
<p><img src="https://mmbiz.qpic.cn/mmbiz_jpg/gBMHA1sBRwmT4bSymyKaN3VhZ0SlmfbM3g8mKI3Gdqib24rH2IMRekTWBF0keeybchPllBzEWvERgbu2lH5pgCg/640?wx_fmt=jpeg&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片">我们团队的创始人</p>
<hr>
<p><img src="https://mmbiz.qpic.cn/mmbiz_jpg/gBMHA1sBRwmT4bSymyKaN3VhZ0SlmfbMlYrROHqzibvPicHr26AiaQCTcp3icWfibjTPLCdwfmFQ2vrdGMNiboLB4WDQ/640?wx_fmt=jpeg&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片">Unite(团结)</p>
<hr>
<p><img src="https://mmbiz.qpic.cn/mmbiz_jpg/gBMHA1sBRwmT4bSymyKaN3VhZ0SlmfbM5b1yZWyjEqsglzfueVmficL1m7piaIDN30trAiaQIMfUrOrKVXD0lc7Jg/640?wx_fmt=jpeg&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片">Share(分享)我们团队是以分享交流知识的形式成长的</p>
<hr>
<p> 此名字是上述团队关键字英文字母的拼接,又可以理解成为一辆学习技术(Technology)的巴士(Bus),走走停停,欢迎志同道合的人上车,结伴同行,一起学习技术,中途也会有一部分人由于种种原因下车。</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_gif/gBMHA1sBRwljzLrHicWkpD3YCFBdnIiadu5SNx2WbQp5JHgUac0kN4Kh0mDApFx7XhkQ1aMdKrMykIiarNphicTnpQ/640?wx_fmt=gif&amp;wxfrom=5&amp;wx_lazy=1" alt="图片"></p>
</description>
</item>
<item>
<title>Blog: cpu多核锁指令-WFE原理</title>
<link>/blog/2022/07/19/cpu%E5%A4%9A%E6%A0%B8%E9%94%81%E6%8C%87%E4%BB%A4-wfe%E5%8E%9F%E7%90%86/</link>
<pubDate>Tue, 19 Jul 2022 00:00:00 +0000</pubDate>
<guid>/blog/2022/07/19/cpu%E5%A4%9A%E6%A0%B8%E9%94%81%E6%8C%87%E4%BB%A4-wfe%E5%8E%9F%E7%90%86/</guid>
<description>
<p>本文最先发表于泰晓科技:</p>
<p>[https://tinylab.org/arm-wfe/]:</p>
<p><a href="https://tinylab.org/arm-wfe/#author-footer">Zhang Binghua</a> 创作于 2020/05/19</p>
<p>[TOC]</p>
<h2 id="1-背景简介">1 背景简介</h2>
<p>大家好,我叫张昺华,中间那个字和“饼”字一个读音,本人非常热衷技术,是个技术狂热者。</p>
<p>今天我想分享一个跟多核锁原理相关的东西,由于我搞 arm 居多,所以目前只研究了 arm 架构下的 WFE 指令,分享出来,如果有表述不精准或者错误的地方还请大家指出,非常感谢。研究这个原因也是只是想搞清楚所以然和来龙去脉,以后写代码可以更游刃有余。</p>
<h2 id="2-我与-wfe-的初次见面">2 我与 WFE 的初次见面</h2>
<p>偶然看 <code>spin_lock</code> 的 arm 架构下的 smp 源码的时候,发现了 <code>wfe()</code> 这个接口:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#204a87;font-weight:bold">static</span> <span style="color:#204a87;font-weight:bold">inline</span> <span style="color:#204a87;font-weight:bold">void</span> <span style="color:#000">arch_spin_lock</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">arch_spinlock_t</span> <span style="color:#ce5c00;font-weight:bold">*</span><span style="color:#000">lock</span><span style="color:#000;font-weight:bold">)</span>
</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">{</span>
</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">unsigned</span> <span style="color:#204a87;font-weight:bold">long</span> <span style="color:#000">tmp</span><span style="color:#000;font-weight:bold">;</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">u32</span> <span style="color:#000">newval</span><span style="color:#000;font-weight:bold">;</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">arch_spinlock_t</span> <span style="color:#000">lockval</span><span style="color:#000;font-weight:bold">;</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">prefetchw</span><span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">lock</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">slock</span><span style="color:#000;font-weight:bold">);</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">__asm__</span> <span style="color:#000">__volatile__</span><span style="color:#000;font-weight:bold">(</span>
</span></span><span style="display:flex;"><span><span style="color:#4e9a06">&#34;1: ldrex %0, [%3]</span><span style="color:#4e9a06">\n</span><span style="color:#4e9a06">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#4e9a06">&#34; add %1, %0, %4</span><span style="color:#4e9a06">\n</span><span style="color:#4e9a06">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#4e9a06">&#34; strex %2, %1, [%3]</span><span style="color:#4e9a06">\n</span><span style="color:#4e9a06">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#4e9a06">&#34; teq %2, #0</span><span style="color:#4e9a06">\n</span><span style="color:#4e9a06">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#4e9a06">&#34; bne 1b&#34;</span>
</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">:</span> <span style="color:#4e9a06">&#34;=&amp;r&#34;</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#000">lockval</span><span style="color:#000;font-weight:bold">),</span> <span style="color:#4e9a06">&#34;=&amp;r&#34;</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#000">newval</span><span style="color:#000;font-weight:bold">),</span> <span style="color:#4e9a06">&#34;=&amp;r&#34;</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#000">tmp</span><span style="color:#000;font-weight:bold">)</span>
</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">:</span> <span style="color:#4e9a06">&#34;r&#34;</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">lock</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">slock</span><span style="color:#000;font-weight:bold">),</span> <span style="color:#4e9a06">&#34;I&#34;</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#0000cf;font-weight:bold">1</span> <span style="color:#ce5c00;font-weight:bold">&lt;&lt;</span> <span style="color:#000">TICKET_SHIFT</span><span style="color:#000;font-weight:bold">)</span>
</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">:</span> <span style="color:#4e9a06">&#34;cc&#34;</span><span style="color:#000;font-weight:bold">);</span>
</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">while</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#000">lockval</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">tickets</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">next</span> <span style="color:#ce5c00;font-weight:bold">!=</span> <span style="color:#000">lockval</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">tickets</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">owner</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">wfe</span><span style="color:#000;font-weight:bold">();</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">lockval</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">tickets</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">owner</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">READ_ONCE</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">lock</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">tickets</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">owner</span><span style="color:#000;font-weight:bold">);</span>
</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">smp_mb</span><span style="color:#000;font-weight:bold">();</span>
</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">}</span>
</span></span></code></pre></div><p>我印象之前的 kernel 是没有这个 wfe 这个函数的,当 cpu0 获取到锁后,如果 cpu1 再想获取锁,此时会被 lock 住,然后进入死等的状态,那么 wfe 这个指令的作用是会让 cpu 进入 low power standby,这样可以降低功耗,本来发生竞态时其他的 cpu 都要等待这个锁释放才能运行,有了这个指令,相当于是“因祸得福”了,还可以降低功耗,当然这是有条件的,后面追溯并研究了一下 wfe 这个指令的作用。</p>
<h2 id="3-spinlock-与-wfesevwfi">3 spinlock 与 WFE、SEV、WFI</h2>
<p>首先 <code>spin_lock</code> 函数,搞内核的大家都知道,那么我把 linux-stable 的代码黏贴出来如下:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#204a87;font-weight:bold">static</span> <span style="color:#000">__always_inline</span> <span style="color:#204a87;font-weight:bold">void</span> <span style="color:#000">spin_lock</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">spinlock_t</span> <span style="color:#ce5c00;font-weight:bold">*</span><span style="color:#000">lock</span><span style="color:#000;font-weight:bold">)</span>
</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">{</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">raw_spin_lock</span><span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">lock</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">rlock</span><span style="color:#000;font-weight:bold">);</span>
</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">}</span>
</span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">#define raw_spin_lock(lock) _raw_spin_lock(lock)
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">#ifndef CONFIG_INLINE_SPIN_LOCK
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"></span><span style="color:#204a87;font-weight:bold">void</span> <span style="color:#000">__lockfunc</span> <span style="color:#000">_raw_spin_lock</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">raw_spinlock_t</span> <span style="color:#ce5c00;font-weight:bold">*</span><span style="color:#000">lock</span><span style="color:#000;font-weight:bold">)</span>
</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">{</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">__raw_spin_lock</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">lock</span><span style="color:#000;font-weight:bold">);</span>
</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">}</span>
</span></span><span style="display:flex;"><span><span style="color:#000">EXPORT_SYMBOL</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">_raw_spin_lock</span><span style="color:#000;font-weight:bold">);</span>
</span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">#endif
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"></span><span style="color:#204a87;font-weight:bold">static</span> <span style="color:#204a87;font-weight:bold">inline</span> <span style="color:#204a87;font-weight:bold">void</span> <span style="color:#000">__raw_spin_lock</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">raw_spinlock_t</span> <span style="color:#ce5c00;font-weight:bold">*</span><span style="color:#000">lock</span><span style="color:#000;font-weight:bold">)</span>
</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">{</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">preempt_disable</span><span style="color:#000;font-weight:bold">();</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">spin_acquire</span><span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">lock</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">dep_map</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">_RET_IP_</span><span style="color:#000;font-weight:bold">);</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">LOCK_CONTENDED</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">lock</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">do_raw_spin_trylock</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">do_raw_spin_lock</span><span style="color:#000;font-weight:bold">);</span>
</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">}</span>
</span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">/*
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">* We are now relying on the NMI watchdog to detect lockup instead of doing
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">* the detection here with an unfair lock which can cause problem of its own.
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#204a87;font-weight:bold">void</span> <span style="color:#000">do_raw_spin_lock</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">raw_spinlock_t</span> <span style="color:#ce5c00;font-weight:bold">*</span><span style="color:#000">lock</span><span style="color:#000;font-weight:bold">)</span>
</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">{</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">debug_spin_lock_before</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">lock</span><span style="color:#000;font-weight:bold">);</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">arch_spin_lock</span><span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">lock</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">raw_lock</span><span style="color:#000;font-weight:bold">);</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">mmiowb_spin_lock</span><span style="color:#000;font-weight:bold">();</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">debug_spin_lock_after</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">lock</span><span style="color:#000;font-weight:bold">);</span>
</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">}</span>
</span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">/*
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">* ARMv6 ticket-based spin-locking.
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">*
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">* A memory barrier is required after we get a lock, and before we
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">* release it, because V6 CPUs are assumed to have weakly ordered
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">* memory.
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#204a87;font-weight:bold">static</span> <span style="color:#204a87;font-weight:bold">inline</span> <span style="color:#204a87;font-weight:bold">void</span> <span style="color:#000">arch_spin_lock</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">arch_spinlock_t</span> <span style="color:#ce5c00;font-weight:bold">*</span><span style="color:#000">lock</span><span style="color:#000;font-weight:bold">)</span>
</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">{</span>
</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">unsigned</span> <span style="color:#204a87;font-weight:bold">long</span> <span style="color:#000">tmp</span><span style="color:#000;font-weight:bold">;</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">u32</span> <span style="color:#000">newval</span><span style="color:#000;font-weight:bold">;</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">arch_spinlock_t</span> <span style="color:#000">lockval</span><span style="color:#000;font-weight:bold">;</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">prefetchw</span><span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">lock</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">slock</span><span style="color:#000;font-weight:bold">);</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">__asm__</span> <span style="color:#000">__volatile__</span><span style="color:#000;font-weight:bold">(</span>
</span></span><span style="display:flex;"><span><span style="color:#4e9a06">&#34;1: ldrex %0, [%3]</span><span style="color:#4e9a06">\n</span><span style="color:#4e9a06">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#4e9a06">&#34; add %1, %0, %4</span><span style="color:#4e9a06">\n</span><span style="color:#4e9a06">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#4e9a06">&#34; strex %2, %1, [%3]</span><span style="color:#4e9a06">\n</span><span style="color:#4e9a06">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#4e9a06">&#34; teq %2, #0</span><span style="color:#4e9a06">\n</span><span style="color:#4e9a06">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#4e9a06">&#34; bne 1b&#34;</span>
</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">:</span> <span style="color:#4e9a06">&#34;=&amp;r&#34;</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#000">lockval</span><span style="color:#000;font-weight:bold">),</span> <span style="color:#4e9a06">&#34;=&amp;r&#34;</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#000">newval</span><span style="color:#000;font-weight:bold">),</span> <span style="color:#4e9a06">&#34;=&amp;r&#34;</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#000">tmp</span><span style="color:#000;font-weight:bold">)</span>
</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">:</span> <span style="color:#4e9a06">&#34;r&#34;</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">lock</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">slock</span><span style="color:#000;font-weight:bold">),</span> <span style="color:#4e9a06">&#34;I&#34;</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#0000cf;font-weight:bold">1</span> <span style="color:#ce5c00;font-weight:bold">&lt;&lt;</span> <span style="color:#000">TICKET_SHIFT</span><span style="color:#000;font-weight:bold">)</span>
</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">:</span> <span style="color:#4e9a06">&#34;cc&#34;</span><span style="color:#000;font-weight:bold">);</span>
</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">while</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#000">lockval</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">tickets</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">next</span> <span style="color:#ce5c00;font-weight:bold">!=</span> <span style="color:#000">lockval</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">tickets</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">owner</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">wfe</span><span style="color:#000;font-weight:bold">();</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">lockval</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">tickets</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">owner</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">READ_ONCE</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">lock</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">tickets</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">owner</span><span style="color:#000;font-weight:bold">);</span>
</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">smp_mb</span><span style="color:#000;font-weight:bold">();</span>
</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">}</span>
</span></span></code></pre></div><p>对于 arm32:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">#if __LINUX_ARM_ARCH__ &gt;= 7 || \
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> (__LINUX_ARM_ARCH__ == 6 &amp;&amp; defined(CONFIG_CPU_32v6K))
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">#define sev() __asm__ __volatile__ (&#34;sev&#34; : : : &#34;memory&#34;)
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">#define wfe() __asm__ __volatile__ (&#34;wfe&#34; : : : &#34;memory&#34;)
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">#define wfi() __asm__ __volatile__ (&#34;wfi&#34; : : : &#34;memory&#34;)
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">#else
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">#define wfe() do { } while (0)
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">#endif
</span></span></span></code></pre></div><p>对于 arm64:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">#define sev() asm volatile(&#34;sev&#34; : : : &#34;memory&#34;)
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">#define wfe() asm volatile(&#34;wfe&#34; : : : &#34;memory&#34;)
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">#define wfi() asm volatile(&#34;wfi&#34; : : : &#34;memory&#34;)
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"></span><span style="color:#204a87;font-weight:bold">static</span> <span style="color:#204a87;font-weight:bold">inline</span> <span style="color:#204a87;font-weight:bold">void</span> <span style="color:#000">arch_spin_unlock</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">arch_spinlock_t</span> <span style="color:#ce5c00;font-weight:bold">*</span><span style="color:#000">lock</span><span style="color:#000;font-weight:bold">)</span>
</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">{</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">smp_mb</span><span style="color:#000;font-weight:bold">();</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">lock</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">tickets</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">owner</span><span style="color:#ce5c00;font-weight:bold">++</span><span style="color:#000;font-weight:bold">;</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">dsb_sev</span><span style="color:#000;font-weight:bold">();</span>
</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">}</span>
</span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">#define SEV __ALT_SMP_ASM(WASM(sev), WASM(nop))
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"></span><span style="color:#204a87;font-weight:bold">static</span> <span style="color:#204a87;font-weight:bold">inline</span> <span style="color:#204a87;font-weight:bold">void</span> <span style="color:#000">dsb_sev</span><span style="color:#000;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">void</span><span style="color:#000;font-weight:bold">)</span>
</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">{</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">dsb</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">ishst</span><span style="color:#000;font-weight:bold">);</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">__asm__</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">SEV</span><span style="color:#000;font-weight:bold">);</span>
</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">}</span>
</span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">#ifdef CONFIG_SMP
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">#define __ALT_SMP_ASM(smp, up) \
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> &#34;9998: &#34; smp &#34;\n&#34; \
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> &#34; .pushsection \&#34;.alt.smp.init\&#34;, \&#34;a\&#34;\n&#34; \
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> &#34; .long 9998b\n&#34; \
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> &#34; &#34; up &#34;\n&#34; \
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> &#34; .popsection\n&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">#else
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">#define __ALT_SMP_ASM(smp, up) up
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">#endif
</span></span></span></code></pre></div><p>以上我们可以看出,在 lock 的时候使用 WFE,在 unlock 的时候使用 SEV,这个必须要成对使用,原因我下面会说。</p>
<p>对于内核版本 Linux 3.0.56:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#204a87;font-weight:bold">static</span> <span style="color:#204a87;font-weight:bold">inline</span> <span style="color:#204a87;font-weight:bold">void</span> <span style="color:#000">arch_spin_lock</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">arch_spinlock_t</span> <span style="color:#ce5c00;font-weight:bold">*</span><span style="color:#000">lock</span><span style="color:#000;font-weight:bold">)</span>
</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">{</span>
</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">unsigned</span> <span style="color:#204a87;font-weight:bold">long</span> <span style="color:#000">tmp</span><span style="color:#000;font-weight:bold">;</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">__asm__</span> <span style="color:#000">__volatile__</span><span style="color:#000;font-weight:bold">(</span>
</span></span><span style="display:flex;"><span><span style="color:#4e9a06">&#34;1: ldrex %0, [%1]</span><span style="color:#4e9a06">\n</span><span style="color:#4e9a06">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#4e9a06">&#34; teq %0, #0</span><span style="color:#4e9a06">\n</span><span style="color:#4e9a06">&#34;</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">WFE</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;ne&#34;</span><span style="color:#000;font-weight:bold">)</span>
</span></span><span style="display:flex;"><span><span style="color:#4e9a06">&#34; strexeq %0, %2, [%1]</span><span style="color:#4e9a06">\n</span><span style="color:#4e9a06">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#4e9a06">&#34; teqeq %0, #0</span><span style="color:#4e9a06">\n</span><span style="color:#4e9a06">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#4e9a06">&#34; bne 1b&#34;</span>
</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">:</span> <span style="color:#4e9a06">&#34;=&amp;r&#34;</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#000">tmp</span><span style="color:#000;font-weight:bold">)</span>
</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">:</span> <span style="color:#4e9a06">&#34;r&#34;</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">lock</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">lock</span><span style="color:#000;font-weight:bold">),</span> <span style="color:#4e9a06">&#34;r&#34;</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">)</span>
</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">:</span> <span style="color:#4e9a06">&#34;cc&#34;</span><span style="color:#000;font-weight:bold">);</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">smp_mb</span><span style="color:#000;font-weight:bold">();</span>
</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">}</span>
</span></span></code></pre></div><p>对于 Linux 2.6.18:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#000">define</span> <span style="color:#000">_raw_spin_lock</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">lock</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#000">__raw_spin_lock</span><span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">lock</span><span style="color:#000;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">raw_lock</span><span style="color:#000;font-weight:bold">)</span>
</span></span><span style="display:flex;"><span><span style="color:#204a87;font-weight:bold">static</span> <span style="color:#204a87;font-weight:bold">inline</span> <span style="color:#204a87;font-weight:bold">void</span> <span style="color:#000">__raw_spin_lock</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">raw_spinlock_t</span> <span style="color:#ce5c00;font-weight:bold">*</span><span style="color:#000">lock</span><span style="color:#000;font-weight:bold">)</span>
</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">{</span>
</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">unsigned</span> <span style="color:#204a87;font-weight:bold">long</span> <span style="color:#000">tmp</span><span style="color:#000;font-weight:bold">;</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">__asm__</span> <span style="color:#000">__volatile__</span><span style="color:#000;font-weight:bold">(</span>
</span></span><span style="display:flex;"><span><span style="color:#4e9a06">&#34;1: ldrex %0, [%1]</span><span style="color:#4e9a06">\n</span><span style="color:#4e9a06">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#4e9a06">&#34; teq %0, #0</span><span style="color:#4e9a06">\n</span><span style="color:#4e9a06">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#4e9a06">&#34; strexeq %0, %2, [%1]</span><span style="color:#4e9a06">\n</span><span style="color:#4e9a06">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#4e9a06">&#34; teqeq %0, #0</span><span style="color:#4e9a06">\n</span><span style="color:#4e9a06">&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#4e9a06">&#34; bne 1b&#34;</span>
</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">:</span> <span style="color:#4e9a06">&#34;=&amp;r&#34;</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#000">tmp</span><span style="color:#000;font-weight:bold">)</span>
</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">:</span> <span style="color:#4e9a06">&#34;r&#34;</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">lock</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">lock</span><span style="color:#000;font-weight:bold">),</span> <span style="color:#4e9a06">&#34;r&#34;</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">)</span>
</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">:</span> <span style="color:#4e9a06">&#34;cc&#34;</span><span style="color:#000;font-weight:bold">);</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">smp_mb</span><span style="color:#000;font-weight:bold">();</span>
</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">}</span>
</span></span></code></pre></div><p>以上大家可以看出,最早期的 kernel 版本是没有 wfe 这条指令的,后面的版本才有。</p>
<h2 id="4-wfesev-与-wfi-的作用与工作原理">4 WFE、SEV 与 WFI 的作用与工作原理</h2>
<p>那这条指令的作用是什么呢?我们可以上 arm 官网去查看这条指令的描述:<a href="http://infocenter.arm.com/help/index.jsp?lang=en">ARM Software development tools</a></p>
<ul>
<li>
<p>SEV</p>
<blockquote>
<p>SEV causes an event to be signaled to all cores within a multiprocessor system. If SEV is implemented, WFE must also be implemented.</p>
</blockquote>
</li>
</ul>
<p>SEV 指令可以产生事件信号,发送给全部的 cpu,让他们唤醒。如果 SEV 实现了,那么 WFE 也必须被实现。这里的事件信号其实会表现为 Event register,这是个一 bit 的 register,如果有事件,那么此 bit 为真。</p>
<ul>
<li>WFE</li>
</ul>
<blockquote>
<p>If the Event Register is not set, WFE suspends execution until one of the following events occurs:</p>
<p>• an IRQ interrupt, unless masked by the CPSR I-bit • an FIQ interrupt, unless masked by the CPSR F-bit • an Imprecise Data abort, unless masked by the CPSR A-bit • a Debug Entry request, if Debug is enabled • an Event signaled by another processor using the SEV instruction.</p>
<p>If the Event Register is set, WFE clears it and returns immediately. If WFE is implemented, SEV must also be implemented.</p>
</blockquote>
<p>对于 WFE,如果 Event Register 没有设置,WFE 会让 cpu 进入 low-power state,直到下面列举的五个 events 产生,比如说中断等等都会唤醒当前因为 WFE 而 suspend 的cpu。</p>
<p>如果 Event Register 被设置了,那么 WFE 会直接返回,不让 cpu 进入low-power state,目的是因为既然有事件产生了,说明当前 cpu 需要干活,不能 suspend,所以才这样设计。</p>
<p>这里我很好奇 Event Register 到底是怎么理解的。因此需要阅读手册《ARM Architecture Reference Manual.pdf》,下面我会做说明。</p>
<ul>
<li>WFI</li>
</ul>
<blockquote>
<p>WFI suspends execution until one of the following events occurs:</p>
<p>• an IRQ interrupt, regardless of the CPSR I-bit • an FIQ interrupt, regardless of the CPSR F-bit • an Imprecise Data abort, unless masked by the CPSR A-bit • a Debug Entry request, regardless of whether Debug is enabled.</p>
</blockquote>
<p>而对于 WFI 这种,不会判断 Event register,暴力的直接让 cpu 进入 low-power state,直到有上述四个 events 产生才会唤醒 cpu。</p>
<p>注意,这里 WFE 比 WFI 多了一个唤醒特性:</p>
<blockquote>
<p>an Event signaled by another processor using the SEV instruction.</p>
</blockquote>
<p>也就是说 SEV 是不会唤醒 WFI 指令休眠的 cpu 的。这点需要特别注意。</p>
<p>接下来我谈下这个 Event Register 是怎么回事了。看这个文档《ARM Architecture Reference Manual.pdf》</p>
<ul>
<li>The Event Register</li>
</ul>
<blockquote>
<p>The Event Register is a single bit register for each processor. When set, an event register indicates that an event has occurred, since the register was last cleared, that might require some action by the processor. Therefore, the processor must not suspend operation on issuing a WFE instruction.</p>
<p>The reset value of the Event Register is UNKNOWN.</p>
<p>The Event Register is set by:</p>
<p>• an SEV instruction • an event sent by some IMPLEMENTATION DEFINED mechanism • a debug event that causes entry into Debug state • an exception return.</p>
<p>As shown in this list, the Event Register might be set by IMPLEMENTATION DEFINED mechanisms. The Event Register is cleared only by a Wait For Event instruction. Software cannot read or write the value of the Event Register directly.</p>
</blockquote>
<p>以上就是 Event Register 的表述,上述已经说的很明白了,Event Register 只有一个 bit,可以被 set 的情况总有四种大类型。当任意一个条件满足的时候,Event Register 都可以被 set,那么当 WFE 进入的时候会进行 Event Register 的判断,如果为真,就直接返回。</p>
<p>再来看看 WFE 的介绍:</p>
<blockquote>
<p>Wait For Event is a hint instruction that permits the processor to enter a low-power state until one of a number of events occurs, including events signaled by executing the SEV instruction on any processor in the multiprocessor system. For more information, see Wait For Event and Send Event on page B1-1197.</p>
<p>In an implementation that includes the Virtualization Extensions, if HCR.TWE is set to 1, execution of a WFE instruction in a Non-secure mode other than Hyp mode generates a Hyp Trap exception if, ignoring the value of the HCR.TWE bit, conditions permit the processor to suspend execution. For more information see Trapping use of the WFI and WFE instructions on page B1-1249.</p>
</blockquote>
<p>接下来上 WFE 这条指令的伪代码流程:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#000">Assembler</span> <span style="color:#000">syntax</span>
</span></span><span style="display:flex;"><span><span style="color:#000">WFE</span><span style="color:#000;font-weight:bold">{</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">c</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#000;font-weight:bold">}{</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">q</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#000;font-weight:bold">}</span>
</span></span><span style="display:flex;"><span><span style="color:#f57900">where</span><span style="color:#000;font-weight:bold">:</span>
</span></span><span style="display:flex;"><span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">c</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">q</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">See</span> <span style="color:#000">Standard</span> <span style="color:#000">assembler</span> <span style="color:#000">syntax</span> <span style="color:#000">fields</span> <span style="color:#000">on</span> <span style="color:#000">page</span> <span style="color:#000">A8</span><span style="color:#ce5c00;font-weight:bold">-</span><span style="color:#0000cf;font-weight:bold">285.</span>
</span></span><span style="display:flex;"><span><span style="color:#000">Operation</span>
</span></span><span style="display:flex;"><span><span style="color:#204a87;font-weight:bold">if</span> <span style="color:#000">ConditionPassed</span><span style="color:#000;font-weight:bold">()</span> <span style="color:#000">then</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">EncodingSpecificOperations</span><span style="color:#000;font-weight:bold">();</span>
</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">if</span> <span style="color:#000">EventRegistered</span><span style="color:#000;font-weight:bold">()</span> <span style="color:#000">then</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">ClearEventRegister</span><span style="color:#000;font-weight:bold">();</span>
</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">else</span>
</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">if</span> <span style="color:#000">HaveVirtExt</span><span style="color:#000;font-weight:bold">()</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;</span> <span style="color:#ce5c00;font-weight:bold">!</span><span style="color:#000">IsSecure</span><span style="color:#000;font-weight:bold">()</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;</span> <span style="color:#ce5c00;font-weight:bold">!</span><span style="color:#000">CurrentModeIsHyp</span><span style="color:#000;font-weight:bold">()</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;</span> <span style="color:#000">HCR</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">TWE</span> <span style="color:#ce5c00;font-weight:bold">==</span> <span style="color:#4e9a06">&#39;1&#39;</span> <span style="color:#000">then</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">HSRString</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">Zeros</span><span style="color:#000;font-weight:bold">(</span><span style="color:#0000cf;font-weight:bold">25</span><span style="color:#000;font-weight:bold">);</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">HSRString</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#4e9a06">&#39;1&#39;</span><span style="color:#000;font-weight:bold">;</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">WriteHSR</span><span style="color:#000;font-weight:bold">(</span><span style="color:#a40000">&#39;</span><span style="color:#0000cf;font-weight:bold">000001</span><span style="color:#a40000">&#39;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">HSRString</span><span style="color:#000;font-weight:bold">);</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">TakeHypTrapException</span><span style="color:#000;font-weight:bold">();</span>
</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">else</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">WaitForEvent</span><span style="color:#000;font-weight:bold">();</span>
</span></span><span style="display:flex;"><span><span style="color:#000">Exceptions</span>
</span></span><span style="display:flex;"><span><span style="color:#000">Hyp</span> <span style="color:#000">Trap</span><span style="color:#000;font-weight:bold">.</span>
</span></span></code></pre></div><p>看了上面这段 WFE 的伪代码,一目了然,首先判断 <code>ConditionPassed()</code>,这些函数大家可以在 arm 手册中查看其详细含义,如果 <code>EventResigerted()</code> 函数为真,也就是这个 1 bit 的寄存器为真,那么就清除此 bit,然后退出返回,不会让 cpu 进入 low power state;</p>
<p>如果不是异常处理,<code>TakeHypTrapException()</code>,那么就 <code>WaitForEvent()</code>,等待唤醒事件到来,到来了,就唤醒当前 cpu。</p>
<p>为什么有事件来了就直接返回呢,因为 WFE 的设计认为,如果此时有 event 事件,那么说明当前 cpu 要干活,那就没必要进入 low power state 模式。</p>
<p>如果没有事件产生,那么就可以进入 low power state 模式,因为 cpu 反正也是在等待锁,此时也干不了别的事情,还不如休眠还可以降低功耗。</p>
<p>当然,irq,fiq 等很多中断都可以让 WFE 休眠的 cpu 唤醒,那么这样做还有什么意义呢?比如说时钟中断是一直产生的,那么 cpu 很快就醒了啊,都不用等到发 SEV,那么既然是用 <code>spin_lock</code>,也可以在中断上半部使用,也可以在进程上下文,既然是自旋锁,就意味着保护的这段代码是要足够精简,不希望被其他东西打断,那么如果你保护的这部分代码非常长,这时候整个系统响应很可能会变慢,因为如果这时候有人也要使用这个锁的话,那么是否保护的这段代码设计上是有问题的。因此用 <code>spin_lock</code> 保护的函数尽可能要短,如果长的话可能需要换其他锁,或者考虑下是否真的要这么长的保护措施。</p>
<p><strong><code>TakeHypTrapException()</code>,是进入异常处理</strong></p>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#000">Pseudocode</span> <span style="color:#000">description</span> <span style="color:#000">of</span> <span style="color:#000">taking</span> <span style="color:#000">the</span> <span style="color:#000">Hyp</span> <span style="color:#000">Trap</span> <span style="color:#000">exception</span>
</span></span><span style="display:flex;"><span><span style="color:#000">The</span> <span style="color:#000">TakeHypTrapException</span><span style="color:#000;font-weight:bold">()</span> <span style="color:#000">pseudocode</span> <span style="color:#000">procedure</span> <span style="color:#000">describes</span> <span style="color:#000">how</span> <span style="color:#000">the</span> <span style="color:#000">processor</span> <span style="color:#000">takes</span> <span style="color:#000">the</span> <span style="color:#f57900">exception</span><span style="color:#000;font-weight:bold">:</span>
</span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">// TakeHypTrapException()
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">// ======================
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"></span><span style="color:#000">TakeHypTrapException</span><span style="color:#000;font-weight:bold">()</span>
</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic">// HypTrapException is caused by executing an instruction that is trapped to Hyp mode as a
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"></span> <span style="color:#8f5902;font-style:italic">// result of a trap set by a bit in the HCR, HCPTR, HSTR or HDCR. By definition, it can only
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"></span> <span style="color:#8f5902;font-style:italic">// be generated in a Non-secure mode other than Hyp mode.
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"></span> <span style="color:#8f5902;font-style:italic">// Note that, when a Supervisor Call exception is taken to Hyp mode because HCR.TGE==1, this
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"></span> <span style="color:#8f5902;font-style:italic">// is not a trap of the SVC instruction. See the TakeSVCException() pseudocode for this case.
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"></span> <span style="color:#000">preferred_exceptn_return</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">if</span> <span style="color:#000">CPSR</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">T</span> <span style="color:#ce5c00;font-weight:bold">==</span> <span style="color:#4e9a06">&#39;1&#39;</span> <span style="color:#000">then</span> <span style="color:#000">PC</span><span style="color:#ce5c00;font-weight:bold">-</span><span style="color:#0000cf;font-weight:bold">4</span> <span style="color:#204a87;font-weight:bold">else</span> <span style="color:#000">PC</span><span style="color:#ce5c00;font-weight:bold">-</span><span style="color:#0000cf;font-weight:bold">8</span><span style="color:#000;font-weight:bold">;</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">new_spsr_value</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">CPSR</span><span style="color:#000;font-weight:bold">;</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">EnterHypMode</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">new_spsr_value</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">preferred_exceptn_return</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">20</span><span style="color:#000;font-weight:bold">);</span>
</span></span><span style="display:flex;"><span><span style="color:#000">Additional</span> <span style="color:#000">pseudocode</span> <span style="color:#000">functions</span> <span style="color:#204a87;font-weight:bold">for</span> <span style="color:#000">exception</span> <span style="color:#000">handling</span> <span style="color:#000">on</span> <span style="color:#000">page</span> <span style="color:#000">B1</span><span style="color:#ce5c00;font-weight:bold">-</span><span style="color:#0000cf;font-weight:bold">1221</span> <span style="color:#000">defines</span> <span style="color:#000">the</span> <span style="color:#000">EnterHypMode</span><span style="color:#000;font-weight:bold">()</span> <span style="color:#000">pseudocode</span>
</span></span><span style="display:flex;"><span><span style="color:#000">procedure</span><span style="color:#000;font-weight:bold">.</span>
</span></span></code></pre></div>
<div class="card rounded p-2 td-post-card mb-4 mt-4" style="max-width: 810px">
<img class="card-img-top" src="/blog/2022/07/19/cpu%E5%A4%9A%E6%A0%B8%E9%94%81%E6%8C%87%E4%BB%A4-wfe%E5%8E%9F%E7%90%86/image-20220719201300279_hu16ba9ede6f8109a7933eccf29aa0d9ee_82343_800x400_fill_catmullrom_smart1_3.png" width="800" height="400">
<div class="card-body px-0 pt-2 pb-0">
<p class="card-text">
<small class="text-muted"><br/>arm spec</small></p>
</div>
</div>
<p><strong>ClearEventRegister()</strong></p>
<p>Clear the Event Register of the current processor 清除Event Register的bit</p>
<p><strong>EventRegistered()</strong></p>
<p>Determine whether the Event Register of the current processor is set Event Register bit为真,即被设置过</p>
<p><strong>WaitForEvent()</strong></p>
<p>Wait until WFE instruction completes</p>
<p>等待 Events 事件,有任何一个 Event 事件来临,都会唤醒当前被 WFE suspend 下去的 cpu, 如果是 SEV,会唤醒全部被 WFE suspend 下去的cpu。</p>
<p>如下是关于 WFE 的 wake up events 事件描述和列举:</p>
<blockquote>
<p>WFE wake-up events</p>
<p>The following events are WFE wake-up events:</p>
<p>• the execution of an SEV instruction on any processor in the multiprocessor system • a physical IRQ interrupt, unless masked by the CPSR.I bit • a physical FIQ interrupt, unless masked by the CPSR.F bit • a physical asynchronous abort, unless masked by the CPSR.A bit • in Non-secure state in any mode other than Hyp mode: — when HCR.IMO is set to 1, a virtual IRQ interrupt, unless masked by the CPSR.I bit — when HCR.FMO is set to 1, a virtual FIQ interrupt, unless masked by the CPSR.F bit — when HCR.AMO is set to 1, a virtual asynchronous abort, unless masked by the CPSR.A bit • an asynchronous debug event, if invasive debug is enabled and the debug event is permitted • an event sent by the timer event stream, see Event streams on page B8-1934 • an event sent by some IMPLEMENTATION DEFINED mechanism.</p>
<p>In addition to the possible masking of WFE wake-up events shown in this list, when invasive debug is enabled and DBGDSCR[15:14] is not set to 0b00, DBGDSCR.INTdis can mask interrupts, including masking them acting as WFE wake-up events. For more information, see DBGDSCR, Debug Status and Control Register on page C11-2206. As shown in the list of wake-up events, an implementation can include IMPLEMENTATION DEFINED hardware mechanisms to generate wake-up events. NoteFor more information about CPSR masking see Asynchronous exception masking on page B1-1181. If the configuration of the masking controls provided by the Security Extensions, or Virtualization Extensions, mean that a CPSR mask bit cannot mask the corresponding exception, then the physical exception is a WFE wake-up event, regardless of the value of the CPSR mask bit.</p>
</blockquote>
<p>接下来我们看下 WFI 的伪代码:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#000">Assembler</span> <span style="color:#000">syntax</span>
</span></span><span style="display:flex;"><span><span style="color:#000">WFI</span><span style="color:#000;font-weight:bold">{</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">c</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#000;font-weight:bold">}{</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">q</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#000;font-weight:bold">}</span>
</span></span><span style="display:flex;"><span><span style="color:#f57900">where</span><span style="color:#000;font-weight:bold">:</span>
</span></span><span style="display:flex;"><span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">c</span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">q</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000">See</span> <span style="color:#000">Standard</span> <span style="color:#000">assembler</span> <span style="color:#000">syntax</span> <span style="color:#000">fields</span> <span style="color:#000">on</span> <span style="color:#000">page</span> <span style="color:#000">A8</span><span style="color:#ce5c00;font-weight:bold">-</span><span style="color:#0000cf;font-weight:bold">285.</span>
</span></span><span style="display:flex;"><span><span style="color:#000">Operation</span>
</span></span><span style="display:flex;"><span><span style="color:#204a87;font-weight:bold">if</span> <span style="color:#000">ConditionPassed</span><span style="color:#000;font-weight:bold">()</span> <span style="color:#000">then</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">EncodingSpecificOperations</span><span style="color:#000;font-weight:bold">();</span>
</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">if</span> <span style="color:#000">HaveVirtExt</span><span style="color:#000;font-weight:bold">()</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;</span> <span style="color:#ce5c00;font-weight:bold">!</span><span style="color:#000">IsSecure</span><span style="color:#000;font-weight:bold">()</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;</span> <span style="color:#ce5c00;font-weight:bold">!</span><span style="color:#000">CurrentModeIsHyp</span><span style="color:#000;font-weight:bold">()</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;</span> <span style="color:#000">HCR</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">TWI</span> <span style="color:#ce5c00;font-weight:bold">==</span> <span style="color:#4e9a06">&#39;1&#39;</span> <span style="color:#000">then</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">HSRString</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">Zeros</span><span style="color:#000;font-weight:bold">(</span><span style="color:#0000cf;font-weight:bold">25</span><span style="color:#000;font-weight:bold">);</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">HSRString</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#4e9a06">&#39;1&#39;</span><span style="color:#000;font-weight:bold">;</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">WriteHSR</span><span style="color:#000;font-weight:bold">(</span><span style="color:#a40000">&#39;</span><span style="color:#0000cf;font-weight:bold">000001</span><span style="color:#a40000">&#39;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">HSRString</span><span style="color:#000;font-weight:bold">);</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">TakeHypTrapException</span><span style="color:#000;font-weight:bold">();</span>
</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">else</span>
</span></span><span style="display:flex;"><span> <span style="color:#000">WaitForInterrupt</span><span style="color:#000;font-weight:bold">();</span>
</span></span><span style="display:flex;"><span><span style="color:#000">Exceptions</span>
</span></span><span style="display:flex;"><span><span style="color:#000">Hyp</span> <span style="color:#000">Trap</span><span style="color:#000;font-weight:bold">.</span>
</span></span></code></pre></div><p>相关解释:</p>
<blockquote>
<p>WFI</p>
<p>Wait For Interrupt is a hint instruction that permits the processor to enter a low-power state until one of a number of asynchronous events occurs. For more information, see Wait For Interrupt on page B1-1200. In an implementation that includes the Virtualization Extensions, if HCR.TWI is set to 1, execution of a WFE instruction in a Non-secure mode other than Hyp mode generates a Hyp Trap exception if, ignoring the value of the HCR.TWI bit, conditions permit the processor to suspend execution. For more information see Trapping use of the WFI and WFE instructions on page B1-1249.</p>
</blockquote>
<p>以上我们可以看出,WFI 并没有去判断 event register,因此看伪代码可以很直观的看出 WFI 与 WFE 的区别。</p>
<p>以上是我个人的理解,如果有表述不精准或者不准确的地方还请大家指出,欢迎交流。</p>
<h2 id="5-参考资料">5 参考资料</h2>
<ul>
<li><a href="https://blog.csdn.net/adaptiver/article/details/72389453">ARM 架构下 spinlock 原理 (代码解读)</a></li>
<li><a href="http://www.wowotech.net/armv8a_arch/wfe_wfi.html">ARM WFI 和 WFE 指令</a></li>
<li><a href="http://infocenter.arm.com/help/index.jsp?lang=en">ARM Software development tools</a></li>
<li><a href="https://www.jianshu.com/p/f0d6e7103d9b">Linux 内核自旋锁 <code>spinlock_t</code> 机制</a></li>
</ul>
</description>
</item>
<item>
<title>Blog: qemu-lunchlinux</title>
<link>/blog/2022/07/18/qemu-lunchlinux/</link>
<pubDate>Mon, 18 Jul 2022 00:00:00 +0000</pubDate>
<guid>/blog/2022/07/18/qemu-lunchlinux/</guid>
<description>
<h1 id="版本信息">版本信息</h1>
<p>系统版本:Ubuntu Server 20.04 LTS 64bit
编译器:9.4.0
交叉编译器:arm-linux-gnueabi-gcc (Linaro GCC 7.5-2019.12) 7.5.0
linux内核:linux-5.15.53
busybox:1.35.0
QEMU:7.0.0
ninja-build:1.10.0</p>
<h1 id="获取交叉编译链">获取交叉编译链</h1>
<p>下载地址:<a href="https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/arm-linux-gnueabi/">Linaro Releases</a>
<img src="C:%5CUsers%5Cliulf%5CDesktop%5C%E5%8D%9A%E5%AE%A2%5Cpictures.assets%5Cimage-20220718155906055.png" alt="image-20220718155906055"></p>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>tar xvf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabi.tar.tar <span style="color:#8f5902;font-style:italic">#解压</span>
</span></span><span style="display:flex;"><span>vi ~/.bashrc <span style="color:#8f5902;font-style:italic">#修改环境变量PATH,让系统先去指定目录寻找交叉编译链的可执行文件</span>
</span></span></code></pre></div><p><img src="https://raw.githubusercontent.com/gitliulf/picture/main/image-20220718160818198.png" alt="image-20220718160818198">
在.bashrc文件加上这行,交叉工具链的目录取决于自己解压的目录
export PATH=/home/ubuntu/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabi/bin:$PATH</p>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span><span style="color:#204a87">source</span> ~/.bashrc <span style="color:#8f5902;font-style:italic">#让.bashrc生效</span>
</span></span></code></pre></div><p>安装成功
<img src="https://raw.githubusercontent.com/gitliulf/picture/main/image-20220718160830447.png" alt="image-20220718160830447"></p>
<h1 id="编译qemu">编译QEMU</h1>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>sudo apt-get install ninja-build <span style="color:#8f5902;font-style:italic">#Need ninja. Ninja is a small build system with a focus on speed. </span>
</span></span><span style="display:flex;"><span>wget https://download.qemu.org/qemu-7.0.0.tar.xz <span style="color:#8f5902;font-style:italic">#下载源码</span>
</span></span><span style="display:flex;"><span>tar xvf qemu-7.0.0.tar.xz <span style="color:#8f5902;font-style:italic">#解压</span>
</span></span><span style="display:flex;"><span>mkdir qemu_build <span style="color:#ce5c00;font-weight:bold">&amp;&amp;</span> <span style="color:#204a87">cd</span> qemu_build <span style="color:#8f5902;font-style:italic"># 在下载目录新建文件夹build</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"># 以下均在/build目录下</span>
</span></span><span style="display:flex;"><span>../qemu-7.0.0/configure
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>make <span style="color:#ce5c00;font-weight:bold">&amp;&amp;</span> make install <span style="color:#8f5902;font-style:italic">#出去喝杯咖啡,打两把游戏在来看结果</span>
</span></span></code></pre></div><p>编译成功后,qemu-system-arm就生成在当前目录
和上面一样,将编译出的qemu的可执行文件的目录加入PATH环境变量。</p>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>vi ~/.bashrc <span style="color:#8f5902;font-style:italic">#修改环境变量PATH</span>
</span></span></code></pre></div><p>在.bashrc文件上次修改的基础上,重新修改
export PATH=/home/ubuntu/qemu_build:/home/ubuntu/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabi/bin:$PATH</p>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span><span style="color:#204a87">source</span> ~/.bashrc <span style="color:#8f5902;font-style:italic">#让.bashrc生效</span>
</span></span></code></pre></div><p>安装成功
<img src="https://raw.githubusercontent.com/gitliulf/picture/main/image-20220718160842204.png" alt="image-20220718160842204"></p>
<h1 id="编译linux内核">编译Linux内核</h1>
<p>内核代码下载地址:<a href="https://www.kernel.org/">The Linux Kernel Archives</a></p>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>make <span style="color:#000">ARCH</span><span style="color:#ce5c00;font-weight:bold">=</span>arm <span style="color:#000">CROSS_COMPILE</span><span style="color:#ce5c00;font-weight:bold">=</span>arm-linux-gnueabi- vexpress_defconfig
</span></span><span style="display:flex;"><span>make <span style="color:#000">ARCH</span><span style="color:#ce5c00;font-weight:bold">=</span>arm <span style="color:#000">CROSS_COMPILE</span><span style="color:#ce5c00;font-weight:bold">=</span>arm-linux-gnueabi- menuconfig
</span></span><span style="display:flex;"><span>make <span style="color:#000">ARCH</span><span style="color:#ce5c00;font-weight:bold">=</span>arm <span style="color:#000">CROSS_COMPILE</span><span style="color:#ce5c00;font-weight:bold">=</span>arm-linux-gnueabi- -j2
</span></span></code></pre></div><p>ps:Versatile Express系统由ARM Ltd提供,作为CortexA9四核处理器的开发环境,硬件由uATX主板和CoreTile Express A9x4子板组成。</p>
<h2 id="验证只启动linux内核">验证只启动Linux内核</h2>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>qemu-system-arm -M vexpress-a9 -m 128M -kernel ~/linux-5.15.53/arch/arm/boot/zImage -dtb ~/linux-5.15.53/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic
</span></span></code></pre></div><p>ps:内核和设备树的路径每个人可能不一样,需要自己注意下</p>
<p><img src="https://raw.githubusercontent.com/gitliulf/picture/main/image-20220718160857131.png" alt="image-20220718160857131">
启动成功,但还没有文件系统,操作系统稍后制作。
输入ctrl+A+x退出qemu</p>
<h1 id="编译busybox制作文件系统">编译busybox,制作文件系统</h1>
<h2 id="编译">编译</h2>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>wget https://busybox.net/downloads/busybox-1.35.0.tar.bz2 <span style="color:#8f5902;font-style:italic">#下载源码</span>
</span></span><span style="display:flex;"><span>tar xvf busybox-1.35.0.tar.bz2 <span style="color:#8f5902;font-style:italic">#解压</span>
</span></span><span style="display:flex;"><span><span style="color:#204a87">cd</span> busybox-1.35.0/
</span></span><span style="display:flex;"><span>make <span style="color:#000">ARCH</span><span style="color:#ce5c00;font-weight:bold">=</span>arm <span style="color:#000">CROSS_COMPILE</span><span style="color:#ce5c00;font-weight:bold">=</span>arm-linux-gnueabi- defconfig
</span></span><span style="display:flex;"><span>make <span style="color:#000">ARCH</span><span style="color:#ce5c00;font-weight:bold">=</span>arm <span style="color:#000">CROSS_COMPILE</span><span style="color:#ce5c00;font-weight:bold">=</span>arm-linux-gnueabi- menuconfig
</span></span></code></pre></div><ul>
<li>
<blockquote>
<p>Settings —&gt;</p>
<ul>
<li>[*] Build static binary (no shared libs) #使用静态库</li>
</ul>
</blockquote>
</li>
</ul>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>make <span style="color:#000">ARCH</span><span style="color:#ce5c00;font-weight:bold">=</span>arm <span style="color:#000">CROSS_COMPILE</span><span style="color:#ce5c00;font-weight:bold">=</span>arm-linux-gnueabi- -j4
</span></span><span style="display:flex;"><span>make <span style="color:#000">ARCH</span><span style="color:#ce5c00;font-weight:bold">=</span>arm <span style="color:#000">CROSS_COMPILE</span><span style="color:#ce5c00;font-weight:bold">=</span>arm-linux-gnueabi- install
</span></span></code></pre></div><ul>
<li>生成结果位于:当前根目录下的_install文件夹下</li>
<li>备注:默认安装到根目录下的_install,若想更改,可以通过menuconfig里面的选项更改</li>
</ul>
<h2 id="制作文件系统镜像">制作文件系统镜像</h2>
<h3 id="根目录构建">根目录构建</h3>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>mkdir -p rootfs/<span style="color:#ce5c00;font-weight:bold">{</span>dev,etc/init.d,lib,proc,sys<span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#8f5902;font-style:italic">#创建根目录</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>cp -raf busybox-1.35.0/_install/* rootfs <span style="color:#8f5902;font-style:italic">#拷贝busybox命令到根目录</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>sudo mknod -m <span style="color:#0000cf;font-weight:bold">666</span> rootfs/dev/tty1 c <span style="color:#0000cf;font-weight:bold">4</span> 1 <span style="color:#8f5902;font-style:italic">#创建4个tty端终设备</span>
</span></span><span style="display:flex;"><span>sudo mknod -m <span style="color:#0000cf;font-weight:bold">666</span> rootfs/dev/tty1 c <span style="color:#0000cf;font-weight:bold">4</span> <span style="color:#0000cf;font-weight:bold">2</span>
</span></span><span style="display:flex;"><span>sudo mknod -m <span style="color:#0000cf;font-weight:bold">666</span> rootfs/dev/tty2 c <span style="color:#0000cf;font-weight:bold">4</span> <span style="color:#0000cf;font-weight:bold">2</span>
</span></span><span style="display:flex;"><span>sudo mknod -m <span style="color:#0000cf;font-weight:bold">666</span> rootfs/dev/tty3 c <span style="color:#0000cf;font-weight:bold">4</span> <span style="color:#0000cf;font-weight:bold">3</span>
</span></span><span style="display:flex;"><span>sudo mknod -m <span style="color:#0000cf;font-weight:bold">666</span> rootfs/dev/tty4 c <span style="color:#0000cf;font-weight:bold">4</span> <span style="color:#0000cf;font-weight:bold">4</span>
</span></span><span style="display:flex;"><span>sudo mknod -m <span style="color:#0000cf;font-weight:bold">666</span> rootfs/dev/console c <span style="color:#0000cf;font-weight:bold">5</span> 1 <span style="color:#8f5902;font-style:italic">#创建console字符设备</span>
</span></span><span style="display:flex;"><span>sudo mknod -m <span style="color:#0000cf;font-weight:bold">666</span> rootfs/dev/null c <span style="color:#0000cf;font-weight:bold">1</span> 3 <span style="color:#8f5902;font-style:italic">#创建null 字符设备</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>vim rootfs/etc/init.d/rcS <span style="color:#8f5902;font-style:italic">#输入如下内容</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">#!/bin/bash
</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"></span>mount -t proc proc /proc
</span></span><span style="display:flex;"><span>mount -t sysfs sysfs /sys
</span></span><span style="display:flex;"><span>/sbin/mdev -s
</span></span><span style="display:flex;"><span><span style="color:#204a87">echo</span> /sbin/mdev &gt; /proc/sys/kernel/hotplug <span style="color:#8f5902;font-style:italic">#支持热插拔</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>sudo chmod +x rootfs/etc/init.d/rcS
</span></span><span style="display:flex;"><span><span style="color:#204a87">cd</span> rootfs
</span></span><span style="display:flex;"><span>find ./ <span style="color:#000;font-weight:bold">|</span> cpio -o --format<span style="color:#ce5c00;font-weight:bold">=</span>newc &gt; ./rootfs.img
</span></span></code></pre></div><h2 id="启动qemu">启动qemu</h2>
<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>qemu-system-arm -M vexpress-a9 -m 128M -kernel linux-5.15.53/arch/arm/boot/zImage -dtb linux-5.15.53/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -append <span style="color:#4e9a06">&#34;root=/dev/ram rdinit=sbin/init console=ttyAMA0&#34;</span> -nographic -initrd rootfs/rootfs.img
</span></span></code></pre></div><p>启动成功
<img src="https://raw.githubusercontent.com/gitliulf/picture/main/image-20220718160906354.png" alt="image-20220718160906354"></p>
</description>
</item>
</channel>
</rss>