标签: mmu

Linux页表管理和MMU

我对linux内核和MMU之间的关系有疑问.我现在明确指出Linux内核管理虚拟内存地址和物理内存地址之间的页表.同时在x86架构中有MMU,它管理虚拟内存地址和物理内存地址之间的页表.如果MMU出现在CPU附近,内核是否还需要处理页表?

这个问题可能是愚蠢的,但另一个问题是,如果MMU负责内存空间,谁管理高内存和低内存?我相信内核将从MMU接收虚拟内存大小(4位,32位),然后内核将区分虚拟地址中的用户空间和内核空间.我对么?还是完全错了?

非常感谢提前!

linux kernel computer-architecture mmu

8
推荐指数
1
解决办法
5953
查看次数

桌面操作系统上的C编译器使用多少个内存页来检测堆栈溢出?

这个问题涉及但来自不同这一个约在C99可变长度数组.

答案指出,在堆栈中分配可变长度数组(或者只是固定大小的大数组)的一个危险是分配可能会无声地失败,而不是调用malloc,这显然告诉调用者分配是否成功.

现代非嵌入式编译平台使用无效的内存区域来检测一些堆栈溢出,而无需额外成本(检查只是MMU已经免费进行的检查).这不能保证100%免受上述问题的影响,因为非常大的本地数组可能导致堆栈指针跳过无效区域.

有没有人知道通常会为此检测分配多少页?我想这至少是4KiB,但它可能会更多.这是由编译器或操作系统做出的选择,在任何一种情况下,有没有办法改变它?

c c99 variable-length-array mmu

7
推荐指数
2
解决办法
347
查看次数

现代cpus如何处理跨页不对齐访问?

我试图理解未对齐的内存访问(UMA)如何在现代处理器(即x86-64和ARM体系结构)上工作.我知道我可能遇到UMA问题,从性能下降到CPU故障.我阅读posix_memalign并缓存行.

我找不到的是当我的请求超出页面边界时,现代系统/硬件如何处理这种情况?

这是一个例子:

  1. malloc()是一块8KB的内存.
  2. 假设malloc()没有足够的内存和sbrk()8KB的话.
  3. 内核获取两个内存页(每个4KB)并将它们映射到我的进程的虚拟地址空间(假设这两个页面在内存中不是一个接一个)
  4. movq (offset + $0xffc), %rax 我从第4092字节开始请求8个字节,这意味着我需要从第一页末尾开始的4个字节和从第二页开始开始的4个字节.

物理内存:

---|---------------|---------------|-->
   |... 4b|        |        |4b ...|-->
Run Code Online (Sandbox Code Playgroud)

我需要在页面边界分割的8个字节.

x86-64和ARM上的MMU如何处理这个问题?内核MM中是否有任何机制以某种方式为这种请求做准备?是否有某种保护malloc?处理器做什么?他们取两页吗?

我的意思是完成这样的请求MMU必须将一个虚拟地址转换为两个物理地址.它如何处理这样的请求?

如果我是软件程序员,我应该关心这些事情吗?为什么?

我正在阅读谷歌,SO,drepper的cpumemory.pdf和gorman的Linux VMM书中的很多链接.但它是一个信息的海洋.如果您至少向我提供一些我可以使用的指针或关键字,那将会很棒.

linux arm x86-64 memory-alignment mmu

6
推荐指数
1
解决办法
917
查看次数

为什么访问未映射的位置不会产生硬件异常(Microblaze)

我想编写我的代码来处理Microblaze上的TLB未命中,当然还有页面表等.这些都是在OVPsim上完成的.

在我学习的过程中,我编写了这个小程序集以引用未映射的位置(0x1000000) - 我将此作为特权代码运行,其中VM为:

ori r20, r0, 0
ori r12, r0, 0x1000000
/* next line should break it */
sw  r20, r12, r0
Run Code Online (Sandbox Code Playgroud)

(即,将内容写入r20 == 0ORing形成的地址r12 == 0x1000000,r0 == 0 => 0x1000000显然.)

但是,GDB没有跳转到异常向量,而是报告"程序收到SIGSEV" - 我出错了什么?我没有在MSR中启用硬件异常位,但是手册说你无法在任何情况下掩盖这些异常,所以这不应该是问题.

进一步的信息我不能得到任何(例如,包括错位异常)要执行的异常处理代码,(除非我明确地调用它),无论我是否使用调试器.关闭调试器后,我从OVPsim得到这个输出(NB我只是改变了测试地址 - 上面的0xA000000和0x100000之间没有区别):

Processor Exception (PC_PRX) Processor 'platform/cpu0' 0x248: sw       r20, r12, r0
Processor Exception (PC_WPX) No write access at 0xa000000
Run Code Online (Sandbox Code Playgroud)

