Hello!
I have USB working: [init -> drivers -> usb_hid_drv] dev_info: input: USB HID v1.00 Mouse [HID 04b4:0060] on usb-usbbus-/input0 [init -> drivers -> usb_hid_drv] dev_info: input: USB HID v1.00 Device [HID 04b4:0060] on usb-usbbus-/input1 Kernel: MMU-fault not handled ESR=0x92000061 Kernel: init -> drivers -> gui_fb -> ep raised unhandled MMU fault ip=0x1009bb4 fault-addr=0x113d76ac type=unknown
But as you can see , if I move the mouse pointer I get that ESR after the pointer moves a small amount of pixels. and graphics stops.
I have no idea why. The framebuffer, which is defined by u-boot, is above the specified RAM. I get the expected graphics , so it works that far. Two things can crash it. 1) The Mouse 2) Scout.
I really want to add my own framebuffer using genode allocated ram.. it might help. But I don't know how.
Please advise,
Michael
On Thu, 12 Jan 2023 at 03:19, Michael Grunditz michael.grunditz@gmail.com wrote:
Hello!
I have USB working: [init -> drivers -> usb_hid_drv] dev_info: input: USB HID v1.00 Mouse [HID 04b4:0060] on usb-usbbus-/input0 [init -> drivers -> usb_hid_drv] dev_info: input: USB HID v1.00 Device [HID 04b4:0060] on usb-usbbus-/input1 Kernel: MMU-fault not handled ESR=0x92000061 Kernel: init -> drivers -> gui_fb -> ep raised unhandled MMU fault ip=0x1009bb4 fault-addr=0x113d76ac type=unknown
But as you can see , if I move the mouse pointer I get that ESR after the pointer moves a small amount of pixels. and graphics stops.
I have no idea why. The framebuffer, which is defined by u-boot, is above the specified RAM. I get the expected graphics , so it works that far. Two things can crash it.
- The Mouse
- Scout.
I really want to add my own framebuffer using genode allocated ram.. it might help. But I don't know how.
Some more info. The crash is in the copy to fb ... _captured_screen.apply_to_surface(surface); It fails right away when moving the mouse. I have checked the size and it is always the same and the fault address is half way in (~ about where the mouse pointer is). I don't understand. The driver samples from screen and writes to fb. It is done with a timer , so I can't see how it can be affected by changes in screen. Another thing is that it might get interrupted by the usb interrupt, but it seems quite unlikely. ESR is still unaligned write. I can provoke it directly with a odd size.
Michael
Hi Michael,
Kernel: MMU-fault not handled ESR=0x92000061 Kernel: init -> drivers -> gui_fb -> ep raised unhandled MMU fault ip=0x1009bb4 fault-addr=0x113d76ac type=unknown
But as you can see , if I move the mouse pointer I get that ESR after the pointer moves a small amount of pixels. and graphics stops.
I am bit confused by the role of the gui_fb component in your scenario. Since we introduced the 'Capture' session in 20.08 [1], this component (and more generally the 'Framebuffer' session interface) should no longer be needed for most GUI scenarios. Only in scenarios where nitpicker is used in a nested way (Sculpt's Leitzentrale, demo.run), the gui_fb component serves a purpose nowadays.
A modern framebuffer driver should be a mere client of the 'Capture' service provided by the nitpicker GUI server.
BTW, the official way to obtain a contiguous RAM buffer (for the use as framebuffer) is platform driver. For a 'Dma_buffer' object, you can request the 'dma_addr' [2] to be poked into the graphics device register for the framebuffer base address.
[1] https://genode.org/documentation/release-notes/20.08#The_GUI_stack__restacke... [2] https://github.com/genodelabs/genode/blob/master/repos/os/include/platform_s...
Some more info. The crash is in the copy to fb ... _captured_screen.apply_to_surface(surface); It fails right away when moving the mouse. I have checked the size and it is always the same and the fault address is half way in (~ about where the mouse pointer is). I don't understand. The driver samples from screen and writes to fb. It is done with a timer , so I can't see how it can be affected by changes in screen. Another thing is that it might get interrupted by the usb interrupt, but it seems quite unlikely. ESR is still unaligned write. I can provoke it directly with a odd size.
Generally speaking, while blitting 32-bit pixels, pixels may be read/written at 32-bit boundaries. When moving the mouse cursor to an uneven position, the 16x16 pixels of the mouse cursor are copied from/to a 32-bit aligned (not 64-bit aligned) position.
The symptom reminds me of [3] (allowing unaligned memory accesses in user space), but why would that configuration be ineffective in your case? Maybe the fault IP refers to some special (neon?) instruction with tighter constraints? Have you had a look at the faulting instruction?
[3] https://github.com/genodelabs/genode/issues/3370
Cheers Norman
On Thu, 12 Jan 2023 at 18:08, Norman Feske norman.feske@genode-labs.com wrote:
Hi Michael,
Hi , and thanks a lot for answer.
Kernel: MMU-fault not handled ESR=0x92000061 Kernel: init -> drivers -> gui_fb -> ep raised unhandled MMU fault ip=0x1009bb4 fault-addr=0x113d76ac type=unknown
But as you can see , if I move the mouse pointer I get that ESR after the pointer moves a small amount of pixels. and graphics stops.
I am bit confused by the role of the gui_fb component in your scenario. Since we introduced the 'Capture' session in 20.08 [1], this component (and more generally the 'Framebuffer' session interface) should no longer be needed for most GUI scenarios. Only in scenarios where nitpicker is used in a nested way (Sculpt's Leitzentrale, demo.run), the gui_fb component serves a purpose nowadays.
Sorry it is just a name that managed to creep into my drivers.config. Could be any name. The component gui_fb is not part of the build.
A modern framebuffer driver should be a mere client of the 'Capture' service provided by the nitpicker GUI server.
I am using the "boot" driver.
BTW, the official way to obtain a contiguous RAM buffer (for the use as framebuffer) is platform driver. For a 'Dma_buffer' object, you can request the 'dma_addr' [2] to be poked into the graphics device register for the framebuffer base address.
[1] https://genode.org/documentation/release-notes/20.08#The_GUI_stack__restacke... [2] https://github.com/genodelabs/genode/blob/master/repos/os/include/platform_s...
Will try this after every other option :-) I doubt it will solve alignment fault.
Some more info. The crash is in the copy to fb ... _captured_screen.apply_to_surface(surface); It fails right away when moving the mouse. I have checked the size and it is always the same and the fault address is half way in (~ about where the mouse pointer is). I don't understand. The driver samples from screen and writes to fb. It is done with a timer , so I can't see how it can be affected by changes in screen. Another thing is that it might get interrupted by the usb interrupt, but it seems quite unlikely. ESR is still unaligned write. I can provoke it directly with a odd size.
Generally speaking, while blitting 32-bit pixels, pixels may be read/written at 32-bit boundaries. When moving the mouse cursor to an uneven position, the 16x16 pixels of the mouse cursor are copied from/to a 32-bit aligned (not 64-bit aligned) position.
Well ,shouldn't be a problem.
The symptom reminds me of [3] (allowing unaligned memory accesses in user space), but why would that configuration be ineffective in your case?
I doubt that it is related. The "A" bit is set to '0'.
Maybe the fault IP refers to some special (neon?) instruction with tighter constraints? Have you had a look at the faulting instruction?
Sorry , for being uneducated, but is "ip" an instruction (doesn't make sense , isn't an opcode) or is it an address? If address, where can I look it up?
Thanks , again. USB is currently a mess. I started from older imx8 driver which depends on u-boot to start. I use u-boot "usb start" before boot. But it works :-)
Michael
Update!
It is the surface clipping that generates the fault (as expected) commenting that out makes things work. I guess it is slower without clipping.
On Thu, 12 Jan 2023 at 21:32, Michael Grunditz michael.grunditz@gmail.com wrote:
Update!
It is the surface clipping that generates the fault (as expected) commenting that out makes things work. I guess it is slower without clipping.
The movie: https://twitter.com/QtARM/status/1613638001573396480
Kernel: MMU-fault not handled ESR=0x92000061 Kernel: init -> drivers -> gui_fb -> ep raised unhandled MMU fault ip=0x1009bb4 fault-addr=0x113d76ac type=unknown
Maybe the fault IP refers to some special (neon?) instruction with tighter constraints? Have you had a look at the faulting instruction?
Sorry , for being uneducated, but is "ip" an instruction (doesn't make sense , isn't an opcode) or is it an address? If address, where can I look it up?
I see you've already found/fixed the issue (congrats on your RiscOS endeavour, always had a sweet spot for sixteen/thirty-two bits OS'es since the 1990s), but in case you still want the info: I asked the same a few years back and was told about the "(arch-name-here)-addr2line" gcc Genode toolchain utility. So when a crash occurs, I substract the driver's base address, e.g.
$ pc
0x1009bb4 - 0x1001000
... /bin/pc outputs the delta here ...
And then I feed it to addr2line, with the path to the driver's "debug" (not-stripped-of-symbols) binary, and get the function name and file and line number. Very convenient once you get the hang of it:
$ ....addr2line .. -e ... /path/to/binary .. ..type delta here..
Cedric
On Fri, 13 Jan 2023 at 09:51, ttcoder@netcourrier.com wrote:
Kernel: MMU-fault not handled ESR=0x92000061 Kernel: init -> drivers -> gui_fb -> ep raised unhandled MMU fault ip=0x1009bb4 fault-addr=0x113d76ac type=unknown
Maybe the fault IP refers to some special (neon?) instruction with tighter constraints? Have you had a look at the faulting instruction?
Sorry , for being uneducated, but is "ip" an instruction (doesn't make sense , isn't an opcode) or is it an address? If address, where can I look it up?
I see you've already found/fixed the issue (congrats on your RiscOS endeavour, always had a sweet spot for sixteen/thirty-two bits OS'es since the 1990s),
Thanks , it is a giant project.. and there are a lot of things that I haven't a clue how I should do -:)
but in case you still want the info: I asked the same a few years back and was told about the "(arch-name-here)-addr2line" gcc Genode toolchain utility. So when a crash occurs, I substract the driver's base address, e.g.
$ pc
0x1009bb4 - 0x1001000
... /bin/pc outputs the delta here ...
I don't know how I get the base address. I have tried the addresses from bootlog and subtracted image base.
And then I feed it to addr2line, with the path to the driver's "debug" (not-stripped-of-symbols) binary, and get the function name and file and line number. Very convenient once you get the hang of it:
I only get ?0 from above
----------------------------
About the alignment fault: I wonder if the clip function could be modified to round up. I am going to try that. It is very slow without some clipping. But if someone has a better idea , please tell me.
Michael
Hi Michael,
BTW, the official way to obtain a contiguous RAM buffer (for the use as framebuffer) is platform driver. For a 'Dma_buffer' object, you can request the 'dma_addr' [2] to be poked into the graphics device register for the framebuffer base address.
Will try this after every other option :-) I doubt it will solve alignment fault.
here is my guess:
- The boot loader sets up the framebuffer in a known RAM area. - This framebuffer is mapped as uncached memory, similar one would map an memory-mapped I/O resource. - Unaligned memory accesses by the user land are allowed in principle, but - Unaligned memory accesses to uncached memory are always forbidden. - The blitting code assumes that unaligned accesses at 32-bit boundaries are fine. - Your boot-fb driver reuses the original framebuffer mapping, hence it inherits the way of how the framebuffer is originally mapped. Consequently, the blitting code issues unaligned bus accesses to uncached memory.
If this is the case, the use of a fresh allocated DMA buffer using the platform driver would indeed solve this issue because the blitting code would not touch uncached memory.
Should this work and you see caching artifacts on screen, you may need to explicitly call 'cache_clean_invalidate_data' to write back the pixel data to RAM after blitting.
Keeping my fingers crossed...
Cheers Norman
Hi again,
Kernel: MMU-fault not handled ESR=0x92000061 Kernel: init -> drivers -> gui_fb -> ep raised unhandled MMU fault ip=0x1009bb4 fault-addr=0x113d76ac type=unknown
[...]
Maybe the fault IP refers to some special (neon?) instruction with tighter constraints? Have you had a look at the faulting instruction?
Sorry , for being uneducated, but is "ip" an instruction (doesn't make sense , isn't an opcode) or is it an address? If address, where can I look it up?
just noticed that I left your question unanswered.
IP stands for "instruction pointer". It is printed in the page-fault message (in this case 'ip=0x1009bb4').
When I see such an address, I'm usually using objdump to look up the code around it, using the debug version of binary. In this case:
build/arm_v8a$ genode-aarch64-objdump -lSd debug/gui_fb | less
In less, I search for '1009bb4', where I can see both the source line numbers around the IP (scrolling back helps sometimes for heavily inlined code), and also the opcode of the instruction at the IP.
However, if my guess of the previous posting is correct, the particular instruction is probably innocent.
Thanks , again. USB is currently a mess. I started from older imx8 driver which depends on u-boot to start. I use u-boot "usb start" before boot. But it works :-)
Congratulations, it's a miracle! :)
Cheers Norman
On Fri, 13 Jan 2023 at 12:05, Norman Feske norman.feske@genode-labs.com wrote:
Hi again,
Kernel: MMU-fault not handled ESR=0x92000061 Kernel: init -> drivers -> gui_fb -> ep raised unhandled MMU fault ip=0x1009bb4 fault-addr=0x113d76ac type=unknown
[...]
Maybe the fault IP refers to some special (neon?) instruction with tighter constraints? Have you had a look at the faulting instruction?
Sorry , for being uneducated, but is "ip" an instruction (doesn't make sense , isn't an opcode) or is it an address? If address, where can I look it up?
just noticed that I left your question unanswered.
IP stands for "instruction pointer". It is printed in the page-fault message (in this case 'ip=0x1009bb4').
When I see such an address, I'm usually using objdump to look up the code around it, using the debug version of binary. In this case:
build/arm_v8a$ genode-aarch64-objdump -lSd debug/gui_fb | less
In less, I search for '1009bb4', where I can see both the source line numbers around the IP (scrolling back helps sometimes for heavily inlined code), and also the opcode of the instruction at the IP.
However, if my guess of the previous posting is correct, the particular instruction is probably innocent.
Thanks , again. USB is currently a mess. I started from older imx8 driver which depends on u-boot to start. I use u-boot "usb start" before boot. But it works :-)
Congratulations, it's a miracle! :)
Thanks I am happy! I have worked with this for 9 days and 9 nights since the first serial output. I will try to devise a platform driver .. I think I already did this ( but not right now, things got bad for unknown reasons , so reverted ).
Michael
OK .. so for framebuffer I took the imx53 driver and modified it to rockchip.
From my understanding it does what I want. However, nothing happens. No
error or anything.
This is from my driver.config
<start name="platform_drv" caps="150" managing_system="yes"> <binary name="rk3588_platform_drv"/> <resource name="RAM" quantum="2M"/> <provides> <service name="Platform"/> </provides> <config> <policy label="gui_fb -> "> </policy> <policy label="usb_drv -> " info="yes"> <device name="usb_host_2"/> <device name="usb_phy_2"/> </policy>
</config> <route> <any-service> <parent/> </any-service> </route> </start>
<start name="gui_fb" caps="250"> <binary name="rk3588dma_fb_drv"/>
<resource name="RAM" quantum="40M"/> <!-- <provides> <service name="Framebuffer"/> </provides> --> <route> <service name="RM"> <parent/> </service> <service name="ROM" label="config"> <parent label="fb_drv.config"/> </service> <service name="ROM"> <parent/> </service> <service name="PD"> <parent/> </service> <service name="CPU"> <parent/> </service> <service name="LOG"> <parent/> </service> <service name="Timer"> <parent/> </service> <service name="Capture"> <parent/> </service> <service name="IO_MEM"> <parent/> </service> <service name="Platform"> <child name="platform_drv"/> </service> </route> </start>
On Fri, 13 Jan 2023 at 15:33, Michael Grunditz michael.grunditz@gmail.com wrote:
OK .. so for framebuffer I took the imx53 driver and modified it to rockchip. From my understanding it does what I want. However, nothing happens. No error or anything.
After some tinkering I get it to start .. now I just need to fix the actual write to video chip.
On Fri, 13 Jan 2023 at 16:51, Michael Grunditz michael.grunditz@gmail.com wrote:
On Fri, 13 Jan 2023 at 15:33, Michael Grunditz michael.grunditz@gmail.com wrote:
OK .. so for framebuffer I took the imx53 driver and modified it to rockchip. From my understanding it does what I want. However, nothing happens. No error or anything.
After some tinkering I get it to start .. now I just need to fix the actual write to video chip.
I have a display now and it is really fast! However clipping doesn't work as it should. It doesn't crash but it makes graphics a bit blurry if active, and so is mouse pointer. There is no speed gain with clipping.
With clipping: http://micken.se/pix/blurry_genode.jpg
I really appreciate how the io mem is handled. At first I did it the hacky c way .. but then I looked into ipu.h from mx53 driver. It basically does everything automatically .
I have a display now and it is really fast! However clipping doesn't work as it should. It doesn't crash but it makes graphics a bit blurry if active, and so is mouse pointer. There is no speed gain with clipping.
Solved! I had "CACHE" as attribute for the dma buffer. I changed to WRITE_COMBINED now, and it all works! Thanks to Norman who suggested cache problems.
Hello Michael,
On Wed, Jan 18, 2023 at 02:39:25PM +0100, Michael Grunditz wrote:
I have a display now and it is really fast! However clipping doesn't work as it should. It doesn't crash but it makes graphics a bit blurry if active, and so is mouse pointer. There is no speed gain with clipping.
Solved! I had "CACHE" as attribute for the dma buffer. I changed to WRITE_COMBINED now, and it all works! Thanks to Norman who suggested cache problems.
I'm pretty sure that Norman did not want you to set the DMA buffer to WRITE_COMBINED. Actually, this pseudo cache setting only exists for historical reasons, and will get removed as soon as possible from the public API. It is not really a 'cache feature'. It is not available on ARM, but is simply mapped to UNCACHED.
That means you have set your DMA buffers to UNCACHED, which obviously solves cache maintainance problems to the price of performance.
Regards Stefan
Genode users mailing list users@lists.genode.org https://lists.genode.org/listinfo/users
On Thu, 19 Jan 2023 at 11:31, Stefan Kalkowski stefan.kalkowski@genode-labs.com wrote:
I'm pretty sure that Norman did not want you to set the DMA buffer to WRITE_COMBINED. Actually, this pseudo cache setting only exists for historical reasons, and will get removed as soon as possible from the public API. It is not really a 'cache feature'. It is not available on ARM, but is simply mapped to UNCACHED.
That means you have set your DMA buffers to UNCACHED, which obviously solves cache maintainance problems to the price of performance.
OK. Norman suggested the functions in chaćhe.h (invalidate). However no matter how I tried I got artifacts on screen. The best I could get was a mouse pointer that leaves traces on the screen. I also notice that moving pointer x-wise worked .. only y-wise didn't.
Here is a bit of the code:
Genode::addr_t invalid = (rect.x1()+(rect.y1()*(size.w())))*sizeof(Pixel);
Genode::addr_t invalidz =(((rect.h()-1)*(size.w()))+(rect.w()-1))*sizeof(Pixel)) Genode::addr_t xxx = (Genode::addr_t)surface.addr(); cache_clean_invalidate_data(xxx+invalid,(invalidz));
I guess the calculations are wrong.., if so please suggest what I should change. I noticed that rect.w() and hight added 1 to them. I have tried with -1 as above and without modification.
Michael
Hi Michael,
I suspect that the arguments of the 'cache_clean_invalidate_data' function must be cache-line-aligned.
Here is a bit of the code:
Genode::addr_t invalid = (rect.x1()+(rect.y1()*(size.w())))*sizeof(Pixel);
Genode::addr_t invalidz =(((rect.h()-1)*(size.w()))+(rect.w()-1))*sizeof(Pixel)) Genode::addr_t xxx = (Genode::addr_t)surface.addr(); cache_clean_invalidate_data(xxx+invalid,(invalidz));
I guess the calculations are wrong.., if so please suggest what I should change. I noticed that rect.w() and hight added 1 to them. I have tried with -1 as above and without modification.
The -1s look wrong to me.
It might be easier to (1) calculate both the start offset and the end offset, then (2) truncate the start offset to the cache-line size, (3) round the end offset to the cache-line size, (4) calculate the size argument by subtracting the start from the end offset.
Regarding (2), when calculating the end offset via surface.w()*rect.y2() + rect.x2(), it will refer to the pixel at the lower-right corner of the dirty rectangle. You have to add 1 to this offset value, so that the subsequent subtraction yields the number of covered pixels, not the difference. E.g., think of a rectangle of only one pixel where p1 == p2. Here we want to flush the cache line around this pixel. The difference between the start and end offsets would be zero. But the number of covered pixels is one.
Cheers Norman
It might be easier to (1) calculate both the start offset and the end offset, then (2) truncate the start offset to the cache-line size, (3) round the end offset to the cache-line size, (4) calculate the size argument by subtracting the start from the end offset.
Regarding (2), when calculating the end offset via surface.w()*rect.y2()
- rect.x2(), it will refer to the pixel at the lower-right corner of the
dirty rectangle. You have to add 1 to this offset value, so that the subsequent subtraction yields the number of covered pixels, not the difference. E.g., think of a rectangle of only one pixel where p1 == p2. Here we want to flush the cache line around this pixel. The difference between the start and end offsets would be zero. But the number of covered pixels is one.
I have tried with 16,32 and 64. Same result. Movement y wise makes traces with mouse and bigger artifacts for windows. These sorts of things are really my weak spot.
int a=0; int r=0; a=64; Genode::addr_t invalid = (rect.x1()+(rect.y1()*(size.w())))*sizeof(Pixel); log("unaligned invalid: ",invalid);
invalid = invalid&~63;
Genode::addr_t endoffset = (1+(size.w()*rect.y2())+ rect.x2())*sizeof(Pixel); log("endoffset: ",endoffset);
r = endoffset%a; endoffset = r? endoffset + (a - r) : endoffset; log("invalid: ",invalid); log("invalidz: ",endoffset);
Genode::addr_t xxx = (Genode::addr_t)surface.addr();
cache_clean_invalidate_data(xxx+invalid,endoffset-invalid);
On Thu, 19 Jan 2023 at 17:04, Michael Grunditz michael.grunditz@gmail.com wrote:
It might be easier to (1) calculate both the start offset and the end offset, then (2) truncate the start offset to the cache-line size, (3) round the end offset to the cache-line size, (4) calculate the size argument by subtracting the start from the end offset.
Regarding (2), when calculating the end offset via surface.w()*rect.y2()
- rect.x2(), it will refer to the pixel at the lower-right corner of the
dirty rectangle. You have to add 1 to this offset value, so that the subsequent subtraction yields the number of covered pixels, not the difference. E.g., think of a rectangle of only one pixel where p1 == p2. Here we want to flush the cache line around this pixel. The difference between the start and end offsets would be zero. But the number of covered pixels is one.
I have tried with 16,32 and 64. Same result. Movement y wise makes traces with mouse and bigger artifacts for windows. These sorts of things are really my weak spot.
int a=0; int r=0; a=64; Genode::addr_t invalid = (rect.x1()+(rect.y1()*(size.w())))*sizeof(Pixel); log("unaligned invalid: ",invalid);
invalid = invalid&~63; Genode::addr_t endoffset =
(1+(size.w()*rect.y2())+ rect.x2())*sizeof(Pixel); log("endoffset: ",endoffset);
r = endoffset%a; endoffset = r? endoffset + (a - r) : endoffset; log("invalid: ",invalid); log("invalidz: ",endoffset); Genode::addr_t xxx = (Genode::addr_t)surface.addr(); cache_clean_invalidate_data(xxx+invalid,endoffset-invalid);
I have tested with full screen invalidate. It doesn't look pretty when moving a window.. but mouse pointer is ok. I have tried the below. Result: No traces if moving up , left or right. Down , traces. So the start address is wrong, probably.
cache_clean_invalidate_data(xxx+invalid,(size.count()*sizeof(Pixel))-invalid);
I have tested with full screen invalidate. It doesn't look pretty when moving a window.. but mouse pointer is ok. I have tried the below. Result: No traces if moving up , left or right. Down , traces. So the start address is wrong, probably.
cache_clean_invalidate_data(xxx+invalid,(size.count()*sizeof(Pixel))-invalid);
The imx8 doesn't use cached dma-buffer? Is there soeḿething (apart from imx53) that does use cached framebuffer?
/Michael
OK so stupid me.. Invalidation should be after Blit. I don't know where my brain is :-) Thanks for reading!