RISC-V架构——物理内存保护机制设置函数(pmp_set、pmp_get)解析

1、物理内存保护机制

参考博客:《RISC-V架构——物理内存属性和物理内存保护》

2、pmp_set函数源码

int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
	    unsigned long log2len)
{
	int pmpcfg_csr, pmpcfg_shift, pmpaddr_csr;
	unsigned long cfgmask, pmpcfg;
	unsigned long addrmask, pmpaddr;

	/* check parameters */
	if (n >= PMP_COUNT || log2len > __riscv_xlen || log2len < PMP_SHIFT)
		return SBI_EINVAL;

	/* 计算配置项所在pmpcfg是哪一个,已经配置项在pmpcfg中的偏移量 */
#if __riscv_xlen == 32
	pmpcfg_csr   = CSR_PMPCFG0 + (n >> 2);
	pmpcfg_shift = (n & 3) << 3;
#elif __riscv_xlen == 64
	pmpcfg_csr   = (CSR_PMPCFG0 + (n >> 2)) & ~1;
	pmpcfg_shift = (n & 7) << 3;
#else
# error "Unexpected __riscv_xlen"
#endif
	pmpaddr_csr = CSR_PMPADDR0 + n;

	//清除配置项里地址匹配模式
	prot &= ~PMP_A;	
	//如果是要设置的物理内存是4个字节则用NA4模式,否则用NAPOT模式
	prot |= (log2len == PMP_SHIFT) ? PMP_A_NA4 : PMP_A_NAPOT;	
	cfgmask = ~(0xffUL << pmpcfg_shift);
	//读取出对于pmpcfg寄存器的值,并且将对应表项清零
	pmpcfg	= (csr_read_num(pmpcfg_csr) & cfgmask);
	//设置对应表项
	pmpcfg |= ((prot << pmpcfg_shift) & ~cfgmask);

	/* 配置pmp地址寄存器,如果要设置的物理地址范围是4字节 */
	if (log2len == PMP_SHIFT) {	
		pmpaddr = (addr >> PMP_SHIFT);
	} else {	
		if (log2len == __riscv_xlen) {	//__riscv_xlen是寄存器的位宽,相等则是要设置整个物理地址空间
			pmpaddr = -1UL;
		} else {
			addrmask = (1UL << (log2len - PMP_SHIFT)) - 1;	
			pmpaddr	 = ((addr >> PMP_SHIFT) & ~addrmask); //将要设置的物理地址范围左移2位,然后低(log2len - 2)位清0
			pmpaddr |= (addrmask >> 1);	//设置pmp地址寄存器,此时pmpaddr寄存器的值,最低位开始有(log2len - 3)个1
		}
	}

	/* 设置pmp表项和pmp地址寄存器 */
	csr_write_num(pmpaddr_csr, pmpaddr);
	csr_write_num(pmpcfg_csr, pmpcfg);

	return 0;
}

3、pmp_set函数分析

3.1、函数传参分析

在这里插入图片描述

3.2、pmp配置表项设置

在这里插入图片描述

3.3、pmp地址寄存器的值计算

在这里插入图片描述

4、pmp_get函数源码

int pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out,
	    unsigned long *log2len)
{
	int pmpcfg_csr, pmpcfg_shift, pmpaddr_csr;
	unsigned long cfgmask, pmpcfg, prot;
	unsigned long t1, addr, len;

	/* check parameters */
	if (n >= PMP_COUNT || !prot_out || !addr_out || !log2len)
		return SBI_EINVAL;
	*prot_out = *addr_out = *log2len = 0;

	/* calculate PMP register and offset */
#if __riscv_xlen == 32
	pmpcfg_csr   = CSR_PMPCFG0 + (n >> 2);
	pmpcfg_shift = (n & 3) << 3;
#elif __riscv_xlen == 64
	pmpcfg_csr   = (CSR_PMPCFG0 + (n >> 2)) & ~1;
	pmpcfg_shift = (n & 7) << 3;
#else
# error "Unexpected __riscv_xlen"
#endif
	pmpaddr_csr = CSR_PMPADDR0 + n;

	/* decode PMP config */
	cfgmask = (0xffUL << pmpcfg_shift);
	pmpcfg	= csr_read_num(pmpcfg_csr) & cfgmask;
	prot	= pmpcfg >> pmpcfg_shift;

	/* decode PMP address */
	if ((prot & PMP_A) == PMP_A_NAPOT) {
		addr = csr_read_num(pmpaddr_csr);
		if (addr == -1UL) {
			addr	= 0;
			len	= __riscv_xlen;
		} else {
			t1	= ctz(~addr);
			addr	= (addr & ~((1UL << t1) - 1)) << PMP_SHIFT;
			len	= (t1 + PMP_SHIFT + 1);
		}
	} else {
		addr	= csr_read_num(pmpaddr_csr) << PMP_SHIFT;
		len	= PMP_SHIFT;
	}

	/* return details */
	*prot_out    = prot;
	*addr_out    = addr;
	*log2len     = len;

	return 0;
}

pmp_get函数就是pmp_set函数的逆过程,解析出当前设置过哪些物理地址范围保护;

注意事项

pmp_set函数和pmp_get函数时摘抄自opensbi,还严格按照RISC-V规范编写的,但实际芯片在设计时并不会严格按照RISC-V规定的物理内存保护机制去设计,上面的代码移植到特定芯片平台时可能是要经过适配才行。就我遇到的情况,平头哥的玄铁C906就不能直接使用上面的函数来设置和获取物理内存保护。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
ALU(算术逻辑单元)是计算机处理器中负责执行算术和逻辑操作的核心组件。在设计RISC-V处理器的过程中,ALU的优化是至关重要的一步。 首先,我们可以通过增加多个ALU管道来提高处理器的性能。这样,指令可以在多个ALU之间并行执行,从而加快处理速度。另外,还可以采用超标量技术,将多个ALU分组,并行执行不同的指令,进一步提高处理器效率。 其次,为了提高ALU的性能,我们可以通过增加更多的功能单元来支持多种操作。例如,我们可以添加浮点运算单元,以支持浮点运算指令。此外,还可以添加位移单元和乘法单元等,以执行各种操作。通过提供更多的功能单元,ALU可以在单个周期内执行更多的操作,提高处理器的性能。 另外,在ALU的设计中,还需要考虑到电路延迟的问题。通过优化电路布线和信号传输路径,可以减少ALU操作所需的时间。此外,采用流水线技术也可以提高处理器的吞吐量。通过将ALU操作划分为多个阶段,并行执行多条指令,可以大大提高处理器的效率。 最后,为了优化ALU的设计,还需要考虑功耗的问题。通过采用低功耗电路设计和节能技术,可以有效降低ALU的功耗。此外,在处理器的设计过程中,还可以采用动态电压调整和时钟频率调整等技术,根据实际负载情况动态调整ALU的电压和频率,以达到节能的目的。 综上所述,通过增加ALU管道、添加更多功能单元、优化电路延迟、采用流水线技术和优化功耗等方法,可以对RISC-V处理器中的ALU进行优化,提高处理器的性能和效率。这些优化措施能够使处理器更快、更强大,更适应各种复杂的计算任务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

正在起飞的蜗牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值