diff --git a/.cargo/config.toml b/.cargo/config.toml index 995f555..5deb8e6 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,20 +1,20 @@ [target.armv8r-none-eabihf] # Note, this requires QEMU 9 or higher -runner = "qemu-system-arm -machine mps3-an536 -cpu cortex-r52 -semihosting -nographic -kernel" +runner = "qemu-system-arm -machine mps3-an536 -cpu cortex-r52 -semihosting -nographic -audio none -kernel" [target.armv7r-none-eabihf] -runner = "qemu-system-arm -machine versatileab -cpu cortex-r5f -semihosting -nographic -kernel" +runner = "qemu-system-arm -machine versatileab -cpu cortex-r5f -semihosting -nographic -audio none -kernel" [target.armv7r-none-eabi] # change '-mcpu=cortex-r5' to '-mcpu=cortex-r5f' if you use eabi-fpu feature, otherwise # qemu-system-arm will lock up -runner = "qemu-system-arm -machine versatileab -cpu cortex-r5 -semihosting -nographic -kernel" +runner = "qemu-system-arm -machine versatileab -cpu cortex-r5 -semihosting -nographic -audio none -kernel" [target.armv7a-none-eabihf] -runner = "qemu-system-arm -machine versatileab -cpu cortex-a8 -semihosting -nographic -kernel" +runner = "qemu-system-arm -machine versatileab -cpu cortex-a8 -semihosting -nographic -audio none -kernel" [target.armv7a-none-eabi] -runner = "qemu-system-arm -machine versatileab -cpu cortex-a8 -semihosting -nographic -kernel" +runner = "qemu-system-arm -machine versatileab -cpu cortex-a8 -semihosting -nographic -audio none -kernel" [unstable] build-std = ["core", "alloc"] diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 176f29a..198bb7f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -102,8 +102,10 @@ jobs: cargo build # Build the workspace for the target architecture but using nightly to compile libcore + # Technically it doens't need 'setup' but it makes the graph look nicer build-tier3: runs-on: ubuntu-24.04 + needs: setup strategy: matrix: target: @@ -292,15 +294,24 @@ jobs: run: | cargo test --manifest-path cortex-ar/Cargo.toml - # Run some programs in QEMU + # Run some programs in QEMU 9 qemu-test: runs-on: ubuntu-24.04 needs: [build-all] steps: - - run: sudo apt-get -y update && sudo apt-get -y install qemu-system-arm - name: Checkout uses: actions/checkout@v4 - - run: ./tests.sh + - name: Install Dependencies + run: | + sudo apt-get -y update + sudo apt-get -y install libpixman-1-0 libfdt1 libglib2.0-0t64 + - name: Install custom QEMU into /opt + run: | + curl -sSL https://github.com/jonathanpallant/qemu9-for-ubuntu-2404/releases/download/qemu-9.2.3%2Bbuild0/qemu-9.2.3-ubuntu-24.04.tar.gz | sudo tar xvzf - -C / + - name: Run tests in QEMU + run: | + export PATH=/opt/qemu/bin:$PATH + ./tests.sh # Gather all the above xxx-all jobs together for the purposes of getting an overall pass-fail all: diff --git a/examples/mps3-an536/reference/generic_timer-armv8r-none-eabihf.out b/examples/mps3-an536/reference/generic_timer-armv8r-none-eabihf.out new file mode 100644 index 0000000..4ef900d --- /dev/null +++ b/examples/mps3-an536/reference/generic_timer-armv8r-none-eabihf.out @@ -0,0 +1,23 @@ +cntfrq = 62.500 MHz +Using physical timer ************************ +Print five, every 100ms... +i = 0 +i = 1 +i = 2 +i = 3 +i = 4 +Waiting for 31250000 physical ticks to count up... +Matched! physical +Waiting for 31250000 physical ticks to count down... +physical countdown hit zero! +Using virtual timer ************************ +Print five, every 100ms... +i = 0 +i = 1 +i = 2 +i = 3 +i = 4 +Waiting for 31250000 virtual ticks to count up... +Matched! virtual +Waiting for 31250000 virtual ticks to count down... +virtual countdown hit zero! diff --git a/examples/mps3-an536/reference/gic-armv8r-none-eabihf.out b/examples/mps3-an536/reference/gic-armv8r-none-eabihf.out new file mode 100644 index 0000000..56b80a0 --- /dev/null +++ b/examples/mps3-an536/reference/gic-armv8r-none-eabihf.out @@ -0,0 +1,12 @@ +Found PERIPHBASE 0xf0000000 +Creating GIC driver @ 0xf0000000 / 0xf0100000 +Calling git.setup(0) +Configure SGI... +gic.enable_interrupt() +Enabling interrupts... +CPSR: CPSR { N=0 Z=1 C=1 V=0 Q=0 J=0 E=0 A=0 I=1 F=1 T=0 MODE=Ok(Sys) } +CPSR: CPSR { N=0 Z=1 C=1 V=0 Q=0 J=0 E=0 A=0 I=0 F=1 T=0 MODE=Ok(Sys) } +Send SGI +> IRQ +- IRQ handle SGI 3 +< IRQ diff --git a/examples/mps3-an536/reference/hello-armv8r-none-eabihf.out b/examples/mps3-an536/reference/hello-armv8r-none-eabihf.out new file mode 100644 index 0000000..c3d6c35 --- /dev/null +++ b/examples/mps3-an536/reference/hello-armv8r-none-eabihf.out @@ -0,0 +1,11 @@ +Hello, this is semihosting! x = 1.000, y = 2.000 +PANIC: PanicInfo { + message: I am an example panic, + location: Location { + file: "src/bin/hello.rs", + line: 26, + col: 5, + }, + can_unwind: true, + force_no_backtrace: false, +} diff --git a/examples/mps3-an536/reference/registers-armv8r-none-eabihf.out b/examples/mps3-an536/reference/registers-armv8r-none-eabihf.out new file mode 100644 index 0000000..2b4411f --- /dev/null +++ b/examples/mps3-an536/reference/registers-armv8r-none-eabihf.out @@ -0,0 +1,39 @@ +MIDR { implementer=0x41 variant=0x1 arch=0xf part_no=0xd13 rev=0x3 } +CPSR { N=0 Z=1 C=1 V=0 Q=0 J=0 E=0 A=0 I=1 F=1 T=0 MODE=Ok(Sys) } +IMP_CBAR { 0xf0000000 } +VBAR { 0x08000000 } +PMSA-v8 MPUIR: Mpuir { iregions: 0, dregions: 16, non_unified: false } +Region 0: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 1: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 2: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 3: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 4: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 5: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 6: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 7: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 8: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 9: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 10: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 11: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 12: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 13: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 14: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 15: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 0: Region { range: 0x0..=0x3fffffff, shareability: OuterShareable, access: ReadWrite, no_exec: true, mair: 0, enable: true } +Region 1: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 2: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 3: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 4: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 5: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 6: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 7: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 8: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 9: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 10: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 11: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 12: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 13: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 14: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +Region 15: Region { range: 0x0..=0x3f, shareability: NonShareable, access: ReadWriteNoEL0, no_exec: false, mair: 0, enable: false } +SCTLR { IE=0 TE=0 NMFI=0 EE=0 U=1 FI=0 DZ=1 BR=1 RR=0 V=0 I=0 Z=1 SW=0 C=0 A=0 M=0 } before setting C, I and Z +SCTLR { IE=0 TE=0 NMFI=0 EE=0 U=1 FI=0 DZ=1 BR=1 RR=0 V=0 I=1 Z=1 SW=0 C=1 A=0 M=0 } after diff --git a/examples/mps3-an536/reference/svc-armv8r-none-eabihf.out b/examples/mps3-an536/reference/svc-armv8r-none-eabihf.out new file mode 100644 index 0000000..fee2bd6 --- /dev/null +++ b/examples/mps3-an536/reference/svc-armv8r-none-eabihf.out @@ -0,0 +1,14 @@ +x = 1, y = 2, z = 3.000 +In _svc_handler, with arg=0xabcdef +In _svc_handler, with arg=0x456789 +x = 1, y = 2, z = 3.000 +PANIC: PanicInfo { + message: I am an example panic, + location: Location { + file: "src/bin/svc.rs", + line: 29, + col: 5, + }, + can_unwind: true, + force_no_backtrace: false, +} diff --git a/examples/mps3-an536/src/bin/generic_timer.rs b/examples/mps3-an536/src/bin/generic_timer.rs index 4d19b59..00ca739 100644 --- a/examples/mps3-an536/src/bin/generic_timer.rs +++ b/examples/mps3-an536/src/bin/generic_timer.rs @@ -23,7 +23,7 @@ fn main() { let cntfrq = cortex_ar::register::Cntfrq::read().0; println!("cntfrq = {:.03} MHz", cntfrq as f32 / 1_000_000.0); - let delay_ticks = cntfrq * 2; + let delay_ticks = cntfrq / 2; let mut pgt = unsafe { El1PhysicalTimer::new() }; let mut vgt = unsafe { El1VirtualTimer::new() }; @@ -34,21 +34,20 @@ fn main() { for (timer, name) in [(pgt_ref, "physical"), (vgt_ref, "virtual")] { println!("Using {} timer ************************", name); - println!("Print five, one per second..."); + println!("Print five, every 100ms..."); for i in 0..5 { println!("i = {}", i); - timer.delay_ms(1000); + timer.delay_ms(100); } let now = timer.counter(); - println!("{} is now: {}", name, now); println!("Waiting for {} {} ticks to count up...", delay_ticks, name); timer.counter_compare_set(now + delay_ticks as u64); timer.enable(true); while !timer.interrupt_status() { core::hint::spin_loop(); } - println!("Matched! {} count now {}", name, timer.counter()); + println!("Matched! {}", name); println!( "Waiting for {} {} ticks to count down...", @@ -58,10 +57,6 @@ fn main() { while !timer.interrupt_status() { core::hint::spin_loop(); } - println!( - "{} countdown hit zero! (and is now {})", - name, - timer.countdown() as i32 - ); + println!("{} countdown hit zero!", name,); } } diff --git a/tests.sh b/tests.sh index 6b4ba05..7fe2653 100755 --- a/tests.sh +++ b/tests.sh @@ -6,6 +6,8 @@ rustup target add armv7r-none-eabi rustup target add armv7r-none-eabihf rustup target add armv7a-none-eabi +rustup toolchain add nightly +rustup component add rust-src --toolchain=nightly FAILURE=0 @@ -19,31 +21,45 @@ fail() { mkdir -p ./target versatile_ab_cargo="--manifest-path examples/versatileab/Cargo.toml" +mps3_an536_cargo="--manifest-path examples/mps3-an536/Cargo.toml" + +my_diff() { + file_a=$1 + file_b=$2 + # - Fix Windows path separators (\\) to look like UNIX ones (/) in the QEMU + # output + # - Fix the CRLF line endings in the files on disk, because git adds them to + # text files. + diff <(cat $file_a | tr -d '\r') <(cat $file_b | sed 's~\\\\~/~g') +} # armv7r-none-eabi tests for binary in hello registers svc; do cargo run ${versatile_ab_cargo} --target=armv7r-none-eabi --bin $binary | tee ./target/$binary-armv7r-none-eabi.out - diff ./examples/versatileab/reference/$binary-armv7r-none-eabi.out ./target/$binary-armv7r-none-eabi.out || fail $binary "armv7r-none-eabi" + my_diff ./examples/versatileab/reference/$binary-armv7r-none-eabi.out ./target/$binary-armv7r-none-eabi.out || fail $binary "armv7r-none-eabi" done # armv7r-none-eabihf tests for binary in hello registers svc undef-exception prefetch-exception abt-exception; do cargo run ${versatile_ab_cargo} --target=armv7r-none-eabihf --bin $binary | tee ./target/$binary-armv7r-none-eabihf.out - diff ./examples/versatileab/reference/$binary-armv7r-none-eabihf.out ./target/$binary-armv7r-none-eabihf.out || fail $binary "armv7r-none-eabihf" + my_diff ./examples/versatileab/reference/$binary-armv7r-none-eabihf.out ./target/$binary-armv7r-none-eabihf.out || fail $binary "armv7r-none-eabihf" done # armv7a-none-eabi tests for binary in hello registers svc undef-exception prefetch-exception abt-exception; do cargo run ${versatile_ab_cargo} --target=armv7a-none-eabi --bin $binary | tee ./target/$binary-armv7a-none-eabi.out - diff ./examples/versatileab/reference/$binary-armv7a-none-eabi.out ./target/$binary-armv7a-none-eabi.out || fail $binary "armv7a-none-eabi" + my_diff ./examples/versatileab/reference/$binary-armv7a-none-eabi.out ./target/$binary-armv7a-none-eabi.out || fail $binary "armv7a-none-eabi" done +# These tests only run on QEMU 9 or higher. # Ubuntu 24.04 supplies QEMU 8, which doesn't support the machine we have configured for this target -# # armv8r-none-eabihf tests -# for binary in hello registers svc gic; do -# cargo +nightly run --target=armv8r-none-eabihf --bin $binary --features=gic -Zbuild-std=core | tee ./target/$binary-armv8r-none-eabihf.out -# diff ./cortex-r-examples/reference/$binary-armv8r-none-eabihf.out ./target/$binary-armv8r-none-eabihf.out || fail $binary "armv8r-none-eabihf" -# done +if qemu-system-arm --version | grep "version 9"; then + # armv8r-none-eabihf tests + for binary in hello registers svc gic generic_timer; do + cargo +nightly run ${mps3_an536_cargo} --target=armv8r-none-eabihf --bin $binary --features=gic -Zbuild-std=core | tee ./target/$binary-armv8r-none-eabihf.out + my_diff ./examples/mps3-an536/reference/$binary-armv8r-none-eabihf.out ./target/$binary-armv8r-none-eabihf.out || fail $binary "armv8r-none-eabihf" + done +fi if [ "$FAILURE" == "1" ]; then echo "***************************************************"