<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Bug &#8211; richliu&#039;s blog</title>
	<atom:link href="https://richliu.com/tag/bug/feed/" rel="self" type="application/rss+xml" />
	<link>https://richliu.com</link>
	<description>Linux, 工作, 生活, 家人</description>
	<lastBuildDate>Tue, 06 Jan 2015 16:23:36 +0000</lastBuildDate>
	<language>zh-TW</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>[跟風] 程式設計師, 你調試過最難的 BUG</title>
		<link>https://richliu.com/2015/01/07/1730/%e8%b7%9f%e9%a2%a8-%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e5%b8%ab-%e4%bd%a0%e8%aa%bf%e8%a9%a6%e9%81%8e%e6%9c%80%e9%9b%a3%e7%9a%84-bug/</link>
					<comments>https://richliu.com/2015/01/07/1730/%e8%b7%9f%e9%a2%a8-%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e5%b8%ab-%e4%bd%a0%e8%aa%bf%e8%a9%a6%e9%81%8e%e6%9c%80%e9%9b%a3%e7%9a%84-bug/#comments</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Tue, 06 Jan 2015 16:22:32 +0000</pubDate>
				<category><![CDATA[ARM]]></category>
		<category><![CDATA[Embedded]]></category>
		<category><![CDATA[Hardware]]></category>
		<category><![CDATA[IC Design]]></category>
		<category><![CDATA[工作]]></category>
		<category><![CDATA[arm]]></category>
		<category><![CDATA[Bug]]></category>
		<category><![CDATA[Cache]]></category>
		<category><![CDATA[Hardest Bug]]></category>
		<category><![CDATA[linux kernel]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=1730</guid>

					<description><![CDATA[<p>看到一篇文章 簡體中文翻譯: 程序员，你调试过的最难的 Bug 是？ 原文: What&#8217;s the [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2015/01/07/1730/%e8%b7%9f%e9%a2%a8-%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e5%b8%ab-%e4%bd%a0%e8%aa%bf%e8%a9%a6%e9%81%8e%e6%9c%80%e9%9b%a3%e7%9a%84-bug/">[跟風] 程式設計師, 你調試過最難的 BUG</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>看到一篇文章<br />
簡體中文翻譯: <a href="http://blog.jobbole.com/50995/" target="_blank" rel="noopener">程序员，你调试过的最难的 Bug 是？</a><br />
原文: <a href="http://www.quora.com/Whats-the-hardest-bug-youve-debugged" target="_blank" rel="noopener">What&#8217;s the hardest bug you&#8217;ve debugged?</a></p>
<p>看原文比翻譯好一點, 從原文大概只可能猜出, 改過 timer 之後, 可能影響到 interrupt 的速度.<br />
但是從最後的描述猜也可能是動到 clock tree 去影響 timer 進而影響到其他的行為.<br />
有碰到這種 BUG 的第一個一定先猜 timing , 純軟體的反而不會這樣想, 所以他覺得最難的 BUG<br />
我們看起來就還好.</p>
<p>這個描述讓我也想寫一下, 我碰過最難的 BUG.<br />
<span id="more-1730"></span></p>
<p>那是新的 SoC 剛回來的時候, 各個 block 都要驗, 我是負責帶領系統驗証部門的,<br />
所以一開始就有一大堆 BUG, 其中有一個 BUG 就是資料存取有問題, 而且要很久才會出現一次的.</p>
<p><strong>最難的 BUG 要件之一就是很久才會出現一次, 這表示會搞很久. </strong></p>
<p>因為當時我是負責 SATA 部份的驗証, 所以這個工作自然就是我去追了.<br />
看倌呀, SOC 就是統統要自己來, 從 hardware CPU/SATA/CLOCK 到 kernel 層都可能有問題.</p>
<p>第一件事情就是, 想辦法找出可以複製的方法. 我們知道資料存取有問題<br />
所以我就寫了一個 sh script 從 A Disk Copy 到 B Disk 再做比對. 然後一直 COPY 下去, 直到找到為止.</p>
<p>這個 sh script 大概可以在 200 次大檔案 COPY, 找到一次錯誤的結果.<br />
大概要花二個小時以上, 一開始的時候, 這個 script 執行下去, 其實並沒有辦法抓出問題.</p>
<p>流程大概是這樣<br />
# dd if=/dev/zero of=test bs=1M count=1024<br />
# md5sum test<br />
這樣就會有一次寫入, 一次讀出, 這樣就可以比對 md5.</p>
<p>有沒有看出什麼問題?</p>
<p>其實這個錯誤可能很少人會意會到, 就是測試 pattern 不能為零, 假設今天 block 寫錯了, 而資料是零, 再怎麼寫入讀出, 資料還是正確的. 所以後來我都改用 AV file 做 test pattern, 工程師的惡趣味就在這邊了.<br />
&#8220;我今天有 update 新的 test pattern 哦&#8230;. &#8221;<br />
大家就知道發生什麼事情了.</p>
<p>修改完 script 之後,  md5 checksum 的結果的確是不一樣. 這時就要猜測是什麼地方在作怪.<br />
首先一定先關心 SATA Hardware 是不是有問題, 所以就拿 PCIe SATA 還有 USB 來驗証比對.<br />
同時間, 看 Linux kernel 追 SATA 這一層在搞什麼飛機.</p>
<p>其實相對於 USB Protocol , AHCI SATA Interface 是很簡單的 interface, 很快的就排除掉這個犯人了. 而且 PCIe SATA 和 USB 的結果顯示也是會複製錯誤.</p>
<p>這下子人就可能是 CPU 和 Kernel 殺的. 還有記憶體.<br />
SoC 守則, 只要資料有錯, 八成是記憶體殺的. 各位可能會問, 那為什麼要先測 SATA? 因為記憶體己經先掃過一輪沒問題了, 所以當然先丟 SATA. 不過這邊的先掃過一輪沒有問題是不是真的沒有問題&#8230;.<br />
這個原因是這樣, 所謂的記憶體沒有問題是用 NON-OS Code 下去掃的, 可能會有切 MMU Mode 和 NonMMU Mode. 總之是這樣測的.</p>
<p>然後我就 mount ramdisk 開 memtest 狂測一天. 果然出問題了. 哼哼, 是你吧.<br />
不過接下來問題才大條. RAM 出問題很麻煩的. 要怎麼定位到到底是什麼出問題呢?</p>
<p>專業的讀者應該就會猜, 那就降速跑.<br />
正解, RAM 出問題就要先降速跑. 所以 DRAM 就跑在 200Mhz (DDR2-800 是 400Mhz, 最低應該是 DDR-400 跑在 200Mhz). 反正都降速, 所以 CPU 也從 600Mhz 降到 400Mhz 跑.<br />
當然老天一定不會這麼容易讓我們破關的, 所以資料錯誤的 BUG 還是可以重現.<br />
同時間 NON-OS 的測試結果仍然是顯示沒有問題.</p>
<p>然後就是猜了. 因為如果 NON-OS 的 memory test 是正確的, 而 Linux 是錯誤的, 那可能問題是出在其他的部份. 這麼複雜的系統一定就是要猜.</p>
<p>猜也是一門學問, 接下來就是先關 L1/L2 Cache .<br />
各位, 為什麼 CACHE 要最後再測, 因為 CACHE 關掉整個系統會變更慢. 所以預期二小時會發生的, 可能測試就要拉到二天, 我還有碰過 Cache 關掉就複製不出來的 BUG.</p>
<p>Disable Cache 有二項, 因為 L2 Enable 一定要 L1 也 Enable.<br />
Disable L1/L2<br />
Disable L2<br />
除了 Disable Cache 以外, 和 CPU 相關的還有 SMP (因為 SoC 有二顆 CPU), 還有 Cache Driver 新舊版的問題.</p>
<p>這幾個測試項測下來, 果然 Disable Cache 就不會出問題了, 而且是 Disable L2 Cache.</p>
<p>走到這邊大概己經測試了三個星期. 快搞死了, SoC 慢就算了, 掉資料是不允許的啊啊啊.<br />
對一個 engineer 來說這根本是不可接受的事.<br />
而且同時間還有一堆 BUG 待解待查. SoC 剛回來天天都是屁股在燒.</p>
<p>為了保險起見. 必需要找到資料錯誤的 Pattern .<br />
所以寫了一個可以 binary compare 並且顯示出那邊不一樣的小程式.<br />
翻了一下當年的痕跡, 原來除了 binary compare, 還有程式內加上 invalidate cache 的相關程式.<br />
我還記得為了這件事翻了整層的 Linux kernel cache 和 memory management 機制.</p>
<p>最後確認到是 cache 的問題是, 使用 binary compare 找出 32bytes, 相當於一條 L2 cache line size.<br />
而且可以重覆這個測試.</p>
<p>到這邊幾乎可以確定是 L2 cache Line 的問題, 而且是硬體的問題, 當然 L2 還有一些測試項目.<br />
像是調整 Cache Latency 之類的. 這個應該都做了, 不過做了以後應該是更久才會再出現一次.</p>
<p>所以我就將我知道的東西整理一下, 寫了一封信問 ARM . (還好當時公司有付錢買 ARM 的服務).</p>
<p>ARM 的回答也很乾脆,<br />
關掉那個 L2 Cache I Prefetch 的功能就可以了. 在 PL310 內, 這個功能只是 1 bit 的改變.<br />
(I Prefetch 是 Instruction Prefetch command , 快要執行到指令時, 先去記憶體先抓回來放在 Cache 內)</p>
<p><strong>然後就一切正常了&#8230;..</strong></p>
<p><strong>然後就一切正常了&#8230;..</strong></p>
<p><strong>然後就一切正常了&#8230;..</strong></p>
<p>1 個 bit, 快要一個月的青春啊~~ 所以這個 BUG 記到現在還在記.</p>
<p>這應該算難嗎? 不知道的 BUG 都很難, 知道之後就不難了.</p>
<p>==</p>
<p>後記1: NON-OS 為什麼沒有測出來, 其實 Cache 那邊的參數也是從 NON-OS 來的, 為什麼 NON-OS 沒有問題呢?<br />
猜想是因為 NON-OS 的 Code Size 很小, 所以 Code 都在 L1 Cache 內, 並不會動用到 I prefetch 的功能. 所以自然也驗不出來了.</p>
<p>後記2: 我覺得很多細節我都忘了, 所以這應該只是大致的情節. 雖然寫起來很輕鬆, 但是當時很慘烈呀~~~~</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2015/01/07/1730/%e8%b7%9f%e9%a2%a8-%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e5%b8%ab-%e4%bd%a0%e8%aa%bf%e8%a9%a6%e9%81%8e%e6%9c%80%e9%9b%a3%e7%9a%84-bug/">[跟風] 程式設計師, 你調試過最難的 BUG</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2015/01/07/1730/%e8%b7%9f%e9%a2%a8-%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e5%b8%ab-%e4%bd%a0%e8%aa%bf%e8%a9%a6%e9%81%8e%e6%9c%80%e9%9b%a3%e7%9a%84-bug/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
	</channel>
</rss>
