-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Run tests for cross-compiled platforms in QEMU #33114
Comments
@japaric I've been thinking a little more about this and how it relates to a lot of the cross-compiled testing you've been working on recently. I'm thinking that the ideal here would be to take a very Android-like approach:
This'd allow us to sidestep all concerns about qemu userspace emulation bugs (e.g. with threads) and give us a full-featured testing environment (whole kernel and everything). Additionally we can perhaps get a tighter control over the environment by customizing how it's installed. Would you be interested in prototyping this? I think it could make a great addition to the test suite we run on Travis! |
@alexcrichton Sounds good to me. I already have an idea of how to make this test server transparently work with
The main reason I have never attempted QEMU system emulation is that I don't know where to get e.g. a compiled ARM kernel / rootfs. I suppose that Ubuntu / Debian must have binary releases of such things but I don't know where they are hiding them. |
Yeah it's true that assembling the qemu image would be a pain. I know for the libc-test images we use for FreeBSD and NetBSD were a pain to create. I'd hope though that there's a "base image" with some minimal install from somewhere though that we could use! |
OK. I found where Ubuntu was hiding their stuff: There are binary releases for armhf, ppc64el and s390x. Apart from i686 and amd64. There's a rootfs for powerpc but no kernel AFAICT. And I got a script to turn those tarballs into a QEMU image (the armhf image is around 300MB in size). Now we are just missing the test server. |
Holy cow, awesome! That was fast :) My guess is that we could make a super simple test protocol server for now, something like:
|
Yeah, I got a simpler test server (no stdin or arguments) working on the host but it doesn't when the server part is running inside QEMU. I could be doing the QEMU TCP redirection wrong and some sort of networking has to be done on the guest. Here's the code (sorry, it's an Usage looks like this:
I'm launching QEMU like this:
And it gets stuck like this
AFAICT, the client does open a connection and sends the data because QEMU is listening on port 12345 but QEMU is not passing that data to the guest for some reason. |
Hm some of the QEMU documentation alludes to:
Maybe |
I had already tried explicitly listing 127.0.0.1 in several places. It didn't help
I just tested this ... no dice. QEMU does report the port forwarding is enabled though:
Does ... TCP not work in Linux if you forget to initialize some service? I tried I also discarded this being an architecture specific problem because I also tried running |
For the record, the architecture you've outlined would work well for testing on devices and such as well, which would be nice. We have something similar we used for Firefox testing on devices in the past called the SUTAgent, although it's been deprecated in favor of using ADB directly for Android testing on devices or in emulators now. |
@japaric hm I poked around a bit and could reproduce everything you mentioned as well. I was seeing some odd errors though about a readonly filesystem and I added I wonder if there's some kernel option that's not being passed or something like that? I have very little experience with qemu network and barely understand it whenever it works, so it could be an obvious problem that we're just missing... |
Ok I've spent what is now an embarassing amount of time trying to get this work. Along the way I think I'm learning things about Linux, but who knows! @japaric so I think what's going on in your gist is that the guest doesn't have networking configured. Now that being said I have no idea how to configure the network with such a minimal image. As a result I opted to try a different strategy, outlined in a gist. Everything's a bit of a mess, so I figured I'd list a few things in detail:
So given all that the gisted
Unfortunately it's not working yet. I believe the reason is that reads of Figured I'd at least give a bit of an update. For the number of hours I've put into this so far it seems I've only made a tiny bit of progress! |
Oh also apologies for the state of the gist, everything's a mess :(. GitHub apparently loses directory structure when gisting, but it should have a relatively self-explanatory layout. |
You need to use the entropy ioctl (your ioctl numbers may vary, please check with a C compiler): extern crate libc;
use std::io;
use std::os::unix::io::AsRawFd;
use std::fs::File;
const _IOC_READ: libc::c_ulong = 2;
const RNDGETENTCNT: libc::c_ulong =
(4<<29) +
(4<<16) +
((b'R' as libc::c_ulong)<<8) +
(0x00<<0);
const RNDADDENTROPY: libc::c_ulong =
(2<<29) +
(8<<16) +
((b'R' as libc::c_ulong)<<8) +
(0x03<<0);
#[repr(C)]
pub struct RandPoolInfo {
entropy_count: libc::c_int,
buf_size: libc::c_int,
buf: [u32; 4]
}
fn main() {
main2().unwrap();
}
fn get_entropy_count(file: &File) -> io::Result<libc::c_int> {
let fd = file.as_raw_fd();
let mut data = 0;
let result = unsafe {
libc::ioctl(fd, RNDGETENTCNT as _, &mut data as *mut _)
};
if result != 0 {
return Err(io::Error::last_os_error());
}
Ok(data)
}
fn add_entropy(file: &File, buf: [u32; 4]) -> io::Result<()> {
let pool = RandPoolInfo {
entropy_count: 128,
buf_size: 16,
buf: buf,
};
let fd = file.as_raw_fd();
let result = unsafe {
libc::ioctl(fd, RNDADDENTROPY as _, &pool as *const RandPoolInfo)
};
if result != 0 {
return Err(io::Error::last_os_error());
}
Ok(())
}
fn main2() -> io::Result<()> {
let f = File::open("/dev/random")?;
println!("entropy before: {}", get_entropy_count(&f)?);
add_entropy(
&f,
// chosen by fair dice roll, guaranteed to be random
// please use 4 fresh random words in production
[1825268108, 1056140314, 3447110939, 1873895583]
)?;
println!("entropy after: {}", get_entropy_count(&f)?);
Ok(())
} |
Thanks for the tip @arielb1! I ended up stumbling upon something similar last night as well. @japaric I've packaged everything up in a repo and it should all be working now for a smoke test at least: https://github.com/alexcrichton/cross-test-arm-server. There's still one or two pieces I'm not 100% sure about, but it should be much closer to the point we can start integrating into rust-lang/rust! |
I was running PowerPC quite successfully in fully-emulated mode to debug the i128 issue. These are the flags I used:
The disk.img contains a barebones installation of debian (downloaded from ftp://ftp.se.debian.org/debian-cd/8.7.1/powerpc/iso-cd/). Then I extracted the # extract offset of the boot partition
echo -e 'unit b\np' | parted disk.img
2 32768B 236033023B 236000256B ext2 untitled
# mount the partition
sudo mount -o loop,ro,offset=32768 -text2 disk.img somedir
# copy out the kernel/initrd and unmount. I found https://gmplib.org/~tege/qemu.html to be very useful resource. Also, you might want to setup the |
Ok I've now implemented this entirely for ARM on on a branch: alexcrichton@72059f6 On that repo |
This commit adds support to the build system to execute test suites that cannot run natively but can instead run inside of a QEMU emulator. A proof-of-concept builder was added for the `arm-unknown-linux-gnueabihf` target to show off how this might work. In general the architecture is to have a server running inside of the emulator which a local client connects to. The protocol between the server/client supports compiling tests on the host and running them on the target inside the emulator. Closes rust-lang#33114
I've posted a PR for this. |
Add support for test suites emulated in QEMU This commit adds support to the build system to execute test suites that cannot run natively but can instead run inside of a QEMU emulator. A proof-of-concept builder was added for the `arm-unknown-linux-gnueabihf` target to show off how this might work. In general the architecture is to have a server running inside of the emulator which a local client connects to. The protocol between the server/client supports compiling tests on the host and running them on the target inside the emulator. Closes rust-lang#33114
Add support for test suites emulated in QEMU This commit adds support to the build system to execute test suites that cannot run natively but can instead run inside of a QEMU emulator. A proof-of-concept builder was added for the `arm-unknown-linux-gnueabihf` target to show off how this might work. In general the architecture is to have a server running inside of the emulator which a local client connects to. The protocol between the server/client supports compiling tests on the host and running them on the target inside the emulator. Closes rust-lang#33114
Add support for test suites emulated in QEMU This commit adds support to the build system to execute test suites that cannot run natively but can instead run inside of a QEMU emulator. A proof-of-concept builder was added for the `arm-unknown-linux-gnueabihf` target to show off how this might work. In general the architecture is to have a server running inside of the emulator which a local client connects to. The protocol between the server/client supports compiling tests on the host and running them on the target inside the emulator. Closes rust-lang#33114
QEMU has some pretty nice acceleration for x86_64/x86 targets, and it can run basically everything else under the sun in an emulation mode. We should try to run all our cross-compiled targets' tests in QEMU, or at least some subset of tests (e.g. run-pass + stdtest or something like that).
Some targets to run tests for would include:
x86_64-unknown-freebsd
x86_64-unknown-netbsd
arm-unknown-linux-gnueabi
aarch64-unknown-linux-gnu
etc
We could at least start out with testing in QEMU and then eventually upgrade one day to running a bootstrap or running the compiler in QEMU if it works out well enough.
The text was updated successfully, but these errors were encountered: