2016-01-06 66 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()调用不应该在原子上下文中完成。

相关问题