# HG changeset patch # User yamahata@xxxxxxxxxxxxx # Node ID ad6bc6838c06b97650543a9dfd6e8a0a2a0d4a6e # Parent a1ee4f149ce788ede1361c448ee595999faacab8 grant table support. PATCHNAME: grant_table_xen Signed-off-by: Isaku Yamahata diff -r a1ee4f149ce7 -r ad6bc6838c06 xen/arch/ia64/xen/domain.c --- a/xen/arch/ia64/xen/domain.c Mon May 8 11:42:30 2006 +0900 +++ b/xen/arch/ia64/xen/domain.c Mon May 8 11:42:32 2006 +0900 @@ -394,6 +394,10 @@ static void relinquish_memory(struct dom /* Follow the list chain and /then/ potentially free the page. */ ent = ent->next; +#ifdef CONFIG_XEN_IA64_DOM0_VP + if (page_get_owner(page) == d) + set_gpfn_from_mfn(page_to_mfn(page), INVALID_M2P_ENTRY); +#endif put_page(page); } @@ -483,6 +487,7 @@ void new_thread(struct vcpu *v, } } +//XXX !xxx_present() should be used instread of !xxx_none()? static pte_t* lookup_alloc_domain_pte(struct domain* d, unsigned long mpaddr) { @@ -1006,6 +1011,175 @@ out1: put_domain(rd); out0: return error; +} + +// grant table host mapping +// mpaddr: host_addr: pseudo physical address +// mfn: frame: machine page frame +// flags: GNTMAP_readonly | GNTMAP_application_map | GNTMAP_contains_pte +int +create_grant_host_mapping(unsigned long gpaddr, + unsigned long mfn, unsigned int flags) +{ + struct domain* d = current->domain; + + if (flags & (GNTMAP_application_map | GNTMAP_contains_pte)) { + DPRINTK("%s: flags 0x%x\n", __func__, flags); + return GNTST_general_error; + } + if (flags & GNTMAP_readonly) { +#if 0 + DPRINTK("%s: GNTMAP_readonly is not implemented yet. flags %x\n", + __func__, flags); +#endif + flags &= ~GNTMAP_readonly; + } + + assign_domain_page_replace(d, gpaddr, mfn, flags); + + return GNTST_okay; +} + +// grant table host unmapping +int +destroy_grant_host_mapping(unsigned long gpaddr, + unsigned long mfn, unsigned int flags) +{ + struct domain* d = current->domain; + pte_t* pte; + pte_t old_pte; + unsigned long old_mfn = INVALID_MFN; + + if (flags & (GNTMAP_application_map | GNTMAP_contains_pte)) { + DPRINTK("%s: flags 0x%x\n", __func__, flags); + return GNTST_general_error; + } + if (flags & GNTMAP_readonly) { +#if 0 + DPRINTK("%s: GNTMAP_readonly is not implemented yet. flags %x\n", + __func__, flags); +#endif + flags &= ~GNTMAP_readonly; + } + + // get_page(mfn_to_page(mfn)) is not needed. + // the caller, __gnttab_map_grant_ref() does it. + + pte = lookup_noalloc_domain_pte(d, gpaddr); + if (pte == NULL || !pte_present(*pte) || pte_pfn(*pte) != mfn) + return GNTST_general_error;//XXX GNTST_bad_pseudo_phys_addr + + // update pte + old_pte = ptep_get_and_clear(d->arch.mm, gpaddr, pte); + if (pte_present(old_pte)) { + old_mfn = pte_pfn(old_pte);//XXX + } + domain_page_flush(d, gpaddr, old_mfn, INVALID_MFN); + + return GNTST_okay; +} + +//XXX needs refcount patch +//XXX heavily depends on the struct page layout. +//XXX SMP +int +steal_page_for_grant_transfer(struct domain *d, struct page_info *page) +{ +#if 0 /* if big endian */ +# error "implement big endian version of steal_page_for_grant_transfer()" +#endif + u32 _d, _nd; + u64 x, nx, y; + unsigned long mpaddr = get_gpfn_from_mfn(page_to_mfn(page)) << PAGE_SHIFT; + struct page_info *new; + + // zap_domain_page_one() does put_page(page) + if (get_page(page, d) == 0) { + DPRINTK("%s:%d page %p mfn %ld d 0x%p id %d\n", + __func__, __LINE__, page, page_to_mfn(page), d, d->domain_id); + return -1; + } + zap_domain_page_one(d, mpaddr); + + spin_lock(&d->page_alloc_lock); + + /* + * The tricky bit: atomically release ownership while there is just one + * benign reference to the page (PGC_allocated). If that reference + * disappears then the deallocation routine will safely spin. + */ + _d = pickle_domptr(d); + y = *((u64*)&page->count_info); + do { + x = y; + nx = x & 0xffffffff; + // page->count_info: untouched + // page->u.inused._domain = 0; + _nd = x >> 32; + + if (unlikely((x & (PGC_count_mask | PGC_allocated)) != + (1 | PGC_allocated)) || + unlikely(_nd != _d)) { + struct domain* nd = unpickle_domptr(_nd); + if (nd == NULL) { + DPRINTK("gnttab_transfer: Bad page %p: ed=%p(%u) 0x%x, " + "sd=%p 0x%x," + " caf=%016lx, taf=%" PRtype_info "\n", + (void *) page_to_mfn(page), + d, d->domain_id, _d, + nd, _nd, + x, + page->u.inuse.type_info); + } else { + DPRINTK("gnttab_transfer: Bad page %p: ed=%p(%u) 0x%x, " + "sd=%p(%u) 0x%x," + " caf=%016lx, taf=%" PRtype_info "\n", + (void *) page_to_mfn(page), + d, d->domain_id, _d, + nd, nd->domain_id, _nd, + x, + page->u.inuse.type_info); + } + spin_unlock(&d->page_alloc_lock); + return -1; + } + + y = cmpxchg((u64*)&page->count_info, x, nx); + } while (unlikely(y != x)); + + /* + * Unlink from 'd'. At least one reference remains (now anonymous), so + * noone else is spinning to try to delete this page from 'd'. + */ + d->tot_pages--; + list_del(&page->list); + + spin_unlock(&d->page_alloc_lock); + +#if 1 + //XXX Until net_rx_action() fix + // assign new page for this mpaddr + new = assign_new_domain_page(d, mpaddr); + BUG_ON(new == NULL);//XXX +#endif + + return 0; +} + +void +guest_physmap_add_page(struct domain *d, unsigned long gpfn, + unsigned long mfn) +{ + assign_domain_page_replace(d, gpfn << PAGE_SHIFT, mfn, 0/* XXX */); + set_gpfn_from_mfn(mfn, gpfn); +} + +void +guest_physmap_remove_page(struct domain *d, unsigned long gpfn, + unsigned long mfn) +{ + BUG_ON(mfn == 0);//XXX + zap_domain_page_one(d, gpfn << PAGE_SHIFT); } #endif diff -r a1ee4f149ce7 -r ad6bc6838c06 xen/include/asm-ia64/config.h --- a/xen/include/asm-ia64/config.h Mon May 8 11:42:30 2006 +0900 +++ b/xen/include/asm-ia64/config.h Mon May 8 11:42:32 2006 +0900 @@ -243,6 +243,10 @@ void dummy_called(char *function); // these declarations got moved at some point, find a better place for them extern int ht_per_core; +#ifdef CONFIG_XEN_IA64_DOM0_VP +#define CONFIG_SHADOW 1 +#endif + // xen/include/asm/config.h /****************************************************************************** * config.h diff -r a1ee4f149ce7 -r ad6bc6838c06 xen/include/asm-ia64/grant_table.h --- a/xen/include/asm-ia64/grant_table.h Mon May 8 11:42:30 2006 +0900 +++ b/xen/include/asm-ia64/grant_table.h Mon May 8 11:42:32 2006 +0900 @@ -7,10 +7,22 @@ #define ORDER_GRANT_FRAMES 0 +#ifndef CONFIG_XEN_IA64_DOM0_VP +// for grant map/unmap #define create_grant_host_mapping(a, f, fl) 0 #define destroy_grant_host_mapping(a, f, fl) 0 +// for grant transfer #define steal_page_for_grant_transfer(d, p) 0 +#else +// for grant map/unmap +int create_grant_host_mapping(unsigned long gpaddr, unsigned long mfn, unsigned int flags); +int destroy_grant_host_mapping(unsigned long gpaddr, unsigned long mfn, unsigned int flags); + +// for grant transfer +int steal_page_for_grant_transfer(struct domain *d, struct page_info *page); +void guest_physmap_add_page(struct domain *d, unsigned long gpfn, unsigned long mfn); +#endif #define gnttab_create_shared_page(d, t, i) ((void)0) @@ -20,13 +32,21 @@ #define gnttab_shared_maddr(d, t, i) \ virt_to_maddr((char*)(t)->shared + ((i) << PAGE_SHIFT)) -#define gnttab_shared_gmfn(d, t, i) \ +#ifndef CONFIG_XEN_IA64_DOM0_VP +# define gnttab_shared_gmfn(d, t, i) \ ({ ((d) == dom0) ? \ (virt_to_maddr((t)->shared) >> PAGE_SHIFT) + (i): \ assign_domain_page((d), \ IA64_GRANT_TABLE_PADDR + ((i) << PAGE_SHIFT), \ gnttab_shared_maddr(d, t, i)), \ (IA64_GRANT_TABLE_PADDR >> PAGE_SHIFT) + (i);}) +#else +# define gnttab_shared_gmfn(d, t, i) \ + ({ assign_domain_page((d), \ + IA64_GRANT_TABLE_PADDR + ((i) << PAGE_SHIFT), \ + gnttab_shared_maddr((d), (t), (i))); \ + (IA64_GRANT_TABLE_PADDR >> PAGE_SHIFT) + (i);}) +#endif #define gnttab_log_dirty(d, f) ((void)0) diff -r a1ee4f149ce7 -r ad6bc6838c06 xen/include/asm-ia64/linux-xen/asm/pgtable.h --- a/xen/include/asm-ia64/linux-xen/asm/pgtable.h Mon May 8 11:42:30 2006 +0900 +++ b/xen/include/asm-ia64/linux-xen/asm/pgtable.h Mon May 8 11:42:32 2006 +0900 @@ -383,6 +383,7 @@ ptep_test_and_clear_dirty (struct vm_are return 1; #endif } +#endif static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) @@ -396,6 +397,7 @@ ptep_get_and_clear(struct mm_struct *mm, #endif } +#ifndef XEN static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { diff -r a1ee4f149ce7 -r ad6bc6838c06 xen/include/asm-ia64/shadow.h --- a/xen/include/asm-ia64/shadow.h Mon May 8 11:42:30 2006 +0900 +++ b/xen/include/asm-ia64/shadow.h Mon May 8 11:42:32 2006 +0900 @@ -1,2 +1,57 @@ -/* empty */ +/****************************************************************************** + * include/asm-ia64/shadow.h + * + * Copyright (c) 2006 Isaku Yamahata + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef _XEN_SHADOW_H +#define _XEN_SHADOW_H + +#include + +#ifdef CONFIG_XEN_IA64_DOM0_VP +#ifndef CONFIG_SHADOW +# error "CONFIG_SHADOW must be defined" +#endif + +#define shadow_drop_references(d, p) ((void)0) + +// this is used only x86-specific code +//#define shadow_sync_and_drop_references(d, p) ((void)0) + +#define shadow_mode_translate(d) (1) + +// for granttab transfer. XENMEM_populate_physmap +void guest_physmap_add_page(struct domain *d, unsigned long gpfn, unsigned long mfn); +// for balloon driver. XENMEM_decrease_reservation +void guest_physmap_remove_page(struct domain *d, unsigned long gpfn, unsigned long mfn); +#endif + +#endif // _XEN_SHADOW_H + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ +