-
Notifications
You must be signed in to change notification settings - Fork 61
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
Testing infrastructure #20
Comments
Definitely! I've been thinking about in the future custom test runners could make this really nice, but we can hack something together now. |
Indeed, do you happen to know if there is an RFC for custom test runners somewhere around? |
https://internals.rust-lang.org/t/test-and-external-test-harnesses/3145 this is all I know of. |
Well my rust-lang/rfcs#1133 might make |
Thanks, I definitely look forward to rust-lang/rfcs#1133 this should simplify things quite a bit. |
It should be fairly straightforward to use the KVM bindings though that crate itself has been lightly tested. I think we can just use the native test harness as long as the test runner has access to /dev/kvm |
Let's get the ball rolling! QuiltOS@0a52a0d |
If anybody can figure out how to remove the mmap that would be cool. I'd like to avoid writing a crude linker :). |
In the past, I've mapped in the entire process using /proc/self/maps. That way you can write the tests in and use their address as normal. I'm traveling for the next couple days but happy to help when I'm back |
Still a bit buried for the next little while. I started on mapping the binary in via /proc/self/maps: It's not working yet since the VCPU needs to be in long mode and therefore also needs a page table, but that should all work without needing to link it specially. |
I have some time issues as well on my side right now but this looks awesome, thanks! 👍 |
But, what do I even have to do with KVM? Signed-off-by: Gerd Zellweger <mail@gerdzellweger.com>
I did quick&dirty initial virtual space layout by doing an identity map (which I assume I get away with for now :O?) and trying to set cr0/cr3/cr4 to what they should be. But to be honest, I'm not sure what you actually need to do here: Does it need to run some bootstrap code inside the VM to go in long mode or can it be set-up all externally? AFAIK it also needs a MSR write to enable the IA32-e paging... |
It can all be done externally. I worked on mine a bit and it works if I manually write in the inb instruction, but not if I use the naked function. I'm guessing I got my paging map incorrect but maybe another pair of eyes can help. Feel free to harvest from that code |
You'll see in my code how I set the control registers and the EFER MSR to enable paging, long mode, etc. Also the CS is set to long-mode and CR3 points to a (supposed) valid PML4 which was supposed to identity map the entire lower half of the address space. |
Got it :) that will help, thanks! |
I was working on this yesterday: https://github.com/QuiltOS/rust-x86 for some misc cleanups. I think on my machine at least the program is being loaded into the upper half, which would be the problem. It's a chore, but I guess the solution is to map in each memmap as contiguous physical memory, and then page it in to its proper place. Haven't done that yet. |
https://github.com/japaric/utest @japaric might have just gotten this unstuck! |
Indeed, this looks pretty good! |
Btw. I think the reason we can't access the .text code pages seems to be because it's mapped at a very high host virtual address (rust binaries are weird, .text starts at ~0x560c8dd7d000). I did a few tests and it seems that every mapping with host virtual above 1<<40 is not readable by KVM (maybe because it restricts the guest physical address space to 40 bits?). |
Alright, some more tinkering it seems to execute the naked function now, when compiled with relocation-model=static:
|
Signed-off-by: Gerd Zellweger <mail@gerdzellweger.com>
Signed-off-by: Gerd Zellweger <mail@gerdzellweger.com>
Alright, it seems the technique they use in utest also works without no_std, you simply override the default test crate in your Cargo.toml. This together with procedural macros should let us build something quite nice to automatically set-up the virtual CPU according to the test requirements etc. 👍 |
Cool! Pretty busy ATM but I'll have to try this soon! |
Signed-off-by: Gerd Zellweger <mail@gerdzellweger.com>
Signed-off-by: Gerd Zellweger <mail@gerdzellweger.com>
Signed-off-by: Gerd Zellweger <mail@gerdzellweger.com>
Signed-off-by: Gerd Zellweger <mail@gerdzellweger.com>
Signed-off-by: Gerd Zellweger <mail@gerdzellweger.com>
Did a bit more hacking, this is slowly starting to look like proper tests: |
Seems like a good way to handle panics would be with plugging in a custom libpanic implementation (rust-lang/rust#32837). Unfortunately this is not yet supported, rustc allows only libabort_panic and libabort_unwind. |
Ideally, there would be a way to override the panic_abort crate as a hack with xargo. I tried the following for now: Using target.json:
And Xargo.toml:
Which gives:
(and supplying -p panic_abort:0.0.1 on xargo doesn't seem to work) |
Now that rust-lang/rfcs#2318 has landed I plan to revisit this again. |
I cleaned this up a bit and since it is in good enough shape now to be easily extended and can run tests I am going to close this. Only took two years :) |
Ideally I'd like have an infrastructure for unit testing at least some parts of this crate. Potential candidates to use are qemu or directly @dschatzberg kvm bindings (https://github.com/dschatzberg/kvm).
The text was updated successfully, but these errors were encountered: