Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Userland emulation, API #56

Open
6 of 10 tasks
LekKit opened this issue Nov 18, 2022 · 98 comments
Open
6 of 10 tasks

Userland emulation, API #56

LekKit opened this issue Nov 18, 2022 · 98 comments
Assignees
Labels
documentation Improvements or additions to documentation enhancement New feature or request

Comments

@LekKit
Copy link
Owner

LekKit commented Nov 18, 2022

RVVM is usable as a generic CPU execution engine, not just as a complete machine.
This suggests for working userspace emulation, which runs RISC-V code inside a host process, directly accesses it's memory and defers syscall execution to the host kernel.
For convenience, it's also great to expose an API for that, there is a working project that already needs that (https://github.com/X547/UserlandVM), which uses RVVM for HaikuOS RISC-V userland emulation.

Progress tracking:

  • Decide on the initial userland API draft (See Add Haiku host support #55 for discussion on that)
  • Implement the Userland API
  • Test regressions with rebased UserlandVM as a primary API user
  • Test RVJIT cache tracking
  • Von Neumann RVJIT cache for userland
  • Signal handling
  • Upstream ELF loader
  • Linux process stack setup
  • Simple system call shims
  • Full Linux syscall emulation

Discussions & suggestions are welcome.

@LekKit LekKit added documentation Improvements or additions to documentation enhancement New feature or request labels Nov 18, 2022
@LekKit LekKit self-assigned this Nov 18, 2022
LekKit added a commit that referenced this issue Nov 18, 2022
- Implement Userland API as defined by draft. This is WIP, requesting validation by @X547. If you have any issues, try to build lib with USE_JIT=0 and report in #56.
- Icache invalidation is tricky without a soft MMU, hence rvvm_flush_icache() is very inefficient as of now. This will be improved when we finish with other relevant stuff.

Machine mode improvements:
- Implement default PLIC/PCI handling functions
- De-initialize machine devices in reversed order. This makes sure that references to parent devices are always safe, otherwise device thread may be accessing a PCI bus or PLIC while we are freeing it. The general rule now is: Devices shouldn't do anything after they return from dev->remove().
@X547
Copy link
Contributor

X547 commented Nov 18, 2022

Is it possible to build librvvm.a with pkg-config information?

@X547
Copy link
Contributor

X547 commented Nov 18, 2022

I tried to adapt UserlandVM to new librvvm API and it currently crash in riscv_mmu_op.

@LekKit
Copy link
Owner Author

LekKit commented Nov 18, 2022

I tried to adapt UserlandVM to new librvvm API and it currently crash in riscv_mmu_op.

Can you give a backtrace?

@LekKit
Copy link
Owner Author

LekKit commented Nov 18, 2022

Is it possible to build librvvm.a with pkg-config information?

Will do. I have no experience with pkg-config however 😅

@X547
Copy link
Contributor

X547 commented Nov 18, 2022

Some obvious fixes:

diff --git a/src/rvvm.c b/src/rvvm.c
index c782080..a3427af 100644
--- a/src/rvvm.c
+++ b/src/rvvm.c
@@ -707,11 +707,15 @@ PUBLIC rvvm_cpu_handle_t rvvm_create_user_thread(rvvm_machine_t* machine)
     vector_emplace_back(machine->harts);
     rvvm_hart_t* vm = &vector_at(machine->harts, vector_size(machine->harts) - 1);
     riscv_hart_init(vm, machine->rv64);
+    vm->machine = machine;
+    vm->mem = machine->mem;
 #ifdef USE_FPU
     // Initialize FPU properly
 #endif
     return (rvvm_cpu_handle_t)vm;
 }
@@ -743,8 +747,9 @@ PUBLIC rvvm_addr_t rvvm_read_cpu_reg(rvvm_cpu_handle_t cpu, size_t reg_id)
         return vm->csr.cause[PRIVILEGE_USER];
     } else if (reg_id == RVVM_REGID_TVAL) {
         return vm->csr.tval[PRIVILEGE_USER];
+    } else {
+        rvvm_warn("Unknown register %d in rvvm_read_cpu_reg()!", (uint32_t)reg_id);
     }
