首页 > 其他分享 ># loongarch架构介绍#[三]地址翻译

# loongarch架构介绍#[三]地址翻译

时间:2023-02-01 22:03:00浏览次数:55  
标签:架构 映射 虚拟地址 地址 页表 loongarch CSR

作者:蒋卫峰 李涛

前言

本文是loongarch架构介绍系列的第三篇文章。前面的第一篇文章介绍了loongarch架构中的基础指令和使用,第二篇文章介绍了内存模型、原子指令与栅障指令的使用。

虚拟内存系统是软硬协同的一个经典案例,如今主流的架构和操作系统都已经支持虚拟内存机制。本文介绍loongarch虚拟内存系统中的地址翻译部分,主要包括地址翻译模式、loongarch中多级页表和相关的配置。另外本文中许多寄存器等资源属于特权资源,因此也会介绍loongarch中的csr特权指令和特权级作为背景知识。

1. 特权级和csr特权指令

虚拟内存相关的寄存器等资源属于特权资源,因此在介绍loongarch虚拟内存相关机制之前,先对loongarch中的特权指令和特权级进行介绍。

1.1 特权级

loongarch架构中有4个特权等级(Privilege Level,简称PLV),分别为PLV0-PLV3。其中PLV0的权限最高,也是唯一可以使用特权指令并访问所有特权资源的特权等级。而PLV3的权限最低。并且PLV1-PLV3这三个特权级下大部分情况下都不能执行特权执行以访问特权资源。

例如,在Linux系统loongarch架构相关代码中,内核态处于PLV0,而用户态处于PLV3。

loongarch架构中有许多控制状态寄存器(CSR),在loongarch资料中一般用CSR.xxx来表示某个控制状态寄存器。cpu当前所处的特权级就由当前模式信息寄存器CSR.CRMD中的PLV域确定,即通过配置CSR.CRMD.PLV可以设置当前特权级。

1.2 csr特权指令

csr特权指令用于访问和配置控制状态寄存器,有以下几种:

  • csrrd:读取CSR。如csrrd rd, csr_num表示将csr_num对应的CSR的值写入到通用寄存器rd中。其中csr_num为loongarch中控制状态寄存器的编号,如CSR.CRMD对应的编号为0。

    如下面代码将CSR.CRMD中值读到临时寄存器t0中:

    csrrd   t0, 0 // CSR.CRMD对应的编号为0
    
  • csrwr:写入CSR。如csrwr rd, csr_num表示将通用寄存器rd中的值写入csr_num对应的CSR,同时将csr_num对应CSR中的旧值返回到rd中。

    如使用下面代码可以设置特权级为PLV3:

    li.d    t0, 0xXXXXXXXXXXXXXXX3 // 最低两位为3
    csrwr   t0, 0
    
  • csrxchg:如csrxchg rd, rj, csr_num表示将通用寄存器rj中的值作为掩码mask,将rd中值写入到csr_num对应CSR中对应掩码为1的那些比特,该CSR中的其余比特不变。同时将csr_num对应CSR中的旧值返回到rd中。

    如以下代码同样可以设置特权级为PLV3:

    li.d    t0, 0x3
    csrxchg t0, t0, 0 // 只将CSR.CRMD最后两位置1
    

下图为CSR.CRMD表中PLV部分描述:

CSR.CRMD.PLV.png

2. 地址空间

loongarch中的虚拟地址空间大小为:

  • LA32中虚拟地址空间大小为$2^{32}$字节

  • LA64中虚拟地址空间大小为$2^{64}$字节

loongarch中的物理地址空间大小为$2^{PALEN}$字节,其中:

  • LA32中,PALEN为一个不超过36的正整数,通常为32

  • LA64中,PALEN为一个不超过60的正整数

  • PALEN由具体的实现决定,软件可以通过CPUCFG指令读取PALEN的值

3. 地址翻译模式

loongarch虚实地址转换机制首先由其地址翻译模式所确定。

