@@ -341,7 +341,6 @@ fn call_malloc(size: i32) -> i32 {
341341}
342342
343343#[ guest_function( "FillHeapAndCauseException" ) ]
344- #[ cfg( target_arch = "x86_64" ) ]
345344fn fill_heap_and_cause_exception ( ) {
346345 let layout: Layout = Layout :: new :: < u8 > ( ) ;
347346 let mut ptr = unsafe { alloc:: alloc:: alloc_zeroed ( layout) } ;
@@ -351,7 +350,7 @@ fn fill_heap_and_cause_exception() {
351350 }
352351
353352 // trigger an undefined instruction exception
354- unsafe { core :: arch :: asm! ( "ud2" ) } ;
353+ trigger_exception ( ) ;
355354}
356355
357356#[ guest_function( "ExhaustHeap" ) ]
@@ -452,7 +451,13 @@ fn test_guest_panic(message: String) {
452451fn execute_on_heap ( ) -> String {
453452 unsafe {
454453 // NO-OP followed by RET
455- let heap_memory = Box :: new ( [ 0x90u8 , 0xC3 ] ) ;
454+ let mut heap_memory = Box :: new (
455+ #[ cfg( target_arch = "x86_64" ) ]
456+ [ 0x90u8 , 0xC3 ] ,
457+ #[ cfg( target_arch = "aarch64" ) ]
458+ [ 0x1f , 0x20 , 0x03 , 0xd5 , 0xc0 , 0x03 , 0x5f , 0xd6 ] ,
459+ ) ;
460+ dicachesync ( heap_memory. as_mut_ptr ( ) , heap_memory. len ( ) ) ;
456461 let heap_fn: fn ( ) = core:: mem:: transmute ( Box :: into_raw ( heap_memory) ) ;
457462 heap_fn ( ) ;
458463 black_box ( heap_fn) ; // avoid optimization when running in release mode
@@ -485,17 +490,23 @@ fn log_message(message: String, level: i32) {
485490}
486491
487492#[ guest_function( "TriggerException" ) ]
488- #[ cfg( target_arch = "x86_64" ) ]
489493fn trigger_exception ( ) {
490494 // trigger an undefined instruction exception
491- unsafe { core:: arch:: asm!( "ud2" ) } ;
495+ #[ cfg( target_arch = "x86_64" ) ]
496+ unsafe {
497+ core:: arch:: asm!( "ud2" )
498+ } ;
499+ #[ cfg( target_arch = "aarch64" ) ]
500+ unsafe {
501+ core:: arch:: asm!( "udf #0" )
502+ } ;
492503}
493504
494505/// Execute an OUT instruction with an arbitrary port and value.
495506/// This is used to test that invalid OUT ports cause errors.
496507#[ guest_function( "OutbWithPort" ) ]
497- #[ cfg( target_arch = "x86_64" ) ]
498508fn outb_with_port ( port : u32 , value : u32 ) {
509+ #[ cfg( target_arch = "x86_64" ) ]
499510 unsafe {
500511 core:: arch:: asm!(
501512 "out dx, eax" ,
@@ -504,6 +515,12 @@ fn outb_with_port(port: u32, value: u32) {
504515 options( preserves_flags, nomem, nostack)
505516 ) ;
506517 }
518+ #[ cfg( target_arch = "aarch64" ) ]
519+ unsafe {
520+ ( hyperlight_common:: layout:: io_page ( ) . unwrap ( ) . 1 as * mut u64 )
521+ . wrapping_add ( port as usize )
522+ . write_volatile ( value as u64 ) ;
523+ }
507524}
508525
509526// =============================================================================
@@ -716,16 +733,28 @@ fn use_sse2_registers() {
716733}
717734
718735#[ guest_function( "SetDr0" ) ]
719- #[ cfg( target_arch = "x86_64" ) ]
720736fn set_dr0 ( value : u64 ) {
721- unsafe { core:: arch:: asm!( "mov dr0, {}" , in( reg) value) } ;
737+ #[ cfg( target_arch = "x86_64" ) ]
738+ unsafe {
739+ core:: arch:: asm!( "mov dr0, {}" , in( reg) value)
740+ } ;
741+ #[ cfg( target_arch = "aarch64" ) ]
742+ unsafe {
743+ core:: arch:: asm!( "msr dbgbvr0_el1, {}" , in( reg) value)
744+ } ;
722745}
723746
724747#[ guest_function( "GetDr0" ) ]
725- #[ cfg( target_arch = "x86_64" ) ]
726748fn get_dr0 ( ) -> u64 {
727749 let value: u64 ;
728- unsafe { core:: arch:: asm!( "mov {}, dr0" , out( reg) value) } ;
750+ #[ cfg( target_arch = "x86_64" ) ]
751+ unsafe {
752+ core:: arch:: asm!( "mov {}, dr0" , out( reg) value)
753+ } ;
754+ #[ cfg( target_arch = "aarch64" ) ]
755+ unsafe {
756+ core:: arch:: asm!( "mrs {}, dbgbvr0_el1" , out( reg) value)
757+ } ;
729758 value
730759}
731760
@@ -759,7 +788,6 @@ fn read_from_user_memory(num: u64, expected: Vec<u8>) -> Result<Vec<u8>> {
759788 Ok ( bytes)
760789}
761790
762- #[ cfg( target_arch = "x86_64" ) ]
763791#[ guest_function( "ReadMappedBuffer" ) ]
764792fn read_mapped_buffer ( base : u64 , len : u64 , do_map : bool ) -> Vec < u8 > {
765793 let base = base as usize as * const u8 ;
@@ -786,15 +814,13 @@ fn read_mapped_buffer(base: u64, len: u64, do_map: bool) -> Vec<u8> {
786814 data. to_vec ( )
787815}
788816
789- #[ cfg( target_arch = "x86_64" ) ]
790817#[ guest_function( "CheckMapped" ) ]
791818fn check_mapped_buffer ( base : u64 ) -> bool {
792819 hyperlight_guest_bin:: paging:: virt_to_phys ( base)
793820 . next ( )
794821 . is_some ( )
795822}
796823
797- #[ cfg( target_arch = "x86_64" ) ]
798824#[ guest_function( "WriteMappedBuffer" ) ]
799825fn write_mapped_buffer ( base : u64 , len : u64 ) -> bool {
800826 let base = base as usize as * mut u8 ;
@@ -823,7 +849,60 @@ fn write_mapped_buffer(base: u64, len: u64) -> bool {
823849 true
824850}
825851
826- #[ cfg( target_arch = "x86_64" ) ]
852+ fn dicachesync ( _base : * mut u8 , _len : usize ) {
853+ #[ cfg( target_arch = "aarch64" ) ]
854+ unsafe {
855+ let ctr_el0: u64 ;
856+ core:: arch:: asm!( "mrs {}, ctr_el0" , out( reg) ctr_el0) ;
857+ let iminline = 4 * ( 1 << ( ctr_el0 & 0xf ) ) ;
858+ #[ allow( unused) ]
859+ let dminline = 4 * ( 1 << ( ( ctr_el0 >> 16 ) & 0xf ) ) ;
860+ // See the comment in the `KVM_EXIT_ARM_NISV` case of
861+ // `run_vcpu` in
862+ // src/hyperlight_host/src/hypervisor/virtual_machine/kvm.rs
863+ // for an explanation of why this cache maintenance sequence
864+ // is so complex.
865+ core:: arch:: asm!( "
866+ ldr xzr, [{addr}]
867+ msr nzcv, xzr
868+ b 2f
869+
870+ 0: ldr xzr, [{tmp}]
871+ msr nzcv, xzr
872+ b 3f
873+ 1: ldr xzr, [{tmp}]
874+ msr nzcv, xzr
875+ b 4f
876+
877+ 2: mov {tmp}, {addr}
878+
879+ 3: dc cvau, {tmp}
880+ b.eq 0b
881+ add {tmp}, {tmp}, {dminline:x}
882+ cmp {tmp}, {max}
883+ b.lt 3b
884+
885+ dsb ish
886+
887+ mov {tmp}, {addr}
888+
889+ 4: ic ivau, {tmp}
890+ b.eq 1b
891+ add {tmp}, {tmp}, {iminline:x}
892+ cmp {tmp}, {max}
893+ b.lt 4b
894+
895+ dsb ish
896+ isb
897+ " ,
898+ iminline = in( reg) iminline,
899+ dminline = in( reg) dminline,
900+ addr = in( reg) _base as usize ,
901+ max = in( reg) _base as usize + _len,
902+ tmp = out( reg) _) ;
903+ }
904+ }
905+
827906#[ guest_function( "ExecMappedBuffer" ) ]
828907fn exec_mapped_buffer ( base : u64 , len : u64 ) -> bool {
829908 let base = base as usize as * mut u8 ;
@@ -847,6 +926,9 @@ fn exec_mapped_buffer(base: u64, len: u64) -> bool {
847926
848927 // Should be safe as long as data is something like a NOOP followed by a RET
849928 let func: fn ( ) = unsafe { core:: mem:: transmute ( data. as_ptr ( ) ) } ;
929+
930+ dicachesync ( base, len) ;
931+
850932 func ( ) ;
851933
852934 true
@@ -991,7 +1073,6 @@ fn fuzz_guest_trace(max_depth: u32, msg: String) -> u32 {
9911073 fuzz_traced_function ( 0 , max_depth, & msg)
9921074}
9931075
994- #[ cfg( target_arch = "x86_64" ) ]
9951076#[ guest_function( "CorruptOutputSizePrefix" ) ]
9961077fn corrupt_output_size_prefix ( ) -> i32 {
9971078 unsafe {
@@ -1004,19 +1085,11 @@ fn corrupt_output_size_prefix() -> i32 {
10041085 buf[ 8 ..12 ] . copy_from_slice ( & 0xFFFF_FFFBu32 . to_le_bytes ( ) ) ;
10051086 buf[ 12 ..16 ] . copy_from_slice ( & [ 0u8 ; 4 ] ) ;
10061087 buf[ 16 ..24 ] . copy_from_slice ( & 8_u64 . to_le_bytes ( ) ) ;
1007-
1008- core:: arch:: asm!(
1009- "out dx, eax" ,
1010- "cli" ,
1011- "hlt" ,
1012- in( "dx" ) hyperlight_common:: outb:: VmAction :: Halt as u16 ,
1013- in( "eax" ) 0u32 ,
1014- options( noreturn) ,
1015- ) ;
1088+ outb_with_port ( hyperlight_common:: outb:: VmAction :: Halt as u32 , 0u32 ) ;
1089+ unreachable ! ( ) ;
10161090 }
10171091}
10181092
1019- #[ cfg( target_arch = "x86_64" ) ]
10201093#[ guest_function( "CorruptOutputBackPointer" ) ]
10211094fn corrupt_output_back_pointer ( ) -> i32 {
10221095 unsafe {
@@ -1028,15 +1101,8 @@ fn corrupt_output_back_pointer() -> i32 {
10281101 buf[ 0 ..8 ] . copy_from_slice ( & 24_u64 . to_le_bytes ( ) ) ;
10291102 buf[ 8 ..16 ] . copy_from_slice ( & [ 0u8 ; 8 ] ) ;
10301103 buf[ 16 ..24 ] . copy_from_slice ( & 0xDEAD_u64 . to_le_bytes ( ) ) ;
1031-
1032- core:: arch:: asm!(
1033- "out dx, eax" ,
1034- "cli" ,
1035- "hlt" ,
1036- in( "dx" ) hyperlight_common:: outb:: VmAction :: Halt as u16 ,
1037- in( "eax" ) 0u32 ,
1038- options( noreturn) ,
1039- ) ;
1104+ outb_with_port ( hyperlight_common:: outb:: VmAction :: Halt as u32 , 0u32 ) ;
1105+ unreachable ! ( ) ;
10401106 }
10411107}
10421108
0 commit comments