这是所有代码都以特权模式运行,所以除非我没有正确配置Microblaze ,否则我没有看到它没有调用处理程序的明显原因.我打开了这些:

icmAddStringAttr(cpu1_attr, "endian", "big");
icmAddDoubleAttr(cpu1_attr, "mips", 100.000000);
icmAddStringAttr(cpu1_attr, "variant", "V8_20");
icmAddBoolAttr(cpu1_attr, "verbose", …
Run Code Online (Sandbox Code Playgroud)

gdb memory-management microblaze mmu ovp

6
推荐指数
1
解决办法
669
查看次数

禁用ARM中内存页面的写保护

我已经研究了在linux上禁用内核文本写保护的主题,我只能找到x86 linux的解决方案,它暂时清除cr0寄存器的第16位,写入内存,然后设置第16位cr0再次注册.但是,这对ARMv6及更高版本不起作用.这方面的一个例子是在这个页面内:Linux内核:系统调用挂钩示例.

ARM体系结构中不存在cr0寄存器,并且在链接的答案中声明的一些函数(如lookup_address,change_page_attr等)也不存在于ARM中.我尝试了ARM中存在的解决方案,比如set_memory_rw(没有改变任何东西,写入内核文本仍会导致oops),mem_text_write_kernel_word(写入内核文本仍会导致oops)等.

oops日志示例(格式化为演示文稿):

<3>[  239.987689] RKP -> Inst bf3e0098 out of cpu_v7_set_pte_ext range\
 from c01159c4 to c0115a1c
<1>[  239.988079] Unable to handle kernel paging request at virtual\
 address c01c1d50
<1>[  239.988123] pgd = ea8e4000
<1>[  239.988280] [c01c1d50] *pgd=0da00011
<0>[  239.988377] Internal error: Oops: 80f [#1] PREEMPT SMP ARM
<4>[  239.988416] Modules linked in: my_mod(O+) wlan(PO) mhi(O)
<4>[  239.988469] CPU: 0 PID: 5443 Comm: insmod \
 Tainted: P        W  O 3.10.0-2413392 #1
<4>[  239.988521] task: e4af4ec0 ti: da95a000 …
Run Code Online (Sandbox Code Playgroud)

arm linux-kernel mmu

6
推荐指数
1
解决办法
1552
查看次数

手臂架构领域意味着什么

当我在Cortex-A9 MPCore中调试MMU时,总是看到域访问控制寄存器,但是域的含义是什么?最多16个域?有人可以给我一个链接来解释吗?

arm mmu cortex-a

6
推荐指数
1
解决办法
1124
查看次数

如何调试aarch64翻译错误?

我在armv8(aarch64)中编写了一个简单的内核。

MMU配置:

  • 48 VA位(T1SZ = 64-48 = 16)
  • 4K页面大小
  • 所有物理RAM平面映射到内核虚拟内存(在TTBR1_EL1上)(MMU在TTBR0_EL1 = 0时处于活动状态,因此我仅使用0xffff <addr>中的地址,所有地址均映射到物理内存中)

我正在将新的地址空间(从1 << 40开始)映射到一些空闲的物理区域。当我尝试访问地址1 << 40时,出现异常(类型为“使用SP1的EL1,同步”):

ESR_EL1=0x96000044
FAR_EL1=0xffff010000000000
Run Code Online (Sandbox Code Playgroud)

检查其他寄存器,我有:

TTBR1_EL1=0x82000000
TTBR1_EL1[2]=0x0000000082003003
Run Code Online (Sandbox Code Playgroud)

因此,基于《 ARMv8的ARM体系结构参考手册》(ARMv8-A配置文件):

  • ESR(异常征兆寄存器)转换为:D7-1933平方英尺上的异常类= 100101(数据异常中止而没有更改异常级别);WnR = 1(故障指令为写操作);D7-1958 页的DFSC = 0b000100(0级转换错误);
  • FAR_EL1是故障地址;它指示使用了TTBR1_EL1(因为高位全为1)。VA的前9位为0b000000010,表示表中使用了条目2;
  • 该表中的条目2指示位于物理地址0x82003000的下一级表(低位0b11)。

因此,转换在0级失败,而在0级应该失败。

我的问题是:我做错什么了吗?我是否缺少一些可能导致翻译错误的信息?而且,更一般而言,如何调试翻译错误?

更新:
在启用MMU之前我写表时一切都正常。
每当我在启用MMU之后(通过平面映射表区域)写入表时,映射就永远无法进行。我不知道为什么会这样。

我还尝试了手动写入选定的表(以消除我的mmapping函数的任何副作用):相同的结果(当在MMU开启之前完成写操作时,它会起作用;而在失败之后,它会失败)。

我尝试进行操作tlbidsb sy说明,其后isb没有效果。此时只有一个CPU正在运行,因此缓存应该不是问题-编写指令和MMU可以访问相同的缓存(但我将在下一步进行测试)。

kernel arm mmu arm64 armv8

6
推荐指数
1
解决办法
4295
查看次数

CPU 物理地址空间如何映射到物理 DRAM?

在系统内存映射(也称为 cpu 内存映射)中,地址范围被分配给 RAM 内存范围,MMIO 用于 PCI 设备等。

让我们举一个例子,其中 RAM 的地址范围从地址 0 开始到 512MB,其中包括 DOS 兼容内存空间,从 0 开始到 1MB。

现在当我们说这 512MB 的区域将被映射到内存中时,这是否意味着 CPU 地址空间中的地址 0 将被映射到物理 RAM 中的地址 0,并且同样高达 512MB?如果不是那么映射是如何完成的?

CPU地址空间中分配的内存地址范围是否与系统中安装的RAM大小完全相等?如果不是这种情况,那么在这种情况下如何进行映射?

另外,DOS 兼容区域的内存映射将如何完成?如果使用 DOS 以外的操作系统,该区域是否会在内存中未被使用?

内存映射是否意味着当 CPU 生成从 0 到 512 MB 的地址时,只会重定向到 RAM 中?CPU 生成的任何其他地址永远不会被 MMU 定向到 RAM 中?在这种情况下,所有应用程序的地址都在 0 到 512MB 之间,以便访问内存?

我在这里考虑使用 x86 系统。

memory x86 cpu-architecture memory-address mmu

6
推荐指数
1
解决办法
1493
查看次数

在C中访问两个不连续的内存块作为单个连续块?

在Linux的用户空间:假设我分配的3MiB连续存储ABC,其中A,BC各1MiB.有没有办法以某种方式AC作为单个连续2MiB内存访问(一种用户空间MMU)?

背景:我的方案是用C模拟ASIC芯片.芯片有一个3MiB内存,芯片中的两个组件可以访问相同的内存硬件,但具有不同的地址映射.要在C中对其进行建模,一种方法可能是为两个组件复制3MiB内存,并在两个内存副本之间添加一些同步机制.另一种方式可能是只有一个3MiB内存副本,一个组件按原样访问内存,而另一个组件则添加一种包装器来进行地址转换.我只是想知道是否有更简洁的方法,避免内存重复和地址转换包装...

PS:根据Maxim的回答,我写了一个简单的测试程序,它只是起作用.看来我不应该MAP_ANONYMOUSE为我的目的使用旗帜.另外,根据mmap()手册,为了MAP_FIXED正常工作,对齐C应该是PAGE_SIZE目标平台上的多个(我的x86_64 Ubuntu).我粘贴下面的代码以防万一...

#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>

#define SZ_A     (64 * 1024)   // A
#define SZ_B    (204 * 1024)   // B
#define SZ_C      (4 * 1024)   // C
#define SZ_ABC  (272 * 1024)   // ABC
#define SZ_AB   (268 * 1024)   // AB
#define SZ_AC    (68 * 1024) …
Run Code Online (Sandbox Code Playgroud)

c linux mmu

6
推荐指数
1
解决办法
141
查看次数

内核中 MMU 上下文中的 PMM 竞技场是什么(锆石/紫红色)

我想了解 Zircon 的(Fuchsia OS 内核)如何在 ARM64 中分配页面,所以我找到了 mmu.cpp https://fuchsia.googlesource.com/fuchsia/+/4277d3203daa0fc5e4dd1625cf96891dd9882f44/zircon/zircon/ .cc#328

但它只是:

  if (likely(!test_page_alloc_func_)) {
    status = pmm_alloc_page(0, &page, paddrp);
  }
Run Code Online (Sandbox Code Playgroud)

从哪里来pmm_alloc_pagehttps : //fuchsia.googlesource.com/fuchsia/+/4277d3203daa0fc5e4dd1625cf96891dd9882f44/zircon/kernel/vm/pmm.cc#61

此处定义的 pmm 节点:https : //fuchsia.googlesource.com/fuchsia/+/4277d3203daa0fc5e4dd1625cf96891dd9882f44/zircon/kernel/vm/pmm_node.h说:

// per numa node collection of pmm arenas and worker threads
class PmmNode {
Run Code Online (Sandbox Code Playgroud)

我在谷歌和 Fuchsia 文档中都找不到 PMM 区域是什么。有人可以向我澄清这些概念吗?

我想了解在 Zircon 内核上的 ARM64 中如何处理 MMU

kernel mmu fuchsia

6
推荐指数
1
解决办法
72
查看次数