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

Changes for successful build on aarch64 #759

Merged
merged 10 commits into from
Jan 18, 2019

Conversation

dianpopa
Copy link
Contributor

@dianpopa dianpopa commented Dec 10, 2018

Addressed Issue

#756.

Description of changes

Necessary changes for successful build on a A-72 Cortex (aarch64).

  • added dummy code for non x86_64 architecture inside dumbo and fc_util. Opened issue for adding implementation Get the processor’s time-stamp counter in aarch64 #758
  • x86_64 crate was replaced by the arch crate which was written in such way that the architectural specific code is conditionally compiled
  • syscalls that were used for seccomp filtering are architecture dependent. Added new module for conditionally compiling them.
  • cpuid crate is compiled only on x86_64 platforms
  • added workaround for being able to statically link against musl on aarch64 platforms. See rust issue.

Does firecracker now compile on aarch64?

Yes

cargo build --target aarch64-unknown-linux-musl
./target/aarch64-unknown-linux-musl/debug/firecracker

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@dianpopa dianpopa self-assigned this Dec 10, 2018
@dianpopa dianpopa force-pushed the i556 branch 2 times, most recently from 60510b0 to a5ba4b9 Compare December 11, 2018 11:51
Copy link
Contributor

@alexandruag alexandruag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I may have done something wrong, but I got some warnings when I tried to build the sources on an ARM instance. Maybe you can have a look if this also happens to you by running cargo clean first and then building.

version = "0.1.0"
authors = ["The Chromium OS Authors"]

[dependencies]
byteorder = "=1.2.1"
libc = ">=0.2.39"

kvm_gen = { path = "../kvm_gen" }
arch_gen = { path = "../arch_gen" }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: In the commit message you still refer to this crate (I think) as arch_sys.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed. Adjusted commit message.

@@ -1,2 +1,6 @@
[build]
target = "x86_64-unknown-linux-musl"

[target.aarch64-unknown-linux-musl]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the config file supports comments, it would be nice to add a short explanation/link regarding these particular configuration options and why the workaround is needed. We could even write it as an issue of our own, because we'll probably forget the workaround is in place here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am already referencing the original issue in the conversation of this PR and in a separate issue of our own: #756.
I also added a comment where I explain why the workaround is needed. let me know if you think something else is needed.

@@ -26,7 +26,7 @@ kernel = { path = "../kernel" }
memory_model = { path = "../memory_model" }
net_util = { path = "../net_util" }
rate_limiter = { path = "../rate_limiter" }
x86_64 = { path = "../x86_64" }
arch = { path = "../arch" }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would look nice on top of the local dependencies list, because otherwise the alphabetical order is broken. I think there is at least one more Cargo.toml where this happens.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

#[allow(non_upper_case_globals)]
#[allow(non_camel_case_types)]
#[allow(non_snake_case)]
pub mod bootparam;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this isn't fully auto generated, it would look nice to have the module declarations first, and then the impls.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

arch/src/lib.rs Outdated
ZeroPageSetup,
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
/// X86_64 specific error triggered during system configuration.
X86_64Setup(x86_64::Error),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alphabetical order ruined again.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solved.

@@ -1651,4 +1656,11 @@ pub(crate) mod tests {
// and we don't wait for our FIN to be ACKed.
assert!(c.is_done());
}

#[test]
fn test_xor_rng_u32() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is not really useful, because 1000 such comparisons don't necessarily have be true. I think we should drop this altogether, unless we're testing some meaningful statistical property of xor_rng_u32.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am failing to understand why the rdtsc (i.e number of clock cycles since reset) would return same thing upon different invocations. Can you please clarify?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rdtsc will indeed return different values for different invocations, but the comment refers to the xor_rng32 function itself. What I'm trying to say here is:

  • I'm not sure if all those bit operations from xor_rng32 will always lead to different results for different inputs (via rdtsc). Maybe we could find an answer just by doing a bit of analysis on that particular formula, but
  • Even if the previous point is false, a rng function in general makes no guarantee about generating different outputs for successive invocations, so the test is a bit semantically incongruent from that perspective also :D

arch/src/lib.rs Outdated
#[cfg(target_arch = "x86_64")]
mod x86_64;

#[cfg(not(target_arch = "x86_64"))]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not have

#[cfg(target_arch = "aarch64")]
mod aarch64;

instead of a generic template?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My intention was to firstly add a template that in a later PR I turn into aarch64 code. I removed the template all along to not be confusing.