-    rvvm_warn("Unknown register %d in rvvm_read_cpu_reg()!", (uint32_t)reg_id);
     return 0;
 }
 
@@ -763,6 +768,7 @@ PUBLIC void rvvm_write_cpu_reg(rvvm_cpu_handle_t cpu, size_t reg_id, rvvm_addr_t
         vm->csr.cause[PRIVILEGE_USER] = reg;
     } else if (reg_id == RVVM_REGID_TVAL) {
         vm->csr.tval[PRIVILEGE_USER] = reg;
+    } else {
+        rvvm_warn("Unknown register %d in rvvm_write_cpu_reg()!", (uint32_t)reg_id);
     }
-    rvvm_warn("Unknown register %d in rvvm_write_cpu_reg()!", (uint32_t)reg_id);
 }

@LekKit
Copy link
Owner Author

LekKit commented Nov 18, 2022

Some obvious fixes:

diff --git a/src/rvvm.c b/src/rvvm.c
index c782080..a3427af 100644
--- a/src/rvvm.c
+++ b/src/rvvm.c
@@ -707,11 +707,15 @@ PUBLIC rvvm_cpu_handle_t rvvm_create_user_thread(rvvm_machine_t* machine)
     vector_emplace_back(machine->harts);
     rvvm_hart_t* vm = &vector_at(machine->harts, vector_size(machine->harts) - 1);
     riscv_hart_init(vm, machine->rv64);
+    vm->machine = machine;
+    vm->mem = machine->mem;
 #ifdef USE_FPU
     // Initialize FPU properly
 #endif
     return (rvvm_cpu_handle_t)vm;
 }
@@ -743,8 +747,9 @@ PUBLIC rvvm_addr_t rvvm_read_cpu_reg(rvvm_cpu_handle_t cpu, size_t reg_id)
         return vm->csr.cause[PRIVILEGE_USER];
     } else if (reg_id == RVVM_REGID_TVAL) {
         return vm->csr.tval[PRIVILEGE_USER];
+    } else {
+        rvvm_warn("Unknown register %d in rvvm_read_cpu_reg()!", (uint32_t)reg_id);
     }
-    rvvm_warn("Unknown register %d in rvvm_read_cpu_reg()!", (uint32_t)reg_id);
     return 0;
 }
 
@@ -763,6 +768,7 @@ PUBLIC void rvvm_write_cpu_reg(rvvm_cpu_handle_t cpu, size_t reg_id, rvvm_addr_t
         vm->csr.cause[PRIVILEGE_USER] = reg;
     } else if (reg_id == RVVM_REGID_TVAL) {
         vm->csr.tval[PRIVILEGE_USER] = reg;
+    } else {
+        rvvm_warn("Unknown register %d in rvvm_write_cpu_reg()!", (uint32_t)reg_id);
     }
-    rvvm_warn("Unknown register %d in rvvm_write_cpu_reg()!", (uint32_t)reg_id);
 }

Oh... Silly me
Does it work now?

@LekKit
Copy link
Owner Author

LekKit commented Nov 18, 2022

Apart from the possible explosions from RVJIT and my poor checking of my own code, I tried to copy your approach and also used some proper functions for FPU enablement and other cpu state setup

@X547
Copy link
Contributor

X547 commented Nov 18, 2022

Does it work now?

Not yet. Crash after first syscall with NULL guest dereference. Maybe my fault, need to debug more. TinyEMU engine still working.

@LekKit
Copy link
Owner Author

LekKit commented Nov 18, 2022

Does it work now?

Not yet. Crash after first syscall with NULL guest dereference. Maybe my fault, need to debug more. TinyEMU engine still working.

See my comment from d20c2d2 (Concern about PC increment behavior)

Where should the PC increment happen? In UserlandVM, merely returning from riscv_trap() means we land on a next instruction after the one that triggered the trap. This implementation preserves this behavior, but may need some re-arrangement. For example, we can increment the PC on the next entry to riscv_hart_run_userland(), or perhaps defer this to outside code (Will require changes on UserlandVM side)