loongarch中有两种地址翻译模式:

  • 直接地址翻译模式:在该模式下,物理地址直接等于虚拟地址的低PALEN位,不足补0。相当于没有进行映射。

  • 映射地址翻译模式:在该模式下,又分为两种模式:

    • 直接映射地址翻译模式(简称直接映射模式):相当于线性映射。具体细节见后文中说明。

    • 页表映射地址翻译模式(简称页表映射模式):相当于分页机制。具体细节见后文中说明。

其中,直接地址翻译模式和映射地址翻译模式不能够同时启用。但在映射地址翻译模式下,可以同时启用直接映射模式和页表映射模式,进行地址翻译时,会优先使用直接映射模式,如果无法使用直接映射模式,才会使用页表映射模式进行翻译。

3.1 地址翻译模式的配置

loongarch中通过控制寄存器CSR.CRMD配置地址翻译模式:

  • CSR.CRMD中DA=1且PG=0:直接地址翻译模式
  • CSR.CRMD中DA=0且PG=1:映射地址翻译模式
  • 其他DA和PG值的组合的行为未定义

CSR.CRMD表中DA和PG部分如下图: CSR.CRMD.DAPG.png

类似于上文中特权级的设置,地址翻译模式的设置同样使用csrwr等指令。

3.2 直接映射模式及其配置

loongarch中的直接映射模式是一种线性的映射方式,有点类似于分段。loongarch中通过配置直接映射配置窗口寄存器,来配置直接映射。

共有4个直接映射配置窗口寄存器,CSR.DMW0-CSR.DMW3,配置一个窗口相当于映射一段内存区域。其中CSR.DMW0和CSR.DMW1映射的内存区域可以同时用于取指和load/store操作,而CSR.DMW2和CSR.DMW3映射的内存区域仅用于load/store操作。

下面对直接映射模式配置和映射规则进行说明。

3.2.1 LA32

下面以LA32、且PALEN=32为例进行说明。

LA32中直接映射配置窗口寄存器内容如下图:

CSR.DMW32.png

其中:

  • PLV0等域为使能CSR.DMW寄存器,且与访问特权级相关

  • MAT域与内存一致性模型和内存访问类型相关,可参考上一篇文章

  • PSEG域为配置的物理地址最高3位

  • VSEG域为配置的虚拟地址最高3位

例如,以下代码配置CSR.DMW0,将虚拟地址0x80000000-0x9fffffff映射到物理地址0x0-0x1fffffff:

li.w    t0, 0x80000011
csrwr   t0, 0x180    // 0x180对应CSR.DMW0

解释如下:

  • 0x80000011中,VSEG为0b100,表示匹配的虚拟地址的最高3位为0b100,即虚拟地址0x80000000-0x9fffffff

  • 0x80000011中,PSEG为0b0,表示匹配的物理地址的最高3位为0b0,即对应物理地址0x0-0x1fffffff

3.2.2 LA64

下面以LA64、且PALEN=48为例进行说明。

LA64中直接映射配置窗口寄存器内容如下图:

CSR.DMW64.png

其中:

  • PLV0等域、MAT域与LA32中作用相同

  • VSEG域与LA32中类似,但是有4位

例如,以下代码配置CSR.DMW0,将虚拟地址0x9000000000000000-0x9000ffffffffffff映射到物理地址0x0-0xffffffffffff:

li.d    t0, 0x9000000000000011
csrwr   t0, 0x180    // 0x180对应CSR.DMW0

解释如下:

  • 0x9000000000000011中,VSEG为0x9,表示匹配的虚拟地址的最高4位为0x9,即虚拟地址0x9000000000000000-0x9000ffffffffffff

  • PALEN=48,对应的物理地址为整个$2^{48}$大小的地址范围,即0x0-0xffffffffffff

3.3 页表映射模式及其配置

3.3.1 页表基址

在开启页表映射模式之后,首先需要配置页表基址。

loongarch中可以同时有两个pgd(页全局目录)基址,地址分别存储于寄存器CSR.PGDL(低半地址空间全局目录基址)和CSR.PGDH(高半地址空间全局目录基址),分别对应低半地址空间和高半地址空间。CSR.PGDL和CSR.PGDH如下图:

CSR.PGDL.png

CSR.PGDH.png

上图中,GRLEN表示寄存器长度,VALEN表示虚拟地址长度。LA32中GRLEN为32,VALEN为32;LA64中GRLEN为64,VALEN为64。

低半地址空间和高半地址空间实际上就是对虚拟地址空间对半分成了两个部分。虚拟地址最高位为0则表示处于低半地址空间;为1则表示处于高半地址空间。两个部分的地址都用对应部分的pgd进行地址转换,互不干扰。

在Linux中,CSR.PGDH存放内核进程的pgd,CSR.PGDL中存放用户进程的pgd。loongarch中相当于在硬件上又对内核空间和用户空间的页表进行了隔离。

3.3.2 页表分级

loongarch中可以自定义页表的分级,使用页表前需要配置页表分级。

loongarch中页表的具体分级由寄存器CSR.PWCL和CSR.PWCH决定,这两个寄存器分别控制低半部分和高半部分的页表分级,其中CSR.PWCH只存在于LA64。注:这里的低半部分和高半部分指的是寄存器分成了两部分。CSR.PWCL和CSR.PWCH分别如下图:

CSR.PWCL.png

CSR.PWCH.png

下图是一个多级页表的示例:

multilevel page table.png

解释如下:

  • 其中xxbase表示该级在虚拟地址中的起始位置,xxwidth表示该级在虚拟地址中的长度

  • 以LA64为例,配置Dir4_base、PTbase等域和Dir4_width、PTwidth等域,相当于指定了虚拟地址按分级页表规则的解析方式

  • 虚拟地址的解析过程示例如下:

    1. 首先根据最高位选择CSR.PGDH或CSR.PGDL中的pgd,即目录4的基址

    2. 将虚拟地址中Dir4_base和Dir4_width指定范围的值作为索引,在目录4查找对应目录3的基址

    3. 将虚拟地址中Dir3_base和Dir3_width指定范围的值作为索引,在目录3查找对应目录2的基址

    4. 将虚拟地址中Dir2_base和Dir2_width指定范围的值作为索引,在目录2查找对应目录1的基址

    5. 将虚拟地址中Dir1_base和Dir1_width指定范围的值作为索引,在目录1查找对应末级页表的基址

    6. 将虚拟地址中PTbase和PTwidth指定范围的值作为索引,在末级页表中查找最终页表项

其中具体页表项相关信息见后续文章。

3.3.3 配置

本小节以Linux源码中loongarch下页表基址和分级的配置进行分析。

代码如下:

static void setup_ptwalker(void)
{
    unsigned long pwctl0, pwctl1;
    unsigned long pgd_i = 0, pgd_w = 0; // Dir3_base和Dir3_width
    unsigned long pud_i = 0, pud_w = 0; // Dir2_base和Dir2_width
    unsigned long pmd_i = 0, pmd_w = 0; // Dir1_base和Dir1_width
    unsigned long pte_i = 0, pte_w = 0; // PTbase和PTwidth
    // PTEWidth为0,表示每个表项为64bit
    // Dir4_base和Dir4_width未设置

    pgd_i = PGDIR_SHIFT;
    pgd_w = PAGE_SHIFT - 3;
#if CONFIG_PGTABLE_LEVELS > 3
    pud_i = PUD_SHIFT;
    pud_w = PAGE_SHIFT - 3;
#endif
#if CONFIG_PGTABLE_LEVELS > 2
    pmd_i = PMD_SHIFT;
    pmd_w = PAGE_SHIFT - 3;
#endif
    pte_i = PAGE_SHIFT;
    pte_w = PAGE_SHIFT - 3;

    pwctl0 = pte_i | pte_w << 5 | pmd_i << 10 | pmd_w << 15 | pud_i << 20 | pud_w << 25;
    pwctl1 = pgd_i | pgd_w << 6;

    // 设置CSR.PWCL和CSR.PWCH,LOONGARCH_CSR_PWCTL0为CSR.PWCL
    // LOONGARCH_CSR_PWCTL1为CSR.PWCH
    csr_write64(pwctl0, LOONGARCH_CSR_PWCTL0);
    csr_write64(pwctl1, LOONGARCH_CSR_PWCTL1);

    // 设置CSR.PGDL和CSR.PGDH
    // CSR.PGDH中swapper_pg_dir为内核空间pgd
    // CSR.PGDL为用户空间pgd,暂时设置为invalid_pg_dir,到进程创建等操作时分配
    csr_write64((long)swapper_pg_dir, LOONGARCH_CSR_PGDH);
    csr_write64((long)invalid_pg_dir, LOONGARCH_CSR_PGDL);

    ...
}

