Hi
I am working on getting the RPCEmu (RiscPC emulator) to run on Genode. I have a some problems , and will list some of them,
1) Graphics doesn't update without exposing it. I have used testnit as a base and uses blit function to push out pixels to screen. How can I make it redraw? 2) When trying ro use the JIT version Genode complains about non executable memory. Any idea what that might be?
I use base hw on x86_64.
Screenshot: https://twitter.com/QtARM/status/1316535724959727620 (real hw) Best regards
Michael Grunditz
Hi Michael,
I am working on getting the RPCEmu (RiscPC emulator) to run on Genode.
that is super cool! I was a proud owner of a RiscPC 600 once and loved RiscOS. So your screenshot evokes fond memories. ;-)
- Graphics doesn't update without exposing it. I have used testnit as
a base and uses blit function to push out pixels to screen. How can I make it redraw?
You will have to call 'Framebuffer::Session::refresh' to inform the GUI server about the changed portions of your virtual framebuffer.
- When trying ro use the JIT version Genode complains about non
executable memory. Any idea what that might be?
By default, data stored in RAM is not executable on Genode. For the instructions generated by the JIT compiler, however, the underlying memory must be mapped as executable. In cases like this, you can explicitly request executable memory mapping using 'mmap' for allocating an anonymous chunk of memory by passing both the MAP_ANONYMOUS and PROT_EXEC flags as argument.
Should you not use the libc but the raw Genode API, you can create executable mappings via 'env.rm().attach_executable' [1].
[1] https://github.com/genodelabs/genode/blob/master/repos/base/include/region_m...
Cheers Norman
On Thu, 15 Oct 2020 at 13:33, Norman Feske norman.feske@genode-labs.com wrote:
You will have to call 'Framebuffer::Session::refresh' to inform the GUI server about the changed portions of your virtual framebuffer.
- When trying ro use the JIT version Genode complains about non
executable memory. Any idea what that might be?
By default, data stored in RAM is not executable on Genode. For the instructions generated by the JIT compiler, however, the underlying memory must be mapped as executable. In cases like this, you can explicitly request executable memory mapping using 'mmap' for allocating an anonymous chunk of memory by passing both the MAP_ANONYMOUS and PROT_EXEC flags as argument.
When I try map to allocate memory by using fd=-1 , I get a error (no plugin error)
Should you not use the libc but the raw Genode API, you can create executable mappings via 'env.rm().attach_executable' [1].
Might be possible , my main file is using Genode api. So a call to that might do the trick,
[1] https://github.com/genodelabs/genode/blob/master/repos/base/include/region_m...
Cheers Norman
-- Dr.-Ing. Norman Feske Genode Labs
https://www.genode-labs.com · https://genode.org
Genode Labs GmbH · Amtsgericht Dresden · HRB 28424 · Sitz Dresden Geschäftsführer: Dr.-Ing. Norman Feske, Christian Helmuth
Genode users mailing list users@lists.genode.org https://lists.genode.org/listinfo/users
On Thu, 15 Oct 2020 at 14:13, Michael Grunditz michael.grunditz@gmail.com wrote:
On Thu, 15 Oct 2020 at 13:33, Norman Feske norman.feske@genode-labs.com wrote:
You will have to call 'Framebuffer::Session::refresh' to inform the GUI server about the changed portions of your virtual framebuffer.
Done!
- When trying ro use the JIT version Genode complains about non
executable memory. Any idea what that might be?
By default, data stored in RAM is not executable on Genode. For the instructions generated by the JIT compiler, however, the underlying memory must be mapped as executable. In cases like this, you can explicitly request executable memory mapping using 'mmap' for allocating an anonymous chunk of memory by passing both the MAP_ANONYMOUS and PROT_EXEC flags as argument.
When I try map to allocate memory by using fd=-1 , I get a error (no plugin error)
Should you not use the libc but the raw Genode API, you can create executable mappings via 'env.rm().attach_executable' [1].
Might be possible , my main file is using Genode api. So a call to that might do the trick,
Or not. I don't know about Dataspace_capabilities. What is it and how can I get it?
New tweet with bootup poweron to desktop. Quite fast https://twitter.com/QtARM/status/1316738380902862848
Michael
Hi Michael,
Or not. I don't know about Dataspace_capabilities. What is it and how can I get it?
here is a small example of allocating a RAM dataspace and attaching it to the local address space:
Dataspace_capability ds = env.pd().alloc(4096);
void *local_ptr = env.rm().attach(ds, 0, /* map entire dataspace */ 0, /* no offset within dataspace */ false, /* ignore local addr */ (void *)0, /* local addr */ true, /* executable */ true /* writeable */);
log("RAM dataspace locally mapped at ", local_ptr);
For the underlying concepts, let me refer you to the Genode Foundations book:
https://genode.org/documentation/genode-foundations-20-05.pdf https://genode.org/documentation/genode-foundations/20.05/index.html
Cheers Norman
On Thu, 15 Oct 2020 at 17:24, Norman Feske norman.feske@genode-labs.com wrote:
Hi Michael,
Or not. I don't know about Dataspace_capabilities. What is it and how can I get it?
here is a small example of allocating a RAM dataspace and attaching it to the local address space:
Dataspace_capability ds = env.pd().alloc(4096);
void *local_ptr = env.rm().attach(ds, 0, /* map entire dataspace */ 0, /* no offset within dataspace */ false, /* ignore local addr */ (void *)0, /* local addr */ true, /* executable */ true /* writeable */);
log("RAM dataspace locally mapped at ", local_ptr);
Thanks for the example , however .. I didn't say at first , the engine already has a area and uses mprotect on it. So now passing local address -> region conflict error.
For the underlying concepts, let me refer you to the Genode Foundations book:
https://genode.org/documentation/genode-foundations-20-05.pdf https://genode.org/documentation/genode-foundations/20.05/index.html
I have been reading that book , and the header files.
Hi Michael,
Thanks for the example , however .. I didn't say at first , the engine already has a area and uses mprotect on it. So now passing local address -> region conflict error.
Genode does not allow the changing of mapping attributes after the fact. Hence, mprotect cannot work. I'm afraid that there is no way around modifying the engine with respect to the allocation of the buffer used for the JIT instructions.
Since you are using the libc, the cleanest way forward would be the mmap (PROT_EXEC) approach. You are right that (our current version of) mmap does not support the passing of -1 as fd. But passing a valid file descriptor is supposed to work, for example:
int const zero_fd = open("/dev/zero", O_RDWR);
void *ptr = mmap((void *)-1, 1024*512, PROT_EXEC, MAP_ANONYMOUS, zero_fd, 0);
close(zero_fd);
printf("mmap returned ptr=%p\n", ptr);
Cheers Norman
On Thu, 15 Oct 2020 at 22:02, Norman Feske norman.feske@genode-labs.com wrote:
Since you are using the libc, the cleanest way forward would be the mmap (PROT_EXEC) approach. You are right that (our current version of) mmap does not support the passing of -1 as fd. But passing a valid file descriptor is supposed to work, for example:
int const zero_fd = open("/dev/zero", O_RDWR);
void *ptr = mmap((void *)-1, 1024*512, PROT_EXEC, MAP_ANONYMOUS, zero_fd, 0);
Not related to Genode , but my main issue is that the instruction table *was* a static 2d array.. Hard to change base address of that one! So I have now converted the whole thing to use a pointer , which is allocated using the Genode API. It doesn't work, getting exec faults from ram. But I will get there.
Just one more related question. Can exec fault reported by Genode mean a invalid instruction or is it just that it can't exec it?
Michael
Hi Michael,
So I have now converted the whole thing to use a pointer , which is allocated using the Genode API. It doesn't work, getting exec faults from ram. But I will get there.
Just one more related question. Can exec fault reported by Genode mean a invalid instruction or is it just that it can't exec it?
It is hard to tell remotely. Such problems are best debugged by running Genode on Linux where GDB is readily available. Assuming that your port of RPCEmu works fine on Genode/Linux, you may find the following article useful:
https://genodians.org/ssumpf/2019-04-26-java-gdb
Cheers Norman
I am very happy to tell you that JIT is now working in Genode! The thing that puzzles me now , is that framebuffer refresh stoped working. It do sort of work , and I am refreshing the whole fb. This will change to letting the emulator decide what to refresh and when.
Michael
In message <CAAqgp_Rb+2jA2p8mxogEJPCNyZqC9Xi-Uxmu=d0O1ZJxT2f3eQ@mail.g mail.com> Michael Grunditz michael.grunditz@gmail.com wrote:
I am very happy to tell you that JIT is now working in Genode!
The thing that puzzles me now , is that framebuffer refresh stoped working.
Sorry! late night hacking, it works now.. had it set to fb coordinates , rather then local!
A little question about clocks and timers: My timer irq is running every 200000ns. In qemu it works perfectly well, but on real hardware it runs ok for 3-4s than pause for some time and back again. If this was just on my quite fast PC , then ok. But the same problem can also be seen on my not so fast laptop. The laptop is around the speed of Qemu kvm on the big pc.
I am using libc clocking to measure time. Should I use a Genode native function instead?
Hello Michael,
On Tue, Oct 20, 2020 at 22:19:28 CEST, Michael Grunditz wrote:
A little question about clocks and timers: My timer irq is running every 200000ns. In qemu it works perfectly well, but on real hardware it runs ok for 3-4s than pause for some time and back again. If this was just on my quite fast PC , then ok. But the same problem can also be seen on my not so fast laptop. The laptop is around the speed of Qemu kvm on the big pc.
This behavior is strange and unexpected. Could you isolate the issue in a small test program and run script?
Also, you may investigate yourself by running the "top" tool in your scenario and see if any component is seizing the CPU while iot should be blocked. Please have a look at [1] for an example integration.
I am using libc clocking to measure time. Should I use a Genode native function instead?
The libc functions should be fine as long as the main thread does not spin for long periods. The implementation of I/O handling (including timing) in the libc depends on the responsiveness of the main thread/entrypoint.
[1] https://github.com/genodelabs/genode/blob/91f82816189c1aad5d03168cc86c4b4946...
Regards