如何修改 ARM64 上 Linux 内核中页表项 (PTE) 中的位?

问题描述 投票:0回答:1

我正在研究ARMV8.9的新功能,称为“Permission Indirection”,它类似于X86内存保护密钥。 PIIndex(权限间接索引,如 MPK 密钥)由 PTE 中的 PTE_UXN, PTE_PXN, PTE_WRITE, PTE_USER 组成,我尝试修改这些位以更改索引。我怎样才能做到这一点?

在我的内核模块中,我分配一个页面,并使用 

virt_to_kpte

 来获取其 PTE。然后我使用 
ptep_get_and_clear
set_pte_at
 重新配置 PTE 的 PIIndex。这是我的代码:
static __u64 set_kpage_piindex(unsigned long kaddr, __u64 piindex) { pte_t *ptep, pte; __u64 old_piindex; ptep = virt_to_kpte(kaddr); pte = ptep_get_and_clear(&init_mm, kaddr, ptep); old_piindex = pte_pi_index((pte.pte)); // clear piindex and reset pte = clear_pte_bit(pte, __pgprot(PTE_UXN | PTE_PXN | PTE_WRITE | PTE_USER)); pte = set_pte_bit(pte, __pgprot((PTE_UXN & ((piindex) & 0x8) << 51) | (PTE_PXN & ((piindex) & 0x4) << 51) | (PTE_WRITE & ((piindex) & 0x2) << 50) | (PTE_USER & ((piindex) & 0x1) << 6))); set_pte_at(&init_mm, kaddr, ptep, pte); return old_piindex; }

此外,我还导出 
init_mm

以支持这些内核函数的使用。但我注意到修改延迟,这意味着实际修改可能会在设置后一段时间才会生效。这两个函数是直接使用

ptep_modify_prot_start
ptep_modify_prot_commit
:
static inline pte_t ptep_modify_prot_start(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) { return __ptep_modify_prot_start(vma, addr, ptep); } static inline void ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep, pte_t old_pte, pte_t pte) { __ptep_modify_prot_commit(vma, addr, ptep, pte); }

我确实注意到评论说“ptep_modify_prot_commit实际上可能不会更新pte,而只是将更新排队等待稍后完成。但是,必须在释放pte锁之前实际提交更新”。那么如何避免这种修改延迟呢?内核修改是可以接受的。

linux memory memory-management linux-kernel
1个回答
0
投票
这里

。设置 PIIndex 后我需要刷新数据缓存: flush_dcache_page(virt_to_page(kaddr));

我不确定这是否是设置 PIIndex 的正确方法,但目前它有效。

© www.soinside.com 2019 - 2024. All rights reserved.