AT91RM9200 and possibly other ARM targets are broken in 8-current after recent commit (more)

Hans Petter Selasky hselasky at c2i.net
Tue Apr 22 21:00:12 UTC 2008


Hi Mark,

Here is the modified and compiled code:

#define USBD_P2U POINTER_TO_UNSIGNED

static void
dumppv(vm_offset_t kva)
{
        struct pv_entry *pv;
        pd_entry_t *pde;
        pt_entry_t *pte;
        vm_paddr_t pa;
        struct vm_page *pg;

        printf("dumping 0x%08x ", kva);

        vm_page_lock_queues();          /* XXX paranoid XXX */
                /* get the physical address */
        pa = pmap_kextract(kva);
        if (pa == 0) {
                printf("dumppv: 0x%08x no mapping\n", kva);
                vm_page_unlock_queues();
                return;
        }
                /* find the vm_page for physical address */
        pg = PHYS_TO_VM_PAGE(pa);
        if (pg == NULL) {
                printf("dumppv: 0x%08x 0x%08x no vm_page\n", kva, pa);
                vm_page_unlock_queues();
                return;
        }

                /* dump the vm_page attributes */
        printf("dumppv attrs: 0x%08x\n", pg->md.pvh_attrs);

                /* run through all those that share the page */
        TAILQ_FOREACH(pv, &(pg->md.pv_list), pv_list) {
                        /* indicate kernel or user mapping */
                if (pv->pv_pmap == pmap_kernel())
                        printf  ("dumppv kpv: ");
                else
                        printf  ("dumppv upv: ");
                        /* print entry */
                printf("0x%08x 0x%08x 0x%08x ", USBD_P2U(pv->pv_pmap), pv->pv_va, pv->pv_flags);
                        /* print the PDE or PTE which will hold caching */
                if (pmap_get_pde_pte(pv->pv_pmap, pv->pv_va, &pde, &pte)) {
                        if (pmap_pde_section(pde))
                                printf("sec: 0x%08x", *pde);
                        else
                                printf("pte: 0x%08x 0x%08x", *pde, *pte);
                }
                printf("\n");
        }
        vm_page_unlock_queues();
        return;
}

This is what I get:

usbd_pc_alloc_mem:
dumping 0xcc009500 dumppv attrs: 0x00000000
usbd_pc_alloc_mem:
dumping 0xcc00a480 dumppv attrs: 0x00000000
usbd_pc_alloc_mem:
dumping 0xcc00b400 dumppv attrs: 0x00000000
usbd_pc_alloc_mem:
dumping 0xcc00c380 dumppv attrs: 0x00000000
usbd_pc_alloc_mem:
dumping 0xcc00d300 dumppv attrs: 0x00000000
usbd_pc_alloc_mem:
dumping 0xcc00e280 dumppv attrs: 0x00000000
usbd_pc_alloc_mem:
dumping 0xcc00f200 dumppv attrs: 0x00000000
usbd_pc_alloc_mem:
dumping 0xcc010180 dumppv attrs: 0x00000000
usbd_pc_alloc_mem:
dumping 0xcc011100 dumppv attrs: 0x00000000
usbd_pc_alloc_mem:
dumping 0xcc012080 dumppv attrs: 0x00000000
usbd_pc_alloc_mem:
dumping 0xcc013000 dumppv attrs: 0x00000000
usbd_pc_alloc_mem:
dumping 0xcc014e80 dumppv attrs: 0x00000000
usbd_pc_alloc_mem:
dumping 0xcc015e00 dumppv attrs: 0x00000000
usbd_pc_alloc_mem:
dumping 0xcc016d80 dumppv attrs: 0x00000000
usbd_pc_load_mem:
dumping 0xc1544150 dumppv attrs: 0x00000000
usbd_pc_load_mem:
dumping 0xc1544148 dumppv attrs: 0x00000000
usbd_pc_load_mem:
dumping 0xc1544150 dumppv attrs: 0x00000000

Does it make any sense to you? Looks like the page structure is not initialised.

--HPS


