[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] RE: [Xen-ia64-devel][PATCH][VTD]change ioports_permit_access interface
Isaku Yamahata wrote: > On Fri, Oct 17, 2008 at 04:45:09PM +0800, Xu, Anthony wrote: >> Hi isaku, >> >> If I remembered correctly, last time I encountered issue at line >> page = mfn_to_page(mfn); Page returns 0. > > Which line do you have trouble? > Do you mean that mfn_to_page(mfn) returned NULL? Yes it returns NULL > or > Did you hit BUG_ON(page_get_owner(page) == NULL)? > > > >> >> I suspect if page_info for IOPORTs is initialized. >> Any idea? >> >> Thanks, >> Anthony >> >> >> mm_teardown_pte(struct domain* d, volatile pte_t* pte, unsigned long >> offset) { pte_t old_pte; >> unsigned long mfn; >> struct page_info* page; >> >> old_pte = ptep_get_and_clear(&d->arch.mm, offset, pte);// >> acquire semantics >> >> // vmx domain use bit[58:56] to distinguish io region from >> memory. // see vmx_build_physmap_table() in vmx_init.c >> if (!pte_mem(old_pte)) >> return; >> >> // domain might map IO space or acpi table pages. check it. >> mfn = pte_pfn(old_pte); if (!mfn_valid(mfn)) >> return; >> page = mfn_to_page(mfn); >> BUG_ON(page_get_owner(page) == NULL); >> >> >> >> >> Isaku Yamahata wrote: >>> On Fri, Oct 17, 2008 at 03:22:18PM +0800, Xu, Anthony wrote: >>>> Isaku Yamahata wrote: >>>>> On Thu, Oct 16, 2008 at 07:37:51PM +0800, Xu, Anthony wrote: >>>>>> use VTD to assing device, guest port may not be equal to host >>>>>> port. Change ioports_permit_access interface >>>>>> add deassign_domain_mmio_page interface >>>>>> >>>>>> Signed-off-by; Anthony Xu < anthony.xu@xxxxxxxxx > >>>>> >>>>> Some comments. >>>>> >>>>> - ioports_permit_access() >>>>> x86 didn't change its prototype. >>>>> Why does only ia64 need to change it? >>>>> Or will x86 also change it? >>>> In x86 side, only it is identity mapping, guest can access the >>>> port directly. If it is not identity mapping, guest can not access >>>> the port directly, at this situation, xen will intercept io port >>>> access first, and xen access the corresponding physical port. >>>> >>>> In ia64 side, guest can acess all assigned port whenever it is >>>> identity mapping or not. So we need to change the interface. >>> >>> Understood. x86 have io instructions. >>> Okay, please split out ioports_permit_access(), then I'll take it. >>> >>>> >>>> >>>>> >>>>> I suppose, it would be nice to map the port io area >>>>> to arbitrary guest physical area. >>>>> But I'm not sure how x86 will go with XEN_DOMCTL_ioport_mapping. >>>>> >>>>> - deassign_domain_mmio_page() >>>>> calling __assgin_domain_page() may result in page reference >>>>> count leak because the corresponding p2m entry may be changed to >>>>> another value. So you want to modify zap_domain_page_one() so >>>>> that it accepts iomem page and call it from >>>>> deassign_domain_mmio_page(). >>>> >>>> There is no page_info for mmio page, I didn't see reference count >>>> issue. >>>> >>>> If VTD is enabled, in the life of guest, p2m can not be changed, >>>> Because it VTD operation hit a page table miss, the DMA operation >>>> can not be resumed. >>> >>> Hmm, it is possible for qemu-dm (or any tools stack in dom0) can >>> issue racy hypercall, isn't it. >>> Anyway __assgin_domain_page() isn't assumed to use for deassigning >>> page. (Sorry, I have to admit those functions are somewhat >>> confusing...) How about the following patch? I did only compile >>> test, though. With the following modification zap_domain_page_one() >>> could be used by deassign_domain_mmio_page(). >>> Probably you may want to twist mfn_valid() with is_iomem_page() or >>> something. >>> >>> thanks, >>> >>> diff -r 7db30bf36b0e xen/arch/ia64/xen/mm.c >>> --- a/xen/arch/ia64/xen/mm.c Fri Oct 17 15:33:03 2008 +0900 >>> +++ b/xen/arch/ia64/xen/mm.c Fri Oct 17 16:58:34 2008 +0900 @@ >>> -1422,8 +1422,9 @@ again: >>> // memory_exchange() calls guest_physmap_remove_page() with >>> // a stealed page. i.e. page owner = NULL. >>> - BUG_ON(page_get_owner(mfn_to_page(mfn)) != d && >>> - page_get_owner(mfn_to_page(mfn)) != NULL); >>> + BUG_ON(mfn_valid(mfn) && >>> + (page_get_owner(mfn_to_page(mfn)) != d && >>> + page_get_owner(mfn_to_page(mfn)) != NULL)); >>> old_arflags = pte_val(*pte) & ~_PAGE_PPN_MASK; >>> old_pte = pfn_pte(mfn, __pgprot(old_arflags)); >>> new_pte = __pte(0); @@ -1445,12 +1446,15 @@ >>> BUG_ON(mfn != pte_pfn(ret_pte)); >>> } >>> >>> + perfc_incr(zap_domain_page_one); >>> + if (!mfn_valid(mfn)) >>> + return; >>> + >>> page = mfn_to_page(mfn); >>> BUG_ON((page->count_info & PGC_count_mask) == 0); >>> >>> BUG_ON(clear_PGC_allocate && (page_get_owner(page) == NULL)); >>> domain_put_page(d, mpaddr, pte, old_pte, clear_PGC_allocate); >>> - perfc_incr(zap_domain_page_one); >>> } >>> >>> unsigned long >>> >>> >>>> >>>> >>>> Thanks, >>>> Anthony >>>> >>>>> >>>>> - probably it would better to split this patch into two ones. >>>>> >>>>> thanks, >>>>> >>>>>> use VTD to assing device, guest port may not be equal to host >>>>>> port. Change ioports_permit_access interface >>>>>> add deassign_domain_mmio_page interface >>>>>> >>>>>> Signed-off-by; Anthony Xu < anthony.xu@xxxxxxxxx > >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> diff -r 42c7733c1a2a xen/arch/ia64/xen/dom0_ops.c >>>>>> --- a/xen/arch/ia64/xen/dom0_ops.c Thu Oct 16 18:18:39 2008 >>>>>> +0800 +++ b/xen/arch/ia64/xen/dom0_ops.c Thu Oct 16 19:13:01 >>>>>> 2008 +0800 @@ -203,7 +203,7 @@ ret = 0; >>>>>> else { if (op->u.ioport_permission.allow_access) >>>>>> - ret = ioports_permit_access(d, fp, lp); >>>>>> + ret = ioports_permit_access(d, fp, fp, lp); >>>>>> else ret = ioports_deny_access(d, fp, lp); } @@ >>>>>> -522,7 +522,7 @@ fp = space_number << IO_SPACE_BITS; >>>>>> lp = fp | 0xffff; >>>>>> >>>>>> - return ioports_permit_access(d, fp, lp); >>>>>> + return ioports_permit_access(d, fp, fp, lp); >>>>>> } >>>>>> >>>>>> unsigned long >>>>>> diff -r 42c7733c1a2a xen/arch/ia64/xen/domain.c >>>>>> --- a/xen/arch/ia64/xen/domain.c Thu Oct 16 18:18:39 2008 >>>>>> +0800 +++ b/xen/arch/ia64/xen/domain.c Thu Oct 16 19:13:01 >>>>>> 2008 +0800 @@ -1995,7 +1995,7 @@ BUG(); >>>>>> if (irqs_permit_access(d, 0, NR_IRQS-1)) >>>>>> BUG(); >>>>>> - if (ioports_permit_access(d, 0, 0xffff)) >>>>>> + if (ioports_permit_access(d, 0, 0, 0xffff)) >>>>>> BUG(); >>>>>> } >>>>>> >>>>>> diff -r 42c7733c1a2a xen/arch/ia64/xen/mm.c >>>>>> --- a/xen/arch/ia64/xen/mm.c Thu Oct 16 18:18:39 2008 +0800 >>>>>> +++ b/xen/arch/ia64/xen/mm.c Thu Oct 16 19:13:01 2008 +0800 @@ >>>>>> -984,15 +984,22 @@ >>>>>> ASSIGN_writable >>>>>>> ASSIGN_pgc_allocated); } >>>>>> >>>>>> +/* >>>>>> + * Inpurt >>>>>> + * fgp: first guest port >>>>>> + * fmp: first machine port >>>>>> + * lmp: last machine port >>>>>> + */ >>>>>> int >>>>>> -ioports_permit_access(struct domain *d, unsigned int fp, >>>>>> unsigned int lp) +ioports_permit_access(struct domain *d, >>>>>> unsigned int fgp, + unsigned int fmp, unsigned int lmp) >>>>>> { >>>>>> struct io_space *space; >>>>>> - unsigned long mmio_start, mmio_end, mach_start; >>>>>> + unsigned long mmio_start, mach_start, mach_end; int >>>>>> ret; >>>>>> >>>>>> - if (IO_SPACE_NR(fp) >= num_io_spaces) { >>>>>> - dprintk(XENLOG_WARNING, "Unknown I/O Port range 0x%x - >>>>>> 0x%x\n", fp, lp); + if (IO_SPACE_NR(fmp) >= num_io_spaces) { >>>>>> + dprintk(XENLOG_WARNING, "Unknown I/O Port range 0x%x - >>>>>> 0x%x\n", fmp, lmp); return -EFAULT; } >>>>>> >>>>>> @@ -1006,42 +1013,44 @@ >>>>>> * I/O port spaces and thus will number port spaces >>>>>> differently. >>>>>> * This is ok, they don't make use of this interface. >>>>>> */ - ret = rangeset_add_range(d->arch.ioport_caps, fp, lp); >>>>>> + ret = rangeset_add_range(d->arch.ioport_caps, fmp, lmp); >>>>>> if (ret != 0) return ret; >>>>>> >>>>>> - space = &io_space[IO_SPACE_NR(fp)]; >>>>>> + space = &io_space[IO_SPACE_NR(fmp)]; >>>>>> >>>>>> /* Legacy I/O on dom0 is already setup */ >>>>>> if (d == dom0 && space == &io_space[0]) >>>>>> return 0; >>>>>> >>>>>> - fp = IO_SPACE_PORT(fp); >>>>>> - lp = IO_SPACE_PORT(lp); >>>>>> + fmp = IO_SPACE_PORT(fmp); >>>>>> + lmp = IO_SPACE_PORT(lmp); >>>>>> >>>>>> if (space->sparse) { >>>>>> - mmio_start = IO_SPACE_SPARSE_ENCODING(fp) & PAGE_MASK; >>>>>> - mmio_end = PAGE_ALIGN(IO_SPACE_SPARSE_ENCODING(lp)); >>>>>> + mach_start = IO_SPACE_SPARSE_ENCODING(fmp) & PAGE_MASK; >>>>>> + mach_end = PAGE_ALIGN(IO_SPACE_SPARSE_ENCODING(lmp)); } >>>>>> else { >>>>>> - mmio_start = fp & PAGE_MASK; >>>>>> - mmio_end = PAGE_ALIGN(lp); >>>>>> + mach_start = fmp & PAGE_MASK; >>>>>> + mach_end = PAGE_ALIGN(lmp); >>>>>> } >>>>>> >>>>>> /* >>>>>> * The "machine first port" is not necessarily identity >>>>>> mapped >>>>>> * to the guest first port. At least for the legacy range. >>>>>> */ - mach_start = mmio_start | __pa(space->mmio_base); >>>>>> + mach_start = mach_start | __pa(space->mmio_base); >>>>>> + mach_end = mach_end | __pa(space->mmio_base); >>>>>> >>>>>> - if (space == &io_space[0]) { >>>>>> + mmio_start = IO_SPACE_SPARSE_ENCODING(fgp) & PAGE_MASK; + >>>>>> + if ( VMX_DOMAIN(d->vcpu[0])) >>>>>> + mmio_start |= LEGACY_IO_START; >>>>>> + else if (space == &io_space[0]) >>>>>> mmio_start |= IO_PORTS_PADDR; >>>>>> - mmio_end |= IO_PORTS_PADDR; >>>>>> - } else { >>>>>> + else >>>>>> mmio_start |= __pa(space->mmio_base); >>>>>> - mmio_end |= __pa(space->mmio_base); >>>>>> - } >>>>>> >>>>>> - while (mmio_start <= mmio_end) { >>>>>> + while (mach_start < mach_end) { >>>>>> __assign_domain_page(d, mmio_start, >>>>>> mach_start, ASSIGN_nocache | ASSIGN_direct_io); >>>>>> mmio_start += PAGE_SIZE; >>>>>> @@ -1091,7 +1100,9 @@ >>>>>> mmio_end = PAGE_ALIGN(lp_base); >>>>>> } >>>>>> >>>>>> - if (space == &io_space[0] && d != dom0) >>>>>> + if (VMX_DOMAIN(d->vcpu[0])) >>>>>> + mmio_base = LEGACY_IO_START; >>>>>> + else if (space == &io_space[0] && d != dom0) >>>>>> mmio_base = IO_PORTS_PADDR; >>>>>> else >>>>>> mmio_base = __pa(space->mmio_base); >>>>>> @@ -1217,6 +1228,33 @@ >>>>>> >>>>>> return mpaddr; >>>>>> } >>>>>> + >>>>>> +int >>>>>> +deassign_domain_mmio_page(struct domain *d, unsigned long >>>>>> mpaddr, + unsigned long phys_addr, unsigned long size ) +{ >>>>>> + unsigned long addr = mpaddr & PAGE_MASK; >>>>>> + unsigned long end = PAGE_ALIGN(mpaddr + size); + + if >>>>>> (size == 0) { + gdprintk(XENLOG_INFO, "%s: domain %p >>>>>> mpaddr 0x%lx size = 0x%lx\n", + __func__, d, >>>>>> mpaddr, size); + } + if (!efi_mmio(phys_addr, size)) { >>>>>> +#ifndef NDEBUG + gdprintk(XENLOG_INFO, "%s: domain %p >>>>>> mpaddr 0x%lx size = 0x%lx\n", + __func__, d, >>>>>> mpaddr, size); +#endif + return -EINVAL; + } >>>>>> + >>>>>> + for (; addr < end; addr += PAGE_SIZE ) { >>>>>> + __assign_domain_page(d, addr, 0, >>>>>> + ASSIGN_nocache | ASSIGN_direct_io); + } + >>>>>> return 0; +} + >>>>>> >>>>>> unsigned long >>>>>> assign_domain_mach_page(struct domain *d, >>>>>> diff -r 42c7733c1a2a xen/include/asm-ia64/iocap.h >>>>>> --- a/xen/include/asm-ia64/iocap.h Thu Oct 16 18:18:39 2008 >>>>>> +0800 +++ b/xen/include/asm-ia64/iocap.h Thu Oct 16 19:13:01 >>>>>> 2008 +0800 @@ -7,7 +7,7 @@ #ifndef __IA64_IOCAP_H__ #define >>>>>> __IA64_IOCAP_H__ >>>>>> >>>>>> -extern int ioports_permit_access(struct domain *d, >>>>>> +extern int ioports_permit_access(struct domain *d, unsigned int >>>>>> gs, unsigned int s, unsigned int >>>>>> e); extern int ioports_deny_access(struct domain *d, >>>>>> unsigned int s, unsigned int e); >>>> >>>> _______________________________________________ >>>> Xen-ia64-devel mailing list >>>> Xen-ia64-devel@xxxxxxxxxxxxxxxxxxx >>>> http://lists.xensource.com/xen-ia64-devel >> >> _______________________________________________ >> Xen-ia64-devel mailing list >> Xen-ia64-devel@xxxxxxxxxxxxxxxxxxx >> http://lists.xensource.com/xen-ia64-devel _______________________________________________ Xen-ia64-devel mailing list Xen-ia64-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-ia64-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |