简体   繁体   English

如何在不崩溃Linux内核的情况下访问mmaped / dev / mem?

[英]How to access mmaped /dev/mem without crashing the Linux kernel?

I have a simple program that tries to access the physical memory in user space, where the kernel stores the 1st struct page. 我有一个简单的程序,尝试访问用户空间中的物理内存,内核在其中存储了第一个struct页面。 On a 64 bit machine this address is: 在64位计算机上,此地址为:

  • kernel virtual address: ffffea0000000000 内核虚拟地址:ffffea0000000000
  • physical address: 0000620000000000 物理地址:0000620000000000

I am trying to access this physical address through mmap in user space. 我正在尝试通过用户空间中的mmap访问此物理地址。 But the following code crashes the kernel. 但是以下代码使内核崩溃。

int *addr;
if ((fd = open("/dev/mem", O_RDWR|O_SYNC)) < 0 ) {
    printf("Error opening file. \n");
    close(fd);
    return (-1);
}
/* mmap.  address of first struct page for 64 bit architectures 
 * is 0x0000620000000000.
 */
addr = (int *)mmap(0, num*STRUCT_PAGE_SIZE, PROT_READ, MAP_PRIVATE,
            fd, 0x0000620000000000);
printf("addr: %p \n",addr);
printf("addr: %d \n",*addr); /* CRASH. */

I think I've found the issue -- it's to do with /dev/mem memory mapping protection on the x86. 我想我已经找到了问题-与x86上的/ dev / mem内存映射保护有关。

Pl refer to this LWN article: "x86: introduce /dev/mem restrictions with a config option" http://lwn.net/Articles/267427/ 请参阅此LWN文章:“ x86:通过配置选项引入/ dev / mem限制” http://lwn.net/Articles/267427/

CONFIG_NONPROMISC_DEVMEM CONFIG_NONPROMISC_DEVMEM

Now (i tested this on a recent 3.2.21 kernel), the config option seems to be called CONFIG_STRICT_DEVMEM. 现在(我在最近的3.2.21内核上对此进行了测试),config选项似乎称为CON​​FIG_STRICT_DEVMEM。

I changed my kernel config: 我更改了内核配置:

$ grep DEVMEM .config
# CONFIG_STRICT_DEVMEM is not set
$ 

When the above prg was run with the previous kernel, with CONFIG_STRICT_DEVMEM SET: dmesg shows: 当上述prg与先前的内核一起运行时,使用CONFIG_STRICT_DEVMEM SET设置:dmesg显示:

[29537.565599] Program a.out tried to access /dev/mem between 1000000->1001000.
[29537.565663] a.out[13575]: segfault at ffffffff ip 080485bd sp bfb8d640 error 4 in a.out[8048000+1000]

This is because of the kernel protection.. 这是由于内核保护。

When the kernel was rebuilt (with the CONFIG_STRICT_DEVMEM UNSET ) and the above prg was run : 重建内核(使用CONFIG_STRICT_DEVMEM UNSET )并运行上述prg时:

# ./a.out 
mmap failed: Invalid argument
# 

This is because the 'offset' parameter is > 1 MB (invalid on x86) (it was 16MB). 这是因为'offset'参数> 1 MB(在x86上无效)(当时为16MB)。

After making the mmap offset to be within 1 MB: 将mmap偏移量控制在1 MB以内:

# ./a.out 
addr: 0xb7758000
*addr: 138293760 
# 

It works! 有用! See the above LWN article for details. 有关详细信息,请参见上面的LWN文章。

On x86 architectures with PAT support (Page Attribute Table), the kernel still prevents the mapping of DRAM regions. 在具有PAT支持(页面属性表)的x86体系结构上,内核仍然阻止DRAM区域的映射。 The reason for this as mentioned in the kernel source is: 内核源代码中提到的原因是:

This check is nedded to avoid cache aliasing when PAT is enabled

This check will cause a similar error to the one mentioned above. 此检查将导致与上述错误类似的错误。 For example: 例如:

Program a.out tried to access /dev/mem between [mem 68200000-68201000].

This restriction can be removed by disabling PAT. 可以通过禁用PAT来消除此限制。 PAT can be disabled by adding the "nopat" argument to the kernel command line at boot time. 可以通过在启动时将“ nopat”参数添加到内核命令行来禁用PAT。

On x86 architectures with PAT support (Page Attribute Table), the kernel can prevent the mapping of DRAM regions (even if it is compiled without setting CONFIG_NONPROMISC_DEVMEM). 在具有PAT支持(页面属性表)的x86架构上,内核可以防止DRAM区域的映射(即使在未设置CONFIG_NONPROMISC_DEVMEM的情况下进行编译)。

The reason for this as mentioned in the kernel source is: 内核源代码中提到的原因是:

This check is nedded to avoid cache aliasing when PAT is enabled

This check will cause a similar error to appear in dmesg as the one mentioned in kaiwan's answer above above. 此检查将导致dmesg出现与上面kaiwan的答案中提到的错误类似的错误。 For example: 例如:

Program a.out tried to access /dev/mem between [mem 68200000-68201000].

This restriction can be removed by disabling PAT. 可以通过禁用PAT来消除此限制。

PAT can be disabled by adding the nopat argument to the kernel command-line at boot time. 可以通过在引导时将nopat参数添加到内核命令行来禁用PAT。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM