hi, I've got some qeustion about ppc(ppc44x) paging:
how can I manually map a virtual address to a physical address through a specific pgd? How does ppc translate virt address to physical one? I think besides from tlb, the CPU will search the page table entries via the pgd, can I alter the pgd value to change the memory translation? under i386, it's very simple, we can just rewrite %%cr3, it even could invalidate all tlb entries automatically, how can I do this under ppc? I've tried rewrite current->mm->pgd and current->thread.pgdir, but sounds like it still not insufficiant, am I missing something vital? Any hint will be greatly approciated. Regards, Wang P.S: here is the code: #define save_pd(pd) ((pd) = (unsigned long)(current->mm->pgd)) #define load_pd(pd) (current->mm->pgd = (pd)) ... static inline pgd_t* __pgd_offset(unsigned long pgd_base, unsigned long va) { return (pgd_t*)((pgd_t*)pgd_base + pgd_index(va)); } static inline pte_t* pte_offset(pmd_t* pte_base, unsigned long va) { return (pte_t*)((pte_t*)pte_base + pte_index(va)); } static inline unsigned long get_free_pages_atomic(int order) { return __get_free_pages(GFP_ATOMIC, order); } ... unsigned long create_page_directory (unsigned long (*alloc_page) (void)) { unsigned long pd, c_pd; unsigned long idx; save_pd(c_pd); pd = get_free_pages_atomic(PGD_ORDER); if(!pd) return 0; memset((void*)pd, 0, PGD_ORDER << PAGE_SHIFT); /* * copy kernel page directies */ idx = pgd_index(PAGE_OFFSET); memcpy((pgd_t*)pd + idx, (pgd_t*)c_pd + idx, (PTRS_PER_PGD - idx) * sizeof(pgd_t)); printk(KERN_EMERG"create_page_directory return: 0x%lx, c_pd: 0x%lx\n", pd, c_pd); return pd; } /* * allocate a user page at @vaddress if possible * TODO: add tlb/slb/bat for fast page/block address translation */ unsigned long allocate_user_page (unsigned long pd, unsigned long vaddress, unsigned long (*alloc_page) (void)) { pgd_t* pgd; pud_t* pud; pmd_t* pmd; pte_t* pte; unsigned long page = 0; #define mm_debug printk mm_debug("allocate_user_page(0x%lx, 0x%lx, 0x%lx)\n", pd, vaddress, alloc_page); pgd = __pgd_offset(pd, vaddress); if(!pgd_present(*pgd) || !(*pgd)){ pud_t* pud_entry = (pud_t*)get_free_pages_atomic(PUD_ORDER); if(!pud_entry) return 0; *pgd = __pa(pud_entry) & PAGE_MASK; mm_debug("!pgd_present, pgd: 0x%lx, *pgd: 0x%lx\n", pgd, *pgd); } pud = pud_offset(pgd, vaddress); if(!pud_present(*pud) || !(*pud)){ pmd_t* pmd_entry = (pmd_t*)get_free_pages_atomic(PMD_ORDER); if(!pmd_entry) return 0; *pud = __pa(pmd_entry) & PAGE_MASK; mm_debug("!pud_present, pud: 0x%lx, *pud: 0x%lx\n", pud, *pud); } pmd = pmd_offset(pud, vaddress); if(!pmd_present(*pmd) || !(*pmd)){ pte_t* pte_entry = (pte_t*)get_free_pages_atomic(PTE_ORDER); if(!pte_entry) return 0; *pmd = __pa(pte_entry) & PAGE_MASK; *pmd |= _PMD_PRESENT; mm_debug("!pmd_present, pmd: 0x%lx, *pmd: 0x%lx\n", pmd, *pmd); } pte = pte_offset(pmd, vaddress); if(!pte_present(*pte) || !(*pte) || pte_none(*pte)){ unsigned long pfn; page = get_free_pages_atomic(PAGE_ORDER); mm_debug("page: 0x%lx\n", page); pfn = __pa(page) & PAGE_MASK; mm_debug("pfn: 0x%lx\n", pfn); set_pte_at(current->mm, page, pte, pfn_pte(pfn >> PAGE_SHIFT, __pgprot(PAGE_SHARED_X))); mm_debug("pte_present now?: %lld\n", pte_present(*pte)); mm_debug("!pte_present, pte: 0x%lx\n", pte); } mm_debug("allocate_user_page: return 0x%lx\n", page); #undef mm_debug return page; } -- Wang, Baojun Lanzhou University Distributed & Embedded System Lab http://dslab.lzu.edu.cn School of Information Science and Engeneering [EMAIL PROTECTED] Tianshui South Road 222. Lanzhou 730000 .P.R.China Tel:+86-931-8912025 Fax:+86-931-8912022 _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev