Re: Cache incoherencies [example code]

rmk@arm.linux.org.uk
Thu, 26 Aug 1999 10:55:42 -0400 (EDT)


Hi Ben,

Here is an example of the modifications required to vmalloc to enable
uncached spaces to be allocated. In fact, it allows any pgprot to be
specified for the vmalloc'd area. I think that the names of the new
functions follow Linus' naming scheme - __vmalloc() is more generic
and does `less' than vmalloc().

Note that this is just an example; it seems to compile (on 2.2.5),
but I have not tested it at all.

--- vmalloc.c.rmk Thu Aug 26 10:52:39 1999
+++ vmalloc.c Thu Aug 26 10:53:58 1999
@@ -82,7 +82,7 @@
flush_tlb_all();
}

-static inline int alloc_area_pte(pte_t * pte, unsigned long address, unsigned long size)
+static inline int alloc_area_pte(pte_t * pte, unsigned long address, unsigned long size, pgprot_t prot)
{
unsigned long end;

@@ -97,14 +97,14 @@
page = __get_free_page(GFP_KERNEL);
if (!page)
return -ENOMEM;
- set_pte(pte, mk_pte(page, PAGE_KERNEL));
+ set_pte(pte, mk_pte(page, prot));
address += PAGE_SIZE;
pte++;
}
return 0;
}

-static inline int alloc_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size)
+static inline int alloc_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, pgprot_t prot)
{
unsigned long end;

@@ -116,7 +116,7 @@
pte_t * pte = pte_alloc_kernel(pmd, address);
if (!pte)
return -ENOMEM;
- if (alloc_area_pte(pte, address, end - address))
+ if (alloc_area_pte(pte, address, end - address, prot))
return -ENOMEM;
address = (address + PMD_SIZE) & PMD_MASK;
pmd++;
@@ -124,7 +124,7 @@
return 0;
}

-int vmalloc_area_pages(unsigned long address, unsigned long size)
+inline int __vmalloc_area_pages(unsigned long address, unsigned long size, pgprot_t prot)
{
pgd_t * dir;
unsigned long end = address + size;
@@ -138,7 +138,7 @@
pmd = pmd_alloc_kernel(dir, address);
if (!pmd)
return -ENOMEM;
- if (alloc_area_pmd(pmd, address, end - address))
+ if (alloc_area_pmd(pmd, address, end - address, prot))
return -ENOMEM;
if (pgd_val(olddir) != pgd_val(*dir))
set_pgdir(address, *dir);
@@ -149,6 +149,11 @@
return 0;
}

+int vmalloc_area_pages(unsigned long address, unsigned long size)
+{
+ return __vmalloc_area_pages(address, size, PAGE_KERNEL);
+}
+
struct vm_struct * get_vm_area(unsigned long size)
{
unsigned long addr;
@@ -195,7 +200,7 @@
printk("Trying to vfree() nonexistent vm area (%p)\n", addr);
}

-void * vmalloc(unsigned long size)
+inline void * __vmalloc(unsigned long size, pgprot_t prot)
{
void * addr;
struct vm_struct *area;
@@ -207,11 +212,16 @@
if (!area)
return NULL;
addr = area->addr;
- if (vmalloc_area_pages(VMALLOC_VMADDR(addr), size)) {
+ if (__vmalloc_area_pages(VMALLOC_VMADDR(addr), size, prot)) {
vfree(addr);
return NULL;
}
return addr;
+}
+
+void * vmalloc(unsigned long size)
+{
+ return __vmalloc(size, PAGE_KERNEL);
}

long vread(char *buf, char *addr, unsigned long count)

_____
|_____| ------------------------------------------------- ---+---+-
| | Russell King rmk@arm.linux.org.uk --- ---
| | | | http://www.arm.linux.org.uk/~rmk/aboutme.html / / |
| +-+-+ --- -+-
/ | THE developer of ARM Linux |+| /|\
/ | | | --- |
+-+-+ ------------------------------------------------- /\\\ |

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/