mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
Merge with xen-ia64-unstable.hg.
This commit is contained in:
commit
6f7ae0fe6f
44 files changed
+786
-373
No files matched your search
@@ -138,6 +138,7 @@
|
||||
^tools/misc/miniterm/miniterm$
|
||||
^tools/misc/xc_shadow$
|
||||
^tools/misc/xen_cpuperf$
|
||||
^tools/misc/xen-detect$
|
||||
^tools/misc/xenperf$
|
||||
^tools/pygrub/build/.*$
|
||||
^tools/python/build/.*$
|
||||
|
||||
@@ -29,10 +29,12 @@
|
||||
|
||||
struct xenkbd_info
|
||||
{
|
||||
struct input_dev *dev;
|
||||
struct input_dev *kbd;
|
||||
struct input_dev *ptr;
|
||||
struct xenkbd_page *page;
|
||||
int irq;
|
||||
struct xenbus_device *xbdev;
|
||||
char phys[32];
|
||||
};
|
||||
|
||||
static int xenkbd_remove(struct xenbus_device *);
|
||||
@@ -56,23 +58,36 @@ static irqreturn_t input_handler(int rq, void *dev_id, struct pt_regs *regs)
|
||||
rmb(); /* ensure we see ring contents up to prod */
|
||||
for (cons = page->in_cons; cons != prod; cons++) {
|
||||
union xenkbd_in_event *event;
|
||||
struct input_dev *dev;
|
||||
event = &XENKBD_IN_RING_REF(page, cons);
|
||||
|
||||
dev = info->ptr;
|
||||
switch (event->type) {
|
||||
case XENKBD_TYPE_MOTION:
|
||||
input_report_rel(info->dev, REL_X, event->motion.rel_x);
|
||||
input_report_rel(info->dev, REL_Y, event->motion.rel_y);
|
||||
input_report_rel(dev, REL_X, event->motion.rel_x);
|
||||
input_report_rel(dev, REL_Y, event->motion.rel_y);
|
||||
break;
|
||||
case XENKBD_TYPE_KEY:
|
||||
input_report_key(info->dev, event->key.keycode, event->key.pressed);
|
||||
dev = NULL;
|
||||
if (test_bit(event->key.keycode, info->kbd->keybit))
|
||||
dev = info->kbd;
|
||||
if (test_bit(event->key.keycode, info->ptr->keybit))
|
||||
dev = info->ptr;
|
||||
if (dev)
|
||||
input_report_key(dev, event->key.keycode,
|
||||
event->key.pressed);
|
||||
else
|
||||
printk("xenkbd: unhandled keycode 0x%x\n",
|
||||
event->key.keycode);
|
||||
break;
|
||||
case XENKBD_TYPE_POS:
|
||||
input_report_abs(info->dev, ABS_X, event->pos.abs_x);
|
||||
input_report_abs(info->dev, ABS_Y, event->pos.abs_y);
|
||||
input_report_abs(dev, ABS_X, event->pos.abs_x);
|
||||
input_report_abs(dev, ABS_Y, event->pos.abs_y);
|
||||
break;
|
||||
}
|
||||
if (dev)
|
||||
input_sync(dev);
|
||||
}
|
||||
input_sync(info->dev);
|
||||
mb(); /* ensure we got ring contents */
|
||||
page->in_cons = cons;
|
||||
notify_remote_via_irq(info->irq);
|
||||
@@ -85,7 +100,7 @@ int __devinit xenkbd_probe(struct xenbus_device *dev,
|
||||
{
|
||||
int ret, i;
|
||||
struct xenkbd_info *info;
|
||||
struct input_dev *input_dev;
|
||||
struct input_dev *kbd, *ptr;
|
||||
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
if (!info) {
|
||||
@@ -94,6 +109,7 @@ int __devinit xenkbd_probe(struct xenbus_device *dev,
|
||||
}
|
||||
dev->dev.driver_data = info;
|
||||
info->xbdev = dev;
|
||||
snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename);
|
||||
|
||||
info->page = (void *)__get_free_page(GFP_KERNEL);
|
||||
if (!info->page)
|
||||
@@ -101,32 +117,52 @@ int __devinit xenkbd_probe(struct xenbus_device *dev,
|
||||
info->page->in_cons = info->page->in_prod = 0;
|
||||
info->page->out_cons = info->page->out_prod = 0;
|
||||
|
||||
input_dev = input_allocate_device();
|
||||
if (!input_dev)
|
||||
/* keyboard */
|
||||
kbd = input_allocate_device();
|
||||
if (!kbd)
|
||||
goto error_nomem;
|
||||
kbd->name = "Xen Virtual Keyboard";
|
||||
kbd->phys = info->phys;
|
||||
kbd->id.bustype = BUS_PCI;
|
||||
kbd->id.vendor = 0x5853;
|
||||
kbd->id.product = 0xffff;
|
||||
kbd->evbit[0] = BIT(EV_KEY);
|
||||
for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
|
||||
set_bit(i, kbd->keybit);
|
||||
for (i = KEY_OK; i < KEY_MAX; i++)
|
||||
set_bit(i, kbd->keybit);
|
||||
|
||||
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
|
||||
input_dev->keybit[LONG(BTN_MOUSE)]
|
||||
= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
|
||||
/* TODO additional buttons */
|
||||
input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
|
||||
|
||||
/* FIXME not sure this is quite right */
|
||||
for (i = 0; i < 256; i++)
|
||||
set_bit(i, input_dev->keybit);
|
||||
|
||||
input_dev->name = "Xen Virtual Keyboard/Mouse";
|
||||
|
||||
input_set_abs_params(input_dev, ABS_X, 0, XENFB_WIDTH, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_Y, 0, XENFB_HEIGHT, 0, 0);
|
||||
|
||||
ret = input_register_device(input_dev);
|
||||
ret = input_register_device(kbd);
|
||||
if (ret) {
|
||||
input_free_device(input_dev);
|
||||
xenbus_dev_fatal(dev, ret, "input_register_device");
|
||||
input_free_device(kbd);
|
||||
xenbus_dev_fatal(dev, ret, "input_register_device(kbd)");
|
||||
goto error;
|
||||
}
|
||||
info->dev = input_dev;
|
||||
info->kbd = kbd;
|
||||
|
||||
/* pointing device */
|
||||
ptr = input_allocate_device();
|
||||
if (!ptr)
|
||||
goto error_nomem;
|
||||
ptr->name = "Xen Virtual Pointer";
|
||||
ptr->phys = info->phys;
|
||||
ptr->id.bustype = BUS_PCI;
|
||||
ptr->id.vendor = 0x5853;
|
||||
ptr->id.product = 0xfffe;
|
||||
ptr->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
|
||||
for (i = BTN_LEFT; i <= BTN_TASK; i++)
|
||||
set_bit(i, ptr->keybit);
|
||||
ptr->relbit[0] = BIT(REL_X) | BIT(REL_Y);
|
||||
input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0);
|
||||
input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0);
|
||||
|
||||
ret = input_register_device(ptr);
|
||||
if (ret) {
|
||||
input_free_device(ptr);
|
||||
xenbus_dev_fatal(dev, ret, "input_register_device(ptr)");
|
||||
goto error;
|
||||
}
|
||||
info->ptr = ptr;
|
||||
|
||||
ret = xenkbd_connect_backend(dev, info);
|
||||
if (ret < 0)
|
||||
@@ -155,7 +191,8 @@ static int xenkbd_remove(struct xenbus_device *dev)
|
||||
struct xenkbd_info *info = dev->dev.driver_data;
|
||||
|
||||
xenkbd_disconnect_backend(info);
|
||||
input_unregister_device(info->dev);
|
||||
input_unregister_device(info->kbd);
|
||||
input_unregister_device(info->ptr);
|
||||
free_page((unsigned long)info->page);
|
||||
kfree(info);
|
||||
return 0;
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
#ifndef __I386_A_OUT_H__
|
||||
#define __I386_A_OUT_H__
|
||||
|
||||
struct exec
|
||||
{
|
||||
unsigned long a_info; /* Use macros N_MAGIC, etc for access */
|
||||
unsigned a_text; /* length of text, in bytes */
|
||||
unsigned a_data; /* length of data, in bytes */
|
||||
unsigned a_bss; /* length of uninitialized data area for file, in bytes */
|
||||
unsigned a_syms; /* length of symbol table data in file, in bytes */
|
||||
unsigned a_entry; /* start address */
|
||||
unsigned a_trsize; /* length of relocation info for text, in bytes */
|
||||
unsigned a_drsize; /* length of relocation info for data, in bytes */
|
||||
};
|
||||
|
||||
#define N_TRSIZE(a) ((a).a_trsize)
|
||||
#define N_DRSIZE(a) ((a).a_drsize)
|
||||
#define N_SYMSIZE(a) ((a).a_syms)
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define STACK_TOP (TASK_SIZE - 3*PAGE_SIZE)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __A_OUT_GNU_H__ */
|
||||
@@ -1896,6 +1896,29 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* skb_pull_rcsum - pull skb and update receive checksum
|
||||
* @skb: buffer to update
|
||||
* @start: start of data before pull
|
||||
* @len: length of data pulled
|
||||
*
|
||||
* This function performs an skb_pull on the packet and updates
|
||||
* update the CHECKSUM_HW checksum. It should be used on receive
|
||||
* path processing instead of skb_pull unless you know that the
|
||||
* checksum difference is zero (e.g., a valid IP header) or you
|
||||
* are setting ip_summed to CHECKSUM_NONE.
|
||||
*/
|
||||
unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len)
|
||||
{
|
||||
BUG_ON(len > skb->len);
|
||||
skb->len -= len;
|
||||
BUG_ON(skb->len < skb->data_len);
|
||||
skb_postpull_rcsum(skb, skb->data, len);
|
||||
return skb->data += len;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(skb_pull_rcsum);
|
||||
|
||||
/**
|
||||
* skb_segment - Perform protocol segmentation on skb.
|
||||
* @skb: buffer to segment
|
||||
@@ -2022,29 +2045,6 @@ err:
|
||||
|
||||
EXPORT_SYMBOL_GPL(skb_segment);
|
||||
|
||||
/**
|
||||
* skb_pull_rcsum - pull skb and update receive checksum
|
||||
* @skb: buffer to update
|
||||
* @start: start of data before pull
|
||||
* @len: length of data pulled
|
||||
*
|
||||
* This function performs an skb_pull on the packet and updates
|
||||
* update the CHECKSUM_HW checksum. It should be used on receive
|
||||
* path processing instead of skb_pull unless you know that the
|
||||
* checksum difference is zero (e.g., a valid IP header) or you
|
||||
* are setting ip_summed to CHECKSUM_NONE.
|
||||
*/
|
||||
unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len)
|
||||
{
|
||||
BUG_ON(len > skb->len);
|
||||
skb->len -= len;
|
||||
BUG_ON(skb->len < skb->data_len);
|
||||
skb_postpull_rcsum(skb, skb->data, len);
|
||||
return skb->data += len;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(skb_pull_rcsum);
|
||||
|
||||
void __init skb_init(void)
|
||||
{
|
||||
skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
|
||||
|
||||
@@ -46,6 +46,13 @@ then
|
||||
fi
|
||||
fi
|
||||
|
||||
RET=0
|
||||
ip link show $bridge 1>/dev/null 2>&1 || RET=1
|
||||
if [ "$RET" -eq 1 ]
|
||||
then
|
||||
fatal "Could not find bridge device $bridge"
|
||||
fi
|
||||
|
||||
case "$command" in
|
||||
online)
|
||||
setup_bridge_port "$vif"
|
||||
|
||||
@@ -28,14 +28,15 @@ export LANG="POSIX"
|
||||
unset $(set | grep ^LC_ | cut -d= -f1)
|
||||
|
||||
fatal() {
|
||||
xenstore_write "$XENBUS_PATH"/hotplug-status error
|
||||
xenstore_write "$XENBUS_PATH/hotplug-error" "$*" \
|
||||
"$XENBUS_PATH/hotplug-status" error
|
||||
log err "$@"
|
||||
exit 1
|
||||
}
|
||||
|
||||
success() {
|
||||
# Tell DevController that backend is "connected"
|
||||
xenstore_write "$XENBUS_PATH"/hotplug-status connected
|
||||
xenstore_write "$XENBUS_PATH/hotplug-status" connected
|
||||
}
|
||||
|
||||
do_or_die() {
|
||||
|
||||
@@ -3339,6 +3339,10 @@ void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
|
||||
pci_conf[0x0a] = PCI_CLASS_SUB_VGA;
|
||||
pci_conf[0x0b] = PCI_CLASS_BASE_DISPLAY;
|
||||
pci_conf[0x0e] = PCI_CLASS_HEADERTYPE_00h;
|
||||
pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */
|
||||
pci_conf[0x2d] = 0x58;
|
||||
pci_conf[0x2e] = 0x01; /* subsystem device */
|
||||
pci_conf[0x2f] = 0x00;
|
||||
|
||||
/* setup VGA */
|
||||
s = &d->cirrus_vga;
|
||||
|
||||
@@ -2502,6 +2502,10 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn)
|
||||
pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE
|
||||
pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage
|
||||
pci_conf[0x0e] = 0x00; // header_type
|
||||
pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */
|
||||
pci_conf[0x2d] = 0x58;
|
||||
pci_conf[0x2e] = 0x01; /* subsystem device */
|
||||
pci_conf[0x2f] = 0x00;
|
||||
|
||||
pci_register_io_region((PCIDevice *)d, 4, 0x10,
|
||||
PCI_ADDRESS_SPACE_IO, bmdma_map);
|
||||
|
||||
@@ -3423,8 +3423,10 @@ void pci_rtl8139_init(PCIBus *bus, NICInfo *nd)
|
||||
pci_conf[0x0e] = 0x00; /* header_type */
|
||||
pci_conf[0x3d] = 1; /* interrupt pin 0 */
|
||||
pci_conf[0x34] = 0xdc;
|
||||
pci_conf[0x2c] = pci_conf[0x00]; // same as Vendor ID
|
||||
pci_conf[0x2d] = pci_conf[0x01];
|
||||
pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */
|
||||
pci_conf[0x2d] = 0x58;
|
||||
pci_conf[0x2e] = 0x01; /* subsystem device */
|
||||
pci_conf[0x2f] = 0x00;
|
||||
|
||||
s = &d->rtl8139;
|
||||
|
||||
|
||||
+59
-1
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "vl.h"
|
||||
#include "block_int.h"
|
||||
#include <unistd.h>
|
||||
|
||||
static struct xs_handle *xsh = NULL;
|
||||
static char *hd_filename[MAX_DISKS];
|
||||
@@ -52,11 +53,40 @@ void xenstore_check_new_media_present(int timeout)
|
||||
qemu_mod_timer(insert_timer, qemu_get_clock(rt_clock) + timeout);
|
||||
}
|
||||
|
||||
static int waitForDevice(char *path, char *field, char *desired)
|
||||
{
|
||||
char *buf = NULL, *stat = NULL;
|
||||
unsigned int len;
|
||||
int val = 1;
|
||||
|
||||
/* loop until we find a value in xenstore, return
|
||||
* if it was what we wanted, or not
|
||||
*/
|
||||
while (1) {
|
||||
if (pasprintf(&buf, "%s/%s", path, field) == -1)
|
||||
goto done;
|
||||
free(stat);
|
||||
stat = xs_read(xsh, XBT_NULL, buf, &len);
|
||||
if (stat == NULL) {
|
||||
usleep(100000); /* 1/10th second, no path found */
|
||||
} else {
|
||||
val = strcmp(stat, desired);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
free(stat);
|
||||
free(buf);
|
||||
return val;
|
||||
}
|
||||
|
||||
void xenstore_parse_domain_config(int domid)
|
||||
{
|
||||
char **e = NULL;
|
||||
char *buf = NULL, *path;
|
||||
char *bpath = NULL, *dev = NULL, *params = NULL, *type = NULL;
|
||||
char *fpath = NULL, *bpath = NULL,
|
||||
*dev = NULL, *params = NULL, *type = NULL;
|
||||
int i;
|
||||
unsigned int len, num, hd_index;
|
||||
|
||||
@@ -120,7 +150,35 @@ void xenstore_parse_domain_config(int domid)
|
||||
hd_filename[hd_index] = params; /* strdup() */
|
||||
params = NULL; /* don't free params on re-use */
|
||||
}
|
||||
/*
|
||||
* check if device has a phantom vbd; the phantom is hooked
|
||||
* to the frontend device (for ease of cleanup), so lookup
|
||||
* the frontend device, and see if there is a phantom_vbd
|
||||
* if there is, we will use resolution as the filename
|
||||
*/
|
||||
if (pasprintf(&buf, "%s/device/vbd/%s/phantom_vbd", path, e[i]) == -1)
|
||||
continue;
|
||||
free(fpath);
|
||||
fpath = xs_read(xsh, XBT_NULL, buf, &len);
|
||||
if (fpath != NULL) {
|
||||
|
||||
if (waitForDevice(fpath, "hotplug-status", "connected")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pasprintf(&buf, "%s/dev", fpath) == -1)
|
||||
continue;
|
||||
params = xs_read(xsh, XBT_NULL, buf , &len);
|
||||
if (params != NULL) {
|
||||
free(hd_filename[hd_index]);
|
||||
hd_filename[hd_index] = params;
|
||||
params = NULL; /* don't free params on re-use */
|
||||
}
|
||||
}
|
||||
bs_table[hd_index] = bdrv_new(dev);
|
||||
/* re-establish buf */
|
||||
if (pasprintf(&buf, "%s/params", bpath) == -1)
|
||||
continue;
|
||||
/* check if it is a cdrom */
|
||||
if (type && !strcmp(type, "cdrom")) {
|
||||
bdrv_set_type_hint(bs_table[hd_index], BDRV_TYPE_CDROM);
|
||||
|
||||
@@ -69,7 +69,6 @@ read_exact(int fd, void *buf, size_t count)
|
||||
int xc_hvm_restore(int xc_handle, int io_fd,
|
||||
uint32_t dom, unsigned long nr_pfns,
|
||||
unsigned int store_evtchn, unsigned long *store_mfn,
|
||||
unsigned int console_evtchn, unsigned long *console_mfn,
|
||||
unsigned int pae, unsigned int apic)
|
||||
{
|
||||
DECLARE_DOMCTL;
|
||||
@@ -104,8 +103,8 @@ int xc_hvm_restore(int xc_handle, int io_fd,
|
||||
memsize = (unsigned long long)*store_mfn;
|
||||
v_end = memsize << 20;
|
||||
|
||||
DPRINTF("xc_hvm_restore:dom=%d, nr_pfns=0x%lx, store_evtchn=%d, *store_mfn=%ld, console_evtchn=%d, *console_mfn=%ld, pae=%u, apic=%u.\n",
|
||||
dom, nr_pfns, store_evtchn, *store_mfn, console_evtchn, *console_mfn, pae, apic);
|
||||
DPRINTF("xc_hvm_restore:dom=%d, nr_pfns=0x%lx, store_evtchn=%d, *store_mfn=%ld, pae=%u, apic=%u.\n",
|
||||
dom, nr_pfns, store_evtchn, *store_mfn, pae, apic);
|
||||
|
||||
max_pfn = nr_pfns;
|
||||
|
||||
|
||||
+27
-43
@@ -27,6 +27,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <xen/hvm/e820.h>
|
||||
|
||||
#include "xc_private.h"
|
||||
#include "xg_private.h"
|
||||
@@ -275,9 +276,8 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
/* A copy of the CPU context of the guest. */
|
||||
vcpu_guest_context_t ctxt;
|
||||
|
||||
/* A table containg the type of each PFN (/not/ MFN!). */
|
||||
unsigned long *pfn_type = NULL;
|
||||
unsigned long *pfn_batch = NULL;
|
||||
/* A table containg the PFNs (/not/ MFN!) to map. */
|
||||
xen_pfn_t *pfn_batch = NULL;
|
||||
|
||||
/* A copy of hvm domain context buffer*/
|
||||
uint32_t hvm_buf_size;
|
||||
@@ -290,7 +290,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
unsigned char *region_base = NULL;
|
||||
|
||||
uint32_t nr_pfns, rec_size, nr_vcpus;
|
||||
unsigned long *page_array = NULL;
|
||||
|
||||
/* power of 2 order of max_pfn */
|
||||
int order_nr;
|
||||
@@ -361,18 +360,12 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
goto out;
|
||||
}
|
||||
|
||||
max_pfn = live_shinfo->arch.max_pfn;
|
||||
|
||||
DPRINTF("saved hvm domain info:max_memkb=0x%lx, max_mfn=0x%lx, nr_pages=0x%lx\n", info.max_memkb, max_mfn, info.nr_pages);
|
||||
|
||||
/* nr_pfns: total pages excluding vga acc mem
|
||||
* max_pfn: nr_pfns + 0x20 vga hole(0xa0~0xc0)
|
||||
* getdomaininfo.tot_pages: all the allocated pages for this domain
|
||||
*/
|
||||
if (live) {
|
||||
ERROR("hvm domain doesn't support live migration now.\n");
|
||||
goto out;
|
||||
|
||||
|
||||
if (xc_shadow_control(xc_handle, dom,
|
||||
XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY,
|
||||
NULL, 0, NULL, 0, NULL) < 0) {
|
||||
@@ -381,6 +374,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
}
|
||||
|
||||
/* excludes vga acc mem */
|
||||
/* XXX will need to check whether acceleration is enabled here! */
|
||||
nr_pfns = info.nr_pages - 0x800;
|
||||
|
||||
last_iter = 0;
|
||||
@@ -396,8 +390,8 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
ERROR("HVM Domain appears not to have suspended");
|
||||
goto out;
|
||||
}
|
||||
nr_pfns = info.nr_pages;
|
||||
DPRINTF("after suspend hvm domain nr_pages=0x%x.\n", nr_pfns);
|
||||
|
||||
nr_pfns = info.nr_pages;
|
||||
}
|
||||
|
||||
DPRINTF("after 1st handle hvm domain nr_pfns=0x%x, nr_pages=0x%lx, max_memkb=0x%lx, live=%d.\n",
|
||||
@@ -406,10 +400,15 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
info.max_memkb,
|
||||
live);
|
||||
|
||||
nr_pfns = info.nr_pages;
|
||||
|
||||
/*XXX: caculate the VGA hole*/
|
||||
max_pfn = nr_pfns + 0x20;
|
||||
/* Calculate the highest PFN of "normal" memory:
|
||||
* HVM memory is sequential except for the VGA and MMIO holes, and
|
||||
* we have nr_pfns of it (which now excludes the cirrus video RAM) */
|
||||
max_pfn = nr_pfns;
|
||||
/* Skip the VGA hole from 0xa0000 to 0xc0000 */
|
||||
max_pfn += 0x20;
|
||||
/* Skip the MMIO hole: 256MB just below 4GB */
|
||||
if ( max_pfn >= (HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT) )
|
||||
max_pfn += (HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT);
|
||||
|
||||
skip_this_iter = 0;/*XXX*/
|
||||
/* pretend we sent all the pages last iteration */
|
||||
@@ -424,7 +423,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
to_send = malloc(BITMAP_SIZE);
|
||||
to_skip = malloc(BITMAP_SIZE);
|
||||
|
||||
page_array = (unsigned long *) malloc( sizeof(unsigned long) * max_pfn);
|
||||
|
||||
hvm_buf_size = xc_domain_hvm_getcontext(xc_handle, dom, 0, 0);
|
||||
if ( hvm_buf_size == -1 )
|
||||
@@ -434,7 +432,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
}
|
||||
hvm_buf = malloc(hvm_buf_size);
|
||||
|
||||
if (!to_send ||!to_skip ||!page_array ||!hvm_buf) {
|
||||
if (!to_send ||!to_skip ||!hvm_buf) {
|
||||
ERROR("Couldn't allocate memory");
|
||||
goto out;
|
||||
}
|
||||
@@ -454,26 +452,16 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
|
||||
analysis_phase(xc_handle, dom, max_pfn, to_skip, 0);
|
||||
|
||||
/* get all the HVM domain pfns */
|
||||
for ( i = 0; i < max_pfn; i++)
|
||||
page_array[i] = i;
|
||||
|
||||
|
||||
/* We want zeroed memory so use calloc rather than malloc. */
|
||||
pfn_type = calloc(MAX_BATCH_SIZE, sizeof(*pfn_type));
|
||||
pfn_batch = calloc(MAX_BATCH_SIZE, sizeof(*pfn_batch));
|
||||
|
||||
if ((pfn_type == NULL) || (pfn_batch == NULL)) {
|
||||
ERROR("failed to alloc memory for pfn_type and/or pfn_batch arrays");
|
||||
if (pfn_batch == NULL) {
|
||||
ERROR("failed to alloc memory for pfn_batch array");
|
||||
errno = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (lock_pages(pfn_type, MAX_BATCH_SIZE * sizeof(*pfn_type))) {
|
||||
ERROR("Unable to lock");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Start writing out the saved-domain record. */
|
||||
if (!write_exact(io_fd, &max_pfn, sizeof(unsigned long))) {
|
||||
ERROR("write: max_pfn");
|
||||
@@ -511,16 +499,15 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
}
|
||||
|
||||
|
||||
/* load pfn_type[] with the mfn of all the pages we're doing in
|
||||
/* load pfn_batch[] with the mfn of all the pages we're doing in
|
||||
this batch. */
|
||||
for (batch = 0; batch < MAX_BATCH_SIZE && N < max_pfn ; N++) {
|
||||
|
||||
int n = permute(N, max_pfn, order_nr);
|
||||
|
||||
if (debug) {
|
||||
DPRINTF("%d pfn= %08lx mfn= %08lx %d \n",
|
||||
iter, (unsigned long)n, page_array[n],
|
||||
test_bit(n, to_send));
|
||||
DPRINTF("%d pfn= %08lx %d \n",
|
||||
iter, (unsigned long)n, test_bit(n, to_send));
|
||||
}
|
||||
|
||||
if (!last_iter && test_bit(n, to_send)&& test_bit(n, to_skip))
|
||||
@@ -530,10 +517,12 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
(test_bit(n, to_send) && last_iter)))
|
||||
continue;
|
||||
|
||||
if (n >= 0xa0 && n < 0xc0) {
|
||||
/* DPRINTF("get a vga hole pfn= %x.\n", n);*/
|
||||
/* Skip PFNs that aren't really there */
|
||||
if ((n >= 0xa0 && n < 0xc0) /* VGA hole */
|
||||
|| (n >= (HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT)
|
||||
&& n < (1ULL << 32) >> PAGE_SHIFT)) /* 4G MMIO hole */
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
** we get here if:
|
||||
** 1. page is marked to_send & hasn't already been re-dirtied
|
||||
@@ -541,7 +530,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
*/
|
||||
|
||||
pfn_batch[batch] = n;
|
||||
pfn_type[batch] = page_array[n];
|
||||
|
||||
batch++;
|
||||
}
|
||||
@@ -573,7 +561,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
sent_this_iter += batch;
|
||||
|
||||
munmap(region_base, batch*PAGE_SIZE);
|
||||
@@ -723,9 +710,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
}
|
||||
|
||||
free(hvm_buf);
|
||||
free(page_array);
|
||||
|
||||
free(pfn_type);
|
||||
free(pfn_batch);
|
||||
free(to_send);
|
||||
free(to_skip);
|
||||
|
||||
@@ -58,8 +58,7 @@ int xc_linux_restore(int xc_handle, int io_fd, uint32_t dom,
|
||||
*/
|
||||
int xc_hvm_restore(int xc_handle, int io_fd, uint32_t dom,
|
||||
unsigned long nr_pfns, unsigned int store_evtchn,
|
||||
unsigned long *store_mfn, unsigned int console_evtchn,
|
||||
unsigned long *console_mfn,
|
||||
unsigned long *store_mfn,
|
||||
unsigned int pae, unsigned int apic);
|
||||
|
||||
/**
|
||||
|
||||
@@ -210,8 +210,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
__attribute__((weak))
|
||||
int xc_hvm_restore(int xc_handle, int io_fd, uint32_t dom,
|
||||
unsigned long nr_pfns, unsigned int store_evtchn,
|
||||
unsigned long *store_mfn, unsigned int console_evtchn,
|
||||
unsigned long *console_mfn,
|
||||
unsigned long *store_mfn,
|
||||
unsigned int pae, unsigned int apic)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
|
||||
+2
-2
@@ -9,7 +9,7 @@ CFLAGS += $(INCLUDES)
|
||||
|
||||
HDRS = $(wildcard *.h)
|
||||
|
||||
TARGETS = xenperf xc_shadow
|
||||
TARGETS = xenperf xc_shadow xen-detect
|
||||
|
||||
INSTALL_BIN = $(TARGETS) xencons
|
||||
INSTALL_SBIN = netfix xm xen-bugtool xen-python-path xend xenperf
|
||||
@@ -41,5 +41,5 @@ clean:
|
||||
%.o: %.c $(HDRS) Makefile
|
||||
$(CC) -c $(CFLAGS) -o $@ $<
|
||||
|
||||
$(TARGETS): %: %.o Makefile
|
||||
xenperf xc_shadow: %: %.o Makefile
|
||||
$(CC) $(CFLAGS) -o $@ $< -L$(XEN_LIBXC) -lxenctrl
|
||||
@@ -0,0 +1,108 @@
|
||||
/******************************************************************************
|
||||
* xen_detect.c
|
||||
*
|
||||
* Simple GNU C / POSIX application to detect execution on Xen VMM platform.
|
||||
*
|
||||
* Copyright (c) 2007, XenSource Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static int pv_context;
|
||||
|
||||
static void cpuid(uint32_t idx,
|
||||
uint32_t *eax,
|
||||
uint32_t *ebx,
|
||||
uint32_t *ecx,
|
||||
uint32_t *edx)
|
||||
{
|
||||
asm volatile (
|
||||
"test %1,%1 ; jz 1f ; ud2a ; .ascii \"xen\" ; 1: cpuid"
|
||||
: "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
|
||||
: "0" (idx), "1" (pv_context) );
|
||||
}
|
||||
|
||||
static int check_for_xen(void)
|
||||
{
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
char signature[13];
|
||||
|
||||
cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
|
||||
*(uint32_t *)(signature + 0) = ebx;
|
||||
*(uint32_t *)(signature + 4) = ecx;
|
||||
*(uint32_t *)(signature + 8) = edx;
|
||||
signature[12] = '\0';
|
||||
|
||||
if ( strcmp("XenVMMXenVMM", signature) || (eax < 0x40000002) )
|
||||
return 0;
|
||||
|
||||
cpuid(0x40000001, &eax, &ebx, &ecx, &edx);
|
||||
printf("Running in %s context on Xen v%d.%d.\n",
|
||||
pv_context ? "PV" : "HVM", (uint16_t)(eax >> 16), (uint16_t)eax);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
pid_t pid;
|
||||
int status;
|
||||
uint32_t dummy;
|
||||
|
||||
/* Check for execution in HVM context. */
|
||||
if ( check_for_xen() )
|
||||
return 0;
|
||||
|
||||
/* Now we check for execution in PV context. */
|
||||
pv_context = 1;
|
||||
|
||||
/*
|
||||
* Fork a child to test the paravirtualised CPUID instruction.
|
||||
* If executed outside Xen PV context, the extended opcode will fault.
|
||||
*/
|
||||
pid = fork();
|
||||
switch ( pid )
|
||||
{
|
||||
case 0:
|
||||
/* Child: test paravirtualised CPUID opcode and then exit cleanly. */
|
||||
cpuid(0x40000000, &dummy, &dummy, &dummy, &dummy);
|
||||
exit(0);
|
||||
case -1:
|
||||
fprintf(stderr, "Fork failed.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parent waits for child to terminate and checks for clean exit.
|
||||
* Only if the exit is clean is it safe for us to try the extended CPUID.
|
||||
*/
|
||||
waitpid(pid, &status, 0);
|
||||
if ( WIFEXITED(status) && check_for_xen() )
|
||||
return 0;
|
||||
|
||||
printf("Not running on Xen.\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -239,8 +239,11 @@ def restore(xd, fd, dominfo = None, paused = False):
|
||||
|
||||
forkHelper(cmd, fd, handler.handler, True)
|
||||
|
||||
if handler.store_mfn is None or handler.console_mfn is None:
|
||||
raise XendError('Could not read store/console MFN')
|
||||
if handler.store_mfn is None:
|
||||
raise XendError('Could not read store MFN')
|
||||
|
||||
if not is_hvm and handler.console_mfn is None:
|
||||
raise XendError('Could not read console MFN')
|
||||
|
||||
dominfo.waitForDevices() # Wait for backends to set up
|
||||
if not paused:
|
||||
|
||||
@@ -1148,6 +1148,47 @@ class XendConfig(dict):
|
||||
# no valid device to add
|
||||
return ''
|
||||
|
||||
def phantom_device_add(self, dev_type, cfg_xenapi = None,
|
||||
target = None):
|
||||
"""Add a phantom tap device configuration in XenAPI struct format.
|
||||
"""
|
||||
|
||||
if target == None:
|
||||
target = self
|
||||
|
||||
if dev_type not in XendDevices.valid_devices() and \
|
||||
dev_type not in XendDevices.pseudo_devices():
|
||||
raise XendConfigError("XendConfig: %s not a valid device type" %
|
||||
dev_type)
|
||||
|
||||
if cfg_xenapi == None:
|
||||
raise XendConfigError("XendConfig: device_add requires some "
|
||||
"config.")
|
||||
|
||||
if cfg_xenapi:
|
||||
log.debug("XendConfig.phantom_device_add: %s" % str(cfg_xenapi))
|
||||
|
||||
if cfg_xenapi:
|
||||
dev_info = {}
|
||||
if dev_type in ('vbd', 'tap'):
|
||||
if dev_type == 'vbd':
|
||||
dev_info['uname'] = cfg_xenapi.get('image', '')
|
||||
dev_info['dev'] = '%s:disk' % cfg_xenapi.get('device')
|
||||
elif dev_type == 'tap':
|
||||
if cfg_xenapi.get('image').find('tap:') == -1:
|
||||
dev_info['uname'] = 'tap:qcow:%s' % cfg_xenapi.get('image')
|
||||
dev_info['dev'] = '/dev/%s' % cfg_xenapi.get('device')
|
||||
dev_info['uname'] = cfg_xenapi.get('image')
|
||||
dev_info['mode'] = cfg_xenapi.get('mode')
|
||||
dev_info['backend'] = '0'
|
||||
dev_uuid = cfg_xenapi.get('uuid', uuid.createString())
|
||||
dev_info['uuid'] = dev_uuid
|
||||
self['devices'][dev_uuid] = (dev_type, dev_info)
|
||||
self['vbd_refs'].append(dev_uuid)
|
||||
return dev_uuid
|
||||
|
||||
return ''
|
||||
|
||||
def console_add(self, protocol, location, other_config = {}):
|
||||
dev_uuid = uuid.createString()
|
||||
if protocol == 'vt100':
|
||||
|
||||
@@ -800,7 +800,10 @@ class XendDomain:
|
||||
"support.")
|
||||
|
||||
path = self._managed_check_point_path(dom_uuid)
|
||||
fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC)
|
||||
oflags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
|
||||
if hasattr(os, "O_LARGEFILE"):
|
||||
oflags |= os.O_LARGEFILE
|
||||
fd = os.open(path, oflags)
|
||||
try:
|
||||
# For now we don't support 'live checkpoint'
|
||||
XendCheckpoint.save(fd, dominfo, False, False, path)
|
||||
@@ -840,8 +843,11 @@ class XendDomain:
|
||||
# Restore that replaces the existing XendDomainInfo
|
||||
try:
|
||||
log.debug('Current DomainInfo state: %d' % dominfo.state)
|
||||
oflags = os.O_RDONLY
|
||||
if hasattr(os, "O_LARGEFILE"):
|
||||
oflags |= os.O_LARGEFILE
|
||||
XendCheckpoint.restore(self,
|
||||
os.open(chkpath, os.O_RDONLY),
|
||||
os.open(chkpath, oflags),
|
||||
dominfo,
|
||||
paused = start_paused)
|
||||
os.unlink(chkpath)
|
||||
@@ -1009,7 +1015,10 @@ class XendDomain:
|
||||
@raise XendError: Failure to restore domain
|
||||
"""
|
||||
try:
|
||||
fd = os.open(src, os.O_RDONLY)
|
||||
oflags = os.O_RDONLY
|
||||
if hasattr(os, "O_LARGEFILE"):
|
||||
oflags |= os.O_LARGEFILE
|
||||
fd = os.open(src, oflags)
|
||||
try:
|
||||
return self.domain_restore_fd(fd, paused=paused)
|
||||
finally:
|
||||
@@ -1193,7 +1202,10 @@ class XendDomain:
|
||||
if dominfo.getDomid() == DOM0_ID:
|
||||
raise XendError("Cannot save privileged domain %i" % domid)
|
||||
|
||||
fd = os.open(dst, os.O_WRONLY | os.O_CREAT | os.O_TRUNC)
|
||||
oflags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
|
||||
if hasattr(os, "O_LARGEFILE"):
|
||||
oflags |= os.O_LARGEFILE
|
||||
fd = os.open(dst, oflags)
|
||||
try:
|
||||
# For now we don't support 'live checkpoint'
|
||||
XendCheckpoint.save(fd, dominfo, False, False, dst)
|
||||
|
||||
@@ -1416,7 +1416,7 @@ class XendDomainInfo:
|
||||
self.info['image'],
|
||||
self.info['devices'])
|
||||
|
||||
localtime = self.info.get('localtime', False)
|
||||
localtime = self.info.get('platform_localtime', False)
|
||||
if localtime:
|
||||
xc.domain_set_time_offset(self.domid)
|
||||
|
||||
@@ -1565,19 +1565,54 @@ class XendDomainInfo:
|
||||
# VM Destroy
|
||||
#
|
||||
|
||||
def _prepare_phantom_paths(self):
|
||||
# get associated devices to destroy
|
||||
# build list of phantom devices to be removed after normal devices
|
||||
plist = []
|
||||
from xen.xend.xenstore.xstransact import xstransact
|
||||
t = xstransact("%s/device/vbd" % GetDomainPath(self.domid))
|
||||
for dev in t.list():
|
||||
backend_phantom_vbd = xstransact.Read("%s/device/vbd/%s/phantom_vbd" \
|
||||
% (self.dompath, dev))
|
||||
if backend_phantom_vbd is not None:
|
||||
frontend_phantom_vbd = xstransact.Read("%s/frontend" \
|
||||
% backend_phantom_vbd)
|
||||
plist.append(backend_phantom_vbd)
|
||||
plist.append(frontend_phantom_vbd)
|
||||
return plist
|
||||
|
||||
def _cleanup_phantom_devs(self, plist):
|
||||
# remove phantom devices
|
||||
if not plist == []:
|
||||
time.sleep(2)
|
||||
for paths in plist:
|
||||
if paths.find('backend') != -1:
|
||||
from xen.xend.server import DevController
|
||||
# Modify online status /before/ updating state (latter is watched by
|
||||
# drivers, so this ordering avoids a race).
|
||||
xstransact.Write(paths, 'online', "0")
|
||||
xstransact.Write(paths, 'state', str(DevController.xenbusState['Closing']))
|
||||
# force
|
||||
xstransact.Remove(paths)
|
||||
|
||||
def destroy(self):
|
||||
"""Cleanup VM and destroy domain. Nothrow guarantee."""
|
||||
|
||||
log.debug("XendDomainInfo.destroy: domid=%s", str(self.domid))
|
||||
|
||||
paths = self._prepare_phantom_paths()
|
||||
|
||||
self._cleanupVm()
|
||||
if self.dompath is not None:
|
||||
self.destroyDomain()
|
||||
|
||||
self._cleanup_phantom_devs(paths)
|
||||
|
||||
def destroyDomain(self):
|
||||
log.debug("XendDomainInfo.destroyDomain(%s)", str(self.domid))
|
||||
|
||||
paths = self._prepare_phantom_paths()
|
||||
|
||||
try:
|
||||
if self.domid is not None:
|
||||
xc.domain_destroy(self.domid)
|
||||
@@ -1591,7 +1626,7 @@ class XendDomainInfo:
|
||||
XendDomain.instance().remove_domain(self)
|
||||
|
||||
self.cleanupDomain()
|
||||
|
||||
self._cleanup_phantom_devs(paths)
|
||||
|
||||
def resumeDomain(self):
|
||||
log.debug("XendDomainInfo.resumeDomain(%s)", str(self.domid))
|
||||
@@ -2211,6 +2246,25 @@ class XendDomainInfo:
|
||||
|
||||
return dev_uuid
|
||||
|
||||
def create_phantom_vbd_with_vdi(self, xenapi_vbd, vdi_image_path):
|
||||
"""Create a VBD using a VDI from XendStorageRepository.
|
||||
|
||||
@param xenapi_vbd: vbd struct from the Xen API
|
||||
@param vdi_image_path: VDI UUID
|
||||
@rtype: string
|
||||
@return: uuid of the device
|
||||
"""
|
||||
xenapi_vbd['image'] = vdi_image_path
|
||||
dev_uuid = self.info.phantom_device_add('tap', cfg_xenapi = xenapi_vbd)
|
||||
if not dev_uuid:
|
||||
raise XendError('Failed to create device')
|
||||
|
||||
if self.state == XEN_API_VM_POWER_STATE_RUNNING:
|
||||
_, config = self.info['devices'][dev_uuid]
|
||||
config['devid'] = self.getDeviceController('tap').createDevice(config)
|
||||
|
||||
return config['devid']
|
||||
|
||||
def create_vif(self, xenapi_vif):
|
||||
"""Create VIF device from the passed struct in Xen API format.
|
||||
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
|
||||
|
||||
from xen.xend.server.blkif import BlkifController
|
||||
from xen.xend.XendLogging import log
|
||||
|
||||
phantomDev = 0;
|
||||
phantomId = 0;
|
||||
|
||||
class BlktapController(BlkifController):
|
||||
def __init__(self, vm):
|
||||
@@ -12,3 +15,62 @@ class BlktapController(BlkifController):
|
||||
"""@see DevController#frontendRoot"""
|
||||
|
||||
return "%s/device/vbd" % self.vm.getDomainPath()
|
||||
|
||||
def getDeviceDetails(self, config):
|
||||
(devid, back, front) = BlkifController.getDeviceDetails(self, config)
|
||||
|
||||
phantomDevid = 0
|
||||
wrapped = False
|
||||
|
||||
try:
|
||||
imagetype = self.vm.info['image']['type']
|
||||
except:
|
||||
imagetype = ""
|
||||
|
||||
if imagetype == 'hvm':
|
||||
tdevname = back['dev']
|
||||
index = ['c', 'd', 'e', 'f', 'g', 'h', 'i', \
|
||||
'j', 'l', 'm', 'n', 'o', 'p']
|
||||
while True:
|
||||
global phantomDev
|
||||
global phantomId
|
||||
import os, stat
|
||||
|
||||
phantomId = phantomId + 1
|
||||
if phantomId == 16:
|
||||
if index[phantomDev] == index[-1]:
|
||||
if wrapped:
|
||||
raise VmError(" No loopback block \
|
||||
devices are available. ")
|
||||
wrapped = True
|
||||
phantomDev = 0
|
||||
else:
|
||||
phantomDev = phantomDev + 1
|
||||
phantomId = 1
|
||||
devname = 'xvd%s%d' % (index[phantomDev], phantomId)
|
||||
try:
|
||||
info = os.stat('/dev/%s' % devname)
|
||||
except:
|
||||
break
|
||||
|
||||
vbd = { 'mode': 'w', 'device': devname }
|
||||
fn = 'tap:%s' % back['params']
|
||||
|
||||
# recurse ... by creating the vbd, then fallthrough
|
||||
# and finish creating the original device
|
||||
|
||||
from xen.xend import XendDomain
|
||||
dom0 = XendDomain.instance().privilegedDomain()
|
||||
phantomDevid = dom0.create_phantom_vbd_with_vdi(vbd, fn)
|
||||
# we need to wait for this device at a higher level
|
||||
# the vbd that gets created will have a link to us
|
||||
# and will let them do it there
|
||||
|
||||
# add a hook to point to the phantom device,
|
||||
# root path is always the same (dom0 tap)
|
||||
if phantomDevid != 0:
|
||||
front['phantom_vbd'] = '/local/domain/0/backend/tap/0/%s' \
|
||||
% str(phantomDevid)
|
||||
|
||||
return (devid, back, front)
|
||||
|
||||
@@ -153,9 +153,9 @@ class DevController:
|
||||
log.debug("Waiting for %s.", devid)
|
||||
|
||||
if not self.hotplug:
|
||||
return
|
||||
|
||||
status = self.waitForBackend(devid)
|
||||
return
|
||||
|
||||
(status, err) = self.waitForBackend(devid)
|
||||
|
||||
if status == Timeout:
|
||||
self.destroyDevice(devid, False)
|
||||
@@ -165,25 +165,22 @@ class DevController:
|
||||
|
||||
elif status == Error:
|
||||
self.destroyDevice(devid, False)
|
||||
raise VmError("Device %s (%s) could not be connected. "
|
||||
"Backend device not found." %
|
||||
(devid, self.deviceClass))
|
||||
|
||||
if err is None:
|
||||
raise VmError("Device %s (%s) could not be connected. "
|
||||
"Backend device not found." %
|
||||
(devid, self.deviceClass))
|
||||
else:
|
||||
raise VmError("Device %s (%s) could not be connected. "
|
||||
"%s" % (devid, self.deviceClass, err))
|
||||
elif status == Missing:
|
||||
# Don't try to destroy the device; it's already gone away.
|
||||
raise VmError("Device %s (%s) could not be connected. "
|
||||
"Device not found." % (devid, self.deviceClass))
|
||||
|
||||
elif status == Busy:
|
||||
err = None
|
||||
frontpath = self.frontendPath(devid)
|
||||
backpath = xstransact.Read(frontpath, "backend")
|
||||
if backpath:
|
||||
err = xstransact.Read(backpath, HOTPLUG_ERROR_NODE)
|
||||
if not err:
|
||||
err = "Busy."
|
||||
|
||||
self.destroyDevice(devid, False)
|
||||
if err is None:
|
||||
err = "Busy."
|
||||
raise VmError("Device %s (%s) could not be connected.\n%s" %
|
||||
(devid, self.deviceClass, err))
|
||||
|
||||
@@ -476,19 +473,36 @@ class DevController:
|
||||
def waitForBackend(self, devid):
|
||||
|
||||
frontpath = self.frontendPath(devid)
|
||||
# lookup a phantom
|
||||
phantomPath = xstransact.Read(frontpath, 'phantom_vbd')
|
||||
if phantomPath is not None:
|
||||
log.debug("Waiting for %s's phantom %s.", devid, phantomPath)
|
||||
statusPath = phantomPath + '/' + HOTPLUG_STATUS_NODE
|
||||
ev = Event()
|
||||
result = { 'status': Timeout }
|
||||
xswatch(statusPath, hotplugStatusCallback, ev, result)
|
||||
ev.wait(DEVICE_CREATE_TIMEOUT)
|
||||
err = xstransact.Read(statusPath, HOTPLUG_ERROR_NODE)
|
||||
if result['status'] != 'Connected':
|
||||
return (result['status'], err)
|
||||
|
||||
backpath = xstransact.Read(frontpath, "backend")
|
||||
|
||||
|
||||
if backpath:
|
||||
statusPath = backpath + '/' + HOTPLUG_STATUS_NODE
|
||||
ev = Event()
|
||||
result = { 'status': Timeout }
|
||||
|
||||
|
||||
xswatch(statusPath, hotplugStatusCallback, ev, result)
|
||||
|
||||
ev.wait(DEVICE_CREATE_TIMEOUT)
|
||||
return result['status']
|
||||
|
||||
err = xstransact.Read(backpath, HOTPLUG_ERROR_NODE)
|
||||
|
||||
return (result['status'], err)
|
||||
else:
|
||||
return Missing
|
||||
return (Missing, None)
|
||||
|
||||
|
||||
def backendPath(self, backdom, devid):
|
||||
|
||||
@@ -45,14 +45,15 @@ main(int argc, char **argv)
|
||||
/* pass the memsize to xc_hvm_restore to find the store_mfn */
|
||||
store_mfn = hvm;
|
||||
ret = xc_hvm_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn,
|
||||
&store_mfn, console_evtchn, &console_mfn, pae, apic);
|
||||
&store_mfn, pae, apic);
|
||||
} else
|
||||
ret = xc_linux_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn,
|
||||
&store_mfn, console_evtchn, &console_mfn);
|
||||
|
||||
if (ret == 0) {
|
||||
printf("store-mfn %li\n", store_mfn);
|
||||
printf("console-mfn %li\n", console_mfn);
|
||||
if (!hvm)
|
||||
printf("console-mfn %li\n", console_mfn);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -57,7 +57,8 @@ unsigned char keycode_table[512];
|
||||
static void *kbd_layout;
|
||||
|
||||
static int btnmap[] = {
|
||||
BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, BTN_FORWARD, BTN_BACK
|
||||
BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, BTN_SIDE,
|
||||
BTN_EXTRA, BTN_FORWARD, BTN_BACK, BTN_TASK
|
||||
};
|
||||
|
||||
static void on_kbd_event(rfbBool down, rfbKeySym keycode, rfbClientPtr cl)
|
||||
@@ -73,11 +74,12 @@ static void on_kbd_event(rfbBool down, rfbKeySym keycode, rfbClientPtr cl)
|
||||
*/
|
||||
rfbScreenInfoPtr server = cl->screen;
|
||||
struct xenfb *xenfb = server->screenData;
|
||||
int scancode;
|
||||
|
||||
if( keycode >= 'A' && keycode <= 'Z' )
|
||||
if (keycode >= 'A' && keycode <= 'Z')
|
||||
keycode += 'a' - 'A';
|
||||
|
||||
int scancode = keycode_table[keysym2scancode(kbd_layout, keycode)];
|
||||
scancode = keycode_table[keysym2scancode(kbd_layout, keycode)];
|
||||
if (scancode == 0)
|
||||
return;
|
||||
if (xenfb_send_key(xenfb, down, scancode) < 0)
|
||||
|
||||
@@ -19,6 +19,11 @@ void machine_reboot_kexec(xen_kexec_image_t *image)
|
||||
printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void machine_kexec(xen_kexec_image_t *image)
|
||||
{
|
||||
printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/elf.h>
|
||||
#include <asm/percpu.h>
|
||||
#include <asm/kexec.h>
|
||||
#include <xen/types.h>
|
||||
#include <xen/irq.h>
|
||||
#include <asm/ipi.h>
|
||||
|
||||
@@ -106,7 +106,6 @@ void hvm_migrate_timers(struct vcpu *v)
|
||||
pit_migrate_timers(v);
|
||||
rtc_migrate_timers(v);
|
||||
hpet_migrate_timers(v);
|
||||
pmtimer_migrate_timers(v);
|
||||
if ( vcpu_vlapic(v)->pt.enabled )
|
||||
migrate_timer(&vcpu_vlapic(v)->pt.timer, v->processor);
|
||||
}
|
||||
@@ -170,7 +169,6 @@ void hvm_domain_destroy(struct domain *d)
|
||||
{
|
||||
pit_deinit(d);
|
||||
rtc_deinit(d);
|
||||
pmtimer_deinit(d);
|
||||
hpet_deinit(d);
|
||||
|
||||
if ( d->arch.hvm_domain.shared_page_va )
|
||||
|
||||
+42
-33
@@ -2,17 +2,6 @@
|
||||
#include <asm/hvm/io.h>
|
||||
#include <asm/hvm/support.h>
|
||||
|
||||
#define TMR_STS (1 << 0)
|
||||
static void pmt_update_status(void *opaque)
|
||||
{
|
||||
PMTState *s = opaque;
|
||||
s->pm1_status |= TMR_STS;
|
||||
|
||||
/* TODO: When TMR_EN == 1, generate a SCI event */
|
||||
|
||||
set_timer(&s->timer, NOW() + (1000000000ULL << 31) / FREQUENCE_PMTIMER);
|
||||
}
|
||||
|
||||
static int handle_pmt_io(ioreq_t *p)
|
||||
{
|
||||
struct vcpu *v = current;
|
||||
@@ -30,42 +19,62 @@ static int handle_pmt_io(ioreq_t *p)
|
||||
/* PM_TMR_BLK is read-only */
|
||||
return 1;
|
||||
} else if (p->dir == 1) { /* read */
|
||||
/* Set the correct value in the timer, accounting for time
|
||||
* elapsed since the last time we did that. */
|
||||
curr_gtime = hvm_get_guest_time(s->vcpu);
|
||||
s->pm1_timer += ((curr_gtime - s->last_gtime) * s->scale) >> 32;
|
||||
p->data = s->pm1_timer;
|
||||
s->pm.timer += ((curr_gtime - s->last_gtime) * s->scale) >> 32;
|
||||
p->data = s->pm.timer;
|
||||
s->last_gtime = curr_gtime;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pmtimer_save(struct domain *d, hvm_domain_context_t *h)
|
||||
{
|
||||
PMTState *s = &d->arch.hvm_domain.pl_time.vpmt;
|
||||
uint32_t x;
|
||||
|
||||
/* Update the counter to the guest's current time. We always save
|
||||
* with the domain paused, so the saved time should be after the
|
||||
* last_gtime, but just in case, make sure we only go forwards */
|
||||
x = ((s->vcpu->arch.hvm_vcpu.guest_time - s->last_gtime) * s->scale) >> 32;
|
||||
if ( x < 1UL<<31 )
|
||||
s->pm.timer += x;
|
||||
return hvm_save_entry(PMTIMER, 0, h, &s->pm);
|
||||
}
|
||||
|
||||
static int pmtimer_load(struct domain *d, hvm_domain_context_t *h)
|
||||
{
|
||||
PMTState *s = &d->arch.hvm_domain.pl_time.vpmt;
|
||||
|
||||
/* Reload the counter */
|
||||
if ( hvm_load_entry(PMTIMER, h, &s->pm) )
|
||||
return -EINVAL;
|
||||
|
||||
/* Calculate future counter values from now. */
|
||||
s->last_gtime = hvm_get_guest_time(s->vcpu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HVM_REGISTER_SAVE_RESTORE(PMTIMER, pmtimer_save, pmtimer_load,
|
||||
1, HVMSR_PER_DOM);
|
||||
|
||||
|
||||
void pmtimer_init(struct vcpu *v, int base)
|
||||
{
|
||||
PMTState *s = &v->domain->arch.hvm_domain.pl_time.vpmt;
|
||||
|
||||
s->pm1_timer = 0;
|
||||
s->pm1_status = 0;
|
||||
s->pm.timer = 0;
|
||||
s->scale = ((uint64_t)FREQUENCE_PMTIMER << 32) / ticks_per_sec(v);
|
||||
s->vcpu = v;
|
||||
|
||||
init_timer(&s->timer, pmt_update_status, s, v->processor);
|
||||
/* ACPI supports a 32-bit power management timer */
|
||||
set_timer(&s->timer, NOW() + (1000000000ULL << 31) / FREQUENCE_PMTIMER);
|
||||
|
||||
/* Not implemented: we should set TMR_STS (bit 0 of PM1a_STS) every
|
||||
* time the timer's top bit flips, and generate an SCI if TMR_EN
|
||||
* (bit 0 of PM1a_EN) is set. For now, those registers are in
|
||||
* qemu-dm, and we just calculate the timer's value on demand. */
|
||||
|
||||
register_portio_handler(v->domain, base, 4, handle_pmt_io);
|
||||
}
|
||||
|
||||
void pmtimer_migrate_timers(struct vcpu *v)
|
||||
{
|
||||
struct PMTState *vpmt = &v->domain->arch.hvm_domain.pl_time.vpmt;
|
||||
|
||||
if (vpmt->vcpu == v)
|
||||
migrate_timer(&vpmt->timer, v->processor);
|
||||
}
|
||||
|
||||
void pmtimer_deinit(struct domain *d)
|
||||
{
|
||||
PMTState *s = &d->arch.hvm_domain.pl_time.vpmt;
|
||||
|
||||
kill_timer(&s->timer);
|
||||
}
|
||||
@@ -15,11 +15,15 @@
|
||||
#include <xen/types.h>
|
||||
#include <xen/console.h>
|
||||
#include <xen/kexec.h>
|
||||
#include <asm/kexec.h>
|
||||
#include <xen/domain_page.h>
|
||||
#include <asm/fixmap.h>
|
||||
#include <asm/hvm/hvm.h>
|
||||
|
||||
typedef void (*relocate_new_kernel_t)(
|
||||
unsigned long indirection_page,
|
||||
unsigned long *page_list,
|
||||
unsigned long start_address);
|
||||
|
||||
int machine_kexec_load(int type, int slot, xen_kexec_image_t *image)
|
||||
{
|
||||
unsigned long prev_ma = 0;
|
||||
@@ -40,8 +44,26 @@ int machine_kexec_load(int type, int slot, xen_kexec_image_t *image)
|
||||
else
|
||||
{
|
||||
/* Odd pages: va for previous ma. */
|
||||
set_fixmap(fix_base + (k >> 1), prev_ma);
|
||||
image->page_list[k] = fix_to_virt(fix_base + (k >> 1));
|
||||
if ( IS_COMPAT(dom0) )
|
||||
{
|
||||
|
||||
/*
|
||||
* The compatability bounce code sets up a page table
|
||||
* with a 1-1 mapping of the first 1G of memory so
|
||||
* VA==PA here.
|
||||
*
|
||||
* This Linux purgatory code still sets up separate
|
||||
* high and low mappings on the control page (entries
|
||||
* 0 and 1) but it is harmless if they are equal since
|
||||
* that PT is not live at the time.
|
||||
*/
|
||||
image->page_list[k] = prev_ma;
|
||||
}
|
||||
else
|
||||
{
|
||||
set_fixmap(fix_base + (k >> 1), prev_ma);
|
||||
image->page_list[k] = fix_to_virt(fix_base + (k >> 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +116,31 @@ void machine_reboot_kexec(xen_kexec_image_t *image)
|
||||
BUG();
|
||||
}
|
||||
|
||||
void machine_kexec(xen_kexec_image_t *image)
|
||||
{
|
||||
#ifdef CONFIG_COMPAT
|
||||
if ( IS_COMPAT(dom0) )
|
||||
{
|
||||
extern void compat_machine_kexec(unsigned long rnk,
|
||||
unsigned long indirection_page,
|
||||
unsigned long *page_list,
|
||||
unsigned long start_address);
|
||||
compat_machine_kexec(image->page_list[1],
|
||||
image->indirection_page,
|
||||
image->page_list,
|
||||
image->start_address);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
relocate_new_kernel_t rnk;
|
||||
|
||||
rnk = (relocate_new_kernel_t) image->page_list[1];
|
||||
(*rnk)(image->indirection_page, image->page_list,
|
||||
image->start_address);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
obj-y += entry.o
|
||||
obj-y += compat_kexec.o
|
||||
obj-y += gpr_switch.o
|
||||
obj-y += mm.o
|
||||
obj-y += traps.o
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Compatibility kexec handler.
|
||||
*/
|
||||
|
||||
#include <xen/config.h>
|
||||
|
||||
#include <asm/asm_defns.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
.text
|
||||
|
||||
.code64
|
||||
|
||||
ENTRY(compat_machine_kexec)
|
||||
/* x86/64 x86/32 */
|
||||
/* %rdi - relocate_new_kernel_t CALL */
|
||||
/* %rsi - indirection page 4(%esp) */
|
||||
/* %rdx - page_list 8(%esp) */
|
||||
/* %rcx - start address 12(%esp) */
|
||||
/* cpu has pae 16(%esp) */
|
||||
|
||||
/* Shim the 64 bit page_list into a 32 bit page_list. */
|
||||
mov $12,%r9
|
||||
lea compat_page_list(%rip), %rbx
|
||||
1: dec %r9
|
||||
movl (%rdx,%r9,8),%eax
|
||||
movl %eax,(%rbx,%r9,4)
|
||||
test %r9,%r9
|
||||
jnz 1b
|
||||
|
||||
movq %rbx,%rdx
|
||||
mov $__PAGE_OFFSET,%rbx
|
||||
sub %rbx, %rdx
|
||||
|
||||
/*
|
||||
* Setup an identity mapped region in PML4[0] of idle page
|
||||
* table.
|
||||
*/
|
||||
lea idle_pg_table_l3(%rip),%rax
|
||||
sub %rbx,%rax
|
||||
or $0x63,%rax
|
||||
mov %rax, idle_pg_table(%rip)
|
||||
|
||||
/* Switch to idle page table. */
|
||||
movq $(idle_pg_table - __PAGE_OFFSET), %rax
|
||||
movq %rax, %cr3
|
||||
|
||||
/* Jump to low identity mapping in compatibility mode. */
|
||||
ljmp *compatibility_mode_far(%rip)
|
||||
ud2
|
||||
|
||||
compatibility_mode_far:
|
||||
.long compatibility_mode - __PAGE_OFFSET
|
||||
.long __HYPERVISOR_CS32
|
||||
|
||||
.code32
|
||||
|
||||
compatibility_mode:
|
||||
/* Setup some sane segments. */
|
||||
movl $__HYPERVISOR_DS32, %eax
|
||||
movl %eax, %ds
|
||||
movl %eax, %es
|
||||
movl %eax, %fs
|
||||
movl %eax, %gs
|
||||
movl %eax, %ss
|
||||
|
||||
/* Push arguments onto stack. */
|
||||
pushl $1 /* 16(%esp) - cpu has pae */
|
||||
pushl %ecx /* 12(%esp) - start address */
|
||||
pushl %edx /* 8(%esp) - page list */
|
||||
pushl %esi /* 4(%esp) - indirection page */
|
||||
pushl %edi /* 0(%esp) - CALL */
|
||||
|
||||
/* Disable paging and therefore leave 64 bit mode. */
|
||||
movl %cr0, %eax
|
||||
andl $~X86_CR0_PG, %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
/* Switch to 32 bit page table. */
|
||||
movl $compat_pg_table - __PAGE_OFFSET, %eax
|
||||
movl %eax, %cr3
|
||||
|
||||
/* Clear MSR_EFER[LME], disabling long mode */
|
||||
movl $MSR_EFER,%ecx
|
||||
rdmsr
|
||||
btcl $_EFER_LME,%eax
|
||||
wrmsr
|
||||
|
||||
/* Re-enable paging, but only 32 bit mode now. */
|
||||
movl %cr0, %eax
|
||||
orl $X86_CR0_PG, %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
popl %eax
|
||||
call *%eax
|
||||
ud2
|
||||
|
||||
compat_page_list:
|
||||
.fill 12,4,0
|
||||
|
||||
.align 32,0
|
||||
|
||||
/*
|
||||
* These compat page tables contain an identity mapping of the
|
||||
* first 1G of the physical address space.
|
||||
*/
|
||||
compat_pg_table:
|
||||
.long compat_pg_table_l2 + 0*PAGE_SIZE + 0x01 - __PAGE_OFFSET, 0
|
||||
.long 0, 0
|
||||
.long 0, 0
|
||||
.long 0, 0
|
||||
|
||||
.align 4096,0
|
||||
|
||||
compat_pg_table_l2:
|
||||
.macro identmap from=0, count=512
|
||||
.if \count-1
|
||||
identmap "(\from+0)","(\count/2)"
|
||||
identmap "(\from+(0x200000*(\count/2)))","(\count/2)"
|
||||
.else
|
||||
.quad 0x00000000000000e3 + \from
|
||||
.endif
|
||||
.endm
|
||||
|
||||
identmap
|
||||
@@ -6,7 +6,6 @@
|
||||
* - Magnus Damm <magnus@valinux.co.jp>
|
||||
*/
|
||||
|
||||
#include <asm/kexec.h>
|
||||
#include <xen/lib.h>
|
||||
#include <xen/ctype.h>
|
||||
#include <xen/errno.h>
|
||||
|
||||
+6
-4
@@ -175,11 +175,13 @@ int guest_remove_page(struct domain *d, unsigned long gmfn)
|
||||
|
||||
if ( unlikely(!page_is_removable(page)) )
|
||||
{
|
||||
shadow_drop_references(d, page);
|
||||
/* We'll make this a guest-visible error in future, so take heed! */
|
||||
gdprintk(XENLOG_INFO, "Dom%d freeing in-use page %lx (pseudophys %lx):"
|
||||
" count=%lx type=%lx\n",
|
||||
d->domain_id, mfn, get_gpfn_from_mfn(mfn),
|
||||
(unsigned long)page->count_info, page->u.inuse.type_info);
|
||||
if ( !page_is_removable(page) )
|
||||
gdprintk(XENLOG_INFO, "Dom%d freeing in-use page %lx "
|
||||
"(pseudophys %lx): count=%lx type=%lx\n",
|
||||
d->domain_id, mfn, get_gpfn_from_mfn(mfn),
|
||||
(unsigned long)page->count_info, page->u.inuse.type_info);
|
||||
}
|
||||
|
||||
guest_physmap_remove_page(d, gmfn, mfn);
|
||||
|
||||
@@ -223,7 +223,7 @@ int console_steal(int handle, void (*fn)(const char *))
|
||||
if ( (handle == -1) || (handle != sercon_handle) )
|
||||
return 0;
|
||||
|
||||
if ( serial_steal_fn == NULL )
|
||||
if ( serial_steal_fn != NULL )
|
||||
return -EBUSY;
|
||||
|
||||
serial_steal_fn = fn;
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
#ifndef __IA64_KEXEC_H__
|
||||
#define __IA64_KEXEC_H__
|
||||
|
||||
#include <xen/lib.h> /* for printk() used in stub */
|
||||
#include <xen/types.h>
|
||||
#include <public/xen.h>
|
||||
#include <xen/kexec.h>
|
||||
|
||||
static inline void machine_kexec(xen_kexec_image_t *image)
|
||||
{
|
||||
printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
#endif /* __IA64_KEXEC_H__ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
#ifndef _ASM_KEXEC_H__
|
||||
#define _ASM_KEXEC_H__
|
||||
|
||||
#include <xen/lib.h> /* for printk() used in stub */
|
||||
#include <xen/types.h>
|
||||
#include <public/xen.h>
|
||||
#include <xen/kexec.h>
|
||||
|
||||
static inline void machine_kexec(xen_kexec_image_t *image)
|
||||
{
|
||||
printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
#endif /* _ASM_KEXEC_H__ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
|
||||
@@ -145,9 +145,9 @@
|
||||
* Compatibility guest area layout:
|
||||
* 0x0000000000000000 - 0x00000000f57fffff [3928MB, PML4:0]
|
||||
* Guest-defined use.
|
||||
* 0x0000000f58000000 - 0x00000000ffffffff [168MB, PML4:0]
|
||||
* 0x00000000f5800000 - 0x00000000ffffffff [168MB, PML4:0]
|
||||
* Read-only machine-to-phys translation table (GUEST ACCESSIBLE).
|
||||
* 0x0000000000000000 - 0x00000000ffffffff [508GB, PML4:0]
|
||||
* 0x0000000100000000 - 0x0000007fffffffff [508GB, PML4:0]
|
||||
* Unused.
|
||||
* 0x0000008000000000 - 0x000000ffffffffff [512GB, 2^39 bytes, PML4:1]
|
||||
* Hypercall argument translation area.
|
||||
|
||||
@@ -94,14 +94,12 @@ typedef struct RTCState {
|
||||
struct periodic_time pt;
|
||||
} RTCState;
|
||||
|
||||
#define FREQUENCE_PMTIMER 3579545
|
||||
#define FREQUENCE_PMTIMER 3579545 /* Timer should run at 3.579545 MHz */
|
||||
typedef struct PMTState {
|
||||
uint32_t pm1_timer;
|
||||
uint32_t pm1_status;
|
||||
uint64_t last_gtime;
|
||||
struct timer timer;
|
||||
uint64_t scale;
|
||||
struct vcpu *vcpu;
|
||||
struct hvm_hw_pmtimer pm; /* 32bit timer value */
|
||||
struct vcpu *vcpu; /* Keeps sync with this vcpu's guest-time */
|
||||
uint64_t last_gtime; /* Last (guest) time we updated the timer */
|
||||
uint64_t scale; /* Multiplier to get from tsc to timer ticks */
|
||||
} PMTState;
|
||||
|
||||
struct pl_time { /* platform time */
|
||||
@@ -134,8 +132,6 @@ void rtc_migrate_timers(struct vcpu *v);
|
||||
void rtc_deinit(struct domain *d);
|
||||
int is_rtc_periodic_irq(void *opaque);
|
||||
void pmtimer_init(struct vcpu *v, int base);
|
||||
void pmtimer_migrate_timers(struct vcpu *v);
|
||||
void pmtimer_deinit(struct domain *d);
|
||||
|
||||
void hpet_migrate_timers(struct vcpu *v);
|
||||
void hpet_init(struct vcpu *v);
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
#ifndef __X86_KEXEC_H__
|
||||
#define __X86_KEXEC_H__
|
||||
|
||||
#ifdef __x86_64__
|
||||
#include <asm/x86_64/kexec.h>
|
||||
#else
|
||||
#include <asm/x86_32/kexec.h>
|
||||
#endif
|
||||
|
||||
#endif /* __X86_KEXEC_H__ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -355,8 +355,9 @@ int sh_remove_all_mappings(struct vcpu *v, mfn_t target_mfn);
|
||||
static inline void
|
||||
shadow_drop_references(struct domain *d, struct page_info *p)
|
||||
{
|
||||
/* See the comment about locking in sh_remove_all_mappings */
|
||||
sh_remove_all_mappings(d->vcpu[0], _mfn(page_to_mfn(p)));
|
||||
if ( unlikely(shadow_mode_enabled(d)) )
|
||||
/* See the comment about locking in sh_remove_all_mappings */
|
||||
sh_remove_all_mappings(d->vcpu[0], _mfn(page_to_mfn(p)));
|
||||
}
|
||||
|
||||
/* Remove all shadows of the guest mfn. */
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
/******************************************************************************
|
||||
* kexec.h
|
||||
*
|
||||
* Based heavily on machine_kexec.c and kexec.h from Linux 2.6.19-rc1
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __X86_KEXEC_X86_32_H__
|
||||
#define __X86_KEXEC_X86_32_H__
|
||||
|
||||
#include <xen/types.h>
|
||||
#include <xen/kexec.h>
|
||||
|
||||
typedef asmlinkage void (*relocate_new_kernel_t)(
|
||||
unsigned long indirection_page,
|
||||
unsigned long page_list,
|
||||
unsigned long start_address,
|
||||
unsigned int has_pae);
|
||||
|
||||
static inline void machine_kexec(xen_kexec_image_t *image)
|
||||
{
|
||||
relocate_new_kernel_t rnk;
|
||||
|
||||
rnk = (relocate_new_kernel_t) image->page_list[1];
|
||||
(*rnk)(image->indirection_page, (unsigned long)image->page_list,
|
||||
image->start_address, (unsigned long)cpu_has_pae);
|
||||
}
|
||||
|
||||
#endif /* __X86_KEXEC_X86_32_H__ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -1,38 +0,0 @@
|
||||
/******************************************************************************
|
||||
* kexec.h
|
||||
*
|
||||
* Based heavily on machine_kexec.c and kexec.h from Linux 2.6.19-rc1
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __X86_64_KEXEC_H__
|
||||
#define __X86_64_KEXEC_H__
|
||||
|
||||
#include <xen/types.h>
|
||||
#include <xen/kexec.h>
|
||||
|
||||
typedef void (*relocate_new_kernel_t)(
|
||||
unsigned long indirection_page,
|
||||
unsigned long page_list,
|
||||
unsigned long start_address);
|
||||
|
||||
static inline void machine_kexec(xen_kexec_image_t *image)
|
||||
{
|
||||
relocate_new_kernel_t rnk;
|
||||
|
||||
rnk = (relocate_new_kernel_t) image->page_list[1];
|
||||
(*rnk)(image->indirection_page, (unsigned long)image->page_list,
|
||||
image->start_address);
|
||||
}
|
||||
|
||||
#endif /* __X86_64_KEXEC_H__ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-set-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -382,10 +382,20 @@ struct hvm_hw_hpet {
|
||||
DECLARE_HVM_SAVE_TYPE(HPET, 12, struct hvm_hw_hpet);
|
||||
|
||||
|
||||
/*
|
||||
* PM timer
|
||||
*/
|
||||
|
||||
struct hvm_hw_pmtimer {
|
||||
uint32_t timer;
|
||||
};
|
||||
|
||||
DECLARE_HVM_SAVE_TYPE(PMTIMER, 13, struct hvm_hw_pmtimer);
|
||||
|
||||
/*
|
||||
* Largest type-code in use
|
||||
*/
|
||||
#define HVM_SAVE_CODE_MAX 12
|
||||
#define HVM_SAVE_CODE_MAX 13
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -25,6 +25,7 @@ int machine_kexec_load(int type, int slot, xen_kexec_image_t *image);
|
||||
void machine_kexec_unload(int type, int slot, xen_kexec_image_t *image);
|
||||
void machine_kexec_reserved(xen_kexec_reserve_t *reservation);
|
||||
void machine_reboot_kexec(xen_kexec_image_t *image);
|
||||
void machine_kexec(xen_kexec_image_t *image);
|
||||
void kexec_crash(void);
|
||||
void kexec_crash_save_cpu(void);
|
||||
crash_xen_info_t *kexec_crash_save_info(void);
|
||||
|
||||