Ioremapped address in kernel - c

I have basic query about ioremap used to map device IO addressed into kernel's virtual memory.
I would like to know if returned address from ioremap is passed to routines like virt_to_phys(), would it return back Device IO address ?
Thanks

virt_to_phys() is only valid for virtual addresses within the kernel linear map, since it's just some fast address arithmetic, not a full software table walk. The linear map normally only covers RAM. The virtual address returned by ioremap(), however, will usually (probably always, but I don't have the patience to check every implementation) be a vmalloc address, so if you pass that to virt_to_phys() you'll get nonsense back.

Related

memcpy takes virtual address or physical address?

I am working on Video HAL Application & there I am getting Camera frame CallBack from HAL Layer. During programming I found that memcpy copying data from physical address gets crashed while it is ok by copying data from virtual address. I searched for such a information about memcpy but found no where & even not on its man page.
so, my question is does memcpy required physical address or virtual address? Anywhere mentioned this type of information about memcpy?
memcpy is implemented in C or optimized in assembler. As such, it doesn't care about what type of address it gets. It just loads the addresses in the CPU registers and executes mov instructions.
It is the operating system and memory hardware architecture that are responsible for mapping any logical (virtual) address to a physical address.
Note also that with modern OS/memory architectures, each process gets its own address space. Passing addresses between address spaces will not work.
In these cases, the OS will probably provide functionality to exchange memory objects (shared or otherwise) between processes.
As Paul Ogilvie correctly explained, memcpy deals with user space addresses. As such they are virtual addresses, not necessarily physical addresses.
Yet there is a possibility for very large areas with very specific alignment characteristics to optimize memcpy by requesting the OS to remap some of the destination virtual addresses as duplicates of the physical memory mapped to the source addresses. These pages would get the COPY_ON_WRITE attribute to ensure that the program only modifies pages in the appropriate array, if and when it writes to either one. The generic implementation of memcpy in the GlibC does this (see glibc-2.3.5/sysdeps/generic/memcpy.c). But this is transparent for the programmer who still provides addresses in user space.

I/O memory region remap

The main reason for I/O memory region is to read/write anything to that memory.
If the register address is given, we can use readx/writex (x stands for b/l/w).
Then why do we have to use the address returned by io_remap which is nothing but the same as the address of the particular register given in the data sheet?
ioremap is architecture specific function/macro. On some architectures it won't do anything and just basically return the address specified as an argument. It may do much more than that on other architectures, though. Take arm or x86 as an example - the ioremap will do a lot of checks before letting you using the memory region, for example.
What's more important than those checks, however, is that ioremap can setup a mapping of virtual addresses (from vmalloc area) to the requested physical ones and ensure that caching is disabled for addresses you are going to use. So in most cases pointer returned by ioremap will not be the same as just numeric address from the datasheet.
You want caching to be disabled because I/O registers are controlled by some external (from CPU point of view) devices. This means that processor can't know when its content changed, making cache content invalid.
The thing returned by request_mem_region is a struct resource *, you don't use it to access the I/O memory, and you don't have to do much of anything with it except check it for NULL. request_mem_region isn't part of the mapping you need to do to access the I/O, and your driver would actually (probably) work without it, but by calling it you make some information available in kernel data structures, and make sure that two drivers aren't trying to use overlapping memory ranges.

How do I get DRAM address instead of Virtual address

