ARMv8 创建1、2、3级页表代码与注释

对下面的地址空间创建3级页表

// level 1 table, 4 entries:
// 0000 0000 - 3FFF FFFF, 1GB block, DDR
// 4000 0000 - 7FFF FFFF, 1GB block, DDR
// 8000 0000 - BFFF FFFF, 1GB block, DDR
// C000 0000 - FFFF FFFF, point to level2 tabel
//
// level 2 table, 512 entries:
// C000 0000 - DFFF FFFF, 256 entries, 512MB DDR, 2MB block
// E000 0000 - EFFF FFFF, 128  entries, 256MB OSPI0 flash, 2MB block
// F000 0000 - F01F FFFF, 1 entries, resever , 2MB block, device
// F020 0000 - F03F FFFF, 1 entry, point to level 3_1
// F040 0000 - F05F FFFF, 1 entry, point to level 3_2
// F060 0000 - F07F FFFF, 1 entry, point to level 3_3
// F080 0000 - F09F FFFF, 1 entries, 2MB block, normal memory, RNE_MEM, 1.5M acture, SRAM
// F0A0 0000 - F0BF FFFF, 1 entries, 2MB block, device, RNE_CFG1

下面是创建过程与添加的注释。

#include "v8_mmu.h"

    .text
    .cfi_sections .debug_frame  // put stack frame info into .debug_frame instead of .eh_frame

	.global setup_ttb
	.global ZeroBlock

    .global __ttb0_l1
    .global __ttb0_l2_ram
    .global __ttb0_l3_ram_1
    .global __ttb0_l3_ram_2
    .global __ttb0_l3_ram_3


//----------------------------------------------------------------
// setup translation table
// level 1 table, 4 entries:
// 0000 0000 - 3FFF FFFF, 1GB block, DDR
// 4000 0000 - 7FFF FFFF, 1GB block, DDR
// 8000 0000 - BFFF FFFF, 1GB block, DDR
// C000 0000 - FFFF FFFF, point to level2 tabel
//
// level 2 table, 512 entries:
// C000 0000 - DFFF FFFF, 256 entries, 512MB DDR, 2MB block
// E000 0000 - EFFF FFFF, 128  entries, 256MB OSPI0 flash, 2MB block
// F000 0000 - F01F FFFF, 1 entries, resever , 2MB block, device
// F020 0000 - F03F FFFF, 1 entry, point to level 3_1
// F040 0000 - F05F FFFF, 1 entry, point to level 3_2
// F060 0000 - F07F FFFF, 1 entry, point to level 3_3
// F080 0000 - F09F FFFF, 1 entries, 2MB block, normal memory, RNE_MEM, 1.5M acture, SRAM
// F0A0 0000 - F0BF FFFF, 1 entries, 2MB block, device, RNE_CFG1
//----------------------------------------------------------------


    .type setup_ttb, "function"
    .cfi_startproc
setup_ttb:

    //
    // x21 = address of L1 tables
    // x22 = address of L2 tables
    // x23 = address of L3 tables F02
    // x24 = address of L3 tables F04
    // x25 = address of L3 tables F06
    //
    ldr x2, =0  // x2 = 0 (用于清零内存)
    ldr x3, =0 // x3 = 0 (同上)

	// 清零 L1 页表 (__ttb0_l1) (L1 页表(32 字节,4 个条目))
    ldr x21, =__ttb0_l1  // x21 = L1 页表基地址
    mov x0, x21            // x0 = 当前操作地址
    mov x1, #(4 << 3)      // x1 = 4个条目 * 8字节 = 32字节 (L1页表大小)
    add x0, x0, x1         // x0 指向区域末尾 (预递减清零准备)
    // can not call func ZeroBlock,  not support nesting
