mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
Merge with xen-ia64-unstable.hg
This commit is contained in:
commit
3a8a387d6e
29 files changed
+464
-232
No files matched your search
@@ -22,7 +22,7 @@
|
||||
^\.pc
|
||||
^TAGS$
|
||||
^tags$
|
||||
^build.*$
|
||||
^build-.*$
|
||||
^dist/.*$
|
||||
^docs/.*\.aux$
|
||||
^docs/.*\.dvi$
|
||||
|
||||
@@ -199,3 +199,7 @@ Xend (the Xen daemon) has the following runtime dependencies:
|
||||
* For optional PAM support, PyPAM:
|
||||
URL: http://www.pangalactic.org/PyPAM/
|
||||
Debian: python-pam
|
||||
|
||||
* For optional XenAPI support in XM, PyXML:
|
||||
URL: http://pyxml.sourceforge.net
|
||||
YUM: PyXML
|
||||
@@ -622,14 +622,14 @@ static int network_open(struct net_device *dev)
|
||||
|
||||
memset(&np->stats, 0, sizeof(np->stats));
|
||||
|
||||
spin_lock(&np->rx_lock);
|
||||
spin_lock_bh(&np->rx_lock);
|
||||
if (netfront_carrier_ok(np)) {
|
||||
network_alloc_rx_buffers(dev);
|
||||
np->rx.sring->rsp_event = np->rx.rsp_cons + 1;
|
||||
if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx))
|
||||
netif_rx_schedule(dev);
|
||||
}
|
||||
spin_unlock(&np->rx_lock);
|
||||
spin_unlock_bh(&np->rx_lock);
|
||||
|
||||
network_maybe_wake_tx(dev);
|
||||
|
||||
@@ -1307,7 +1307,7 @@ static int netif_poll(struct net_device *dev, int *pbudget)
|
||||
int pages_flipped = 0;
|
||||
int err;
|
||||
|
||||
spin_lock(&np->rx_lock);
|
||||
spin_lock(&np->rx_lock); /* no need for spin_lock_bh() in ->poll() */
|
||||
|
||||
if (unlikely(!netfront_carrier_ok(np))) {
|
||||
spin_unlock(&np->rx_lock);
|
||||
@@ -1520,7 +1520,7 @@ static void netif_release_rx_bufs(struct netfront_info *np)
|
||||
|
||||
skb_queue_head_init(&free_list);
|
||||
|
||||
spin_lock(&np->rx_lock);
|
||||
spin_lock_bh(&np->rx_lock);
|
||||
|
||||
for (id = 0; id < NET_RX_RING_SIZE; id++) {
|
||||
if ((ref = np->grant_rx_ref[id]) == GRANT_INVALID_REF) {
|
||||
@@ -1588,7 +1588,7 @@ static void netif_release_rx_bufs(struct netfront_info *np)
|
||||
while ((skb = __skb_dequeue(&free_list)) != NULL)
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
spin_unlock(&np->rx_lock);
|
||||
spin_unlock_bh(&np->rx_lock);
|
||||
}
|
||||
|
||||
static int network_close(struct net_device *dev)
|
||||
@@ -1708,8 +1708,8 @@ static int network_connect(struct net_device *dev)
|
||||
IPRINTK("device %s has %sing receive path.\n",
|
||||
dev->name, np->copying_receiver ? "copy" : "flipp");
|
||||
|
||||
spin_lock_bh(&np->rx_lock);
|
||||
spin_lock_irq(&np->tx_lock);
|
||||
spin_lock(&np->rx_lock);
|
||||
|
||||
/*
|
||||
* Recovery procedure:
|
||||
@@ -1761,8 +1761,8 @@ static int network_connect(struct net_device *dev)
|
||||
network_tx_buf_gc(dev);
|
||||
network_alloc_rx_buffers(dev);
|
||||
|
||||
spin_unlock(&np->rx_lock);
|
||||
spin_unlock_irq(&np->tx_lock);
|
||||
spin_unlock_bh(&np->rx_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1818,7 +1818,7 @@ static ssize_t store_rxbuf_min(struct class_device *cd,
|
||||
if (target > RX_MAX_TARGET)
|
||||
target = RX_MAX_TARGET;
|
||||
|
||||
spin_lock(&np->rx_lock);
|
||||
spin_lock_bh(&np->rx_lock);
|
||||
if (target > np->rx_max_target)
|
||||
np->rx_max_target = target;
|
||||
np->rx_min_target = target;
|
||||
@@ -1827,7 +1827,7 @@ static ssize_t store_rxbuf_min(struct class_device *cd,
|
||||
|
||||
network_alloc_rx_buffers(netdev);
|
||||
|
||||
spin_unlock(&np->rx_lock);
|
||||
spin_unlock_bh(&np->rx_lock);
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -1861,7 +1861,7 @@ static ssize_t store_rxbuf_max(struct class_device *cd,
|
||||
if (target > RX_MAX_TARGET)
|
||||
target = RX_MAX_TARGET;
|
||||
|
||||
spin_lock(&np->rx_lock);
|
||||
spin_lock_bh(&np->rx_lock);
|
||||
if (target < np->rx_min_target)
|
||||
np->rx_min_target = target;
|
||||
np->rx_max_target = target;
|
||||
@@ -1870,7 +1870,7 @@ static ssize_t store_rxbuf_max(struct class_device *cd,
|
||||
|
||||
network_alloc_rx_buffers(netdev);
|
||||
|
||||
spin_unlock(&np->rx_lock);
|
||||
spin_unlock_bh(&np->rx_lock);
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -2033,11 +2033,11 @@ inetdev_notify(struct notifier_block *this, unsigned long event, void *ptr)
|
||||
static void netif_disconnect_backend(struct netfront_info *info)
|
||||
{
|
||||
/* Stop old i/f to prevent errors whilst we rebuild the state. */
|
||||
spin_lock_bh(&info->rx_lock);
|
||||
spin_lock_irq(&info->tx_lock);
|
||||
spin_lock(&info->rx_lock);
|
||||
netfront_carrier_off(info);
|
||||
spin_unlock(&info->rx_lock);
|
||||
spin_unlock_irq(&info->tx_lock);
|
||||
spin_unlock_bh(&info->rx_lock);
|
||||
|
||||
if (info->irq)
|
||||
unbind_from_irqhandler(info->irq, info->netdev);
|
||||
|
||||
@@ -688,33 +688,22 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
|
||||
ERROR("error zeroing magic pages");
|
||||
goto out;
|
||||
}
|
||||
|
||||
xc_set_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, magic_pfns[0]);
|
||||
xc_set_hvm_param(xc_handle, dom, HVM_PARAM_BUFIOREQ_PFN, magic_pfns[1]);
|
||||
xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, magic_pfns[2]);
|
||||
xc_set_hvm_param(xc_handle, dom, HVM_PARAM_PAE_ENABLED, pae);
|
||||
xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_EVTCHN, store_evtchn);
|
||||
*store_mfn = magic_pfns[2];
|
||||
|
||||
/* Read vcpu contexts */
|
||||
for ( i = 0; i <= max_vcpu_id; i++ )
|
||||
|
||||
if ( (rc = xc_set_hvm_param(xc_handle, dom,
|
||||
HVM_PARAM_IOREQ_PFN, magic_pfns[0]))
|
||||
|| (rc = xc_set_hvm_param(xc_handle, dom,
|
||||
HVM_PARAM_BUFIOREQ_PFN, magic_pfns[1]))
|
||||
|| (rc = xc_set_hvm_param(xc_handle, dom,
|
||||
HVM_PARAM_STORE_PFN, magic_pfns[2]))
|
||||
|| (rc = xc_set_hvm_param(xc_handle, dom,
|
||||
HVM_PARAM_PAE_ENABLED, pae))
|
||||
|| (rc = xc_set_hvm_param(xc_handle, dom,
|
||||
HVM_PARAM_STORE_EVTCHN, store_evtchn)) )
|
||||
{
|
||||
if ( !(vcpumap & (1ULL << i)) )
|
||||
continue;
|
||||
|
||||
if ( !read_exact(io_fd, &(ctxt), sizeof(ctxt)) )
|
||||
{
|
||||
ERROR("error read vcpu context.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ( (rc = xc_vcpu_setcontext(xc_handle, dom, i, &ctxt)) )
|
||||
{
|
||||
ERROR("Could not set vcpu context, rc=%d", rc);
|
||||
goto out;
|
||||
}
|
||||
rc = 1;
|
||||
ERROR("error setting HVM params: %i", rc);
|
||||
goto out;
|
||||
}
|
||||
*store_mfn = magic_pfns[2];
|
||||
|
||||
/* Read HVM context */
|
||||
if ( !read_exact(io_fd, &rec_len, sizeof(uint32_t)) )
|
||||
|
||||
@@ -378,8 +378,7 @@ static int analysis_phase(int xc_handle, uint32_t domid, int p2m_size,
|
||||
|
||||
|
||||
static int suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd,
|
||||
int dom, xc_dominfo_t *info,
|
||||
vcpu_guest_context_t *ctxt)
|
||||
int dom, xc_dominfo_t *info)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
@@ -397,10 +396,6 @@ static int suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( xc_vcpu_getcontext(xc_handle, dom, 0, ctxt) )
|
||||
ERROR("Could not get vcpu context");
|
||||
|
||||
|
||||
if ( info->dying )
|
||||
{
|
||||
ERROR("domain is dying");
|
||||
@@ -663,10 +658,11 @@ static xen_pfn_t *xc_map_m2p(int xc_handle,
|
||||
static xen_pfn_t *map_and_save_p2m_table(int xc_handle,
|
||||
int io_fd,
|
||||
uint32_t dom,
|
||||
vcpu_guest_context_t *ctxt,
|
||||
unsigned long p2m_size,
|
||||
shared_info_t *live_shinfo)
|
||||
{
|
||||
vcpu_guest_context_t ctxt;
|
||||
|
||||
/* Double and single indirect references to the live P2M table */
|
||||
xen_pfn_t *live_p2m_frame_list_list = NULL;
|
||||
xen_pfn_t *live_p2m_frame_list = NULL;
|
||||
@@ -730,13 +726,19 @@ static xen_pfn_t *map_and_save_p2m_table(int xc_handle,
|
||||
}
|
||||
}
|
||||
|
||||
if ( xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt) )
|
||||
{
|
||||
ERROR("Could not get vcpu context");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write an extended-info structure to inform the restore code that
|
||||
* a PAE guest understands extended CR3 (PDPTs above 4GB). Turns off
|
||||
* slow paths in the restore code.
|
||||
*/
|
||||
if ( (pt_levels == 3) &&
|
||||
(ctxt->vm_assist & (1UL << VMASST_TYPE_pae_extended_cr3)) )
|
||||
(ctxt.vm_assist & (1UL << VMASST_TYPE_pae_extended_cr3)) )
|
||||
{
|
||||
unsigned long signature = ~0UL;
|
||||
uint32_t tot_sz = sizeof(struct vcpu_guest_context) + 8;
|
||||
@@ -746,7 +748,7 @@ static xen_pfn_t *map_and_save_p2m_table(int xc_handle,
|
||||
!write_exact(io_fd, &tot_sz, sizeof(tot_sz)) ||
|
||||
!write_exact(io_fd, &chunk_sig, 4) ||
|
||||
!write_exact(io_fd, &chunk_sz, sizeof(chunk_sz)) ||
|
||||
!write_exact(io_fd, ctxt, sizeof(*ctxt)) )
|
||||
!write_exact(io_fd, &ctxt, sizeof(ctxt)) )
|
||||
{
|
||||
ERROR("write: extended info");
|
||||
goto out;
|
||||
@@ -853,11 +855,6 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt) )
|
||||
{
|
||||
ERROR("Could not get vcpu context");
|
||||
goto out;
|
||||
}
|
||||
shared_info_frame = info.shared_info_frame;
|
||||
|
||||
/* Map the shared info frame */
|
||||
@@ -900,7 +897,7 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
else
|
||||
{
|
||||
/* This is a non-live suspend. Suspend the domain .*/
|
||||
if ( suspend_and_state(suspend, xc_handle, io_fd, dom, &info, &ctxt) )
|
||||
if ( suspend_and_state(suspend, xc_handle, io_fd, dom, &info) )
|
||||
{
|
||||
ERROR("Domain appears not to have suspended");
|
||||
goto out;
|
||||
@@ -999,7 +996,7 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
|
||||
/* Map the P2M table, and write the list of P2M frames */
|
||||
live_p2m = map_and_save_p2m_table(xc_handle, io_fd, dom,
|
||||
&ctxt, p2m_size, live_shinfo);
|
||||
p2m_size, live_shinfo);
|
||||
if ( live_p2m == NULL )
|
||||
{
|
||||
ERROR("Failed to map/save the p2m frame list");
|
||||
@@ -1304,17 +1301,13 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
DPRINTF("Start last iteration\n");
|
||||
last_iter = 1;
|
||||
|
||||
if ( suspend_and_state(suspend, xc_handle, io_fd, dom, &info,
|
||||
&ctxt) )
|
||||
if ( suspend_and_state(suspend, xc_handle, io_fd, dom, &info) )
|
||||
{
|
||||
ERROR("Domain appears not to have suspended");
|
||||
goto out;
|
||||
}
|
||||
|
||||
DPRINTF("SUSPEND shinfo %08lx eip %08lx edx %08lx\n",
|
||||
info.shared_info_frame,
|
||||
(unsigned long)ctxt.user_regs.eip,
|
||||
(unsigned long)ctxt.user_regs.edx);
|
||||
DPRINTF("SUSPEND shinfo %08lx\n", info.shared_info_frame);
|
||||
}
|
||||
|
||||
if ( xc_shadow_control(xc_handle, dom,
|
||||
@@ -1410,27 +1403,6 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Save vcpu contexts */
|
||||
|
||||
for ( i = 0; i <= info.max_vcpu_id; i++ )
|
||||
{
|
||||
if ( !(vcpumap & (1ULL << i)) )
|
||||
continue;
|
||||
|
||||
if ( xc_vcpu_getcontext(xc_handle, dom, i, &ctxt) )
|
||||
{
|
||||
ERROR("HVM:Could not get vcpu context");
|
||||
goto out;
|
||||
}
|
||||
|
||||
DPRINTF("write vcpu %d context.\n", i);
|
||||
if ( !write_exact(io_fd, &(ctxt), sizeof(ctxt)) )
|
||||
{
|
||||
ERROR("write vcpu context failed!\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get HVM context from Xen and save it too */
|
||||
if ( (rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf,
|
||||
hvm_buf_size)) == -1 )
|
||||
@@ -1494,6 +1466,12 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
}
|
||||
}
|
||||
|
||||
if ( xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt) )
|
||||
{
|
||||
ERROR("Could not get vcpu context");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Canonicalise the suspend-record frame number. */
|
||||
if ( !translate_mfn_to_pfn(&ctxt.user_regs.edx) )
|
||||
{
|
||||
|
||||
@@ -198,18 +198,6 @@ __attribute__((weak))
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int xc_get_hvm_param(
|
||||
int handle, domid_t dom, int param, unsigned long *value)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int xc_set_hvm_param(
|
||||
int handle, domid_t dom, int param, unsigned long value)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
|
||||
+11
-7
@@ -61,13 +61,6 @@ def get_active_partition(file):
|
||||
if struct.unpack("<c", buf[poff:poff+1]) == ('\x80',):
|
||||
return buf[poff:poff+16]
|
||||
|
||||
# type=0xee: GUID partition table
|
||||
# XXX assume the first partition is active
|
||||
if struct.unpack("<c", buf[poff+4:poff+5]) == ('\xee',):
|
||||
os.lseek(fd, 0x400, 0)
|
||||
buf = os.read(fd, 512)
|
||||
return buf[24:40] # XXX buf[32:40]
|
||||
|
||||
# if there's not a partition marked as active, fall back to
|
||||
# the first partition
|
||||
return buf[446:446+16]
|
||||
@@ -97,8 +90,16 @@ def get_solaris_slice(file, offset):
|
||||
|
||||
raise RuntimeError, "No root slice found"
|
||||
|
||||
def get_fs_offset_gpt(file):
|
||||
fd = os.open(file, os.O_RDONLY)
|
||||
# assume the first partition is an EFI system partition.
|
||||
os.lseek(fd, SECTOR_SIZE * 2, 0)
|
||||
buf = os.read(fd, 512)
|
||||
return struct.unpack("<Q", buf[32:40])[0] * SECTOR_SIZE
|
||||
|
||||
FDISK_PART_SOLARIS=0xbf
|
||||
FDISK_PART_SOLARIS_OLD=0x82
|
||||
FDISK_PART_GPT=0xee
|
||||
|
||||
def get_fs_offset(file):
|
||||
if not is_disk_image(file):
|
||||
@@ -115,6 +116,9 @@ def get_fs_offset(file):
|
||||
if type == FDISK_PART_SOLARIS or type == FDISK_PART_SOLARIS_OLD:
|
||||
offset += get_solaris_slice(file, offset)
|
||||
|
||||
if type == FDISK_PART_GPT:
|
||||
offset = get_fs_offset_gpt(file)
|
||||
|
||||
return offset
|
||||
|
||||
class GrubLineEditor(curses.textpad.Textbox):
|
||||
|
||||
@@ -96,7 +96,10 @@ def datetime(when = None):
|
||||
@param when The time in question, given as seconds since the epoch, UTC.
|
||||
May be None, in which case the current time is used.
|
||||
"""
|
||||
return xmlrpclib.DateTime(time.gmtime(when))
|
||||
if when is None:
|
||||
return xmlrpclib.DateTime(time.gmtime())
|
||||
else:
|
||||
return xmlrpclib.DateTime(time.gmtime(when))
|
||||
|
||||
|
||||
# ---------------------------------------------------
|
||||
@@ -1304,6 +1307,7 @@ class XendAPI(object):
|
||||
('set_memory_dynamic_max_live', None),
|
||||
('set_memory_dynamic_min_live', None),
|
||||
('send_trigger', None),
|
||||
('migrate', None),
|
||||
('destroy', None)]
|
||||
|
||||
VM_funcs = [('create', 'VM'),
|
||||
@@ -1823,6 +1827,17 @@ class XendAPI(object):
|
||||
xendom.domain_send_trigger(xeninfo.getDomid(), trigger, vcpu)
|
||||
return xen_api_success_void()
|
||||
|
||||
def VM_migrate(self, _, vm_ref, destination_url, live, other_config):
|
||||
xendom = XendDomain.instance()
|
||||
xeninfo = xendom.get_vm_by_uuid(vm_ref)
|
||||
|
||||
resource = other_config.get("resource", 0)
|
||||
port = other_config.get("port", 0)
|
||||
|
||||
xendom.domain_migrate(xeninfo.getDomid(), destination_url,
|
||||
bool(live), resource, port)
|
||||
return xen_api_success_void()
|
||||
|
||||
def VM_save(self, _, vm_ref, dest, checkpoint):
|
||||
xendom = XendDomain.instance()
|
||||
xeninfo = xendom.get_vm_by_uuid(vm_ref)
|
||||
|
||||
@@ -150,8 +150,10 @@ class XendNode:
|
||||
|
||||
# Get a mapping from interface to bridge
|
||||
|
||||
if_to_br = dict(reduce(lambda ls,(b,ifs):[(i,b) for i in ifs] + ls,
|
||||
Brctl.get_state().items(), []))
|
||||
if_to_br = dict([(i,b)
|
||||
for (b,ifs) in Brctl.get_state().items()
|
||||
for i in ifs])
|
||||
|
||||
# initialise PIFs
|
||||
saved_pifs = self.state_store.load_state('pif')
|
||||
if saved_pifs:
|
||||
|
||||
@@ -23,7 +23,7 @@ import sys
|
||||
|
||||
from xen.xm.opts import *
|
||||
|
||||
from main import server
|
||||
from main import server, serverType, get_single_vm, SERVER_XEN_API
|
||||
|
||||
gopts = Opts(use="""[options] DOM HOST
|
||||
|
||||
@@ -60,5 +60,16 @@ def main(argv):
|
||||
|
||||
dom = args[0]
|
||||
dst = args[1]
|
||||
server.xend.domain.migrate(dom, dst, opts.vals.live, opts.vals.resource,
|
||||
opts.vals.port)
|
||||
|
||||
if serverType == SERVER_XEN_API:
|
||||
vm_ref = get_single_vm(dom)
|
||||
other_config = {
|
||||
"port": opts.vals.port,
|
||||
"resource": opts.vals.resource
|
||||
}
|
||||
server.xenapi.VM.migrate(vm_ref, dst, bool(opts.vals.live),
|
||||
other_config)
|
||||
else:
|
||||
server.xend.domain.migrate(dom, dst, opts.vals.live,
|
||||
opts.vals.resource,
|
||||
opts.vals.port)
|
||||
@@ -48,7 +48,7 @@ def get_name_description(node):
|
||||
|
||||
def get_text_in_child_node(node, child):
|
||||
tag_node = node.getElementsByTagName(child)[0]
|
||||
return tag_node.nodeValue
|
||||
return " ".join([child.nodeValue for child in tag_node.childNodes])
|
||||
|
||||
def get_child_node_attribute(node, child, attribute):
|
||||
tag_node = node.getElementsByTagName(child)[0]
|
||||
@@ -264,7 +264,23 @@ class xenapi_create:
|
||||
"platform":
|
||||
get_child_nodes_as_dict(vm, "platform", "key", "value"),
|
||||
"other_config":
|
||||
get_child_nodes_as_dict(vm, "other_config", "key", "value")
|
||||
get_child_nodes_as_dict(vm, "other_config", "key", "value"),
|
||||
"PV_bootloader":
|
||||
"",
|
||||
"PV_kernel":
|
||||
"",
|
||||
"PV_ramdisk":
|
||||
"",
|
||||
"PV_args":
|
||||
"",
|
||||
"PV_bootloader_args":
|
||||
"",
|
||||
"HVM_boot_policy":
|
||||
"",
|
||||
"HVM_boot_params":
|
||||
{},
|
||||
"PCI_bus":
|
||||
""
|
||||
}
|
||||
|
||||
if len(vm.getElementsByTagName("pv")) > 0:
|
||||
@@ -494,7 +510,7 @@ class sxp2xml:
|
||||
# Make version tag
|
||||
|
||||
version = document.createElement("version")
|
||||
version.appendChild(document.createTextNode("1.0"))
|
||||
version.appendChild(document.createTextNode("0"))
|
||||
vm.appendChild(version)
|
||||
|
||||
# Make pv or hvm tag
|
||||
|
||||
@@ -21,6 +21,12 @@
|
||||
#include <xen/config.h>
|
||||
#include <xen/lib.h>
|
||||
|
||||
extern void __xchg_called_with_bad_pointer(void);
|
||||
void __xchg_called_with_bad_pointer(void)
|
||||
{
|
||||
BUG();
|
||||
}
|
||||
|
||||
extern void __cmpxchg_called_with_bad_pointer(void);
|
||||
void __cmpxchg_called_with_bad_pointer(void)
|
||||
{
|
||||
|
||||
@@ -229,7 +229,7 @@ int construct_dom0(struct domain *d,
|
||||
/* Load the dom0 kernel. */
|
||||
elf.dest = (void *)dst;
|
||||
elf_load_binary(&elf);
|
||||
v->arch.ctxt.pc = dst - rma;
|
||||
v->arch.ctxt.pc = dst - rma + (parms.virt_entry - parms.virt_kstart);
|
||||
dst = ALIGN_UP(dst + parms.virt_kend, PAGE_SIZE);
|
||||
|
||||
/* Load the initrd. */
|
||||
|
||||
@@ -264,7 +264,7 @@ static ofdn_t ofd_chosen_props(void *m, const char *cmdline)
|
||||
ofdn_t n;
|
||||
ofdn_t p;
|
||||
static const char path[] = "/chosen";
|
||||
char bootargs[256];
|
||||
char bootargs[256] = { 0, };
|
||||
int bsz;
|
||||
int sz;
|
||||
int rm;
|
||||
@@ -276,7 +276,8 @@ static ofdn_t ofd_chosen_props(void *m, const char *cmdline)
|
||||
&path[1], sizeof (path) - 1);
|
||||
}
|
||||
|
||||
strlcpy(bootargs, cmdline, sizeof(bootargs));
|
||||
if (cmdline)
|
||||
strlcpy(bootargs, cmdline, sizeof(bootargs));
|
||||
bsz = strlen(bootargs) + 1;
|
||||
rm = sizeof (bootargs) - bsz;
|
||||
|
||||
|
||||
@@ -1540,8 +1540,10 @@ void domain_relinquish_resources(struct domain *d)
|
||||
relinquish_memory(d, &d->xenpage_list, PGT_l2_page_table);
|
||||
relinquish_memory(d, &d->page_list, PGT_l2_page_table);
|
||||
|
||||
/* Free page used by xen oprofile buffer */
|
||||
/* Free page used by xen oprofile buffer. */
|
||||
free_xenoprof_pages(d);
|
||||
|
||||
hvm_domain_relinquish_resources(d);
|
||||
}
|
||||
|
||||
void arch_dump_domain_info(struct domain *d)
|
||||
|
||||
+180
-42
@@ -101,7 +101,7 @@ void hvm_set_guest_time(struct vcpu *v, u64 gtime)
|
||||
|
||||
u64 hvm_get_guest_time(struct vcpu *v)
|
||||
{
|
||||
u64 host_tsc;
|
||||
u64 host_tsc;
|
||||
|
||||
rdtscll(host_tsc);
|
||||
return host_tsc + v->arch.hvm_vcpu.cache_tsc_offset;
|
||||
@@ -125,7 +125,7 @@ void hvm_do_resume(struct vcpu *v)
|
||||
pt_thaw_time(v);
|
||||
|
||||
/* NB. Optimised for common case (p->state == STATE_IOREQ_NONE). */
|
||||
p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq;
|
||||
p = &get_ioreq(v)->vp_ioreq;
|
||||
while ( p->state != STATE_IOREQ_NONE )
|
||||
{
|
||||
switch ( p->state )
|
||||
@@ -146,6 +146,73 @@ void hvm_do_resume(struct vcpu *v)
|
||||
}
|
||||
}
|
||||
|
||||
static void hvm_init_ioreq_page(
|
||||
struct domain *d, struct hvm_ioreq_page *iorp)
|
||||
{
|
||||
memset(iorp, 0, sizeof(*iorp));
|
||||
spin_lock_init(&iorp->lock);
|
||||
domain_pause(d);
|
||||
}
|
||||
|
||||
static void hvm_destroy_ioreq_page(
|
||||
struct domain *d, struct hvm_ioreq_page *iorp)
|
||||
{
|
||||
spin_lock(&iorp->lock);
|
||||
|
||||
ASSERT(d->is_dying);
|
||||
|
||||
if ( iorp->va != NULL )
|
||||
{
|
||||
unmap_domain_page_global(iorp->va);
|
||||
put_page_and_type(iorp->page);
|
||||
iorp->va = NULL;
|
||||
}
|
||||
|
||||
spin_unlock(&iorp->lock);
|
||||
}
|
||||
|
||||
static int hvm_set_ioreq_page(
|
||||
struct domain *d, struct hvm_ioreq_page *iorp, unsigned long gmfn)
|
||||
{
|
||||
struct page_info *page;
|
||||
unsigned long mfn;
|
||||
void *va;
|
||||
|
||||
mfn = gmfn_to_mfn(d, gmfn);
|
||||
if ( !mfn_valid(mfn) )
|
||||
return -EINVAL;
|
||||
|
||||
page = mfn_to_page(mfn);
|
||||
if ( !get_page_and_type(page, d, PGT_writable_page) )
|
||||
return -EINVAL;
|
||||
|
||||
va = map_domain_page_global(mfn);
|
||||
if ( va == NULL )
|
||||
{
|
||||
put_page_and_type(page);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spin_lock(&iorp->lock);
|
||||
|
||||
if ( (iorp->va != NULL) || d->is_dying )
|
||||
{
|
||||
spin_unlock(&iorp->lock);
|
||||
unmap_domain_page_global(va);
|
||||
put_page_and_type(mfn_to_page(mfn));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
iorp->va = va;
|
||||
iorp->page = page;
|
||||
|
||||
spin_unlock(&iorp->lock);
|
||||
|
||||
domain_unpause(d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hvm_domain_initialise(struct domain *d)
|
||||
{
|
||||
int rc;
|
||||
@@ -158,10 +225,8 @@ int hvm_domain_initialise(struct domain *d)
|
||||
}
|
||||
|
||||
spin_lock_init(&d->arch.hvm_domain.pbuf_lock);
|
||||
spin_lock_init(&d->arch.hvm_domain.buffered_io_lock);
|
||||
spin_lock_init(&d->arch.hvm_domain.irq_lock);
|
||||
|
||||
/* paging support will be determined inside paging.c */
|
||||
rc = paging_enable(d, PG_refcounts|PG_translate|PG_external);
|
||||
if ( rc != 0 )
|
||||
return rc;
|
||||
@@ -169,28 +234,31 @@ int hvm_domain_initialise(struct domain *d)
|
||||
vpic_init(d);
|
||||
vioapic_init(d);
|
||||
|
||||
hvm_init_ioreq_page(d, &d->arch.hvm_domain.ioreq);
|
||||
hvm_init_ioreq_page(d, &d->arch.hvm_domain.buf_ioreq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hvm_domain_relinquish_resources(struct domain *d)
|
||||
{
|
||||
hvm_destroy_ioreq_page(d, &d->arch.hvm_domain.ioreq);
|
||||
hvm_destroy_ioreq_page(d, &d->arch.hvm_domain.buf_ioreq);
|
||||
}
|
||||
|
||||
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 )
|
||||
unmap_domain_page_global(
|
||||
(void *)d->arch.hvm_domain.shared_page_va);
|
||||
|
||||
if ( d->arch.hvm_domain.buffered_io_va )
|
||||
unmap_domain_page_global((void *)d->arch.hvm_domain.buffered_io_va);
|
||||
}
|
||||
|
||||
static int hvm_save_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
|
||||
{
|
||||
struct vcpu *v;
|
||||
struct hvm_hw_cpu ctxt;
|
||||
struct vcpu_guest_context *vc;
|
||||
|
||||
for_each_vcpu(d, v)
|
||||
{
|
||||
@@ -199,7 +267,40 @@ static int hvm_save_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
|
||||
if ( test_bit(_VPF_down, &v->pause_flags) )
|
||||
continue;
|
||||
|
||||
/* Architecture-specific vmcs/vmcb bits */
|
||||
hvm_funcs.save_cpu_ctxt(v, &ctxt);
|
||||
|
||||
/* Other vcpu register state */
|
||||
vc = &v->arch.guest_context;
|
||||
if ( vc->flags & VGCF_i387_valid )
|
||||
memcpy(ctxt.fpu_regs, &vc->fpu_ctxt, sizeof(ctxt.fpu_regs));
|
||||
else
|
||||
memset(ctxt.fpu_regs, 0, sizeof(ctxt.fpu_regs));
|
||||
ctxt.rax = vc->user_regs.eax;
|
||||
ctxt.rbx = vc->user_regs.ebx;
|
||||
ctxt.rcx = vc->user_regs.ecx;
|
||||
ctxt.rdx = vc->user_regs.edx;
|
||||
ctxt.rbp = vc->user_regs.ebp;
|
||||
ctxt.rsi = vc->user_regs.esi;
|
||||
ctxt.rdi = vc->user_regs.edi;
|
||||
/* %rsp handled by arch-specific call above */
|
||||
#ifdef __x86_64__
|
||||
ctxt.r8 = vc->user_regs.r8;
|
||||
ctxt.r9 = vc->user_regs.r9;
|
||||
ctxt.r10 = vc->user_regs.r10;
|
||||
ctxt.r11 = vc->user_regs.r11;
|
||||
ctxt.r12 = vc->user_regs.r12;
|
||||
ctxt.r13 = vc->user_regs.r13;
|
||||
ctxt.r14 = vc->user_regs.r14;
|
||||
ctxt.r15 = vc->user_regs.r15;
|
||||
#endif
|
||||
ctxt.dr0 = vc->debugreg[0];
|
||||
ctxt.dr1 = vc->debugreg[1];
|
||||
ctxt.dr2 = vc->debugreg[2];
|
||||
ctxt.dr3 = vc->debugreg[3];
|
||||
ctxt.dr6 = vc->debugreg[6];
|
||||
ctxt.dr7 = vc->debugreg[7];
|
||||
|
||||
if ( hvm_save_entry(CPU, v->vcpu_id, h, &ctxt) != 0 )
|
||||
return 1;
|
||||
}
|
||||
@@ -208,9 +309,10 @@ static int hvm_save_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
|
||||
|
||||
static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
|
||||
{
|
||||
int vcpuid;
|
||||
int vcpuid, rc;
|
||||
struct vcpu *v;
|
||||
struct hvm_hw_cpu ctxt;
|
||||
struct vcpu_guest_context *vc;
|
||||
|
||||
/* Which vcpu is this? */
|
||||
vcpuid = hvm_load_instance(h);
|
||||
@@ -219,13 +321,52 @@ static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
|
||||
gdprintk(XENLOG_ERR, "HVM restore: domain has no vcpu %u\n", vcpuid);
|
||||
return -EINVAL;
|
||||
}
|
||||
vc = &v->arch.guest_context;
|
||||
|
||||
/* Need to init this vcpu before loading its contents */
|
||||
LOCK_BIGLOCK(d);
|
||||
if ( !v->is_initialised )
|
||||
if ( (rc = boot_vcpu(d, vcpuid, vc)) != 0 )
|
||||
return rc;
|
||||
UNLOCK_BIGLOCK(d);
|
||||
|
||||
if ( hvm_load_entry(CPU, h, &ctxt) != 0 )
|
||||
return -EINVAL;
|
||||
|
||||
/* Architecture-specific vmcs/vmcb bits */
|
||||
if ( hvm_funcs.load_cpu_ctxt(v, &ctxt) < 0 )
|
||||
return -EINVAL;
|
||||
|
||||
/* Other vcpu register state */
|
||||
memcpy(&vc->fpu_ctxt, ctxt.fpu_regs, sizeof(ctxt.fpu_regs));
|
||||
vc->user_regs.eax = ctxt.rax;
|
||||
vc->user_regs.ebx = ctxt.rbx;
|
||||
vc->user_regs.ecx = ctxt.rcx;
|
||||
vc->user_regs.edx = ctxt.rdx;
|
||||
vc->user_regs.ebp = ctxt.rbp;
|
||||
vc->user_regs.esi = ctxt.rsi;
|
||||
vc->user_regs.edi = ctxt.rdi;
|
||||
vc->user_regs.esp = ctxt.rsp;
|
||||
#ifdef __x86_64__
|
||||
vc->user_regs.r8 = ctxt.r8;
|
||||
vc->user_regs.r9 = ctxt.r9;
|
||||
vc->user_regs.r10 = ctxt.r10;
|
||||
vc->user_regs.r11 = ctxt.r11;
|
||||
vc->user_regs.r12 = ctxt.r12;
|
||||
vc->user_regs.r13 = ctxt.r13;
|
||||
vc->user_regs.r14 = ctxt.r14;
|
||||
vc->user_regs.r15 = ctxt.r15;
|
||||
#endif
|
||||
vc->debugreg[0] = ctxt.dr0;
|
||||
vc->debugreg[1] = ctxt.dr1;
|
||||
vc->debugreg[2] = ctxt.dr2;
|
||||
vc->debugreg[3] = ctxt.dr3;
|
||||
vc->debugreg[6] = ctxt.dr6;
|
||||
vc->debugreg[7] = ctxt.dr7;
|
||||
|
||||
vc->flags = VGCF_i387_valid | VGCF_online;
|
||||
v->fpu_initialised = 1;
|
||||
|
||||
/* Auxiliary processors should be woken immediately. */
|
||||
if ( test_and_clear_bit(_VPF_down, &v->pause_flags) )
|
||||
vcpu_wake(v);
|
||||
@@ -250,10 +391,20 @@ int hvm_vcpu_initialise(struct vcpu *v)
|
||||
}
|
||||
|
||||
/* Create ioreq event channel. */
|
||||
v->arch.hvm_vcpu.xen_port = alloc_unbound_xen_event_channel(v, 0);
|
||||
if ( get_sp(v->domain) && get_vio(v->domain, v->vcpu_id) )
|
||||
get_vio(v->domain, v->vcpu_id)->vp_eport =
|
||||
v->arch.hvm_vcpu.xen_port;
|
||||
rc = alloc_unbound_xen_event_channel(v, 0);
|
||||
if ( rc < 0 )
|
||||
{
|
||||
hvm_funcs.vcpu_destroy(v);
|
||||
vlapic_destroy(v);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Register ioreq event channel. */
|
||||
v->arch.hvm_vcpu.xen_port = rc;
|
||||
spin_lock(&v->domain->arch.hvm_domain.ioreq.lock);
|
||||
if ( v->domain->arch.hvm_domain.ioreq.va != NULL )
|
||||
get_ioreq(v)->vp_eport = v->arch.hvm_vcpu.xen_port;
|
||||
spin_unlock(&v->domain->arch.hvm_domain.ioreq.lock);
|
||||
|
||||
INIT_LIST_HEAD(&v->arch.hvm_vcpu.tm_list);
|
||||
|
||||
@@ -334,7 +485,7 @@ void hvm_send_assist_req(struct vcpu *v)
|
||||
if ( unlikely(!vcpu_start_shutdown_deferral(v)) )
|
||||
return; /* implicitly bins the i/o operation */
|
||||
|
||||
p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq;
|
||||
p = &get_ioreq(v)->vp_ioreq;
|
||||
if ( unlikely(p->state != STATE_IOREQ_NONE) )
|
||||
{
|
||||
/* This indicates a bug in the device model. Crash the domain. */
|
||||
@@ -852,10 +1003,9 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
|
||||
case HVMOP_get_param:
|
||||
{
|
||||
struct xen_hvm_param a;
|
||||
struct hvm_ioreq_page *iorp;
|
||||
struct domain *d;
|
||||
struct vcpu *v;
|
||||
unsigned long mfn;
|
||||
void *p;
|
||||
|
||||
if ( copy_from_guest(&a, arg, 1) )
|
||||
return -EFAULT;
|
||||
@@ -882,30 +1032,18 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
|
||||
switch ( a.index )
|
||||
{
|
||||
case HVM_PARAM_IOREQ_PFN:
|
||||
if ( d->arch.hvm_domain.shared_page_va )
|
||||
goto param_fail;
|
||||
mfn = gmfn_to_mfn(d, a.value);
|
||||
if ( mfn == INVALID_MFN )
|
||||
goto param_fail;
|
||||
p = map_domain_page_global(mfn);
|
||||
if ( p == NULL )
|
||||
goto param_fail;
|
||||
d->arch.hvm_domain.shared_page_va = (unsigned long)p;
|
||||
/* Initialise evtchn port info if VCPUs already created. */
|
||||
for_each_vcpu ( d, v )
|
||||
get_vio(d, v->vcpu_id)->vp_eport =
|
||||
v->arch.hvm_vcpu.xen_port;
|
||||
iorp = &d->arch.hvm_domain.ioreq;
|
||||
rc = hvm_set_ioreq_page(d, iorp, a.value);
|
||||
spin_lock(&iorp->lock);
|
||||
if ( (rc == 0) && (iorp->va != NULL) )
|
||||
/* Initialise evtchn port info if VCPUs already created. */
|
||||
for_each_vcpu ( d, v )
|
||||
get_ioreq(v)->vp_eport = v->arch.hvm_vcpu.xen_port;
|
||||
spin_unlock(&iorp->lock);
|
||||
break;
|
||||
case HVM_PARAM_BUFIOREQ_PFN:
|
||||
if ( d->arch.hvm_domain.buffered_io_va )
|
||||
goto param_fail;
|
||||
mfn = gmfn_to_mfn(d, a.value);
|
||||
if ( mfn == INVALID_MFN )
|
||||
goto param_fail;
|
||||
p = map_domain_page_global(mfn);
|
||||
if ( p == NULL )
|
||||
goto param_fail;
|
||||
d->arch.hvm_domain.buffered_io_va = (unsigned long)p;
|
||||
case HVM_PARAM_BUFIOREQ_PFN:
|
||||
iorp = &d->arch.hvm_domain.buf_ioreq;
|
||||
rc = hvm_set_ioreq_page(d, iorp, a.value);
|
||||
break;
|
||||
case HVM_PARAM_CALLBACK_IRQ:
|
||||
hvm_set_callback_via(d, a.value);
|
||||
|
||||
@@ -158,34 +158,26 @@ static inline void hvm_mmio_access(struct vcpu *v,
|
||||
int hvm_buffered_io_send(ioreq_t *p)
|
||||
{
|
||||
struct vcpu *v = current;
|
||||
spinlock_t *buffered_io_lock;
|
||||
buffered_iopage_t *buffered_iopage =
|
||||
(buffered_iopage_t *)(v->domain->arch.hvm_domain.buffered_io_va);
|
||||
unsigned long tmp_write_pointer = 0;
|
||||
struct hvm_ioreq_page *iorp = &v->domain->arch.hvm_domain.buf_ioreq;
|
||||
buffered_iopage_t *pg = iorp->va;
|
||||
|
||||
buffered_io_lock = &v->domain->arch.hvm_domain.buffered_io_lock;
|
||||
spin_lock(buffered_io_lock);
|
||||
spin_lock(&iorp->lock);
|
||||
|
||||
if ( buffered_iopage->write_pointer - buffered_iopage->read_pointer ==
|
||||
(unsigned int)IOREQ_BUFFER_SLOT_NUM ) {
|
||||
/* the queue is full.
|
||||
* send the iopacket through the normal path.
|
||||
* NOTE: The arithimetic operation could handle the situation for
|
||||
* write_pointer overflow.
|
||||
*/
|
||||
spin_unlock(buffered_io_lock);
|
||||
if ( (pg->write_pointer - pg->read_pointer) == IOREQ_BUFFER_SLOT_NUM )
|
||||
{
|
||||
/* The queue is full: send the iopacket through the normal path. */
|
||||
spin_unlock(&iorp->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tmp_write_pointer = buffered_iopage->write_pointer % IOREQ_BUFFER_SLOT_NUM;
|
||||
memcpy(&pg->ioreq[pg->write_pointer % IOREQ_BUFFER_SLOT_NUM],
|
||||
p, sizeof(ioreq_t));
|
||||
|
||||
memcpy(&buffered_iopage->ioreq[tmp_write_pointer], p, sizeof(ioreq_t));
|
||||
|
||||
/*make the ioreq_t visible before write_pointer*/
|
||||
/* Make the ioreq_t visible /before/ write_pointer. */
|
||||
wmb();
|
||||
buffered_iopage->write_pointer++;
|
||||
pg->write_pointer++;
|
||||
|
||||
spin_unlock(buffered_io_lock);
|
||||
spin_unlock(&iorp->lock);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -832,7 +832,7 @@ void hvm_io_assist(void)
|
||||
|
||||
io_opp = &v->arch.hvm_vcpu.io_op;
|
||||
regs = &io_opp->io_context;
|
||||
vio = get_vio(d, v->vcpu_id);
|
||||
vio = get_ioreq(v);
|
||||
|
||||
p = &vio->vp_ioreq;
|
||||
if ( p->state != STATE_IORESP_READY )
|
||||
|
||||
@@ -221,7 +221,6 @@ static inline unsigned long get_immediate(int ad_size, const unsigned char *inst
|
||||
|
||||
inst++; //skip ModR/M byte
|
||||
if ( ad_size != WORD && mod != 3 && rm == 4 ) {
|
||||
rm = *inst & 7;
|
||||
inst++; //skip SIB byte
|
||||
}
|
||||
|
||||
@@ -257,6 +256,33 @@ static inline unsigned long get_immediate(int ad_size, const unsigned char *inst
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Some instructions, like "add $imm8, r/m16"/"MOV $imm32, r/m64" require
|
||||
* the src immediate operand be sign-extented befere the op is executed. Here
|
||||
* we always sign-extend the operand to a "unsigned long" variable.
|
||||
*
|
||||
* Note: to simplify the logic here, the sign-extension here may be performed
|
||||
* redundantly against some instructions, like "MOV $imm16, r/m16" -- however
|
||||
* this is harmless, since we always remember the operand's size.
|
||||
*/
|
||||
static inline unsigned long get_immediate_sign_ext(int ad_size,
|
||||
const unsigned char *inst,
|
||||
int op_size)
|
||||
{
|
||||
unsigned long result = get_immediate(ad_size, inst, op_size);
|
||||
|
||||
if ( op_size == QUAD )
|
||||
op_size = LONG;
|
||||
|
||||
ASSERT( op_size == BYTE || op_size == WORD || op_size == LONG );
|
||||
|
||||
if ( result & (1UL << ((8*op_size) - 1)) )
|
||||
{
|
||||
unsigned long mask = ~0UL >> (8 * (sizeof(mask) - op_size));
|
||||
result = ~mask | (result & mask);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline int get_index(const unsigned char *inst, unsigned char rex)
|
||||
{
|
||||
int mod, reg, rm;
|
||||
@@ -394,7 +420,9 @@ static int mmio_decode(int address_bytes, unsigned char *opcode,
|
||||
case 8:
|
||||
if ( *op_size == 0 )
|
||||
*op_size = rex & 0x8 ? QUAD : LONG;
|
||||
if ( *ad_size == 0 )
|
||||
if ( *ad_size == WORD )
|
||||
*ad_size = LONG;
|
||||
else if ( *ad_size == 0 )
|
||||
*ad_size = QUAD;
|
||||
break;
|
||||
#endif
|
||||
@@ -520,10 +548,10 @@ static int mmio_decode(int address_bytes, unsigned char *opcode,
|
||||
/* opcode 0x83 always has a single byte operand */
|
||||
if ( opcode[0] == 0x83 )
|
||||
mmio_op->immediate =
|
||||
(signed char)get_immediate(*ad_size, opcode + 1, BYTE);
|
||||
get_immediate_sign_ext(*ad_size, opcode + 1, BYTE);
|
||||
else
|
||||
mmio_op->immediate =
|
||||
get_immediate(*ad_size, opcode + 1, *op_size);
|
||||
get_immediate_sign_ext(*ad_size, opcode + 1, *op_size);
|
||||
|
||||
mmio_op->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE);
|
||||
mmio_op->operand[1] = mk_operand(size_reg, 0, 0, MEMORY);
|
||||
@@ -677,7 +705,7 @@ static int mmio_decode(int address_bytes, unsigned char *opcode,
|
||||
|
||||
mmio_op->operand[0] = mk_operand(*op_size, 0, 0, IMMEDIATE);
|
||||
mmio_op->immediate =
|
||||
get_immediate(*ad_size, opcode + 1, *op_size);
|
||||
get_immediate_sign_ext(*ad_size, opcode + 1, *op_size);
|
||||
mmio_op->operand[1] = mk_operand(*op_size, 0, 0, MEMORY);
|
||||
|
||||
return DECODE_success;
|
||||
@@ -699,7 +727,7 @@ static int mmio_decode(int address_bytes, unsigned char *opcode,
|
||||
|
||||
mmio_op->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE);
|
||||
mmio_op->immediate =
|
||||
get_immediate(*ad_size, opcode + 1, *op_size);
|
||||
get_immediate_sign_ext(*ad_size, opcode + 1, *op_size);
|
||||
mmio_op->operand[1] = mk_operand(size_reg, 0, 0, MEMORY);
|
||||
|
||||
return DECODE_success;
|
||||
@@ -838,7 +866,7 @@ void send_pio_req(unsigned long port, unsigned long count, int size,
|
||||
port, count, size, value, dir, value_is_ptr);
|
||||
}
|
||||
|
||||
vio = get_vio(v->domain, v->vcpu_id);
|
||||
vio = get_ioreq(v);
|
||||
if ( vio == NULL ) {
|
||||
printk("bad shared page: %lx\n", (unsigned long) vio);
|
||||
domain_crash_synchronous();
|
||||
@@ -887,7 +915,7 @@ static void send_mmio_req(unsigned char type, unsigned long gpa,
|
||||
type, gpa, count, size, value, dir, value_is_ptr);
|
||||
}
|
||||
|
||||
vio = get_vio(v->domain, v->vcpu_id);
|
||||
vio = get_ioreq(v);
|
||||
if (vio == NULL) {
|
||||
printk("bad shared page\n");
|
||||
domain_crash_synchronous();
|
||||
@@ -948,7 +976,7 @@ void send_invalidate_req(void)
|
||||
vcpu_iodata_t *vio;
|
||||
ioreq_t *p;
|
||||
|
||||
vio = get_vio(v->domain, v->vcpu_id);
|
||||
vio = get_ioreq(v);
|
||||
if ( vio == NULL )
|
||||
{
|
||||
printk("bad shared page: %lx\n", (unsigned long) vio);
|
||||
|
||||
@@ -233,7 +233,7 @@ int svm_vmcb_save(struct vcpu *v, struct hvm_hw_cpu *c)
|
||||
{
|
||||
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
|
||||
|
||||
c->eip = vmcb->rip;
|
||||
c->rip = vmcb->rip;
|
||||
|
||||
#ifdef HVM_DEBUG_SUSPEND
|
||||
printk("%s: eip=0x%"PRIx64".\n",
|
||||
@@ -241,10 +241,11 @@ int svm_vmcb_save(struct vcpu *v, struct hvm_hw_cpu *c)
|
||||
inst_len, c->eip);
|
||||
#endif
|
||||
|
||||
c->esp = vmcb->rsp;
|
||||
c->eflags = vmcb->rflags;
|
||||
c->rsp = vmcb->rsp;
|
||||
c->rflags = vmcb->rflags;
|
||||
|
||||
c->cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
|
||||
c->cr2 = v->arch.hvm_svm.cpu_cr2;
|
||||
c->cr3 = v->arch.hvm_svm.cpu_cr3;
|
||||
c->cr4 = v->arch.hvm_svm.cpu_shadow_cr4;
|
||||
|
||||
@@ -315,14 +316,14 @@ int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c)
|
||||
unsigned long mfn, old_base_mfn;
|
||||
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
|
||||
|
||||
vmcb->rip = c->eip;
|
||||
vmcb->rsp = c->esp;
|
||||
vmcb->rflags = c->eflags;
|
||||
vmcb->rip = c->rip;
|
||||
vmcb->rsp = c->rsp;
|
||||
vmcb->rflags = c->rflags;
|
||||
|
||||
v->arch.hvm_svm.cpu_shadow_cr0 = c->cr0;
|
||||
vmcb->cr0 = c->cr0 | X86_CR0_WP | X86_CR0_ET;
|
||||
if ( !paging_mode_hap(v->domain) )
|
||||
vmcb->cr0 |= X86_CR0_PG;
|
||||
vmcb->cr0 = c->cr0 | X86_CR0_WP | X86_CR0_ET | X86_CR0_PG;
|
||||
|
||||
v->arch.hvm_svm.cpu_cr2 = c->cr2;
|
||||
|
||||
#ifdef HVM_DEBUG_SUSPEND
|
||||
printk("%s: cr3=0x%"PRIx64", cr0=0x%"PRIx64", cr4=0x%"PRIx64".\n",
|
||||
@@ -421,6 +422,19 @@ int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c)
|
||||
vmcb->sysenter_esp = c->sysenter_esp;
|
||||
vmcb->sysenter_eip = c->sysenter_eip;
|
||||
|
||||
/* update VMCB for nested paging restore */
|
||||
if ( paging_mode_hap(v->domain) ) {
|
||||
vmcb->cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
|
||||
vmcb->cr4 = v->arch.hvm_svm.cpu_shadow_cr4;
|
||||
vmcb->cr3 = c->cr3;
|
||||
vmcb->np_enable = 1;
|
||||
vmcb->g_pat = 0x0007040600070406ULL; /* guest PAT */
|
||||
vmcb->h_cr3 = pagetable_get_paddr(v->domain->arch.phys_table);
|
||||
}
|
||||
|
||||
vmcb->dr6 = c->dr6;
|
||||
vmcb->dr7 = c->dr7;
|
||||
|
||||
paging_update_paging_modes(v);
|
||||
return 0;
|
||||
|
||||
@@ -440,6 +454,7 @@ void svm_save_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
|
||||
data->msr_cstar = vmcb->cstar;
|
||||
data->msr_syscall_mask = vmcb->sfmask;
|
||||
data->msr_efer = v->arch.hvm_svm.cpu_shadow_efer;
|
||||
data->msr_flags = -1ULL;
|
||||
|
||||
data->tsc = hvm_get_guest_time(v);
|
||||
}
|
||||
|
||||
@@ -370,11 +370,12 @@ static inline void __restore_debug_registers(struct vcpu *v)
|
||||
|
||||
int vmx_vmcs_save(struct vcpu *v, struct hvm_hw_cpu *c)
|
||||
{
|
||||
c->eip = __vmread(GUEST_RIP);
|
||||
c->esp = __vmread(GUEST_RSP);
|
||||
c->eflags = __vmread(GUEST_RFLAGS);
|
||||
c->rip = __vmread(GUEST_RIP);
|
||||
c->rsp = __vmread(GUEST_RSP);
|
||||
c->rflags = __vmread(GUEST_RFLAGS);
|
||||
|
||||
c->cr0 = v->arch.hvm_vmx.cpu_shadow_cr0;
|
||||
c->cr2 = v->arch.hvm_vmx.cpu_cr2;
|
||||
c->cr3 = v->arch.hvm_vmx.cpu_cr3;
|
||||
c->cr4 = v->arch.hvm_vmx.cpu_shadow_cr4;
|
||||
|
||||
@@ -444,13 +445,15 @@ int vmx_vmcs_restore(struct vcpu *v, struct hvm_hw_cpu *c)
|
||||
|
||||
vmx_vmcs_enter(v);
|
||||
|
||||
__vmwrite(GUEST_RIP, c->eip);
|
||||
__vmwrite(GUEST_RSP, c->esp);
|
||||
__vmwrite(GUEST_RFLAGS, c->eflags);
|
||||
__vmwrite(GUEST_RIP, c->rip);
|
||||
__vmwrite(GUEST_RSP, c->rsp);
|
||||
__vmwrite(GUEST_RFLAGS, c->rflags);
|
||||
|
||||
v->arch.hvm_vmx.cpu_shadow_cr0 = c->cr0;
|
||||
__vmwrite(CR0_READ_SHADOW, v->arch.hvm_vmx.cpu_shadow_cr0);
|
||||
|
||||
v->arch.hvm_vmx.cpu_cr2 = c->cr2;
|
||||
|
||||
#ifdef HVM_DEBUG_SUSPEND
|
||||
printk("vmx_vmcs_restore: cr3=0x%"PRIx64", cr0=0x%"PRIx64", cr4=0x%"PRIx64".\n",
|
||||
c->cr3,
|
||||
@@ -555,6 +558,8 @@ int vmx_vmcs_restore(struct vcpu *v, struct hvm_hw_cpu *c)
|
||||
__vmwrite(GUEST_SYSENTER_ESP, c->sysenter_esp);
|
||||
__vmwrite(GUEST_SYSENTER_EIP, c->sysenter_eip);
|
||||
|
||||
__vmwrite(GUEST_DR7, c->dr7);
|
||||
|
||||
vmx_vmcs_exit(v);
|
||||
|
||||
paging_update_paging_modes(v);
|
||||
@@ -590,7 +595,7 @@ void vmx_save_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
|
||||
data->shadow_gs = guest_state->shadow_gs;
|
||||
|
||||
/* save msrs */
|
||||
data->flags = guest_flags;
|
||||
data->msr_flags = guest_flags;
|
||||
data->msr_lstar = guest_state->msrs[VMX_INDEX_MSR_LSTAR];
|
||||
data->msr_star = guest_state->msrs[VMX_INDEX_MSR_STAR];
|
||||
data->msr_cstar = guest_state->msrs[VMX_INDEX_MSR_CSTAR];
|
||||
@@ -607,7 +612,7 @@ void vmx_load_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data)
|
||||
struct vmx_msr_state *guest_state = &v->arch.hvm_vmx.msr_state;
|
||||
|
||||
/* restore msrs */
|
||||
guest_state->flags = data->flags;
|
||||
guest_state->flags = data->msr_flags;
|
||||
guest_state->msrs[VMX_INDEX_MSR_LSTAR] = data->msr_lstar;
|
||||
guest_state->msrs[VMX_INDEX_MSR_STAR] = data->msr_star;
|
||||
guest_state->msrs[VMX_INDEX_MSR_CSTAR] = data->msr_cstar;
|
||||
|
||||
+13
-9
@@ -2041,7 +2041,7 @@ int do_mmuext_op(
|
||||
MEM_LOG("Error while pinning mfn %lx", mfn);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if ( unlikely(test_and_set_bit(_PGT_pinned,
|
||||
&page->u.inuse.type_info)) )
|
||||
{
|
||||
@@ -2054,14 +2054,18 @@ int do_mmuext_op(
|
||||
/* A page is dirtied when its pin status is set. */
|
||||
mark_dirty(d, mfn);
|
||||
|
||||
/*
|
||||
* We can race domain destruction (domain_relinquish_resources).
|
||||
* NB. The dying-flag test must happen /after/ setting PGT_pinned.
|
||||
*/
|
||||
if ( unlikely(this_cpu(percpu_mm_info).foreign != NULL) &&
|
||||
this_cpu(percpu_mm_info).foreign->is_dying &&
|
||||
test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
|
||||
put_page_and_type(page);
|
||||
/* We can race domain destruction (domain_relinquish_resources). */
|
||||
if ( unlikely(this_cpu(percpu_mm_info).foreign != NULL) )
|
||||
{
|
||||
int drop_ref;
|
||||
spin_lock(&FOREIGNDOM->page_alloc_lock);
|
||||
drop_ref = (FOREIGNDOM->is_dying &&
|
||||
test_and_clear_bit(_PGT_pinned,
|
||||
&page->u.inuse.type_info));
|
||||
spin_unlock(&FOREIGNDOM->page_alloc_lock);
|
||||
if ( drop_ref )
|
||||
put_page_and_type(page);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
@@ -313,9 +313,6 @@ void domain_kill(struct domain *d)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Tear down state /after/ setting the dying flag. */
|
||||
smp_wmb();
|
||||
|
||||
gnttab_release_mappings(d);
|
||||
domain_relinquish_resources(d);
|
||||
put_domain(d);
|
||||
|
||||
@@ -28,7 +28,11 @@
|
||||
#include <asm/processor.h>
|
||||
#include <asm/msr.h>
|
||||
|
||||
#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
|
||||
#define xchg(ptr,x) \
|
||||
({ \
|
||||
__typeof__(*(ptr)) _x_ = (x); \
|
||||
(__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \
|
||||
})
|
||||
|
||||
static __inline__ unsigned long
|
||||
__xchg_u32(volatile int *m, unsigned long val)
|
||||
|
||||
@@ -28,10 +28,16 @@
|
||||
#include <public/hvm/params.h>
|
||||
#include <public/hvm/save.h>
|
||||
|
||||
struct hvm_ioreq_page {
|
||||
spinlock_t lock;
|
||||
struct page_info *page;
|
||||
void *va;
|
||||
};
|
||||
|
||||
struct hvm_domain {
|
||||
unsigned long shared_page_va;
|
||||
unsigned long buffered_io_va;
|
||||
spinlock_t buffered_io_lock;
|
||||
struct hvm_ioreq_page ioreq;
|
||||
struct hvm_ioreq_page buf_ioreq;
|
||||
|
||||
s64 tsc_frequency;
|
||||
struct pl_time pl_time;
|
||||
|
||||
|
||||
@@ -145,6 +145,7 @@ struct hvm_function_table {
|
||||
extern struct hvm_function_table hvm_funcs;
|
||||
|
||||
int hvm_domain_initialise(struct domain *d);
|
||||
void hvm_domain_relinquish_resources(struct domain *d);
|
||||
void hvm_domain_destroy(struct domain *d);
|
||||
|
||||
int hvm_vcpu_initialise(struct vcpu *v);
|
||||
|
||||
@@ -32,14 +32,13 @@
|
||||
#define HVM_DEBUG 1
|
||||
#endif
|
||||
|
||||
static inline shared_iopage_t *get_sp(struct domain *d)
|
||||
static inline vcpu_iodata_t *get_ioreq(struct vcpu *v)
|
||||
{
|
||||
return (shared_iopage_t *) d->arch.hvm_domain.shared_page_va;
|
||||
}
|
||||
|
||||
static inline vcpu_iodata_t *get_vio(struct domain *d, unsigned long cpu)
|
||||
{
|
||||
return &get_sp(d)->vcpu_iodata[cpu];
|
||||
struct domain *d = v->domain;
|
||||
shared_iopage_t *p = d->arch.hvm_domain.ioreq.va;
|
||||
ASSERT((v == current) || spin_is_locked(&d->arch.hvm_domain.ioreq.lock));
|
||||
ASSERT(d->arch.hvm_domain.ioreq.va != NULL);
|
||||
return &p->vcpu_iodata[v->vcpu_id];
|
||||
}
|
||||
|
||||
/* XXX these are really VMX specific */
|
||||
|
||||
@@ -87,13 +87,40 @@ DECLARE_HVM_SAVE_TYPE(HEADER, 1, struct hvm_save_header);
|
||||
*/
|
||||
|
||||
struct hvm_hw_cpu {
|
||||
uint64_t eip;
|
||||
uint64_t esp;
|
||||
uint64_t eflags;
|
||||
uint8_t fpu_regs[512];
|
||||
|
||||
uint64_t rax;
|
||||
uint64_t rbx;
|
||||
uint64_t rcx;
|
||||
uint64_t rdx;
|
||||
uint64_t rbp;
|
||||
uint64_t rsi;
|
||||
uint64_t rdi;
|
||||
uint64_t rsp;
|
||||
uint64_t r8;
|
||||
uint64_t r9;
|
||||
uint64_t r10;
|
||||
uint64_t r11;
|
||||
uint64_t r12;
|
||||
uint64_t r13;
|
||||
uint64_t r14;
|
||||
uint64_t r15;
|
||||
|
||||
uint64_t rip;
|
||||
uint64_t rflags;
|
||||
|
||||
uint64_t cr0;
|
||||
uint64_t cr2;
|
||||
uint64_t cr3;
|
||||
uint64_t cr4;
|
||||
|
||||
uint64_t dr0;
|
||||
uint64_t dr1;
|
||||
uint64_t dr2;
|
||||
uint64_t dr3;
|
||||
uint64_t dr6;
|
||||
uint64_t dr7;
|
||||
|
||||
uint32_t cs_sel;
|
||||
uint32_t ds_sel;
|
||||
uint32_t es_sel;
|
||||
@@ -142,9 +169,9 @@ struct hvm_hw_cpu {
|
||||
|
||||
/* msr for em64t */
|
||||
uint64_t shadow_gs;
|
||||
uint64_t flags;
|
||||
|
||||
/* msr content saved/restored. */
|
||||
uint64_t msr_flags;
|
||||
uint64_t msr_lstar;
|
||||
uint64_t msr_star;
|
||||
uint64_t msr_cstar;
|
||||
|
||||
@@ -96,10 +96,10 @@ domain_mmap_cache_destroy(struct domain_mmap_cache *cache)
|
||||
|
||||
#else /* !CONFIG_DOMAIN_PAGE */
|
||||
|
||||
#define map_domain_page(mfn) maddr_to_virt((mfn)<<PAGE_SHIFT)
|
||||
#define map_domain_page(mfn) mfn_to_virt(mfn)
|
||||
#define unmap_domain_page(va) ((void)(va))
|
||||
|
||||
#define map_domain_page_global(mfn) maddr_to_virt((mfn)<<PAGE_SHIFT)
|
||||
#define map_domain_page_global(mfn) mfn_to_virt(mfn)
|
||||
#define unmap_domain_page_global(va) ((void)(va))
|
||||
|
||||
struct domain_mmap_cache {
|
||||
|
||||