This part should be more explicit and well documented. I'm not sure if this is the thing that broke for you, but just be aware.
As for now, I'm not sure how do i set up UserlandVM to debug this myself, and not sure if any intervention is needed. There isn't much code changed so maybe you can wriggle around it and see potential fixes.

@X547
Copy link
Contributor

X547 commented Nov 18, 2022

PC register is 4 inside syscall handler.

> UserlandVM /boot/home/Tests/UserlandVM/apps/StyledEdit
syscall 193(_kern_create_area)
  PC: 4
[!] unhandled trap: Hart 0x7fda61ed74d0 trap at 00000000, cause 1, tval 0x000004
FP: 0x138f4fc8fd0, PC: 0
FP: 0x138f4fc9000, PC: 0xf6ae739332
FP: 0, PC: 0x209fe946018

@X547
Copy link
Contributor

X547 commented Nov 18, 2022

Virtual CPU still try to jump at TVEC that is zero. It should be not done for userland emulation mode.

@LekKit
Copy link
Owner Author

LekKit commented Nov 18, 2022

Virtual CPU still try to jump at TVEC that is zero. It should be not done for userland emulation mode.

Weird. I'm not sure how that's happening (Unless you are calling riscv_hart_run() or clearing vm->user_traps), I grep'ed the source tree for manupulations on REGISTER_PC and did not see any other way.

@X547
Copy link
Contributor

X547 commented Nov 18, 2022

I used older version of riscv_hart.c 😅.

Now it seems crash on FPU instruction:

syscall 223(_kern_write_port_etc)
  PC: 1052861742872
syscall 219(_kern_port_buffer_size_etc)
  PC: 1052861742808
syscall 221(_kern_read_port_etc)
  PC: 1052861742840
[!] unhandled trap: Hart 0x7f314e9fc940 trap at 0x193b9f4cc70, cause 2, tval 0x102773
FP: 0xb4e19de740, PC: </boot/home/Tests/UserlandVM/apps/lib/libbe.so> 0x193c70
FP: 0xb4e19de7e0, PC: </boot/home/Tests/UserlandVM/apps/lib/libtracker.so> 0x11362a
FP: 0xb4e19de820, PC: </boot/home/Tests/UserlandVM/apps/lib/libtracker.so> 0x11392e
FP: 0xb4e19de8c0, PC: </boot/home/Tests/UserlandVM/apps/lib/libtracker.so> 0xe30ce
FP: 0xb4e19dead0, PC: </boot/home/Tests/UserlandVM/apps/lib/libtracker.so> 0xe4738
FP: 0xb4e19dec50, PC: </boot/home/Tests/UserlandVM/apps/lib/libtracker.so> 0xe53ac
FP: 0xb4e19ded20, PC: </boot/home/Tests/UserlandVM/apps/lib/libtracker.so> 0xe0156
FP: 0xb4e19dedf0, PC: </boot/home/Tests/UserlandVM/apps/StyledEdit> 0x152c0
FP: 0xb4e19defa0, PC: </boot/home/Tests/UserlandVM/apps/StyledEdit> 0x12100
FP: 0xb4e19defd0, PC: </boot/home/Tests/UserlandVM/apps/StyledEdit> 0x121f6
FP: 0xb4e19df000, PC: 0x9476af3370
FP: 0, PC: 0x10e62d5e018

@X547
Copy link
Contributor

X547 commented Nov 18, 2022

It started after recovering my old HART state initialization code:

    maxlen_t mstatus = 0xA00000000 + (FS_INITIAL << 13);
    riscv_csr_op(vm, 0x300, &mstatus, CSR_SWAP);

screenshot492

@LekKit
Copy link
Owner Author

LekKit commented Nov 18, 2022

It started after recovering my old HART state initialization code:

Neat! I will provide upstream fixes soon.
Does RVJIT work? 😅

@X547
Copy link
Contributor

X547 commented Nov 18, 2022

Seems yes, but not with all programs.

screenshot493

@LekKit
Copy link
Owner Author

LekKit commented Nov 18, 2022

Seems yes, but not with all programs.

Well, considering the absolute lack of cache coherence in userland mode, it's understandable.
I think there are places where you could've missed the need to call rvvm_icache_flush(), for example munmap syscalls and other stuff that invalidates the code in memory.
Alas, rvvm_icache_flush() is also potentially racy. I don't know for sure, would need to have your environment & working ThreadSanitizer. I remember you tried wrapping cpu runner in a lock for TEmu, so maybe you can try the same & see if it fixes anything.

@X547
Copy link
Contributor

X547 commented Nov 18, 2022

Something wrong is happening with multiple threads (host heap corruption etc.).

@X547
Copy link
Contributor

X547 commented Nov 18, 2022

This part should be more explicit and well documented. I'm not sure if this is the thing that broke for you, but just be aware.

Real RISC-V behavior is not incrementing PC on ECALL trap. This is also what TinyEMU does: https://github.com/X547/UserlandVM/blob/master/VirtualCpuRiscVTemu.cpp#L48.

@LekKit
Copy link
Owner Author

LekKit commented Nov 18, 2022

Real RISC-V behavior is not incrementing PC on ECALL trap. This is also what TinyEMU does: https://github.com/X547/UserlandVM/blob/master/VirtualCpuRiscVTemu.cpp#L48.

I know, it's just an implementation detail (And optimization) of RVVM interpreter that leaked when we abandoned machine mode. After each interpreted instruction it increments PC by instruction size, but the trap handling jumps to TVEC which makes the PC increment invisible to the guest.

Omitting the increment for userland emulation also adds confusion when it's not the ECALL instruction: we aren't sure what's the size of the instruction (Which is why it was initially done this way internally)

LekKit added a commit that referenced this issue Nov 18, 2022
- Fix initialization of per-cpu variables
- Fix FPU initialization
- Fix bogus warns from rvvm_write_cpu_reg()

See #56 for details
@X547
Copy link
Contributor

X547 commented Nov 18, 2022

rvvm_create_user_thread have no machine->harts thread protection and rvvm_free_user_thread do not remove hart from list.

@LekKit
Copy link
Owner Author

LekKit commented Nov 18, 2022

rvvm_create_user_thread have no machine->harts thread protection and rvvm_free_user_thread do not remove hart from list.

There are some disastrous things from that vector manipulation already with CPU hotplug, a patch is on the way. You can try placing spin_lock(&global_lock) there, but another horrific issue arises from the vector reallocation which moves our cpus in memory (OH GOD).
So heh, i think another round or two of patches is expected.

@LekKit
Copy link
Owner Author

LekKit commented Nov 18, 2022

Just looked at my git diff --stat

21 files changed, 3502 insertions(+), 3152 deletions(-)
Oh... Poor networking, hid & fb stuff... I probably should start upstreaming them somehow

@LekKit
Copy link
Owner Author

LekKit commented Dec 25, 2022

I'm currently deciding some license-related changes, and I'd like to hear your feedback if possible (Could benefit UserlandVM)

I'm heavily against closed forks, together with @cerg2010cerg2010, but GPL is slightly restrictive sometimes when it comes to distributing/integrating the project. GPL requires accompanying code to be GPL-compatible, and requires that modifications are always possible.

I'm investigating the dual-licensing approach, where you aren't forced to open your code or change licensing when linking with upstream librvvm (no matter statically or dynamically), or distributing it. It would "just work" under terms of any other license if you are using upstream version, but if you want to modify librvvm sources you should make them available under GPL terms.

This usecase is perfectly covered by Artistic License 2.0 which is also OSI-approved, MPL looks like a good choice as well. It would allow, for example, to distribute RVVM in Apple App Store (otherwise it would violate the modifications are always possible part of GPL).

I'm curious if this can help integrate RVVM with UserlandVM more easily, or allow distributing it in FreeBSD/Haiku repositories. Would like to hear your thoughts on that, or any other ideas you may have. I hope we can make a good compromise for both end users and us, developers)
After discussing this together with @cerg2010cerg2010 he approved this, as long as we don't relicense his code as overly permissive because closed forks are bad :D

