ia64/xen-unstable

changeset 14076:0deb53ff4b67

[IA64] Handle MMIO EFI mappings outside the page table range

We cannot rely on MMIO pages presented in the EFI mem-map can be
mapped directly to the same meta-physical address, because of
restrictions on the address range imposed by the page tables.

As an example, IO ports are located at 0x1ffffffffc000000 on many SN2
systems.

Change assign_domain_mmio_page() to take a flags and a source and
destination address to handle this and catch IO ports above
0x1ffffffff0000000 and map them down to a safe area.

Signed-off-by: Jes Sorensen <jes@sgi.com>
author awilliam@xenbuild2.aw
date Thu Mar 01 11:21:44 2007 -0700 (2007-03-01)
parents f21250323a30
children 8a58ea36e420
files xen/arch/ia64/xen/dom0_ops.c xen/arch/ia64/xen/dom_fw.c xen/arch/ia64/xen/mm.c xen/include/asm-ia64/mm.h
line diff
     1.1 --- a/xen/arch/ia64/xen/dom0_ops.c	Thu Mar 01 10:31:58 2007 -0700
     1.2 +++ b/xen/arch/ia64/xen/dom0_ops.c	Thu Mar 01 11:21:44 2007 -0700
     1.3 @@ -299,13 +299,17 @@ dom0vp_ioremap(struct domain *d, unsigne
     1.4      if (size == 0)
     1.5          size = PAGE_SIZE;
     1.6  
     1.7 +    if (size == 0)
     1.8 +        printk(XENLOG_WARNING "ioremap(): Trying to map %lx, size 0\n", mpaddr);
     1.9 +
    1.10      end = PAGE_ALIGN(mpaddr + size);
    1.11  
    1.12      if (!iomem_access_permitted(d, mpaddr >> PAGE_SHIFT,
    1.13                                  (end >> PAGE_SHIFT) - 1))
    1.14          return -EPERM;
    1.15  
    1.16 -    return assign_domain_mmio_page(d, mpaddr, size);
    1.17 +    return assign_domain_mmio_page(d, mpaddr, mpaddr, size,
    1.18 +                                   ASSIGN_writable | ASSIGN_nocache);
    1.19  }
    1.20  
    1.21  unsigned long
     2.1 --- a/xen/arch/ia64/xen/dom_fw.c	Thu Mar 01 10:31:58 2007 -0700
     2.2 +++ b/xen/arch/ia64/xen/dom_fw.c	Thu Mar 01 11:21:44 2007 -0700
     2.3 @@ -534,6 +534,7 @@ complete_dom0_memmap(struct domain *d,
     2.4  		u64 start = md->phys_addr;
     2.5  		u64 size = md->num_pages << EFI_PAGE_SHIFT;
     2.6  		u64 end = start + size;
     2.7 +		u64 mpaddr;
     2.8  		unsigned long flags;
     2.9  
    2.10  		switch (md->type) {
    2.11 @@ -566,10 +567,22 @@ complete_dom0_memmap(struct domain *d,
    2.12  			break;
    2.13  
    2.14  		case EFI_MEMORY_MAPPED_IO_PORT_SPACE:
    2.15 +			flags = ASSIGN_writable;	/* dummy - zero */
    2.16 +			if (md->attribute & EFI_MEMORY_UC)
    2.17 +				flags |= ASSIGN_nocache;
    2.18 +
    2.19 +			if (start > 0x1ffffffff0000000UL) {
    2.20 +				mpaddr = 0x4000000000000UL - size;
    2.21 +				printk(XENLOG_INFO "Remapping IO ports from "
    2.22 +				       "%lx to %lx\n", start, mpaddr);
    2.23 +			} else
    2.24 +				mpaddr = start;
    2.25 +
    2.26  			/* Map into dom0.  */
    2.27 -			assign_domain_mmio_page(d, start, size);
    2.28 +			assign_domain_mmio_page(d, mpaddr, start, size, flags);
    2.29  			/* Copy descriptor.  */
    2.30  			*dom_md = *md;
    2.31 +			dom_md->phys_addr = mpaddr;
    2.32  			dom_md->virt_addr = 0;
    2.33  			num_mds++;
    2.34  			break;
    2.35 @@ -652,8 +665,12 @@ complete_dom0_memmap(struct domain *d,
    2.36  		if (domain_page_mapped(d, addr))
    2.37  			continue;
    2.38  		
    2.39 -		if (efi_mmio(addr, PAGE_SIZE))
    2.40 -			assign_domain_mmio_page(d, addr, PAGE_SIZE);
    2.41 +		if (efi_mmio(addr, PAGE_SIZE)) {
    2.42 +			unsigned long flags;
    2.43 +			flags = ASSIGN_writable | ASSIGN_nocache;
    2.44 +			assign_domain_mmio_page(d, addr, addr,
    2.45 +						PAGE_SIZE, flags);
    2.46 +		}
    2.47  	}
    2.48  	return num_mds;
    2.49  }
     3.1 --- a/xen/arch/ia64/xen/mm.c	Thu Mar 01 10:31:58 2007 -0700
     3.2 +++ b/xen/arch/ia64/xen/mm.c	Thu Mar 01 11:21:44 2007 -0700
     3.3 @@ -1044,9 +1044,11 @@ efi_mmio(unsigned long physaddr, unsigne
     3.4  }
     3.5  
     3.6  unsigned long
     3.7 -assign_domain_mmio_page(struct domain *d,
     3.8 -                        unsigned long mpaddr, unsigned long size)
     3.9 +assign_domain_mmio_page(struct domain *d, unsigned long mpaddr,
    3.10 +                        unsigned long phys_addr, unsigned long size,
    3.11 +                        unsigned long flags)
    3.12  {
    3.13 +    unsigned long end = PAGE_ALIGN(mpaddr + size);
    3.14      if (size == 0) {
    3.15          gdprintk(XENLOG_INFO, "%s: domain %p mpaddr 0x%lx size = 0x%lx\n",
    3.16                  __func__, d, mpaddr, size);
    3.17 @@ -1058,7 +1060,12 @@ assign_domain_mmio_page(struct domain *d
    3.18  #endif
    3.19          return -EINVAL;
    3.20      }
    3.21 -    assign_domain_same_page(d, mpaddr, size, ASSIGN_writable | ASSIGN_nocache);
    3.22 +
    3.23 +    for (mpaddr &= PAGE_MASK; mpaddr < end;
    3.24 +         mpaddr += PAGE_SIZE, phys_addr += PAGE_SIZE) {
    3.25 +        __assign_domain_page(d, mpaddr, phys_addr, flags);
    3.26 +    }
    3.27 +
    3.28      return mpaddr;
    3.29  }
    3.30  
     4.1 --- a/xen/include/asm-ia64/mm.h	Thu Mar 01 10:31:58 2007 -0700
     4.2 +++ b/xen/include/asm-ia64/mm.h	Thu Mar 01 11:21:44 2007 -0700
     4.3 @@ -433,7 +433,7 @@ struct p2m_entry;
     4.4  extern unsigned long lookup_domain_mpa(struct domain *d, unsigned long mpaddr, struct p2m_entry* entry);
     4.5  extern void *domain_mpa_to_imva(struct domain *d, unsigned long mpaddr);
     4.6  extern volatile pte_t *lookup_noalloc_domain_pte(struct domain* d, unsigned long mpaddr);
     4.7 -extern unsigned long assign_domain_mmio_page(struct domain *d, unsigned long mpaddr, unsigned long size);
     4.8 +extern unsigned long assign_domain_mmio_page(struct domain *d, unsigned long mpaddr, unsigned long phys_addr, unsigned long size, unsigned long flags);
     4.9  extern unsigned long assign_domain_mach_page(struct domain *d, unsigned long mpaddr, unsigned long size, unsigned long flags);
    4.10  int domain_page_mapped(struct domain *d, unsigned long mpaddr);
    4.11  int efi_mmio(unsigned long physaddr, unsigned long size);