by satether » Mon Aug 11, 2014 12:53 am
A mapping created using /dev/mem will be uncached if it's above the top of RAM, not what we want. We had to write a driver for our own device /dev/ocm. LDREX/STREX work properly on a mapping constructed like this:
$this->bbcode_second_pass_code('', '
#define OCM_PHYSADDR 0xfffc0000UL
#define OCM_SIZE 65536UL
/* Protection bits we don't want to meddle with. */
#define PROTECTION_MASK (L_PTE_VALID | L_PTE_DIRTY | L_PTE_USER)
/* This mmap() implementation ignores the offset and flags arguments;
it always starts a shared mapping at the beginning of the OCM. The
user will still have to use the right size argument because the OS
uses it to determine how large a virtual address range to allocate
for the user's process, and that happens before this function is
called. Private mappings aren't allowed; silly COW. */
static int devocm_mmap(struct file *filp, struct vm_area_struct *vma) {
unsigned long const size = vma->vm_end - vma->vm_start;
if (size != OCM_SIZE) {
printk(KERN_WARNING "Invalid OCM size given to mmap().\n");
return -EINVAL;
}
vma->vm_page_prot = (vma->vm_page_prot & PROTECTION_MASK) | L_PTE_MT_WRITEALLOC | L_PTE_XN | L_PTE_SHARED;
if(remap_pfn_range(vma, vma->vm_start, OCM_PHYSADDR >> PAGE_SHIFT, OCM_SIZE, vma->vm_page_prot)) {
printk(KERN_WARNING "remap_pfn_range() failed for OCM.\n");
return -EAGAIN;
}
return 0;
}
')
Last edited by
WarheadsSE on Mon Aug 11, 2014 12:59 am, edited 1 time in total.
Reason: Added code tags for you :)