[linux-sh:03344] Re: [linuxsh-dev] Re: Howto convert from process virtual (linear address) to physical address?
Stuart MENEFY <[email protected]> Fri, 8 Oct 2004 19:25:58 +0100
| Newsgroups | gmane.linux.ports.sh.general,gmane.linux.ports.sh.devel |
|---|---|
| Organization | STMicroelectronics (Bristol) |
| Message-ID | <[email protected]> |
On Fri, 8 Oct 2004 20:34:22 +0300 Paul Mundt <[email protected]> wrote: > On Fri, Oct 08, 2004 at 05:40:32PM +0100, Alex Bennee wrote: > > Now I'm probably just lost because I haven't got my head fully wrapped > > around the multi-level page tables but this is what I've got: > > > > do { > > pgd_t *pgd; > > pmd_t *pmd; > > pte_t *ptep, pte; > > struct page *the_page; > > unsigned long phys_addr; > > > > get_user(addr, start_addr); > > start_addr++; > > > > pgd = pgd_offset(tsk->mm, addr); > > if (pgd_none(*pgd) || pgd_bad(*pgd)) > > goto out; > > > > pmd = pmd_offset(pgd, addr); > > if (pmd_none(*pmd) || pmd_bad(*pmd)) > > goto out; > > > > ptep = pte_offset(pmd, addr); > > if (!ptep) > > goto out; > > > > pte = *ptep; > > > > the_page = pte_page(pte); > > phys_addr = page_to_phys(the_page)+(addr&PAGE_MASK); > > This looks problematic. > > What about: > > phys_addr = pte_val(*ptep) & PTE_PHYS_MASK; You still need to OR in the page offset, so: phys_addr = (pte_val(*ptep) & PTE_PHYS_MASK) | (addr&(PAGE_SIZE-1)); would be my version. > > Any idea where I'm going wrong? A pointer to code that actually needs to > > convert from user-space linear address to actual physical address would > > be cool if anyone can point me to one. > > > The closest you will probably get is copy/clear_user_page(), but that > probably won't help you much. I'd suggest __do_page_fault() but you're missing the last step, converting a PTE to an address with that. Either way, I think your code is roughly right, the problem is that the HUDI doesn't allow you to look at physical memory directly. You're still seeing memory through the CPU, so you need to use a full 32 bit address. So you could have done: (gdb) x/i 0x00413dc8 directly, which might work, if the ASID is still correct, and the TLB entry was still present. The problem comes when there is no TLB entry mapping the virtual address, in this case the code running in the ASE mode has no way to fix up the TLB miss (if it even knows about it), so returns garbage. So you need to use the page table walk your doing, but then use a P1 or P2 address, in this case: (gdb) x/i 0x89e57dc8 should have done the right thing. Stuart -- Stuart Menefy [email protected] STMicroelectronics Ltd ST Intranet: linux.bri.st.com Bristol, UK Rest of the World: www.superhlinux.com
signature.asc
(application/pgp-signature, 189 B)
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.1 (GNU/Linux) iD8DBQFBZtu261BlSKQGbXkRAtJSAJ9DE0WAnUdj7U/WhPlkWlQpxn/1AwCgiSa7 85XDIkvy9hwmUKwORFhbSVQ= =dzBI -----END PGP SIGNATURE-----