mirror of
https://github.com/xen-project/xen.git
synced 2026-10-30 03:00:05 +01:00
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 <edwin.zhai@intel.com>
Signed-off-by: Arun Sharma <arun.sharma@intel.com>
This commit is contained in:
1 parent
e6ecaec2c6
commit
03d545ffcd
26 files changed
+253
-195
No files matched your search
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
#============================================================================
|
||||
#
|
||||
# config item for qemu device model
|
||||
# Note: no space between =
|
||||
#-----------------------------------------------------------------------------
|
||||
# Qemu binary path
|
||||
qemubin='/usr/bin/qemu-dm'
|
||||
# New stuff
|
||||
device_model = '/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
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
/*
|
||||
|
||||
@@ -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, },
|
||||
};
|
||||
|
||||
|
||||
@@ -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)"
|
||||
|
||||
@@ -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 &
|
||||
@@ -45,14 +45,16 @@
|
||||
|
||||
#include <limits.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "xc.h"
|
||||
#include <io/ioreq.h>
|
||||
|
||||
#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);
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo $* > /tmp/args
|
||||
echo $DISPLAY >> /tmp/args
|
||||
exec /usr/bin/qemu-dm $*
|
||||
+8
-2
@@ -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) {
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "xc_elf.h"
|
||||
#include <stdlib.h>
|
||||
#include <zlib.h>
|
||||
#include <xen/io/ioreq.h>
|
||||
#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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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')))
|
||||
|
||||
@@ -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)
|
||||
|
||||
+3
-3
@@ -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))) {
|
||||
/*
|
||||
|
||||
@@ -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*/
|
||||
|
||||
+19
-16
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include <asm/vmx_vmcs.h>
|
||||
#include <asm/i387.h>
|
||||
|
||||
#include <public/io/ioreq.h>
|
||||
|
||||
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__ */
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <xen/errno.h>
|
||||
#include <public/io/ioreq.h>
|
||||
|
||||
|
||||
#define MAX_IO_HANDLER 6
|
||||
|
||||
typedef int (*intercept_action_t)(ioreq_t*);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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_ */
|
||||