├── user ├── lib │ ├── .gitignore │ ├── Cargo.toml │ ├── src │ │ ├── lib.rs │ │ └── console.rs │ └── module.lds └── init │ ├── build.rs │ ├── Cargo.toml │ └── src │ └── main.rs ├── .mailmap ├── kernel ├── .cargo │ └── config.toml ├── src │ ├── acpi │ │ └── mod.rs │ ├── debug │ │ └── mod.rs │ ├── virtio │ │ ├── mod.rs │ │ └── error.rs │ ├── tdx │ │ ├── mod.rs │ │ ├── ve.rs │ │ └── error.rs │ ├── block │ │ ├── mod.rs │ │ ├── error.rs │ │ └── api.rs │ ├── greq │ │ └── mod.rs │ ├── vmm │ │ ├── mod.rs │ │ ├── message.rs │ │ └── registers.rs │ ├── syscall │ │ ├── mod.rs │ │ ├── class3.rs │ │ └── class0.rs │ ├── cpu │ │ ├── idt │ │ │ └── mod.rs │ │ ├── x86 │ │ │ ├── smap.S │ │ │ ├── mod.rs │ │ │ ├── smap.rs │ │ │ └── x2apic.rs │ │ ├── isst.rs │ │ ├── mod.rs │ │ ├── features.rs │ │ ├── efer.rs │ │ ├── mem.rs │ │ └── registers.rs │ ├── mm │ │ ├── vm │ │ │ ├── mod.rs │ │ │ └── mapping │ │ │ │ ├── mod.rs │ │ │ │ └── reserved.rs │ │ ├── mod.rs │ │ └── address_space.verus.rs │ ├── hyperv │ │ ├── msr.rs │ │ └── mod.rs │ ├── fs │ │ ├── mod.rs │ │ └── init.rs │ ├── types.verus.rs │ ├── utils │ │ ├── mod.rs │ │ └── vec.rs │ ├── kernel_region.rs │ ├── locking │ │ └── mod.rs │ ├── task │ │ ├── waiting.rs │ │ └── mod.rs │ ├── sev │ │ ├── mod.rs │ │ └── tlb.rs │ ├── platform │ │ ├── guest_cpu.rs │ │ └── capabilities.rs │ ├── testutils.rs │ ├── svsm.lds │ ├── stage2.lds │ ├── protocols │ │ └── mod.rs │ └── lib.rs └── build.rs ├── stage1 ├── .cargo │ └── config.toml ├── Cargo.toml ├── build.rs ├── stage1.lds └── src │ └── reset.S ├── cpuarch ├── src │ ├── lib.rs │ └── snp_cpuid.rs └── Cargo.toml ├── fuzz ├── acpi-dict.txt ├── fuzz_targets │ ├── insn.rs │ └── acpi.rs └── Cargo.toml ├── rust-toolchain.toml ├── libtcgtpm ├── deps │ ├── libcrt │ │ ├── include │ │ │ ├── assert.h │ │ │ ├── ctype.h │ │ │ ├── dirent.h │ │ │ ├── endian.h │ │ │ ├── errno.h │ │ │ ├── fcntl.h │ │ │ ├── inttypes.h │ │ │ ├── limits.h │ │ │ ├── memory.h │ │ │ ├── setjmp.h │ │ │ ├── stdarg.h │ │ │ ├── stdbool.h │ │ │ ├── stddef.h │ │ │ ├── stdint.h │ │ │ ├── stdio.h │ │ │ ├── stdlib.h │ │ │ ├── string.h │ │ │ ├── strings.h │ │ │ ├── sys │ │ │ │ ├── shm.h │ │ │ │ ├── stat.h │ │ │ │ ├── time.h │ │ │ │ ├── syscall.h │ │ │ │ ├── types.h │ │ │ │ └── utsname.h │ │ │ ├── time.h │ │ │ ├── unistd.h │ │ │ └── stdatomic.h │ │ └── src │ │ │ ├── ctype │ │ │ ├── isdigit.c │ │ │ ├── isascii.c │ │ │ ├── islower.c │ │ │ ├── isupper.c │ │ │ ├── isspace.c │ │ │ ├── tolower.c │ │ │ └── toupper.c │ │ │ ├── string │ │ │ ├── strrchr.c │ │ │ ├── strcpy.c │ │ │ ├── strncpy.c │ │ │ ├── strcat.c │ │ │ ├── strchr.c │ │ │ ├── strcmp.c │ │ │ ├── memcmp.c │ │ │ ├── strncat.c │ │ │ ├── strdup.c │ │ │ ├── strncmp.c │ │ │ ├── memrchr.c │ │ │ ├── strncasecmp.c │ │ │ ├── strcasecmp.c │ │ │ ├── strcspn.c │ │ │ ├── strspn.c │ │ │ ├── strlen.c │ │ │ ├── memchr.c │ │ │ ├── stpcpy.c │ │ │ ├── strchrnul.c │ │ │ ├── stpncpy.c │ │ │ └── memmove.c │ │ │ ├── stdio │ │ │ ├── vsprintf.c │ │ │ ├── vsnprintf.c │ │ │ ├── asprintf.c │ │ │ ├── fprintf.c │ │ │ ├── sprintf.c │ │ │ ├── snprintf.c │ │ │ ├── vasprintf.c │ │ │ └── printf.c │ │ │ ├── exit │ │ │ └── assert.c │ │ │ ├── stdlib │ │ │ ├── atoi.c │ │ │ └── qsort_nr.c │ │ │ ├── time │ │ │ ├── gmtime_r.c │ │ │ ├── time.c │ │ │ └── __secs_to_tm.c │ │ │ └── setjmp │ │ │ └── x86_64 │ │ │ ├── longjmp.s │ │ │ └── setjmp.s │ ├── TpmConfiguration │ │ ├── TpmConfiguration │ │ │ ├── TpmProfile.h │ │ │ └── VendorCommands │ │ │ │ ├── HandleProcess.inl │ │ │ │ ├── CommandAttributeData_s_ccAttr.inl │ │ │ │ ├── CommandDispatchData_s_CommandDataArray.inl │ │ │ │ ├── prototypes │ │ │ │ └── Vendor_TCG_Test_fp.h │ │ │ │ ├── CommandAttributeData_s_commandAttributes.inl │ │ │ │ ├── VendorCommandList.h │ │ │ │ ├── CommandDispatcher.inl │ │ │ │ └── CommandDispatchData_CommandStructures.inl │ │ └── TpmVendorCommandHandlers │ │ │ └── Vendor_TCG_Test.c │ └── openssl_svsm.conf ├── Cargo.toml └── src │ └── lib.rs ├── test ├── Cargo.toml └── src │ └── lib.rs ├── SECURITY.md ├── release ├── Cargo.toml ├── build.rs └── src │ └── lib.rs ├── virtio-drivers ├── src │ ├── device │ │ ├── mod.rs │ │ └── common.rs │ └── Cargo.toml ├── Cargo.toml └── LICENSE ├── tools ├── cbit │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── aproxy │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── igvmbuilder │ ├── Cargo.toml │ ├── src │ │ ├── main.rs │ │ ├── platform.rs │ │ ├── firmware.rs │ │ └── paging.rs │ └── README.md └── igvmmeasure │ ├── Cargo.toml │ └── src │ └── utils.rs ├── bootlib ├── Cargo.toml └── src │ ├── lib.rs │ ├── platform.rs │ └── firmware.rs ├── verification ├── verus_macro_stub │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── verify_proof │ ├── src │ │ ├── bits.rs │ │ ├── lib.rs │ │ ├── sum.rs │ │ └── set.rs │ ├── Cargo.toml │ └── build.rs ├── verify_external │ ├── src │ │ ├── hw_spec │ │ │ └── mod.rs │ │ ├── ptr.rs │ │ ├── convert.rs │ │ ├── lib.rs │ │ ├── convert.verus.rs │ │ └── ptr.verus.rs │ ├── Cargo.toml │ └── build.rs └── verus_stub │ ├── src │ └── lib.rs │ └── Cargo.toml ├── scripts ├── install-hooks.sh ├── gen_igvm_signing_keys.sh ├── vfmt.sh ├── test_sign_qemu_igvm.sh ├── show-stack-sizes.sh ├── test-qemu-nocc-svsm.sh ├── pre-commit ├── vinstall.sh └── check-signed-off.sh ├── CODEOWNERS ├── elf ├── Cargo.toml └── src │ ├── types.rs │ ├── lib.rs │ └── file_range.rs ├── syscall ├── Cargo.toml └── src │ ├── console.rs │ ├── lib.rs │ ├── class3.rs │ ├── class0.rs │ └── obj.rs ├── xbuild ├── Cargo.toml └── src │ ├── version.rs │ ├── kernel.rs │ ├── helpers.rs │ ├── fw.rs │ └── features.rs ├── .gitmodules ├── .cargo └── config.toml ├── .gitignore ├── .github └── workflows │ ├── signed-off.yml │ ├── manual-verify.yml │ ├── publish-docs.yml │ └── rust.yml ├── libaproxy ├── Cargo.toml └── src │ ├── negotiation.rs │ └── lib.rs ├── configs ├── test │ ├── qemu-test-target.json │ ├── hyperv-test-target.json │ └── vanadium-test-target.json ├── hyperv-target.json ├── qemu-target.json ├── vanadium-target.json └── all-targets.json ├── Documentation ├── mkdocs.yml └── docs │ ├── index.md │ └── developer │ └── DOC-GUIDELINES.md └── LICENSE-MIT /user/lib/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Joerg Roedel 2 | -------------------------------------------------------------------------------- /kernel/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "x86_64-unknown-none" 3 | -------------------------------------------------------------------------------- /stage1/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "x86_64-unknown-none" 3 | -------------------------------------------------------------------------------- /cpuarch/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | 3 | pub mod snp_cpuid; 4 | pub mod vmsa; 5 | -------------------------------------------------------------------------------- /fuzz/acpi-dict.txt: -------------------------------------------------------------------------------- 1 | "etc/acpi/rsdp" 2 | "etc/acpi/tables" 3 | "APIC" 4 | "\x00\x00\x00\x14" 5 | -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "1.86.0" 3 | targets = [ "x86_64-unknown-none" ] 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/assert.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/ctype.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/dirent.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/endian.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/errno.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/fcntl.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/inttypes.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/limits.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/memory.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/setjmp.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/stdarg.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/stdbool.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/stddef.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/stdint.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/stdio.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/stdlib.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/string.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/strings.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/sys/shm.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/sys/stat.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/sys/time.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/time.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/unistd.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/stdatomic.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/sys/syscall.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/sys/types.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/include/sys/utsname.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /test/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/ctype/isdigit.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int isdigit(int c) 4 | { 5 | return (unsigned)c-'0' < 10; 6 | } 7 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Issue Response Process 2 | 3 | Please report any security issue to this [email address](mailto:security@coconut-svsm.dev). 4 | -------------------------------------------------------------------------------- /user/init/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("cargo:rustc-link-arg=-Tuser/lib/module.lds"); 3 | println!("cargo:rustc-link-arg=-no-pie"); 4 | } 5 | -------------------------------------------------------------------------------- /release/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "release" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | 8 | [lints] 9 | workspace = true 10 | -------------------------------------------------------------------------------- /virtio-drivers/src/device/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | //! Drivers for specific VirtIO devices. 4 | 5 | pub mod blk; 6 | pub(crate) mod common; 7 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/ctype/isascii.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | 5 | int isascii(int c) 6 | { 7 | return !(c&~0x7f); 8 | } 9 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/ctype/islower.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | 5 | int islower(int c) 6 | { 7 | return (unsigned)c-'a' < 26; 8 | } 9 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/ctype/isupper.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | 5 | int isupper(int c) 6 | { 7 | return (unsigned)c-'A' < 26; 8 | } 9 | -------------------------------------------------------------------------------- /kernel/src/acpi/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2022-2023 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | 7 | pub mod tables; 8 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/ctype/isspace.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | 5 | int isspace(int c) 6 | { 7 | return c == ' ' || (unsigned)c-'\t' < 5; 8 | } 9 | -------------------------------------------------------------------------------- /user/lib/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "userlib" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | syscall.workspace = true 8 | 9 | [lints] 10 | workspace = true 11 | -------------------------------------------------------------------------------- /tools/cbit/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cbit" 3 | version = "0.1.0" 4 | edition = "2024" 5 | 6 | [dependencies] 7 | bitfield-struct.workspace = true 8 | 9 | [lints] 10 | workspace = true 11 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/ctype/tolower.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | 5 | int tolower(int c) 6 | { 7 | if (isupper(c)) return c | 32; 8 | return c; 9 | } 10 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/ctype/toupper.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | 5 | int toupper(int c) 6 | { 7 | if (islower(c)) return c & 0x5f; 8 | return c; 9 | } 10 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/string/strrchr.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | 5 | char *strrchr(const char *s, int c) 6 | { 7 | return __memrchr(s, c, strlen(s) + 1); 8 | } 9 | -------------------------------------------------------------------------------- /bootlib/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bootlib" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | uuid.workspace = true 8 | zerocopy.workspace = true 9 | 10 | [lints] 11 | workspace = true 12 | -------------------------------------------------------------------------------- /kernel/src/debug/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2022-2023 SUSE LLC 4 | // 5 | // Author: Nicolai Stange 6 | 7 | pub mod gdbstub; 8 | pub mod stacktrace; 9 | -------------------------------------------------------------------------------- /libtcgtpm/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "libtcgtpm" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | 8 | [build-dependencies] 9 | bindgen = "0.71.0" 10 | 11 | [lints] 12 | workspace = true 13 | -------------------------------------------------------------------------------- /verification/verus_macro_stub/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "verus_macro_stub" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | proc-macro = true 8 | 9 | [dependencies] 10 | proc-macro2 = "1.0.94" 11 | -------------------------------------------------------------------------------- /scripts/install-hooks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # SPDX-License-Identifier: MIT OR Apache-2.0 3 | # 4 | # Copyright (c) 2023 SUSE LLC 5 | # 6 | # Author: Joerg Roedel 7 | 8 | install -m 755 scripts/pre-commit .git/hooks/ 9 | -------------------------------------------------------------------------------- /cpuarch/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cpuarch" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | bitfield-struct.workspace = true 8 | zerocopy.workspace = true 9 | 10 | [lints] 11 | workspace = true 12 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/string/strcpy.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | 5 | char *strcpy(char *restrict dest, const char *restrict src) 6 | { 7 | __stpcpy(dest, src); 8 | return dest; 9 | } 10 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/string/strncpy.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | 5 | char *strncpy(char *restrict d, const char *restrict s, size_t n) 6 | { 7 | __stpncpy(d, s, n); 8 | return d; 9 | } 10 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/string/strcat.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | 5 | char *strcat(char *restrict dest, const char *restrict src) 6 | { 7 | strcpy(dest + strlen(dest), src); 8 | return dest; 9 | } 10 | -------------------------------------------------------------------------------- /verification/verify_proof/src/bits.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Ziqiao Zhou 6 | 7 | #[cfg(verus_keep_ghost)] 8 | include!("bits.verus.rs"); 9 | -------------------------------------------------------------------------------- /verification/verify_external/src/hw_spec/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Ziqiao Zhou 6 | #[cfg(verus_keep_ghost)] 7 | include!("mm.verus.rs"); 8 | -------------------------------------------------------------------------------- /verification/verify_external/src/ptr.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Ziqiao Zhou 6 | 7 | #[cfg(verus_keep_ghost)] 8 | include!("ptr.verus.rs"); 9 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/string/strchr.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | 5 | char *strchr(const char *s, int c) 6 | { 7 | char *r = __strchrnul(s, c); 8 | return *(unsigned char *)r == (unsigned char)c ? r : 0; 9 | } 10 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/string/strcmp.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | 5 | int strcmp(const char *l, const char *r) 6 | { 7 | for (; *l==*r && *l; l++, r++); 8 | return *(unsigned char *)l - *(unsigned char *)r; 9 | } 10 | -------------------------------------------------------------------------------- /verification/verify_external/src/convert.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Ziqiao Zhou 6 | 7 | #[cfg(verus_keep_ghost)] 8 | include!("convert.verus.rs"); 9 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/stdio/vsprintf.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | #include 5 | 6 | int vsprintf(char *restrict s, const char *restrict fmt, va_list ap) 7 | { 8 | return vsnprintf(s, INT_MAX, fmt, ap); 9 | } 10 | -------------------------------------------------------------------------------- /verification/verus_stub/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | 3 | #[cfg(feature = "disable")] 4 | pub use verus_builtin_macros::*; 5 | 6 | #[cfg(feature = "disable")] 7 | pub use vstd::prelude::*; 8 | 9 | #[cfg(not(feature = "disable"))] 10 | pub use verus_macro_stub::*; 11 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # CODEOWNERS file for COCONUT-SVSM 2 | 3 | # Technical Steering Committee (TSC) 4 | # Joerg Roedel, Jon Lange, Peter Fang, Stefano Garzarella 5 | * joerg.roedel@amd.com jlange@microsoft.com peter.fang@intel.com sgarzare@redhat.com 6 | 7 | # Subsystem Maintainers 8 | -------------------------------------------------------------------------------- /kernel/src/virtio/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2025 Red Hat, Inc. 4 | // 5 | // Author: Oliver Steffen 6 | 7 | pub mod devices; 8 | pub mod error; 9 | mod hal; 10 | 11 | pub use error::VirtioError; 12 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/stdio/vsnprintf.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | #include 5 | 6 | int vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list ap) 7 | { 8 | return vsnprints(s, n, fmt, ap); 9 | } 10 | -------------------------------------------------------------------------------- /elf/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "elf" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | bitflags.workspace = true 10 | 11 | [lints] 12 | workspace = true 13 | -------------------------------------------------------------------------------- /kernel/src/tdx/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Jon Lange 6 | 7 | pub mod apic; 8 | pub mod error; 9 | pub mod tdcall; 10 | pub mod ve; 11 | 12 | pub use error::TdxError; 13 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/string/memcmp.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | 5 | int memcmp(const void *vl, const void *vr, size_t n) 6 | { 7 | const unsigned char *l=vl, *r=vr; 8 | for (; n && *l == *r; n--, l++, r++); 9 | return n ? *l-*r : 0; 10 | } 11 | -------------------------------------------------------------------------------- /syscall/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "syscall" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | bitflags.workspace = true 10 | 11 | [lints] 12 | workspace = true 13 | -------------------------------------------------------------------------------- /user/init/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "userinit" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [[bin]] 7 | name = "userinit" 8 | path = "src/main.rs" 9 | test = false 10 | doctest = false 11 | 12 | [dependencies] 13 | userlib.workspace = true 14 | 15 | [lints] 16 | workspace = true 17 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/string/strncat.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | 5 | char *strncat(char *restrict d, const char *restrict s, size_t n) 6 | { 7 | char *a = d; 8 | d += strlen(d); 9 | while (n && *s) n--, *d++ = *s++; 10 | *d++ = 0; 11 | return a; 12 | } 13 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/string/strdup.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | char *strdup(const char *s) 8 | { 9 | size_t l = strlen(s); 10 | char *d = malloc(l+1); 11 | if (!d) return NULL; 12 | return memcpy(d, s, l+1); 13 | } 14 | -------------------------------------------------------------------------------- /kernel/src/block/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2024 Red Hat, Inc. 4 | // 5 | // Author: Oliver Steffen 6 | 7 | pub mod api; 8 | pub mod error; 9 | #[cfg(feature = "virtio-drivers")] 10 | pub mod virtio_blk; 11 | 12 | pub use error::BlockDeviceError; 13 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/exit/assert.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | #include 5 | 6 | void __assert_fail(const char *expr, const char *file, int line, const char *func) 7 | { 8 | printf("Assertion failed: %s (%s: %s: %d)\n", expr, file, func, line); 9 | abort(); 10 | } 11 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/stdio/asprintf.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | #include 5 | 6 | int asprintf(char **s, const char *fmt, ...) 7 | { 8 | int ret; 9 | va_list ap; 10 | va_start(ap, fmt); 11 | ret = vasprintf(s, fmt, ap); 12 | va_end(ap); 13 | return ret; 14 | } 15 | -------------------------------------------------------------------------------- /kernel/src/greq/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (C) 2023 IBM 4 | // 5 | // Author: Claudio Carvalho 6 | 7 | //! `SNP_GUEST_REQUEST` mechanism to communicate with the PSP 8 | 9 | pub mod driver; 10 | pub mod msg; 11 | pub mod pld_report; 12 | pub mod services; 13 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/stdio/fprintf.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | #include 5 | 6 | int fprintf(FILE *restrict f, const char *restrict fmt, ...) 7 | { 8 | int ret; 9 | va_list ap; 10 | va_start(ap, fmt); 11 | ret = vprints(fmt, ap); 12 | va_end(ap); 13 | return ret; 14 | } 15 | -------------------------------------------------------------------------------- /kernel/src/vmm/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Jon Lange (jlange@microsoft.com) 6 | 7 | pub mod execloop; 8 | pub mod message; 9 | pub mod registers; 10 | 11 | pub use execloop::enter_guest; 12 | pub use message::*; 13 | pub use registers::*; 14 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/stdio/sprintf.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | #include 5 | 6 | int sprintf(char *restrict s, const char *restrict fmt, ...) 7 | { 8 | int ret; 9 | va_list ap; 10 | va_start(ap, fmt); 11 | ret = vsprintf(s, fmt, ap); 12 | va_end(ap); 13 | return ret; 14 | } 15 | -------------------------------------------------------------------------------- /kernel/src/syscall/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // 3 | // Copyright (c) 2024 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | 7 | mod class0; 8 | mod class1; 9 | mod class3; 10 | mod obj; 11 | 12 | pub use class0::*; 13 | pub use class1::*; 14 | pub use class3::*; 15 | pub use obj::{Obj, ObjError, ObjHandle}; 16 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/string/strncmp.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | 5 | int strncmp(const char *_l, const char *_r, size_t n) 6 | { 7 | const unsigned char *l=(void *)_l, *r=(void *)_r; 8 | if (!n--) return 0; 9 | for (; *l && *r && n && *l == *r ; l++, r++, n--); 10 | return *l - *r; 11 | } 12 | -------------------------------------------------------------------------------- /xbuild/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "xbuild" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | clap = { workspace = true, features = ["color", "derive", "help", "std", "suggestions", "usage"] } 8 | serde = { version = "1.0.219", features = ["derive"] } 9 | serde_json = "1.0.140" 10 | 11 | [lints] 12 | workspace = true 13 | -------------------------------------------------------------------------------- /kernel/src/cpu/idt/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2022-2023 SUSE LLC 4 | // 5 | // Author: Thomas Leroy 6 | 7 | pub mod common; 8 | pub mod stage2; 9 | pub mod svsm; 10 | 11 | pub use common::{IdtEntry, EARLY_IDT_ENTRIES, IDT}; 12 | pub use svsm::{load_static_idt, GLOBAL_IDT}; 13 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/string/memrchr.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | 5 | void *__memrchr(const void *m, int c, size_t n) 6 | { 7 | const unsigned char *s = m; 8 | c = (unsigned char)c; 9 | while (n--) if (s[n]==c) return (void *)(s+n); 10 | return 0; 11 | } 12 | 13 | weak_alias(__memrchr, memrchr); 14 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/stdio/snprintf.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | #include 5 | 6 | int snprintf(char *restrict s, size_t n, const char *restrict fmt, ...) 7 | { 8 | int ret; 9 | va_list ap; 10 | va_start(ap, fmt); 11 | ret = vsnprintf(s, n, fmt, ap); 12 | va_end(ap); 13 | return ret; 14 | } 15 | 16 | -------------------------------------------------------------------------------- /stage1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stage1" 3 | version = "0.1.0" 4 | edition = "2021" 5 | rust-version = "1.86.0" 6 | 7 | [[bin]] 8 | name = "stage1" 9 | path = "src/stage1.rs" 10 | test = false 11 | 12 | [features] 13 | default = [] 14 | load-stage2 = [] 15 | 16 | [dependencies] 17 | bootlib.workspace = true 18 | 19 | [lints] 20 | workspace = true 21 | -------------------------------------------------------------------------------- /kernel/src/block/error.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2025 Red Hat, Inc. 4 | // 5 | // Author: Oliver Steffen 6 | 7 | #[derive(Debug, Clone, Copy, PartialEq)] 8 | pub enum BlockDeviceError { 9 | /// Generic error for all read and write operations on a block device. 10 | Failed, 11 | } 12 | -------------------------------------------------------------------------------- /kernel/src/vmm/message.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Jon Lange (jlange@microsoft.com) 6 | 7 | use crate::protocols::RequestParams; 8 | 9 | #[derive(Clone, Copy, Debug)] 10 | pub enum GuestExitMessage { 11 | NoMappings, 12 | Svsm((u32, u32, RequestParams)), 13 | } 14 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libtcgtpm/deps/openssl"] 2 | path = libtcgtpm/deps/openssl 3 | url = https://github.com/openssl/openssl.git 4 | [submodule "libtcgtpm/deps/tpm-20-ref"] 5 | path = libtcgtpm/deps/tpm-20-ref 6 | url = https://github.com/TrustedComputingGroup/TPM.git 7 | [submodule "packit"] 8 | path = packit 9 | url = https://github.com/coconut-svsm/packit.git 10 | -------------------------------------------------------------------------------- /kernel/src/cpu/x86/smap.S: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // 3 | // Copyright (c) 2024 SUSE LLC 4 | // 5 | // Author: Thomas Leroy 6 | 7 | .code64 8 | 9 | .section .text 10 | .macro asm_clac 11 | .if !CFG_NOSMAP 12 | clac 13 | .endif 14 | .endm 15 | 16 | .macro asm_stac 17 | .if !CFG_NOSMAP 18 | stac 19 | .endif 20 | .endm 21 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/string/strncasecmp.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | #include 5 | 6 | int strncasecmp(const char *_l, const char *_r, size_t n) 7 | { 8 | const unsigned char *l=(void *)_l, *r=(void *)_r; 9 | if (!n--) return 0; 10 | for (; *l && *r && n && (*l == *r || tolower(*l) == tolower(*r)); l++, r++, n--); 11 | return tolower(*l) - tolower(*r); 12 | } 13 | -------------------------------------------------------------------------------- /syscall/src/console.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // 3 | // Copyright (c) 2024 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | 7 | use crate::{write, FsObjHandle, ObjHandle, SysCallError}; 8 | 9 | static CONSOLE_HANDLE: FsObjHandle = FsObjHandle::new(ObjHandle::new(0)); 10 | 11 | pub fn write_console(buf: &[u8]) -> Result { 12 | write(&CONSOLE_HANDLE, buf) 13 | } 14 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/stdio/vasprintf.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | int vasprintf(char **s, const char *fmt, va_list ap) 8 | { 9 | va_list ap2; 10 | va_copy(ap2, ap); 11 | int l = vsnprintf(0, 0, fmt, ap2); 12 | va_end(ap2); 13 | 14 | if (l<0 || !(*s=malloc(l+1U))) return -1; 15 | return vsnprintf(*s, l+1U, fmt, ap); 16 | } 17 | -------------------------------------------------------------------------------- /verification/verify_external/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "verify_external" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | verus_builtin = { workspace = true, optional = true } 8 | verus_builtin_macros = { workspace = true } 9 | vstd = { workspace = true, optional = true } 10 | 11 | [lints] 12 | workspace = true 13 | 14 | [features] 15 | default = [] 16 | noverify = [] 17 | verus = ["verus_builtin", "vstd"] 18 | -------------------------------------------------------------------------------- /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | 3 | [target.x86_64-unknown-none] 4 | rustflags = [ 5 | "-C", "force-frame-pointers", 6 | "-C", "linker-flavor=ld", 7 | "--cfg", "aes_force_soft", 8 | "--cfg", "polyval_force_soft", 9 | ] 10 | 11 | [target.x86_64-unknown-linux-gnu] 12 | rustflags = [ 13 | "-C", "code-model=kernel", 14 | ] 15 | 16 | [alias] 17 | verify = "v build --features verus" 18 | xbuild = "run --package xbuild --release --" 19 | -------------------------------------------------------------------------------- /kernel/src/cpu/x86/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // 3 | // Copyright (c) 2024 SUSE LLC 4 | // 5 | // Author: Thomas Leroy 6 | 7 | pub mod apic; 8 | pub mod smap; 9 | pub mod x2apic; 10 | 11 | pub use apic::{ 12 | apic_enable, apic_eoi, apic_in_service, apic_initialize, apic_post_irq, apic_sw_enable, 13 | ApicAccess, X86Apic, MSR_APIC_BASE, 14 | }; 15 | pub use x2apic::{X2ApicAccessor, X2APIC_ACCESSOR}; 16 | -------------------------------------------------------------------------------- /elf/src/types.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: (GPL-2.0-or-later OR MIT) 2 | // 3 | // Copyright (c) 2023 SUSE LLC 4 | // 5 | // Author: Nicolai Stange 6 | // 7 | // vim: ts=4 sw=4 et 8 | 9 | pub type Elf64Addr = u64; 10 | pub type Elf64Off = u64; 11 | pub type Elf64Half = u16; 12 | pub type Elf64Word = u32; 13 | pub type Elf64Sword = i32; 14 | pub type Elf64Xword = u64; 15 | pub type Elf64Sxword = i64; 16 | pub type Elf64char = u8; 17 | -------------------------------------------------------------------------------- /kernel/src/mm/vm/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2022-2023 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | 7 | mod mapping; 8 | mod range; 9 | 10 | pub use mapping::{ 11 | Mapping, RawAllocMapping, VMFileMapping, VMFileMappingFlags, VMKernelStack, VMMAdapter, 12 | VMPhysMem, VMReserved, VMalloc, VirtualMapping, VMM, 13 | }; 14 | pub use range::{VMRMapping, VMR, VMR_GRANULE}; 15 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/stdlib/atoi.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | #include 5 | 6 | int atoi(const char *s) 7 | { 8 | int n=0, neg=0; 9 | while (isspace(*s)) s++; 10 | switch (*s) { 11 | case '-': neg=1; 12 | case '+': s++; 13 | } 14 | /* Compute n as a negative number to avoid overflow on INT_MIN */ 15 | while (isdigit(*s)) 16 | n = 10*n - (*s++ - '0'); 17 | return neg ? n : -n; 18 | } 19 | -------------------------------------------------------------------------------- /syscall/src/lib.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // 3 | // Copyright (c) 2024 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | #![no_std] 7 | 8 | mod call; 9 | mod class0; 10 | mod class1; 11 | mod class3; 12 | mod console; 13 | mod def; 14 | mod obj; 15 | 16 | pub use call::SysCallError; 17 | pub use class0::*; 18 | pub use class1::*; 19 | pub use class3::*; 20 | pub use console::*; 21 | pub use def::*; 22 | pub use obj::*; 23 | -------------------------------------------------------------------------------- /kernel/src/hyperv/msr.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Jon Lange (jlange@microsoft.com) 6 | 7 | #[repr(u32)] 8 | #[derive(Clone, Copy, Debug)] 9 | pub enum HyperVMsr { 10 | GuestOSID = 0x40000000, 11 | Hypercall = 0x40000001, 12 | } 13 | 14 | impl From for u32 { 15 | fn from(msr: HyperVMsr) -> Self { 16 | msr as u32 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/stdlib/qsort_nr.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #define _BSD_SOURCE 4 | #include 5 | 6 | typedef int (*cmpfun)(const void *, const void *); 7 | 8 | static int wrapper_cmp(const void *v1, const void *v2, void *cmp) 9 | { 10 | return ((cmpfun)cmp)(v1, v2); 11 | } 12 | 13 | void qsort(void *base, size_t nel, size_t width, cmpfun cmp) 14 | { 15 | __qsort_r(base, nel, width, wrapper_cmp, (void *)cmp); 16 | } 17 | -------------------------------------------------------------------------------- /kernel/src/fs/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2023 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | 7 | mod api; 8 | mod buffer; 9 | mod console; 10 | mod filesystem; 11 | mod init; 12 | mod obj; 13 | mod ramfs; 14 | 15 | pub use api::*; 16 | pub use buffer::*; 17 | pub use console::{stdout_open, ConsoleFile}; 18 | pub use filesystem::*; 19 | pub use init::populate_ram_fs; 20 | pub use obj::FsObj; 21 | -------------------------------------------------------------------------------- /verification/verus_stub/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "verus_stub" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | 8 | verus_builtin_macros = { workspace = true, optional = true } 9 | vstd = { workspace = true, optional = true } 10 | verus_macro_stub = { workspace = true, optional = true} 11 | 12 | [features] 13 | default = ["dep:verus_macro_stub"] 14 | disable = ["verus_builtin_macros", "vstd"] 15 | 16 | [lints] 17 | workspace = true 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # build artifacts 2 | /bin/ 3 | /target/ 4 | 5 | # release files 6 | release/src/git_version.rs 7 | 8 | # signing test keys for IGVM 9 | # See `scripts/gen_igvm_signing_keys.sh` and `scripts/test_sign_qemu_igvm.sh` 10 | testkeys/ 11 | 12 | # IDE/editors tmp files 13 | *.swp 14 | *~ 15 | .idea/ 16 | 17 | # verification logs 18 | verus*.log 19 | 20 | # local fuzzing artifacts 21 | **/fuzz/target 22 | **/fuzz/corpus 23 | **/fuzz/artifacts 24 | **/fuzz/coverage 25 | -------------------------------------------------------------------------------- /kernel/src/cpu/isst.rs: -------------------------------------------------------------------------------- 1 | use core::num::NonZeroU8; 2 | 3 | use crate::address::VirtAddr; 4 | 5 | #[derive(Debug, Default, Clone, Copy)] 6 | #[repr(C)] 7 | pub struct Isst { 8 | _reserved: u64, 9 | entries: [VirtAddr; 7], 10 | } 11 | 12 | impl Isst { 13 | pub fn set(&mut self, index: NonZeroU8, addr: VirtAddr) { 14 | // ISST entries start at index 1 15 | let index = usize::from(index.get() - 1); 16 | self.entries[index] = addr; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /bootlib/src/lib.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Jon Lange (jlange@microsoft.com) 6 | 7 | //! This crate provides definitions of structures used bo COCONUT-SVSM during 8 | //! its boot process, which must also be shared with the utility that builds 9 | //! the boot image file. 10 | 11 | #![no_std] 12 | 13 | pub mod firmware; 14 | pub mod igvm_params; 15 | pub mod kernel_launch; 16 | pub mod platform; 17 | -------------------------------------------------------------------------------- /libtcgtpm/deps/TpmConfiguration/TpmConfiguration/TpmProfile.h: -------------------------------------------------------------------------------- 1 | // The primary configuration file that collects all configuration options for a 2 | // TPM build. 3 | #ifndef _TPM_PROFILE_H_ 4 | #define _TPM_PROFILE_H_ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #endif // _TPM_PROFILE_H_ 12 | -------------------------------------------------------------------------------- /libtcgtpm/deps/TpmConfiguration/TpmConfiguration/VendorCommands/HandleProcess.inl: -------------------------------------------------------------------------------- 1 | // This file contains an inlined portion of the HandleProcssor switch statement. 2 | // 3 | // IMPORTANT: This file is included in the middle of a switch statement, and 4 | // therefore it must not contain anything other than switch blocks 5 | // (This is why the file has the .INL extension, it's not a normal header. 6 | // 7 | #if CC_Vendor_TCG_Test 8 | case TPM_CC_Vendor_TCG_Test: 9 | break; 10 | #endif // CC_Vendor_TCG_Test 11 | -------------------------------------------------------------------------------- /syscall/src/class3.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2025 Intel Corporation. 4 | // 5 | // Author: Chuanxiao Dong 6 | 7 | use super::call::{syscall1, SysCallError}; 8 | use super::SYS_CAPABILITIES; 9 | 10 | pub fn capabilities(index: u32) -> Result { 11 | // SAFETY: Invokes a system call and does not directly change any memory of 12 | // the process. 13 | unsafe { syscall1(SYS_CAPABILITIES, index.into()) } 14 | } 15 | -------------------------------------------------------------------------------- /kernel/src/types.verus.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Ziqiao Zhou 6 | verus! { 7 | 8 | pub broadcast group group_types_proof { 9 | verify_proof::bits::lemma_bit_usize_shl_values, 10 | } 11 | 12 | broadcast use group_types_proof; 13 | 14 | pub broadcast proof fn lemma_page_size() 15 | ensures 16 | #[trigger] PAGE_SIZE == 0x1000, 17 | { 18 | assert(1usize << 12 == 0x1000); 19 | } 20 | 21 | } // verus! 22 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/time/gmtime_r.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | #include 5 | 6 | char *__utc = "UTC"; 7 | 8 | struct tm *gmtime_r(const time_t *restrict t, struct tm *restrict tm) 9 | { 10 | if (__secs_to_tm(*t, tm) < 0) { 11 | errno = EOVERFLOW; 12 | return 0; 13 | } 14 | tm->tm_isdst = 0; 15 | tm->tm_gmtoff = 0; 16 | tm->tm_zone = __utc; 17 | return tm; 18 | } 19 | 20 | 21 | struct tm *gmtime(const time_t *t) 22 | { 23 | static struct tm tm; 24 | return gmtime_r(t, &tm); 25 | } 26 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/string/strcasecmp.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | #include 5 | 6 | int strcasecmp(const char *_l, const char *_r) 7 | { 8 | const unsigned char *l=(void *)_l, *r=(void *)_r; 9 | for (; *l && *r && (*l == *r || tolower(*l) == tolower(*r)); l++, r++); 10 | return tolower(*l) - tolower(*r); 11 | } 12 | 13 | #if 0 14 | int __strcasecmp_l(const char *l, const char *r, locale_t loc) 15 | { 16 | return strcasecmp(l, r); 17 | } 18 | 19 | weak_alias(__strcasecmp_l, strcasecmp_l); 20 | #endif 21 | -------------------------------------------------------------------------------- /kernel/src/utils/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2022-2023 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | 7 | pub mod bitmap_allocator; 8 | pub mod immut_after_init; 9 | pub mod memory_region; 10 | pub mod scoped; 11 | pub mod tcb_ptr; 12 | pub mod util; 13 | pub mod vec; 14 | 15 | pub use memory_region::MemoryRegion; 16 | pub use scoped::{ScopedMut, ScopedRef}; 17 | pub use util::{ 18 | align_down, align_up, is_aligned, overlap, page_align_up, page_offset, round_to_pages, 19 | zero_mem_region, 20 | }; 21 | -------------------------------------------------------------------------------- /tools/aproxy/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aproxy" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [target.'cfg(all(target_os = "linux"))'.dependencies] 7 | reqwest = { version = "0.12.9", default-features = false, features = ["blocking", "cookies", "json"] } 8 | kbs-types.workspace = true 9 | 10 | [dependencies] 11 | anyhow = "1.0.93" 12 | base64 = { workspace = true, features = ["std"] } 13 | clap = { version = "4.5", features = ["derive"] } 14 | libaproxy.workspace = true 15 | serde.workspace = true 16 | serde_json.workspace = true 17 | 18 | [lints] 19 | workspace = true 20 | -------------------------------------------------------------------------------- /libtcgtpm/src/lib.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // 3 | // Copyright (c) 2024 IBM Corporation 4 | // 5 | // Author: Claudio Carvalho 6 | 7 | //! This crate provides the libtcgtpm definitions used by the COCONUT-SVSM 8 | //! for the vTPM. 9 | 10 | #![no_std] 11 | 12 | /// C bindings 13 | pub mod bindings { 14 | #![allow(non_upper_case_globals)] 15 | #![allow(non_camel_case_types)] 16 | #![allow(non_snake_case)] 17 | #![allow(unused)] 18 | #![allow(improper_ctypes)] 19 | 20 | include!(concat!(env!("OUT_DIR"), "/bindings.rs")); 21 | } 22 | -------------------------------------------------------------------------------- /scripts/gen_igvm_signing_keys.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # SPDX-License-Identifier: MIT OR Apache-2.0 3 | # 4 | # Copyright (c) 2024 SUSE LLC 5 | # 6 | # Author: Roy Hopkins 7 | # 8 | # Generate keys for testing that can be used for signing an IGVM file 9 | set -e 10 | SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) 11 | 12 | mkdir -p $SCRIPT_DIR/../testkeys/ 13 | openssl ecparam -name secp384r1 -genkey -noout -out $SCRIPT_DIR/../testkeys/id_key.pem 14 | openssl ecparam -name secp384r1 -genkey -noout -out $SCRIPT_DIR/../testkeys/author_key.pem 15 | -------------------------------------------------------------------------------- /stage1/build.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (C) 2024 Intel Corporation 4 | // 5 | // Author: Peter Fang 6 | 7 | fn main() { 8 | println!("cargo:rustc-link-arg-bin=stage1=-nostdlib"); 9 | println!("cargo:rustc-link-arg-bin=stage1=--build-id=none"); 10 | println!("cargo:rustc-link-arg-bin=stage1=-Tstage1/stage1.lds"); 11 | println!("cargo:rustc-link-arg-bin=stage1=-no-pie"); 12 | println!("cargo:rustc-link-arg-bin=stage1=-no-gc-sections"); 13 | 14 | println!("cargo:rerun-if-changed=stage1.lds"); 15 | } 16 | -------------------------------------------------------------------------------- /kernel/src/kernel_region.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Jon Lange (jlange@microsoft.com) 6 | 7 | use crate::address::PhysAddr; 8 | use crate::utils::MemoryRegion; 9 | use bootlib::kernel_launch::KernelLaunchInfo; 10 | 11 | pub fn new_kernel_region(launch_info: &KernelLaunchInfo) -> MemoryRegion { 12 | let start = PhysAddr::from(launch_info.kernel_region_phys_start); 13 | let end = PhysAddr::from(launch_info.kernel_region_phys_end); 14 | MemoryRegion::from_addresses(start, end) 15 | } 16 | -------------------------------------------------------------------------------- /tools/igvmbuilder/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "igvmbuilder" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # specify dependencies' target to avoid feature unification with SVSM 7 | # see https://doc.rust-lang.org/cargo/reference/features.html#feature-unification 8 | [target.'cfg(all(target_os = "linux"))'.dependencies] 9 | bootlib.workspace = true 10 | 11 | clap = { workspace = true, default-features = true, features = ["derive"] } 12 | igvm_defs.workspace = true 13 | igvm.workspace = true 14 | uuid.workspace = true 15 | zerocopy.workspace = true 16 | 17 | [lints] 18 | workspace = true 19 | -------------------------------------------------------------------------------- /kernel/src/block/api.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2024 Red Hat, Inc. 4 | // 5 | // Author: Stefano Garzarella 6 | // Author: Oliver Steffen 7 | 8 | use crate::error::SvsmError; 9 | 10 | pub trait BlockDriver { 11 | fn read_blocks(&self, block_id: usize, buf: &mut [u8]) -> Result<(), SvsmError>; 12 | fn write_blocks(&self, block_id: usize, buf: &[u8]) -> Result<(), SvsmError>; 13 | fn block_size_log2(&self) -> u8; 14 | fn size(&self) -> usize; 15 | fn flush(&self) -> Result<(), SvsmError>; 16 | } 17 | -------------------------------------------------------------------------------- /libtcgtpm/deps/TpmConfiguration/TpmVendorCommandHandlers/Vendor_TCG_Test.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #if CC_Vendor_TCG_Test // Conditional expansion of this file 4 | 5 | # include 6 | # include 7 | 8 | TPM_RC 9 | TPM2_Vendor_TCG_Test(Vendor_TCG_Test_In* in, // IN: input parameter list 10 | Vendor_TCG_Test_Out* out // OUT: output parameter list 11 | ) 12 | { 13 | out->outputData = in->inputData; 14 | return TPM_RC_SUCCESS; 15 | } 16 | 17 | #endif // CC_Vendor_TCG_Test -------------------------------------------------------------------------------- /kernel/src/syscall/class3.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2025 Intel Corporation. 4 | // 5 | // Author: Chuanxiao Dong 6 | 7 | use crate::platform::capabilities::Cap; 8 | use crate::platform::CAPS; 9 | use syscall::SysCallError; 10 | 11 | pub fn sys_capabilities(index: u32) -> Result { 12 | let cap = match index { 13 | 0 => Cap::NrCaps, 14 | i if i <= Cap::NrCaps as u32 => (i - 1).try_into().unwrap(), 15 | _ => return Err(SysCallError::ENOTFOUND), 16 | }; 17 | Ok(CAPS.get(cap)) 18 | } 19 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/string/strcspn.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | 5 | #define BITOP(a,b,op) \ 6 | ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a)))) 7 | 8 | size_t strcspn(const char *s, const char *c) 9 | { 10 | const char *a = s; 11 | size_t byteset[32/sizeof(size_t)]; 12 | 13 | if (!c[0] || !c[1]) return __strchrnul(s, *c)-a; 14 | 15 | memset(byteset, 0, sizeof byteset); 16 | for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++); 17 | for (; *s && !BITOP(byteset, *(unsigned char *)s, &); s++); 18 | return s-a; 19 | } 20 | -------------------------------------------------------------------------------- /verification/verify_proof/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "verify_proof" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | verus_builtin = { workspace = true, optional = true } 10 | verus_builtin_macros = { workspace = true } 11 | vstd = { workspace = true, optional = true } 12 | verus_state_machines_macros = { workspace = true } 13 | seq-macro = "0.3" 14 | 15 | [lints] 16 | workspace = true 17 | 18 | [features] 19 | default = [] 20 | noverify = [] 21 | verus = ["verus_builtin", "vstd"] 22 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/string/strspn.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | 5 | #define BITOP(a,b,op) \ 6 | ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a)))) 7 | 8 | size_t strspn(const char *s, const char *c) 9 | { 10 | const char *a = s; 11 | size_t byteset[32/sizeof(size_t)] = { 0 }; 12 | 13 | if (!c[0]) return 0; 14 | if (!c[1]) { 15 | for (; *s == *c; s++); 16 | return s-a; 17 | } 18 | 19 | for (; *c && BITOP(byteset, *(unsigned char *)c, |=); c++); 20 | for (; *s && BITOP(byteset, *(unsigned char *)s, &); s++); 21 | return s-a; 22 | } 23 | -------------------------------------------------------------------------------- /tools/igvmmeasure/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "igvmmeasure" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # specify dependencies' target to avoid feature unification with SVSM 7 | # see https://doc.rust-lang.org/cargo/reference/features.html#feature-unification 8 | [target.'cfg(all(target_os = "linux"))'.dependencies] 9 | clap = { workspace = true, default-features = true, features = ["derive"] } 10 | sha2 = { workspace = true, default-features = true } 11 | igvm.workspace = true 12 | igvm_defs.workspace = true 13 | p384.workspace = true 14 | zerocopy.workspace = true 15 | 16 | [lints] 17 | workspace = true 18 | -------------------------------------------------------------------------------- /scripts/vfmt.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # SPDX-License-Identifier: MIT OR Apache-2.0 3 | # 4 | # Copyright (c) Microsoft Corporation 5 | # 6 | # Author: Ziqiao Zhou 7 | # A script to format code inside verus macro. 8 | 9 | for f in `find ./ -type f -name "*.verus.rs"` 10 | do 11 | output=$(verusfmt $f $@ 2>&1) 12 | if [ $? -ne 0 ]; then 13 | # Check if the output contains "Failed to parse" 14 | if echo "$output" | grep -q "Failed to parse"; then 15 | echo "Continuing despite parse failure: $output" 16 | else 17 | echo "Error occurred: $output" 18 | exit 1 19 | fi 20 | fi 21 | done 22 | -------------------------------------------------------------------------------- /.github/workflows/signed-off.yml: -------------------------------------------------------------------------------- 1 | name: SignedOff 2 | 3 | on: [pull_request] 4 | 5 | jobs: 6 | check: 7 | name: Check commits 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Checkout 11 | uses: actions/checkout@v3 12 | with: 13 | ref: ${{ github.event.pull_request.head.sha }} 14 | fetch-depth: 0 15 | 16 | - name: Check commits 17 | run: | 18 | git fetch 19 | git fetch origin ${{ github.event.pull_request.base.ref }} 20 | ${GITHUB_WORKSPACE}/scripts/check-signed-off.sh ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }} 21 | -------------------------------------------------------------------------------- /kernel/src/virtio/error.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2025 Red Hat, Inc. 4 | // 5 | // Author: Oliver Steffen 6 | 7 | #[derive(Debug, Clone, Copy, PartialEq)] 8 | pub enum VirtioError { 9 | /// No valid VirtIO device found the specified address. This can be due to 10 | /// a bad magic number, an unsupported VirtIO version, or a zeroed device ID. 11 | InvalidDevice, 12 | /// The supplied VirtIO device is not of the extpected type. 13 | /// This is returned, for example, when a blk device driver is given the MMIO address of a vsock device. 14 | InvalidDeviceType, 15 | } 16 | -------------------------------------------------------------------------------- /kernel/src/mm/vm/mapping/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2022-2023 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | 7 | pub mod api; 8 | pub mod file_mapping; 9 | pub mod kernel_stack; 10 | pub mod phys_mem; 11 | pub mod rawalloc; 12 | pub mod reserved; 13 | pub mod vmalloc; 14 | 15 | pub use api::{Mapping, VMMAdapter, VMPageFaultResolution, VirtualMapping, VMM}; 16 | pub use file_mapping::{VMFileMapping, VMFileMappingFlags}; 17 | pub use kernel_stack::VMKernelStack; 18 | pub use phys_mem::VMPhysMem; 19 | pub use rawalloc::RawAllocMapping; 20 | pub use reserved::VMReserved; 21 | pub use vmalloc::VMalloc; 22 | -------------------------------------------------------------------------------- /tools/igvmbuilder/src/main.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2023 SUSE LLC 4 | // 5 | // Author: Roy Hopkins 6 | #![forbid(unsafe_code)] 7 | 8 | use gpa_map::GpaMap; 9 | use igvm_builder::IgvmBuilder; 10 | use std::error::Error; 11 | 12 | mod cmd_options; 13 | mod cpuid; 14 | mod firmware; 15 | mod gpa_map; 16 | mod igvm_builder; 17 | mod igvm_firmware; 18 | mod ovmf_firmware; 19 | mod paging; 20 | mod platform; 21 | mod sipi; 22 | mod stage2_stack; 23 | mod vmsa; 24 | 25 | fn main() -> Result<(), Box> { 26 | let builder = IgvmBuilder::new()?; 27 | builder.build()?; 28 | Ok(()) 29 | } 30 | -------------------------------------------------------------------------------- /kernel/src/locking/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2022-2023 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | 7 | pub mod common; 8 | pub mod rwlock; 9 | pub mod spinlock; 10 | 11 | pub use common::{IrqGuardLocking, IrqLocking, TprGuardLocking}; 12 | pub use rwlock::{ 13 | RWLock, RWLockAnyTpr, RWLockIrqSafe, RWLockTpr, ReadLockGuard, ReadLockGuardAnyTpr, 14 | ReadLockGuardIrqSafe, WriteLockGuard, WriteLockGuardAnyTpr, WriteLockGuardIrqSafe, 15 | }; 16 | pub use spinlock::{ 17 | LockGuard, LockGuardAnyTpr, LockGuardIrqSafe, RawLockGuard, SpinLock, SpinLockAnyTpr, 18 | SpinLockIrqSafe, SpinLockTpr, 19 | }; 20 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/string/strlen.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define ALIGN (sizeof(size_t)) 8 | #define ONES ((size_t)-1/UCHAR_MAX) 9 | #define HIGHS (ONES * (UCHAR_MAX/2+1)) 10 | #define HASZERO(x) (((x)-ONES) & ~(x) & HIGHS) 11 | 12 | size_t strlen(const char *s) 13 | { 14 | const char *a = s; 15 | #ifdef __GNUC__ 16 | typedef size_t __attribute__((__may_alias__)) word; 17 | const word *w; 18 | for (; (uintptr_t)s % ALIGN; s++) if (!*s) return s-a; 19 | for (w = (const void *)s; !HASZERO(*w); w++); 20 | s = (const void *)w; 21 | #endif 22 | for (; *s; s++); 23 | return s-a; 24 | } 25 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/stdio/printf.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | #include 5 | 6 | int printf(const char *restrict fmt, ...) 7 | { 8 | int ret; 9 | va_list ap; 10 | va_start(ap, fmt); 11 | ret = vprints(fmt, ap); 12 | va_end(ap); 13 | return ret; 14 | } 15 | 16 | int dprintf(int fd, const char *__restrict fmt, ...) 17 | { 18 | int ret; 19 | va_list ap; 20 | va_start(ap, fmt); 21 | ret = vprints(fmt, ap); 22 | va_end(ap); 23 | return ret; 24 | } 25 | 26 | int vdprintf(int fd, const char *restrict fmt, va_list ap) 27 | { 28 | return vprints(fmt, ap); 29 | } 30 | 31 | int puts(const char *s) 32 | { 33 | return printf("%s\n", s); 34 | } 35 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/setjmp/x86_64/longjmp.s: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | /* Copyright 2011-2012 Nicholas J. Kain, licensed under standard MIT license */ 3 | 4 | .global _longjmp 5 | .global longjmp 6 | .type _longjmp,@function 7 | .type longjmp,@function 8 | _longjmp: 9 | longjmp: 10 | xor %eax,%eax 11 | cmp $1,%esi /* CF = val ? 0 : 1 */ 12 | adc %esi,%eax /* eax = val + !val */ 13 | mov (%rdi),%rbx /* rdi is the jmp_buf, restore regs from it */ 14 | mov 8(%rdi),%rbp 15 | mov 16(%rdi),%r12 16 | mov 24(%rdi),%r13 17 | mov 32(%rdi),%r14 18 | mov 40(%rdi),%r15 19 | mov 48(%rdi),%rsp 20 | jmp *56(%rdi) /* goto saved address without altering rsp */ 21 | -------------------------------------------------------------------------------- /fuzz/fuzz_targets/insn.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | 3 | use libfuzzer_sys::{fuzz_target, Corpus}; 4 | use svsm::insn_decode::{Instruction, TestCtx, MAX_INSN_SIZE}; 5 | 6 | fuzz_target!(|input: &[u8]| -> Corpus { 7 | let Some(input) = input.get(..MAX_INSN_SIZE) else { 8 | return Corpus::Reject; 9 | }; 10 | 11 | let mut data = [0u8; MAX_INSN_SIZE]; 12 | data.copy_from_slice(input); 13 | 14 | let insn = Instruction::new(data); 15 | let _ = core::hint::black_box({ 16 | let mut ctx = TestCtx::default(); 17 | match insn.decode(&ctx) { 18 | Ok(insn_ctx) => insn_ctx.emulate(&mut ctx), 19 | Err(e) => Err(e), 20 | } 21 | }); 22 | 23 | Corpus::Keep 24 | }); 25 | -------------------------------------------------------------------------------- /verification/verify_external/build.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Ziqiao Zhou 6 | 7 | fn main() { 8 | init_verify(); 9 | } 10 | 11 | fn init_verify() { 12 | if cfg!(feature = "noverify") { 13 | println!("cargo:rustc-env=VERUS_ARGS=--no-verify"); 14 | } else { 15 | let verus_args = [ 16 | "--rlimit=1", 17 | "--expand-errors", 18 | "--multiple-errors=5", 19 | "--no-auto-recommends-check", 20 | "--trace", 21 | "-Z unstable-options", 22 | ]; 23 | println!("cargo:rustc-env=VERUS_ARGS={}", verus_args.join(" ")); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /kernel/src/task/waiting.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2024 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | 7 | use super::tasks::TaskPointer; 8 | 9 | #[derive(Debug, Default)] 10 | pub struct WaitQueue { 11 | waiter: Option, 12 | } 13 | 14 | impl WaitQueue { 15 | pub const fn new() -> Self { 16 | Self { waiter: None } 17 | } 18 | 19 | pub fn wait_for_event(&mut self, current_task: TaskPointer) { 20 | assert!(self.waiter.is_none()); 21 | 22 | current_task.set_task_blocked(); 23 | self.waiter = Some(current_task); 24 | } 25 | 26 | pub fn wakeup(&mut self) -> Option { 27 | self.waiter.take() 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /virtio-drivers/src/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "virtio-drivers" 3 | version = "0.7.5" 4 | license = "MIT" 5 | authors = [ 6 | "Jiajie Chen ", 7 | "Runji Wang ", 8 | "Yuekai Jia ", 9 | "Andrew Walbran ", 10 | ] 11 | edition = "2021" 12 | description = "VirtIO guest drivers based on https://github.com/rcore-os/virtio-drivers, adapted for Coconut SVSM" 13 | keywords = ["virtio"] 14 | categories = ["hardware-support", "no-std"] 15 | 16 | [dependencies] 17 | log = { workspace = true } 18 | bitflags = { workspace = true } 19 | enumn = "0.1.14" 20 | zerocopy = { workspace = true, features = ["derive"] } 21 | 22 | [features] 23 | default = ["alloc"] 24 | alloc = ["zerocopy/alloc"] 25 | -------------------------------------------------------------------------------- /kernel/src/sev/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2022-2023 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | 7 | pub mod ghcb; 8 | pub mod hv_doorbell; 9 | pub mod msr_protocol; 10 | pub mod secrets_page; 11 | pub mod snp_apic; 12 | pub mod status; 13 | pub mod tlb; 14 | pub mod vmsa; 15 | 16 | pub mod utils; 17 | 18 | pub use msr_protocol::init_hypervisor_ghcb_features; 19 | pub use secrets_page::{secrets_page, secrets_page_mut, SecretsPage, VMPCK_SIZE}; 20 | pub use snp_apic::{GHCBApicAccessor, GHCB_APIC_ACCESSOR}; 21 | pub use status::sev_status_init; 22 | pub use status::sev_status_verify; 23 | pub use utils::{pvalidate, pvalidate_range, PvalidateOp, SevSnpError}; 24 | pub use utils::{rmp_adjust, RMPFlags}; 25 | -------------------------------------------------------------------------------- /bootlib/src/platform.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Jon Lange (jlange@microsoft.com) 6 | 7 | /// Defines the underlying platform type on which the SVSM will run. 8 | #[derive(Copy, Clone, Debug, PartialEq)] 9 | #[repr(C)] 10 | pub enum SvsmPlatformType { 11 | Native = 0, 12 | Snp = 1, 13 | Tdp = 2, 14 | } 15 | 16 | impl From for SvsmPlatformType { 17 | fn from(value: u32) -> Self { 18 | match value { 19 | 1 => Self::Snp, 20 | 2 => Self::Tdp, 21 | _ => Self::Native, 22 | } 23 | } 24 | } 25 | 26 | impl From for u32 { 27 | fn from(p: SvsmPlatformType) -> u32 { 28 | p as u32 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /kernel/src/platform/guest_cpu.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Jon Lange (jlange@microsoft.com) 6 | 7 | pub trait GuestCpuState { 8 | fn get_tpr(&self) -> u8; 9 | fn set_tpr(&mut self, tpr: u8); 10 | fn request_nmi(&mut self); 11 | fn queue_interrupt(&mut self, irq: u8); 12 | fn try_deliver_interrupt_immediately(&mut self, irq: u8) -> bool; 13 | fn in_intr_shadow(&self) -> bool; 14 | fn interrupts_enabled(&self) -> bool; 15 | fn check_and_clear_pending_nmi(&mut self) -> bool; 16 | fn check_and_clear_pending_interrupt_event(&mut self) -> u8; 17 | fn check_and_clear_pending_virtual_interrupt(&mut self) -> u8; 18 | fn disable_alternate_injection(&mut self); 19 | } 20 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/setjmp/x86_64/setjmp.s: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | /* Copyright 2011-2012 Nicholas J. Kain, licensed under standard MIT license */ 3 | 4 | .global __setjmp 5 | .global _setjmp 6 | .global setjmp 7 | .type __setjmp,@function 8 | .type _setjmp,@function 9 | .type setjmp,@function 10 | __setjmp: 11 | _setjmp: 12 | setjmp: 13 | mov %rbx,(%rdi) /* rdi is jmp_buf, move registers onto it */ 14 | mov %rbp,8(%rdi) 15 | mov %r12,16(%rdi) 16 | mov %r13,24(%rdi) 17 | mov %r14,32(%rdi) 18 | mov %r15,40(%rdi) 19 | lea 8(%rsp),%rdx /* this is our rsp WITHOUT current ret addr */ 20 | mov %rdx,48(%rdi) 21 | mov (%rsp),%rdx /* save return addr ptr for new rip */ 22 | mov %rdx,56(%rdi) 23 | xor %eax,%eax /* always return 0 */ 24 | ret 25 | -------------------------------------------------------------------------------- /virtio-drivers/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "virtio-drivers" 3 | version = "0.7.5" 4 | license = "MIT" 5 | authors = [ 6 | "Jiajie Chen ", 7 | "Runji Wang ", 8 | "Yuekai Jia ", 9 | "Andrew Walbran ", 10 | ] 11 | edition = "2021" 12 | description = "VirtIO guest drivers based on https://github.com/rcore-os/virtio-drivers, adapted for Coconut SVSM" 13 | keywords = ["virtio"] 14 | categories = ["hardware-support", "no-std"] 15 | 16 | [dependencies] 17 | log = { workspace = true } 18 | bitflags = { workspace = true } 19 | enumn = "0.1.14" 20 | zerocopy = { workspace = true, features = ["derive"] } 21 | 22 | [features] 23 | default = ["alloc"] 24 | alloc = ["zerocopy/alloc"] 25 | 26 | [lints] 27 | workspace = true 28 | -------------------------------------------------------------------------------- /libtcgtpm/deps/TpmConfiguration/TpmConfiguration/VendorCommands/CommandAttributeData_s_ccAttr.inl: -------------------------------------------------------------------------------- 1 | // This file contains an inlined portion of the s_ccAttr array definition 2 | // for vendor commands. 3 | // 4 | // IMPORTANT: This file is included in the middle of an array initializer 5 | // therefore it must not contain anything other than comments and exactly one TPMA_CC 6 | // entry per vendor command. See the private Tpm header CommandAttributeData.h for 7 | // more info. 8 | // (This is why the file has the .INL extension, it's not a normal header. 9 | // 10 | #ifndef _COMMAND_CODE_ATTRIBUTES_ 11 | # error This file should be included only within CommandAttributeData.h 12 | #endif 13 | #if (PAD_LIST || CC_Vendor_TCG_Test) 14 | // TPM_CC_Vendor_TCG_Test 15 | TPMA_CC_INITIALIZER(0x0000, 0, 0, 0, 0, 0, 0, 1, 0), 16 | #endif 17 | -------------------------------------------------------------------------------- /verification/verify_proof/build.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Ziqiao Zhou 6 | 7 | fn main() { 8 | init_verify(); 9 | } 10 | 11 | fn init_verify() { 12 | if cfg!(feature = "noverify") { 13 | println!("cargo:rustc-env=VERUS_ARGS=--no-verify"); 14 | } else { 15 | // Set rlimit higher here for expensive but reusable proofs. 16 | let verus_args = [ 17 | "--rlimit=4", 18 | "--expand-errors", 19 | "--multiple-errors=5", 20 | "--no-auto-recommends-check", 21 | "--trace", 22 | "-Z unstable-options", 23 | ]; 24 | println!("cargo:rustc-env=VERUS_ARGS={}", verus_args.join(" ")); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /libaproxy/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "libaproxy" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | base64 = { workspace = true, features = ["alloc"] } 8 | cocoon-tpm-crypto = { workspace = true, features = [ 9 | "enable_arch_math_asm", "zeroize", 10 | # Enable x86 rdseed based rng. 11 | "enable_x86_64_rdseed", 12 | # At least one of block cipher, mode and hash is needed, 13 | # otherwise compilation will fail due to empty enums. 14 | "aes", "cbc", "cfb", "sha256", "sha384", "sha512", 15 | "ecc", "ecdh", "ecdsa", 16 | "ecc_nist_p224", "ecc_nist_p256", 17 | "ecc_nist_p384", "ecc_nist_p521", 18 | ]} 19 | cocoon-tpm-tpm2-interface.workspace = true 20 | kbs-types = { workspace = true, features = ["alloc"] } 21 | serde.workspace = true 22 | 23 | [lints] 24 | workspace = true 25 | -------------------------------------------------------------------------------- /tools/igvmbuilder/src/platform.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2024 Microsoft Corporation 4 | // 5 | // Author: Jon Lange 6 | 7 | use std::sync::atomic::{AtomicU32, Ordering}; 8 | 9 | pub struct PlatformMask { 10 | mask: AtomicU32, 11 | } 12 | 13 | impl PlatformMask { 14 | pub const fn new() -> Self { 15 | Self { 16 | mask: AtomicU32::new(0), 17 | } 18 | } 19 | 20 | pub fn get(&self) -> u32 { 21 | self.mask.load(Ordering::Relaxed) 22 | } 23 | 24 | pub fn add(&self, add_mask: u32) { 25 | self.mask.fetch_or(add_mask, Ordering::Relaxed); 26 | } 27 | 28 | pub fn contains(&self, test_mask: u32) -> bool { 29 | (self.mask.load(Ordering::Relaxed) & test_mask) != 0 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /verification/verus_macro_stub/src/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate proc_macro; 2 | use proc_macro::TokenStream; 3 | 4 | #[proc_macro_attribute] 5 | pub fn verus_verify(_attr: TokenStream, item: TokenStream) -> TokenStream { 6 | item 7 | } 8 | 9 | #[proc_macro_attribute] 10 | pub fn verus_spec(_attr: TokenStream, item: TokenStream) -> TokenStream { 11 | item 12 | } 13 | 14 | #[proc_macro] 15 | pub fn verus(input: proc_macro::TokenStream) -> proc_macro::TokenStream { 16 | input 17 | } 18 | 19 | #[proc_macro] 20 | pub fn proof(_input: TokenStream) -> TokenStream { 21 | TokenStream::new() 22 | } 23 | 24 | #[proc_macro] 25 | pub fn proof_decl(_input: TokenStream) -> TokenStream { 26 | TokenStream::new() 27 | } 28 | 29 | #[proc_macro] 30 | pub fn proof_with(_input: TokenStream) -> TokenStream { 31 | TokenStream::new() 32 | } 33 | -------------------------------------------------------------------------------- /kernel/src/task/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2022-2023 SUSE LLC 4 | // 5 | // Author: Roy Hopkins 6 | 7 | mod exec; 8 | mod schedule; 9 | mod task_mm; 10 | mod tasks; 11 | mod waiting; 12 | 13 | pub use schedule::{ 14 | create_user_task, current_task, current_task_terminated, finish_user_task, go_idle, 15 | is_current_task, schedule, schedule_init, schedule_task, scheduler_idle, set_affinity, 16 | start_kernel_task, start_kernel_thread, terminate, RunQueue, TASKLIST, 17 | }; 18 | 19 | pub use tasks::{ 20 | is_task_fault, KernelThreadStartInfo, Task, TaskContext, TaskError, TaskListAdapter, 21 | TaskPointer, TaskRunListAdapter, TaskState, INITIAL_TASK_ID, TASK_FLAG_SHARE_PT, 22 | }; 23 | 24 | pub use exec::exec_user; 25 | pub use waiting::WaitQueue; 26 | -------------------------------------------------------------------------------- /kernel/src/testutils.rs: -------------------------------------------------------------------------------- 1 | use crate::platform::SVSM_PLATFORM; 2 | use bootlib::platform::SvsmPlatformType; 3 | use core::sync::atomic::{AtomicBool, Ordering}; 4 | 5 | static HAS_QEMU_TESTDEV: AtomicBool = AtomicBool::new(false); 6 | static HAS_TEST_IOREQUESTS: AtomicBool = AtomicBool::new(false); 7 | 8 | pub fn has_qemu_testdev() -> bool { 9 | HAS_QEMU_TESTDEV.load(Ordering::Acquire) 10 | } 11 | pub fn has_test_iorequests() -> bool { 12 | HAS_TEST_IOREQUESTS.load(Ordering::Acquire) 13 | } 14 | 15 | pub fn is_test_platform_type(platform_type: SvsmPlatformType) -> bool { 16 | SVSM_PLATFORM.platform_type() == platform_type 17 | } 18 | 19 | pub fn set_has_qemu_testdev() { 20 | HAS_QEMU_TESTDEV.store(true, Ordering::Release) 21 | } 22 | 23 | pub fn set_has_test_iorequests() { 24 | HAS_TEST_IOREQUESTS.store(true, Ordering::Release) 25 | } 26 | -------------------------------------------------------------------------------- /libtcgtpm/deps/TpmConfiguration/TpmConfiguration/VendorCommands/CommandDispatchData_s_CommandDataArray.inl: -------------------------------------------------------------------------------- 1 | // This file contains an inlined portion of the s_ccAttr array definition 2 | // for vendor commands. 3 | // 4 | // IMPORTANT: This file is included in the middle of an array initializer 5 | // therefore it must not contain anything other than comments and exactly one TPMA_CC 6 | // entry per vendor command. See the private Tpm header CommandAttributeData.h for 7 | // more info. 8 | // (This is why the file has the .INL extension, it's not a normal header. 9 | // 10 | #ifndef _COMMAND_TABLE_DISPATCH_ 11 | #error This file should only be included inside CommandDispatchData.h when table dispatching is turned on. 12 | #endif 13 | #if (PAD_LIST || CC_Vendor_TCG_Test) 14 | (COMMAND_DESCRIPTOR_t*)_Vendor_TCG_TestDataAddress, 15 | #endif // CC_Vendor_TCG_Test 16 | -------------------------------------------------------------------------------- /libtcgtpm/deps/TpmConfiguration/TpmConfiguration/VendorCommands/prototypes/Vendor_TCG_Test_fp.h: -------------------------------------------------------------------------------- 1 | 2 | #if CC_Vendor_TCG_Test // Command must be enabled 3 | 4 | # ifndef _TPM_INCLUDE_PRIVATE_PROTOTYPES_VENDOR_TCG_TEST_FP_H_ 5 | # define _TPM_INCLUDE_PRIVATE_PROTOTYPES_VENDOR_TCG_TEST_FP_H_ 6 | 7 | // Input structure definition 8 | typedef struct 9 | { 10 | TPM2B_DATA inputData; 11 | } Vendor_TCG_Test_In; 12 | 13 | // Output structure definition 14 | typedef struct 15 | { 16 | TPM2B_DATA outputData; 17 | } Vendor_TCG_Test_Out; 18 | 19 | // Response code modifiers 20 | # define RC_Vendor_TCG_Test_inputData (TPM_RC_P + TPM_RC_1) 21 | 22 | // Function prototype 23 | TPM_RC 24 | TPM2_Vendor_TCG_Test(Vendor_TCG_Test_In* in, Vendor_TCG_Test_Out* out); 25 | 26 | # endif // _TPM_INCLUDE_PRIVATE_PROTOTYPES_VENDOR_TCG_TEST_FP_H_ 27 | #endif // CC_Vendor_TCG_Test 28 | -------------------------------------------------------------------------------- /libtcgtpm/deps/TpmConfiguration/TpmConfiguration/VendorCommands/CommandAttributeData_s_commandAttributes.inl: -------------------------------------------------------------------------------- 1 | // This file contains an inlined portion of the s_commandAttributes array 2 | // definition for vendor commands. 3 | // 4 | // IMPORTANT: This file is included in the middle of an array initializer 5 | // therefore it must not contain anything other than comments and exactly one 6 | // COMMAND_ATTRIBUTES entry per vendor command. See the private Tpm header 7 | // CommandAttributeData.h for more info. (This is why the file has the .INL 8 | // extension, it's not a normal header. 9 | // 10 | #ifndef _COMMAND_CODE_ATTRIBUTES_ 11 | # error This file should be included only within CommandAttributeData.h 12 | #endif 13 | #if (PAD_LIST || CC_Vendor_TCG_Test) 14 | (COMMAND_ATTRIBUTES)(CC_Vendor_TCG_Test* // 0x0000 15 | (DECRYPT_2 + ENCRYPT_2)), 16 | #endif 17 | -------------------------------------------------------------------------------- /libtcgtpm/deps/TpmConfiguration/TpmConfiguration/VendorCommands/VendorCommandList.h: -------------------------------------------------------------------------------- 1 | // This file defines any Vendor command IDs, and must also define the 2 | // VENDOR_COMMAND_ARRAY_COUNT which is consumed by the CoreLibrary. 3 | // This file is included inside TpmProfile_CommandList.h and therefore 4 | // has access to CC_YES and CC_NO for turning commands on and off. 5 | 6 | #ifndef _TPM_PROFILE_COMMAND_LIST_H_ 7 | # error This file should be included only within TpmProfile_CommandList.h 8 | #endif 9 | 10 | #define CC_Vendor_TCG_Test CC_NO 11 | 12 | #define VENDOR_COMMAND_ARRAY_COUNT (CC_Vendor_TCG_Test) 13 | 14 | // actually define vendor command IDs here 15 | #if CC_Vendor_TCG_Test == YES 16 | # define TPM_CC_Vendor_TCG_Test (TPM_CC)(CC_VEND | 0x0000) 17 | #else 18 | // nothing 19 | #endif 20 | // and command attributes must be defined in TpmProfile_CommandList_AttributeData.inl -------------------------------------------------------------------------------- /configs/test/qemu-test-target.json: -------------------------------------------------------------------------------- 1 | { 2 | "igvm": { 3 | "qemu": { 4 | "output": "coconut-test-qemu.igvm", 5 | "platforms": [ 6 | "snp", 7 | "tdp", 8 | "native" 9 | ], 10 | "measure": "print" 11 | } 12 | }, 13 | "kernel": { 14 | "svsm": { 15 | "type": "make", 16 | "output_file": "bin/test-kernel.elf" 17 | }, 18 | "stage2": { 19 | "manifest": "kernel/Cargo.toml", 20 | "binary": true, 21 | "objcopy": "binary" 22 | }, 23 | "tdx-stage1": { 24 | "type": "make", 25 | "output_file": "bin/stage1-trampoline", 26 | "objcopy": "binary" 27 | } 28 | }, 29 | "firmware": {}, 30 | "fs": { 31 | "modules": {} 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/string/memchr.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define SS (sizeof(size_t)) 8 | #define ALIGN (sizeof(size_t)-1) 9 | #define ONES ((size_t)-1/UCHAR_MAX) 10 | #define HIGHS (ONES * (UCHAR_MAX/2+1)) 11 | #define HASZERO(x) (((x)-ONES) & ~(x) & HIGHS) 12 | 13 | void *memchr(const void *src, int c, size_t n) 14 | { 15 | const unsigned char *s = src; 16 | c = (unsigned char)c; 17 | #ifdef __GNUC__ 18 | for (; ((uintptr_t)s & ALIGN) && n && *s != c; s++, n--); 19 | if (n && *s != c) { 20 | typedef size_t __attribute__((__may_alias__)) word; 21 | const word *w; 22 | size_t k = ONES * c; 23 | for (w = (const void *)s; n>=SS && !HASZERO(*w^k); w++, n-=SS); 24 | s = (const void *)w; 25 | } 26 | #endif 27 | for (; n && *s != c; s++, n--); 28 | return n ? (void *)s : 0; 29 | } 30 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/string/stpcpy.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define ALIGN (sizeof(size_t)) 8 | #define ONES ((size_t)-1/UCHAR_MAX) 9 | #define HIGHS (ONES * (UCHAR_MAX/2+1)) 10 | #define HASZERO(x) (((x)-ONES) & ~(x) & HIGHS) 11 | 12 | char *__stpcpy(char *restrict d, const char *restrict s) 13 | { 14 | #ifdef __GNUC__ 15 | typedef size_t __attribute__((__may_alias__)) word; 16 | word *wd; 17 | const word *ws; 18 | if ((uintptr_t)s % ALIGN == (uintptr_t)d % ALIGN) { 19 | for (; (uintptr_t)s % ALIGN; s++, d++) 20 | if (!(*d=*s)) return d; 21 | wd=(void *)d; ws=(const void *)s; 22 | for (; !HASZERO(*ws); *wd++ = *ws++); 23 | d=(void *)wd; s=(const void *)ws; 24 | } 25 | #endif 26 | for (; (*d=*s); s++, d++); 27 | 28 | return d; 29 | } 30 | 31 | weak_alias(__stpcpy, stpcpy); 32 | -------------------------------------------------------------------------------- /verification/verify_proof/src/lib.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Ziqiao Zhou 6 | 7 | #![no_std] 8 | #![allow(unused_braces)] 9 | #![allow(unexpected_cfgs)] 10 | #![allow(missing_debug_implementations)] 11 | use verus_builtin_macros::*; 12 | 13 | pub mod bits; 14 | #[cfg(verus_keep_ghost)] 15 | pub mod frac_perm; 16 | #[cfg(verus_keep_ghost)] 17 | pub mod frac_ptr; 18 | #[cfg(verus_keep_ghost)] 19 | pub mod nonlinear; 20 | #[cfg(verus_keep_ghost)] 21 | pub mod set; 22 | #[cfg(verus_keep_ghost)] 23 | pub mod sum; 24 | 25 | verus! { 26 | 27 | global size_of usize == 8; 28 | 29 | #[cfg_attr(verus_keep_ghost, verifier::broadcast_use_by_default_when_this_crate_is_imported)] 30 | pub broadcast group group_axioms { 31 | set::lemma_set_usize_finite, 32 | } 33 | 34 | } // verus! 35 | -------------------------------------------------------------------------------- /scripts/test_sign_qemu_igvm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # SPDX-License-Identifier: MIT OR Apache-2.0 3 | # 4 | # Copyright (c) 2024 SUSE LLC 5 | # 6 | # Author: Roy Hopkins 7 | # 8 | # Sign the QEMU IGVM file with test keys, generating 9 | # the test keys if they do not exist. 10 | set -e 11 | SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) 12 | SVSM_DIR=$SCRIPT_DIR/.. 13 | 14 | # Generate the test keys if they do not already exist 15 | if [ ! -d $SVSM_DIR/testkeys ] || [ ! -f $SVSM_DIR/testkeys/id_key.pem ]; then 16 | echo "Generating test keys" 17 | $SCRIPT_DIR/gen_igvm_signing_keys.sh 18 | fi 19 | 20 | echo "Signing file: $SVSM_DIR/bin/coconut-qemu.igvm" 21 | $SVSM_DIR/bin/igvmmeasure $SVSM_DIR/bin/coconut-qemu.igvm sign --output bin/coconut-qemu-signed.igvm --id-key $SVSM_DIR/testkeys/id_key.pem --author-key $SVSM_DIR/testkeys/author_key.pem 22 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/string/strchrnul.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define ALIGN (sizeof(size_t)) 8 | #define ONES ((size_t)-1/UCHAR_MAX) 9 | #define HIGHS (ONES * (UCHAR_MAX/2+1)) 10 | #define HASZERO(x) (((x)-ONES) & ~(x) & HIGHS) 11 | 12 | char *__strchrnul(const char *s, int c) 13 | { 14 | c = (unsigned char)c; 15 | if (!c) return (char *)s + strlen(s); 16 | 17 | #ifdef __GNUC__ 18 | typedef size_t __attribute__((__may_alias__)) word; 19 | const word *w; 20 | for (; (uintptr_t)s % ALIGN; s++) 21 | if (!*s || *(unsigned char *)s == c) return (char *)s; 22 | size_t k = ONES * c; 23 | for (w = (void *)s; !HASZERO(*w) && !HASZERO(*w^k); w++); 24 | s = (void *)w; 25 | #endif 26 | for (; *s && *(unsigned char *)s != c; s++); 27 | return (char *)s; 28 | } 29 | 30 | weak_alias(__strchrnul, strchrnul); 31 | -------------------------------------------------------------------------------- /user/lib/src/lib.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // 3 | // Copyright (c) 2024 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | 7 | #![cfg_attr(all(not(test), target_os = "none"), no_std)] 8 | 9 | pub mod console; 10 | pub mod locking; 11 | 12 | pub use console::*; 13 | pub use locking::*; 14 | pub use syscall::*; 15 | 16 | #[macro_export] 17 | macro_rules! declare_main { 18 | ($path:path) => { 19 | const _: () = { 20 | #[export_name = "_start"] 21 | pub extern "C" fn launch_module() -> ! { 22 | let main_fn: fn() -> u32 = $path; 23 | let ret = main_fn(); 24 | exit(ret); 25 | } 26 | }; 27 | }; 28 | } 29 | 30 | #[cfg(all(not(test), target_os = "none"))] 31 | #[panic_handler] 32 | fn panic(info: &core::panic::PanicInfo<'_>) -> ! { 33 | println!("Panic: {}", info); 34 | exit(!0); 35 | } 36 | -------------------------------------------------------------------------------- /.github/workflows/manual-verify.yml: -------------------------------------------------------------------------------- 1 | name: Verification 2 | 3 | # Only run this workflow when manually triggered 4 | on: 5 | workflow_dispatch: 6 | 7 | env: 8 | CARGO_TERM_COLOR: always 9 | 10 | jobs: 11 | check: 12 | name: Verification Check 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v3 17 | with: 18 | submodules: recursive 19 | 20 | - name: Install verus toolchains 21 | run: ./scripts/vinstall.sh --prebuilt-verusfmt 22 | 23 | - name: Format spec/proof code 24 | run: | 25 | verusfmt --check `find ./ -name *.verus.rs` --verus-only 26 | 27 | - name: Verify svsm with verus 28 | run: cargo verify 29 | working-directory: kernel 30 | 31 | - name: Verify extra proof libs with verus 32 | run: cargo verify 33 | working-directory: verification/verify_proof 34 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/time/time.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | // Calls the rdtsc instruction to read the current value of the processor's 8 | // time-stamp counter (a 64-bit MSR) 9 | clock_t clock(void) { 10 | return rdtsc(); 11 | } 12 | 13 | uint64_t secs; 14 | 15 | int clock_gettime(clockid_t clk_id, struct timespec *tp) { 16 | (void) clk_id; 17 | if (tp) { 18 | tp->tv_nsec = rdtsc(); 19 | tp->tv_sec = secs++; 20 | } 21 | return 0; 22 | } 23 | 24 | // time() returns the time as the number of seconds since the Epoch 25 | time_t time(time_t *tloc) { 26 | (void)tloc; 27 | time_t t = rdtsc(); 28 | return t; 29 | } 30 | 31 | int gettimeofday(struct timeval *restrict tv, void *restrict tz) 32 | { 33 | if (!tv) return 0; 34 | tv->tv_sec = clock(); 35 | tv->tv_usec = 0; 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /stage1/stage1.lds: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT OR Apache-2.0 */ 2 | 3 | /* 4 | * Copyright (c) 2022-2023 SUSE LLC 5 | * 6 | * Author: Joerg Roedel 7 | */ 8 | 9 | OUTPUT_ARCH(i386:x86-64) 10 | 11 | SECTIONS 12 | { 13 | .stext = ALIGN(.sdata - SIZEOF(.text) - 4095, 4096); 14 | . = .stext; 15 | .text : { *(.startup.*) } 16 | 17 | /* 18 | * Subtract an extra byte so that edata and the .init function 19 | * symbols don't alias, which would be confusing when 20 | * examining the resulting binary. 21 | */ 22 | .sdata = ALIGN(.sinit - SIZEOF(.data) - 4095 - 1, 4096); 23 | . = .sdata; 24 | .data : { *(.data) } 25 | edata = .; 26 | 27 | . = 0xfffffe00; 28 | .sinit = .; 29 | .init : { 30 | *(.init); 31 | . = 512 - 32 - 256; 32 | *(.sevmeta); 33 | . = 512 - 16; 34 | *(.resetvector); 35 | . = 512; 36 | } 37 | einit = .; 38 | 39 | /DISCARD/ : {*(.*)} 40 | } 41 | 42 | ENTRY(startup_32) 43 | -------------------------------------------------------------------------------- /configs/test/hyperv-test-target.json: -------------------------------------------------------------------------------- 1 | { 2 | "igvm": { 3 | "hyper-v": { 4 | "output": "coconut-test-hyperv.igvm", 5 | "platforms": [ 6 | "snp", 7 | "tdp", 8 | "vsm" 9 | ], 10 | "policy": "0x30000", 11 | "comport": "3", 12 | "measure": "print" 13 | } 14 | }, 15 | "kernel": { 16 | "svsm": { 17 | "type": "make", 18 | "output_file": "bin/test-kernel.elf" 19 | }, 20 | "stage2": { 21 | "manifest": "kernel/Cargo.toml", 22 | "binary": true, 23 | "objcopy": "binary" 24 | }, 25 | "tdx-stage1": { 26 | "type": "make", 27 | "output_file": "bin/stage1-trampoline", 28 | "objcopy": "binary" 29 | } 30 | }, 31 | "firmware": {}, 32 | "fs": { 33 | "modules": {} 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /kernel/src/svsm.lds: -------------------------------------------------------------------------------- 1 | OUTPUT_ARCH(i386:x86-64) 2 | 3 | SECTIONS 4 | { 5 | . = 0xffffff8000000000; 6 | .text : { 7 | *(.startup.*) 8 | *(.text) 9 | *(.text.*) 10 | . = ALIGN(16); 11 | entry_code_start = .; 12 | *(.entry.text) 13 | entry_code_end = .; 14 | . = ALIGN(16); 15 | early_exception_table_start = .; 16 | KEEP(*(__early_exception_table)) 17 | early_exception_table_end = .; 18 | . = ALIGN(16); 19 | exception_table_start = .; 20 | KEEP(*(__exception_table)) 21 | exception_table_end = .; 22 | } 23 | . = ALIGN(4096); 24 | .rodata : { *(.rodata) *(.rodata.*) } 25 | . = ALIGN(4096); 26 | .data : { *(.data) *(.data.*) } 27 | . = ALIGN(4096); 28 | .ro_after_init : { 29 | ro_after_init_start = .; 30 | *(.ro_after_init) *(.ro_after_init.*) 31 | . = ALIGN(4096); 32 | ro_after_init_end = .; 33 | } 34 | . = ALIGN(4096); 35 | .bss : { 36 | *(.bss) *(.bss.*) 37 | . = ALIGN(4096); 38 | } 39 | . = ALIGN(4096); 40 | } 41 | 42 | ENTRY(startup_64) 43 | -------------------------------------------------------------------------------- /configs/test/vanadium-test-target.json: -------------------------------------------------------------------------------- 1 | { 2 | "igvm": { 3 | "vanadium": { 4 | "output": "coconut-test-vanadium.igvm", 5 | "platforms": [ 6 | "snp", 7 | "tdp" 8 | ], 9 | "policy": "0x30000", 10 | "measure": "print", 11 | "check-kvm": true, 12 | "measure-native-zeroes": true 13 | } 14 | }, 15 | "kernel": { 16 | "svsm": { 17 | "type": "make", 18 | "output_file": "bin/test-kernel.elf" 19 | }, 20 | "stage2": { 21 | "manifest": "kernel/Cargo.toml", 22 | "binary": true, 23 | "objcopy": "binary" 24 | }, 25 | "tdx-stage1": { 26 | "type": "make", 27 | "output_file": "bin/stage1-trampoline", 28 | "objcopy": "binary" 29 | } 30 | }, 31 | "firmware": {}, 32 | "fs": { 33 | "modules": {} 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /virtio-drivers/src/device/common.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | //! Common part shared across all the devices. 4 | 5 | use bitflags::bitflags; 6 | 7 | bitflags! { 8 | #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] 9 | pub(crate) struct Feature: u64 { 10 | // device independent 11 | const NOTIFY_ON_EMPTY = 1 << 24; // legacy 12 | const ANY_LAYOUT = 1 << 27; // legacy 13 | const RING_INDIRECT_DESC = 1 << 28; 14 | const RING_EVENT_IDX = 1 << 29; 15 | const UNUSED = 1 << 30; // legacy 16 | const VERSION_1 = 1 << 32; // detect legacy 17 | 18 | // since virtio v1.1 19 | const ACCESS_PLATFORM = 1 << 33; 20 | const RING_PACKED = 1 << 34; 21 | const IN_ORDER = 1 << 35; 22 | const ORDER_PLATFORM = 1 << 36; 23 | const SR_IOV = 1 << 37; 24 | const NOTIFICATION_DATA = 1 << 38; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /kernel/src/cpu/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2022-2023 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | 7 | pub mod apic; 8 | pub mod control_regs; 9 | pub mod cpuid; 10 | pub mod cpuset; 11 | pub mod efer; 12 | pub mod extable; 13 | pub mod features; 14 | pub mod gdt; 15 | pub mod idt; 16 | pub mod ipi; 17 | pub mod irq_state; 18 | pub mod isst; 19 | pub mod mem; 20 | pub mod msr; 21 | pub mod percpu; 22 | pub mod registers; 23 | pub mod shadow_stack; 24 | pub mod smp; 25 | pub mod sse; 26 | pub mod tlb; 27 | pub mod tss; 28 | pub mod vc; 29 | pub mod vmsa; 30 | pub mod x86; 31 | 32 | pub use apic::LocalApic; 33 | pub use idt::common::X86ExceptionContext; 34 | pub use irq_state::{irqs_disabled, irqs_enabled, IrqGuard, IrqState, TprGuard}; 35 | pub use percpu::{irq_nesting_count, irqs_disable, irqs_enable, lower_tpr, raise_tpr}; 36 | pub use registers::{X86GeneralRegs, X86InterruptFrame, X86SegmentRegs}; 37 | pub use shadow_stack::ShadowStackInit; 38 | pub use tlb::*; 39 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/string/stpncpy.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define ALIGN (sizeof(size_t)-1) 8 | #define ONES ((size_t)-1/UCHAR_MAX) 9 | #define HIGHS (ONES * (UCHAR_MAX/2+1)) 10 | #define HASZERO(x) (((x)-ONES) & ~(x) & HIGHS) 11 | 12 | char *__stpncpy(char *restrict d, const char *restrict s, size_t n) 13 | { 14 | #ifdef __GNUC__ 15 | typedef size_t __attribute__((__may_alias__)) word; 16 | word *wd; 17 | const word *ws; 18 | if (((uintptr_t)s & ALIGN) == ((uintptr_t)d & ALIGN)) { 19 | for (; ((uintptr_t)s & ALIGN) && n && (*d=*s); n--, s++, d++); 20 | if (!n || !*s) goto tail; 21 | wd=(void *)d; ws=(const void *)s; 22 | for (; n>=sizeof(size_t) && !HASZERO(*ws); 23 | n-=sizeof(size_t), ws++, wd++) *wd = *ws; 24 | d=(void *)wd; s=(const void *)ws; 25 | } 26 | #endif 27 | for (; n && (*d=*s); n--, s++, d++); 28 | tail: 29 | memset(d, 0, n); 30 | return d; 31 | } 32 | 33 | weak_alias(__stpncpy, stpncpy); 34 | 35 | -------------------------------------------------------------------------------- /fuzz/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "svsm-fuzz" 3 | version = "0.0.0" 4 | publish = false 5 | edition = "2021" 6 | 7 | [package.metadata] 8 | cargo-fuzz = true 9 | 10 | [dependencies] 11 | svsm = { workspace = true, features = [] } 12 | 13 | arbitrary = { workspace = true, features = ["derive"] } 14 | libfuzzer-sys.workspace = true 15 | 16 | [[bin]] 17 | name = "acpi" 18 | path = "fuzz_targets/acpi.rs" 19 | test = false 20 | doc = false 21 | 22 | [[bin]] 23 | name = "fs" 24 | path = "fuzz_targets/fs.rs" 25 | test = false 26 | doc = false 27 | 28 | [[bin]] 29 | name = "page_alloc" 30 | path = "fuzz_targets/page_alloc.rs" 31 | test = false 32 | doc = false 33 | 34 | [[bin]] 35 | name = "alloc" 36 | path = "fuzz_targets/alloc.rs" 37 | test = false 38 | doc = false 39 | 40 | [[bin]] 41 | name = "insn" 42 | path = "fuzz_targets/insn.rs" 43 | test = false 44 | doc = false 45 | 46 | [[bin]] 47 | name = "bitmap_allocator" 48 | path = "fuzz_targets/bitmap_allocator.rs" 49 | test = false 50 | doc = false 51 | 52 | [lints] 53 | workspace = true 54 | -------------------------------------------------------------------------------- /verification/verify_external/src/lib.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Ziqiao Zhou 6 | // 7 | // Goal: This crate provides specifications for external, unverified libraries. 8 | // These specifications are placeholders, and the number of verification targets 9 | // should always remain zero since these libraries are not formally verified. 10 | // Why: While vstd defines some specifications for std/core, these are 11 | // incomplete. SVSM may also rely on other unverified crates, which necessitates 12 | // these specifications. 13 | 14 | #![no_std] 15 | #![allow(unused_braces)] 16 | #![allow(unexpected_cfgs)] 17 | 18 | // Add spec for convert traits 19 | pub mod convert; 20 | 21 | pub mod hw_spec; 22 | 23 | pub mod ptr; 24 | 25 | use verus_builtin_macros::*; 26 | 27 | verus! { 28 | #[cfg_attr(verus_keep_ghost, verifier::broadcast_use_by_default_when_this_crate_is_imported)] 29 | pub broadcast group external_axiom { 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Documentation/mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: COCONUT-SVSM 2 | theme: 3 | name: material 4 | features: 5 | - content.code.copy 6 | 7 | markdown_extensions: 8 | - pymdownx.highlight: 9 | anchor_linenums: true 10 | line_spans: __span 11 | pygments_lang_class: true 12 | - pymdownx.inlinehilite 13 | - pymdownx.snippets 14 | - pymdownx.superfences 15 | - pymdownx.tasklist 16 | 17 | nav: 18 | - Documentation Home: 'index.md' 19 | - Building and launching: 20 | - 'installation/INSTALL.md' 21 | - Build Recipe Documentation: 22 | - 'installation/BUILD_RECIPES.md' 23 | 24 | - Developer Information: 25 | - 'developer/DOC-GUIDELINES.md' 26 | - Development Plan Overview: 'developer/DEVELOPMENT-PLAN.md' 27 | - Rustdoc Guidelines: 'developer/RUSTDOC-GUIDELINES.md' 28 | - Fuzzing: 'developer/FUZZING.md' 29 | - Contributing to COCONUT-SVSM: 'developer/CONTRIBUTING.md' 30 | - Formal Verification: 'developer/VERIFICATION.md' 31 | - Attestation: 'developer/ATTESTATION.md' 32 | - 'COCONUT-SVSM Rustdoc': 'rustdoc/svsm' 33 | -------------------------------------------------------------------------------- /configs/hyperv-target.json: -------------------------------------------------------------------------------- 1 | { 2 | "igvm": { 3 | "hyper-v": { 4 | "output": "coconut-hyperv.igvm", 5 | "platforms": [ 6 | "snp", 7 | "tdp", 8 | "vsm" 9 | ], 10 | "policy": "0x30000", 11 | "comport": "3", 12 | "measure": "print" 13 | } 14 | }, 15 | "kernel": { 16 | "svsm": { 17 | "features": "vtpm", 18 | "binary": false 19 | }, 20 | "stage2": { 21 | "manifest": "kernel/Cargo.toml", 22 | "binary": true, 23 | "objcopy": "binary" 24 | }, 25 | "tdx-stage1": { 26 | "type": "make", 27 | "output_file": "bin/stage1-trampoline", 28 | "objcopy": "binary" 29 | } 30 | }, 31 | "firmware": { 32 | "env": "HV_FW_FILE" 33 | }, 34 | "fs": { 35 | "modules": { 36 | "userinit": { 37 | "path": "/init" 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /configs/qemu-target.json: -------------------------------------------------------------------------------- 1 | { 2 | "igvm": { 3 | "qemu": { 4 | "output": "coconut-qemu.igvm", 5 | "platforms": [ 6 | "snp", 7 | "tdp", 8 | "native" 9 | ], 10 | "policy": "0x30000", 11 | "measure": "print", 12 | "check-kvm": true 13 | } 14 | }, 15 | "kernel": { 16 | "svsm": { 17 | "features": "vtpm", 18 | "binary": false 19 | }, 20 | "stage2": { 21 | "manifest": "kernel/Cargo.toml", 22 | "binary": true, 23 | "objcopy": "binary" 24 | }, 25 | "tdx-stage1": { 26 | "type": "make", 27 | "output_file": "bin/stage1-trampoline", 28 | "objcopy": "binary" 29 | } 30 | }, 31 | "firmware": { 32 | "env": "FW_FILE" 33 | }, 34 | "fs": { 35 | "modules": { 36 | "userinit": { 37 | "path": "/init" 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /configs/vanadium-target.json: -------------------------------------------------------------------------------- 1 | { 2 | "igvm": { 3 | "vanadium": { 4 | "output": "coconut-vanadium.igvm", 5 | "platforms": [ 6 | "snp", 7 | "tdp" 8 | ], 9 | "policy": "0x30000", 10 | "measure": "print", 11 | "check-kvm": true, 12 | "measure-native-zeroes": true 13 | } 14 | }, 15 | "kernel": { 16 | "svsm": { 17 | "features": "vtpm", 18 | "binary": false 19 | }, 20 | "stage2": { 21 | "manifest": "kernel/Cargo.toml", 22 | "binary": true, 23 | "objcopy": "binary" 24 | }, 25 | "tdx-stage1": { 26 | "type": "make", 27 | "output_file": "bin/stage1-trampoline", 28 | "objcopy": "binary" 29 | } 30 | }, 31 | "firmware": { 32 | "env": "FW_FILE" 33 | }, 34 | "fs": { 35 | "modules": { 36 | "userinit": { 37 | "path": "/init" 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /scripts/show-stack-sizes.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # SPDX-License-Identifier: MIT OR Apache-2.0 3 | # 4 | # Author: Tom Dohrmann 5 | # A script to find functions with excessive stack sizes. 6 | # Requires yq-go and llvm-readelf (bundled with llvm) to be installed. 7 | 8 | # Forcefully enable a nightly toolchain. 9 | export RUSTUP_TOOLCHAIN=nightly 10 | 11 | # Append -Z emit-stack-sizes to the set of rustflags. The RUSTFLAGS environment variable overrides the flags in the config. 12 | RUSTFLAGS=$(yq '.target.x86_64-unknown-none.rustflags | join(" ")' .cargo/config.toml) 13 | export RUSTFLAGS="$RUSTFLAGS -Z emit-stack-sizes" 14 | 15 | # Build the SVSM kernel. 16 | make bin/svsm-kernel.elf 17 | 18 | # Determine the path to the built binary. 19 | if [[ -z "${RELEASE}" ]]; then 20 | TARGET_PATH=debug 21 | else 22 | TARGET_PATH=release 23 | fi 24 | SVSM_PATH=target/x86_64-unknown-none/${TARGET_PATH}/svsm 25 | 26 | # Print stack frame sizes for all functions, sorted from small to large. 27 | llvm-readelf -C --stack-sizes target/x86_64-unknown-none/${TARGET_PATH}/svsm | sort -bn 28 | -------------------------------------------------------------------------------- /kernel/src/cpu/x86/smap.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // 3 | // Copyright (c) 2024 SUSE LLC 4 | // 5 | // Author: Thomas Leroy 6 | 7 | use core::arch::asm; 8 | 9 | /// Clears RFLAGS.AC to enable SMAP. 10 | /// This is currently only used when SMAP is supported and enabled. 11 | /// SMAP protection is effective only if CR4.SMAP is set and if RFLAGS.AC = 0. 12 | #[inline(always)] 13 | pub fn clac() { 14 | if !cfg!(feature = "nosmap") { 15 | // SAFETY: `clac` instruction doesn't break memory safety. 16 | unsafe { asm!("clac", options(att_syntax, nomem, nostack, preserves_flags)) } 17 | } 18 | } 19 | 20 | /// Sets RFLAGS.AC to disable SMAP. 21 | /// This is currently only used when SMAP is supported and enabled. 22 | /// SMAP protection is effective only if CR4.SMAP is set and if RFLAGS.AC = 0. 23 | #[inline(always)] 24 | pub fn stac() { 25 | if !cfg!(feature = "nosmap") { 26 | // SAFETY: `stac` instruction doesn't break memory safety. 27 | unsafe { asm!("stac", options(att_syntax, nomem, nostack, preserves_flags)) } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /kernel/src/mm/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2022-2023 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | 7 | pub mod address_space; 8 | pub mod alloc; 9 | pub mod global_memory; 10 | pub mod guestmem; 11 | pub mod mappings; 12 | pub mod memory; 13 | pub mod page_visibility; 14 | mod pagebox; 15 | pub mod pagetable; 16 | pub mod ptguards; 17 | pub mod ro_after_init; 18 | pub mod validate; 19 | pub mod virtualrange; 20 | pub mod vm; 21 | 22 | pub use address_space::*; 23 | pub use guestmem::{copy_from_user, copy_to_user, GuestPtr}; 24 | pub use memory::{valid_phys_address, writable_phys_addr}; 25 | pub use pagebox::*; 26 | pub use ptguards::*; 27 | 28 | pub use pagetable::PageTablePart; 29 | 30 | pub use alloc::{allocate_file_page, PageRef}; 31 | 32 | pub use global_memory::{ 33 | map_global_range, map_global_range_2m_private, map_global_range_2m_shared, 34 | map_global_range_4k_private, map_global_range_4k_shared, GlobalRangeGuard, 35 | }; 36 | pub use mappings::{mmap_kernel, mmap_user, munmap_kernel, munmap_user, VMMappingGuard}; 37 | -------------------------------------------------------------------------------- /scripts/test-qemu-nocc-svsm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # SPDX-License-Identifier: MIT 3 | # 4 | # Copyright (c) 2025 Red Hat, Inc. 5 | # 6 | # Author: Oliver Steffen 7 | set -u 8 | 9 | SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) 10 | 11 | # When we see this string on the serial output, consider 12 | # SVSM booted and the test passed. 13 | SUCCESS="All tests passed" 14 | 15 | # Fail the test after this timeout 16 | TIMEOUT=180s 17 | 18 | # Clone STDOUT for live log reporting 19 | exec 3>&1 20 | 21 | echo "================================================================================" 22 | timeout $TIMEOUT \ 23 | grep -q -m 1 "$SUCCESS" \ 24 | <("$SCRIPT_DIR/test-in-svsm.sh" --nocc &1 | tee /proc/self/fd/3) 25 | RES=$? 26 | echo "================================================================================" 27 | 28 | case $RES in 29 | 0) 30 | echo "Test Pass!" 31 | exit 0 32 | ;; 33 | 124) 34 | echo "Test failed: timeout" 35 | exit 1 36 | ;; 37 | *) 38 | echo "Test failed: Unknown error" 39 | exit 1 40 | ;; 41 | esac 42 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/string/memmove.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | #include 5 | 6 | #ifdef __GNUC__ 7 | typedef __attribute__((__may_alias__)) size_t WT; 8 | #define WS (sizeof(WT)) 9 | #endif 10 | 11 | void *memmove(void *dest, const void *src, size_t n) 12 | { 13 | char *d = dest; 14 | const char *s = src; 15 | 16 | if (d==s) return d; 17 | if ((uintptr_t)s-(uintptr_t)d-n <= -2*n) return memcpy(d, s, n); 18 | 19 | if (d=WS; n-=WS, d+=WS, s+=WS) *(WT *)d = *(WT *)s; 27 | } 28 | #endif 29 | for (; n; n--) *d++ = *s++; 30 | } else { 31 | #ifdef __GNUC__ 32 | if ((uintptr_t)s % WS == (uintptr_t)d % WS) { 33 | while ((uintptr_t)(d+n) % WS) { 34 | if (!n--) return dest; 35 | d[n] = s[n]; 36 | } 37 | while (n>=WS) n-=WS, *(WT *)(d+n) = *(WT *)(s+n); 38 | } 39 | #endif 40 | while (n) n--, d[n] = s[n]; 41 | } 42 | 43 | return dest; 44 | } 45 | -------------------------------------------------------------------------------- /verification/verify_external/src/convert.verus.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Ziqiao Zhou 6 | use vstd::prelude::*; 7 | use vstd::std_specs::convert::{FromSpec, IntoSpec}; 8 | verus! { 9 | 10 | #[verifier(inline)] 11 | pub open spec fn exists_into(v: T, r: spec_fn(v: U) -> bool) -> bool where T: Into { 12 | exists|u: U| #[trigger] T::into.ensures((v,), u) && r(u) 13 | } 14 | 15 | #[verifier(inline)] 16 | pub open spec fn forall_into(v: T, r: spec_fn(v: U) -> bool) -> bool where T: Into { 17 | forall|u: U| #[trigger] T::into.ensures((v,), u) ==> r(u) 18 | } 19 | 20 | #[verifier(inline)] 21 | pub open spec fn exists_from(v: T, r: spec_fn(v: U) -> bool) -> bool where U: From { 22 | exists|u: U| #[trigger] U::from.ensures((v,), u) && r(u) 23 | } 24 | 25 | #[verifier(inline)] 26 | pub open spec fn forall_from(v: T, r: spec_fn(v: U) -> bool) -> bool where U: From { 27 | forall|u: U| #[trigger] U::from.ensures((v,), u) ==> r(u) 28 | } 29 | 30 | } // verus! 31 | -------------------------------------------------------------------------------- /cpuarch/src/snp_cpuid.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2022-2023 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | 7 | const SNP_CPUID_MAX_COUNT: usize = 64; 8 | 9 | #[derive(Copy, Clone, Default, Debug)] 10 | #[repr(C, packed)] 11 | pub struct SnpCpuidFn { 12 | pub eax_in: u32, 13 | pub ecx_in: u32, 14 | pub xcr0_in: u64, 15 | pub xss_in: u64, 16 | pub eax_out: u32, 17 | pub ebx_out: u32, 18 | pub ecx_out: u32, 19 | pub edx_out: u32, 20 | pub reserved_1: u64, 21 | } 22 | 23 | #[derive(Copy, Clone, Debug)] 24 | #[repr(C, packed)] 25 | pub struct SnpCpuidTable { 26 | pub count: u32, 27 | pub reserved_1: u32, 28 | pub reserved_2: u64, 29 | pub func: [SnpCpuidFn; SNP_CPUID_MAX_COUNT], 30 | } 31 | 32 | impl Default for SnpCpuidTable { 33 | fn default() -> Self { 34 | SnpCpuidTable { 35 | count: Default::default(), 36 | reserved_1: Default::default(), 37 | reserved_2: Default::default(), 38 | func: [SnpCpuidFn::default(); SNP_CPUID_MAX_COUNT], 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /user/init/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use userlib::*; 5 | 6 | use core::ptr::{addr_of, addr_of_mut}; 7 | 8 | static mut SOME_BSS_DATA: [u64; 128] = [0; 128]; 9 | static mut SOME_DATA: [u64; 128] = [0x01; 128]; 10 | static SOME_RO_DATA: [u64; 128] = [0xee; 128]; 11 | 12 | fn check(arr: &[u64; 128], val: u64) { 13 | for v in arr.iter() { 14 | if *v != val { 15 | panic!("Unexpected array value"); 16 | } 17 | } 18 | } 19 | 20 | fn write(arr: &mut [u64; 128], val: u64) { 21 | for v in arr.iter_mut() { 22 | *v = val; 23 | } 24 | } 25 | 26 | declare_main!(main); 27 | 28 | fn main() -> u32 { 29 | println!("COCONUT-SVSM init process starting"); 30 | 31 | // SAFETY: Single-threaded process, so no data races. Safe to access global 32 | // mutable data. 33 | unsafe { 34 | write(&mut *addr_of_mut!(SOME_DATA), 0xcc); 35 | write(&mut *addr_of_mut!(SOME_BSS_DATA), 0xaa); 36 | check(&*addr_of!(SOME_DATA), 0xccu64); 37 | check(&*addr_of!(SOME_RO_DATA), 0xeeu64); 38 | check(&*addr_of!(SOME_BSS_DATA), 0xaa); 39 | } 40 | 0 41 | } 42 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (C) 2022-2023 SUSE LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /kernel/src/utils/vec.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2025 Red Hat, Inc 4 | // 5 | // Author: Tyler Fanelli 6 | 7 | extern crate alloc; 8 | 9 | use alloc::{collections::TryReserveError, vec::Vec}; 10 | 11 | /// Allocate a generic Vec of a certain size and copy data from a slice into it. Alternative to the 12 | /// `.to_vec` method for slices that panics if enough size to allocate the corresponding Vec isn't 13 | /// available. 14 | pub fn try_to_vec(input: &[T]) -> Result, TryReserveError> { 15 | let mut vec = Vec::new(); 16 | let len = input.len(); 17 | 18 | vec.try_reserve_exact(len)?; 19 | vec.extend_from_slice(input); 20 | 21 | Ok(vec) 22 | } 23 | 24 | /// Allocate a Vec of a certain size. Alternative to the `vec!` macro that panics if enough bytes 25 | /// to allocate the corresponding Vec isn't available. 26 | pub fn vec_sized(size: usize) -> Result, TryReserveError> { 27 | let mut vec: Vec = Vec::new(); 28 | 29 | vec.try_reserve_exact(size)?; 30 | vec.resize(size, T::default()); 31 | 32 | Ok(vec) 33 | } 34 | -------------------------------------------------------------------------------- /virtio-drivers/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-2020 rCore Developers 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /kernel/src/cpu/features.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2022-2023 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | 7 | use crate::platform::SvsmPlatform; 8 | 9 | const X86_FEATURE_PGE: u32 = 13; 10 | const X86_FEATURE_SMEP: u32 = 7; 11 | const X86_FEATURE_SMAP: u32 = 20; 12 | const X86_FEATURE_UMIP: u32 = 2; 13 | 14 | pub fn cpu_has_pge(platform: &dyn SvsmPlatform) -> bool { 15 | platform 16 | .cpuid(0x0000_0001, 0) 17 | .map_or_else(|| false, |c| (c.edx >> X86_FEATURE_PGE) & 1 == 1) 18 | } 19 | 20 | pub fn cpu_has_smep(platform: &dyn SvsmPlatform) -> bool { 21 | platform 22 | .cpuid(0x0000_0007, 0) 23 | .map_or_else(|| false, |c| (c.ebx >> X86_FEATURE_SMEP & 1) == 1) 24 | } 25 | 26 | pub fn cpu_has_smap(platform: &dyn SvsmPlatform) -> bool { 27 | platform 28 | .cpuid(0x0000_0007, 0) 29 | .map_or_else(|| false, |c| (c.ebx >> X86_FEATURE_SMAP & 1) == 1) 30 | } 31 | 32 | pub fn cpu_has_umip(platform: &dyn SvsmPlatform) -> bool { 33 | platform 34 | .cpuid(0x0000_0007, 0) 35 | .map_or_else(|| false, |c| (c.ecx >> X86_FEATURE_UMIP & 1) == 1) 36 | } 37 | -------------------------------------------------------------------------------- /user/lib/module.lds: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | /* 4 | * Copyright (c) 2024 SUSE LLC 5 | * 6 | * Author: Joerg Roedel 7 | */ 8 | 9 | OUTPUT_ARCH(i386:x86-64) 10 | 11 | PHDRS 12 | { 13 | text PT_LOAD FLAGS(0x5); /* Read + Execute */ 14 | rodata PT_LOAD FLAGS(4); /* Read-only */ 15 | data PT_LOAD FLAGS(0x6); /* Read + Write */ 16 | bss PT_LOAD FLAGS(0x6); /* Read + Write */ 17 | } 18 | 19 | SECTIONS 20 | { 21 | . = 64k; 22 | _stext = .; 23 | .text : { 24 | *(.text) 25 | *(.text.*) 26 | . = ALIGN(16); 27 | } :text 28 | _etext = .; 29 | . = ALIGN(4096); 30 | .got : { 31 | *(.got) 32 | *(.got.*) 33 | } :data 34 | . = ALIGN(4096); 35 | _sdata = .; 36 | .data : { 37 | *(.data) 38 | *(.data.*) 39 | . = ALIGN(16); 40 | } :data 41 | _edata = .; 42 | . = ALIGN(4096); 43 | _srodata = .; 44 | .rodata : { 45 | *(.rodata) 46 | *(.rodata.*) 47 | . = ALIGN(16); 48 | } :rodata 49 | _erodata = .; 50 | . = ALIGN(4096); 51 | .bss : { 52 | _bss = .; 53 | *(.bss) *(.bss.[0-9a-zA-Z_]*) 54 | . = ALIGN(16); 55 | _ebss = .; 56 | } :bss 57 | . = ALIGN(4096); 58 | heap_start = .; 59 | } 60 | 61 | ENTRY(_start) 62 | -------------------------------------------------------------------------------- /user/lib/src/console.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // 3 | // Copyright (c) 2024 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | 7 | use crate::SpinLock; 8 | use core::fmt; 9 | use syscall::write_console; 10 | 11 | #[derive(Debug, Default)] 12 | struct ConsoleWriter {} 13 | 14 | impl ConsoleWriter { 15 | const fn new() -> Self { 16 | Self {} 17 | } 18 | } 19 | 20 | impl fmt::Write for ConsoleWriter { 21 | fn write_str(&mut self, s: &str) -> fmt::Result { 22 | // Ignore any errors from console writing. 23 | let _ = write_console(s.as_bytes()); 24 | Ok(()) 25 | } 26 | } 27 | 28 | static CONSOLE_WRITER: SpinLock = SpinLock::new(ConsoleWriter::new()); 29 | 30 | #[doc(hidden)] 31 | pub fn console_print(args: fmt::Arguments<'_>) { 32 | use core::fmt::Write; 33 | CONSOLE_WRITER.lock().write_fmt(args).unwrap() 34 | } 35 | 36 | #[macro_export] 37 | macro_rules! print { 38 | ($($arg:tt)*) => (console_print(format_args!($($arg)*))) 39 | } 40 | 41 | #[macro_export] 42 | macro_rules! println { 43 | () => (print!("\n")); 44 | ($($arg:tt)*) => (print!("{}\n", format_args!($($arg)*))); 45 | } 46 | -------------------------------------------------------------------------------- /bootlib/src/firmware.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Author: Carlos López 4 | 5 | use uuid::{uuid, Uuid}; 6 | 7 | pub const OVMF_RESET_VECTOR_GUID: Uuid = uuid!("813d7b2c-9558-4d88-8b31-1427a85abe69"); 8 | pub const OVMF_SEV_METADATA_GUID: Uuid = uuid!("dc886566-984a-4798-a75e-5585a7bf67cc"); 9 | pub const OVMF_TDX_METADATA_GUID: Uuid = uuid!("e47a6535-984a-4798-865e-4685a7bf8ec2"); 10 | pub const OVMF_IGVM_METADATA_GUID: Uuid = uuid!("784fa70e-3176-4677-8a20-04b68699e374"); 11 | pub const OVMF_TABLE_FOOTER_GUID: Uuid = uuid!("96b582de-1fb2-45f7-baea-a366c55a082d"); 12 | pub const SEV_INFO_BLOCK_GUID: Uuid = uuid!("00f771de-1a7e-4fcb-890e-68c77e2fb44e"); 13 | pub const SVSM_INFO_GUID: Uuid = uuid!("a789a612-0597-4c4b-a49f-cbb1fe9d1ddd"); 14 | 15 | pub const SEV_META_DESC_TYPE_MEM: u32 = 1; 16 | pub const SEV_META_DESC_TYPE_SECRETS: u32 = 2; 17 | pub const SEV_META_DESC_TYPE_CPUID: u32 = 3; 18 | pub const SEV_META_DESC_TYPE_CAA: u32 = 4; 19 | pub const SEV_META_DESC_TYPE_KERNEL_HASHES: u32 = 16; 20 | 21 | pub const IGVM_META_DESC_TYPE_PARAM_AREA: u32 = 0x100; 22 | pub const IGVM_META_DESC_TYPE_MEMORY_MAP: u32 = 0x101; 23 | pub const IGVM_META_DESC_TYPE_HOB_AREA: u32 = 0x200; 24 | -------------------------------------------------------------------------------- /elf/src/lib.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: (GPL-2.0-or-later OR MIT) 2 | // 3 | // Copyright (c) 2023 SUSE LLC 4 | // 5 | // Author: Nicolai Stange 6 | // 7 | // vim: ts=4 sw=4 et 8 | 9 | #![no_std] 10 | 11 | mod addr_range; 12 | mod dynamic; 13 | mod error; 14 | mod file; 15 | mod file_range; 16 | mod header; 17 | mod load_segments; 18 | mod program_header; 19 | mod relocation; 20 | mod section_header; 21 | mod syms; 22 | mod types; 23 | 24 | pub use addr_range::Elf64AddrRange; 25 | pub use dynamic::{Elf64Dynamic, Elf64DynamicRelocTable}; 26 | pub use error::ElfError; 27 | pub use file::Elf64File; 28 | pub use file_range::Elf64FileRange; 29 | use header::Elf64Hdr; 30 | pub use load_segments::{ 31 | Elf64ImageLoadSegment, Elf64ImageLoadSegmentIterator, Elf64ImageLoadVaddrAllocInfo, 32 | Elf64LoadSegments, 33 | }; 34 | pub use program_header::{Elf64Phdr, Elf64PhdrFlags}; 35 | pub use relocation::{ 36 | Elf64AppliedRelaIterator, Elf64Rela, Elf64Relas, Elf64RelocOp, Elf64RelocProcessor, 37 | Elf64X86RelocProcessor, 38 | }; 39 | pub use section_header::{Elf64Shdr, Elf64ShdrFlags, Elf64ShdrIterator}; 40 | pub use syms::{Elf64Strtab, Elf64Sym, Elf64Symtab}; 41 | pub use types::*; 42 | 43 | #[cfg(test)] 44 | mod tests; 45 | -------------------------------------------------------------------------------- /test/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! This crate contains a very stripped down copy of the `test` crate. 2 | //! `test` usually requires full `std` support, but we need to use it from a 3 | //! `no_std` target. 4 | //! The `test` crate is implicitly used by the `#[test]` attribute. 5 | #![no_std] 6 | 7 | #[derive(Clone, Copy)] 8 | pub struct TestDescAndFn { 9 | pub testfn: StaticTestFn, 10 | pub desc: TestDesc, 11 | } 12 | 13 | #[derive(Clone, Copy)] 14 | pub struct StaticTestFn(pub fn()); 15 | 16 | #[derive(Clone, Copy)] 17 | pub struct TestDesc { 18 | pub name: StaticTestName, 19 | pub ignore: bool, 20 | pub ignore_message: Option<&'static str>, 21 | pub source_file: &'static str, 22 | pub start_line: usize, 23 | pub start_col: usize, 24 | pub end_line: usize, 25 | pub end_col: usize, 26 | pub should_panic: ShouldPanic, 27 | pub compile_fail: bool, 28 | pub no_run: bool, 29 | pub test_type: TestType, 30 | } 31 | 32 | #[derive(Clone, Copy)] 33 | pub struct StaticTestName(pub &'static str); 34 | 35 | #[derive(Clone, Copy)] 36 | pub enum TestType { 37 | UnitTest, 38 | } 39 | 40 | #[derive(PartialEq, Eq, Clone, Copy)] 41 | pub enum ShouldPanic { 42 | Yes, 43 | No, 44 | } 45 | 46 | pub fn assert_test_result(_: ()) {} 47 | -------------------------------------------------------------------------------- /kernel/src/stage2.lds: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT OR Apache-2.0 */ 2 | 3 | /* 4 | * Copyright (c) 2022-2023 SUSE LLC 5 | * 6 | * Author: Joerg Roedel 7 | */ 8 | 9 | OUTPUT_ARCH(i386:x86-64) 10 | 11 | SECTIONS 12 | { 13 | /* Base address is 8 MB + 32 KB */ 14 | . = 8m + 32k; 15 | .stext = .; 16 | .text : { 17 | *(.startup.*) 18 | *(.text) 19 | *(.text.*) 20 | . = ALIGN(16); 21 | entry_code_start = .; 22 | *(.entry.text) 23 | entry_code_end = .; 24 | . = ALIGN(16); 25 | early_exception_table_start = .; 26 | KEEP(*(__early_exception_table)) 27 | early_exception_table_end = .; 28 | . = ALIGN(16); 29 | exception_table_start = .; 30 | KEEP(*(__exception_table)) 31 | exception_table_end = .; 32 | } 33 | . = ALIGN(16); 34 | .data : { *(.data) } 35 | edata = .; 36 | . = ALIGN(16); 37 | .bss : { 38 | _bss = .; 39 | *(.bss) *(.bss.[0-9a-zA-Z_]*) 40 | . = ALIGN(16); 41 | _ebss = .; 42 | } 43 | /* Move rodata to follow bss so that the in-memory image has the same 44 | * length as the ELF image. This is required so that the IGVM 45 | * builder does not have to parse the ELF file to know how much space 46 | * to reserve for BSS. */ 47 | . = ALIGN(16); 48 | .rodata : { *(.rodata) } 49 | } 50 | 51 | ENTRY(startup_32) 52 | -------------------------------------------------------------------------------- /tools/igvmmeasure/src/utils.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // 3 | // Copyright (c) 2024 SUSE LLC 4 | // 5 | // Author: Roy Hopkins 6 | 7 | use igvm::{IgvmFile, IgvmPlatformHeader}; 8 | use igvm_defs::IgvmPlatformType; 9 | 10 | pub fn get_policy(igvm: &IgvmFile, compatibility_mask: u32) -> Option { 11 | let mut policy: Option = None; 12 | for init in igvm.initializations() { 13 | if let igvm::IgvmInitializationHeader::GuestPolicy { 14 | policy: guest_policy, 15 | compatibility_mask: guest_cm, 16 | } = init 17 | { 18 | if (compatibility_mask & guest_cm) != 0 { 19 | policy = Some(*guest_policy); 20 | break; 21 | } 22 | } 23 | } 24 | policy 25 | } 26 | 27 | pub fn get_compatibility_mask(igvm: &IgvmFile, platform: IgvmPlatformType) -> Option { 28 | let mut compatibility_mask: Option = None; 29 | for pl in igvm.platforms() { 30 | let IgvmPlatformHeader::SupportedPlatform(supported) = pl; 31 | if supported.platform_type == platform { 32 | compatibility_mask = Some(supported.compatibility_mask); 33 | break; 34 | } 35 | } 36 | compatibility_mask 37 | } 38 | -------------------------------------------------------------------------------- /libtcgtpm/deps/TpmConfiguration/TpmConfiguration/VendorCommands/CommandDispatcher.inl: -------------------------------------------------------------------------------- 1 | // This file contains an inlined portion of the CommandDispatcher.c 2 | // command dispatch switch statement. 3 | // 4 | // IMPORTANT: This file is included in the middle of a switch statement, and 5 | // therefore it must not contain anything other than switch blocks 6 | // (This is why the file has the .INL extension, it's not a normal header. 7 | // 8 | #if CC_Vendor_TCG_Test 9 | case TPM_CC_Vendor_TCG_Test: 10 | { 11 | Vendor_TCG_Test_In* in = 12 | (Vendor_TCG_Test_In*)MemoryGetInBuffer(sizeof(Vendor_TCG_Test_In)); 13 | Vendor_TCG_Test_Out* out = 14 | (Vendor_TCG_Test_Out*)MemoryGetOutBuffer(sizeof(Vendor_TCG_Test_Out)); 15 | result = TPM2B_DATA_Unmarshal(&in->inputData, paramBuffer, paramBufferSize); 16 | EXIT_IF_ERROR_PLUS(RC_Vendor_TCG_Test_inputData); 17 | if(*paramBufferSize != 0) 18 | { 19 | result = TPM_RC_SIZE; 20 | goto Exit; 21 | } 22 | result = TPM2_Vendor_TCG_Test(in, out); 23 | if(result != TPM_RC_SUCCESS) 24 | return result; 25 | rSize = sizeof(Vendor_TCG_Test_Out); 26 | *respParmSize += TPM2B_DATA_Marshal(&out->outputData, responseBuffer, &rSize); 27 | break; 28 | } 29 | #endif // CC_Vendor_TCG_Test 30 | -------------------------------------------------------------------------------- /scripts/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # SPDX-License-Identifier: MIT OR Apache-2.0 3 | # 4 | # Copyright (c) 2023 SUSE LLC 5 | # 6 | # Author: Joerg Roedel 7 | 8 | check_file_header() { 9 | header_warning="Header format incorrect in $1, follow the header structure in other files" 10 | IFS=$'\n' 11 | arr=($(head -n 5 "$1")) 12 | if ! [[ "${arr[0]}" == "// SPDX-License-Identifier: MIT OR Apache-2.0" || 13 | "${arr[0]}" == "// SPDX-License-Identifier: MIT" ]] ; then 14 | echo "${header_warning}" 15 | return 1 16 | fi 17 | if ! [[ "${arr[2]}" =~ ^//[[:space:]]Copyright ]] ; then 18 | echo "${header_warning}" 19 | return 1 20 | fi 21 | if ! [[ "${arr[4]}" =~ ^//[[:space:]]Author: ]] ; then 22 | echo "${header_warning}" 23 | return 1 24 | fi 25 | return 0 26 | } 27 | 28 | RET=0 29 | 30 | for file in `git diff --diff-filter=d --name-only --staged`; do 31 | ext=${file##*.} 32 | if [ "$ext" == "rs" ]; then 33 | rustfmt --check --edition 2021 $file > /dev/null 2>&1 34 | if [ "$?" == "1" ]; then 35 | echo "$file needs rustfmt checking" 36 | RET=1 37 | fi 38 | check_file_header $file 39 | if [ "$?" == "1" ]; then 40 | RET=1 41 | fi 42 | fi 43 | done 44 | 45 | make clippy || exit 1 46 | 47 | exit $RET 48 | 49 | -------------------------------------------------------------------------------- /syscall/src/class0.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2024 Intel Corporation. 4 | // 5 | // Author: Chuanxiao Dong 6 | 7 | use super::call::{syscall1, syscall3, SysCallError}; 8 | use super::{SYS_EXEC, SYS_EXIT}; 9 | use core::ffi::CStr; 10 | 11 | pub fn exit(code: u32) -> ! { 12 | // SAFETY: SYS_EXIT is supported syscall number by the svsm kernel. 13 | unsafe { 14 | let _ = syscall1(SYS_EXIT, u64::from(code)); 15 | } 16 | unreachable!("Should never return from SYS_EXIT syscall"); 17 | } 18 | 19 | #[allow(dead_code)] 20 | #[derive(Debug)] 21 | pub struct Tid(u32); 22 | 23 | pub fn exec(file: &CStr, root: &CStr, flags: u32) -> Result { 24 | // SAFETY: 25 | // 1. SYS_EXEC is a supported syscall number by the svsm kernel. 26 | // 2. Parameters `file.as_ptr()` and `root.as_ptr()` are passed as raw pointers. 27 | // but the function `sys_exec` which this function delegates to, performs the 28 | // necessary checks. 29 | // 3. Currently `flags` parameter is unused. 30 | unsafe { 31 | syscall3( 32 | SYS_EXEC, 33 | file.as_ptr() as u64, 34 | root.as_ptr() as u64, 35 | u64::from(flags), 36 | ) 37 | .map(|ret| Tid(ret as u32)) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /kernel/src/protocols/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2023 IBM Corp 4 | // 5 | // Author: Dov Murik 6 | 7 | pub mod apic; 8 | pub mod attest; 9 | pub mod core; 10 | pub mod errors; 11 | #[cfg(all(feature = "vtpm", not(test)))] 12 | pub mod vtpm; 13 | 14 | extern crate alloc; 15 | use crate::vmm::GuestRegister; 16 | use alloc::vec::Vec; 17 | use cpuarch::vmsa::VMSA; 18 | 19 | // SVSM protocols 20 | pub const SVSM_CORE_PROTOCOL: u32 = 0; 21 | pub const SVSM_ATTEST_PROTOCOL: u32 = 1; 22 | pub const SVSM_VTPM_PROTOCOL: u32 = 2; 23 | pub const SVSM_APIC_PROTOCOL: u32 = 3; 24 | pub const SVSM_UEFI_MM_PROTOCOL: u32 = 4; 25 | 26 | #[derive(Debug, Default, Clone, Copy)] 27 | pub struct RequestParams { 28 | sev_features: u64, 29 | rcx: u64, 30 | rdx: u64, 31 | r8: u64, 32 | } 33 | 34 | impl RequestParams { 35 | pub fn from_vmsa(vmsa: &VMSA) -> Self { 36 | RequestParams { 37 | sev_features: vmsa.sev_features, 38 | rcx: vmsa.rcx, 39 | rdx: vmsa.rdx, 40 | r8: vmsa.r8, 41 | } 42 | } 43 | 44 | pub fn capture(&self, regs: &mut Vec) { 45 | regs.push(GuestRegister::X64Rcx(self.rcx)); 46 | regs.push(GuestRegister::X64Rdx(self.rdx)); 47 | regs.push(GuestRegister::X64R8(self.r8)); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /syscall/src/obj.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2024 Intel Corporation. 4 | // 5 | // Author: Chuanxiao Dong 6 | 7 | use super::call::syscall1; 8 | use super::SYS_CLOSE; 9 | 10 | /// The object is exposed to the user mode via the object-opening related 11 | /// syscalls, which returns the id of the object created by the COCONUT-SVSM 12 | /// kernel. The user mode can make use this id to access the corresponding 13 | /// object via other syscalls. From the user mode's point of view, an 14 | /// ObjHanle is defined to wrap a u32 which is the value returned by an 15 | /// object-opening syscall. This u32 value can be used as the input for the 16 | /// syscalls to access the corresponding kernel object. 17 | #[derive(Debug)] 18 | pub struct ObjHandle(u32); 19 | 20 | impl ObjHandle { 21 | pub(crate) const fn new(id: u32) -> Self { 22 | Self(id) 23 | } 24 | } 25 | 26 | impl From<&ObjHandle> for u32 { 27 | #[inline] 28 | fn from(obj_handle: &ObjHandle) -> Self { 29 | obj_handle.0 30 | } 31 | } 32 | 33 | pub trait Obj { 34 | fn id(&self) -> u32; 35 | } 36 | 37 | impl Drop for ObjHandle { 38 | fn drop(&mut self) { 39 | // SAFETY: SYS_CLOSE is supported syscall number by the svsm kernel. 40 | unsafe { 41 | let _ = syscall1(SYS_CLOSE, self.0.into()); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /kernel/src/tdx/ve.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2025 Intel Corporation. 4 | // 5 | // Author: Chuanxiao Dong 6 | 7 | use super::tdcall::{tdcall_get_ve_info, tdvmcall_cpuid}; 8 | use super::TdxError; 9 | use crate::cpu::idt::common::X86ExceptionContext; 10 | use crate::error::SvsmError; 11 | 12 | const VMX_EXIT_REASON_CPUID: u32 = 10; 13 | 14 | pub fn handle_virtualization_exception(ctx: &mut X86ExceptionContext) -> Result<(), SvsmError> { 15 | let veinfo = tdcall_get_ve_info().expect("Failed to get #VE info"); 16 | 17 | match veinfo.exit_reason { 18 | VMX_EXIT_REASON_CPUID => handle_cpuid(ctx), 19 | _ => Err(TdxError::Unknown(veinfo.exit_reason.into()).into()), 20 | }?; 21 | 22 | let new_rip = ctx.frame.rip + veinfo.exit_instruction_length as usize; 23 | // SAFETY: we are advancing the instruction pointer by the size of the exit 24 | // instruction. 25 | unsafe { 26 | ctx.set_rip(new_rip); 27 | } 28 | Ok(()) 29 | } 30 | 31 | fn handle_cpuid(ctx: &mut X86ExceptionContext) -> Result<(), SvsmError> { 32 | let cpuidinfo = tdvmcall_cpuid(ctx.regs.rax as u32, ctx.regs.rcx as u32); 33 | ctx.regs.rax = cpuidinfo.eax as usize; 34 | ctx.regs.rbx = cpuidinfo.ebx as usize; 35 | ctx.regs.rcx = cpuidinfo.ecx as usize; 36 | ctx.regs.rdx = cpuidinfo.edx as usize; 37 | Ok(()) 38 | } 39 | -------------------------------------------------------------------------------- /Documentation/docs/index.md: -------------------------------------------------------------------------------- 1 | # COCONUT-SVSM Documentation 2 | This is the main documentation site for the COCONUT Secure VM Service Module 3 | (SVSM): software which aims to provide secure services and device emulations to 4 | guest operating systems in confidential virtual machines (CVMs). 5 | 6 | ## Getting started 7 | Follow the building and installation guide starting with [Installing the 8 | COCONUT-SVSM](installation/INSTALL.md). 9 | 10 | ## Source code 11 | The COCONUT-SVSM source code can be found at the [COCONUT-SVSM github 12 | repository](https://github.com/coconut-svsm/svsm). 13 | 14 | ## Rustdoc documentation 15 | The Rustdoc documentation can be found by clicking [COCONUT-SVSM 16 | Rustdoc](rustdoc/svsm) in the navigation menu on the left. 17 | 18 | ## Development Plan 19 | 20 | The [development plan document](developer/DEVELOPMENT-PLAN.md) lists planned 21 | and in-progress work items for the COCONUT-SVSM project as well as the first 22 | principles applied when making design decisions. 23 | 24 | ## Community 25 | Development discussions happen on the project mailing list: 26 | - address: coconut-svsm@lists.linux.dev 27 | - archive: https://lore.kernel.org/coconut-svsm/ 28 | - subscription/unsubscription: https://subspace.kernel.org/lists.linux.dev.html 29 | 30 | Regular development calls are scheduled via the mailing list. 31 | 32 | ## Release Process 33 | 34 | The process for making releases is documented in the [Release 35 | Process](RELEASE-PROCESS.md) document. 36 | -------------------------------------------------------------------------------- /scripts/vinstall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # SPDX-License-Identifier: MIT OR Apache-2.0 3 | # 4 | # Copyright (c) Microsoft Corporation 5 | # 6 | # Author: Ziqiao Zhou 7 | # A script to install verus tools 8 | VERISMO_REV=4f504b7 9 | VERUS_RUST_VERSION=1.91.0 10 | VERUSFMT_REV=0.5.7 11 | PREBUILT_VERUSFMT="" 12 | 13 | for arg in "$@"; do 14 | case "$arg" in 15 | --prebuilt-verusfmt) 16 | PREBUILT_VERUSFMT="https://github.com/verus-lang/verusfmt/releases/download/v$VERUSFMT_REV/verusfmt-installer.sh" 17 | ;; 18 | esac 19 | done 20 | 21 | # Install x86_64-unknown-none target for verus-compatible Rust version 22 | export RUSTUP_TOOLCHAIN=$VERUS_RUST_VERSION 23 | rustup target add x86_64-unknown-none --toolchain $RUSTUP_TOOLCHAIN 24 | # Install the verus toolchain 25 | cargo install --git https://github.com/microsoft/verismo/ --rev $VERISMO_REV cargo-v 26 | # verus-rustc as a wrapper to call verus with proper rustc flags. 27 | cargo install --git https://github.com/microsoft/verismo/ --rev $VERISMO_REV verus-rustc 28 | cargo v install-verus 29 | 30 | # Install verusfmt 31 | if [ -n $PREBUILT_VERUSFMT ]; then 32 | if ! verusfmt --version 2>/dev/null | grep -q "$VERUSFMT_REV$"; then 33 | curl --proto '=https' --tlsv1.2 -LsSf "$PREBUILT_VERUSFMT" | sh 34 | else 35 | echo "verusfmt is already at version $VERUSFMT_REV" 36 | fi 37 | else 38 | cargo install --git https://github.com/verus-lang/verusfmt --rev v$VERUSFMT_REV 39 | fi 40 | -------------------------------------------------------------------------------- /elf/src/file_range.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: (GPL-2.0-or-later OR MIT) 2 | // 3 | // Copyright (c) 2023-2024 SUSE LLC 4 | // 5 | // Author: Nicolai Stange 6 | // 7 | // vim: ts=4 sw=4 et 8 | 9 | use super::types::*; 10 | use super::ElfError; 11 | 12 | /// This struct represents a parsed 64-bit ELF file. It contains information 13 | /// about the ELF file's header, load segments, dynamic section, and more. 14 | 15 | #[derive(Default, Debug, Clone, Copy, PartialEq)] 16 | pub struct Elf64FileRange { 17 | pub offset_begin: usize, 18 | pub offset_end: usize, 19 | } 20 | 21 | impl TryFrom<(Elf64Off, Elf64Xword)> for Elf64FileRange { 22 | type Error = ElfError; 23 | 24 | /// Tries to create an [`Elf64FileRange`] from a tuple of [`(Elf64Off, Elf64Xword)`]. 25 | /// 26 | /// 27 | /// # Errors 28 | /// 29 | /// Returns an [`ElfError::InvalidFileRange`] if the calculation of `offset_end` 30 | /// results in an invalid file range. 31 | fn try_from(value: (Elf64Off, Elf64Xword)) -> Result { 32 | let offset_begin = usize::try_from(value.0).map_err(|_| ElfError::InvalidFileRange)?; 33 | let size = usize::try_from(value.1).map_err(|_| ElfError::InvalidFileRange)?; 34 | let offset_end = offset_begin 35 | .checked_add(size) 36 | .ok_or(ElfError::InvalidFileRange)?; 37 | Ok(Self { 38 | offset_begin, 39 | offset_end, 40 | }) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /release/build.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // 3 | // Copyright (c) 2025 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | 7 | use std::fs::OpenOptions; 8 | use std::io::prelude::*; 9 | use std::process::Command; 10 | use std::string::String; 11 | 12 | fn git_version() -> Result { 13 | let output = Command::new("git") 14 | .args(["describe", "--always", "--dirty=+"]) 15 | .output() 16 | .map_err(|_| ())?; 17 | if !output.status.success() { 18 | return Err(()); 19 | } 20 | 21 | let stdout = String::from_utf8(output.stdout).unwrap(); 22 | let mut lines = stdout.lines(); 23 | let first_line = lines.next().unwrap().trim(); 24 | // Strip leading `v` from git tag 25 | let version = first_line.strip_prefix("v").unwrap_or(first_line); 26 | Ok(String::from(version)) 27 | } 28 | 29 | fn write_version(version: String) { 30 | let mut file = OpenOptions::new() 31 | .create(true) 32 | .write(true) 33 | .truncate(true) 34 | .open("src/git_version.rs") 35 | .unwrap(); 36 | writeln!(&mut file, "// SPDX-License-Identifier: MIT\n//").unwrap(); 37 | writeln!( 38 | &mut file, 39 | "// This file is automatically generated - Any changes will be overwritten\n//\n" 40 | ) 41 | .unwrap(); 42 | writeln!(&mut file, "pub const GIT_VERSION: &str = \"{}\";", version).unwrap(); 43 | } 44 | 45 | fn main() { 46 | write_version(git_version().unwrap_or_default()); 47 | } 48 | -------------------------------------------------------------------------------- /kernel/src/syscall/class0.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // 3 | // Copyright (c) 2024 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | 7 | use super::obj::obj_close; 8 | use crate::address::VirtAddr; 9 | use crate::cpu::percpu::current_task; 10 | use crate::fs::find_dir; 11 | use crate::mm::guestmem::UserPtr; 12 | use crate::task::{current_task_terminated, exec_user, schedule}; 13 | use core::ffi::c_char; 14 | use syscall::SysCallError; 15 | 16 | pub fn sys_exit(exit_code: u32) -> ! { 17 | log::info!( 18 | "Terminating task {}, exit_code {exit_code}", 19 | current_task().get_task_name() 20 | ); 21 | current_task_terminated(); 22 | schedule(); 23 | unreachable!("schedule() returned in sys_exit()"); 24 | } 25 | 26 | pub fn sys_exec(file: usize, root: usize, _flags: usize) -> Result { 27 | let user_file_ptr = UserPtr::::new(VirtAddr::from(file)); 28 | let user_root_ptr = UserPtr::::new(VirtAddr::from(root)); 29 | 30 | let file_str = user_file_ptr.read_c_string()?; 31 | let root_str = user_root_ptr.read_c_string()?; 32 | let real_root = find_dir(current_task().rootdir(), &root_str)?; 33 | let tid = exec_user(&file_str, real_root)?; 34 | 35 | Ok(tid.into()) 36 | } 37 | 38 | pub fn sys_close(obj_id: u32) -> Result { 39 | // According to syscall ABI/API spec, close always returns 0 even 40 | // if called with an invalid handle 41 | let _ = obj_close(obj_id.into()); 42 | Ok(0) 43 | } 44 | -------------------------------------------------------------------------------- /libtcgtpm/deps/openssl_svsm.conf: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | # 3 | # Copyright (C) 2023 IBM Corporation 4 | # 5 | # Author: Claudio Carvalho 6 | 7 | my %targets = ( 8 | "SVSM" => { 9 | inherit_from => [ "BASE_unix" ], 10 | perlasm_scheme => "elf", 11 | CC => "gcc", 12 | CFLAGS => add(combine(picker(default => "-Wall -ffunction-sections -fdata-sections", 13 | debug => "-g -O0", 14 | # When compiled with any optmization (e.g. -O1), 15 | # the gcc generates code with instructions that are 16 | # not supported at the SVSM level (e.g. the SSE pxor). 17 | # That crashes the SVSM boot with an unhandled 18 | # exception 6 (invalid opcode) usually in: 19 | # vtpm_init()->libtpm:manufacture()->libcrypto:BN_CTX_new() 20 | release => "-O0"), 21 | "-fPIE -m64 -nostdinc -nostdlib -static -fno-stack-protector -mno-red-zone")), 22 | bn_ops => "SIXTY_FOUR_BIT_LONG", 23 | lib_cppflags => add("-DL_ENDIAN -DNO_SYSLOG -DOPENSSL_SMALL_FOOTPRINT -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -DOPENSSL_USE_USLEEP"), 24 | sys_id => "SVSM" 25 | }, 26 | ); 27 | -------------------------------------------------------------------------------- /stage1/src/reset.S: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT OR Apache-2.0 */ 2 | 3 | /* 4 | * Copyright (c) 2022-2023 SUSE LLC 5 | * 6 | * Author: Joerg Roedel 7 | */ 8 | 9 | .code16gcc 10 | .section .init 11 | /* to_pm_mode must be at 0xfffffe00 */ 12 | .globl to_pm_mode 13 | to_pm_mode: 14 | xor %bx, %bx 15 | mov %bx, %ds 16 | mov %bx, %es 17 | mov %bx, %fs 18 | mov %bx, %gs 19 | mov %bx, %ss 20 | 21 | and $~((1 << 30) | (1 << 29)), %eax 22 | or $1, %al 23 | mov %eax, %cr0 24 | 25 | lgdtl %cs:0xfe00 + gdt32_descr - to_pm_mode 26 | ljmpl $8, $protected_mode 27 | 28 | .code32 29 | td_mode: 30 | and $~((1 << 30) | (1 << 29)), %eax 31 | mov %eax, %cr0 32 | 33 | lgdtl %cs:gdt32_descr // flat 32-bit code segment 34 | ljmpl $8, $protected_mode 35 | 36 | protected_mode: 37 | mov $16, %ax 38 | mov %ax, %ds 39 | mov %ax, %es 40 | mov %ax, %fs 41 | mov %ax, %gs 42 | mov %ax, %ss 43 | ljmp $0x8, $startup_32 44 | 45 | gdt32: 46 | .quad 0 47 | .quad 0x00cf9b000000ffff // flat 32-bit code segment 48 | .quad 0x00cf93000000ffff // flat 32-bit data segment 49 | gdt32_end: 50 | 51 | gdt32_descr: 52 | .word gdt32_end - gdt32 - 1 53 | .long gdt32 54 | 55 | .globl end_to_pm_mode 56 | end_to_pm_mode: 57 | 58 | .section .sevmeta 59 | .incbin "bin/meta.bin" 60 | 61 | .code16gcc 62 | .section .resetvector 63 | mov %cr0, %eax 64 | test $1, %al 65 | // "JZ rel8" is compatible with both 16-bit and 32-bit mode 66 | jz real_mode 67 | .code32 68 | jmp td_mode 69 | .code16 70 | real_mode: 71 | jmp to_pm_mode 72 | -------------------------------------------------------------------------------- /tools/igvmbuilder/src/firmware.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2024 SUSE LLC 4 | // 5 | // Author: Roy Hopkins 6 | 7 | use std::error::Error; 8 | 9 | use bootlib::igvm_params::{IgvmGuestContext, IgvmParamBlockFwInfo}; 10 | use igvm::IgvmDirectiveHeader; 11 | 12 | use crate::cmd_options::CmdOptions; 13 | use crate::igvm_firmware::IgvmFirmware; 14 | use crate::ovmf_firmware::OvmfFirmware; 15 | 16 | pub trait Firmware { 17 | fn directives(&self) -> &Vec; 18 | fn get_guest_context(&self) -> Option; 19 | fn get_vtom(&self) -> u64; 20 | fn get_fw_info(&self) -> IgvmParamBlockFwInfo; 21 | } 22 | 23 | pub fn parse_firmware( 24 | options: &CmdOptions, 25 | parameter_count: u32, 26 | compatibility_mask: u32, 27 | ) -> Result, Box> { 28 | if let Some(filename) = &options.firmware { 29 | match options.hypervisor { 30 | crate::cmd_options::Hypervisor::Qemu => { 31 | OvmfFirmware::parse(filename, parameter_count, compatibility_mask) 32 | } 33 | crate::cmd_options::Hypervisor::HyperV => { 34 | IgvmFirmware::parse(filename, parameter_count, compatibility_mask) 35 | } 36 | crate::cmd_options::Hypervisor::Vanadium => { 37 | OvmfFirmware::parse(filename, parameter_count, compatibility_mask) 38 | } 39 | } 40 | } else { 41 | Err("No firmware filename specified".into()) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /kernel/src/platform/capabilities.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (C) 2025 Intel Corporation 4 | // 5 | // Author: Chuanxiao Dong 6 | 7 | #[derive(Copy, Clone, Debug)] 8 | pub enum Cap { 9 | AvailableVmBitmap = 0, 10 | GlobalFeatureBitmap, 11 | NrCaps, 12 | } 13 | 14 | impl TryFrom for Cap { 15 | type Error = (); 16 | 17 | fn try_from(value: u32) -> Result { 18 | if value == (Cap::AvailableVmBitmap as u32) { 19 | Ok(Cap::AvailableVmBitmap) 20 | } else if value == (Cap::GlobalFeatureBitmap as u32) { 21 | Ok(Cap::GlobalFeatureBitmap) 22 | } else if value == (Cap::NrCaps as u32) { 23 | Ok(Cap::NrCaps) 24 | } else { 25 | Err(()) 26 | } 27 | } 28 | } 29 | 30 | impl From for u32 { 31 | fn from(cap: Cap) -> Self { 32 | cap as Self 33 | } 34 | } 35 | 36 | #[derive(Copy, Clone, Debug)] 37 | pub struct Caps([u64; Cap::NrCaps as usize]); 38 | 39 | impl Caps { 40 | pub fn new(vm_bitmap: u64, global_feat_bitmap: u64) -> Self { 41 | let mut caps = [0; Cap::NrCaps as usize]; 42 | 43 | caps[Cap::AvailableVmBitmap as usize] = vm_bitmap; 44 | caps[Cap::GlobalFeatureBitmap as usize] = global_feat_bitmap; 45 | Self(caps) 46 | } 47 | 48 | pub fn get(&self, idx: Cap) -> u64 { 49 | match idx { 50 | Cap::NrCaps => Cap::NrCaps as u64, 51 | _ => *self.0.get(idx as usize).unwrap(), 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /libaproxy/src/negotiation.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2024 Red Hat, Inc 4 | // 5 | // Author: Stefano Garzarella 6 | // Author: Tyler Fanelli 7 | 8 | extern crate alloc; 9 | 10 | use super::*; 11 | use alloc::vec::Vec; 12 | use serde::{Deserialize, Serialize}; 13 | 14 | /// The initial payload sent from SVSM to the attestation proxy. The version indicates the version 15 | /// of the SVSM attestation protocol to use. 16 | #[derive(Serialize, Deserialize, Debug)] 17 | pub struct NegotiationRequest { 18 | /// Version of the attestation protocol, represented as semver (MAJOR.MINOR.PATCH). 19 | pub version: (u32, u32, u32), 20 | pub tee: kbs_types::Tee, 21 | } 22 | 23 | /// A parameter that must be hashed into the negotiation hash. 24 | #[derive(Serialize, Deserialize, Debug)] 25 | pub enum NegotiationParam { 26 | /// Hash the challenge returned from attestation server. 27 | Challenge, 28 | /// Hash the EC public key's `Elliptic-Curve-Point-to-Octet-String` encoding. 29 | EcPublicKeyBytes, 30 | } 31 | 32 | #[derive(Serialize, Deserialize, Debug)] 33 | pub struct NegotiationResponse { 34 | /// Challenge returned from the attestation server to verify freshness of attestation evidence. 35 | #[serde( 36 | serialize_with = "serialize_base64", 37 | deserialize_with = "deserialize_base64" 38 | )] 39 | pub challenge: Vec, 40 | /// Parameters to be hashed in the specific order defined by the array 41 | pub params: Vec, 42 | } 43 | -------------------------------------------------------------------------------- /tools/cbit/src/main.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2025 SUSE LLC 4 | // 5 | // Author: Carlos López 6 | 7 | use std::{ 8 | arch::x86_64::{__cpuid, CpuidResult}, 9 | process::ExitCode, 10 | }; 11 | 12 | use bitfield_struct::bitfield; 13 | 14 | // AMD Programmer's Manual Volume 3 15 | // - Section "Function 8000_0000h - Maximum Extended Function Number and Vendor String" 16 | // - Section "Function 8000_001Fh - Encrypted Memory Capabilities" 17 | const CPUID_MAX_EXTENDED_LEAF: u32 = 0x80000000; 18 | const CPUID_ENCRYPT_MEM_CAPAB: u32 = 0x8000001f; 19 | 20 | #[bitfield(u32)] 21 | struct EncryptMemCapEax { 22 | sme: bool, 23 | sev: bool, 24 | #[bits(30)] 25 | _unused: u32, 26 | } 27 | 28 | #[bitfield(u32)] 29 | struct EncryptMemCapEbx { 30 | #[bits(6)] 31 | cbit: u8, 32 | #[bits(6)] 33 | phys_addr_reduction: u8, 34 | #[bits(4)] 35 | vmpls: u8, 36 | _reserved: u16, 37 | } 38 | 39 | fn cpuid(eax: u32) -> CpuidResult { 40 | // SAFETY: CPUID is always safe 41 | unsafe { __cpuid(eax) } 42 | } 43 | 44 | fn main() -> ExitCode { 45 | let res = cpuid(CPUID_MAX_EXTENDED_LEAF); 46 | if res.eax < CPUID_ENCRYPT_MEM_CAPAB { 47 | return ExitCode::FAILURE; 48 | } 49 | 50 | let res = cpuid(CPUID_ENCRYPT_MEM_CAPAB); 51 | let cap1 = EncryptMemCapEax::from(res.eax); 52 | if !cap1.sev() { 53 | return ExitCode::FAILURE; 54 | } 55 | 56 | let cap2 = EncryptMemCapEbx::from(res.ebx); 57 | println!("{}", cap2.cbit()); 58 | 59 | ExitCode::SUCCESS 60 | } 61 | -------------------------------------------------------------------------------- /.github/workflows/publish-docs.yml: -------------------------------------------------------------------------------- 1 | name: PublishDocs 2 | on: 3 | push: 4 | branches: 5 | - main 6 | permissions: 7 | contents: write 8 | jobs: 9 | deploy: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v3 14 | with: 15 | submodules: recursive 16 | 17 | - name: Configure Git Credentials 18 | run: | 19 | git config user.name github-actions[bot] 20 | git config user.email 41898282+github-actions[bot]@users.noreply.github.com 21 | 22 | - name: Install latest Rust stable 23 | uses: actions-rs/toolchain@v1 24 | with: 25 | toolchain: stable 26 | target: x86_64-unknown-none 27 | profile: minimal 28 | override: true 29 | 30 | - name: Install TPM 2.0 Reference Implementation build dependencies 31 | run: sudo apt install -y build-essential cmake pkg-config 32 | 33 | - uses: actions/setup-python@v5 34 | with: 35 | python-version: 3.x 36 | - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV 37 | - uses: actions/cache@v4 38 | with: 39 | key: mkdocs-material-${{ env.cache_id }} 40 | path: .cache 41 | restore-keys: | 42 | mkdocs-material- 43 | - run: pip install mkdocs-material 44 | 45 | - name: Make documentation site 46 | run: | 47 | make docsite 48 | 49 | - name: Deploy 50 | run: mkdocs gh-deploy -f Documentation/mkdocs.yml -d ../target/x86_64-unknown-none/site --dirty --force 51 | -------------------------------------------------------------------------------- /kernel/src/vmm/registers.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Jon Lange (jlange@microsoft.com) 6 | 7 | use cpuarch::vmsa::VMSA; 8 | 9 | #[derive(Copy, Clone, Debug)] 10 | pub enum GuestRegister { 11 | X64Rax(u64), 12 | X64Rcx(u64), 13 | X64Rdx(u64), 14 | X64Rbx(u64), 15 | X64Rsp(u64), 16 | X64Rbp(u64), 17 | X64Rsi(u64), 18 | X64Rdi(u64), 19 | X64R8(u64), 20 | X64R9(u64), 21 | X64R10(u64), 22 | X64R11(u64), 23 | X64R12(u64), 24 | X64R13(u64), 25 | X64R14(u64), 26 | X64R15(u64), 27 | } 28 | 29 | pub fn set_guest_register(vmsa: &mut VMSA, reg: &GuestRegister) { 30 | match reg { 31 | GuestRegister::X64Rax(r) => vmsa.rax = *r, 32 | GuestRegister::X64Rcx(r) => vmsa.rcx = *r, 33 | GuestRegister::X64Rdx(r) => vmsa.rdx = *r, 34 | GuestRegister::X64Rbx(r) => vmsa.rbx = *r, 35 | GuestRegister::X64Rsp(r) => vmsa.rsp = *r, 36 | GuestRegister::X64Rbp(r) => vmsa.rbp = *r, 37 | GuestRegister::X64Rsi(r) => vmsa.rsi = *r, 38 | GuestRegister::X64Rdi(r) => vmsa.rdi = *r, 39 | GuestRegister::X64R8(r) => vmsa.r8 = *r, 40 | GuestRegister::X64R9(r) => vmsa.r9 = *r, 41 | GuestRegister::X64R10(r) => vmsa.r10 = *r, 42 | GuestRegister::X64R11(r) => vmsa.r11 = *r, 43 | GuestRegister::X64R12(r) => vmsa.r12 = *r, 44 | GuestRegister::X64R13(r) => vmsa.r13 = *r, 45 | GuestRegister::X64R14(r) => vmsa.r14 = *r, 46 | GuestRegister::X64R15(r) => vmsa.r15 = *r, 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /configs/all-targets.json: -------------------------------------------------------------------------------- 1 | { 2 | "igvm": { 3 | "qemu": { 4 | "output": "coconut-qemu.igvm", 5 | "platforms": [ 6 | "snp", 7 | "tdp" 8 | ], 9 | "policy": "0x30000", 10 | "measure": "print", 11 | "check-kvm": true 12 | }, 13 | "hyper-v": { 14 | "output": "coconut-hyperv.igvm", 15 | "platforms": [ 16 | "snp", 17 | "tdp", 18 | "vsm" 19 | ], 20 | "policy": "0x30000", 21 | "comport": "3", 22 | "measure": "print" 23 | }, 24 | "vanadium": { 25 | "output": "coconut-vanadium.igvm", 26 | "platforms": [ 27 | "snp", 28 | "tdp" 29 | ], 30 | "policy": "0x30000", 31 | "measure": "print", 32 | "check-kvm": true, 33 | "measure-native-zeroes": true 34 | } 35 | }, 36 | "kernel": { 37 | "svsm": { 38 | "features": "vtpm,enable-gdb", 39 | "binary": false 40 | }, 41 | "stage2": { 42 | "manifest": "kernel/Cargo.toml", 43 | "binary": true, 44 | "objcopy": "binary" 45 | }, 46 | "tdx-stage1": { 47 | "type": "make", 48 | "output_file": "bin/stage1-trampoline", 49 | "objcopy": "binary" 50 | } 51 | }, 52 | "fs": { 53 | "modules": { 54 | "userinit": { 55 | "path": "/init" 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /kernel/src/cpu/efer.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2022-2023 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | 7 | use super::msr::{read_msr, write_msr, EFER}; 8 | use bitflags::bitflags; 9 | 10 | bitflags! { 11 | #[derive(Clone, Copy, Debug)] 12 | pub struct EFERFlags: u64 { 13 | const SCE = 1 << 0; // System Call Extensions 14 | const LME = 1 << 8; // Long Mode Enable 15 | const LMA = 1 << 10; // Long Mode Active 16 | const NXE = 1 << 11; // No-Execute Enable 17 | const SVME = 1 << 12; // Secure Virtual Machine Enable 18 | const LMSLE = 1 << 13; // Long Mode Segment Limit Enable 19 | const FFXSR = 1 << 14; // Fast FXSAVE/FXRSTOR 20 | const TCE = 1 << 15; // Translation Cache Extension 21 | const MCOMMIT = 1 << 17; // Enable MCOMMIT instruction 22 | const INTWB = 1 << 18; // Interruptible WBINVD/WBNOINVD enable 23 | const UAIE = 1 << 20; // Upper Address Ignore Enable 24 | } 25 | } 26 | 27 | pub fn read_efer() -> EFERFlags { 28 | EFERFlags::from_bits_truncate(read_msr(EFER)) 29 | } 30 | 31 | /// # Safety 32 | /// 33 | /// The caller should ensure that the new value written to EFER MSR doesn't 34 | /// break memory safety. 35 | pub unsafe fn write_efer(efer: EFERFlags) { 36 | let val = efer.bits(); 37 | // SAFETY: requirements should be verified by the caller. 38 | unsafe { 39 | write_msr(EFER, val); 40 | } 41 | } 42 | 43 | impl From for EFERFlags { 44 | fn from(bits: usize) -> Self { 45 | EFERFlags::from_bits_truncate(bits as u64) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /xbuild/src/version.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // 3 | // Copyright (c) 2025 SUSE LLC 4 | // Copyright (c) 2025 Advanced Micro Devices, Inc 5 | // 6 | // Author: Joerg Roedel 7 | 8 | use std::fs::OpenOptions; 9 | use std::io::prelude::*; 10 | use std::process::Command; 11 | use std::string::String; 12 | 13 | const RELEASE_FILE: &str = "release/src/git_version.rs"; 14 | 15 | fn git_version() -> Result { 16 | let output = Command::new("git") 17 | .args(["describe", "--always", "--dirty=+"]) 18 | .output() 19 | .map_err(|_| ())?; 20 | if !output.status.success() { 21 | return Err(()); 22 | } 23 | 24 | let stdout = String::from_utf8(output.stdout).map_err(|_| ())?; 25 | let mut lines = stdout.lines(); 26 | let first_line = lines.next().ok_or(())?.trim(); 27 | // Strip leading `v` from git tag 28 | let version = first_line.strip_prefix("v").unwrap_or(first_line); 29 | Ok(String::from(version)) 30 | } 31 | 32 | fn write_version(version: String) { 33 | let mut file = OpenOptions::new() 34 | .create(true) 35 | .write(true) 36 | .truncate(true) 37 | .open(RELEASE_FILE) 38 | .unwrap(); 39 | writeln!(&mut file, "// SPDX-License-Identifier: MIT\n//").unwrap(); 40 | writeln!( 41 | &mut file, 42 | "// This file is automatically generated - Any changes will be overwritten\n//\n" 43 | ) 44 | .unwrap(); 45 | writeln!(&mut file, "pub const GIT_VERSION: &str = \"{}\";", version).unwrap(); 46 | } 47 | 48 | pub fn generate_release_file() { 49 | write_version(git_version().unwrap_or_default()); 50 | } 51 | -------------------------------------------------------------------------------- /kernel/src/cpu/mem.rs: -------------------------------------------------------------------------------- 1 | use core::arch::asm; 2 | 3 | /// Copy `size` bytes from `src` to `dst`. 4 | /// 5 | /// # Safety 6 | /// 7 | /// This function has all the safety requirements of `core::ptr::copy` except 8 | /// that data races (both on `src` and `dst`) are explicitly permitted. 9 | #[inline(always)] 10 | pub unsafe fn unsafe_copy_bytes(src: *const T, dst: *mut T, count: usize) { 11 | let size = count * core::mem::size_of::(); 12 | // SAFETY: Inline assembly to perform a memory copy. 13 | // The safery requirements of the parameters are delegated to the caller of 14 | // this function which is unsafe. 15 | unsafe { 16 | asm!( 17 | "rep movsb", 18 | inout("rsi") src => _, 19 | inout("rdi") dst => _, 20 | inout("rcx") size => _, 21 | options(nostack), 22 | ); 23 | } 24 | } 25 | 26 | /// Set `size` bytes at `dst` to `val`. 27 | /// 28 | /// # Safety 29 | /// 30 | /// This function has all the safety requirements of `core::ptr::write_bytes` except 31 | /// that data races are explicitly permitted. 32 | #[inline(always)] 33 | pub unsafe fn write_bytes(dst: *mut T, count: usize, value: u8) { 34 | let size = count * core::mem::size_of::(); 35 | // SAFETY: Inline assembly to perform a memory write. 36 | // The safery requirements of the parameters are delegated to the caller of 37 | // this function which is unsafe. 38 | unsafe { 39 | asm!( 40 | "rep stosb", 41 | inout("rdi") dst => _, 42 | inout("rcx") size => _, 43 | in("al") value, 44 | options(nostack), 45 | ); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /xbuild/src/kernel.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Author: Carlos López 4 | 5 | use crate::{features::Features, Args, BuildResult, BuildTarget, Component, ComponentConfig}; 6 | use serde::Deserialize; 7 | use std::collections::HashMap; 8 | use std::path::PathBuf; 9 | 10 | /// Components to build the kernel. It consists of a list of 11 | /// component names and their respective build configurations. 12 | #[derive(Debug, Clone, Deserialize)] 13 | pub struct KernelConfig { 14 | #[serde(flatten, default)] 15 | components: HashMap, 16 | } 17 | 18 | impl KernelConfig { 19 | fn components(&self) -> impl Iterator> + '_ { 20 | self.components 21 | .iter() 22 | .map(|(name, conf)| Component::new(name.as_str(), conf)) 23 | } 24 | 25 | pub fn build( 26 | &self, 27 | args: &Args, 28 | mut dst: PathBuf, 29 | cmd_feats: &mut Features, 30 | ) -> BuildResult> { 31 | if !dst.try_exists()? { 32 | std::fs::create_dir(&dst)?; 33 | } 34 | 35 | // Build each component and copy it to the output path 36 | let mut objs = Vec::new(); 37 | for comp in self.components() { 38 | // Build the component and objcopy it into bin/ 39 | let bin = comp.build(args, BuildTarget::svsm_kernel(), cmd_feats)?; 40 | dst.push(comp.name); 41 | comp.config.objcopy.copy(&bin, &dst, args)?; 42 | objs.push(dst.clone()); 43 | dst.pop(); 44 | } 45 | Ok(objs) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Documentation/docs/developer/DOC-GUIDELINES.md: -------------------------------------------------------------------------------- 1 | Documentation Guidelines 2 | ======================== 3 | 4 | This documentation site is generated using [mkdocs](https://www.mkdocs.org/) 5 | from markdown files in the repository at: 6 | [`Documentation/docs`](https://github.com/coconut-svsm/svsm/tree/main/Documentation/docs). 7 | 8 | You can add documentation pages to this site by creating a pull request. You 9 | will need to add any new pages to the the [mkdocs configuration 10 | file](https://github.com/coconut-svsm/svsm/tree/main/Documentation/mkdocs.yml) 11 | in the `nav` section. See the mkdocs documentation for more details. 12 | 13 | Previewing documentation changes 14 | -------------------------------- 15 | 16 | The documentation pages can be built locally on a development system in order to 17 | preview the changes before publishing. 18 | 19 | The `mkdocs` tool needs to be installed in order to build the site pages. On 20 | openSUSE `mkdocs` can be installed with: 21 | 22 | ``` 23 | $ sudo zypper in python312-mkdocs 24 | ``` 25 | 26 | You can then run a local server that renders the documentation pages with: 27 | 28 | ``` 29 | $ make docsite-serve 30 | ``` 31 | 32 | The documentation can then be previewed at: http://localhost:8000. 33 | 34 | Note that the links to the Rustdocs will not work in the preview. 35 | 36 | Publishing the documentation 37 | ---------------------------- 38 | 39 | When a PR containing documentation is merged, a github action is used to build 40 | the documentation and push the html files to [the `gh-pages` 41 | branch](https://github.com/coconut-svsm/svsm/tree/gh-pages). 42 | 43 | Another github action automatically publishes this branch at the Github pages 44 | site: [https://coconut-svsm.github.io/svsm/](https://coconut-svsm.github.io/svsm/). -------------------------------------------------------------------------------- /release/src/lib.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // 3 | // Copyright (c) 2025 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | 7 | #![no_std] 8 | 9 | mod git_version; 10 | 11 | use core::fmt; 12 | use git_version::GIT_VERSION; 13 | 14 | #[allow(dead_code)] 15 | #[derive(Debug)] 16 | enum ReleaseType { 17 | /// Development Release 18 | Development, 19 | /// Stable Release Candidate 20 | Candidate(u32), 21 | /// Stable Release 22 | Stable(u32), 23 | } 24 | 25 | #[derive(Debug)] 26 | pub struct SvsmVersion { 27 | year: u32, 28 | month: u32, 29 | release_type: ReleaseType, 30 | } 31 | 32 | impl fmt::Display for SvsmVersion { 33 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 34 | #[allow(clippy::const_is_empty)] 35 | if !GIT_VERSION.is_empty() { 36 | write!(f, "{}", GIT_VERSION) 37 | } else { 38 | match self.release_type { 39 | ReleaseType::Development => { 40 | write!(f, "{}.{:#02}-devel", self.year, self.month) 41 | } 42 | ReleaseType::Candidate(counter) => { 43 | write!(f, "{}.{:#02}-rc{}", self.year, self.month, counter) 44 | } 45 | ReleaseType::Stable(counter) => { 46 | write!(f, "{}.{:#02}.{}", self.year, self.month, counter) 47 | } 48 | } 49 | } 50 | } 51 | } 52 | 53 | const VERSION_YEAR: u32 = 2025; 54 | const VERSION_MONTH: u32 = 12; 55 | #[allow(dead_code)] 56 | const VERSION_COUNTER: u32 = 0; 57 | 58 | pub static COCONUT_VERSION: SvsmVersion = SvsmVersion { 59 | year: VERSION_YEAR, 60 | month: VERSION_MONTH, 61 | release_type: ReleaseType::Development, 62 | }; 63 | -------------------------------------------------------------------------------- /kernel/src/mm/vm/mapping/reserved.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2022-2023 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | 7 | use crate::address::PhysAddr; 8 | use crate::mm::pagetable::PTEntryFlags; 9 | 10 | use super::{Mapping, VirtualMapping}; 11 | 12 | /// Reserve a region of address space so that no other mapping will be 13 | /// established there. The map function for this type will always return 14 | /// `None`. 15 | #[derive(Default, Debug, Clone, Copy)] 16 | pub struct VMReserved { 17 | /// Size in bytes to reserve. Must be aligned to PAGE_SIZE 18 | size: usize, 19 | } 20 | 21 | impl VMReserved { 22 | /// Create new instance of VMReserved 23 | /// 24 | /// # Arguments 25 | /// 26 | /// * `size` - Number of bytes to reserve 27 | /// 28 | /// # Returns 29 | /// 30 | /// New instance of VMReserved 31 | pub fn new(size: usize) -> Self { 32 | VMReserved { size } 33 | } 34 | 35 | /// Create new [`Mapping`] of [`VMReserved`] 36 | /// 37 | /// # Arguments 38 | /// 39 | /// * `size` - Number of bytes to reserve 40 | /// 41 | /// # Returns 42 | /// 43 | /// New Mapping of VMReserved 44 | pub fn new_mapping(size: usize) -> Mapping { 45 | Mapping::new(Self::new(size)) 46 | } 47 | } 48 | 49 | impl VirtualMapping for VMReserved { 50 | fn mapping_size(&self) -> usize { 51 | self.size 52 | } 53 | 54 | fn has_data(&self) -> bool { 55 | false 56 | } 57 | 58 | fn map(&self, _offset: usize) -> Option { 59 | None 60 | } 61 | 62 | fn pt_flags(&self, _offset: usize) -> PTEntryFlags { 63 | PTEntryFlags::NX | PTEntryFlags::ACCESSED | PTEntryFlags::WRITABLE | PTEntryFlags::DIRTY 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /verification/verify_proof/src/sum.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Ziqiao Zhou 6 | use vstd::multiset::Multiset; 7 | use vstd::prelude::*; 8 | 9 | verus! { 10 | 11 | pub trait CountTrait { 12 | spec fn count(&self) -> nat; 13 | } 14 | 15 | pub open spec fn sum(s: Multiset) -> nat 16 | decreases s.len(), 17 | { 18 | if s.len() > 0 { 19 | let e = s.choose(); 20 | e.count() + sum(s.remove(e)) 21 | } else { 22 | 0 23 | } 24 | } 25 | 26 | pub proof fn lemma_sum_insert(s: Multiset, elem: T) 27 | ensures 28 | sum(s) + elem.count() == sum(s.insert(elem)), 29 | { 30 | assert(s.insert(elem).remove(elem) =~= s); 31 | lemma_sum_remove(s.insert(elem), elem); 32 | } 33 | 34 | pub proof fn lemma_sum_remove(s: Multiset, elem: T) 35 | requires 36 | s.contains(elem), 37 | ensures 38 | sum(s.remove(elem)) + elem.count() == sum(s), 39 | decreases s.len(), 40 | { 41 | let news = s.remove(elem); 42 | if s.len() > 1 { 43 | let e = s.choose(); 44 | if e != elem { 45 | assert(sum(s.remove(e)) + e.count() == sum(s)); 46 | lemma_sum_remove(s.remove(e), elem); 47 | lemma_sum_remove(s.remove(elem), e); 48 | assert(s.remove(elem).remove(e) =~= s.remove(e).remove(elem)); 49 | } else { 50 | assert(sum(s.remove(elem)) + elem.count() == sum(s)); 51 | } 52 | } else { 53 | Multiset::lemma_is_singleton(s); 54 | let e = s.choose(); 55 | assert(s.contains(e)); 56 | assert(news.len() == 0); 57 | assert(sum(news) == 0); 58 | assert(e == elem); 59 | } 60 | } 61 | 62 | } // verus! 63 | -------------------------------------------------------------------------------- /kernel/src/lib.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2022-2023 SUSE LLC 4 | // 5 | // Author: Nicolai Stange 6 | 7 | #![no_std] 8 | #![cfg_attr(all(test, test_in_svsm), no_main)] 9 | #![cfg_attr(all(test, test_in_svsm), feature(custom_test_frameworks))] 10 | #![cfg_attr(all(test, test_in_svsm), test_runner(crate::testing::svsm_test_runner))] 11 | #![cfg_attr(all(test, test_in_svsm), reexport_test_harness_main = "test_main")] 12 | #![cfg_attr(verus_keep_ghost, feature(proc_macro_hygiene))] 13 | 14 | pub mod acpi; 15 | pub mod address; 16 | #[cfg(feature = "attest")] 17 | pub mod attest; 18 | pub mod block; 19 | pub mod config; 20 | pub mod console; 21 | pub mod cpu; 22 | pub mod crypto; 23 | pub mod debug; 24 | pub mod error; 25 | pub mod fs; 26 | pub mod fw_cfg; 27 | pub mod greq; 28 | pub mod hyperv; 29 | pub mod igvm_params; 30 | pub mod insn_decode; 31 | pub mod io; 32 | pub mod kernel_region; 33 | pub mod locking; 34 | pub mod mm; 35 | pub mod platform; 36 | pub mod protocols; 37 | pub mod requests; 38 | pub mod serial; 39 | pub mod sev; 40 | pub mod svsm_paging; 41 | pub mod syscall; 42 | pub mod task; 43 | pub mod tdx; 44 | pub mod types; 45 | pub mod utils; 46 | #[cfg(feature = "virtio-drivers")] 47 | pub mod virtio; 48 | pub mod vmm; 49 | #[cfg(all(feature = "vtpm", not(test)))] 50 | pub mod vtpm; 51 | 52 | #[test] 53 | fn test_nop() {} 54 | 55 | // When running tests inside the SVSM: 56 | // Build the kernel entrypoint. 57 | #[cfg(all(test, test_in_svsm))] 58 | #[path = "svsm.rs"] 59 | pub mod svsm_bin; 60 | // The kernel expects to access this crate as svsm, so reexport. 61 | #[cfg(all(test, test_in_svsm))] 62 | extern crate self as svsm; 63 | // Include a module containing the test runner. 64 | #[cfg(all(test, test_in_svsm))] 65 | pub mod testing; 66 | // Utilities for test configurations. 67 | #[cfg(test)] 68 | pub mod testutils; 69 | -------------------------------------------------------------------------------- /kernel/src/cpu/x86/x2apic.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // Copyright (c) SUSE LLC 5 | // 6 | // Author: Jon Lange 7 | // Author: Joerg Roedel 8 | 9 | use super::{ApicAccess, MSR_APIC_BASE}; 10 | use crate::cpu::msr::{read_msr, write_msr}; 11 | 12 | /// X2APIC Base MSR 13 | pub const MSR_X2APIC_BASE: u32 = 0x800; 14 | /// End-of-Interrupt register MSR offset 15 | pub const MSR_X2APIC_EOI: u32 = 0x80B; 16 | /// Spurious-Interrupt-Register MSR offset 17 | pub const MSR_X2APIC_SPIV: u32 = 0x80F; 18 | /// Interrupt-Service-Register base MSR offset 19 | pub const MSR_X2APIC_ISR: u32 = 0x810; 20 | /// Interrupt-Control-Register register MSR offset 21 | pub const MSR_X2APIC_ICR: u32 = 0x830; 22 | /// SELF-IPI register MSR offset 23 | pub const MSR_X2APIC_SELF_IPI: u32 = 0x83F; 24 | 25 | #[derive(Debug)] 26 | pub struct X2ApicAccessor {} 27 | 28 | impl ApicAccess for X2ApicAccessor { 29 | fn update_apic_base(&self, and_mask: u64, or_mask: u64) { 30 | let current_value = read_msr(MSR_APIC_BASE); 31 | let new_value = (current_value & and_mask) | or_mask; 32 | 33 | if current_value != new_value { 34 | // SAFETY: Writes to MSR_APIC_BASE to not impact memory safety. 35 | unsafe { 36 | write_msr(MSR_APIC_BASE, new_value); 37 | } 38 | } 39 | } 40 | 41 | fn apic_write(&self, offset: usize, value: u64) { 42 | let msr = MSR_X2APIC_BASE + u32::try_from(offset).unwrap(); 43 | // SAFETY: Writes to X2APIC MSRs never harms memory safety. 44 | unsafe { write_msr(msr, value) }; 45 | } 46 | 47 | fn apic_read(&self, offset: usize) -> u64 { 48 | let msr = MSR_X2APIC_BASE + u32::try_from(offset).unwrap(); 49 | read_msr(msr) 50 | } 51 | } 52 | 53 | pub static X2APIC_ACCESSOR: X2ApicAccessor = X2ApicAccessor {}; 54 | -------------------------------------------------------------------------------- /libtcgtpm/deps/TpmConfiguration/TpmConfiguration/VendorCommands/CommandDispatchData_CommandStructures.inl: -------------------------------------------------------------------------------- 1 | // This file contains an inlined portion of the s_ccAttr array definition 2 | // for vendor commands. 3 | // 4 | // IMPORTANT: This file is included in the middle of an array initializer 5 | // therefore it must not contain anything other than comments and exactly one TPMA_CC 6 | // entry per vendor command. See the private Tpm header CommandAttributeData.h for 7 | // more info. 8 | // (This is why the file has the .INL extension, it's not a normal header. 9 | // 10 | #ifndef _COMMAND_TABLE_DISPATCH_ 11 | #error This file should only be included inside CommandDispatchData.h when table dispatching is turned on. 12 | #endif 13 | 14 | #if CC_Vendor_TCG_Test 15 | # include "TpmConfiguration/VendorCommands/prototypes/Vendor_TCG_Test_fp.h" 16 | 17 | typedef TPM_RC(Vendor_TCG_Test_Entry)(Vendor_TCG_Test_In* in, 18 | Vendor_TCG_Test_Out* out); 19 | 20 | typedef const struct 21 | { 22 | Vendor_TCG_Test_Entry* entry; 23 | UINT16 inSize; 24 | UINT16 outSize; 25 | UINT16 offsetOfTypes; 26 | BYTE types[4]; 27 | } Vendor_TCG_Test_COMMAND_DESCRIPTOR_t; 28 | 29 | Vendor_TCG_Test_COMMAND_DESCRIPTOR_t _Vendor_TCG_TestData = { 30 | /* entry */ &TPM2_Vendor_TCG_Test, 31 | /* inSize */ (UINT16)(sizeof(Vendor_TCG_Test_In)), 32 | /* outSize */ (UINT16)(sizeof(Vendor_TCG_Test_Out)), 33 | /* offsetOfTypes */ offsetof(Vendor_TCG_Test_COMMAND_DESCRIPTOR_t, types), 34 | /* offsets */ // No parameter offsets 35 | /* types */ 36 | {TPM2B_DATA_P_UNMARSHAL, END_OF_LIST, TPM2B_DATA_P_MARSHAL, END_OF_LIST}}; 37 | 38 | # define _Vendor_TCG_TestDataAddress (&_Vendor_TCG_TestData) 39 | #else 40 | # define _Vendor_TCG_TestDataAddress 0 41 | #endif // CC_Vendor_TCG_Test 42 | -------------------------------------------------------------------------------- /verification/verify_proof/src/set.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Ziqiao Zhou 6 | use vstd::prelude::*; 7 | 8 | verus! { 9 | 10 | pub open spec fn set_usize_range(start: usize, end: int) -> Set { 11 | Set::new(|i| start <= i < end) 12 | } 13 | 14 | pub broadcast proof fn lemma_set_usize_range(start: usize, end: int) 15 | requires 16 | start <= end, 17 | end <= usize::MAX + 1, 18 | ensures 19 | (#[trigger] set_usize_range(start, end)).finite(), 20 | set_usize_range(start, end).len() == end - start, 21 | decreases end - start, 22 | { 23 | if end > start { 24 | let e2 = (end - 1) as usize; 25 | let s1 = set_usize_range(start, end); 26 | let s2 = set_usize_range(start, e2 as int); 27 | lemma_set_usize_range(start, e2 as int); 28 | assert(s1 =~= s2.insert(e2)); 29 | } else { 30 | assert(set_usize_range(start, end) =~= Set::empty()); 31 | } 32 | } 33 | 34 | pub broadcast proof fn lemma_set_usize_finite(s: Set) 35 | ensures 36 | #[trigger] s.finite(), 37 | { 38 | let maxset = set_usize_range(0, usize::MAX + 1); 39 | lemma_set_usize_range(0, usize::MAX + 1); 40 | assert(s.subset_of(maxset)); 41 | } 42 | 43 | pub broadcast proof fn lemma_len_filter(s: Set, f: spec_fn(A) -> bool) 44 | requires 45 | s.finite(), 46 | ensures 47 | (#[trigger] s.filter(f)).finite(), 48 | s.filter(f).len() <= s.len(), 49 | { 50 | s.lemma_len_filter(f) 51 | } 52 | 53 | pub broadcast proof fn lemma_len_subset(s1: Set, s2: Set) 54 | requires 55 | s2.finite(), 56 | #[trigger] s1.subset_of(s2), 57 | ensures 58 | s1.len() <= s2.len(), 59 | s1.finite(), 60 | { 61 | vstd::set_lib::lemma_len_subset(s1, s2) 62 | } 63 | 64 | } // verus! 65 | -------------------------------------------------------------------------------- /tools/aproxy/src/main.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2024 Red Hat, Inc 4 | // 5 | // Author: Stefano Garzarella 6 | // Author: Tyler Fanelli 7 | 8 | mod attest; 9 | mod backend; 10 | 11 | use anyhow::Context; 12 | use clap::{Parser, ValueEnum}; 13 | use std::{fs, os::unix::net::UnixListener}; 14 | 15 | #[derive(Parser, Debug)] 16 | #[clap(version, about, long_about = None)] 17 | struct Args { 18 | /// HTTP url to KBS (e.g. http://server:4242) 19 | #[clap(long)] 20 | url: String, 21 | 22 | /// Backend attestation protocol that the server implements. 23 | #[clap(long = "protocol")] 24 | backend: ArgsBackend, 25 | 26 | /// UNIX domain socket path to the SVSM serial port 27 | #[clap(long)] 28 | unix: String, 29 | 30 | /// Force Unix domain socket removal before bind 31 | #[clap(long, short, default_value_t = false)] 32 | force: bool, 33 | } 34 | 35 | /// Enum to represent possible backends in the CLI. 36 | /// This must not have any attached data to its variants for `ValueEnum` 37 | /// to work. 38 | #[derive(Clone, Copy, Debug, ValueEnum)] 39 | enum ArgsBackend { 40 | Kbs, 41 | } 42 | 43 | fn main() -> anyhow::Result<()> { 44 | let args = Args::parse(); 45 | 46 | if args.force { 47 | let _ = fs::remove_file(args.unix.clone()); 48 | } 49 | 50 | let listener = UnixListener::bind(args.unix).context("unable to bind to UNIX socket")?; 51 | 52 | for stream in listener.incoming() { 53 | match stream { 54 | Ok(mut stream) => { 55 | let mut http_client = 56 | backend::HttpClient::new(args.url.clone(), args.backend.into())?; 57 | attest::attest(&mut stream, &mut http_client)?; 58 | } 59 | Err(_) => { 60 | panic!("error"); 61 | } 62 | } 63 | } 64 | 65 | Ok(()) 66 | } 67 | -------------------------------------------------------------------------------- /xbuild/src/helpers.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Author: Carlos López 4 | 5 | use crate::{features::Features, Args, BuildTarget, Component, ComponentConfig}; 6 | use std::path::PathBuf; 7 | use std::sync::OnceLock; 8 | 9 | /// A data structure that lazily builds helper programs. 10 | #[derive(Clone, Debug)] 11 | pub struct Helpers { 12 | igvmbuilder: OnceLock, 13 | igvmmeasure: OnceLock, 14 | packit: OnceLock, 15 | } 16 | 17 | impl Helpers { 18 | const fn new() -> Self { 19 | Self { 20 | igvmbuilder: OnceLock::new(), 21 | igvmmeasure: OnceLock::new(), 22 | packit: OnceLock::new(), 23 | } 24 | } 25 | 26 | pub fn igvmbuilder(&self, args: &Args, cmd_feats: &mut Features) -> &PathBuf { 27 | self.igvmbuilder.get_or_init(|| { 28 | Component::new_default("igvmbuilder") 29 | .build(args, BuildTarget::Host, cmd_feats) 30 | .expect("failed to build igvmbuilder") 31 | }) 32 | } 33 | 34 | pub fn igvmmeasure(&self, args: &Args, cmd_feats: &mut Features) -> &PathBuf { 35 | self.igvmmeasure.get_or_init(|| { 36 | Component::new_default("igvmmeasure") 37 | .build(args, BuildTarget::Host, cmd_feats) 38 | .expect("failed to build igvmmeasure") 39 | }) 40 | } 41 | 42 | pub fn packit(&self, args: &Args, cmd_feats: &mut Features) -> &PathBuf { 43 | self.packit.get_or_init(|| { 44 | Component::new( 45 | "packit", 46 | ComponentConfig { 47 | features: Some("cli".into()), 48 | ..Default::default() 49 | }, 50 | ) 51 | .build(args, BuildTarget::Host, cmd_feats) 52 | .expect("failed to build packit") 53 | }) 54 | } 55 | } 56 | 57 | pub static HELPERS: Helpers = Helpers::new(); 58 | -------------------------------------------------------------------------------- /kernel/src/tdx/error.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Jon Lange 6 | 7 | use crate::error::SvsmError; 8 | 9 | #[derive(Clone, Copy, Debug, PartialEq)] 10 | pub enum TdxSuccess { 11 | Success, 12 | PageAlreadyAccepted, 13 | Unknown(u64), 14 | } 15 | 16 | #[derive(Clone, Copy, Debug, PartialEq)] 17 | pub enum TdxError { 18 | OperandInvalid, 19 | NoVeInfo, 20 | PageSizeMismatch, 21 | Unimplemented, 22 | Vmcall(TdVmcallError), 23 | Unknown(u64), 24 | } 25 | 26 | #[derive(Clone, Copy, Debug, PartialEq)] 27 | pub enum TdVmcallError { 28 | OperandInvalid, 29 | Retry, 30 | Unknown(u64), 31 | } 32 | 33 | impl From for SvsmError { 34 | fn from(err: TdxError) -> SvsmError { 35 | SvsmError::Tdx(err) 36 | } 37 | } 38 | 39 | pub fn tdx_result(err: u64) -> Result { 40 | let code = err >> 32; 41 | if code < 0x8000_0000 { 42 | match code { 43 | 0 => Ok(TdxSuccess::Success), 44 | 0x0000_0B0A => Ok(TdxSuccess::PageAlreadyAccepted), 45 | _ => Ok(TdxSuccess::Unknown(err)), 46 | } 47 | } else { 48 | match code { 49 | 0xC000_0100 => Err(TdxError::OperandInvalid), 50 | 0xC000_0704 => Err(TdxError::NoVeInfo), 51 | 0xC000_0B0B => Err(TdxError::PageSizeMismatch), 52 | _ => Err(TdxError::Unknown(err)), 53 | } 54 | } 55 | } 56 | 57 | pub fn tdx_recoverable_error(err: u64) -> bool { 58 | // Bit 63: ERROR 59 | // Bit 62: NON_RECOVERABLE 60 | (err >> 62) == 2 61 | } 62 | 63 | pub fn tdvmcall_result(err: u64) -> Result<(), TdxError> { 64 | match err { 65 | 0 => Ok(()), 66 | 1 => Err(TdxError::Vmcall(TdVmcallError::Retry)), 67 | 0x8000_0000_0000_0000 => Err(TdxError::Vmcall(TdVmcallError::OperandInvalid)), 68 | _ => Err(TdxError::Vmcall(TdVmcallError::Unknown(err))), 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /xbuild/src/fw.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Author: Carlos López 4 | 5 | use crate::{run_cmd_checked, Args, BuildResult}; 6 | use serde::Deserialize; 7 | use std::env::{self, VarError}; 8 | use std::path::PathBuf; 9 | use std::process::Command; 10 | 11 | /// Guest firmware build configuration 12 | #[derive(Clone, Debug, Deserialize, Default)] 13 | pub struct FirmwareConfig { 14 | env: Option, 15 | file: Option, 16 | command: Option>, 17 | } 18 | 19 | impl FirmwareConfig { 20 | fn run_command(&self, args: &Args) -> BuildResult<()> { 21 | let Some(command) = self.command.as_ref() else { 22 | return Ok(()); 23 | }; 24 | if args.verbose { 25 | println!("{:?}", command); 26 | } 27 | let prog = command.first().ok_or("firmware: empty command")?; 28 | let mut cmd = Command::new(prog); 29 | if let Some(args) = command.get(1..) { 30 | cmd.args(args); 31 | } 32 | run_cmd_checked(cmd, args) 33 | } 34 | 35 | /// Builds the firmware image based on the parsed configuration 36 | /// and returns the path to the image, if any. 37 | pub fn build(&self, args: &Args) -> BuildResult> { 38 | // If the config specifies a command, run it 39 | self.run_command(args)?; 40 | 41 | // If the config specifies a file, that's the output 42 | if let Some(file) = self.file.as_ref() { 43 | return Ok(Some(file.into())); 44 | } 45 | 46 | // If the config specifies an environment variable, return 47 | // its contents. 48 | let Some(env) = self.env.as_ref() else { 49 | return Ok(None); 50 | }; 51 | 52 | match env::var(env) { 53 | Ok(val) => Ok(Some(val.into())), 54 | Err(VarError::NotPresent) => Ok(None), 55 | Err(e) => Err(format!("{env}: {e}").into()), 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /fuzz/fuzz_targets/acpi.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2023 SUSE LLC 4 | // 5 | // Author: Carlos López 6 | 7 | #![no_main] 8 | 9 | use core::num::NonZeroUsize; 10 | use core::sync::atomic::{AtomicUsize, Ordering}; 11 | use libfuzzer_sys::{fuzz_target, Corpus}; 12 | use std::hint::black_box; 13 | use svsm::acpi::tables::load_fw_cpu_info; 14 | use svsm::fw_cfg::FwCfg; 15 | use svsm::io::IOPort; 16 | 17 | /// A structure that emulates port I/O from a libfuzzer input. 18 | #[derive(Debug)] 19 | struct FuzzIo<'a> { 20 | data: &'a [u8], 21 | len: NonZeroUsize, 22 | pos: AtomicUsize, 23 | } 24 | 25 | impl<'a> FuzzIo<'a> { 26 | /// Create a new [`FuzzIo`] instance. Returns [`None`] if the input is 27 | /// empty. 28 | fn new(data: &'a [u8]) -> Option { 29 | let len = NonZeroUsize::new(data.len())?; 30 | let pos = AtomicUsize::new(0); 31 | Some(Self { data, len, pos }) 32 | } 33 | } 34 | 35 | impl IOPort for FuzzIo<'_> { 36 | fn outb(&self, _port: u16, _value: u8) {} 37 | fn outw(&self, _port: u16, _value: u16) {} 38 | 39 | fn inb(&self, _port: u16) -> u8 { 40 | let pos = self.pos.load(Ordering::Relaxed); 41 | // SAFETY: we always keep `pos` within bounds by using the 42 | // modulo operation before updating it. 43 | let val = unsafe { *self.data.get_unchecked(pos) }; 44 | self.pos.store((pos + 1) % self.len, Ordering::Relaxed); 45 | val 46 | } 47 | 48 | fn inw(&self, port: u16) -> u16 { 49 | let mut buf = [0u8; 2]; 50 | buf[0] = self.inb(port); 51 | buf[1] = self.inb(port); 52 | u16::from_le_bytes(buf) 53 | } 54 | } 55 | 56 | fuzz_target!(|data: &[u8]| -> Corpus { 57 | let Some(io) = FuzzIo::new(data) else { 58 | return Corpus::Reject; 59 | }; 60 | let fwcfg = FwCfg::new(&io); 61 | 62 | if let Ok(info) = load_fw_cpu_info(&fwcfg) { 63 | let _ = black_box(info); 64 | } 65 | 66 | Corpus::Keep 67 | }); 68 | -------------------------------------------------------------------------------- /kernel/src/mm/address_space.verus.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Ziqiao Zhou 6 | // 7 | // This module defines specification helper functions to verify the correct use of memory. 8 | // 9 | // Trusted Assumptions: 10 | // - hw_spec::SpecMemMapTr is correct 11 | // Proofs: 12 | // - FixedAddressMappingRange is viewed as LinearMap 13 | // - LinearMap satisfies all properties in hw_spec::SpecMemMapTr 14 | use verify_external::hw_spec::SpecMemMapTr; 15 | use vstd::std_specs::convert::FromSpec; 16 | 17 | use crate::address::VADDR_RANGE_SIZE; 18 | 19 | mod address_space_spec { 20 | use super::*; 21 | include!("address_space_spec.verus.rs"); 22 | } 23 | 24 | pub use address_space_spec::LinearMap; 25 | 26 | verus! { 27 | 28 | impl FixedAddressMappingRange { 29 | pub closed spec fn view(&self) -> LinearMap { 30 | LinearMap::spec_new(self.virt_start, self.virt_end, self.phys_start) 31 | } 32 | 33 | pub open spec fn req_new( 34 | virt_start: VirtAddr, 35 | virt_end: VirtAddr, 36 | phys_start: PhysAddr, 37 | ) -> bool { 38 | &&& virt_start@ % crate::types::PAGE_SIZE == phys_start@ % crate::types::PAGE_SIZE 39 | &&& virt_end@ > virt_start@ 40 | &&& virt_end@ - virt_start@ + phys_start@ < usize::MAX + 1 41 | } 42 | 43 | #[verifier::type_invariant] 44 | pub closed spec fn wf(&self) -> bool { 45 | &&& Self::req_new(self.virt_start, self.virt_end, self.phys_start) 46 | } 47 | 48 | pub proof fn use_type_invariant(tracked &self) 49 | ensures 50 | self@.wf(), 51 | self.wf(), 52 | { 53 | broadcast use verify_proof::bits::lemma_bit_usize_shl_values; 54 | 55 | use_type_invariant(self); 56 | use_type_invariant(self.virt_start); 57 | use_type_invariant(self.virt_end); 58 | assert(crate::address::VADDR_UPPER_MASK == 0xffff_8000_0000_0000) by (compute); 59 | reveal(LinearMap::wf_virt_phy_page); 60 | } 61 | } 62 | 63 | } // verus! 64 | -------------------------------------------------------------------------------- /libaproxy/src/lib.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2024 Red Hat, Inc 4 | // 5 | // Author: Stefano Garzarella 6 | // Author: Tyler Fanelli 7 | 8 | #![no_std] 9 | 10 | extern crate alloc; 11 | 12 | mod attestation; 13 | mod negotiation; 14 | 15 | pub use attestation::*; 16 | pub use negotiation::*; 17 | 18 | use alloc::{string::String, vec::Vec}; 19 | use base64::{prelude::BASE64_STANDARD, Engine}; 20 | use serde::Deserialize; 21 | 22 | #[derive(Debug)] 23 | pub enum Error { 24 | InvalidKeyType, 25 | KeyParamDecode(base64::DecodeError), 26 | InvalidParams, 27 | } 28 | 29 | fn serialize_base64(sub: &Vec, serializer: S) -> core::result::Result 30 | where 31 | S: serde::Serializer, 32 | { 33 | let encoded = BASE64_STANDARD.encode(sub); 34 | serializer.serialize_str(&encoded) 35 | } 36 | 37 | fn deserialize_base64<'de, D>(deserializer: D) -> core::result::Result, D::Error> 38 | where 39 | D: serde::Deserializer<'de>, 40 | { 41 | let encoded = String::deserialize(deserializer)?; 42 | let decoded = BASE64_STANDARD 43 | .decode(encoded) 44 | .map_err(serde::de::Error::custom)?; 45 | 46 | Ok(decoded) 47 | } 48 | 49 | fn serialize_base64_option( 50 | sub: &Option>, 51 | serializer: S, 52 | ) -> core::result::Result 53 | where 54 | S: serde::Serializer, 55 | { 56 | match sub { 57 | Some(value) => { 58 | let encoded = BASE64_STANDARD.encode(value); 59 | serializer.serialize_str(&encoded) 60 | } 61 | None => serializer.serialize_none(), 62 | } 63 | } 64 | 65 | fn deserialize_base64_option<'de, D>( 66 | deserializer: D, 67 | ) -> core::result::Result>, D::Error> 68 | where 69 | D: serde::Deserializer<'de>, 70 | { 71 | let encoded = String::deserialize(deserializer)?; 72 | 73 | let decoded = BASE64_STANDARD 74 | .decode(encoded) 75 | .map_err(serde::de::Error::custom)?; 76 | 77 | Ok(Some(decoded)) 78 | } 79 | -------------------------------------------------------------------------------- /tools/igvmbuilder/src/paging.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2024 Microsoft Corporation 4 | // 5 | // Author: Jon Lange 6 | 7 | use igvm::IgvmDirectiveHeader; 8 | use igvm_defs::{IgvmPageDataFlags, IgvmPageDataType, PAGE_SIZE_4K}; 9 | 10 | use zerocopy::{Immutable, IntoBytes}; 11 | 12 | #[derive(Clone, Copy, Immutable, IntoBytes)] 13 | struct PageTablePage { 14 | ptes: [u64; 512], 15 | } 16 | 17 | #[derive(Clone, Copy, Default)] 18 | struct InitPageTables { 19 | pages: [PageTablePage; 2], 20 | } 21 | 22 | impl Default for PageTablePage { 23 | fn default() -> Self { 24 | Self { ptes: [0; 512] } 25 | } 26 | } 27 | 28 | pub fn construct_init_page_tables( 29 | init_page_table_gpa: u64, 30 | compatibility_mask: u32, 31 | directives: &mut Vec, 32 | ) { 33 | let mut page_tables: InitPageTables = InitPageTables::default(); 34 | 35 | // The initial page tables comprise a single PML4E that points to a page 36 | // that includes entries which map the low 4 GB of the address space 37 | // with an identity map of 1 GB pages. 38 | // This PML4E is present, writable, accessed, and dirty. 39 | page_tables.pages[0].ptes[0] = 0x63 | (init_page_table_gpa + PAGE_SIZE_4K); 40 | 41 | for i in 0..4 { 42 | // This PTE is present, writable, accessed, dirty, and large page. 43 | page_tables.pages[1].ptes[i] = 0xE3 | ((i as u64) << 30); 44 | } 45 | 46 | for (i, data) in page_tables.pages.iter().enumerate() { 47 | // Allocate a byte vector to contain a copy of the initial page table 48 | // data. 49 | let mut page_table_data = Vec::::new(); 50 | page_table_data.extend_from_slice(data.as_bytes()); 51 | 52 | directives.push(IgvmDirectiveHeader::PageData { 53 | gpa: init_page_table_gpa + (i as u64) * PAGE_SIZE_4K, 54 | compatibility_mask, 55 | flags: IgvmPageDataFlags::new(), 56 | data_type: IgvmPageDataType::NORMAL, 57 | data: page_table_data, 58 | }); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /kernel/src/sev/tlb.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2022-2023 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | 7 | use crate::address::{Address, VirtAddr}; 8 | use crate::cpu::tlb::TlbFlushScope; 9 | 10 | use core::arch::asm; 11 | 12 | const INVLPGB_VALID_VA: u64 = 1u64 << 0; 13 | //const INVLPGB_VALID_PCID: u64 = 1u64 << 1; 14 | const INVLPGB_VALID_ASID: u64 = 1u64 << 2; 15 | const INVLPGB_VALID_GLOBAL: u64 = 1u64 << 3; 16 | 17 | #[inline] 18 | fn do_invlpgb(rax: u64, rcx: u64, rdx: u64) { 19 | // SAFETY: Inline assembly to invalidate TLB Entries, which does not change 20 | // any state related to memory safety. 21 | unsafe { 22 | asm!("invlpgb", 23 | in("rax") rax, 24 | in("rcx") rcx, 25 | in("rdx") rdx, 26 | options(att_syntax)); 27 | } 28 | } 29 | 30 | #[inline] 31 | fn do_tlbsync() { 32 | // SAFETY: Inline assembly to synchronize TLB invalidations. It does not 33 | // change any state. 34 | unsafe { 35 | asm!("tlbsync", options(att_syntax)); 36 | } 37 | } 38 | 39 | pub fn flush_tlb() { 40 | let rax: u64 = INVLPGB_VALID_ASID; 41 | do_invlpgb(rax, 0, 0); 42 | } 43 | 44 | pub fn flush_tlb_sync() { 45 | flush_tlb(); 46 | do_tlbsync(); 47 | } 48 | 49 | pub fn flush_tlb_global() { 50 | let rax: u64 = INVLPGB_VALID_ASID | INVLPGB_VALID_GLOBAL; 51 | do_invlpgb(rax, 0, 0); 52 | } 53 | 54 | pub fn flush_tlb_global_sync() { 55 | flush_tlb_global(); 56 | do_tlbsync(); 57 | } 58 | 59 | pub fn flush_address(va: VirtAddr) { 60 | let rax: u64 = (va.page_align().bits() as u64) 61 | | INVLPGB_VALID_VA 62 | | INVLPGB_VALID_ASID 63 | | INVLPGB_VALID_GLOBAL; 64 | do_invlpgb(rax, 0, 0); 65 | } 66 | 67 | pub fn flush_address_sync(va: VirtAddr) { 68 | flush_address(va); 69 | do_tlbsync(); 70 | } 71 | 72 | pub fn flush_tlb_scope(flush_scope: &TlbFlushScope) { 73 | match flush_scope { 74 | TlbFlushScope::AllGlobal => flush_tlb_global_sync(), 75 | TlbFlushScope::AllNonGlobal => flush_tlb_sync(), 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /tools/igvmbuilder/README.md: -------------------------------------------------------------------------------- 1 | # IGVMBuilder 2 | A tool to build IGVM files that describe the configuration of a guest that 3 | includes coconut SVSM along with firmware such as OVMF. 4 | 5 | The IGVM format allows a guest to be configured regardless of the virtualization 6 | stack it will be running on. An IGVM file includes an ordered list of directives 7 | that define the memory layout, initial CPU state and location and content of 8 | binary images including firmware and SVSM. This allows the configuration of the 9 | guest to be fixed at build time which, when working with trusted execution 10 | environments such as AMD SEV-SNP or Intel TDX, can allow for pre-calculation of 11 | a launch measurement that can be verified by hardware. 12 | 13 | The IGVMBuilder currently creates IGVM files that are suitable for launching 14 | SEV-SNP guests on QEMU/KVM and Hyper-V including coconut SVSM with or without 15 | firmware - OVMF on QEMU and IGVM-based firmware on Hyper-V. 16 | 17 | 18 | ## Usage 19 | `igvmbuilder [OPTIONS] --stage2 --kernel --output ` 20 | 21 | ### Arguments: 22 | ``` 23 | 24 | Hypervisor to generate IGVM file for 25 | 26 | Possible values: 27 | - qemu: Build an IGVM file compatible with QEMU 28 | - hyper-v: Build an IGVM file compatible with Hyper-V 29 | ``` 30 | 31 | ### Options: 32 | ``` 33 | -s, --stage2 34 | Stage 2 binary file 35 | 36 | -k, --kernel 37 | Kernel elf file 38 | 39 | --filesystem 40 | Optional filesystem image 41 | 42 | -f, --firmware 43 | Optional firmware file, e.g. OVMF.fd 44 | 45 | -o, --output 46 | Output filename for the generated IGVM file 47 | 48 | -c, --comport 49 | COM port to use for the SVSM console. Valid values are 1-4 50 | [default: 1] 51 | 52 | -v, --verbose 53 | Print verbose output 54 | 55 | --sort 56 | Sort the IGVM Page directives by GPA from lowest to highest 57 | 58 | --policy 59 | A hex value containing the guest policy to apply. For example: 0x30000 60 | 61 | -h, --help 62 | Print help (see a summary with '-h') 63 | ``` 64 | -------------------------------------------------------------------------------- /kernel/src/hyperv/mod.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Jon Lange (jlange@microsoft.com) 6 | 7 | pub mod hv; 8 | pub mod msr; 9 | 10 | pub use hv::*; 11 | pub use msr::*; 12 | 13 | use bitfield_struct::bitfield; 14 | use zerocopy::{Immutable, IntoBytes}; 15 | 16 | #[bitfield(u8)] 17 | #[derive(IntoBytes, Immutable)] 18 | pub struct HvInputVtl { 19 | #[bits(4)] 20 | target_vtl: u8, 21 | use_target_vtl: bool, 22 | #[bits(3)] 23 | _rsvd_5_7: u8, 24 | } 25 | 26 | impl HvInputVtl { 27 | pub fn use_self() -> Self { 28 | Self::new() 29 | } 30 | 31 | pub fn use_vtl(vtl: u8) -> Self { 32 | Self::new().with_target_vtl(vtl).with_use_target_vtl(true) 33 | } 34 | } 35 | 36 | #[repr(C)] 37 | #[derive(Clone, Copy, Debug, Default, IntoBytes, Immutable)] 38 | pub struct HvSegmentRegister { 39 | pub base: u64, 40 | pub limit: u32, 41 | pub selector: u16, 42 | pub attributes: u16, 43 | } 44 | 45 | #[repr(C)] 46 | #[derive(Clone, Copy, Debug, Default, IntoBytes, Immutable)] 47 | pub struct HvTableRegister { 48 | pub _rsvd: [u16; 3], 49 | pub limit: u16, 50 | pub base: u64, 51 | } 52 | 53 | #[repr(C)] 54 | #[derive(Clone, Copy, Debug, Default, IntoBytes, Immutable)] 55 | pub struct HvInitialVpContext { 56 | pub rip: u64, 57 | pub rsp: u64, 58 | pub rflags: u64, 59 | pub cs: HvSegmentRegister, 60 | pub ds: HvSegmentRegister, 61 | pub es: HvSegmentRegister, 62 | pub fs: HvSegmentRegister, 63 | pub gs: HvSegmentRegister, 64 | pub ss: HvSegmentRegister, 65 | pub tr: HvSegmentRegister, 66 | pub ldtr: HvSegmentRegister, 67 | pub idtr: HvTableRegister, 68 | pub gdtr: HvTableRegister, 69 | pub efer: u64, 70 | pub cr0: u64, 71 | pub cr3: u64, 72 | pub cr4: u64, 73 | pub pat: u64, 74 | } 75 | 76 | #[repr(u32)] 77 | #[derive(Clone, Copy, Debug)] 78 | pub enum HvRegisterName { 79 | VsmVpStatus = 0xD0003, 80 | } 81 | 82 | #[bitfield(u64)] 83 | pub struct HvRegisterVsmVpStatus { 84 | #[bits(4)] 85 | pub active_vtl: u8, 86 | pub active_mbec_enabled: bool, 87 | #[bits(11)] 88 | _rsvd_5_15: u64, 89 | pub enabled_vtl_set: u16, 90 | _rsvd_32_63: u32, 91 | } 92 | -------------------------------------------------------------------------------- /kernel/src/fs/init.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2023 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | 7 | use crate::address::{Address, PhysAddr}; 8 | use crate::error::SvsmError; 9 | use crate::mm::ptguards::PerCPUPageMappingGuard; 10 | use packit::PackItArchiveDecoder; 11 | 12 | use super::*; 13 | 14 | extern crate alloc; 15 | use alloc::slice; 16 | 17 | /// Used to create a SVSM RAM filesystem from a filesystem archive. 18 | /// 19 | /// # Arguments 20 | /// 21 | /// - `kernel_fs_start`: denotes the physical address at which the archive starts. 22 | /// - `kernel_fs_end`: denotes the physical address at which the archive ends. 23 | /// 24 | /// # Assertion 25 | /// 26 | /// asserts if `kernel_fs_end` is greater than or equal to `kernel_fs_start`. 27 | /// 28 | /// # Returns 29 | /// [`Result<(), SvsmError>`]: A [`Result`] containing the unit value if successful, 30 | /// [`SvsmError`] otherwise. 31 | pub fn populate_ram_fs(kernel_fs_start: u64, kernel_fs_end: u64) -> Result<(), SvsmError> { 32 | assert!(kernel_fs_end >= kernel_fs_start); 33 | 34 | let pstart = PhysAddr::from(kernel_fs_start); 35 | let pend = PhysAddr::from(kernel_fs_end); 36 | let size = pend - pstart; 37 | 38 | if size == 0 { 39 | return Ok(()); 40 | } 41 | 42 | log::info!("Unpacking FS archive..."); 43 | 44 | let guard = PerCPUPageMappingGuard::create(pstart.page_align(), pend.page_align_up(), 0)?; 45 | let vstart = guard.virt_addr() + pstart.page_offset(); 46 | 47 | // SAFETY: `vstart` is just mapped and the mapping covers the entire `size` 48 | let data: &[u8] = unsafe { slice::from_raw_parts(vstart.as_ptr(), size) }; 49 | let archive = PackItArchiveDecoder::load(data)?; 50 | 51 | for file in archive { 52 | let file = file?; 53 | let handle = create_all(file.name())?; 54 | handle.truncate(0)?; 55 | let written = handle.write(file.data())?; 56 | if written != file.data().len() { 57 | log::error!("Incomplete data write to {}", file.name()); 58 | return Err(SvsmError::FileSystem(FsError::inval())); 59 | } 60 | 61 | log::info!(" Unpacked {}", file.name()); 62 | } 63 | 64 | log::info!("Unpacking done"); 65 | 66 | Ok(()) 67 | } 68 | -------------------------------------------------------------------------------- /libtcgtpm/deps/libcrt/src/time/__secs_to_tm.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: MIT */ 2 | 3 | #include 4 | #include 5 | 6 | /* 2000-03-01 (mod 400 year, immediately after feb29 */ 7 | #define LEAPOCH (946684800LL + 86400*(31+29)) 8 | 9 | #define DAYS_PER_400Y (365*400 + 97) 10 | #define DAYS_PER_100Y (365*100 + 24) 11 | #define DAYS_PER_4Y (365*4 + 1) 12 | 13 | int __secs_to_tm(long long t, struct tm *tm) 14 | { 15 | long long days, secs, years; 16 | int remdays, remsecs, remyears; 17 | int qc_cycles, c_cycles, q_cycles; 18 | int months; 19 | int wday, yday, leap; 20 | static const char days_in_month[] = {31,30,31,30,31,31,30,31,30,31,31,29}; 21 | 22 | /* Reject time_t values whose year would overflow int */ 23 | if (t < INT_MIN * 31622400LL || t > INT_MAX * 31622400LL) 24 | return -1; 25 | 26 | secs = t - LEAPOCH; 27 | days = secs / 86400; 28 | remsecs = secs % 86400; 29 | if (remsecs < 0) { 30 | remsecs += 86400; 31 | days--; 32 | } 33 | 34 | wday = (3+days)%7; 35 | if (wday < 0) wday += 7; 36 | 37 | qc_cycles = days / DAYS_PER_400Y; 38 | remdays = days % DAYS_PER_400Y; 39 | if (remdays < 0) { 40 | remdays += DAYS_PER_400Y; 41 | qc_cycles--; 42 | } 43 | 44 | c_cycles = remdays / DAYS_PER_100Y; 45 | if (c_cycles == 4) c_cycles--; 46 | remdays -= c_cycles * DAYS_PER_100Y; 47 | 48 | q_cycles = remdays / DAYS_PER_4Y; 49 | if (q_cycles == 25) q_cycles--; 50 | remdays -= q_cycles * DAYS_PER_4Y; 51 | 52 | remyears = remdays / 365; 53 | if (remyears == 4) remyears--; 54 | remdays -= remyears * 365; 55 | 56 | leap = !remyears && (q_cycles || !c_cycles); 57 | yday = remdays + 31 + 28 + leap; 58 | if (yday >= 365+leap) yday -= 365+leap; 59 | 60 | years = remyears + 4*q_cycles + 100*c_cycles + 400LL*qc_cycles; 61 | 62 | for (months=0; days_in_month[months] <= remdays; months++) 63 | remdays -= days_in_month[months]; 64 | 65 | if (months >= 10) { 66 | months -= 12; 67 | years++; 68 | } 69 | 70 | if (years+100 > INT_MAX || years+100 < INT_MIN) 71 | return -1; 72 | 73 | tm->tm_year = years + 100; 74 | tm->tm_mon = months + 2; 75 | tm->tm_mday = remdays + 1; 76 | tm->tm_wday = wday; 77 | tm->tm_yday = yday; 78 | 79 | tm->tm_hour = remsecs / 3600; 80 | tm->tm_min = remsecs / 60 % 60; 81 | tm->tm_sec = remsecs % 60; 82 | 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /scripts/check-signed-off.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # SPDX-License-Identifier: MIT OR Apache-2.0 3 | # 4 | # Copyright (c) 2023 SUSE LLC 5 | # 6 | # Author: Carlos López 7 | # 8 | # Simple script to check that a commit has a Signed-off-by trailer and a 9 | # nonempty commit body. 10 | 11 | matches_any() { 12 | needle=$1 13 | haystack=$2 14 | 15 | while IFS= read -r item; do 16 | if [ "$needle" = "$item" ]; then 17 | return 0 18 | fi 19 | done < <(printf '%s\n' "$haystack") 20 | 21 | return 1 22 | } 23 | 24 | # Check that the body for the given commit is not empty 25 | nonempty_body() { 26 | body=$(git show --no-patch --format="%b" "$1" | sed '/^ *$/d') 27 | trailers=$(git show --no-patch --format="%(trailers:only)" "$1") 28 | 29 | body_len=$(echo "$body" | wc -l) 30 | trailer_len=$(echo "$trailers" | wc -l) 31 | 32 | # If the body is the same length as the trailers it means the body is empty 33 | [ "$body_len" = "$trailer_len" ] && return 1 34 | return 0 35 | } 36 | 37 | if [ $# -lt 1 ]; then 38 | echo "Usage: $0 []" 39 | exit 1 40 | fi 41 | 42 | start=$1 43 | end=$2 44 | 45 | commits=$(git log --no-merges "${start}".."${end}" --format="%H") 46 | for c in ${commits[@]}; do 47 | 48 | echo "Checking $c" 49 | 50 | nonempty_body "$c" 51 | if [ "$?" != "0" ]; then 52 | echo "Message body is empty for commit $c" 53 | exit 1 54 | fi 55 | 56 | commit_email=$(git show --no-patch --format="%ae" "$c" || exit 1) 57 | commit_name=$(git show --no-patch --format="%an" "$c" || exit 1) 58 | sign_names=$(git show --no-patch "$c" | sed -nr 's/^[[:space:]]*Signed-off-by: (.*) <(.*)>/\1/p' || exit 1) 59 | sign_emails=$(git show --no-patch "$c" | sed -nr 's/^[[:space:]]*Signed-off-by: (.*) <(.*)>/\2/p' || exit 1) 60 | 61 | matches_any "$commit_name" "$sign_names" 62 | if [ "$?" != "0" ]; then 63 | echo "Author name mismatch on commit $c" 64 | echo " Commit author name: $commit_name" 65 | echo " Signed-off-by name(s):" $sign_names 66 | exit 1 67 | fi 68 | 69 | matches_any "$commit_email" "$sign_emails" 70 | if [ "$?" != "0" ]; then 71 | echo "Author email mismatch on commit $c" 72 | echo " Commit author email: $commit_email" 73 | echo " Signed-off-by email(s):" $sign_emails 74 | exit 1 75 | fi 76 | 77 | done 78 | 79 | exit 0 80 | -------------------------------------------------------------------------------- /xbuild/src/features.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // 3 | // Copyright (c) 2025 AMD Inc. 4 | // 5 | // Author: Joerg Roedel 6 | 7 | use crate::Args; 8 | use std::string::String; 9 | 10 | #[derive(Debug)] 11 | pub struct CmdLineFeature { 12 | raw: String, 13 | pkg: String, 14 | feat: String, 15 | consumed: bool, 16 | } 17 | 18 | impl CmdLineFeature { 19 | pub fn create_from_raw(raw: String) -> Self { 20 | let spec = raw.clone(); 21 | let (pkg, feat) = if let Some((p, f)) = spec.split_once(':') { 22 | (p, f) 23 | } else { 24 | ("svsm", spec.trim()) 25 | }; 26 | 27 | Self { 28 | raw, 29 | pkg: String::from(pkg.trim()), 30 | feat: String::from(feat.trim()), 31 | consumed: false, 32 | } 33 | } 34 | 35 | pub fn consume(&mut self) { 36 | self.consumed = true; 37 | } 38 | 39 | pub fn was_consumed(&self) -> bool { 40 | self.consumed 41 | } 42 | } 43 | 44 | #[derive(Debug)] 45 | pub struct Features { 46 | list: Vec, 47 | } 48 | 49 | impl Features { 50 | pub fn create_from_args(args: &Args) -> Self { 51 | let list = args 52 | .features 53 | .iter() 54 | .map(|f| CmdLineFeature::create_from_raw(String::from(f))) 55 | .collect(); 56 | Self { list } 57 | } 58 | 59 | pub fn print_empty_features(&self) { 60 | for f in &self.list { 61 | if f.feat.is_empty() { 62 | eprintln!("WARNING: Empty feature specified: '{}'", f.raw); 63 | } 64 | } 65 | } 66 | 67 | pub fn print_unused_features(&self) { 68 | for f in &self.list { 69 | if !f.was_consumed() { 70 | eprintln!("WARNING: Command line feature not used: '{}'", f.raw); 71 | } 72 | } 73 | } 74 | 75 | pub fn feature_list(&mut self, pkg: &str) -> Vec { 76 | self.list 77 | .iter_mut() 78 | .filter_map(|f| { 79 | if f.pkg == pkg { 80 | f.consume(); 81 | Some(f.feat.clone()) 82 | } else { 83 | None 84 | } 85 | }) 86 | .collect() 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | check: 14 | name: Check 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v3 19 | with: 20 | submodules: recursive 21 | 22 | - name: Install rust toolchain 23 | run: rustup toolchain install --profile minimal 24 | 25 | - name: Add rust components 26 | run: rustup component add rustfmt rust-src clippy 27 | 28 | - name: Check that Cargo.lock is up to date. 29 | run: cargo update --workspace --locked 30 | 31 | - name: Install TPM 2.0 Reference Implementation build dependencies 32 | run: sudo apt install -y build-essential cmake pkg-config 33 | 34 | - name: Build (non-test) debug images 35 | run: cargo xbuild ./configs/*.json 36 | 37 | - name: Build (non-test) debug images with all features 38 | run: cargo xbuild --all-features ./configs/*.json 39 | 40 | - name: Build (non-test) release images 41 | run: cargo xbuild --release ./configs/*.json 42 | 43 | - name: Run tests 44 | run: make test 45 | 46 | - name: Run tests on release image 47 | run: make test RELEASE=1 48 | 49 | - name: Format 50 | run: cargo fmt --all -- --check 51 | 52 | - name: Clippy 53 | run: make clippy 54 | 55 | - name: Check documentation 56 | run: make doc 57 | env: 58 | RUSTDOCFLAGS: -D warnings 59 | 60 | nightly-check: 61 | runs-on: ubuntu-latest 62 | continue-on-error: true 63 | steps: 64 | - name: Checkout 65 | uses: actions/checkout@v3 66 | with: 67 | submodules: recursive 68 | 69 | - name: Install latest nightly 70 | run: rustup toolchain install nightly -t x86_64-unknown-none --profile minimal --force -c rustfmt 71 | 72 | # release/src/git_version.rs is auto-generated via a build.rs file. Touch 73 | # it here to avoid CI failures. 74 | - name: Touch release/src/git_version.rs 75 | run: echo "" > release/src/git_version.rs 76 | 77 | - name: Format doctests 78 | run: cargo +nightly fmt --all -- --check --config "format_code_in_doc_comments=true" 79 | -------------------------------------------------------------------------------- /kernel/src/cpu/registers.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2022-2023 SUSE LLC 4 | // 5 | // Author: Roy Hopkins 6 | 7 | use bitflags::bitflags; 8 | 9 | #[repr(C, packed)] 10 | #[derive(Default, Debug, Clone, Copy)] 11 | pub struct X86GeneralRegs { 12 | pub r15: usize, 13 | pub r14: usize, 14 | pub r13: usize, 15 | pub r12: usize, 16 | pub r11: usize, 17 | pub r10: usize, 18 | pub r9: usize, 19 | pub r8: usize, 20 | pub rbp: usize, 21 | pub rdi: usize, 22 | pub rsi: usize, 23 | pub rdx: usize, 24 | pub rcx: usize, 25 | pub rbx: usize, 26 | pub rax: usize, 27 | } 28 | 29 | #[repr(C, packed)] 30 | #[derive(Default, Debug, Clone, Copy)] 31 | pub struct X86SegmentRegs { 32 | pub cs: usize, 33 | pub ds: usize, 34 | pub es: usize, 35 | pub fs: usize, 36 | pub gs: usize, 37 | pub ss: usize, 38 | } 39 | 40 | #[repr(C, packed)] 41 | #[derive(Default, Debug, Clone, Copy)] 42 | pub struct X86InterruptFrame { 43 | pub rip: usize, 44 | pub cs: usize, 45 | pub flags: usize, 46 | pub rsp: usize, 47 | pub ss: usize, 48 | } 49 | 50 | bitflags! { 51 | #[derive(Copy, Clone, Debug, PartialEq)] 52 | pub struct SegDescAttrFlags: u64 { 53 | const A = 1 << 40; 54 | const R_W = 1 << 41; 55 | const C_E = 1 << 42; 56 | const C_D = 1 << 43; 57 | const S = 1 << 44; 58 | const AVL = 1 << 52; 59 | const L = 1 << 53; 60 | const DB = 1 << 54; 61 | const G = 1 << 55; 62 | } 63 | } 64 | 65 | bitflags! { 66 | #[derive(Clone, Copy, Debug)] 67 | pub struct RFlags: usize { 68 | const CF = 1 << 0; 69 | const FIXED = 1 << 1; 70 | const PF = 1 << 2; 71 | const AF = 1 << 4; 72 | const ZF = 1 << 6; 73 | const SF = 1 << 7; 74 | const TF = 1 << 8; 75 | const IF = 1 << 9; 76 | const DF = 1 << 10; 77 | const OF = 1 << 11; 78 | const IOPL = 3 << 12; 79 | const NT = 1 << 14; 80 | const MD = 1 << 15; 81 | const RF = 1 << 16; 82 | const VM = 1 << 17; 83 | const AC = 1 << 18; 84 | const VIF = 1 << 19; 85 | const VIP = 1 << 20; 86 | const ID = 1 << 21; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /verification/verify_external/src/ptr.verus.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) Microsoft Corporation 4 | // 5 | // Author: Ziqiao Zhou 6 | use vstd::prelude::*; 7 | use vstd::raw_ptr::*; 8 | 9 | macro_rules! pointer_specs { 10 | ($mod_ident:ident, $ptr_from_data:ident, $mu:tt) => { 11 | #[cfg(verus_keep_ghost)] 12 | mod $mod_ident { 13 | use super::*; 14 | 15 | verus!{ 16 | pub open spec fn spec_add(p: *$mu T, offset: usize) -> *$mu T { 17 | $ptr_from_data(PtrData { addr: (p@.addr + offset * size_of::()) as usize, .. p@ }) 18 | } 19 | 20 | pub open spec fn spec_wrapping_add(p: *$mu T, offset: usize) -> *$mu T { 21 | let addr = if (p@.addr + offset * size_of::()) <= usize::MAX { 22 | (p@.addr + offset * size_of::()) as usize 23 | } else { 24 | (p@.addr + offset * size_of::() - usize::MAX - 1) as usize 25 | }; 26 | $ptr_from_data(PtrData { addr, .. p@ }) 27 | } 28 | 29 | /// TODO(verus): Allow passing tracked variable to avoid all UB. 30 | /// # Safety: 31 | /// * Avoid UB due to overflow. 32 | /// * UB due to unallocated memory is only avoidable later when memory is accessed with memory permission. 33 | #[verifier::when_used_as_spec(spec_add)] 34 | pub assume_specification[<*$mu T>::add](p: *$mu T, offset: usize) -> (q: *$mu T) 35 | requires 36 | (p@.addr + offset * size_of::()) <= usize::MAX, 37 | ensures 38 | q == spec_add(p, offset) 39 | opens_invariants none 40 | no_unwind; 41 | 42 | #[verifier::when_used_as_spec(spec_wrapping_add)] 43 | pub assume_specification[<*$mu T>::wrapping_add](p: *$mu T, offset: usize) -> (q: *$mu T) 44 | returns 45 | spec_wrapping_add(p, offset) 46 | opens_invariants none 47 | no_unwind; 48 | } 49 | } 50 | }; 51 | } 52 | 53 | pointer_specs!(ptr_mut_specs, ptr_mut_from_data, mut); 54 | 55 | pointer_specs!(ptr_const_specs, ptr_from_data, const); 56 | -------------------------------------------------------------------------------- /kernel/build.rs: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT OR Apache-2.0 2 | // 3 | // Copyright (c) 2022-2023 SUSE LLC 4 | // 5 | // Author: Joerg Roedel 6 | 7 | fn main() { 8 | // Extra cfgs 9 | println!("cargo::rustc-check-cfg=cfg(fuzzing)"); 10 | println!("cargo::rustc-check-cfg=cfg(test_in_svsm)"); 11 | println!("cargo::rustc-check-cfg=cfg(verus_keep_ghost)"); 12 | println!("cargo::rustc-check-cfg=cfg(verus_keep_ghost_body)"); 13 | println!("cargo::rustc-check-cfg=cfg(verus_verify_core)"); 14 | 15 | // Stage 2 16 | println!("cargo:rustc-link-arg-bin=stage2=-nostdlib"); 17 | println!("cargo:rustc-link-arg-bin=stage2=--build-id=none"); 18 | println!("cargo:rustc-link-arg-bin=stage2=-Tkernel/src/stage2.lds"); 19 | println!("cargo:rustc-link-arg-bin=stage2=-no-pie"); 20 | 21 | // SVSM 2 22 | println!("cargo:rustc-link-arg-bin=svsm=-nostdlib"); 23 | println!("cargo:rustc-link-arg-bin=svsm=--build-id=none"); 24 | println!("cargo:rustc-link-arg-bin=svsm=--no-relax"); 25 | println!("cargo:rustc-link-arg-bin=svsm=-Tkernel/src/svsm.lds"); 26 | println!("cargo:rustc-link-arg-bin=svsm=-no-pie"); 27 | 28 | // Extra linker args for tests. 29 | println!("cargo:rerun-if-env-changed=LINK_TEST"); 30 | if std::env::var("LINK_TEST").is_ok() { 31 | println!("cargo:rustc-cfg=test_in_svsm"); 32 | println!("cargo:rustc-link-arg=-nostdlib"); 33 | println!("cargo:rustc-link-arg=--build-id=none"); 34 | println!("cargo:rustc-link-arg=--no-relax"); 35 | println!("cargo:rustc-link-arg=-Tkernel/src/svsm.lds"); 36 | println!("cargo:rustc-link-arg=-no-pie"); 37 | } 38 | 39 | println!("cargo:rerun-if-changed=kernel/src/stage2.lds"); 40 | println!("cargo:rerun-if-changed=kernel/src/svsm.lds"); 41 | println!("cargo:rerun-if-changed=build.rs"); 42 | init_verify(); 43 | } 44 | 45 | fn init_verify() { 46 | if cfg!(feature = "noverify") { 47 | println!("cargo:rustc-env=VERUS_ARGS=--no-verify"); 48 | } else { 49 | let verus_args = [ 50 | "--rlimit=1", 51 | "--expand-errors", 52 | "--multiple-errors=5", 53 | "--no-auto-recommends-check", 54 | "--trace", 55 | "-Z unstable-options", 56 | ]; 57 | println!("cargo:rustc-env=VERUS_ARGS={}", verus_args.join(" ")); 58 | } 59 | } 60 | --------------------------------------------------------------------------------