loop_zero_0:
    subs x1, x1, #16       // 每次处理16字节 (2个条目),更新计数器
    stp  x2, x3, [x0, #-16]! // 存储双零并递减地址: [x0-16] = (0,0), x0-=16
    b.ne loop_zero_0        // 循环直到x1=0

    // 清零 L2 页表 (__ttb0_l2_ram) (L2 页表(4096 字节,512 条目))
    ldr x22, =__ttb0_l2_ram // x22 = L2 页表基地址
    mov x1, #(512 << 3)    // x1 = 512条目 * 8字节 = 4096字节 (标准2MB块大小)
    mov x0, x22            // x0 = 当前操作地址
    add x0, x0, x1         // x0 指向区域末尾
    //循环使用 subs + b.ne 实现精确计数(当 x1 减至 0 时退出)
loop_zero_1:
    subs x1, x1, #16       // 每次16字节
    stp  x2, x3, [x0, #-16]! // 存储双零并前移指针
    b.ne loop_zero_1       // 循环

    // 清零第一个 L3 页表 (__ttb0_l3_ram_1) (三个 L3 页表(各 4096 字节))
    ldr x23, =__ttb0_l3_ram_1 // x23 = L3 页表1基地址
    mov x1, #(512 << 3)    // 4096字节 (标准4KB页表大小)
    mov x0, x23
    add x0, x0, x1        // 指向末尾
loop_zero_2:
    subs x1, x1, #16
    stp  x2, x3, [x0, #-16]!
    b.ne loop_zero_2

    // 清零第二个 L3 页表 (__ttb0_l3_ram_2)
    ldr x24, =__ttb0_l3_ram_2 // x24 = L3 页表2基地址
    mov x1, #(512 << 3)    // 4096字节
    mov x0, x24
    add x0, x0, x1        // 指向末尾
loop_zero_3:
    subs x1, x1, #16
    stp  x2, x3, [x0, #-16]!
    b.ne loop_zero_3

	// 清零第三个 L3 页表 (__ttb0_l3_ram_3)
    ldr x25, =__ttb0_l3_ram_3 // x25 = L3 页表3基地址
    mov x1, #(512 << 3)    // 4096字节
    mov x0, x25
    add x0, x0, x1         // 指向末尾
loop_zero_4:
    subs x1, x1, #16
    stp  x2, x3, [x0, #-16]!
    b.ne loop_zero_4

 	// 设置 L1 页表项配置
	// 0000 0000 - 3FFF FFFF, 1GB block, DDR
	// 4000 0000 - 7FFF FFFF, 1GB block, DDR
	// 8000 0000 - BFFF FFFF, 1GB block, DDR
	// 3 1G block, write to l1 table
	//
	ldr x1, =3                // x1 = 3 (需要配置的页表项数量)
	ldr x2, =0x40000000      // x2 = 1GB 地址增量 (每个 L1 条目映射 1GB 空间)

	 // 构建 L1 块描述符属性值:
    // - 物理地址基址: 0x00000000
    // - 块描述符类型 (TT_S1_ATTR_BLOCK)  TT_S1_ATTR_BLOCK:使用块描述符 (1GB/2MB 大页)
    // - 内存属性索引 1 (MATTR=1) 普通内存,适用于ddr
    // - 非安全状态 (NS)
    // - 特权读写权限 (AP_RW_PL1)
    // - 内部可共享 (SH_INNER)
    // - 访问标志 (AF)
    // - 非全局映射 (nG)
	ldr x3, =(0x00000000	   | \
			  TT_S1_ATTR_BLOCK | \
             (1 << TT_S1_ATTR_MATTR_LSB) | \
              TT_S1_ATTR_NS | \
              TT_S1_ATTR_AP_RW_PL1 | \
              TT_S1_ATTR_SH_INNER | \
              TT_S1_ATTR_AF | \
              TT_S1_ATTR_nG)
    mov x4, x21                // x4 = L1 页表基址指针 (x21 来自前段代码)

#if 1	// enable after ddr ready
loop1:
	str x3, [x4], #8         // 存储每次的x3描述符到 L1 页表并后移指针
	add x3, x3, x2           // 物理地址增加 1GB (0x40000000)
	subs x1, x1, #1           // 递减计数器
	bne loop1                 // 循环直到 3 个条目配置完成
#else
loop1:
	add x4, x4, #8           // 仅移动指针 (不存储)
	add x3, x3, x2          // 物理地址增加 1GB
	subs x1, x1, #1
	bne loop1
#endif

    // 配置 L1 页表中 C0000000-FFFFFFFF 区域的条目
	// C000 0000 - FFFF FFFF, point to level2 tabel, write to l1 table
    orr x1, x22, #TT_S1_ATTR_PAGE  // 将 L2 表基址(x22)与页表描述符属性组合。TT_S1_ATTR_PAGE:页表描述符 (指向下级页表)
    str x1, [x4]              // 存储到 L1 页表 (指向 L2 页表)


    // 配置 L2 页表:DDR 区域 (C0000000-DFFFFFFF, 512MB)
	// level 2 table: C000 0000 - DFFF FFFF, 256 entries, 512MB DDR, 2MB block
	ldr x1, =256              // 256 个条目 (256 * 2MB = 512MB)
	ldr x2, =0x200000         // x2 = 2MB 地址增量 (块大小)

	 // 构建 DDR 区域的 L2 块描述符:
    // - 物理地址基址: 0xC0000000
    // - 块描述符类型
    // - 内存属性索引 1 (普通内存)
	ldr x3, =(0xC0000000	   | \
			  TT_S1_ATTR_BLOCK | \
             (1 << TT_S1_ATTR_MATTR_LSB) | \
              TT_S1_ATTR_NS | \
              TT_S1_ATTR_AP_RW_PL1 | \
              TT_S1_ATTR_SH_INNER | \
              TT_S1_ATTR_AF | \
              TT_S1_ATTR_nG)
    mov x4, x22              // x4 = L2 页表基址指针 (x22)
loop2_ddr:
	str x3, [x4], #8          // 存储每次的x3到描述符到 L2 页表并后移指针
	add x3, x3, x2           // 物理地址增加 2MB
	subs x1, x1, #1          // 递减计数器
	bne loop2_ddr            // 循环配置 256 个条目


	// 配置 L2 页表:OSPI0 Flash 区域 (E0000000-EFFFFFFF, 256MB)
	// level 2 table: E000 0000 - EFFF FFFF, 64 entries, 128MB OSPI0 flash, 2MB block
	ldr x1, =128              // 128 个条目 (128 * 2MB = 256MB)
	ldr x2, =0x200000         // 2MB 块大小

	// 构建 OSPI Flash 的 L2 块描述符:
    // - 物理地址基址: 0xE0000000
    // - 内存属性索引TT_S1_ATTR_MATTR_LSB 2 (通常用于设备内存)
    //AP_RW_PL1:特权读写权限
	//SH_INNER:内部可共享
	//AF:访问标志 (Access Flag)
	//nG:非全局映射
	ldr x3, =(0xE0000000	   | \
			  TT_S1_ATTR_BLOCK | \
             (2 << TT_S1_ATTR_MATTR_LSB) | \
              TT_S1_ATTR_NS | \
              TT_S1_ATTR_AP_RW_PL1 | \
              TT_S1_ATTR_SH_INNER | \
              TT_S1_ATTR_AF | \
              TT_S1_ATTR_nG)
loop2_ospi0:
	str x3, [x4], #8         // 继续在 L2 页表存储 (紧接 DDR 区域之后)
	add x3, x3, x2         	 // 物理地址增加 2MB
	subs x1, x1, #1           // 递减计数器
	bne loop2_ospi0           // 循环配置 128 个条目


	// F0800000-F09FFFFF 区域:2MB 块映射 (普通内存)
	// F000 0000 - F01F FFFF, resever, no need to set this block
	// F080 0000 - F09F FFFF, 1 entries, 2MB block, normal memory, RNE_MEM, 1.5M acture, SRAM
	// 物理地址 + 属性
	ldr x1, =(0xF0800000	   | \
		TT_S1_ATTR_BLOCK | \
             (1 << TT_S1_ATTR_MATTR_LSB) | \
              TT_S1_ATTR_NS | \
              TT_S1_ATTR_AP_RW_PL1 | \
              TT_S1_ATTR_SH_INNER | \
              TT_S1_ATTR_AF | \
              TT_S1_ATTR_nG)
	ldr x2, =0xF0800000  // 目标虚拟地址
	ubfx x3, x2, #21, #9            // 提取 L2 索引 (位[29:21]) ?
	str x1, [x22, x3, lsl #3]      // 写入 L2 页表 (x22) ?

	// F0A00000-F0BFFFFF 区域:2MB 块映射 (设备内存)
	// F0A0 0000 - F0BF FFFF, 1 entries, 2MB block, device, RNE_CFG1
	// 物理地址 + 属性
	ldr x1, =(0xF0A00000	   | \
		TT_S1_ATTR_BLOCK | \
             (2 << TT_S1_ATTR_MATTR_LSB) | \
              TT_S1_ATTR_NS | \
              TT_S1_ATTR_AP_RW_PL1 | \
              TT_S1_ATTR_SH_INNER | \
              TT_S1_ATTR_AF | \
              TT_S1_ATTR_nG)
	ldr x2, =0xF0A00000            // 目标虚拟地址
	ubfx x3, x2, #21, #9         // 提取 L2 索引
	str x1, [x22, x3, lsl #3]      // 写入 L2 页表


	/*
	0x00000000 ~ 0xc0000000                          ----l1
	0xc0000000 ~ 0xe0000000                          ----l2
	0xe0000000 ~ 0xf0000000                          ----l2

	0xf0800000 ~ 0xf0870000 rne_mem                    ----l2
	0xf0a00000 ~ 0xf0bfffff rne_cfg                    ----l2

	0xf0000000 ~ 0xf02fffff  rsv
	0xf0314000 ~ 0xf03effff  peri                   -----0xf0200000 ~ 0xf03fffff : l2 -> l3 3_1
	0xf0400000 ~ 0xf04fffff usb                     -----
	0xf0500000 ~ 0xf0517fff peri                    -----0xf0400000 ~ 0xf05fffff : l2 -> l3 3_2
	0xf0600000 ~ 0xf062ffff ddr gic noc acodec      -----0xf0600000 ~ 0xf07fffff : l2 -> l3 3_3

	地址转换:
	L2 索引:ubfx 提取位[29:21] (#21, #9)
	L3 索引:ubfx 提取位[20:12] (#12, #9)
	页表项位置:基址 + 索引 × 8 (lsl #3)
	*/


	// 设置 L2 页表项:F0200000-F03FFFFF 指向 L3 页表 (x23)
	// level 2 table: F020 0000 - F03F FFFF, 1 entry, point to level 3_1
    orr x1, x23, #TT_S1_ATTR_TABLE  // 组合 L3 基址和表描述符属性
    ldr x2, =0xF0200000             // 虚拟地址范围起始
	ubfx x3, x2, #21, #9           // 提取 L2 索引
    str x1, [x22, x3, lsl #3]       // 写入 L2 页表

	// 设置 L2 页表项:F0400000-F05FFFFF 指向 L3 页表 (x24)
	// level 2 table: F040 0000 - F05F FFFF, 1 entry, point to level 3_2
    orr x1, x24, #TT_S1_ATTR_TABLE  // 组合 L3 基址和表描述符属性
    ldr x2, =0xF0400000            // 虚拟地址范围起始
	ubfx x3, x2, #21, #9           // 提取 L2 索引
    str x1, [x22, x3, lsl #3]       // 写入 L2 页表

	// 设置 L2 页表项:F0600000-F12A5FFF 指向 L3 页表 (x25)
	// level 2 table: F060 0000 - F12A 5FFF, 1 entry, point to level 3_3
    orr x1, x25, #TT_S1_ATTR_TABLE  // 组合 L3 基址和表描述符属性
    ldr x2, =0xF0600000            // 虚拟地址范围起始
	ubfx x3, x2, #21, #9           // 提取 L2 索引
    str x1, [x22, x3, lsl #3]      // 写入 L2 页表

	// 填充 L3 页表 (x23):F0200000-F03FFFFF 区域 (512 个 4KB 页)
	// level 3 table: F02 0000 - F03F FFFF, 512 entry, x24
	// valid addr  F020 0000 - F03F FFFF
	ldr x1, =0x1000                // 页大小:4KB
	ldr x2, =((0xF03FFFFF + 1 - 0xF0200000) >> 12) // 计算页数
	ldr x3, =0xF0200000                        // 物理地址起始

	// 页描述符属性
	// 设备内存属性
	ldr x4, = (TT_S1_ATTR_PAGE | \
             (2 << TT_S1_ATTR_MATTR_LSB) | \
              TT_S1_ATTR_NS | \
              TT_S1_ATTR_AP_RW_PL1 | \
              TT_S1_ATTR_SH_INNER | \
              TT_S1_ATTR_AF | \
              TT_S1_ATTR_nG)
loop3_1:
	ubfx x5, x3, #12, #9            // 提取页内索引 (位[20:12])
    orr x6, x3, x4                // 组合物理地址和属性
	str x6, [x23, x5, lsl #3]       // 存储到 L3 页表 (x23)
	add x3, x3, x1                 // 移动到下一页
	subs x2, x2, #1               // 递减页计数器
	bne loop3_1                    // 循环直到所有页映射完成

	// 填充 L3 页表 (x24):F0400000-F05FFFFF 区域 (512 个 4KB 页)
	// level 3 table: F040 0000 - F05F FFFF,, 512 entry, x25
	// valid addr  F040 0000 - F05F FFFF
	ldr x1, =0x1000                 // 页大小:4KB
	ldr x2, =((0xF05FFFFF + 1 - 0xF0400000) >> 12) // 计算页数
	ldr x3, =0xF0400000             // 物理地址起始

	 // 设备内存属性
	ldr x4, = (TT_S1_ATTR_PAGE | \
             (2 << TT_S1_ATTR_MATTR_LSB) | \
              TT_S1_ATTR_NS | \
              TT_S1_ATTR_AP_RW_PL1 | \
              TT_S1_ATTR_SH_INNER | \
              TT_S1_ATTR_AF | \
              TT_S1_ATTR_nG)
loop3_2:
	ubfx x5, x3, #12, #9        // 提取页内索引
    orr x6, x3, x4              // 组合物理地址和属性
	str x6, [x24, x5, lsl #3]      // 存储到 L3 页表 (x24)
	add x3, x3, x1               // 下一页
	subs x2, x2, #1               // 递减页计数器
	bne loop3_2               // 循环


	// 填充 L3 页表 (x25):F0600000-F07FFFFF 区域 (512 个 4KB 页)
	// level 3 table: F060 0000 - F07F FFFF, 512 entry, x25
	// valid addr  F060 0000 - F07F FFFF
	ldr x1, =0x1000               // 页大小:4KB
	ldr x2, =((0xF07FFFFF + 1 - 0xF0600000) >> 12) // 计算页数
	ldr x3, =0xF0600000             // 物理地址起始

	// 设备内存属性
	ldr x4, = (TT_S1_ATTR_PAGE | \
             (2 << TT_S1_ATTR_MATTR_LSB) | \
              TT_S1_ATTR_NS | \
              TT_S1_ATTR_AP_RW_PL1 | \
              TT_S1_ATTR_SH_INNER | \
              TT_S1_ATTR_AF | \
              TT_S1_ATTR_nG)
loop3_3:
	ubfx x5, x3, #12, #9          // 提取页内索引
    orr x6, x3, x4               // 组合物理地址和属性
	str x6, [x25, x5, lsl #3]      // 存储到 L3 页表 (x25)
	add x3, x3, x1            	// 下一页
	subs x2, x2, #1             // 递减页计数器
	bne loop3_3           		// 循环

    ret
    .cfi_endproc

内容概要:本文针对火电厂参直购交易挤占风电上网空间的问题,提出了一种风火打捆参大用户直购交易的新模式。通过分析可再生能源配额机制下的双边博弈关系,建立了基于动态非合作博弈理论的博弈模型,以直购电价和直购电量为决策变量,实现双方收益均衡最大化。论文论证了纳什均衡的存在性,并提出了基于纳什谈判法的风-火利益分配方法。算例结果表明,该模式能够增加各方收益、促进风电消纳并提高电网灵活性。文中详细介绍了模型构建、成本计算和博弈均衡的实现过程,并通过Python代码复现了模型,包括参数定义、收益函数、纳什均衡求解、利益分配及可视化分析等功能。 适合人群:电力系统研究人员、能源政策制定者、从事电力市场交易的工程师和分析师。 使用场景及目标:①帮助理解风火打捆参大用户直购交易的博弈机制;②为电力市场设计提供理论依据和技术支持;③评估不同政策(如可再生能源配额)对电力市场的影响;④通过代码实现和可视化工具辅助教学和研究。 其他说明:该研究不仅提供了理论分析,还通过详细的代码实现和算例验证了模型的有效性,为实际应用提供了参考。此外,论文还探讨了不同场景下的敏感性分析,如证书价格、风电比例等对市场结果的影响,进一步丰富了研究内容。
资源下载链接为: https://pan.quark.cn/s/d37d4dbee12c A:计算机视觉,作为人工智能领域的关键分支,致力于赋予计算机系统 “看懂” 世界的能力,从图像、视频等视觉数据中提取有用信息并据此决策。 其发展历程颇为漫长。早期图像处理技术为其奠基,后续逐步探索三维信息提取,人工智能结合,又经历数学理论深化、机器学习兴起,直至当下深度学习引领浪潮。如今,图像生成和合成技术不断发展,让计算机视觉更深入人们的日常生活。 计算机视觉综合了图像处理、机器学习、模式识别和深度学习等技术。深度学习兴起后,卷积神经网络成为核心工具,能自动提炼复杂图像特征。它的工作流程,首先是图像获取,用相机等设备捕获视觉信息并数字化;接着进行预处理,通过滤波、去噪等操作提升图像质量;然后进入关键的特征提取和描述环节,提炼图像关键信息;之后利用这些信息训练模型,学习视觉模式和规律;最终用于模式识别、分类、对象检测等实际应用。 在实际应用中,计算机视觉用途极为广泛。在安防领域,能进行人脸识别、目标跟踪,保障公共安全;在自动驾驶领域,帮助车辆识别道路、行人、交通标志,实现安全行驶;在医疗领域,辅助医生分析医学影像,进行疾病诊断;在工业领域,用于产品质量检测、机器人操作引导等。 不过,计算机视觉发展也面临挑战。比如图像生成技术带来深度伪造风险,虚假图像和视频可能误导大众、扰乱秩序。为此,各界积极研究检测技术,以应对这一问题。随着技术持续进步,计算机视觉有望在更多领域发挥更大作用,进一步改变人们的生活和工作方式 。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

liuluyang530

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

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

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

打赏作者

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

抵扣说明:

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

余额充值