当前位置: 首页 > java >正文

linux之 内存管理(6)-arm64 内核虚拟地址空间变化

一、新内核变动

           kernel变化的真快,之前我记得4.x的内核的内核空间的线性映射区位于内核空间的高地址处的128TB,且当前的博客和一些书籍也都还是这样介绍。可翻了翻kernel的Documentation/arm64/memory.rst文档,发现最新的kernel已将这128TB移到了内核空间的最低地址处了。具体是2019年8月的一个commit,如下:

commit 14c127c957c1c6070647c171e72f06e0db275ebf
Author: Steve Capper <steve.capper@arm.com>
Date:   Wed Aug 7 16:55:14 2019 +0100arm64: mm: Flip kernel VA spaceIn order to allow for a KASAN shadow that changes size at boot time, onemust fix the KASAN_SHADOW_END for both 48 & 52-bit VAs and "grow" thestart address. Also, it is highly desirable to maintain the samefunction addresses in the kernel .text between VA sizes. Both of theserequirements necessitate us to flip the kernel address space halves s.t.the direct linear map occupies the lower addresses.This patch puts the direct linear map in the lower addresses of thekernel VA range and everything else in the higher ranges.

 二、虚拟地址空间

内核 4.x  和 5.0 版本的虚拟地址空间分布:

新arm64 内存分布:我的内核版本是5.15

各体系架构处理器的虚拟地址空间的布局各不相同,下面是ARM64位处理器使用48位虚拟地址,4级页表,页面大小4KB时的layout:

Start                 End                     Size            Use
-----------------------------------------------------------------------
0000000000000000      0000ffffffffffff         256TB          user
ffff000000000000      ffff7fffffffffff         128TB          kernel logical memory map
ffff800000000000      ffff9fffffffffff          32TB          kasan shadow region
ffffa00000000000      ffffa00007ffffff         128MB          bpf jit region
ffffa00008000000      ffffa0000fffffff         128MB          modules
ffffa00010000000      fffffdffbffeffff         ~93TB          vmalloc
fffffdffbfff0000      fffffdfffe5f8fff        ~998MB          [guard region]
fffffdfffe5f9000      fffffdfffe9fffff        4124KB          fixed mappings
fffffdfffea00000      fffffdfffebfffff           2MB          [guard region]
fffffdfffec00000      fffffdffffbfffff          16MB          PCI I/O space
fffffdffffc00000      fffffdffffdfffff           2MB          [guard region]
fffffdffffe00000      ffffffffffdfffff           2TB          vmemmap
ffffffffffe00000      ffffffffffffffff           2MB          [guard region]

地址空间的定义:

内核中划分的这么多区域,且都有自己对应的地址与大小,这些地址和大小在kernel中哪里定义着呢?具体位于:arch/arm64/include/asm/memory.h。

#define PAGE_OFFSET             (_PAGE_OFFSET(VA_BITS))
#define KIMAGE_VADDR            (MODULES_END)
#define BPF_JIT_REGION_START    (KASAN_SHADOW_END)
#define BPF_JIT_REGION_SIZE     (SZ_128M)
#define BPF_JIT_REGION_END      (BPF_JIT_REGION_START + BPF_JIT_REGION_SIZE)
#define MODULES_END             (MODULES_VADDR + MODULES_VSIZE)
.....
  • PAGE_OFFSET
    内核线性映射区的起始地址,大小为128TB。
  • KASAN_SHADOW_START
    KASAN影子内存的起始虚拟地址,大小为32TB。为什么是32TB呢?因为KASAN通常使用1:8或1:16比例的内存来做影子内存,分别对应大小为256TB/8=32TB或256TB/16=16TB,这里表示的是1:8的情况所以是32TB。
  • KIMAGE_VADDR
    定义了内核镜像的链接地址,通过其定义"#define KIMAGE_VADDR (MODULES_END)"看出它整好位于modules区域的结尾处,即vmalloc区域的起始地址。vmlinux.ld.S文件设置链接地址时会用到它,start_kernel->paging_init->map_kernel会将内核镜像的各个段依次映射到该区域。
  • VMALLOC_START
    定义了vmalloc区域的起始地址,大小约等于93TB。记得之前ARM32可以通过bootargs去控制vmalloc区域的大小,不知道64还有没。但是有没有也没所谓了,毕竟64位的处理器上虚拟地址空间已不像32位处理器那么紧张。
  • VMEMMAP_START
    定义了vmemmap区域的起始地址,大小2TB。sparsemem内存模型中用来存放所有struct page的虚拟地址空间。

寄存器TTBR0和TTBR1:

本文讲到了内核地址空间和用户地址空间,这就不得不提一下ARM64相关的两个寄存器TTBR0和TTBR1。它们的功能类似于X86里的CR3寄存器用来存放进程的1级页表(PGD)的基地址。但不同的是ARM64使用了两个寄存器分别存放用户空间和内核空间的1级页表基地址。

我们知道所有进程的内核地址空间的页表是共用一套的,所以TTBR1中的内容不会改变,永远等于init_mm->swapper_pg_dir。但各个进程的用户空间的页表各自独立,那么TTBR0中的内容则等于各自进程的task_struct->mm_struct->pgd

最后提一下,处理器如何知道什么时候访问TTBR0,什么时候访问TTBR1呢?ARMv8手册中有提到,当CPU访问地址时,若地址的第63bit为1则自动使用TTBR1,为0则使用TTBR0。

备注: 各个版本的虚拟地址分布, 有一点差异,但是大致区域是一致。比如不同的地方:

上面的知乎网友的图, vmalloc_start 的地址是 0xffffa00000000000; 而我打印的  vmalloc_start 的地址是 0xffff800010000000;

http://www.xdnf.cn/news/12991.html

相关文章:

  • Conda安装pytorch和cuda出现问题的解决记录
  • pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
  • Java多线程实现之Thread类深度解析
  • 【Kafka】Kafka从入门到实战:构建高吞吐量分布式消息系统
  • GeoDrive:基于三维几何信息有精确动作控制的驾驶世界模型
  • 快速使用 Flutter 的 Dialog 和 AlertDialog
  • Delivering Arbitrary-Modal Semantic Segmentation(CVPR2023)任意模态语义分割论文阅读
  • 基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
  • 如何把工业通信协议转换成http websocket
  • MongoDB 入门指南:安装、配置与 Navicat 连接教程
  • Vue3学习(接口,泛型,自定义类型,v-for,props)
  • 时间同步技术在电力系统中的应用
  • 水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关
  • 达梦数据库CASE WHEN条件
  • Spring Boot 启动流程详解
  • 打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
  • Android Native 之 lmkd进程分析
  • 嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)
  • NLP-数据集
  • wifi改ip地址有什么用?wifi改ip地址怎么改
  • LeetCode - 3. 无重复字符的最长子串
  • 无源一阶低通电路噪声如何计算
  • 音乐“穿梭机”AudioRelay,让你的音频“无缝对接”
  • push [特殊字符] present
  • 深入解析 Qwen3 基础模型:架构设计与技术创新
  • 第2课 SiC MOSFET与 Si IGBT 静态特性对比
  • 从0开始学习R语言--Day20--Wilcoxon秩和检验
  • 组件库实战-基建思路
  • Docker拉取MySQL后数据库连接失败的解决方案
  • P3 QT项目----记事本(3.8)