Isaku Yamahata wrote:
> On Fri, Oct 17, 2008 at 05:58:45PM +0900, 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?
>> or
>> Did you hit BUG_ON(page_get_owner(page) == NULL)?
>>
>>
>>
>>>
>>> I suspect if page_info for IOPORTs is initialized.
>>> Any idea?
>
> Ah, I think they are initialized, but they are free.
> i.e. page refcount = 0, page owner = NULL.
> So you may need to make them owned by DOMID_IO somewhere of the
> initialization.
> i.e. page refcount = 1, page owner = DOMID_IO.
I think it is better to do this through dom0, instead of directly do it in xen.
Because xen doesn't have all knowledge of MMIO
Anthony
>
>>>
>>> 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
|