@X547
Copy link
Contributor

X547 commented Dec 26, 2022

I'm currently deciding some license-related changes, and I'd like to hear your feedback if possible (Could benefit UserlandVM)

librvvm license allowing to use it with MIT-licensed code would be beneficial for Haiku. It would allow to distribute RVVM based CPU engine plugin for UserlandVM as part of system. I originally planned to distribute TinyEMU based engine as default and RVVM engine as optionally installable.

@LekKit
Copy link
Owner Author

LekKit commented Dec 26, 2022

I'm currently deciding some license-related changes, and I'd like to hear your feedback if possible (Could benefit UserlandVM)

librvvm license allowing to use it with MIT-licensed code would be beneficial for Haiku. It would allow to distribute RVVM based CPU engine plugin for UserlandVM as part of system. I originally planned to distribute TinyEMU based engine as default and RVVM engine as optionally installable.

Will MPL or Artistic license be compatible with MIT? That looks to me like a nice middle-ground between permissive and copyleft, since we just drop the requirement that "modifications are always possible" and the viral nature of GPL linkage, while still insisting that changes made to librvvm code should be public. You may even build a proprietary version of UserlandVM which links to librvvm statically, and the only concern would be that you may no longer make modifications to librvvm internals and should use it as-is (Or publish your changes to it, without the need to relicense or open any other parts of your software).

@X547
Copy link
Contributor

X547 commented Dec 26, 2022

If it will be possible to link closed-sourced fork of UserlandVM to unmodified librvvm.a, it should be fine.

@LekKit
Copy link
Owner Author

LekKit commented Dec 27, 2022

If it will be possible to link closed-sourced fork of UserlandVM to unmodified librvvm.a, it should be fine.

Hope that's resolved now, see the repo
The sources files still carry baggage of GPL headers, but the main repo licenses take precedence. They will be gradually migrated to SPDX or dual-headers, all the other contributors personally agreed with such changes (I hope you too, since I2C hid and Haiku window are copyrighted by you).
Discussions to further improve the situation are welcome. See 9cedfdf commit explanation for more details.

@LekKit
Copy link
Owner Author

LekKit commented Feb 21, 2023

I found one regression with new librvvm: menu windows are displayed at wrong position and size. Issue is not present with old embedded RVVM code and with TinyEMU code. Probably FPU related because float type is used in GUI coordinates.

Depending on what reference commit you used in your fork, it could've lacked NaN boxing (Which is now implemented properly, see src/mem_ops.h), which fills upper 64-bit register part with 0xFFFFFFFF when working with 32-bit floats. There are no other significant changes that could cause that.

I will be returning to my debugging efforts with legacy librvvm soon, but I want to upstream a few things in the meantime (RTL8169, Initial Linux user emulation support).

@LekKit
Copy link
Owner Author

LekKit commented Mar 29, 2023

Upstreamed a new reusable ELF loader lib. It loads userspace Linux ELFs into process address space fine, and even runs some of them (Syscall emulation and stack setup are unstable and limited, not upstreamed yet).
It also loads firmware/kernel ELFs now, same as QEMU does (basically in-house objcopy -O binary)

No FPU issues with rvvm-user + Linux binaries that I see so far. To be continued...

@LekKit
Copy link
Owner Author

LekKit commented Jan 12, 2024

New RVJIT optimization allows 1:1 translation of load/store instructions to host instructions in userland emulation, this should boost perf a lot, @X547 can you evaluate if it works OK with UserlandVM?

@fish4terrisa-MSDSM
Copy link
Contributor

