@@ -9,9 +9,9 @@ const KVM_CPUID_SIGNATURE: u32 = 0x40000000;
99
1010// See `include/uapi/linux/kvm_para.h`. (These hypercalls numbers can change depending on the
1111// upstream progress.)
12- const KVM_HC_PKVM_OP : u32 = 20 ;
13- const PKVM_GHC_IOREAD : u32 = KVM_HC_PKVM_OP + 3 ;
14- const PKVM_GHC_IOWRITE : u32 = KVM_HC_PKVM_OP + 4 ;
12+ const KVM_HC_PKVM_OP : u64 = 20 ;
13+ const PKVM_GHC_IOREAD : u64 = KVM_HC_PKVM_OP + 3 ;
14+ const PKVM_GHC_IOWRITE : u64 = KVM_HC_PKVM_OP + 4 ;
1515
1616/// The maximum number of bytes that can be read or written by a single IO hypercall.
1717const HYP_IO_MAX : usize = 8 ;
@@ -42,48 +42,58 @@ pub fn cpuid_signature() -> [u8; 4] {
4242 signature. to_le_bytes ( )
4343}
4444
45- /// Asks the hypervisor to perform an IO read at the given physical address.
46- pub fn hyp_io_read ( address : u64 , size : usize ) -> u64 {
47- let data;
45+ fn __vmcall_impl ( hypcall : u64 , a1 : u64 , a2 : u64 , a3 : u64 , a4 : u64 ) -> u64 {
46+ let ret: u64 ;
4847
49- // SAFETY: Assembly call. Arguments for vmcall are passed via rax, rbx, rcx and rdx. Ideally
50- // using a named argument in the inline asm for rbx would be more straightforward, but when
51- // "rbx" is used directly LLVM complains that it is used internally.
48+ // SAFETY: Assembly call. Arguments for vmcall are passed via rax, rbx, rcx, rdx and rsi.
49+ // Ideally using a named argument in the inline asm for rbx would be more straightforward,
50+ // but when "rbx" is used directly LLVM complains that it is used internally.
5251 //
53- // Therefore use r8 temporary, push rbx to the stack, perform proper call and pop rbx again .
52+ // Therefore use temp register to store rbx content and restore it back afterwards .
5453 unsafe {
55- asm ! (
56- "push rbx" ,
57- "mov rbx, r8" ,
58- "vmcall" ,
59- "pop rbx" ,
60- inout( "rax" ) u64 :: from( PKVM_GHC_IOREAD ) => data,
61- in( "r8" ) address,
62- in( "rcx" ) size,
63- ) ;
64- }
65- data
54+ core:: arch:: asm!(
55+ "xchg %rbx, {0:r}" ,
56+ "vmcall" ,
57+ "xchg %rbx, {0:r}" ,
58+ in( reg) a1,
59+ inout( "rax" ) hypcall => ret,
60+ in( "rcx" ) a2,
61+ in( "rdx" ) a3,
62+ in( "rsi" ) a4,
63+ options( att_syntax) ) ;
64+ } ;
65+ ret
66+ }
67+
68+ // This block uses inline assembly to perform a vmcall, interacting directly with the hypervisor.
69+ // The pKVM hypervisor can share RAX/RBX/RCX/RDX/RSI with pKVM host during hypercall
70+ // handling.
71+ macro_rules! vmcall {
72+ ( $hypcall: expr) => {
73+ __vmcall_impl( $hypcall, 0 , 0 , 0 , 0 )
74+ } ;
75+ ( $hypcall: expr, $a1: expr) => {
76+ __vmcall_impl( $hypcall, $a1, 0 , 0 , 0 )
77+ } ;
78+ ( $hypcall: expr, $a1: expr, $a2: expr) => {
79+ __vmcall_impl( $hypcall, $a1, $a2, 0 , 0 )
80+ } ;
81+ ( $hypcall: expr, $a1: expr, $a2: expr, $a3: expr) => {
82+ __vmcall_impl( $hypcall, $a1, $a2, $a3, 0 )
83+ } ;
84+ ( $hypcall: expr, $a1: expr, $a2: expr, $a3: expr, $a4: expr) => {
85+ __vmcall_impl( $hypcall, $a1, $a2, $a3, $a4)
86+ } ;
87+ }
88+
89+ /// Asks the hypervisor to perform an IO read at the given physical address.
90+ pub fn hyp_io_read ( address : u64 , size : usize ) -> u64 {
91+ vmcall ! ( PKVM_GHC_IOREAD , address, size as u64 )
6692}
6793
6894/// Asks the hypervisor to perform an IO write at the given physical address.
6995pub fn hyp_io_write ( address : u64 , size : usize , data : u64 ) {
70- // SAFETY: Assembly call. Arguments for vmcall are passed via rax, rbx, rcx and rdx. Ideally
71- // using a named argument in the inline asm for rbx would be more straightforward but when
72- // "rbx" is used directly used LLVM complains that it is used internally.
73- //
74- // Therefore use r8 temporary, push rbx to the stack, perform proper call and pop rbx again.
75- unsafe {
76- asm ! (
77- "push rbx" ,
78- "mov rbx, r8" ,
79- "vmcall" ,
80- "pop rbx" ,
81- in( "rax" ) PKVM_GHC_IOWRITE ,
82- in( "r8" ) address,
83- in( "rcx" ) size,
84- in( "rdx" ) data,
85- ) ;
86- }
96+ vmcall ! ( PKVM_GHC_IOWRITE , address, size as u64 , data) ;
8797}
8898
8999/// A region of physical address space which may be accessed by IO read and/or write hypercalls.
0 commit comments