unicorn icon indicating copy to clipboard operation
unicorn copied to clipboard

ARM and MMU

Open mickenx opened this issue 2 years ago • 16 comments

I have a issue with the MMU in ARM emulation. It is difficult to reproduce due to complexity. I have a kernel that uses armv7 styled mmu setup. When the kernel switches to logical addresses it seems that unicorn tries to access them as physical, which obvisually is a bad idea. The kernel is at 0xffCExxxx in logical mapping.

So is the MMU emulation supposed to work and in that case at which arm revision?

Here is the mmu activation: https://gitlab.riscosopen.org/RiscOS/Sources/Kernel/-/blob/master/s/HAL The section that leads up to MMU activation starts at line 382.

I have never seen this failure on real hardware. Earlier in startup it sets up the RAM region. I set that to the start and end defined with uc_mem_map. It is very unlikely that the kernel starts mapping/accessing pages outside of the specified RAM.

RISC OS doesn't need much hardware to start the kernel , something to write log to and the cpu/mmu. On real hardware the log is written to uart during debug phase, I don't have uart , but I redirect everything with a SWI handler. Needless to say , I also tried starting without that , but it still gives me the error below.

Output: PC is the logical mapping.

Failed on uc_emu_start() with error returned: Invalid memory fetch (UC_ERR_FETCH_UNMAPPED)

Emulation done. Below is the CPU context R0 = 0x0 R1 = 0x2533001 R8 = 0xfc02d32c PC = 0xfc02d32c LR = 0x30000

mickenx avatar Apr 27 '22 20:04 mickenx

I don’t think we can help too much without a reproduction script…

wtdcode avatar Apr 28 '22 07:04 wtdcode

A example, not exactly the same as in kernel (kernel is very complex context). Anyway It treats logical address as physical. I added printf to qemu cputlb: vaddr 0x100000 paddr 0x2ef00000 size 1048576 If it would do it the other way around , it would crash. PC is the same as vaddr. Same problem as in kernel but because , what I assume, is the logical address , actually fits in phys ram it doesn't crash.

I would be very happy if someone could do a testprogram that works with this code.

mmu.s.txt

mickenx avatar Apr 28 '22 10:04 mickenx

OK so here is a test c code to launch the mmu code: mmuhack_c.c.txt

mickenx avatar Apr 28 '22 11:04 mickenx

When I tried to enable the MMU in the past, I couldn't get any part of that to work - it only used the simple MMU mappings assigned from Unicorn's memory assignment, and didn't use the TLBs. So I gave up. If this is working now it might be interesting to use for me too.

gerph avatar Apr 28 '22 14:04 gerph

I have checked a bit more now. It seems like translation works up to returning the phys_pc. My testprogram (the asm file) didn't work as expected. I can see now that phys_pc is -1 (0xffffffff). With the kernel I get expected phys_pc addresses. So either it goes wrong after translation OR my memory config is wrong.

mickenx avatar Apr 28 '22 16:04 mickenx

When I tried to enable the MMU in the past, I couldn't get any part of that to work - it only used the simple MMU mappings assigned from Unicorn's memory assignment, and didn't use the TLBs. So I gave up. If this is working now it might be interesting to use for me too.

I tried a bit to make ARM MMU work when I developed Unicorn2. You might have another try?

wtdcode avatar Apr 28 '22 17:04 wtdcode

mmu.s.txt

The sample doesn't work since /home/micken/mmuhack,ffd is missing. Note even it's not missing, I can't help too much if you can't narrow down the problem to a few instructions.

wtdcode avatar May 06 '22 21:05 wtdcode

mmu.s.txt

The sample doesn't work since /home/micken/mmuhack,ffd is missing. Note even it's not missing, I can't help too much if you can't narrow down the problem to a few instructions.

That is just a example. You put your binary there, which you assembled from the asm code. I think the asm file is the minimum for turning mmu on. You just need to replace AREA with .text and END with .end to assemble with gnu assembler. It needs to be in pure binary for it to work. If you can't assemble the file I can see if a compiled version can be uploaded somewhere.

Also ... You don't need to dig into the assembly. You will see the problem immediately, it uses the virtual address directly to the mapped ram. If it used the physical (which is a high address) it would have crashed directly.

mickenx avatar May 07 '22 09:05 mickenx

mmu.s.txt

The sample doesn't work since /home/micken/mmuhack,ffd is missing. Note even it's not missing, I can't help too much if you can't narrow down the problem to a few instructions.

That is just a example. You put your binary there, which you assembled from the asm code. I think the asm file is the minimum for turning mmu on. You just need to replace AREA with .text and END with .end to assemble with gnu assembler. It needs to be in pure binary for it to work. If you can't assemble the file I can see if a compiled version can be uploaded somewhere.

Also ... You don't need to dig into the assembly. You will see the problem immediately, it uses the virtual address directly to the mapped ram. If it used the physical (which is a high address) it would have crashed directly.

So what's really relevant to reproduce? If the content of the files is irrelevant, why do you need it?

wtdcode avatar May 07 '22 11:05 wtdcode

So what's really relevant to reproduce? If the content of the files is irrelevant, why do you need it?

You need something to trigger the problem. Otherwise it is just my words, which is fine with me.

mickenx avatar May 07 '22 11:05 mickenx

So what's really relevant to reproduce? If the content of the files is irrelevant, why do you need it?

You need something to trigger the problem. Otherwise it is just my words, which is fine with me.

I can't understand what "trigger the problem" means. Again, without a proper reproduction, no one can understand what your problem is. Check #1608 to see what a reproduction looks like.

wtdcode avatar May 07 '22 11:05 wtdcode

OK. Can't do much more. If you want to test MMU functionality you need code for it. I have checked #1608 , and it is a very different issue. Since you don't want to test MMU translation , I close this issue.

mickenx avatar May 07 '22 12:05 mickenx

I'm not sure how this thread managed to get to the point where it's closed. It seems like there's a misunderstanding here between @mickenx and @wtdcode.

  • @wtdcode wants a reproduction case.
  • @mickenx produced source, but not something that's actually able to work as it stands.
  • @wtdcode asked for the actual binary
  • @mickenx said (paraphase) build it yourself.
  • @wtdcode said (paraphrase) that it wasn't a reproduction case (because the code wasn't present).
  • @mickenx said (paraphrase) that they couldn't do much more and claimed that wtdcode didn't want to test it.

The problem here is that a reproduction case is a complete set of minimal code that will reproduce the problem. That has not been supplied - as the assembler source is not assemblable and the C code refers to the file that is not supplied.

@mickenx said that they couldn't supply the built binary that was necessary. I don't understand why they couldn't supply it, but it should be buildable if you've got the right toolchain and know how (which presumably mickenx had but somehow couldn't use to build the binary nessary).

These are soluable problems.

I can create the necessary binaries and attach them here. The important missing binary file is (in my archive) mmu - assuming it has assembled properly. If it has not, this certainly goes back to @mickenx to supply the binary that they are reporting as a problem.

My reproduction case...

export.zip

  • I had to modify the .c file to make it reference the built local file.
  • I had to modify the .s file to make it use a MOV instruction - previously there was an ADRL in there which didn't work properly.
  • My filename is slightly different - I've just called the binary under test mmu.

How to use:

Type make test to build the code and run the test. This uses curl to invoke the build service to build the mmu file. @mickenx may be able to confirm whether that is correct or not. Then we build the C file with GCC and run the resulting code to test it.

When I run it I get this:

charles@phonewave ~/mmu-problems> make test
rm -f src.zip
zip src.zip .robuild.yml build,feb mmu_s
  adding: .robuild.yml (deflated 42%)
  adding: build,feb (deflated 37%)
  adding: mmu_s (deflated 62%)
# Build the sources
curl -F [email protected] -o mmu http://json.build.riscos.online/build/binary
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1603  100   120  100  1483     30    378  0:00:04  0:00:03  0:00:01   408
./mmuhack_c
Emulate ARM code
read: Undefined error: 0
make: *** [test] Segmentation fault: 11
  • The read: Undefined error: 0 appears to be a bug in the test code (it calls perror when nothing has been returned).
  • I'm pretty sure this is a different problem to what @mickenx was reporting, as they didn't say anything about the system crashing.

I've tested this with the dev branch at SHA 64050aafb197f6c6d95b33eeb8fa160069e50d7d. I may have built unicorn wrongly, or I may have incorrectly built this repro case - at this point I hand back to @mickenx if they want to actually have the problem looked at.

gerph avatar May 09 '22 09:05 gerph

I'm not sure how this thread managed to get to the point where it's closed. It seems like there's a misunderstanding here between @mickenx and @wtdcode.

  • @wtdcode wants a reproduction case.
  • @mickenx produced source, but not something that's actually able to work as it stands.
  • @wtdcode asked for the actual binary
  • @mickenx said (paraphase) build it yourself.
  • @wtdcode said (paraphrase) that it wasn't a reproduction case (because the code wasn't present).
  • @mickenx said (paraphrase) that they couldn't do much more and claimed that wtdcode didn't want to test it.

The problem here is that a reproduction case is a complete set of minimal code that will reproduce the problem. That has not been supplied - as the assembler source is not assemblable and the C code refers to the file that is not supplied.

@mickenx said that they couldn't supply the built binary that was necessary. I don't understand why they couldn't supply it, but it should be buildable if you've got the right toolchain and know how (which presumably mickenx had but somehow couldn't use to build the binary nessary).

These are soluable problems.

I can create the necessary binaries and attach them here. The important missing binary file is (in my archive) mmu - assuming it has assembled properly. If it has not, this certainly goes back to @mickenx to supply the binary that they are reporting as a problem.

My reproduction case...

export.zip

  • I had to modify the .c file to make it reference the built local file.
  • I had to modify the .s file to make it use a MOV instruction - previously there was an ADRL in there which didn't work properly.
  • My filename is slightly different - I've just called the binary under test mmu.

How to use:

Type make test to build the code and run the test. This uses curl to invoke the build service to build the mmu file. @mickenx may be able to confirm whether that is correct or not. Then we build the C file with GCC and run the resulting code to test it.

When I run it I get this:

charles@phonewave ~/mmu-problems> make test
rm -f src.zip
zip src.zip .robuild.yml build,feb mmu_s
  adding: .robuild.yml (deflated 42%)
  adding: build,feb (deflated 37%)
  adding: mmu_s (deflated 62%)
# Build the sources
curl -F [email protected] -o mmu http://json.build.riscos.online/build/binary
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1603  100   120  100  1483     30    378  0:00:04  0:00:03  0:00:01   408
./mmuhack_c
Emulate ARM code
read: Undefined error: 0
make: *** [test] Segmentation fault: 11
  • The read: Undefined error: 0 appears to be a bug in the test code (it calls perror when nothing has been returned).
  • I'm pretty sure this is a different problem to what @mickenx was reporting, as they didn't say anything about the system crashing.

I've tested this with the dev branch at SHA 64050aafb197f6c6d95b33eeb8fa160069e50d7d. I may have built unicorn wrongly, or I may have incorrectly built this repro case - at this point I hand back to @mickenx if they want to actually have the problem looked at.

I appreciate your patience in illustrating this. If you still have problems about MMU, you might send a reproduction here, or the issue will remain closed.

wtdcode avatar May 09 '22 14:05 wtdcode

I did. See the export.zip in the last message.

gerph avatar May 09 '22 15:05 gerph

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 15 days.

github-actions[bot] avatar Jul 18 '22 05:07 github-actions[bot]

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 15 days.

github-actions[bot] avatar Oct 01 '22 05:10 github-actions[bot]

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 15 days.

github-actions[bot] avatar Dec 01 '22 05:12 github-actions[bot]

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 15 days.

github-actions[bot] avatar Feb 01 '23 05:02 github-actions[bot]

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 15 days.

github-actions[bot] avatar Apr 08 '23 05:04 github-actions[bot]

I think this can actually be closed due to new tlb ctl. I will confirm it.

wtdcode avatar Apr 24 '23 14:04 wtdcode

I have just tried it again.. still same issue. However I think the mmu in itself isn't a problem , just mappings that isn't linear translated. I am very sorry that I haven't been able to give you something better to try. It would be nice to know if it should work. That was with "main" branch. Tried with "dev" and that behaved quite different. It crashed directly on hitting the first mapped word. I configured it to have a bit more ram allocated than the mmu translated address. With "main" it goes up to the limit, in "dev" it doesn't.

mickenx avatar Apr 24 '23 20:04 mickenx

The fix is only in dev, so you need to test with dev.

I just have tested the PoC (export.zip) and got UC_ERR_INSN_INVALID. Looks like this is a problem of the PoC. I'll check this.

It crashed directly on hitting the first mapped word

What do you mean with crashed? Does uc_emu_start return an error or something else?

PhilippTakacs avatar Apr 25 '23 08:04 PhilippTakacs

So after a bit testing the invalid instruction is at 0x10060 the code there (produced by the test case) is 0x116a1e3. I can't disassemble this. When I look at the disassembly of the produced binary this not always match with the code.

I couldn't find a good tool to build the binary at my machine so any hints there would help to debug this.

PhilippTakacs avatar Apr 25 '23 10:04 PhilippTakacs

After a bit more testing with a realworld kernel. I can successfully access my mapped ram! Very happy! I think this finally be closed ( for real this time). Thanks a lot for the fix!

mickenx avatar Apr 25 '23 21:04 mickenx

Thanks for confirmation! Closed.

wtdcode avatar Apr 26 '23 20:04 wtdcode