原創翻譯,轉載請註明出處。安全
在一些平臺,所謂的內存映射I/O在保序執行這方面是沒有保障的。在這些平臺,驅動寫入器負責保證I/O寫操做按照預期的順序寫到設備內存映射地址。翻譯
表明性的作法是經過讀取一個安全的設備或橋接寄存器,該寄存器能夠致使I/O芯片在任何讀操做發生前刷新全部帶處理的寫操做到設備上。rest
驅動一般在一退出由自旋鎖保護的臨界區代碼時就使用這種技術。這就能夠保證後發生的寫操做只能在以前已有的寫操做的後面執行,這個相似只對I/O操做使用一個內存屏障操做,mb()。
下面舉一個具體例子,假設一個設備驅動:code
... CPU A: spin_lock_irqsave(&dev_lock, flags) CPU A: val = readl(my_status); CPU A: ... CPU A: writel(newval, ring_ptr); CPU A: spin_unlock_irqrestore(&dev_lock, flags) ... CPU B: spin_lock_irqsave(&dev_lock, flags) CPU B: val = readl(my_status); CPU B: ... CPU B: writel(newval2, ring_ptr); CPU B: spin_unlock_irqrestore(&dev_lock, flags) ...
以上例子會發生設備可能接收到newval2在newval以前,這樣就會引發問題,須要以下修改才能正常:blog
... CPU A: spin_lock_irqsave(&dev_lock, flags) CPU A: val = readl(my_status); CPU A: ... CPU A: writel(newval, ring_ptr); CPU A: (void)readl(safe_register); /* maybe a config register? */ CPU A: spin_unlock_irqrestore(&dev_lock, flags) ... CPU B: spin_lock_irqsave(&dev_lock, flags) CPU B: val = readl(my_status); CPU B: ... CPU B: writel(newval2, ring_ptr); CPU B: (void)readl(safe_register); /* maybe a config register? */ CPU B: spin_unlock_irqrestore(&dev_lock, flags)
這樣,想safe_register讀取就會讓I/O芯片在收到讀操做以前刷新以前的未處理的寫操做,從而防止數據污染。內存