# HG changeset patch # User yamahata@xxxxxxxxxxxxx # Date 1155118991 -32400 # Node ID 5e2fec53ecc5c62acb0e2b083464b527d77b9bcf # Parent 519d868316914cb894ba38f34dc7e64be0a032f2 expose p2m table. xen side part PATCHNAME: expose_p2m_table_xen_side Signed-off-by: Isaku Yamahata diff -r 519d86831691 -r 5e2fec53ecc5 xen/arch/ia64/Rules.mk --- a/xen/arch/ia64/Rules.mk Tue Aug 08 16:55:05 2006 +0900 +++ b/xen/arch/ia64/Rules.mk Wed Aug 09 19:23:11 2006 +0900 @@ -4,6 +4,7 @@ HAS_ACPI := y HAS_ACPI := y VALIDATE_VT ?= n xen_ia64_pervcpu_vhpt ?= y +xen_ia64_expose_p2m ?= y no_warns ?= n ifneq ($(COMPILE_ARCH),$(TARGET_ARCH)) @@ -45,6 +46,9 @@ ifeq ($(xen_ia64_deferred_free),y) ifeq ($(xen_ia64_deferred_free),y) CFLAGS += -DCONFIG_XEN_IA64_DEFERRED_FREE endif +ifeq ($(xen_ia64_expose_p2m),y) +CFLAGS += -DCONFIG_XEN_IA64_EXPOSE_P2M +endif ifeq ($(no_warns),y) CFLAGS += -Wa,--fatal-warnings -Werror -Wno-uninitialized endif diff -r 519d86831691 -r 5e2fec53ecc5 xen/arch/ia64/vmx/vmx_init.c --- a/xen/arch/ia64/vmx/vmx_init.c Tue Aug 08 16:55:05 2006 +0900 +++ b/xen/arch/ia64/vmx/vmx_init.c Wed Aug 09 19:23:11 2006 +0900 @@ -345,7 +345,7 @@ static void vmx_build_physmap_table(stru for (j = io_ranges[i].start; j < io_ranges[i].start + io_ranges[i].size; j += PAGE_SIZE) - __assign_domain_page(d, j, io_ranges[i].type, ASSIGN_writable); + (void)__assign_domain_page(d, j, io_ranges[i].type, ASSIGN_writable); } /* Map normal memory below 3G */ diff -r 519d86831691 -r 5e2fec53ecc5 xen/arch/ia64/xen/dom0_ops.c --- a/xen/arch/ia64/xen/dom0_ops.c Tue Aug 08 16:55:05 2006 +0900 +++ b/xen/arch/ia64/xen/dom0_ops.c Wed Aug 09 19:23:11 2006 +0900 @@ -232,7 +232,7 @@ do_dom0vp_op(unsigned long cmd, case IA64_DOM0VP_phystomach: ret = ____lookup_domain_mpa(d, arg0 << PAGE_SHIFT); if (ret == INVALID_MFN) { - DPRINTK("%s:%d INVALID_MFN ret: 0x%lx\n", __func__, __LINE__, ret); + //DPRINTK("%s:%d INVALID_MFN ret: 0x%lx\n", __func__, __LINE__, ret); } else { ret = (ret & _PFN_MASK) >> PAGE_SHIFT;//XXX pte_pfn() } @@ -253,6 +253,11 @@ do_dom0vp_op(unsigned long cmd, ret = dom0vp_add_physmap(d, arg0, arg1, (unsigned int)arg2, (domid_t)arg3); break; +#ifdef CONFIG_XEN_IA64_EXPOSE_P2M + case IA64_DOM0VP_expose_p2m: + ret = dom0vp_expose_p2m(d, arg0, arg1, arg2, arg3); + break; +#endif default: ret = -1; printf("unknown dom0_vp_op 0x%lx\n", cmd); diff -r 519d86831691 -r 5e2fec53ecc5 xen/arch/ia64/xen/mm.c --- a/xen/arch/ia64/xen/mm.c Tue Aug 08 16:55:05 2006 +0900 +++ b/xen/arch/ia64/xen/mm.c Wed Aug 09 19:23:11 2006 +0900 @@ -800,7 +800,7 @@ flags_to_prot (unsigned long flags) // flags: currently only ASSIGN_readonly, ASSIGN_nocache, ASSIGN_tlb_tack // This is called by assign_domain_mmio_page(). // So accessing to pte is racy. -void +int __assign_domain_page(struct domain *d, unsigned long mpaddr, unsigned long physaddr, unsigned long flags) @@ -816,8 +816,11 @@ __assign_domain_page(struct domain *d, old_pte = __pte(0); new_pte = pfn_pte(physaddr >> PAGE_SHIFT, __pgprot(prot)); ret_pte = ptep_cmpxchg_rel(&d->arch.mm, mpaddr, pte, old_pte, new_pte); - if (pte_val(ret_pte) == pte_val(old_pte)) + if (pte_val(ret_pte) == pte_val(old_pte)) { smp_mb(); + return 0; + } + return -EAGAIN; } /* get_page() and map a physical address to the specified metaphysical addr */ @@ -834,7 +837,7 @@ assign_domain_page(struct domain *d, set_gpfn_from_mfn(physaddr >> PAGE_SHIFT, mpaddr >> PAGE_SHIFT); // because __assign_domain_page() uses set_pte_rel() which has // release semantics, smp_mb() isn't needed. - __assign_domain_page(d, mpaddr, physaddr, ASSIGN_writable); + (void)__assign_domain_page(d, mpaddr, physaddr, ASSIGN_writable); } int @@ -857,8 +860,8 @@ ioports_permit_access(struct domain *d, lp_offset = PAGE_ALIGN(IO_SPACE_SPARSE_ENCODING(lp)); for (off = fp_offset; off <= lp_offset; off += PAGE_SIZE) - __assign_domain_page(d, IO_PORTS_PADDR + off, - __pa(ia64_iobase) + off, ASSIGN_nocache); + (void)__assign_domain_page(d, IO_PORTS_PADDR + off, + __pa(ia64_iobase) + off, ASSIGN_nocache); return 0; } @@ -927,7 +930,7 @@ assign_domain_same_page(struct domain *d //XXX optimization unsigned long end = PAGE_ALIGN(mpaddr + size); for (mpaddr &= PAGE_MASK; mpaddr < end; mpaddr += PAGE_SIZE) { - __assign_domain_page(d, mpaddr, mpaddr, flags); + (void)__assign_domain_page(d, mpaddr, mpaddr, flags); } } @@ -1255,6 +1258,123 @@ out1: put_domain(rd); return error; } + +#ifdef CONFIG_XEN_IA64_EXPOSE_P2M +static struct page_info* p2m_pte_zero_page = NULL; + +void +expose_p2m_init(void) +{ + pte_t* pte; + + pte = pte_alloc_one_kernel(NULL, 0); + BUG_ON(pte == NULL); + smp_mb();// make contents of the page visible. + p2m_pte_zero_page = virt_to_page(pte); +} + +static int +expose_p2m_page(struct domain* d, unsigned long mpaddr, struct page_info* page) +{ + // we can't get_page(page) here. + // pte page is allocated form xen heap.(see pte_alloc_one_kernel().) + // so that the page has NULL page owner and it's reference count + // is useless. + // see also relinquish_pte()'s page_get_owner() == NULL check. + BUG_ON(page_get_owner(page) != NULL); + + if (__assign_domain_page(d, mpaddr, page_to_maddr(page), + ASSIGN_readonly) < 0) { + // There was a race. + return -EAGAIN; + } + return 0; +} + +// It is possible to optimize loop, But this isn't performance critical. +unsigned long +dom0vp_expose_p2m(struct domain* d, + unsigned long conv_start_gpfn, + unsigned long assign_start_gpfn, + unsigned long expose_size, unsigned long granule_pfn) +{ + unsigned long expose_num_pfn = expose_size >> PAGE_SHIFT; + unsigned long i; + volatile pte_t* conv_pte; + volatile pte_t* assign_pte; + + if ((expose_size % PAGE_SIZE) != 0 || + (granule_pfn % PTRS_PER_PTE) != 0 || + (expose_num_pfn % PTRS_PER_PTE) != 0 || + (conv_start_gpfn % granule_pfn) != 0 || + (assign_start_gpfn % granule_pfn) != 0 || + (expose_num_pfn % granule_pfn) != 0) { + DPRINTK("%s conv_start_gpfn 0x%016lx assign_start_gpfn 0x%016lx " + "expose_size 0x%016lx granulte_pfn 0x%016lx\n", + __func__, + conv_start_gpfn, assign_start_gpfn, expose_size, granule_pfn); + return -EINVAL; + } + + if (granule_pfn != PTRS_PER_PTE) { + DPRINTK("%s granule_pfn 0x%016lx PTRS_PER_PTE 0x%016lx\n", + __func__, granule_pfn, PTRS_PER_PTE); + return -ENOSYS; + } + + // allocate pgd, pmd. + for (i = conv_start_gpfn; i < expose_num_pfn + 1; i++) { + conv_pte = lookup_noalloc_domain_pte(d, (conv_start_gpfn + i) << PAGE_SHIFT); + if (conv_pte == NULL) { + continue; + } + + assign_pte = lookup_alloc_domain_pte(d, (assign_start_gpfn << PAGE_SHIFT) + i * sizeof(pte_t)); + if (assign_pte == NULL) { + DPRINTK("%s failed to allocate pte page\n", __func__); + return -ENOMEM; + } + + // skip to next pte page + i += PTRS_PER_PTE; + i &= ~(PTRS_PER_PTE - 1); + i--;// compensate i++ + } + + // expose pte page + for (i = 0; i < expose_num_pfn + 1; i++) { + conv_pte = lookup_noalloc_domain_pte(d, (conv_start_gpfn + i) << PAGE_SHIFT); + if (conv_pte == NULL) { + continue; + } + + if (expose_p2m_page(d, (assign_start_gpfn << PAGE_SHIFT) + i * sizeof(pte_t), virt_to_page(conv_pte)) < 0) { + DPRINTK("%s failed to assign page\n", __func__); + return -EAGAIN; + } + + // skip to next pte page + i += PTRS_PER_PTE; + i &= ~(PTRS_PER_PTE - 1); + i--;// compensate i++ + } + + // expose p2m_pte_zero_page + for (i = 0; i < (expose_num_pfn >> PAGE_SHIFT) + 1; i++) { + assign_pte = lookup_noalloc_domain_pte(d, (assign_start_gpfn + i) << PAGE_SHIFT); + BUG_ON(assign_pte == NULL); + if (pte_present(*assign_pte)) { + continue; + } + if (expose_p2m_page(d, assign_start_gpfn + i, p2m_pte_zero_page) < 0) { + DPRINTK("%s failed to assign zero-pte page\n", __func__); + return -EAGAIN; + } + } + + return 0; +} +#endif // grant table host mapping // mpaddr: host_addr: pseudo physical address diff -r 519d86831691 -r 5e2fec53ecc5 xen/arch/ia64/xen/xensetup.c --- a/xen/arch/ia64/xen/xensetup.c Tue Aug 08 16:55:05 2006 +0900 +++ b/xen/arch/ia64/xen/xensetup.c Wed Aug 09 19:23:11 2006 +0900 @@ -496,6 +496,10 @@ printk("num_online_cpus=%d, max_cpus=%d\ efi.hcdp = NULL; } +#ifdef CONFIG_XEN_IA64_EXPOSE_P2M + expose_p2m_init(); +#endif + /* Create initial domain 0. */ dom0 = domain_create(0); if ( (dom0 == NULL) || (alloc_vcpu(dom0, 0, 0) == NULL) ) diff -r 519d86831691 -r 5e2fec53ecc5 xen/include/asm-ia64/mm.h --- a/xen/include/asm-ia64/mm.h Tue Aug 08 16:55:05 2006 +0900 +++ b/xen/include/asm-ia64/mm.h Wed Aug 09 19:23:11 2006 +0900 @@ -428,7 +428,7 @@ extern void relinquish_mm(struct domain* extern void relinquish_mm(struct domain* d); extern struct page_info * assign_new_domain_page(struct domain *d, unsigned long mpaddr); extern void assign_new_domain0_page(struct domain *d, unsigned long mpaddr); -extern void __assign_domain_page(struct domain *d, unsigned long mpaddr, unsigned long physaddr, unsigned long flags); +extern int __assign_domain_page(struct domain *d, unsigned long mpaddr, unsigned long physaddr, unsigned long flags); extern void assign_domain_page(struct domain *d, unsigned long mpaddr, unsigned long physaddr); extern void assign_domain_io_page(struct domain *d, unsigned long mpaddr, unsigned long flags); struct p2m_entry; @@ -443,6 +443,10 @@ extern unsigned long do_dom0vp_op(unsign extern unsigned long do_dom0vp_op(unsigned long cmd, unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3); extern unsigned long dom0vp_zap_physmap(struct domain *d, unsigned long gpfn, unsigned int extent_order); extern unsigned long dom0vp_add_physmap(struct domain* d, unsigned long gpfn, unsigned long mfn, unsigned long flags, domid_t domid); +#ifdef CONFIG_XEN_IA64_EXPOSE_P2M +extern void expose_p2m_init(void); +extern unsigned long dom0vp_expose_p2m(struct domain* d, unsigned long conv_start_gpfn, unsigned long assign_start_gpfn, unsigned long expose_size, unsigned long granule_pfn); +#endif extern volatile unsigned long *mpt_table; extern unsigned long gmfn_to_mfn_foreign(struct domain *d, unsigned long gpfn); diff -r 519d86831691 -r 5e2fec53ecc5 xen/include/public/arch-ia64.h --- a/xen/include/public/arch-ia64.h Tue Aug 08 16:55:05 2006 +0900 +++ b/xen/include/public/arch-ia64.h Wed Aug 09 19:23:11 2006 +0900 @@ -355,6 +355,8 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_conte #define IA64_DOM0VP_add_physmap 18 // assigne machine page frane // to dom0's pseudo physical // address space. +#define IA64_DOM0VP_expose_p2m 32 // expose the p2m table into + // domain // flags for page assignement to pseudo physical address space #define _ASSIGN_readonly 0 #define ASSIGN_readonly (1UL << _ASSIGN_readonly)