1#[cfg(target_os = "zkvm")]
16use core::arch::asm;
17use core::{cmp::min, ffi::CStr, ptr::null_mut, slice, str::Utf8Error};
18
19use num_enum::{FromPrimitive, IntoPrimitive};
20use paste::paste;
21
22use crate::WORD_SIZE;
23
24pub mod ecall {
25 pub const HALT: u32 = 0;
26 pub const INPUT: u32 = 1;
27 pub const SOFTWARE: u32 = 2;
28 pub const SHA: u32 = 3;
29 pub const BIGINT: u32 = 4;
30 pub const USER: u32 = 5;
31 pub const BIGINT2: u32 = 6;
32 pub const POSEIDON2: u32 = 7;
33}
34
35pub mod halt {
36 pub const TERMINATE: u32 = 0;
37 pub const PAUSE: u32 = 1;
38 pub const SPLIT: u32 = 2;
39}
40
41pub mod reg_abi {
42 pub const REG_ZERO: usize = 0; pub const REG_RA: usize = 1; pub const REG_SP: usize = 2; pub const REG_GP: usize = 3; pub const REG_TP: usize = 4; pub const REG_T0: usize = 5; pub const REG_T1: usize = 6; pub const REG_T2: usize = 7; pub const REG_S0: usize = 8; pub const REG_FP: usize = 8; pub const REG_S1: usize = 9; pub const REG_A0: usize = 10; pub const REG_A1: usize = 11; pub const REG_A2: usize = 12; pub const REG_A3: usize = 13; pub const REG_A4: usize = 14; pub const REG_A5: usize = 15; pub const REG_A6: usize = 16; pub const REG_A7: usize = 17; pub const REG_S2: usize = 18; pub const REG_S3: usize = 19; pub const REG_S4: usize = 20; pub const REG_S5: usize = 21; pub const REG_S6: usize = 22; pub const REG_S7: usize = 23; pub const REG_S8: usize = 24; pub const REG_S9: usize = 25; pub const REG_S10: usize = 26; pub const REG_S11: usize = 27; pub const REG_T3: usize = 28; pub const REG_T4: usize = 29; pub const REG_T5: usize = 30; pub const REG_T6: usize = 31; pub const REG_MAX: usize = 32; }
77
78pub mod keccak_mode {
79 pub const KECCAK_PERMUTE: u32 = 0;
80 pub const KECCAK_PROVE: u32 = 1;
81}
82
83pub const DIGEST_WORDS: usize = 8;
84pub const DIGEST_BYTES: usize = WORD_SIZE * DIGEST_WORDS;
85
86pub const KECCACK_STATE_BYTES: usize = 200;
87pub const KECCACK_STATE_WORDS: usize = 200 / WORD_SIZE;
88pub const KECCACK_STATE_DWORDS: usize = 200 / 8;
89
90pub const IO_CHUNK_WORDS: usize = 4;
92
93pub const MAX_BUF_BYTES: usize = 4 * 1024;
96pub const MAX_BUF_WORDS: usize = MAX_BUF_BYTES / WORD_SIZE;
97pub const MAX_SHA_COMPRESS_BLOCKS: usize = 1000;
98
99pub mod bigint {
100 pub const OP_MULTIPLY: u32 = 0;
101
102 pub const WIDTH_BITS: usize = 256;
104
105 pub const WIDTH_BYTES: usize = WIDTH_BITS / 8;
107
108 pub const WIDTH_WORDS: usize = WIDTH_BYTES / crate::WORD_SIZE;
110}
111
112#[derive(Clone, Copy, Debug)]
114#[repr(transparent)]
115pub struct SyscallName(*const u8);
116
117#[macro_export]
125macro_rules! declare_syscall {
126 (
127 $(#[$meta:meta])*
128 $vis:vis $name:ident
129 ) => {
130 $(#[$meta])*
132 $vis const $name: $crate::syscall::SyscallName = match ::core::ffi::CStr::from_bytes_until_nul(
133 concat!(module_path!(), "::", stringify!($name), "\0").as_bytes(),
134 ) {
135 Ok(c_str) => match $crate::syscall::SyscallName::from_c_str(c_str) {
136 Ok(name) => name,
137 Err(_) => unreachable!(),
138 },
139 Err(_) => unreachable!(),
140 };
141 };
142}
143
144pub mod nr {
145 declare_syscall!(pub SYS_ARGC);
146 declare_syscall!(pub SYS_ARGV);
147 declare_syscall!(pub SYS_CYCLE_COUNT);
148 declare_syscall!(pub SYS_EXIT);
149 declare_syscall!(pub SYS_FORK);
150 declare_syscall!(pub SYS_GETENV);
151 declare_syscall!(pub SYS_KECCAK);
152 declare_syscall!(pub SYS_LOG);
153 declare_syscall!(pub SYS_PANIC);
154 declare_syscall!(pub SYS_PIPE);
155 #[deprecated]
156 pub const SYS_PROVE_KECCAK: crate::syscall::SyscallName = unsafe {
157 crate::syscall::SyscallName::from_bytes_with_nul(
158 c"risc0-zkvm-platform::syscall::SYS_PROVE_KECCAK".as_ptr() as *const u8,
159 )
160 };
161 #[deprecated]
162 pub const SYS_PROVE_ZKR: crate::syscall::SyscallName = unsafe {
163 crate::syscall::SyscallName::from_bytes_with_nul(
164 c"risc0-zkvm-platform::syscall::SYS_PROVE_ZKR".as_ptr() as *const u8,
165 )
166 };
167 declare_syscall!(pub SYS_RANDOM);
168 declare_syscall!(pub SYS_READ);
169 declare_syscall!(pub SYS_VERIFY_INTEGRITY);
170 declare_syscall!(pub SYS_VERIFY_INTEGRITY2);
171 declare_syscall!(pub SYS_WRITE);
172}
173
174#[repr(usize)]
175#[derive(Copy, Clone, Debug, Eq, PartialEq, IntoPrimitive, FromPrimitive)]
176pub enum Syscall {
177 #[num_enum(catch_all)]
178 Unknown(usize) = 0,
179 Argc = 1,
180 Argv = 2,
181 CycleCount = 3,
182 Exit = 4,
183 Fork = 5,
184 Getenv = 6,
185 Keccak = 7,
186 Log = 8,
187 Panic = 9,
188 Pipe = 10,
189 Random = 11,
190 Read = 12,
191 User = 13,
192 VerifyIntegrity = 14,
193 VerifyIntegrity2 = 15,
194 Write = 16,
195 ProveZkr = 17,
196}
197
198impl SyscallName {
199 #[inline]
201 pub const fn from_c_str(c_str: &'static CStr) -> Result<Self, Utf8Error> {
202 match c_str.to_str() {
203 Ok(_) => Ok(unsafe { Self::from_bytes_with_nul(c_str.as_ptr().cast()) }),
204 Err(error) => Err(error),
205 }
206 }
207
208 pub const unsafe fn from_bytes_with_nul(ptr: *const u8) -> Self {
214 Self(ptr)
215 }
216
217 pub fn as_ptr(&self) -> *const u8 {
218 self.0
219 }
220
221 pub fn as_str(&self) -> &str {
222 core::str::from_utf8(unsafe { core::ffi::CStr::from_ptr(self.as_ptr().cast()).to_bytes() })
223 .unwrap()
224 }
225}
226
227impl AsRef<str> for SyscallName {
228 fn as_ref(&self) -> &str {
229 self.as_str()
230 }
231}
232
233#[repr(C)]
235pub struct Return(pub u32, pub u32);
236
237macro_rules! impl_syscall {
238 ($func_name:ident
239 $(, $a0:ident $(, $a1:ident $(, $a2: ident $(, $a3: ident $(, $a4: ident )? )? )? )? )?
242 ) => {
243 #[cfg_attr(feature = "export-syscalls", unsafe(no_mangle))]
249 #[deprecated]
250 pub unsafe extern "C" fn $func_name(
251 syscall_name: SyscallName,
252 from_host: *mut u32,
253 from_host_words: usize
254 $(,$a0: u32 $(,$a1: u32 $(,$a2: u32 $(,$a3: u32 $(,$a4: u32)? )? )? )? )?
255 ) -> Return {
256 unimplemented!();
257 }
258
259
260 paste! {
261 #[cfg_attr(feature = "export-syscalls", unsafe(no_mangle))]
267 pub unsafe extern "C" fn [<$func_name _nr>] (
268 syscall: usize,
269 syscall_name: SyscallName,
270 from_host: *mut u32,
271 from_host_words: usize
272 $(,$a0: u32 $(,$a1: u32 $(,$a2: u32 $(,$a3: u32 $(,$a4: u32)? )? )? )? )?
273 ) -> Return {
274 #[cfg(target_os = "zkvm")] {
275 let a0: u32;
276 let a1: u32;
277 unsafe {
278 ::core::arch::asm!(
279 "ecall",
280 in("t0") $crate::syscall::ecall::SOFTWARE,
281 in("t6") syscall,
282 inlateout("a0") from_host => a0,
283 inlateout("a1") from_host_words => a1,
284 in("a2") syscall_name.as_ptr()
285 $(,in("a3") $a0 $(,in("a4") $a1 $(,in("a5") $a2 $(,in("a6") $a3 $(,in("a7") $a4 )? )? )? )? )?
286 );
287 }
288 Return(a0, a1)
289 }
290 #[cfg(not(target_os = "zkvm"))]
291 unimplemented!()
292 }
293 }
294 }
295}
296
297impl_syscall!(syscall_0);
298impl_syscall!(syscall_1, a3);
299impl_syscall!(syscall_2, a3, a4);
300impl_syscall!(syscall_3, a3, a4, a5);
301impl_syscall!(syscall_4, a3, a4, a5, a6);
302impl_syscall!(syscall_5, a3, a4, a5, a6, a7);
303
304fn ecall_1(t0: u32, a0: u32, a1: u32) {
305 #[cfg(target_os = "zkvm")]
306 unsafe {
307 asm!(
308 "ecall",
309 in("t0") t0,
310 in("a0") a0,
311 in("a1") a1,
312 )
313 };
314 #[cfg(not(target_os = "zkvm"))]
315 {
316 core::hint::black_box((t0, a0, a1));
317 unimplemented!()
318 }
319}
320
321fn ecall_3(t0: u32, a0: u32, a1: u32, a2: u32, a3: u32) {
322 #[cfg(target_os = "zkvm")]
323 unsafe {
324 asm!(
325 "ecall",
326 in("t0") t0,
327 in("a0") a0,
328 in("a1") a1,
329 in("a2") a2,
330 in("a3") a3,
331 )
332 };
333 #[cfg(not(target_os = "zkvm"))]
334 {
335 core::hint::black_box((t0, a0, a1, a2, a3));
336 unimplemented!()
337 }
338}
339
340fn ecall_4(t0: u32, a0: u32, a1: u32, a2: u32, a3: u32, a4: u32) {
341 #[cfg(target_os = "zkvm")]
342 unsafe {
343 asm!(
344 "ecall",
345 in("t0") t0,
346 in("a0") a0,
347 in("a1") a1,
348 in("a2") a2,
349 in("a3") a3,
350 in("a4") a4,
351 )
352 };
353 #[cfg(not(target_os = "zkvm"))]
354 {
355 core::hint::black_box((t0, a0, a1, a2, a3, a4));
356 unimplemented!()
357 }
358}
359
360#[inline(never)]
368#[cfg_attr(feature = "export-syscalls", no_mangle)]
369pub extern "C" fn sys_halt(user_exit: u8, out_state: *const [u32; DIGEST_WORDS]) -> ! {
370 ecall_1(
371 ecall::HALT,
372 halt::TERMINATE | ((user_exit as u32) << 8),
373 out_state as u32,
374 );
375 unreachable!();
376}
377
378#[inline(never)]
386#[cfg_attr(feature = "export-syscalls", no_mangle)]
387pub unsafe extern "C" fn sys_pause(user_exit: u8, out_state: *const [u32; DIGEST_WORDS]) {
388 ecall_1(
389 ecall::HALT,
390 halt::PAUSE | ((user_exit as u32) << 8),
391 out_state as u32,
392 );
393}
394
395#[cfg_attr(feature = "export-syscalls", no_mangle)]
396pub extern "C" fn sys_input(index: u32) -> u32 {
397 let t0 = ecall::INPUT;
398 let index = index & 0x07;
399 #[cfg(target_os = "zkvm")]
400 unsafe {
401 let a0: u32;
402 asm!(
403 "ecall",
404 in("t0") t0,
405 inlateout("a0") index => a0,
406 );
407 a0
408 }
409 #[cfg(not(target_os = "zkvm"))]
410 {
411 core::hint::black_box((t0, index));
412 unimplemented!()
413 }
414}
415
416#[cfg_attr(feature = "export-syscalls", no_mangle)]
421#[cfg_attr(not(feature = "export-syscalls"), inline(always))]
422pub unsafe extern "C" fn sys_sha_compress(
423 out_state: *mut [u32; DIGEST_WORDS],
424 in_state: *const [u32; DIGEST_WORDS],
425 block1_ptr: *const [u32; DIGEST_WORDS],
426 block2_ptr: *const [u32; DIGEST_WORDS],
427) {
428 ecall_4(
429 ecall::SHA,
430 out_state as u32,
431 in_state as u32,
432 block1_ptr as u32,
433 block2_ptr as u32,
434 1,
435 );
436}
437
438#[cfg_attr(feature = "export-syscalls", no_mangle)]
442#[cfg_attr(not(feature = "export-syscalls"), inline(always))]
443pub unsafe extern "C" fn sys_sha_buffer(
444 out_state: *mut [u32; DIGEST_WORDS],
445 in_state: *const [u32; DIGEST_WORDS],
446 buf: *const u8,
447 count: u32,
448) {
449 let mut ptr = buf;
450 let mut count_remain = count;
451 let mut in_state = in_state;
452 while count_remain > 0 {
453 let count = min(count_remain, MAX_SHA_COMPRESS_BLOCKS as u32);
454 ecall_4(
455 ecall::SHA,
456 out_state as u32,
457 in_state as u32,
458 ptr as u32,
459 ptr.add(DIGEST_BYTES) as u32,
460 count,
461 );
462 count_remain -= count;
463 ptr = ptr.add(2 * DIGEST_BYTES * count as usize);
464 in_state = out_state;
465 }
466}
467
468#[cfg_attr(feature = "export-syscalls", no_mangle)]
473#[cfg_attr(not(feature = "export-syscalls"), inline(always))]
474pub unsafe extern "C" fn sys_poseidon2(
475 state_addr: *mut [u32; DIGEST_WORDS],
476 in_buf_addr: *const u8,
477 out_buf_addr: *mut [u32; DIGEST_WORDS],
478 bits_count: u32,
479) {
480 debug_assert!(state_addr as usize % WORD_SIZE == 0);
481 debug_assert!(in_buf_addr as usize % WORD_SIZE == 0);
482 debug_assert!(out_buf_addr as usize % WORD_SIZE == 0);
483
484 ecall_3(
485 ecall::POSEIDON2,
486 state_addr as u32 / WORD_SIZE as u32,
487 in_buf_addr as u32 / WORD_SIZE as u32,
488 out_buf_addr as u32 / WORD_SIZE as u32,
489 bits_count,
490 );
491}
492
493#[cfg_attr(feature = "export-syscalls", no_mangle)]
497#[cfg_attr(not(feature = "export-syscalls"), inline(always))]
498pub unsafe extern "C" fn sys_bigint(
499 result: *mut [u32; bigint::WIDTH_WORDS],
500 op: u32,
501 x: *const [u32; bigint::WIDTH_WORDS],
502 y: *const [u32; bigint::WIDTH_WORDS],
503 modulus: *const [u32; bigint::WIDTH_WORDS],
504) {
505 ecall_4(
506 ecall::BIGINT,
507 result as u32,
508 op,
509 x as u32,
510 y as u32,
511 modulus as u32,
512 );
513}
514
515#[cfg_attr(feature = "export-syscalls", no_mangle)]
519pub unsafe extern "C" fn sys_rand(recv_buf: *mut u32, words: usize) {
520 unsafe { syscall_0_nr(Syscall::Random.into(), nr::SYS_RANDOM, recv_buf, words) };
521}
522
523#[cfg_attr(feature = "export-syscalls", no_mangle)]
527pub unsafe extern "C" fn sys_panic(msg_ptr: *const u8, len: usize) -> ! {
528 unsafe {
529 syscall_2_nr(
530 Syscall::Panic.into(),
531 nr::SYS_PANIC,
532 null_mut(),
533 0,
534 msg_ptr as u32,
535 len as u32,
536 )
537 };
538
539 #[cfg(target_os = "zkvm")]
541 asm!("sw x0, 1(x0)");
542 unreachable!()
543}
544
545#[cfg_attr(feature = "export-syscalls", no_mangle)]
549pub unsafe extern "C" fn sys_log(msg_ptr: *const u8, len: usize) {
550 unsafe {
551 syscall_2_nr(
552 Syscall::Log.into(),
553 nr::SYS_LOG,
554 null_mut(),
555 0,
556 msg_ptr as u32,
557 len as u32,
558 )
559 };
560}
561
562#[cfg_attr(feature = "export-syscalls", no_mangle)]
563pub extern "C" fn sys_cycle_count() -> u64 {
564 let Return(hi, lo) = unsafe {
565 syscall_0_nr(
566 Syscall::CycleCount.into(),
567 nr::SYS_CYCLE_COUNT,
568 null_mut(),
569 0,
570 )
571 };
572 ((hi as u64) << 32) + lo as u64
573}
574
575#[allow(dead_code)]
576fn print(msg: &str) {
577 let msg = msg.as_bytes();
578 unsafe {
579 sys_log(msg.as_ptr(), msg.len());
580 }
581}
582
583#[cfg_attr(feature = "export-syscalls", unsafe(no_mangle))]
596pub unsafe extern "C" fn sys_read(fd: u32, recv_ptr: *mut u8, nbytes: usize) -> usize {
597 let Return(nbytes_read, final_word) = unsafe {
598 syscall_2_nr(
599 Syscall::Read.into(),
600 nr::SYS_READ,
601 recv_ptr as *mut u32,
602 nbytes,
603 fd,
604 nbytes as u32,
605 )
606 };
607
608 nbytes_read as usize
609}
610
611#[cfg_attr(feature = "export-syscalls", no_mangle)]
630pub unsafe extern "C" fn sys_read_words(fd: u32, recv_ptr: *mut u32, nwords: usize) -> usize {
631 let nbytes = nwords * WORD_SIZE;
632 let Return(nbytes_read, final_word) = unsafe {
633 syscall_2_nr(
634 Syscall::Read.into(),
635 nr::SYS_READ,
636 recv_ptr,
637 nbytes,
638 fd,
639 nbytes as u32,
640 )
641 };
642 nbytes_read as usize
643}
644
645#[cfg_attr(feature = "export-syscalls", no_mangle)]
649pub unsafe extern "C" fn sys_write(fd: u32, write_ptr: *const u8, nbytes: usize) {
650 unsafe {
651 syscall_3_nr(
652 Syscall::Write.into(),
653 nr::SYS_WRITE,
654 null_mut(),
655 0,
656 fd,
657 write_ptr as u32,
658 nbytes as u32,
659 )
660 };
661}
662
663const ALLOWED_ENV_VARNAMES: &[&[u8]] = &[
667 b"RUST_BACKTRACE",
668 b"RUST_LIB_BACKTRACE",
669 b"RISC0_KECCAK_PO2",
670];
671
672#[cfg_attr(feature = "export-syscalls", no_mangle)]
690pub unsafe extern "C" fn sys_getenv(
691 out_words: *mut u32,
692 out_nwords: usize,
693 varname: *const u8,
694 varname_len: usize,
695) -> usize {
696 if cfg!(not(feature = "sys-getenv")) {
697 let mut allowed = false;
698 for allowed_varname in ALLOWED_ENV_VARNAMES {
699 let varname_buf = unsafe { slice::from_raw_parts(varname, varname_len) };
700 if *allowed_varname == varname_buf {
701 allowed = true;
702 break;
703 }
704 }
705 if !allowed {
706 const MSG_1: &[u8] = "sys_getenv not enabled for var".as_bytes();
707 unsafe { sys_log(MSG_1.as_ptr(), MSG_1.len()) };
708 unsafe { sys_log(varname, varname_len) };
709 const MSG_2: &[u8] = "sys_getenv is disabled; can be enabled with the sys-getenv feature flag on risc0-zkvm-platform".as_bytes();
710 unsafe { sys_panic(MSG_2.as_ptr(), MSG_2.len()) };
711 }
712 }
713 let Return(a0, _) = unsafe {
714 syscall_2_nr(
715 Syscall::Getenv.into(),
716 nr::SYS_GETENV,
717 out_words,
718 out_nwords,
719 varname as u32,
720 varname_len as u32,
721 )
722 };
723 if a0 == u32::MAX {
724 usize::MAX
725 } else {
726 a0 as usize
727 }
728}
729
730#[cfg_attr(feature = "export-syscalls", no_mangle)]
735pub extern "C" fn sys_argc() -> usize {
736 if cfg!(not(feature = "sys-args")) {
737 const MSG: &[u8] = "sys_argc is disabled; can be enabled with the sys-args feature flag on risc0-zkvm-platform".as_bytes();
738 unsafe { sys_panic(MSG.as_ptr(), MSG.len()) };
739 }
740 let Return(a0, _) = unsafe { syscall_0_nr(Syscall::Argc.into(), nr::SYS_ARGC, null_mut(), 0) };
741 a0 as usize
742}
743
744#[cfg_attr(feature = "export-syscalls", no_mangle)]
762pub unsafe extern "C" fn sys_argv(
763 out_words: *mut u32,
764 out_nwords: usize,
765 arg_index: usize,
766) -> usize {
767 if cfg!(not(feature = "sys-args")) {
768 const MSG: &[u8] = "sys_argv is disabled; can be enabled with the sys-args feature flag on risc0-zkvm-platform".as_bytes();
769 unsafe { sys_panic(MSG.as_ptr(), MSG.len()) };
770 }
771 let Return(a0, _) = unsafe {
772 syscall_1_nr(
773 Syscall::Argv.into(),
774 nr::SYS_ARGV,
775 out_words,
776 out_nwords,
777 arg_index as u32,
778 )
779 };
780 a0 as usize
781}
782
783#[cfg_attr(feature = "export-syscalls", no_mangle)]
784#[deprecated]
785pub extern "C" fn sys_alloc_words(nwords: usize) -> *mut u32 {
786 unsafe { sys_alloc_aligned(WORD_SIZE * nwords, WORD_SIZE) as *mut u32 }
787}
788
789#[cfg(all(feature = "export-syscalls", not(target_os = "zkvm")))]
793#[no_mangle]
794pub unsafe extern "C" fn sys_alloc_aligned(bytes: usize, align: usize) -> *mut u8 {
795 unimplemented!("sys_alloc_aligned called outside of target_os = zkvm");
796}
797
798#[cfg(all(
802 feature = "export-syscalls",
803 feature = "heap-embedded-alloc",
804 target_os = "zkvm"
805))]
806#[no_mangle]
807pub unsafe extern "C" fn sys_alloc_aligned(bytes: usize, align: usize) -> *mut u8 {
808 use core::alloc::GlobalAlloc;
809 crate::heap::embedded::HEAP.alloc(core::alloc::Layout::from_size_align(bytes, align).unwrap())
810}
811
812#[cfg(all(
816 feature = "export-syscalls",
817 not(feature = "heap-embedded-alloc"),
818 target_os = "zkvm"
819))]
820#[no_mangle]
821pub unsafe extern "C" fn sys_alloc_aligned(bytes: usize, align: usize) -> *mut u8 {
822 crate::heap::bump::alloc_aligned(bytes, align)
823}
824
825#[cfg(feature = "export-syscalls")]
837#[no_mangle]
838pub unsafe extern "C" fn sys_verify_integrity(
839 claim_digest: *const [u32; DIGEST_WORDS],
840 control_root: *const [u32; DIGEST_WORDS],
841) {
842 let mut to_host = [0u32; DIGEST_WORDS * 2];
843 to_host[..DIGEST_WORDS].copy_from_slice(claim_digest.as_ref().unwrap_unchecked());
844 to_host[DIGEST_WORDS..].copy_from_slice(control_root.as_ref().unwrap_unchecked());
845
846 let Return(a0, _) = unsafe {
848 syscall_2_nr(
849 Syscall::VerifyIntegrity.into(),
850 nr::SYS_VERIFY_INTEGRITY,
851 null_mut(),
852 0,
853 to_host.as_ptr() as u32,
854 (DIGEST_BYTES * 2) as u32,
855 )
856 };
857
858 if a0 != 0 {
862 const MSG: &[u8] = "sys_verify_integrity returned error result".as_bytes();
863 unsafe { sys_panic(MSG.as_ptr(), MSG.len()) };
864 }
865}
866
867#[cfg(feature = "export-syscalls")]
874#[no_mangle]
875pub unsafe extern "C" fn sys_verify_integrity2(
876 claim_digest: *const [u32; DIGEST_WORDS],
877 control_root: *const [u32; DIGEST_WORDS],
878) {
879 let mut to_host = [0u32; DIGEST_WORDS * 2];
880 to_host[..DIGEST_WORDS].copy_from_slice(claim_digest.as_ref().unwrap_unchecked());
881 to_host[DIGEST_WORDS..].copy_from_slice(control_root.as_ref().unwrap_unchecked());
882
883 let Return(a0, _) = unsafe {
885 syscall_2_nr(
886 Syscall::VerifyIntegrity2.into(),
887 nr::SYS_VERIFY_INTEGRITY2,
888 null_mut(),
889 0,
890 to_host.as_ptr() as u32,
891 (DIGEST_BYTES * 2) as u32,
892 )
893 };
894
895 if a0 != 0 {
899 const MSG: &[u8] = "sys_verify_integrity2 returned error result".as_bytes();
900 unsafe { sys_panic(MSG.as_ptr(), MSG.len()) };
901 }
902}
903#[cfg(not(feature = "export-syscalls"))]
905extern "C" {
906 pub fn sys_alloc_aligned(nwords: usize, align: usize) -> *mut u8;
907}
908
909#[cfg(feature = "export-syscalls")]
922#[no_mangle]
923pub extern "C" fn sys_fork() -> i32 {
924 let Return(a0, _) = unsafe { syscall_0_nr(Syscall::Fork.into(), nr::SYS_FORK, null_mut(), 0) };
925 a0 as i32
926}
927
928#[cfg(feature = "export-syscalls")]
945#[no_mangle]
946pub unsafe extern "C" fn sys_pipe(pipefd: *mut u32) -> i32 {
947 let Return(a0, _) = unsafe { syscall_0_nr(Syscall::Pipe.into(), nr::SYS_PIPE, pipefd, 2) };
948 a0 as i32
949}
950
951#[cfg(feature = "export-syscalls")]
955#[no_mangle]
956pub extern "C" fn sys_exit(status: i32) -> ! {
957 let Return(a0, _) = unsafe { syscall_0_nr(Syscall::Exit.into(), nr::SYS_EXIT, null_mut(), 0) };
958 #[allow(clippy::empty_loop)]
959 loop {
960 }
963}
964
965#[cfg_attr(feature = "export-syscalls", no_mangle)]
969pub unsafe extern "C" fn sys_keccak(
970 in_state: *const [u64; KECCACK_STATE_DWORDS],
971 out_state: *mut [u64; KECCACK_STATE_DWORDS],
972) -> i32 {
973 let Return(a0, _) = unsafe {
974 syscall_3_nr(
975 Syscall::Keccak.into(),
976 nr::SYS_KECCAK,
977 out_state as *mut u32,
978 KECCACK_STATE_WORDS,
979 keccak_mode::KECCAK_PERMUTE,
980 in_state as u32,
981 0,
982 )
983 };
984 a0 as i32
985}
986
987#[cfg_attr(feature = "export-syscalls", no_mangle)]
1001pub unsafe extern "C" fn sys_prove_keccak(
1002 claim_digest: *const [u32; DIGEST_WORDS],
1003 control_root: *const [u32; DIGEST_WORDS],
1004) {
1005 let Return(a0, _) = unsafe {
1006 syscall_3_nr(
1007 Syscall::Keccak.into(),
1008 nr::SYS_KECCAK,
1009 null_mut(),
1010 0,
1011 keccak_mode::KECCAK_PROVE,
1012 claim_digest as u32,
1013 control_root as u32,
1014 )
1015 };
1016
1017 if a0 != 0 {
1021 const MSG: &[u8] = "sys_prove_keccak returned error result".as_bytes();
1022 unsafe { sys_panic(MSG.as_ptr(), MSG.len()) };
1023 }
1024}
1025
1026#[repr(C)]
1027pub struct BigIntBlobHeader {
1028 pub nondet_program_size: u32,
1029 pub verify_program_size: u32,
1030 pub consts_size: u32,
1031 pub temp_size: u32,
1032}
1033
1034macro_rules! impl_sys_bigint2 {
1035 ($func_name:ident, $a1:ident
1036 $(, $a2: ident
1037 $(, $a3: ident
1038 $(, $a4: ident
1039 $(, $a5: ident
1040 $(, $a6: ident)?
1041 )?
1042 )?
1043 )?
1044 )?
1045 ) => {
1046 #[cfg_attr(feature = "export-syscalls", no_mangle)]
1052 pub unsafe extern "C" fn $func_name(blob_ptr: *const u8, a1: *const u32
1053 $(, $a2: *const u32
1054 $(, $a3: *const u32
1055 $(, $a4: *const u32
1056 $(, $a5: *const u32
1057 $(, $a6: *const u32)?
1058 )?
1059 )?
1060 )?
1061 )?
1062 ) {
1063 #[cfg(target_os = "zkvm")]
1064 {
1065 let header = blob_ptr as *const $crate::syscall::BigIntBlobHeader;
1066 let nondet_program_ptr = (header.add(1)) as *const u32;
1067 let verify_program_ptr = nondet_program_ptr.add((*header).nondet_program_size as usize);
1068 let consts_ptr = verify_program_ptr.add((*header).verify_program_size as usize);
1069 let temp_space = ((*header).temp_size as usize) << 2;
1070
1071 ::core::arch::asm!(
1072 "sub sp, sp, {temp_space}",
1073 "ecall",
1074 "add sp, sp, {temp_space}",
1075 temp_space = in(reg) temp_space,
1076 in("t0") ecall::BIGINT2,
1077 in("t1") nondet_program_ptr,
1078 in("t2") verify_program_ptr,
1079 in("t3") consts_ptr,
1080 in("a0") blob_ptr,
1081 in("a1") a1,
1082 $(in("a2") $a2,
1083 $(in("a3") $a3,
1084 $(in("a4") $a4,
1085 $(in("a5") $a5,
1086 $(in("a6") $a6)?
1087 )?
1088 )?
1089 )?
1090 )?
1091 );
1092 }
1093
1094 #[cfg(not(target_os = "zkvm"))]
1095 unimplemented!()
1096 }
1097 }
1098}
1099
1100impl_sys_bigint2!(sys_bigint2_1, a1);
1101impl_sys_bigint2!(sys_bigint2_2, a1, a2);
1102impl_sys_bigint2!(sys_bigint2_3, a1, a2, a3);
1103impl_sys_bigint2!(sys_bigint2_4, a1, a2, a3, a4);
1104impl_sys_bigint2!(sys_bigint2_5, a1, a2, a3, a4, a5);
1105impl_sys_bigint2!(sys_bigint2_6, a1, a2, a3, a4, a5, a6);