Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 22 Feb 2012 17:01:40 -0800
From:      Cy Schubert <Cy.Schubert@komquats.com>
To:        Andriy Gapon <avg@FreeBSD.org>
Cc:        freebsd-emulation@FreeBSD.org, Doug Barton <dougb@FreeBSD.org>, decke@FreeBSD.org, FreeBSD ports list <freebsd-ports@FreeBSD.org>
Subject:   Re: Virtualbox 4.1.8 vboxdrv instantly panics on 8-stable i386
Message-ID:  <201202230101.q1N11fVJ006417@slippy.cwsent.com>
In-Reply-To: Message from Andriy Gapon <avg@FreeBSD.org> of "Thu, 23 Feb 2012 01:31:52 %2B0200." <4F457AE8.4090708@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help
I'll give it a try on my testbed (which runs 9.0 and 8.2 -- my 7 partitions 
don't have the ports to test it without taking a lot of time to build 
prereqs).. If not tonight (PST) then I'll have some time Saturday evening.


-- 
Cheers,
Cy Schubert <Cy.Schubert@komquats.com>
FreeBSD UNIX:  <cy@FreeBSD.org>   Web:  http://www.FreeBSD.org

	The need of the many outweighs the greed of the few.


In message <4F457AE8.4090708@FreeBSD.org>, Andriy Gapon writes:
> This is a multi-part message in MIME format.
> --------------080309080104030002060603
> Content-Type: text/plain; charset=ISO-8859-1
> Content-Transfer-Encoding: 7bit
> 
> on 22/02/2012 12:48 Doug Barton said the following:
> > On 02/22/2012 02:23, Andriy Gapon wrote:
> >> The attached patched should try to grab the memory harder.
> > 
> > Same result, different memory address:
> > 
> > supdrvGipCreate: failed to allocate the GIP page. rc=-8
> > vboxdrv: supdrvInitDevExt failed, rc=-8
> > module_register_init: MOD_LOAD (vboxdrv, 0xc66e8410, 0) error 12
> 
> OK, now that, thanks to more testers, I realize that this issue is entirely
> i386-specific, I think that I might have been barking at the wrong trees.
> Now something very i386-ish to try to deal with the problem - the usual patch
> file is attached.
> 
> > ... and not sure it's relevant, but both times I've tried loading these
> > modules it has killed my sound. /dev/mixer goes away, and I have to
> > reboot to get it back. This has never happened before, so I'm pretty
> > sure it's connected.
> 
> No ideas whatsoever at this front.
> 
> -- 
> Andriy Gapon
> 
> --------------080309080104030002060603
> Content-Type: text/plain;
> 	name="patch-src-VBox-Runtime-r0drv-freebsd-memobj-r0drv-freebsd.c"
> Content-Transfer-Encoding: 7bit
> Content-Disposition: attachment;
> 	filename*0="patch-src-VBox-Runtime-r0drv-freebsd-memobj-r0drv-freebsd.c
> "
> 
> --- src/VBox/Runtime/r0drv/freebsd/memobj-r0drv-freebsd.c.orig	2011-12
> -19 15:01:31.000000000 +0200
> +++ src/VBox/Runtime/r0drv/freebsd/memobj-r0drv-freebsd.c	2012-02-23 01:2
> 4:32.111859551 +0200
> @@ -5,6 +5,7 @@
>  
>  /*
>   * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
> + * Copyright (c) 2011 Andriy Gapon <avg@FreeBSD.org>
>   *
>   * Permission is hereby granted, free of charge, to any person
>   * obtaining a copy of this software and associated documentation
> @@ -54,23 +55,8 @@
>      /** The core structure. */
>      RTR0MEMOBJINTERNAL  Core;
>      /** Type dependent data */
> -    union
> -    {
> -        /** Non physical memory allocations */
> -        struct
> -        {
> -            /** The VM object associated with the allocation. */
> -            vm_object_t         pObject;
> -        } NonPhys;
> -        /** Physical memory allocations */
> -        struct
> -        {
> -            /** Number of pages */
> -            uint32_t            cPages;
> -            /** Array of pages - variable */
> -            vm_page_t           apPages[1];
> -        } Phys;
> -    } u;
> +    /** The VM object associated with the allocation. */
> +    vm_object_t         pObject;
>  } RTR0MEMOBJFREEBSD, *PRTR0MEMOBJFREEBSD;
>  
>  
> @@ -125,25 +111,14 @@
>  
>      switch (pMemFreeBSD->Core.enmType)
>      {
> -        case RTR0MEMOBJTYPE_CONT:
> -            contigfree(pMemFreeBSD->Core.pv, pMemFreeBSD->Core.cb, M_IPRTMOB
> J);
> -            break;
> -
>          case RTR0MEMOBJTYPE_PAGE:
> +        case RTR0MEMOBJTYPE_LOW:
> +        case RTR0MEMOBJTYPE_CONT:
>          {
>              rc = vm_map_remove(kernel_map,
>                                  (vm_offset_t)pMemFreeBSD->Core.pv,
>                                  (vm_offset_t)pMemFreeBSD->Core.pv + pMemFree
> BSD->Core.cb);
>              AssertMsg(rc == KERN_SUCCESS, ("%#x", rc));
> -
> -            vm_page_lock_queues();
> -            for (uint32_t iPage = 0; iPage < pMemFreeBSD->u.Phys.cPages; iPa
> ge++)
> -            {
> -                vm_page_t pPage = pMemFreeBSD->u.Phys.apPages[iPage];
> -                vm_page_unwire(pPage, 0);
> -                vm_page_free(pPage);
> -            }
> -            vm_page_unlock_queues();
>              break;
>          }
>  
> @@ -165,8 +140,8 @@
>          case RTR0MEMOBJTYPE_RES_VIRT:
>          {
>              vm_map_t pMap = kernel_map;
> -            if (pMemFreeBSD->Core.u.Lock.R0Process != NIL_RTR0PROCESS)
> -                pMap = &((struct proc *)pMemFreeBSD->Core.u.Lock.R0Process)-
> >p_vmspace->vm_map;
> +            if (pMemFreeBSD->Core.u.ResVirt.R0Process != NIL_RTR0PROCESS)
> +                pMap = &((struct proc *)pMemFreeBSD->Core.u.ResVirt.R0Proces
> s)->p_vmspace->vm_map;
>              rc = vm_map_remove(pMap,
>                                 (vm_offset_t)pMemFreeBSD->Core.pv,
>                                 (vm_offset_t)pMemFreeBSD->Core.pv + pMemFreeB
> SD->Core.cb);
> @@ -180,7 +155,6 @@
>  
>              if (pMemFreeBSD->Core.u.Mapping.R0Process != NIL_RTR0PROCESS)
>                  pMap = &((struct proc *)pMemFreeBSD->Core.u.Mapping.R0Proces
> s)->p_vmspace->vm_map;
> -
>              rc = vm_map_remove(pMap,
>                                 (vm_offset_t)pMemFreeBSD->Core.pv,
>                                 (vm_offset_t)pMemFreeBSD->Core.pv + pMemFreeB
> SD->Core.cb);
> @@ -191,26 +165,21 @@
>          case RTR0MEMOBJTYPE_PHYS:
>          case RTR0MEMOBJTYPE_PHYS_NC:
>          {
> +            VM_OBJECT_LOCK(pMemFreeBSD->pObject);
> +            vm_page_t pPage = vm_page_find_least(pMemFreeBSD->pObject, 0);
>              vm_page_lock_queues();
> -            for (uint32_t iPage = 0; iPage < pMemFreeBSD->u.Phys.cPages; iPa
> ge++)
> +            for (vm_page_t pPage = vm_page_find_least(pMemFreeBSD->pObject, 
> 0);
> +                 pPage != NULL;
> +                 pPage = vm_page_next(pPage))
>              {
> -                vm_page_t pPage = pMemFreeBSD->u.Phys.apPages[iPage];
>                  vm_page_unwire(pPage, 0);
> -                vm_page_free(pPage);
>              }
>              vm_page_unlock_queues();
> +            VM_OBJECT_UNLOCK(pMemFreeBSD->pObject);
> +            vm_object_deallocate(pMemFreeBSD->pObject);
>              break;
>          }
>  
> -#ifdef USE_KMEM_ALLOC_ATTR
> -        case RTR0MEMOBJTYPE_LOW:
> -        {
> -            kmem_free(kernel_map, (vm_offset_t)pMemFreeBSD->Core.pv, pMemFre
> eBSD->Core.cb);
> -            break;
> -        }
> -#else
> -        case RTR0MEMOBJTYPE_LOW: /* unused */
> -#endif
>          default:
>              AssertMsgFailed(("enmType=%d\n", pMemFreeBSD->Core.enmType));
>              return VERR_INTERNAL_ERROR;
> @@ -220,183 +189,183 @@
>  }
>  
>  
> -DECLHIDDEN(int) rtR0MemObjNativeAllocPage(PPRTR0MEMOBJINTERNAL ppMem, size_t
>  cb, bool fExecutable)
> -{
> -    int rc;
> -    size_t cPages = cb >> PAGE_SHIFT;
> -
> -    /* create the object. */
> -    PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(RT_OF
> FSETOF(RTR0MEMOBJFREEBSD, u.Phys.apPages[cPages]),
> -                                                                       RTR0M
> EMOBJTYPE_PAGE, NULL, cb);
> -    if (!pMemFreeBSD)
> -        return VERR_NO_MEMORY;
> -
> -    pMemFreeBSD->u.Phys.cPages = cPages;
> +static vm_page_t FreeBSDContigPhysAllocHelper(vm_object_t pObject, vm_pindex
> _t iPIndex,
> +                                              u_long cPages, vm_paddr_t VmPh
> ysAddrHigh,
> +                                              u_long uAlignment, bool fWire)
> +{
> +    vm_page_t pPages;
> +    int tries = 0;
> +#if __FreeBSD_version > 1000000
> +    int flags = VM_ALLOC_INTERRUPT | VM_ALLOC_NOBUSY;
> +
> +    if (fWire)
> +        flags |= VM_ALLOC_WIRED;
> +    while (1)
> +    {
> +        VM_OBJECT_LOCK(pObject);
> +        pPages = vm_page_alloc_contig(pObject, iPIndex, flags, cPages, 0, Vm
> PhysAddrHigh, uAlignment, 0, VM_MEMATTR_DEFAULT);
> +        VM_OBJECT_UNLOCK(pObject);
> +        if (pPages || tries >= 1)
> +            break;
> +        vm_contig_grow_cache(tries, 0, VmPhysAddrHigh);
> +        tries++;
> +    }
> +    return pPages;
> +#else
>  
> -    vm_offset_t MapAddress = vm_map_min(kernel_map);
> -    rc = vm_map_find(kernel_map,                /* map */
> -                     NULL,                      /* object */
> -                     0,                         /* offset */
> -                     &MapAddress,               /* addr (IN/OUT) */
> -                     cb,                        /* length */
> -                     TRUE,                      /* find_space */
> -                     fExecutable                /* protection */
> -                     ? VM_PROT_ALL
> -                     : VM_PROT_RW,
> -                     VM_PROT_ALL,               /* max(_prot) */
> -                     0);                        /* cow (copy-on-write) */
> -    if (rc == KERN_SUCCESS)
> +    while (1)
>      {
> -        rc = VINF_SUCCESS;
> -
> -        for (size_t iPage = 0; iPage < cPages; iPage++)
> +        pPages = vm_phys_alloc_contig(cPages, 0, VmPhysAddrHigh, uAlignment,
>  0);
> +        if (pPages || tries >= 1)
> +            break;
> +        vm_contig_grow_cache(tries, 0, VmPhysAddrHigh);
> +        tries++;
> +    }
> +    if (!pPages)
> +        return pPages;
> +    VM_OBJECT_LOCK(pObject);
> +    for (vm_pindex_t iPage = 0; iPage < cPages; iPage++)
> +    {
> +        vm_page_t pPage = pPages + iPage;
> +        vm_page_insert(pPage, pObject, iPIndex + iPage);
> +        pPage->valid = VM_PAGE_BITS_ALL;
> +        if (fWire)
>          {
> -            vm_page_t   pPage;
> +            pPage->wire_count = 1;
> +            atomic_add_int(&cnt.v_wire_count, 1);
> +        }
> +    }
> +    VM_OBJECT_UNLOCK(pObject);
> +    return pPages;
> +#endif
> +}
>  
> -            pPage = vm_page_alloc(NULL, iPage,
> -                                  VM_ALLOC_SYSTEM |
> -                                  VM_ALLOC_WIRED | VM_ALLOC_NOOBJ);
> +static int FreeBSDPhysAllocHelper(vm_object_t pObject, u_long cPages,
> +                                  vm_paddr_t VmPhysAddrHigh, u_long uAlignme
> nt,
> +                                  bool fContiguous, bool fWire)
> +{
> +    if (fContiguous)
> +    {
> +        if (FreeBSDContigPhysAllocHelper(pObject, 0, cPages, VmPhysAddrHigh,
>  uAlignment, fWire) != NULL)
> +            return VINF_SUCCESS;
> +        else
> +            return VERR_NO_MEMORY;
> +    }
>  
> -            if (!pPage)
> +    for (vm_pindex_t iPage = 0; iPage < cPages; iPage++)
> +    {
> +        vm_page_t pPage = FreeBSDContigPhysAllocHelper(pObject, iPage, 1, Vm
> PhysAddrHigh, uAlignment, fWire);
> +        if (!pPage)
> +        {
> +            /* Free all allocated pages */
> +            VM_OBJECT_LOCK(pObject);
> +            while (iPage-- > 0)
>              {
> -                /*
> -                    * Out of pages
> -                    * Remove already allocated pages
> -                    */
> -                while (iPage-- > 0)
> -                {
> -                    pPage = pMemFreeBSD->u.Phys.apPages[iPage];
> -                    vm_page_lock_queues();
> +                pPage = vm_page_lookup(pObject, iPage);
> +                vm_page_lock_queues();
> +                if (fWire)
>                      vm_page_unwire(pPage, 0);
> -                    vm_page_free(pPage);
> -                    vm_page_unlock_queues();
> -                }
> -                rc = VERR_NO_MEMORY;
> -                break;
> +                vm_page_free(pPage);
> +                vm_page_unlock_queues();
>              }
> -
> -            pPage->valid = VM_PAGE_BITS_ALL;
> -            pMemFreeBSD->u.Phys.apPages[iPage] = pPage;
> +            VM_OBJECT_UNLOCK(pObject);
> +            return VERR_NO_MEMORY;
>          }
> +    }
> +    return VINF_SUCCESS;
> +}
>  
> -        if (rc == VINF_SUCCESS)
> -        {
> -            vm_offset_t AddressDst = MapAddress;
> +static int FreeBSDAllocHelper(PRTR0MEMOBJFREEBSD pMemFreeBSD, bool fExecutab
> le,
> +                              vm_paddr_t VmPhysAddrHigh, bool fContiguous)
> +{
> +    int rc;
> +    size_t cPages = atop(pMemFreeBSD->Core.cb);
>  
> -            for (size_t iPage = 0; iPage < cPages; iPage++)
> -            {
> -                vm_page_t pPage = pMemFreeBSD->u.Phys.apPages[iPage];
> +    pMemFreeBSD->pObject = vm_object_allocate(OBJT_PHYS, cPages);
> +    vm_offset_t MapAddress = vm_map_min(kernel_map);
>  
> -                MY_PMAP_ENTER(kernel_map->pmap, AddressDst, pPage,
> -                              fExecutable
> -                              ? VM_PROT_ALL
> -                              : VM_PROT_RW,
> -                              TRUE);
> +    // no additional object reference for auto-deallocation upon unmapping
> +    rc = vm_map_find(kernel_map, pMemFreeBSD->pObject, 0,
> +                     &MapAddress, pMemFreeBSD->Core.cb, VMFS_ANY_SPACE,
> +                     fExecutable ? VM_PROT_ALL : VM_PROT_RW, VM_PROT_ALL, 0)
> ;
>  
> -                AddressDst += PAGE_SIZE;
> -            }
> +    if (rc == KERN_SUCCESS)
> +    {
> +        rc = FreeBSDPhysAllocHelper(pMemFreeBSD->pObject, cPages, VmPhysAddr
> High, PAGE_SIZE, fContiguous, false);
> +        if (RT_SUCCESS(rc))
> +        {
> +            vm_map_wire(kernel_map, MapAddress, MapAddress + pMemFreeBSD->Co
> re.cb, VM_MAP_WIRE_SYSTEM|VM_MAP_WIRE_NOHOLES);
>  
>              /* Store start address */
>              pMemFreeBSD->Core.pv = (void *)MapAddress;
> -            *ppMem = &pMemFreeBSD->Core;
>              return VINF_SUCCESS;
>          }
> -    }
> -    rc = VERR_NO_MEMORY; /** @todo fix translation (borrow from darwin) */
>  
> -    rtR0MemObjDelete(&pMemFreeBSD->Core);
> +        vm_map_remove(kernel_map, MapAddress, MapAddress + pMemFreeBSD->Core
> .cb);
> +    }
> +    else
> +    {
> +        rc = VERR_NO_MEMORY; /** @todo fix translation (borrow from darwin) 
> */
> +        vm_object_deallocate(pMemFreeBSD->pObject);
> +    }
>      return rc;
>  }
>  
> -
> -DECLHIDDEN(int) rtR0MemObjNativeAllocLow(PPRTR0MEMOBJINTERNAL ppMem, size_t 
> cb, bool fExecutable)
> +DECLHIDDEN(int) rtR0MemObjNativeAllocPage(PPRTR0MEMOBJINTERNAL ppMem, size_t
>  cb, bool fExecutable)
>  {
> -#ifdef USE_KMEM_ALLOC_ATTR
> -    /*
> -     * Use kmem_alloc_attr, fExectuable is not needed because the
> -     * memory will be executable by default
> -     */
> -    NOREF(fExecutable);
> -
> -    /* create the object. */
> -    PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeo
> f(*pMemFreeBSD), RTR0MEMOBJTYPE_LOW, NULL, cb);
> +    PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeo
> f(*pMemFreeBSD),
> +                                                                       RTR0M
> EMOBJTYPE_PAGE, NULL, cb);
>      if (!pMemFreeBSD)
>          return VERR_NO_MEMORY;
>  
> -    pMemFreeBSD->Core.pv = (void *)kmem_alloc_attr(kernel_map,          /* K
> ernel */
> -                                                   cb,                  /* A
> mount */
> -                                                   M_ZERO,              /* Z
> ero memory */
> -                                                   0,                   /* L
> ow physical address */
> -                                                   _4G - PAGE_SIZE,     /* H
> ighest physical address */
> -                                                   VM_MEMATTR_DEFAULT); /* D
> efault memory attributes */
> -    if (!pMemFreeBSD->Core.pv)
> -        return VERR_NO_MEMORY;
> -
> -    *ppMem = &pMemFreeBSD->Core;
> -
> -    return VINF_SUCCESS;
> -#else
> -    /*
> -     * Try a Alloc first and see if we get luck, if not try contigmalloc.
> -     * Might wish to try find our own pages or something later if this
> -     * turns into a problemspot on AMD64 boxes.
> -     */
> -    int rc = rtR0MemObjNativeAllocPage(ppMem, cb, fExecutable);
> -    if (RT_SUCCESS(rc))
> +    int rc = FreeBSDAllocHelper(pMemFreeBSD, fExecutable, ~(vm_paddr_t)0, fa
> lse);
> +    if (RT_FAILURE(rc))
>      {
> -        size_t iPage = cb >> PAGE_SHIFT;
> -        while (iPage-- > 0)
> -            if (rtR0MemObjNativeGetPagePhysAddr(*ppMem, iPage) > (_4G - PAGE
> _SIZE))
> -            {
> -                RTR0MemObjFree(*ppMem, false);
> -                *ppMem = NULL;
> -                rc = VERR_NO_MEMORY;
> -                break;
> -            }
> +        rtR0MemObjDelete(&pMemFreeBSD->Core);
> +        return rc;
>      }
> -    if (RT_FAILURE(rc))
> -        rc = rtR0MemObjNativeAllocCont(ppMem, cb, fExecutable);
> +
> +    *ppMem = &pMemFreeBSD->Core;
>      return rc;
> -#endif
>  }
>  
>  
> -DECLHIDDEN(int) rtR0MemObjNativeAllocCont(PPRTR0MEMOBJINTERNAL ppMem, size_t
>  cb, bool fExecutable)
> +DECLHIDDEN(int) rtR0MemObjNativeAllocLow(PPRTR0MEMOBJINTERNAL ppMem, size_t 
> cb, bool fExecutable)
>  {
> -    /* create the object. */
> -    PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeo
> f(*pMemFreeBSD), RTR0MEMOBJTYPE_CONT, NULL, cb);
> +    PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeo
> f(*pMemFreeBSD),
> +                                                                       RTR0M
> EMOBJTYPE_LOW, NULL, cb);
>      if (!pMemFreeBSD)
>          return VERR_NO_MEMORY;
>  
> -    /* do the allocation. */
> -    pMemFreeBSD->Core.pv = contigmalloc(cb,                   /* size */
> -                                        M_IPRTMOBJ,           /* type */
> -                                        M_NOWAIT | M_ZERO,    /* flags */
> -                                        0,                    /* lowest phys
> ical address*/
> -                                        _4G-1,                /* highest phy
> sical address */
> -                                        PAGE_SIZE,            /* alignment. 
> */
> -                                        0);                   /* boundary */
> -    if (pMemFreeBSD->Core.pv)
> +    int rc = FreeBSDAllocHelper(pMemFreeBSD, fExecutable, _4G - 1, false);
> +    if (RT_FAILURE(rc))
>      {
> -        pMemFreeBSD->Core.u.Cont.Phys = vtophys(pMemFreeBSD->Core.pv);
> -        *ppMem = &pMemFreeBSD->Core;
> -        return VINF_SUCCESS;
> +        rtR0MemObjDelete(&pMemFreeBSD->Core);
> +        return rc;
>      }
>  
> -    NOREF(fExecutable);
> -    rtR0MemObjDelete(&pMemFreeBSD->Core);
> -    return VERR_NO_MEMORY;
> +    *ppMem = &pMemFreeBSD->Core;
> +    return rc;
>  }
>  
>  
> -static void rtR0MemObjFreeBSDPhysPageInit(vm_page_t pPage, vm_pindex_t iPage
> )
> +DECLHIDDEN(int) rtR0MemObjNativeAllocCont(PPRTR0MEMOBJINTERNAL ppMem, size_t
>  cb, bool fExecutable)
>  {
> -    pPage->wire_count = 1;
> -    pPage->pindex     = iPage;
> -    pPage->act_count  = 0;
> -    pPage->oflags     = 0;
> -    pPage->flags      = PG_UNMANAGED;
> -    atomic_add_int(&cnt.v_wire_count, 1);
> +    PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeo
> f(*pMemFreeBSD),
> +                                                                       RTR0M
> EMOBJTYPE_CONT, NULL, cb);
> +    if (!pMemFreeBSD)
> +        return VERR_NO_MEMORY;
> +
> +    int rc = FreeBSDAllocHelper(pMemFreeBSD, fExecutable, _4G - 1, true);
> +    if (RT_FAILURE(rc))
> +    {
> +        rtR0MemObjDelete(&pMemFreeBSD->Core);
> +        return rc;
> +    }
> +
> +    pMemFreeBSD->Core.u.Cont.Phys = vtophys(pMemFreeBSD->Core.pv);
> +    *ppMem = &pMemFreeBSD->Core;
> +    return rc;
>  }
>  
>  
> @@ -405,69 +374,36 @@
>                                             RTHCPHYS PhysHighest, size_t uAli
> gnment,
>                                             bool fContiguous)
>  {
> -    int        rc = VINF_SUCCESS;
> -    uint32_t   cPages = cb >> PAGE_SHIFT;
> +    uint32_t   cPages = atop(cb);
>      vm_paddr_t VmPhysAddrHigh;
>  
>      /* create the object. */
> -    PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(RT_OF
> FSETOF(RTR0MEMOBJFREEBSD, u.Phys.apPages[cPages]),
> +    PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeo
> f(*pMemFreeBSD),
>                                                                         enmTy
> pe, NULL, cb);
>      if (!pMemFreeBSD)
>          return VERR_NO_MEMORY;
>  
> -    pMemFreeBSD->u.Phys.cPages = cPages;
> +    pMemFreeBSD->pObject = vm_object_allocate(OBJT_PHYS, atop(cb));
>  
>      if (PhysHighest != NIL_RTHCPHYS)
>          VmPhysAddrHigh = PhysHighest;
>      else
>          VmPhysAddrHigh = ~(vm_paddr_t)0;
>  
> -    if (fContiguous)
> -    {
> -        vm_page_t pPage = vm_phys_alloc_contig(cPages, 0, VmPhysAddrHigh, uA
> lignment, 0);
> -
> -        if (pPage)
> -            for (uint32_t iPage = 0; iPage < cPages; iPage++)
> -            {
> -                rtR0MemObjFreeBSDPhysPageInit(&pPage[iPage], iPage);
> -                pMemFreeBSD->u.Phys.apPages[iPage] = &pPage[iPage];
> -            }
> -        else
> -            rc = VERR_NO_MEMORY;
> -    }
> -    else
> -    {
> -        /* Allocate page by page */
> -        for (uint32_t iPage = 0; iPage < cPages; iPage++)
> -        {
> -            vm_page_t pPage = vm_phys_alloc_contig(1, 0, VmPhysAddrHigh, uAl
> ignment, 0);
> -
> -            if (!pPage)
> -            {
> -                /* Free all allocated pages */
> -                while (iPage-- > 0)
> -                {
> -                    pPage = pMemFreeBSD->u.Phys.apPages[iPage];
> -                    vm_page_lock_queues();
> -                    vm_page_unwire(pPage, 0);
> -                    vm_page_free(pPage);
> -                    vm_page_unlock_queues();
> -                }
> -                rc = VERR_NO_MEMORY;
> -                break;
> -            }
> -            rtR0MemObjFreeBSDPhysPageInit(pPage, iPage);
> -            pMemFreeBSD->u.Phys.apPages[iPage] = pPage;
> -        }
> -    }
> +    int rc = FreeBSDPhysAllocHelper(pMemFreeBSD->pObject, cPages, VmPhysAddr
> High, uAlignment, fContiguous, true);
>  
> -    if (RT_FAILURE(rc))
> +    if (RT_FAILURE(rc)) {
> +        vm_object_deallocate(pMemFreeBSD->pObject);
>          rtR0MemObjDelete(&pMemFreeBSD->Core);
> +    }
>      else
>      {
> -        if (enmType == RTR0MEMOBJTYPE_PHYS)
> +        if (fContiguous)
>          {
> -            pMemFreeBSD->Core.u.Phys.PhysBase = VM_PAGE_TO_PHYS(pMemFreeBSD-
> >u.Phys.apPages[0]);
> +            Assert(enmType == RTR0MEMOBJTYPE_PHYS);
> +            VM_OBJECT_LOCK(pMemFreeBSD->pObject);
> +            pMemFreeBSD->Core.u.Phys.PhysBase = VM_PAGE_TO_PHYS(vm_page_find
> _least(pMemFreeBSD->pObject, 0));
> +            VM_OBJECT_UNLOCK(pMemFreeBSD->pObject);
>              pMemFreeBSD->Core.u.Phys.fAllocated = true;
>          }
>  
> @@ -480,42 +416,13 @@
>  
>  DECLHIDDEN(int) rtR0MemObjNativeAllocPhys(PPRTR0MEMOBJINTERNAL ppMem, size_t
>  cb, RTHCPHYS PhysHighest, size_t uAlignment)
>  {
> -#if 1
>      return rtR0MemObjFreeBSDAllocPhysPages(ppMem, RTR0MEMOBJTYPE_PHYS, cb, P
> hysHighest, uAlignment, true);
> -#else
> -    /* create the object. */
> -    PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeo
> f(*pMemFreeBSD), RTR0MEMOBJTYPE_CONT, NULL, cb);
> -    if (!pMemFreeBSD)
> -        return VERR_NO_MEMORY;
> -
> -    /* do the allocation. */
> -    pMemFreeBSD->Core.pv = contigmalloc(cb,                   /* size */
> -                                        M_IPRTMOBJ,           /* type */
> -                                        M_NOWAIT | M_ZERO,    /* flags */
> -                                        0,                    /* lowest phys
> ical address*/
> -                                        _4G-1,                /* highest phy
> sical address */
> -                                        uAlignment,           /* alignment. 
> */
> -                                        0);                   /* boundary */
> -    if (pMemFreeBSD->Core.pv)
> -    {
> -        pMemFreeBSD->Core.u.Cont.Phys = vtophys(pMemFreeBSD->Core.pv);
> -        *ppMem = &pMemFreeBSD->Core;
> -        return VINF_SUCCESS;
> -    }
> -
> -    rtR0MemObjDelete(&pMemFreeBSD->Core);
> -    return VERR_NO_MEMORY;
> -#endif
>  }
>  
>  
>  DECLHIDDEN(int) rtR0MemObjNativeAllocPhysNC(PPRTR0MEMOBJINTERNAL ppMem, size
> _t cb, RTHCPHYS PhysHighest)
>  {
> -#if 1
>      return rtR0MemObjFreeBSDAllocPhysPages(ppMem, RTR0MEMOBJTYPE_PHYS_NC, cb
> , PhysHighest, PAGE_SIZE, false);
> -#else
> -    return VERR_NOT_SUPPORTED;
> -#endif
>  }
>  
>  
> @@ -625,49 +532,41 @@
>      if (!pMemFreeBSD)
>          return VERR_NO_MEMORY;
>  
> -    /*
> -     * Allocate an empty VM object and map it into the requested map.
> -     */
> -    pMemFreeBSD->u.NonPhys.pObject = vm_object_allocate(OBJT_DEFAULT, cb >> 
> PAGE_SHIFT);
> -    if (pMemFreeBSD->u.NonPhys.pObject)
> +    vm_offset_t MapAddress = pvFixed != (void *)-1
> +                           ? (vm_offset_t)pvFixed
> +                           : vm_map_min(pMap);
> +    if (pvFixed != (void *)-1)
> +        vm_map_remove(pMap,
> +                      MapAddress,
> +                      MapAddress + cb);
> +
> +    rc = vm_map_find(pMap,                          /* map */
> +                     NULL,                          /* object */
> +                     0,                             /* offset */
> +                     &MapAddress,                   /* addr (IN/OUT) */
> +                     cb,                            /* length */
> +                     pvFixed == (void *)-1 ? VMFS_ANY_SPACE : VMFS_NO_SPACE,
> +                                                    /* find_space */
> +                     VM_PROT_NONE,                  /* protection */
> +                     VM_PROT_ALL,                   /* max(_prot) ?? */
> +                     0);                            /* cow (copy-on-write) *
> /
> +    if (rc == KERN_SUCCESS)
>      {
> -        vm_offset_t MapAddress = pvFixed != (void *)-1
> -                               ? (vm_offset_t)pvFixed
> -                               : vm_map_min(pMap);
> -        if (pvFixed != (void *)-1)
> -            vm_map_remove(pMap,
> -                          MapAddress,
> -                          MapAddress + cb);
> -
> -        rc = vm_map_find(pMap,                          /* map */
> -                         pMemFreeBSD->u.NonPhys.pObject, /* object */
> -                         0,                             /* offset */
> -                         &MapAddress,                   /* addr (IN/OUT) */
> -                         cb,                            /* length */
> -                         pvFixed == (void *)-1,         /* find_space */
> -                         VM_PROT_NONE,                  /* protection */
> -                         VM_PROT_ALL,                   /* max(_prot) ?? */
> -                         0);                            /* cow (copy-on-writ
> e) */
> -        if (rc == KERN_SUCCESS)
> +        if (R0Process != NIL_RTR0PROCESS)
>          {
> -            if (R0Process != NIL_RTR0PROCESS)
> -            {
> -                rc = vm_map_inherit(pMap,
> -                                    MapAddress,
> -                                    MapAddress + cb,
> -                                    VM_INHERIT_SHARE);
> -                AssertMsg(rc == KERN_SUCCESS, ("%#x\n", rc));
> -            }
> -            pMemFreeBSD->Core.pv = (void *)MapAddress;
> -            pMemFreeBSD->Core.u.ResVirt.R0Process = R0Process;
> -            *ppMem = &pMemFreeBSD->Core;
> -            return VINF_SUCCESS;
> +            rc = vm_map_inherit(pMap,
> +                                MapAddress,
> +                                MapAddress + cb,
> +                                VM_INHERIT_SHARE);
> +            AssertMsg(rc == KERN_SUCCESS, ("%#x\n", rc));
>          }
> -        vm_object_deallocate(pMemFreeBSD->u.NonPhys.pObject);
> -        rc = VERR_NO_MEMORY; /** @todo fix translation (borrow from darwin) 
> */
> +        pMemFreeBSD->Core.pv = (void *)MapAddress;
> +        pMemFreeBSD->Core.u.ResVirt.R0Process = R0Process;
> +        *ppMem = &pMemFreeBSD->Core;
> +        return VINF_SUCCESS;
>      }
> -    else
> -        rc = VERR_NO_MEMORY;
> +
> +    rc = VERR_NO_MEMORY; /** @todo fix translation (borrow from darwin) */
>      rtR0MemObjDelete(&pMemFreeBSD->Core);
>      return rc;
>  
> @@ -690,7 +589,7 @@
>  DECLHIDDEN(int) rtR0MemObjNativeMapKernel(PPRTR0MEMOBJINTERNAL ppMem, RTR0ME
> MOBJ pMemToMap, void *pvFixed, size_t uAlignment,
>                                            unsigned fProt, size_t offSub, siz
> e_t cbSub)
>  {
> -    AssertMsgReturn(!offSub && !cbSub, ("%#x %#x\n", offSub, cbSub), VERR_NO
> T_SUPPORTED);
> +//  AssertMsgReturn(!offSub && !cbSub, ("%#x %#x\n", offSub, cbSub), VERR_NO
> T_SUPPORTED);
>      AssertMsgReturn(pvFixed == (void *)-1, ("%p\n", pvFixed), VERR_NOT_SUPPO
> RTED);
>  
>      /*
> @@ -699,21 +598,68 @@
>      if (uAlignment > PAGE_SIZE)
>          return VERR_NOT_SUPPORTED;
>  
> -/* Phys: see pmap_mapdev in i386/i386/pmap.c (http://fxr.watson.org/fxr/sour
> ce/i386/i386/pmap.c?v=RELENG62#L2860) */
> -/** @todo finish the implementation. */
> +    int                rc;
> +    PRTR0MEMOBJFREEBSD pMemToMapFreeBSD = (PRTR0MEMOBJFREEBSD)pMemToMap;
>  
> -    return VERR_NOT_SUPPORTED;
> +    /* calc protection */
> +    vm_prot_t       ProtectionFlags = 0;
> +    if ((fProt & RTMEM_PROT_NONE) == RTMEM_PROT_NONE)
> +        ProtectionFlags = VM_PROT_NONE;
> +    if ((fProt & RTMEM_PROT_READ) == RTMEM_PROT_READ)
> +        ProtectionFlags |= VM_PROT_READ;
> +    if ((fProt & RTMEM_PROT_WRITE) == RTMEM_PROT_WRITE)
> +        ProtectionFlags |= VM_PROT_WRITE;
> +    if ((fProt & RTMEM_PROT_EXEC) == RTMEM_PROT_EXEC)
> +        ProtectionFlags |= VM_PROT_EXECUTE;
> +
> +    vm_offset_t  Addr = vm_map_min(kernel_map);
> +    if (cbSub == 0)
> +        cbSub = pMemToMap->cb - offSub;
> +
> +    vm_object_reference(pMemToMapFreeBSD->pObject);
> +    rc = vm_map_find(kernel_map,            /* Map to insert the object in *
> /
> +                     pMemToMapFreeBSD->pObject, /* Object to map */
> +                     offSub,                /* Start offset in the object */
> +                     &Addr,                 /* Start address IN/OUT */
> +                     cbSub,                 /* Size of the mapping */
> +                     VMFS_ANY_SPACE,        /* Whether a suitable address sh
> ould be searched for first */
> +                     ProtectionFlags,       /* protection flags */
> +                     VM_PROT_ALL,           /* Maximum protection flags */
> +                     0);                    /* copy-on-write and similar fla
> gs */
> +
> +    if (rc == KERN_SUCCESS)
> +    {
> +        rc = vm_map_wire(kernel_map, Addr, Addr + cbSub, VM_MAP_WIRE_SYSTEM|
> VM_MAP_WIRE_NOHOLES);
> +        AssertMsg(rc == KERN_SUCCESS, ("%#x\n", rc));
> +
> +        PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(s
> izeof(RTR0MEMOBJFREEBSD),
> +                                                                           R
> TR0MEMOBJTYPE_MAPPING,
> +                                                                           (
> void *)Addr,
> +                                                                           c
> bSub);
> +        if (pMemFreeBSD)
> +        {
> +            Assert((vm_offset_t)pMemFreeBSD->Core.pv == Addr);
> +            pMemFreeBSD->Core.u.Mapping.R0Process = NIL_RTR0PROCESS;
> +            *ppMem = &pMemFreeBSD->Core;
> +            return VINF_SUCCESS;
> +        }
> +        rc = vm_map_remove(kernel_map, Addr, Addr + cbSub);
> +        AssertMsg(rc == KERN_SUCCESS, ("Deleting mapping failed\n"));
> +    }
> +    else
> +        vm_object_deallocate(pMemToMapFreeBSD->pObject);
> +
> +    return VERR_NO_MEMORY;
>  }
>  
>  
> -/* see http://markmail.org/message/udhq33tefgtyfozs */
> -DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMO
> BJ pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment, unsigned fProt, RTR0PROC
> ESS R0Process)
> +DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMO
> BJ pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment,
> +                                        unsigned fProt, RTR0PROCESS R0Proces
> s)
>  {
>      /*
>       * Check for unsupported stuff.
>       */
>      AssertMsgReturn(R0Process == RTR0ProcHandleSelf(), ("%p != %p\n", R0Proc
> ess, RTR0ProcHandleSelf()), VERR_NOT_SUPPORTED);
> -    AssertMsgReturn(R3PtrFixed == (RTR3PTR)-1, ("%p\n", R3PtrFixed), VERR_NO
> T_SUPPORTED);
>      if (uAlignment > PAGE_SIZE)
>          return VERR_NOT_SUPPORTED;
>  
> @@ -734,62 +680,38 @@
>          ProtectionFlags |= VM_PROT_EXECUTE;
>  
>      /* calc mapping address */
> -    PROC_LOCK(pProc);
> -    vm_offset_t AddrR3 = round_page((vm_offset_t)pProc->p_vmspace->vm_daddr 
> + lim_max(pProc, RLIMIT_DATA));
> -    PROC_UNLOCK(pProc);
> +    vm_offset_t AddrR3;
> +    if (R3PtrFixed == (RTR3PTR)-1)
> +    {
> +        // is this needed?
> +        PROC_LOCK(pProc);
> +        AddrR3 = round_page((vm_offset_t)pProc->p_vmspace->vm_daddr + lim_ma
> x(pProc, RLIMIT_DATA));
> +        PROC_UNLOCK(pProc);
> +    }
> +    else
> +        AddrR3 = (vm_offset_t)R3PtrFixed;
>  
> -    /* Insert the object in the map. */
> +    /* Insert the pObject in the map. */
> +    vm_object_reference(pMemToMapFreeBSD->pObject);
>      rc = vm_map_find(pProcMap,              /* Map to insert the object in *
> /
> -                     NULL,                  /* Object to map */
> +                     pMemToMapFreeBSD->pObject, /* Object to map */
>                       0,                     /* Start offset in the object */
>                       &AddrR3,               /* Start address IN/OUT */
>                       pMemToMap->cb,         /* Size of the mapping */
> -                     TRUE,                  /* Whether a suitable address sh
> ould be searched for first */
> +                     R3PtrFixed == (RTR3PTR)-1 ? VMFS_ANY_SPACE : VMFS_NO_SP
> ACE,
> +                                            /* Whether a suitable address sh
> ould be searched for first */
>                       ProtectionFlags,       /* protection flags */
>                       VM_PROT_ALL,           /* Maximum protection flags */
> -                     0);                    /* Copy on write */
> +                     0);                    /* copy-on-write and similar fla
> gs */
>  
> -    /* Map the memory page by page into the destination map. */
>      if (rc == KERN_SUCCESS)
>      {
> -        size_t         cPages       = pMemToMap->cb >> PAGE_SHIFT;;
> -        pmap_t         pPhysicalMap = pProcMap->pmap;
> -        vm_offset_t    AddrR3Dst    = AddrR3;
> -
> -        if (   pMemToMap->enmType == RTR0MEMOBJTYPE_PHYS
> -            || pMemToMap->enmType == RTR0MEMOBJTYPE_PHYS_NC
> -            || pMemToMap->enmType == RTR0MEMOBJTYPE_PAGE)
> -        {
> -            /* Mapping physical allocations */
> -            Assert(cPages == pMemToMapFreeBSD->u.Phys.cPages);
> +        rc = vm_map_wire(pProcMap, AddrR3, AddrR3 + pMemToMap->cb, VM_MAP_WI
> RE_USER|VM_MAP_WIRE_NOHOLES);
> +        AssertMsg(rc == KERN_SUCCESS, ("%#x\n", rc));
>  
> -            /* Insert the memory page by page into the mapping. */
> -            for (uint32_t iPage = 0; iPage < cPages; iPage++)
> -            {
> -                vm_page_t pPage = pMemToMapFreeBSD->u.Phys.apPages[iPage];
> +        rc = vm_map_inherit(pProcMap, AddrR3, AddrR3 + pMemToMap->cb, VM_INH
> ERIT_SHARE);
> +        AssertMsg(rc == KERN_SUCCESS, ("%#x\n", rc));
>  
> -                MY_PMAP_ENTER(pPhysicalMap, AddrR3Dst, pPage, ProtectionFlag
> s, TRUE);
> -                AddrR3Dst += PAGE_SIZE;
> -            }
> -        }
> -        else
> -        {
> -            /* Mapping cont or low memory types */
> -            vm_offset_t AddrToMap = (vm_offset_t)pMemToMap->pv;
> -
> -            for (uint32_t iPage = 0; iPage < cPages; iPage++)
> -            {
> -                vm_page_t pPage = PHYS_TO_VM_PAGE(vtophys(AddrToMap));
> -
> -                MY_PMAP_ENTER(pPhysicalMap, AddrR3Dst, pPage, ProtectionFlag
> s, TRUE);
> -                AddrR3Dst += PAGE_SIZE;
> -                AddrToMap += PAGE_SIZE;
> -            }
> -        }
> -    }
> -
> -    if (RT_SUCCESS(rc))
> -    {
>          /*
>           * Create a mapping object for it.
>           */
> @@ -805,9 +727,11 @@
>              return VINF_SUCCESS;
>          }
>  
> -        rc = vm_map_remove(pProcMap, ((vm_offset_t)AddrR3), ((vm_offset_t)Ad
> drR3) + pMemToMap->cb);
> +        rc = vm_map_remove(pProcMap, AddrR3, AddrR3 + pMemToMap->cb);
>          AssertMsg(rc == KERN_SUCCESS, ("Deleting mapping failed\n"));
>      }
> +    else
> +        vm_object_deallocate(pMemToMapFreeBSD->pObject);
>  
>      return VERR_NO_MEMORY;
>  }
> @@ -855,49 +779,47 @@
>                  return NIL_RTHCPHYS;
>              }
>  
> -            vm_offset_t pb = (vm_offset_t)pMemFreeBSD->Core.pv + (iPage << P
> AGE_SHIFT);
> +            vm_offset_t pb = (vm_offset_t)pMemFreeBSD->Core.pv + ptoa(iPage)
> ;
>  
>              struct proc    *pProc     = (struct proc *)pMemFreeBSD->Core.u.L
> ock.R0Process;
>              struct vm_map  *pProcMap  = &pProc->p_vmspace->vm_map;
> -            pmap_t pPhysicalMap       = pProcMap->pmap;
> +            pmap_t pPhysicalMap       = vm_map_pmap(pProcMap);
>  
>              return pmap_extract(pPhysicalMap, pb);
>          }
>  
>          case RTR0MEMOBJTYPE_MAPPING:
>          {
> -            vm_offset_t pb = (vm_offset_t)pMemFreeBSD->Core.pv + (iPage << P
> AGE_SHIFT);
> +            vm_offset_t pb = (vm_offset_t)pMemFreeBSD->Core.pv + ptoa(iPage)
> ;
>  
>              if (pMemFreeBSD->Core.u.Mapping.R0Process != NIL_RTR0PROCESS)
>              {
>                  struct proc    *pProc     = (struct proc *)pMemFreeBSD->Core
> .u.Mapping.R0Process;
>                  struct vm_map  *pProcMap  = &pProc->p_vmspace->vm_map;
> -                pmap_t pPhysicalMap       = pProcMap->pmap;
> +                pmap_t pPhysicalMap       = vm_map_pmap(pProcMap);
>  
>                  return pmap_extract(pPhysicalMap, pb);
>              }
>              return vtophys(pb);
>          }
>  
> -        case RTR0MEMOBJTYPE_CONT:
> -            return pMemFreeBSD->Core.u.Cont.Phys + (iPage << PAGE_SHIFT);
> -
> -        case RTR0MEMOBJTYPE_PHYS:
> -            return pMemFreeBSD->Core.u.Phys.PhysBase + (iPage << PAGE_SHIFT)
> ;
> -
>          case RTR0MEMOBJTYPE_PAGE:
> -        case RTR0MEMOBJTYPE_PHYS_NC:
> -            return VM_PAGE_TO_PHYS(pMemFreeBSD->u.Phys.apPages[iPage]);
> -
> -#ifdef USE_KMEM_ALLOC_ATTR
>          case RTR0MEMOBJTYPE_LOW:
> +        case RTR0MEMOBJTYPE_PHYS_NC:
>          {
> -            vm_offset_t pb = (vm_offset_t)pMemFreeBSD->Core.pv + (iPage << P
> AGE_SHIFT);
> -            return vtophys(pb);
> +            RTHCPHYS addr;
> +            VM_OBJECT_LOCK(pMemFreeBSD->pObject);
> +            addr = VM_PAGE_TO_PHYS(vm_page_lookup(pMemFreeBSD->pObject, iPag
> e));
> +            VM_OBJECT_UNLOCK(pMemFreeBSD->pObject);
> +            return addr;
>          }
> -#else
> -        case RTR0MEMOBJTYPE_LOW:
> -#endif
> +
> +        case RTR0MEMOBJTYPE_PHYS:
> +            return pMemFreeBSD->Core.u.Cont.Phys + ptoa(iPage);
> +
> +        case RTR0MEMOBJTYPE_CONT:
> +            return pMemFreeBSD->Core.u.Phys.PhysBase + ptoa(iPage);
> +
>          case RTR0MEMOBJTYPE_RES_VIRT:
>          default:
>              return NIL_RTHCPHYS;
> 
> --------------080309080104030002060603
> Content-Type: text/plain; charset="us-ascii"
> MIME-Version: 1.0
> Content-Transfer-Encoding: 7bit
> Content-Disposition: inline
> 
> _______________________________________________
> freebsd-emulation@freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-emulation
> To unsubscribe, send any mail to "freebsd-emulation-unsubscribe@freebsd.org"
> 
> --------------080309080104030002060603--
> 
> 





Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201202230101.q1N11fVJ006417>