On Tuesday 22 April 2008, Mark Tinguely wrote:
> >  Line 2730:
> >
> >          /* allocate memory */
> >          if (bus_dmamem_alloc(
> >              utag->tag, &ptr, (BUS_DMA_WAITOK | BUS_DMA_COHERENT), &map))
> > { goto error;
> >          }
> >
> >  > I *think* this new address lives in DMA S/G lists and should not be
> >  > mapped into an address space except to temporarily to copy data
> >  > in/out. I will assume this assumption is incorrect and look through
> >  > the pmap code all over again.
> >
> >  Is there a function I can call that will tell if the memory I get is in
> > cache enabled memory or not ?
> >
> >  If there are any prints you want me to add in the kernel code I can
> > easily do that within short time.
>
> /* Assuming the calling VA is mapped into the KVM  - put into arm/pmap.c
>  *
>  * kva is the kernel virtual address of the page to test.
>  *
>  * pvh_attrs/pv_flags are listed in include/pmap.h
>  * the PDE/PTE will have cache information too.
>  *
>  */
> void
> dumppv(vm_offset_t kva)
> {
>         struct pv_entry *pv;
> 	pd_entry_t *pde;
> 	pt_entry_t *pte;
> 	vm_paddr_t pa;
> 	struct vm_page pg;
>
> 	vm_page_lock_queues();		/* XXX paranoid XXX */
> 		/* get the physical address */
> 	pa = pmap_kextract(kva);
> 	if (pa == 0) {
> 		printf("dumppv: 0x%08x no mapping\n", kva);
> 		vm_page_unlock_queues();
> 		return;
> 	}
> 		/* find the vm_page for physical address */
> 	pg = PHYS_TO_VM_PAGE(pa);
> 	if (pg == NULL) {
> 		printf("dumppv: 0x%08x 0x%08x no vm_page\n", kva, pa);
> 		vm_page_unlock_queues();
> 		return;
> 	}
>
> 		/* dump the vm_page attributes */
>         printf("dumppv attrs: 0x%08x\n", pg->md.pvh_attrs);
>
> 		/* run through all those that share the page */
>         TAILQ_FOREACH(pv, pg->md.pv_list, pv_list) {
> 			/* indicate kernel or user mapping */
> 		if (pv->pv_pmap == pmap_kernel())
> 			printf  ("dumppv kpv: ");
> 		else
> 			printf  ("dumppv upv: ");
> 			/* print entry */
>                 printf("0x%08x 0x%08x 0x%08x ", pv->pv_pmap, pv->pv_va,
> pv->pv_flags); /* print the PDE or PTE which will hold caching */
> 		if (pmap_get_pde_pte(pv->pv_pmap, pv->pv_va, &pde, &pte)) {
> 			if (pmap_pde_section(pde))
> 				printf("sec: 0x%08x", *pde);
> 			else
> 				printf("pte: 0x%08x 0x%08x", *pde, *pte);
>         	}
> 		printf("\n");
>         }
> 	vm_page_unlock_queues();
> }
>
> Warning Will Rogers ....  This is crude attempt using existing routines.
> Untested, Uncompiled - do not use in a routine that already locked the
> the pmap and vm_page.
>
> >  I think what has happend is that when the USB code is reading back the
> > OHCI transfer descriptors after that the transfer has completed we are
> > still looking at the old length field which then tells the USB stack that
> > the transfer is short. It is not "SET_CONFIG" that fails, but probably
> > reading the USB descriptors.
> >
> >  >  2) set configuration has a USBD_ERR_SHORT_XFER error.
> >  >
> >  > I don't know if turning on USB debug printing will give more clues.
> >
> >  If I turn on full debugging the problem disappears, which I think is
> > because the CPU cache is used up due to the excessive prints which the
> > following debug level settings cause:
> >
> >  sysctl hw.usb.ohci.debug=16
> >  sysctl hw.usb.debug=15
>
> Strange that the debug cause things to work. filling the cache does not not
> make sense to me. adding another process map to mix would. Does it start
> working with the debug levels are very small (like 1)?
>
> >  > I will look through the pmap code and see if I can chase up something.
> >
> >  I see one problem:
> >
> >  "malloc" is used by BUS-DMA to allocate DMA memory having a size less
> > than PAGE_SIZE. What happens when you have multiple DMA allocations in
> > the same PAGE and you then turn on/off the CPU caching on a per
> > allocation/free basis ?
> >
> >  Mark, I really appreciate that you look into this.
>
> Walking through the pmap stuff will take a long, long time (days).
> I guess I need to chase down how add a COHERENT mapping.
>
> Maybe the dumppv() will find something and not crash on you.
>
> --Mark Tinguely




More information about the freebsd-arm mailing list