3

i am writing a piece of code that needs to store 10k of memory located in specific physical address before the SOC shuts down.

My problem is that this physical address is not part of kernel space so i have to create an ad -hoc memory mapping so i can access this memory space.

i tried using io-remap but it doesn't (apparently) work on non-kernel space.

is there any API for doing this ? should i used kmap ?

Thanks in advance

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Strudle
  • 331
  • 2
  • 5
  • 14
  • 1
    Can you determine which memory regions to reserve during boot (in a U-Boot function?), exclude those regions in the (valid) memory list, then write a driver to actually map and use that "special" memory? http://stackoverflow.com/questions/11580285/pass-large-amount-of-binary-data-from-u-boot-to-linux-kernel/12137511#12137511 – sawdust Nov 28 '12 at 01:42
  • i can exclude the memory from the ATAGs during boot, but how do i map those areas ? ioremap didn't seem to work previously. maybe because the area was part of a different memory space ? – Strudle Nov 29 '12 at 06:56
  • *"io-remap ... doesn't ... work on non-kernel space"* - "Kernel" and "user" memory space refer to **virtual** memory. `ioremap()` has to be provided a **physical** address range. Beware that using the word "memory" without a virtual or physical qualifier can be ambiguous or confusing. Perhaps you need to revisit & analyze why `ioremap()` did not seem to "work". Here's another Q&A involving carving out physical memory for kernel driver use: http://stackoverflow.com/questions/12516603/after-adding-request-mem-region-my-driver-fails-every-first-access-with-busy-m/12557974#12557974 – sawdust Nov 29 '12 at 22:05
  • @JonathanLeffler - Your edits, especially *"this physical address is in user space"*, makes no sense, and probably misstates the issues. – sawdust Nov 29 '12 at 22:15
  • @sawdust: OK; then fix it, please. Never mind, I'll roll it back and let someone else have a go at it. – Jonathan Leffler Nov 29 '12 at 23:15

2 Answers2

2

Sounds like memory mapped peripheral. For tight binding into your kernel, it would have entry added into initdata which goes to iotable_init(). For example arch/arm/mach-vexpress/ct-ca9x4.c ct_ca9x4_io_desc[]. That creates virtual to physical mapping. Then kernel code could use writel with virtual address to write there.

Joe Kul
  • 2,454
  • 16
  • 16
  • actually the address space is the first 10k of every DRAM chip select, and those may change depending on the board setup. So, I must do this on runtime. i cant tell the address space location at compile time. – Strudle Nov 27 '12 at 20:13
  • There is some good info in http://stackoverflow.com/questions/7894160/accessing-physical-memory-from-linux-kernel. But n.b. "This is a very complicated programming area and you're not likely to get the answer you need in such limited space..." – Joe Kul Nov 27 '12 at 21:26
1

Found the answer

the key is to use the vmap function which create a mapping for a given page table. the problem was how to initialize a page table structure to a certain physical address but it appears there exists an API for that as well

here is an example to allocate a single page

void *virt_addr_ptr
struct page **my_page = kmalloc(sizeof (*my_page), GFP_KERNEL);
my_page = phys_to_page(phys_addr_ptr);
virt_addr_ptr = vmap(my_page, 1, VM_MAP, PAGE_KERNEL);

/*now its possible to access this space */
memcpy(store_buffer, virt_addr_ptr, store_size);
Strudle
  • 331
  • 2
  • 5
  • 14
  • Did you do this in user land or within a kernel module? – Joe C Jun 21 '13 at 18:43
  • Hopefully this post isn't too dead for an edit. `my_page = phys_to_page(phys_addr_ptr);` should be `*my_page = phys_to_page(phys_addr_ptr);` due to the return of `phys_to_page()` being a `struct page *` – d4r3llo5 Aug 24 '16 at 19:10