arch/src/lib.rs Outdated
interrupts, regs, CMDLINE_START, COMMAND_LINE_SIZE, ZERO_PAGE_START,
};

#[cfg(not(target_arch = "x86_64"))]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The template vs aarch64 argument also applies here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above comment. aarch64 will come in a later PR. Removed template all along.

@@ -0,0 +1,30 @@
use memory_model::{GuestAddress, GuestMemory};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned before, I think this should be turned into a stub for aarch64, instead of a generic template. If it will eventually turn into aarch64 we might as well do it now. Otherwise, I don't really like something like this lingering in the repository. If its purpose was to document the required functionality that ppl must implement to support new architectures, we could move all this information in an actual doc somewhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See grand-previous comment.

Ok(())
}

#[cfg(not(target_arch = "x86_64"))]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should change this to #[cfg(target_arch = "aarch64")].

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed this. In a later PR this will be aarch64 labeled.

Copy link
Member

@andreeaflorescu andreeaflorescu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will do another round of reviews cause I didn't got the chance to review it all.

@@ -26,7 +26,7 @@ kernel = { path = "../kernel" }
memory_model = { path = "../memory_model" }
net_util = { path = "../net_util" }
rate_limiter = { path = "../rate_limiter" }
x86_64 = { path = "../x86_64" }
arch = { path = "../arch" }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a temporary state of affairs or is this the final solution for adding support for more architectures?

I am asking this because I always found the x86_64 crate to be out of place and renaming it to arch is not making the situation better. I would rather have it split in crates that have a better meaning. Memory related modules should be placed in the memory crate, bootparams should probably be in kernel (or better yet just have the HIMEM variable there since this is the only thing that we use from the generated file) and so on.

If this is just a temporary solution to kick start the arm support it is totally fine, but if we choose to go down this path with the design it would be interesting to know what is the reasoning in still grouping these under a single crate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andreeaflorescu , let us brainstorm to find another name for this crate. I agree that arch is not the best one.

extern crate memory_model;

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub mod x86;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case we shouldn't advertise the target_arch to both x86 and x86_64. But anyway, I don't think it makes a big difference here because the Linux headers are the same for both x86 and x86_64 so the autogenerated code will look the same for both architectures.

@dianpopa dianpopa force-pushed the i556 branch 3 times, most recently from 80ef66a to 10cb637 Compare January 8, 2019 17:41
@dianpopa
Copy link
Contributor Author

dianpopa commented Jan 8, 2019

@alexandruag As far as the warnings are related-> there is some code which is currently used only in x86 specific functions but which is not x86 specific functionality (the best example is the ioctl_with_mut_ptr from kvm/src/lib.rs). This kind of code is the one that triggers warnings right now. I think at this point it is more confusing adding a label to code that is not x86 specific than having warnings on aaarch64 build (where we do not yet have functionality).

acatangiu
acatangiu previously approved these changes Jan 16, 2019
/// Cannot set the memory regions.
SetUserMemoryRegion(sys_util::Error),
#[cfg(target_arch = "x86_64")]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we add multiple archs we might want to order errors like these by arch rather than just alphabetically.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MSRS setup is available for x86 and x86_64. You should add both here and to all the other errors as well.

@@ -15,6 +15,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "api_server"
version = "0.1.0"
dependencies = [
"arch 0.1.0",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we also discussed face-to-face I don't think that arch is a good crate name because it is too generic and can be misleading for people reading the code. When I looked at this code the first time I thought that you want to write all architecture specific code in one arch crate.
The arch crate seems to offer functionality to configure the system before/after boot and should have a name that better suggests what it is doing. I honestly don't have a better suggestion now, but we should really think about changing this name in the near future.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless someone can contribute a better name, I think arch is the right way to go. This is a standard naming convention in many projects.

IMHO renaming would only be necessary if we were to make this crate public. But in the context of an internal crate containing various arch-specific code, arch is a perfectly valid name.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really don't like that name because it doesn't say anything about the content of the crate. It is just telling me that the code there might work on many architectures or be specific to some architectures. I am not saying we should change it now, but just to be open about changing it and maybe refactor the contents of it at a later time.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch-specific-misc-code 😆

authors = ["Amazon firecracker team <firecracker-devel@amazon.com>"]

[dependencies]
memory_model = { path = "../memory_model" }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is rather strange to have an auto-generated crate having a dependency on memory-model. Can we have the dependent code in arch instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. I will take a look and see where that comes from.

}
pub type Result<T> = result::Result<T, Error>;

