From 03d545ffcd1ce8bacd36c9842d0a54aeb079566e Mon Sep 17 00:00:00 2001 From: "arun.sharma@intel.com[kaf24]" Date: Thu, 30 Jun 2005 08:07:29 +0000 Subject: bitkeeper revision 1.1773 (42c3a841nLib9kdSmthr05jouqiNeg) [PATCH] Device model cleanup. Device model cleanup. - Single config file for xen and device models (Shell script doesn't source xmdefconfig anymore) - No more device-model shell script by default. You can have one if needed (qemu-dm.debug) - All logic in the script device-model is moved to python - $DISPLAY is passed from xm to xend - Don't fork vncviewer on dryruns - Add support for killing device models on domain destroy - info vmxiopage command added to the monitor - Refactor shared io page into global and per vcpu state - Remove the hard coding of IOPACKET_PORT - move the virtual_platform_def up to domain struct from vcpu - xm create -n: (vm (name ExampleVMXDomain) (memory 128) (ssidref -1) (image (vmx (kernel /usr/lib/xen/boot/vmxloader) (root '/dev/hda1 ro') (vcpus 1) ) ) (memmap ) (device_model /tmp/foo) (hda /var/images/min-el3-i386.img) (hdb ) (hdc ) (hdd ) (cdrom ) (boot c) (fda ) (fdb ) (localtime 0) (serial ) (macaddr ) (stdvga 0) (isa 0) (nographic 0) (vnc 0) (sdl 0) (display localhost:10.0) ) Signed-off-by: Edwin Zhai Signed-off-by: Arun Sharma --- .rootkeys | 2 +- tools/examples/xmexample.vmx | 14 ++--- tools/ioemu/exec.c | 2 +- tools/ioemu/hw/i8254.c | 4 +- tools/ioemu/monitor.c | 2 + tools/ioemu/target-i386-dm/Makefile | 2 +- tools/ioemu/target-i386-dm/device-model | 91 ------------------------------- tools/ioemu/target-i386-dm/helper2.c | 23 +++++--- tools/ioemu/target-i386-dm/qemu-dm.debug | 5 ++ tools/ioemu/vl.c | 10 +++- tools/ioemu/vl.h | 1 + tools/libxc/xc_vmx_build.c | 15 +++++ tools/python/xen/xend/image.py | 94 +++++++++++++++++++++----------- tools/python/xen/xm/create.py | 78 +++++++++++++++++++++++--- xen/arch/x86/domain.c | 5 +- xen/arch/x86/vmx.c | 6 +- xen/arch/x86/vmx_intercept.c | 10 ++-- xen/arch/x86/vmx_io.c | 35 ++++++------ xen/arch/x86/vmx_platform.c | 9 +-- xen/arch/x86/vmx_vmcs.c | 6 +- xen/include/asm-x86/domain.h | 2 +- xen/include/asm-x86/vmx.h | 12 ++++ xen/include/asm-x86/vmx_intercept.h | 1 - xen/include/asm-x86/vmx_platform.h | 2 +- xen/include/asm-x86/vmx_vmcs.h | 1 - xen/include/public/io/ioreq.h | 16 +++++- 26 files changed, 253 insertions(+), 195 deletions(-) delete mode 100755 tools/ioemu/target-i386-dm/device-model create mode 100644 tools/ioemu/target-i386-dm/qemu-dm.debug diff --git a/.rootkeys b/.rootkeys index eabfd517d7..ea79aae998 100644 --- a/.rootkeys +++ b/.rootkeys @@ -738,8 +738,8 @@ 428d0d89FY-g4UPH-ZW7t5ZCqvQVTQ tools/ioemu/readline.c 428d0d89dLURbktZFufDKSHan01GFg tools/ioemu/sdl.c 428d0d82dUmXkgIy11G-hoKTkhvkfQ tools/ioemu/target-i386-dm/Makefile -428d0d8atdIE_8ACJPPii5_asQNafw tools/ioemu/target-i386-dm/device-model 428d0d8ahpRAYl6s_itBxnTcxyMHaQ tools/ioemu/target-i386-dm/helper2.c +42c3a83bi-eu2QI4iQLkImYUVs0H6w tools/ioemu/target-i386-dm/qemu-dm.debug 428d0d8aU3Moaq4zNW5QMV_NxD-4XA tools/ioemu/target-i386-dm/qemu-ifup 428d0d8aqidj8n5H2_2qhBV0mIIJzA tools/ioemu/target-i386-dm/qemu-vgaram-bin.gz 428d0d8bMq0ZpccpHb1iVvSNbJjRxg tools/ioemu/thunk.c diff --git a/tools/examples/xmexample.vmx b/tools/examples/xmexample.vmx index 1936d46a69..ca63096cae 100644 --- a/tools/examples/xmexample.vmx +++ b/tools/examples/xmexample.vmx @@ -87,18 +87,12 @@ root = "/dev/hda1 ro" #============================================================================ + # New stuff -memmap = '/etc/xen/mem-map.sxp' -device_model = '/usr/bin/device-model' -device_config = '/etc/xen/xmexample.vmx' +device_model = '/usr/bin/qemu-dm' -#============================================================================ -# -# config item for qemu device model -# Note: no space between = -#----------------------------------------------------------------------------- -# Qemu binary path -qemubin='/usr/bin/qemu-dm' +# Advanced users only. Don't touch if you don't know what you're doing +memmap = '/etc/xen/mem-map.sxp' #----------------------------------------------------------------------------- # Disk image for diff --git a/tools/ioemu/exec.c b/tools/ioemu/exec.c index e9cdf243e2..102798e26a 100644 --- a/tools/ioemu/exec.c +++ b/tools/ioemu/exec.c @@ -127,7 +127,7 @@ void cpu_exec_init(void) void cpu_set_log(int log_flags) { loglevel = log_flags; - if (loglevel && !logfile) { + if (!logfile) { logfile = fopen(logfilename, "w"); if (!logfile) { perror(logfilename); diff --git a/tools/ioemu/hw/i8254.c b/tools/ioemu/hw/i8254.c index 29a270e399..afa772644e 100644 --- a/tools/ioemu/hw/i8254.c +++ b/tools/ioemu/hw/i8254.c @@ -217,7 +217,7 @@ int pit_get_gate(PITState *pit, int channel) void pit_reset_vmx_vectors() { - extern void *shared_page; + extern shared_iopage_t *shared_page; ioreq_t *req; int irq, i; PITChannelState *s; @@ -239,7 +239,7 @@ void pit_reset_vmx_vectors() s = &pit_state.channels[vmx_channel]; fprintf(logfile, "VMX_PIT:guest init pit channel %d!\n", vmx_channel); - req = &((vcpu_iodata_t *) shared_page)->vp_ioreq; + req = &shared_page->vcpu_iodata[0].vp_ioreq; req->state = STATE_IORESP_HOOK; /* diff --git a/tools/ioemu/monitor.c b/tools/ioemu/monitor.c index 2234d775ba..ea3bc28280 100644 --- a/tools/ioemu/monitor.c +++ b/tools/ioemu/monitor.c @@ -353,6 +353,8 @@ static term_cmd_t info_cmds[] = { "", "show i8259 (PIC) state", }, { "pci", "", pci_info, "", "show PCI info", }, + { "vmxiopage", "", sp_info, + "", "show VMX device model shared page info", }, { NULL, NULL, }, }; diff --git a/tools/ioemu/target-i386-dm/Makefile b/tools/ioemu/target-i386-dm/Makefile index bfe8befc25..50919429b5 100644 --- a/tools/ioemu/target-i386-dm/Makefile +++ b/tools/ioemu/target-i386-dm/Makefile @@ -390,7 +390,7 @@ install: all ifneq ($(PROGS),) install -m 755 -s $(PROGS) "$(DESTDIR)$(bindir)" endif - install -m 755 device-model "$(DESTDIR)$(bindir)" + install -m 755 qemu-dm.debug "$(DESTDIR)$(bindir)" install -m 755 qemu-ifup "$(DESTDIR)$(configdir)" gunzip -c qemu-vgaram-bin.gz >qemu-vgaram-bin install -m 755 qemu-vgaram-bin "$(DESTDIR)$(configdir)" diff --git a/tools/ioemu/target-i386-dm/device-model b/tools/ioemu/target-i386-dm/device-model deleted file mode 100755 index a7f5e3838f..0000000000 --- a/tools/ioemu/target-i386-dm/device-model +++ /dev/null @@ -1,91 +0,0 @@ -#!/bin/sh - -. /etc/rc.d/init.d/functions - -qemubin=/usr/bin/qemu-dm - -ulimit -c unlimited - -# Use this for debugging: -#gdb --args /usr/sbin/qemu-dm -hda /var/images/qemu-linux.img -nographic \ -# -serial pty -l 'ioport,int' $* - -# XXX this is a bit skanky. we assume an order of arguments here. -# namely to have configfile and vncconnect argument as the first -# two arguments. - -while getopts ":f:v:d:" opt; -do - case $opt in - f) QEMUCONFIGFILE=$OPTARG;; - v) VNCCONNECT=$OPTARG;; - d) DOMAIN=$OPTARG;; - \?) echo;; - esac -done -if [ "x$QEMUCONFIGFILE" != "x" ]; then shift; shift; fi -if [ "x$VNCCONNECT" != "x" ]; then shift; shift; fi - - -echo $QEMUCONFIGFILE -if [ ! -z $QEMUCONFIGFILE ];then - . $QEMUCONFIGFILE -else - echo "no config file specified!" > /dev/tty - echo "no config file specified!" >> /tmp/qemustart.log - exit -fi - -PARMETER="" - -if [ ! -z $hda ];then -PARMETER="$PARMETER -hda $hda" -fi - -if [ ! -z $hdb ];then -PARMETER="$PARMETER -hdb $hdb" -fi - -if [ ! -z $hdc ];then -PARMETER="$PARMETER -hdc $hdc" -fi - -if [ ! -z $hdd ];then -PARMETER="$PARMETER -hdd $hdd" -fi - -if [ ! -z $cdrom ];then -PARMETER="$PARMETER -cdrom $cdrom" -fi - -if [ ! -z $boot ];then -PARMETER="$PARMETER -boot $boot" -fi - -if [ ! -z $nographic ] && [ $nographic -eq 1 ];then -PARMETER="$PARMETER -nographic" -fi - -vnc=${vnc:=1} -sdl=${sdl:=0} -if qemu-dm 2>&1 |grep vnc > /dev/null;then - if [ $vnc -eq 1 ] && [ $sdl -eq 1 ];then - PARMETER="$PARMETER -vnc-and-sdl -k en-us" - elif [ $vnc -eq 1 ];then - PARMETER="$PARMETER -vnc -k en-us" - fi - VNCPORT=`expr 5900 + $DOMAIN` - PARMETER="$PARMETER -vncport $VNCPORT" - if [ "x$VNCCONNECT" != "x" ]; then - PARMETER="$PARMETER -vncconnect $VNCCONNECT" - fi -fi - -#optional cmdline for qemu -# -nographic \ -# -serial pty \ - - -PARMETER="$PARMETER -l int $*"; -echo "$qemubin $PARMETER" >>/tmp/qemustart.log -$qemubin $PARMETER & diff --git a/tools/ioemu/target-i386-dm/helper2.c b/tools/ioemu/target-i386-dm/helper2.c index 6ac4349fc5..a53c04cbff 100644 --- a/tools/ioemu/target-i386-dm/helper2.c +++ b/tools/ioemu/target-i386-dm/helper2.c @@ -45,14 +45,16 @@ #include #include +#include #include "xc.h" #include #include "cpu.h" #include "exec-all.h" +#include "vl.h" -void *shared_page; +shared_iopage_t *shared_page = NULL; CPUX86State *cpu_86_init(void) { @@ -116,19 +118,27 @@ int evtchn_fd = -1; //the evtchn port for polling the notification, should be inputed as bochs's parameter u16 ioreq_port = 0; -void *shared_page = NULL; - //some functions to handle the io req packet +void +sp_info() +{ + ioreq_t *req; + + req = &(shared_page->vcpu_iodata[0].vp_ioreq); + term_printf("event port: %d\n", shared_page->sp_global.eport); + term_printf("req state: %x, pvalid: %x, addr: %llx, data: %llx, count: %llx, size: %llx\n", req->state, req->pdata_valid, req->addr, req->u.data, req->count, req->size); +} //get the ioreq packets from share mem ioreq_t* __cpu_get_ioreq(void) { ioreq_t *req; - req = &((vcpu_iodata_t *) shared_page)->vp_ioreq; + + req = &(shared_page->vcpu_iodata[0].vp_ioreq); if (req->state == STATE_IOREQ_READY) { req->state = STATE_IOREQ_INPROCESS; } else { - fprintf(logfile, "False I/O requrest ... in-service already: %x, pvalid: %x,port: %llx, data: %llx, count: %llx, size: %llx\n", req->state, req->pdata_valid, req->addr, req->u.data, req->count, req->size); + fprintf(logfile, "False I/O request ... in-service already: %x, pvalid: %x,port: %llx, data: %llx, count: %llx, size: %llx\n", req->state, req->pdata_valid, req->addr, req->u.data, req->count, req->size); req = NULL; } @@ -310,8 +320,7 @@ do_interrupt(CPUState *env, int vector) // Send a message on the event channel. Add the vector to the shared mem // page. - - intr = &(((vcpu_iodata_t *) shared_page)->vp_intr[0]); + intr = &(shared_page->vcpu_iodata[0].vp_intr[0]); atomic_set_bit(vector, intr); if (loglevel & CPU_LOG_INT) fprintf(logfile, "injecting vector: %x\n", vector); diff --git a/tools/ioemu/target-i386-dm/qemu-dm.debug b/tools/ioemu/target-i386-dm/qemu-dm.debug new file mode 100644 index 0000000000..f53a1b9159 --- /dev/null +++ b/tools/ioemu/target-i386-dm/qemu-dm.debug @@ -0,0 +1,5 @@ +#!/bin/sh + +echo $* > /tmp/args +echo $DISPLAY >> /tmp/args +exec /usr/bin/qemu-dm $* diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index 350b76d451..51d11476a2 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -116,7 +116,7 @@ const char* keyboard_layout = 0; int64_t ticks_per_sec; int boot_device = 'c'; int ram_size; -int domid; +int domid = -1; static char network_script[1024]; int pit_min_timer_count = 0; int nb_nics; @@ -2402,6 +2402,9 @@ int main(int argc, char **argv) macaddr[4] = 0x34; macaddr[5] = 0x56; + /* init debug */ + cpu_set_log(0); + optind = 1; for(;;) { if (optind >= argc) @@ -2808,11 +2811,14 @@ int main(int argc, char **argv) exit(-1); } - shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, PROT_READ|PROT_WRITE, page_array[nr_pages - 1]); + + fprintf(logfile, "shared page at pfn:%lx, mfn: %lx\n", (nr_pages-1), + (page_array[nr_pages - 1])); + /* we always create the cdrom drive, even if no disk is there */ bdrv_init(); if (has_cdrom) { diff --git a/tools/ioemu/vl.h b/tools/ioemu/vl.h index fcee3da4a7..c9667ffe8a 100644 --- a/tools/ioemu/vl.h +++ b/tools/ioemu/vl.h @@ -624,6 +624,7 @@ void pic_init(void); uint32_t pic_intack_read(CPUState *env); void pic_info(void); void irq_info(void); +void sp_info(void); int pic_irq2vec(int irq); /* i8254.c */ diff --git a/tools/libxc/xc_vmx_build.c b/tools/libxc/xc_vmx_build.c index 4d34d0ed8d..7b46651854 100644 --- a/tools/libxc/xc_vmx_build.c +++ b/tools/libxc/xc_vmx_build.c @@ -8,6 +8,7 @@ #include "xc_elf.h" #include #include +#include #include "linux_boot_params.h" #define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER) @@ -174,6 +175,9 @@ static int setup_guest(int xc_handle, unsigned long vpt_end; unsigned long v_end; + unsigned long shared_page_frame = 0; + shared_iopage_t *sp; + memset(&dsi, 0, sizeof(struct domain_setup_info)); if ( (rc = parseelfimage(image, image_size, &dsi)) != 0 ) @@ -382,6 +386,8 @@ static int setup_guest(int xc_handle, boot_paramsp->e820_map[i].addr = mem_mapp->map[i].addr; boot_paramsp->e820_map[i].size = mem_mapp->map[i].size; boot_paramsp->e820_map[i].type = mem_mapp->map[i].type; + if (mem_mapp->map[i].type == E820_SHARED) + shared_page_frame = (mem_mapp->map[i].addr >> PAGE_SHIFT); } munmap(boot_paramsp, PAGE_SIZE); @@ -407,6 +413,15 @@ static int setup_guest(int xc_handle, shared_info->vcpu_data[i].evtchn_upcall_mask = 1; munmap(shared_info, PAGE_SIZE); + /* Populate the event channel port in the shared page */ + if ((sp = (shared_iopage_t *) xc_map_foreign_range( + xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, + page_array[shared_page_frame])) == 0) + goto error_out; + memset(sp, 0, PAGE_SIZE); + sp->sp_global.eport = control_evtchn; + munmap(sp, PAGE_SIZE); + /* * Pin down l2tab addr as page dir page - causes hypervisor to provide * correct protection for the page diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py index ac96641ce9..793c72be67 100644 --- a/tools/python/xen/xend/image.py +++ b/tools/python/xen/xend/image.py @@ -231,7 +231,7 @@ class VmxImageHandler(ImageHandler): ostype = "vmx" memmap = None - memmap_value = None + memmap_value = [] device_channel = None def createImage(self): @@ -242,9 +242,12 @@ class VmxImageHandler(ImageHandler): self.createDomain() def buildDomain(self): + # Create an event channel + self.device_channel = channel.eventChannel(0, self.vm.getDomain()) + log.info("VMX device model port: %d", self.device_channel.port2) return xc.vmx_build(dom = self.vm.getDomain(), image = self.kernel, - control_evtchn = 0, + control_evtchn = self.device_channel.port2, memsize = self.vm.memory, memmap = self.memmap_value, cmdline = self.cmdline, @@ -254,51 +257,74 @@ class VmxImageHandler(ImageHandler): def parseMemmap(self): self.memmap = sxp.child_value(self.vm.config, "memmap") if self.memmap is None: - raise VmError("missing memmap") + return memmap = sxp.parse(open(self.memmap))[0] from xen.util.memmap import memmap_parse self.memmap_value = memmap_parse(memmap) - def createDeviceModel_old(self): - device_model = sxp.child_value(self.vm.config, 'device_model') - if not device_model: - raise VmError("vmx: missing device model") - device_config = sxp.child_value(self.vm.config, 'device_config') - if not device_config: - raise VmError("vmx: missing device config") - # Create an event channel. - self.device_channel = channel.eventChannel(0, self.vm.getDomain()) - # Execute device model. - #todo: Error handling - os.system(device_model - + " -f %s" % device_config - + " -d %d" % self.vm.getDomain() - + " -p %d" % self.device_channel['port1'] - + " -m %s" % self.vm.memory) - + # Return a list of cmd line args to the device models based on the + # xm config file + def parseDeviceModelArgs(self): + dmargs = [ 'hda', 'hdb', 'hdc', 'hdd', 'cdrom', 'boot', 'fda', 'fdb', + 'localtime', 'serial', 'macaddr', 'stdvga', 'isa' ] + ret = [] + for a in dmargs: + v = sxp.child_value(self.vm.config, a) + + # python doesn't allow '-' in variable names + if a == 'stdvga': a = 'std-vga' + + # Handle booleans gracefully + if a in ['localtime', 'std-vga', 'isa']: + v = int(v) + + log.debug("args: %s, val: %s" % (a,v)) + if v: + ret.append("-%s" % a) + ret.append("%s" % v) + + # Handle graphics library related options + vnc = int(sxp.child_value(self.vm.config, 'vnc')) + sdl = int(sxp.child_value(self.vm.config, 'sdl')) + nographic = int(sxp.child_value(self.vm.config, 'nographic')) + if nographic: + ret.append('-nographic') + return ret + + if vnc and sdl: + ret = ret + ['-vnc-and-sdl', '-k', 'en-us'] + elif vnc: + ret = ret + ['-vnc', '-k', 'en-us'] + if vnc: + vncport = int(self.vm.getDomain()) + 5900 + ret = ret + ['-vncport', '%d' % vncport] + return ret + def createDeviceModel(self): device_model = sxp.child_value(self.vm.config, 'device_model') if not device_model: raise VmError("vmx: missing device model") - device_config = sxp.child_value(self.vm.config, 'device_config') - if not device_config: - raise VmError("vmx: missing device config") - # Create an event channel - self.device_channel = channel.eventChannel(0, self.vm.getDomain()) # Execute device model. #todo: Error handling # XXX RN: note that the order of args matter! - os.system(device_model - + " -f %s" % device_config - + self.vncParams() - + " -d %d" % self.vm.getDomain() - + " -p %d" % (int(self.device_channel.port1)-1) - + " -m %s" % self.vm.memory) + args = [device_model] + vnc = self.vncParams() + if len(vnc): + args = args + vnc + args = args + ([ "-d", "%d" % self.vm.getDomain(), + "-p", "%d" % self.device_channel.port1, + "-m", "%s" % self.vm.memory ]) + args = args + self.parseDeviceModelArgs() + env = dict(os.environ) + env['DISPLAY'] = sxp.child_value(self.vm.config, 'display') + log.info("spawning device models: %s %s", device_model, args) + self.pid = os.spawnve(os.P_NOWAIT, device_model, args, env) + log.info("device model pid: %d", self.pid) def vncParams(self): # see if a vncviewer was specified # XXX RN: bit of a hack. should unify this, maybe stick in config space - vncconnect="" + vncconnect=[] image = self.config args = sxp.child_value(image, "args") if args: @@ -306,12 +332,14 @@ class VmxImageHandler(ImageHandler): for arg in arg_list: al = string.split(arg, '=') if al[0] == "VNC_VIEWER": - vncconnect=" -v %s" % al[1] + vncconnect=["-vncconnect", "%s" % al[1]] break return vncconnect def destroy(self): channel.eventChannelClose(self.device_channel) + os.system("kill -KILL" + + " %d" % self.pid) def getDomainMemory(self, mem_mb): return (mem_mb * 1024) + self.getPageTableSize(mem_mb) diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index 2b81b06969..7af150f790 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -254,9 +254,69 @@ gopts.var('device_model', val='FILE', fn=set_value, default='', use="Path to device model program.") -gopts.var('device_config', val='FILE', +gopts.var('hda', val='FILE', fn=set_value, default='', - use="Path to device model configuration.") + use="Path to hda") + +gopts.var('hdb', val='FILE', + fn=set_value, default='', + use="Path to hdb") + +gopts.var('hdc', val='FILE', + fn=set_value, default='', + use="Path to hdc") + +gopts.var('hdd', val='FILE', + fn=set_value, default='', + use="Path to hdd") + +gopts.var('fda', val='FILE', + fn=set_value, default='', + use="Path to fda") + +gopts.var('fdb', val='FILE', + fn=set_value, default='', + use="Path to fdb") + +gopts.var('serial', val='FILE', + fn=set_value, default='', + use="Path to serial or pty or vc") + +gopts.var('localtime', val='no|yes', + fn=set_bool, default=0, + use="Is RTC set to localtime?") + +gopts.var('stdvga', val='no|yes', + fn=set_bool, default=0, + use="Use std vga or cirrhus logic graphics") + +gopts.var('isa', val='no|yes', + fn=set_bool, default=0, + use="Simulate an ISA only system?") + +gopts.var('cdrom', val='FILE', + fn=set_value, default='', + use="Path to cdrom") + +gopts.var('macaddr', val='MACADDR', + fn=set_value, default='', + use="Macaddress of the first network interface") + +gopts.var('boot', val="a|b|c|d", + fn=set_value, default='c', + use="Default boot device") + +gopts.var('nographic', val='no|yes', + fn=set_bool, default=0, + use="Should device models use graphics?") + +gopts.var('sdl', val='', + fn=set_value, default=None, + use="""Should the device model use SDL?""") + +gopts.var('display', val='DISPLAY', + fn=set_value, default='localhost:0', + use="X11 display to use") def strip(pre, s): """Strip prefix 'pre' if present. @@ -382,12 +442,11 @@ def configure_vfr(opts, config, vals): def configure_vmx(opts, config_devs, vals): """Create the config for VMX devices. """ - memmap = vals.memmap - device_model = vals.device_model - device_config = vals.device_config - config_devs.append(['memmap', memmap]) - config_devs.append(['device_model', device_model]) - config_devs.append(['device_config', device_config]) + args = [ 'memmap', 'device_model', 'hda', 'hdb', 'hdc', 'hdd', 'cdrom', + 'boot', 'fda', 'fdb', 'localtime', 'serial', 'macaddr', 'stdvga', + 'isa', 'nographic', 'vnc', 'sdl', 'display'] + for a in args: + config_devs.append([a, vals.__dict__[a]]) def run_bootloader(opts, config, vals): if not os.access(vals.bootloader, os.X_OK): @@ -614,10 +673,13 @@ def main(argv): if '=' in arg: (var, val) = arg.strip().split('=', 1) gopts.setvar(var.strip(), val.strip()) + opts.vals.display = os.getenv("DISPLAY") if opts.vals.config: config = opts.vals.config else: opts.load_defconfig() + if opts.vals.dryrun: + opts.vals.vnc = 0 preprocess(opts, opts.vals) if not opts.getopt('name') and opts.getopt('defconfig'): opts.setopt('name', os.path.basename(opts.getopt('defconfig'))) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 8dc812aa84..fca6e135d9 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -345,7 +345,7 @@ static int vmx_final_setup_guest( v->arch.schedule_tail = arch_vmx_do_launch; #if defined (__i386) - v->arch.arch_vmx.vmx_platform.real_mode_data = + v->domain->arch.vmx_platform.real_mode_data = (unsigned long *) regs->esi; #endif @@ -356,7 +356,6 @@ static int vmx_final_setup_guest( */ memset(&v->domain->shared_info->evtchn_mask[0], 0xff, sizeof(v->domain->shared_info->evtchn_mask)); - clear_bit(IOPACKET_PORT, &v->domain->shared_info->evtchn_mask[0]); /* Put the domain in shadow mode even though we're going to be using * the shared 1:1 page table initially. It shouldn't hurt */ @@ -906,7 +905,7 @@ static void vmx_relinquish_resources(struct vcpu *v) v->arch.arch_vmx.vmcs = 0; free_monitor_pagetable(v); - rem_ac_timer(&v->arch.arch_vmx.vmx_platform.vmx_pit.pit_timer); + rem_ac_timer(&v->domain->arch.vmx_platform.vmx_pit.pit_timer); } #else #define vmx_relinquish_resources(_v) ((void)0) diff --git a/xen/arch/x86/vmx.c b/xen/arch/x86/vmx.c index fc8a1fe8fa..8717d4bea0 100644 --- a/xen/arch/x86/vmx.c +++ b/xen/arch/x86/vmx.c @@ -388,7 +388,7 @@ static void vmx_io_instruction(struct cpu_user_regs *regs, return; } - vio = (vcpu_iodata_t *) d->arch.arch_vmx.vmx_platform.shared_page_va; + vio = get_vio(d->domain, d->vcpu_id); if (vio == 0) { printk("bad shared page: %lx", (unsigned long) vio); domain_crash_synchronous(); @@ -458,7 +458,7 @@ static void vmx_io_instruction(struct cpu_user_regs *regs, set_bit(ARCH_VMX_IO_WAIT, &d->arch.arch_vmx.flags); p->state = STATE_IOREQ_READY; - evtchn_send(IOPACKET_PORT); + evtchn_send(iopacket_port(d->domain)); vmx_wait_io(); } @@ -1260,7 +1260,7 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs) (unsigned long)regs.eax, (unsigned long)regs.ebx, (unsigned long)regs.ecx, (unsigned long)regs.edx, (unsigned long)regs.esi, (unsigned long)regs.edi); - v->arch.arch_vmx.vmx_platform.mpci.inst_decoder_regs = ®s; + v->domain->arch.vmx_platform.mpci.inst_decoder_regs = ®s; if (!(error = vmx_do_page_fault(va, ®s))) { /* diff --git a/xen/arch/x86/vmx_intercept.c b/xen/arch/x86/vmx_intercept.c index e64b626d29..b6b0fffe70 100644 --- a/xen/arch/x86/vmx_intercept.c +++ b/xen/arch/x86/vmx_intercept.c @@ -35,7 +35,7 @@ int vmx_io_intercept(ioreq_t *p) { struct vcpu *d = current; - struct vmx_handler_t *handler = &(d->arch.arch_vmx.vmx_platform.vmx_handler); + struct vmx_handler_t *handler = &(d->domain->arch.vmx_platform.vmx_handler); int i; unsigned long addr, offset; for (i = 0; i < handler->num_slot; i++) { @@ -51,7 +51,7 @@ int vmx_io_intercept(ioreq_t *p) int register_io_handler(unsigned long addr, unsigned long offset, intercept_action_t action) { struct vcpu *d = current; - struct vmx_handler_t *handler = &(d->arch.arch_vmx.vmx_platform.vmx_handler); + struct vmx_handler_t *handler = &(d->domain->arch.vmx_platform.vmx_handler); int num = handler->num_slot; if (num >= MAX_IO_HANDLER) { @@ -163,7 +163,7 @@ static void resume_pit_io(ioreq_t *p) int intercept_pit_io(ioreq_t *p) { struct vcpu *d = current; - struct vmx_virpit_t *vpit = &(d->arch.arch_vmx.vmx_platform.vmx_pit); + struct vmx_virpit_t *vpit = &(d->domain->arch.vmx_platform.vmx_pit); if (p->size != 1 || p->pdata_valid || @@ -206,10 +206,10 @@ static void pit_timer_fn(void *data) */ void vmx_hooks_assist(struct vcpu *d) { - vcpu_iodata_t *vio = (vcpu_iodata_t *) d->arch.arch_vmx.vmx_platform.shared_page_va; + vcpu_iodata_t * vio = get_vio(d->domain, d->vcpu_id); ioreq_t *p = &vio->vp_ioreq; unsigned long *intr = &(vio->vp_intr[0]); - struct vmx_virpit_t *vpit = &(d->arch.arch_vmx.vmx_platform.vmx_pit); + struct vmx_virpit_t *vpit = &(d->domain->arch.vmx_platform.vmx_pit); int rw_mode; /* load init count*/ diff --git a/xen/arch/x86/vmx_io.c b/xen/arch/x86/vmx_io.c index 3914791a77..daa2d7d471 100644 --- a/xen/arch/x86/vmx_io.c +++ b/xen/arch/x86/vmx_io.c @@ -317,10 +317,11 @@ void vmx_io_assist(struct vcpu *v) struct mi_per_cpu_info *mpci_p; struct cpu_user_regs *inst_decoder_regs; - mpci_p = &v->arch.arch_vmx.vmx_platform.mpci; + mpci_p = &v->domain->arch.vmx_platform.mpci; inst_decoder_regs = mpci_p->inst_decoder_regs; - vio = (vcpu_iodata_t *) v->arch.arch_vmx.vmx_platform.shared_page_va; + vio = get_vio(v->domain, v->vcpu_id); + if (vio == 0) { VMX_DBG_LOG(DBG_LEVEL_1, "bad shared page: %lx", (unsigned long) vio); @@ -356,10 +357,10 @@ void vmx_io_assist(struct vcpu *v) } int size = -1, index = -1; - size = operand_size(v->arch.arch_vmx.vmx_platform.mpci.mmio_target); - index = operand_index(v->arch.arch_vmx.vmx_platform.mpci.mmio_target); + size = operand_size(v->domain->arch.vmx_platform.mpci.mmio_target); + index = operand_index(v->domain->arch.vmx_platform.mpci.mmio_target); - if (v->arch.arch_vmx.vmx_platform.mpci.mmio_target & WZEROEXTEND) { + if (v->domain->arch.vmx_platform.mpci.mmio_target & WZEROEXTEND) { p->u.data = p->u.data & 0xffff; } set_reg_value(size, index, 0, regs, p->u.data); @@ -404,18 +405,18 @@ void vmx_io_assist(struct vcpu *v) int vmx_clear_pending_io_event(struct vcpu *v) { struct domain *d = v->domain; + int port = iopacket_port(d); /* evtchn_pending is shared by other event channels in 0-31 range */ - if (!d->shared_info->evtchn_pending[IOPACKET_PORT>>5]) - clear_bit(IOPACKET_PORT>>5, &v->vcpu_info->evtchn_pending_sel); + if (!d->shared_info->evtchn_pending[port>>5]) + clear_bit(port>>5, &v->vcpu_info->evtchn_pending_sel); /* Note: VMX domains may need upcalls as well */ if (!v->vcpu_info->evtchn_pending_sel) clear_bit(0, &v->vcpu_info->evtchn_upcall_pending); - /* clear the pending bit for IOPACKET_PORT */ - return test_and_clear_bit(IOPACKET_PORT, - &d->shared_info->evtchn_pending[0]); + /* clear the pending bit for port */ + return test_and_clear_bit(port, &d->shared_info->evtchn_pending[0]); } /* Because we've cleared the pending events first, we need to guarantee that @@ -437,17 +438,17 @@ void vmx_check_events(struct vcpu *d) void vmx_wait_io() { extern void do_block(); + int port = iopacket_port(current->domain); do { - if(!test_bit(IOPACKET_PORT, - ¤t->domain->shared_info->evtchn_pending[0])) + if(!test_bit(port, ¤t->domain->shared_info->evtchn_pending[0])) do_block(); vmx_check_events(current); if (!test_bit(ARCH_VMX_IO_WAIT, ¤t->arch.arch_vmx.flags)) break; /* Events other than IOPACKET_PORT might have woken us up. In that case, safely go back to sleep. */ - clear_bit(IOPACKET_PORT>>5, ¤t->vcpu_info->evtchn_pending_sel); + clear_bit(port>>5, ¤t->vcpu_info->evtchn_pending_sel); clear_bit(0, ¤t->vcpu_info->evtchn_upcall_pending); } while(1); } @@ -522,7 +523,8 @@ static inline int find_highest_pending_irq(struct vcpu *d) { vcpu_iodata_t *vio; - vio = (vcpu_iodata_t *) d->arch.arch_vmx.vmx_platform.shared_page_va; + vio = get_vio(d->domain, d->vcpu_id); + if (vio == 0) { VMX_DBG_LOG(DBG_LEVEL_1, "bad shared page: %lx", (unsigned long) vio); @@ -536,7 +538,8 @@ static inline void clear_highest_bit(struct vcpu *d, int vector) { vcpu_iodata_t *vio; - vio = (vcpu_iodata_t *) d->arch.arch_vmx.vmx_platform.shared_page_va; + vio = get_vio(d->domain, d->vcpu_id); + if (vio == 0) { VMX_DBG_LOG(DBG_LEVEL_1, "bad shared page: %lx", (unsigned long) vio); @@ -555,7 +558,7 @@ void vmx_intr_assist(struct vcpu *d) { int highest_vector = find_highest_pending_irq(d); unsigned long intr_fields, eflags; - struct vmx_virpit_t *vpit = &(d->arch.arch_vmx.vmx_platform.vmx_pit); + struct vmx_virpit_t *vpit = &(d->domain->arch.vmx_platform.vmx_pit); if (highest_vector == -1) return; diff --git a/xen/arch/x86/vmx_platform.c b/xen/arch/x86/vmx_platform.c index 36a95f5117..9ec14c8c8e 100644 --- a/xen/arch/x86/vmx_platform.c +++ b/xen/arch/x86/vmx_platform.c @@ -565,10 +565,11 @@ static void send_mmio_req(unsigned long gpa, struct cpu_user_regs *inst_decoder_regs; extern long evtchn_send(int lport); - mpci_p = ¤t->arch.arch_vmx.vmx_platform.mpci; + mpci_p = ¤t->domain->arch.vmx_platform.mpci; inst_decoder_regs = mpci_p->inst_decoder_regs; - vio = (vcpu_iodata_t *) d->arch.arch_vmx.vmx_platform.shared_page_va; + vio = get_vio(d->domain, d->vcpu_id); + if (vio == NULL) { printk("bad shared page\n"); domain_crash_synchronous(); @@ -612,7 +613,7 @@ static void send_mmio_req(unsigned long gpa, p->port_mm, p->size, p->addr, value, p->count); #endif - evtchn_send(IOPACKET_PORT); + evtchn_send(iopacket_port(d->domain)); vmx_wait_io(); } @@ -626,7 +627,7 @@ void handle_mmio(unsigned long va, unsigned long gpa) unsigned char inst[MAX_INST_LEN]; int vm86, ret; - mpci_p = ¤t->arch.arch_vmx.vmx_platform.mpci; + mpci_p = ¤t->domain->arch.vmx_platform.mpci; inst_decoder_regs = mpci_p->inst_decoder_regs; __vmread(GUEST_RIP, &eip); diff --git a/xen/arch/x86/vmx_vmcs.c b/xen/arch/x86/vmx_vmcs.c index 439eb0dd76..160a88ca36 100644 --- a/xen/arch/x86/vmx_vmcs.c +++ b/xen/arch/x86/vmx_vmcs.c @@ -151,8 +151,10 @@ int vmx_setup_platform(struct vcpu *d, struct cpu_user_regs *regs) /* Initialise shared page */ mpfn = phys_to_machine_mapping(gpfn); p = map_domain_page(mpfn); - memset(p, 0, PAGE_SIZE); - d->arch.arch_vmx.vmx_platform.shared_page_va = (unsigned long)p; + d->domain->arch.vmx_platform.shared_page_va = (unsigned long)p; + + clear_bit(iopacket_port(d->domain), + &d->domain->shared_info->evtchn_mask[0]); return 0; } diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index 864fbfcbdb..d637e78a5d 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -63,7 +63,7 @@ struct arch_domain struct list_head free_shadow_frames; pagetable_t phys_table; /* guest 1:1 pagetable */ - + struct virtual_platform_def vmx_platform; } __cacheline_aligned; struct arch_vcpu diff --git a/xen/include/asm-x86/vmx.h b/xen/include/asm-x86/vmx.h index 1aab977981..66974a156c 100644 --- a/xen/include/asm-x86/vmx.h +++ b/xen/include/asm-x86/vmx.h @@ -26,6 +26,8 @@ #include #include +#include + extern void vmx_asm_vmexit_handler(struct cpu_user_regs); extern void vmx_asm_do_resume(void); extern void vmx_asm_do_launch(void); @@ -337,4 +339,14 @@ static inline int vmx_paging_enabled(struct vcpu *v) return (cr0 & X86_CR0_PE) && (cr0 & X86_CR0_PG); } +static inline vcpu_iodata_t *get_vio(struct domain *d, unsigned long cpu) +{ + return &((shared_iopage_t *) d->arch.vmx_platform.shared_page_va)->vcpu_iodata[cpu]; +} + +static inline int iopacket_port(struct domain *d) +{ + return ((shared_iopage_t *) d->arch.vmx_platform.shared_page_va)->sp_global.eport; +} + #endif /* __ASM_X86_VMX_H__ */ diff --git a/xen/include/asm-x86/vmx_intercept.h b/xen/include/asm-x86/vmx_intercept.h index 54f118ce39..9687f8cdec 100644 --- a/xen/include/asm-x86/vmx_intercept.h +++ b/xen/include/asm-x86/vmx_intercept.h @@ -9,7 +9,6 @@ #include #include - #define MAX_IO_HANDLER 6 typedef int (*intercept_action_t)(ioreq_t*); diff --git a/xen/include/asm-x86/vmx_platform.h b/xen/include/asm-x86/vmx_platform.h index 2b2682394c..4a388d1c81 100644 --- a/xen/include/asm-x86/vmx_platform.h +++ b/xen/include/asm-x86/vmx_platform.h @@ -77,7 +77,7 @@ struct mi_per_cpu_info struct cpu_user_regs *inst_decoder_regs; }; -struct virutal_platform_def { +struct virtual_platform_def { unsigned long *real_mode_data; /* E820, etc. */ unsigned long shared_page_va; struct vmx_virpit_t vmx_pit; diff --git a/xen/include/asm-x86/vmx_vmcs.h b/xen/include/asm-x86/vmx_vmcs.h index 571a4b05b8..ef8cbe91bc 100644 --- a/xen/include/asm-x86/vmx_vmcs.h +++ b/xen/include/asm-x86/vmx_vmcs.h @@ -68,7 +68,6 @@ struct arch_vmx_struct { unsigned long cpu_cr3; unsigned long cpu_state; struct msr_state msr_content; - struct virutal_platform_def vmx_platform; }; #define vmx_schedule_tail(next) \ diff --git a/xen/include/public/io/ioreq.h b/xen/include/public/io/ioreq.h index 2f01d88385..52f2afcb33 100644 --- a/xen/include/public/io/ioreq.h +++ b/xen/include/public/io/ioreq.h @@ -29,8 +29,6 @@ #define STATE_IORESP_READY 3 #define STATE_IORESP_HOOK 4 -#define IOPACKET_PORT 2 - /* VMExit dispatcher should cooperate with instruction decoder to prepare this structure and notify service OS and DM by sending virq */ @@ -53,9 +51,23 @@ typedef struct { #define BITS_PER_BYTE 8 #define INTR_LEN (MAX_VECTOR/(BITS_PER_BYTE * sizeof(unsigned long))) +/* We only track the master PIC state here */ +typedef struct { + uint16_t irr; /* interrupt request register */ + uint16_t imr; /* interrupt mask register */ + uint16_t isr; /* interrupt service register */ + + int eport; /* Event channel port */ +} global_iodata_t; + typedef struct { ioreq_t vp_ioreq; unsigned long vp_intr[INTR_LEN]; } vcpu_iodata_t; +typedef struct { + global_iodata_t sp_global; + vcpu_iodata_t vcpu_iodata[1]; +} shared_iopage_t; + #endif /* _IOREQ_H_ */ -- cgit v1.2.3