Obtaining and accessing device abstractions in L4Re

Paul Boddie paul at boddie.org.uk
Sat Jul 22 20:07:38 CEST 2017


On Thursday 6. July 2017 01.05.58 Paul Boddie wrote:
> On Wednesday 5. July 2017 22.53.35 Matthias Lange wrote:
> > 
> > That's not the whole story. Devices declared in e.g. hw_devices.io
> > describe physical (real) devices and their resources. The device handle
> > that you obtain via the Vbus API points to a virtual device and only
> > virtual devices can be assigned to a client's virtual bus. A virtual
> > device can wrap a physical one but e.g. in the case of GPIOs it can be
> > composed of individual (or ranges) of physical GPIO resources (= pins).

I've been trying to use this API and it seems rather confusing, both when 
trying to initialise the virtual devices, and when actually trying to access 
them.

First of all, it appears that any device based on Hw::Gpio_device will cause 
any corresponding virtual device to have its "hid" set to "GPIO". This makes 
the general examples on virtual bus configuration misleading because one might 
think that doing a match on the original hid will yield a device reference, 
but the l4vbus_get_device_by_hid function actually needs "GPIO" to produce the 
virtual device.

Obviously, this renaming or re-aliasing is also not helpful where there are 
many separate GPIO devices. I noticed that the OMAP hardware device 
definitions provide multiple GPIO devices under a common container, and this 
seemed like a reasonable way of partitioning the different "PORT" collections 
in the hardware I'm describing. Here is the related example from before:

[...]

>   GPIO = Hw.Device(function()
>     Property.hid = "JZ4740 GPIO";
> 
>     PORTA = Hw.Gpio_jz4740_chip(function()
>       Property.hid = "jz4740-gpio-PORTA";
>       Property.pins = 32;
>       compatible = {"mips,jz4740-gpio"};
>       Resource.regs = Res.mmio(0x10010000, 0x100100ff);
>       Resource.irq = Res.irq(28, Io.Resource.Irq_type_level_high);
>     end);
> 
>     ... -- PORTB, PORTC, PORTD
> 
>   end);

But having all such devices appear as "GPIO" in the virtual bus is rather 
inconvenient. If I knew what the intentions were for the API design in this 
regard, I might have a better idea of how it is supposed to be used, but there 
are no relevant, specific examples that I can find.

To get this working, then, I made a hid method in the virtual GPIO device that 
returns the actual device hid value. Then, the application is able to look up 
the device using what would be the expected hid value, not "GPIO".

Then there is the matter of resources. It seems, following the rather 
complicated framework code, that the virtual devices can be told how many pins 
they have by consulting the actual device. However, the resources associated 
with the actual device are not propagated to the virtual device. This is seen 
in the debugging output:

IO      | gpio: [N12_GLOBAL__N_112Virtual_sbusE]
IO      |   Resources: ==== start ====
IO      |   Resources: ===== end =====
IO      |   L4ICU: [N2Vi6Sw_icuE]
IO      |     Resources: ==== start ====
IO      |     Resources: ===== end =====
IO      |    jz4780-gpio-PORTF.PORTF
IO      |     Resources: ==== start ====
IO      |     Resources: ===== end =====
IO      |    jz4780-gpio-PORTD.PORTD
IO      |     Resources: ==== start ====
IO      |     Resources: ===== end =====

Here, the latter two devices do have resources defined in the actual hardware 
description. Consequently, if I understand it correctly, the matter of 
"enabling" the pins is not carried out because there are no resources 
associated with these virtual devices.

(I guess this extra layer of functionality around enabling pins is to provide 
some kind of additional benefit, but I don't see anything that tells me what 
that benefit is, nor anything that indicates why the actual devices can't just 
handle pin validity since they have to do that anyway.)

I have tried adding code to initialise the resources from each actual device 
when initialising the corresponding virtual device. But I get the impression 
that what I should really be doing is to use some kind of factory that 
produces the "right" kind of resource objects that know about the particular 
"resource space" that can enable the pins. It isn't obvious to me what I 
should be doing to achieve this. I would have thought just mentioning the 
things in the Lua script would do it, but I guess not.

Maybe the method of describing these devices in a virtual bus is different 
from the other ways of describing devices, but I haven't seen a single example 
that might give me some hints. Indeed, the mechanisms employed don't seem to 
be documented, either, which means that one is left to chase down the details 
in the source code. That ceases to be particularly rewarding after a few 
hours.

Is there any guidance out there about this particular framework? Does anyone 
even use it?

Paul




More information about the l4-hackers mailing list