Skip to content

Commit

Permalink
x86: PAT use reserve free memtype in ioremap and iounmap
Browse files Browse the repository at this point in the history
Use reserve_memtype and free_memtype interfaces in ioremap/iounmap to avoid
aliasing.

If there is an existing alias for the region, inherit the memory type from
the alias. If there are conflicting aliases for the entire region, then fail
ioremap.

Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
venkatesh.pallipadi@intel.com authored and Ingo Molnar committed Apr 17, 2008
1 parent 3a96ce8 commit d7677d4
Showing 1 changed file with 28 additions and 7 deletions.
35 changes: 28 additions & 7 deletions arch/x86/mm/ioremap.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include <asm/pgalloc.h>
#include <asm/pat.h>

#ifdef CONFIG_X86_64

Expand Down Expand Up @@ -118,6 +119,7 @@ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
{
unsigned long pfn, offset, last_addr, vaddr;
struct vm_struct *area;
unsigned long new_prot_val;
pgprot_t prot;

/* Don't allow wraparound or zero size */
Expand Down Expand Up @@ -151,6 +153,28 @@ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
WARN_ON_ONCE(is_ram);
}

/*
* Mappings have to be page-aligned
*/
offset = phys_addr & ~PAGE_MASK;
phys_addr &= PAGE_MASK;
size = PAGE_ALIGN(last_addr+1) - phys_addr;

if (reserve_memtype(phys_addr, phys_addr + size,
prot_val, &new_prot_val)) {
/*
* Do not fallback to certain memory types with certain
* requested type:
* - request is uncached, return cannot be write-back
*/
if ((prot_val == _PAGE_CACHE_UC &&
new_prot_val == _PAGE_CACHE_WB)) {
free_memtype(phys_addr, phys_addr + size);
return NULL;
}
prot_val = new_prot_val;
}

switch (prot_val) {
case _PAGE_CACHE_UC:
default:
Expand All @@ -161,13 +185,6 @@ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
break;
}

/*
* Mappings have to be page-aligned
*/
offset = phys_addr & ~PAGE_MASK;
phys_addr &= PAGE_MASK;
size = PAGE_ALIGN(last_addr+1) - phys_addr;

/*
* Ok, go for it..
*/
Expand All @@ -177,11 +194,13 @@ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
area->phys_addr = phys_addr;
vaddr = (unsigned long) area->addr;
if (ioremap_page_range(vaddr, vaddr + size, phys_addr, prot)) {
free_memtype(phys_addr, phys_addr + size);
free_vm_area(area);
return NULL;
}

if (ioremap_change_attr(vaddr, size, prot_val) < 0) {
free_memtype(phys_addr, phys_addr + size);
vunmap(area->addr);
return NULL;
}
Expand Down Expand Up @@ -265,6 +284,8 @@ void iounmap(volatile void __iomem *addr)
return;
}

free_memtype(p->phys_addr, p->phys_addr + get_vm_area_size(p));

/* Finally remove it */
o = remove_vm_area((void *)addr);
BUG_ON(p != o || o == NULL);
Expand Down

0 comments on commit d7677d4

Please sign in to comment.