如何在所有CPU上执行一段内核代码?

时间:2016-01-06 12:50:01

标签: linux-kernel multiprocessing msr

我正在尝试制作内核模块,以便为x87 FPU启用FOP兼容模式。这是通过设置IA32_MISC_ENABLE MSR中的位2来完成的。这是代码:

#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上执行的(我的Core i7有4核* HT = 8个逻辑CPU),所以我有1/8的机会获得&#34 ;启用&#34;在rmmod上打印。重复循环约20次后,我得到了一致的启用&#34;打印,我的用户空间应用程序很乐意使用它。

所以现在我的问题是:如何让我的代码在系统上的所有逻辑CPU上执行,以便为所有这些CPU启用兼容模式?

1 个答案:

答案 0 :(得分:5)

对于每个CPU上的执行代码,使用on_each_cpu函数。

签名:

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

说明

  

在所有处理器上调用函数。

如果wait参数非零,则等待所有CPU上的函数完成。

函数func不应该休眠,但不应在原子上下文中完成整个on_each_cpu()调用。