想了解更多关于开源的址翻内容,请访问:
51CTO 开源基础软件社区
https://ost.51cto.com
本文是构介loongarch架构介绍系列的第三篇文章。前面的绍地第一篇文章介绍了loongarch架构中的基础指令和使用,第二篇文章介绍了内存模型、址翻原子指令与栅障指令的构介使用。
虚拟内存系统是绍地软硬协同的一个经典案例,如今主流的址翻架构和操作系统都已经支持虚拟内存机制。本文介绍loongarch虚拟内存系统中的构介地址翻译部分,主要包括地址翻译模式、绍地loongarch中多级页表和相关的址翻配置。另外本文中许多寄存器等资源属于特权资源,构介因此也会介绍loongarch中的绍地csr特权指令和特权级作为背景知识。
虚拟内存相关的寄存器等资源属于特权资源,因此在介绍loongarch虚拟内存相关机制之前,先对loongarch中的特权指令和特权级进行介绍。
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可以设置当前特权级。
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部分描述:
loongarch中的虚拟地址空间大小为:
loongarch中的物理地址空间大小为2^{ PALEN}2PALEN字节,其中:
loongarch虚实地址转换机制首先由其地址翻译模式所确定。
loongarch中有两种地址翻译模式:
直接地址翻译模式:在该模式下,物理地址直接等于虚拟地址的低PALEN位,不足补0。相当于没有进行映射。
映射地址翻译模式:在该模式下,又分为两种模式:
其中,直接地址翻译模式和映射地址翻译模式不能够同时启用。但在映射地址翻译模式下,可以同时启用直接映射模式和页表映射模式,进行地址翻译时,会优先使用直接映射模式,如果无法使用直接映射模式,才会使用页表映射模式进行翻译。
loongarch中通过控制寄存器CSR.CRMD配置地址翻译模式:
CSR.CRMD表中DA和PG部分如下图:
类似于上文中特权级的设置,地址翻译模式的设置同样使用csrwr等指令。
loongarch中的直接映射模式是一种线性的映射方式,有点类似于分段。loongarch中通过配置直接映射配置窗口寄存器,来配置直接映射。
共有4个直接映射配置窗口寄存器,CSR.DMW0-CSR.DMW3,配置一个窗口相当于映射一段内存区域。其中CSR.DMW0和CSR.DMW1映射的内存区域可以同时用于取指和load/store操作,而CSR.DMW2和CSR.DMW3映射的内存区域仅用于load/store操作。
下面对直接映射模式配置和映射规则进行说明。
下面以LA32、且PALEN=32为例进行说明。
LA32中直接映射配置窗口寄存器内容如下图:
其中:
例如,以下代码配置CSR.DMW0,将虚拟地址0x80000000-0x9fffffff映射到物理地址0x0-0x1fffffff:
li.w t0, 0x80000011
csrwr t0, 0x180 // 0x180对应CSR.DMW0
解释如下:
下面以LA64、且PALEN=48为例进行说明。
LA64中直接映射配置窗口寄存器内容如下图:
其中:
例如,以下代码配置CSR.DMW0,将虚拟地址0x9000000000000000-0x9000ffffffffffff映射到物理地址0x0-0xffffffffffff:
li.d t0, 0x9000000000000011
csrwr t0, 0x180 // 0x180对应CSR.DMW0
解释如下:
在开启页表映射模式之后,首先需要配置页表基址。
loongarch中可以同时有两个pgd(页全局目录)基址,地址分别存储于寄存器CSR.PGDL(低半地址空间全局目录基址)和CSR.PGDH(高半地址空间全局目录基址),分别对应低半地址空间和高半地址空间。CSR.PGDL和CSR.PGDH如下图:
上图中,GRLEN表示寄存器长度,VALEN表示虚拟地址长度。LA32中GRLEN为32,VALEN为32;LA64中GRLEN为64,VALEN为64。
低半地址空间和高半地址空间实际上就是对虚拟地址空间对半分成了两个部分。虚拟地址最高位为0则表示处于低半地址空间;为1则表示处于高半地址空间。两个部分的地址都用对应部分的pgd进行地址转换,互不干扰。
在Linux中,CSR.PGDH存放内核进程的pgd,CSR.PGDL中存放用户进程的pgd。loongarch中相当于在硬件上又对内核空间和用户空间的页表进行了隔离。
loongarch中可以自定义页表的分级,使用页表前需要配置页表分级。
loongarch中页表的具体分级由寄存器CSR.PWCL和CSR.PWCH决定,这两个寄存器分别控制低半部分和高半部分的页表分级,其中CSR.PWCH只存在于LA64。注:这里的低半部分和高半部分指的是寄存器分成了两部分。CSR.PWCL和CSR.PWCH分别如下图:
下图是一个多级页表的示例:
解释如下:
其中xxbase表示该级在虚拟地址中的起始位置,xxwidth表示该级在虚拟地址中的长度
以LA64为例,配置Dir4_base、PTbase等域和Dir4_width、PTwidth等域,相当于指定了虚拟地址按分级页表规则的解析方式
虚拟地址的解析过程示例如下:
其中具体页表项相关信息见后续文章。
本小节以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虚拟内存系统中的其他部分。
想了解更多关于开源的内容,请访问:
51CTO 开源基础软件社区
https://ost.51cto.com
责任编辑:jianghua 来源: 51CTO 开源基础软件社区 地址翻译模式loongarch(责任编辑:焦点)
智升集团控股(08370.HK)发布业绩公告:全年公司拥有人应占亏损2700万元
人民币中间价升幅创近两个月新高 2019年人民币将进入周期性上涨通道
银行服务制造业发展有“质”有“量” 满足企业多元化的金融需求
远东发展(00035.HK)获执行董事邱达昌增持33万股 涉资约92.1万港元