Merge with xen-ia64-unstable.hg.

This commit is contained in:
kfraser@localhost.localdomain committed 2007-02-08 17:27:30 +00:00
commit 6f7ae0fe6f
44 files changed
+786 -373

No files matched your search

+1
View File
@@ -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__ */
+23 -23
View File
@@ -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",
+7
View File
@@ -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"
+3 -2
View File
@@ -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() {
+4
View File
@@ -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;
+4
View File
@@ -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);
+4 -2
View File
@@ -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
View File
@@ -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);
+2 -3
View File
@@ -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
View File
@@ -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);
+1 -2
View File
@@ -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);
/**
+1 -2
View File
@@ -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
View File
@@ -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
+108
View File
@@ -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;
}
+5 -2
View File
@@ -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:
+41
View File
@@ -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':
+16 -4
View File
@@ -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)
+56 -2
View File
@@ -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)
+32 -18
View File
@@ -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):
+3 -2
View File
@@ -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
View File
@@ -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)
+5
View File
@@ -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
-1
View File
@@ -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>
-2
View File
@@ -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
View File
@@ -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);
}
+50 -3
View File
@@ -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
View File
@@ -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
+126
View File
@@ -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
-1
View File
@@ -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
View File
@@ -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);
+1 -1
View File
@@ -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;
-25
View File
@@ -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:
*/
-25
View File
@@ -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:
*/
+2 -2
View File
@@ -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.
+5 -9
View File
@@ -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);
-20
View File
@@ -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:
*/
+3 -2
View File
@@ -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. */
-39
View File
@@ -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:
*/
-38
View File
@@ -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:
*/
+11 -1
View File
@@ -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
/*
+1
View File
@@ -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);
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.