#!/usr/bin/python3 ''' To make use of this script, you will need to run it as root and have installed the Python portio package. You need to have patched the portio operation in vmx.c and svm.c which can be found at xen/arch/x86/hvm/{vmx,svm}/{vmx.c,svm.c} as shown below so that it will run the deprivileged mode when we perform a particular port operation. My series has the basic hook in there for patch 2 but this is commented out/removed in later patches as there was a functional change (you can no longer just enter the mode, you need to supply an operation to jump to so this will need to be updated to work with that). This is in vmx_vmexit_handler and svm_vmexit_handler Here is the svm part of this copied here for completeness: uint16_t port = (vmcb->exitinfo1 >> 16) & 0xFFFF; int bytes = ((vmcb->exitinfo1 >> 4) & 0x07); int dir = (vmcb->exitinfo1 & 1) ? IOREQ_READ : IOREQ_WRITE; /* DEBUG: Run only for a specific port */ if(port == 0x1000) { if( guest_cpu_user_regs()->eax == 0x1) { hvm_deprivileged_user_mode(); } __update_guest_eip(regs, vmcb->exitinfo2 - vmcb->rip); break; } if ( handle_pio(port, bytes, dir) ) __update_guest_eip(regs, vmcb->exitinfo2 - vmcb->rip); } ''' import array #Use for command line args import sys import pickle import time from portio import ioperm, iopl, outb def prepare_portio(port): #Get access to all ports (needed on Linux pre 2.6.? kernel) if( iopl(3) != 0 ): print("ERROR: Elevating access to ports " + str(port) + "\n") return False #get access to port, only one port, and enable it if( ioperm(port, 1, 1) != 0 ): print("ERROR: Preparing port " + str(port) + "\n") return False return True """ Clean up after portio operations """ def release_portio(port): if( ioperm(port, 1, 0) != 0 ): print("ERROR: Releasing port " + str(port) + " \n") return False if( iopl(0) != 0 ): print("ERROR: Clearing access to ports " + str(port) + "\n") return False return True ''' Needs root to run ''' def send_data(port, data): outb(data, port) def profile(outputTimes, numIterations, port, data): i = 0 while (i < numIterations): before = time.time() send_data(port, data) after = time.time() timeDelta = after - before outputTimes.append( timeDelta) i = i + 1 def main(): outputTimesWith = array.array("f") outputTimesWithout = array.array("f") portWith = 0x1000 portWithout = 0x1000 dataWith = 0x1 dataWithout =0x2 numIterations = 100000 prepare_portio(portWith) #Profile the system #With the deprivileged op profile(outputTimesWith, numIterations, portWith, dataWith); release_portio(portWith) #Without the deprivileged op prepare_portio(portWithout) profile(outputTimesWithout, numIterations, portWithout, dataWithout); release_portio(portWithout) data =[outputTimesWith, outputTimesWithout] outputFile = open("data", "wb") pickle.dump(data, outputFile) outputFile.close() return if __name__ == '__main__': main()