mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
Merged.
This commit is contained in:
commit
1676162e17
162 files changed
+7271
-1638
No files matched your search
@@ -181,6 +181,7 @@
|
||||
^xen/TAGS$
|
||||
^xen/arch/x86/asm-offsets\.s$
|
||||
^xen/arch/x86/boot/mkelf32$
|
||||
^xen/arch/x86/xen\.lds$
|
||||
^xen/ddb/.*$
|
||||
^xen/include/asm$
|
||||
^xen/include/asm-.*/asm-offsets\.h$
|
||||
|
||||
@@ -25,8 +25,9 @@ int xen_init(void)
|
||||
|
||||
xen_start_info = __va(s->arch.start_info_pfn << PAGE_SHIFT);
|
||||
xen_start_info->flags = s->arch.flags;
|
||||
printk("Running on Xen! start_info_pfn=0x%lx lags=0x%x\n",
|
||||
s->arch.start_info_pfn, xen_start_info->flags);
|
||||
printk("Running on Xen! start_info_pfn=0x%lx nr_pages=%d flags=0x%x\n",
|
||||
s->arch.start_info_pfn, xen_start_info->nr_pages,
|
||||
xen_start_info->flags);
|
||||
|
||||
evtchn_init();
|
||||
initialized = 1;
|
||||
|
||||
@@ -77,8 +77,6 @@ install kernel_install:
|
||||
install -m0664 .config $(INSTALL_PATH)/boot/config-$(XINSTALL_NAME)$(INSTALL_SUFFIX)
|
||||
install -m0664 System.map $(INSTALL_PATH)/boot/System.map-$(XINSTALL_NAME)$(INSTALL_SUFFIX)
|
||||
ln -f -s vmlinuz-$(XINSTALL_NAME)$(INSTALL_SUFFIX) $(INSTALL_PATH)/boot/vmlinuz-$(VERSION).$(PATCHLEVEL)$(XENGUEST)$(INSTALL_SUFFIX)
|
||||
mkdir -p $(INSTALL_PATH)/usr/include/xen/linux
|
||||
install -m0644 $(srctree)/include/asm-xen/linux-public/*.h $(INSTALL_PATH)/usr/include/xen/linux
|
||||
|
||||
archclean:
|
||||
@if [ -e arch/xen/arch ]; then $(MAKE) $(clean)=arch/xen/arch; fi;
|
||||
|
||||
@@ -40,8 +40,6 @@
|
||||
#include <asm/fixmap.h>
|
||||
#endif
|
||||
|
||||
void (*pm_power_off)(void) = NULL;
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
|
||||
static inline void acpi_madt_oem_check(char *oem_id, char *oem_table_id) { }
|
||||
|
||||
@@ -67,8 +67,11 @@ int mtrr_add_page(unsigned long base, unsigned long size,
|
||||
op.u.add_memtype.pfn = base;
|
||||
op.u.add_memtype.nr_pfns = size;
|
||||
op.u.add_memtype.type = type;
|
||||
if ((error = HYPERVISOR_dom0_op(&op)))
|
||||
error = HYPERVISOR_dom0_op(&op);
|
||||
if (error) {
|
||||
BUG_ON(error > 0);
|
||||
return error;
|
||||
}
|
||||
|
||||
if (increment)
|
||||
++usage_table[op.u.add_memtype.reg];
|
||||
@@ -121,8 +124,12 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
|
||||
if (--usage_table[reg] < 1) {
|
||||
op.cmd = DOM0_DEL_MEMTYPE;
|
||||
op.u.del_memtype.handle = 0;
|
||||
op.u.add_memtype.reg = reg;
|
||||
(void)HYPERVISOR_dom0_op(&op);
|
||||
op.u.del_memtype.reg = reg;
|
||||
error = HYPERVISOR_dom0_op(&op);
|
||||
if (error) {
|
||||
BUG_ON(error > 0);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
error = reg;
|
||||
out:
|
||||
|
||||
@@ -76,9 +76,7 @@ EXPORT_SYMBOL(ioremap_nocache);
|
||||
EXPORT_SYMBOL(iounmap);
|
||||
EXPORT_SYMBOL(kernel_thread);
|
||||
EXPORT_SYMBOL(pm_idle);
|
||||
#ifdef CONFIG_ACPI_BOOT
|
||||
EXPORT_SYMBOL(pm_power_off);
|
||||
#endif
|
||||
EXPORT_SYMBOL(get_cmos_time);
|
||||
EXPORT_SYMBOL(cpu_khz);
|
||||
EXPORT_SYMBOL(apm_info);
|
||||
|
||||
@@ -389,6 +389,30 @@ grant_write(struct file *file, const char __user *buffer, unsigned long count,
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int __init
|
||||
gnttab_proc_init(void)
|
||||
{
|
||||
/*
|
||||
* /proc/xen/grant : used by libxc to access grant tables
|
||||
*/
|
||||
if ((grant_pde = create_xen_proc_entry("grant", 0600)) == NULL) {
|
||||
WPRINTK("Unable to create grant xen proc entry\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
grant_file_ops.read = grant_pde->proc_fops->read;
|
||||
grant_file_ops.write = grant_pde->proc_fops->write;
|
||||
|
||||
grant_pde->proc_fops = &grant_file_ops;
|
||||
|
||||
grant_pde->read_proc = &grant_read;
|
||||
grant_pde->write_proc = &grant_write;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
device_initcall(gnttab_proc_init);
|
||||
|
||||
#endif /* CONFIG_PROC_FS */
|
||||
|
||||
int
|
||||
@@ -446,29 +470,11 @@ gnttab_init(void)
|
||||
gnttab_free_count = NR_GRANT_ENTRIES - NR_RESERVED_ENTRIES;
|
||||
gnttab_free_head = NR_RESERVED_ENTRIES;
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
/*
|
||||
* /proc/xen/grant : used by libxc to access grant tables
|
||||
*/
|
||||
if ((grant_pde = create_xen_proc_entry("grant", 0600)) == NULL) {
|
||||
WPRINTK("Unable to create grant xen proc entry\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
grant_file_ops.read = grant_pde->proc_fops->read;
|
||||
grant_file_ops.write = grant_pde->proc_fops->write;
|
||||
|
||||
grant_pde->proc_fops = &grant_file_ops;
|
||||
|
||||
grant_pde->read_proc = &grant_read;
|
||||
grant_pde->write_proc = &grant_write;
|
||||
#endif
|
||||
|
||||
printk("Grant table initialized\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
__initcall(gnttab_init);
|
||||
core_initcall(gnttab_init);
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
|
||||
@@ -17,6 +17,13 @@
|
||||
#include <linux/kthread.h>
|
||||
#include <asm-xen/xencons.h>
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
/*
|
||||
* Power off function, if any
|
||||
*/
|
||||
void (*pm_power_off)(void);
|
||||
#endif
|
||||
|
||||
#define SHUTDOWN_INVALID -1
|
||||
#define SHUTDOWN_POWEROFF 0
|
||||
#define SHUTDOWN_REBOOT 1
|
||||
|
||||
@@ -59,9 +59,7 @@ EXPORT_SYMBOL(disable_irq_nosync);
|
||||
EXPORT_SYMBOL(probe_irq_mask);
|
||||
EXPORT_SYMBOL(kernel_thread);
|
||||
EXPORT_SYMBOL(pm_idle);
|
||||
#ifdef CONFIG_ACPI_BOOT
|
||||
EXPORT_SYMBOL(pm_power_off);
|
||||
#endif
|
||||
EXPORT_SYMBOL(get_cmos_time);
|
||||
|
||||
EXPORT_SYMBOL(__down_failed);
|
||||
|
||||
@@ -540,6 +540,9 @@ static int __init blkif_init(void)
|
||||
pending_vaddrs = kmalloc(sizeof(pending_vaddrs[0]) *
|
||||
mmap_pages, GFP_KERNEL);
|
||||
if (!pending_reqs || !pending_grant_handles || !pending_vaddrs) {
|
||||
kfree(pending_reqs);
|
||||
kfree(pending_grant_handles);
|
||||
kfree(pending_vaddrs);
|
||||
printk("%s: out of memory\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -331,7 +331,12 @@ static void connect(struct blkfront_info *info)
|
||||
return;
|
||||
}
|
||||
|
||||
xlvbd_add(sectors, info->vdevice, binfo, sector_size, info);
|
||||
err = xlvbd_add(sectors, info->vdevice, binfo, sector_size, info);
|
||||
if (err) {
|
||||
xenbus_dev_fatal(info->xbdev, err, "xlvbd_add at %s",
|
||||
info->xbdev->otherend);
|
||||
return;
|
||||
}
|
||||
|
||||
(void)xenbus_switch_state(info->xbdev, NULL, XenbusStateConnected);
|
||||
|
||||
|
||||
@@ -208,7 +208,7 @@ static struct page *blktap_nopage(struct vm_area_struct *vma,
|
||||
}
|
||||
|
||||
struct vm_operations_struct blktap_vm_ops = {
|
||||
nopage: blktap_nopage,
|
||||
.nopage = blktap_nopage,
|
||||
};
|
||||
|
||||
/******************************************************************
|
||||
@@ -225,7 +225,7 @@ static int blktap_open(struct inode *inode, struct file *filp)
|
||||
/* Allocate the fe ring. */
|
||||
sring = (blkif_sring_t *)get_zeroed_page(GFP_KERNEL);
|
||||
if (sring == NULL)
|
||||
goto fail_nomem;
|
||||
return -ENOMEM;
|
||||
|
||||
SetPageReserved(virt_to_page(sring));
|
||||
|
||||
@@ -233,9 +233,6 @@ static int blktap_open(struct inode *inode, struct file *filp)
|
||||
FRONT_RING_INIT(&blktap_ufe_ring, sring, PAGE_SIZE);
|
||||
|
||||
return 0;
|
||||
|
||||
fail_nomem:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static int blktap_release(struct inode *inode, struct file *filp)
|
||||
@@ -391,12 +388,12 @@ void blktap_kick_user(void)
|
||||
}
|
||||
|
||||
static struct file_operations blktap_fops = {
|
||||
owner: THIS_MODULE,
|
||||
poll: blktap_poll,
|
||||
ioctl: blktap_ioctl,
|
||||
open: blktap_open,
|
||||
release: blktap_release,
|
||||
mmap: blktap_mmap,
|
||||
.owner = THIS_MODULE,
|
||||
.poll = blktap_poll,
|
||||
.ioctl = blktap_ioctl,
|
||||
.open = blktap_open,
|
||||
.release = blktap_release,
|
||||
.mmap = blktap_mmap,
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -314,39 +314,31 @@ static void __xencons_tx_flush(void)
|
||||
{
|
||||
int sent, sz, work_done = 0;
|
||||
|
||||
if (xen_start_info->flags & SIF_INITDOMAIN) {
|
||||
if (x_char) {
|
||||
if (x_char) {
|
||||
if (xen_start_info->flags & SIF_INITDOMAIN)
|
||||
kcons_write_dom0(NULL, &x_char, 1);
|
||||
x_char = 0;
|
||||
work_done = 1;
|
||||
}
|
||||
else
|
||||
while (x_char)
|
||||
if (xencons_ring_send(&x_char, 1) == 1)
|
||||
break;
|
||||
x_char = 0;
|
||||
work_done = 1;
|
||||
}
|
||||
|
||||
while (wc != wp) {
|
||||
sz = wp - wc;
|
||||
if (sz > (wbuf_size - WBUF_MASK(wc)))
|
||||
sz = wbuf_size - WBUF_MASK(wc);
|
||||
while (wc != wp) {
|
||||
sz = wp - wc;
|
||||
if (sz > (wbuf_size - WBUF_MASK(wc)))
|
||||
sz = wbuf_size - WBUF_MASK(wc);
|
||||
if (xen_start_info->flags & SIF_INITDOMAIN) {
|
||||
kcons_write_dom0(NULL, &wbuf[WBUF_MASK(wc)], sz);
|
||||
wc += sz;
|
||||
work_done = 1;
|
||||
}
|
||||
} else {
|
||||
while (x_char) {
|
||||
if (xencons_ring_send(&x_char, 1) == 1) {
|
||||
x_char = 0;
|
||||
work_done = 1;
|
||||
}
|
||||
}
|
||||
|
||||
while (wc != wp) {
|
||||
sz = wp - wc;
|
||||
if (sz > (wbuf_size - WBUF_MASK(wc)))
|
||||
sz = wbuf_size - WBUF_MASK(wc);
|
||||
} else {
|
||||
sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz);
|
||||
if (sent == 0)
|
||||
break;
|
||||
wc += sent;
|
||||
work_done = 1;
|
||||
}
|
||||
work_done = 1;
|
||||
}
|
||||
|
||||
if (work_done && (xencons_tty != NULL)) {
|
||||
|
||||
@@ -82,7 +82,7 @@ typedef struct netif_st {
|
||||
#define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE)
|
||||
|
||||
void netif_creditlimit(netif_t *netif);
|
||||
int netif_disconnect(netif_t *netif);
|
||||
void netif_disconnect(netif_t *netif);
|
||||
|
||||
netif_t *alloc_netif(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN]);
|
||||
void free_netif(netif_t *netif);
|
||||
|
||||
@@ -183,7 +183,7 @@ static void unmap_frontend_pages(netif_t *netif)
|
||||
int netif_map(netif_t *netif, unsigned long tx_ring_ref,
|
||||
unsigned long rx_ring_ref, unsigned int evtchn)
|
||||
{
|
||||
int err;
|
||||
int err = -ENOMEM;
|
||||
netif_tx_sring_t *txs;
|
||||
netif_rx_sring_t *rxs;
|
||||
evtchn_op_t op = {
|
||||
@@ -196,24 +196,19 @@ int netif_map(netif_t *netif, unsigned long tx_ring_ref,
|
||||
return 0;
|
||||
|
||||
netif->tx_comms_area = alloc_vm_area(PAGE_SIZE);
|
||||
netif->rx_comms_area = alloc_vm_area(PAGE_SIZE);
|
||||
if (netif->tx_comms_area == NULL || netif->rx_comms_area == NULL)
|
||||
if (netif->tx_comms_area == NULL)
|
||||
return -ENOMEM;
|
||||
netif->rx_comms_area = alloc_vm_area(PAGE_SIZE);
|
||||
if (netif->rx_comms_area == NULL)
|
||||
goto err_rx;
|
||||
|
||||
err = map_frontend_pages(netif, tx_ring_ref, rx_ring_ref);
|
||||
if (err) {
|
||||
free_vm_area(netif->tx_comms_area);
|
||||
free_vm_area(netif->rx_comms_area);
|
||||
return err;
|
||||
}
|
||||
if (err)
|
||||
goto err_map;
|
||||
|
||||
err = HYPERVISOR_event_channel_op(&op);
|
||||
if (err) {
|
||||
unmap_frontend_pages(netif);
|
||||
free_vm_area(netif->tx_comms_area);
|
||||
free_vm_area(netif->rx_comms_area);
|
||||
return err;
|
||||
}
|
||||
if (err)
|
||||
goto err_hypervisor;
|
||||
|
||||
netif->evtchn = op.u.bind_interdomain.local_port;
|
||||
|
||||
@@ -241,19 +236,22 @@ int netif_map(netif_t *netif, unsigned long tx_ring_ref,
|
||||
rtnl_unlock();
|
||||
|
||||
return 0;
|
||||
err_hypervisor:
|
||||
unmap_frontend_pages(netif);
|
||||
err_map:
|
||||
free_vm_area(netif->rx_comms_area);
|
||||
err_rx:
|
||||
free_vm_area(netif->tx_comms_area);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void free_netif_callback(void *arg)
|
||||
{
|
||||
netif_t *netif = (netif_t *)arg;
|
||||
|
||||
/* Already disconnected? */
|
||||
if (!netif->irq)
|
||||
return;
|
||||
|
||||
unbind_from_irqhandler(netif->irq, netif);
|
||||
netif->irq = 0;
|
||||
|
||||
if (netif->irq)
|
||||
unbind_from_irqhandler(netif->irq, netif);
|
||||
|
||||
unregister_netdev(netif->dev);
|
||||
|
||||
if (netif->tx.sring) {
|
||||
@@ -290,10 +288,10 @@ void netif_creditlimit(netif_t *netif)
|
||||
#endif
|
||||
}
|
||||
|
||||
int netif_disconnect(netif_t *netif)
|
||||
void netif_disconnect(netif_t *netif)
|
||||
{
|
||||
|
||||
if (netif->status == CONNECTED) {
|
||||
switch (netif->status) {
|
||||
case CONNECTED:
|
||||
rtnl_lock();
|
||||
netif->status = DISCONNECTING;
|
||||
wmb();
|
||||
@@ -301,10 +299,14 @@ int netif_disconnect(netif_t *netif)
|
||||
__netif_down(netif);
|
||||
rtnl_unlock();
|
||||
netif_put(netif);
|
||||
return 0; /* Caller should not send response message. */
|
||||
break;
|
||||
case DISCONNECTED:
|
||||
BUG_ON(atomic_read(&netif->refcnt) != 0);
|
||||
free_netif(netif);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <asm-xen/balloon.h>
|
||||
#include <asm-xen/xen-public/memory.h>
|
||||
|
||||
/*#define NETBE_DEBUG_INTERRUPT*/
|
||||
|
||||
static void netif_idx_release(u16 pending_idx);
|
||||
static void netif_page_release(struct page *page);
|
||||
@@ -727,6 +728,7 @@ static int make_rx_response(netif_t *netif,
|
||||
return notify;
|
||||
}
|
||||
|
||||
#ifdef NETBE_DEBUG_INTERRUPT
|
||||
static irqreturn_t netif_be_dbg(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct list_head *ent;
|
||||
@@ -758,6 +760,7 @@ static irqreturn_t netif_be_dbg(int irq, void *dev_id, struct pt_regs *regs)
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int __init netback_init(void)
|
||||
{
|
||||
@@ -794,6 +797,7 @@ static int __init netback_init(void)
|
||||
|
||||
netif_xenbus_init();
|
||||
|
||||
#ifdef NETBE_DEBUG_INTERRUPT
|
||||
(void)bind_virq_to_irqhandler(
|
||||
VIRQ_DEBUG,
|
||||
0,
|
||||
@@ -801,6 +805,7 @@ static int __init netback_init(void)
|
||||
SA_SHIRQ,
|
||||
"net-be-dbg",
|
||||
&netif_be_dbg);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -117,6 +117,8 @@ struct netfront_info
|
||||
int rx_min_target, rx_max_target, rx_target;
|
||||
struct sk_buff_head rx_batch;
|
||||
|
||||
struct timer_list rx_refill_timer;
|
||||
|
||||
/*
|
||||
* {tx,rx}_skbs store outstanding skbuffs. The first entry in each
|
||||
* array is an index into a chain of free entries.
|
||||
@@ -517,6 +519,13 @@ static void network_tx_buf_gc(struct net_device *dev)
|
||||
}
|
||||
|
||||
|
||||
static void rx_refill_timeout(unsigned long data)
|
||||
{
|
||||
struct net_device *dev = (struct net_device *)data;
|
||||
netif_rx_schedule(dev);
|
||||
}
|
||||
|
||||
|
||||
static void network_alloc_rx_buffers(struct net_device *dev)
|
||||
{
|
||||
unsigned short id;
|
||||
@@ -534,7 +543,7 @@ static void network_alloc_rx_buffers(struct net_device *dev)
|
||||
* Allocate skbuffs greedily, even though we batch updates to the
|
||||
* receive ring. This creates a less bursty demand on the memory
|
||||
* allocator, so should reduce the chance of failed allocation requests
|
||||
* both for ourself and for other kernel subsystems.
|
||||
* both for ourself and for other kernel subsystems.
|
||||
*/
|
||||
batch_target = np->rx_target - (req_prod - np->rx.rsp_cons);
|
||||
for (i = skb_queue_len(&np->rx_batch); i < batch_target; i++) {
|
||||
@@ -545,8 +554,15 @@ static void network_alloc_rx_buffers(struct net_device *dev)
|
||||
skb = alloc_xen_skb(
|
||||
((PAGE_SIZE - sizeof(struct skb_shared_info)) &
|
||||
(-SKB_DATA_ALIGN(1))) - 16);
|
||||
if (skb == NULL)
|
||||
break;
|
||||
if (skb == NULL) {
|
||||
/* Any skbuffs queued for refill? Force them out. */
|
||||
if (i != 0)
|
||||
goto refill;
|
||||
/* Could not allocate any skbuffs. Try again later. */
|
||||
mod_timer(&np->rx_refill_timer,
|
||||
jiffies + (HZ/10));
|
||||
return;
|
||||
}
|
||||
__skb_queue_tail(&np->rx_batch, skb);
|
||||
}
|
||||
|
||||
@@ -554,6 +570,12 @@ static void network_alloc_rx_buffers(struct net_device *dev)
|
||||
if (i < (np->rx_target/2))
|
||||
return;
|
||||
|
||||
/* Adjust our fill target if we risked running out of buffers. */
|
||||
if (((req_prod - np->rx.sring->rsp_prod) < (np->rx_target / 4)) &&
|
||||
((np->rx_target *= 2) > np->rx_max_target))
|
||||
np->rx_target = np->rx_max_target;
|
||||
|
||||
refill:
|
||||
for (i = 0; ; i++) {
|
||||
if ((skb = __skb_dequeue(&np->rx_batch)) == NULL)
|
||||
break;
|
||||
@@ -608,11 +630,6 @@ static void network_alloc_rx_buffers(struct net_device *dev)
|
||||
/* Above is a suitable barrier to ensure backend will see requests. */
|
||||
np->rx.req_prod_pvt = req_prod + i;
|
||||
RING_PUSH_REQUESTS(&np->rx);
|
||||
|
||||
/* Adjust our fill target if we risked running out of buffers. */
|
||||
if (((req_prod - np->rx.sring->rsp_prod) < (np->rx_target / 4)) &&
|
||||
((np->rx_target *= 2) > np->rx_max_target))
|
||||
np->rx_target = np->rx_max_target;
|
||||
}
|
||||
|
||||
|
||||
@@ -1077,6 +1094,10 @@ static int create_netdev(int handle, struct xenbus_device *dev,
|
||||
np->rx_min_target = RX_MIN_TARGET;
|
||||
np->rx_max_target = RX_MAX_TARGET;
|
||||
|
||||
init_timer(&np->rx_refill_timer);
|
||||
np->rx_refill_timer.data = (unsigned long)netdev;
|
||||
np->rx_refill_timer.function = rx_refill_timeout;
|
||||
|
||||
/* Initialise {tx,rx}_skbs as a free chain containing every entry. */
|
||||
for (i = 0; i <= NET_TX_RING_SIZE; i++) {
|
||||
np->tx_skbs[i] = (void *)((unsigned long) i+1);
|
||||
@@ -1188,29 +1209,26 @@ static int netfront_remove(struct xenbus_device *dev)
|
||||
|
||||
DPRINTK("%s\n", dev->nodename);
|
||||
|
||||
netif_free(info);
|
||||
kfree(info);
|
||||
netif_disconnect_backend(info);
|
||||
free_netdev(info->netdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void netif_free(struct netfront_info *info)
|
||||
{
|
||||
netif_disconnect_backend(info);
|
||||
close_netdev(info);
|
||||
}
|
||||
|
||||
|
||||
static void close_netdev(struct netfront_info *info)
|
||||
{
|
||||
if (info->netdev) {
|
||||
spin_lock_irq(&info->netdev->xmit_lock);
|
||||
netif_stop_queue(info->netdev);
|
||||
spin_unlock_irq(&info->netdev->xmit_lock);
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
xennet_proc_delif(info->netdev);
|
||||
xennet_proc_delif(info->netdev);
|
||||
#endif
|
||||
unregister_netdev(info->netdev);
|
||||
info->netdev = NULL;
|
||||
}
|
||||
|
||||
del_timer_sync(&info->rx_refill_timer);
|
||||
|
||||
unregister_netdev(info->netdev);
|
||||
}
|
||||
|
||||
|
||||
@@ -1219,21 +1237,28 @@ static void netif_disconnect_backend(struct netfront_info *info)
|
||||
/* Stop old i/f to prevent errors whilst we rebuild the state. */
|
||||
spin_lock_irq(&info->tx_lock);
|
||||
spin_lock(&info->rx_lock);
|
||||
netif_stop_queue(info->netdev);
|
||||
/* info->backend_state = BEST_DISCONNECTED; */
|
||||
info->backend_state = BEST_DISCONNECTED;
|
||||
spin_unlock(&info->rx_lock);
|
||||
spin_unlock_irq(&info->tx_lock);
|
||||
|
||||
|
||||
if (info->irq)
|
||||
unbind_from_irqhandler(info->irq, info->netdev);
|
||||
info->evtchn = info->irq = 0;
|
||||
|
||||
end_access(info->tx_ring_ref, info->tx.sring);
|
||||
end_access(info->rx_ring_ref, info->rx.sring);
|
||||
info->tx_ring_ref = GRANT_INVALID_REF;
|
||||
info->rx_ring_ref = GRANT_INVALID_REF;
|
||||
info->tx.sring = NULL;
|
||||
info->rx.sring = NULL;
|
||||
}
|
||||
|
||||
if (info->irq)
|
||||
unbind_from_irqhandler(info->irq, info->netdev);
|
||||
info->evtchn = info->irq = 0;
|
||||
|
||||
static void netif_free(struct netfront_info *info)
|
||||
{
|
||||
close_netdev(info);
|
||||
netif_disconnect_backend(info);
|
||||
free_netdev(info->netdev);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -111,7 +111,6 @@ static ssize_t xenbus_dev_write(struct file *filp,
|
||||
struct xenbus_dev_data *u = filp->private_data;
|
||||
struct xenbus_dev_transaction *trans;
|
||||
void *reply;
|
||||
int err = 0;
|
||||
|
||||
if ((len + u->len) > sizeof(u->u.buffer))
|
||||
return -EINVAL;
|
||||
@@ -136,41 +135,36 @@ static ssize_t xenbus_dev_write(struct file *filp,
|
||||
case XS_RM:
|
||||
case XS_SET_PERMS:
|
||||
reply = xenbus_dev_request_and_reply(&u->u.msg);
|
||||
if (IS_ERR(reply)) {
|
||||
err = PTR_ERR(reply);
|
||||
} else {
|
||||
if (u->u.msg.type == XS_TRANSACTION_START) {
|
||||
trans = kmalloc(sizeof(*trans), GFP_KERNEL);
|
||||
trans->handle = (struct xenbus_transaction *)
|
||||
simple_strtoul(reply, NULL, 0);
|
||||
list_add(&trans->list, &u->transactions);
|
||||
} else if (u->u.msg.type == XS_TRANSACTION_END) {
|
||||
list_for_each_entry(trans, &u->transactions,
|
||||
list)
|
||||
if ((unsigned long)trans->handle ==
|
||||
(unsigned long)u->u.msg.tx_id)
|
||||
break;
|
||||
BUG_ON(&trans->list == &u->transactions);
|
||||
list_del(&trans->list);
|
||||
kfree(trans);
|
||||
}
|
||||
queue_reply(u, (char *)&u->u.msg, sizeof(u->u.msg));
|
||||
queue_reply(u, (char *)reply, u->u.msg.len);
|
||||
kfree(reply);
|
||||
if (IS_ERR(reply))
|
||||
return PTR_ERR(reply);
|
||||
|
||||
if (u->u.msg.type == XS_TRANSACTION_START) {
|
||||
trans = kmalloc(sizeof(*trans), GFP_KERNEL);
|
||||
if (!trans)
|
||||
return -ENOMEM;
|
||||
trans->handle = (struct xenbus_transaction *)
|
||||
simple_strtoul(reply, NULL, 0);
|
||||
list_add(&trans->list, &u->transactions);
|
||||
} else if (u->u.msg.type == XS_TRANSACTION_END) {
|
||||
list_for_each_entry(trans, &u->transactions, list)
|
||||
if ((unsigned long)trans->handle ==
|
||||
(unsigned long)u->u.msg.tx_id)
|
||||
break;
|
||||
BUG_ON(&trans->list == &u->transactions);
|
||||
list_del(&trans->list);
|
||||
kfree(trans);
|
||||
}
|
||||
queue_reply(u, (char *)&u->u.msg, sizeof(u->u.msg));
|
||||
queue_reply(u, (char *)reply, u->u.msg.len);
|
||||
kfree(reply);
|
||||
break;
|
||||
|
||||
default:
|
||||
err = -EINVAL;
|
||||
break;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (err == 0) {
|
||||
u->len = 0;
|
||||
err = len;
|
||||
}
|
||||
|
||||
return err;
|
||||
u->len = 0;
|
||||
return len;
|
||||
}
|
||||
|
||||
static int xenbus_dev_open(struct inode *inode, struct file *filp)
|
||||
|
||||
@@ -542,14 +542,6 @@ static int xenbus_probe_node(struct xen_bus_type *bus,
|
||||
const char *type,
|
||||
const char *nodename)
|
||||
{
|
||||
#define CHECK_FAIL \
|
||||
do { \
|
||||
if (err) \
|
||||
goto fail; \
|
||||
} \
|
||||
while (0) \
|
||||
|
||||
|
||||
int err;
|
||||
struct xenbus_device *xendev;
|
||||
size_t stringlen;
|
||||
@@ -584,19 +576,18 @@ static int xenbus_probe_node(struct xen_bus_type *bus,
|
||||
xendev->dev.release = xenbus_dev_release;
|
||||
|
||||
err = bus->get_bus_id(xendev->dev.bus_id, xendev->nodename);
|
||||
CHECK_FAIL;
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
/* Register with generic device framework. */
|
||||
err = device_register(&xendev->dev);
|
||||
CHECK_FAIL;
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
device_create_file(&xendev->dev, &dev_attr_nodename);
|
||||
device_create_file(&xendev->dev, &dev_attr_devtype);
|
||||
|
||||
return 0;
|
||||
|
||||
#undef CHECK_FAIL
|
||||
|
||||
fail:
|
||||
xenbus_dev_free(xendev);
|
||||
return err;
|
||||
|
||||
@@ -372,7 +372,7 @@ HYPERVISOR_memory_op(
|
||||
int ret;
|
||||
__asm__ __volatile__ ( ";; mov r14=%2 ; mov r15=%3 ; mov r2=%1 ; break 0x1000 ;; mov %0=r8 ;;"
|
||||
: "=r" (ret)
|
||||
: "i" (__HYPERVISOR_console_io), "r"(cmd), "r"(arg)
|
||||
: "i" (__HYPERVISOR_memory_op), "r"(cmd), "r"(arg)
|
||||
: "r14","r15","r2","r8","memory" );
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ SUBDIRS += firmware
|
||||
SUBDIRS += security
|
||||
SUBDIRS += console
|
||||
SUBDIRS += xenmon
|
||||
SUBDIRS += guest-headers
|
||||
ifeq ($(VTPM_TOOLS),y)
|
||||
SUBDIRS += vtpm_manager
|
||||
SUBDIRS += vtpm
|
||||
|
||||
@@ -35,6 +35,8 @@ mk-symlinks: LINUX_ROOT=$(XEN_ROOT)/linux-2.6-xen-sparse
|
||||
mk-symlinks:
|
||||
mkdir -p xen
|
||||
( cd xen && ln -sf ../$(XEN_ROOT)/xen/include/public/*.h . )
|
||||
mkdir -p xen/hvm
|
||||
( cd xen/hvm && ln -sf ../../$(XEN_ROOT)/xen/include/public/hvm/*.h . )
|
||||
mkdir -p xen/io
|
||||
( cd xen/io && ln -sf ../../$(XEN_ROOT)/xen/include/public/io/*.h . )
|
||||
mkdir -p xen/linux
|
||||
|
||||
@@ -119,8 +119,8 @@ xendebug_get_context (int xc_handle, uint32_t domid, uint32_t vcpu)
|
||||
|
||||
if ( !ctxt->valid[vcpu] )
|
||||
{
|
||||
if ( (rc = xc_domain_get_vcpu_context(xc_handle, domid, vcpu,
|
||||
&ctxt->context[vcpu])) )
|
||||
if ( (rc = xc_vcpu_getcontext(xc_handle, domid, vcpu,
|
||||
&ctxt->context[vcpu])) )
|
||||
return NULL;
|
||||
|
||||
ctxt->valid[vcpu] = true;
|
||||
@@ -139,10 +139,10 @@ xendebug_set_context (int xc_handle, domain_context_p ctxt, uint32_t vcpu)
|
||||
return -EINVAL;
|
||||
|
||||
op.interface_version = DOM0_INTERFACE_VERSION;
|
||||
op.cmd = DOM0_SETDOMAININFO;
|
||||
op.u.setdomaininfo.domain = ctxt->domid;
|
||||
op.u.setdomaininfo.vcpu = vcpu;
|
||||
op.u.setdomaininfo.ctxt = &ctxt->context[vcpu];
|
||||
op.cmd = DOM0_SETVCPUCONTEXT;
|
||||
op.u.setvcpucontext.domain = ctxt->domid;
|
||||
op.u.setvcpucontext.vcpu = vcpu;
|
||||
op.u.setvcpucontext.ctxt = &ctxt->context[vcpu];
|
||||
|
||||
if ( (rc = mlock(&ctxt->context[vcpu], sizeof(vcpu_guest_context_t))) )
|
||||
return rc;
|
||||
|
||||
@@ -28,7 +28,13 @@ name = "ExampleVMXDomain"
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# the number of cpus guest platform has, default=1
|
||||
vcpus=1
|
||||
#vcpus=1
|
||||
|
||||
# enable/disalbe vmx guest ACPI, default=0 (disabled)
|
||||
#acpi=0
|
||||
|
||||
# enable/disalbe vmx guest APIC, default=0 (disabled)
|
||||
#apic=0
|
||||
|
||||
# List of which CPUS this domain is allowed to use, default Xen picks
|
||||
#cpus = "" # leave to Xen to pick
|
||||
|
||||
@@ -24,7 +24,7 @@ include $(XEN_ROOT)/tools/Rules.mk
|
||||
# The emulator code lives in ROM space
|
||||
TEXTADDR=0x000D0000
|
||||
|
||||
DEFINES=-DDEBUG -D_ACPI_ -DTEXTADDR=$(TEXTADDR)
|
||||
DEFINES=-DDEBUG -DTEXTADDR=$(TEXTADDR)
|
||||
XENINC=-I$(XEN_ROOT)/tools/libxc
|
||||
|
||||
LD = ld
|
||||
|
||||
@@ -17,30 +17,73 @@
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
* Place - Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "../acpi/acpi2_0.h"
|
||||
#include "../acpi/acpi_madt.h"
|
||||
|
||||
#include <xen/hvm/hvm_info_table.h>
|
||||
|
||||
#define NULL ((void*)0)
|
||||
|
||||
extern int puts(const char *s);
|
||||
|
||||
#define VCPU_NR_PAGE 0x0009F000
|
||||
#define VCPU_NR_OFFSET 0x00000800
|
||||
#define VCPU_MAGIC 0x76637075 /* "vcpu" */
|
||||
static struct hvm_info_table *table = NULL;
|
||||
|
||||
/* xc_vmx_builder wrote vcpu block at 0x9F800. Return it. */
|
||||
static int
|
||||
get_vcpu_nr(void)
|
||||
static int validate_hvm_info(struct hvm_info_table *t)
|
||||
{
|
||||
unsigned int *vcpus;
|
||||
char signature[] = "HVM INFO";
|
||||
uint8_t *ptr = (uint8_t *)t;
|
||||
uint8_t sum = 0;
|
||||
int i;
|
||||
|
||||
vcpus = (unsigned int *)(VCPU_NR_PAGE + VCPU_NR_OFFSET);
|
||||
if (vcpus[0] != VCPU_MAGIC) {
|
||||
puts("Bad vcpus magic, set vcpu number to 1 by default.\n");
|
||||
return 1;
|
||||
/* strncmp(t->signature, "HVM INFO", 8) */
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (signature[i] != t->signature[i]) {
|
||||
puts("Bad hvm info signature\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return vcpus[1];
|
||||
for (i = 0; i < t->length; i++)
|
||||
sum += ptr[i];
|
||||
|
||||
return (sum == 0);
|
||||
}
|
||||
|
||||
/* xc_vmx_builder wrote hvm info at 0x9F800. Return it. */
|
||||
static struct hvm_info_table *
|
||||
get_hvm_info_table(void)
|
||||
{
|
||||
struct hvm_info_table *t;
|
||||
int i;
|
||||
|
||||
if (table != NULL)
|
||||
return table;
|
||||
|
||||
t = (struct hvm_info_table *)HVM_INFO_PADDR;
|
||||
|
||||
if (!validate_hvm_info(t)) {
|
||||
puts("Bad hvm info table\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
table = t;
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
int
|
||||
get_vcpu_nr(void)
|
||||
{
|
||||
struct hvm_info_table *t = get_hvm_info_table();
|
||||
return (t ? t->nr_vcpus : 1); /* default 1 vcpu */
|
||||
}
|
||||
|
||||
int
|
||||
get_acpi_enabled(void)
|
||||
{
|
||||
struct hvm_info_table *t = get_hvm_info_table();
|
||||
return (t ? t->acpi_enabled : 0); /* default no acpi */
|
||||
}
|
||||
|
||||
static void *
|
||||
@@ -74,10 +117,10 @@ acpi_madt_get_madt(unsigned char *acpi_start)
|
||||
return madt;
|
||||
}
|
||||
|
||||
static void
|
||||
static void
|
||||
set_checksum(void *start, int checksum_offset, int len)
|
||||
{
|
||||
unsigned char sum = 0;
|
||||
unsigned char sum = 0;
|
||||
unsigned char *ptr;
|
||||
|
||||
ptr = start;
|
||||
@@ -89,9 +132,9 @@ set_checksum(void *start, int checksum_offset, int len)
|
||||
ptr[checksum_offset] = -sum;
|
||||
}
|
||||
|
||||
static int
|
||||
static int
|
||||
acpi_madt_set_local_apics(
|
||||
int nr_vcpu,
|
||||
int nr_vcpu,
|
||||
ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE *madt)
|
||||
{
|
||||
int i;
|
||||
@@ -104,14 +147,14 @@ acpi_madt_set_local_apics(
|
||||
madt->LocalApic[i].Length = sizeof (ACPI_LOCAL_APIC_STRUCTURE);
|
||||
madt->LocalApic[i].AcpiProcessorId = i;
|
||||
madt->LocalApic[i].ApicId = i;
|
||||
madt->LocalApic[i].Flags = 1;
|
||||
madt->LocalApic[i].Flags = 1;
|
||||
}
|
||||
|
||||
madt->Header.Header.Length =
|
||||
sizeof(ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE) -
|
||||
sizeof(ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE) -
|
||||
(MAX_VIRT_CPUS - nr_vcpu)* sizeof(ACPI_LOCAL_APIC_STRUCTURE);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define FIELD_OFFSET(TYPE,Field) ((unsigned int)(&(((TYPE *) 0)->Field)))
|
||||
@@ -133,7 +176,7 @@ int acpi_madt_update(unsigned char *acpi_start)
|
||||
madt, FIELD_OFFSET(ACPI_TABLE_HEADER, Checksum),
|
||||
madt->Header.Header.Length);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include <xen/vmx_assist.h>
|
||||
#include <xen/hvm/vmx_assist.h>
|
||||
|
||||
#define NR_EXCEPTION_HANDLER 32
|
||||
#define NR_INTERRUPT_HANDLERS 16
|
||||
|
||||
@@ -24,12 +24,10 @@
|
||||
#include "machine.h"
|
||||
#include "roms.h"
|
||||
|
||||
#ifdef _ACPI_
|
||||
#include "acpi.h"
|
||||
#include "../acpi/acpi2_0.h" // for ACPI_PHYSICAL_ADDRESS
|
||||
int acpi_madt_update(unsigned char* acpi_start);
|
||||
#endif
|
||||
|
||||
int get_acpi_enabled(void);
|
||||
|
||||
/*
|
||||
* C runtime start off
|
||||
@@ -120,18 +118,17 @@ main(void)
|
||||
memcpy((void *)0xC0000,
|
||||
vgabios_stdvga, sizeof(vgabios_stdvga));
|
||||
}
|
||||
#ifdef _ACPI_
|
||||
puts("Loading ACPI ...\n");
|
||||
|
||||
acpi_madt_update(acpi);
|
||||
|
||||
if (ACPI_PHYSICAL_ADDRESS+sizeof(acpi) <= 0xF0000) {
|
||||
/* make sure acpi table does not overlap rombios
|
||||
* currently acpi less than 8K will be OK.
|
||||
*/
|
||||
memcpy((void *)ACPI_PHYSICAL_ADDRESS, acpi, sizeof(acpi));
|
||||
if (get_acpi_enabled() != 0) {
|
||||
puts("Loading ACPI ...\n");
|
||||
acpi_madt_update((unsigned char*)acpi);
|
||||
if (ACPI_PHYSICAL_ADDRESS+sizeof(acpi) <= 0xF0000) {
|
||||
/* make sure acpi table does not overlap rombios
|
||||
* currently acpi less than 8K will be OK.
|
||||
*/
|
||||
memcpy((void *)ACPI_PHYSICAL_ADDRESS, acpi, sizeof(acpi));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
puts("Loading VMXAssist ...\n");
|
||||
memcpy((void *)TEXTADDR, vmxassist, sizeof(vmxassist));
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
XEN_ROOT=../..
|
||||
linuxsparsetree = $(XEN_ROOT)/linux-2.6-xen-sparse
|
||||
|
||||
check:
|
||||
|
||||
install:
|
||||
mkdir -p $(DESTDIR)/usr/include/xen/linux
|
||||
install -m0644 $(linuxsparsetree)/include/asm-xen/linux-public/*.h $(DESTDIR)/usr/include/xen/linux
|
||||
|
||||
clean:
|
||||
@@ -23,7 +23,7 @@
|
||||
*/
|
||||
#include "vl.h"
|
||||
#include <xenctrl.h>
|
||||
#include <xen/io/ioreq.h>
|
||||
#include <xen/hvm/ioreq.h>
|
||||
|
||||
//#define DEBUG_PIT
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
*/
|
||||
#include "vl.h"
|
||||
#include <xenctrl.h>
|
||||
#include <xen/io/ioreq.h>
|
||||
#include <xen/hvm/ioreq.h>
|
||||
|
||||
/* debug PIC */
|
||||
//#define DEBUG_PIC
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "xenctrl.h"
|
||||
#include <xen/io/ioreq.h>
|
||||
#include <xen/hvm/ioreq.h>
|
||||
#include <stdio.h>
|
||||
#include "cpu.h"
|
||||
#include "cpu-all.h"
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <xenctrl.h>
|
||||
#include <xen/io/ioreq.h>
|
||||
#include <xen/hvm/ioreq.h>
|
||||
#include <xen/linux/evtchn.h>
|
||||
|
||||
#include "cpu.h"
|
||||
|
||||
@@ -2948,6 +2948,7 @@ int main(int argc, char **argv)
|
||||
case QEMU_OPTION_vcpus:
|
||||
vcpus = atoi(optarg);
|
||||
fprintf(logfile, "qemu: the number of cpus is %d\n", vcpus);
|
||||
break;
|
||||
case QEMU_OPTION_pci:
|
||||
pci_enabled = 1;
|
||||
break;
|
||||
|
||||
@@ -55,7 +55,7 @@ xc_domain_dumpcore(int xc_handle,
|
||||
}
|
||||
|
||||
for (i = 0; i < info.max_vcpu_id; i++)
|
||||
if (xc_domain_get_vcpu_context(xc_handle, domid,
|
||||
if (xc_vcpu_getcontext(xc_handle, domid,
|
||||
i, &ctxt[nr_vcpus]) == 0)
|
||||
nr_vcpus++;
|
||||
|
||||
|
||||
+53
-21
@@ -58,16 +58,16 @@ int xc_domain_destroy(int xc_handle,
|
||||
return do_dom0_op(xc_handle, &op);
|
||||
}
|
||||
|
||||
int xc_domain_pincpu(int xc_handle,
|
||||
uint32_t domid,
|
||||
int vcpu,
|
||||
cpumap_t cpumap)
|
||||
int xc_vcpu_setaffinity(int xc_handle,
|
||||
uint32_t domid,
|
||||
int vcpu,
|
||||
cpumap_t cpumap)
|
||||
{
|
||||
DECLARE_DOM0_OP;
|
||||
op.cmd = DOM0_PINCPUDOMAIN;
|
||||
op.u.pincpudomain.domain = (domid_t)domid;
|
||||
op.u.pincpudomain.vcpu = vcpu;
|
||||
op.u.pincpudomain.cpumap = cpumap;
|
||||
op.cmd = DOM0_SETVCPUAFFINITY;
|
||||
op.u.setvcpuaffinity.domain = (domid_t)domid;
|
||||
op.u.setvcpuaffinity.vcpu = vcpu;
|
||||
op.u.setvcpuaffinity.cpumap = cpumap;
|
||||
return do_dom0_op(xc_handle, &op);
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ int xc_domain_getinfolist(int xc_handle,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int xc_domain_get_vcpu_context(int xc_handle,
|
||||
int xc_vcpu_getcontext(int xc_handle,
|
||||
uint32_t domid,
|
||||
uint32_t vcpu,
|
||||
vcpu_guest_context_t *ctxt)
|
||||
@@ -345,10 +345,10 @@ int xc_domain_sethandle(int xc_handle, uint32_t domid,
|
||||
return do_dom0_op(xc_handle, &op);
|
||||
}
|
||||
|
||||
int xc_domain_get_vcpu_info(int xc_handle,
|
||||
uint32_t domid,
|
||||
uint32_t vcpu,
|
||||
xc_vcpuinfo_t *info)
|
||||
int xc_vcpu_getinfo(int xc_handle,
|
||||
uint32_t domid,
|
||||
uint32_t vcpu,
|
||||
xc_vcpuinfo_t *info)
|
||||
{
|
||||
int rc;
|
||||
DECLARE_DOM0_OP;
|
||||
@@ -380,18 +380,18 @@ int xc_domain_ioport_permission(int xc_handle,
|
||||
return do_dom0_op(xc_handle, &op);
|
||||
}
|
||||
|
||||
int xc_domain_setinfo(int xc_handle,
|
||||
uint32_t domid,
|
||||
uint32_t vcpu,
|
||||
vcpu_guest_context_t *ctxt)
|
||||
int xc_vcpu_setcontext(int xc_handle,
|
||||
uint32_t domid,
|
||||
uint32_t vcpu,
|
||||
vcpu_guest_context_t *ctxt)
|
||||
{
|
||||
dom0_op_t op;
|
||||
int rc;
|
||||
|
||||
op.cmd = DOM0_SETDOMAININFO;
|
||||
op.u.setdomaininfo.domain = domid;
|
||||
op.u.setdomaininfo.vcpu = vcpu;
|
||||
op.u.setdomaininfo.ctxt = ctxt;
|
||||
op.cmd = DOM0_SETVCPUCONTEXT;
|
||||
op.u.setvcpucontext.domain = domid;
|
||||
op.u.setvcpucontext.vcpu = vcpu;
|
||||
op.u.setvcpucontext.ctxt = ctxt;
|
||||
|
||||
if ( (rc = mlock(ctxt, sizeof(*ctxt))) != 0 )
|
||||
return rc;
|
||||
@@ -404,6 +404,38 @@ int xc_domain_setinfo(int xc_handle,
|
||||
|
||||
}
|
||||
|
||||
int xc_domain_irq_permission(int xc_handle,
|
||||
uint32_t domid,
|
||||
uint8_t pirq,
|
||||
uint8_t allow_access)
|
||||
{
|
||||
dom0_op_t op;
|
||||
|
||||
op.cmd = DOM0_IRQ_PERMISSION;
|
||||
op.u.irq_permission.domain = domid;
|
||||
op.u.irq_permission.pirq = pirq;
|
||||
op.u.irq_permission.allow_access = allow_access;
|
||||
|
||||
return do_dom0_op(xc_handle, &op);
|
||||
}
|
||||
|
||||
int xc_domain_iomem_permission(int xc_handle,
|
||||
uint32_t domid,
|
||||
unsigned long first_pfn,
|
||||
unsigned long nr_pfns,
|
||||
uint8_t allow_access)
|
||||
{
|
||||
dom0_op_t op;
|
||||
|
||||
op.cmd = DOM0_IOMEM_PERMISSION;
|
||||
op.u.iomem_permission.domain = domid;
|
||||
op.u.iomem_permission.first_pfn = first_pfn;
|
||||
op.u.iomem_permission.nr_pfns = nr_pfns;
|
||||
op.u.iomem_permission.allow_access = allow_access;
|
||||
|
||||
return do_dom0_op(xc_handle, &op);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <zlib.h>
|
||||
#include "xen/arch-ia64.h"
|
||||
#include <xen/io/ioreq.h>
|
||||
#include <xen/hvm/ioreq.h>
|
||||
|
||||
/* this is a very ugly way of getting FPSR_DEFAULT. struct ia64_fpreg is
|
||||
* mysteriously declared in two places: /usr/include/asm/fpu.h and
|
||||
@@ -627,6 +627,7 @@ int xc_vmx_build(int xc_handle,
|
||||
unsigned int control_evtchn,
|
||||
unsigned int lapic,
|
||||
unsigned int vcpus,
|
||||
unsigned int acpi,
|
||||
unsigned int store_evtchn,
|
||||
unsigned long *store_mfn)
|
||||
{
|
||||
@@ -663,7 +664,7 @@ int xc_vmx_build(int xc_handle,
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if ( xc_domain_get_vcpu_context(xc_handle, domid, 0, ctxt) ){
|
||||
if ( xc_vcpu_getcontext(xc_handle, domid, 0, ctxt) ){
|
||||
PERROR("Could not get vcpu context");
|
||||
goto error_out;
|
||||
}
|
||||
@@ -687,11 +688,11 @@ int xc_vmx_build(int xc_handle,
|
||||
|
||||
memset( &launch_op, 0, sizeof(launch_op) );
|
||||
|
||||
launch_op.u.setdomaininfo.domain = (domid_t)domid;
|
||||
launch_op.u.setdomaininfo.vcpu = 0;
|
||||
launch_op.u.setdomaininfo.ctxt = ctxt;
|
||||
launch_op.u.setvcpucontext.domain = (domid_t)domid;
|
||||
launch_op.u.setvcpucontext.vcpu = 0;
|
||||
launch_op.u.setvcpucontext.ctxt = ctxt;
|
||||
|
||||
launch_op.cmd = DOM0_SETDOMAININFO;
|
||||
launch_op.cmd = DOM0_SETVCPUCONTEXT;
|
||||
rc = do_dom0_op(xc_handle, &launch_op);
|
||||
return rc;
|
||||
|
||||
|
||||
@@ -393,10 +393,14 @@ static int setup_guest(int xc_handle,
|
||||
start_info->store_evtchn = store_evtchn;
|
||||
start_info->console_mfn = nr_pages - 1;
|
||||
start_info->console_evtchn = console_evtchn;
|
||||
start_info->nr_pages = nr_pages; // FIXME?: nr_pages - 2 ????
|
||||
if ( initrd_len != 0 )
|
||||
{
|
||||
ctxt->initrd.start = vinitrd_start;
|
||||
ctxt->initrd.size = initrd_len;
|
||||
} else {
|
||||
ctxt->initrd.start = 0;
|
||||
ctxt->initrd.size = 0;
|
||||
}
|
||||
strncpy((char *)ctxt->cmdline, cmdline, IA64_COMMAND_LINE_SIZE);
|
||||
ctxt->cmdline[IA64_COMMAND_LINE_SIZE-1] = '\0';
|
||||
@@ -790,7 +794,7 @@ int xc_linux_build(int xc_handle,
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if ( xc_domain_get_vcpu_context(xc_handle, domid, 0, ctxt) )
|
||||
if ( xc_vcpu_getcontext(xc_handle, domid, 0, ctxt) )
|
||||
{
|
||||
PERROR("Could not get vcpu context");
|
||||
goto error_out;
|
||||
@@ -893,11 +897,11 @@ int xc_linux_build(int xc_handle,
|
||||
|
||||
memset( &launch_op, 0, sizeof(launch_op) );
|
||||
|
||||
launch_op.u.setdomaininfo.domain = (domid_t)domid;
|
||||
launch_op.u.setdomaininfo.vcpu = 0;
|
||||
launch_op.u.setdomaininfo.ctxt = ctxt;
|
||||
launch_op.u.setvcpucontext.domain = (domid_t)domid;
|
||||
launch_op.u.setvcpucontext.vcpu = 0;
|
||||
launch_op.u.setvcpucontext.ctxt = ctxt;
|
||||
|
||||
launch_op.cmd = DOM0_SETDOMAININFO;
|
||||
launch_op.cmd = DOM0_SETVCPUCONTEXT;
|
||||
rc = xc_dom0_op(xc_handle, &launch_op);
|
||||
|
||||
return rc;
|
||||
|
||||
@@ -171,7 +171,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
|
||||
|
||||
|
||||
/* Only have to worry about vcpu 0 even for SMP */
|
||||
if (xc_domain_get_vcpu_context( xc_handle, dom, 0, &ctxt)) {
|
||||
if (xc_vcpu_getcontext( xc_handle, dom, 0, &ctxt)) {
|
||||
ERR("Could not get vcpu context");
|
||||
goto out;
|
||||
}
|
||||
@@ -735,10 +735,10 @@ int xc_linux_restore(int xc_handle, int io_fd,
|
||||
|
||||
DPRINTF("Domain ready to be built.\n");
|
||||
|
||||
op.cmd = DOM0_SETDOMAININFO;
|
||||
op.u.setdomaininfo.domain = (domid_t)dom;
|
||||
op.u.setdomaininfo.vcpu = 0;
|
||||
op.u.setdomaininfo.ctxt = &ctxt;
|
||||
op.cmd = DOM0_SETVCPUCONTEXT;
|
||||
op.u.setvcpucontext.domain = (domid_t)dom;
|
||||
op.u.setvcpucontext.vcpu = 0;
|
||||
op.u.setvcpucontext.ctxt = &ctxt;
|
||||
rc = xc_dom0_op(xc_handle, &op);
|
||||
|
||||
if (rc != 0) {
|
||||
|
||||
@@ -382,7 +382,7 @@ static int suspend_and_state(int xc_handle, int io_fd, int dom,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( xc_domain_get_vcpu_context(xc_handle, dom, 0 /* XXX */, ctxt))
|
||||
if ( xc_vcpu_getcontext(xc_handle, dom, 0 /* XXX */, ctxt))
|
||||
ERR("Could not get vcpu context");
|
||||
|
||||
|
||||
@@ -643,7 +643,7 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
}
|
||||
|
||||
/* Only have to worry about vcpu 0 even for SMP */
|
||||
if (xc_domain_get_vcpu_context(xc_handle, dom, 0, &ctxt)) {
|
||||
if (xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt)) {
|
||||
ERR("Could not get vcpu context");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ unsigned long xc_translate_foreign_address(int xc_handle, uint32_t dom,
|
||||
#define pt_levels 4
|
||||
#endif
|
||||
|
||||
if (xc_domain_get_vcpu_context(xc_handle, dom, vcpu, &ctx) != 0) {
|
||||
if (xc_vcpu_getcontext(xc_handle, dom, vcpu, &ctx) != 0) {
|
||||
fprintf(stderr, "failed to retreive vcpu context\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ fetch_regs(int xc_handle, int cpu, int *online)
|
||||
if (online)
|
||||
*online = 0;
|
||||
if ( !(regs_valid & (1 << cpu)) ) {
|
||||
retval = xc_domain_get_vcpu_context(xc_handle, current_domid,
|
||||
retval = xc_vcpu_getcontext(xc_handle, current_domid,
|
||||
cpu, &ctxt[cpu]);
|
||||
if ( retval )
|
||||
goto done;
|
||||
@@ -43,8 +43,7 @@ fetch_regs(int xc_handle, int cpu, int *online)
|
||||
if ( online == NULL )
|
||||
goto done;
|
||||
|
||||
retval = xc_domain_get_vcpu_info(xc_handle, current_domid,
|
||||
cpu, &info);
|
||||
retval = xc_vcpu_getinfo(xc_handle, current_domid, cpu, &info);
|
||||
*online = info.online;
|
||||
|
||||
done:
|
||||
@@ -395,7 +394,7 @@ xc_ptrace(
|
||||
|
||||
case PTRACE_SETREGS:
|
||||
SET_XC_REGS(((struct gdb_regs *)data), ctxt[cpu].user_regs);
|
||||
retval = xc_domain_setinfo(xc_handle, current_domid, cpu, &ctxt[cpu]);
|
||||
retval = xc_vcpu_setcontext(xc_handle, current_domid, cpu, &ctxt[cpu]);
|
||||
if (retval)
|
||||
goto error_out;
|
||||
break;
|
||||
@@ -405,7 +404,7 @@ xc_ptrace(
|
||||
* during single-stepping - but that just seems retarded
|
||||
*/
|
||||
ctxt[cpu].user_regs.eflags |= PSL_T;
|
||||
retval = xc_domain_setinfo(xc_handle, current_domid, cpu, &ctxt[cpu]);
|
||||
retval = xc_vcpu_setcontext(xc_handle, current_domid, cpu, &ctxt[cpu]);
|
||||
if ( retval )
|
||||
{
|
||||
perror("dom0 op failed");
|
||||
@@ -423,8 +422,8 @@ xc_ptrace(
|
||||
/* Clear trace flag */
|
||||
if ( ctxt[cpu].user_regs.eflags & PSL_T ) {
|
||||
ctxt[cpu].user_regs.eflags &= ~PSL_T;
|
||||
retval = xc_domain_setinfo(xc_handle, current_domid,
|
||||
cpu, &ctxt[cpu]);
|
||||
retval = xc_vcpu_setcontext(xc_handle, current_domid,
|
||||
cpu, &ctxt[cpu]);
|
||||
if ( retval ) {
|
||||
perror("dom0 op failed");
|
||||
goto error_out;
|
||||
|
||||
+78
-71
@@ -9,7 +9,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <zlib.h>
|
||||
#include <xen/io/ioreq.h>
|
||||
#include <xen/hvm/hvm_info_table.h>
|
||||
#include <xen/hvm/ioreq.h>
|
||||
|
||||
#define VMX_LOADER_ENTR_ADDR 0x00100000
|
||||
|
||||
@@ -33,9 +34,6 @@
|
||||
#define E820_MAP_NR_OFFSET 0x000001E8
|
||||
#define E820_MAP_OFFSET 0x000002D0
|
||||
|
||||
#define VCPU_NR_PAGE 0x0009F000
|
||||
#define VCPU_NR_OFFSET 0x00000800
|
||||
|
||||
struct e820entry {
|
||||
uint64_t addr;
|
||||
uint64_t size;
|
||||
@@ -119,26 +117,50 @@ static unsigned char build_e820map(void *e820_page, unsigned long mem_size)
|
||||
return (*(((unsigned char *)e820_page) + E820_MAP_NR_OFFSET) = nr_map);
|
||||
}
|
||||
|
||||
/*
|
||||
* Use E820 reserved memory 0x9F800 to pass number of vcpus to vmxloader
|
||||
* vmxloader will use it to config ACPI MADT table
|
||||
*/
|
||||
#define VCPU_MAGIC 0x76637075 /* "vcpu" */
|
||||
static int set_vcpu_nr(int xc_handle, uint32_t dom,
|
||||
unsigned long *pfn_list, unsigned int vcpus)
|
||||
static void
|
||||
set_hvm_info_checksum(struct hvm_info_table *t)
|
||||
{
|
||||
char *va_map;
|
||||
unsigned int *va_vcpus;
|
||||
uint8_t *ptr = (uint8_t *)t, sum = 0;
|
||||
unsigned int i;
|
||||
|
||||
va_map = xc_map_foreign_range(xc_handle, dom,
|
||||
PAGE_SIZE, PROT_READ|PROT_WRITE,
|
||||
pfn_list[VCPU_NR_PAGE >> PAGE_SHIFT]);
|
||||
t->checksum = 0;
|
||||
|
||||
for (i = 0; i < t->length; i++)
|
||||
sum += *ptr++;
|
||||
|
||||
t->checksum = -sum;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use E820 reserved memory 0x9F800 to pass HVM info to vmxloader
|
||||
* vmxloader will use this info to set BIOS accordingly
|
||||
*/
|
||||
static int set_hvm_info(int xc_handle, uint32_t dom,
|
||||
unsigned long *pfn_list, unsigned int vcpus,
|
||||
unsigned int acpi, unsigned int apic)
|
||||
{
|
||||
char *va_map;
|
||||
struct hvm_info_table *va_hvm;
|
||||
|
||||
va_map = xc_map_foreign_range(
|
||||
xc_handle,
|
||||
dom,
|
||||
PAGE_SIZE,
|
||||
PROT_READ|PROT_WRITE,
|
||||
pfn_list[HVM_INFO_PFN]);
|
||||
|
||||
if ( va_map == NULL )
|
||||
return -1;
|
||||
|
||||
va_vcpus = (unsigned int *)(va_map + VCPU_NR_OFFSET);
|
||||
va_vcpus[0] = VCPU_MAGIC;
|
||||
va_vcpus[1] = vcpus;
|
||||
va_hvm = (struct hvm_info_table *)(va_map + HVM_INFO_OFFSET);
|
||||
memset(va_hvm, 0, sizeof(*va_hvm));
|
||||
strncpy(va_hvm->signature, "HVM INFO", 8);
|
||||
va_hvm->length = sizeof(struct hvm_info_table);
|
||||
va_hvm->acpi_enabled = acpi;
|
||||
va_hvm->apic_enabled = apic;
|
||||
va_hvm->nr_vcpus = vcpus;
|
||||
|
||||
set_hvm_info_checksum(va_hvm);
|
||||
|
||||
munmap(va_map, PAGE_SIZE);
|
||||
|
||||
@@ -279,8 +301,9 @@ static int setup_guest(int xc_handle,
|
||||
vcpu_guest_context_t *ctxt,
|
||||
unsigned long shared_info_frame,
|
||||
unsigned int control_evtchn,
|
||||
unsigned int lapic,
|
||||
unsigned int vcpus,
|
||||
unsigned int acpi,
|
||||
unsigned int apic,
|
||||
unsigned int store_evtchn,
|
||||
unsigned long *store_mfn)
|
||||
{
|
||||
@@ -490,20 +513,14 @@ static int setup_guest(int xc_handle,
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if (set_vcpu_nr(xc_handle, dom, page_array, vcpus)) {
|
||||
fprintf(stderr, "Couldn't set vcpu number for VMX guest.\n");
|
||||
if ( set_hvm_info(xc_handle, dom, page_array, vcpus, acpi, apic) ) {
|
||||
fprintf(stderr, "Couldn't set hvm info for VMX guest.\n");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
*store_mfn = page_array[(v_end-2) >> PAGE_SHIFT];
|
||||
if ( xc_clear_domain_page(xc_handle, dom, *store_mfn) )
|
||||
goto error_out;
|
||||
|
||||
shared_page_frame = (v_end - PAGE_SIZE) >> PAGE_SHIFT;
|
||||
|
||||
if ((e820_page = xc_map_foreign_range(
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
|
||||
page_array[E820_MAP_PAGE >> PAGE_SHIFT])) == 0)
|
||||
if ( (e820_page = xc_map_foreign_range(
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
|
||||
page_array[E820_MAP_PAGE >> PAGE_SHIFT])) == 0 )
|
||||
goto error_out;
|
||||
memset(e820_page, 0, PAGE_SIZE);
|
||||
e820_map_nr = build_e820map(e820_page, v_end);
|
||||
@@ -518,26 +535,30 @@ static int setup_guest(int xc_handle,
|
||||
munmap(e820_page, PAGE_SIZE);
|
||||
|
||||
/* shared_info page starts its life empty. */
|
||||
if ((shared_info = xc_map_foreign_range(
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
|
||||
shared_info_frame)) == 0)
|
||||
if ( (shared_info = xc_map_foreign_range(
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
|
||||
shared_info_frame)) == 0 )
|
||||
goto error_out;
|
||||
memset(shared_info, 0, sizeof(shared_info_t));
|
||||
/* Mask all upcalls... */
|
||||
for ( i = 0; i < MAX_VIRT_CPUS; i++ )
|
||||
shared_info->vcpu_info[i].evtchn_upcall_mask = 1;
|
||||
|
||||
munmap(shared_info, PAGE_SIZE);
|
||||
|
||||
/* Populate the event channel port in the shared page */
|
||||
if ((sp = (shared_iopage_t *) xc_map_foreign_range(
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
|
||||
page_array[shared_page_frame])) == 0)
|
||||
shared_page_frame = page_array[(v_end >> PAGE_SHIFT) - 1];
|
||||
if ( (sp = (shared_iopage_t *) xc_map_foreign_range(
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
|
||||
shared_page_frame)) == 0 )
|
||||
goto error_out;
|
||||
memset(sp, 0, PAGE_SIZE);
|
||||
sp->sp_global.eport = control_evtchn;
|
||||
munmap(sp, PAGE_SIZE);
|
||||
|
||||
*store_mfn = page_array[(v_end >> PAGE_SHIFT) - 2];
|
||||
if ( xc_clear_domain_page(xc_handle, dom, *store_mfn) )
|
||||
goto error_out;
|
||||
|
||||
/* Send the page update requests down to the hypervisor. */
|
||||
if ( xc_finish_mmu_updates(xc_handle, mmu) )
|
||||
goto error_out;
|
||||
@@ -559,7 +580,7 @@ static int setup_guest(int xc_handle,
|
||||
ctxt->user_regs.eax = 0;
|
||||
ctxt->user_regs.esp = 0;
|
||||
ctxt->user_regs.ebx = 0; /* startup_32 expects this to be 0 to signal boot cpu */
|
||||
ctxt->user_regs.ecx = lapic;
|
||||
ctxt->user_regs.ecx = 0;
|
||||
ctxt->user_regs.esi = 0;
|
||||
ctxt->user_regs.edi = 0;
|
||||
ctxt->user_regs.ebp = 0;
|
||||
@@ -574,36 +595,14 @@ static int setup_guest(int xc_handle,
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define VMX_FEATURE_FLAG 0x20
|
||||
|
||||
static int vmx_identify(void)
|
||||
{
|
||||
int eax, ecx;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
#if defined(__i386__)
|
||||
"push %%ebx; cpuid; pop %%ebx"
|
||||
#elif defined(__x86_64__)
|
||||
"push %%rbx; cpuid; pop %%rbx"
|
||||
#endif
|
||||
: "=a" (eax), "=c" (ecx)
|
||||
: "0" (1)
|
||||
: "dx");
|
||||
|
||||
if (!(ecx & VMX_FEATURE_FLAG)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xc_vmx_build(int xc_handle,
|
||||
uint32_t domid,
|
||||
int memsize,
|
||||
const char *image_name,
|
||||
unsigned int control_evtchn,
|
||||
unsigned int lapic,
|
||||
unsigned int vcpus,
|
||||
unsigned int acpi,
|
||||
unsigned int apic,
|
||||
unsigned int store_evtchn,
|
||||
unsigned long *store_mfn)
|
||||
{
|
||||
@@ -613,10 +612,18 @@ int xc_vmx_build(int xc_handle,
|
||||
unsigned long nr_pages;
|
||||
char *image = NULL;
|
||||
unsigned long image_size;
|
||||
xen_capabilities_info_t xen_caps;
|
||||
|
||||
if ( vmx_identify() < 0 )
|
||||
if ( (rc = xc_version(xc_handle, XENVER_capabilities, &xen_caps)) != 0 )
|
||||
{
|
||||
PERROR("CPU doesn't support VMX Extensions");
|
||||
PERROR("Failed to get xen version info");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if ( !strstr(xen_caps, "hvm") )
|
||||
{
|
||||
PERROR("CPU doesn't support VMX Extensions or "
|
||||
"CPU VMX Extensions are not turned on");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
@@ -644,7 +651,7 @@ int xc_vmx_build(int xc_handle,
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if ( xc_domain_get_vcpu_context(xc_handle, domid, 0, ctxt) )
|
||||
if ( xc_vcpu_getcontext(xc_handle, domid, 0, ctxt) )
|
||||
{
|
||||
PERROR("Could not get vcpu context");
|
||||
goto error_out;
|
||||
@@ -659,7 +666,7 @@ int xc_vmx_build(int xc_handle,
|
||||
|
||||
if ( setup_guest(xc_handle, domid, memsize, image, image_size, nr_pages,
|
||||
ctxt, op.u.getdomaininfo.shared_info_frame, control_evtchn,
|
||||
lapic, vcpus, store_evtchn, store_mfn) < 0)
|
||||
vcpus, acpi, apic, store_evtchn, store_mfn) < 0)
|
||||
{
|
||||
ERROR("Error constructing guest OS");
|
||||
goto error_out;
|
||||
@@ -701,11 +708,11 @@ int xc_vmx_build(int xc_handle,
|
||||
|
||||
memset( &launch_op, 0, sizeof(launch_op) );
|
||||
|
||||
launch_op.u.setdomaininfo.domain = (domid_t)domid;
|
||||
launch_op.u.setdomaininfo.vcpu = 0;
|
||||
launch_op.u.setdomaininfo.ctxt = ctxt;
|
||||
launch_op.u.setvcpucontext.domain = (domid_t)domid;
|
||||
launch_op.u.setvcpucontext.vcpu = 0;
|
||||
launch_op.u.setvcpucontext.ctxt = ctxt;
|
||||
|
||||
launch_op.cmd = DOM0_SETDOMAININFO;
|
||||
launch_op.cmd = DOM0_SETVCPUCONTEXT;
|
||||
rc = xc_dom0_op(xc_handle, &launch_op);
|
||||
|
||||
return rc;
|
||||
|
||||
+26
-15
@@ -181,10 +181,11 @@ int xc_domain_unpause(int xc_handle,
|
||||
*/
|
||||
int xc_domain_destroy(int xc_handle,
|
||||
uint32_t domid);
|
||||
int xc_domain_pincpu(int xc_handle,
|
||||
uint32_t domid,
|
||||
int vcpu,
|
||||
cpumap_t cpumap);
|
||||
|
||||
int xc_vcpu_setaffinity(int xc_handle,
|
||||
uint32_t domid,
|
||||
int vcpu,
|
||||
cpumap_t cpumap);
|
||||
|
||||
/**
|
||||
* This function will return information about one or more domains. It is
|
||||
@@ -208,7 +209,7 @@ int xc_domain_getinfo(int xc_handle,
|
||||
|
||||
|
||||
/**
|
||||
* This function will set the vcpu context for the specified domain.
|
||||
* This function will set the execution context for the specified vcpu.
|
||||
*
|
||||
* @parm xc_handle a handle to an open hypervisor interface
|
||||
* @parm domid the domain to set the vcpu context for
|
||||
@@ -216,10 +217,10 @@ int xc_domain_getinfo(int xc_handle,
|
||||
* @parm ctxt pointer to the the cpu context with the values to set
|
||||
* @return the number of domains enumerated or -1 on error
|
||||
*/
|
||||
int xc_domain_setinfo(int xc_handle,
|
||||
uint32_t domid,
|
||||
uint32_t vcpu,
|
||||
vcpu_guest_context_t *ctxt);
|
||||
int xc_vcpu_setcontext(int xc_handle,
|
||||
uint32_t domid,
|
||||
uint32_t vcpu,
|
||||
vcpu_guest_context_t *ctxt);
|
||||
/**
|
||||
* This function will return information about one or more domains, using a
|
||||
* single hypercall. The domain information will be stored into the supplied
|
||||
@@ -249,17 +250,16 @@ int xc_domain_getinfolist(int xc_handle,
|
||||
* domain
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int xc_domain_get_vcpu_context(int xc_handle,
|
||||
int xc_vcpu_getcontext(int xc_handle,
|
||||
uint32_t domid,
|
||||
uint32_t vcpu,
|
||||
vcpu_guest_context_t *ctxt);
|
||||
|
||||
typedef dom0_getvcpuinfo_t xc_vcpuinfo_t;
|
||||
int xc_domain_get_vcpu_info(int xc_handle,
|
||||
uint32_t domid,
|
||||
uint32_t vcpu,
|
||||
xc_vcpuinfo_t *info);
|
||||
|
||||
int xc_vcpu_getinfo(int xc_handle,
|
||||
uint32_t domid,
|
||||
uint32_t vcpu,
|
||||
xc_vcpuinfo_t *info);
|
||||
|
||||
int xc_domain_setcpuweight(int xc_handle,
|
||||
uint32_t domid,
|
||||
@@ -380,6 +380,17 @@ int xc_domain_ioport_permission(int xc_handle,
|
||||
uint32_t nr_ports,
|
||||
uint32_t allow_access);
|
||||
|
||||
int xc_domain_irq_permission(int xc_handle,
|
||||
uint32_t domid,
|
||||
uint8_t pirq,
|
||||
uint8_t allow_access);
|
||||
|
||||
int xc_domain_iomem_permission(int xc_handle,
|
||||
uint32_t domid,
|
||||
unsigned long first_pfn,
|
||||
unsigned long nr_pfns,
|
||||
uint8_t allow_access);
|
||||
|
||||
unsigned long xc_make_page_below_4G(int xc_handle, uint32_t domid,
|
||||
unsigned long mfn);
|
||||
|
||||
|
||||
@@ -56,8 +56,9 @@ int xc_vmx_build(int xc_handle,
|
||||
int memsize,
|
||||
const char *image_name,
|
||||
unsigned int control_evtchn,
|
||||
unsigned int lapic,
|
||||
unsigned int vcpus,
|
||||
unsigned int acpi,
|
||||
unsigned int apic,
|
||||
unsigned int store_evtchn,
|
||||
unsigned long *store_mfn);
|
||||
|
||||
|
||||
@@ -135,9 +135,9 @@ static PyObject *pyxc_domain_destroy(XcObject *self, PyObject *args)
|
||||
}
|
||||
|
||||
|
||||
static PyObject *pyxc_domain_pincpu(XcObject *self,
|
||||
PyObject *args,
|
||||
PyObject *kwds)
|
||||
static PyObject *pyxc_vcpu_setaffinity(XcObject *self,
|
||||
PyObject *args,
|
||||
PyObject *kwds)
|
||||
{
|
||||
uint32_t dom;
|
||||
int vcpu = 0, i;
|
||||
@@ -157,7 +157,7 @@ static PyObject *pyxc_domain_pincpu(XcObject *self,
|
||||
cpumap |= (cpumap_t)1 << PyInt_AsLong(PyList_GetItem(cpulist, i));
|
||||
}
|
||||
|
||||
if ( xc_domain_pincpu(self->xc_handle, dom, vcpu, cpumap) != 0 )
|
||||
if ( xc_vcpu_setaffinity(self->xc_handle, dom, vcpu, cpumap) != 0 )
|
||||
return PyErr_SetFromErrno(xc_error);
|
||||
|
||||
Py_INCREF(zero);
|
||||
@@ -297,7 +297,7 @@ static PyObject *pyxc_vcpu_getinfo(XcObject *self,
|
||||
&dom, &vcpu) )
|
||||
return NULL;
|
||||
|
||||
rc = xc_domain_get_vcpu_info(self->xc_handle, dom, vcpu, &info);
|
||||
rc = xc_vcpu_getinfo(self->xc_handle, dom, vcpu, &info);
|
||||
if ( rc < 0 )
|
||||
return PyErr_SetFromErrno(xc_error);
|
||||
|
||||
@@ -362,21 +362,23 @@ static PyObject *pyxc_vmx_build(XcObject *self,
|
||||
uint32_t dom;
|
||||
char *image;
|
||||
int control_evtchn, store_evtchn;
|
||||
int vcpus = 1;
|
||||
int lapic = 0;
|
||||
int memsize;
|
||||
int vcpus = 1;
|
||||
int acpi = 0;
|
||||
int apic = 0;
|
||||
unsigned long store_mfn = 0;
|
||||
|
||||
static char *kwd_list[] = { "dom", "control_evtchn", "store_evtchn",
|
||||
"memsize", "image", "lapic", "vcpus", NULL };
|
||||
"memsize", "image", "vcpus", "acpi", "apic",
|
||||
NULL };
|
||||
|
||||
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisii", kwd_list,
|
||||
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisiii", kwd_list,
|
||||
&dom, &control_evtchn, &store_evtchn,
|
||||
&memsize, &image, &lapic, &vcpus) )
|
||||
&memsize, &image, &vcpus, &acpi, &apic) )
|
||||
return NULL;
|
||||
|
||||
if ( xc_vmx_build(self->xc_handle, dom, memsize, image, control_evtchn,
|
||||
lapic, vcpus, store_evtchn, &store_mfn) != 0 )
|
||||
vcpus, acpi, apic, store_evtchn, &store_mfn) != 0 )
|
||||
return PyErr_SetFromErrno(xc_error);
|
||||
|
||||
return Py_BuildValue("{s:i}", "store_mfn", store_mfn);
|
||||
@@ -774,6 +776,52 @@ static PyObject *pyxc_domain_ioport_permission(XcObject *self,
|
||||
return zero;
|
||||
}
|
||||
|
||||
static PyObject *pyxc_domain_irq_permission(PyObject *self,
|
||||
PyObject *args,
|
||||
PyObject *kwds)
|
||||
{
|
||||
XcObject *xc = (XcObject *)self;
|
||||
uint32_t dom;
|
||||
int pirq, allow_access, ret;
|
||||
|
||||
static char *kwd_list[] = { "dom", "pirq", "allow_access", NULL };
|
||||
|
||||
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iii", kwd_list,
|
||||
&dom, &pirq, &allow_access) )
|
||||
return NULL;
|
||||
|
||||
ret = xc_domain_irq_permission(
|
||||
xc->xc_handle, dom, pirq, allow_access);
|
||||
if ( ret != 0 )
|
||||
return PyErr_SetFromErrno(xc_error);
|
||||
|
||||
Py_INCREF(zero);
|
||||
return zero;
|
||||
}
|
||||
|
||||
static PyObject *pyxc_domain_iomem_permission(PyObject *self,
|
||||
PyObject *args,
|
||||
PyObject *kwds)
|
||||
{
|
||||
XcObject *xc = (XcObject *)self;
|
||||
uint32_t dom;
|
||||
unsigned long first_pfn, nr_pfns, allow_access, ret;
|
||||
|
||||
static char *kwd_list[] = { "dom", "first_pfn", "nr_pfns", "allow_access", NULL };
|
||||
|
||||
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "illi", kwd_list,
|
||||
&dom, &first_pfn, &nr_pfns, &allow_access) )
|
||||
return NULL;
|
||||
|
||||
ret = xc_domain_iomem_permission(
|
||||
xc->xc_handle, dom, first_pfn, nr_pfns, allow_access);
|
||||
if ( ret != 0 )
|
||||
return PyErr_SetFromErrno(xc_error);
|
||||
|
||||
Py_INCREF(zero);
|
||||
return zero;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *dom_op(XcObject *self, PyObject *args,
|
||||
int (*fn)(int, uint32_t))
|
||||
@@ -842,8 +890,8 @@ static PyMethodDef pyxc_methods[] = {
|
||||
" dom [int]: Identifier of domain to be destroyed.\n\n"
|
||||
"Returns: [int] 0 on success; -1 on error.\n" },
|
||||
|
||||
{ "domain_pincpu",
|
||||
(PyCFunction)pyxc_domain_pincpu,
|
||||
{ "vcpu_setaffinity",
|
||||
(PyCFunction)pyxc_vcpu_setaffinity,
|
||||
METH_VARARGS | METH_KEYWORDS, "\n"
|
||||
"Pin a VCPU to a specified set CPUs.\n"
|
||||
" dom [int]: Identifier of domain to which VCPU belongs.\n"
|
||||
@@ -1070,6 +1118,25 @@ static PyMethodDef pyxc_methods[] = {
|
||||
" allow_access [int]: Non-zero means enable access; else disable access\n\n"
|
||||
"Returns: [int] 0 on success; -1 on error.\n" },
|
||||
|
||||
{ "domain_irq_permission",
|
||||
(PyCFunction)pyxc_domain_irq_permission,
|
||||
METH_VARARGS | METH_KEYWORDS, "\n"
|
||||
"Allow a domain access to a physical IRQ\n"
|
||||
" dom [int]: Identifier of domain to be allowed access.\n"
|
||||
" pirq [int]: The Physical IRQ\n"
|
||||
" allow_access [int]: Non-zero means enable access; else disable access\n\n"
|
||||
"Returns: [int] 0 on success; -1 on error.\n" },
|
||||
|
||||
{ "domain_iomem_permission",
|
||||
(PyCFunction)pyxc_domain_iomem_permission,
|
||||
METH_VARARGS | METH_KEYWORDS, "\n"
|
||||
"Allow a domain access to a range of IO memory pages\n"
|
||||
" dom [int]: Identifier of domain to be allowed access.\n"
|
||||
" first_pfn [long]: First page of I/O Memory\n"
|
||||
" nr_pfns [long]: Number of pages of I/O Memory (>0)\n"
|
||||
" allow_access [int]: Non-zero means enable access; else disable access\n\n"
|
||||
"Returns: [int] 0 on success; -1 on error.\n" },
|
||||
|
||||
{ "pages_to_kib",
|
||||
(PyCFunction)pyxc_pages_to_kib,
|
||||
METH_VARARGS, "\n"
|
||||
|
||||
@@ -443,7 +443,7 @@ class XendDomain:
|
||||
cpumap = map(lambda x: int(x),
|
||||
cpumap.replace("[", "").replace("]", "").split(","))
|
||||
try:
|
||||
return xc.domain_pincpu(dominfo.getDomid(), vcpu, cpumap)
|
||||
return xc.vcpu_setaffinity(dominfo.getDomid(), vcpu, cpumap)
|
||||
except Exception, ex:
|
||||
raise XendError(str(ex))
|
||||
|
||||
|
||||
@@ -1179,7 +1179,7 @@ class XendDomainInfo:
|
||||
for v in range(0, self.info['max_vcpu_id']+1):
|
||||
# pincpu takes a list of ints
|
||||
cpu = [ int( cpus[v % len(cpus)] ) ]
|
||||
xc.domain_pincpu(self.domid, v, cpu)
|
||||
xc.vcpu_setaffinity(self.domid, v, cpu)
|
||||
|
||||
m = self.image.getDomainMemory(self.info['memory'] * 1024)
|
||||
balloon.free(m)
|
||||
|
||||
@@ -189,11 +189,16 @@ class VmxImageHandler(ImageHandler):
|
||||
def configure(self, imageConfig, deviceConfig):
|
||||
ImageHandler.configure(self, imageConfig, deviceConfig)
|
||||
|
||||
info = xc.xeninfo()
|
||||
if not 'hvm' in info['xen_caps']:
|
||||
raise VmError("vmx: not an Intel VT platform, we stop creating!")
|
||||
|
||||
self.dmargs = self.parseDeviceModelArgs(imageConfig, deviceConfig)
|
||||
self.device_model = sxp.child_value(imageConfig, 'device_model')
|
||||
if not self.device_model:
|
||||
raise VmError("vmx: missing device model")
|
||||
self.display = sxp.child_value(imageConfig, 'display')
|
||||
self.xauthority = sxp.child_value(imageConfig, 'xauthority')
|
||||
|
||||
self.vm.storeVm(("image/dmargs", " ".join(self.dmargs)),
|
||||
("image/device-model", self.device_model),
|
||||
@@ -204,10 +209,8 @@ class VmxImageHandler(ImageHandler):
|
||||
|
||||
self.dmargs += self.configVNC(imageConfig)
|
||||
|
||||
self.lapic = 0
|
||||
lapic = sxp.child_value(imageConfig, 'lapic')
|
||||
if not lapic is None:
|
||||
self.lapic = int(lapic)
|
||||
self.acpi = int(sxp.child_value(imageConfig, 'acpi', 0))
|
||||
self.apic = int(sxp.child_value(imageConfig, 'apic', 0))
|
||||
|
||||
def buildDomain(self):
|
||||
# Create an event channel
|
||||
@@ -222,17 +225,18 @@ class VmxImageHandler(ImageHandler):
|
||||
log.debug("control_evtchn = %d", self.device_channel)
|
||||
log.debug("store_evtchn = %d", store_evtchn)
|
||||
log.debug("memsize = %d", self.vm.getMemoryTarget() / 1024)
|
||||
log.debug("lapic = %d", self.lapic)
|
||||
log.debug("vcpus = %d", self.vm.getVCpuCount())
|
||||
log.debug("acpi = %d", self.acpi)
|
||||
log.debug("apic = %d", self.apic)
|
||||
|
||||
return xc.vmx_build(dom = self.vm.getDomid(),
|
||||
image = self.kernel,
|
||||
control_evtchn = self.device_channel,
|
||||
store_evtchn = store_evtchn,
|
||||
memsize = self.vm.getMemoryTarget() / 1024,
|
||||
lapic = self.lapic,
|
||||
vcpus = self.vm.getVCpuCount())
|
||||
|
||||
vcpus = self.vm.getVCpuCount(),
|
||||
acpi = self.acpi,
|
||||
apic = self.apic)
|
||||
|
||||
# Return a list of cmd line args to the device models based on the
|
||||
# xm config file
|
||||
@@ -264,44 +268,44 @@ class VmxImageHandler(ImageHandler):
|
||||
nics = 0
|
||||
for (name, info) in deviceConfig:
|
||||
if name == 'vbd':
|
||||
uname = sxp.child_value(info, 'uname')
|
||||
typedev = sxp.child_value(info, 'dev')
|
||||
(_, vbdparam) = string.split(uname, ':', 1)
|
||||
if re.match('^ioemu:', typedev):
|
||||
(emtype, vbddev) = string.split(typedev, ':', 1)
|
||||
else:
|
||||
emtype = 'vbd'
|
||||
vbddev = typedev
|
||||
if emtype != 'ioemu':
|
||||
continue;
|
||||
vbddev_list = ['hda', 'hdb', 'hdc', 'hdd']
|
||||
if vbddev not in vbddev_list:
|
||||
raise VmError("vmx: for qemu vbd type=file&dev=hda~hdd")
|
||||
ret.append("-%s" % vbddev)
|
||||
ret.append("%s" % vbdparam)
|
||||
uname = sxp.child_value(info, 'uname')
|
||||
typedev = sxp.child_value(info, 'dev')
|
||||
(_, vbdparam) = string.split(uname, ':', 1)
|
||||
if 'ioemu:' in typedev:
|
||||
(emtype, vbddev) = string.split(typedev, ':', 1)
|
||||
else:
|
||||
emtype = 'vbd'
|
||||
vbddev = typedev
|
||||
if emtype == 'vbd':
|
||||
continue;
|
||||
vbddev_list = ['hda', 'hdb', 'hdc', 'hdd']
|
||||
if vbddev not in vbddev_list:
|
||||
raise VmError("vmx: for qemu vbd type=file&dev=hda~hdd")
|
||||
ret.append("-%s" % vbddev)
|
||||
ret.append("%s" % vbdparam)
|
||||
if name == 'vif':
|
||||
type = sxp.child_value(info, 'type')
|
||||
if type != 'ioemu':
|
||||
continue
|
||||
nics += 1
|
||||
if mac != None:
|
||||
continue
|
||||
mac = sxp.child_value(info, 'mac')
|
||||
bridge = sxp.child_value(info, 'bridge')
|
||||
if mac == None:
|
||||
mac = randomMAC()
|
||||
if bridge == None:
|
||||
bridge = 'xenbr0'
|
||||
ret.append("-macaddr")
|
||||
ret.append("%s" % mac)
|
||||
ret.append("-bridge")
|
||||
ret.append("%s" % bridge)
|
||||
type = sxp.child_value(info, 'type')
|
||||
if type != 'ioemu':
|
||||
continue
|
||||
nics += 1
|
||||
if mac != None:
|
||||
continue
|
||||
mac = sxp.child_value(info, 'mac')
|
||||
bridge = sxp.child_value(info, 'bridge')
|
||||
if mac == None:
|
||||
mac = randomMAC()
|
||||
if bridge == None:
|
||||
bridge = 'xenbr0'
|
||||
ret.append("-macaddr")
|
||||
ret.append("%s" % mac)
|
||||
ret.append("-bridge")
|
||||
ret.append("%s" % bridge)
|
||||
if name == 'vtpm':
|
||||
instance = sxp.child_value(info, 'pref_instance')
|
||||
ret.append("-instance")
|
||||
ret.append("%s" % instance)
|
||||
instance = sxp.child_value(info, 'pref_instance')
|
||||
ret.append("-instance")
|
||||
ret.append("%s" % instance)
|
||||
ret.append("-nics")
|
||||
ret.append("%d" % nics)
|
||||
ret.append("%d" % nics)
|
||||
return ret
|
||||
|
||||
def configVNC(self, config):
|
||||
@@ -340,6 +344,8 @@ class VmxImageHandler(ImageHandler):
|
||||
env = dict(os.environ)
|
||||
if self.display:
|
||||
env['DISPLAY'] = self.display
|
||||
if self.xauthority:
|
||||
env['XAUTHORITY'] = self.xauthority
|
||||
log.info("spawning device models: %s %s", self.device_model, args)
|
||||
self.pid = os.spawnve(os.P_NOWAIT, self.device_model, args, env)
|
||||
log.info("device model pid: %d", self.pid)
|
||||
|
||||
@@ -31,7 +31,7 @@ class BlkifController(DevController):
|
||||
"""Block device interface controller. Handles all block devices
|
||||
for a domain.
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, vm):
|
||||
"""Create a block device controller.
|
||||
"""
|
||||
@@ -40,9 +40,9 @@ class BlkifController(DevController):
|
||||
|
||||
def getDeviceDetails(self, config):
|
||||
"""@see DevController.getDeviceDetails"""
|
||||
|
||||
|
||||
dev = sxp.child_value(config, 'dev')
|
||||
if re.match('^ioemu:', dev):
|
||||
if 'ioemu:' in dev:
|
||||
return (None,{},{})
|
||||
|
||||
devid = blkif.blkdev_name_to_number(dev)
|
||||
|
||||
@@ -160,9 +160,13 @@ gopts.var('cpus', val='CPUS',
|
||||
fn=set_int, default=None,
|
||||
use="CPUS to run the domain on.")
|
||||
|
||||
gopts.var('lapic', val='LAPIC',
|
||||
gopts.var('acpi', val='ACPI',
|
||||
fn=set_int, default=0,
|
||||
use="Disable or enable local APIC of VMX domain.")
|
||||
use="Disable or enable ACPI of VMX domain.")
|
||||
|
||||
gopts.var('apic', val='APIC',
|
||||
fn=set_int, default=0,
|
||||
use="Disable or enable APIC of VMX domain.")
|
||||
|
||||
gopts.var('vcpus', val='VCPUS',
|
||||
fn=set_int, default=1,
|
||||
@@ -388,6 +392,10 @@ gopts.var('display', val='DISPLAY',
|
||||
fn=set_value, default=None,
|
||||
use="X11 display to use")
|
||||
|
||||
gopts.var('xauthority', val='XAUTHORITY',
|
||||
fn=set_value, default=None,
|
||||
use="X11 Authority to use")
|
||||
|
||||
|
||||
def err(msg):
|
||||
"""Print an error to stderr and exit.
|
||||
@@ -526,7 +534,8 @@ def configure_vmx(config_image, vals):
|
||||
"""
|
||||
args = [ 'device_model', 'vcpus', 'cdrom', 'boot', 'fda', 'fdb',
|
||||
'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'audio',
|
||||
'vnc', 'vncviewer', 'sdl', 'display', 'ne2000', 'lapic']
|
||||
'vnc', 'vncviewer', 'sdl', 'display', 'ne2000', 'acpi', 'apic',
|
||||
'xauthority' ]
|
||||
for a in args:
|
||||
if (vals.__dict__[a]):
|
||||
config_image.append([a, vals.__dict__[a]])
|
||||
@@ -801,6 +810,9 @@ def parseCommandLine(argv):
|
||||
if not gopts.vals.display:
|
||||
gopts.vals.display = os.getenv("DISPLAY")
|
||||
|
||||
if not gopts.vals.xauthority:
|
||||
gopts.vals.xauthority = os.getenv("XAUTHORITY")
|
||||
|
||||
# Process remaining args as config variables.
|
||||
for arg in args:
|
||||
if '=' in arg:
|
||||
|
||||
@@ -390,7 +390,6 @@ def xm_brief_list(doms):
|
||||
|
||||
|
||||
def xm_vcpu_list(args):
|
||||
print 'Name ID VCPU CPU State Time(s) CPU Affinity'
|
||||
|
||||
from xen.xend.XendClient import server
|
||||
if args:
|
||||
@@ -401,6 +400,8 @@ def xm_vcpu_list(args):
|
||||
lambda x: server.xend_domain_vcpuinfo(sxp.child_value(x, 'name')),
|
||||
doms)
|
||||
|
||||
print 'Name ID VCPU CPU State Time(s) CPU Affinity'
|
||||
|
||||
for dom in dominfo:
|
||||
def get_info(n):
|
||||
return sxp.child_value(dom, n)
|
||||
@@ -625,6 +626,8 @@ def xm_sched_sedf(args):
|
||||
server.xend_domain_cpu_sedf_set(dom, *v)
|
||||
|
||||
def xm_info(args):
|
||||
arg_check(args, "info", 0)
|
||||
|
||||
from xen.xend.XendClient import server
|
||||
info = server.xend_node()
|
||||
|
||||
@@ -645,9 +648,12 @@ def xm_console(args):
|
||||
|
||||
|
||||
def xm_top(args):
|
||||
arg_check(args, "top", 0)
|
||||
|
||||
os.execvp('xentop', ['xentop'])
|
||||
|
||||
def xm_dmesg(args):
|
||||
arg_check(args, "dmesg", 0)
|
||||
|
||||
gopts = Opts(use="""[-c|--clear]
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ int main(int argc, char **argv)
|
||||
regs.ecx = 0x12345678;
|
||||
cr2 = (unsigned long)&res;
|
||||
res = 0x7FFFFFFF;
|
||||
rc = x86_emulate_memop(®s, cr2, &emulops, 4);
|
||||
rc = x86_emulate_memop(®s, cr2, &emulops, X86EMUL_MODE_PROT32);
|
||||
if ( (rc != 0) ||
|
||||
(res != 0x92345677) ||
|
||||
(regs.eflags != 0xa94) ||
|
||||
@@ -110,7 +110,7 @@ int main(int argc, char **argv)
|
||||
regs.ecx = 0x12345678UL;
|
||||
#endif
|
||||
cr2 = (unsigned long)&res;
|
||||
rc = x86_emulate_memop(®s, cr2, &emulops, 4);
|
||||
rc = x86_emulate_memop(®s, cr2, &emulops, X86EMUL_MODE_PROT32);
|
||||
if ( (rc != 0) ||
|
||||
(res != 0x92345677) ||
|
||||
(regs.ecx != 0x8000000FUL) ||
|
||||
@@ -125,7 +125,7 @@ int main(int argc, char **argv)
|
||||
regs.eax = 0x92345677UL;
|
||||
regs.ecx = 0xAA;
|
||||
cr2 = (unsigned long)&res;
|
||||
rc = x86_emulate_memop(®s, cr2, &emulops, 4);
|
||||
rc = x86_emulate_memop(®s, cr2, &emulops, X86EMUL_MODE_PROT32);
|
||||
if ( (rc != 0) ||
|
||||
(res != 0x923456AA) ||
|
||||
(regs.eflags != 0x244) ||
|
||||
@@ -141,7 +141,7 @@ int main(int argc, char **argv)
|
||||
regs.eax = 0xAABBCC77UL;
|
||||
regs.ecx = 0xFF;
|
||||
cr2 = (unsigned long)&res;
|
||||
rc = x86_emulate_memop(®s, cr2, &emulops, 4);
|
||||
rc = x86_emulate_memop(®s, cr2, &emulops, X86EMUL_MODE_PROT32);
|
||||
if ( (rc != 0) ||
|
||||
(res != 0x923456AA) ||
|
||||
((regs.eflags&0x240) != 0x200) ||
|
||||
@@ -157,7 +157,7 @@ int main(int argc, char **argv)
|
||||
regs.eip = (unsigned long)&instr[0];
|
||||
regs.ecx = 0x12345678;
|
||||
cr2 = (unsigned long)&res;
|
||||
rc = x86_emulate_memop(®s, cr2, &emulops, 4);
|
||||
rc = x86_emulate_memop(®s, cr2, &emulops, X86EMUL_MODE_PROT32);
|
||||
if ( (rc != 0) ||
|
||||
(res != 0x12345678) ||
|
||||
(regs.eflags != 0x200) ||
|
||||
@@ -174,7 +174,7 @@ int main(int argc, char **argv)
|
||||
regs.eax = 0x923456AAUL;
|
||||
regs.ecx = 0xDDEEFF00L;
|
||||
cr2 = (unsigned long)&res;
|
||||
rc = x86_emulate_memop(®s, cr2, &emulops, 4);
|
||||
rc = x86_emulate_memop(®s, cr2, &emulops, X86EMUL_MODE_PROT32);
|
||||
if ( (rc != 0) ||
|
||||
(res != 0xDDEEFF00) ||
|
||||
(regs.eflags != 0x244) ||
|
||||
@@ -193,7 +193,7 @@ int main(int argc, char **argv)
|
||||
regs.edi = (unsigned long)&res + 2;
|
||||
regs.error_code = 0; /* read fault */
|
||||
cr2 = regs.esi;
|
||||
rc = x86_emulate_memop(®s, cr2, &emulops, 4);
|
||||
rc = x86_emulate_memop(®s, cr2, &emulops, X86EMUL_MODE_PROT32);
|
||||
if ( (rc != 0) ||
|
||||
(res != 0x44554455) ||
|
||||
(regs.eflags != 0x200) ||
|
||||
@@ -211,7 +211,7 @@ int main(int argc, char **argv)
|
||||
regs.eip = (unsigned long)&instr[0];
|
||||
regs.edi = (unsigned long)&res;
|
||||
cr2 = regs.edi;
|
||||
rc = x86_emulate_memop(®s, cr2, &emulops, 4);
|
||||
rc = x86_emulate_memop(®s, cr2, &emulops, X86EMUL_MODE_PROT32);
|
||||
if ( (rc != 0) ||
|
||||
(res != 0x2233445D) ||
|
||||
((regs.eflags&0x201) != 0x201) ||
|
||||
@@ -229,7 +229,7 @@ int main(int argc, char **argv)
|
||||
regs.eip = (unsigned long)&instr[0];
|
||||
regs.edi = (unsigned long)cmpxchg8b_res;
|
||||
cr2 = regs.edi;
|
||||
rc = x86_emulate_memop(®s, cr2, &emulops, 4);
|
||||
rc = x86_emulate_memop(®s, cr2, &emulops, X86EMUL_MODE_PROT32);
|
||||
if ( (rc != 0) ||
|
||||
(cmpxchg8b_res[0] != 0x9999AAAA) ||
|
||||
(cmpxchg8b_res[1] != 0xCCCCFFFF) ||
|
||||
@@ -243,7 +243,7 @@ int main(int argc, char **argv)
|
||||
regs.eip = (unsigned long)&instr[0];
|
||||
regs.edi = (unsigned long)cmpxchg8b_res;
|
||||
cr2 = regs.edi;
|
||||
rc = x86_emulate_memop(®s, cr2, &emulops, 4);
|
||||
rc = x86_emulate_memop(®s, cr2, &emulops, X86EMUL_MODE_PROT32);
|
||||
if ( (rc != 0) ||
|
||||
(cmpxchg8b_res[0] != 0x9999AAAA) ||
|
||||
(cmpxchg8b_res[1] != 0xCCCCFFFF) ||
|
||||
@@ -260,7 +260,7 @@ int main(int argc, char **argv)
|
||||
regs.ecx = 0x12345678;
|
||||
cr2 = (unsigned long)&res;
|
||||
res = 0x82;
|
||||
rc = x86_emulate_memop(®s, cr2, &emulops, 4);
|
||||
rc = x86_emulate_memop(®s, cr2, &emulops, X86EMUL_MODE_PROT32);
|
||||
if ( (rc != 0) ||
|
||||
(res != 0x82) ||
|
||||
(regs.ecx != 0xFFFFFF82) ||
|
||||
@@ -275,7 +275,7 @@ int main(int argc, char **argv)
|
||||
regs.ecx = 0x12345678;
|
||||
cr2 = (unsigned long)&res;
|
||||
res = 0x1234aa82;
|
||||
rc = x86_emulate_memop(®s, cr2, &emulops, 4);
|
||||
rc = x86_emulate_memop(®s, cr2, &emulops, X86EMUL_MODE_PROT32);
|
||||
if ( (rc != 0) ||
|
||||
(res != 0x1234aa82) ||
|
||||
(regs.ecx != 0xaa82) ||
|
||||
|
||||
@@ -53,11 +53,6 @@ DUMMY_BACKEND -> vtpm_manager listens on /tmp/in.fifo and
|
||||
|
||||
MANUAL_DM_LAUNCH -> Must manually launch & kill VTPMs
|
||||
|
||||
WELL_KNOWN_SRK_AUTH -> Rather than randomly generating the password for the SRK,
|
||||
use a well known value. This is necessary for sharing use
|
||||
of the SRK across applications. Such as VTPM and Dom0
|
||||
measurement software.
|
||||
|
||||
WELL_KNOWN_OWNER_AUTH -> Rather than randomly generating the password for the owner,
|
||||
use a well known value. This is useful for debugging and for
|
||||
poor bios which do not support clearing TPM if OwnerAuth is
|
||||
|
||||
@@ -56,8 +56,7 @@ CFLAGS += -DLOGGING_MODULES="(BITMASK(VTPM_LOG_TCS)|BITMASK(VTPM_LOG_VTSP)|BITMA
|
||||
# Do not have manager launch DMs.
|
||||
#CFLAGS += -DMANUAL_DM_LAUNCH
|
||||
|
||||
# Fixed SRK
|
||||
CFLAGS += -DWELL_KNOWN_SRK_AUTH
|
||||
# Fixed OwnerAuth
|
||||
#CFLAGS += -DWELL_KNOWN_OWNER_AUTH
|
||||
|
||||
# TPM Hardware Device or TPM Simulator
|
||||
|
||||
@@ -65,7 +65,7 @@ TPM_RESULT envelope_encrypt(const buffer_t *inbuf,
|
||||
UINT32 i;
|
||||
struct pack_constbuf_t symkey_cipher32, data_cipher32;
|
||||
|
||||
vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Enveloping[%d]: 0x", buffer_len(inbuf));
|
||||
vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Enveloping Input[%d]: 0x", buffer_len(inbuf));
|
||||
for (i=0; i< buffer_len(inbuf); i++)
|
||||
vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", inbuf->bytes[i]);
|
||||
vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
|
||||
@@ -94,6 +94,12 @@ TPM_RESULT envelope_encrypt(const buffer_t *inbuf,
|
||||
BSG_TPM_SIZE32_DATA, &data_cipher32);
|
||||
|
||||
vtpmloginfo(VTPM_LOG_VTPM, "Saved %d bytes of E(symkey) + %d bytes of E(data)\n", buffer_len(&symkey_cipher), buffer_len(&data_cipher));
|
||||
|
||||
vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Enveloping Output[%d]: 0x", buffer_len(sealed_data));
|
||||
for (i=0; i< buffer_len(sealed_data); i++)
|
||||
vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", sealed_data->bytes[i]);
|
||||
vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
|
||||
|
||||
goto egress;
|
||||
|
||||
abort_egress:
|
||||
@@ -125,7 +131,7 @@ TPM_RESULT envelope_decrypt(const long cipher_size,
|
||||
|
||||
memset(&symkey, 0, sizeof(symkey_t));
|
||||
|
||||
vtpmloginfo(VTPM_LOG_VTPM_DEEP, "envelope decrypting[%ld]: 0x", cipher_size);
|
||||
vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Envelope Decrypt Input[%ld]: 0x", cipher_size);
|
||||
for (i=0; i< cipher_size; i++)
|
||||
vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", cipher[i]);
|
||||
vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
|
||||
@@ -155,6 +161,11 @@ TPM_RESULT envelope_decrypt(const long cipher_size,
|
||||
|
||||
// Decrypt State
|
||||
TPMTRY(TPM_DECRYPT_ERROR, Crypto_symcrypto_decrypt (&symkey, &data_cipher, unsealed_data) );
|
||||
|
||||
vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Envelope Decrypte Output[%d]: 0x", buffer_len(unsealed_data));
|
||||
for (i=0; i< buffer_len(unsealed_data); i++)
|
||||
vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", unsealed_data->bytes[i]);
|
||||
vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
|
||||
|
||||
goto egress;
|
||||
|
||||
@@ -291,124 +302,175 @@ TPM_RESULT VTPM_Handle_Load_NVM(VTPM_DMI_RESOURCE *myDMI,
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
TPM_RESULT VTPM_SaveService(void) {
|
||||
TPM_RESULT status=TPM_SUCCESS;
|
||||
int fh, dmis=-1;
|
||||
|
||||
BYTE *flat_global;
|
||||
int flat_global_size, bytes_written;
|
||||
|
||||
BYTE *flat_boot_key, *flat_dmis, *flat_enc;
|
||||
buffer_t clear_flat_global, enc_flat_global;
|
||||
UINT32 storageKeySize = buffer_len(&vtpm_globals->storageKeyWrap);
|
||||
UINT32 bootKeySize = buffer_len(&vtpm_globals->bootKeyWrap);
|
||||
struct pack_buf_t storage_key_pack = {storageKeySize, vtpm_globals->storageKeyWrap.bytes};
|
||||
|
||||
struct pack_buf_t boot_key_pack = {bootKeySize, vtpm_globals->bootKeyWrap.bytes};
|
||||
|
||||
struct hashtable_itr *dmi_itr;
|
||||
VTPM_DMI_RESOURCE *dmi_res;
|
||||
|
||||
UINT32 flat_global_full_size;
|
||||
|
||||
// Global Values needing to be saved
|
||||
flat_global_full_size = 3*sizeof(TPM_DIGEST) + // Auths
|
||||
sizeof(UINT32) + // storagekeysize
|
||||
storageKeySize + // storage key
|
||||
hashtable_count(vtpm_globals->dmi_map) * // num DMIS
|
||||
(sizeof(UINT32) + 2*sizeof(TPM_DIGEST)); // Per DMI info
|
||||
|
||||
|
||||
flat_global = (BYTE *) malloc( flat_global_full_size);
|
||||
|
||||
flat_global_size = BSG_PackList(flat_global, 4,
|
||||
BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth,
|
||||
BSG_TPM_AUTHDATA, &vtpm_globals->srk_usage_auth,
|
||||
BSG_TPM_SECRET, &vtpm_globals->storage_key_usage_auth,
|
||||
BSG_TPM_SIZE32_DATA, &storage_key_pack);
|
||||
|
||||
|
||||
UINT32 boot_key_size, flat_dmis_size;
|
||||
|
||||
// Initially fill these with buffer sizes for each data type. Later fill
|
||||
// in actual size, once flattened.
|
||||
boot_key_size = sizeof(UINT32) + // bootkeysize
|
||||
bootKeySize; // boot key
|
||||
|
||||
TPMTRYRETURN(buffer_init(&clear_flat_global, 3*sizeof(TPM_DIGEST) + // Auths
|
||||
sizeof(UINT32) +// storagekeysize
|
||||
storageKeySize, NULL) ); // storage key
|
||||
|
||||
flat_dmis_size = (hashtable_count(vtpm_globals->dmi_map) - 1) * // num DMIS (-1 for Dom0)
|
||||
(sizeof(UINT32) + 2*sizeof(TPM_DIGEST)); // Per DMI info
|
||||
|
||||
flat_boot_key = (BYTE *) malloc( boot_key_size );
|
||||
flat_enc = (BYTE *) malloc( sizeof(UINT32) );
|
||||
flat_dmis = (BYTE *) malloc( flat_dmis_size );
|
||||
|
||||
boot_key_size = BSG_PackList(flat_boot_key, 1,
|
||||
BSG_TPM_SIZE32_DATA, &boot_key_pack);
|
||||
|
||||
BSG_PackList(clear_flat_global.bytes, 3,
|
||||
BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth,
|
||||
BSG_TPM_SECRET, &vtpm_globals->storage_key_usage_auth,
|
||||
BSG_TPM_SIZE32_DATA, &storage_key_pack);
|
||||
|
||||
TPMTRYRETURN(envelope_encrypt(&clear_flat_global,
|
||||
&vtpm_globals->bootKey,
|
||||
&enc_flat_global) );
|
||||
|
||||
BSG_PackConst(buffer_len(&enc_flat_global), 4, flat_enc);
|
||||
|
||||
// Per DMI values to be saved
|
||||
if (hashtable_count(vtpm_globals->dmi_map) > 0) {
|
||||
|
||||
|
||||
dmi_itr = hashtable_iterator(vtpm_globals->dmi_map);
|
||||
do {
|
||||
dmi_res = (VTPM_DMI_RESOURCE *) hashtable_iterator_value(dmi_itr);
|
||||
dmis++;
|
||||
|
||||
// No need to save dmi0.
|
||||
if (dmi_res->dmi_id == 0)
|
||||
continue;
|
||||
|
||||
|
||||
flat_global_size += BSG_PackList( flat_global + flat_global_size, 3,
|
||||
BSG_TYPE_UINT32, &dmi_res->dmi_id,
|
||||
BSG_TPM_DIGEST, &dmi_res->NVM_measurement,
|
||||
BSG_TPM_DIGEST, &dmi_res->DMI_measurement);
|
||||
|
||||
if (dmi_res->dmi_id == 0)
|
||||
continue;
|
||||
|
||||
|
||||
flat_dmis_size += BSG_PackList( flat_dmis + flat_dmis_size, 3,
|
||||
BSG_TYPE_UINT32, &dmi_res->dmi_id,
|
||||
BSG_TPM_DIGEST, &dmi_res->NVM_measurement,
|
||||
BSG_TPM_DIGEST, &dmi_res->DMI_measurement);
|
||||
|
||||
} while (hashtable_iterator_advance(dmi_itr));
|
||||
}
|
||||
|
||||
//FIXME: Once we have a way to protect a TPM key, we should use it to
|
||||
// encrypt this blob. BUT, unless there is a way to ensure the key is
|
||||
// not used by other apps, this encryption is useless.
|
||||
|
||||
fh = open(STATE_FILE, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE);
|
||||
if (fh == -1) {
|
||||
vtpmlogerror(VTPM_LOG_VTPM, "Unable to open %s file for write.\n", STATE_FILE);
|
||||
status = TPM_IOERROR;
|
||||
goto abort_egress;
|
||||
}
|
||||
|
||||
if ( (bytes_written = write(fh, flat_global, flat_global_size)) != flat_global_size ) {
|
||||
vtpmlogerror(VTPM_LOG_VTPM, "Failed to save service data. %d/%d bytes written.\n", bytes_written, flat_global_size);
|
||||
|
||||
if ( ( write(fh, flat_boot_key, boot_key_size) != boot_key_size ) ||
|
||||
( write(fh, flat_enc, sizeof(UINT32)) != sizeof(UINT32) ) ||
|
||||
( write(fh, enc_flat_global.bytes, buffer_len(&enc_flat_global)) != buffer_len(&enc_flat_global) ) ||
|
||||
( write(fh, flat_dmis, flat_dmis_size) != flat_dmis_size ) ) {
|
||||
vtpmlogerror(VTPM_LOG_VTPM, "Failed to completely write service data.\n");
|
||||
status = TPM_IOERROR;
|
||||
goto abort_egress;
|
||||
}
|
||||
vtpm_globals->DMI_table_dirty = FALSE;
|
||||
|
||||
}
|
||||
|
||||
vtpm_globals->DMI_table_dirty = FALSE;
|
||||
|
||||
goto egress;
|
||||
|
||||
|
||||
abort_egress:
|
||||
egress:
|
||||
|
||||
free(flat_global);
|
||||
|
||||
free(flat_boot_key);
|
||||
free(flat_enc);
|
||||
buffer_free(&enc_flat_global);
|
||||
free(flat_dmis);
|
||||
close(fh);
|
||||
|
||||
|
||||
vtpmloginfo(VTPM_LOG_VTPM, "Saved VTPM Service state (status = %d, dmis = %d)\n", (int) status, dmis);
|
||||
return status;
|
||||
}
|
||||
|
||||
TPM_RESULT VTPM_LoadService(void) {
|
||||
|
||||
|
||||
TPM_RESULT status=TPM_SUCCESS;
|
||||
int fh, stat_ret, dmis=0;
|
||||
long fh_size = 0, step_size;
|
||||
BYTE *flat_global=NULL;
|
||||
struct pack_buf_t storage_key_pack;
|
||||
UINT32 *dmi_id_key;
|
||||
|
||||
BYTE *flat_table=NULL;
|
||||
buffer_t unsealed_data;
|
||||
struct pack_buf_t storage_key_pack, boot_key_pack;
|
||||
UINT32 *dmi_id_key, enc_size;
|
||||
|
||||
VTPM_DMI_RESOURCE *dmi_res;
|
||||
struct stat file_stat;
|
||||
|
||||
|
||||
TPM_HANDLE boot_key_handle;
|
||||
TPM_AUTHDATA boot_usage_auth;
|
||||
memset(&boot_usage_auth, 0, sizeof(TPM_AUTHDATA));
|
||||
|
||||
fh = open(STATE_FILE, O_RDONLY );
|
||||
stat_ret = fstat(fh, &file_stat);
|
||||
if (stat_ret == 0)
|
||||
if (stat_ret == 0)
|
||||
fh_size = file_stat.st_size;
|
||||
else {
|
||||
status = TPM_IOERROR;
|
||||
goto abort_egress;
|
||||
}
|
||||
|
||||
flat_global = (BYTE *) malloc(fh_size);
|
||||
|
||||
if ((long) read(fh, flat_global, fh_size) != fh_size ) {
|
||||
|
||||
flat_table = (BYTE *) malloc(fh_size);
|
||||
|
||||
if ((long) read(fh, flat_table, fh_size) != fh_size ) {
|
||||
status = TPM_IOERROR;
|
||||
goto abort_egress;
|
||||
}
|
||||
|
||||
|
||||
// Read Boot Key
|
||||
step_size = BSG_UnpackList( flat_table, 2,
|
||||
BSG_TPM_SIZE32_DATA, &boot_key_pack,
|
||||
BSG_TYPE_UINT32, &enc_size);
|
||||
|
||||
TPMTRYRETURN(buffer_init(&vtpm_globals->bootKeyWrap, 0, 0) );
|
||||
TPMTRYRETURN(buffer_append_raw(&vtpm_globals->bootKeyWrap, boot_key_pack.size, boot_key_pack.data) );
|
||||
|
||||
//Load Boot Key
|
||||
TPMTRYRETURN( VTSP_LoadKey( vtpm_globals->manager_tcs_handle,
|
||||
TPM_SRK_KEYHANDLE,
|
||||
&vtpm_globals->bootKeyWrap,
|
||||
&SRK_AUTH,
|
||||
&boot_key_handle,
|
||||
&vtpm_globals->keyAuth,
|
||||
&vtpm_globals->bootKey,
|
||||
FALSE) );
|
||||
|
||||
TPMTRYRETURN( envelope_decrypt(enc_size,
|
||||
flat_table + step_size,
|
||||
vtpm_globals->manager_tcs_handle,
|
||||
boot_key_handle,
|
||||
(const TPM_AUTHDATA*) &boot_usage_auth,
|
||||
&unsealed_data) );
|
||||
step_size += enc_size;
|
||||
|
||||
// Global Values needing to be saved
|
||||
step_size = BSG_UnpackList( flat_global, 4,
|
||||
BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth,
|
||||
BSG_TPM_AUTHDATA, &vtpm_globals->srk_usage_auth,
|
||||
BSG_TPM_SECRET, &vtpm_globals->storage_key_usage_auth,
|
||||
BSG_TPM_SIZE32_DATA, &storage_key_pack);
|
||||
|
||||
BSG_UnpackList( unsealed_data.bytes, 3,
|
||||
BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth,
|
||||
BSG_TPM_SECRET, &vtpm_globals->storage_key_usage_auth,
|
||||
BSG_TPM_SIZE32_DATA, &storage_key_pack);
|
||||
|
||||
TPMTRYRETURN(buffer_init(&vtpm_globals->storageKeyWrap, 0, 0) );
|
||||
TPMTRYRETURN(buffer_append_raw(&vtpm_globals->storageKeyWrap, storage_key_pack.size, storage_key_pack.data) );
|
||||
|
||||
|
||||
// Per DMI values to be saved
|
||||
while ( step_size < fh_size ){
|
||||
if (fh_size - step_size < (long) (sizeof(UINT32) + 2*sizeof(TPM_DIGEST))) {
|
||||
@@ -417,35 +479,38 @@ TPM_RESULT VTPM_LoadService(void) {
|
||||
} else {
|
||||
dmi_res = (VTPM_DMI_RESOURCE *) malloc(sizeof(VTPM_DMI_RESOURCE));
|
||||
dmis++;
|
||||
|
||||
|
||||
dmi_res->connected = FALSE;
|
||||
|
||||
step_size += BSG_UnpackList(flat_global + step_size, 3,
|
||||
BSG_TYPE_UINT32, &dmi_res->dmi_id,
|
||||
BSG_TPM_DIGEST, &dmi_res->NVM_measurement,
|
||||
BSG_TPM_DIGEST, &dmi_res->DMI_measurement);
|
||||
|
||||
|
||||
step_size += BSG_UnpackList(flat_table + step_size, 3,
|
||||
BSG_TYPE_UINT32, &dmi_res->dmi_id,
|
||||
BSG_TPM_DIGEST, &dmi_res->NVM_measurement,
|
||||
BSG_TPM_DIGEST, &dmi_res->DMI_measurement);
|
||||
|
||||
// install into map
|
||||
dmi_id_key = (UINT32 *) malloc (sizeof(UINT32));
|
||||
*dmi_id_key = dmi_res->dmi_id;
|
||||
if (!hashtable_insert(vtpm_globals->dmi_map, dmi_id_key, dmi_res)) {
|
||||
status = TPM_FAIL;
|
||||
goto abort_egress;
|
||||
status = TPM_FAIL;
|
||||
goto abort_egress;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
vtpmloginfo(VTPM_LOG_VTPM, "Loaded saved state (dmis = %d).\n", dmis);
|
||||
goto egress;
|
||||
|
||||
|
||||
abort_egress:
|
||||
vtpmlogerror(VTPM_LOG_VTPM, "Failed to load service data with error = %s\n", tpm_get_error_name(status));
|
||||
egress:
|
||||
|
||||
free(flat_global);
|
||||
|
||||
free(flat_table);
|
||||
close(fh);
|
||||
|
||||
|
||||
// TODO: Could be nice and evict BootKey. (Need to add EvictKey to VTSP.
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -74,16 +74,15 @@ VTPM_GLOBALS *vtpm_globals=NULL;
|
||||
#endif
|
||||
|
||||
// --------------------------- Well Known Auths --------------------------
|
||||
#ifdef WELL_KNOWN_SRK_AUTH
|
||||
static BYTE FIXED_SRK_AUTH[20] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
const TPM_AUTHDATA SRK_AUTH = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
#endif
|
||||
|
||||
#ifdef WELL_KNOWN_OWNER_AUTH
|
||||
static BYTE FIXED_OWNER_AUTH[20] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// -------------------------- Hash table functions --------------------
|
||||
|
||||
static unsigned int hashfunc32(void *ky) {
|
||||
@@ -100,13 +99,7 @@ TPM_RESULT VTPM_Create_Service(){
|
||||
|
||||
TPM_RESULT status = TPM_SUCCESS;
|
||||
|
||||
// Generate Auth's for SRK & Owner
|
||||
#ifdef WELL_KNOWN_SRK_AUTH
|
||||
memcpy(vtpm_globals->srk_usage_auth, FIXED_SRK_AUTH, sizeof(TPM_AUTHDATA));
|
||||
#else
|
||||
Crypto_GetRandom(vtpm_globals->srk_usage_auth, sizeof(TPM_AUTHDATA) );
|
||||
#endif
|
||||
|
||||
// Generate Auth for Owner
|
||||
#ifdef WELL_KNOWN_OWNER_AUTH
|
||||
memcpy(vtpm_globals->owner_usage_auth, FIXED_OWNER_AUTH, sizeof(TPM_AUTHDATA));
|
||||
#else
|
||||
@@ -116,14 +109,14 @@ TPM_RESULT VTPM_Create_Service(){
|
||||
// Take Owership of TPM
|
||||
CRYPTO_INFO ek_cryptoInfo;
|
||||
|
||||
vtpmloginfo(VTPM_LOG_VTPM, "Attempting Pubek Read. NOTE: Failure is ok.\n");
|
||||
status = VTSP_ReadPubek(vtpm_globals->manager_tcs_handle, &ek_cryptoInfo);
|
||||
|
||||
// If we can read PubEK then there is no owner and we should take it.
|
||||
if (status == TPM_SUCCESS) {
|
||||
vtpmloginfo(VTPM_LOG_VTPM, "Failed to readEK meaning TPM has an owner. Creating Keys off existing SRK.\n");
|
||||
TPMTRYRETURN(VTSP_TakeOwnership(vtpm_globals->manager_tcs_handle,
|
||||
(const TPM_AUTHDATA*)&vtpm_globals->owner_usage_auth,
|
||||
(const TPM_AUTHDATA*)&vtpm_globals->srk_usage_auth,
|
||||
&SRK_AUTH,
|
||||
&ek_cryptoInfo,
|
||||
&vtpm_globals->keyAuth));
|
||||
|
||||
@@ -142,7 +135,7 @@ TPM_RESULT VTPM_Create_Service(){
|
||||
TPMTRYRETURN( VTSP_OSAP(vtpm_globals->manager_tcs_handle,
|
||||
TPM_ET_KEYHANDLE,
|
||||
TPM_SRK_KEYHANDLE,
|
||||
(const TPM_AUTHDATA*)&vtpm_globals->srk_usage_auth,
|
||||
&SRK_AUTH,
|
||||
&sharedsecret,
|
||||
&osap) );
|
||||
|
||||
@@ -157,8 +150,43 @@ TPM_RESULT VTPM_Create_Service(){
|
||||
&vtpm_globals->storageKeyWrap,
|
||||
&osap) );
|
||||
|
||||
vtpm_globals->keyAuth.fContinueAuthSession = TRUE;
|
||||
// Generate boot key's auth
|
||||
Crypto_GetRandom( &vtpm_globals->storage_key_usage_auth,
|
||||
sizeof(TPM_AUTHDATA) );
|
||||
|
||||
TPM_AUTHDATA bootKeyWrapAuth;
|
||||
memset(&bootKeyWrapAuth, 0, sizeof(bootKeyWrapAuth));
|
||||
|
||||
TPMTRYRETURN( VTSP_OSAP(vtpm_globals->manager_tcs_handle,
|
||||
TPM_ET_KEYHANDLE,
|
||||
TPM_SRK_KEYHANDLE,
|
||||
&SRK_AUTH,
|
||||
&sharedsecret,
|
||||
&osap) );
|
||||
|
||||
osap.fContinueAuthSession = FALSE;
|
||||
|
||||
// FIXME: This key protects the global secrets on disk. It should use TPM
|
||||
// PCR bindings to limit its use to legit configurations.
|
||||
// Current binds are open, implying a Trusted VM contains this code.
|
||||
// If this VM is not Trusted, use measurement and PCR bindings.
|
||||
TPMTRYRETURN( VTSP_CreateWrapKey( vtpm_globals->manager_tcs_handle,
|
||||
TPM_KEY_BIND,
|
||||
(const TPM_AUTHDATA*)&bootKeyWrapAuth,
|
||||
TPM_SRK_KEYHANDLE,
|
||||
(const TPM_AUTHDATA*)&sharedsecret,
|
||||
&vtpm_globals->bootKeyWrap,
|
||||
&osap) );
|
||||
|
||||
// Populate CRYPTO_INFO vtpm_globals->bootKey. This does not load it into the TPM
|
||||
TPMTRYRETURN( VTSP_LoadKey( vtpm_globals->manager_tcs_handle,
|
||||
TPM_SRK_KEYHANDLE,
|
||||
&vtpm_globals->bootKeyWrap,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&vtpm_globals->bootKey,
|
||||
TRUE ) );
|
||||
goto egress;
|
||||
|
||||
abort_egress:
|
||||
@@ -278,24 +306,26 @@ void *VTPM_Service_Handler(void *threadTypePtr){
|
||||
#endif
|
||||
|
||||
// Check status of rx_fh. If necessary attempt to re-open it.
|
||||
char* s = NULL;
|
||||
if (*rx_fh < 0) {
|
||||
#ifdef VTPM_MULTI_VM
|
||||
*rx_fh = open(VTPM_BE_DEV, O_RDWR);
|
||||
s = VTPM_BE_DEV;
|
||||
#else
|
||||
if (threadType == BE_LISTENER_THREAD)
|
||||
#ifdef DUMMY_BACKEND
|
||||
*rx_fh = open("/tmp/in.fifo", O_RDWR);
|
||||
s = "/tmp/in.fifo";
|
||||
#else
|
||||
*rx_fh = open(VTPM_BE_DEV, O_RDWR);
|
||||
s = VTPM_BE_DEV;
|
||||
#endif
|
||||
else // DMI Listener
|
||||
*rx_fh = open(VTPM_RX_FIFO, O_RDWR);
|
||||
s = VTPM_RX_FIFO;
|
||||
*rx_fh = open(s, O_RDWR);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Respond to failures to open rx_fh
|
||||
if (*rx_fh < 0) {
|
||||
vtpmhandlerlogerror(VTPM_LOG_VTPM, "Can't open inbound fh.\n");
|
||||
vtpmhandlerlogerror(VTPM_LOG_VTPM, "Can't open inbound fh for %s.\n", s);
|
||||
#ifdef VTPM_MULTI_VM
|
||||
return TPM_IOERROR;
|
||||
#else
|
||||
@@ -713,7 +743,7 @@ void *VTPM_Service_Handler(void *threadTypePtr){
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
TPM_RESULT VTPM_Init_Service() {
|
||||
TPM_RESULT status = TPM_FAIL;
|
||||
TPM_RESULT status = TPM_FAIL, serviceStatus;
|
||||
BYTE *randomsead;
|
||||
UINT32 randomsize;
|
||||
|
||||
@@ -737,7 +767,7 @@ TPM_RESULT VTPM_Init_Service() {
|
||||
|
||||
// Create new TCS Object
|
||||
vtpm_globals->manager_tcs_handle = 0;
|
||||
|
||||
|
||||
TPMTRYRETURN(TCS_create());
|
||||
|
||||
// Create TCS Context for service
|
||||
@@ -756,17 +786,24 @@ TPM_RESULT VTPM_Init_Service() {
|
||||
vtpm_globals->keyAuth.fContinueAuthSession = TRUE;
|
||||
|
||||
// If failed, create new Service.
|
||||
if (VTPM_LoadService() != TPM_SUCCESS)
|
||||
serviceStatus = VTPM_LoadService();
|
||||
if (serviceStatus == TPM_IOERROR) {
|
||||
vtpmloginfo(VTPM_LOG_VTPM, "Failed to read service file. Assuming first time initialization.\n");
|
||||
TPMTRYRETURN( VTPM_Create_Service() );
|
||||
} else if (serviceStatus != TPM_SUCCESS) {
|
||||
vtpmlogerror(VTPM_LOG_VTPM, "Failed to read existing service file");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
//Load Storage Key
|
||||
TPMTRYRETURN( VTSP_LoadKey( vtpm_globals->manager_tcs_handle,
|
||||
TPM_SRK_KEYHANDLE,
|
||||
&vtpm_globals->storageKeyWrap,
|
||||
(const TPM_AUTHDATA*)&vtpm_globals->srk_usage_auth,
|
||||
&SRK_AUTH,
|
||||
&vtpm_globals->storageKeyHandle,
|
||||
&vtpm_globals->keyAuth,
|
||||
&vtpm_globals->storageKey) );
|
||||
&vtpm_globals->storageKey,
|
||||
FALSE ) );
|
||||
|
||||
// Create entry for Dom0 for control messages
|
||||
TPMTRYRETURN( VTPM_Handle_New_DMI(NULL) );
|
||||
@@ -797,12 +834,11 @@ void VTPM_Stop_Service() {
|
||||
free (dmi_itr);
|
||||
}
|
||||
|
||||
|
||||
TCS_CloseContext(vtpm_globals->manager_tcs_handle);
|
||||
|
||||
if ( (vtpm_globals->DMI_table_dirty) &&
|
||||
(VTPM_SaveService() != TPM_SUCCESS) )
|
||||
if ( (vtpm_globals->DMI_table_dirty) && (VTPM_SaveService() != TPM_SUCCESS) )
|
||||
vtpmlogerror(VTPM_LOG_VTPM, "Unable to save manager data.\n");
|
||||
|
||||
TCS_CloseContext(vtpm_globals->manager_tcs_handle);
|
||||
TCS_destroy();
|
||||
|
||||
hashtable_destroy(vtpm_globals->dmi_map, 1);
|
||||
free(vtpm_globals);
|
||||
|
||||
@@ -108,6 +108,7 @@ typedef struct tdVTPM_GLOBALS {
|
||||
TCS_CONTEXT_HANDLE manager_tcs_handle; // TCS Handle used by manager
|
||||
TPM_HANDLE storageKeyHandle; // Key used by persistent store
|
||||
CRYPTO_INFO storageKey; // For software encryption
|
||||
CRYPTO_INFO bootKey; // For saving table
|
||||
TCS_AUTH keyAuth; // OIAP session for storageKey
|
||||
BOOL DMI_table_dirty; // Indicates that a command
|
||||
// has updated the DMI table
|
||||
@@ -115,15 +116,17 @@ typedef struct tdVTPM_GLOBALS {
|
||||
|
||||
// Persistent Data
|
||||
TPM_AUTHDATA owner_usage_auth; // OwnerAuth of real TPM
|
||||
TPM_AUTHDATA srk_usage_auth; // SRK Auth of real TPM
|
||||
buffer_t storageKeyWrap; // Wrapped copy of storageKey
|
||||
|
||||
TPM_AUTHDATA srk_usage_auth;
|
||||
TPM_AUTHDATA storage_key_usage_auth;
|
||||
|
||||
|
||||
buffer_t bootKeyWrap; // Wrapped copy of boot key
|
||||
|
||||
}VTPM_GLOBALS;
|
||||
|
||||
//Global dmi map
|
||||
extern VTPM_GLOBALS *vtpm_globals;
|
||||
// --------------------------- Global Values --------------------------
|
||||
extern VTPM_GLOBALS *vtpm_globals; // Key info and DMI states
|
||||
extern const TPM_AUTHDATA SRK_AUTH; // SRK Well Known Auth Value
|
||||
|
||||
// ********************** Command Handler Prototypes ***********************
|
||||
TPM_RESULT VTPM_Handle_Load_NVM( VTPM_DMI_RESOURCE *myDMI,
|
||||
|
||||
@@ -144,7 +144,10 @@ TPM_RESULT VerifyAuth( /*[IN]*/ const BYTE *outParamDigestText,
|
||||
if (memcmp (&hm, &(auth->HMAC), sizeof(TPM_DIGEST)) == 0) // 0 indicates equality
|
||||
return (TPM_SUCCESS);
|
||||
else {
|
||||
VTSP_OIAP( hContext, auth);
|
||||
// If specified, reconnect the OIAP session.
|
||||
// NOTE: This only works for TCS's that never have a 0 context.
|
||||
if (hContext)
|
||||
VTSP_OIAP( hContext, auth);
|
||||
return (TPM_AUTHFAIL);
|
||||
}
|
||||
}
|
||||
@@ -157,6 +160,10 @@ TPM_RESULT VTSP_OIAP(const TCS_CONTEXT_HANDLE hContext,
|
||||
TPMTRYRETURN( TCSP_OIAP(hContext,
|
||||
&auth->AuthHandle,
|
||||
&auth->NonceEven) );
|
||||
|
||||
memset(&auth->HMAC, 0, sizeof(TPM_DIGEST));
|
||||
auth->fContinueAuthSession = FALSE;
|
||||
|
||||
goto egress;
|
||||
|
||||
abort_egress:
|
||||
@@ -195,6 +202,9 @@ TPM_RESULT VTSP_OSAP(const TCS_CONTEXT_HANDLE hContext,
|
||||
BSG_TPM_NONCE, &nonceOddOSAP);
|
||||
|
||||
Crypto_HMAC(sharedSecretText, sizeof(sharedSecretText), (BYTE *) usageAuth, TPM_DIGEST_SIZE, (BYTE *) sharedSecret);
|
||||
|
||||
memset(&auth->HMAC, 0, sizeof(TPM_DIGEST));
|
||||
auth->fContinueAuthSession = FALSE;
|
||||
|
||||
goto egress;
|
||||
|
||||
@@ -288,9 +298,6 @@ TPM_RESULT VTSP_TakeOwnership( const TCS_CONTEXT_HANDLE hContext,
|
||||
|
||||
struct pack_buf_t srkText;
|
||||
|
||||
// GenerateAuth new nonceOdd
|
||||
Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
|
||||
|
||||
//These values are accurate for an enc(AuthData).
|
||||
struct pack_buf_t encOwnerAuth, encSrkAuth;
|
||||
|
||||
@@ -383,9 +390,6 @@ TPM_RESULT VTSP_DisablePubekRead( const TCS_CONTEXT_HANDLE hContext,
|
||||
BYTE *paramText; // Digest to make Auth.
|
||||
UINT32 paramTextSize;
|
||||
|
||||
// Generate HMAC
|
||||
Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
|
||||
|
||||
paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
|
||||
|
||||
paramTextSize = BSG_PackList(paramText, 1,
|
||||
@@ -504,9 +508,6 @@ TPM_RESULT VTSP_CreateWrapKey( const TCS_CONTEXT_HANDLE hContext,
|
||||
newKeyText.data = flatKey;
|
||||
newKeyText.size = flatKeySize;
|
||||
|
||||
// GenerateAuth new nonceOdd
|
||||
Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
|
||||
|
||||
// Generate HMAC
|
||||
paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
|
||||
|
||||
@@ -563,63 +564,66 @@ TPM_RESULT VTSP_LoadKey(const TCS_CONTEXT_HANDLE hContext,
|
||||
const TPM_AUTHDATA *parentAuth,
|
||||
TPM_HANDLE *newKeyHandle,
|
||||
TCS_AUTH *auth,
|
||||
CRYPTO_INFO *cryptoinfo /*= NULL*/) {
|
||||
CRYPTO_INFO *cryptoinfo,
|
||||
const BOOL skipTPMLoad) {
|
||||
|
||||
|
||||
vtpmloginfo(VTPM_LOG_VTSP, "Loading Key.\n%s","");
|
||||
vtpmloginfo(VTPM_LOG_VTSP, "Loading Key %s.\n", (!skipTPMLoad ? "into TPM" : "only into memory"));
|
||||
|
||||
TPM_RESULT status = TPM_SUCCESS;
|
||||
TPM_COMMAND_CODE command = TPM_ORD_LoadKey;
|
||||
|
||||
BYTE *paramText; // Digest to make Auth.
|
||||
|
||||
BYTE *paramText=NULL; // Digest to make Auth.
|
||||
UINT32 paramTextSize;
|
||||
|
||||
// SkipTPMLoad stops key from being loaded into TPM, but still generates CRYPTO_INFO for it
|
||||
if (! skipTPMLoad) {
|
||||
|
||||
if ((rgbWrappedKeyBlob == NULL) || (parentAuth == NULL) ||
|
||||
(newKeyHandle==NULL) || (auth==NULL)) {
|
||||
status = TPM_BAD_PARAMETER;
|
||||
goto abort_egress;
|
||||
}
|
||||
if ((rgbWrappedKeyBlob == NULL) || (parentAuth == NULL) ||
|
||||
(newKeyHandle==NULL) || (auth==NULL)) {
|
||||
status = TPM_BAD_PARAMETER;
|
||||
goto abort_egress;
|
||||
}
|
||||
|
||||
// Generate Extra TCS Parameters
|
||||
TPM_HANDLE phKeyHMAC;
|
||||
// Generate Extra TCS Parameters
|
||||
TPM_HANDLE phKeyHMAC;
|
||||
|
||||
// Generate HMAC
|
||||
Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
|
||||
paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
|
||||
|
||||
paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
|
||||
paramTextSize = BSG_PackList(paramText, 1,
|
||||
BSG_TPM_COMMAND_CODE, &command);
|
||||
|
||||
paramTextSize = BSG_PackList(paramText, 1,
|
||||
BSG_TPM_COMMAND_CODE, &command);
|
||||
memcpy(paramText + paramTextSize, rgbWrappedKeyBlob->bytes, buffer_len(rgbWrappedKeyBlob));
|
||||
paramTextSize += buffer_len(rgbWrappedKeyBlob);
|
||||
|
||||
memcpy(paramText + paramTextSize, rgbWrappedKeyBlob->bytes, buffer_len(rgbWrappedKeyBlob));
|
||||
paramTextSize += buffer_len(rgbWrappedKeyBlob);
|
||||
|
||||
TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
|
||||
TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
|
||||
parentAuth, auth) );
|
||||
|
||||
// Call TCS
|
||||
TPMTRYRETURN( TCSP_LoadKeyByBlob( hContext,
|
||||
hUnwrappingKey,
|
||||
buffer_len(rgbWrappedKeyBlob),
|
||||
rgbWrappedKeyBlob->bytes,
|
||||
auth,
|
||||
newKeyHandle,
|
||||
&phKeyHMAC) );
|
||||
// Call TCS
|
||||
TPMTRYRETURN( TCSP_LoadKeyByBlob( hContext,
|
||||
hUnwrappingKey,
|
||||
buffer_len(rgbWrappedKeyBlob),
|
||||
rgbWrappedKeyBlob->bytes,
|
||||
auth,
|
||||
newKeyHandle,
|
||||
&phKeyHMAC) );
|
||||
|
||||
// Verify Auth
|
||||
paramTextSize = BSG_PackList(paramText, 3,
|
||||
BSG_TPM_RESULT, &status,
|
||||
BSG_TPM_COMMAND_CODE, &command,
|
||||
BSG_TPM_HANDLE, newKeyHandle);
|
||||
// Verify Auth
|
||||
paramTextSize = BSG_PackList(paramText, 3,
|
||||
BSG_TPM_RESULT, &status,
|
||||
BSG_TPM_COMMAND_CODE, &command,
|
||||
BSG_TPM_HANDLE, newKeyHandle);
|
||||
|
||||
TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
|
||||
parentAuth, auth,
|
||||
hContext) );
|
||||
TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
|
||||
parentAuth, auth,
|
||||
hContext) );
|
||||
}
|
||||
|
||||
// Unpack/return key structure
|
||||
// Build cryptoinfo structure for software crypto function.
|
||||
if (cryptoinfo != NULL) {
|
||||
TPM_KEY newKey;
|
||||
|
||||
// Unpack/return key structure
|
||||
BSG_Unpack(BSG_TPM_KEY, rgbWrappedKeyBlob->bytes , &newKey);
|
||||
TPM_RSA_KEY_PARMS rsaKeyParms;
|
||||
|
||||
@@ -670,9 +674,6 @@ TPM_RESULT VTSP_Unbind( const TCS_CONTEXT_HANDLE hContext,
|
||||
BYTE *clear_data_text;
|
||||
UINT32 clear_data_size;
|
||||
|
||||
// Generate HMAC
|
||||
Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
|
||||
|
||||
struct pack_buf_t bound_data32 = {bound_data->size, bound_data->bytes};
|
||||
|
||||
paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
|
||||
@@ -781,6 +782,196 @@ TPM_RESULT VTSP_Bind( CRYPTO_INFO *cryptoInfo,
|
||||
return TPM_SUCCESS;
|
||||
}
|
||||
|
||||
TPM_RESULT VTSP_Seal(const TCS_CONTEXT_HANDLE hContext,
|
||||
const TPM_KEY_HANDLE keyHandle,
|
||||
const TPM_AUTHDATA *sealDataAuth,
|
||||
const TPM_PCR_COMPOSITE *pcrComp,
|
||||
const buffer_t *inData,
|
||||
TPM_STORED_DATA *sealedData,
|
||||
const TPM_SECRET *osapSharedSecret,
|
||||
TCS_AUTH *auth) {
|
||||
|
||||
TPM_RESULT status = TPM_SUCCESS;
|
||||
TPM_COMMAND_CODE command = TPM_ORD_Seal;
|
||||
|
||||
BYTE *paramText; // Digest to make Auth.
|
||||
UINT32 paramTextSize;
|
||||
|
||||
// Generate PCR_Info Struct from Comp
|
||||
TPM_PCR_INFO pcrInfo;
|
||||
UINT32 pcrInfoSize, flatpcrSize;
|
||||
BYTE flatpcr[3 + // PCR_Select = 3 1 byte banks
|
||||
sizeof(UINT16) + // 2 byte UINT16
|
||||
sizeof(UINT32) + // PCR_Comp = 4 byte UINT32
|
||||
24 * sizeof(TPM_PCRVALUE) ]; // up to 24 PCRs
|
||||
|
||||
if (pcrComp != NULL) {
|
||||
//printf("\n\tBinding to PCRs: ");
|
||||
//for(int i = 0 ; i < pcrComp->select.sizeOfSelect ; i++)
|
||||
//printf("%2.2x", pcrComp->select.pcrSelect[i]);
|
||||
|
||||
memcpy(&pcrInfo.pcrSelection, &pcrComp->select, sizeof(TPM_PCR_SELECTION));
|
||||
|
||||
flatpcrSize = BSG_Pack(BSG_TPM_PCR_COMPOSITE, (BYTE *) pcrComp, flatpcr);
|
||||
Crypto_SHA1Full((BYTE *) flatpcr, flatpcrSize, (BYTE *) &(pcrInfo.digestAtRelease));
|
||||
memset(&(pcrInfo.digestAtCreation), 0, sizeof(TPM_DIGEST));
|
||||
pcrInfoSize = BSG_Pack(BSG_TPM_PCR_INFO, (BYTE *) &pcrInfo, flatpcr);
|
||||
} else {
|
||||
//printf("\n\tBinding to no PCRS.");
|
||||
pcrInfoSize = 0;
|
||||
}
|
||||
|
||||
// Calculate encUsageAuth
|
||||
BYTE XORbuffer[sizeof(TPM_SECRET) + sizeof(TPM_NONCE)];
|
||||
UINT32 XORbufferSize = sizeof(XORbuffer);
|
||||
TPM_DIGEST XORKey;
|
||||
TPM_ENCAUTH encAuth;
|
||||
|
||||
BSG_PackList( XORbuffer, 2,
|
||||
BSG_TPM_SECRET, osapSharedSecret,
|
||||
BSG_TPM_NONCE, &auth->NonceEven );
|
||||
|
||||
Crypto_SHA1Full(XORbuffer, XORbufferSize, (BYTE *) &XORKey);
|
||||
|
||||
int i;
|
||||
for (i=0; i < TPM_DIGEST_SIZE; i++)
|
||||
((BYTE *) &encAuth)[i] = ((BYTE *) &XORKey)[i] ^ ((BYTE *) sealDataAuth)[i];
|
||||
|
||||
// Generate Extra TCS Parameters
|
||||
UINT32 inDataSize = buffer_len(inData);
|
||||
struct pack_buf_t inData_pack = {inDataSize, inData->bytes};
|
||||
struct pack_buf_t pcrInfo_pack = {pcrInfoSize, flatpcr};
|
||||
|
||||
UINT32 sealedDataSize;
|
||||
BYTE *flatSealedData=NULL;
|
||||
|
||||
paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
|
||||
|
||||
paramTextSize = BSG_PackList(paramText, 4,
|
||||
BSG_TPM_COMMAND_CODE, &command,
|
||||
BSG_TPM_ENCAUTH, &encAuth,
|
||||
BSG_TPM_SIZE32_DATA, &pcrInfo_pack,
|
||||
BSG_TPM_SIZE32_DATA, &inData_pack);
|
||||
|
||||
TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
|
||||
osapSharedSecret, auth) );
|
||||
|
||||
// Call TCS
|
||||
TPMTRYRETURN( TCSP_Seal( hContext,
|
||||
keyHandle,
|
||||
encAuth,
|
||||
pcrInfoSize,
|
||||
flatpcr,
|
||||
inDataSize,
|
||||
inData->bytes,
|
||||
auth,
|
||||
&sealedDataSize,
|
||||
&flatSealedData) );
|
||||
|
||||
// Unpack/return key structure
|
||||
BSG_Unpack( BSG_TPM_STORED_DATA, flatSealedData, sealedData );
|
||||
|
||||
paramTextSize = BSG_PackList(paramText, 3,
|
||||
BSG_TPM_RESULT, &status,
|
||||
BSG_TPM_COMMAND_CODE, &command,
|
||||
BSG_TPM_STORED_DATA, sealedData);
|
||||
|
||||
TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
|
||||
osapSharedSecret, auth,
|
||||
0) );
|
||||
|
||||
|
||||
goto egress;
|
||||
|
||||
abort_egress:
|
||||
egress:
|
||||
|
||||
if (flatSealedData)
|
||||
TCS_FreeMemory( hContext, flatSealedData);
|
||||
|
||||
free(paramText);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
TPM_RESULT VTSP_Unseal(const TCS_CONTEXT_HANDLE hContext,
|
||||
const TPM_KEY_HANDLE keyHandle,
|
||||
const TPM_STORED_DATA *sealedData,
|
||||
const TPM_AUTHDATA *key_usage_auth,
|
||||
const TPM_AUTHDATA *data_usage_auth,
|
||||
buffer_t *outData,
|
||||
TCS_AUTH *auth,
|
||||
TCS_AUTH *dataAuth) {
|
||||
|
||||
TPM_RESULT status = TPM_SUCCESS;
|
||||
TPM_COMMAND_CODE command = TPM_ORD_Unseal;
|
||||
|
||||
BYTE *paramText; // Digest to make Auth.
|
||||
UINT32 paramTextSize;
|
||||
|
||||
// Generate Extra TCS Parameters
|
||||
UINT32 sealDataSize, clearDataSize;
|
||||
BYTE *flatSealedData= (BYTE *) malloc(sizeof(TPM_VERSION) +
|
||||
2 * sizeof(UINT32) +
|
||||
sealedData->sealInfoSize +
|
||||
sealedData->encDataSize),
|
||||
*clearData=NULL;
|
||||
|
||||
sealDataSize = BSG_Pack(BSG_TPM_STORED_DATA, sealedData, flatSealedData );
|
||||
|
||||
paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
|
||||
|
||||
paramTextSize = BSG_PackList(paramText, 2,
|
||||
BSG_TPM_COMMAND_CODE, &command,
|
||||
BSG_TPM_STORED_DATA, sealedData);
|
||||
|
||||
TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
|
||||
key_usage_auth, auth) );
|
||||
|
||||
TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
|
||||
data_usage_auth, dataAuth) );
|
||||
// Call TCS
|
||||
TPMTRYRETURN( TCSP_Unseal( hContext,
|
||||
keyHandle,
|
||||
sealDataSize,
|
||||
flatSealedData,
|
||||
auth,
|
||||
dataAuth,
|
||||
&clearDataSize,
|
||||
&clearData) );
|
||||
|
||||
// Verify Auth
|
||||
struct pack_buf_t clearData_pack = {clearDataSize, clearData};
|
||||
|
||||
paramTextSize = BSG_PackList(paramText, 3,
|
||||
BSG_TPM_RESULT, &status,
|
||||
BSG_TPM_COMMAND_CODE, &command,
|
||||
BSG_TPM_SIZE32_DATA, &clearData_pack);
|
||||
|
||||
TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
|
||||
key_usage_auth, auth,
|
||||
hContext) );
|
||||
|
||||
TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
|
||||
data_usage_auth, dataAuth,
|
||||
hContext) );
|
||||
|
||||
// Unpack/return key structure
|
||||
TPMTRYRETURN( buffer_init(outData, clearDataSize, clearData) );
|
||||
|
||||
goto egress;
|
||||
|
||||
abort_egress:
|
||||
egress:
|
||||
|
||||
if (flatSealedData)
|
||||
TCS_FreeMemory( hContext, clearData);
|
||||
|
||||
free(paramText);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
// Function Reaches into unsupported TCS command, beware.
|
||||
TPM_RESULT VTSP_RawTransmit(const TCS_CONTEXT_HANDLE hContext,
|
||||
const buffer_t *inbuf,
|
||||
|
||||
@@ -86,7 +86,8 @@ TPM_RESULT VTSP_LoadKey(const TCS_CONTEXT_HANDLE hContext,
|
||||
const TPM_AUTHDATA *parentAuth,
|
||||
TPM_HANDLE *newKeyHandle,
|
||||
TCS_AUTH *pAuth,
|
||||
CRYPTO_INFO *cryptoinfo);
|
||||
CRYPTO_INFO *cryptoinfo,
|
||||
const BOOL skipTPMLoad);
|
||||
|
||||
TPM_RESULT VTSP_Unbind( const TCS_CONTEXT_HANDLE hContext,
|
||||
const TPM_KEY_HANDLE key_handle,
|
||||
@@ -99,4 +100,22 @@ TPM_RESULT VTSP_Bind( CRYPTO_INFO *cryptoInfo,
|
||||
const buffer_t *inData,
|
||||
buffer_t *outData);
|
||||
|
||||
TPM_RESULT VTSP_Seal(const TCS_CONTEXT_HANDLE hContext,
|
||||
const TPM_KEY_HANDLE keyHandle,
|
||||
const TPM_AUTHDATA *sealDataAuth,
|
||||
const TPM_PCR_COMPOSITE *pcrComp,
|
||||
const buffer_t *inData,
|
||||
TPM_STORED_DATA *sealedData,
|
||||
const TPM_SECRET *osapSharedSecret,
|
||||
TCS_AUTH *auth);
|
||||
|
||||
TPM_RESULT VTSP_Unseal(const TCS_CONTEXT_HANDLE hContext,
|
||||
const TPM_KEY_HANDLE keyHandle,
|
||||
const TPM_STORED_DATA *sealedData,
|
||||
const TPM_AUTHDATA *key_usage_auth,
|
||||
const TPM_AUTHDATA *data_usage_auth,
|
||||
buffer_t *outData,
|
||||
TCS_AUTH *auth,
|
||||
TCS_AUTH *dataAuth);
|
||||
|
||||
#endif //_VTSP_H_
|
||||
@@ -636,7 +636,7 @@ TPM_RESULT TCSP_Seal( TCS_CONTEXT_HANDLE hContext, // in
|
||||
TDDL_UINT32 OutLength = TCPA_MAX_BUFFER_LENGTH;
|
||||
|
||||
// check input params
|
||||
if (inData == NULL || pubAuth == NULL || SealedDataSize == NULL || *SealedData == NULL)
|
||||
if (inData == NULL || pubAuth == NULL || SealedDataSize == NULL || SealedData == NULL)
|
||||
return TPM_BAD_PARAMETER;
|
||||
|
||||
// Convert Byte Input parameter in the input byte stream InBuf
|
||||
|
||||
+11
-3
@@ -15,24 +15,32 @@ HDRS = $(wildcard *.h)
|
||||
OBJS = $(patsubst %.c,%.o,$(wildcard *.c))
|
||||
|
||||
BIN = xentrace tbctl setsize
|
||||
LIBBIN = xenctx
|
||||
LIBBIN =
|
||||
SCRIPTS = xentrace_format
|
||||
MAN1 = $(wildcard *.1)
|
||||
MAN8 = $(wildcard *.8)
|
||||
|
||||
ifeq ($(XEN_TARGET_ARCH),x86_32)
|
||||
LIBBIN += xenctx
|
||||
endif
|
||||
|
||||
ifeq ($(XEN_TARGET_ARCH),x86_64)
|
||||
LIBBIN += xenctx
|
||||
endif
|
||||
|
||||
all: build
|
||||
build: $(BIN) $(LIBBIN)
|
||||
|
||||
install: build
|
||||
[ -d $(DESTDIR)/usr/bin ] || $(INSTALL_DIR) $(DESTDIR)/usr/bin
|
||||
[ -d $(DESTDIR)/usr/$(LIBDIR)/xen/bin ] || \
|
||||
[ -z "$(LIBBIN)"] || [ -d $(DESTDIR)/usr/$(LIBDIR)/xen/bin ] || \
|
||||
$(INSTALL_DIR) $(DESTDIR)/usr/$(LIBDIR)/xen/bin
|
||||
[ -d $(DESTDIR)/usr/share/man/man1 ] || \
|
||||
$(INSTALL_DIR) $(DESTDIR)/usr/share/man/man1
|
||||
[ -d $(DESTDIR)/usr/share/man/man8 ] || \
|
||||
$(INSTALL_DIR) $(DESTDIR)/usr/share/man/man8
|
||||
$(INSTALL_PROG) $(BIN) $(SCRIPTS) $(DESTDIR)/usr/bin
|
||||
$(INSTALL_PROG) $(LIBBIN) $(DESTDIR)/usr/$(LIBDIR)/xen/bin
|
||||
[ -z "$(LIBBIN)"] || $(INSTALL_PROG) $(LIBBIN) $(DESTDIR)/usr/$(LIBDIR)/xen/bin
|
||||
$(INSTALL_DATA) $(MAN1) $(DESTDIR)/usr/share/man/man1
|
||||
$(INSTALL_DATA) $(MAN8) $(DESTDIR)/usr/share/man/man8
|
||||
|
||||
|
||||
@@ -380,10 +380,10 @@ void dump_ctx(int vcpu)
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
ret = xc_domain_get_vcpu_context(xc_handle, domid, vcpu, &ctx);
|
||||
ret = xc_vcpu_getcontext(xc_handle, domid, vcpu, &ctx);
|
||||
if (ret < 0) {
|
||||
xc_domain_unpause(xc_handle, domid);
|
||||
perror("xc_domain_get_vcpu_context");
|
||||
perror("xc_vcpu_getcontext");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ TESTS = 01_network_attach_pos.test \
|
||||
03_network_attach_detach_multiple_pos.test \
|
||||
04_network_attach_baddomain_neg.test
|
||||
|
||||
XFAIL_TESTS = 03_network_attach_detach_multiple_pos.test
|
||||
XFAIL_TESTS =
|
||||
|
||||
EXTRA_DIST = $(TESTS) $(XFAIL_TESTS) network_utils.py
|
||||
|
||||
|
||||
+26
-4
@@ -23,6 +23,13 @@ OBJS += bitop.o clear_page.o flush.o copy_page_mck.o \
|
||||
__divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \
|
||||
__divdi3.o __udivdi3.o __moddi3.o __umoddi3.o
|
||||
|
||||
# xen stack unwinder
|
||||
# unwind_decoder.c is included in unwind.c
|
||||
OBJS += unwind.o
|
||||
#unwind.o: CFLAGS += -DUNW_DEBUG=4
|
||||
|
||||
OBJS += process-linux-xen.o
|
||||
|
||||
# perfmon.o
|
||||
# unwind.o needed for kernel unwinding (rare)
|
||||
|
||||
@@ -31,11 +38,26 @@ OBJS := $(subst $(TARGET_ARCH)/asm-offsets.o,,$(OBJS))
|
||||
# remove following line if not privifying in memory
|
||||
# OBJS += privify.o
|
||||
|
||||
default: $(OBJS) head.o xen.lds.s
|
||||
$(LD) -r -o arch.o $(OBJS)
|
||||
default: $(TARGET)
|
||||
|
||||
$(CURDIR)/arch.o: $(OBJS)
|
||||
$(LD) -r -o $@ $(OBJS)
|
||||
|
||||
$(TARGET)-syms: $(ALL_OBJS) head.o xen.lds.s
|
||||
$(LD) $(LDFLAGS) -T $(BASEDIR)/arch/$(TARGET_ARCH)/xen.lds.s -N \
|
||||
-Map map.out head.o $(ALL_OBJS) -o $(TARGET)-syms
|
||||
$(OBJCOPY) -R .note -R .comment -S $(TARGET)-syms $(TARGET)
|
||||
-Map map.out head.o $(ALL_OBJS) -o $@
|
||||
$(NM) -n $@ | $(BASEDIR)/tools/symbols > $(BASEDIR)/xen-syms.S
|
||||
$(MAKE) $(BASEDIR)/xen-syms.o
|
||||
$(LD) $(LDFLAGS) -T $(BASEDIR)/arch/$(TARGET_ARCH)/xen.lds.s -N \
|
||||
-Map map.out head.o $(ALL_OBJS) $(BASEDIR)/xen-syms.o -o $@
|
||||
$(NM) -n $@ | $(BASEDIR)/tools/symbols >$(BASEDIR)/xen-syms.S
|
||||
$(MAKE) $(BASEDIR)/xen-syms.o
|
||||
$(LD) $(LDFLAGS) -T $(BASEDIR)/arch/$(TARGET_ARCH)/xen.lds.s -N \
|
||||
-Map map.out head.o $(ALL_OBJS) $(BASEDIR)/xen-syms.o -o $@
|
||||
rm -f $(BASEDIR)/xen-syms.S $(BASEDIR)/xen-syms.o
|
||||
|
||||
$(TARGET): $(TARGET)-syms
|
||||
$(OBJCOPY) -R .note -R .comment -S $(TARGET)-syms $@
|
||||
$(NM) -n $(TARGET)-syms | grep -v '\( [aUw] \)\|\(__crc_\)\|\( \$[adt]\)'\
|
||||
> $(BASEDIR)/System.map
|
||||
|
||||
|
||||
@@ -1417,7 +1417,6 @@ GLOBAL_ENTRY(ia64_prepare_handle_unaligned)
|
||||
br.cond.sptk.many rp // goes to ia64_leave_kernel
|
||||
END(ia64_prepare_handle_unaligned)
|
||||
|
||||
#ifndef XEN
|
||||
//
|
||||
// unw_init_running(void (*callback)(info, arg), void *arg)
|
||||
//
|
||||
@@ -1463,6 +1462,7 @@ GLOBAL_ENTRY(unw_init_running)
|
||||
br.ret.sptk.many rp
|
||||
END(unw_init_running)
|
||||
|
||||
#ifndef XEN
|
||||
.rodata
|
||||
.align 8
|
||||
.globl sys_call_table
|
||||
|
||||
@@ -0,0 +1,848 @@
|
||||
/*
|
||||
* Architecture-specific setup.
|
||||
*
|
||||
* Copyright (C) 1998-2003 Hewlett-Packard Co
|
||||
* David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
* 04/11/17 Ashok Raj <ashok.raj@intel.com> Added CPU Hotplug Support
|
||||
*/
|
||||
#ifdef XEN
|
||||
#include <xen/types.h>
|
||||
#include <xen/lib.h>
|
||||
#include <xen/symbols.h>
|
||||
#include <xen/smp.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/unwind.h>
|
||||
#else
|
||||
#define __KERNEL_SYSCALLS__ /* see <asm/unistd.h> */
|
||||
#include <linux/config.h>
|
||||
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/elf.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/personality.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/thread_info.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/efi.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kprobes.h>
|
||||
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/elf.h>
|
||||
#include <asm/ia32.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/sal.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/unwind.h>
|
||||
#include <asm/user.h>
|
||||
|
||||
#include "entry.h"
|
||||
|
||||
#ifdef CONFIG_PERFMON
|
||||
# include <asm/perfmon.h>
|
||||
#endif
|
||||
|
||||
#include "sigframe.h"
|
||||
|
||||
void (*ia64_mark_idle)(int);
|
||||
static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
|
||||
|
||||
unsigned long boot_option_idle_override = 0;
|
||||
EXPORT_SYMBOL(boot_option_idle_override);
|
||||
#endif
|
||||
|
||||
void
|
||||
ia64_do_show_stack (struct unw_frame_info *info, void *arg)
|
||||
{
|
||||
unsigned long ip, sp, bsp;
|
||||
char buf[128]; /* don't make it so big that it overflows the stack! */
|
||||
|
||||
printk("\nCall Trace:\n");
|
||||
do {
|
||||
unw_get_ip(info, &ip);
|
||||
if (ip == 0)
|
||||
break;
|
||||
|
||||
unw_get_sp(info, &sp);
|
||||
unw_get_bsp(info, &bsp);
|
||||
snprintf(buf, sizeof(buf),
|
||||
" [<%016lx>] %%s\n"
|
||||
" sp=%016lx bsp=%016lx\n",
|
||||
ip, sp, bsp);
|
||||
print_symbol(buf, ip);
|
||||
} while (unw_unwind(info) >= 0);
|
||||
}
|
||||
|
||||
void
|
||||
show_stack (struct task_struct *task, unsigned long *sp)
|
||||
{
|
||||
if (!task)
|
||||
unw_init_running(ia64_do_show_stack, NULL);
|
||||
else {
|
||||
struct unw_frame_info info;
|
||||
|
||||
unw_init_from_blocked_task(&info, task);
|
||||
ia64_do_show_stack(&info, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef XEN
|
||||
void
|
||||
dump_stack (void)
|
||||
{
|
||||
show_stack(NULL, NULL);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(dump_stack);
|
||||
#endif
|
||||
|
||||
#ifdef XEN
|
||||
void
|
||||
show_registers(struct pt_regs *regs)
|
||||
#else
|
||||
void
|
||||
show_regs (struct pt_regs *regs)
|
||||
#endif
|
||||
{
|
||||
unsigned long ip = regs->cr_iip + ia64_psr(regs)->ri;
|
||||
|
||||
#ifndef XEN
|
||||
print_modules();
|
||||
printk("\nPid: %d, CPU %d, comm: %20s\n", current->pid, smp_processor_id(), current->comm);
|
||||
printk("psr : %016lx ifs : %016lx ip : [<%016lx>] %s\n",
|
||||
regs->cr_ipsr, regs->cr_ifs, ip, print_tainted());
|
||||
#else
|
||||
printk("\nCPU %d\n", smp_processor_id());
|
||||
printk("psr : %016lx ifs : %016lx ip : [<%016lx>]\n",
|
||||
regs->cr_ipsr, regs->cr_ifs, ip);
|
||||
#endif
|
||||
print_symbol("ip is at %s\n", ip);
|
||||
printk("unat: %016lx pfs : %016lx rsc : %016lx\n",
|
||||
regs->ar_unat, regs->ar_pfs, regs->ar_rsc);
|
||||
printk("rnat: %016lx bsps: %016lx pr : %016lx\n",
|
||||
regs->ar_rnat, regs->ar_bspstore, regs->pr);
|
||||
printk("ldrs: %016lx ccv : %016lx fpsr: %016lx\n",
|
||||
regs->loadrs, regs->ar_ccv, regs->ar_fpsr);
|
||||
printk("csd : %016lx ssd : %016lx\n", regs->ar_csd, regs->ar_ssd);
|
||||
printk("b0 : %016lx b6 : %016lx b7 : %016lx\n", regs->b0, regs->b6, regs->b7);
|
||||
printk("f6 : %05lx%016lx f7 : %05lx%016lx\n",
|
||||
regs->f6.u.bits[1], regs->f6.u.bits[0],
|
||||
regs->f7.u.bits[1], regs->f7.u.bits[0]);
|
||||
printk("f8 : %05lx%016lx f9 : %05lx%016lx\n",
|
||||
regs->f8.u.bits[1], regs->f8.u.bits[0],
|
||||
regs->f9.u.bits[1], regs->f9.u.bits[0]);
|
||||
printk("f10 : %05lx%016lx f11 : %05lx%016lx\n",
|
||||
regs->f10.u.bits[1], regs->f10.u.bits[0],
|
||||
regs->f11.u.bits[1], regs->f11.u.bits[0]);
|
||||
|
||||
printk("r1 : %016lx r2 : %016lx r3 : %016lx\n", regs->r1, regs->r2, regs->r3);
|
||||
printk("r8 : %016lx r9 : %016lx r10 : %016lx\n", regs->r8, regs->r9, regs->r10);
|
||||
printk("r11 : %016lx r12 : %016lx r13 : %016lx\n", regs->r11, regs->r12, regs->r13);
|
||||
printk("r14 : %016lx r15 : %016lx r16 : %016lx\n", regs->r14, regs->r15, regs->r16);
|
||||
printk("r17 : %016lx r18 : %016lx r19 : %016lx\n", regs->r17, regs->r18, regs->r19);
|
||||
printk("r20 : %016lx r21 : %016lx r22 : %016lx\n", regs->r20, regs->r21, regs->r22);
|
||||
printk("r23 : %016lx r24 : %016lx r25 : %016lx\n", regs->r23, regs->r24, regs->r25);
|
||||
printk("r26 : %016lx r27 : %016lx r28 : %016lx\n", regs->r26, regs->r27, regs->r28);
|
||||
printk("r29 : %016lx r30 : %016lx r31 : %016lx\n", regs->r29, regs->r30, regs->r31);
|
||||
|
||||
if (user_mode(regs)) {
|
||||
/* print the stacked registers */
|
||||
unsigned long val, *bsp, ndirty;
|
||||
int i, sof, is_nat = 0;
|
||||
|
||||
sof = regs->cr_ifs & 0x7f; /* size of frame */
|
||||
ndirty = (regs->loadrs >> 19);
|
||||
bsp = ia64_rse_skip_regs((unsigned long *) regs->ar_bspstore, ndirty);
|
||||
for (i = 0; i < sof; ++i) {
|
||||
get_user(val, (unsigned long __user *) ia64_rse_skip_regs(bsp, i));
|
||||
printk("r%-3u:%c%016lx%s", 32 + i, is_nat ? '*' : ' ', val,
|
||||
((i == sof - 1) || (i % 3) == 2) ? "\n" : " ");
|
||||
}
|
||||
} else
|
||||
show_stack(NULL, NULL);
|
||||
}
|
||||
|
||||
#ifndef XEN
|
||||
void
|
||||
do_notify_resume_user (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
|
||||
{
|
||||
if (fsys_mode(current, &scr->pt)) {
|
||||
/* defer signal-handling etc. until we return to privilege-level 0. */
|
||||
if (!ia64_psr(&scr->pt)->lp)
|
||||
ia64_psr(&scr->pt)->lp = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PERFMON
|
||||
if (current->thread.pfm_needs_checking)
|
||||
pfm_handle_work();
|
||||
#endif
|
||||
|
||||
/* deal with pending signal delivery */
|
||||
if (test_thread_flag(TIF_SIGPENDING))
|
||||
ia64_do_signal(oldset, scr, in_syscall);
|
||||
}
|
||||
|
||||
static int pal_halt = 1;
|
||||
static int can_do_pal_halt = 1;
|
||||
|
||||
static int __init nohalt_setup(char * str)
|
||||
{
|
||||
pal_halt = can_do_pal_halt = 0;
|
||||
return 1;
|
||||
}
|
||||
__setup("nohalt", nohalt_setup);
|
||||
|
||||
void
|
||||
update_pal_halt_status(int status)
|
||||
{
|
||||
can_do_pal_halt = pal_halt && status;
|
||||
}
|
||||
|
||||
/*
|
||||
* We use this if we don't have any better idle routine..
|
||||
*/
|
||||
void
|
||||
default_idle (void)
|
||||
{
|
||||
local_irq_enable();
|
||||
while (!need_resched())
|
||||
if (can_do_pal_halt)
|
||||
safe_halt();
|
||||
else
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
/* We don't actually take CPU down, just spin without interrupts. */
|
||||
static inline void play_dead(void)
|
||||
{
|
||||
extern void ia64_cpu_local_tick (void);
|
||||
unsigned int this_cpu = smp_processor_id();
|
||||
|
||||
/* Ack it */
|
||||
__get_cpu_var(cpu_state) = CPU_DEAD;
|
||||
|
||||
max_xtp();
|
||||
local_irq_disable();
|
||||
idle_domain_exit();
|
||||
ia64_jump_to_sal(&sal_boot_rendez_state[this_cpu]);
|
||||
/*
|
||||
* The above is a point of no-return, the processor is
|
||||
* expected to be in SAL loop now.
|
||||
*/
|
||||
BUG();
|
||||
}
|
||||
#else
|
||||
static inline void play_dead(void)
|
||||
{
|
||||
BUG();
|
||||
}
|
||||
#endif /* CONFIG_HOTPLUG_CPU */
|
||||
|
||||
void cpu_idle_wait(void)
|
||||
{
|
||||
unsigned int cpu, this_cpu = get_cpu();
|
||||
cpumask_t map;
|
||||
|
||||
set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
|
||||
put_cpu();
|
||||
|
||||
cpus_clear(map);
|
||||
for_each_online_cpu(cpu) {
|
||||
per_cpu(cpu_idle_state, cpu) = 1;
|
||||
cpu_set(cpu, map);
|
||||
}
|
||||
|
||||
__get_cpu_var(cpu_idle_state) = 0;
|
||||
|
||||
wmb();
|
||||
do {
|
||||
ssleep(1);
|
||||
for_each_online_cpu(cpu) {
|
||||
if (cpu_isset(cpu, map) && !per_cpu(cpu_idle_state, cpu))
|
||||
cpu_clear(cpu, map);
|
||||
}
|
||||
cpus_and(map, map, cpu_online_map);
|
||||
} while (!cpus_empty(map));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpu_idle_wait);
|
||||
|
||||
void __attribute__((noreturn))
|
||||
cpu_idle (void)
|
||||
{
|
||||
void (*mark_idle)(int) = ia64_mark_idle;
|
||||
|
||||
/* endless idle loop with no priority at all */
|
||||
while (1) {
|
||||
#ifdef CONFIG_SMP
|
||||
if (!need_resched())
|
||||
min_xtp();
|
||||
#endif
|
||||
while (!need_resched()) {
|
||||
void (*idle)(void);
|
||||
|
||||
if (__get_cpu_var(cpu_idle_state))
|
||||
__get_cpu_var(cpu_idle_state) = 0;
|
||||
|
||||
rmb();
|
||||
if (mark_idle)
|
||||
(*mark_idle)(1);
|
||||
|
||||
idle = pm_idle;
|
||||
if (!idle)
|
||||
idle = default_idle;
|
||||
(*idle)();
|
||||
}
|
||||
|
||||
if (mark_idle)
|
||||
(*mark_idle)(0);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
normal_xtp();
|
||||
#endif
|
||||
schedule();
|
||||
check_pgt_cache();
|
||||
if (cpu_is_offline(smp_processor_id()))
|
||||
play_dead();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ia64_save_extra (struct task_struct *task)
|
||||
{
|
||||
#ifdef CONFIG_PERFMON
|
||||
unsigned long info;
|
||||
#endif
|
||||
|
||||
if ((task->thread.flags & IA64_THREAD_DBG_VALID) != 0)
|
||||
ia64_save_debug_regs(&task->thread.dbr[0]);
|
||||
|
||||
#ifdef CONFIG_PERFMON
|
||||
if ((task->thread.flags & IA64_THREAD_PM_VALID) != 0)
|
||||
pfm_save_regs(task);
|
||||
|
||||
info = __get_cpu_var(pfm_syst_info);
|
||||
if (info & PFM_CPUINFO_SYST_WIDE)
|
||||
pfm_syst_wide_update_task(task, info, 0);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
if (IS_IA32_PROCESS(ia64_task_regs(task)))
|
||||
ia32_save_state(task);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
ia64_load_extra (struct task_struct *task)
|
||||
{
|
||||
#ifdef CONFIG_PERFMON
|
||||
unsigned long info;
|
||||
#endif
|
||||
|
||||
if ((task->thread.flags & IA64_THREAD_DBG_VALID) != 0)
|
||||
ia64_load_debug_regs(&task->thread.dbr[0]);
|
||||
|
||||
#ifdef CONFIG_PERFMON
|
||||
if ((task->thread.flags & IA64_THREAD_PM_VALID) != 0)
|
||||
pfm_load_regs(task);
|
||||
|
||||
info = __get_cpu_var(pfm_syst_info);
|
||||
if (info & PFM_CPUINFO_SYST_WIDE)
|
||||
pfm_syst_wide_update_task(task, info, 1);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
if (IS_IA32_PROCESS(ia64_task_regs(task)))
|
||||
ia32_load_state(task);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the state of an ia-64 thread.
|
||||
*
|
||||
* We get here through the following call chain:
|
||||
*
|
||||
* from user-level: from kernel:
|
||||
*
|
||||
* <clone syscall> <some kernel call frames>
|
||||
* sys_clone :
|
||||
* do_fork do_fork
|
||||
* copy_thread copy_thread
|
||||
*
|
||||
* This means that the stack layout is as follows:
|
||||
*
|
||||
* +---------------------+ (highest addr)
|
||||
* | struct pt_regs |
|
||||
* +---------------------+
|
||||
* | struct switch_stack |
|
||||
* +---------------------+
|
||||
* | |
|
||||
* | memory stack |
|
||||
* | | <-- sp (lowest addr)
|
||||
* +---------------------+
|
||||
*
|
||||
* Observe that we copy the unat values that are in pt_regs and switch_stack. Spilling an
|
||||
* integer to address X causes bit N in ar.unat to be set to the NaT bit of the register,
|
||||
* with N=(X & 0x1ff)/8. Thus, copying the unat value preserves the NaT bits ONLY if the
|
||||
* pt_regs structure in the parent is congruent to that of the child, modulo 512. Since
|
||||
* the stack is page aligned and the page size is at least 4KB, this is always the case,
|
||||
* so there is nothing to worry about.
|
||||
*/
|
||||
int
|
||||
copy_thread (int nr, unsigned long clone_flags,
|
||||
unsigned long user_stack_base, unsigned long user_stack_size,
|
||||
struct task_struct *p, struct pt_regs *regs)
|
||||
{
|
||||
extern char ia64_ret_from_clone, ia32_ret_from_clone;
|
||||
struct switch_stack *child_stack, *stack;
|
||||
unsigned long rbs, child_rbs, rbs_size;
|
||||
struct pt_regs *child_ptregs;
|
||||
int retval = 0;
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/*
|
||||
* For SMP idle threads, fork_by_hand() calls do_fork with
|
||||
* NULL regs.
|
||||
*/
|
||||
if (!regs)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
stack = ((struct switch_stack *) regs) - 1;
|
||||
|
||||
child_ptregs = (struct pt_regs *) ((unsigned long) p + IA64_STK_OFFSET) - 1;
|
||||
child_stack = (struct switch_stack *) child_ptregs - 1;
|
||||
|
||||
/* copy parent's switch_stack & pt_regs to child: */
|
||||
memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack));
|
||||
|
||||
rbs = (unsigned long) current + IA64_RBS_OFFSET;
|
||||
child_rbs = (unsigned long) p + IA64_RBS_OFFSET;
|
||||
rbs_size = stack->ar_bspstore - rbs;
|
||||
|
||||
/* copy the parent's register backing store to the child: */
|
||||
memcpy((void *) child_rbs, (void *) rbs, rbs_size);
|
||||
|
||||
if (likely(user_mode(child_ptregs))) {
|
||||
if ((clone_flags & CLONE_SETTLS) && !IS_IA32_PROCESS(regs))
|
||||
child_ptregs->r13 = regs->r16; /* see sys_clone2() in entry.S */
|
||||
if (user_stack_base) {
|
||||
child_ptregs->r12 = user_stack_base + user_stack_size - 16;
|
||||
child_ptregs->ar_bspstore = user_stack_base;
|
||||
child_ptregs->ar_rnat = 0;
|
||||
child_ptregs->loadrs = 0;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Note: we simply preserve the relative position of
|
||||
* the stack pointer here. There is no need to
|
||||
* allocate a scratch area here, since that will have
|
||||
* been taken care of by the caller of sys_clone()
|
||||
* already.
|
||||
*/
|
||||
child_ptregs->r12 = (unsigned long) child_ptregs - 16; /* kernel sp */
|
||||
child_ptregs->r13 = (unsigned long) p; /* set `current' pointer */
|
||||
}
|
||||
child_stack->ar_bspstore = child_rbs + rbs_size;
|
||||
if (IS_IA32_PROCESS(regs))
|
||||
child_stack->b0 = (unsigned long) &ia32_ret_from_clone;
|
||||
else
|
||||
child_stack->b0 = (unsigned long) &ia64_ret_from_clone;
|
||||
|
||||
/* copy parts of thread_struct: */
|
||||
p->thread.ksp = (unsigned long) child_stack - 16;
|
||||
|
||||
/* stop some PSR bits from being inherited.
|
||||
* the psr.up/psr.pp bits must be cleared on fork but inherited on execve()
|
||||
* therefore we must specify them explicitly here and not include them in
|
||||
* IA64_PSR_BITS_TO_CLEAR.
|
||||
*/
|
||||
child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET)
|
||||
& ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP));
|
||||
|
||||
/*
|
||||
* NOTE: The calling convention considers all floating point
|
||||
* registers in the high partition (fph) to be scratch. Since
|
||||
* the only way to get to this point is through a system call,
|
||||
* we know that the values in fph are all dead. Hence, there
|
||||
* is no need to inherit the fph state from the parent to the
|
||||
* child and all we have to do is to make sure that
|
||||
* IA64_THREAD_FPH_VALID is cleared in the child.
|
||||
*
|
||||
* XXX We could push this optimization a bit further by
|
||||
* clearing IA64_THREAD_FPH_VALID on ANY system call.
|
||||
* However, it's not clear this is worth doing. Also, it
|
||||
* would be a slight deviation from the normal Linux system
|
||||
* call behavior where scratch registers are preserved across
|
||||
* system calls (unless used by the system call itself).
|
||||
*/
|
||||
# define THREAD_FLAGS_TO_CLEAR (IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID \
|
||||
| IA64_THREAD_PM_VALID)
|
||||
# define THREAD_FLAGS_TO_SET 0
|
||||
p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR)
|
||||
| THREAD_FLAGS_TO_SET);
|
||||
ia64_drop_fpu(p); /* don't pick up stale state from a CPU's fph */
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
/*
|
||||
* If we're cloning an IA32 task then save the IA32 extra
|
||||
* state from the current task to the new task
|
||||
*/
|
||||
if (IS_IA32_PROCESS(ia64_task_regs(current))) {
|
||||
ia32_save_state(p);
|
||||
if (clone_flags & CLONE_SETTLS)
|
||||
retval = ia32_clone_tls(p, child_ptregs);
|
||||
|
||||
/* Copy partially mapped page list */
|
||||
if (!retval)
|
||||
retval = ia32_copy_partial_page_list(p, clone_flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PERFMON
|
||||
if (current->thread.pfm_context)
|
||||
pfm_inherit(p, child_ptregs);
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
do_copy_task_regs (struct task_struct *task, struct unw_frame_info *info, void *arg)
|
||||
{
|
||||
unsigned long mask, sp, nat_bits = 0, ip, ar_rnat, urbs_end, cfm;
|
||||
elf_greg_t *dst = arg;
|
||||
struct pt_regs *pt;
|
||||
char nat;
|
||||
int i;
|
||||
|
||||
memset(dst, 0, sizeof(elf_gregset_t)); /* don't leak any kernel bits to user-level */
|
||||
|
||||
if (unw_unwind_to_user(info) < 0)
|
||||
return;
|
||||
|
||||
unw_get_sp(info, &sp);
|
||||
pt = (struct pt_regs *) (sp + 16);
|
||||
|
||||
urbs_end = ia64_get_user_rbs_end(task, pt, &cfm);
|
||||
|
||||
if (ia64_sync_user_rbs(task, info->sw, pt->ar_bspstore, urbs_end) < 0)
|
||||
return;
|
||||
|
||||
ia64_peek(task, info->sw, urbs_end, (long) ia64_rse_rnat_addr((long *) urbs_end),
|
||||
&ar_rnat);
|
||||
|
||||
/*
|
||||
* coredump format:
|
||||
* r0-r31
|
||||
* NaT bits (for r0-r31; bit N == 1 iff rN is a NaT)
|
||||
* predicate registers (p0-p63)
|
||||
* b0-b7
|
||||
* ip cfm user-mask
|
||||
* ar.rsc ar.bsp ar.bspstore ar.rnat
|
||||
* ar.ccv ar.unat ar.fpsr ar.pfs ar.lc ar.ec
|
||||
*/
|
||||
|
||||
/* r0 is zero */
|
||||
for (i = 1, mask = (1UL << i); i < 32; ++i) {
|
||||
unw_get_gr(info, i, &dst[i], &nat);
|
||||
if (nat)
|
||||
nat_bits |= mask;
|
||||
mask <<= 1;
|
||||
}
|
||||
dst[32] = nat_bits;
|
||||
unw_get_pr(info, &dst[33]);
|
||||
|
||||
for (i = 0; i < 8; ++i)
|
||||
unw_get_br(info, i, &dst[34 + i]);
|
||||
|
||||
unw_get_rp(info, &ip);
|
||||
dst[42] = ip + ia64_psr(pt)->ri;
|
||||
dst[43] = cfm;
|
||||
dst[44] = pt->cr_ipsr & IA64_PSR_UM;
|
||||
|
||||
unw_get_ar(info, UNW_AR_RSC, &dst[45]);
|
||||
/*
|
||||
* For bsp and bspstore, unw_get_ar() would return the kernel
|
||||
* addresses, but we need the user-level addresses instead:
|
||||
*/
|
||||
dst[46] = urbs_end; /* note: by convention PT_AR_BSP points to the end of the urbs! */
|
||||
dst[47] = pt->ar_bspstore;
|
||||
dst[48] = ar_rnat;
|
||||
unw_get_ar(info, UNW_AR_CCV, &dst[49]);
|
||||
unw_get_ar(info, UNW_AR_UNAT, &dst[50]);
|
||||
unw_get_ar(info, UNW_AR_FPSR, &dst[51]);
|
||||
dst[52] = pt->ar_pfs; /* UNW_AR_PFS is == to pt->cr_ifs for interrupt frames */
|
||||
unw_get_ar(info, UNW_AR_LC, &dst[53]);
|
||||
unw_get_ar(info, UNW_AR_EC, &dst[54]);
|
||||
unw_get_ar(info, UNW_AR_CSD, &dst[55]);
|
||||
unw_get_ar(info, UNW_AR_SSD, &dst[56]);
|
||||
}
|
||||
|
||||
void
|
||||
do_dump_task_fpu (struct task_struct *task, struct unw_frame_info *info, void *arg)
|
||||
{
|
||||
elf_fpreg_t *dst = arg;
|
||||
int i;
|
||||
|
||||
memset(dst, 0, sizeof(elf_fpregset_t)); /* don't leak any "random" bits */
|
||||
|
||||
if (unw_unwind_to_user(info) < 0)
|
||||
return;
|
||||
|
||||
/* f0 is 0.0, f1 is 1.0 */
|
||||
|
||||
for (i = 2; i < 32; ++i)
|
||||
unw_get_fr(info, i, dst + i);
|
||||
|
||||
ia64_flush_fph(task);
|
||||
if ((task->thread.flags & IA64_THREAD_FPH_VALID) != 0)
|
||||
memcpy(dst + 32, task->thread.fph, 96*16);
|
||||
}
|
||||
|
||||
void
|
||||
do_copy_regs (struct unw_frame_info *info, void *arg)
|
||||
{
|
||||
do_copy_task_regs(current, info, arg);
|
||||
}
|
||||
|
||||
void
|
||||
do_dump_fpu (struct unw_frame_info *info, void *arg)
|
||||
{
|
||||
do_dump_task_fpu(current, info, arg);
|
||||
}
|
||||
|
||||
int
|
||||
dump_task_regs(struct task_struct *task, elf_gregset_t *regs)
|
||||
{
|
||||
struct unw_frame_info tcore_info;
|
||||
|
||||
if (current == task) {
|
||||
unw_init_running(do_copy_regs, regs);
|
||||
} else {
|
||||
memset(&tcore_info, 0, sizeof(tcore_info));
|
||||
unw_init_from_blocked_task(&tcore_info, task);
|
||||
do_copy_task_regs(task, &tcore_info, regs);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
ia64_elf_core_copy_regs (struct pt_regs *pt, elf_gregset_t dst)
|
||||
{
|
||||
unw_init_running(do_copy_regs, dst);
|
||||
}
|
||||
|
||||
int
|
||||
dump_task_fpu (struct task_struct *task, elf_fpregset_t *dst)
|
||||
{
|
||||
struct unw_frame_info tcore_info;
|
||||
|
||||
if (current == task) {
|
||||
unw_init_running(do_dump_fpu, dst);
|
||||
} else {
|
||||
memset(&tcore_info, 0, sizeof(tcore_info));
|
||||
unw_init_from_blocked_task(&tcore_info, task);
|
||||
do_dump_task_fpu(task, &tcore_info, dst);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
dump_fpu (struct pt_regs *pt, elf_fpregset_t dst)
|
||||
{
|
||||
unw_init_running(do_dump_fpu, dst);
|
||||
return 1; /* f0-f31 are always valid so we always return 1 */
|
||||
}
|
||||
|
||||
long
|
||||
sys_execve (char __user *filename, char __user * __user *argv, char __user * __user *envp,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
char *fname;
|
||||
int error;
|
||||
|
||||
fname = getname(filename);
|
||||
error = PTR_ERR(fname);
|
||||
if (IS_ERR(fname))
|
||||
goto out;
|
||||
error = do_execve(fname, argv, envp, regs);
|
||||
putname(fname);
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
|
||||
pid_t
|
||||
kernel_thread (int (*fn)(void *), void *arg, unsigned long flags)
|
||||
{
|
||||
extern void start_kernel_thread (void);
|
||||
unsigned long *helper_fptr = (unsigned long *) &start_kernel_thread;
|
||||
struct {
|
||||
struct switch_stack sw;
|
||||
struct pt_regs pt;
|
||||
} regs;
|
||||
|
||||
memset(®s, 0, sizeof(regs));
|
||||
regs.pt.cr_iip = helper_fptr[0]; /* set entry point (IP) */
|
||||
regs.pt.r1 = helper_fptr[1]; /* set GP */
|
||||
regs.pt.r9 = (unsigned long) fn; /* 1st argument */
|
||||
regs.pt.r11 = (unsigned long) arg; /* 2nd argument */
|
||||
/* Preserve PSR bits, except for bits 32-34 and 37-45, which we can't read. */
|
||||
regs.pt.cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN;
|
||||
regs.pt.cr_ifs = 1UL << 63; /* mark as valid, empty frame */
|
||||
regs.sw.ar_fpsr = regs.pt.ar_fpsr = ia64_getreg(_IA64_REG_AR_FPSR);
|
||||
regs.sw.ar_bspstore = (unsigned long) current + IA64_RBS_OFFSET;
|
||||
regs.sw.pr = (1 << PRED_KERNEL_STACK);
|
||||
return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s.pt, 0, NULL, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(kernel_thread);
|
||||
|
||||
/* This gets called from kernel_thread() via ia64_invoke_thread_helper(). */
|
||||
int
|
||||
kernel_thread_helper (int (*fn)(void *), void *arg)
|
||||
{
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
if (IS_IA32_PROCESS(ia64_task_regs(current))) {
|
||||
/* A kernel thread is always a 64-bit process. */
|
||||
current->thread.map_base = DEFAULT_MAP_BASE;
|
||||
current->thread.task_size = DEFAULT_TASK_SIZE;
|
||||
ia64_set_kr(IA64_KR_IO_BASE, current->thread.old_iob);
|
||||
ia64_set_kr(IA64_KR_TSSD, current->thread.old_k1);
|
||||
}
|
||||
#endif
|
||||
return (*fn)(arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush thread state. This is called when a thread does an execve().
|
||||
*/
|
||||
void
|
||||
flush_thread (void)
|
||||
{
|
||||
/*
|
||||
* Remove function-return probe instances associated with this task
|
||||
* and put them back on the free list. Do not insert an exit probe for
|
||||
* this function, it will be disabled by kprobe_flush_task if you do.
|
||||
*/
|
||||
kprobe_flush_task(current);
|
||||
|
||||
/* drop floating-point and debug-register state if it exists: */
|
||||
current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID);
|
||||
ia64_drop_fpu(current);
|
||||
if (IS_IA32_PROCESS(ia64_task_regs(current)))
|
||||
ia32_drop_partial_page_list(current);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up state associated with current thread. This is called when
|
||||
* the thread calls exit().
|
||||
*/
|
||||
void
|
||||
exit_thread (void)
|
||||
{
|
||||
|
||||
/*
|
||||
* Remove function-return probe instances associated with this task
|
||||
* and put them back on the free list. Do not insert an exit probe for
|
||||
* this function, it will be disabled by kprobe_flush_task if you do.
|
||||
*/
|
||||
kprobe_flush_task(current);
|
||||
|
||||
ia64_drop_fpu(current);
|
||||
#ifdef CONFIG_PERFMON
|
||||
/* if needed, stop monitoring and flush state to perfmon context */
|
||||
if (current->thread.pfm_context)
|
||||
pfm_exit_thread(current);
|
||||
|
||||
/* free debug register resources */
|
||||
if (current->thread.flags & IA64_THREAD_DBG_VALID)
|
||||
pfm_release_debug_registers(current);
|
||||
#endif
|
||||
if (IS_IA32_PROCESS(ia64_task_regs(current)))
|
||||
ia32_drop_partial_page_list(current);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
get_wchan (struct task_struct *p)
|
||||
{
|
||||
struct unw_frame_info info;
|
||||
unsigned long ip;
|
||||
int count = 0;
|
||||
|
||||
/*
|
||||
* Note: p may not be a blocked task (it could be current or
|
||||
* another process running on some other CPU. Rather than
|
||||
* trying to determine if p is really blocked, we just assume
|
||||
* it's blocked and rely on the unwind routines to fail
|
||||
* gracefully if the process wasn't really blocked after all.
|
||||
* --davidm 99/12/15
|
||||
*/
|
||||
unw_init_from_blocked_task(&info, p);
|
||||
do {
|
||||
if (unw_unwind(&info) < 0)
|
||||
return 0;
|
||||
unw_get_ip(&info, &ip);
|
||||
if (!in_sched_functions(ip))
|
||||
return ip;
|
||||
} while (count++ < 16);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
cpu_halt (void)
|
||||
{
|
||||
pal_power_mgmt_info_u_t power_info[8];
|
||||
unsigned long min_power;
|
||||
int i, min_power_state;
|
||||
|
||||
if (ia64_pal_halt_info(power_info) != 0)
|
||||
return;
|
||||
|
||||
min_power_state = 0;
|
||||
min_power = power_info[0].pal_power_mgmt_info_s.power_consumption;
|
||||
for (i = 1; i < 8; ++i)
|
||||
if (power_info[i].pal_power_mgmt_info_s.im
|
||||
&& power_info[i].pal_power_mgmt_info_s.power_consumption < min_power) {
|
||||
min_power = power_info[i].pal_power_mgmt_info_s.power_consumption;
|
||||
min_power_state = i;
|
||||
}
|
||||
|
||||
while (1)
|
||||
ia64_pal_halt(min_power_state);
|
||||
}
|
||||
|
||||
void
|
||||
machine_restart (char *restart_cmd)
|
||||
{
|
||||
(*efi.reset_system)(EFI_RESET_WARM, 0, 0, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
machine_halt (void)
|
||||
{
|
||||
cpu_halt();
|
||||
}
|
||||
|
||||
void
|
||||
machine_power_off (void)
|
||||
{
|
||||
if (pm_power_off)
|
||||
pm_power_off();
|
||||
machine_halt();
|
||||
}
|
||||
#endif // !XEN
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,459 @@
|
||||
/*
|
||||
* Copyright (C) 2000 Hewlett-Packard Co
|
||||
* Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
*
|
||||
* Generic IA-64 unwind info decoder.
|
||||
*
|
||||
* This file is used both by the Linux kernel and objdump. Please keep
|
||||
* the two copies of this file in sync.
|
||||
*
|
||||
* You need to customize the decoder by defining the following
|
||||
* macros/constants before including this file:
|
||||
*
|
||||
* Types:
|
||||
* unw_word Unsigned integer type with at least 64 bits
|
||||
*
|
||||
* Register names:
|
||||
* UNW_REG_BSP
|
||||
* UNW_REG_BSPSTORE
|
||||
* UNW_REG_FPSR
|
||||
* UNW_REG_LC
|
||||
* UNW_REG_PFS
|
||||
* UNW_REG_PR
|
||||
* UNW_REG_RNAT
|
||||
* UNW_REG_PSP
|
||||
* UNW_REG_RP
|
||||
* UNW_REG_UNAT
|
||||
*
|
||||
* Decoder action macros:
|
||||
* UNW_DEC_BAD_CODE(code)
|
||||
* UNW_DEC_ABI(fmt,abi,context,arg)
|
||||
* UNW_DEC_BR_GR(fmt,brmask,gr,arg)
|
||||
* UNW_DEC_BR_MEM(fmt,brmask,arg)
|
||||
* UNW_DEC_COPY_STATE(fmt,label,arg)
|
||||
* UNW_DEC_EPILOGUE(fmt,t,ecount,arg)
|
||||
* UNW_DEC_FRGR_MEM(fmt,grmask,frmask,arg)
|
||||
* UNW_DEC_FR_MEM(fmt,frmask,arg)
|
||||
* UNW_DEC_GR_GR(fmt,grmask,gr,arg)
|
||||
* UNW_DEC_GR_MEM(fmt,grmask,arg)
|
||||
* UNW_DEC_LABEL_STATE(fmt,label,arg)
|
||||
* UNW_DEC_MEM_STACK_F(fmt,t,size,arg)
|
||||
* UNW_DEC_MEM_STACK_V(fmt,t,arg)
|
||||
* UNW_DEC_PRIUNAT_GR(fmt,r,arg)
|
||||
* UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg)
|
||||
* UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg)
|
||||
* UNW_DEC_PRIUNAT_WHEN_PSPREL(fmt,pspoff,arg)
|
||||
* UNW_DEC_PRIUNAT_WHEN_SPREL(fmt,spoff,arg)
|
||||
* UNW_DEC_PROLOGUE(fmt,body,rlen,arg)
|
||||
* UNW_DEC_PROLOGUE_GR(fmt,rlen,mask,grsave,arg)
|
||||
* UNW_DEC_REG_PSPREL(fmt,reg,pspoff,arg)
|
||||
* UNW_DEC_REG_REG(fmt,src,dst,arg)
|
||||
* UNW_DEC_REG_SPREL(fmt,reg,spoff,arg)
|
||||
* UNW_DEC_REG_WHEN(fmt,reg,t,arg)
|
||||
* UNW_DEC_RESTORE(fmt,t,abreg,arg)
|
||||
* UNW_DEC_RESTORE_P(fmt,qp,t,abreg,arg)
|
||||
* UNW_DEC_SPILL_BASE(fmt,pspoff,arg)
|
||||
* UNW_DEC_SPILL_MASK(fmt,imaskp,arg)
|
||||
* UNW_DEC_SPILL_PSPREL(fmt,t,abreg,pspoff,arg)
|
||||
* UNW_DEC_SPILL_PSPREL_P(fmt,qp,t,abreg,pspoff,arg)
|
||||
* UNW_DEC_SPILL_REG(fmt,t,abreg,x,ytreg,arg)
|
||||
* UNW_DEC_SPILL_REG_P(fmt,qp,t,abreg,x,ytreg,arg)
|
||||
* UNW_DEC_SPILL_SPREL(fmt,t,abreg,spoff,arg)
|
||||
* UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg)
|
||||
*/
|
||||
|
||||
static unw_word
|
||||
unw_decode_uleb128 (unsigned char **dpp)
|
||||
{
|
||||
unsigned shift = 0;
|
||||
unw_word byte, result = 0;
|
||||
unsigned char *bp = *dpp;
|
||||
|
||||
while (1)
|
||||
{
|
||||
byte = *bp++;
|
||||
result |= (byte & 0x7f) << shift;
|
||||
if ((byte & 0x80) == 0)
|
||||
break;
|
||||
shift += 7;
|
||||
}
|
||||
*dpp = bp;
|
||||
return result;
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
unw_decode_x1 (unsigned char *dp, unsigned char code, void *arg)
|
||||
{
|
||||
unsigned char byte1, abreg;
|
||||
unw_word t, off;
|
||||
|
||||
byte1 = *dp++;
|
||||
t = unw_decode_uleb128 (&dp);
|
||||
off = unw_decode_uleb128 (&dp);
|
||||
abreg = (byte1 & 0x7f);
|
||||
if (byte1 & 0x80)
|
||||
UNW_DEC_SPILL_SPREL(X1, t, abreg, off, arg);
|
||||
else
|
||||
UNW_DEC_SPILL_PSPREL(X1, t, abreg, off, arg);
|
||||
return dp;
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
unw_decode_x2 (unsigned char *dp, unsigned char code, void *arg)
|
||||
{
|
||||
unsigned char byte1, byte2, abreg, x, ytreg;
|
||||
unw_word t;
|
||||
|
||||
byte1 = *dp++; byte2 = *dp++;
|
||||
t = unw_decode_uleb128 (&dp);
|
||||
abreg = (byte1 & 0x7f);
|
||||
ytreg = byte2;
|
||||
x = (byte1 >> 7) & 1;
|
||||
if ((byte1 & 0x80) == 0 && ytreg == 0)
|
||||
UNW_DEC_RESTORE(X2, t, abreg, arg);
|
||||
else
|
||||
UNW_DEC_SPILL_REG(X2, t, abreg, x, ytreg, arg);
|
||||
return dp;
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
unw_decode_x3 (unsigned char *dp, unsigned char code, void *arg)
|
||||
{
|
||||
unsigned char byte1, byte2, abreg, qp;
|
||||
unw_word t, off;
|
||||
|
||||
byte1 = *dp++; byte2 = *dp++;
|
||||
t = unw_decode_uleb128 (&dp);
|
||||
off = unw_decode_uleb128 (&dp);
|
||||
|
||||
qp = (byte1 & 0x3f);
|
||||
abreg = (byte2 & 0x7f);
|
||||
|
||||
if (byte1 & 0x80)
|
||||
UNW_DEC_SPILL_SPREL_P(X3, qp, t, abreg, off, arg);
|
||||
else
|
||||
UNW_DEC_SPILL_PSPREL_P(X3, qp, t, abreg, off, arg);
|
||||
return dp;
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
unw_decode_x4 (unsigned char *dp, unsigned char code, void *arg)
|
||||
{
|
||||
unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg;
|
||||
unw_word t;
|
||||
|
||||
byte1 = *dp++; byte2 = *dp++; byte3 = *dp++;
|
||||
t = unw_decode_uleb128 (&dp);
|
||||
|
||||
qp = (byte1 & 0x3f);
|
||||
abreg = (byte2 & 0x7f);
|
||||
x = (byte2 >> 7) & 1;
|
||||
ytreg = byte3;
|
||||
|
||||
if ((byte2 & 0x80) == 0 && byte3 == 0)
|
||||
UNW_DEC_RESTORE_P(X4, qp, t, abreg, arg);
|
||||
else
|
||||
UNW_DEC_SPILL_REG_P(X4, qp, t, abreg, x, ytreg, arg);
|
||||
return dp;
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
unw_decode_r1 (unsigned char *dp, unsigned char code, void *arg)
|
||||
{
|
||||
int body = (code & 0x20) != 0;
|
||||
unw_word rlen;
|
||||
|
||||
rlen = (code & 0x1f);
|
||||
UNW_DEC_PROLOGUE(R1, body, rlen, arg);
|
||||
return dp;
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
unw_decode_r2 (unsigned char *dp, unsigned char code, void *arg)
|
||||
{
|
||||
unsigned char byte1, mask, grsave;
|
||||
unw_word rlen;
|
||||
|
||||
byte1 = *dp++;
|
||||
|
||||
mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
|
||||
grsave = (byte1 & 0x7f);
|
||||
rlen = unw_decode_uleb128 (&dp);
|
||||
UNW_DEC_PROLOGUE_GR(R2, rlen, mask, grsave, arg);
|
||||
return dp;
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
unw_decode_r3 (unsigned char *dp, unsigned char code, void *arg)
|
||||
{
|
||||
unw_word rlen;
|
||||
|
||||
rlen = unw_decode_uleb128 (&dp);
|
||||
UNW_DEC_PROLOGUE(R3, ((code & 0x3) == 1), rlen, arg);
|
||||
return dp;
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
unw_decode_p1 (unsigned char *dp, unsigned char code, void *arg)
|
||||
{
|
||||
unsigned char brmask = (code & 0x1f);
|
||||
|
||||
UNW_DEC_BR_MEM(P1, brmask, arg);
|
||||
return dp;
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
unw_decode_p2_p5 (unsigned char *dp, unsigned char code, void *arg)
|
||||
{
|
||||
if ((code & 0x10) == 0)
|
||||
{
|
||||
unsigned char byte1 = *dp++;
|
||||
|
||||
UNW_DEC_BR_GR(P2, ((code & 0xf) << 1) | ((byte1 >> 7) & 1),
|
||||
(byte1 & 0x7f), arg);
|
||||
}
|
||||
else if ((code & 0x08) == 0)
|
||||
{
|
||||
unsigned char byte1 = *dp++, r, dst;
|
||||
|
||||
r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
|
||||
dst = (byte1 & 0x7f);
|
||||
switch (r)
|
||||
{
|
||||
case 0: UNW_DEC_REG_GR(P3, UNW_REG_PSP, dst, arg); break;
|
||||
case 1: UNW_DEC_REG_GR(P3, UNW_REG_RP, dst, arg); break;
|
||||
case 2: UNW_DEC_REG_GR(P3, UNW_REG_PFS, dst, arg); break;
|
||||
case 3: UNW_DEC_REG_GR(P3, UNW_REG_PR, dst, arg); break;
|
||||
case 4: UNW_DEC_REG_GR(P3, UNW_REG_UNAT, dst, arg); break;
|
||||
case 5: UNW_DEC_REG_GR(P3, UNW_REG_LC, dst, arg); break;
|
||||
case 6: UNW_DEC_RP_BR(P3, dst, arg); break;
|
||||
case 7: UNW_DEC_REG_GR(P3, UNW_REG_RNAT, dst, arg); break;
|
||||
case 8: UNW_DEC_REG_GR(P3, UNW_REG_BSP, dst, arg); break;
|
||||
case 9: UNW_DEC_REG_GR(P3, UNW_REG_BSPSTORE, dst, arg); break;
|
||||
case 10: UNW_DEC_REG_GR(P3, UNW_REG_FPSR, dst, arg); break;
|
||||
case 11: UNW_DEC_PRIUNAT_GR(P3, dst, arg); break;
|
||||
default: UNW_DEC_BAD_CODE(r); break;
|
||||
}
|
||||
}
|
||||
else if ((code & 0x7) == 0)
|
||||
UNW_DEC_SPILL_MASK(P4, dp, arg);
|
||||
else if ((code & 0x7) == 1)
|
||||
{
|
||||
unw_word grmask, frmask, byte1, byte2, byte3;
|
||||
|
||||
byte1 = *dp++; byte2 = *dp++; byte3 = *dp++;
|
||||
grmask = ((byte1 >> 4) & 0xf);
|
||||
frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3;
|
||||
UNW_DEC_FRGR_MEM(P5, grmask, frmask, arg);
|
||||
}
|
||||
else
|
||||
UNW_DEC_BAD_CODE(code);
|
||||
return dp;
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
unw_decode_p6 (unsigned char *dp, unsigned char code, void *arg)
|
||||
{
|
||||
int gregs = (code & 0x10) != 0;
|
||||
unsigned char mask = (code & 0x0f);
|
||||
|
||||
if (gregs)
|
||||
UNW_DEC_GR_MEM(P6, mask, arg);
|
||||
else
|
||||
UNW_DEC_FR_MEM(P6, mask, arg);
|
||||
return dp;
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
unw_decode_p7_p10 (unsigned char *dp, unsigned char code, void *arg)
|
||||
{
|
||||
unsigned char r, byte1, byte2;
|
||||
unw_word t, size;
|
||||
|
||||
if ((code & 0x10) == 0)
|
||||
{
|
||||
r = (code & 0xf);
|
||||
t = unw_decode_uleb128 (&dp);
|
||||
switch (r)
|
||||
{
|
||||
case 0:
|
||||
size = unw_decode_uleb128 (&dp);
|
||||
UNW_DEC_MEM_STACK_F(P7, t, size, arg);
|
||||
break;
|
||||
|
||||
case 1: UNW_DEC_MEM_STACK_V(P7, t, arg); break;
|
||||
case 2: UNW_DEC_SPILL_BASE(P7, t, arg); break;
|
||||
case 3: UNW_DEC_REG_SPREL(P7, UNW_REG_PSP, t, arg); break;
|
||||
case 4: UNW_DEC_REG_WHEN(P7, UNW_REG_RP, t, arg); break;
|
||||
case 5: UNW_DEC_REG_PSPREL(P7, UNW_REG_RP, t, arg); break;
|
||||
case 6: UNW_DEC_REG_WHEN(P7, UNW_REG_PFS, t, arg); break;
|
||||
case 7: UNW_DEC_REG_PSPREL(P7, UNW_REG_PFS, t, arg); break;
|
||||
case 8: UNW_DEC_REG_WHEN(P7, UNW_REG_PR, t, arg); break;
|
||||
case 9: UNW_DEC_REG_PSPREL(P7, UNW_REG_PR, t, arg); break;
|
||||
case 10: UNW_DEC_REG_WHEN(P7, UNW_REG_LC, t, arg); break;
|
||||
case 11: UNW_DEC_REG_PSPREL(P7, UNW_REG_LC, t, arg); break;
|
||||
case 12: UNW_DEC_REG_WHEN(P7, UNW_REG_UNAT, t, arg); break;
|
||||
case 13: UNW_DEC_REG_PSPREL(P7, UNW_REG_UNAT, t, arg); break;
|
||||
case 14: UNW_DEC_REG_WHEN(P7, UNW_REG_FPSR, t, arg); break;
|
||||
case 15: UNW_DEC_REG_PSPREL(P7, UNW_REG_FPSR, t, arg); break;
|
||||
default: UNW_DEC_BAD_CODE(r); break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (code & 0xf)
|
||||
{
|
||||
case 0x0: /* p8 */
|
||||
{
|
||||
r = *dp++;
|
||||
t = unw_decode_uleb128 (&dp);
|
||||
switch (r)
|
||||
{
|
||||
case 1: UNW_DEC_REG_SPREL(P8, UNW_REG_RP, t, arg); break;
|
||||
case 2: UNW_DEC_REG_SPREL(P8, UNW_REG_PFS, t, arg); break;
|
||||
case 3: UNW_DEC_REG_SPREL(P8, UNW_REG_PR, t, arg); break;
|
||||
case 4: UNW_DEC_REG_SPREL(P8, UNW_REG_LC, t, arg); break;
|
||||
case 5: UNW_DEC_REG_SPREL(P8, UNW_REG_UNAT, t, arg); break;
|
||||
case 6: UNW_DEC_REG_SPREL(P8, UNW_REG_FPSR, t, arg); break;
|
||||
case 7: UNW_DEC_REG_WHEN(P8, UNW_REG_BSP, t, arg); break;
|
||||
case 8: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSP, t, arg); break;
|
||||
case 9: UNW_DEC_REG_SPREL(P8, UNW_REG_BSP, t, arg); break;
|
||||
case 10: UNW_DEC_REG_WHEN(P8, UNW_REG_BSPSTORE, t, arg); break;
|
||||
case 11: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSPSTORE, t, arg); break;
|
||||
case 12: UNW_DEC_REG_SPREL(P8, UNW_REG_BSPSTORE, t, arg); break;
|
||||
case 13: UNW_DEC_REG_WHEN(P8, UNW_REG_RNAT, t, arg); break;
|
||||
case 14: UNW_DEC_REG_PSPREL(P8, UNW_REG_RNAT, t, arg); break;
|
||||
case 15: UNW_DEC_REG_SPREL(P8, UNW_REG_RNAT, t, arg); break;
|
||||
case 16: UNW_DEC_PRIUNAT_WHEN_GR(P8, t, arg); break;
|
||||
case 17: UNW_DEC_PRIUNAT_PSPREL(P8, t, arg); break;
|
||||
case 18: UNW_DEC_PRIUNAT_SPREL(P8, t, arg); break;
|
||||
case 19: UNW_DEC_PRIUNAT_WHEN_MEM(P8, t, arg); break;
|
||||
default: UNW_DEC_BAD_CODE(r); break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x1:
|
||||
byte1 = *dp++; byte2 = *dp++;
|
||||
UNW_DEC_GR_GR(P9, (byte1 & 0xf), (byte2 & 0x7f), arg);
|
||||
break;
|
||||
|
||||
case 0xf: /* p10 */
|
||||
byte1 = *dp++; byte2 = *dp++;
|
||||
UNW_DEC_ABI(P10, byte1, byte2, arg);
|
||||
break;
|
||||
|
||||
case 0x9:
|
||||
return unw_decode_x1 (dp, code, arg);
|
||||
|
||||
case 0xa:
|
||||
return unw_decode_x2 (dp, code, arg);
|
||||
|
||||
case 0xb:
|
||||
return unw_decode_x3 (dp, code, arg);
|
||||
|
||||
case 0xc:
|
||||
return unw_decode_x4 (dp, code, arg);
|
||||
|
||||
default:
|
||||
UNW_DEC_BAD_CODE(code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
unw_decode_b1 (unsigned char *dp, unsigned char code, void *arg)
|
||||
{
|
||||
unw_word label = (code & 0x1f);
|
||||
|
||||
if ((code & 0x20) != 0)
|
||||
UNW_DEC_COPY_STATE(B1, label, arg);
|
||||
else
|
||||
UNW_DEC_LABEL_STATE(B1, label, arg);
|
||||
return dp;
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
unw_decode_b2 (unsigned char *dp, unsigned char code, void *arg)
|
||||
{
|
||||
unw_word t;
|
||||
|
||||
t = unw_decode_uleb128 (&dp);
|
||||
UNW_DEC_EPILOGUE(B2, t, (code & 0x1f), arg);
|
||||
return dp;
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
unw_decode_b3_x4 (unsigned char *dp, unsigned char code, void *arg)
|
||||
{
|
||||
unw_word t, ecount, label;
|
||||
|
||||
if ((code & 0x10) == 0)
|
||||
{
|
||||
t = unw_decode_uleb128 (&dp);
|
||||
ecount = unw_decode_uleb128 (&dp);
|
||||
UNW_DEC_EPILOGUE(B3, t, ecount, arg);
|
||||
}
|
||||
else if ((code & 0x07) == 0)
|
||||
{
|
||||
label = unw_decode_uleb128 (&dp);
|
||||
if ((code & 0x08) != 0)
|
||||
UNW_DEC_COPY_STATE(B4, label, arg);
|
||||
else
|
||||
UNW_DEC_LABEL_STATE(B4, label, arg);
|
||||
}
|
||||
else
|
||||
switch (code & 0x7)
|
||||
{
|
||||
case 1: return unw_decode_x1 (dp, code, arg);
|
||||
case 2: return unw_decode_x2 (dp, code, arg);
|
||||
case 3: return unw_decode_x3 (dp, code, arg);
|
||||
case 4: return unw_decode_x4 (dp, code, arg);
|
||||
default: UNW_DEC_BAD_CODE(code); break;
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
typedef unsigned char *(*unw_decoder) (unsigned char *, unsigned char, void *);
|
||||
|
||||
static unw_decoder unw_decode_table[2][8] =
|
||||
{
|
||||
/* prologue table: */
|
||||
{
|
||||
unw_decode_r1, /* 0 */
|
||||
unw_decode_r1,
|
||||
unw_decode_r2,
|
||||
unw_decode_r3,
|
||||
unw_decode_p1, /* 4 */
|
||||
unw_decode_p2_p5,
|
||||
unw_decode_p6,
|
||||
unw_decode_p7_p10
|
||||
},
|
||||
{
|
||||
unw_decode_r1, /* 0 */
|
||||
unw_decode_r1,
|
||||
unw_decode_r2,
|
||||
unw_decode_r3,
|
||||
unw_decode_b1, /* 4 */
|
||||
unw_decode_b1,
|
||||
unw_decode_b2,
|
||||
unw_decode_b3_x4
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Decode one descriptor and return address of next descriptor.
|
||||
*/
|
||||
static inline unsigned char *
|
||||
unw_decode (unsigned char *dp, int inside_body, void *arg)
|
||||
{
|
||||
unw_decoder decoder;
|
||||
unsigned char code;
|
||||
|
||||
code = *dp++;
|
||||
decoder = unw_decode_table[inside_body][code >> 5];
|
||||
dp = (*decoder) (dp, code, arg);
|
||||
return dp;
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (C) 2000, 2002-2003 Hewlett-Packard Co
|
||||
* David Mosberger-Tang <davidm@hpl.hp.com>
|
||||
*
|
||||
* Kernel unwind support.
|
||||
*/
|
||||
|
||||
#define UNW_VER(x) ((x) >> 48)
|
||||
#define UNW_FLAG_MASK 0x0000ffff00000000
|
||||
#define UNW_FLAG_OSMASK 0x0000f00000000000
|
||||
#define UNW_FLAG_EHANDLER(x) ((x) & 0x0000000100000000L)
|
||||
#define UNW_FLAG_UHANDLER(x) ((x) & 0x0000000200000000L)
|
||||
#define UNW_LENGTH(x) ((x) & 0x00000000ffffffffL)
|
||||
|
||||
enum unw_register_index {
|
||||
/* primary unat: */
|
||||
UNW_REG_PRI_UNAT_GR,
|
||||
UNW_REG_PRI_UNAT_MEM,
|
||||
|
||||
/* register stack */
|
||||
UNW_REG_BSP, /* register stack pointer */
|
||||
UNW_REG_BSPSTORE,
|
||||
UNW_REG_PFS, /* previous function state */
|
||||
UNW_REG_RNAT,
|
||||
/* memory stack */
|
||||
UNW_REG_PSP, /* previous memory stack pointer */
|
||||
/* return pointer: */
|
||||
UNW_REG_RP,
|
||||
|
||||
/* preserved registers: */
|
||||
UNW_REG_R4, UNW_REG_R5, UNW_REG_R6, UNW_REG_R7,
|
||||
UNW_REG_UNAT, UNW_REG_PR, UNW_REG_LC, UNW_REG_FPSR,
|
||||
UNW_REG_B1, UNW_REG_B2, UNW_REG_B3, UNW_REG_B4, UNW_REG_B5,
|
||||
UNW_REG_F2, UNW_REG_F3, UNW_REG_F4, UNW_REG_F5,
|
||||
UNW_REG_F16, UNW_REG_F17, UNW_REG_F18, UNW_REG_F19,
|
||||
UNW_REG_F20, UNW_REG_F21, UNW_REG_F22, UNW_REG_F23,
|
||||
UNW_REG_F24, UNW_REG_F25, UNW_REG_F26, UNW_REG_F27,
|
||||
UNW_REG_F28, UNW_REG_F29, UNW_REG_F30, UNW_REG_F31,
|
||||
UNW_NUM_REGS
|
||||
};
|
||||
|
||||
struct unw_info_block {
|
||||
u64 header;
|
||||
u64 desc[0]; /* unwind descriptors */
|
||||
/* personality routine and language-specific data follow behind descriptors */
|
||||
};
|
||||
|
||||
struct unw_table {
|
||||
struct unw_table *next; /* must be first member! */
|
||||
const char *name;
|
||||
unsigned long gp; /* global pointer for this load-module */
|
||||
unsigned long segment_base; /* base for offsets in the unwind table entries */
|
||||
unsigned long start;
|
||||
unsigned long end;
|
||||
const struct unw_table_entry *array;
|
||||
unsigned long length;
|
||||
};
|
||||
|
||||
enum unw_where {
|
||||
UNW_WHERE_NONE, /* register isn't saved at all */
|
||||
UNW_WHERE_GR, /* register is saved in a general register */
|
||||
UNW_WHERE_FR, /* register is saved in a floating-point register */
|
||||
UNW_WHERE_BR, /* register is saved in a branch register */
|
||||
UNW_WHERE_SPREL, /* register is saved on memstack (sp-relative) */
|
||||
UNW_WHERE_PSPREL, /* register is saved on memstack (psp-relative) */
|
||||
/*
|
||||
* At the end of each prologue these locations get resolved to
|
||||
* UNW_WHERE_PSPREL and UNW_WHERE_GR, respectively:
|
||||
*/
|
||||
UNW_WHERE_SPILL_HOME, /* register is saved in its spill home */
|
||||
UNW_WHERE_GR_SAVE /* register is saved in next general register */
|
||||
};
|
||||
|
||||
#define UNW_WHEN_NEVER 0x7fffffff
|
||||
|
||||
struct unw_reg_info {
|
||||
unsigned long val; /* save location: register number or offset */
|
||||
enum unw_where where; /* where the register gets saved */
|
||||
int when; /* when the register gets saved */
|
||||
};
|
||||
|
||||
struct unw_reg_state {
|
||||
struct unw_reg_state *next; /* next (outer) element on state stack */
|
||||
struct unw_reg_info reg[UNW_NUM_REGS]; /* register save locations */
|
||||
};
|
||||
|
||||
struct unw_labeled_state {
|
||||
struct unw_labeled_state *next; /* next labeled state (or NULL) */
|
||||
unsigned long label; /* label for this state */
|
||||
struct unw_reg_state saved_state;
|
||||
};
|
||||
|
||||
struct unw_state_record {
|
||||
unsigned int first_region : 1; /* is this the first region? */
|
||||
unsigned int done : 1; /* are we done scanning descriptors? */
|
||||
unsigned int any_spills : 1; /* got any register spills? */
|
||||
unsigned int in_body : 1; /* are we inside a body (as opposed to a prologue)? */
|
||||
unsigned long flags; /* see UNW_FLAG_* in unwind.h */
|
||||
|
||||
u8 *imask; /* imask of spill_mask record or NULL */
|
||||
unsigned long pr_val; /* predicate values */
|
||||
unsigned long pr_mask; /* predicate mask */
|
||||
long spill_offset; /* psp-relative offset for spill base */
|
||||
int region_start;
|
||||
int region_len;
|
||||
int epilogue_start;
|
||||
int epilogue_count;
|
||||
int when_target;
|
||||
|
||||
u8 gr_save_loc; /* next general register to use for saving a register */
|
||||
u8 return_link_reg; /* branch register in which the return link is passed */
|
||||
|
||||
struct unw_labeled_state *labeled_states; /* list of all labeled states */
|
||||
struct unw_reg_state curr; /* current state */
|
||||
};
|
||||
|
||||
enum unw_nat_type {
|
||||
UNW_NAT_NONE, /* NaT not represented */
|
||||
UNW_NAT_VAL, /* NaT represented by NaT value (fp reg) */
|
||||
UNW_NAT_MEMSTK, /* NaT value is in unat word at offset OFF */
|
||||
UNW_NAT_REGSTK /* NaT is in rnat */
|
||||
};
|
||||
|
||||
enum unw_insn_opcode {
|
||||
UNW_INSN_ADD, /* s[dst] += val */
|
||||
UNW_INSN_ADD_PSP, /* s[dst] = (s.psp + val) */
|
||||
UNW_INSN_ADD_SP, /* s[dst] = (s.sp + val) */
|
||||
UNW_INSN_MOVE, /* s[dst] = s[val] */
|
||||
UNW_INSN_MOVE2, /* s[dst] = s[val]; s[dst+1] = s[val+1] */
|
||||
UNW_INSN_MOVE_STACKED, /* s[dst] = ia64_rse_skip(*s.bsp, val) */
|
||||
UNW_INSN_SETNAT_MEMSTK, /* s[dst+1].nat.type = MEMSTK;
|
||||
s[dst+1].nat.off = *s.pri_unat - s[dst] */
|
||||
UNW_INSN_SETNAT_TYPE, /* s[dst+1].nat.type = val */
|
||||
UNW_INSN_LOAD, /* s[dst] = *s[val] */
|
||||
UNW_INSN_MOVE_SCRATCH, /* s[dst] = scratch reg "val" */
|
||||
UNW_INSN_MOVE_CONST, /* s[dst] = constant reg "val" */
|
||||
};
|
||||
|
||||
struct unw_insn {
|
||||
unsigned int opc : 4;
|
||||
unsigned int dst : 9;
|
||||
signed int val : 19;
|
||||
};
|
||||
|
||||
/*
|
||||
* Preserved general static registers (r4-r7) give rise to two script
|
||||
* instructions; everything else yields at most one instruction; at
|
||||
* the end of the script, the psp gets popped, accounting for one more
|
||||
* instruction.
|
||||
*/
|
||||
#define UNW_MAX_SCRIPT_LEN (UNW_NUM_REGS + 5)
|
||||
|
||||
struct unw_script {
|
||||
unsigned long ip; /* ip this script is for */
|
||||
unsigned long pr_mask; /* mask of predicates script depends on */
|
||||
unsigned long pr_val; /* predicate values this script is for */
|
||||
rwlock_t lock;
|
||||
unsigned int flags; /* see UNW_FLAG_* in unwind.h */
|
||||
unsigned short lru_chain; /* used for least-recently-used chain */
|
||||
unsigned short coll_chain; /* used for hash collisions */
|
||||
unsigned short hint; /* hint for next script to try (or -1) */
|
||||
unsigned short count; /* number of instructions in script */
|
||||
struct unw_insn insn[UNW_MAX_SCRIPT_LEN];
|
||||
};
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <asm/vmx_vcpu.h>
|
||||
#include <asm/privop.h>
|
||||
#include <asm/types.h>
|
||||
#include <public/io/ioreq.h>
|
||||
#include <public/hvm/ioreq.h>
|
||||
#include <asm/mm.h>
|
||||
#include <asm/vmx.h>
|
||||
|
||||
|
||||
@@ -218,7 +218,7 @@ void vtm_interruption_update(VCPU *vcpu, vtime_t* vtm)
|
||||
*/
|
||||
void vtm_domain_out(VCPU *vcpu)
|
||||
{
|
||||
if(!is_idle_task(vcpu->domain))
|
||||
if(!is_idle_domain(vcpu->domain))
|
||||
rem_ac_timer(&vcpu->arch.arch_vmx.vtm.vtm_timer);
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ void vtm_domain_in(VCPU *vcpu)
|
||||
{
|
||||
vtime_t *vtm;
|
||||
|
||||
if(!is_idle_task(vcpu->domain)) {
|
||||
if(!is_idle_domain(vcpu->domain)) {
|
||||
vtm=&(vcpu->arch.arch_vmx.vtm);
|
||||
vtm_interruption_update(vcpu, vtm);
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
#include <xen/lib.h>
|
||||
#include <asm/vmmu.h>
|
||||
#include <public/arch-ia64.h>
|
||||
#include <public/io/ioreq.h>
|
||||
#include <public/hvm/ioreq.h>
|
||||
#include <asm/vmx_phy_mode.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/vmx.h>
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#define INITIAL_PSR_VALUE_AT_INTERRUPTION 0x0000001808028034
|
||||
|
||||
|
||||
extern void die_if_kernel(char *str, struct pt_regs *regs, long err);
|
||||
extern void rnat_consumption (VCPU *vcpu);
|
||||
#define DOMN_PAL_REQUEST 0x110000
|
||||
|
||||
@@ -185,8 +186,11 @@ vmx_ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long is
|
||||
}else if(iim == DOMN_PAL_REQUEST){
|
||||
pal_emul(current);
|
||||
vmx_vcpu_increment_iip(current);
|
||||
} else
|
||||
} else {
|
||||
if (iim == 0)
|
||||
die_if_kernel("bug check", regs, iim);
|
||||
vmx_reflect_interruption(ifa,isr,iim,11,regs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -227,7 +231,7 @@ void leave_hypervisor_tail(struct pt_regs *regs)
|
||||
struct domain *d = current->domain;
|
||||
struct vcpu *v = current;
|
||||
// FIXME: Will this work properly if doing an RFI???
|
||||
if (!is_idle_task(d) ) { // always comes from guest
|
||||
if (!is_idle_domain(d) ) { // always comes from guest
|
||||
extern void vmx_dorfirfi(void);
|
||||
struct pt_regs *user_regs = vcpu_regs(current);
|
||||
if (local_softirq_pending())
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*/
|
||||
#include <xen/config.h>
|
||||
#include <xen/sched.h>
|
||||
#include <public/io/ioreq.h>
|
||||
#include <public/hvm/ioreq.h>
|
||||
#include <asm/vmx.h>
|
||||
#include <asm/vmx_vcpu.h>
|
||||
|
||||
|
||||
@@ -861,12 +861,16 @@ dom_fw_init (struct domain *d, char *args, int arglen, char *fw_mem, int fw_mem_
|
||||
bp->console_info.orig_x = 0;
|
||||
bp->console_info.orig_y = 24;
|
||||
bp->fpswa = 0;
|
||||
bp->initrd_start = (dom0_start+dom0_size) -
|
||||
(PAGE_ALIGN(ia64_boot_param->initrd_size) + 4*1024*1024);
|
||||
bp->initrd_size = ia64_boot_param->initrd_size;
|
||||
printf(" initrd start %0xlx", bp->initrd_start);
|
||||
printf(" initrd size %0xlx", bp->initrd_size);
|
||||
|
||||
|
||||
if (d == dom0) {
|
||||
bp->initrd_start = (dom0_start+dom0_size) -
|
||||
(PAGE_ALIGN(ia64_boot_param->initrd_size) + 4*1024*1024);
|
||||
bp->initrd_size = ia64_boot_param->initrd_size;
|
||||
}
|
||||
else {
|
||||
bp->initrd_start = d->arch.initrd_start;
|
||||
bp->initrd_size = d->arch.initrd_len;
|
||||
}
|
||||
printf(" initrd start %0xlx", bp->initrd_start);
|
||||
printf(" initrd size %0xlx", bp->initrd_size);
|
||||
return bp;
|
||||
}
|
||||
+16
-55
@@ -19,6 +19,7 @@
|
||||
#include <xen/delay.h>
|
||||
#include <xen/softirq.h>
|
||||
#include <xen/mm.h>
|
||||
#include <xen/iocap.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
@@ -45,7 +46,7 @@
|
||||
#include <asm/vmx_vcpu.h>
|
||||
#include <asm/vmx_vpd.h>
|
||||
#include <asm/pal.h>
|
||||
#include <public/io/ioreq.h>
|
||||
#include <public/hvm/ioreq.h>
|
||||
|
||||
#define CONFIG_DOMAIN0_CONTIGUOUS
|
||||
unsigned long dom0_start = -1L;
|
||||
@@ -181,7 +182,7 @@ static void init_switch_stack(struct vcpu *v)
|
||||
memset(v->arch._thread.fph,0,sizeof(struct ia64_fpreg)*96);
|
||||
}
|
||||
|
||||
void arch_do_createdomain(struct vcpu *v)
|
||||
int arch_do_createdomain(struct vcpu *v)
|
||||
{
|
||||
struct domain *d = v->domain;
|
||||
struct thread_info *ti = alloc_thread_info(v);
|
||||
@@ -248,7 +249,9 @@ void arch_do_createdomain(struct vcpu *v)
|
||||
}
|
||||
} else
|
||||
d->arch.mm = NULL;
|
||||
printf ("arch_do_create_domain: domain=%p\n", d);
|
||||
printf ("arch_do_create_domain: domain=%p\n", d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void arch_getdomaininfo_ctxt(struct vcpu *v, struct vcpu_guest_context *c)
|
||||
@@ -291,16 +294,7 @@ int arch_set_info_guest(struct vcpu *v, struct vcpu_guest_context *c)
|
||||
d->arch.cmdline = c->cmdline;
|
||||
new_thread(v, regs->cr_iip, 0, 0);
|
||||
|
||||
#ifdef CONFIG_IA64_SPLIT_CACHE
|
||||
/* Sync d/i cache conservatively */
|
||||
if (!running_on_sim) {
|
||||
ret = ia64_pal_cache_flush(4, 0, &progress, NULL);
|
||||
if ((ret!=PAL_STATUS_SUCCESS)&& (ret!=PAL_STATUS_UNIMPLEMENTED))
|
||||
printk("PAL CACHE FLUSH failed for dom0.\n");
|
||||
else
|
||||
printk("Sync i/d cache for guest SUCC\n");
|
||||
}
|
||||
#endif
|
||||
sync_split_caches();
|
||||
v->vcpu_info->arch.evtchn_vector = c->vcpu.evtchn_vector;
|
||||
if ( c->vcpu.privregs && copy_from_user(v->arch.privregs,
|
||||
c->vcpu.privregs, sizeof(mapped_regs_t))) {
|
||||
@@ -428,7 +422,7 @@ extern unsigned long vhpt_paddr, vhpt_pend;
|
||||
{
|
||||
p = alloc_domheap_page(d);
|
||||
// zero out pages for security reasons
|
||||
memset(__va(page_to_phys(p)),0,PAGE_SIZE);
|
||||
if (p) memset(__va(page_to_phys(p)),0,PAGE_SIZE);
|
||||
}
|
||||
if (unlikely(!p)) {
|
||||
printf("map_new_domain_page: Can't alloc!!!! Aaaargh!\n");
|
||||
@@ -763,7 +757,10 @@ void alloc_dom0(void)
|
||||
*/
|
||||
void physdev_init_dom0(struct domain *d)
|
||||
{
|
||||
set_bit(_DOMF_physdev_access, &d->domain_flags);
|
||||
if (iomem_permit_access(d, 0UL, ~0UL))
|
||||
BUG();
|
||||
if (irqs_permit_access(d, 0, NR_PIRQS-1))
|
||||
BUG();
|
||||
}
|
||||
|
||||
unsigned int vmx_dom0 = 0;
|
||||
@@ -912,9 +909,9 @@ int construct_dom0(struct domain *d,
|
||||
memset(si, 0, PAGE_SIZE);
|
||||
d->shared_info->arch.start_info_pfn = __pa(si) >> PAGE_SHIFT;
|
||||
sprintf(si->magic, "xen-%i.%i-ia64", XEN_VERSION, XEN_SUBVERSION);
|
||||
si->nr_pages = d->tot_pages;
|
||||
|
||||
#if 0
|
||||
si->nr_pages = d->tot_pages;
|
||||
si->shared_info = virt_to_phys(d->shared_info);
|
||||
si->flags = SIF_PRIVILEGED | SIF_INITDOMAIN;
|
||||
//si->pt_base = vpt_start;
|
||||
@@ -959,16 +956,7 @@ int construct_dom0(struct domain *d,
|
||||
|
||||
new_thread(v, pkern_entry, 0, 0);
|
||||
physdev_init_dom0(d);
|
||||
#ifdef CONFIG_IA64_SPLIT_CACHE
|
||||
/* Sync d/i cache conservatively */
|
||||
if (!running_on_sim) {
|
||||
ret = ia64_pal_cache_flush(4, 0, &progress, NULL);
|
||||
if ((ret!=PAL_STATUS_SUCCESS)&& (ret!=PAL_STATUS_UNIMPLEMENTED))
|
||||
printk("PAL CACHE FLUSH failed for dom0.\n");
|
||||
else
|
||||
printk("Sync i/d cache for guest SUCC\n");
|
||||
}
|
||||
#endif
|
||||
sync_split_caches();
|
||||
|
||||
// FIXME: Hack for keyboard input
|
||||
#ifdef CLONE_DOMAIN0
|
||||
@@ -1027,16 +1015,7 @@ int construct_domU(struct domain *d,
|
||||
#endif
|
||||
new_thread(v, pkern_entry, 0, 0);
|
||||
printk("new_thread returns\n");
|
||||
#ifdef CONFIG_IA64_SPLIT_CACHE
|
||||
/* Sync d/i cache conservatively */
|
||||
if (!running_on_sim) {
|
||||
ret = ia64_pal_cache_flush(4, 0, &progress, NULL);
|
||||
if ((ret!=PAL_STATUS_SUCCESS)&& (ret!=PAL_STATUS_UNIMPLEMENTED))
|
||||
printk("PAL CACHE FLUSH failed for dom0.\n");
|
||||
else
|
||||
printk("Sync i/d cache for guest SUCC\n");
|
||||
}
|
||||
#endif
|
||||
sync_split_caches();
|
||||
__set_bit(0x30, VCPU(v, delivery_mask));
|
||||
|
||||
return 0;
|
||||
@@ -1050,16 +1029,7 @@ void reconstruct_domU(struct vcpu *v)
|
||||
v->domain->domain_id);
|
||||
loaddomainelfimage(v->domain,v->domain->arch.image_start);
|
||||
new_thread(v, v->domain->arch.entry, 0, 0);
|
||||
#ifdef CONFIG_IA64_SPLIT_CACHE
|
||||
/* Sync d/i cache conservatively */
|
||||
if (!running_on_sim) {
|
||||
ret = ia64_pal_cache_flush(4, 0, &progress, NULL);
|
||||
if ((ret!=PAL_STATUS_SUCCESS)&& (ret!=PAL_STATUS_UNIMPLEMENTED))
|
||||
printk("PAL CACHE FLUSH failed for dom0.\n");
|
||||
else
|
||||
printk("Sync i/d cache for guest SUCC\n");
|
||||
}
|
||||
#endif
|
||||
sync_split_caches();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1100,15 +1070,6 @@ void domain_pend_keyboard_interrupt(int irq)
|
||||
vcpu_pend_interrupt(dom0->vcpu[0],irq);
|
||||
}
|
||||
|
||||
void vcpu_migrate_cpu(struct vcpu *v, int newcpu)
|
||||
{
|
||||
if ( v->processor == newcpu )
|
||||
return;
|
||||
|
||||
set_bit(_VCPUF_cpu_migrated, &v->vcpu_flags);
|
||||
v->processor = newcpu;
|
||||
}
|
||||
|
||||
void sync_vcpu_execstate(struct vcpu *v)
|
||||
{
|
||||
ia64_save_fpu(v->arch._thread.fph);
|
||||
|
||||
@@ -543,6 +543,13 @@ GLOBAL_ENTRY(fast_break_reflect)
|
||||
extr.u r21=r30,IA64_PSR_PP_BIT,1 ;;
|
||||
cmp.ne p7,p0=r21,r0 ;;
|
||||
(p7) br.spnt.few dispatch_break_fault ;;
|
||||
movl r20=IA64_PSR_CPL ;;
|
||||
and r22=r20,r30 ;;
|
||||
cmp.ne p7,p0=r22,r0
|
||||
(p7) br.spnt.many 1f ;;
|
||||
cmp.eq p7,p0=r17,r0
|
||||
(p7) br.spnt.few dispatch_break_fault ;;
|
||||
1:
|
||||
#if 1 /* special handling in case running on simulator */
|
||||
movl r20=first_break;;
|
||||
ld4 r23=[r20];;
|
||||
|
||||
@@ -1378,9 +1378,6 @@ int pirq_guest_bind(struct vcpu *d, int irq, int will_share)
|
||||
unsigned long flags;
|
||||
int rc = 0;
|
||||
|
||||
if ( !IS_CAPABLE_PHYSDEV(d->domain) )
|
||||
return -EPERM;
|
||||
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
|
||||
action = (irq_guest_action_t *)desc->action;
|
||||
|
||||
@@ -839,6 +839,8 @@ ENTRY(break_fault)
|
||||
mov r17=cr.iim
|
||||
mov r31=pr
|
||||
;;
|
||||
cmp.eq p7,p0=r17,r0
|
||||
(p7) br.spnt.few dispatch_break_fault ;;
|
||||
movl r18=XSI_PSR_IC
|
||||
;;
|
||||
ld8 r19=[r18]
|
||||
|
||||
+12
-19
@@ -33,6 +33,7 @@
|
||||
#include <xen/multicall.h>
|
||||
|
||||
extern unsigned long vcpu_get_itir_on_fault(struct vcpu *, UINT64);
|
||||
extern void die_if_kernel(char *str, struct pt_regs *regs, long err);
|
||||
|
||||
extern unsigned long dom0_start, dom0_size;
|
||||
|
||||
@@ -64,26 +65,16 @@ long do_iopl(domid_t domain, unsigned int new_io_pl)
|
||||
|
||||
extern struct schedule_data schedule_data[NR_CPUS];
|
||||
|
||||
void schedule_tail(struct vcpu *next)
|
||||
void schedule_tail(struct vcpu *prev)
|
||||
{
|
||||
unsigned long rr7;
|
||||
//printk("current=%lx,shared_info=%lx\n",current,current->vcpu_info);
|
||||
//printk("next=%lx,shared_info=%lx\n",next,next->vcpu_info);
|
||||
context_saved(prev);
|
||||
|
||||
// TG: Real HACK FIXME.
|
||||
// This is currently necessary because when a new domain is started,
|
||||
// the context_switch function of xen/common/schedule.c(__enter_scheduler)
|
||||
// never returns. Therefore, the lock must be released.
|
||||
// schedule_tail is only called when a domain is started.
|
||||
spin_unlock_irq(&schedule_data[current->processor].schedule_lock);
|
||||
|
||||
/* rr7 will be postponed to last point when resuming back to guest */
|
||||
if(VMX_DOMAIN(current)){
|
||||
vmx_load_all_rr(current);
|
||||
}else{
|
||||
load_region_regs(current);
|
||||
vcpu_load_kernel_regs(current);
|
||||
}
|
||||
if (VMX_DOMAIN(current)) {
|
||||
vmx_load_all_rr(current);
|
||||
} else {
|
||||
load_region_regs(current);
|
||||
vcpu_load_kernel_regs(current);
|
||||
}
|
||||
}
|
||||
|
||||
void tdpfoo(void) { }
|
||||
@@ -251,7 +242,7 @@ void deliver_pending_interrupt(struct pt_regs *regs)
|
||||
struct domain *d = current->domain;
|
||||
struct vcpu *v = current;
|
||||
// FIXME: Will this work properly if doing an RFI???
|
||||
if (!is_idle_task(d) && user_mode(regs)) {
|
||||
if (!is_idle_domain(d) && user_mode(regs)) {
|
||||
//vcpu_poke_timer(v);
|
||||
if (vcpu_deliverable_interrupts(v))
|
||||
reflect_extint(regs);
|
||||
@@ -686,6 +677,8 @@ ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long isr, u
|
||||
vcpu_increment_iip(current);
|
||||
}
|
||||
else {
|
||||
if (iim == 0)
|
||||
die_if_kernel("bug check", regs, iim);
|
||||
PSCB(v,iim) = iim;
|
||||
reflect_interruption(isr,regs,IA64_BREAK_VECTOR);
|
||||
}
|
||||
|
||||
@@ -1085,7 +1085,7 @@ void vcpu_set_next_timer(VCPU *vcpu)
|
||||
/* gloss over the wraparound problem for now... we know it exists
|
||||
* but it doesn't matter right now */
|
||||
|
||||
if (is_idle_task(vcpu->domain)) {
|
||||
if (is_idle_domain(vcpu->domain)) {
|
||||
// printf("****** vcpu_set_next_timer called during idle!!\n");
|
||||
vcpu_safe_set_itm(s);
|
||||
return;
|
||||
|
||||
+29
-12
@@ -25,7 +25,6 @@ unsigned long wait_init_idle;
|
||||
int phys_proc_id[NR_CPUS];
|
||||
unsigned long loops_per_jiffy = (1<<12); // from linux/init/main.c
|
||||
|
||||
void unw_init(void) { printf("unw_init() skipped (NEED FOR KERNEL UNWIND)\n"); }
|
||||
void ia64_mca_init(void) { printf("ia64_mca_init() skipped (Machine check abort handling)\n"); }
|
||||
void ia64_mca_cpu_init(void *x) { }
|
||||
void ia64_patch_mckinley_e9(unsigned long a, unsigned long b) { }
|
||||
@@ -180,11 +179,6 @@ void pgtable_quicklist_free(void *pgtable_entry)
|
||||
// from arch/ia64/traps.c
|
||||
///////////////////////////////
|
||||
|
||||
void show_registers(struct pt_regs *regs)
|
||||
{
|
||||
printf("*** ADD REGISTER DUMP HERE FOR DEBUGGING\n");
|
||||
}
|
||||
|
||||
int is_kernel_text(unsigned long addr)
|
||||
{
|
||||
extern char _stext[], _etext[];
|
||||
@@ -236,7 +230,13 @@ void sys_exit(void)
|
||||
|
||||
void die_if_kernel(char *str, struct pt_regs *regs, long err) /* __attribute__ ((noreturn)) */
|
||||
{
|
||||
printk("die_if_kernel: called, not implemented\n");
|
||||
if (user_mode(regs))
|
||||
return;
|
||||
|
||||
printk("%s: %s %ld\n", __func__, str, err);
|
||||
debugtrace_dump();
|
||||
show_registers(regs);
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
|
||||
long
|
||||
@@ -320,18 +320,15 @@ if (!i--) { printk("+",id); i = 1000000; }
|
||||
ia64_set_iva(&ia64_ivt);
|
||||
ia64_set_pta(VHPT_ADDR | (1 << 8) | (VHPT_SIZE_LOG2 << 2) |
|
||||
VHPT_ENABLED);
|
||||
if (!is_idle_task(current->domain)) {
|
||||
if (!is_idle_domain(current->domain)) {
|
||||
load_region_regs(current);
|
||||
vcpu_load_kernel_regs(current);
|
||||
if (vcpu_timer_expired(current)) vcpu_pend_timer(current);
|
||||
}
|
||||
if (vcpu_timer_expired(current)) vcpu_pend_timer(current);
|
||||
}
|
||||
}
|
||||
|
||||
void context_switch_finalise(struct vcpu *next)
|
||||
{
|
||||
/* nothing to do */
|
||||
context_saved(prev);
|
||||
}
|
||||
|
||||
void continue_running(struct vcpu *same)
|
||||
@@ -368,3 +365,23 @@ loop:
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: for the forseeable future, all cpu's that enable VTi have split
|
||||
* caches and all cpu's that have split caches enable VTi. This may
|
||||
* eventually be untrue though. */
|
||||
#define cpu_has_split_cache vmx_enabled
|
||||
extern unsigned int vmx_enabled;
|
||||
|
||||
void sync_split_caches(void)
|
||||
{
|
||||
unsigned long ret, progress = 0;
|
||||
|
||||
if (cpu_has_split_cache) {
|
||||
/* Sync d/i cache conservatively */
|
||||
ret = ia64_pal_cache_flush(4, 0, &progress, NULL);
|
||||
if ((ret!=PAL_STATUS_SUCCESS)&& (ret!=PAL_STATUS_UNIMPLEMENTED))
|
||||
printk("PAL CACHE FLUSH failed\n");
|
||||
else printk("Sync i/d cache for guest SUCC\n");
|
||||
}
|
||||
else printk("sync_split_caches ignored for CPU with no split cache\n");
|
||||
}
|
||||
@@ -26,7 +26,7 @@ unsigned long xenheap_phys_end;
|
||||
|
||||
char saved_command_line[COMMAND_LINE_SIZE];
|
||||
|
||||
struct vcpu *idle_task[NR_CPUS] = { &idle0_vcpu };
|
||||
struct vcpu *idle_domain[NR_CPUS] = { &idle0_vcpu };
|
||||
|
||||
cpumask_t cpu_present_map;
|
||||
|
||||
@@ -382,8 +382,7 @@ printk("About to call do_createdomain()\n");
|
||||
panic("Could not set up DOM0 guest OS\n");
|
||||
|
||||
/* PIN domain0 on CPU 0. */
|
||||
dom0->vcpu[0]->cpumap=1;
|
||||
set_bit(_VCPUF_cpu_pinned, &dom0->vcpu[0]->vcpu_flags);
|
||||
dom0->vcpu[0]->cpu_affinity = cpumask_of_cpu(0);
|
||||
|
||||
#ifdef CLONE_DOMAIN0
|
||||
{
|
||||
|
||||
@@ -127,7 +127,7 @@ xen_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
|
||||
vcpu_wake(dom0->vcpu[0]);
|
||||
}
|
||||
}
|
||||
if (!is_idle_task(current->domain)) {
|
||||
if (!is_idle_domain(current->domain)) {
|
||||
if (vcpu_timer_expired(current)) {
|
||||
vcpu_pend_timer(current);
|
||||
// ensure another timer interrupt happens even if domain doesn't
|
||||
|
||||
@@ -29,6 +29,7 @@ ifeq ($(TARGET_SUBARCH),x86_32)
|
||||
endif
|
||||
|
||||
OBJS := $(subst $(TARGET_SUBARCH)/asm-offsets.o,,$(OBJS))
|
||||
OBJS := $(subst $(TARGET_SUBARCH)/xen.lds.o,,$(OBJS))
|
||||
|
||||
ifneq ($(crash_debug),y)
|
||||
OBJS := $(patsubst cdb%.o,,$(OBJS))
|
||||
@@ -43,22 +44,25 @@ $(TARGET): $(TARGET)-syms boot/mkelf32
|
||||
$(CURDIR)/arch.o: $(OBJS)
|
||||
$(LD) $(LDFLAGS) -r -o $@ $(OBJS)
|
||||
|
||||
$(TARGET)-syms: boot/$(TARGET_SUBARCH).o $(ALL_OBJS) $(TARGET_SUBARCH)/xen.lds
|
||||
$(LD) $(LDFLAGS) -T $(TARGET_SUBARCH)/xen.lds -N \
|
||||
$(TARGET)-syms: boot/$(TARGET_SUBARCH).o $(ALL_OBJS) xen.lds
|
||||
$(LD) $(LDFLAGS) -T xen.lds -N \
|
||||
boot/$(TARGET_SUBARCH).o $(ALL_OBJS) -o $@
|
||||
$(NM) -n $@ | $(BASEDIR)/tools/symbols >$(BASEDIR)/xen-syms.S
|
||||
$(MAKE) $(BASEDIR)/xen-syms.o
|
||||
$(LD) $(LDFLAGS) -T $(TARGET_SUBARCH)/xen.lds -N \
|
||||
$(LD) $(LDFLAGS) -T xen.lds -N \
|
||||
boot/$(TARGET_SUBARCH).o $(ALL_OBJS) $(BASEDIR)/xen-syms.o -o $@
|
||||
$(NM) -n $@ | $(BASEDIR)/tools/symbols >$(BASEDIR)/xen-syms.S
|
||||
$(MAKE) $(BASEDIR)/xen-syms.o
|
||||
$(LD) $(LDFLAGS) -T $(TARGET_SUBARCH)/xen.lds -N \
|
||||
$(LD) $(LDFLAGS) -T xen.lds -N \
|
||||
boot/$(TARGET_SUBARCH).o $(ALL_OBJS) $(BASEDIR)/xen-syms.o -o $@
|
||||
rm -f $(BASEDIR)/xen-syms.S $(BASEDIR)/xen-syms.o
|
||||
|
||||
asm-offsets.s: $(TARGET_SUBARCH)/asm-offsets.c $(HDRS)
|
||||
$(CC) $(CFLAGS) -S -o $@ $<
|
||||
|
||||
xen.lds: $(TARGET_SUBARCH)/xen.lds.S $(HDRS)
|
||||
$(CC) $(CFLAGS) -P -E -Ui386 -D__ASSEMBLY__ -o $@ $<
|
||||
|
||||
boot/mkelf32: boot/mkelf32.c
|
||||
$(HOSTCC) $(HOSTCFLAGS) -o $@ $<
|
||||
|
||||
@@ -73,5 +77,6 @@ clean:
|
||||
rm -f dm/*.o dm/*~ dm/core
|
||||
rm -f genapic/*.o genapic/*~ genapic/core
|
||||
rm -f cpu/*.o cpu/*~ cpu/core
|
||||
rm -f xen.lds
|
||||
|
||||
.PHONY: default clean
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <xen/config.h>
|
||||
#include <public/xen.h>
|
||||
#include <asm/asm_defns.h>
|
||||
#include <asm/desc.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/msr.h>
|
||||
@@ -53,6 +54,7 @@ __start:
|
||||
mov %ecx,%gs
|
||||
ljmp $(__HYPERVISOR_CS),$(1f)-__PAGE_OFFSET
|
||||
1: lss stack_start-__PAGE_OFFSET,%esp
|
||||
add $(STACK_SIZE-CPUINFO_sizeof-__PAGE_OFFSET),%esp
|
||||
|
||||
/* Reset EFLAGS (subsumes CLI and CLD). */
|
||||
pushl $0
|
||||
@@ -98,7 +100,7 @@ __start:
|
||||
1: stosl /* low mappings cover as much physmem as possible */
|
||||
add $4,%edi
|
||||
add $(1<<L2_PAGETABLE_SHIFT),%eax
|
||||
cmp $__HYPERVISOR_VIRT_START+0xe3,%eax
|
||||
cmp $HYPERVISOR_VIRT_START+0xe3,%eax
|
||||
jne 1b
|
||||
#else
|
||||
/* Initialize low and high mappings of all memory with 4MB pages */
|
||||
@@ -111,7 +113,7 @@ __start:
|
||||
jne 1b
|
||||
1: stosl /* low mappings cover as much physmem as possible */
|
||||
add $(1<<L2_PAGETABLE_SHIFT),%eax
|
||||
cmp $__HYPERVISOR_VIRT_START+0xe3,%eax
|
||||
cmp $HYPERVISOR_VIRT_START+0xe3,%eax
|
||||
jne 1b
|
||||
#endif
|
||||
|
||||
@@ -189,7 +191,7 @@ ignore_int:
|
||||
/*** STACK LOCATION ***/
|
||||
|
||||
ENTRY(stack_start)
|
||||
.long cpu0_stack + STACK_SIZE - 200 - __PAGE_OFFSET
|
||||
.long cpu0_stack
|
||||
.long __HYPERVISOR_DS
|
||||
|
||||
/*** DESCRIPTOR TABLES ***/
|
||||
@@ -256,10 +258,6 @@ ENTRY(idle_pg_table_l2)
|
||||
.fill 1*PAGE_SIZE,1,0
|
||||
#endif
|
||||
|
||||
#if (STACK_ORDER == 0)
|
||||
.section ".bss.page_aligned","w"
|
||||
#else
|
||||
.section ".bss.twopage_aligned","w"
|
||||
#endif
|
||||
.section ".bss.stack_aligned","w"
|
||||
ENTRY(cpu0_stack)
|
||||
.fill STACK_SIZE,1,0
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <xen/config.h>
|
||||
#include <public/xen.h>
|
||||
#include <asm/asm_defns.h>
|
||||
#include <asm/desc.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/msr.h>
|
||||
@@ -121,7 +122,8 @@ skip_boot_checks:
|
||||
mov %rcx,%cr4
|
||||
|
||||
mov stack_start(%rip),%rsp
|
||||
|
||||
or $(STACK_SIZE-CPUINFO_sizeof),%rsp
|
||||
|
||||
/* Reset EFLAGS (subsumes CLI and CLD). */
|
||||
pushq $0
|
||||
popf
|
||||
@@ -140,7 +142,7 @@ __high_start:
|
||||
mov %ecx,%ss
|
||||
|
||||
lidt idt_descr(%rip)
|
||||
|
||||
|
||||
cmp $(SECONDARY_CPU_FLAG),%ebx
|
||||
je start_secondary
|
||||
|
||||
@@ -219,7 +221,7 @@ idt:
|
||||
.quad idt_table
|
||||
|
||||
ENTRY(stack_start)
|
||||
.quad cpu0_stack + STACK_SIZE - 200
|
||||
.quad cpu0_stack
|
||||
|
||||
high_start:
|
||||
.quad __high_start
|
||||
@@ -265,10 +267,6 @@ ENTRY(idle_pg_table_l2)
|
||||
.org 0x4000 + PAGE_SIZE
|
||||
.code64
|
||||
|
||||
#if (STACK_ORDER == 0)
|
||||
.section ".bss.page_aligned","w"
|
||||
#else
|
||||
.section ".bss.twopage_aligned","w"
|
||||
#endif
|
||||
.section ".bss.stack_aligned","w"
|
||||
ENTRY(cpu0_stack)
|
||||
.fill STACK_SIZE,1,0
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <xen/lib.h>
|
||||
#include <xen/errno.h>
|
||||
#include <xen/sched.h>
|
||||
#include <public/io/ioreq.h>
|
||||
#include <public/hvm/ioreq.h>
|
||||
#include <asm/vmx.h>
|
||||
#include <asm/vmx_vpic.h>
|
||||
#include <asm/current.h>
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
#include <xen/lib.h>
|
||||
#include <xen/errno.h>
|
||||
#include <xen/sched.h>
|
||||
#include <public/io/ioreq.h>
|
||||
#include <public/hvm/ioreq.h>
|
||||
#include <asm/vmx.h>
|
||||
#include <asm/vmx_vpic.h>
|
||||
#include <asm/current.h>
|
||||
|
||||
+26
-25
@@ -17,6 +17,7 @@
|
||||
#include <asm/msr.h>
|
||||
#include <xen/trace.h>
|
||||
#include <xen/console.h>
|
||||
#include <xen/iocap.h>
|
||||
#include <asm/shadow.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/processor.h>
|
||||
@@ -35,13 +36,13 @@ static unsigned long msr_hi;
|
||||
|
||||
static void write_msr_for(void *unused)
|
||||
{
|
||||
if ( ((1 << current->processor) & msr_cpu_mask) )
|
||||
if ( ((1 << smp_processor_id()) & msr_cpu_mask) )
|
||||
(void)wrmsr_user(msr_addr, msr_lo, msr_hi);
|
||||
}
|
||||
|
||||
static void read_msr_for(void *unused)
|
||||
{
|
||||
if ( ((1 << current->processor) & msr_cpu_mask) )
|
||||
if ( ((1 << smp_processor_id()) & msr_cpu_mask) )
|
||||
(void)rdmsr_user(msr_addr, msr_lo, msr_hi);
|
||||
}
|
||||
|
||||
@@ -102,12 +103,27 @@ long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op)
|
||||
op->u.add_memtype.nr_pfns,
|
||||
op->u.add_memtype.type,
|
||||
1);
|
||||
if (ret > 0)
|
||||
{
|
||||
(void)__put_user(0, &u_dom0_op->u.add_memtype.handle);
|
||||
(void)__put_user(ret, &u_dom0_op->u.add_memtype.reg);
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DOM0_DEL_MEMTYPE:
|
||||
{
|
||||
ret = mtrr_del_page(op->u.del_memtype.reg, 0, 0);
|
||||
if (op->u.del_memtype.handle == 0
|
||||
/* mtrr/main.c otherwise does a lookup */
|
||||
&& (int)op->u.del_memtype.reg >= 0)
|
||||
{
|
||||
ret = mtrr_del_page(op->u.del_memtype.reg, 0, 0);
|
||||
if (ret > 0)
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
ret = -EINVAL;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -141,7 +157,6 @@ long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op)
|
||||
struct domain *d;
|
||||
unsigned int fp = op->u.ioport_permission.first_port;
|
||||
unsigned int np = op->u.ioport_permission.nr_ports;
|
||||
unsigned int p;
|
||||
|
||||
ret = -EINVAL;
|
||||
if ( (fp + np) > 65536 )
|
||||
@@ -152,26 +167,12 @@ long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op)
|
||||
op->u.ioport_permission.domain)) == NULL) )
|
||||
break;
|
||||
|
||||
ret = -ENOMEM;
|
||||
if ( d->arch.iobmp_mask != NULL )
|
||||
{
|
||||
if ( (d->arch.iobmp_mask = xmalloc_array(
|
||||
u8, IOBMP_BYTES)) == NULL )
|
||||
{
|
||||
put_domain(d);
|
||||
break;
|
||||
}
|
||||
memset(d->arch.iobmp_mask, 0xFF, IOBMP_BYTES);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
for ( p = fp; p < (fp + np); p++ )
|
||||
{
|
||||
if ( op->u.ioport_permission.allow_access )
|
||||
clear_bit(p, d->arch.iobmp_mask);
|
||||
else
|
||||
set_bit(p, d->arch.iobmp_mask);
|
||||
}
|
||||
if ( np == 0 )
|
||||
ret = 0;
|
||||
else if ( op->u.ioport_permission.allow_access )
|
||||
ret = ioports_permit_access(d, fp, fp + np - 1);
|
||||
else
|
||||
ret = ioports_deny_access(d, fp, fp + np - 1);
|
||||
|
||||
put_domain(d);
|
||||
}
|
||||
@@ -193,7 +194,7 @@ long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op)
|
||||
memcpy(pi->hw_cap, boot_cpu_data.x86_capability, NCAPINTS*4);
|
||||
ret = 0;
|
||||
if ( copy_to_user(u_dom0_op, op, sizeof(*op)) )
|
||||
ret = -EFAULT;
|
||||
ret = -EFAULT;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
+65
-77
@@ -20,6 +20,7 @@
|
||||
#include <xen/delay.h>
|
||||
#include <xen/softirq.h>
|
||||
#include <xen/grant_table.h>
|
||||
#include <xen/iocap.h>
|
||||
#include <asm/regs.h>
|
||||
#include <asm/mc146818rtc.h>
|
||||
#include <asm/system.h>
|
||||
@@ -35,9 +36,7 @@
|
||||
#include <xen/console.h>
|
||||
#include <xen/elf.h>
|
||||
#include <asm/vmx.h>
|
||||
#include <asm/vmx_vmcs.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/physdev.h>
|
||||
#include <xen/kernel.h>
|
||||
#include <xen/multicall.h>
|
||||
|
||||
@@ -47,17 +46,16 @@ boolean_param("noreboot", opt_noreboot);
|
||||
|
||||
struct percpu_ctxt {
|
||||
struct vcpu *curr_vcpu;
|
||||
unsigned int context_not_finalised;
|
||||
unsigned int dirty_segment_mask;
|
||||
} __cacheline_aligned;
|
||||
static struct percpu_ctxt percpu_ctxt[NR_CPUS];
|
||||
|
||||
static void continue_idle_task(struct vcpu *v)
|
||||
static void continue_idle_domain(struct vcpu *v)
|
||||
{
|
||||
reset_stack_and_jump(idle_loop);
|
||||
}
|
||||
|
||||
static void continue_nonidle_task(struct vcpu *v)
|
||||
static void continue_nonidle_domain(struct vcpu *v)
|
||||
{
|
||||
reset_stack_and_jump(ret_from_intr);
|
||||
}
|
||||
@@ -93,12 +91,13 @@ void startup_cpu_idle_loop(void)
|
||||
{
|
||||
struct vcpu *v = current;
|
||||
|
||||
ASSERT(is_idle_task(v->domain));
|
||||
ASSERT(is_idle_domain(v->domain));
|
||||
percpu_ctxt[smp_processor_id()].curr_vcpu = v;
|
||||
cpu_set(smp_processor_id(), v->domain->cpumask);
|
||||
v->arch.schedule_tail = continue_idle_task;
|
||||
cpu_set(smp_processor_id(), v->domain->domain_dirty_cpumask);
|
||||
cpu_set(smp_processor_id(), v->vcpu_dirty_cpumask);
|
||||
v->arch.schedule_tail = continue_idle_domain;
|
||||
|
||||
idle_loop();
|
||||
reset_stack_and_jump(idle_loop);
|
||||
}
|
||||
|
||||
static long no_idt[2];
|
||||
@@ -185,11 +184,17 @@ void dump_pageframe_info(struct domain *d)
|
||||
{
|
||||
struct pfn_info *page;
|
||||
|
||||
if ( d->tot_pages < 10 )
|
||||
printk("Memory pages belonging to domain %u:\n", d->domain_id);
|
||||
|
||||
if ( d->tot_pages >= 10 )
|
||||
{
|
||||
printk(" DomPage list too long to display\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
list_for_each_entry ( page, &d->page_list, list )
|
||||
{
|
||||
printk("Page %p: mfn=%p, caf=%08x, taf=%" PRtype_info "\n",
|
||||
printk(" DomPage %p: mfn=%p, caf=%08x, taf=%" PRtype_info "\n",
|
||||
_p(page_to_phys(page)), _p(page_to_pfn(page)),
|
||||
page->count_info, page->u.inuse.type_info);
|
||||
}
|
||||
@@ -197,15 +202,10 @@ void dump_pageframe_info(struct domain *d)
|
||||
|
||||
list_for_each_entry ( page, &d->xenpage_list, list )
|
||||
{
|
||||
printk("XenPage %p: mfn=%p, caf=%08x, taf=%" PRtype_info "\n",
|
||||
printk(" XenPage %p: mfn=%p, caf=%08x, taf=%" PRtype_info "\n",
|
||||
_p(page_to_phys(page)), _p(page_to_pfn(page)),
|
||||
page->count_info, page->u.inuse.type_info);
|
||||
}
|
||||
|
||||
page = virt_to_page(d->shared_info);
|
||||
printk("Shared_info@%p: mfn=%p, caf=%08x, taf=%" PRtype_info "\n",
|
||||
_p(page_to_phys(page)), _p(page_to_pfn(page)), page->count_info,
|
||||
page->u.inuse.type_info);
|
||||
}
|
||||
|
||||
struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id)
|
||||
@@ -250,24 +250,36 @@ void free_perdomain_pt(struct domain *d)
|
||||
#endif
|
||||
}
|
||||
|
||||
void arch_do_createdomain(struct vcpu *v)
|
||||
int arch_do_createdomain(struct vcpu *v)
|
||||
{
|
||||
struct domain *d = v->domain;
|
||||
l1_pgentry_t gdt_l1e;
|
||||
int vcpuid, pdpt_order;
|
||||
int vcpuid, pdpt_order, rc;
|
||||
#ifdef __x86_64__
|
||||
int i;
|
||||
#endif
|
||||
|
||||
if ( is_idle_task(d) )
|
||||
return;
|
||||
if ( is_idle_domain(d) )
|
||||
return 0;
|
||||
|
||||
v->arch.schedule_tail = continue_nonidle_task;
|
||||
d->arch.ioport_caps =
|
||||
rangeset_new(d, "I/O Ports", RANGESETF_prettyprint_hex);
|
||||
if ( d->arch.ioport_caps == NULL )
|
||||
return -ENOMEM;
|
||||
|
||||
if ( (d->shared_info = alloc_xenheap_page()) == NULL )
|
||||
return -ENOMEM;
|
||||
|
||||
if ( (rc = ptwr_init(d)) != 0 )
|
||||
{
|
||||
free_xenheap_page(d->shared_info);
|
||||
return rc;
|
||||
}
|
||||
|
||||
v->arch.schedule_tail = continue_nonidle_domain;
|
||||
|
||||
d->shared_info = alloc_xenheap_page();
|
||||
memset(d->shared_info, 0, PAGE_SIZE);
|
||||
v->vcpu_info = &d->shared_info->vcpu_info[v->vcpu_id];
|
||||
v->cpumap = CPUMAP_RUNANYWHERE;
|
||||
SHARE_PFN_WITH_DOMAIN(virt_to_page(d->shared_info), d);
|
||||
|
||||
pdpt_order = get_order_from_bytes(PDPT_L1_ENTRIES * sizeof(l1_pgentry_t));
|
||||
@@ -308,25 +320,10 @@ void arch_do_createdomain(struct vcpu *v)
|
||||
__PAGE_HYPERVISOR);
|
||||
#endif
|
||||
|
||||
(void)ptwr_init(d);
|
||||
|
||||
shadow_lock_init(d);
|
||||
INIT_LIST_HEAD(&d->arch.free_shadow_frames);
|
||||
}
|
||||
|
||||
void vcpu_migrate_cpu(struct vcpu *v, int newcpu)
|
||||
{
|
||||
if ( v->processor == newcpu )
|
||||
return;
|
||||
|
||||
set_bit(_VCPUF_cpu_migrated, &v->vcpu_flags);
|
||||
v->processor = newcpu;
|
||||
|
||||
if ( VMX_DOMAIN(v) )
|
||||
{
|
||||
__vmpclear(virt_to_phys(v->arch.arch_vmx.vmcs));
|
||||
v->arch.schedule_tail = arch_vmx_do_relaunch;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is called by arch_final_setup_guest and do_boot_vcpu */
|
||||
@@ -348,6 +345,8 @@ int arch_set_info_guest(
|
||||
((c->user_regs.ss & 3) == 0) )
|
||||
return -EINVAL;
|
||||
}
|
||||
else if ( !hvm_enabled )
|
||||
return -EINVAL;
|
||||
|
||||
clear_bit(_VCPUF_fpu_initialised, &v->vcpu_flags);
|
||||
if ( c->flags & VGCF_I387_VALID )
|
||||
@@ -690,7 +689,7 @@ static void __context_switch(void)
|
||||
struct vcpu *p = percpu_ctxt[cpu].curr_vcpu;
|
||||
struct vcpu *n = current;
|
||||
|
||||
if ( !is_idle_task(p->domain) )
|
||||
if ( !is_idle_domain(p->domain) )
|
||||
{
|
||||
memcpy(&p->arch.guest_context.user_regs,
|
||||
stack_regs,
|
||||
@@ -699,7 +698,7 @@ static void __context_switch(void)
|
||||
save_segments(p);
|
||||
}
|
||||
|
||||
if ( !is_idle_task(n->domain) )
|
||||
if ( !is_idle_domain(n->domain) )
|
||||
{
|
||||
memcpy(stack_regs,
|
||||
&n->arch.guest_context.user_regs,
|
||||
@@ -725,7 +724,8 @@ static void __context_switch(void)
|
||||
}
|
||||
|
||||
if ( p->domain != n->domain )
|
||||
cpu_set(cpu, n->domain->cpumask);
|
||||
cpu_set(cpu, n->domain->domain_dirty_cpumask);
|
||||
cpu_set(cpu, n->vcpu_dirty_cpumask);
|
||||
|
||||
write_ptbase(n);
|
||||
|
||||
@@ -738,7 +738,8 @@ static void __context_switch(void)
|
||||
}
|
||||
|
||||
if ( p->domain != n->domain )
|
||||
cpu_clear(cpu, p->domain->cpumask);
|
||||
cpu_clear(cpu, p->domain->domain_dirty_cpumask);
|
||||
cpu_clear(cpu, p->vcpu_dirty_cpumask);
|
||||
|
||||
percpu_ctxt[cpu].curr_vcpu = n;
|
||||
}
|
||||
@@ -748,28 +749,24 @@ void context_switch(struct vcpu *prev, struct vcpu *next)
|
||||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
ASSERT(!local_irq_is_enabled());
|
||||
ASSERT(local_irq_is_enabled());
|
||||
|
||||
set_current(next);
|
||||
|
||||
if ( (percpu_ctxt[cpu].curr_vcpu != next) && !is_idle_task(next->domain) )
|
||||
if ( (percpu_ctxt[cpu].curr_vcpu != next) &&
|
||||
!is_idle_domain(next->domain) )
|
||||
{
|
||||
/* This may happen if next has been migrated by the scheduler. */
|
||||
if ( unlikely(!cpus_empty(next->vcpu_dirty_cpumask)) )
|
||||
{
|
||||
ASSERT(!cpu_isset(cpu, next->vcpu_dirty_cpumask));
|
||||
sync_vcpu_execstate(next);
|
||||
ASSERT(cpus_empty(next->vcpu_dirty_cpumask));
|
||||
}
|
||||
|
||||
local_irq_disable();
|
||||
__context_switch();
|
||||
percpu_ctxt[cpu].context_not_finalised = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void context_switch_finalise(struct vcpu *next)
|
||||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
ASSERT(local_irq_is_enabled());
|
||||
|
||||
if ( percpu_ctxt[cpu].context_not_finalised )
|
||||
{
|
||||
percpu_ctxt[cpu].context_not_finalised = 0;
|
||||
|
||||
BUG_ON(percpu_ctxt[cpu].curr_vcpu != next);
|
||||
local_irq_enable();
|
||||
|
||||
if ( VMX_DOMAIN(next) )
|
||||
{
|
||||
@@ -783,6 +780,8 @@ void context_switch_finalise(struct vcpu *next)
|
||||
}
|
||||
}
|
||||
|
||||
context_saved(prev);
|
||||
|
||||
schedule_tail(next);
|
||||
BUG();
|
||||
}
|
||||
@@ -812,20 +811,11 @@ int __sync_lazy_execstate(void)
|
||||
|
||||
void sync_vcpu_execstate(struct vcpu *v)
|
||||
{
|
||||
unsigned int cpu = v->processor;
|
||||
|
||||
if ( !cpu_isset(cpu, v->domain->cpumask) )
|
||||
return;
|
||||
|
||||
if ( cpu == smp_processor_id() )
|
||||
{
|
||||
if ( cpu_isset(smp_processor_id(), v->vcpu_dirty_cpumask) )
|
||||
(void)__sync_lazy_execstate();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Other cpus call __sync_lazy_execstate from flush ipi handler. */
|
||||
flush_tlb_mask(cpumask_of_cpu(cpu));
|
||||
}
|
||||
|
||||
/* Other cpus call __sync_lazy_execstate from flush ipi handler. */
|
||||
flush_tlb_mask(v->vcpu_dirty_cpumask);
|
||||
}
|
||||
|
||||
unsigned long __hypercall_create_continuation(
|
||||
@@ -951,9 +941,7 @@ void domain_relinquish_resources(struct domain *d)
|
||||
struct vcpu *v;
|
||||
unsigned long pfn;
|
||||
|
||||
BUG_ON(!cpus_empty(d->cpumask));
|
||||
|
||||
physdev_destroy_state(d);
|
||||
BUG_ON(!cpus_empty(d->domain_dirty_cpumask));
|
||||
|
||||
ptwr_destroy(d);
|
||||
|
||||
|
||||
+19
-14
@@ -16,13 +16,13 @@
|
||||
#include <xen/kernel.h>
|
||||
#include <xen/domain.h>
|
||||
#include <xen/compile.h>
|
||||
#include <xen/iocap.h>
|
||||
#include <asm/regs.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/desc.h>
|
||||
#include <asm/i387.h>
|
||||
#include <asm/physdev.h>
|
||||
#include <asm/shadow.h>
|
||||
|
||||
static long dom0_nrpages;
|
||||
@@ -94,9 +94,9 @@ static struct pfn_info *alloc_chunk(struct domain *d, unsigned long max_pages)
|
||||
return page;
|
||||
}
|
||||
|
||||
static void process_dom0_ioports_disable()
|
||||
static void process_dom0_ioports_disable(void)
|
||||
{
|
||||
unsigned long io_from, io_to, io_nr;
|
||||
unsigned long io_from, io_to;
|
||||
char *t, *u, *s = opt_dom0_ioports_disable;
|
||||
|
||||
if ( *s == '\0' )
|
||||
@@ -126,8 +126,8 @@ static void process_dom0_ioports_disable()
|
||||
printk("Disabling dom0 access to ioport range %04lx-%04lx\n",
|
||||
io_from, io_to);
|
||||
|
||||
io_nr = io_to - io_from + 1;
|
||||
physdev_modify_ioport_access_range(dom0, 0, io_from, io_nr);
|
||||
if ( ioports_deny_access(dom0, io_from, io_to) != 0 )
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,7 +183,6 @@ int construct_dom0(struct domain *d,
|
||||
/* Machine address of next candidate page-table page. */
|
||||
unsigned long mpt_alloc;
|
||||
|
||||
extern void physdev_init_dom0(struct domain *);
|
||||
extern void translate_l2pgtable(
|
||||
struct domain *d, l1_pgentry_t *p2m, unsigned long l2mfn);
|
||||
|
||||
@@ -692,9 +691,6 @@ int construct_dom0(struct domain *d,
|
||||
zap_low_mappings(l2start);
|
||||
zap_low_mappings(idle_pg_table_l2);
|
||||
#endif
|
||||
|
||||
/* DOM0 gets access to everything. */
|
||||
physdev_init_dom0(d);
|
||||
|
||||
init_domain_time(d);
|
||||
|
||||
@@ -746,20 +742,29 @@ int construct_dom0(struct domain *d,
|
||||
printk("dom0: shadow setup done\n");
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
/* DOM0 is permitted full I/O capabilities. */
|
||||
i |= ioports_permit_access(dom0, 0, 0xFFFF);
|
||||
i |= iomem_permit_access(dom0, 0UL, ~0UL);
|
||||
i |= irqs_permit_access(dom0, 0, NR_PIRQS-1);
|
||||
|
||||
/*
|
||||
* Modify I/O port access permissions.
|
||||
*/
|
||||
/* Master Interrupt Controller (PIC). */
|
||||
physdev_modify_ioport_access_range(dom0, 0, 0x20, 2);
|
||||
i |= ioports_deny_access(dom0, 0x20, 0x21);
|
||||
/* Slave Interrupt Controller (PIC). */
|
||||
physdev_modify_ioport_access_range(dom0, 0, 0xA0, 2);
|
||||
i |= ioports_deny_access(dom0, 0xA0, 0xA1);
|
||||
/* Interval Timer (PIT). */
|
||||
physdev_modify_ioport_access_range(dom0, 0, 0x40, 4);
|
||||
i |= ioports_deny_access(dom0, 0x40, 0x43);
|
||||
/* PIT Channel 2 / PC Speaker Control. */
|
||||
physdev_modify_ioport_access_range(dom0, 0, 0x61, 1);
|
||||
/* Command-line passed i/o ranges */
|
||||
i |= ioports_deny_access(dom0, 0x61, 0x61);
|
||||
/* Command-line I/O ranges. */
|
||||
process_dom0_ioports_disable();
|
||||
|
||||
BUG_ON(i != 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ struct domain idle0_domain = {
|
||||
|
||||
struct vcpu idle0_vcpu = {
|
||||
processor: 0,
|
||||
cpu_affinity:CPU_MASK_CPU0,
|
||||
domain: &idle0_domain
|
||||
};
|
||||
|
||||
|
||||
@@ -1807,3 +1807,47 @@ int ioapic_guest_write(int apicid, int address, u32 val)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dump_ioapic_irq_info(void)
|
||||
{
|
||||
struct irq_pin_list *entry;
|
||||
struct IO_APIC_route_entry rte;
|
||||
unsigned int irq, pin, printed = 0;
|
||||
unsigned long flags;
|
||||
|
||||
for ( irq = 0; irq < NR_IRQS; irq++ )
|
||||
{
|
||||
entry = &irq_2_pin[irq];
|
||||
if ( entry->pin == -1 )
|
||||
continue;
|
||||
|
||||
if ( !printed++ )
|
||||
printk("IO-APIC interrupt information:\n");
|
||||
|
||||
printk(" IRQ%3d Vec%3d:\n", irq, irq_to_vector(irq));
|
||||
|
||||
for ( ; ; )
|
||||
{
|
||||
pin = entry->pin;
|
||||
|
||||
printk(" Apic 0x%02x, Pin %2d: ", entry->apic, pin);
|
||||
|
||||
spin_lock_irqsave(&ioapic_lock, flags);
|
||||
*(((int *)&rte) + 0) = io_apic_read(entry->apic, 0x10 + 2 * pin);
|
||||
*(((int *)&rte) + 1) = io_apic_read(entry->apic, 0x11 + 2 * pin);
|
||||
spin_unlock_irqrestore(&ioapic_lock, flags);
|
||||
|
||||
printk("vector=%u, delivery_mode=%u, dest_mode=%s, "
|
||||
"delivery_status=%d, polarity=%d, irr=%d, "
|
||||
"trigger=%s, mask=%d\n",
|
||||
rte.vector, rte.delivery_mode,
|
||||
rte.dest_mode ? "logical" : "physical",
|
||||
rte.delivery_status, rte.polarity, rte.irr,
|
||||
rte.trigger ? "level" : "edge", rte.mask);
|
||||
|
||||
if ( entry->next == 0 )
|
||||
break;
|
||||
entry = &irq_2_pin[entry->next];
|
||||
}
|
||||
}
|
||||
}
|
||||
+77
-6
@@ -12,6 +12,7 @@
|
||||
#include <xen/irq.h>
|
||||
#include <xen/perfc.h>
|
||||
#include <xen/sched.h>
|
||||
#include <xen/keyhandler.h>
|
||||
#include <asm/current.h>
|
||||
#include <asm/smpboot.h>
|
||||
|
||||
@@ -198,19 +199,21 @@ int pirq_guest_unmask(struct domain *d)
|
||||
|
||||
int pirq_guest_bind(struct vcpu *v, int irq, int will_share)
|
||||
{
|
||||
unsigned int vector = irq_to_vector(irq);
|
||||
struct domain *d = v->domain;
|
||||
irq_desc_t *desc = &irq_desc[vector];
|
||||
unsigned int vector;
|
||||
irq_desc_t *desc;
|
||||
irq_guest_action_t *action;
|
||||
unsigned long flags;
|
||||
int rc = 0;
|
||||
cpumask_t cpumask = CPU_MASK_NONE;
|
||||
|
||||
if ( !IS_CAPABLE_PHYSDEV(d) )
|
||||
return -EPERM;
|
||||
if ( (irq < 0) || (irq >= NR_IRQS) )
|
||||
return -EINVAL;
|
||||
|
||||
vector = irq_to_vector(irq);
|
||||
if ( vector == 0 )
|
||||
return -EBUSY;
|
||||
return -EINVAL;
|
||||
|
||||
desc = &irq_desc[vector];
|
||||
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
|
||||
@@ -309,3 +312,71 @@ int pirq_guest_unbind(struct domain *d, int irq)
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern void dump_ioapic_irq_info(void);
|
||||
|
||||
static void dump_irqs(unsigned char key)
|
||||
{
|
||||
int i, irq, vector;
|
||||
irq_desc_t *desc;
|
||||
irq_guest_action_t *action;
|
||||
struct domain *d;
|
||||
unsigned long flags;
|
||||
|
||||
printk("Guest interrupt information:\n");
|
||||
|
||||
for ( irq = 0; irq < NR_IRQS; irq++ )
|
||||
{
|
||||
vector = irq_to_vector(irq);
|
||||
if ( vector == 0 )
|
||||
continue;
|
||||
|
||||
desc = &irq_desc[vector];
|
||||
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
|
||||
if ( desc->status & IRQ_GUEST )
|
||||
{
|
||||
action = (irq_guest_action_t *)desc->action;
|
||||
|
||||
printk(" IRQ%3d Vec%3d: type=%-15s status=%08x "
|
||||
"in-flight=%d domain-list=",
|
||||
irq, vector, desc->handler->typename,
|
||||
desc->status, action->in_flight);
|
||||
|
||||
for ( i = 0; i < action->nr_guests; i++ )
|
||||
{
|
||||
d = action->guest[i];
|
||||
printk("%u(%c%c%c%c)",
|
||||
d->domain_id,
|
||||
(test_bit(d->pirq_to_evtchn[irq],
|
||||
&d->shared_info->evtchn_pending[0]) ?
|
||||
'P' : '-'),
|
||||
(test_bit(d->pirq_to_evtchn[irq]/BITS_PER_LONG,
|
||||
&d->shared_info->vcpu_info[0].
|
||||
evtchn_pending_sel) ?
|
||||
'S' : '-'),
|
||||
(test_bit(d->pirq_to_evtchn[irq],
|
||||
&d->shared_info->evtchn_mask[0]) ?
|
||||
'M' : '-'),
|
||||
(test_bit(irq, &d->pirq_mask) ?
|
||||
'M' : '-'));
|
||||
if ( i != action->nr_guests )
|
||||
printk(",");
|
||||
}
|
||||
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
}
|
||||
|
||||
dump_ioapic_irq_info();
|
||||
}
|
||||
|
||||
static int __init setup_dump_irqs(void)
|
||||
{
|
||||
register_keyhandler('i', dump_irqs, "dump interrupt bindings");
|
||||
return 0;
|
||||
}
|
||||
__initcall(setup_dump_irqs);
|
||||
+16
-19
@@ -96,6 +96,7 @@
|
||||
#include <xen/softirq.h>
|
||||
#include <xen/domain_page.h>
|
||||
#include <xen/event.h>
|
||||
#include <xen/iocap.h>
|
||||
#include <asm/shadow.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/flushtlb.h>
|
||||
@@ -437,7 +438,6 @@ get_page_from_l1e(
|
||||
unsigned long mfn = l1e_get_pfn(l1e);
|
||||
struct pfn_info *page = pfn_to_page(mfn);
|
||||
int okay;
|
||||
extern int domain_iomem_in_pfn(struct domain *d, unsigned long pfn);
|
||||
|
||||
if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) )
|
||||
return 1;
|
||||
@@ -455,8 +455,7 @@ get_page_from_l1e(
|
||||
if ( d == dom_io )
|
||||
d = current->domain;
|
||||
|
||||
if ( (!IS_PRIV(d)) &&
|
||||
(!IS_CAPABLE_PHYSDEV(d) || !domain_iomem_in_pfn(d, mfn)) )
|
||||
if ( !iomem_access_permitted(d, mfn, mfn) )
|
||||
{
|
||||
MEM_LOG("Non-privileged attempt to map I/O space %08lx", mfn);
|
||||
return 0;
|
||||
@@ -1458,7 +1457,8 @@ int get_page_type(struct pfn_info *page, unsigned long type)
|
||||
* was GDT/LDT) but those circumstances should be
|
||||
* very rare.
|
||||
*/
|
||||
cpumask_t mask = page_get_owner(page)->cpumask;
|
||||
cpumask_t mask =
|
||||
page_get_owner(page)->domain_dirty_cpumask;
|
||||
tlbflush_filter(mask, page->tlbflush_timestamp);
|
||||
|
||||
if ( unlikely(!cpus_empty(mask)) )
|
||||
@@ -1620,7 +1620,7 @@ static void process_deferred_ops(unsigned int cpu)
|
||||
if ( shadow_mode_enabled(d) )
|
||||
shadow_sync_all(d);
|
||||
if ( deferred_ops & DOP_FLUSH_ALL_TLBS )
|
||||
flush_tlb_mask(d->cpumask);
|
||||
flush_tlb_mask(d->domain_dirty_cpumask);
|
||||
else
|
||||
local_flush_tlb();
|
||||
}
|
||||
@@ -1692,7 +1692,7 @@ static inline cpumask_t vcpumask_to_pcpumask(
|
||||
struct domain *d, unsigned long vmask)
|
||||
{
|
||||
unsigned int vcpu_id;
|
||||
cpumask_t pmask;
|
||||
cpumask_t pmask = CPU_MASK_NONE;
|
||||
struct vcpu *v;
|
||||
|
||||
while ( vmask != 0 )
|
||||
@@ -1701,7 +1701,7 @@ static inline cpumask_t vcpumask_to_pcpumask(
|
||||
vmask &= ~(1UL << vcpu_id);
|
||||
if ( (vcpu_id < MAX_VIRT_CPUS) &&
|
||||
((v = d->vcpu[vcpu_id]) != NULL) )
|
||||
cpu_set(v->processor, pmask);
|
||||
cpus_or(pmask, pmask, v->vcpu_dirty_cpumask);
|
||||
}
|
||||
|
||||
return pmask;
|
||||
@@ -1870,7 +1870,6 @@ int do_mmuext_op(
|
||||
break;
|
||||
}
|
||||
pmask = vcpumask_to_pcpumask(d, vmask);
|
||||
cpus_and(pmask, pmask, d->cpumask);
|
||||
if ( op.cmd == MMUEXT_TLB_FLUSH_MULTI )
|
||||
flush_tlb_mask(pmask);
|
||||
else
|
||||
@@ -1879,15 +1878,15 @@ int do_mmuext_op(
|
||||
}
|
||||
|
||||
case MMUEXT_TLB_FLUSH_ALL:
|
||||
flush_tlb_mask(d->cpumask);
|
||||
flush_tlb_mask(d->domain_dirty_cpumask);
|
||||
break;
|
||||
|
||||
case MMUEXT_INVLPG_ALL:
|
||||
flush_tlb_one_mask(d->cpumask, op.arg1.linear_addr);
|
||||
flush_tlb_one_mask(d->domain_dirty_cpumask, op.arg1.linear_addr);
|
||||
break;
|
||||
|
||||
case MMUEXT_FLUSH_CACHE:
|
||||
if ( unlikely(!IS_CAPABLE_PHYSDEV(d)) )
|
||||
if ( unlikely(!cache_flush_permitted(d)) )
|
||||
{
|
||||
MEM_LOG("Non-physdev domain tried to FLUSH_CACHE.");
|
||||
okay = 0;
|
||||
@@ -2498,7 +2497,7 @@ int do_update_va_mapping(unsigned long va, u64 val64,
|
||||
l1_pgentry_t val = l1e_from_intpte(val64);
|
||||
struct vcpu *v = current;
|
||||
struct domain *d = v->domain;
|
||||
unsigned int cpu = v->processor;
|
||||
unsigned int cpu = smp_processor_id();
|
||||
unsigned long vmask, bmap_ptr;
|
||||
cpumask_t pmask;
|
||||
int rc = 0;
|
||||
@@ -2549,13 +2548,12 @@ int do_update_va_mapping(unsigned long va, u64 val64,
|
||||
local_flush_tlb();
|
||||
break;
|
||||
case UVMF_ALL:
|
||||
flush_tlb_mask(d->cpumask);
|
||||
flush_tlb_mask(d->domain_dirty_cpumask);
|
||||
break;
|
||||
default:
|
||||
if ( unlikely(get_user(vmask, (unsigned long *)bmap_ptr)) )
|
||||
rc = -EFAULT;
|
||||
pmask = vcpumask_to_pcpumask(d, vmask);
|
||||
cpus_and(pmask, pmask, d->cpumask);
|
||||
flush_tlb_mask(pmask);
|
||||
break;
|
||||
}
|
||||
@@ -2570,13 +2568,12 @@ int do_update_va_mapping(unsigned long va, u64 val64,
|
||||
local_flush_tlb_one(va);
|
||||
break;
|
||||
case UVMF_ALL:
|
||||
flush_tlb_one_mask(d->cpumask, va);
|
||||
flush_tlb_one_mask(d->domain_dirty_cpumask, va);
|
||||
break;
|
||||
default:
|
||||
if ( unlikely(get_user(vmask, (unsigned long *)bmap_ptr)) )
|
||||
rc = -EFAULT;
|
||||
pmask = vcpumask_to_pcpumask(d, vmask);
|
||||
cpus_and(pmask, pmask, d->cpumask);
|
||||
flush_tlb_one_mask(pmask, va);
|
||||
break;
|
||||
}
|
||||
@@ -3019,7 +3016,7 @@ void ptwr_flush(struct domain *d, const int which)
|
||||
|
||||
/* Ensure that there are no stale writable mappings in any TLB. */
|
||||
/* NB. INVLPG is a serialising instruction: flushes pending updates. */
|
||||
flush_tlb_one_mask(d->cpumask, l1va);
|
||||
flush_tlb_one_mask(d->domain_dirty_cpumask, l1va);
|
||||
PTWR_PRINTK("[%c] disconnected_l1va at %p now %"PRIpte"\n",
|
||||
PTWR_PRINT_WHICH, ptep, pte.l1);
|
||||
|
||||
@@ -3343,7 +3340,7 @@ int ptwr_do_page_fault(struct domain *d, unsigned long addr,
|
||||
if ( which == PTWR_PT_ACTIVE )
|
||||
{
|
||||
l2e_remove_flags(*pl2e, _PAGE_PRESENT);
|
||||
flush_tlb_mask(d->cpumask);
|
||||
flush_tlb_mask(d->domain_dirty_cpumask);
|
||||
}
|
||||
|
||||
/* Temporarily map the L1 page, and make a copy of it. */
|
||||
@@ -3370,7 +3367,7 @@ int ptwr_do_page_fault(struct domain *d, unsigned long addr,
|
||||
|
||||
emulate:
|
||||
if ( x86_emulate_memop(guest_cpu_user_regs(), addr,
|
||||
&ptwr_mem_emulator, BITS_PER_LONG/8) )
|
||||
&ptwr_mem_emulator, X86EMUL_MODE_HOST) )
|
||||
return 0;
|
||||
perfc_incrc(ptwr_emulations);
|
||||
return EXCRET_fault_fixed;
|
||||
|
||||
@@ -14,27 +14,6 @@
|
||||
extern int ioapic_guest_read(int apicid, int address, u32 *pval);
|
||||
extern int ioapic_guest_write(int apicid, int address, u32 pval);
|
||||
|
||||
void physdev_modify_ioport_access_range(
|
||||
struct domain *d, int enable, int port, int num)
|
||||
{
|
||||
int i;
|
||||
for ( i = port; i < (port + num); i++ )
|
||||
(enable ? clear_bit : set_bit)(i, d->arch.iobmp_mask);
|
||||
}
|
||||
|
||||
void physdev_destroy_state(struct domain *d)
|
||||
{
|
||||
xfree(d->arch.iobmp_mask);
|
||||
d->arch.iobmp_mask = NULL;
|
||||
}
|
||||
|
||||
/* Check if a domain controls a device with IO memory within frame @pfn.
|
||||
* Returns: 1 if the domain should be allowed to map @pfn, 0 otherwise. */
|
||||
int domain_iomem_in_pfn(struct domain *p, unsigned long pfn)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Demuxing hypercall.
|
||||
*/
|
||||
@@ -120,18 +99,6 @@ long do_physdev_op(physdev_op_t *uop)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Domain 0 has read access to all devices. */
|
||||
void physdev_init_dom0(struct domain *d)
|
||||
{
|
||||
/* Access to all I/O ports. */
|
||||
d->arch.iobmp_mask = xmalloc_array(u8, IOBMP_BYTES);
|
||||
BUG_ON(d->arch.iobmp_mask == NULL);
|
||||
memset(d->arch.iobmp_mask, 0, IOBMP_BYTES);
|
||||
|
||||
set_bit(_DOMF_physdev_access, &d->domain_flags);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
|
||||
+117
-117
@@ -92,7 +92,7 @@ unsigned long mmu_cr4_features = X86_CR4_PSE;
|
||||
#endif
|
||||
EXPORT_SYMBOL(mmu_cr4_features);
|
||||
|
||||
struct vcpu *idle_task[NR_CPUS] = { &idle0_vcpu };
|
||||
struct vcpu *idle_domain[NR_CPUS] = { &idle0_vcpu };
|
||||
|
||||
int acpi_disabled;
|
||||
|
||||
@@ -138,131 +138,19 @@ static void __init do_initcalls(void)
|
||||
(*call)();
|
||||
}
|
||||
|
||||
static void __init start_of_day(void)
|
||||
{
|
||||
int i;
|
||||
unsigned long vgdt, gdt_pfn;
|
||||
|
||||
early_cpu_init();
|
||||
|
||||
paging_init();
|
||||
|
||||
/* Unmap the first page of CPU0's stack. */
|
||||
memguard_guard_stack(cpu0_stack);
|
||||
|
||||
open_softirq(NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ, new_tlbflush_clock_period);
|
||||
|
||||
if ( opt_watchdog )
|
||||
nmi_watchdog = NMI_LOCAL_APIC;
|
||||
|
||||
sort_exception_tables();
|
||||
|
||||
arch_do_createdomain(current);
|
||||
|
||||
/*
|
||||
* Map default GDT into its final positions in the idle page table. As
|
||||
* noted in arch_do_createdomain(), we must map for every possible VCPU#.
|
||||
*/
|
||||
vgdt = GDT_VIRT_START(current) + FIRST_RESERVED_GDT_BYTE;
|
||||
gdt_pfn = virt_to_phys(gdt_table) >> PAGE_SHIFT;
|
||||
for ( i = 0; i < MAX_VIRT_CPUS; i++ )
|
||||
{
|
||||
map_pages_to_xen(vgdt, gdt_pfn, 1, PAGE_HYPERVISOR);
|
||||
vgdt += 1 << PDPT_VCPU_VA_SHIFT;
|
||||
}
|
||||
|
||||
find_smp_config();
|
||||
|
||||
smp_alloc_memory();
|
||||
|
||||
dmi_scan_machine();
|
||||
|
||||
generic_apic_probe();
|
||||
|
||||
acpi_boot_table_init();
|
||||
acpi_boot_init();
|
||||
|
||||
if ( smp_found_config )
|
||||
get_smp_config();
|
||||
|
||||
init_apic_mappings();
|
||||
|
||||
init_IRQ();
|
||||
|
||||
trap_init();
|
||||
|
||||
ac_timer_init();
|
||||
|
||||
early_time_init();
|
||||
|
||||
arch_init_memory();
|
||||
|
||||
scheduler_init();
|
||||
|
||||
identify_cpu(&boot_cpu_data);
|
||||
if ( cpu_has_fxsr )
|
||||
set_in_cr4(X86_CR4_OSFXSR);
|
||||
if ( cpu_has_xmm )
|
||||
set_in_cr4(X86_CR4_OSXMMEXCPT);
|
||||
|
||||
if ( opt_nosmp )
|
||||
{
|
||||
max_cpus = 0;
|
||||
smp_num_siblings = 1;
|
||||
boot_cpu_data.x86_num_cores = 1;
|
||||
}
|
||||
|
||||
smp_prepare_cpus(max_cpus);
|
||||
|
||||
/* We aren't hotplug-capable yet. */
|
||||
BUG_ON(!cpus_empty(cpu_present_map));
|
||||
for_each_cpu ( i )
|
||||
cpu_set(i, cpu_present_map);
|
||||
|
||||
/*
|
||||
* Initialise higher-level timer functions. We do this fairly late
|
||||
* (post-SMP) because the time bases and scale factors need to be updated
|
||||
* regularly, and SMP initialisation can cause a long delay with
|
||||
* interrupts not yet enabled.
|
||||
*/
|
||||
init_xen_time();
|
||||
|
||||
initialize_keytable();
|
||||
|
||||
serial_init_postirq();
|
||||
|
||||
BUG_ON(!local_irq_is_enabled());
|
||||
|
||||
for_each_present_cpu ( i )
|
||||
{
|
||||
if ( num_online_cpus() >= max_cpus )
|
||||
break;
|
||||
if ( !cpu_online(i) )
|
||||
__cpu_up(i);
|
||||
}
|
||||
|
||||
printk("Brought up %ld CPUs\n", (long)num_online_cpus());
|
||||
smp_cpus_done(max_cpus);
|
||||
|
||||
do_initcalls();
|
||||
|
||||
schedulers_start();
|
||||
|
||||
watchdog_enable();
|
||||
}
|
||||
|
||||
#define EARLY_FAIL() for ( ; ; ) __asm__ __volatile__ ( "hlt" )
|
||||
|
||||
static struct e820entry e820_raw[E820MAX];
|
||||
|
||||
void __init __start_xen(multiboot_info_t *mbi)
|
||||
{
|
||||
unsigned long vgdt, gdt_pfn;
|
||||
char *cmdline;
|
||||
unsigned long _initrd_start = 0, _initrd_len = 0;
|
||||
unsigned int initrdidx = 1;
|
||||
module_t *mod = (module_t *)__va(mbi->mods_addr);
|
||||
unsigned long nr_pages, modules_length;
|
||||
unsigned long initial_images_start, initial_images_end;
|
||||
unsigned long _initrd_start = 0, _initrd_len = 0;
|
||||
unsigned int initrdidx = 1;
|
||||
physaddr_t s, e;
|
||||
int i, e820_warn = 0, e820_raw_nr = 0, bytes = 0;
|
||||
struct ns16550_defaults ns16550 = {
|
||||
@@ -455,6 +343,12 @@ void __init __start_xen(multiboot_info_t *mbi)
|
||||
BUG_ON(sizeof(shared_info_t) > PAGE_SIZE);
|
||||
BUG_ON(sizeof(vcpu_info_t) != 64);
|
||||
|
||||
/* __foo are defined in public headers. Check they match internal defs. */
|
||||
BUG_ON(__HYPERVISOR_VIRT_START != HYPERVISOR_VIRT_START);
|
||||
#ifdef HYPERVISOR_VIRT_END
|
||||
BUG_ON(__HYPERVISOR_VIRT_END != HYPERVISOR_VIRT_END);
|
||||
#endif
|
||||
|
||||
init_frametable();
|
||||
|
||||
end_boot_allocator();
|
||||
@@ -486,7 +380,113 @@ void __init __start_xen(multiboot_info_t *mbi)
|
||||
|
||||
early_boot = 0;
|
||||
|
||||
start_of_day();
|
||||
early_cpu_init();
|
||||
|
||||
paging_init();
|
||||
|
||||
/* Unmap the first page of CPU0's stack. */
|
||||
memguard_guard_stack(cpu0_stack);
|
||||
|
||||
open_softirq(NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ, new_tlbflush_clock_period);
|
||||
|
||||
if ( opt_watchdog )
|
||||
nmi_watchdog = NMI_LOCAL_APIC;
|
||||
|
||||
sort_exception_tables();
|
||||
|
||||
if ( arch_do_createdomain(current) != 0 )
|
||||
BUG();
|
||||
|
||||
/*
|
||||
* Map default GDT into its final positions in the idle page table. As
|
||||
* noted in arch_do_createdomain(), we must map for every possible VCPU#.
|
||||
*/
|
||||
vgdt = GDT_VIRT_START(current) + FIRST_RESERVED_GDT_BYTE;
|
||||
gdt_pfn = virt_to_phys(gdt_table) >> PAGE_SHIFT;
|
||||
for ( i = 0; i < MAX_VIRT_CPUS; i++ )
|
||||
{
|
||||
map_pages_to_xen(vgdt, gdt_pfn, 1, PAGE_HYPERVISOR);
|
||||
vgdt += 1 << PDPT_VCPU_VA_SHIFT;
|
||||
}
|
||||
|
||||
find_smp_config();
|
||||
|
||||
smp_alloc_memory();
|
||||
|
||||
dmi_scan_machine();
|
||||
|
||||
generic_apic_probe();
|
||||
|
||||
acpi_boot_table_init();
|
||||
acpi_boot_init();
|
||||
|
||||
if ( smp_found_config )
|
||||
get_smp_config();
|
||||
|
||||
init_apic_mappings();
|
||||
|
||||
init_IRQ();
|
||||
|
||||
trap_init();
|
||||
|
||||
ac_timer_init();
|
||||
|
||||
early_time_init();
|
||||
|
||||
arch_init_memory();
|
||||
|
||||
scheduler_init();
|
||||
|
||||
identify_cpu(&boot_cpu_data);
|
||||
if ( cpu_has_fxsr )
|
||||
set_in_cr4(X86_CR4_OSFXSR);
|
||||
if ( cpu_has_xmm )
|
||||
set_in_cr4(X86_CR4_OSXMMEXCPT);
|
||||
|
||||
if ( opt_nosmp )
|
||||
{
|
||||
max_cpus = 0;
|
||||
smp_num_siblings = 1;
|
||||
boot_cpu_data.x86_num_cores = 1;
|
||||
}
|
||||
|
||||
smp_prepare_cpus(max_cpus);
|
||||
|
||||
/* We aren't hotplug-capable yet. */
|
||||
BUG_ON(!cpus_empty(cpu_present_map));
|
||||
for_each_cpu ( i )
|
||||
cpu_set(i, cpu_present_map);
|
||||
|
||||
/*
|
||||
* Initialise higher-level timer functions. We do this fairly late
|
||||
* (post-SMP) because the time bases and scale factors need to be updated
|
||||
* regularly, and SMP initialisation can cause a long delay with
|
||||
* interrupts not yet enabled.
|
||||
*/
|
||||
init_xen_time();
|
||||
|
||||
initialize_keytable();
|
||||
|
||||
serial_init_postirq();
|
||||
|
||||
BUG_ON(!local_irq_is_enabled());
|
||||
|
||||
for_each_present_cpu ( i )
|
||||
{
|
||||
if ( num_online_cpus() >= max_cpus )
|
||||
break;
|
||||
if ( !cpu_online(i) )
|
||||
__cpu_up(i);
|
||||
}
|
||||
|
||||
printk("Brought up %ld CPUs\n", (long)num_online_cpus());
|
||||
smp_cpus_done(max_cpus);
|
||||
|
||||
do_initcalls();
|
||||
|
||||
schedulers_start();
|
||||
|
||||
watchdog_enable();
|
||||
|
||||
shadow_mode_init();
|
||||
|
||||
|
||||
@@ -1800,7 +1800,7 @@ static void sync_all(struct domain *d)
|
||||
}
|
||||
|
||||
/* Other VCPUs mustn't use the revoked writable mappings. */
|
||||
other_vcpus_mask = d->cpumask;
|
||||
other_vcpus_mask = d->domain_dirty_cpumask;
|
||||
cpu_clear(smp_processor_id(), other_vcpus_mask);
|
||||
flush_tlb_mask(other_vcpus_mask);
|
||||
|
||||
|
||||
Loaded 100 of 162 files, more files were not shown because too many files have changed in this diff.
Show more