如何获得 fault_ipa hva 请参卡一下文章:
https://blog.csdn.net/weixin_46485500/article/details/118339827?spm=1001.2014.3001.5501
static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
struct kvm_memory_slot *memslot, unsigned long hva,
unsigned long fault_status)
gfn = fault_ipa >> PAGE_SHIFT;
由hva 可得到 hpa (host physical address)
pfn = gfn_to_pfn_prot(kvm, gfn, write_fault, &writable);
//pfn : physical frame number
//__pfn_to_phys(pfn) : physical address
//在将 ifault_ipa 映射的 hpa (__pfn_to_phys(pfn)) , 这就是stage 2 映射
ret = kvm_pgtable_stage2_map(pgt, fault_ipa, vma_pagesize,
__pfn_to_phys(pfn), prot,
memcache);
user_mem_abort fault_ipa 0x100000 hva 0x9c7bd000 fault_status 0x4
kvm_pfn_t gfn_to_pfn_prot(struct kvm *kvm, gfn_t gfn, bool write_fault,
bool *writable)
{
return __gfn_to_pfn_memslot(gfn_to_memslot(kvm, gfn), gfn, false, NULL,
write_fault, writable);
}
由hva 获得hpa
static kvm_pfn_t hva_to_pfn(unsigned long addr, bool atomic, bool *async,
bool write_fault, bool *writable)
hva_to_pfn->hva_to_pfn_fast->get_user_page_fast_only->get_user_pages_fast_only->internal_get_user_pages_fast->lockless_pages_from_mm->gup_pgd_range
static void gup_pgd_range(unsigned long addr, unsigned long end,
unsigned int flags, struct page **pages, int *nr)
{
unsigned long next;
pgd_t *pgdp;
pgdp = pgd_offset(current->mm, addr); //获得addr 在当前进程pgd 中的位置,这个addr是
//hpa
do {
pgd_t pgd = READ_ONCE(*pgdp);
next = pgd_addr_end(addr, end);
if (pgd_none(pgd))
return;
if (unlikely(pgd_huge(pgd))) {
if (!gup_huge_pgd(pgd, pgdp, addr, next, flags,
pages, nr))
return;
} else if (unlikely(is_hugepd(__hugepd(pgd_val(pgd))))) {
if (!gup_huge_pd(__hugepd(pgd_val(pgd)), addr,
PGDIR_SHIFT, next, flags, pages, nr))
return;
} else if (!gup_p4d_range(pgdp, pgd, addr, next, flags, pages, nr))
return;
} while (pgdp++, addr = next, addr != end);
}
然后一级一级的找,最后找到physical address
gup_p4d_range->gup_pud_range->gup_pmd_range->gup_pte_range
struct task_struct {
...
struct mm_struct *mm
...
}
struct mm_struct {
...
pgd_t * pgd; //进程地址映射表。
...
}