On Tuesday, 23 May 2023 17:32:16 CEST Paul Boddie wrote:
> 
> But the DMA domain is still not found when assigning the space. I did wonder
> whether I might need to create a device to hold the DMA domain resource,
> but my attempt to implement this failed:
> 
> for resource in hw:resources() do
>   print("resource name=" .. resource:id())
>   if resource:id() == 1145130308 then
>     device = Io.Vi.System_bus()
>     device:add_resource(resource)
>     bus:add_child(device)
>   end
> end

Well, this proved to be the wrong track, as I imagined, but the following 
helped me onto the right track:

> Here, Io crashes...
> 
> IO      | L4Re[rm]: unhandled read page fault at 0x31 pc=0x102aba0
> IO      | L4Re: rom/io: Unhandled exception: PC=0x102aba0 PFA=0x30
> LdrFlgs=0x0
> 
> ...which is the following line in Dma_domain::add_to_group:
> 
>   if (!_v_domain && !g->_set)
> 
> I imagine that I am making this harder than it should be, though.

I already suspected that I needed a DMA domain inside an actual device, as 
opposed to the system bus, so that the code in Io would be able to find the 
resource. Obviously, the attempt above did not achieve this, indicating that 
there is more involved in the initialisation than simply "copying" a resource 
into a suitable location.

I then discovered that the Hw_device_DF_dma_supported property flag would 
allow a search using the vbus to yield a DMA domain resource with a valid 
identifier and for Io to find this by itself when assigning a DMA space to a 
domain. Although the SoC I am using has no notion of device-specific DMA 
domains, conceptually it makes sense to associate DMA with the peripheral I am 
trying to configure, so I introduced the following to my LCD controller 
device:

  LCD = Hw.Device(function()
    Property.hid = "jz4780-lcd";
    -- compatible = {"mips,jz4780-lcd"};
    Resource.regs = Res.mmio(0x13050000, 0x130517ff);
    Resource.irq = Res.irq({31, 31}, Io.Resource.Irq_type_level_high);
    Property.flags = Io.Hw_device_DF_dma_supported;
  end);

However, one counterintuitive aspect of assigning a DMA space involves the DMA 
domain identifier. As suggested by the nvme-driver code, although a DMA domain 
has a resource identifier of 0x44414d44 ("DMAD"), the assign operation 
actually wants the start address associated with the resource. This turns out 
to be zero in my case.

I still wasn't completely done, however. The map operation was failing with 
what tends to be described in the error messages as a "bad, unknown runtime 
error". Eventually, I tracked this down to the _get_ds function found in pkg/
l4re-core/moe/server/src/dma_space.cc which has some L4Re::chksys invocations. 
These invocations are quite unhelpful, obscuring the actual error, which was 
due to the received DMA space capability not having write permission.

In fact, I see that the nvme-driver code for invoking the operation uses the 
make_cap_rw method on a L4::Ipc::Cap instance, whereas those using the C 
library have to set the rights bits the old-fashioned way. I don't think I 
have needed to do this for anything before, so this caught me out.

In any case, with all this tidied up, I finally got hold of those physical 
addresses again, and thankfully the rest of my existing code still worked. I 
do wonder about where I might put that Hw_device_DF_dma_supported property, 
but I imagine that even if it were replicated on all appropriate devices, it 
would not matter which device such a global domain would be acquired from.

Anyway, I hope this counts as some kind of feedback about how these frameworks 
are experienced by outsiders such as myself. I will now aim to pick up where I 
left off a few weeks ago...

Thanks for the help given!

Paul



_______________________________________________
l4-hackers mailing list
l4-hackers@os.inf.tu-dresden.de
https://os.inf.tu-dresden.de/mailman/listinfo/l4-hackers

Reply via email to