7
votes

I will allocate memory in user application using malloc and send the malloc returned address to a kernel module through character driver interface.

I will pin the pages for this memory using get_user_pages_fast in kernel module.

Can I use virt_to_phys to get the address returned by malloc. Is it valid? If not then how can I get proper physical address?

My aim is to get physical address of user space allocated memory. I m limiting my transfer size to pagesize (4KB).

3
Do you need actual physical addresses or DMA addresses? You can use dma_map_page() on a pinned page, or use dma_map_sg() if you have created a scatter-gather list from the pinned pages. If you want CPU access to the page, you can use kmap_atomic() to get a kernel virtual address for the page. Note that pages mapped with kmap_atomic() need to be unmapped in exactly reverse order to the order they were mapped.Ian Abbott

3 Answers

2
votes

No you can't, virt_to_phys converts kernel virtual addresses into physical addresses. There exist 3 (or 4) types of addresses in linux:

  • kernel virtual address: which is physical address +/- an offset (PAGE_OFFSET).
  • kernel physical address: actual physical address (obtained by __pa or virt_to_phys functions).
  • user virtual address: the translation to physical address is inside the page table of the process.

Note that page table 'layout' depends on the architecture of the processor, so you need to implement a software page table walk that corresponds to the architecture you work on.

And last word, the 4th kind of addresses that exists is :

  • bus address: which is an address as seen by a device.
1
votes

malloc returns the user virtual address. So I think you can not use the address returned by malloc from inside the driver.

virt_to_phys: The returned physical address is the physical (CPU) mapping for the memory address given. It is only valid to use this function on addresses directly mapped or allocated via kmalloc. It means It is used by the kernel to translate kernel virtual address (not user virtual address) to physical address

0
votes

This program will help you to access the physical memory directly. Idea is to mmap with /dev/mem(RAM)

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    if (argc < 3) {
        printf("Usage: %s <phys_addr> <offset>\n", argv[0]);
        return 0;
    }

    off_t offset = strtoul(argv[1], NULL, 0);
    size_t len = strtoul(argv[2], NULL, 0);

    // Truncate offset to a multiple of the page size, or mmap will fail.
    size_t pagesize = sysconf(_SC_PAGE_SIZE);
    off_t page_base = (offset / pagesize) * pagesize;
    off_t page_offset = offset - page_base;

    int fd = open("/dev/mem", O_SYNC);
    unsigned char *mem = mmap(NULL, page_offset + len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, page_base);
    if (mem == MAP_FAILED) {
        perror("Can't map memory");
        return -1;
    }

    size_t i;
    for (i = 0; i < len; ++i)
        printf("%02x ", (int)mem[page_offset + i]);

    return 0;
}

Credit goes to Accessing physical address from user space