yygg
yygg

Reputation: 51

map specifc virtual address to a specific physical one

I am writing a Linux kernel module that needs to map a specific physical address to a specific virtual one, and I just can't find a way to do it.

Upvotes: 1

Views: 1191

Answers (2)

yygg
yygg

Reputation: 51

OK, This is my current solution. To map phys_addr to virt_addr I use this code:

page = pfn_to_page(virt_addr >> PAGE_SHIFT);
pte = get_locked_pte(&init_mm, phys_addr, &ptl);
set_pte_at(&init_mm, phys_addr, pte, mk_pte(page, VM_READ | VM_WRITE | VM_EXEC));
spin_unlock(ptl);
flush_tlb_all();

Some explenations: I use the pfn_to_page func to get the page struct corresponding to my virt_addr. I get the page table entry (pte) with the get_locked_pte func which needs the physical address corresponding to the wanted pte and an uninitalized spinlock (ptl). Then, I actually map the page using set_pte_at func and the mk_pte macro, unlock the spinlock and flush the tlb cache.

This solution seems to work pretty well, though it does not survive a context switch.

Upvotes: 3

tian_yufeng
tian_yufeng

Reputation: 1826

Could you tell us the kernel version and CPU architecture/type you are using? Generally speaking, if the specific virtual address you want to mapping to does not overlap with kernel virtual address(such as 0xC0000000), and also if the physical address which your device is using does not overlap with system memory physical address range, you can using the low-level functions(if there is not, you can using assemble language to set up MMU TLB entries directly during kernel booting up) to set up MMU TLB entries to map the specific address to a specific virtual one during kernel booting up. I can provide one example based on 2.6.10 kernel version and Freescale PowerPC CPU, there is a function io_block_mapping to do the thing you want.

Upvotes: 0

Related Questions