fix(qemu): select the rva23s64 CPU for riscv64 under TCG
Ubuntu builds its riscv64 port against the RVA23 profile (since 25.10), and QEMU's default rv64 CPU does not implement all profile extensions: Ubuntu binaries die with SIGILL during init and the kernel panics with 'Attempted to kill init'. Select the rva23s64 profile CPU (QEMU 10.1+) for riscv64 under TCG; profiles are supersets, so baseline rv64gc rootfses run unchanged on it. KVM mode keeps -cpu host.
This commit is contained in:
@@ -159,6 +159,9 @@ pub fn launch_qemu(config: QemuConfig) -> Result<()> {
|
|||||||
args.push("-enable-kvm".to_string());
|
args.push("-enable-kvm".to_string());
|
||||||
args.push("-cpu".to_string());
|
args.push("-cpu".to_string());
|
||||||
args.push("host".to_string());
|
args.push("host".to_string());
|
||||||
|
} else if let Some(cpu) = cpu_for_arch(&config.arch) {
|
||||||
|
args.push("-cpu".to_string());
|
||||||
|
args.push(cpu.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute QEMU
|
// Execute QEMU
|
||||||
@@ -201,6 +204,22 @@ fn machine_for_arch(arch: &str) -> Option<&'static str> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the QEMU TCG CPU model to select for the target architecture, when
|
||||||
|
/// the emulator default is not sufficient.
|
||||||
|
///
|
||||||
|
/// Ubuntu builds its riscv64 port against the RVA23 profile (since 25.10),
|
||||||
|
/// so its binaries execute instructions QEMU's default `rv64` CPU does not
|
||||||
|
/// implement and die with SIGILL early in boot. `rva23s64` implements the
|
||||||
|
/// full supervisor profile; baseline rv64gc rootfses (Alpine, older
|
||||||
|
/// Ubuntu) run unchanged on it because profiles are supersets. The named
|
||||||
|
/// profile CPU needs QEMU 10.1+.
|
||||||
|
fn cpu_for_arch(arch: &str) -> Option<&'static str> {
|
||||||
|
match crate::utils::Arch::from_str(arch) {
|
||||||
|
crate::utils::Arch::Riscv64 => Some("rva23s64"),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get architecture suffix for package names
|
/// Get architecture suffix for package names
|
||||||
fn get_arch_package_suffix(arch: &str) -> &'static str {
|
fn get_arch_package_suffix(arch: &str) -> &'static str {
|
||||||
crate::utils::Arch::from_str(arch).qemu_package_suffix()
|
crate::utils::Arch::from_str(arch).qemu_package_suffix()
|
||||||
@@ -635,6 +654,18 @@ mod tests {
|
|||||||
assert_eq!(machine_for_arch("s390x"), None);
|
assert_eq!(machine_for_arch("s390x"), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_cpu_for_arch() {
|
||||||
|
// Ubuntu's riscv64 userland needs the RVA23 profile CPU; QEMU's
|
||||||
|
// default `rv64` CPU SIGILLs on it early in boot
|
||||||
|
assert_eq!(cpu_for_arch("riscv64"), Some("rva23s64"));
|
||||||
|
// Other architectures keep their emulator's default CPU
|
||||||
|
assert_eq!(cpu_for_arch("amd64"), None);
|
||||||
|
assert_eq!(cpu_for_arch("x86_64"), None);
|
||||||
|
assert_eq!(cpu_for_arch("arm64"), None);
|
||||||
|
assert_eq!(cpu_for_arch("aarch64"), None);
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse a newc cpio archive into (name, ino, mode, nlink, file_size, data) tuples
|
/// Parse a newc cpio archive into (name, ino, mode, nlink, file_size, data) tuples
|
||||||
fn parse_cpio(archive: Vec<u8>) -> Vec<(String, u32, u32, u32, u32, Vec<u8>)> {
|
fn parse_cpio(archive: Vec<u8>) -> Vec<(String, u32, u32, u32, u32, Vec<u8>)> {
|
||||||
let mut cursor = std::io::Cursor::new(archive);
|
let mut cursor = std::io::Cursor::new(archive);
|
||||||
|
|||||||
Reference in New Issue
Block a user