I understand if I try to print the address of an element of an array it would be an address from virtual memory not from real memory (physical memory) i.e DRAM.
printf ("Address of A[5] and A[6] are %u and %u", &A[5], &A[6]);
I found addresses were consecutive (assuming elements are chars). In reality they may not be consecutive at least not in the DRAM. I want to know the real addresses. How do I get that?
I need to know this for either Windows or Linux.
You can't get the physical address for a virtual address from user code; only the lowest levels of the kernel deal with physical addresses, and you'd have to intercept things there.
Note that the physical address for a virtual address may not be constant while the program runs — the page might be paged out from one physical address and paged back in to a different physical address. And if you make a system call, this remapping could happen between the time when the kernel identifies the physical address and when the function call completes because the program requesting the information was unscheduled and partially paged out and then paged in again.
The simple answer is that, in general, for user processes or threads in a multiprocessing OS such as Windows or Linux, it is not possible to find the address even of of a static variable in the processor's memory address space, let alone the DRAM address.
There are a number of reasons for this:
The memory allocated to a process is virtual memory. The OS can remap this process memory from time-to-time from one physical address range to another, and there is no way to detect this remaping in the user process. That is, the physical address of a variable can change during the lifetime of a process.
There is no interface from userspace to kernel space that would allow a userspace process to walk through the kernel's process table and page cache in order to find the physical address of the process. In Linux you can write a kernel module or driver that can do this.
The DRAM is often mapped to the procesor address space through a memory management unit (MMU) and memory cache. Although the MMU maping of DRAM to the processor address space is usually done only once, during system boot, the processor's use of the cache can mean that values written to a variable might not be written through to the DRAM in all cases.
There are OS-specific ways to "pin" a block of allocated memory to a static physical location. This is often done by device drivers that use DMA. However, this requires a level of privilege not available to userspace processes, and, even if you have the physical address of such a block, there is no pragma or directive in the commonly used linkers that you could use to allocate the BSS for a process at such a physical address.
Even inside the Linux kernel, virtual to physical address translation is not possible in the general case, and requires knowledge about the means that were used to allocate the memory to which a particular virtual address refers.
Here is a link to an article called Translating Virtual to Physical Address on Windows: Physical Addresses that gives you a hint as to the extreme ends to which you must go to get physical addresses on Windows.

Why it is not possible to use ioremap then remap_pfn_range?

In my driver, I am trying to map an address returned from ioremap to a userspace address.
What kind of an address is returned from ioremap?
How is it different from a kmalloc address ?
How can I map an address returned from ioremap?
Which address should be inserted to remap_pfn_range?
You don't need ioremap() if you're using remap_pfn_range(). ioremap() maps a physical address into a kernel virtual address. remap_pfn_range() maps physical addresses directly to user space. Just pass your physical address (downshifted by PAGE_SHIFT to produce a pfn) directly to remap_pfn_range(). Your questions in order:
kernel virtual address
kmalloc returns kernel virtual, but guarantees contiguous memory See question 116343
you could do this if you call virt_to_phys() first, to convert kernel virtual address to physical. But skip a step if you don't actually need kernel access to this memory range
physical address, downshifted by PAGE_SHIFT to produce a pfn
ioremap() returns the kernel space virtual address. This can't be accessed directly from user space. There is mechanism called mmap(), refer here and Mapping physical addresses to virtual address linux for working sample.

How to convert kmalloc() address to physical address

I have a PCI device which exposes a BAR and few offsets in the bar for accessing the device.
On one of the Bar offset, i need to program a 64KB allocated memory. In my Linux driver, i allocate a 64KB of memory using kmalloc() which as i know returns virtual address. If this is programmed into the offset, HW won't be able to see the same. How do i convert this virtual address to physical ?
When i Google, i see few links pointing to virt_to_phys() but few responses says this doesn't work well with kmalloc(). Any idea how to go about this?
You normally use pci_resource_start() / pci_resource_end() from within a kernel driver. I assume you are writing a device driver ?
I won't map the memory yourself : That's where the kernel functions are for. That way, you're sure it works on all platforms. That 64k block I assume is some memory map that is provided by the PCI device ? if yes, then the above is correct. If no, please give more information.
Rather than using kmalloc() , use alloc_pages() function.
struct page* alloc_pages(gfp_t gfp_mask, 4 );
one page is of 4K, so it will allocate 2^4=16 pages which is equal to 16 * 4K = 64K memory and returns physical address.

Resources