总结

本文介绍了地址翻译模式以及相关的配置。下一篇文章将继续对loongarch虚拟内存系统中的其他部分。

更多原创内容请关注:深开鸿技术团队

入门到精通、技巧到案例,系统化分享OpenHarmony开发技术,欢迎投稿和订阅,让我们一起携手前行共建生态。

想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com/#bkwz​

标签:架构,映射,虚拟地址,地址,页表,loongarch,CSR
From: https://blog.51cto.com/harmonyos/6030964

相关文章

  • opencv_contrib全部版本下载地址
    opencv_contrib全部版本下载地址地址:​​https://github.com/opencv/opencv_contrib/tags​​......
  • MTK平台工作原理与架构
    MTK平台工作原理及主要芯片的作用MTK平台按电路功能来划分,可以分成4个组成部分:射频电路部分,控制电路部分,基带电路部分,接口电路部分。如图1-1所示:ANT:天线馈点FEM:F......
  • 开源字体的官方下载地址
    一,思源黑体、思源宋体、思源等宽官方地址:https://github.com/orgs/adobe-fonts/repositories说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.co......
  • 使用IP地址监控工具扫描MAC 地址
    OpUtils包括IP地址监控工具、流氓检测工具和MAC地址解析器,用于日常监控和管理DNS名称、IP和MAC地址。地址监控工具用于IP监控,用于管理DNS名称、网络的IP和M......
  • 三层架构
    三层架构:软件设计架构1.页面层(表示层):用户看的页面,用户可以通过界面上的组件和服务器进行交互2.业务逻辑层:处理业务逻辑的3.数据访问层:操作数据存储文件 ......
  • 随堂笔记3-spring之底层架构核心概念解析
    1.BeanDefinition:bean定义,有一些特定属性描述bean,比如bean类型-class,scope作用域,lazyInit是否懒加载2.beanDefinitionReader:beanDefinition读取器,比如AnnotationBeanDe......
  • 部署在docker里的java程序获取真实的用户ip地址
    目前我们的服务都是全部docker化,网关zuul和各微服务都部署在docker里,构成了集群。用户请求全部到HaProxy,由HaProxy转发到zuul,再由zuul分发给各微服务。那么我们在做黑名单,或......
  • 读Java8函数式编程笔记07_设计和架构的原则
    1. SOLID原则1.1. 开发良好面向对象程序的准则1.2. Liskovsubstitution里氏替换1.3. Interfacesegregation接口隔离1.4. Singleresponsibility单一功能原则1......
  • ARM架构的CentOS7使用virt-manager创建虚拟机提示max socket is 4095
    ARM架构的CentOS7使用virt-manager创建虚拟机提示maxsocketis4095问题描述ARM架构的CentOS7安装libvirt、qemu-kvm和virt-manager后,启动virt-manager后报错:Errorpoll......
  • Git下载地址
    Git下载地址 下载地址:官网--- Git-DownloadingPackage(git-scm.com)  或者阿里云盘----https://www.aliyundrive.com/s/UN8XXgZxRtH(版本Git-2.37.1-64-bi......