[PATCH] CRIS update: mm
Memory management patches. * SMP support. * Non-executable stack (on v32). * 4-level page tables. * Added simple Thread Local Storage support. Signed-off-by: Mikael Starvik <starvik@axis.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Šī revīzija ir iekļauta:

revīziju iesūtīja
Linus Torvalds

vecāks
7cf32cad15
revīzija
4f18cfbf09
@@ -14,9 +14,10 @@
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/arch/memmap.h>
|
||||
|
||||
extern inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
|
||||
unsigned long phys_addr, unsigned long flags)
|
||||
unsigned long phys_addr, pgprot_t prot)
|
||||
{
|
||||
unsigned long end;
|
||||
|
||||
@@ -31,9 +32,7 @@ extern inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned l
|
||||
printk("remap_area_pte: page already exists\n");
|
||||
BUG();
|
||||
}
|
||||
set_pte(pte, mk_pte_phys(phys_addr, __pgprot(_PAGE_PRESENT | __READABLE |
|
||||
__WRITEABLE | _PAGE_GLOBAL |
|
||||
_PAGE_KERNEL | flags)));
|
||||
set_pte(pte, mk_pte_phys(phys_addr, prot));
|
||||
address += PAGE_SIZE;
|
||||
phys_addr += PAGE_SIZE;
|
||||
pte++;
|
||||
@@ -41,7 +40,7 @@ extern inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned l
|
||||
}
|
||||
|
||||
static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
|
||||
unsigned long phys_addr, unsigned long flags)
|
||||
unsigned long phys_addr, pgprot_t prot)
|
||||
{
|
||||
unsigned long end;
|
||||
|
||||
@@ -56,7 +55,7 @@ static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned lo
|
||||
pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address);
|
||||
if (!pte)
|
||||
return -ENOMEM;
|
||||
remap_area_pte(pte, address, end - address, address + phys_addr, flags);
|
||||
remap_area_pte(pte, address, end - address, address + phys_addr, prot);
|
||||
address = (address + PMD_SIZE) & PMD_MASK;
|
||||
pmd++;
|
||||
} while (address && (address < end));
|
||||
@@ -64,7 +63,7 @@ static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned lo
|
||||
}
|
||||
|
||||
static int remap_area_pages(unsigned long address, unsigned long phys_addr,
|
||||
unsigned long size, unsigned long flags)
|
||||
unsigned long size, pgprot_t prot)
|
||||
{
|
||||
int error;
|
||||
pgd_t * dir;
|
||||
@@ -77,13 +76,19 @@ static int remap_area_pages(unsigned long address, unsigned long phys_addr,
|
||||
BUG();
|
||||
spin_lock(&init_mm.page_table_lock);
|
||||
do {
|
||||
pud_t *pud;
|
||||
pmd_t *pmd;
|
||||
pmd = pmd_alloc(&init_mm, dir, address);
|
||||
|
||||
error = -ENOMEM;
|
||||
pud = pud_alloc(&init_mm, dir, address);
|
||||
if (!pud)
|
||||
break;
|
||||
pmd = pmd_alloc(&init_mm, pud, address);
|
||||
|
||||
if (!pmd)
|
||||
break;
|
||||
if (remap_area_pmd(pmd, address, end - address,
|
||||
phys_addr + address, flags))
|
||||
phys_addr + address, prot))
|
||||
break;
|
||||
error = 0;
|
||||
address = (address + PGDIR_SIZE) & PGDIR_MASK;
|
||||
@@ -107,9 +112,9 @@ static int remap_area_pages(unsigned long address, unsigned long phys_addr,
|
||||
* have to convert them into an offset in a page-aligned mapping, but the
|
||||
* caller shouldn't need to know that small detail.
|
||||
*/
|
||||
void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
|
||||
void __iomem * __ioremap_prot(unsigned long phys_addr, unsigned long size, pgprot_t prot)
|
||||
{
|
||||
void * addr;
|
||||
void __iomem * addr;
|
||||
struct vm_struct * area;
|
||||
unsigned long offset, last_addr;
|
||||
|
||||
@@ -131,15 +136,36 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
|
||||
area = get_vm_area(size, VM_IOREMAP);
|
||||
if (!area)
|
||||
return NULL;
|
||||
addr = area->addr;
|
||||
if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
|
||||
vfree(addr);
|
||||
addr = (void __iomem *)area->addr;
|
||||
if (remap_area_pages((unsigned long) addr, phys_addr, size, prot)) {
|
||||
vfree((void __force *)addr);
|
||||
return NULL;
|
||||
}
|
||||
return (void *) (offset + (char *)addr);
|
||||
return (void __iomem *) (offset + (char __iomem *)addr);
|
||||
}
|
||||
|
||||
void iounmap(void *addr)
|
||||
void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
|
||||
{
|
||||
return __ioremap_prot(phys_addr, size,
|
||||
__pgprot(_PAGE_PRESENT | __READABLE |
|
||||
__WRITEABLE | _PAGE_GLOBAL |
|
||||
_PAGE_KERNEL | flags));
|
||||
}
|
||||
|
||||
/**
|
||||
* ioremap_nocache - map bus memory into CPU space
|
||||
* @offset: bus address of the memory
|
||||
* @size: size of the resource to map
|
||||
*
|
||||
* Must be freed with iounmap.
|
||||
*/
|
||||
|
||||
void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
|
||||
{
|
||||
return __ioremap(phys_addr | MEM_NON_CACHEABLE, size, 0);
|
||||
}
|
||||
|
||||
void iounmap(volatile void __iomem *addr)
|
||||
{
|
||||
if (addr > high_memory)
|
||||
return vfree((void *) (PAGE_MASK & (unsigned long) addr));
|
||||
|
Atsaukties uz šo jaunā problēmā
Block a user