diff --git a/Cargo.lock b/Cargo.lock index b2a787ca..2126bc5d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,16 +3,19 @@ version = 3 [[package]] -name = "align-address" -version = "0.1.0" +name = "aarch64-cpu" +version = "9.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d39c09fbfba977f4842e1f6bdc48b979112b64f8886993a34e051bc5f3c5c288" +checksum = "ac42a04a61c19fc8196dd728022a784baecc5d63d7e256c01ad1b3fbfab26287" +dependencies = [ + "tock-registers", +] [[package]] -name = "align-data" +name = "align-address" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1926655ba000b19e21f0402be09a1d52d318c8a8a68622870bfb7af2a71315cd" +checksum = "d39c09fbfba977f4842e1f6bdc48b979112b64f8886993a34e051bc5f3c5c288" [[package]] name = "allocator-api2" @@ -141,8 +144,8 @@ dependencies = [ name = "hermit-loader" version = "0.4.5" dependencies = [ + "aarch64-cpu", "align-address", - "align-data", "allocator-api2", "cc", "exclusive_cell", @@ -387,6 +390,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +[[package]] +name = "tock-registers" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "696941a0aee7e276a165a978b37918fd5d22c55c3d6bda197813070ca9c0f21c" + [[package]] name = "uart_16550" version = "0.3.0" diff --git a/Cargo.toml b/Cargo.toml index e466eb39..a08c7229 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ uart_16550 = "0.3" x86_64 = { version = "0.14", default-features = false, features = ["instructions"] } [target.'cfg(target_arch = "aarch64")'.dependencies] -align-data = "0.1" +aarch64-cpu = "9" hermit-dtb = { version = "0.1" } goblin = { version = "0.8", default-features = false, features = ["elf64"] } diff --git a/src/arch/aarch64/entry.rs b/src/arch/aarch64/entry.rs index 8c37bfaf..248e4851 100644 --- a/src/arch/aarch64/entry.rs +++ b/src/arch/aarch64/entry.rs @@ -2,6 +2,7 @@ use core::arch::{asm, global_asm}; +use aarch64_cpu::registers::{Writeable, SCTLR_EL1}; use log::info; extern "C" { @@ -53,17 +54,21 @@ global_asm!(include_str!("entry.s")); #[no_mangle] #[link_section = ".text._start"] pub unsafe fn _start_rust() -> ! { - pre_init() + unsafe { pre_init() } } unsafe fn pre_init() -> ! { info!("Enter startup code"); /* disable interrupts */ - asm!("msr daifset, 0b111", options(nostack),); + unsafe { + asm!("msr daifset, 0b111", options(nostack)); + } /* reset thread id registers */ - asm!("msr tpidr_el0, xzr", "msr tpidr_el1, xzr", options(nostack),); + unsafe { + asm!("msr tpidr_el0, xzr", "msr tpidr_el1, xzr", options(nostack)); + } /* * Disable the MMU. We may have entered the kernel with it on and @@ -72,16 +77,20 @@ unsafe fn pre_init() -> ! { * but in this case the code to find where we are running from * would have also failed. */ - asm!("dsb sy", - "mrs x2, sctlr_el1", - "bic x2, x2, 0x1", - "msr sctlr_el1, x2", - "isb", - out("x2") _, - options(nostack), - ); + unsafe { + asm!("dsb sy", + "mrs x2, sctlr_el1", + "bic x2, x2, 0x1", + "msr sctlr_el1, x2", + "isb", + out("x2") _, + options(nostack), + ); + } - asm!("ic iallu", "tlbi vmalle1is", "dsb ish", options(nostack),); + unsafe { + asm!("ic iallu", "tlbi vmalle1is", "dsb ish", options(nostack)); + } /* * Setup memory attribute type tables @@ -101,44 +110,54 @@ unsafe fn pre_init() -> ! { | mair(0x0c, MT_DEVICE_GRE) | mair(0x44, MT_NORMAL_NC) | mair(0xff, MT_NORMAL); - asm!("msr mair_el1, {}", - in(reg) mair_el1, - options(nostack), - ); + unsafe { + asm!("msr mair_el1, {}", + in(reg) mair_el1, + options(nostack), + ); + } /* * Setup translation control register (TCR) */ // determine physical address size - asm!("mrs x0, id_aa64mmfr0_el1", - "and x0, x0, 0xF", - "lsl x0, x0, 32", - "orr x0, x0, {tcr_bits}", - "mrs x1, id_aa64mmfr0_el1", - "bfi x0, x1, #32, #3", - "msr tcr_el1, x0", - tcr_bits = in(reg) tcr_size(VA_BITS) | TCR_TG1_4K | TCR_FLAGS, - out("x0") _, - out("x1") _, - ); + unsafe { + asm!("mrs x0, id_aa64mmfr0_el1", + "and x0, x0, 0xF", + "lsl x0, x0, 32", + "orr x0, x0, {tcr_bits}", + "mrs x1, id_aa64mmfr0_el1", + "bfi x0, x1, #32, #3", + "msr tcr_el1, x0", + tcr_bits = in(reg) tcr_size(VA_BITS) | TCR_TG1_4K | TCR_FLAGS, + out("x0") _, + out("x1") _, + ); + } /* * Enable FP/ASIMD in Architectural Feature Access Control Register, */ let bit_mask: u64 = 3 << 20; - asm!("msr cpacr_el1, {mask}", - mask = in(reg) bit_mask, - options(nostack), - ); + unsafe { + asm!("msr cpacr_el1, {mask}", + mask = in(reg) bit_mask, + options(nostack), + ); + } /* * Reset debug control register */ - asm!("msr mdscr_el1, xzr", options(nostack)); + unsafe { + asm!("msr mdscr_el1, xzr", options(nostack)); + } /* Memory barrier */ - asm!("dsb sy", options(nostack)); + unsafe { + asm!("dsb sy", options(nostack)); + } /* * Prepare system control register (SCTRL) @@ -148,51 +167,38 @@ unsafe fn pre_init() -> ! { - Fill in the missing Documentation for some of the bits and verify if we care about them or if loading and not setting them would be the appropriate action. */ - let sctrl_el1: u64 = 0 - | (1 << 26) /* UCI Enables EL0 access in AArch64 for DC CVAU, DC CIVAC, - DC CVAC and IC IVAU instructions */ - | (0 << 25) /* EE Explicit data accesses at EL1 and Stage 1 translation - table walks at EL1 & EL0 are little-endian */ - | (0 << 24) /* EOE Explicit data accesses at EL0 are little-endian */ - | (1 << 23) - | (1 << 22) - | (1 << 20) - | (0 << 19) /* WXN Regions with write permission are not forced to XN */ - | (1 << 18) /* nTWE WFE instructions are executed as normal */ - | (0 << 17) - | (1 << 16) /* nTWI WFI instructions are executed as normal */ - | (1 << 15) /* UCT Enables EL0 access in AArch64 to the CTR_EL0 register */ - | (1 << 14) /* DZE Execution of the DC ZVA instruction is allowed at EL0 */ - | (0 << 13) - | (1 << 12) /* I Instruction caches enabled at EL0 and EL1 */ - | (1 << 11) - | (0 << 10) - | (0 << 9) /* UMA Disable access to the interrupt masks from EL0 */ - | (1 << 8) /* SED The SETEND instruction is available */ - | (0 << 7) /* ITD The IT instruction functionality is available */ - | (0 << 6) /* THEE ThumbEE is disabled */ - | (0 << 5) /* CP15BEN CP15 barrier operations disabled */ - | (1 << 4) /* SA0 Stack Alignment check for EL0 enabled */ - | (1 << 3) /* SA Stack Alignment check enabled */ - | (1 << 2) /* C Data and unified enabled */ - | (0 << 1) /* A Alignment fault checking disabled */ - | (0 << 0) /* M MMU enable */ - ; - - asm!( - "msr sctlr_el1, {0}", - in(reg) sctrl_el1, - options(nostack), + + SCTLR_EL1.write( + SCTLR_EL1::UCI::DontTrap + + SCTLR_EL1::EE::LittleEndian + + SCTLR_EL1::E0E::LittleEndian + + SCTLR_EL1::WXN::Disable + + SCTLR_EL1::NTWE::DontTrap + + SCTLR_EL1::NTWI::DontTrap + + SCTLR_EL1::UCT::DontTrap + + SCTLR_EL1::DZE::DontTrap + + SCTLR_EL1::I::Cacheable + + SCTLR_EL1::UMA::Trap + + SCTLR_EL1::NAA::Disable + + SCTLR_EL1::SA0::Enable + + SCTLR_EL1::SA::Enable + + SCTLR_EL1::C::Cacheable + + SCTLR_EL1::A::Disable + + SCTLR_EL1::M::Disable, ); // Enter loader - loader_main(); + unsafe { + loader_main(); + } unreachable!() } pub unsafe fn wait_forever() -> ! { loop { - asm!("wfe") + unsafe { + asm!("wfe"); + } } } diff --git a/src/arch/aarch64/mod.rs b/src/arch/aarch64/mod.rs index 83ea4290..744027f3 100644 --- a/src/arch/aarch64/mod.rs +++ b/src/arch/aarch64/mod.rs @@ -57,7 +57,7 @@ pub fn message_output_init() { let stdout = core::str::from_utf8(stdout) .unwrap() .trim_matches(char::from(0)); - if let Some(pos) = stdout.find("@") { + if let Some(pos) = stdout.find('@') { let len = stdout.len(); u32::from_str_radix(&stdout[pos + 1..len], 16).unwrap_or(SERIAL_PORT_ADDRESS) } else { @@ -79,7 +79,7 @@ pub fn output_message_byte(byte: u8) { } pub unsafe fn get_memory(_memory_size: u64) -> u64 { - (&kernel_end as *const u8 as u64).align_up(LargePageSize::SIZE as u64) + (unsafe { &kernel_end } as *const u8 as u64).align_up(LargePageSize::SIZE as u64) } pub fn find_kernel() -> &'static [u8] { @@ -98,7 +98,7 @@ pub fn find_kernel() -> &'static [u8] { } else if let Some(value) = value.strip_prefix("0X") { usize::from_str_radix(value, 16).unwrap() } else { - usize::from_str_radix(value, 10).unwrap() + value.parse().unwrap() } }) .unwrap(); @@ -107,10 +107,8 @@ pub fn find_kernel() -> &'static [u8] { &*core::mem::transmute::<*const u8, *const Header>(sptr::from_exposed_addr(module_start)) }; - for i in 0..SELFMAG { - if header.e_ident[i] != ELFMAG[i] { - panic!("Don't found valid ELF file!"); - } + if header.e_ident[0..SELFMAG] != ELFMAG[..] { + panic!("Don't found valid ELF file!"); } #[cfg(target_endian = "little")] @@ -155,69 +153,77 @@ pub unsafe fn boot_kernel(kernel_info: LoadedKernel) -> ! { let uart_address: u32 = unsafe { COM1.get_port() }; info!("Detect UART at {:#x}", uart_address); - let pgt_slice = core::slice::from_raw_parts_mut(&mut l0_pgtable as *mut u64, 512); + let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&mut l0_pgtable as *mut u64, 512) }; for i in pgt_slice.iter_mut() { *i = 0; } - pgt_slice[0] = &l1_pgtable as *const u64 as u64 + PT_PT; - pgt_slice[511] = &l0_pgtable as *const u64 as u64 + PT_PT + PT_SELF; + pgt_slice[0] = unsafe { &l1_pgtable as *const u64 as u64 + PT_PT }; + pgt_slice[511] = unsafe { &l0_pgtable as *const u64 as u64 + PT_PT + PT_SELF }; - let pgt_slice = core::slice::from_raw_parts_mut(&mut l1_pgtable as *mut u64, 512); + let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&mut l1_pgtable as *mut u64, 512) }; for i in pgt_slice.iter_mut() { *i = 0; } - pgt_slice[0] = &l2_pgtable as *const _ as u64 + PT_PT; - pgt_slice[1] = &l2k_pgtable as *const _ as u64 + PT_PT; + pgt_slice[0] = unsafe { &l2_pgtable as *const _ as u64 + PT_PT }; + pgt_slice[1] = unsafe { &l2k_pgtable as *const _ as u64 + PT_PT }; - let pgt_slice = core::slice::from_raw_parts_mut(&mut l2_pgtable as *mut u64, 512); + let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&mut l2_pgtable as *mut u64, 512) }; for i in pgt_slice.iter_mut() { *i = 0; } - pgt_slice[0] = &l3_pgtable as *const u64 as u64 + PT_PT; + pgt_slice[0] = unsafe { &l3_pgtable as *const u64 as u64 + PT_PT }; - let pgt_slice = core::slice::from_raw_parts_mut(&mut l3_pgtable as *mut u64, 512); + let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&mut l3_pgtable as *mut u64, 512) }; for i in pgt_slice.iter_mut() { *i = 0; } pgt_slice[1] = uart_address as u64 + PT_MEM_CD; // map kernel to KERNEL_START and stack below the kernel - let pgt_slice = core::slice::from_raw_parts_mut(&mut l2k_pgtable as *mut u64, 512); + let pgt_slice = unsafe { core::slice::from_raw_parts_mut(&mut l2k_pgtable as *mut u64, 512) }; for i in pgt_slice.iter_mut() { *i = 0; } - for i in 0..10 { - pgt_slice[i] = - &mut L0mib_pgtable as *mut _ as u64 + (i * BasePageSize::SIZE) as u64 + PT_PT; + for (i, pgt_slice) in pgt_slice.iter_mut().enumerate().take(10) { + *pgt_slice = unsafe { &mut L0mib_pgtable } as *mut _ as u64 + + (i * BasePageSize::SIZE) as u64 + + PT_PT; } - let pgt_slice = core::slice::from_raw_parts_mut(&mut L0mib_pgtable as *mut u64, 10 * 512); + let pgt_slice = + unsafe { core::slice::from_raw_parts_mut(&mut L0mib_pgtable as *mut u64, 10 * 512) }; for (i, entry) in pgt_slice.iter_mut().enumerate() { *entry = RAM_START + (i * BasePageSize::SIZE) as u64 + PT_MEM; } - COM1.set_port(0x1000); + unsafe { + COM1.set_port(0x1000); + } // Load TTBRx - asm!( - "msr ttbr1_el1, xzr", - "msr ttbr0_el1, {}", - "dsb sy", - "isb", - in(reg) &l0_pgtable as *const _ as u64, - options(nostack), - ); + unsafe { + asm!( + "msr ttbr1_el1, xzr", + "msr ttbr0_el1, {}", + "dsb sy", + "isb", + in(reg) &l0_pgtable as *const _ as u64, + options(nostack), + ); + } // Enable paging - asm!( - "mrs x0, sctlr_el1", - "orr x0, x0, #1", - "msr sctlr_el1, x0", - "bl 0f", - "0:", - out("x0") _, - options(nostack), - ); + unsafe { + asm!( + "mrs x0, sctlr_el1", + "orr x0, x0, #1", + "msr sctlr_el1, x0", + "bl 0f", + "0:", + out("x0") _, + options(nostack), + ); + } let current_stack_address = load_info.kernel_image_addr_range.start - KERNEL_STACK_SIZE as u64; pub static mut BOOT_INFO: Option = None; @@ -239,7 +245,7 @@ pub unsafe fn boot_kernel(kernel_info: LoadedKernel) -> ! { let ram_start = u64::from_be_bytes(start_slice.try_into().unwrap()); let ram_size = u64::from_be_bytes(size_slice.try_into().unwrap()); - BOOT_INFO = { + let boot_info = { let boot_info = BootInfo { hardware_info: HardwareInfo { phys_addr_range: ram_start..ram_start + ram_size, @@ -249,9 +255,13 @@ pub unsafe fn boot_kernel(kernel_info: LoadedKernel) -> ! { load_info, platform_info: PlatformInfo::LinuxBoot, }; - Some(RawBootInfo::from(boot_info)) + RawBootInfo::from(boot_info) }; + unsafe { + BOOT_INFO = Some(boot_info); + } + // Jump to the kernel entry point and provide the Multiboot information to it. info!( "Jumping to HermitCore Application Entry Point at {:#x}", @@ -259,7 +269,9 @@ pub unsafe fn boot_kernel(kernel_info: LoadedKernel) -> ! { ); /* Memory barrier */ - asm!("dsb sy", options(nostack)); + unsafe { + asm!("dsb sy", options(nostack)); + } #[allow(dead_code)] const ENTRY_TYPE_CHECK: Entry = { @@ -272,13 +284,15 @@ pub unsafe fn boot_kernel(kernel_info: LoadedKernel) -> ! { entry_signature }; - asm!( - "mov sp, {stack_address}", - "br {entry}", - stack_address = in(reg) current_stack_address, - entry = in(reg) entry_point, - in("x0") BOOT_INFO.as_ref().unwrap(), - in("x1") 0, - options(noreturn) - ); + unsafe { + asm!( + "mov sp, {stack_address}", + "br {entry}", + stack_address = in(reg) current_stack_address, + entry = in(reg) entry_point, + in("x0") BOOT_INFO.as_ref().unwrap(), + in("x1") 0, + options(noreturn) + ) + } } diff --git a/src/arch/aarch64/serial.rs b/src/arch/aarch64/serial.rs index b9607a08..bdc51c0c 100644 --- a/src/arch/aarch64/serial.rs +++ b/src/arch/aarch64/serial.rs @@ -8,11 +8,13 @@ impl SerialPort { } pub unsafe fn set_port(&mut self, addr: u32) { - core::ptr::write_volatile(&mut self.port_address, addr); + unsafe { + core::ptr::write_volatile(&mut self.port_address, addr); + } } pub unsafe fn get_port(&self) -> u32 { - core::ptr::read_volatile(&self.port_address) + unsafe { core::ptr::read_volatile(&self.port_address) } } pub fn write_byte(&self, byte: u8) { diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 31f20e14..f15feb77 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -142,11 +142,14 @@ impl flags::Clippy { fn run(self) -> Result<()> { let sh = Shell::new()?; - // TODO: Enable clippy for aarch64 - // https://github.com/hermitcore/loader/issues/78 // TODO: Enable clippy for x86_64-uefi // https://github.com/hermitcore/loader/issues/122 - for target in [Target::X86_64, Target::X86_64Fc, Target::Riscv64] { + for target in [ + Target::X86_64, + Target::X86_64Fc, + Target::AArch64, + Target::Riscv64, + ] { target.install()?; let triple = target.triple(); let feature_flags = target.feature_flags();