// Magic addresses used to lay out x86_64 VMs.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why were these moved from the layout.rs file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that some of the constants here are made public even though they do not need to be (they are hardcoded values that are used only in this crate. For example MPTABLE_START is used only once in mptable.rs and was made public or the EBDA_START which was only used in mod.rs). Variables FIRST_ADDR_PAST_32BITS and MEM_32BIT_GAP_SIZE were defined in mod.rs not in layout so there was also some inconsistency. To make things clear moved I left in the public module layout the variables that are externally used for setting up things and moved the variables that are private to this module in their specific file. I also turned the comments for each variable in layout.rs to doc comments since they need to be public.
Take a look.

@@ -14,23 +14,24 @@ use std::result;

#[derive(Debug, PartialEq)]
pub enum Error {
#[cfg(target_arch = "x86_64")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this code only x86_64 specific? I am expecting the setup to be sort of the same for both x86 and x86_64 so I don't think we should be so restrictive with errors. I suspect that changes would be minor between the 2 which means that the 2 architecture (x86 & x86_64) can share one module and have maybe just few lines specific to each architecture.

/// Cannot set the memory regions.
SetUserMemoryRegion(sys_util::Error),
#[cfg(target_arch = "x86_64")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MSRS setup is available for x86 and x86_64. You should add both here and to all the other errors as well.

@@ -28,6 +27,9 @@ rate_limiter = { path = "../rate_limiter" }
seccomp = { path = "../seccomp" }
sys_util = { path = "../sys_util" }

[target.'cfg(target_arch = "x86_64")'.dependencies]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and target_arch = "x86"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All method labeled in this commit as x86_64 should be x86_64 and x86 as per KVM API documentation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Firecracker does not run on x86 out of the box. We have x86_64 specific code inside our implementation (dumbo crate).
I do not understand why you are invoking the KVM API documentation for the vmm crate toml file. I did respect by hard the KVM API but for the kvm crate where we are implementing wrappers on the kvm api. Take a look at ioctl_defs.h and functions calling those ioctl (kvm/src/lib.rs).
By labeling this crate as x86 we are also implying that it builds on x86, right? vmm depends on the devices crate which in turn depends on dumbo (dumbo
does not build on x86, take a look at xor_rng_u32).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since Firecracker isn't supposed to support x86, I think we should not have cfg(target_arch = "x86") anywhere in the code.

In the case of a crate that we can move to crates.io, it makes sense to also do x86 as long as the crate is fully functional on x86 as well.

@@ -298,6 +298,7 @@ impl KvmContext {
check_cap(&kvm, Cap::Ioeventfd)?;
check_cap(&kvm, Cap::Irqfd)?;
// check_cap(&kvm, Cap::ImmediateExit)?;
#[cfg(target_arch = "x86_64")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

& x86 here as well.

Also,
* move the autogenerated code in a different crate named `arch_gen`
* x86_64 code code inside `arch` and `arch_gen` is labeled as such

Signed-off-by: Diana Popa <dpopa@amazon.com>
Signed-off-by: Diana Popa <dpopa@amazon.com>
On other architectures different than x86_64, the function will
return a dummy value.

Signed-off-by: Diana Popa <dpopa@amazon.com>
On other architectures, make this function return a dummy value.
Also, added unit test for the x86_64 scenarios.

Signed-off-by: Diana Popa <dpopa@amazon.com>
- Refactored crate to support addition of non-x86_64 architectures
- Labeled code accordingly
- non-x86_64 code was moved outside x86_64 folder
- Adjusted vmm related code
- Added aarch64 dummy template

Signed-off-by: Diana Popa <dpopa@amazon.com>
libc syscalls are dependent on the architecture.
Thus, "default_syscalls" is now a module that conditionally compiles
allowed syscalls depending on target architecture.

Signed-off-by: Diana Popa <dpopa@amazon.com>
* labeled x86_64 specific code
* conditonal compilation for cpuid

Signed-off-by: Diana Popa <dpopa@amazon.com>
for aarch64 musl target.

Signed-off-by: Diana Popa <dpopa@amazon.com>
Signed-off-by: Diana Popa <dpopa@amazon.com>
@acatangiu acatangiu merged commit 472e5d2 into firecracker-microvm:master Jan 18, 2019
@raduweiss raduweiss modified the milestone: ARM Support Feb 15, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants