ia64/xen-unstable

changeset 10240:f3be4eb8dac9

[IA64] split domain.c into mm.c and domain.c

domain.c has grown too much. split it into two files.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author awilliam@xenbuild.aw
date Sat Jun 03 13:21:38 2006 -0600 (2006-06-03)
parents 34455164dd33
children 4533f6c9fa11
files xen/arch/ia64/xen/Makefile xen/arch/ia64/xen/domain.c xen/arch/ia64/xen/mm.c xen/include/asm-ia64/domain.h xen/include/asm-ia64/mm.h
line diff
     1.1 --- a/xen/arch/ia64/xen/Makefile	Sat Jun 03 13:21:14 2006 -0600
     1.2 +++ b/xen/arch/ia64/xen/Makefile	Sat Jun 03 13:21:38 2006 -0600
     1.3 @@ -9,6 +9,7 @@ obj-y += hyperprivop.o
     1.4  obj-y += idle0_task.o
     1.5  obj-y += irq.o
     1.6  obj-y += ivt.o
     1.7 +obj-y += mm.o
     1.8  obj-y += mm_init.o
     1.9  obj-y += pcdp.o
    1.10  obj-y += privop.o
     2.1 --- a/xen/arch/ia64/xen/domain.c	Sat Jun 03 13:21:14 2006 -0600
     2.2 +++ b/xen/arch/ia64/xen/domain.c	Sat Jun 03 13:21:38 2006 -0600
     2.3 @@ -8,6 +8,10 @@
     2.4   *	Kun Tian (Kevin Tian) <kevin.tian@intel.com>
     2.5   *
     2.6   * 05/04/29 Kun Tian (Kevin Tian) <kevin.tian@intel.com> Add VTI domain support
     2.7 + *
     2.8 + * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
     2.9 + *                    VA Linux Systems Japan K.K.
    2.10 + *                    dom0 vp model support
    2.11   */
    2.12  
    2.13  #include <xen/config.h>
    2.14 @@ -77,44 +81,6 @@ extern void serial_input_init(void);
    2.15  static void init_switch_stack(struct vcpu *v);
    2.16  void build_physmap_table(struct domain *d);
    2.17  
    2.18 -static void try_to_clear_PGC_allocate(struct domain* d,
    2.19 -                                      struct page_info* page);
    2.20 -
    2.21 -#ifdef CONFIG_XEN_IA64_DOM0_VP
    2.22 -static struct domain *dom_xen, *dom_io;
    2.23 -
    2.24 -// followings are stolen from arch_init_memory() @ xen/arch/x86/mm.c
    2.25 -void
    2.26 -alloc_dom_xen_and_dom_io(void)
    2.27 -{
    2.28 -    /*
    2.29 -     * Initialise our DOMID_XEN domain.
    2.30 -     * Any Xen-heap pages that we will allow to be mapped will have
    2.31 -     * their domain field set to dom_xen.
    2.32 -     */
    2.33 -    dom_xen = alloc_domain();
    2.34 -    BUG_ON(dom_xen == NULL);
    2.35 -    spin_lock_init(&dom_xen->page_alloc_lock);
    2.36 -    INIT_LIST_HEAD(&dom_xen->page_list);
    2.37 -    INIT_LIST_HEAD(&dom_xen->xenpage_list);
    2.38 -    atomic_set(&dom_xen->refcnt, 1);
    2.39 -    dom_xen->domain_id = DOMID_XEN;
    2.40 -
    2.41 -    /*
    2.42 -     * Initialise our DOMID_IO domain.
    2.43 -     * This domain owns I/O pages that are within the range of the page_info
    2.44 -     * array. Mappings occur at the priv of the caller.
    2.45 -     */
    2.46 -    dom_io = alloc_domain();
    2.47 -    BUG_ON(dom_io == NULL);
    2.48 -    spin_lock_init(&dom_io->page_alloc_lock);
    2.49 -    INIT_LIST_HEAD(&dom_io->page_list);
    2.50 -    INIT_LIST_HEAD(&dom_io->xenpage_list);
    2.51 -    atomic_set(&dom_io->refcnt, 1);
    2.52 -    dom_io->domain_id = DOMID_IO;
    2.53 -}
    2.54 -#endif
    2.55 -
    2.56  /* this belongs in include/asm, but there doesn't seem to be a suitable place */
    2.57  void arch_domain_destroy(struct domain *d)
    2.58  {
    2.59 @@ -416,106 +382,6 @@ static void relinquish_memory(struct dom
    2.60      spin_unlock_recursive(&d->page_alloc_lock);
    2.61  }
    2.62  
    2.63 -static void
    2.64 -relinquish_pte(struct domain* d, pte_t* pte)
    2.65 -{
    2.66 -    unsigned long mfn = pte_pfn(*pte);
    2.67 -    struct page_info* page;
    2.68 -
    2.69 -    // vmx domain use bit[58:56] to distinguish io region from memory.
    2.70 -    // see vmx_build_physmap_table() in vmx_init.c
    2.71 -    if (((mfn << PAGE_SHIFT) & GPFN_IO_MASK) != GPFN_MEM)
    2.72 -        return;
    2.73 -
    2.74 -    // domain might map IO space or acpi table pages. check it.
    2.75 -    if (!mfn_valid(mfn))
    2.76 -        return;
    2.77 -    page = mfn_to_page(mfn);
    2.78 -    // struct page_info corresponding to mfn may exist or not depending
    2.79 -    // on CONFIG_VIRTUAL_FRAME_TABLE.
    2.80 -    // This check is too easy.
    2.81 -    // The right way is to check whether this page is of io area or acpi pages
    2.82 -    if (page_get_owner(page) == NULL) {
    2.83 -        BUG_ON(page->count_info != 0);
    2.84 -        return;
    2.85 -    }
    2.86 -
    2.87 -#ifdef CONFIG_XEN_IA64_DOM0_VP
    2.88 -    if (page_get_owner(page) == d) {
    2.89 -        BUG_ON(get_gpfn_from_mfn(mfn) == INVALID_M2P_ENTRY);
    2.90 -        set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY);
    2.91 -    }
    2.92 -#endif
    2.93 -    try_to_clear_PGC_allocate(d, page);
    2.94 -    put_page(page);
    2.95 -}
    2.96 -
    2.97 -static void
    2.98 -relinquish_pmd(struct domain* d, pmd_t* pmd, unsigned long offset)
    2.99 -{
   2.100 -    unsigned long i;
   2.101 -    pte_t* pte = pte_offset_map(pmd, offset);
   2.102 -
   2.103 -    for (i = 0; i < PTRS_PER_PTE; i++, pte++) {
   2.104 -        if (!pte_present(*pte))
   2.105 -            continue;
   2.106 -        
   2.107 -        relinquish_pte(d, pte);
   2.108 -    }
   2.109 -    pte_free_kernel(pte_offset_map(pmd, offset));
   2.110 -}
   2.111 -
   2.112 -static void
   2.113 -relinquish_pud(struct domain* d, pud_t *pud, unsigned long offset)
   2.114 -{
   2.115 -    unsigned long i;
   2.116 -    pmd_t *pmd = pmd_offset(pud, offset);
   2.117 -    
   2.118 -    for (i = 0; i < PTRS_PER_PMD; i++, pmd++) {
   2.119 -        if (!pmd_present(*pmd))
   2.120 -            continue;
   2.121 -        
   2.122 -        relinquish_pmd(d, pmd, offset + (i << PMD_SHIFT));
   2.123 -    }
   2.124 -    pmd_free(pmd_offset(pud, offset));
   2.125 -}
   2.126 -
   2.127 -static void
   2.128 -relinquish_pgd(struct domain* d, pgd_t *pgd, unsigned long offset)
   2.129 -{
   2.130 -    unsigned long i;
   2.131 -    pud_t *pud = pud_offset(pgd, offset);
   2.132 -
   2.133 -    for (i = 0; i < PTRS_PER_PUD; i++, pud++) {
   2.134 -        if (!pud_present(*pud))
   2.135 -            continue;
   2.136 -
   2.137 -        relinquish_pud(d, pud, offset + (i << PUD_SHIFT));
   2.138 -    }
   2.139 -    pud_free(pud_offset(pgd, offset));
   2.140 -}
   2.141 -
   2.142 -static void
   2.143 -relinquish_mm(struct domain* d)
   2.144 -{
   2.145 -    struct mm_struct* mm = &d->arch.mm;
   2.146 -    unsigned long i;
   2.147 -    pgd_t* pgd;
   2.148 -
   2.149 -    if (mm->pgd == NULL)
   2.150 -        return;
   2.151 -
   2.152 -    pgd = pgd_offset(mm, 0);
   2.153 -    for (i = 0; i < PTRS_PER_PGD; i++, pgd++) {
   2.154 -        if (!pgd_present(*pgd))
   2.155 -            continue;
   2.156 -
   2.157 -        relinquish_pgd(d, pgd, i << PGDIR_SHIFT);
   2.158 -    }
   2.159 -    pgd_free(mm->pgd);
   2.160 -    mm->pgd = NULL;
   2.161 -}
   2.162 -
   2.163  void domain_relinquish_resources(struct domain *d)
   2.164  {
   2.165      /* Relinquish every page of memory. */
   2.166 @@ -600,451 +466,6 @@ void new_thread(struct vcpu *v,
   2.167  	}
   2.168  }
   2.169  
   2.170 -// stolen from share_xen_page_with_guest() in xen/arch/x86/mm.c
   2.171 -void
   2.172 -share_xen_page_with_guest(struct page_info *page,
   2.173 -                          struct domain *d, int readonly)
   2.174 -{
   2.175 -    if ( page_get_owner(page) == d )
   2.176 -        return;
   2.177 -
   2.178 -#if 1
   2.179 -    if (readonly) {
   2.180 -        printk("%s:%d readonly is not supported yet\n", __func__, __LINE__);
   2.181 -    }
   2.182 -#endif
   2.183 -
   2.184 -    // alloc_xenheap_pages() doesn't initialize page owner.
   2.185 -    //BUG_ON(page_get_owner(page) != NULL);
   2.186 -#if 0
   2.187 -    if (get_gpfn_from_mfn(page_to_mfn(page)) != INVALID_M2P_ENTRY) {
   2.188 -        printk("%s:%d page 0x%p mfn 0x%lx gpfn 0x%lx\n", __func__, __LINE__,
   2.189 -               page, page_to_mfn(page), get_gpfn_from_mfn(page_to_mfn(page)));
   2.190 -    }
   2.191 -#endif
   2.192 -    // grant_table_destroy() release these pages.
   2.193 -    // but it doesn't clear m2p entry. So there might remain stale entry.
   2.194 -    // We clear such a stale entry here.
   2.195 -    set_gpfn_from_mfn(page_to_mfn(page), INVALID_M2P_ENTRY);
   2.196 -
   2.197 -    spin_lock(&d->page_alloc_lock);
   2.198 -
   2.199 -#ifndef __ia64__
   2.200 -    /* The incremented type count pins as writable or read-only. */
   2.201 -    page->u.inuse.type_info  = (readonly ? PGT_none : PGT_writable_page);
   2.202 -    page->u.inuse.type_info |= PGT_validated | 1;
   2.203 -#endif
   2.204 -
   2.205 -    page_set_owner(page, d);
   2.206 -    wmb(); /* install valid domain ptr before updating refcnt. */
   2.207 -    ASSERT(page->count_info == 0);
   2.208 -    page->count_info |= PGC_allocated | 1;
   2.209 -
   2.210 -    if ( unlikely(d->xenheap_pages++ == 0) )
   2.211 -        get_knownalive_domain(d);
   2.212 -    list_add_tail(&page->list, &d->xenpage_list);
   2.213 -
   2.214 -    spin_unlock(&d->page_alloc_lock);
   2.215 -}
   2.216 -
   2.217 -void
   2.218 -share_xen_page_with_privileged_guests(struct page_info *page, int readonly)
   2.219 -{
   2.220 -    share_xen_page_with_guest(page, dom_xen, readonly);
   2.221 -}
   2.222 -
   2.223 -//XXX !xxx_present() should be used instread of !xxx_none()?
   2.224 -static pte_t*
   2.225 -lookup_alloc_domain_pte(struct domain* d, unsigned long mpaddr)
   2.226 -{
   2.227 -    struct mm_struct *mm = &d->arch.mm;
   2.228 -    pgd_t *pgd;
   2.229 -    pud_t *pud;
   2.230 -    pmd_t *pmd;
   2.231 -
   2.232 -    BUG_ON(mm->pgd == NULL);
   2.233 -    pgd = pgd_offset(mm, mpaddr);
   2.234 -    if (pgd_none(*pgd)) {
   2.235 -        pgd_populate(mm, pgd, pud_alloc_one(mm,mpaddr));
   2.236 -    }
   2.237 -
   2.238 -    pud = pud_offset(pgd, mpaddr);
   2.239 -    if (pud_none(*pud)) {
   2.240 -        pud_populate(mm, pud, pmd_alloc_one(mm,mpaddr));
   2.241 -    }
   2.242 -
   2.243 -    pmd = pmd_offset(pud, mpaddr);
   2.244 -    if (pmd_none(*pmd)) {
   2.245 -        pmd_populate_kernel(mm, pmd, pte_alloc_one_kernel(mm, mpaddr));
   2.246 -    }
   2.247 -
   2.248 -    return pte_offset_map(pmd, mpaddr);
   2.249 -}
   2.250 -
   2.251 -//XXX xxx_none() should be used instread of !xxx_present()?
   2.252 -static pte_t*
   2.253 -lookup_noalloc_domain_pte(struct domain* d, unsigned long mpaddr)
   2.254 -{
   2.255 -    struct mm_struct *mm = &d->arch.mm;
   2.256 -    pgd_t *pgd;
   2.257 -    pud_t *pud;
   2.258 -    pmd_t *pmd;
   2.259 -
   2.260 -    BUG_ON(mm->pgd == NULL);
   2.261 -    pgd = pgd_offset(mm, mpaddr);
   2.262 -    if (!pgd_present(*pgd))
   2.263 -        goto not_present;
   2.264 -
   2.265 -    pud = pud_offset(pgd, mpaddr);
   2.266 -    if (!pud_present(*pud))
   2.267 -        goto not_present;
   2.268 -
   2.269 -    pmd = pmd_offset(pud, mpaddr);
   2.270 -    if (!pmd_present(*pmd))
   2.271 -        goto not_present;
   2.272 -
   2.273 -    return pte_offset_map(pmd, mpaddr);
   2.274 -
   2.275 -not_present:
   2.276 -    return NULL;
   2.277 -}
   2.278 -
   2.279 -#ifdef CONFIG_XEN_IA64_DOM0_VP
   2.280 -static pte_t*
   2.281 -lookup_noalloc_domain_pte_none(struct domain* d, unsigned long mpaddr)
   2.282 -{
   2.283 -    struct mm_struct *mm = &d->arch.mm;
   2.284 -    pgd_t *pgd;
   2.285 -    pud_t *pud;
   2.286 -    pmd_t *pmd;
   2.287 -
   2.288 -    BUG_ON(mm->pgd == NULL);
   2.289 -    pgd = pgd_offset(mm, mpaddr);
   2.290 -    if (pgd_none(*pgd))
   2.291 -        goto not_present;
   2.292 -
   2.293 -    pud = pud_offset(pgd, mpaddr);
   2.294 -    if (pud_none(*pud))
   2.295 -        goto not_present;
   2.296 -
   2.297 -    pmd = pmd_offset(pud, mpaddr);
   2.298 -    if (pmd_none(*pmd))
   2.299 -        goto not_present;
   2.300 -
   2.301 -    return pte_offset_map(pmd, mpaddr);
   2.302 -
   2.303 -not_present:
   2.304 -    return NULL;
   2.305 -}
   2.306 -#endif
   2.307 -
   2.308 -/* Allocate a new page for domain and map it to the specified metaphysical 
   2.309 -   address.  */
   2.310 -struct page_info *
   2.311 -__assign_new_domain_page(struct domain *d, unsigned long mpaddr, pte_t* pte)
   2.312 -{
   2.313 -    struct page_info *p = NULL;
   2.314 -    unsigned long maddr;
   2.315 -    int ret;
   2.316 -
   2.317 -    BUG_ON(!pte_none(*pte));
   2.318 -
   2.319 -#ifdef CONFIG_DOMAIN0_CONTIGUOUS
   2.320 -    if (d == dom0) {
   2.321 -#if 0
   2.322 -        if (mpaddr < dom0_start || mpaddr >= dom0_start + dom0_size) {
   2.323 -            /* FIXME: is it true ?
   2.324 -               dom0 memory is not contiguous!  */
   2.325 -            panic("assign_new_domain_page: bad domain0 "
   2.326 -                  "mpaddr=%lx, start=%lx, end=%lx!\n",
   2.327 -                  mpaddr, dom0_start, dom0_start+dom0_size);
   2.328 -        }
   2.329 -#endif
   2.330 -        p = mfn_to_page((mpaddr >> PAGE_SHIFT));
   2.331 -        return p;
   2.332 -    }
   2.333 -#endif
   2.334 -
   2.335 -    p = alloc_domheap_page(d);
   2.336 -    if (unlikely(!p)) {
   2.337 -        printf("assign_new_domain_page: Can't alloc!!!! Aaaargh!\n");
   2.338 -        return(p);
   2.339 -    }
   2.340 -
   2.341 -    // zero out pages for security reasons
   2.342 -    clear_page(page_to_virt(p));
   2.343 -    maddr = page_to_maddr (p);
   2.344 -    if (unlikely(maddr > __get_cpu_var(vhpt_paddr)
   2.345 -                 && maddr < __get_cpu_var(vhpt_pend))) {
   2.346 -        /* FIXME: how can this happen ?
   2.347 -           vhpt is allocated by alloc_domheap_page.  */
   2.348 -        printf("assign_new_domain_page: reassigned vhpt page %lx!!\n",
   2.349 -               maddr);
   2.350 -    }
   2.351 -
   2.352 -    ret = get_page(p, d);
   2.353 -    BUG_ON(ret == 0);
   2.354 -    set_pte(pte, pfn_pte(maddr >> PAGE_SHIFT,
   2.355 -                         __pgprot(__DIRTY_BITS | _PAGE_PL_2 | _PAGE_AR_RWX)));
   2.356 -
   2.357 -    mb ();
   2.358 -    //XXX CONFIG_XEN_IA64_DOM0_VP
   2.359 -    //    TODO racy
   2.360 -    set_gpfn_from_mfn(page_to_mfn(p), mpaddr >> PAGE_SHIFT);
   2.361 -    return p;
   2.362 -}
   2.363 -
   2.364 -struct page_info *
   2.365 -assign_new_domain_page(struct domain *d, unsigned long mpaddr)
   2.366 -{
   2.367 -#ifdef CONFIG_DOMAIN0_CONTIGUOUS
   2.368 -    pte_t dummy_pte = __pte(0);
   2.369 -    return __assign_new_domain_page(d, mpaddr, &dummy_pte);
   2.370 -#else
   2.371 -    struct page_info *p = NULL;
   2.372 -    pte_t *pte;
   2.373 -
   2.374 -    pte = lookup_alloc_domain_pte(d, mpaddr);
   2.375 -    if (pte_none(*pte)) {
   2.376 -        p = __assign_new_domain_page(d, mpaddr, pte);
   2.377 -    } else {
   2.378 -        DPRINTK("%s: d 0x%p mpaddr %lx already mapped!\n",
   2.379 -                __func__, d, mpaddr);
   2.380 -    }
   2.381 -
   2.382 -    return p;
   2.383 -#endif
   2.384 -}
   2.385 -
   2.386 -void
   2.387 -assign_new_domain0_page(struct domain *d, unsigned long mpaddr)
   2.388 -{
   2.389 -#ifndef CONFIG_DOMAIN0_CONTIGUOUS
   2.390 -    pte_t *pte;
   2.391 -
   2.392 -    BUG_ON(d != dom0);
   2.393 -    pte = lookup_alloc_domain_pte(d, mpaddr);
   2.394 -    if (pte_none(*pte)) {
   2.395 -        struct page_info *p = __assign_new_domain_page(d, mpaddr, pte);
   2.396 -        if (p == NULL) {
   2.397 -            panic("%s: can't allocate page for dom0", __func__);
   2.398 -        }
   2.399 -    }
   2.400 -#endif
   2.401 -}
   2.402 -
   2.403 -/* map a physical address to the specified metaphysical addr */
   2.404 -// flags: currently only ASSIGN_readonly
   2.405 -void
   2.406 -__assign_domain_page(struct domain *d,
   2.407 -                     unsigned long mpaddr, unsigned long physaddr,
   2.408 -                     unsigned long flags)
   2.409 -{
   2.410 -    pte_t *pte;
   2.411 -    unsigned long arflags = (flags & ASSIGN_readonly)? _PAGE_AR_R: _PAGE_AR_RWX;
   2.412 -
   2.413 -    pte = lookup_alloc_domain_pte(d, mpaddr);
   2.414 -    if (pte_none(*pte)) {
   2.415 -        set_pte(pte, pfn_pte(physaddr >> PAGE_SHIFT,
   2.416 -                             __pgprot(__DIRTY_BITS | _PAGE_PL_2 | arflags)));
   2.417 -        mb ();
   2.418 -    } else
   2.419 -        printk("%s: mpaddr %lx already mapped!\n", __func__, mpaddr);
   2.420 -}
   2.421 -
   2.422 -/* get_page() and map a physical address to the specified metaphysical addr */
   2.423 -void
   2.424 -assign_domain_page(struct domain *d,
   2.425 -                   unsigned long mpaddr, unsigned long physaddr)
   2.426 -{
   2.427 -    struct page_info* page = mfn_to_page(physaddr >> PAGE_SHIFT);
   2.428 -    int ret;
   2.429 -
   2.430 -    BUG_ON((physaddr & GPFN_IO_MASK) != GPFN_MEM);
   2.431 -    ret = get_page(page, d);
   2.432 -    BUG_ON(ret == 0);
   2.433 -    __assign_domain_page(d, mpaddr, physaddr, ASSIGN_writable);
   2.434 -
   2.435 -    //XXX CONFIG_XEN_IA64_DOM0_VP
   2.436 -    //    TODO racy
   2.437 -    set_gpfn_from_mfn(physaddr >> PAGE_SHIFT, mpaddr >> PAGE_SHIFT);
   2.438 -}
   2.439 -
   2.440 -#ifdef CONFIG_XEN_IA64_DOM0_VP
   2.441 -static void
   2.442 -assign_domain_same_page(struct domain *d,
   2.443 -                        unsigned long mpaddr, unsigned long size,
   2.444 -                        unsigned long flags)
   2.445 -{
   2.446 -    //XXX optimization
   2.447 -    unsigned long end = mpaddr + size;
   2.448 -    for (; mpaddr < end; mpaddr += PAGE_SIZE) {
   2.449 -        __assign_domain_page(d, mpaddr, mpaddr, flags);
   2.450 -    }
   2.451 -}
   2.452 -
   2.453 -static int
   2.454 -efi_mmio(unsigned long physaddr, unsigned long size)
   2.455 -{
   2.456 -    void *efi_map_start, *efi_map_end;
   2.457 -    u64 efi_desc_size;
   2.458 -    void* p;
   2.459 -
   2.460 -    efi_map_start = __va(ia64_boot_param->efi_memmap);
   2.461 -    efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
   2.462 -    efi_desc_size = ia64_boot_param->efi_memdesc_size;
   2.463 -
   2.464 -    for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
   2.465 -        efi_memory_desc_t* md = (efi_memory_desc_t *)p;
   2.466 -        unsigned long start = md->phys_addr;
   2.467 -        unsigned long end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
   2.468 -        
   2.469 -        if (start <= physaddr && physaddr < end) {
   2.470 -            if ((physaddr + size) > end) {
   2.471 -                DPRINTK("%s:%d physaddr 0x%lx size = 0x%lx\n",
   2.472 -                        __func__, __LINE__, physaddr, size);
   2.473 -                return 0;
   2.474 -            }
   2.475 -
   2.476 -            // for io space
   2.477 -            if (md->type == EFI_MEMORY_MAPPED_IO ||
   2.478 -                md->type == EFI_MEMORY_MAPPED_IO_PORT_SPACE) {
   2.479 -                return 1;
   2.480 -            }
   2.481 -
   2.482 -            // for runtime
   2.483 -            // see efi_enter_virtual_mode(void)
   2.484 -            // in linux/arch/ia64/kernel/efi.c
   2.485 -            if ((md->attribute & EFI_MEMORY_RUNTIME) &&
   2.486 -                !(md->attribute & EFI_MEMORY_WB)) {
   2.487 -                return 1;
   2.488 -            }
   2.489 -
   2.490 -            DPRINTK("%s:%d physaddr 0x%lx size = 0x%lx\n",
   2.491 -                    __func__, __LINE__, physaddr, size);
   2.492 -            return 0;
   2.493 -        }
   2.494 -
   2.495 -        if (physaddr < start) {
   2.496 -            break;
   2.497 -        }
   2.498 -    }
   2.499 -
   2.500 -    return 1;
   2.501 -}
   2.502 -
   2.503 -unsigned long
   2.504 -assign_domain_mmio_page(struct domain *d,
   2.505 -                        unsigned long mpaddr, unsigned long size)
   2.506 -{
   2.507 -    if (size == 0) {
   2.508 -        DPRINTK("%s: domain %p mpaddr 0x%lx size = 0x%lx\n",
   2.509 -                __func__, d, mpaddr, size);
   2.510 -    }
   2.511 -    if (!efi_mmio(mpaddr, size)) {
   2.512 -        DPRINTK("%s:%d domain %p mpaddr 0x%lx size = 0x%lx\n",
   2.513 -                __func__, __LINE__, d, mpaddr, size);
   2.514 -        return -EINVAL;
   2.515 -    }
   2.516 -    assign_domain_same_page(d, mpaddr, size, ASSIGN_writable);
   2.517 -    return mpaddr;
   2.518 -}
   2.519 -
   2.520 -unsigned long
   2.521 -assign_domain_mach_page(struct domain *d,
   2.522 -                        unsigned long mpaddr, unsigned long size,
   2.523 -                        unsigned long flags)
   2.524 -{
   2.525 -    assign_domain_same_page(d, mpaddr, size, flags);
   2.526 -    return mpaddr;
   2.527 -}
   2.528 -
   2.529 -//XXX selege hammer.
   2.530 -//    flush finer range.
   2.531 -void
   2.532 -domain_page_flush(struct domain* d, unsigned long mpaddr,
   2.533 -                  unsigned long old_mfn, unsigned long new_mfn)
   2.534 -{
   2.535 -    domain_flush_vtlb_all();
   2.536 -}
   2.537 -#endif
   2.538 -
   2.539 -//XXX heavily depends on the struct page_info layout.
   2.540 -//
   2.541 -// if (page_get_owner(page) == d &&
   2.542 -//     test_and_clear_bit(_PGC_allocated, &page->count_info)) {
   2.543 -//     put_page(page);
   2.544 -// }
   2.545 -static void
   2.546 -try_to_clear_PGC_allocate(struct domain* d, struct page_info* page)
   2.547 -{
   2.548 -    u32 _d, _nd;
   2.549 -    u64 x, nx, y;
   2.550 -
   2.551 -    _d = pickle_domptr(d);
   2.552 -    y = *((u64*)&page->count_info);
   2.553 -    do {
   2.554 -        x = y;
   2.555 -        _nd = x >> 32;
   2.556 -        nx = x - 1;
   2.557 -        __clear_bit(_PGC_allocated, &nx);
   2.558 -
   2.559 -        if (unlikely(!(x & PGC_allocated)) || unlikely(_nd != _d)) {
   2.560 -            struct domain* nd = unpickle_domptr(_nd);
   2.561 -            if (nd == NULL) {
   2.562 -                DPRINTK("gnttab_transfer: Bad page %p: ed=%p(%u) 0x%x, "
   2.563 -                        "sd=%p 0x%x,"
   2.564 -                        " caf=%016lx, taf=%" PRtype_info "\n",
   2.565 -                        (void *) page_to_mfn(page),
   2.566 -                        d, d->domain_id, _d,
   2.567 -                        nd, _nd,
   2.568 -                        x,
   2.569 -                        page->u.inuse.type_info);
   2.570 -            }
   2.571 -            break;
   2.572 -        }
   2.573 -
   2.574 -        BUG_ON((nx & PGC_count_mask) < 1);
   2.575 -        y = cmpxchg((u64*)&page->count_info, x, nx);
   2.576 -    } while (unlikely(y != x));
   2.577 -}
   2.578 -
   2.579 -#ifdef CONFIG_XEN_IA64_DOM0_VP
   2.580 -static void
   2.581 -zap_domain_page_one(struct domain *d, unsigned long mpaddr, int do_put_page)
   2.582 -{
   2.583 -    struct mm_struct *mm = &d->arch.mm;
   2.584 -    pte_t *pte;
   2.585 -    pte_t old_pte;
   2.586 -    unsigned long mfn;
   2.587 -    struct page_info *page;
   2.588 -
   2.589 -    pte = lookup_noalloc_domain_pte_none(d, mpaddr);
   2.590 -    if (pte == NULL)
   2.591 -        return;
   2.592 -    if (pte_none(*pte))
   2.593 -        return;
   2.594 -
   2.595 -    // update pte
   2.596 -    old_pte = ptep_get_and_clear(mm, mpaddr, pte);
   2.597 -    mfn = pte_pfn(old_pte);
   2.598 -    page = mfn_to_page(mfn);
   2.599 -    BUG_ON((page->count_info & PGC_count_mask) == 0);
   2.600 -
   2.601 -    if (page_get_owner(page) == d) {
   2.602 -        BUG_ON(get_gpfn_from_mfn(mfn) != (mpaddr >> PAGE_SHIFT));
   2.603 -        set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY);
   2.604 -    }
   2.605 -
   2.606 -    domain_page_flush(d, mpaddr, mfn, INVALID_MFN);
   2.607 -
   2.608 -    if (do_put_page) {
   2.609 -        try_to_clear_PGC_allocate(d, page);
   2.610 -        put_page(page);
   2.611 -    }
   2.612 -}
   2.613 -#endif
   2.614 -
   2.615  void build_physmap_table(struct domain *d)
   2.616  {
   2.617  	struct list_head *list_ent = d->page_list.next;
   2.618 @@ -1062,438 +483,6 @@ void build_physmap_table(struct domain *
   2.619  	d->arch.physmap_built = 1;
   2.620  }
   2.621  
   2.622 -void mpafoo(unsigned long mpaddr)
   2.623 -{
   2.624 -	extern unsigned long privop_trace;
   2.625 -	if (mpaddr == 0x3800)
   2.626 -		privop_trace = 1;
   2.627 -}
   2.628 -
   2.629 -#ifdef CONFIG_XEN_IA64_DOM0_VP
   2.630 -unsigned long
   2.631 -____lookup_domain_mpa(struct domain *d, unsigned long mpaddr)
   2.632 -{
   2.633 -    pte_t *pte;
   2.634 -
   2.635 -    pte = lookup_noalloc_domain_pte(d, mpaddr);
   2.636 -    if (pte == NULL)
   2.637 -        goto not_present;
   2.638 -
   2.639 -    if (pte_present(*pte))
   2.640 -        return (pte->pte & _PFN_MASK);
   2.641 -    else if (VMX_DOMAIN(d->vcpu[0]))
   2.642 -        return GPFN_INV_MASK;
   2.643 -
   2.644 -not_present:
   2.645 -    return INVALID_MFN;
   2.646 -}
   2.647 -
   2.648 -unsigned long
   2.649 -__lookup_domain_mpa(struct domain *d, unsigned long mpaddr)
   2.650 -{
   2.651 -    unsigned long machine = ____lookup_domain_mpa(d, mpaddr);
   2.652 -    if (machine != INVALID_MFN)
   2.653 -        return machine;
   2.654 -
   2.655 -    printk("%s: d 0x%p id %d current 0x%p id %d\n",
   2.656 -           __func__, d, d->domain_id, current, current->vcpu_id);
   2.657 -    printk("%s: bad mpa 0x%lx (max_pages 0x%lx)\n",
   2.658 -           __func__, mpaddr, (unsigned long)d->max_pages << PAGE_SHIFT);
   2.659 -    return INVALID_MFN;
   2.660 -}
   2.661 -#endif
   2.662 -
   2.663 -unsigned long lookup_domain_mpa(struct domain *d, unsigned long mpaddr)
   2.664 -{
   2.665 -	pte_t *pte;
   2.666 -
   2.667 -#ifdef CONFIG_DOMAIN0_CONTIGUOUS
   2.668 -	if (d == dom0) {
   2.669 -		pte_t pteval;
   2.670 -		if (mpaddr < dom0_start || mpaddr >= dom0_start + dom0_size) {
   2.671 -			//printk("lookup_domain_mpa: bad dom0 mpaddr 0x%lx!\n",mpaddr);
   2.672 -			//printk("lookup_domain_mpa: start=0x%lx,end=0x%lx!\n",dom0_start,dom0_start+dom0_size);
   2.673 -			mpafoo(mpaddr);
   2.674 -		}
   2.675 -		pteval = pfn_pte(mpaddr >> PAGE_SHIFT,
   2.676 -			__pgprot(__DIRTY_BITS | _PAGE_PL_2 | _PAGE_AR_RWX));
   2.677 -		return pte_val(pteval);
   2.678 -	}
   2.679 -#endif
   2.680 -	pte = lookup_noalloc_domain_pte(d, mpaddr);
   2.681 -	if (pte != NULL) {
   2.682 -		if (pte_present(*pte)) {
   2.683 -//printk("lookup_domain_page: found mapping for %lx, pte=%lx\n",mpaddr,pte_val(*pte));
   2.684 -			return pte_val(*pte);
   2.685 -		} else if (VMX_DOMAIN(d->vcpu[0]))
   2.686 -			return GPFN_INV_MASK;
   2.687 -	}
   2.688 -
   2.689 -	printk("%s: d 0x%p id %d current 0x%p id %d\n",
   2.690 -	       __func__, d, d->domain_id, current, current->vcpu_id);
   2.691 -	if ((mpaddr >> PAGE_SHIFT) < d->max_pages)
   2.692 -		printk("%s: non-allocated mpa 0x%lx (< 0x%lx)\n", __func__,
   2.693 -		       mpaddr, (unsigned long)d->max_pages << PAGE_SHIFT);
   2.694 -	else
   2.695 -		printk("%s: bad mpa 0x%lx (=> 0x%lx)\n", __func__,
   2.696 -		       mpaddr, (unsigned long)d->max_pages << PAGE_SHIFT);
   2.697 -	mpafoo(mpaddr);
   2.698 -
   2.699 -	//XXX This is a work around until the emulation memory access to a region
   2.700 -	//    where memory or device are attached is implemented.
   2.701 -	return pte_val(pfn_pte(0, __pgprot(__DIRTY_BITS | _PAGE_PL_2 | _PAGE_AR_RWX)));
   2.702 -}
   2.703 -
   2.704 -#ifdef CONFIG_XEN_IA64_DOM0_VP
   2.705 -//XXX SMP
   2.706 -unsigned long
   2.707 -dom0vp_zap_physmap(struct domain *d, unsigned long gpfn,
   2.708 -                   unsigned int extent_order)
   2.709 -{
   2.710 -    unsigned long ret = 0;
   2.711 -    if (extent_order != 0) {
   2.712 -        //XXX
   2.713 -        ret = -ENOSYS;
   2.714 -        goto out;
   2.715 -    }
   2.716 -
   2.717 -    zap_domain_page_one(d, gpfn << PAGE_SHIFT, 1);
   2.718 -
   2.719 -out:
   2.720 -    return ret;
   2.721 -}
   2.722 -
   2.723 -// caller must get_page(mfn_to_page(mfn)) before
   2.724 -// caller must call set_gpfn_from_mfn().
   2.725 -// flags: currently only ASSIGN_readonly
   2.726 -static void
   2.727 -assign_domain_page_replace(struct domain *d, unsigned long mpaddr,
   2.728 -                           unsigned long mfn, unsigned long flags)
   2.729 -{
   2.730 -    struct mm_struct *mm = &d->arch.mm;
   2.731 -    pte_t* pte;
   2.732 -    pte_t old_pte;
   2.733 -    pte_t npte;
   2.734 -    unsigned long arflags = (flags & ASSIGN_readonly)? _PAGE_AR_R: _PAGE_AR_RWX;
   2.735 -
   2.736 -    pte = lookup_alloc_domain_pte(d, mpaddr);
   2.737 -
   2.738 -    // update pte
   2.739 -    npte = pfn_pte(mfn, __pgprot(__DIRTY_BITS | _PAGE_PL_2 | arflags));
   2.740 -    old_pte = ptep_xchg(mm, mpaddr, pte, npte);
   2.741 -    if (pte_mem(old_pte)) {
   2.742 -        unsigned long old_mfn;
   2.743 -        struct page_info* old_page;
   2.744 -
   2.745 -        // XXX should previous underlying page be removed?
   2.746 -        //  or should error be returned because it is a due to a domain?
   2.747 -        old_mfn = pte_pfn(old_pte);//XXX
   2.748 -        old_page = mfn_to_page(old_mfn);
   2.749 -
   2.750 -        if (page_get_owner(old_page) == d) {
   2.751 -            BUG_ON(get_gpfn_from_mfn(old_mfn) != (mpaddr >> PAGE_SHIFT));
   2.752 -            set_gpfn_from_mfn(old_mfn, INVALID_M2P_ENTRY);
   2.753 -        }
   2.754 -
   2.755 -        domain_page_flush(d, mpaddr, old_mfn, mfn);
   2.756 -
   2.757 -        try_to_clear_PGC_allocate(d, old_page);
   2.758 -        put_page(old_page);
   2.759 -    } else {
   2.760 -        BUG_ON(!mfn_valid(mfn));
   2.761 -        BUG_ON(page_get_owner(mfn_to_page(mfn)) == d &&
   2.762 -               get_gpfn_from_mfn(mfn) != INVALID_M2P_ENTRY);
   2.763 -    }
   2.764 -}
   2.765 -
   2.766 -unsigned long
   2.767 -dom0vp_add_physmap(struct domain* d, unsigned long gpfn, unsigned long mfn,
   2.768 -                   unsigned long flags, domid_t domid)
   2.769 -{
   2.770 -    int error = 0;
   2.771 -    struct domain* rd;
   2.772 -
   2.773 -    rd = find_domain_by_id(domid);
   2.774 -    if (unlikely(rd == NULL)) {
   2.775 -        switch (domid) {
   2.776 -        case DOMID_XEN:
   2.777 -            rd = dom_xen;
   2.778 -            break;
   2.779 -        case DOMID_IO:
   2.780 -            rd = dom_io;
   2.781 -            break;
   2.782 -        default:
   2.783 -            DPRINTK("d 0x%p domid %d "
   2.784 -                    "pgfn 0x%lx mfn 0x%lx flags 0x%lx domid %d\n",
   2.785 -                    d, d->domain_id, gpfn, mfn, flags, domid);
   2.786 -            error = -ESRCH;
   2.787 -            goto out0;
   2.788 -        }
   2.789 -        BUG_ON(rd == NULL);
   2.790 -        get_knownalive_domain(rd);
   2.791 -    }
   2.792 -
   2.793 -    if (unlikely(rd == d)) {
   2.794 -        error = -EINVAL;
   2.795 -        goto out1;
   2.796 -    }
   2.797 -    if (unlikely(get_page(mfn_to_page(mfn), rd) == 0)) {
   2.798 -        error = -EINVAL;
   2.799 -        goto out1;
   2.800 -    }
   2.801 -
   2.802 -    assign_domain_page_replace(d, gpfn << PAGE_SHIFT, mfn, flags);
   2.803 -    //don't update p2m table because this page belongs to rd, not d.
   2.804 -out1:
   2.805 -    put_domain(rd);
   2.806 -out0:
   2.807 -    return error;
   2.808 -}
   2.809 -
   2.810 -// grant table host mapping
   2.811 -// mpaddr: host_addr: pseudo physical address
   2.812 -// mfn: frame: machine page frame
   2.813 -// flags: GNTMAP_readonly | GNTMAP_application_map | GNTMAP_contains_pte
   2.814 -int
   2.815 -create_grant_host_mapping(unsigned long gpaddr,
   2.816 -			  unsigned long mfn, unsigned int flags)
   2.817 -{
   2.818 -    struct domain* d = current->domain;
   2.819 -    struct page_info* page;
   2.820 -    int ret;
   2.821 -
   2.822 -    if (flags & (GNTMAP_device_map | 
   2.823 -                 GNTMAP_application_map | GNTMAP_contains_pte)) {
   2.824 -        DPRINTK("%s: flags 0x%x\n", __func__, flags);
   2.825 -        return GNTST_general_error;
   2.826 -    }
   2.827 -
   2.828 -    page = mfn_to_page(mfn);
   2.829 -    ret = get_page(page, page_get_owner(page));
   2.830 -    BUG_ON(ret == 0);
   2.831 -
   2.832 -    assign_domain_page_replace(d, gpaddr, mfn, (flags & GNTMAP_readonly)?
   2.833 -                                              ASSIGN_readonly: ASSIGN_writable);
   2.834 -    return GNTST_okay;
   2.835 -}
   2.836 -
   2.837 -// grant table host unmapping
   2.838 -int
   2.839 -destroy_grant_host_mapping(unsigned long gpaddr,
   2.840 -			   unsigned long mfn, unsigned int flags)
   2.841 -{
   2.842 -    struct domain* d = current->domain;
   2.843 -    pte_t* pte;
   2.844 -    pte_t old_pte;
   2.845 -    unsigned long old_mfn = INVALID_MFN;
   2.846 -    struct page_info* old_page;
   2.847 -
   2.848 -    if (flags & (GNTMAP_application_map | GNTMAP_contains_pte)) {
   2.849 -        DPRINTK("%s: flags 0x%x\n", __func__, flags);
   2.850 -        return GNTST_general_error;
   2.851 -    }
   2.852 -
   2.853 -    pte = lookup_noalloc_domain_pte(d, gpaddr);
   2.854 -    if (pte == NULL || !pte_present(*pte) || pte_pfn(*pte) != mfn)
   2.855 -        return GNTST_general_error;
   2.856 -
   2.857 -    // update pte
   2.858 -    old_pte = ptep_get_and_clear(&d->arch.mm, gpaddr, pte);
   2.859 -    if (pte_present(old_pte)) {
   2.860 -        old_mfn = pte_pfn(old_pte);
   2.861 -    } else {
   2.862 -        return GNTST_general_error;
   2.863 -    }
   2.864 -    domain_page_flush(d, gpaddr, old_mfn, INVALID_MFN);
   2.865 -
   2.866 -    old_page = mfn_to_page(old_mfn);
   2.867 -    BUG_ON(page_get_owner(old_page) == d);//try_to_clear_PGC_allocate(d, page) is not needed.
   2.868 -    put_page(old_page);
   2.869 -
   2.870 -    return GNTST_okay;
   2.871 -}
   2.872 -
   2.873 -//XXX needs refcount patch
   2.874 -//XXX heavily depends on the struct page layout.
   2.875 -//XXX SMP
   2.876 -int
   2.877 -steal_page_for_grant_transfer(struct domain *d, struct page_info *page)
   2.878 -{
   2.879 -#if 0 /* if big endian */
   2.880 -# error "implement big endian version of steal_page_for_grant_transfer()"
   2.881 -#endif
   2.882 -    u32 _d, _nd;
   2.883 -    u64 x, nx, y;
   2.884 -    unsigned long mpaddr = get_gpfn_from_mfn(page_to_mfn(page)) << PAGE_SHIFT;
   2.885 -    struct page_info *new;
   2.886 -
   2.887 -    zap_domain_page_one(d, mpaddr, 0);
   2.888 -    put_page(page);
   2.889 -
   2.890 -    spin_lock(&d->page_alloc_lock);
   2.891 -
   2.892 -    /*
   2.893 -     * The tricky bit: atomically release ownership while there is just one
   2.894 -     * benign reference to the page (PGC_allocated). If that reference
   2.895 -     * disappears then the deallocation routine will safely spin.
   2.896 -     */
   2.897 -    _d  = pickle_domptr(d);
   2.898 -    y = *((u64*)&page->count_info);
   2.899 -    do {
   2.900 -        x = y;
   2.901 -        nx = x & 0xffffffff;
   2.902 -        // page->count_info: untouched
   2.903 -        // page->u.inused._domain = 0;
   2.904 -        _nd = x >> 32;
   2.905 -
   2.906 -        if (unlikely((x & (PGC_count_mask | PGC_allocated)) !=
   2.907 -                     (1 | PGC_allocated)) ||
   2.908 -            unlikely(_nd != _d)) {
   2.909 -            struct domain* nd = unpickle_domptr(_nd);
   2.910 -            if (nd == NULL) {
   2.911 -                DPRINTK("gnttab_transfer: Bad page %p: ed=%p(%u) 0x%x, "
   2.912 -                        "sd=%p 0x%x,"
   2.913 -                        " caf=%016lx, taf=%" PRtype_info "\n",
   2.914 -                        (void *) page_to_mfn(page),
   2.915 -                        d, d->domain_id, _d,
   2.916 -                        nd, _nd,
   2.917 -                        x,
   2.918 -                        page->u.inuse.type_info);
   2.919 -            } else {
   2.920 -                DPRINTK("gnttab_transfer: Bad page %p: ed=%p(%u) 0x%x, "
   2.921 -                        "sd=%p(%u) 0x%x,"
   2.922 -                        " caf=%016lx, taf=%" PRtype_info "\n",
   2.923 -                        (void *) page_to_mfn(page),
   2.924 -                        d, d->domain_id, _d,
   2.925 -                        nd, nd->domain_id, _nd,
   2.926 -                        x,
   2.927 -                        page->u.inuse.type_info);
   2.928 -            }
   2.929 -            spin_unlock(&d->page_alloc_lock);
   2.930 -            return -1;
   2.931 -        }
   2.932 -
   2.933 -        y = cmpxchg((u64*)&page->count_info, x, nx);
   2.934 -    } while (unlikely(y != x));
   2.935 -
   2.936 -    /*
   2.937 -     * Unlink from 'd'. At least one reference remains (now anonymous), so
   2.938 -     * noone else is spinning to try to delete this page from 'd'.
   2.939 -     */
   2.940 -    d->tot_pages--;
   2.941 -    list_del(&page->list);
   2.942 -
   2.943 -    spin_unlock(&d->page_alloc_lock);
   2.944 -
   2.945 -#if 1
   2.946 -    //XXX Until net_rx_action() fix
   2.947 -    // assign new page for this mpaddr
   2.948 -    new = assign_new_domain_page(d, mpaddr);
   2.949 -    BUG_ON(new == NULL);//XXX
   2.950 -#endif
   2.951 -
   2.952 -    return 0;
   2.953 -}
   2.954 -
   2.955 -void
   2.956 -guest_physmap_add_page(struct domain *d, unsigned long gpfn,
   2.957 -                       unsigned long mfn)
   2.958 -{
   2.959 -    int ret;
   2.960 -
   2.961 -    ret = get_page(mfn_to_page(mfn), d);
   2.962 -    BUG_ON(ret == 0);
   2.963 -    assign_domain_page_replace(d, gpfn << PAGE_SHIFT, mfn, ASSIGN_writable);
   2.964 -    set_gpfn_from_mfn(mfn, gpfn);//XXX SMP
   2.965 -
   2.966 -    //BUG_ON(mfn != ((lookup_domain_mpa(d, gpfn << PAGE_SHIFT) & _PFN_MASK) >> PAGE_SHIFT));
   2.967 -}
   2.968 -
   2.969 -void
   2.970 -guest_physmap_remove_page(struct domain *d, unsigned long gpfn,
   2.971 -                          unsigned long mfn)
   2.972 -{
   2.973 -    BUG_ON(mfn == 0);//XXX
   2.974 -    zap_domain_page_one(d, gpfn << PAGE_SHIFT, 1);
   2.975 -}
   2.976 -#endif
   2.977 -
   2.978 -/* Flush cache of domain d.  */
   2.979 -void domain_cache_flush (struct domain *d, int sync_only)
   2.980 -{
   2.981 -	struct mm_struct *mm = &d->arch.mm;
   2.982 -	pgd_t *pgd = mm->pgd;
   2.983 -	unsigned long maddr;
   2.984 -	int i,j,k, l;
   2.985 -	int nbr_page = 0;
   2.986 -	void (*flush_func)(unsigned long start, unsigned long end);
   2.987 -	extern void flush_dcache_range (unsigned long, unsigned long);
   2.988 -
   2.989 -	if (sync_only)
   2.990 -		flush_func = &flush_icache_range;
   2.991 -	else
   2.992 -		flush_func = &flush_dcache_range;
   2.993 -
   2.994 -#ifdef CONFIG_DOMAIN0_CONTIGUOUS
   2.995 -	if (d == dom0) {
   2.996 -		/* This is not fully correct (because of hole), but it should
   2.997 -		   be enough for now.  */
   2.998 -		(*flush_func)(__va_ul (dom0_start),
   2.999 -			      __va_ul (dom0_start + dom0_size));
  2.1000 -		return;
  2.1001 -	}
  2.1002 -#endif
  2.1003 -	for (i = 0; i < PTRS_PER_PGD; pgd++, i++) {
  2.1004 -		pud_t *pud;
  2.1005 -		if (!pgd_present(*pgd))
  2.1006 -			continue;
  2.1007 -		pud = pud_offset(pgd, 0);
  2.1008 -		for (j = 0; j < PTRS_PER_PUD; pud++, j++) {
  2.1009 -			pmd_t *pmd;
  2.1010 -			if (!pud_present(*pud))
  2.1011 -				continue;
  2.1012 -			pmd = pmd_offset(pud, 0);
  2.1013 -			for (k = 0; k < PTRS_PER_PMD; pmd++, k++) {
  2.1014 -				pte_t *pte;
  2.1015 -				if (!pmd_present(*pmd))
  2.1016 -					continue;
  2.1017 -				pte = pte_offset_map(pmd, 0);
  2.1018 -				for (l = 0; l < PTRS_PER_PTE; pte++, l++) {
  2.1019 -					if (!pte_present(*pte))
  2.1020 -						continue;
  2.1021 -					/* Convert PTE to maddr.  */
  2.1022 -					maddr = __va_ul (pte_val(*pte)
  2.1023 -							 & _PAGE_PPN_MASK);
  2.1024 -					(*flush_func)(maddr, maddr+ PAGE_SIZE);
  2.1025 -					nbr_page++;
  2.1026 -				}
  2.1027 -			}
  2.1028 -		}
  2.1029 -	}
  2.1030 -	//printf ("domain_cache_flush: %d %d pages\n", d->domain_id, nbr_page);
  2.1031 -}
  2.1032 -
  2.1033 -// FIXME: ONLY USE FOR DOMAIN PAGE_SIZE == PAGE_SIZE
  2.1034 -#if 1
  2.1035 -unsigned long domain_mpa_to_imva(struct domain *d, unsigned long mpaddr)
  2.1036 -{
  2.1037 -	unsigned long pte = lookup_domain_mpa(d,mpaddr);
  2.1038 -	unsigned long imva;
  2.1039 -
  2.1040 -	pte &= _PAGE_PPN_MASK;
  2.1041 -	imva = (unsigned long) __va(pte);
  2.1042 -	imva |= mpaddr & ~PAGE_MASK;
  2.1043 -	return(imva);
  2.1044 -}
  2.1045 -#else
  2.1046 -unsigned long domain_mpa_to_imva(struct domain *d, unsigned long mpaddr)
  2.1047 -{
  2.1048 -    unsigned long imva = __gpa_to_mpa(d, mpaddr);
  2.1049 -
  2.1050 -    return __va(imva);
  2.1051 -}
  2.1052 -#endif
  2.1053 -
  2.1054  // remove following line if not privifying in memory
  2.1055  //#define HAVE_PRIVIFY_MEMORY
  2.1056  #ifndef HAVE_PRIVIFY_MEMORY
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/xen/arch/ia64/xen/mm.c	Sat Jun 03 13:21:38 2006 -0600
     3.3 @@ -0,0 +1,1036 @@
     3.4 +/*
     3.5 + *  Copyright (C) 2005 Intel Co
     3.6 + *	Kun Tian (Kevin Tian) <kevin.tian@intel.com>
     3.7 + *
     3.8 + * 05/04/29 Kun Tian (Kevin Tian) <kevin.tian@intel.com> Add VTI domain support
     3.9 + *
    3.10 + * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
    3.11 + *                    VA Linux Systems Japan K.K.
    3.12 + *                    dom0 vp model support
    3.13 + */
    3.14 +
    3.15 +#include <xen/config.h>
    3.16 +#include <asm/xentypes.h>
    3.17 +#include <asm/mm.h>
    3.18 +#include <asm/pgalloc.h>
    3.19 +#include <asm/vhpt.h>
    3.20 +#include <linux/efi.h>
    3.21 +
    3.22 +#ifndef CONFIG_XEN_IA64_DOM0_VP
    3.23 +#define CONFIG_DOMAIN0_CONTIGUOUS
    3.24 +#else
    3.25 +static void domain_page_flush(struct domain* d, unsigned long mpaddr,
    3.26 +                              unsigned long old_mfn, unsigned long new_mfn);
    3.27 +#endif
    3.28 +
    3.29 +static struct domain *dom_xen, *dom_io;
    3.30 +
    3.31 +// followings are stolen from arch_init_memory() @ xen/arch/x86/mm.c
    3.32 +void
    3.33 +alloc_dom_xen_and_dom_io(void)
    3.34 +{
    3.35 +    /*
    3.36 +     * Initialise our DOMID_XEN domain.
    3.37 +     * Any Xen-heap pages that we will allow to be mapped will have
    3.38 +     * their domain field set to dom_xen.
    3.39 +     */
    3.40 +    dom_xen = alloc_domain();
    3.41 +    BUG_ON(dom_xen == NULL);
    3.42 +    spin_lock_init(&dom_xen->page_alloc_lock);
    3.43 +    INIT_LIST_HEAD(&dom_xen->page_list);
    3.44 +    INIT_LIST_HEAD(&dom_xen->xenpage_list);
    3.45 +    atomic_set(&dom_xen->refcnt, 1);
    3.46 +    dom_xen->domain_id = DOMID_XEN;
    3.47 +
    3.48 +    /*
    3.49 +     * Initialise our DOMID_IO domain.
    3.50 +     * This domain owns I/O pages that are within the range of the page_info
    3.51 +     * array. Mappings occur at the priv of the caller.
    3.52 +     */
    3.53 +    dom_io = alloc_domain();
    3.54 +    BUG_ON(dom_io == NULL);
    3.55 +    spin_lock_init(&dom_io->page_alloc_lock);
    3.56 +    INIT_LIST_HEAD(&dom_io->page_list);
    3.57 +    INIT_LIST_HEAD(&dom_io->xenpage_list);
    3.58 +    atomic_set(&dom_io->refcnt, 1);
    3.59 +    dom_io->domain_id = DOMID_IO;
    3.60 +}
    3.61 +
    3.62 +// heavily depends on the struct page_info layout.
    3.63 +// if (page_get_owner(page) == d &&
    3.64 +//     test_and_clear_bit(_PGC_allocated, &page->count_info)) {
    3.65 +//     put_page(page);
    3.66 +// }
    3.67 +static void
    3.68 +try_to_clear_PGC_allocate(struct domain* d, struct page_info* page)
    3.69 +{
    3.70 +    u32 _d, _nd;
    3.71 +    u64 x, nx, y;
    3.72 +
    3.73 +    _d = pickle_domptr(d);
    3.74 +    y = *((u64*)&page->count_info);
    3.75 +    do {
    3.76 +        x = y;
    3.77 +        _nd = x >> 32;
    3.78 +        nx = x - 1;
    3.79 +        __clear_bit(_PGC_allocated, &nx);
    3.80 +
    3.81 +        if (unlikely(!(x & PGC_allocated)) || unlikely(_nd != _d)) {
    3.82 +            struct domain* nd = unpickle_domptr(_nd);
    3.83 +            if (nd == NULL) {
    3.84 +                DPRINTK("gnttab_transfer: Bad page %p: ed=%p(%u) 0x%x, "
    3.85 +                        "sd=%p 0x%x,"
    3.86 +                        " caf=%016lx, taf=%" PRtype_info "\n",
    3.87 +                        (void *) page_to_mfn(page),
    3.88 +                        d, d->domain_id, _d,
    3.89 +                        nd, _nd,
    3.90 +                        x,
    3.91 +                        page->u.inuse.type_info);
    3.92 +            }
    3.93 +            break;
    3.94 +        }
    3.95 +
    3.96 +        BUG_ON((nx & PGC_count_mask) < 1);
    3.97 +        y = cmpxchg((u64*)&page->count_info, x, nx);
    3.98 +    } while (unlikely(y != x));
    3.99 +}
   3.100 +
   3.101 +static void
   3.102 +relinquish_pte(struct domain* d, pte_t* pte)
   3.103 +{
   3.104 +    unsigned long mfn = pte_pfn(*pte);
   3.105 +    struct page_info* page;
   3.106 +
   3.107 +    // vmx domain use bit[58:56] to distinguish io region from memory.
   3.108 +    // see vmx_build_physmap_table() in vmx_init.c
   3.109 +    if (((mfn << PAGE_SHIFT) & GPFN_IO_MASK) != GPFN_MEM)
   3.110 +        return;
   3.111 +
   3.112 +    // domain might map IO space or acpi table pages. check it.
   3.113 +    if (!mfn_valid(mfn))
   3.114 +        return;
   3.115 +    page = mfn_to_page(mfn);
   3.116 +    // struct page_info corresponding to mfn may exist or not depending
   3.117 +    // on CONFIG_VIRTUAL_FRAME_TABLE.
   3.118 +    // This check is too easy.
   3.119 +    // The right way is to check whether this page is of io area or acpi pages
   3.120 +    if (page_get_owner(page) == NULL) {
   3.121 +        BUG_ON(page->count_info != 0);
   3.122 +        return;
   3.123 +    }
   3.124 +
   3.125 +#ifdef CONFIG_XEN_IA64_DOM0_VP
   3.126 +    if (page_get_owner(page) == d) {
   3.127 +        BUG_ON(get_gpfn_from_mfn(mfn) == INVALID_M2P_ENTRY);
   3.128 +        set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY);
   3.129 +    }
   3.130 +#endif
   3.131 +    try_to_clear_PGC_allocate(d, page);
   3.132 +    put_page(page);
   3.133 +}
   3.134 +
   3.135 +static void
   3.136 +relinquish_pmd(struct domain* d, pmd_t* pmd, unsigned long offset)
   3.137 +{
   3.138 +    unsigned long i;
   3.139 +    pte_t* pte = pte_offset_map(pmd, offset);
   3.140 +
   3.141 +    for (i = 0; i < PTRS_PER_PTE; i++, pte++) {
   3.142 +        if (!pte_present(*pte))
   3.143 +            continue;
   3.144 +
   3.145 +        relinquish_pte(d, pte);
   3.146 +    }
   3.147 +    pte_free_kernel(pte_offset_map(pmd, offset));
   3.148 +}
   3.149 +
   3.150 +static void
   3.151 +relinquish_pud(struct domain* d, pud_t *pud, unsigned long offset)
   3.152 +{
   3.153 +    unsigned long i;
   3.154 +    pmd_t *pmd = pmd_offset(pud, offset);
   3.155 +
   3.156 +    for (i = 0; i < PTRS_PER_PMD; i++, pmd++) {
   3.157 +        if (!pmd_present(*pmd))
   3.158 +            continue;
   3.159 +
   3.160 +        relinquish_pmd(d, pmd, offset + (i << PMD_SHIFT));
   3.161 +    }
   3.162 +    pmd_free(pmd_offset(pud, offset));
   3.163 +}
   3.164 +
   3.165 +static void
   3.166 +relinquish_pgd(struct domain* d, pgd_t *pgd, unsigned long offset)
   3.167 +{
   3.168 +    unsigned long i;
   3.169 +    pud_t *pud = pud_offset(pgd, offset);
   3.170 +
   3.171 +    for (i = 0; i < PTRS_PER_PUD; i++, pud++) {
   3.172 +        if (!pud_present(*pud))
   3.173 +            continue;
   3.174 +
   3.175 +        relinquish_pud(d, pud, offset + (i << PUD_SHIFT));
   3.176 +    }
   3.177 +    pud_free(pud_offset(pgd, offset));
   3.178 +}
   3.179 +
   3.180 +void
   3.181 +relinquish_mm(struct domain* d)
   3.182 +{
   3.183 +    struct mm_struct* mm = &d->arch.mm;
   3.184 +    unsigned long i;
   3.185 +    pgd_t* pgd;
   3.186 +
   3.187 +    if (mm->pgd == NULL)
   3.188 +        return;
   3.189 +
   3.190 +    pgd = pgd_offset(mm, 0);
   3.191 +    for (i = 0; i < PTRS_PER_PGD; i++, pgd++) {
   3.192 +        if (!pgd_present(*pgd))
   3.193 +            continue;
   3.194 +
   3.195 +        relinquish_pgd(d, pgd, i << PGDIR_SHIFT);
   3.196 +    }
   3.197 +    pgd_free(mm->pgd);
   3.198 +    mm->pgd = NULL;
   3.199 +}
   3.200 +
   3.201 +// stolen from share_xen_page_with_guest() in xen/arch/x86/mm.c
   3.202 +void
   3.203 +share_xen_page_with_guest(struct page_info *page,
   3.204 +                          struct domain *d, int readonly)
   3.205 +{
   3.206 +    if ( page_get_owner(page) == d )
   3.207 +        return;
   3.208 +
   3.209 +#if 1
   3.210 +    if (readonly) {
   3.211 +        printk("%s:%d readonly is not supported yet\n", __func__, __LINE__);
   3.212 +    }
   3.213 +#endif
   3.214 +
   3.215 +    // alloc_xenheap_pages() doesn't initialize page owner.
   3.216 +    //BUG_ON(page_get_owner(page) != NULL);
   3.217 +#if 0
   3.218 +    if (get_gpfn_from_mfn(page_to_mfn(page)) != INVALID_M2P_ENTRY) {
   3.219 +        printk("%s:%d page 0x%p mfn 0x%lx gpfn 0x%lx\n", __func__, __LINE__,
   3.220 +               page, page_to_mfn(page), get_gpfn_from_mfn(page_to_mfn(page)));
   3.221 +    }
   3.222 +#endif
   3.223 +    // grant_table_destroy() release these pages.
   3.224 +    // but it doesn't clear m2p entry. So there might remain stale entry.
   3.225 +    // We clear such a stale entry here.
   3.226 +    set_gpfn_from_mfn(page_to_mfn(page), INVALID_M2P_ENTRY);
   3.227 +
   3.228 +    spin_lock(&d->page_alloc_lock);
   3.229 +
   3.230 +#ifndef __ia64__
   3.231 +    /* The incremented type count pins as writable or read-only. */
   3.232 +    page->u.inuse.type_info  = (readonly ? PGT_none : PGT_writable_page);
   3.233 +    page->u.inuse.type_info |= PGT_validated | 1;
   3.234 +#endif
   3.235 +
   3.236 +    page_set_owner(page, d);
   3.237 +    wmb(); /* install valid domain ptr before updating refcnt. */
   3.238 +    ASSERT(page->count_info == 0);
   3.239 +    page->count_info |= PGC_allocated | 1;
   3.240 +
   3.241 +    if ( unlikely(d->xenheap_pages++ == 0) )
   3.242 +        get_knownalive_domain(d);
   3.243 +    list_add_tail(&page->list, &d->xenpage_list);
   3.244 +
   3.245 +    spin_unlock(&d->page_alloc_lock);
   3.246 +}
   3.247 +
   3.248 +void
   3.249 +share_xen_page_with_privileged_guests(struct page_info *page, int readonly)
   3.250 +{
   3.251 +    share_xen_page_with_guest(page, dom_xen, readonly);
   3.252 +}
   3.253 +
   3.254 +//XXX !xxx_present() should be used instread of !xxx_none()?
   3.255 +static pte_t*
   3.256 +lookup_alloc_domain_pte(struct domain* d, unsigned long mpaddr)
   3.257 +{
   3.258 +    struct mm_struct *mm = &d->arch.mm;
   3.259 +    pgd_t *pgd;
   3.260 +    pud_t *pud;
   3.261 +    pmd_t *pmd;
   3.262 +
   3.263 +    BUG_ON(mm->pgd == NULL);
   3.264 +    pgd = pgd_offset(mm, mpaddr);
   3.265 +    if (pgd_none(*pgd)) {
   3.266 +        pgd_populate(mm, pgd, pud_alloc_one(mm,mpaddr));
   3.267 +    }
   3.268 +
   3.269 +    pud = pud_offset(pgd, mpaddr);
   3.270 +    if (pud_none(*pud)) {
   3.271 +        pud_populate(mm, pud, pmd_alloc_one(mm,mpaddr));
   3.272 +    }
   3.273 +
   3.274 +    pmd = pmd_offset(pud, mpaddr);
   3.275 +    if (pmd_none(*pmd)) {
   3.276 +        pmd_populate_kernel(mm, pmd, pte_alloc_one_kernel(mm, mpaddr));
   3.277 +    }
   3.278 +
   3.279 +    return pte_offset_map(pmd, mpaddr);
   3.280 +}
   3.281 +
   3.282 +//XXX xxx_none() should be used instread of !xxx_present()?
   3.283 +static pte_t*
   3.284 +lookup_noalloc_domain_pte(struct domain* d, unsigned long mpaddr)
   3.285 +{
   3.286 +    struct mm_struct *mm = &d->arch.mm;
   3.287 +    pgd_t *pgd;
   3.288 +    pud_t *pud;
   3.289 +    pmd_t *pmd;
   3.290 +
   3.291 +    BUG_ON(mm->pgd == NULL);
   3.292 +    pgd = pgd_offset(mm, mpaddr);
   3.293 +    if (!pgd_present(*pgd))
   3.294 +        goto not_present;
   3.295 +
   3.296 +    pud = pud_offset(pgd, mpaddr);
   3.297 +    if (!pud_present(*pud))
   3.298 +        goto not_present;
   3.299 +
   3.300 +    pmd = pmd_offset(pud, mpaddr);
   3.301 +    if (!pmd_present(*pmd))
   3.302 +        goto not_present;
   3.303 +
   3.304 +    return pte_offset_map(pmd, mpaddr);
   3.305 +
   3.306 +not_present:
   3.307 +    return NULL;
   3.308 +}
   3.309 +
   3.310 +#ifdef CONFIG_XEN_IA64_DOM0_VP
   3.311 +static pte_t*
   3.312 +lookup_noalloc_domain_pte_none(struct domain* d, unsigned long mpaddr)
   3.313 +{
   3.314 +    struct mm_struct *mm = &d->arch.mm;
   3.315 +    pgd_t *pgd;
   3.316 +    pud_t *pud;
   3.317 +    pmd_t *pmd;
   3.318 +
   3.319 +    BUG_ON(mm->pgd == NULL);
   3.320 +    pgd = pgd_offset(mm, mpaddr);
   3.321 +    if (pgd_none(*pgd))
   3.322 +        goto not_present;
   3.323 +
   3.324 +    pud = pud_offset(pgd, mpaddr);
   3.325 +    if (pud_none(*pud))
   3.326 +        goto not_present;
   3.327 +
   3.328 +    pmd = pmd_offset(pud, mpaddr);
   3.329 +    if (pmd_none(*pmd))
   3.330 +        goto not_present;
   3.331 +
   3.332 +    return pte_offset_map(pmd, mpaddr);
   3.333 +
   3.334 +not_present:
   3.335 +    return NULL;
   3.336 +}
   3.337 +
   3.338 +unsigned long
   3.339 +____lookup_domain_mpa(struct domain *d, unsigned long mpaddr)
   3.340 +{
   3.341 +    pte_t *pte;
   3.342 +
   3.343 +    pte = lookup_noalloc_domain_pte(d, mpaddr);
   3.344 +    if (pte == NULL)
   3.345 +        goto not_present;
   3.346 +
   3.347 +    if (pte_present(*pte))
   3.348 +        return (pte->pte & _PFN_MASK);
   3.349 +    else if (VMX_DOMAIN(d->vcpu[0]))
   3.350 +        return GPFN_INV_MASK;
   3.351 +
   3.352 +not_present:
   3.353 +    return INVALID_MFN;
   3.354 +}
   3.355 +
   3.356 +unsigned long
   3.357 +__lookup_domain_mpa(struct domain *d, unsigned long mpaddr)
   3.358 +{
   3.359 +    unsigned long machine = ____lookup_domain_mpa(d, mpaddr);
   3.360 +    if (machine != INVALID_MFN)
   3.361 +        return machine;
   3.362 +
   3.363 +    printk("%s: d 0x%p id %d current 0x%p id %d\n",
   3.364 +           __func__, d, d->domain_id, current, current->vcpu_id);
   3.365 +    printk("%s: bad mpa 0x%lx (max_pages 0x%lx)\n",
   3.366 +           __func__, mpaddr, (unsigned long)d->max_pages << PAGE_SHIFT);
   3.367 +    return INVALID_MFN;
   3.368 +}
   3.369 +#endif
   3.370 +
   3.371 +void mpafoo(unsigned long mpaddr)
   3.372 +{
   3.373 +    extern unsigned long privop_trace;
   3.374 +    if (mpaddr == 0x3800)
   3.375 +        privop_trace = 1;
   3.376 +}
   3.377 +
   3.378 +unsigned long lookup_domain_mpa(struct domain *d, unsigned long mpaddr)
   3.379 +{
   3.380 +    pte_t *pte;
   3.381 +
   3.382 +#ifdef CONFIG_DOMAIN0_CONTIGUOUS
   3.383 +    if (d == dom0) {
   3.384 +        pte_t pteval;
   3.385 +        if (mpaddr < dom0_start || mpaddr >= dom0_start + dom0_size) {
   3.386 +            //printk("lookup_domain_mpa: bad dom0 mpaddr 0x%lx!\n",mpaddr);
   3.387 +            //printk("lookup_domain_mpa: start=0x%lx,end=0x%lx!\n",dom0_start,dom0_start+dom0_size);
   3.388 +            mpafoo(mpaddr);
   3.389 +        }
   3.390 +        pteval = pfn_pte(mpaddr >> PAGE_SHIFT,
   3.391 +            __pgprot(__DIRTY_BITS | _PAGE_PL_2 | _PAGE_AR_RWX));
   3.392 +        return pte_val(pteval);
   3.393 +    }
   3.394 +#endif
   3.395 +    pte = lookup_noalloc_domain_pte(d, mpaddr);
   3.396 +    if (pte != NULL) {
   3.397 +        if (pte_present(*pte)) {
   3.398 +//printk("lookup_domain_page: found mapping for %lx, pte=%lx\n",mpaddr,pte_val(*pte));
   3.399 +            return pte_val(*pte);
   3.400 +        } else if (VMX_DOMAIN(d->vcpu[0]))
   3.401 +            return GPFN_INV_MASK;
   3.402 +    }
   3.403 +
   3.404 +    printk("%s: d 0x%p id %d current 0x%p id %d\n",
   3.405 +           __func__, d, d->domain_id, current, current->vcpu_id);
   3.406 +    if ((mpaddr >> PAGE_SHIFT) < d->max_pages)
   3.407 +        printk("%s: non-allocated mpa 0x%lx (< 0x%lx)\n", __func__,
   3.408 +               mpaddr, (unsigned long)d->max_pages << PAGE_SHIFT);
   3.409 +    else
   3.410 +        printk("%s: bad mpa 0x%lx (=> 0x%lx)\n", __func__,
   3.411 +               mpaddr, (unsigned long)d->max_pages << PAGE_SHIFT);
   3.412 +    mpafoo(mpaddr);
   3.413 +
   3.414 +    //XXX This is a work around until the emulation memory access to a region
   3.415 +    //    where memory or device are attached is implemented.
   3.416 +    return pte_val(pfn_pte(0, __pgprot(__DIRTY_BITS | _PAGE_PL_2 | _PAGE_AR_RWX)));
   3.417 +}
   3.418 +
   3.419 +// FIXME: ONLY USE FOR DOMAIN PAGE_SIZE == PAGE_SIZE
   3.420 +#if 1
   3.421 +unsigned long domain_mpa_to_imva(struct domain *d, unsigned long mpaddr)
   3.422 +{
   3.423 +    unsigned long pte = lookup_domain_mpa(d,mpaddr);
   3.424 +    unsigned long imva;
   3.425 +
   3.426 +    pte &= _PAGE_PPN_MASK;
   3.427 +    imva = (unsigned long) __va(pte);
   3.428 +    imva |= mpaddr & ~PAGE_MASK;
   3.429 +    return(imva);
   3.430 +}
   3.431 +#else
   3.432 +unsigned long domain_mpa_to_imva(struct domain *d, unsigned long mpaddr)
   3.433 +{
   3.434 +    unsigned long imva = __gpa_to_mpa(d, mpaddr);
   3.435 +
   3.436 +    return __va(imva);
   3.437 +}
   3.438 +#endif
   3.439 +
   3.440 +/* Allocate a new page for domain and map it to the specified metaphysical
   3.441 +   address.  */
   3.442 +struct page_info *
   3.443 +__assign_new_domain_page(struct domain *d, unsigned long mpaddr, pte_t* pte)
   3.444 +{
   3.445 +    struct page_info *p = NULL;
   3.446 +    unsigned long maddr;
   3.447 +    int ret;
   3.448 +
   3.449 +    BUG_ON(!pte_none(*pte));
   3.450 +
   3.451 +#ifdef CONFIG_DOMAIN0_CONTIGUOUS
   3.452 +    if (d == dom0) {
   3.453 +#if 0
   3.454 +        if (mpaddr < dom0_start || mpaddr >= dom0_start + dom0_size) {
   3.455 +            /* FIXME: is it true ?
   3.456 +               dom0 memory is not contiguous!  */
   3.457 +            panic("assign_new_domain_page: bad domain0 "
   3.458 +                  "mpaddr=%lx, start=%lx, end=%lx!\n",
   3.459 +                  mpaddr, dom0_start, dom0_start+dom0_size);
   3.460 +        }
   3.461 +#endif
   3.462 +        p = mfn_to_page((mpaddr >> PAGE_SHIFT));
   3.463 +        return p;
   3.464 +    }
   3.465 +#endif
   3.466 +
   3.467 +    p = alloc_domheap_page(d);
   3.468 +    if (unlikely(!p)) {
   3.469 +        printf("assign_new_domain_page: Can't alloc!!!! Aaaargh!\n");
   3.470 +        return(p);
   3.471 +    }
   3.472 +
   3.473 +    // zero out pages for security reasons
   3.474 +    clear_page(page_to_virt(p));
   3.475 +    maddr = page_to_maddr (p);
   3.476 +    if (unlikely(maddr > __get_cpu_var(vhpt_paddr)
   3.477 +                 && maddr < __get_cpu_var(vhpt_pend))) {
   3.478 +        /* FIXME: how can this happen ?
   3.479 +           vhpt is allocated by alloc_domheap_page.  */
   3.480 +        printf("assign_new_domain_page: reassigned vhpt page %lx!!\n",
   3.481 +               maddr);
   3.482 +    }
   3.483 +
   3.484 +    ret = get_page(p, d);
   3.485 +    BUG_ON(ret == 0);
   3.486 +    set_pte(pte, pfn_pte(maddr >> PAGE_SHIFT,
   3.487 +                         __pgprot(__DIRTY_BITS | _PAGE_PL_2 | _PAGE_AR_RWX)));
   3.488 +
   3.489 +    mb ();
   3.490 +    //XXX CONFIG_XEN_IA64_DOM0_VP
   3.491 +    //    TODO racy
   3.492 +    set_gpfn_from_mfn(page_to_mfn(p), mpaddr >> PAGE_SHIFT);
   3.493 +    return p;
   3.494 +}
   3.495 +
   3.496 +struct page_info *
   3.497 +assign_new_domain_page(struct domain *d, unsigned long mpaddr)
   3.498 +{
   3.499 +#ifdef CONFIG_DOMAIN0_CONTIGUOUS
   3.500 +    pte_t dummy_pte = __pte(0);
   3.501 +    return __assign_new_domain_page(d, mpaddr, &dummy_pte);
   3.502 +#else
   3.503 +    struct page_info *p = NULL;
   3.504 +    pte_t *pte;
   3.505 +
   3.506 +    pte = lookup_alloc_domain_pte(d, mpaddr);
   3.507 +    if (pte_none(*pte)) {
   3.508 +        p = __assign_new_domain_page(d, mpaddr, pte);
   3.509 +    } else {
   3.510 +        DPRINTK("%s: d 0x%p mpaddr %lx already mapped!\n",
   3.511 +                __func__, d, mpaddr);
   3.512 +    }
   3.513 +
   3.514 +    return p;
   3.515 +#endif
   3.516 +}
   3.517 +
   3.518 +void
   3.519 +assign_new_domain0_page(struct domain *d, unsigned long mpaddr)
   3.520 +{
   3.521 +#ifndef CONFIG_DOMAIN0_CONTIGUOUS
   3.522 +    pte_t *pte;
   3.523 +
   3.524 +    BUG_ON(d != dom0);
   3.525 +    pte = lookup_alloc_domain_pte(d, mpaddr);
   3.526 +    if (pte_none(*pte)) {
   3.527 +        struct page_info *p = __assign_new_domain_page(d, mpaddr, pte);
   3.528 +        if (p == NULL) {
   3.529 +            panic("%s: can't allocate page for dom0", __func__);
   3.530 +        }
   3.531 +    }
   3.532 +#endif
   3.533 +}
   3.534 +
   3.535 +/* map a physical address to the specified metaphysical addr */
   3.536 +// flags: currently only ASSIGN_readonly
   3.537 +void
   3.538 +__assign_domain_page(struct domain *d,
   3.539 +                     unsigned long mpaddr, unsigned long physaddr,
   3.540 +                     unsigned long flags)
   3.541 +{
   3.542 +    pte_t *pte;
   3.543 +    unsigned long arflags = (flags & ASSIGN_readonly)? _PAGE_AR_R: _PAGE_AR_RWX;
   3.544 +
   3.545 +    pte = lookup_alloc_domain_pte(d, mpaddr);
   3.546 +    if (pte_none(*pte)) {
   3.547 +        set_pte(pte, pfn_pte(physaddr >> PAGE_SHIFT,
   3.548 +                             __pgprot(__DIRTY_BITS | _PAGE_PL_2 | arflags)));
   3.549 +        mb ();
   3.550 +    } else
   3.551 +        printk("%s: mpaddr %lx already mapped!\n", __func__, mpaddr);
   3.552 +}
   3.553 +
   3.554 +/* get_page() and map a physical address to the specified metaphysical addr */
   3.555 +void
   3.556 +assign_domain_page(struct domain *d,
   3.557 +                   unsigned long mpaddr, unsigned long physaddr)
   3.558 +{
   3.559 +    struct page_info* page = mfn_to_page(physaddr >> PAGE_SHIFT);
   3.560 +    int ret;
   3.561 +
   3.562 +    BUG_ON((physaddr & GPFN_IO_MASK) != GPFN_MEM);
   3.563 +    ret = get_page(page, d);
   3.564 +    BUG_ON(ret == 0);
   3.565 +    __assign_domain_page(d, mpaddr, physaddr, ASSIGN_writable);
   3.566 +
   3.567 +    //XXX CONFIG_XEN_IA64_DOM0_VP
   3.568 +    //    TODO racy
   3.569 +    set_gpfn_from_mfn(physaddr >> PAGE_SHIFT, mpaddr >> PAGE_SHIFT);
   3.570 +}
   3.571 +
   3.572 +#ifdef CONFIG_XEN_IA64_DOM0_VP
   3.573 +static void
   3.574 +assign_domain_same_page(struct domain *d,
   3.575 +                        unsigned long mpaddr, unsigned long size,
   3.576 +                        unsigned long flags)
   3.577 +{
   3.578 +    //XXX optimization
   3.579 +    unsigned long end = mpaddr + size;
   3.580 +    for (; mpaddr < end; mpaddr += PAGE_SIZE) {
   3.581 +        __assign_domain_page(d, mpaddr, mpaddr, flags);
   3.582 +    }
   3.583 +}
   3.584 +
   3.585 +static int
   3.586 +efi_mmio(unsigned long physaddr, unsigned long size)
   3.587 +{
   3.588 +    void *efi_map_start, *efi_map_end;
   3.589 +    u64 efi_desc_size;
   3.590 +    void* p;
   3.591 +
   3.592 +    efi_map_start = __va(ia64_boot_param->efi_memmap);
   3.593 +    efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
   3.594 +    efi_desc_size = ia64_boot_param->efi_memdesc_size;
   3.595 +
   3.596 +    for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
   3.597 +        efi_memory_desc_t* md = (efi_memory_desc_t *)p;
   3.598 +        unsigned long start = md->phys_addr;
   3.599 +        unsigned long end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
   3.600 +
   3.601 +        if (start <= physaddr && physaddr < end) {
   3.602 +            if ((physaddr + size) > end) {
   3.603 +                DPRINTK("%s:%d physaddr 0x%lx size = 0x%lx\n",
   3.604 +                        __func__, __LINE__, physaddr, size);
   3.605 +                return 0;
   3.606 +            }
   3.607 +
   3.608 +            // for io space
   3.609 +            if (md->type == EFI_MEMORY_MAPPED_IO ||
   3.610 +                md->type == EFI_MEMORY_MAPPED_IO_PORT_SPACE) {
   3.611 +                return 1;
   3.612 +            }
   3.613 +
   3.614 +            // for runtime
   3.615 +            // see efi_enter_virtual_mode(void)
   3.616 +            // in linux/arch/ia64/kernel/efi.c
   3.617 +            if ((md->attribute & EFI_MEMORY_RUNTIME) &&
   3.618 +                !(md->attribute & EFI_MEMORY_WB)) {
   3.619 +                return 1;
   3.620 +            }
   3.621 +
   3.622 +            DPRINTK("%s:%d physaddr 0x%lx size = 0x%lx\n",
   3.623 +                    __func__, __LINE__, physaddr, size);
   3.624 +            return 0;
   3.625 +        }
   3.626 +
   3.627 +        if (physaddr < start) {
   3.628 +            break;
   3.629 +        }
   3.630 +    }
   3.631 +
   3.632 +    return 1;
   3.633 +}
   3.634 +
   3.635 +unsigned long
   3.636 +assign_domain_mmio_page(struct domain *d,
   3.637 +                        unsigned long mpaddr, unsigned long size)
   3.638 +{
   3.639 +    if (size == 0) {
   3.640 +        DPRINTK("%s: domain %p mpaddr 0x%lx size = 0x%lx\n",
   3.641 +                __func__, d, mpaddr, size);
   3.642 +    }
   3.643 +    if (!efi_mmio(mpaddr, size)) {
   3.644 +        DPRINTK("%s:%d domain %p mpaddr 0x%lx size = 0x%lx\n",
   3.645 +                __func__, __LINE__, d, mpaddr, size);
   3.646 +        return -EINVAL;
   3.647 +    }
   3.648 +    assign_domain_same_page(d, mpaddr, size, ASSIGN_writable);
   3.649 +    return mpaddr;
   3.650 +}
   3.651 +
   3.652 +unsigned long
   3.653 +assign_domain_mach_page(struct domain *d,
   3.654 +                        unsigned long mpaddr, unsigned long size,
   3.655 +                        unsigned long flags)
   3.656 +{
   3.657 +    assign_domain_same_page(d, mpaddr, size, flags);
   3.658 +    return mpaddr;
   3.659 +}
   3.660 +
   3.661 +// caller must get_page(mfn_to_page(mfn)) before
   3.662 +// caller must call set_gpfn_from_mfn().
   3.663 +// flags: currently only ASSIGN_readonly
   3.664 +static void
   3.665 +assign_domain_page_replace(struct domain *d, unsigned long mpaddr,
   3.666 +                           unsigned long mfn, unsigned long flags)
   3.667 +{
   3.668 +    struct mm_struct *mm = &d->arch.mm;
   3.669 +    pte_t* pte;
   3.670 +    pte_t old_pte;
   3.671 +    pte_t npte;
   3.672 +    unsigned long arflags = (flags & ASSIGN_readonly)? _PAGE_AR_R: _PAGE_AR_RWX;
   3.673 +
   3.674 +    pte = lookup_alloc_domain_pte(d, mpaddr);
   3.675 +
   3.676 +    // update pte
   3.677 +    npte = pfn_pte(mfn, __pgprot(__DIRTY_BITS | _PAGE_PL_2 | arflags));
   3.678 +    old_pte = ptep_xchg(mm, mpaddr, pte, npte);
   3.679 +    if (pte_mem(old_pte)) {
   3.680 +        unsigned long old_mfn;
   3.681 +        struct page_info* old_page;
   3.682 +
   3.683 +        // XXX should previous underlying page be removed?
   3.684 +        //  or should error be returned because it is a due to a domain?
   3.685 +        old_mfn = pte_pfn(old_pte);//XXX
   3.686 +        old_page = mfn_to_page(old_mfn);
   3.687 +
   3.688 +        if (page_get_owner(old_page) == d) {
   3.689 +            BUG_ON(get_gpfn_from_mfn(old_mfn) != (mpaddr >> PAGE_SHIFT));
   3.690 +            set_gpfn_from_mfn(old_mfn, INVALID_M2P_ENTRY);
   3.691 +        }
   3.692 +
   3.693 +        domain_page_flush(d, mpaddr, old_mfn, mfn);
   3.694 +
   3.695 +        try_to_clear_PGC_allocate(d, old_page);
   3.696 +        put_page(old_page);
   3.697 +    } else {
   3.698 +        BUG_ON(!mfn_valid(mfn));
   3.699 +        BUG_ON(page_get_owner(mfn_to_page(mfn)) == d &&
   3.700 +               get_gpfn_from_mfn(mfn) != INVALID_M2P_ENTRY);
   3.701 +    }
   3.702 +}
   3.703 +
   3.704 +static void
   3.705 +zap_domain_page_one(struct domain *d, unsigned long mpaddr, int do_put_page)
   3.706 +{
   3.707 +    struct mm_struct *mm = &d->arch.mm;
   3.708 +    pte_t *pte;
   3.709 +    pte_t old_pte;
   3.710 +    unsigned long mfn;
   3.711 +    struct page_info *page;
   3.712 +
   3.713 +    pte = lookup_noalloc_domain_pte_none(d, mpaddr);
   3.714 +    if (pte == NULL)
   3.715 +        return;
   3.716 +    if (pte_none(*pte))
   3.717 +        return;
   3.718 +
   3.719 +    // update pte
   3.720 +    old_pte = ptep_get_and_clear(mm, mpaddr, pte);
   3.721 +    mfn = pte_pfn(old_pte);
   3.722 +    page = mfn_to_page(mfn);
   3.723 +    BUG_ON((page->count_info & PGC_count_mask) == 0);
   3.724 +
   3.725 +    if (page_get_owner(page) == d) {
   3.726 +        BUG_ON(get_gpfn_from_mfn(mfn) != (mpaddr >> PAGE_SHIFT));
   3.727 +        set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY);
   3.728 +    }
   3.729 +
   3.730 +    domain_page_flush(d, mpaddr, mfn, INVALID_MFN);
   3.731 +
   3.732 +    if (do_put_page) {
   3.733 +        try_to_clear_PGC_allocate(d, page);
   3.734 +        put_page(page);
   3.735 +    }
   3.736 +}
   3.737 +
   3.738 +//XXX SMP
   3.739 +unsigned long
   3.740 +dom0vp_zap_physmap(struct domain *d, unsigned long gpfn,
   3.741 +                   unsigned int extent_order)
   3.742 +{
   3.743 +    unsigned long ret = 0;
   3.744 +    if (extent_order != 0) {
   3.745 +        //XXX
   3.746 +        ret = -ENOSYS;
   3.747 +        goto out;
   3.748 +    }
   3.749 +
   3.750 +    zap_domain_page_one(d, gpfn << PAGE_SHIFT, 1);
   3.751 +
   3.752 +out:
   3.753 +    return ret;
   3.754 +}
   3.755 +
   3.756 +unsigned long
   3.757 +dom0vp_add_physmap(struct domain* d, unsigned long gpfn, unsigned long mfn,
   3.758 +                   unsigned long flags, domid_t domid)
   3.759 +{
   3.760 +    int error = 0;
   3.761 +    struct domain* rd;
   3.762 +
   3.763 +    rd = find_domain_by_id(domid);
   3.764 +    if (unlikely(rd == NULL)) {
   3.765 +        switch (domid) {
   3.766 +        case DOMID_XEN:
   3.767 +            rd = dom_xen;
   3.768 +            break;
   3.769 +        case DOMID_IO:
   3.770 +            rd = dom_io;
   3.771 +            break;
   3.772 +        default:
   3.773 +            DPRINTK("d 0x%p domid %d "
   3.774 +                    "pgfn 0x%lx mfn 0x%lx flags 0x%lx domid %d\n",
   3.775 +                    d, d->domain_id, gpfn, mfn, flags, domid);
   3.776 +            error = -ESRCH;
   3.777 +            goto out0;
   3.778 +        }
   3.779 +        BUG_ON(rd == NULL);
   3.780 +        get_knownalive_domain(rd);
   3.781 +    }
   3.782 +
   3.783 +    if (unlikely(rd == d)) {
   3.784 +        error = -EINVAL;
   3.785 +        goto out1;
   3.786 +    }
   3.787 +    if (unlikely(get_page(mfn_to_page(mfn), rd) == 0)) {
   3.788 +        error = -EINVAL;
   3.789 +        goto out1;
   3.790 +    }
   3.791 +
   3.792 +    assign_domain_page_replace(d, gpfn << PAGE_SHIFT, mfn, flags);
   3.793 +    //don't update p2m table because this page belongs to rd, not d.
   3.794 +out1:
   3.795 +    put_domain(rd);
   3.796 +out0:
   3.797 +    return error;
   3.798 +}
   3.799 +
   3.800 +// grant table host mapping
   3.801 +// mpaddr: host_addr: pseudo physical address
   3.802 +// mfn: frame: machine page frame
   3.803 +// flags: GNTMAP_readonly | GNTMAP_application_map | GNTMAP_contains_pte
   3.804 +int
   3.805 +create_grant_host_mapping(unsigned long gpaddr,
   3.806 +              unsigned long mfn, unsigned int flags)
   3.807 +{
   3.808 +    struct domain* d = current->domain;
   3.809 +    struct page_info* page;
   3.810 +    int ret;
   3.811 +
   3.812 +    if (flags & (GNTMAP_device_map |
   3.813 +                 GNTMAP_application_map | GNTMAP_contains_pte)) {
   3.814 +        DPRINTK("%s: flags 0x%x\n", __func__, flags);
   3.815 +        return GNTST_general_error;
   3.816 +    }
   3.817 +
   3.818 +    page = mfn_to_page(mfn);
   3.819 +    ret = get_page(page, page_get_owner(page));
   3.820 +    BUG_ON(ret == 0);
   3.821 +
   3.822 +    assign_domain_page_replace(d, gpaddr, mfn, (flags & GNTMAP_readonly)?
   3.823 +                                              ASSIGN_readonly: ASSIGN_writable);
   3.824 +    return GNTST_okay;
   3.825 +}
   3.826 +
   3.827 +// grant table host unmapping
   3.828 +int
   3.829 +destroy_grant_host_mapping(unsigned long gpaddr,
   3.830 +               unsigned long mfn, unsigned int flags)
   3.831 +{
   3.832 +    struct domain* d = current->domain;
   3.833 +    pte_t* pte;
   3.834 +    pte_t old_pte;
   3.835 +    unsigned long old_mfn = INVALID_MFN;
   3.836 +    struct page_info* old_page;
   3.837 +
   3.838 +    if (flags & (GNTMAP_application_map | GNTMAP_contains_pte)) {
   3.839 +        DPRINTK("%s: flags 0x%x\n", __func__, flags);
   3.840 +        return GNTST_general_error;
   3.841 +    }
   3.842 +
   3.843 +    pte = lookup_noalloc_domain_pte(d, gpaddr);
   3.844 +    if (pte == NULL || !pte_present(*pte) || pte_pfn(*pte) != mfn)
   3.845 +        return GNTST_general_error;
   3.846 +
   3.847 +    // update pte
   3.848 +    old_pte = ptep_get_and_clear(&d->arch.mm, gpaddr, pte);
   3.849 +    if (pte_present(old_pte)) {
   3.850 +        old_mfn = pte_pfn(old_pte);
   3.851 +    } else {
   3.852 +        return GNTST_general_error;
   3.853 +    }
   3.854 +    domain_page_flush(d, gpaddr, old_mfn, INVALID_MFN);
   3.855 +
   3.856 +    old_page = mfn_to_page(old_mfn);
   3.857 +    BUG_ON(page_get_owner(old_page) == d);//try_to_clear_PGC_allocate(d, page) is not needed.
   3.858 +    put_page(old_page);
   3.859 +
   3.860 +    return GNTST_okay;
   3.861 +}
   3.862 +
   3.863 +// heavily depends on the struct page layout.
   3.864 +//XXX SMP
   3.865 +int
   3.866 +steal_page_for_grant_transfer(struct domain *d, struct page_info *page)
   3.867 +{
   3.868 +#if 0 /* if big endian */
   3.869 +# error "implement big endian version of steal_page_for_grant_transfer()"
   3.870 +#endif
   3.871 +    u32 _d, _nd;
   3.872 +    u64 x, nx, y;
   3.873 +    unsigned long mpaddr = get_gpfn_from_mfn(page_to_mfn(page)) << PAGE_SHIFT;
   3.874 +    struct page_info *new;
   3.875 +
   3.876 +    zap_domain_page_one(d, mpaddr, 0);
   3.877 +    put_page(page);
   3.878 +
   3.879 +    spin_lock(&d->page_alloc_lock);
   3.880 +
   3.881 +    /*
   3.882 +     * The tricky bit: atomically release ownership while there is just one
   3.883 +     * benign reference to the page (PGC_allocated). If that reference
   3.884 +     * disappears then the deallocation routine will safely spin.
   3.885 +     */
   3.886 +    _d  = pickle_domptr(d);
   3.887 +    y = *((u64*)&page->count_info);
   3.888 +    do {
   3.889 +        x = y;
   3.890 +        nx = x & 0xffffffff;
   3.891 +        // page->count_info: untouched
   3.892 +        // page->u.inused._domain = 0;
   3.893 +        _nd = x >> 32;
   3.894 +
   3.895 +        if (unlikely((x & (PGC_count_mask | PGC_allocated)) !=
   3.896 +                     (1 | PGC_allocated)) ||
   3.897 +            unlikely(_nd != _d)) {
   3.898 +            struct domain* nd = unpickle_domptr(_nd);
   3.899 +            if (nd == NULL) {
   3.900 +                DPRINTK("gnttab_transfer: Bad page %p: ed=%p(%u) 0x%x, "
   3.901 +                        "sd=%p 0x%x,"
   3.902 +                        " caf=%016lx, taf=%" PRtype_info "\n",
   3.903 +                        (void *) page_to_mfn(page),
   3.904 +                        d, d->domain_id, _d,
   3.905 +                        nd, _nd,
   3.906 +                        x,
   3.907 +                        page->u.inuse.type_info);
   3.908 +            } else {
   3.909 +                DPRINTK("gnttab_transfer: Bad page %p: ed=%p(%u) 0x%x, "
   3.910 +                        "sd=%p(%u) 0x%x,"
   3.911 +                        " caf=%016lx, taf=%" PRtype_info "\n",
   3.912 +                        (void *) page_to_mfn(page),
   3.913 +                        d, d->domain_id, _d,
   3.914 +                        nd, nd->domain_id, _nd,
   3.915 +                        x,
   3.916 +                        page->u.inuse.type_info);
   3.917 +            }
   3.918 +            spin_unlock(&d->page_alloc_lock);
   3.919 +            return -1;
   3.920 +        }
   3.921 +
   3.922 +        y = cmpxchg((u64*)&page->count_info, x, nx);
   3.923 +    } while (unlikely(y != x));
   3.924 +
   3.925 +    /*
   3.926 +     * Unlink from 'd'. At least one reference remains (now anonymous), so
   3.927 +     * noone else is spinning to try to delete this page from 'd'.
   3.928 +     */
   3.929 +    d->tot_pages--;
   3.930 +    list_del(&page->list);
   3.931 +
   3.932 +    spin_unlock(&d->page_alloc_lock);
   3.933 +
   3.934 +#if 1
   3.935 +    //XXX Until net_rx_action() fix
   3.936 +    // assign new page for this mpaddr
   3.937 +    new = assign_new_domain_page(d, mpaddr);
   3.938 +    BUG_ON(new == NULL);//XXX
   3.939 +#endif
   3.940 +
   3.941 +    return 0;
   3.942 +}
   3.943 +
   3.944 +void
   3.945 +guest_physmap_add_page(struct domain *d, unsigned long gpfn,
   3.946 +                       unsigned long mfn)
   3.947 +{
   3.948 +    int ret;
   3.949 +
   3.950 +    ret = get_page(mfn_to_page(mfn), d);
   3.951 +    BUG_ON(ret == 0);
   3.952 +    assign_domain_page_replace(d, gpfn << PAGE_SHIFT, mfn, ASSIGN_writable);
   3.953 +    set_gpfn_from_mfn(mfn, gpfn);//XXX SMP
   3.954 +
   3.955 +    //BUG_ON(mfn != ((lookup_domain_mpa(d, gpfn << PAGE_SHIFT) & _PFN_MASK) >> PAGE_SHIFT));
   3.956 +}
   3.957 +
   3.958 +void
   3.959 +guest_physmap_remove_page(struct domain *d, unsigned long gpfn,
   3.960 +                          unsigned long mfn)
   3.961 +{
   3.962 +    BUG_ON(mfn == 0);//XXX
   3.963 +    zap_domain_page_one(d, gpfn << PAGE_SHIFT, 1);
   3.964 +}
   3.965 +
   3.966 +//XXX sledgehammer.
   3.967 +//    flush finer range.
   3.968 +void
   3.969 +domain_page_flush(struct domain* d, unsigned long mpaddr,
   3.970 +                  unsigned long old_mfn, unsigned long new_mfn)
   3.971 +{
   3.972 +    domain_flush_vtlb_all();
   3.973 +}
   3.974 +#endif
   3.975 +
   3.976 +/* Flush cache of domain d.  */
   3.977 +void domain_cache_flush (struct domain *d, int sync_only)
   3.978 +{
   3.979 +    struct mm_struct *mm = &d->arch.mm;
   3.980 +    pgd_t *pgd = mm->pgd;
   3.981 +    unsigned long maddr;
   3.982 +    int i,j,k, l;
   3.983 +    int nbr_page = 0;
   3.984 +    void (*flush_func)(unsigned long start, unsigned long end);
   3.985 +    extern void flush_dcache_range (unsigned long, unsigned long);
   3.986 +
   3.987 +    if (sync_only)
   3.988 +        flush_func = &flush_icache_range;
   3.989 +    else
   3.990 +        flush_func = &flush_dcache_range;
   3.991 +
   3.992 +#ifdef CONFIG_DOMAIN0_CONTIGUOUS
   3.993 +    if (d == dom0) {
   3.994 +        /* This is not fully correct (because of hole), but it should
   3.995 +           be enough for now.  */
   3.996 +        (*flush_func)(__va_ul (dom0_start),
   3.997 +                  __va_ul (dom0_start + dom0_size));
   3.998 +        return;
   3.999 +    }
  3.1000 +#endif
  3.1001 +    for (i = 0; i < PTRS_PER_PGD; pgd++, i++) {
  3.1002 +        pud_t *pud;
  3.1003 +        if (!pgd_present(*pgd))
  3.1004 +            continue;
  3.1005 +        pud = pud_offset(pgd, 0);
  3.1006 +        for (j = 0; j < PTRS_PER_PUD; pud++, j++) {
  3.1007 +            pmd_t *pmd;
  3.1008 +            if (!pud_present(*pud))
  3.1009 +                continue;
  3.1010 +            pmd = pmd_offset(pud, 0);
  3.1011 +            for (k = 0; k < PTRS_PER_PMD; pmd++, k++) {
  3.1012 +                pte_t *pte;
  3.1013 +                if (!pmd_present(*pmd))
  3.1014 +                    continue;
  3.1015 +                pte = pte_offset_map(pmd, 0);
  3.1016 +                for (l = 0; l < PTRS_PER_PTE; pte++, l++) {
  3.1017 +                    if (!pte_present(*pte))
  3.1018 +                        continue;
  3.1019 +                    /* Convert PTE to maddr.  */
  3.1020 +                    maddr = __va_ul (pte_val(*pte)
  3.1021 +                             & _PAGE_PPN_MASK);
  3.1022 +                    (*flush_func)(maddr, maddr+ PAGE_SIZE);
  3.1023 +                    nbr_page++;
  3.1024 +                }
  3.1025 +            }
  3.1026 +        }
  3.1027 +    }
  3.1028 +    //printf ("domain_cache_flush: %d %d pages\n", d->domain_id, nbr_page);
  3.1029 +}
  3.1030 +
  3.1031 +/*
  3.1032 + * Local variables:
  3.1033 + * mode: C
  3.1034 + * c-set-style: "BSD"
  3.1035 + * c-basic-offset: 4
  3.1036 + * tab-width: 4
  3.1037 + * indent-tabs-mode: nil
  3.1038 + * End:
  3.1039 + */
     4.1 --- a/xen/include/asm-ia64/domain.h	Sat Jun 03 13:21:14 2006 -0600
     4.2 +++ b/xen/include/asm-ia64/domain.h	Sat Jun 03 13:21:38 2006 -0600
     4.3 @@ -118,22 +118,6 @@ struct arch_vcpu {
     4.4      struct arch_vmx_struct arch_vmx; /* Virtual Machine Extensions */
     4.5  };
     4.6  
     4.7 -struct page_info * assign_new_domain_page(struct domain *d, unsigned long mpaddr);
     4.8 -void assign_new_domain0_page(struct domain *d, unsigned long mpaddr);
     4.9 -void __assign_domain_page(struct domain *d, unsigned long mpaddr, unsigned long physaddr, unsigned long flags);
    4.10 -void assign_domain_page(struct domain *d, unsigned long mpaddr, unsigned long physaddr);
    4.11 -void assign_domain_io_page(struct domain *d, unsigned long mpaddr, unsigned long flags);
    4.12 -#ifdef CONFIG_XEN_IA64_DOM0_VP
    4.13 -void alloc_dom_xen_and_dom_io(void);
    4.14 -unsigned long assign_domain_mmio_page(struct domain *d, unsigned long mpaddr, unsigned long size);
    4.15 -unsigned long assign_domain_mach_page(struct domain *d, unsigned long mpaddr, unsigned long size, unsigned long flags);
    4.16 -unsigned long do_dom0vp_op(unsigned long cmd, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3);
    4.17 -unsigned long dom0vp_zap_physmap(struct domain *d, unsigned long gpfn, unsigned int extent_order);
    4.18 -unsigned long dom0vp_add_physmap(struct domain* d, unsigned long gpfn, unsigned long mfn, unsigned long flags, domid_t domid);
    4.19 -#else
    4.20 -#define alloc_dom_xen_and_dom_io()      do { } while (0)
    4.21 -#endif
    4.22 -
    4.23  #include <asm/uaccess.h> /* for KERNEL_DS */
    4.24  #include <asm/pgtable.h>
    4.25  
     5.1 --- a/xen/include/asm-ia64/mm.h	Sat Jun 03 13:21:14 2006 -0600
     5.2 +++ b/xen/include/asm-ia64/mm.h	Sat Jun 03 13:21:38 2006 -0600
     5.3 @@ -1,3 +1,8 @@
     5.4 +/*
     5.5 + * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
     5.6 + *                    VA Linux Systems Japan K.K.
     5.7 + *                    dom0 vp model support
     5.8 + */
     5.9  #ifndef __ASM_IA64_MM_H__
    5.10  #define __ASM_IA64_MM_H__
    5.11  
    5.12 @@ -416,14 +421,28 @@ extern unsigned long num_physpages;
    5.13  extern unsigned long totalram_pages;
    5.14  extern int nr_swap_pages;
    5.15  
    5.16 +extern void alloc_dom_xen_and_dom_io(void);
    5.17 +extern void relinquish_mm(struct domain* d);
    5.18 +extern struct page_info * assign_new_domain_page(struct domain *d, unsigned long mpaddr);
    5.19 +extern void assign_new_domain0_page(struct domain *d, unsigned long mpaddr);
    5.20 +extern void __assign_domain_page(struct domain *d, unsigned long mpaddr, unsigned long physaddr, unsigned long flags);
    5.21 +extern void assign_domain_page(struct domain *d, unsigned long mpaddr, unsigned long physaddr);
    5.22 +extern void assign_domain_io_page(struct domain *d, unsigned long mpaddr, unsigned long flags);
    5.23 +extern unsigned long lookup_domain_mpa(struct domain *d, unsigned long mpaddr);
    5.24 +
    5.25 +#ifdef CONFIG_XEN_IA64_DOM0_VP
    5.26 +extern unsigned long assign_domain_mmio_page(struct domain *d, unsigned long mpaddr, unsigned long size);
    5.27 +extern unsigned long assign_domain_mach_page(struct domain *d, unsigned long mpaddr, unsigned long size, unsigned long flags);
    5.28 +extern unsigned long __lookup_domain_mpa(struct domain *d, unsigned long mpaddr);
    5.29 +extern unsigned long ____lookup_domain_mpa(struct domain *d, unsigned long mpaddr);
    5.30 +extern unsigned long do_dom0vp_op(unsigned long cmd, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3);
    5.31 +extern unsigned long dom0vp_zap_physmap(struct domain *d, unsigned long gpfn, unsigned int extent_order);
    5.32 +extern unsigned long dom0vp_add_physmap(struct domain* d, unsigned long gpfn, unsigned long mfn, unsigned long flags, domid_t domid);
    5.33 +#endif
    5.34 +
    5.35  extern unsigned long *mpt_table;
    5.36  extern unsigned long gmfn_to_mfn_foreign(struct domain *d, unsigned long gpfn);
    5.37  extern u64 translate_domain_pte(u64 pteval, u64 address, u64 itir__, u64* logps);
    5.38 -extern unsigned long lookup_domain_mpa(struct domain *d, unsigned long mpaddr);
    5.39 -#ifdef CONFIG_XEN_IA64_DOM0_VP
    5.40 -extern unsigned long __lookup_domain_mpa(struct domain *d, unsigned long mpaddr);
    5.41 -extern unsigned long ____lookup_domain_mpa(struct domain *d, unsigned long mpaddr);
    5.42 -#endif
    5.43  #define machine_to_phys_mapping	mpt_table
    5.44  
    5.45  #define INVALID_M2P_ENTRY        (~0UL)