├── .gitignore ├── .gitmodules ├── README.md ├── common.sh ├── images └── create-image.sh ├── launch-opentdx.sh ├── opentdx-intel.pdf ├── scripts ├── launch-td.sh └── load-kvm.sh └── setup.sh /.gitignore: -------------------------------------------------------------------------------- 1 | kvm-* 2 | images/l* 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "qemu-l0"] 2 | path = qemu-l0 3 | url = https://github.com/sslab-gatech/tdx-qemu.git 4 | branch = opentdx-host 5 | [submodule "qemu-l1"] 6 | path = qemu-l1 7 | url = https://github.com/sslab-gatech/tdx-qemu.git 8 | branch = opentdx-guest 9 | [submodule "linux-l0"] 10 | path = linux-l0 11 | url = https://github.com/sslab-gatech/tdx-linux.git 12 | branch = opentdx-host 13 | [submodule "linux-l1"] 14 | path = linux-l1 15 | url = https://github.com/sslab-gatech/tdx-linux.git 16 | branch = opentdx-guest 17 | [submodule "linux-l2"] 18 | path = linux-l2 19 | url = https://github.com/sslab-gatech/tdx-linux.git 20 | branch = opentdx-guest 21 | [submodule "seabios"] 22 | path = seabios 23 | url = https://github.com/sslab-gatech/seabios.git 24 | branch = opentdx 25 | [submodule "seam-loader"] 26 | path = seam-loader 27 | url = https://github.com/sslab-gatech/seam-loader.git 28 | branch = opentdx-built 29 | [submodule "edk2"] 30 | path = edk2 31 | url = https://github.com/tianocore/edk2 32 | branch = edk2-stable202502 33 | [submodule "tdx-module"] 34 | path = tdx-module 35 | url = https://github.com/sslab-gatech/tdx-module.git 36 | branch = opentdx 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenTDX: Emulating TDX Machine 2 | 3 | ## Introduction 4 | 5 | OpenTDX is a TDX emulation framework on KVM, which runs TDX host kernel in L1 VM, and TDX guest kernel (i.e., TD VM) in L2 VM. 6 | With OpenTDX, researchers (and developers) can customize the TDX module, test a sotfware stack of TDX, or just play with TDX without a real TDX machine. 7 | Based on KVM, OpenTDX implements key features of TDX including Intel SMX, MKTME, SEAM. 8 | 9 | ## Directory Structure 10 | 11 | ``` 12 | open-tdx/ 13 | |- linux-l0 : Linux source for LO (i.e., baremetal) 14 | |- qemu-l0 : QEMU source to launch L1 VM (i.e., TDX host) 15 | |- seabios : Seabios source (i.e., BIOS of L1 VM) 16 | |- seam-loader : np-seamldr/p-seamldr source loaded by Seabios 17 | |- tdx-module : TDX module source 18 | | 19 | |- linux-l1 : Linux source for L1 (i.e., TDX host) 20 | |- qemu-l1 : QEMU source to launch L2 VM (i.e., TDX guest) 21 | |- edk2 : TDVF source (i.e., BIOS of L2 VM) 22 | | 23 | `- linux-l2 : Linux source for L2 (i.e., TDX guest, TD VM) 24 | ``` 25 | 26 | ## Setup & Usage 27 | Scripts are tested on Ubuntu 22.04. 28 | 29 | **Caution: running `setup.sh` installs a baremetal kernel. To avoid installing new kernel, you should manually modify KVM based on your kernel's source code.* 30 | 31 | ### Preparation 32 | ``` 33 | ./setup.sh # This updates git submodules, builds sources, and creates VM images 34 | ``` 35 | After `setup.sh` is done, please reboot using newly installed kernel, which can be selected in GRUB menu. 36 | Then, reload `kvm-intel` module with `open_tdx` parameter enabled. 37 | ``` 38 | sudo modprobe -r kvm_intel 39 | sudo modprobe kvm_intel open_tdx=1 # This may require loading other dependent modules as well 40 | ``` 41 | 42 | ### Launching TD 43 | ``` 44 | ./launch-opentdx.sh # This will launch L1 VM (i.e., TDX host) 45 | ssh -i images/l1.id_rsa -p 10032 root@localhost # ssh into L1 VM 46 | 47 | (l1-vm) $ ./scripts/load-kvm.sh 48 | (l1-vm) $ ./scripts/launch-td.sh 49 | ``` 50 | 51 | ### SSH into TD VM 52 | ``` 53 | ssh -i images/l2.id_rsa -p 10033 root@localhost 54 | ``` 55 | 56 | Running `dmesg | grep -i tdx` inside TD VM will show following messages: 57 | ``` 58 | [ 0.000000] tdx: Guest detected 59 | [ 0.000000] tdx: Attributes: SEPT_VE_DISABLE 60 | [ 0.000000] tdx: TD_CTLS: PENDING_VE_DISABLE ENUM_TOPOLOGY 61 | [ 6.497421] process: using TDX aware idle routine 62 | [ 6.497421] Memory Encryption Features active: Intel TDX 63 | ``` 64 | 65 | ### Customizing TDX Module 66 | We provide scripts for building TDX module. After modifying TDX module source, one can build it with following commands (it needs docker): 67 | ``` 68 | cd tdx-module 69 | OPENTDX=1 ./build.sh # This will output libtdx.so & libtdx.so.sigstruct under bin/debug 70 | ``` 71 | As environment variables you can give 72 | - `OPENTDX`: required to build a TDX module that runs on OpenTDX 73 | - `DEBUGTRACE`: enable logging in TDX module 74 | - `UNSTRIPPED`: output debug symbols under `bin/debug.unstripped` directory (used for loading symbol file in GDB) 75 | 76 | ## Other Tips 77 | OpenTDX contains various helper scripts for implementations and debuggins. 78 | 79 | ### Adding New Features to KVM 80 | After `setup.sh` is done, `kvm-l0`, `kvm-l1` directories are produced. Developers can directly build `kvm` modules only by running `build.sh` scripts in such directories, and reloads such modules only. 81 | 82 | ### Manuals of scripts 83 | - `common.sh` 84 | ``` 85 | Usage: ./common.sh [-t ] [-l ] [-d ] [-s ] 86 | Options: 87 | -t Specify which target to run 88 | - options: qemu, image, seabios, ovmf, tdx-module, 89 | seam-loader, linux, kernel, initrd, kvm, vm 90 | -l Specify the VM nested level 91 | - options: l0, l1 92 | -d Specify the distribution version of Debian 93 | - options: bookworm 94 | -s Specify the image size (MB) 95 | - examples: 32768 (32G) 96 | ``` 97 | - `launch-opentdx.h` 98 | ``` 99 | Usage: ./launch-opentdx.sh [-m ] [-s ] [-p ] 100 | Options: 101 | -m Specify the memory size 102 | - default: 8g 103 | -s Specify the SMP 104 | - default: 8 105 | -p Specify the ssh port for l1/l2 106 | port for l2 will be + 1 107 | - default: 10032 108 | ``` 109 | - `scripts/launch-td.h` in L1 VM 110 | ``` 111 | Usage: ./scripts/launch-td.sh [-m ] [-s ] 112 | Options: 113 | -m Specify the memory size 114 | - default: 1g 115 | -s Specify the SMP 116 | - default: 1 117 | ``` 118 | -------------------------------------------------------------------------------- /common.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | run_cmd() 4 | { 5 | echo "$*" 6 | 7 | eval "$*" || { 8 | echo "Error: $*" 9 | exit 1 10 | } 11 | } 12 | 13 | check_argument() 14 | { 15 | opt=$1 16 | arg=$2 17 | val=$3 18 | 19 | if [ -z ${val} ] 20 | then 21 | echo "Error: Please provide ${opt} <${arg}>" 22 | exit 1 23 | fi 24 | } 25 | 26 | run_mount() 27 | { 28 | local tmp=$1 29 | local img=$2 30 | 31 | [ -d ${tmp} ] && { 32 | echo "Error: ${tmp} already exist, please remove it" 33 | exit 1 34 | } 35 | mkdir -p ${tmp} 36 | 37 | run_cmd sudo mount images/${img}.img ${tmp} 38 | sleep 1 39 | } 40 | 41 | run_umount() 42 | { 43 | local tmp=$1 44 | 45 | run_cmd sudo umount ${tmp} 46 | rm -rf ${tmp} 47 | } 48 | 49 | run_chroot() 50 | { 51 | root=$1 52 | script=$2 53 | nocheck=$3 54 | 55 | sudo chroot ${root} /bin/bash -c """ 56 | set -ex 57 | ${script} 58 | exit 59 | """ 60 | if [ -z $nocheck ] && [ $? -ne 0 ]; then 61 | echo "Error: chroot failed" 62 | exit 1 63 | fi 64 | } 65 | 66 | fix_phy_bits() 67 | { 68 | [[ "$(ls -A seabios)" || "$(ls -A tdx-module)" || "$(ls -A linux-l0)" || "$(ls -A linux-l1)" ]] || { 69 | echo "Error: submodules not fetched" 70 | exit 1 71 | } 72 | 73 | phybits=$(lscpu | grep "Address sizes" | awk '{print $3}') 74 | maxgpa=$(( phybits-1 )) 75 | # When phybits is small, mktmebits should be reduced to avoid occupying real GPA 76 | mktmebits=$(( (phybits-36<6) ? phybits-36 : 6)) 77 | 78 | if [ $phybits -le 36 ]; 79 | then 80 | echo "Error: this machine has physical address bits (${phybits}) lower than 36" 81 | exit 1 82 | fi 83 | 84 | if [ $mktmebits -ne 6 ]; 85 | then 86 | sed -i "253s/andl \$0xf/movl \$0x${mktmebits}/" seabios/src/fw/tdx.c 87 | sed -i "14s/6ULL/${mktmebits}ULL/" linux-l0/arch/x86/kvm/vmx/mktme.h 88 | fi 89 | 90 | sed -i "104s/46/${phybits}/g" tdx-module/src/common/helpers/helpers.h 91 | sed -i "113s/45/${maxgpa}/g" tdx-module/src/common/helpers/helpers.h 92 | sed -i "113s/46/${phybits}/g" tdx-module/src/common/helpers/helpers.h 93 | sed -i "128s/45/${maxgpa}/g" tdx-module/src/common/helpers/helpers.h 94 | sed -i "615s/46/${phybits}/g" tdx-module/src/common/x86_defs/x86_defs.h 95 | 96 | sed -i "43s/45/${maxgpa}/g" linux-l1/arch/x86/kvm/vmx/tdx.c 97 | } 98 | 99 | build_qemu() 100 | { 101 | local vm_level=$1 102 | local distribution=$2 103 | 104 | check_argument "-l" "vm_level" ${vm_level} 105 | check_argument "-d" "distribution" ${distribution} 106 | 107 | if [ ${vm_level} = "l2" ]; 108 | then 109 | echo "Error: build_qemu not supported for ${vm_level}" 110 | exit 1 111 | fi 112 | 113 | NUM_CORES=$(nproc) 114 | MAX_CORES=$(($NUM_CORES - 1)) 115 | 116 | [ "$(ls -A qemu-${vm_level})" ] || { 117 | echo "Error: qemu-${vm_level} not fetched" 118 | exit 1 119 | } 120 | 121 | if [ ${vm_level} = "l0" ]; 122 | then 123 | sudo sed -i 's/# deb-src/deb-src/' /etc/apt/sources.list 124 | 125 | run_cmd sudo apt update 126 | 127 | export DEBIAN_FRONTEND=noninteractive 128 | run_cmd sudo apt install -y build-essential git libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev 129 | run_cmd sudo -E apt build-dep -y qemu 130 | run_cmd sudo apt install -y libaio-dev libbluetooth-dev libbrlapi-dev libbz2-dev 131 | run_cmd sudo apt install -y libsasl2-dev libsdl1.2-dev libseccomp-dev libsnappy-dev libssh2-1-dev 132 | run_cmd sudo apt install -y python3 python-is-python3 python3-venv 133 | 134 | mkdir -p qemu-${vm_level}/build 135 | pushd qemu-${vm_level}/build >/dev/null 136 | run_cmd ../configure --target-list=x86_64-softmmu --enable-kvm -enable-slirp --disable-werror 137 | make -j ${MAX_CORES} 138 | popd >/dev/null 139 | else # l1 140 | [ -f images/${vm_level}.img ] || { 141 | echo "Error: ${vm_level}.img not existing" 142 | exit 1 143 | } 144 | 145 | tmp=$(realpath tmp) 146 | run_mount ${tmp} ${vm_level} 147 | 148 | run_cmd sudo mkdir ${tmp}/root/qemu-${vm_level} 149 | run_cmd sudo mkdir ${tmp}/root/build-qemu-${vm_level} 150 | 151 | run_cmd sudo mount --bind qemu-${vm_level} ${tmp}/root/qemu-${vm_level} 152 | 153 | run_chroot ${tmp} """ 154 | echo 'nameserver 8.8.8.8' > /etc/resolv.conf 155 | echo 'deb-src https://deb.debian.org/debian ${distribution} main non-free-firmware' >> /etc/apt/sources.list 156 | 157 | apt update 158 | 159 | export DEBIAN_FRONTEND=noninteractive 160 | 161 | apt install -y build-essential git libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev 162 | apt build-dep -y qemu 163 | apt install -y libaio-dev libbluetooth-dev libbrlapi-dev libbz2-dev 164 | apt install -y libsasl2-dev libsdl1.2-dev libseccomp-dev libsnappy-dev libssh2-1-dev 165 | apt install -y python3 python-is-python3 python3-venv 166 | 167 | cd /root/build-qemu-${vm_level} 168 | ../qemu-${vm_level}/configure --target-list=x86_64-softmmu --enable-kvm --enable-slirp --disable-werror 169 | make -j ${MAX_CORES} 170 | """ 171 | 172 | run_cmd sudo umount ${tmp}/root/qemu-${vm_level} 173 | run_cmd sudo rm -rf ${tmp}/root/qemu-${vm_level} 174 | run_umount ${tmp} 175 | fi 176 | } 177 | 178 | build_image() 179 | { 180 | local vm_level=$1 181 | local distribution=$2 182 | local size=$3 183 | 184 | check_argument "-l" "vm_level" ${vm_level} 185 | check_argument "-d" "distribution" ${distribution} 186 | check_argument "-s" "image_size" ${size} 187 | 188 | run_cmd sudo apt install -y debootstrap 189 | 190 | if [ ${vm_level} = "l0" ] 191 | then 192 | echo "Error: build_image not supported for ${vm_level}" 193 | exit 1 194 | fi 195 | 196 | pushd images > /dev/null 197 | 198 | run_cmd chmod +x create-image.sh 199 | 200 | echo "[+] Build ${image} image ..." 201 | 202 | run_cmd ./create-image.sh -d ${distribution} -s ${size} 203 | run_cmd mv ${distribution}.img ${vm_level}.img 204 | run_cmd mv ${distribution}.id_rsa ${vm_level}.id_rsa 205 | run_cmd mv ${distribution}.id_rsa.pub ${vm_level}.id_rsa.pub 206 | 207 | popd > /dev/null 208 | } 209 | 210 | finalize_vms() 211 | { 212 | if [[ ! -f images/l1.img || ! -f images/l2.img ]] 213 | then 214 | echo "Error: images/l1.img,l2.img not found" 215 | exit 1 216 | fi 217 | 218 | tmp=$(realpath tmp) 219 | run_mount ${tmp} l2 220 | 221 | sudo sed -i 's/eth0/enp0s1/g' ${tmp}/etc/network/interfaces 222 | 223 | run_umount ${tmp} 224 | 225 | run_mount ${tmp} l1 226 | 227 | run_cmd sudo mkdir -p ${tmp}/root/images 228 | run_cmd sudo cp images/l2.img ${tmp}/root/images/ 229 | 230 | fstab="" 231 | for dir in "qemu-l1" "kvm-l1" "linux-l2" "edk2" "scripts" 232 | do 233 | fstab+="${dir} /root/${dir} 9p trans=virtio,version=9p2000.L 0 0\n" 234 | done 235 | 236 | echo -ne ${fstab} | sudo tee -a ${tmp}/etc/fstab 237 | 238 | run_umount ${tmp} 239 | } 240 | 241 | build_seabios() 242 | { 243 | [ "$(ls -A seabios)" ] || { 244 | echo "Error: seabios not fetched" 245 | exit 1 246 | } 247 | 248 | run_cmd sudo apt install -y build-essential python3 python-is-python3 249 | 250 | pushd seabios >/dev/null 251 | 252 | run_cmd make defconfig 253 | run_cmd ./config.sh 254 | run_cmd make -j 255 | 256 | popd >/dev/null 257 | } 258 | 259 | build_tdx_module() 260 | { 261 | [ "$(ls -A tdx-module)" ] || { 262 | echo "Error: tdx-module not fetched" 263 | exit 1 264 | } 265 | 266 | run_cmd sudo apt install -y python3-dev 267 | 268 | pushd tdx-module >/dev/null 269 | run_cmd "OPENTDX=1 ./build.sh" 270 | popd >/dev/null 271 | } 272 | 273 | build_seam_loader() 274 | { 275 | [ "$(ls -A seam-loader)" ] || { 276 | echo "Error: seam-loader not fetched" 277 | exit 1 278 | } 279 | 280 | echo "build seam_loader" 281 | } 282 | 283 | build_ovmf() 284 | { 285 | [ "$(ls -A edk2)" ] || { 286 | echo "Error: edk2 not existing" 287 | } 288 | 289 | run_cmd sudo apt install -y nasm iasl python3 python-is-python3 python3-venv uuid-dev 290 | 291 | pushd edk2 >/dev/null 292 | run_cmd git submodule update --init --recursive 293 | 294 | run_cmd make -C BaseTools 295 | . ./edksetup.sh 296 | 297 | sed -i 's/= IA32/= X64/g' Conf/target.txt 298 | sed -i 's/= VS2022/= GCC5/g' Conf/target.txt 299 | 300 | run_cmd build -v -t GCC5 -DBUILD_TARGETS=RELEASE -DDEBUG_ON_SERIAL_PORT=FALSE -a X64 -p OvmfPkg/OvmfPkgX64.dsc -Y COMPILE_INFO -y .dummy -b RELEASE # I don't know -y option 301 | 302 | popd >/dev/null 303 | } 304 | 305 | 306 | build_linux() 307 | { 308 | local vm_level=$1 309 | 310 | check_argument "-l" "vm_level" ${vm_level} 311 | 312 | NUM_CORES=$(nproc) 313 | MAX_CORES=$(($NUM_CORES - 1)) 314 | 315 | run_cmd sudo apt install -y git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc flex \ 316 | libelf-dev bison cpio zstd 317 | 318 | [ "$(ls -A linux-${vm_level})" ] || { 319 | echo "Error: linux-${vm_level} not existing" 320 | exit 1 321 | } 322 | 323 | MAKE="make -C linux-${vm_level} -j${MAX_CORES} LOCALVERSION=" 324 | 325 | run_cmd ${MAKE} distclean 326 | 327 | pushd linux-${vm_level} > /dev/null 328 | 329 | if [ ${vm_level} = "l0" ]; 330 | then 331 | [ -f /boot/config-$(uname -r) ] || { 332 | echo "Error: /boot/config-$(uname -r) not found" 333 | exit 1 334 | } 335 | run_cmd cp -f /boot/config-$(uname -r) .config 336 | 337 | ./scripts/config --enable CONFIG_EXPERT 338 | ./scripts/config --enable CONFIG_KVM_SW_PROTECTED_VM 339 | ./scripts/config --enable CONFIG_KVM_GENERIC_PRIVATE_MEM 340 | 341 | ./scripts/config --disable SYSTEM_TRUSTED_KEYS 342 | ./scripts/config --disable SYSTEM_REVOCATION_KEYS 343 | else # l1, l2 344 | run_cmd make defconfig 345 | run_cmd make kvm_guest.config 346 | 347 | ./scripts/config --enable CONFIG_CONFIGFS_FS 348 | ./scripts/config --module CONFIG_KVM 349 | ./scripts/config --module CONFIG_KVM_INTEL 350 | 351 | # For TDX host 352 | ./scripts/config --enable CONFIG_EXPERT 353 | ./scripts/config --enable CONFIG_KVM_SW_PROTECTED_VM 354 | ./scripts/config --enable CONFIG_KVM_GENERIC_PRIVATE_MEM 355 | ./scripts/config --enable CONFIG_X86_SGX_KVM 356 | 357 | ./scripts/config --enable CONFIG_X86_X2APIC 358 | ./scripts/config --enable CONFIG_CMA 359 | ./scripts/config --disable CONFIG_KEXEC 360 | ./scripts/config --enable CONFIG_CONTIG_ALLOC 361 | ./scripts/config --enable CONFIG_ARCH_KEEP_MEMBLOCK 362 | ./scripts/config --enable CONFIG_INTEL_TDX_HOST 363 | ./scripts/config --enable CONFIG_KVM_INTEL_TDX 364 | 365 | ./scripts/config --disable CONFIG_KSM 366 | ./scripts/config --disable CONFIG_EISA 367 | ./scripts/config --enable CONFIG_BLK_MQ_VIRTIO 368 | ./scripts/config --enable CONFIG_VIRTIO_NET 369 | ./scripts/config --enable CONFIG_IRQ_REMAP 370 | 371 | # Huge page for optimizing TD page accepting 372 | ./scripts/config --enable CONFIG_TRANSPARENT_HUGEPAGE 373 | 374 | # For TDX guest 375 | ./scripts/config --enable CONFIG_SGX 376 | ./scripts/config --enable CONFIG_INTEL_TDX_GUEST 377 | ./scripts/config --enable CONFIG_VIRT_DRIVERS 378 | ./scripts/config --module CONFIG_TDX_GUEST_DRIVER 379 | ./scripts/config --disable CONFIG_HYPERV 380 | 381 | 382 | # For debugging 383 | ./scripts/config --enable CONFIG_DEBUG_INFO_DWARF5 384 | ./scripts/config --enable CONFIG_DEBUG_INFO 385 | ./scripts/config --disable CONFIG_RANDOMIZE_BASE 386 | ./scripts/config --enable CONFIG_GDB_SCRIPTS 387 | fi 388 | 389 | popd > /dev/null 390 | 391 | run_cmd ${MAKE} olddefconfig 392 | 393 | # TODO: Need to check configs are correctly set 394 | 395 | echo "[+] Build linux kernel..." 396 | run_cmd ${MAKE} 397 | } 398 | 399 | install_kernel() 400 | { 401 | local vm_level=$1 402 | 403 | check_argument "-l" "vm_level" ${vm_level} 404 | 405 | run_cmd sudo apt install -y rsync grub2 406 | 407 | NUM_CORES=$(nproc) 408 | MAX_CORES=$(($NUM_CORES - 1)) 409 | 410 | [ -f linux-${vm_level}/arch/x86/boot/bzImage ] || { 411 | echo "Error: linux-${vm_level} not built" 412 | exit 1 413 | } 414 | 415 | version=$(cat linux-${vm_level}/include/config/kernel.release) 416 | 417 | if [ ${vm_level} = "l0" ]; 418 | then 419 | pushd linux-${vm_level} >/dev/null 420 | 421 | run_cmd sudo make -j${MAX_CORES} INSTALL_MOD_STRIP=1 modules_install 422 | run_cmd sudo make -j${MAX_CORES} headers_install 423 | run_cmd sudo make install 424 | 425 | popd >/dev/null 426 | 427 | # TODO grub 428 | sudo sed -i "s/GRUB_TIMEOUT=0/GRUB_TIMEOUT=10/g" /etc/default/grub 429 | sudo sed -i "s/GRUB_TIMEOUT_STYLE=hidden/GRUB_TIMEOUT_STYLE=menu/g" /etc/default/grub 430 | run_cmd sudo update-grub 431 | else # l1, l2 432 | [ -f images/${vm_level}.img ] || { 433 | echo "Error: images/${vm_level}.img not found" 434 | exit 1 435 | } 436 | 437 | tmp=$(realpath tmp) 438 | run_mount ${tmp} ${vm_level} 439 | 440 | pushd linux-${vm_level} > /dev/null 441 | 442 | run_cmd sudo rm -rf ${tmp}/usr/src/linux-headers-${version} 443 | [ -d ${tmp}/usr/src/linux-headers-${version}/arch/x86 ] || { 444 | run_cmd sudo mkdir -p ${tmp}/usr/src/linux-headers-${version}/arch/x86 445 | } 446 | [ -d ${tmp}/usr/src/linux-headers-${version}/arch/x86 ] && { 447 | run_cmd sudo cp arch/x86/Makefile* ${tmp}/usr/src/linux-headers-${version}/arch/x86 448 | run_cmd sudo cp -r arch/x86/include ${tmp}/usr/src/linux-headers-${version}/arch/x86 449 | } 450 | run_cmd sudo cp -r include ${tmp}/usr/src/linux-headers-${version} 451 | run_cmd sudo cp -r scripts ${tmp}/usr/src/linux-headers-${version} 452 | 453 | [ -d ${tmp}/usr/src/linux-headers-${version}/tools/objtool ] || { 454 | run_cmd sudo mkdir -p ${tmp}/usr/src/linux-headers-${version}/tools/objtool 455 | } 456 | 457 | [ -d ${tmp}/usr/src/linux-headers-${version}/tools/objtool ] && { 458 | run_cmd sudo cp tools/objtool/objtool ${tmp}/usr/src/linux-headers-${version}/tools/objtool 459 | } 460 | 461 | run_cmd sudo rm -rf ${tmp}/lib/modules/${version} 462 | 463 | run_cmd sudo make -j${MAX_CORES} INSTALL_MOD_PATH=${tmp} modules_install 464 | run_cmd sudo make -j${MAX_CORES} INSTALL_HDR_PATH=${tmp} headers_install 465 | 466 | run_cmd sudo mkdir -p ${tmp}/usr/lib/modules/${version} 467 | 468 | run_cmd sudo rm -rf ${tmp}/usr/lib/modules/${version}/source 469 | run_cmd sudo ln -s /usr/src/linux-headers-${version} ${tmp}/usr/lib/modules/${version}/source 470 | run_cmd sudo rm -rf ${tmp}/usr/lib/modules/${version}/build 471 | run_cmd sudo ln -s /usr/src/linux-headers-${version} ${tmp}/usr/lib/modules/${version}/build 472 | 473 | run_cmd sudo cp Module.symvers ${tmp}/usr/src/linux-headers-${version}/Module.symvers 474 | run_cmd sudo cp Makefile ${tmp}/usr/src/linux-headers-${version}/Makefile 475 | 476 | popd > /dev/null 477 | 478 | run_umount ${tmp} 479 | fi 480 | } 481 | 482 | build_initrd() 483 | { 484 | local vm_level=$1 485 | 486 | check_argument "-l" "vm_level" ${vm_level} 487 | 488 | if [ ${vm_level} = "l0" ] 489 | then 490 | echo "Error: build_initrd not supported for ${vm_level}" 491 | exit 1 492 | fi 493 | 494 | [ -f linux-${vm_level}/arch/x86/boot/bzImage ] || { 495 | echo "Error: linux-${vm_level} not built" 496 | exit 1 497 | } 498 | 499 | version=$(cat linux-${vm_level}/include/config/kernel.release) 500 | 501 | tmp=$(realpath tmp) 502 | run_mount ${tmp} ${vm_level} 503 | 504 | [ -d ${tmp}/lib/modules/${version} ] || { 505 | echo "Error: linux-${vm_level} not installed in ${vm_level}.img" 506 | exit 1 507 | } 508 | 509 | run_cmd sudo cp linux-${vm_level}/.config ${tmp}/boot/config-${version} 510 | 511 | run_chroot ${tmp} """ 512 | echo 'nameserver 8.8.8.8' > /etc/resolv.conf 513 | apt update 514 | 515 | export DEBIAN_FRONTEND=noninteractive 516 | apt install -y initramfs-tools 517 | 518 | set +ex 519 | PATH=/usr/sbin/:\$PATH update-initramfs -k ${version} -c -b /boot/ 520 | """ 521 | 522 | run_cmd sudo cp ${tmp}/boot/initrd.img-${version} linux-${vm_level}/initrd.img-${vm_level} 523 | 524 | run_umount ${tmp} 525 | } 526 | 527 | extract_kvm() 528 | { 529 | local vm_level=$1 530 | 531 | check_argument "-l" "vm_level" ${vm_level} 532 | 533 | kvm=kvm-${vm_level} 534 | 535 | [ -d $kvm ] || { 536 | mkdir -p $kvm 537 | } 538 | rm -rf $kvm/* 539 | 540 | echo "yes" 541 | 542 | for f in $(ls linux-${vm_level}/arch/x86/kvm/*.c) 543 | do 544 | run_cmd ln -s $PWD/$f $kvm/$(basename $f) 545 | done 546 | 547 | for f in $(ls linux-${vm_level}/arch/x86/kvm/*.h) 548 | do 549 | run_cmd ln -s $PWD/$f $kvm/$(basename $f) 550 | done 551 | 552 | for d in $(ls -d linux-${vm_level}/arch/x86/kvm/*/) 553 | do 554 | run_cmd ln -s $PWD/$d $kvm/$(basename $d) 555 | done 556 | 557 | run_cmd ln -s $PWD/linux-${vm_level}/virt $kvm/virt 558 | 559 | targets="" 560 | for f in $(ls linux-${vm_level}/virt/kvm/*.c) 561 | do 562 | target=${f%.?}.o 563 | targets+="virt\/kvm\/$(basename $target) " 564 | done 565 | 566 | run_cmd ln -s $PWD/linux-${vm_level}/arch/x86/kvm/Kconfig $kvm/Kconfig 567 | 568 | run_cmd cp linux-${vm_level}/arch/x86/kvm/Makefile $kvm/Makefile 569 | 570 | sed -i '/ccflags-y/s/$/ -IPWD/' $kvm/Makefile 571 | sed -i "s|-IPWD|-I"$PWD/$kvm"|g" $kvm/Makefile 572 | sed -i '/include $(srctree)\/virt\/kvm\/Makefile.kvm/a KVM := virt/kvm' $kvm/Makefile 573 | sed -i '/include $(srctree)\/virt\/kvm\/Makefile.kvm/s/^/#/' $kvm/Makefile 574 | 575 | sed -i "0,/^kvm-y\s\+[-+]\?=\s\+/s//kvm-y += ${targets}\\\''\n /" $kvm/Makefile 576 | sed -i "s/''//g" $kvm/Makefile 577 | 578 | echo "make -j -C $PWD/linux-${vm_level} M=$PWD/$kvm" > $kvm/build.sh 579 | chmod +x $kvm/build.sh 580 | } 581 | 582 | # Function to show usage information 583 | usage() { 584 | echo "Usage: $0 [-t ] [-l ] [-d ] [-s ]" 1>&2 585 | echo "Options:" 1>&2 586 | echo " -t Specify which target to run" 1>&2 587 | echo " - options: qemu, image, seabios, ovmf, tdx-module," 1>&2 588 | echo " seam-loader, linux, kernel, initrd, kvm, vm" 1>&2 589 | echo " -l Specify the VM nested level" >&2 590 | echo " - options: l0, l1" 1>&2 591 | echo " -d Specify the distribution version of Debian" 1>&2 592 | echo " - options: bookworm" 1>&2 593 | echo " -s Specify the image size (MB)" 1>&2 594 | echo " - examples: 32768 (32G)" 1>&2 595 | exit 1 596 | } 597 | 598 | # Parse command line options 599 | while getopts ":ht:l:d:s:" opt; do 600 | case $opt in 601 | h) 602 | usage 603 | ;; 604 | t) 605 | target=$OPTARG 606 | echo "Target: ${target}" 607 | ;; 608 | l) 609 | vm_level=$OPTARG 610 | echo "VM Level: ${vm_level}" 611 | ;; 612 | d) 613 | distribution=$OPTARG 614 | echo "Distribution version: ${distribution}" 615 | ;; 616 | s) 617 | image_size=$OPTARG 618 | echo "Image size: ${image_size}" 619 | ;; 620 | \?) 621 | echo "Invalid option: -$OPTARG" >&2 622 | usage 623 | ;; 624 | :) 625 | echo "Option -$OPTARG requires an argument." >&2 626 | usage 627 | ;; 628 | esac 629 | done 630 | 631 | shift $((OPTIND -1)) 632 | 633 | case $target in 634 | "phybits") 635 | fix_phy_bits 636 | ;; 637 | "qemu") 638 | build_qemu ${vm_level} ${distribution} 639 | ;; 640 | "image") 641 | build_image ${vm_level} ${distribution} ${image_size} 642 | ;; 643 | "seabios") 644 | build_seabios 645 | ;; 646 | "ovmf") 647 | build_ovmf 648 | ;; 649 | "tdx-module") 650 | build_tdx_module 651 | ;; 652 | "seam-loader") 653 | build_seam_loader 654 | ;; 655 | "linux") 656 | build_linux ${vm_level} 657 | ;; 658 | "kernel") 659 | install_kernel ${vm_level} 660 | ;; 661 | "initrd") 662 | build_initrd ${vm_level} 663 | ;; 664 | "kvm") 665 | extract_kvm ${vm_level} 666 | ;; 667 | "vm") 668 | finalize_vms 669 | ;; 670 | *) 671 | echo "Please provide -t " 672 | ;; 673 | esac 674 | -------------------------------------------------------------------------------- /images/create-image.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Copyright 2016 syzkaller project authors. All rights reserved. 3 | # Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 4 | 5 | # create-image.sh creates a minimal Debian Linux image suitable for syzkaller. 6 | 7 | set -eux 8 | 9 | # Create a minimal Debian distribution in a directory. 10 | DIR=chroot 11 | PREINSTALL_PKGS=openssh-server,curl,tar,gcc,libc6-dev,time,strace,sudo,less,psmisc,selinux-utils,policycoreutils,checkpolicy,selinux-policy-default,firmware-atheros,debian-ports-archive-keyring 12 | 13 | # If ADD_PACKAGE is not defined as an external environment variable, use our default packages 14 | if [ -z ${ADD_PACKAGE+x} ]; then 15 | ADD_PACKAGE="make,sysbench,git,vim,tmux,usbutils,tcpdump" 16 | fi 17 | 18 | # Variables affected by options 19 | ARCH=$(uname -m) 20 | RELEASE=bullseye 21 | FEATURE=minimal 22 | SEEK=2047 23 | PERF=false 24 | 25 | # Display help function 26 | display_help() { 27 | echo "Usage: $0 [option...] " >&2 28 | echo 29 | echo " -a, --arch Set architecture" 30 | echo " -d, --distribution Set on which debian distribution to create" 31 | echo " -f, --feature Check what packages to install in the image, options are minimal, full" 32 | echo " -s, --seek Image size (MB), default 2048 (2G)" 33 | echo " -h, --help Display help message" 34 | echo " -p, --add-perf Add perf support with this option enabled. Please set envrionment variable \$KERNEL at first" 35 | echo 36 | } 37 | 38 | while true; do 39 | if [ $# -eq 0 ];then 40 | echo $# 41 | break 42 | fi 43 | case "$1" in 44 | -h | --help) 45 | display_help 46 | exit 0 47 | ;; 48 | -a | --arch) 49 | ARCH=$2 50 | shift 2 51 | ;; 52 | -d | --distribution) 53 | RELEASE=$2 54 | shift 2 55 | ;; 56 | -f | --feature) 57 | FEATURE=$2 58 | shift 2 59 | ;; 60 | -s | --seek) 61 | SEEK=$(($2 - 1)) 62 | shift 2 63 | ;; 64 | -p | --add-perf) 65 | PERF=true 66 | shift 1 67 | ;; 68 | -*) 69 | echo "Error: Unknown option: $1" >&2 70 | exit 1 71 | ;; 72 | *) # No more options 73 | break 74 | ;; 75 | esac 76 | done 77 | 78 | # Handle cases where qemu and Debian use different arch names 79 | case "$ARCH" in 80 | ppc64le) 81 | DEBARCH=ppc64el 82 | ;; 83 | aarch64) 84 | DEBARCH=arm64 85 | ;; 86 | arm) 87 | DEBARCH=armel 88 | ;; 89 | x86_64) 90 | DEBARCH=amd64 91 | ;; 92 | *) 93 | DEBARCH=$ARCH 94 | ;; 95 | esac 96 | 97 | # Foreign architecture 98 | 99 | FOREIGN=false 100 | if [ $ARCH != $(uname -m) ]; then 101 | # i386 on an x86_64 host is exempted, as we can run i386 binaries natively 102 | if [ $ARCH != "i386" -o $(uname -m) != "x86_64" ]; then 103 | FOREIGN=true 104 | fi 105 | fi 106 | 107 | if [ $FOREIGN = "true" ]; then 108 | # Check for according qemu static binary 109 | if ! which qemu-$ARCH-static; then 110 | echo "Please install qemu static binary for architecture $ARCH (package 'qemu-user-static' on Debian/Ubuntu/Fedora)" 111 | exit 1 112 | fi 113 | # Check for according binfmt entry 114 | if [ ! -r /proc/sys/fs/binfmt_misc/qemu-$ARCH ]; then 115 | echo "binfmt entry /proc/sys/fs/binfmt_misc/qemu-$ARCH does not exist" 116 | exit 1 117 | fi 118 | fi 119 | 120 | # Double check KERNEL when PERF is enabled 121 | if [ $PERF = "true" ] && [ -z ${KERNEL+x} ]; then 122 | echo "Please set KERNEL environment variable when PERF is enabled" 123 | exit 1 124 | fi 125 | 126 | # If full feature is chosen, install more packages 127 | if [ $FEATURE = "full" ]; then 128 | PREINSTALL_PKGS=$PREINSTALL_PKGS","$ADD_PACKAGE 129 | fi 130 | 131 | sudo rm -rf $DIR 132 | sudo mkdir -p $DIR 133 | sudo chmod 0755 $DIR 134 | 135 | # 1. debootstrap stage 136 | 137 | DEBOOTSTRAP_PARAMS="--arch=$DEBARCH --include=$PREINSTALL_PKGS --no-check-gpg --components=main,contrib,non-free,non-free-firmware $RELEASE $DIR" 138 | if [ $FOREIGN = "true" ]; then 139 | DEBOOTSTRAP_PARAMS="--foreign $DEBOOTSTRAP_PARAMS" 140 | fi 141 | 142 | # riscv64 is hosted in the debian-ports repository 143 | # debian-ports doesn't include non-free, so we exclude firmware-atheros 144 | if [ $DEBARCH == "riscv64" ]; then 145 | DEBOOTSTRAP_PARAMS="--keyring /usr/share/keyrings/debian-ports-archive-keyring.gpg --exclude firmware-atheros $DEBOOTSTRAP_PARAMS http://deb.debian.org/debian-ports" 146 | fi 147 | sudo --preserve-env=http_proxy,https_proxy,ftp_proxy,no_proxy debootstrap $DEBOOTSTRAP_PARAMS 148 | 149 | # 2. debootstrap stage: only necessary if target != host architecture 150 | 151 | if [ $FOREIGN = "true" ]; then 152 | sudo cp $(which qemu-$ARCH-static) $DIR/$(which qemu-$ARCH-static) 153 | sudo chroot $DIR /bin/bash -c "/debootstrap/debootstrap --second-stage" 154 | fi 155 | 156 | # Set some defaults and enable promtless ssh to the machine for root. 157 | sudo sed -i '/^root/ { s/:x:/::/ }' $DIR/etc/passwd 158 | echo 'T0:23:respawn:/sbin/getty -L ttyS0 115200 vt100' | sudo tee -a $DIR/etc/inittab 159 | printf '\nauto eth0\niface eth0 inet dhcp\n' | sudo tee -a $DIR/etc/network/interfaces 160 | echo '/dev/root / ext4 defaults 0 0' | sudo tee -a $DIR/etc/fstab 161 | echo 'debugfs /sys/kernel/debug debugfs defaults 0 0' | sudo tee -a $DIR/etc/fstab 162 | echo 'securityfs /sys/kernel/security securityfs defaults 0 0' | sudo tee -a $DIR/etc/fstab 163 | echo 'configfs /sys/kernel/config/ configfs defaults 0 0' | sudo tee -a $DIR/etc/fstab 164 | echo 'binfmt_misc /proc/sys/fs/binfmt_misc binfmt_misc defaults 0 0' | sudo tee -a $DIR/etc/fstab 165 | echo -en "127.0.0.1\tlocalhost\n" | sudo tee $DIR/etc/hosts 166 | echo "nameserver 8.8.8.8" | sudo tee -a $DIR/etc/resolve.conf 167 | echo "syzkaller" | sudo tee $DIR/etc/hostname 168 | ssh-keygen -f $RELEASE.id_rsa -t rsa -N '' 169 | sudo mkdir -p $DIR/root/.ssh/ 170 | cat $RELEASE.id_rsa.pub | sudo tee $DIR/root/.ssh/authorized_keys 171 | 172 | # Add perf support 173 | if [ $PERF = "true" ]; then 174 | cp -r $KERNEL $DIR/tmp/ 175 | BASENAME=$(basename $KERNEL) 176 | sudo chroot $DIR /bin/bash -c "apt-get update; apt-get install -y flex bison python-dev libelf-dev libunwind8-dev libaudit-dev libslang2-dev libperl-dev binutils-dev liblzma-dev libnuma-dev" 177 | sudo chroot $DIR /bin/bash -c "cd /tmp/$BASENAME/tools/perf/; make" 178 | sudo chroot $DIR /bin/bash -c "cp /tmp/$BASENAME/tools/perf/perf /usr/bin/" 179 | rm -r $DIR/tmp/$BASENAME 180 | fi 181 | 182 | # Add udev rules for custom drivers. 183 | # Create a /dev/vim2m symlink for the device managed by the vim2m driver 184 | echo 'ATTR{name}=="vim2m", SYMLINK+="vim2m"' | sudo tee -a $DIR/etc/udev/rules.d/50-udev-default.rules 185 | 186 | # Build a disk image 187 | dd if=/dev/zero of=$RELEASE.img bs=1M seek=$SEEK count=1 188 | sudo mkfs.ext4 -F $RELEASE.img 189 | sudo mkdir -p /mnt/$DIR 190 | sudo mount -o loop $RELEASE.img /mnt/$DIR 191 | sudo cp -a $DIR/. /mnt/$DIR/. 192 | sudo umount /mnt/$DIR 193 | 194 | sudo rm -rf $DIR 195 | -------------------------------------------------------------------------------- /launch-opentdx.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | QEMU=$PWD/qemu-l0/build/qemu-system-x86_64 4 | SEABIOS=$PWD/seabios/out/bios.bin 5 | 6 | NPSEAMLDR=$PWD/seam-loader/seam-loader-main-1.5/np-seam-loader/seamldr_src/Projects/Server/Emr/Seamldr/output/ENG_TR_O1/EMR_NP_SEAMLDR_ENG_TR_O1.DBG.bin 7 | 8 | TDXMODULE=$PWD/tdx-module/bin/debug/libtdx.so 9 | TDXMODULE_SIGSTRUCT=${TDXMODULE}.sigstruct 10 | 11 | KERNEL=linux-l1/arch/x86/boot/bzImage 12 | INITRD=linux-l1/initrd.img-l1 13 | 14 | IMG=images/l1.img 15 | QEMU_L1=qemu-l1 16 | KVM_L1=kvm-l1 17 | LINUX_L2=linux-l2 18 | EDK2=edk2 19 | SCRIPTS=scripts 20 | 21 | run_qemu() 22 | { 23 | local mem=$1 24 | local smp=$2 25 | local ssh_port=$3 26 | local debug_port=$4 27 | 28 | nested_ssh_port=$((ssh_port + 1)) 29 | nested_debug_port=$((debug_port + 1)) 30 | 31 | 32 | cmdline="console=ttyS0 root=/dev/sda rw earlyprintk=serial net.ifnames=0 nohibernate debug" 33 | gpu_str="" 34 | 35 | [ ! -z ${GPU} ] && { 36 | bdfs=($(lspci | grep -i nvidia | cut -d' ' -f1)) 37 | [ ${#bdfs[@]} -eq 0 ] && { 38 | echo "[-] No GPU found" 39 | exit 1 40 | } 41 | 42 | vdids=$(lspci -nn | grep -i nvidia | sed -n 's/.*\[\(....:....\)\].*/\1/p' | paste -sd,) 43 | 44 | cmdline+=" intel_iommu=on iommu=on" 45 | cmdline+=" vfio-pci.ids=${vdids}" 46 | 47 | gpu_str="-device intel-iommu,intremap=on,caching-mode=on \\" 48 | gpu_str+="-device pci-bridge,id=bridge0,chassis_nr=1 \\" 49 | for bdf in ${bdfs[@]} 50 | do 51 | gpu_str+="-device vfio-pci,bus=bridge0,host=${bdf} \\" 52 | done 53 | } 54 | 55 | qemu_str="" 56 | qemu_str+="${QEMU} -cpu host -machine q35,kernel_irqchip=split -enable-kvm \\" 57 | qemu_str+="-m ${mem} -smp ${smp} \\" 58 | qemu_str+="-bios ${SEABIOS} \\" 59 | 60 | qemu_str+="-fw_cfg opt/opentdx.npseamldr,file=${NPSEAMLDR} \\" 61 | qemu_str+="-fw_cfg opt/opentdx.tdx_module,file=${TDXMODULE} \\" 62 | qemu_str+="-fw_cfg opt/opentdx.seam_sigstruct,file=${TDXMODULE_SIGSTRUCT} \\" 63 | 64 | qemu_str+="-drive format=raw,file=${IMG} \\" 65 | 66 | qemu_str+="-device virtio-net-pci,netdev=net0 \\" 67 | qemu_str+="-netdev user,id=net0,host=10.0.2.10,hostfwd=tcp::${ssh_port}-:22,hostfwd=tcp::${nested_ssh_port}-:10032,hostfwd=tcp::${nested_debug_port}-:1234 \\" 68 | 69 | qemu_str+="-virtfs local,path=${QEMU_L1},mount_tag=${QEMU_L1},security_model=passthrough,id=${QEMU_L1} \\" 70 | qemu_str+="-virtfs local,path=${KVM_L1},mount_tag=${KVM_L1},security_model=passthrough,id=${KVM_L1} \\" 71 | qemu_str+="-virtfs local,path=${LINUX_L2},mount_tag=${LINUX_L2},security_model=passthrough,id=${LINUX_L2} \\" 72 | qemu_str+="-virtfs local,path=${SCRIPTS},mount_tag=${SCRIPTS},security_model=passthrough,id=${SCRIPTS} \\" 73 | qemu_str+="-virtfs local,path=${EDK2},mount_tag=${EDK2},security_model=passthrough,id=${EDK2} \\" 74 | 75 | qemu_str+=${gpu_str} 76 | 77 | qemu_str+="-kernel ${KERNEL} -initrd ${INITRD} -append \"${cmdline}\" \\" 78 | 79 | [ ! -z ${DEBUG} ] && { 80 | qemu_str+="-S -gdb tcp::${debug_port} \\" 81 | } 82 | 83 | qemu_str+="-nographic" 84 | 85 | eval sudo ${qemu_str} 86 | } 87 | 88 | # Function to show usage information 89 | usage() { 90 | echo "Usage: $0 [-m ] [-s ] [-p ] [-d ]" 1>&2 91 | echo "Options:" 1>&2 92 | echo " -m Specify the memory size" 1>&2 93 | echo " - default: 8g" 1>&2 94 | echo " -s Specify the SMP" >&2 95 | echo " - default: 8" 1>&2 96 | echo " -p Specify the ssh port for l1/l2" 1>&2 97 | echo " port for l2 will be + 1" 1>&2 98 | echo " - default: 10032" 1>&2 99 | echo " -d Specify the debug port for l1/l2" 1>&2 100 | echo " port for l2 will be + 1" 1>&2 101 | echo " - default: 1234" 1>&2 102 | exit 1 103 | } 104 | 105 | mem=8g 106 | smp=8 107 | ssh_port=10032 108 | debug_port=1234 109 | 110 | while getopts ":hm:s:p:d:" opt; do 111 | case $opt in 112 | h) 113 | usage 114 | ;; 115 | m) 116 | mem=$OPTARG 117 | echo "Memory: ${mem}" 118 | ;; 119 | s) 120 | smp=$OPTARG 121 | echo "SMP: ${smp}" 122 | ;; 123 | p) 124 | ssh_port=$OPTARG 125 | echo "SSH Port: ${ssh_port}" 126 | ;; 127 | d) 128 | debug_port=$OPTARG 129 | echo "Debug Port: ${debug_port}" 130 | ;; 131 | \?) 132 | echo "Invalid option: -$OPTARG" >&2 133 | usage 134 | ;; 135 | esac 136 | done 137 | 138 | shift $((OPTIND -1)) 139 | 140 | run_qemu ${mem} ${smp} ${ssh_port} ${debug_port} 141 | -------------------------------------------------------------------------------- /opentdx-intel.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sslab-gatech/open-tdx/09d700074a1305d6b30f8d5ec7d2d1fb224473db/opentdx-intel.pdf -------------------------------------------------------------------------------- /scripts/launch-td.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | QEMU=$PWD/build-qemu-l1/qemu-system-x86_64 4 | OVMF=$PWD/edk2/Build/OvmfX64/RELEASE_GCC5/FV/OVMF.fd 5 | 6 | KERNEL=linux-l2/arch/x86/boot/bzImage 7 | INITRD=linux-l2/initrd.img-l2 8 | 9 | IMG=images/l2.img 10 | 11 | cmdline="console=ttyS0 root=/dev/sda rw" 12 | 13 | run_qemu() 14 | { 15 | local mem=$1 16 | local smp=$2 17 | local ssh_port=10032 18 | 19 | qemu_str="" 20 | qemu_str+="${QEMU} -cpu host -enable-kvm \\" 21 | qemu_str+="-m ${mem} -smp ${smp} \\" 22 | qemu_str+="-bios ${OVMF} \\" 23 | 24 | qemu_str+="-object tdx-guest,id=tdx \\" 25 | qemu_str+="-machine q35,kernel-irqchip=split,confidential-guest-support=tdx \\" 26 | 27 | qemu_str+="-device e1000,netdev=net0 \\" 28 | qemu_str+="-netdev user,id=net0,host=10.0.2.10,hostfwd=tcp::${ssh_port}-:22 \\" 29 | 30 | qemu_str+="-drive format=raw,file=${IMG} \\" 31 | 32 | qemu_str+="-kernel ${KERNEL} -initrd ${INITRD} -append \"${cmdline}\" \\" 33 | qemu_str+="-vga none -nodefaults -nographic -serial stdio" 34 | 35 | eval ${qemu_str} 36 | } 37 | 38 | # Function to show usage information 39 | usage() { 40 | echo "Usage: $0 [-m ] [-s ]" 1>&2 41 | echo "Options:" 1>&2 42 | echo " -m Specify the memory size" 1>&2 43 | echo " - default: 1g" 1>&2 44 | echo " -s Specify the SMP" >&2 45 | echo " - default: 1" 1>&2 46 | exit 1 47 | } 48 | 49 | mem=1g 50 | smp=1 51 | 52 | while getopts ":hm:s:p:" opt; do 53 | case $opt in 54 | h) 55 | usage 56 | ;; 57 | m) 58 | mem=$OPTARG 59 | echo "Memory: ${mem}" 60 | ;; 61 | s) 62 | smp=$OPTARG 63 | echo "SMP: ${smp}" 64 | ;; 65 | \?) 66 | echo "Invalid option: -$OPTARG" >&2 67 | usage 68 | ;; 69 | esac 70 | done 71 | 72 | shift $((OPTIND -1)) 73 | 74 | run_qemu ${mem} ${smp} 75 | -------------------------------------------------------------------------------- /scripts/load-kvm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -ex 2 | 3 | lsmod | grep kvm >/dev/null && { 4 | modprobe -r kvm_intel 5 | modprobe -r kvm 6 | } 7 | 8 | insmod kvm-l1/kvm.ko 9 | insmod kvm-l1/kvm-intel.ko tdx=1 10 | -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | distribution=bookworm 4 | l1_size=16384 5 | l2_size=8192 6 | 7 | echo "Running this script will install host kernel" 8 | read -r -p "Is it okay? [y/N] " okay 9 | case ${okay} in 10 | [yY][eE][sS]|[yY]) 11 | ;; 12 | *) 13 | echo "Aborted" 14 | exit 1 15 | ;; 16 | esac 17 | 18 | echo "Setting up OpenTDX..." 19 | 20 | git submodule update --init 21 | 22 | ./common.sh -t phybits 23 | 24 | ./common.sh -t qemu -l l0 -d ${distribution} 25 | ./common.sh -t image -l l1 -d ${distribution} -s ${l1_size} 26 | ./common.sh -t image -l l2 -d ${distribution} -s ${l2_size} 27 | ./common.sh -t qemu -l l1 -d ${distribution} 28 | 29 | ./common.sh -t seabios 30 | ./common.sh -t ovmf 31 | ./common.sh -t tdx-module 32 | ./common.sh -t seam-loader 33 | ./common.sh -t linux -l l0 34 | ./common.sh -t linux -l l1 35 | ./common.sh -t linux -l l2 36 | 37 | ./common.sh -t kernel -l l0 38 | ./common.sh -t kernel -l l1 39 | ./common.sh -t kernel -l l2 40 | 41 | ./common.sh -t initrd -l l1 42 | ./common.sh -t initrd -l l2 43 | 44 | ./common.sh -t kvm -l l0 45 | ./common.sh -t kvm -l l1 46 | 47 | pushd kvm-l1 >/dev/null 48 | ./build.sh 49 | popd >/dev/null 50 | 51 | ./common.sh -t vm 52 | 53 | echo "============================================================" 54 | echo "= Installation is done =" 55 | echo "= Please reboot and select installed kernel in GRUB window =" 56 | echo "============================================================" 57 | --------------------------------------------------------------------------------