2016-01-06 71 views
2

我試圖做一個內核模塊來啓用x87 FPU的FOP兼容模式。這是通過設置IA32_MISC_ENABLE MSR中的位2完成的。下面的代碼:如何在所有CPU上執行一段內核代碼?

#include <linux/init.h> 
#include <linux/module.h> 
#include <linux/kernel.h> 
#include <asm/msr-index.h> 
#include <asm/msr.h> 

MODULE_LICENSE("GPL"); 
MODULE_AUTHOR("10110111"); 
MODULE_DESCRIPTION("Module to enable FOPcode compatibility mode"); 
MODULE_VERSION("0.1"); 

static int __init fopCompat_init(void) 
{ 
    unsigned long long misc_enable=native_read_msr(MSR_IA32_MISC_ENABLE); 
    printk(KERN_INFO "Before trying to set FOP_COMPAT, IA32_MISC_ENABLE=%llx," 
        " i.e. FOP_COMPAT is %senabled\n" 
        ,misc_enable,misc_enable&MSR_IA32_MISC_ENABLE_X87_COMPAT?"":"NOT "); 

    wrmsrl(MSR_IA32_MISC_ENABLE,misc_enable|MSR_IA32_MISC_ENABLE_X87_COMPAT); 
    misc_enable=native_read_msr(MSR_IA32_MISC_ENABLE); 

    printk(KERN_INFO "Tried to set FOP_COMPAT. Result: IA32_MISC_ENABLE=%llx," 
        " i.e. FOP_COMPAT is now %senabled\n" 
        ,misc_enable,misc_enable&MSR_IA32_MISC_ENABLE_X87_COMPAT?"":"NOT "); 
    return 0; 
} 

static void __exit fopCompat_exit(void) 
{ 
    const unsigned long long misc_enable=native_read_msr(MSR_IA32_MISC_ENABLE); 
    printk(KERN_INFO "Quitting FOP-compat with IA32_MISC_ENABLE=%llx\n",misc_enable); 
    if(!(misc_enable & MSR_IA32_MISC_ENABLE_X87_COMPAT)) 
     printk(KERN_INFO "NOTE: seems some CPUs still have to be set up, " 
         "or compatibility mode will work inconsistently\n"); 
    printk(KERN_INFO "\n"); 
} 

module_init(fopCompat_init); 
module_exit(fopCompat_exit); 

看來工作,但在多個insmod/rmmod週期我有時會dmesg輸出仍然不啓用兼容模式,雖然它做wrmsr後立即。在經過一番思考之後,我意識到這是因爲模塊代碼是在不同的邏輯CPU上執行的(我有4個內核* HT = 8個邏輯CPU的Core i7),所以我有1/8的機會在執行rmmod 。重複該循環大約20次後,我得到了一致的「啓用」打印,並且我的用戶空間應用程序很高興地使用它。

所以現在我的問題是:如何讓我的代碼在系統上的所有邏輯CPU上執行,以便爲所有邏輯CPU啓用兼容模式?

回答

5

用於執行代碼在每個CPU上使用on_each_cpu函數。

簽名:

int on_each_cpu(void (*func) (void *info), void *info, int wait) 

說明:

呼籲所有處理器的功能。

如果wait參數非零,它將等待函數在所有CPU上完成。

功能func不應該睡覺,但整個on_each_cpu()調用不應該在原子上下文中完成。

相關問題