cachepc-amdsev

Fork of AMDESE/AMDSEV with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-amdsev
Log | Files | Refs | README | sfeed.txt

launch-qemu.sh (9626B)


      1#!/bin/bash
      2
      3#
      4# user changeable parameters
      5#
      6HDA="/home/amd/fedora-30.raw"
      7MEM="2048"
      8SMP="4"
      9VNC=""
     10CONSOLE="serial"
     11USE_VIRTIO="1"
     12
     13SEV="0"
     14SEV_ES="0"
     15SEV_SNP="0"
     16ALLOW_DEBUG="0"
     17USE_GDB="0"
     18
     19EXEC_PATH="$PREFIX/usr/local"
     20UEFI_PATH="$EXEC_PATH/share/qemu"
     21
     22usage() {
     23	echo "$0 [options]"
     24	echo "Available <commands>:"
     25	echo " -sev               launch SEV guest"
     26	echo " -sev-es            launch SEV guest"
     27	echo " -sev-snp           launch SNP guest"
     28	echo " -bios              the bios to use (default $UEFI_PATH)"
     29	echo " -hda PATH          hard disk file (default $HDA)"
     30	echo " -mem MEM           guest memory size in MB (default $MEM)"
     31	echo " -smp NCPUS         number of virtual cpus (default $SMP)"
     32	echo " -cdrom             CDROM image"
     33	echo " -allow-debug       dump vmcb on exit and enable the trace"
     34	exit 1
     35}
     36
     37add_opts() {
     38	echo -n "$* " >> ${QEMU_CMDLINE}
     39}
     40
     41exit_from_int() {
     42	stop_network
     43	rm -rf ${QEMU_CMDLINE}
     44	# restore the mapping
     45	stty intr ^c
     46	exit 1
     47}
     48
     49run_cmd () {
     50	$*
     51	if [ $? -ne 0 ]; then
     52		echo "command $* failed"
     53		exit 1
     54	fi
     55}
     56
     57get_cbitpos() {
     58	modprobe cpuid
     59	#
     60	# Get C-bit position directly from the hardware
     61	#   Reads of /dev/cpu/x/cpuid have to be 16 bytes in size
     62	#     and the seek position represents the CPUID function
     63	#     to read.
     64	#   The skip parameter of DD skips ibs-sized blocks, so
     65	#     can't directly go to 0x8000001f function (since it
     66	#     is not a multiple of 16). So just start at 0x80000000
     67	#     function and read 32 functions to get to 0x8000001f
     68	#   To get to EBX, which contains the C-bit position, skip
     69	#     the first 4 bytes (EAX) and then convert 4 bytes.
     70	#
     71
     72	EBX=$(dd if=/dev/cpu/0/cpuid ibs=16 count=32 skip=134217728 | tail -c 16 | od -An -t u4 -j 4 -N 4 | sed -re 's|^ *||')
     73	CBITPOS=$((EBX & 0x3f))
     74}
     75
     76trap exit_from_int SIGINT
     77
     78if [ `id -u` -ne 0 ]; then
     79	echo "Must be run as root!"
     80	exit 1
     81fi
     82
     83while [ -n "$1" ]; do
     84	case "$1" in
     85		-sev-snp)	SEV_SNP="1"
     86				SEV_ES="1"
     87				SEV="1"
     88				;;
     89		-sev-es)	SEV_ES="1"
     90				SEV="1"
     91				;;
     92		-sev)		SEV="1"
     93				;;
     94		-hda) 		HDA="$2"
     95				shift
     96				;;
     97		-cdrom)		CDROM_FILE="$2"
     98				shift
     99				;;
    100		-mem)  		MEM="$2"
    101				shift
    102				;;
    103		-smp)		SMP="$2"
    104				shift
    105				;;
    106		-vnc)		VNC="$2"
    107				shift
    108				if [ "$VNC" = "" ]; then
    109					usage
    110				fi
    111				;;
    112		-console)	CONSOLE="$2"
    113				shift
    114				;;
    115		-bios)          UEFI_PATH="$2"
    116				shift
    117				;;
    118		-allow-debug)   ALLOW_DEBUG="1"
    119				;;
    120		-novirtio)      USE_VIRTIO="0"
    121				;;
    122		-kernel)	KERNEL_FILE=$2
    123				shift
    124				;;
    125		-initrd)	INITRD_FILE=$2
    126				shift
    127				;;
    128		-append) 	APPEND="$2"
    129				shift
    130				;;
    131		*) 		echo "Calling usage, cannot understand argument $1"; usage
    132				;;
    133	esac
    134
    135	shift
    136done
    137
    138TMP="$EXEC_PATH/bin/qemu-system-x86_64"
    139QEMU_EXE="$(readlink -e $TMP)"
    140[ -z "$QEMU_EXE" ] && {
    141	echo "Can't locate qemu executable [$TMP]"
    142	usage
    143}
    144
    145[ -n "$HDA" ] && {
    146	TMP="$HDA"
    147	HDA="$(readlink -e $TMP)"
    148	[ -z "$HDA" ] && {
    149		echo "Can't locate guest image file [$TMP]"
    150		usage
    151	}
    152
    153	GUEST_NAME="$(basename $TMP | sed -re 's|\.[^\.]+$||')"
    154}
    155
    156[ -n "$CDROM_FILE" ] && {
    157	TMP="$CDROM_FILE"
    158	CDROM_FILE="$(readlink -e $TMP)"
    159	[ -z "$CDROM_FILE" ] && {
    160		echo "Can't locate CD-Rom file [$TMP]"
    161		usage
    162	}
    163
    164	[ -z "$GUEST_NAME" ] && GUEST_NAME="$(basename $TMP | sed -re 's|\.[^\.]+$||')"
    165}
    166
    167setup_bridge_network() {
    168	BRIDGE_DEV="virbr0"
    169	# Get last tap device on host
    170	TAP_NUM=`ifconfig | grep tap | tail -1 | cut -c4- | cut -f1 -d ' ' | cut -f1 -d:`
    171	if [ "$TAP_NUM" = "" ]; then
    172		TAP_NUM="1"
    173	fi
    174	TAP_NUM=`echo $(( TAP_NUM + 1 ))`
    175	GUEST_TAP_NAME="tap${TAP_NUM}"
    176
    177	[ "$USE_VIRTIO" = "1" ] && PREFIX="52:54:00" || PREFIX="02:16:1e"
    178	SUFFIX="$(ip address show dev ${BRIDGE_DEV} | grep link/ether | awk '{print $2}' | awk -F : '{print $4 ":" $5}')"
    179	GUEST_MAC_ADDR="$(printf "%s:%s:%02x" $PREFIX $SUFFIX $TAP_NUM)"
    180
    181	echo "Starting network adapter '${GUEST_TAP_NAME}' MAC=$GUEST_MAC_ADDR"
    182	run_cmd "ip tuntap add $GUEST_TAP_NAME mode tap user `whoami`"
    183	run_cmd "ip link set $GUEST_TAP_NAME up"
    184	run_cmd "ip link set $GUEST_TAP_NAME master ${BRIDGE_DEV}"
    185
    186	if [ "$USE_VIRTIO" = "1" ]; then
    187		add_opts "-netdev type=tap,script=no,downscript=no,id=net0,ifname=$GUEST_TAP_NAME"
    188		add_opts "-device virtio-net-pci,mac=${GUEST_MAC_ADDR},netdev=net0,disable-legacy=on,iommu_platform=true,romfile="
    189	else
    190		add_opts "-netdev tap,id=net0,ifname=$GUEST_TAP_NAME,script=no,downscript=no"
    191		add_opts "-device e1000,mac=${GUEST_MAC_ADDR},netdev=net0,romfile="
    192	fi
    193}
    194stop_network() {
    195	if [ "$GUEST_TAP_NAME" = "" ]; then
    196		return
    197	fi
    198	run_cmd "ip tuntap del ${GUEST_TAP_NAME} mode tap"
    199}
    200
    201TMP="$UEFI_PATH/OVMF_CODE.fd"
    202UEFI_CODE="$(readlink -e $TMP)"
    203[ -z "$UEFI_CODE" ] && {
    204	echo "Can't locate UEFI code file [$TMP]"
    205	usage
    206}
    207
    208[ -e "./$GUEST_NAME.fd" ] || {
    209	TMP="$UEFI_PATH/OVMF_VARS.fd"
    210	UEFI_VARS="$(readlink -e $TMP)"
    211	[ -z "$UEFI_VARS" ] && {
    212		echo "Can't locate UEFI variable file [$TMP]"
    213		usage
    214	}
    215
    216	run_cmd "cp $UEFI_VARS ./$GUEST_NAME.fd"
    217}
    218UEFI_VARS="$(readlink -e ./$GUEST_NAME.fd)"
    219
    220if [ "$ALLOW_DEBUG" = "1" ]; then
    221	# This will dump all the VMCB on VM exit
    222	echo 1 > /sys/module/kvm_amd/parameters/dump_all_vmcbs
    223
    224	# Enable some KVM tracing to the debug
    225	#echo kvm: >/sys/kernel/debug/tracing/set_event
    226	#echo kvm:* >/sys/kernel/debug/tracing/set_event
    227	#echo kvm:kvm_page_fault >/sys/kernel/debug/tracing/set_event
    228	#echo >/sys/kernel/debug/tracing/set_event
    229	#echo > /sys/kernel/debug/tracing/trace
    230	#echo 1 > /sys/kernel/debug/tracing/tracing_on
    231fi
    232
    233# we add all the qemu command line options into a file
    234QEMU_CMDLINE=/tmp/cmdline.$$
    235rm -rf $QEMU_CMDLINE
    236
    237add_opts "taskset --cpu-list 2 $QEMU_EXE"
    238
    239add_opts "-s"
    240
    241#add_opts "-device vfio-pci,host=00:01.0,id=net10"
    242
    243# Basic virtual machine property
    244add_opts "-enable-kvm -cpu EPYC-v4 -machine q35"
    245
    246# add number of VCPUs
    247[ -n "${SMP}" ] && add_opts "-smp ${SMP},maxcpus=8"
    248
    249# define guest memory
    250add_opts "-m ${MEM}M,slots=5,maxmem=30G"
    251
    252# don't reboot for SEV-ES guest
    253add_opts "-no-reboot"
    254
    255# The OVMF binary, including the non-volatile variable store, appears as a
    256# "normal" qemu drive on the host side, and it is exposed to the guest as a
    257# persistent flash device.
    258add_opts "-drive if=pflash,format=raw,unit=0,file=${UEFI_CODE},readonly"
    259add_opts "-drive if=pflash,format=raw,unit=1,file=${UEFI_VARS}"
    260
    261# add CDROM if specified
    262[ -n "${CDROM_FILE}" ] && add_opts "-drive file=${CDROM_FILE},media=cdrom -boot d"
    263
    264# check if host has bridge network
    265BR0_STATUS="$(ip link show virbr0 type bridge 2>/dev/null)"
    266if [ -n "$BR0_STATUS" ]; then
    267	setup_bridge_network
    268else
    269	# Louis: Added port forwarding
    270	add_opts "-netdev user,id=vmnic,hostfwd=tcp::8000-:22 -device e1000,netdev=vmnic,romfile="
    271fi
    272
    273# add network support and fwd port 22 to 8000
    274# echo "guest port 22 is fwd to host 8000..."
    275# add_opts "-netdev user,id=vmnic,hostfwd=tcp::8000-:22 -device e1000,netdev=vmnic,romfile="
    276# add_opts "-netdev user,id=vmnic"
    277# add_opts " -device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile="
    278
    279# If harddisk file is specified then add the HDD drive
    280if [ -n "${HDA}" ]; then
    281	if [ "$USE_VIRTIO" = "1" ]; then
    282		if [[ ${HDA} = *"qcow2" ]]; then
    283			add_opts "-drive file=${HDA},if=none,id=disk0,format=qcow2"
    284		else
    285			add_opts "-drive file=${HDA},if=none,id=disk0,format=raw"
    286		fi
    287		add_opts "-device virtio-scsi-pci,id=scsi0,disable-legacy=on,iommu_platform=true"
    288		add_opts "-device scsi-hd,drive=disk0"
    289	else
    290		if [[ ${HDA} = *"qcow2" ]]; then
    291			add_opts "-drive file=${HDA},format=qcow2"
    292		else
    293			add_opts "-drive file=${HDA},format=raw"
    294		fi
    295	fi
    296fi
    297
    298# If this is SEV guest then add the encryption device objects to enable support
    299if [ ${SEV} = "1" ]; then
    300	add_opts "-machine memory-encryption=sev0,vmport=off" 
    301	get_cbitpos
    302
    303	if [ "${ALLOW_DEBUG}" = 1 -a "${SEV_SNP}" = 1 ]; then
    304		POLICY=$(((1<<17)|(1<<16))) # smt enable
    305		[ "${ALLOW_DEBUG}" = "1" ] && POLICY=$((POLICY | (1<<19)))
    306		SNP_POLICY=$(printf ",policy=%#x" $POLICY)
    307	elif [ "${ALLOW_DEBUG}" = "1" -o "${SEV_ES}" = "1" ]; then
    308		POLICY=$((0x01))
    309		[ "${ALLOW_DEBUG}" = "1" ] && POLICY=$((POLICY & ~0x01))
    310		[ "${SEV_ES}" = "1" ] && POLICY=$((POLICY | 0x04))
    311		SEV_POLICY=$(printf ",policy=%#x" $POLICY)
    312	fi
    313
    314	if [ "${SEV_SNP}" = 1 ]; then
    315		add_opts "-object sev-snp-guest,id=sev0${SNP_POLICY},cbitpos=${CBITPOS},reduced-phys-bits=1"
    316	else
    317		add_opts "-object sev-guest,id=sev0${SEV_POLICY},cbitpos=${CBITPOS},reduced-phys-bits=1"
    318	fi
    319fi
    320
    321# if -kernel arg is specified then use the kernel provided in command line for boot
    322if [ "${KERNEL_FILE}" != "" ]; then
    323	add_opts "-kernel $KERNEL_FILE"
    324	#add_opts "-append \"console=ttyS0 earlyprintk=serial root=/dev/sda2\""
    325	[ ! -z ${INITRD_FILE} ] && add_opts "-initrd ${INITRD_FILE}"
    326	if [[ -n "${APPEND}" ]]; then
    327		add_opts "-append \"${APPEND}\""
    328	fi
    329fi
    330
    331# if console is serial then disable graphical interface
    332if [ "${CONSOLE}" = "serial" ]; then
    333	add_opts "-nographic"
    334else
    335	add_opts "-vga ${CONSOLE}"
    336fi
    337
    338
    339
    340
    341# start vnc server
    342[ -n "${VNC}" ] && add_opts "-vnc :${VNC}" && echo "Starting VNC on port ${VNC}"
    343
    344
    345# start monitor on pty and named socket 'monitor'
    346add_opts "-monitor pty -monitor unix:monitor,server,nowait"
    347
    348# log the console  output in stdout.log
    349QEMU_CONSOLE_LOG=`pwd`/stdout.log
    350
    351# save the command line args into log file
    352cat $QEMU_CMDLINE | tee ${QEMU_CONSOLE_LOG}
    353echo | tee -a ${QEMU_CONSOLE_LOG}
    354
    355#touch /tmp/events
    356#add_opts "-trace events=/tmp/events"
    357
    358# map CTRL-C to CTRL ]
    359echo "Mapping CTRL-C to CTRL-]"
    360stty intr ^]
    361
    362echo "Launching VM ..."
    363echo "  $QEMU_CMDLINE"
    364sleep 1
    365bash ${QEMU_CMDLINE} 2>&1 | tee -a ${QEMU_CONSOLE_LOG}
    366
    367# restore the mapping
    368stty intr ^c
    369
    370rm -rf ${QEMU_CMDLINE}
    371if [ -n "$BR0_STATUS" ]; then
    372	stop_network
    373fi