* Physical address @ 2003-12-08 15:07 moi toi 2003-12-08 15:23 ` William Lee Irwin III ` (2 more replies) 0 siblings, 3 replies; 5+ messages in thread From: moi toi @ 2003-12-08 15:07 UTC (permalink / raw) To: linux-kernel Hi I am a newbie in the development of Linux driver. I have some difficulties to understand how the memory management works. I am working on a Pentium IV ( 512M of RAM), with the Red Hat 9.0. I want to create buffers in the RAM which are available for DMA transfer, and I want that process can map them. I reserve at boot time some space in the RAM (mem=400M). And then I remap a buffer into the driver with the following command: >unsigned long Ram_Buffer_addr; >#define POSITION 0x19000000 //400*1024*1024=400M >#define SIZE 8*1024 > >Ram_Buffer_addr = (unsigned long) ioremap (POSITION, SIZE); The addresses of the buffer are the following: Ram_Buffer_addr = 0xD9DCB000 Virt_to_phys(Ram_Buffer_addr) = 0x19DCB000 Virt_to_bus(Ram_Buffer_addr) = 0x19DCB000 The virtual address is of course different from the physical address, and the physical address and the bus address are the same, because I m working on a PC. But I don t understand why the physical address is different from the one I gave to the function ioremap. I did a second test: I change the position of the buffer instead of taking it at the address 0x19000000, the buffer start at the address: 0x1f400000 (500M). >unsigned long Ram_Buffer_addr; >#define POSITION 0x1F400000 //500*1024*1024=500M >#define SIZE 8*1024 > >Ram_Buffer_addr = (unsigned long) ioremap (POSITION, SIZE); The addresses of the buffer are the following: Ram_Buffer_addr = 0xD9DCB000 Virt_to_phys(Ram_Buffer_addr) = 0x19DCB000 Virt_to_bus(Ram_Buffer_addr) = 0x19DCB000 The addresses are exactly the same. I m ok for the virtual addresses, but it sounds pretty weird for the physical and bus addresses, they shouldn t be the same than in the first test. ---------------------------------------------------------------------- When I map the buffer from a process, I use the virtual address of the buffer with the function mmap, but in the mmap call-back function in the driver, I use the true physical address with the function: remap_page_range( vma, vma->vm_start, POSITION,(vma->vm_end - vma->vm_start), (pgprot_t) vma->vm_page_prot); And it seems work! But if instead of POSITION, I set Virt_to_phys(Ram_Buffer_addr), it doesn t work anymore. Does that mean that the functions virt_to_phys and virt_to_bus don t work on virtual addresses? Does anyone know, how to get the real physical address of the buffer. Thanks Francois. ____________________________________________________________________________________ Do You Yahoo!? -- Avec Yahoo! soyez au coeur de la récolte de dons pour le Téléthon. http://fr.promotions.yahoo.com/caritatif/ ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Physical address 2003-12-08 15:07 Physical address moi toi @ 2003-12-08 15:23 ` William Lee Irwin III 2003-12-08 15:42 ` Richard B. Johnson 2003-12-09 16:04 ` Jesper Juhl 2 siblings, 0 replies; 5+ messages in thread From: William Lee Irwin III @ 2003-12-08 15:23 UTC (permalink / raw) To: moi toi; +Cc: linux-kernel On Mon, Dec 08, 2003 at 04:07:13PM +0100, moi toi wrote: > Does that mean that the functions virt_to_phys and > virt_to_bus don't work on virtual addresses? Does anyone know, how to > get the real physical address of the buffer. Linux assumes 1:1 mapping of kernel virtual addresses, with various exceptions. virt_to_bus() and virt_to_phys() only work on that statically mapped area's virtual addreses. ioremap() dynamically establishes translations for the areas, and the virtual addresses returned by it are not valid to resolve to physical addresses with virt_to_bus() and virt_to_phys(). Probably the best way to find the physical address is by a direct pagetable lookup. Something like the following (untested) may be of use: static dma_addr_t ioremap_to_phys(unsigned long vaddr) { pgd_t *pgd; pmd_t *pmd; pte_t *pte; pgd = pgd_offset_k(vaddr); if (!pgd_present(*pgd)) return 0; pmd = pmd_offset(pgd, vaddr); if (!pmd_present(*pmd)) return 0; pte = pte_offset_kernel(pmd, vaddr); if (!pte_present(*pte)) return 0; return ((dma_addr_t)pte_pfn(*pte) << PAGE_SHIFT) | (addr & ~PAGE_MASK); } -- wli ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Physical address 2003-12-08 15:07 Physical address moi toi 2003-12-08 15:23 ` William Lee Irwin III @ 2003-12-08 15:42 ` Richard B. Johnson 2003-12-08 16:05 ` Matthias Urlichs 2003-12-09 16:04 ` Jesper Juhl 2 siblings, 1 reply; 5+ messages in thread From: Richard B. Johnson @ 2003-12-08 15:42 UTC (permalink / raw) To: moi toi; +Cc: linux-kernel On Mon, 8 Dec 2003, [iso-8859-1] moi toi wrote: > Hi > > I am a newbie in the development of Linux driver. I > have some > difficulties to understand how the memory management > works. > > I am working on a Pentium IV ( 512M of RAM), with the > Red Hat 9.0. > I want to create buffers in the RAM which are > available for DMA > transfer, and I want that process can map them. > > I reserve at boot time some space in the RAM > (mem=400M). > And then I remap a buffer into the driver with the > following command: > > >unsigned long Ram_Buffer_addr; > >#define POSITION 0x19000000 > //400*1024*1024=400M > >#define SIZE 8*1024 > > > >Ram_Buffer_addr = (unsigned long) ioremap (POSITION, > SIZE); > > The addresses of the buffer are the following: > Ram_Buffer_addr = 0xD9DCB000 > Virt_to_phys(Ram_Buffer_addr) = 0x19DCB000 > Virt_to_bus(Ram_Buffer_addr) = 0x19DCB000 > > The virtual address is of course different from the > physical address, > and the physical address and the bus address are the > same, because I m > working on a PC. But I don t understand why the > physical address is > different from the one I gave to the function ioremap. > > I did a second test: I change the position of the > buffer instead of > taking it at the address 0x19000000, the buffer start > at the address: > 0x1f400000 (500M). > > >unsigned long Ram_Buffer_addr; > >#define POSITION 0x1F400000 > //500*1024*1024=500M > >#define SIZE 8*1024 > > > >Ram_Buffer_addr = (unsigned long) ioremap (POSITION, > SIZE); > > The addresses of the buffer are the following: > Ram_Buffer_addr = 0xD9DCB000 > Virt_to_phys(Ram_Buffer_addr) = 0x19DCB000 > Virt_to_bus(Ram_Buffer_addr) = 0x19DCB000 > > The addresses are exactly the same. I m ok for the > virtual addresses, > but it sounds pretty weird for the physical and bus > addresses, they > shouldn t be the same than in the first test. > > ---------------------------------------------------------------------- > When I map the buffer from a process, I use the > virtual address of the > buffer with the function mmap, but in the mmap > call-back function in > the driver, I use the true physical address with the > function: > remap_page_range( vma, vma->vm_start, > POSITION,(vma->vm_end - > vma->vm_start), (pgprot_t) vma->vm_page_prot); > And it seems work! > But if instead of POSITION, I set > Virt_to_phys(Ram_Buffer_addr), it > doesn t work anymore. > > Does that mean that the functions virt_to_phys and > virt_to_bus don t > work on virtual addresses? Does anyone know, how to > get the real > physical address of the buffer. > > Thanks > > Francois. The way pages are set up on Linux makes the virtual address = physical + PAGE_OFFSET. So, a __non__portable__ driver can just use that information to access physical addresses. But, you really should use the macros provided to make a driver that has a chance of running on different systems. In your case, you oremap(0x1f400000) = df400000 which makes sense. However, depending upon the kernel version you are using, some "portable pedantics" corrupted the return values into "cookies", not real addresses. This forces you to use the macros provided to access these addresses. In other words, they are __not__ pointers, so they don't make any sense. A trick to get around all this stuff is to just save the junk returned from ioremap(). You use this for iounmap(). Then just take the address you asked for (the physical address) and use that for your hardware, and the virtual address (add PAGE_OFFSET to it) for your pointer(s). Don't expect any help from some LK pedantics, but this hack will get you started if you are not using any special addresses (like high RAM). Also, don't tell anybody .... <grin>... Cheers, Dick Johnson Penguin : Linux version 2.4.22 on an i686 machine (797.90 BogoMips). Note 96.31% of all statistics are fiction. ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Physical address 2003-12-08 15:42 ` Richard B. Johnson @ 2003-12-08 16:05 ` Matthias Urlichs 0 siblings, 0 replies; 5+ messages in thread From: Matthias Urlichs @ 2003-12-08 16:05 UTC (permalink / raw) To: linux-kernel Hi, Richard B. Johnson wrote: > Don't expect any help > from some LK pedantics, but this hack will get you started if > you are not using any special addresses (like high RAM). ... and if the driver will never run on non-PC-like or non-x86 systems. > Also, don't tell anybody .... <grin>... *Grumble*. IMHO you(generic) should do this right the first time. The learning curve may be a bit steeper, but OTOH you won't get into any bad habits, and you won't leave a mess for other people to debug. -- Matthias Urlichs | {M:U} IT Design @ m-u-it.de | smurf@smurf.noris.de Disclaimer: The quote was selected randomly. Really. | http://smurf.noris.de - - We are bits of stellar matter that got cold by accident, bits of a star gone wrong. -- Sir Arthur Eddington ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Physical address 2003-12-08 15:07 Physical address moi toi 2003-12-08 15:23 ` William Lee Irwin III 2003-12-08 15:42 ` Richard B. Johnson @ 2003-12-09 16:04 ` Jesper Juhl 2 siblings, 0 replies; 5+ messages in thread From: Jesper Juhl @ 2003-12-09 16:04 UTC (permalink / raw) To: moi toi; +Cc: linux-kernel On Mon, 8 Dec 2003, moi toi wrote: > Hi > > I am a newbie in the development of Linux driver. I > have some > difficulties to understand how the memory management > works. > > I am working on a Pentium IV ( 512M of RAM), with the > Red Hat 9.0. > I want to create buffers in the RAM which are > available for DMA > transfer, and I want that process can map them. > I recently came across a good article in Linux Journal by Robert Love that explains how to allocate memory in the kernel and the various options you have. The article was called "Allocating Memory in the Kernel" and appeared in the December 2003 issue. You can also find it online here: http://www.linuxjournal.com/article.php?sid=6930 Hope this helps you. Kind regards, Jesper Juhl ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2003-12-09 16:07 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2003-12-08 15:07 Physical address moi toi 2003-12-08 15:23 ` William Lee Irwin III 2003-12-08 15:42 ` Richard B. Johnson 2003-12-08 16:05 ` Matthias Urlichs 2003-12-09 16:04 ` Jesper Juhl
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).