Linux之arm SMMUv3 驱动重要宏和函数解析(11)
1.ARM_LPAE_LVL_SHIFT
ARM_LPAE_LVL_SHIFT宏计算第l级页表在虚拟地址中的偏移。如果页表大小为4KB,采用4级页表,具体如下:
- 级别3(最低级):
(4-3)*9 + 3 = 12比特偏移 - 级别2:
(4-2)*9 + 3 = 21比特偏移 - 级别1:
(4-1)*9 + 3 = 30比特偏移 - 级别0(根级):
(4-0)*9 + 3 = 39比特偏移
[drivers/iommu/io-pgtable-arm.c]
#define ARM_LPAE_MAX_ADDR_BITS 52
#define ARM_LPAE_S2_MAX_CONCAT_PAGES 16
#define ARM_LPAE_MAX_LEVELS 4
/* 4KB : bits_per_level == 9,* 16KB: bits_per_level == 11,* 64KB: bits_per_level == 13,* ilog2(sizeof(arm_lpae_iopte)) == 3*/
#define ARM_LPAE_LVL_SHIFT(l,d) \(((ARM_LPAE_MAX_LEVELS - (l)) * (d)->bits_per_level) + \ilog2(sizeof(arm_lpae_iopte)))
2.ARM_LPAE_GRANULE
ARM_LPAE_GRANULE宏用于计算页表(除了根页表大小)大小。
[drivers/iommu/io-pgtable-arm.c]
// 4KB = (0x8 << 9), 16KB = (0x8 << 11), 64KB = (0x8 << 13),
#define ARM_LPAE_GRANULE(d) \(sizeof(arm_lpae_iopte) << (d)->bits_per_level)
3.ARM_LPAE_PGD_SIZE
ARM_LPAE_PGD_SIZE宏用于计算根页表大小,通常情况下,根页表和其他页表大小相等。由于根页表访问频率较高,有些系统中会进行优化,根页表大小可能会大于其他页表。
[drivers/iommu/io-pgtable-arm.c]
// 4KB = (0x8 << 9)
#define ARM_LPAE_PGD_SIZE(d) \(sizeof(arm_lpae_iopte) << (d)->pgd_bits)
4.ARM_LPAE_PTES_PER_TABLE
ARM_LPAE_PTES_PER_TABLE用于计算每个页表包含的页表项数量。
- 4KB粒度,8字节页表项
- ARM_LPAE_GRANULE(d) = 4096(4KB)
- sizeof(arm_lpae_iopte) = 8(字节)
- ilog2(8) = 3(因为2^3=8)
- 计算:4096 >> 3 = 4096 ÷ 8 = 512个页表项
- 16KB粒度,8字节页表项
- ARM_LPAE_GRANULE(d) = 16384(16KB)
- sizeof(arm_lpae_iopte) = 8
- ilog2(8) = 3
- 计算:16384 >> 3 = 16384 ÷ 8 = 2048个页表项
- 64KB粒度,8字节页表项