I am very interested in rvvm-user, can i build and try it on my machine?
And, since currently rvvm VM mode is very fast, why not use 9pfs in the VM mode and run the binary in the guest instead?(Opensbi and linux kernel won't use too much memory). User mode will cause a lot of problems on premissions, syscalls, rootfs and many others.(See proot and qemu-user) That will also help if users want to transfer files between guest and host. (Maybe we can have a fake metadata mode for the 9pfs option, just like humfs in User mode linux, so that a normal user can boot the system from 9pfs)

@LekKit
Copy link
Owner Author

LekKit commented Jan 12, 2024

I am very interested in rvvm-user, can i build and try it on my machine?

See cdfea8b. It is very WIP, and the entire point of userland emulator in future is that more perf can be squeezed, it fully integrates with your system (GUI goes directly over host X/Wayland, same with sound, etc) and even things like GPU drivers could work I guess. It is also very nice for foreign-arch build systems.

@LekKit
Copy link
Owner Author

LekKit commented Jan 12, 2024

Tiny progress on running dyn RISC-V Linux ELFs.. (Here running buildroot chroot & PrBoom)
Seems like argv alignment isn't done properly, different arg count may cause a crash

image

@LekKit
Copy link
Owner Author

LekKit commented Jan 13, 2024

@X547 should I actually omit PC increment entirely for userland API (like TEMU does)? I think it's actually a good idea now, and if it should be done it better be early than late

Basically I figured the PC increments on faulty instructions (load/store traps, illegal instructions etc) as well which is not nice at all, whereas only incrementing PC after ECALL is also weird

@X547
Copy link
Contributor

X547 commented Jan 13, 2024

@X547 should I actually omit PC increment entirely for userland API (like TEMU does)? I think it's actually a good idea now, and if it should be done it better be early than late

I am fine with both, but it would be nice to be consistent with how real RISC-V works (do not increment PC on ECALL).

@LekKit
Copy link
Owner Author

LekKit commented Jan 13, 2024

I am fine with both, but it would be nice to be consistent with how real RISC-V works (do not increment PC on ECALL).

I will be doing exactly that soon, then. It will cause a slight breakage for UserlandVM tho - you will need to patch it to add 4 bytes to PC on ecall. Considering I am only doing this for v0.6 and RVVM_ABI_VERSION is different there, I guess it's ok.

UPD: cc3466c

@LekKit
Copy link
Owner Author

LekKit commented Jan 13, 2024

Many static binaries & Musl-linked dynamic binaries work in rvvm-user at this point.

However, there is a strange issue that glibc dyn ELFs do crash early in ld-linux when running rvvm-user in chroot on x86 host, yet work fine when running rvvm-user on a RISC-V host (I.e. emulating RISC-V userland on RISC-V).

I've implemented detailed guest exception handling and debug output, but struggle to debug this. If anyone is interested in joining the efforts, here is a direction:

  • Get a 64-bit Linux host
  • Uncomment this:
    //#define RVVM_USER_TEST
  • Patch the beginning of main() in main.c to have this:
int rvvm_user(int argc, char** argv, char** envp);

int main(int argc, char** argv, char** envp)
{
    if (argc > 2 && rvvm_strcmp(argv[1], "-user")) {
        rvvm_set_loglevel(LOG_INFO);
        return rvvm_user(argc - 2, argv + 2, envp);
    }
    ...
  • Build RVVM with make CFLAGS="-static"
  • Try running some RISC-V binaries with rvvm -user [command]

@X547
Copy link
Contributor

X547 commented Jan 13, 2024

Try running some RISC-V binaries with rvvm -user [command]

I think that it would be better to put userland Linux emulator into separate executable, something like rvvm-user-linux [command]. Unlike machine emulation, userland emulator is very platform-dependent and non-portable.

@LekKit
Copy link
Owner Author

LekKit commented Jan 13, 2024

I think that it would be better to put userland Linux emulator into separate executable, something like rvvm-user-linux [command]. Unlike machine emulation, userland emulator is very platform-dependent and non-portable.

It's a good idea, esp. considering that binfmt-misc only allows to pass argv to emulator. I just want some quick solution for now that doesn't need to modify ton of stuff in repo like build systems etc.

Honestly tho I like the idea that both user and machine modes share like 95% of emulation/JIT code. It's not entirely nonportable either (Its in theory possible to run Linux programs on Haiku or FreeBSD).

@X547
Copy link
Contributor

X547 commented Jan 13, 2024

Honestly tho I like the idea that both user and machine modes share like 95% of emulation/JIT code.

This is what dynamic libraries for.

It's not entirely nonportable either (Its in theory possible to run Linux programs on Haiku or FreeBSD).

So are you planning to implement Linux syscalls on top of POSIX, not like UserlandVM where host and guest syscalls are assumed to be the same? It would be much more complex and likely cause a lot of compatibility problems.

@LekKit
Copy link
Owner Author

LekKit commented Jan 13, 2024

So are you planning to implement Linux syscalls on top of POSIX, not like UserlandVM where host and guest syscalls are assumed to be the same? It would be much more complex and likely cause a lot of compatibility problems.

So far I am simply calling POSIX/Linux specific libc functions that correspond to their syscall and it's not problematic. There are a few things that can be done with this to ensure maximum compatibility, like converting ABI/endianness in structs passed between kernel<->user, like QEMU does.

@LekKit
Copy link
Owner Author

LekKit commented Jan 14, 2024

@X547 big news: (TLDR: I got glibc dyn binaries to work)

We can't simply jump from guest syscalls to host kernel (as you suggested earlier). It turns out structures passed in Linux syscalls are defined subtly different on different architectures, so simply passing a pointer to struct stat from RISC-V process to x86_64 kernel results in corruption. So when I implemented conversion most of the mad crashes went away.

This also means that subtle difference between POSIX systems like Haiku or BSD can be also eliminated this way and allow to run some apps on a foreign kernel

@LekKit
Copy link
Owner Author

LekKit commented Jan 14, 2024

Managed to launch pacman in chroot. Some structs are not yet converted properly, and there are bugs, so it still doesn't work perfectly but at least something works x)

image

@X547
Copy link
Contributor

X547 commented Jan 14, 2024

thread failed to start

I suppose some special handling is needed when spawning new threads like in UserlandVM.

@LekKit
Copy link
Owner Author

LekKit commented Jan 14, 2024

I suppose some special handling is needed when spawning new threads like in UserlandVM.

I guess so. The struct conversion is still WIP so I'd need to finish it first, also I don't see that guest touch clone() syscall at all.

@LekKit
Copy link
Owner Author

LekKit commented Jan 14, 2024

Went further and now crashes immediately in the newly clone()'d thread. The main thread survives tho, and complains a lot.

image

@LekKit
Copy link
Owner Author

LekKit commented Jan 15, 2024

Another useful trick: On a RISC-V host, selectively bypass syscalls directly to syscall(NR, ...) to bisect whether your shim is working properly.

There are only a few syscalls that won't ever work that way, one notable exception is clone() which, if executed directly would make a child thread return into RVVM emulation code and crash. Also this helped me to figure out that my clone() implementation is faulty because pacman is broken the same way even when all other syscalls are bypassed

@fish4terrisa-MSDSM
Copy link
Contributor

It seems that currently RVVM have fake chroot and fake bind options. Maybe fake pid and uid can also be added? We may add a fake pid namespace to RVVM so that we can boot the system by running rvvm-user /sbin/init and get full service functions of systemd.

@LekKit
Copy link
Owner Author

LekKit commented Jan 19, 2024

It seems that currently RVVM have fake chroot and fake bind options. Maybe fake pid and uid can also be added? We may add a fake pid namespace to RVVM so that we can boot the system by running rvvm-user /sbin/init and get full service functions of systemd.

Fake uid indeed could be implemented as in proot so the guest thinks it's running as root. However running systemd like that might turn out complicated, we'll see.

@LekKit
Copy link
Owner Author

LekKit commented Mar 12, 2024

I have reworked CMake build system so static libs can be built properly and not split into librvvm.a/librvvm_cpu32.a/librvvm_cpu64.a/librvjit.a - instead, only librvvm_static.a is provided. Shared library librvvm.so is also built by default now.

Building rvvm CLI binary is unchanged.

Perhaps I can also implement an install target if you need it for Haiku RVVM package/port. But make install does this job already for RVVM packaging purposes and CMake in this repo is more like a tool oriented for devs that are used to CMake, or use an OS that is incompatible with POSIX & Make (Windows).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants