From 75c73974d7d41d0d28c743ce3cb551c856c6d190 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Thu, 8 Mar 2007 15:35:28 +0000 Subject: [PATCH 001/170] [BUILDER]: Initialize code segment selectors in virtual IDT to 0. These should not be set until the guest kernel kernel configures an entry point otherwise the null_trap_bounce() check gets confused. This change was made to the old domain builder in 12455:3fa6635d04b9 but was lost in the transition to the new builder. Signed-off-by: Ian Campbell --- tools/libxc/xc_dom_x86.c | 30 ++++-------------------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/tools/libxc/xc_dom_x86.c b/tools/libxc/xc_dom_x86.c index 695e5a168d..19296daf10 100644 --- a/tools/libxc/xc_dom_x86.c +++ b/tools/libxc/xc_dom_x86.c @@ -433,24 +433,12 @@ static int vcpu_x86_32(struct xc_dom_image *dom, void *ptr) { vcpu_guest_context_x86_32_t *ctxt = ptr; xen_pfn_t cr3_pfn; - int i; xc_dom_printf("%s: called\n", __FUNCTION__); /* clear everything */ memset(ctxt, 0, sizeof(*ctxt)); - /* Virtual IDT is empty at start-of-day. */ - for ( i = 0; i < 256; i++ ) - { - ctxt->trap_ctxt[i].vector = i; - ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS_X86_32; - } - - /* No callback handlers. */ - ctxt->event_callback_cs = FLAT_KERNEL_CS_X86_32; - ctxt->failsafe_callback_cs = FLAT_KERNEL_CS_X86_32; - ctxt->user_regs.ds = FLAT_KERNEL_DS_X86_32; ctxt->user_regs.es = FLAT_KERNEL_DS_X86_32; ctxt->user_regs.fs = FLAT_KERNEL_DS_X86_32; @@ -464,9 +452,8 @@ static int vcpu_x86_32(struct xc_dom_image *dom, void *ptr) dom->parms.virt_base + (dom->start_info_pfn) * PAGE_SIZE_X86; ctxt->user_regs.eflags = 1 << 9; /* Interrupt Enable */ - ctxt->kernel_ss = FLAT_KERNEL_SS_X86_32; - ctxt->kernel_sp = - dom->parms.virt_base + (dom->bootstack_pfn + 1) * PAGE_SIZE_X86; + ctxt->kernel_ss = ctxt->user_regs.ss; + ctxt->kernel_sp = ctxt->user_regs.esp; ctxt->flags = VGCF_in_kernel_X86_32; if ( dom->parms.pae == 2 /* extended_cr3 */ || @@ -485,20 +472,12 @@ static int vcpu_x86_64(struct xc_dom_image *dom, void *ptr) { vcpu_guest_context_x86_64_t *ctxt = ptr; xen_pfn_t cr3_pfn; - int i; xc_dom_printf("%s: called\n", __FUNCTION__); /* clear everything */ memset(ctxt, 0, sizeof(*ctxt)); - /* Virtual IDT is empty at start-of-day. */ - for ( i = 0; i < 256; i++ ) - { - ctxt->trap_ctxt[i].vector = i; - ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS_X86_64; - } - ctxt->user_regs.ds = FLAT_KERNEL_DS_X86_64; ctxt->user_regs.es = FLAT_KERNEL_DS_X86_64; ctxt->user_regs.fs = FLAT_KERNEL_DS_X86_64; @@ -512,9 +491,8 @@ static int vcpu_x86_64(struct xc_dom_image *dom, void *ptr) dom->parms.virt_base + (dom->start_info_pfn) * PAGE_SIZE_X86; ctxt->user_regs.rflags = 1 << 9; /* Interrupt Enable */ - ctxt->kernel_ss = FLAT_KERNEL_SS_X86_64; - ctxt->kernel_sp = - dom->parms.virt_base + (dom->bootstack_pfn + 1) * PAGE_SIZE_X86; + ctxt->kernel_ss = ctxt->user_regs.ss; + ctxt->kernel_sp = ctxt->user_regs.esp; ctxt->flags = VGCF_in_kernel_X86_64; cr3_pfn = xc_dom_p2m_guest(dom, dom->pgtables_seg.pfn); From d861c10c24742a04e8452dd7fc09e961a0ec6be4 Mon Sep 17 00:00:00 2001 From: Christian Limpach Date: Thu, 8 Mar 2007 15:51:32 +0000 Subject: [PATCH 002/170] [xen] Update the hvm rtc clock state if the domain's time offset is changed. The settimeoffset domctl had no effect on hvm domains since the offset was only read in rtc_init which is done when the domain is created. Signed-off-by: Christian Limpach --- xen/arch/x86/hvm/rtc.c | 15 +++++++++++++-- xen/include/asm-x86/hvm/vpt.h | 1 + 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/hvm/rtc.c b/xen/arch/x86/hvm/rtc.c index 5cda6bbb75..036eba7bfe 100644 --- a/xen/arch/x86/hvm/rtc.c +++ b/xen/arch/x86/hvm/rtc.c @@ -174,6 +174,11 @@ static void rtc_copy_date(RTCState *s) { const struct tm *tm = &s->current_tm; + if (s->time_offset_seconds != s->pt.vcpu->domain->time_offset_seconds) { + s->current_tm = gmtime(get_localtime(s->pt.vcpu->domain)); + s->time_offset_seconds = s->pt.vcpu->domain->time_offset_seconds; + } + s->hw.cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec); s->hw.cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min); if ( s->hw.cmos_data[RTC_REG_B] & RTC_24H ) @@ -211,10 +216,16 @@ static int get_days_in_month(int month, int year) } /* update 'tm' to the next second */ -static void rtc_next_second(struct tm *tm) +static void rtc_next_second(RTCState *s) { + struct tm *tm = &s->current_tm; int days_in_month; + if (s->time_offset_seconds != s->pt.vcpu->domain->time_offset_seconds) { + s->current_tm = gmtime(get_localtime(s->pt.vcpu->domain)); + s->time_offset_seconds = s->pt.vcpu->domain->time_offset_seconds; + } + tm->tm_sec++; if ((unsigned)tm->tm_sec >= 60) { tm->tm_sec = 0; @@ -258,7 +269,7 @@ static void rtc_update_second(void *opaque) } else { - rtc_next_second(&s->current_tm); + rtc_next_second(s); if ( !(s->hw.cmos_data[RTC_REG_B] & RTC_SET) ) s->hw.cmos_data[RTC_REG_A] |= RTC_UIP; diff --git a/xen/include/asm-x86/hvm/vpt.h b/xen/include/asm-x86/hvm/vpt.h index 02bc3fa05c..bda54adfc3 100644 --- a/xen/include/asm-x86/hvm/vpt.h +++ b/xen/include/asm-x86/hvm/vpt.h @@ -92,6 +92,7 @@ typedef struct RTCState { struct timer second_timer; struct timer second_timer2; struct periodic_time pt; + int32_t time_offset_seconds; } RTCState; #define FREQUENCE_PMTIMER 3579545 /* Timer should run at 3.579545 MHz */ From 05b8af2e2c3ad661d605c0e58925e94ce8bb789b Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Thu, 8 Mar 2007 16:18:50 +0000 Subject: [PATCH 003/170] [XEN] Shadow: tidy up page_info before handing back to the allocator which expects count_info fields to be zero. Signed-off-by: Tim Deegan --- xen/arch/x86/mm/shadow/common.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c index f341fe3bc8..92bcc001ab 100644 --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -1129,6 +1129,7 @@ shadow_free_p2m_page(struct domain *d, struct page_info *pg) SHADOW_ERROR("Odd p2m page count c=%#x t=%"PRtype_info"\n", pg->count_info, pg->u.inuse.type_info); } + pg->count_info = 0; /* Free should not decrement domain's total allocation, since * these pages were allocated without an owner. */ page_set_owner(pg, NULL); @@ -1243,6 +1244,9 @@ static unsigned int sh_set_allocation(struct domain *d, list_del(&sp->list); d->arch.paging.shadow.free_pages -= 1<arch.paging.shadow.total_pages -= 1< Date: Thu, 8 Mar 2007 16:20:01 +0000 Subject: [PATCH 004/170] [XEN] Shadow: fix mark_dirty invocation to use gfn, not mfn Signed-off-by: Tim Deegan --- xen/arch/x86/hvm/hvm.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index f48bb6f49a..d03824bc0e 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -380,7 +380,7 @@ void hvm_triple_fault(void) */ static int __hvm_copy(void *buf, paddr_t addr, int size, int dir, int virt) { - unsigned long mfn; + unsigned long gfn, mfn; char *p; int count, todo; @@ -390,9 +390,11 @@ static int __hvm_copy(void *buf, paddr_t addr, int size, int dir, int virt) count = min_t(int, PAGE_SIZE - (addr & ~PAGE_MASK), todo); if ( virt ) - mfn = get_mfn_from_gpfn(paging_gva_to_gfn(current, addr)); + gfn = paging_gva_to_gfn(current, addr); else - mfn = get_mfn_from_gpfn(addr >> PAGE_SHIFT); + gfn = addr >> PAGE_SHIFT; + + mfn = get_mfn_from_gpfn(gfn); if ( mfn == INVALID_MFN ) return todo; @@ -400,14 +402,15 @@ static int __hvm_copy(void *buf, paddr_t addr, int size, int dir, int virt) p = (char *)map_domain_page(mfn) + (addr & ~PAGE_MASK); if ( dir ) + { memcpy(p, buf, count); /* dir == TRUE: *to* guest */ + mark_dirty(current->domain, gfn); + } else memcpy(buf, p, count); /* dir == FALSE: *from guest */ unmap_domain_page(p); - mark_dirty(current->domain, mfn); - addr += count; buf += count; todo -= count; From cf3e43db4af509762467cc4bcf0d9444b7807a9b Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 8 Mar 2007 16:26:17 +0000 Subject: [PATCH 005/170] linux: Remove an unused data structure from TPM frontend. Some more code style changes. Signed-off-by: Stefan Berger --- .../drivers/char/tpm/tpm_vtpm.c | 2 -- .../drivers/char/tpm/tpm_vtpm.h | 13 --------- .../drivers/char/tpm/tpm_xen.c | 28 ++----------------- 3 files changed, 3 insertions(+), 40 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c index 4e841fb55a..1f6982e6c2 100644 --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c @@ -504,7 +504,6 @@ static struct tpm_vendor_specific tpm_vtpm = { }; struct tpm_chip *init_vtpm(struct device *dev, - struct tpm_virtual_device *tvd, struct tpm_private *tp) { long rc; @@ -516,7 +515,6 @@ struct tpm_chip *init_vtpm(struct device *dev, return ERR_PTR(-ENOMEM); vtpm_state_init(vtpms); - vtpms->tpmvd = tvd; vtpms->tpm_private = tp; chip = tpm_register_hardware(dev, &tpm_vtpm); diff --git a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h index 27dba1a51d..77aa342baa 100644 --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h @@ -4,16 +4,6 @@ struct tpm_chip; struct tpm_private; -struct tpm_virtual_device { - /* - * This field indicates the maximum size the driver can - * transfer in one chunk. It is filled in by the front-end - * driver and should be propagated to the generic tpm driver - * for allocation of buffers. - */ - unsigned int max_tx_size; -}; - struct vtpm_state { struct transmission *current_request; spinlock_t req_list_lock; @@ -30,8 +20,6 @@ struct vtpm_state { unsigned long disconnect_time; - struct tpm_virtual_device *tpmvd; - /* * The following is a private structure of the underlying * driver. It is passed as parameter in the send function. @@ -51,7 +39,6 @@ int vtpm_vd_send(struct tpm_private * tp, /* these functions are offered by tpm_vtpm.c */ struct tpm_chip *init_vtpm(struct device *, - struct tpm_virtual_device *, struct tpm_private *); void cleanup_vtpm(struct device *); int vtpm_vd_recv(const struct tpm_chip* chip, diff --git a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c index 8b62b07724..5488217463 100644 --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c @@ -369,10 +369,6 @@ static void backend_changed(struct xenbus_device *dev, } } -struct tpm_virtual_device tvd = { - .max_tx_size = PAGE_SIZE * TPMIF_TX_RING_SIZE, -}; - static int tpmfront_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { @@ -383,7 +379,7 @@ static int tpmfront_probe(struct xenbus_device *dev, if (!tp) return -ENOMEM; - tp->chip = init_vtpm(&dev->dev, &tvd, tp); + tp->chip = init_vtpm(&dev->dev, tp); if (IS_ERR(tp->chip)) return PTR_ERR(tp->chip); @@ -500,11 +496,6 @@ static void __init init_tpm_xenbus(void) xenbus_register_frontend(&tpmfront); } -static void __exit exit_tpm_xenbus(void) -{ - xenbus_unregister_driver(&tpmfront); -} - static int tpmif_allocate_tx_buffers(struct tpm_private *tp) { unsigned int i; @@ -530,13 +521,11 @@ static void tpmif_free_tx_buffers(struct tpm_private *tp) static void tpmif_rx_action(unsigned long priv) { struct tpm_private *tp = (struct tpm_private *)priv; - int i = 0; unsigned int received; unsigned int offset = 0; u8 *buffer; - tpmif_tx_request_t *tx; - tx = &tp->tx->ring[i].req; + tpmif_tx_request_t *tx = &tp->tx->ring[i].req; atomic_set(&tp->tx_busy, 0); wake_up_interruptible(&tp->wait_q); @@ -545,7 +534,7 @@ static void tpmif_rx_action(unsigned long priv) buffer = kmalloc(received, GFP_ATOMIC); if (!buffer) - goto exit; + return; for (i = 0; i < TPMIF_TX_RING_SIZE && offset < received; i++) { struct tx_buffer *txb = tp->tx_buffers[i]; @@ -566,10 +555,6 @@ static void tpmif_rx_action(unsigned long priv) vtpm_vd_recv(tp->chip, buffer, received, tp->tx_remember); kfree(buffer); - -exit: - - return; } @@ -730,13 +715,6 @@ static int __init tpmif_init(void) } -void __exit tpmif_exit(void) -{ - exit_tpm_xenbus(); - tpm_private_put(); - gnttab_free_grant_references(gref_head); -} - module_init(tpmif_init); MODULE_LICENSE("Dual BSD/GPL"); From 78938b42ad38d4c475e1a041914ef5e4518c0d39 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Thu, 8 Mar 2007 16:38:15 +0000 Subject: [PATCH 006/170] [HVM] Save/restore: make sure all ioreqs are gone when a domain is saved by pausing the domain and pulling them through. Signed-off-by: Tim Deegan --- tools/ioemu/hw/ide.c | 55 ++++++++++++++++++++++++---- tools/ioemu/target-i386-dm/helper2.c | 21 +++++++++++ tools/ioemu/vl.h | 1 + tools/libxc/xc_hvm_restore.c | 8 ++++ tools/libxc/xc_hvm_save.c | 23 +++++++++++- tools/libxc/xenguest.h | 2 + tools/libxc/xg_private.c | 5 +++ xen/arch/x86/hvm/hvm.c | 48 ++++++++++++++++++++++++ xen/include/public/hvm/hvm_op.h | 8 ++++ 9 files changed, 162 insertions(+), 9 deletions(-) diff --git a/tools/ioemu/hw/ide.c b/tools/ioemu/hw/ide.c index c4db9fe738..274dd8f850 100644 --- a/tools/ioemu/hw/ide.c +++ b/tools/ioemu/hw/ide.c @@ -396,17 +396,41 @@ typedef struct PCIIDEState { #ifdef DMA_MULTI_THREAD +static pthread_t ide_dma_thread; static int file_pipes[2]; static void ide_dma_loop(BMDMAState *bm); static void dma_thread_loop(BMDMAState *bm); +extern int suspend_requested; static void *dma_thread_func(void* opaque) { BMDMAState* req; + fd_set fds; + int rv, nfds = file_pipes[0] + 1; + struct timeval tm; - while (read(file_pipes[0], &req, sizeof(req))) { - dma_thread_loop(req); + while (1) { + + /* Wait at most a second for the pipe to become readable */ + FD_ZERO(&fds); + FD_SET(file_pipes[0], &fds); + tm.tv_sec = 1; + tm.tv_usec = 0; + rv = select(nfds, &fds, NULL, NULL, &tm); + + if (rv != 0) { + if (read(file_pipes[0], &req, sizeof(req)) == 0) + return NULL; + dma_thread_loop(req); + } else { + if (suspend_requested) { + /* Need to tidy up the DMA thread so that we don't end up + * finishing operations after the domain's ioreqs are + * drained and its state saved */ + return NULL; + } + } } return NULL; @@ -414,24 +438,41 @@ static void *dma_thread_func(void* opaque) static void dma_create_thread(void) { - pthread_t tid; int rt; + pthread_attr_t a; if (pipe(file_pipes) != 0) { fprintf(stderr, "create pipe failed\n"); exit(1); } - if ((rt = pthread_create(&tid, NULL, dma_thread_func, NULL))) { + if ((rt = pthread_attr_init(&a)) + || (rt = pthread_attr_setdetachstate(&a, PTHREAD_CREATE_JOINABLE))) { + fprintf(stderr, "Oops, dma thread attr setup failed, errno=%d\n", rt); + exit(1); + } + + if ((rt = pthread_create(&ide_dma_thread, &a, dma_thread_func, NULL))) { fprintf(stderr, "Oops, dma thread creation failed, errno=%d\n", rt); exit(1); } +} - if ((rt = pthread_detach(tid))) { - fprintf(stderr, "Oops, dma thread detachment failed, errno=%d\n", rt); - exit(1); +void ide_stop_dma_thread(void) +{ + int rc; + /* Make sure the IDE DMA thread is stopped */ + if ( (rc = pthread_join(ide_dma_thread, NULL)) != 0 ) + { + fprintf(stderr, "Oops, error collecting IDE DMA thread (%s)\n", + strerror(rc)); } } + +#else +void ide_stop_dma_thread(void) +{ +} #endif /* DMA_MULTI_THREAD */ #if defined(__ia64__) diff --git a/tools/ioemu/target-i386-dm/helper2.c b/tools/ioemu/target-i386-dm/helper2.c index dc3394d5b7..7a5f3412c9 100644 --- a/tools/ioemu/target-i386-dm/helper2.c +++ b/tools/ioemu/target-i386-dm/helper2.c @@ -577,7 +577,28 @@ int main_loop(void) destroy_hvm_domain(); else { char qemu_file[20]; + ioreq_t *req; + int rc; + sprintf(qemu_file, "/tmp/xen.qemu-dm.%d", domid); + xc_domain_pause(xc_handle, domid); + + /* Pull all outstanding ioreqs through the system */ + handle_buffered_io(env); + main_loop_wait(1); /* For the select() on events */ + + /* Stop the IDE thread */ + ide_stop_dma_thread(); + + /* Make sure that all outstanding IO responses are handled too */ + if ( xc_hvm_drain_io(xc_handle, domid) != 0 ) + { + fprintf(stderr, "error clearing ioreq rings (%s)\n", + strerror(errno)); + return -1; + } + + /* Save the device state */ if (qemu_savevm(qemu_file) < 0) fprintf(stderr, "qemu save fail.\n"); } diff --git a/tools/ioemu/vl.h b/tools/ioemu/vl.h index 8535ba689c..a6b53aa312 100644 --- a/tools/ioemu/vl.h +++ b/tools/ioemu/vl.h @@ -843,6 +843,7 @@ void pci_cmd646_ide_init(PCIBus *bus, BlockDriverState **hd_table, void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn); int pmac_ide_init (BlockDriverState **hd_table, SetIRQFunc *set_irq, void *irq_opaque, int irq); +void ide_stop_dma_thread(void); /* cdrom.c */ int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track); diff --git a/tools/libxc/xc_hvm_restore.c b/tools/libxc/xc_hvm_restore.c index 001fe2a6e4..a5e51e84e8 100644 --- a/tools/libxc/xc_hvm_restore.c +++ b/tools/libxc/xc_hvm_restore.c @@ -281,6 +281,14 @@ int xc_hvm_restore(int xc_handle, int io_fd, else shared_page_nr = (v_end >> PAGE_SHIFT) - 1; + /* Paranoia: clean pages. */ + if ( xc_clear_domain_page(xc_handle, dom, shared_page_nr) || + xc_clear_domain_page(xc_handle, dom, shared_page_nr-1) || + xc_clear_domain_page(xc_handle, dom, shared_page_nr-2) ) { + ERROR("error clearing comms frames!\n"); + goto out; + } + xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, shared_page_nr-1); xc_set_hvm_param(xc_handle, dom, HVM_PARAM_BUFIOREQ_PFN, shared_page_nr-2); xc_set_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, shared_page_nr); diff --git a/tools/libxc/xc_hvm_save.c b/tools/libxc/xc_hvm_save.c index d1b44bd1c6..c422e296e6 100644 --- a/tools/libxc/xc_hvm_save.c +++ b/tools/libxc/xc_hvm_save.c @@ -27,12 +27,14 @@ #include #include #include -#include #include "xc_private.h" #include "xg_private.h" #include "xg_save_restore.h" +#include +#include + /* ** Default values for important tuning parameters. Can override by passing ** non-zero replacement values to xc_hvm_save(). @@ -49,12 +51,29 @@ static unsigned long max_mfn; /* virtual starting address of the hypervisor */ static unsigned long hvirt_start; -/* #levels of page tables used by the currrent guest */ +/* #levels of page tables used by the current guest */ static unsigned int pt_levels; /* total number of pages used by the current guest */ static unsigned long max_pfn; +int xc_hvm_drain_io(int handle, domid_t dom) +{ + DECLARE_HYPERCALL; + xen_hvm_drain_io_t arg; + int rc; + + hypercall.op = __HYPERVISOR_hvm_op; + hypercall.arg[0] = HVMOP_drain_io; + hypercall.arg[1] = (unsigned long)&arg; + arg.domid = dom; + if ( lock_pages(&arg, sizeof(arg)) != 0 ) + return -1; + rc = do_xen_hypercall(handle, &hypercall); + unlock_pages(&arg, sizeof(arg)); + return rc; +} + /* ** During (live) save/migrate, we maintain a number of bitmaps to track ** which pages we have to send, to fixup, and to skip. diff --git a/tools/libxc/xenguest.h b/tools/libxc/xenguest.h index cb3c6a4d1c..0f77217978 100644 --- a/tools/libxc/xenguest.h +++ b/tools/libxc/xenguest.h @@ -155,6 +155,8 @@ int xc_set_hvm_param( int xc_get_hvm_param( int handle, domid_t dom, int param, unsigned long *value); +int xc_hvm_drain_io(int handle, domid_t dom); + /* PowerPC specific. */ int xc_prose_build(int xc_handle, uint32_t domid, diff --git a/tools/libxc/xg_private.c b/tools/libxc/xg_private.c index 63ffea4aad..2332ef4c6c 100644 --- a/tools/libxc/xg_private.c +++ b/tools/libxc/xg_private.c @@ -229,6 +229,11 @@ __attribute__((weak)) int xc_set_hvm_param( return -ENOSYS; } +__attribute__((weak)) int xc_hvm_drain_io(int handle, domid_t dom) +{ + return -ENOSYS; +} + /* * Local variables: * mode: C diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index d03824bc0e..09515203de 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -146,6 +146,48 @@ void hvm_do_resume(struct vcpu *v) } } +/* Called from the tools when saving a domain to make sure the io + * request-response ring is entirely empty. */ +static int hvmop_drain_io( + XEN_GUEST_HANDLE(xen_hvm_drain_io_t) uop) +{ + struct xen_hvm_drain_io op; + struct domain *d; + struct vcpu *v; + ioreq_t *p; + int rc; + + if ( copy_from_guest(&op, uop, 1) ) + return -EFAULT; + + if ( !IS_PRIV(current->domain) ) + return -EPERM; + + d = rcu_lock_domain_by_id(op.domid); + if ( d == NULL ) + return -ESRCH; + + rc = -EINVAL; + /* Can't do this to yourself, or to a domain without an ioreq ring */ + if ( d == current->domain || !is_hvm_domain(d) || get_sp(d) == NULL ) + goto out; + + rc = 0; + + domain_pause(d); /* It's not safe to do this to running vcpus */ + for_each_vcpu(d, v) + { + p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq; + if ( p->state == STATE_IORESP_READY ) + hvm_io_assist(v); + } + domain_unpause(d); + + out: + rcu_unlock_domain(d); + return rc; +} + int hvm_domain_initialise(struct domain *d) { int rc; @@ -916,6 +958,12 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) guest_handle_cast(arg, xen_hvm_set_pci_link_route_t)); break; + case HVMOP_drain_io: + rc = hvmop_drain_io( + guest_handle_cast(arg, xen_hvm_drain_io_t)); + break; + + default: { gdprintk(XENLOG_WARNING, "Bad HVM op %ld.\n", op); diff --git a/xen/include/public/hvm/hvm_op.h b/xen/include/public/hvm/hvm_op.h index f568050949..f03ad288bb 100644 --- a/xen/include/public/hvm/hvm_op.h +++ b/xen/include/public/hvm/hvm_op.h @@ -70,4 +70,12 @@ struct xen_hvm_set_pci_link_route { typedef struct xen_hvm_set_pci_link_route xen_hvm_set_pci_link_route_t; DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_link_route_t); +/* Drain all outstanding qemu-dm IO responses from a domain's ioreq ring. */ +#define HVMOP_drain_io 5 +struct xen_hvm_drain_io { + domid_t domid; +}; +typedef struct xen_hvm_drain_io xen_hvm_drain_io_t; +DEFINE_XEN_GUEST_HANDLE(xen_hvm_drain_io_t); + #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */ From 8ae71c0646f17428e172d239be6c2ba1041c6934 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Thu, 8 Mar 2007 16:40:35 +0000 Subject: [PATCH 007/170] [HVM] Save/restore: tidy PFN handling in the tools. Make the differences clearer between the number of frames, the max PFN and the size of the pfn array, and handle te framebuffer more cleanly. Signed-off-by: Tim Deegan --- tools/libxc/xc_hvm_restore.c | 57 +++++------ tools/libxc/xc_hvm_save.c | 122 ++++++++++++++++-------- tools/libxc/xenguest.h | 1 + tools/python/xen/xend/XendCheckpoint.py | 7 +- 4 files changed, 117 insertions(+), 70 deletions(-) diff --git a/tools/libxc/xc_hvm_restore.c b/tools/libxc/xc_hvm_restore.c index a5e51e84e8..0dafa82874 100644 --- a/tools/libxc/xc_hvm_restore.c +++ b/tools/libxc/xc_hvm_restore.c @@ -101,6 +101,9 @@ int xc_hvm_restore(int xc_handle, int io_fd, /* Number of pages of memory the guest has. *Not* the same as max_pfn. */ unsigned long nr_pages; + /* The size of an array big enough to contain all guest pfns */ + unsigned long pfn_array_size = max_pfn + 1; + /* hvm guest mem size (Mb) */ memsize = (unsigned long long)*store_mfn; v_end = memsize << 20; @@ -127,7 +130,7 @@ int xc_hvm_restore(int xc_handle, int io_fd, } - pfns = malloc(max_pfn * sizeof(xen_pfn_t)); + pfns = malloc(pfn_array_size * sizeof(xen_pfn_t)); if (pfns == NULL) { ERROR("memory alloc failed"); errno = ENOMEM; @@ -139,11 +142,11 @@ int xc_hvm_restore(int xc_handle, int io_fd, goto out; } - for ( i = 0; i < max_pfn; i++ ) + for ( i = 0; i < pfn_array_size; i++ ) pfns[i] = i; - for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < max_pfn; i++ ) + for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < pfn_array_size; i++ ) pfns[i] += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT; - arch_max_pfn = pfns[max_pfn - 1];/* used later */ + arch_max_pfn = pfns[max_pfn];/* used later */ /* Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. */ rc = xc_domain_memory_populate_physmap( @@ -297,29 +300,6 @@ int xc_hvm_restore(int xc_handle, int io_fd, *store_mfn = (v_end >> PAGE_SHIFT) - 2; DPRINTF("hvm restore:calculate new store_mfn=0x%lx,v_end=0x%llx..\n", *store_mfn, v_end); - /* restore hvm context including pic/pit/shpage */ - if (!read_exact(io_fd, &rec_len, sizeof(uint32_t))) { - ERROR("error read hvm context size!\n"); - goto out; - } - - hvm_buf = malloc(rec_len); - if (hvm_buf == NULL) { - ERROR("memory alloc for hvm context buffer failed"); - errno = ENOMEM; - goto out; - } - - if (!read_exact(io_fd, hvm_buf, rec_len)) { - ERROR("error read hvm buffer!\n"); - goto out; - } - - if (( rc = xc_domain_hvm_setcontext(xc_handle, dom, hvm_buf, rec_len))) { - ERROR("error set hvm buffer!\n"); - goto out; - } - if (!read_exact(io_fd, &nr_vcpus, sizeof(uint32_t))) { ERROR("error read nr vcpu !\n"); goto out; @@ -347,6 +327,29 @@ int xc_hvm_restore(int xc_handle, int io_fd, } } + /* restore hvm context including pic/pit/shpage */ + if (!read_exact(io_fd, &rec_len, sizeof(uint32_t))) { + ERROR("error read hvm context size!\n"); + goto out; + } + + hvm_buf = malloc(rec_len); + if (hvm_buf == NULL) { + ERROR("memory alloc for hvm context buffer failed"); + errno = ENOMEM; + goto out; + } + + if (!read_exact(io_fd, hvm_buf, rec_len)) { + ERROR("error read hvm buffer!\n"); + goto out; + } + + if (( rc = xc_domain_hvm_setcontext(xc_handle, dom, hvm_buf, rec_len))) { + ERROR("error set hvm buffer!\n"); + goto out; + } + /* Shared-info pfn */ if (!read_exact(io_fd, &(shared_info_frame), sizeof(uint32_t)) ) { ERROR("reading the shared-info pfn failed!\n"); diff --git a/tools/libxc/xc_hvm_save.c b/tools/libxc/xc_hvm_save.c index c422e296e6..ac06db72a1 100644 --- a/tools/libxc/xc_hvm_save.c +++ b/tools/libxc/xc_hvm_save.c @@ -54,9 +54,6 @@ static unsigned long hvirt_start; /* #levels of page tables used by the current guest */ static unsigned int pt_levels; -/* total number of pages used by the current guest */ -static unsigned long max_pfn; - int xc_hvm_drain_io(int handle, domid_t dom) { DECLARE_HYPERCALL; @@ -80,7 +77,7 @@ int xc_hvm_drain_io(int handle, domid_t dom) */ #define BITS_PER_LONG (sizeof(unsigned long) * 8) -#define BITMAP_SIZE ((max_pfn + BITS_PER_LONG - 1) / 8) +#define BITMAP_SIZE ((pfn_array_size + BITS_PER_LONG - 1) / 8) #define BITMAP_ENTRY(_nr,_bmap) \ ((unsigned long *)(_bmap))[(_nr)/BITS_PER_LONG] @@ -202,7 +199,7 @@ static int print_stats(int xc_handle, uint32_t domid, int pages_sent, return 0; } -static int analysis_phase(int xc_handle, uint32_t domid, int max_pfn, +static int analysis_phase(int xc_handle, uint32_t domid, int pfn_array_size, unsigned long *arr, int runs) { long long start, now; @@ -215,7 +212,7 @@ static int analysis_phase(int xc_handle, uint32_t domid, int max_pfn, int i; xc_shadow_control(xc_handle, domid, XEN_DOMCTL_SHADOW_OP_CLEAN, - arr, max_pfn, NULL, 0, NULL); + arr, pfn_array_size, NULL, 0, NULL); DPRINTF("#Flush\n"); for ( i = 0; i < 40; i++ ) { usleep(50000); @@ -255,7 +252,7 @@ static int suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd, if (info->shutdown && info->shutdown_reason == SHUTDOWN_suspend) - return 0; // success + return 0; // success if (info->paused) { // try unpausing domain, wait, and retest @@ -287,11 +284,21 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, int rc = 1, i, j, last_iter, iter = 0; int live = (flags & XCFLAGS_LIVE); int debug = (flags & XCFLAGS_DEBUG); + int stdvga = (flags & XCFLAGS_STDVGA); int sent_last_iter, skip_this_iter; + /* The highest guest-physical frame number used by the current guest */ + unsigned long max_pfn; + + /* The size of an array big enough to contain all guest pfns */ + unsigned long pfn_array_size; + /* The new domain's shared-info frame number. */ unsigned long shared_info_frame; + /* Other magic frames: ioreqs and xenstore comms */ + unsigned long ioreq_pfn, bufioreq_pfn, store_pfn; + /* A copy of the CPU context of the guest. */ vcpu_guest_context_t ctxt; @@ -310,7 +317,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, uint32_t rec_size, nr_vcpus; - /* power of 2 order of max_pfn */ + /* power of 2 order of pfn_array_size */ int order_nr; /* bitmap of pages: @@ -372,6 +379,15 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } + if ( xc_get_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, &store_pfn) + || xc_get_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, &ioreq_pfn) + || xc_get_hvm_param(xc_handle, dom, + HVM_PARAM_BUFIOREQ_PFN, &bufioreq_pfn) ) + { + ERROR("HVM: Could not read magic PFN parameters"); + goto out; + } + DPRINTF("saved hvm domain info:max_memkb=0x%lx, max_mfn=0x%lx, " "nr_pages=0x%lx\n", info.max_memkb, max_mfn, info.nr_pages); @@ -387,6 +403,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } last_iter = 0; + DPRINTF("hvm domain live migration debug start: logdirty enable.\n"); } else { /* This is a non-live suspend. Issue the call back to get the @@ -407,20 +424,28 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, /* Calculate the highest PFN of "normal" memory: * HVM memory is sequential except for the VGA and MMIO holes. */ - max_pfn = info.nr_pages; + max_pfn = info.nr_pages - 1; + /* If the domain has a Cirrus framebuffer and we haven't already + * suspended qemu-dm, it will have 8MB of framebuffer memory + * still allocated, which we don't want to copy: qemu will save it + * for us later */ + if ( live && !stdvga ) + max_pfn -= 0x800; /* Skip the VGA hole from 0xa0000 to 0xc0000 */ - max_pfn += 0x20; + max_pfn += 0x20; /* Skip the MMIO hole: 256MB just below 4GB */ if ( max_pfn >= (HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT) ) max_pfn += (HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT); - skip_this_iter = 0;/*XXX*/ - /* pretend we sent all the pages last iteration */ - sent_last_iter = max_pfn; + /* Size of any array that covers 0 ... max_pfn */ + pfn_array_size = max_pfn + 1; - /* calculate the power of 2 order of max_pfn, e.g. + /* pretend we sent all the pages last iteration */ + sent_last_iter = pfn_array_size; + + /* calculate the power of 2 order of pfn_array_size, e.g. 15->4 16->4 17->5 */ - for (i = max_pfn-1, order_nr = 0; i ; i >>= 1, order_nr++) + for (i = pfn_array_size-1, order_nr = 0; i ; i >>= 1, order_nr++) continue; /* Setup to_send / to_fix and to_skip bitmaps */ @@ -454,7 +479,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, return 1; } - analysis_phase(xc_handle, dom, max_pfn, to_skip, 0); + analysis_phase(xc_handle, dom, pfn_array_size, to_skip, 0); /* We want zeroed memory so use calloc rather than malloc. */ @@ -484,9 +509,17 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, DPRINTF("Saving HVM domain memory pages: iter %d 0%%", iter); - while( N < max_pfn ){ + if (last_iter && (max_pfn != live_shinfo->arch.max_pfn)) { + DPRINTF("calculated max_pfn as %#lx, shinfo says %#lx\n", + max_pfn, live_shinfo->arch.max_pfn); + ERROR("Max pfn doesn't match shared info"); + goto out; + } - unsigned int this_pc = (N * 100) / max_pfn; + while( N < pfn_array_size ){ + + unsigned int this_pc = (N * 100) / pfn_array_size; + int rc; if ((this_pc - prev_pc) >= 5) { DPRINTF("\b\b\b\b%3d%%", this_pc); @@ -495,9 +528,9 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, /* slightly wasteful to peek the whole array evey time, but this is fast enough for the moment. */ - if (!last_iter && xc_shadow_control( - xc_handle, dom, XEN_DOMCTL_SHADOW_OP_PEEK, - to_skip, max_pfn, NULL, 0, NULL) != max_pfn) { + if (!last_iter && (rc = xc_shadow_control( + xc_handle, dom, XEN_DOMCTL_SHADOW_OP_PEEK, to_skip, + pfn_array_size, NULL, 0, NULL)) != pfn_array_size) { ERROR("Error peeking HVM shadow bitmap"); goto out; } @@ -505,11 +538,11 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, /* load pfn_batch[] with the mfn of all the pages we're doing in this batch. */ - for (batch = 0; batch < MAX_BATCH_SIZE && N < max_pfn ; N++) { + for (batch = 0; batch < MAX_BATCH_SIZE && N < pfn_array_size; N++){ - int n = permute(N, max_pfn, order_nr); + int n = permute(N, pfn_array_size, order_nr); - if (debug) { + if (0&&debug) { DPRINTF("%d pfn= %08lx %d \n", iter, (unsigned long)n, test_bit(n, to_send)); } @@ -524,7 +557,10 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, /* Skip PFNs that aren't really there */ if ((n >= 0xa0 && n < 0xc0) /* VGA hole */ || (n >= (HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT) - && n < (1ULL << 32) >> PAGE_SHIFT)) /* 4G MMIO hole */ + && n < (1ULL << 32) >> PAGE_SHIFT) /* 4G MMIO hole */ + || n == store_pfn + || n == ioreq_pfn + || n == bufioreq_pfn) continue; /* @@ -589,7 +625,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, print_stats( xc_handle, dom, sent_this_iter, &stats, 1); DPRINTF("Total pages sent= %ld (%.2fx)\n", - total_sent, ((float)total_sent)/max_pfn ); + total_sent, ((float)total_sent)/pfn_array_size ); } if (last_iter && debug){ @@ -616,7 +652,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, ((sent_this_iter > sent_last_iter) && RATE_IS_MAX()) || (iter >= max_iters) || (sent_this_iter+skip_this_iter < 50) || - (total_sent > max_pfn*max_factor) ) { + (total_sent > pfn_array_size*max_factor) ) { DPRINTF("Start last iteration for HVM domain\n"); last_iter = 1; @@ -635,7 +671,8 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, if (xc_shadow_control(xc_handle, dom, XEN_DOMCTL_SHADOW_OP_CLEAN, to_send, - max_pfn, NULL, 0, &stats) != max_pfn) { + pfn_array_size, NULL, + 0, &stats) != pfn_array_size) { ERROR("Error flushing shadow PT"); goto out; } @@ -659,20 +696,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } - if ( (rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf, - hvm_buf_size)) == -1) { - ERROR("HVM:Could not get hvm buffer"); - goto out; - } - - if (!write_exact(io_fd, &rec_size, sizeof(uint32_t))) { - ERROR("error write hvm buffer size"); - goto out; - } - - if ( !write_exact(io_fd, hvm_buf, rec_size) ) { - ERROR("write HVM info failed!\n"); - } /* save vcpu/vmcs context */ if (!write_exact(io_fd, &nr_vcpus, sizeof(uint32_t))) { @@ -701,6 +724,21 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } } + if ( (rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf, + hvm_buf_size)) == -1) { + ERROR("HVM:Could not get hvm buffer"); + goto out; + } + + if (!write_exact(io_fd, &rec_size, sizeof(uint32_t))) { + ERROR("error write hvm buffer size"); + goto out; + } + + if ( !write_exact(io_fd, hvm_buf, rec_size) ) { + ERROR("write HVM info failed!\n"); + } + /* Shared-info pfn */ if (!write_exact(io_fd, &(shared_info_frame), sizeof(uint32_t)) ) { ERROR("write shared-info pfn failed!\n"); diff --git a/tools/libxc/xenguest.h b/tools/libxc/xenguest.h index 0f77217978..5b6e7c6d2a 100644 --- a/tools/libxc/xenguest.h +++ b/tools/libxc/xenguest.h @@ -12,6 +12,7 @@ #define XCFLAGS_LIVE 1 #define XCFLAGS_DEBUG 2 #define XCFLAGS_HVM 4 +#define XCFLAGS_STDVGA 8 /** diff --git a/tools/python/xen/xend/XendCheckpoint.py b/tools/python/xen/xend/XendCheckpoint.py index e94d9fbde7..92ba37d4fd 100644 --- a/tools/python/xen/xend/XendCheckpoint.py +++ b/tools/python/xen/xend/XendCheckpoint.py @@ -74,9 +74,13 @@ def save(fd, dominfo, network, live, dst, checkpoint=False): image_cfg = dominfo.info.get('image', {}) hvm = image_cfg.has_key('hvm') + stdvga = 0 if hvm: log.info("save hvm domain") + if image_cfg['hvm']['devices']['stdvga'] == 1: + stdvga = 1 + # xc_save takes three customization parameters: maxit, max_f, and # flags the last controls whether or not save is 'live', while the # first two further customize behaviour when 'live' save is @@ -84,7 +88,8 @@ def save(fd, dominfo, network, live, dst, checkpoint=False): # libxenguest; see the comments and/or code in xc_linux_save() for # more information. cmd = [xen.util.auxbin.pathTo(XC_SAVE), str(fd), - str(dominfo.getDomid()), "0", "0", str(int(live) | (int(hvm) << 2)) ] + str(dominfo.getDomid()), "0", "0", + str(int(live) | (int(hvm) << 2) | (int(stdvga) << 3)) ] log.debug("[xc_save]: %s", string.join(cmd)) def saveInputHandler(line, tochild): From 45e2bb215f82be3da84a506c4a084587f4423055 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Thu, 8 Mar 2007 22:33:47 +0000 Subject: [PATCH 008/170] Fix duplicate consts around xc_error declarations. Signed-off-by: Ewan Mellor --- tools/libxc/xc_private.c | 2 +- tools/libxc/xenctrl.h | 6 +++--- tools/python/xen/lowlevel/xc/xc.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c index 77321c458b..3816b0a83b 100644 --- a/tools/libxc/xc_private.c +++ b/tools/libxc/xc_private.c @@ -23,7 +23,7 @@ void xc_default_error_handler(const xc_error const *err) fprintf(stderr, "ERROR %s: %s\n", desc, err->message); } -const xc_error const *xc_get_last_error(void) +const xc_error *xc_get_last_error(void) { return &last_error; } diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index 199750de73..96ba314503 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -770,19 +770,19 @@ typedef struct { * data pointed to are only valid until the next call to * libxc. */ -const xc_error const *xc_get_last_error(void); +const xc_error *xc_get_last_error(void); /* * Clear the last error */ void xc_clear_last_error(void); -typedef void (*xc_error_handler)(const xc_error const* err); +typedef void (*xc_error_handler)(const xc_error * const err); /* * The default error handler which prints to stderr */ -void xc_default_error_handler(const xc_error const* err); +void xc_default_error_handler(const xc_error * const err); /* * Convert an error code into a text description diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c index b3dbb20ed7..7da0288cbd 100644 --- a/tools/python/xen/lowlevel/xc/xc.c +++ b/tools/python/xen/lowlevel/xc/xc.c @@ -47,7 +47,7 @@ static PyObject *dom_op(XcObject *self, PyObject *args, static PyObject *pyxc_error_to_exception(void) { PyObject *pyerr; - const xc_error const *err = xc_get_last_error(); + const xc_error *err = xc_get_last_error(); const char *desc = xc_error_code_to_desc(err->code); if (err->code == XC_ERROR_NONE) From 9c3b29a7729ff0aefb9fdcbb715df48c4d45a9f5 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Thu, 8 Mar 2007 23:16:34 +0000 Subject: [PATCH 009/170] Remove crashdump.create -- this doesn't make sense. Signed-off-by: Ewan Mellor --- docs/xen-api/xenapi-datamodel.tex | 96 ++++++++++------------------ tools/libxen/include/xen_crashdump.h | 23 +++---- tools/libxen/src/xen_crashdump.c | 47 +++++--------- 3 files changed, 55 insertions(+), 111 deletions(-) diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex index cce4ae5cc7..319713e2e2 100644 --- a/docs/xen-api/xenapi-datamodel.tex +++ b/docs/xen-api/xenapi-datamodel.tex @@ -11885,6 +11885,38 @@ $\mathit{RO}_\mathit{ins}$ & {\tt VDI} & VDI ref & the virtual disk \\ \hline \end{longtable} \subsection{Additional RPCs associated with class: crashdump} +\subsubsection{RPC name:~destroy} + +{\bf Overview:} +Destroy the specified crashdump. + + \noindent {\bf Signature:} +\begin{verbatim} void destroy (session_id s, crashdump ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt crashdump ref } & self & The crashdump to destroy \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +void +} + + + +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} \subsubsection{RPC name:~get\_all} {\bf Overview:} @@ -11999,70 +12031,6 @@ VDI ref value of the field -\vspace{0.3cm} -\vspace{0.3cm} -\vspace{0.3cm} -\subsubsection{RPC name:~create} - -{\bf Overview:} -Create a new crashdump instance, and return its handle. - - \noindent {\bf Signature:} -\begin{verbatim} (crashdump ref) create (session_id s, crashdump record args)\end{verbatim} - - -\noindent{\bf Arguments:} - - -\vspace{0.3cm} -\begin{tabular}{|c|c|p{7cm}|} - \hline -{\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt crashdump record } & args & All constructor arguments \\ \hline - -\end{tabular} - -\vspace{0.3cm} - - \noindent {\bf Return Type:} -{\tt -crashdump ref -} - - -reference to the newly created object -\vspace{0.3cm} -\vspace{0.3cm} -\vspace{0.3cm} -\subsubsection{RPC name:~destroy} - -{\bf Overview:} -Destroy the specified crashdump instance. - - \noindent {\bf Signature:} -\begin{verbatim} void destroy (session_id s, crashdump ref self)\end{verbatim} - - -\noindent{\bf Arguments:} - - -\vspace{0.3cm} -\begin{tabular}{|c|c|p{7cm}|} - \hline -{\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt crashdump ref } & self & reference to the object \\ \hline - -\end{tabular} - -\vspace{0.3cm} - - \noindent {\bf Return Type:} -{\tt -void -} - - - \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} diff --git a/tools/libxen/include/xen_crashdump.h b/tools/libxen/include/xen_crashdump.h index fff0a1a144..00869dbb4c 100644 --- a/tools/libxen/include/xen_crashdump.h +++ b/tools/libxen/include/xen_crashdump.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, XenSource Inc. + * Copyright (c) 2006-2007, XenSource Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -161,20 +161,6 @@ extern bool xen_crashdump_get_by_uuid(xen_session *session, xen_crashdump *result, char *uuid); -/** - * Create a new crashdump instance, and return its handle. - */ -extern bool -xen_crashdump_create(xen_session *session, xen_crashdump *result, xen_crashdump_record *record); - - -/** - * Destroy the specified crashdump instance. - */ -extern bool -xen_crashdump_destroy(xen_session *session, xen_crashdump crashdump); - - /** * Get the uuid field of the given crashdump. */ @@ -196,6 +182,13 @@ extern bool xen_crashdump_get_vdi(xen_session *session, xen_vdi *result, xen_crashdump crashdump); +/** + * Destroy the specified crashdump + */ +extern bool +xen_crashdump_destroy(xen_session *session, xen_crashdump self); + + /** * Return a list of all the crashdumps known to the system. */ diff --git a/tools/libxen/src/xen_crashdump.c b/tools/libxen/src/xen_crashdump.c index 53504ba249..2d3840896e 100644 --- a/tools/libxen/src/xen_crashdump.c +++ b/tools/libxen/src/xen_crashdump.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, XenSource Inc. + * Copyright (c) 2006-2007, XenSource Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -114,37 +114,6 @@ xen_crashdump_get_by_uuid(xen_session *session, xen_crashdump *result, char *uui } -bool -xen_crashdump_create(xen_session *session, xen_crashdump *result, xen_crashdump_record *record) -{ - abstract_value param_values[] = - { - { .type = &xen_crashdump_record_abstract_type_, - .u.struct_val = record } - }; - - abstract_type result_type = abstract_type_string; - - *result = NULL; - XEN_CALL_("crashdump.create"); - return session->ok; -} - - -bool -xen_crashdump_destroy(xen_session *session, xen_crashdump crashdump) -{ - abstract_value param_values[] = - { - { .type = &abstract_type_string, - .u.string_val = crashdump } - }; - - xen_call_(session, "crashdump.destroy", param_values, 1, NULL, NULL); - return session->ok; -} - - bool xen_crashdump_get_vm(xen_session *session, xen_vm *result, xen_crashdump crashdump) { @@ -179,6 +148,20 @@ xen_crashdump_get_vdi(xen_session *session, xen_vdi *result, xen_crashdump crash } +bool +xen_crashdump_destroy(xen_session *session, xen_crashdump self) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = self } + }; + + xen_call_(session, "crashdump.destroy", param_values, 1, NULL, NULL); + return session->ok; +} + + bool xen_crashdump_get_all(xen_session *session, struct xen_crashdump_set **result) { From 5579ba52ec6f1db9497e03edd80d440460c3c55d Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Thu, 8 Mar 2007 23:22:56 +0000 Subject: [PATCH 010/170] Added VM_BAD_POWER_STATE error code to VM.hard_shutdown. Signed-off-by: Ewan Mellor --- docs/xen-api/xenapi-datamodel.tex | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex index 319713e2e2..c7b7496509 100644 --- a/docs/xen-api/xenapi-datamodel.tex +++ b/docs/xen-api/xenapi-datamodel.tex @@ -1362,8 +1362,10 @@ void \vspace{0.3cm} -\vspace{0.3cm} -\vspace{0.3cm} + +\noindent{\bf Possible Error Codes:} {\tt VM\_BAD\_POWER\_STATE} + +\vspace{0.6cm} \subsubsection{RPC name:~hard\_reboot} {\bf Overview:} From 9e92a72fb5e29900dd1bc57cf0592d916a03a109 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Thu, 8 Mar 2007 23:47:24 +0000 Subject: [PATCH 011/170] Added {VIF,VBD}.{plug,unplug} methods. Docs and C bindings -- Xend to follow. Signed-off-by: Ewan Mellor --- docs/xen-api/xenapi-datamodel.tex | 130 ++++++++++++++++++++++++++++++ tools/libxen/include/xen_vbd.h | 16 ++++ tools/libxen/include/xen_vif.h | 16 ++++ tools/libxen/src/xen_vbd.c | 28 +++++++ tools/libxen/src/xen_vif.c | 28 +++++++ 5 files changed, 218 insertions(+) diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex index c7b7496509..02ef2e90bd 100644 --- a/docs/xen-api/xenapi-datamodel.tex +++ b/docs/xen-api/xenapi-datamodel.tex @@ -7118,6 +7118,71 @@ $\mathit{RO}_\mathit{run}$ & {\tt metrics} & VIF\_metrics ref & metrics associa \hline \end{longtable} \subsection{Additional RPCs associated with class: VIF} +\subsubsection{RPC name:~plug} + +{\bf Overview:} +Hotplug the specified VIF, dynamically attaching it to the running VM. + + \noindent {\bf Signature:} +\begin{verbatim} void plug (session_id s, VIF ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VIF ref } & self & The VIF to hotplug \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +void +} + + + +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~unplug} + +{\bf Overview:} +Hot-unplug the specified VIF, dynamically unattaching it from the running +VM. + + \noindent {\bf Signature:} +\begin{verbatim} void unplug (session_id s, VIF ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VIF ref } & self & The VIF to hot-unplug \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +void +} + + + +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} \subsubsection{RPC name:~get\_all} {\bf Overview:} @@ -10461,6 +10526,71 @@ void +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~plug} + +{\bf Overview:} +Hotplug the specified VBD, dynamically attaching it to the running VM. + + \noindent {\bf Signature:} +\begin{verbatim} void plug (session_id s, VBD ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VBD ref } & self & The VBD to hotplug \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +void +} + + + +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~unplug} + +{\bf Overview:} +Hot-unplug the specified VBD, dynamically unattaching it from the running +VM. + + \noindent {\bf Signature:} +\begin{verbatim} void unplug (session_id s, VBD ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VBD ref } & self & The VBD to hot-unplug \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +void +} + + + \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} diff --git a/tools/libxen/include/xen_vbd.h b/tools/libxen/include/xen_vbd.h index 86ad38f207..7b36266a04 100644 --- a/tools/libxen/include/xen_vbd.h +++ b/tools/libxen/include/xen_vbd.h @@ -357,6 +357,22 @@ extern bool xen_vbd_media_change(xen_session *session, xen_vbd vbd, xen_vdi vdi); +/** + * Hotplug the specified VBD, dynamically attaching it to the running + * VM + */ +extern bool +xen_vbd_plug(xen_session *session, xen_vbd self); + + +/** + * Hot-unplug the specified VBD, dynamically unattaching it from the + * running VM + */ +extern bool +xen_vbd_unplug(xen_session *session, xen_vbd self); + + /** * Return a list of all the VBDs known to the system. */ diff --git a/tools/libxen/include/xen_vif.h b/tools/libxen/include/xen_vif.h index 05a070aff4..8a1cffb7bd 100644 --- a/tools/libxen/include/xen_vif.h +++ b/tools/libxen/include/xen_vif.h @@ -331,6 +331,22 @@ extern bool xen_vif_remove_from_qos_algorithm_params(xen_session *session, xen_vif vif, char *key); +/** + * Hotplug the specified VIF, dynamically attaching it to the running + * VM + */ +extern bool +xen_vif_plug(xen_session *session, xen_vif self); + + +/** + * Hot-unplug the specified VIF, dynamically unattaching it from the + * running VM + */ +extern bool +xen_vif_unplug(xen_session *session, xen_vif self); + + /** * Return a list of all the VIFs known to the system. */ diff --git a/tools/libxen/src/xen_vbd.c b/tools/libxen/src/xen_vbd.c index def7403ef9..300f1d857d 100644 --- a/tools/libxen/src/xen_vbd.c +++ b/tools/libxen/src/xen_vbd.c @@ -551,6 +551,34 @@ xen_vbd_media_change(xen_session *session, xen_vbd vbd, xen_vdi vdi) } +bool +xen_vbd_plug(xen_session *session, xen_vbd self) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = self } + }; + + xen_call_(session, "VBD.plug", param_values, 1, NULL, NULL); + return session->ok; +} + + +bool +xen_vbd_unplug(xen_session *session, xen_vbd self) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = self } + }; + + xen_call_(session, "VBD.unplug", param_values, 1, NULL, NULL); + return session->ok; +} + + bool xen_vbd_get_all(xen_session *session, struct xen_vbd_set **result) { diff --git a/tools/libxen/src/xen_vif.c b/tools/libxen/src/xen_vif.c index 11cba1dcbd..a139a83bc3 100644 --- a/tools/libxen/src/xen_vif.c +++ b/tools/libxen/src/xen_vif.c @@ -499,6 +499,34 @@ xen_vif_remove_from_qos_algorithm_params(xen_session *session, xen_vif vif, char } +bool +xen_vif_plug(xen_session *session, xen_vif self) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = self } + }; + + xen_call_(session, "VIF.plug", param_values, 1, NULL, NULL); + return session->ok; +} + + +bool +xen_vif_unplug(xen_session *session, xen_vif self) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = self } + }; + + xen_call_(session, "VIF.unplug", param_values, 1, NULL, NULL); + return session->ok; +} + + bool xen_vif_get_all(xen_session *session, struct xen_vif_set **result) { From 35dc73888007d5317bb606ceecadb305d9fefb03 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Fri, 9 Mar 2007 00:35:29 +0000 Subject: [PATCH 012/170] Changed the example of linked references (Set(Ref(x)) <-> Ref(y)) to use VM and VIFs rather than VM and VMGroups, now that we've deleted VMGroups. Signed-off-by: Ewan Mellor --- docs/xen-api/presentation.tex | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/xen-api/presentation.tex b/docs/xen-api/presentation.tex index ba7ebdbde7..abc18bafe9 100644 --- a/docs/xen-api/presentation.tex +++ b/docs/xen-api/presentation.tex @@ -57,14 +57,14 @@ type $t_1$ to values of type $t_2$. \end{itemize} Note that there are a number of cases where {\em Ref}s are {\em doubly -linked\/}---e.g.\ a VM has a field called {\tt groups} of type -$(\mathit{VMGroup}~\mathit{Ref})~\mathit{Set}$; this field lists -the VMGroups that a particular VM is part of. Similarly, the VMGroups -class has a field called {\tt VMs} of type $(\mathit{VM}~{\mathit -Ref})~\mathit{Set}$ that contains the VMs that are part of a particular -VMGroup. These two fields are {\em bound together\/}, in the sense that -adding a new VMGroup to a VM causes the VMs field of the corresponding -VMGroup object to be updated automatically. +linked\/}---e.g.\ a VM has a field called {\tt VIFs} of type +$(\mathit{VIF}~\mathit{Ref})~\mathit{Set}$; this field lists +the network interfaces attached to a particular VM. Similarly, the VIF +class has a field called {\tt VM} of type $(\mathit{VM}~{\mathit +Ref})$ which references the VM to which the interface is connected. +These two fields are {\em bound together\/}, in the sense that +creating a new VIF causes the {\tt VIFs} field of the corresponding +VM object to be updated automatically. The API reference explicitly lists the fields that are bound together in this way. It also contains a diagram that shows From ee1ed8aafb077965fb118210ebddde886d8c0a15 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Fri, 9 Mar 2007 00:44:10 +0000 Subject: [PATCH 013/170] Added section on references vs UUIDs. Signed-off-by: Ewan Mellor --- docs/xen-api/wire-protocol.tex | 46 ++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/docs/xen-api/wire-protocol.tex b/docs/xen-api/wire-protocol.tex index 1548f41c9e..2d11f739c9 100644 --- a/docs/xen-api/wire-protocol.tex +++ b/docs/xen-api/wire-protocol.tex @@ -30,8 +30,13 @@ These types are mapped onto XML-RPC types in a straight-forward manner: \item Floats, Bools, DateTimes and Strings map directly to the XML-RPC {\tt double}, {\tt boolean}, {\tt dateTime.iso8601}, and {\tt string} elements. - \item all our ``{\tt ref\_}'' types (e.g.\ {\tt ref\_vm} in the above - example) map to XML-RPC's {\tt String} type. The string itself is the OSF + \item all ``{\tt ref\_}'' types are opaque references, encoded as the + XML-RPC's {\tt String} type. Users of the API should not make assumptions + about the concrete form of these strings and should not expect them to + remain valid after the client's session with the server has terminated. + + \item fields named ``{\tt uuid}'' of type ``{\tt String}'' are mapped to + the XML-RPC {\tt String} type. The string itself is the OSF DCE UUID presentation format (as output by {\tt uuidgen}, etc). \item ints are all assumed to be 64-bit in our API and are encoded as a @@ -84,6 +89,32 @@ These types are mapped onto XML-RPC types in a straight-forward manner: \end{itemize} +\subsection{Note on References vs UUIDs} + +References are opaque types --- encoded as XML-RPC strings on the wire --- understood +only by the particular server which generated them. Servers are free to choose +any concrete representation they find convenient; clients should not make any +assumptions or attempt to parse the string contents. References are not guaranteed +to be permanent identifiers for objects; clients should not assume that references +generated during one session are valid for any future session. References do not +allow objects to be compared for equality. Two references to the same object are +not guaranteed to be textually identical. + +UUIDs are intended to be permanent names for objects. They are +guaranteed to be in the OSF DCE UUID presentation format (as output by {\tt uuidgen}. +Clients may store UUIDs on disk and use them to lookup objects in subsequent sessions +with the server. Clients may also test equality on objects by comparing UUID strings. + +The API provides mechanisms +for translating between UUIDs and opaque references. Each class that contains a UUID +field provides: +\begin{itemize} +\item A ``{\tt get\_by\_uuid}'' method that takes a UUID, $u$, and returns an opaque reference +to the server-side object that has UUID=$u$; +\item A {\tt get\_uuid} function (a regular ``field getter'' RPC) that takes an opaque reference, +$r$, and returns the UUID of the server-side object that is referenced by $r$. +\end{itemize} + \subsection{Return Values/Status Codes} \label{synchronous-result} @@ -138,7 +169,7 @@ may look like this: \subsection{Transport Layer} -We ought to support at least +The following transport layers are currently supported: \begin{itemize} \item HTTP/S for remote administration \item HTTP over Unix domain sockets for local administration @@ -247,13 +278,12 @@ call takes the session token as the only parameter) \begin{verbatim} >>> all_vms = host.get_resident_VMs(session)['Value'] >>> all_vms -['b7b92d9e-d442-4710-92a5-ab039fd7d89b', '23e1e837-abbf-4675-b077-d4007989b0cc', - '2045dbc0-0734-4eea-9cb2-b8218c6b5bf2', '3202ae18-a046-4c32-9fda-e32e9631866e'] +['OpaqueRef:1', 'OpaqueRef:2', 'OpaqueRef:3', 'OpaqueRef:4' ] \end{verbatim} -The VM references here are UUIDs, though they may not be that simple in the -future, and you should treat them as opaque strings. Once a reference to a VM -has been acquired a lifecycle operation may be invoked: +The VM references here have the form {\tt OpaqueRef:X}, though they may not be +that simple in the future, and you should treat them as opaque strings. +Once a reference to a VM has been acquired a lifecycle operation may be invoked: \begin{verbatim} >>> xen.VM.start(session, all_vms[3], False) From 409ea8c19780a9fc87a289fc7de469f3df24c131 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Fri, 9 Mar 2007 00:46:50 +0000 Subject: [PATCH 014/170] Remove the word "Additional" from all the RPC subheadings -- we include all the methods now, not just the non-accessors. Signed-off-by: Ewan Mellor --- docs/xen-api/xenapi-datamodel.tex | 46 +++++++++++++++---------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex index 02ef2e90bd..19b2abfd70 100644 --- a/docs/xen-api/xenapi-datamodel.tex +++ b/docs/xen-api/xenapi-datamodel.tex @@ -231,7 +231,7 @@ $\mathit{RO}_\mathit{run}$ & {\tt this\_user} & user ref & Currently connected $\mathit{RO}_\mathit{run}$ & {\tt last\_active} & int & Timestamp for last time session was active \\ \hline \end{longtable} -\subsection{Additional RPCs associated with class: session} +\subsection{RPCs associated with class: session} \subsubsection{RPC name:~login\_with\_password} {\bf Overview:} @@ -505,7 +505,7 @@ $\mathit{RO}_\mathit{run}$ & {\tt error\_info} & string Set & if the task has f $\mathit{RO}_\mathit{run}$ & {\tt allowed\_operations} & (task\_allowed\_operations) Set & Operations allowed on this task \\ \hline \end{longtable} -\subsection{Additional RPCs associated with class: task} +\subsection{RPCs associated with class: task} \subsubsection{RPC name:~cancel} {\bf Overview:} @@ -1104,7 +1104,7 @@ $\mathit{RO}_\mathit{run}$ & {\tt metrics} & VM\_metrics ref & metrics associat $\mathit{RO}_\mathit{run}$ & {\tt guest\_metrics} & VM\_guest\_metrics ref & metrics associated with the running guest \\ \hline \end{longtable} -\subsection{Additional RPCs associated with class: VM} +\subsection{RPCs associated with class: VM} \subsubsection{RPC name:~clone} {\bf Overview:} @@ -4247,7 +4247,7 @@ $\mathit{RO}_\mathit{run}$ & {\tt VCPUs/number} & int & Current number of VCPUs $\mathit{RO}_\mathit{run}$ & {\tt VCPUs/utilisation} & (int $\rightarrow$ float) Map & Utilisation for all of guest's current VCPUs \\ \hline \end{longtable} -\subsection{Additional RPCs associated with class: VM\_metrics} +\subsection{RPCs associated with class: VM\_metrics} \subsubsection{RPC name:~get\_all} {\bf Overview:} @@ -4483,7 +4483,7 @@ $\mathit{RO}_\mathit{run}$ & {\tt networks} & (string $\rightarrow$ string) Map $\mathit{RO}_\mathit{run}$ & {\tt other} & (string $\rightarrow$ string) Map & anything else \\ \hline \end{longtable} -\subsection{Additional RPCs associated with class: VM\_guest\_metrics} +\subsection{RPCs associated with class: VM\_guest\_metrics} \subsubsection{RPC name:~get\_all} {\bf Overview:} @@ -4827,7 +4827,7 @@ $\mathit{RO}_\mathit{run}$ & {\tt host\_CPUs} & (host\_cpu ref) Set & The physi $\mathit{RO}_\mathit{ins}$ & {\tt metrics} & host\_metrics ref & metrics associated with this host. \\ \hline \end{longtable} -\subsection{Additional RPCs associated with class: host} +\subsection{RPCs associated with class: host} \subsubsection{RPC name:~disable} {\bf Overview:} @@ -6080,7 +6080,7 @@ $\mathit{RO}_\mathit{run}$ & {\tt memory/total} & int & Host's total memory (by $\mathit{RO}_\mathit{run}$ & {\tt memory/free} & int & Host's free memory (bytes) \\ \hline \end{longtable} -\subsection{Additional RPCs associated with class: host\_metrics} +\subsection{RPCs associated with class: host\_metrics} \subsubsection{RPC name:~get\_all} {\bf Overview:} @@ -6285,7 +6285,7 @@ $\mathit{RO}_\mathit{run}$ & {\tt flags} & string & the flags of the physical C $\mathit{RO}_\mathit{run}$ & {\tt utilisation} & float & the current CPU utilisation \\ \hline \end{longtable} -\subsection{Additional RPCs associated with class: host\_cpu} +\subsection{RPCs associated with class: host\_cpu} \subsubsection{RPC name:~get\_all} {\bf Overview:} @@ -6679,7 +6679,7 @@ $\mathit{RO}_\mathit{run}$ & {\tt VIFs} & (VIF ref) Set & list of connected vif $\mathit{RO}_\mathit{run}$ & {\tt PIFs} & (PIF ref) Set & list of connected pifs \\ \hline \end{longtable} -\subsection{Additional RPCs associated with class: network} +\subsection{RPCs associated with class: network} \subsubsection{RPC name:~get\_all} {\bf Overview:} @@ -7117,7 +7117,7 @@ $\mathit{RO}_\mathit{run}$ & {\tt qos/supported\_algorithms} & string Set & sup $\mathit{RO}_\mathit{run}$ & {\tt metrics} & VIF\_metrics ref & metrics associated with this VIF. \\ \hline \end{longtable} -\subsection{Additional RPCs associated with class: VIF} +\subsection{RPCs associated with class: VIF} \subsubsection{RPC name:~plug} {\bf Overview:} @@ -8009,7 +8009,7 @@ $\mathit{RO}_\mathit{run}$ & {\tt io/read\_kbs} & float & Read bandwidth (KiB/s $\mathit{RO}_\mathit{run}$ & {\tt io/write\_kbs} & float & Write bandwidth (KiB/s) \\ \hline \end{longtable} -\subsection{Additional RPCs associated with class: VIF\_metrics} +\subsection{RPCs associated with class: VIF\_metrics} \subsubsection{RPC name:~get\_all} {\bf Overview:} @@ -8215,7 +8215,7 @@ $\mathit{RW}$ & {\tt VLAN} & int & VLAN tag for all traffic passing through thi $\mathit{RO}_\mathit{ins}$ & {\tt metrics} & PIF\_metrics ref & metrics associated with this PIF. \\ \hline \end{longtable} -\subsection{Additional RPCs associated with class: PIF} +\subsection{RPCs associated with class: PIF} \subsubsection{RPC name:~create\_VLAN} {\bf Overview:} @@ -8786,7 +8786,7 @@ $\mathit{RO}_\mathit{run}$ & {\tt io/read\_kbs} & float & Read bandwidth (KiB/s $\mathit{RO}_\mathit{run}$ & {\tt io/write\_kbs} & float & Write bandwidth (KiB/s) \\ \hline \end{longtable} -\subsection{Additional RPCs associated with class: PIF\_metrics} +\subsection{RPCs associated with class: PIF\_metrics} \subsubsection{RPC name:~get\_all} {\bf Overview:} @@ -8993,7 +8993,7 @@ $\mathit{RO}_\mathit{ins}$ & {\tt type} & string & type of the storage reposito $\mathit{RO}_\mathit{ins}$ & {\tt location} & string & a string that uniquely determines the location of the storage repository; the format of this string depends on the repository's type \\ \hline \end{longtable} -\subsection{Additional RPCs associated with class: SR} +\subsection{RPCs associated with class: SR} \subsubsection{RPC name:~clone} {\bf Overview:} @@ -9627,7 +9627,7 @@ $\mathit{RW}$ & {\tt sharable} & bool & true if this disk may be shared \\ $\mathit{RW}$ & {\tt read\_only} & bool & true if this disk may ONLY be mounted read-only \\ \hline \end{longtable} -\subsection{Additional RPCs associated with class: VDI} +\subsection{RPCs associated with class: VDI} \subsubsection{RPC name:~snapshot} {\bf Overview:} @@ -10493,7 +10493,7 @@ $\mathit{RO}_\mathit{run}$ & {\tt qos/supported\_algorithms} & string Set & sup $\mathit{RO}_\mathit{run}$ & {\tt metrics} & VBD\_metrics ref & metrics associated with this VBD \\ \hline \end{longtable} -\subsection{Additional RPCs associated with class: VBD} +\subsection{RPCs associated with class: VBD} \subsubsection{RPC name:~media\_change} {\bf Overview:} @@ -11486,7 +11486,7 @@ $\mathit{RO}_\mathit{run}$ & {\tt io/read\_kbs} & float & Read bandwidth (KiB/s $\mathit{RO}_\mathit{run}$ & {\tt io/write\_kbs} & float & Write bandwidth (KiB/s) \\ \hline \end{longtable} -\subsection{Additional RPCs associated with class: VBD\_metrics} +\subsection{RPCs associated with class: VBD\_metrics} \subsubsection{RPC name:~get\_all} {\bf Overview:} @@ -11688,7 +11688,7 @@ $\mathit{RO}_\mathit{ins}$ & {\tt device\_config} & (string $\rightarrow$ strin $\mathit{RO}_\mathit{run}$ & {\tt currently\_attached} & bool & is the SR currently attached on this host? \\ \hline \end{longtable} -\subsection{Additional RPCs associated with class: PBD} +\subsection{RPCs associated with class: PBD} \subsubsection{RPC name:~get\_all} {\bf Overview:} @@ -12016,7 +12016,7 @@ $\mathit{RO}_\mathit{ins}$ & {\tt VM} & VM ref & the virtual machine \\ $\mathit{RO}_\mathit{ins}$ & {\tt VDI} & VDI ref & the virtual disk \\ \hline \end{longtable} -\subsection{Additional RPCs associated with class: crashdump} +\subsection{RPCs associated with class: crashdump} \subsubsection{RPC name:~destroy} {\bf Overview:} @@ -12248,7 +12248,7 @@ $\mathit{RO}_\mathit{ins}$ & {\tt VM} & VM ref & the virtual machine \\ $\mathit{RO}_\mathit{ins}$ & {\tt backend} & VM ref & the domain where the backend is located \\ \hline \end{longtable} -\subsection{Additional RPCs associated with class: VTPM} +\subsection{RPCs associated with class: VTPM} \subsubsection{RPC name:~get\_uuid} {\bf Overview:} @@ -12493,7 +12493,7 @@ $\mathit{RO}_\mathit{run}$ & {\tt VM} & VM ref & VM to which this console is at $\mathit{RW}$ & {\tt other\_config} & (string $\rightarrow$ string) Map & additional configuration \\ \hline \end{longtable} -\subsection{Additional RPCs associated with class: console} +\subsection{RPCs associated with class: console} \subsubsection{RPC name:~get\_all} {\bf Overview:} @@ -12928,7 +12928,7 @@ $\mathit{RO}_\mathit{ins}$ & {\tt short\_name} & string & short name (e.g. user $\mathit{RW}$ & {\tt fullname} & string & full name \\ \hline \end{longtable} -\subsection{Additional RPCs associated with class: user} +\subsection{RPCs associated with class: user} \subsubsection{RPC name:~get\_uuid} {\bf Overview:} @@ -13193,7 +13193,7 @@ all fields from the object \section{Class: debug} \subsection{Fields for class: debug} {\bf Class debug has no fields.} -\subsection{Additional RPCs associated with class: debug} +\subsection{RPCs associated with class: debug} \subsubsection{RPC name:~get\_all} {\bf Overview:} From 9f7e9b282085e8253f5497df465d70f6175c72fb Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Fri, 9 Mar 2007 01:06:11 +0000 Subject: [PATCH 015/170] Move the booting description out of the VM class description into the VM Lifecycle section of the doc. Signed-off-by: Ewan Mellor --- docs/xen-api/vm-lifecycle.tex | 16 ++++++++++++++ docs/xen-api/xenapi-datamodel.tex | 35 +------------------------------ tools/libxen/include/xen_vm.h | 33 ----------------------------- 3 files changed, 17 insertions(+), 67 deletions(-) diff --git a/docs/xen-api/vm-lifecycle.tex b/docs/xen-api/vm-lifecycle.tex index 23ddb9e9ae..cf790cbcba 100644 --- a/docs/xen-api/vm-lifecycle.tex +++ b/docs/xen-api/vm-lifecycle.tex @@ -22,3 +22,19 @@ Figure~\ref{fig-vm-lifecycle} shows the states that a VM can be in and the API calls that can be used to move the VM between these states. + +\section{VM boot parameters} + +The VM class contains a number of fields that control the way in which the VM is booted. +With reference to the fields defined in the VM class (see later in this document), +this section outlines the boot options available and the mechanisms provided for controlling them. + +VM booting is controlled by setting one of the two mutually exclusive groups: ``PV'', and ``HVM''. If HVM.boot\_policy is the empty string, then paravirtual domain building and booting will be used; otherwise the VM will be loaded as an HVM domain, and booted using an emulated BIOS. + +When paravirtual booting is in use, the PV/bootloader field indicates the bootloader to use. It may be ``pygrub'', in which case the platform's default installation of pygrub will be used, or a full path within the control domain to some other bootloader. The other fields, PV/kernel, PV/ramdisk, PV/args and PV/bootloader\_args will be passed to the bootloader unmodified, and interpretation of those fields is then specific to the bootloader itself, including the possibility that the bootloader will ignore some or all of those given values. Finally the paths of all bootable disks are added to the bootloader commandline (a disk is bootable if its VBD has the bootable flag set). There may be zero, one or many bootable disks; the bootloader decides which disk (if any) to boot from. + +If the bootloader is pygrub, then the menu.lst is parsed if present in the guest's filesystem, otherwise the specified kernel and ramdisk are used, or an autodetected kernel is used if nothing is specified and autodetection is possible. PV/args is appended to the kernel command line, no matter which mechanism is used for finding the kernel. + +If PV/bootloader is empty but PV/kernel is specified, then the kernel and ramdisk values will be treated as paths within the control domain. If both PV/bootloader and PV/kernel are empty, then the behaviour is as if PV/bootloader was specified as ``pygrub''. + +When using HVM booting, HVM/boot\_policy and HVM/boot\_params specify the boot handling. Only one policy is currently defined: ``BIOS order''. In this case, HVM/boot\_params should contain one key-value pair ``order'' = ``N'' where N is the string that will be passed to QEMU. \ No newline at end of file diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex index 19b2abfd70..c1e4a7cfc6 100644 --- a/docs/xen-api/xenapi-datamodel.tex +++ b/docs/xen-api/xenapi-datamodel.tex @@ -1022,40 +1022,7 @@ references to objects with match names \hline \multicolumn{1}{|l}{Name} & \multicolumn{3}{l|}{\bf VM} \\ \multicolumn{1}{|l}{Description} & \multicolumn{3}{l|}{\parbox{11cm}{\em A -virtual machine (or 'guest'). - -VM booting is controlled by setting one of the two mutually exclusive -groups: "PV", and "HVM". If HVM.boot\_policy is the empty string, then -paravirtual domain building and booting will be used; otherwise the VM will -be loaded as an HVM domain, and booted using an emulated BIOS. - -When paravirtual booting is in use, the PV/bootloader field indicates the -bootloader to use. It may be "pygrub", in which case the platform's -default installation of pygrub will be used, or a full path within the -control domain to some other bootloader. The other fields, PV/kernel, -PV/ramdisk, PV/args and PV/bootloader\_args will be passed to the -bootloader unmodified, and interpretation of those fields is then specific -to the bootloader itself, including the possibility that the bootloader -will ignore some or all of those given values. Finally the paths of all -bootable disks are added to the bootloader commandline (a disk is bootable -if its VBD has the bootable flag set). There may be zero, one or many -bootable disks; the bootloader decides which disk (if any) to boot from. - -If the bootloader is pygrub, then the menu.lst is parsed if present in the -guest's filesystem, otherwise the specified kernel and ramdisk are used, or -an autodetected kernel is used if nothing is specified and autodetection is -possible. PV/args is appended to the kernel command line, no matter which -mechanism is used for finding the kernel. - -If PV/bootloader is empty but PV/kernel is specified, then the kernel and -ramdisk values will be treated as paths within the control domain. If both -PV/bootloader and PV/kernel are empty, then the behaviour is as if -PV/bootloader was specified as "pygrub". - -When using HVM booting, HVM/boot\_policy and HVM/boot\_params specify the -boot handling. Only one policy is currently defined: "BIOS order". In -this case, HVM/boot\_params should contain one key-value pair "order" = "N" -where N is the string that will be passed to QEMU.}} \\ +virtual machine (or 'guest').}} \\ \hline Quals & Field & Type & Description \\ \hline diff --git a/tools/libxen/include/xen_vm.h b/tools/libxen/include/xen_vm.h index 71a3f62ca4..947ecc6ac6 100644 --- a/tools/libxen/include/xen_vm.h +++ b/tools/libxen/include/xen_vm.h @@ -40,39 +40,6 @@ * The VM class. * * A virtual machine (or 'guest'). - * - * VM booting is controlled by setting one of the two mutually exclusive - * groups: "PV", and "HVM". If HVM.boot_policy is the empty string, then - * paravirtual domain building and booting will be used; otherwise the VM will - * be loaded as an HVM domain, and booted using an emulated BIOS. - * - * When paravirtual booting is in use, the PV/bootloader field indicates the - * bootloader to use. It may be "pygrub", in which case the platform's - * default installation of pygrub will be used, or a full path within the - * control domain to some other bootloader. The other fields, PV/kernel, - * PV/ramdisk, PV/args and PV/bootloader_args will be passed to the bootloader - * unmodified, and interpretation of those fields is then specific to the - * bootloader itself, including the possibility that the bootloader will - * ignore some or all of those given values. Finally the paths of all bootable - * disks are added to the bootloader commandline (a disk is bootable if its - * VBD has the bootable flag set). There may be zero, one or many bootable - * disks; the bootloader decides which disk (if any) to boot from. - * - * If the bootloader is pygrub, then the menu.lst is parsed if present in the - * guest's filesystem, otherwise the specified kernel and ramdisk are used, or - * an autodetected kernel is used if nothing is specified and autodetection is - * possible. PV/args is appended to the kernel command line, no matter which - * mechanism is used for finding the kernel. - * - * If PV/bootloader is empty but PV/kernel is specified, then the kernel and - * ramdisk values will be treated as paths within the control domain. If both - * PV/bootloader and PV/kernel are empty, then the behaviour is as if - * PV/bootloader was specified as "pygrub". - * - * When using HVM booting, HVM/boot_policy and HVM/boot_params specify the - * boot handling. Only one policy is currently defined: "BIOS order". In - * this case, HVM/boot_params should contain one key-value pair "order" = "N" - * where N is the string that will be passed to QEMU.. */ From 4eb63aba01bb805a03a0829ef5dc4a3174a71dba Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Fri, 9 Mar 2007 01:15:07 +0000 Subject: [PATCH 016/170] Fancy headings. Signed-off-by: Ewan Mellor --- docs/xen-api/coversheet.tex | 2 +- docs/xen-api/xenapi.tex | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/xen-api/coversheet.tex b/docs/xen-api/coversheet.tex index cd0ad615d6..f7e4425ce6 100644 --- a/docs/xen-api/coversheet.tex +++ b/docs/xen-api/coversheet.tex @@ -47,4 +47,4 @@ Date: \datestring{} \legalnotice{} \newpage -\pagestyle{plain} \ No newline at end of file +\pagestyle{fancy} \ No newline at end of file diff --git a/docs/xen-api/xenapi.tex b/docs/xen-api/xenapi.tex index ff8cfa9fcc..e671d84156 100644 --- a/docs/xen-api/xenapi.tex +++ b/docs/xen-api/xenapi.tex @@ -16,6 +16,7 @@ \usepackage{a4wide} \usepackage{graphics} \usepackage{longtable} +\usepackage{fancyhdr} \setlength\topskip{0cm} \setlength\topmargin{0cm} @@ -35,7 +36,7 @@ \chapter{Introduction} -This document contains a proposal for a Xen Management API---an interface for +This document contains a description of the Xen Management API---an interface for remotely configuring and controlling virtualised guests running on a Xen-enabled host. From d0a005909aa12e8b75ad6dfacc9d48d9e7eb22b4 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Fri, 9 Mar 2007 01:25:43 +0000 Subject: [PATCH 017/170] Remove VDI.set_SR -- this was always unimplemented, and pretty mad. Signed-off-by: Ewan Mellor --- docs/xen-api/xenapi-datamodel.tex | 36 +------------------------------ tools/libxen/include/xen_vdi.h | 7 ------ tools/libxen/src/xen_vdi.c | 16 -------------- tools/python/xen/xend/XendAPI.py | 7 ++---- 4 files changed, 3 insertions(+), 63 deletions(-) diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex index c1e4a7cfc6..90d9abf875 100644 --- a/docs/xen-api/xenapi-datamodel.tex +++ b/docs/xen-api/xenapi-datamodel.tex @@ -9583,7 +9583,7 @@ Quals & Field & Type & Description \\ $\mathit{RO}_\mathit{run}$ & {\tt uuid} & string & unique identifier/object reference \\ $\mathit{RW}$ & {\tt name/label} & string & a human-readable name \\ $\mathit{RW}$ & {\tt name/description} & string & a notes field containg human-readable description \\ -$\mathit{RW}$ & {\tt SR} & SR ref & storage repository in which the VDI resides \\ +$\mathit{RO}_\mathit{ins}$ & {\tt SR} & SR ref & storage repository in which the VDI resides \\ $\mathit{RO}_\mathit{run}$ & {\tt VBDs} & (VBD ref) Set & list of vbds that refer to this disk \\ $\mathit{RO}_\mathit{run}$ & {\tt crash\_dumps} & (crashdump ref) Set & list of crash dumps that refer to this disk \\ $\mathit{RW}$ & {\tt virtual\_size} & int & size of disk as presented to the guest (in bytes). Note that, depending on storage backend type, requested size may not be respected exactly \\ @@ -9876,40 +9876,6 @@ SR ref value of the field -\vspace{0.3cm} -\vspace{0.3cm} -\vspace{0.3cm} -\subsubsection{RPC name:~set\_SR} - -{\bf Overview:} -Set the SR field of the given VDI. - - \noindent {\bf Signature:} -\begin{verbatim} void set_SR (session_id s, VDI ref self, SR ref value)\end{verbatim} - - -\noindent{\bf Arguments:} - - -\vspace{0.3cm} -\begin{tabular}{|c|c|p{7cm}|} - \hline -{\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VDI ref } & self & reference to the object \\ \hline - -{\tt SR ref } & value & New value to set \\ \hline - -\end{tabular} - -\vspace{0.3cm} - - \noindent {\bf Return Type:} -{\tt -void -} - - - \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} diff --git a/tools/libxen/include/xen_vdi.h b/tools/libxen/include/xen_vdi.h index 90120370d5..26e147250e 100644 --- a/tools/libxen/include/xen_vdi.h +++ b/tools/libxen/include/xen_vdi.h @@ -292,13 +292,6 @@ extern bool xen_vdi_set_name_description(xen_session *session, xen_vdi vdi, char *description); -/** - * Set the SR field of the given VDI. - */ -extern bool -xen_vdi_set_sr(xen_session *session, xen_vdi vdi, xen_sr sr); - - /** * Set the virtual_size field of the given VDI. */ diff --git a/tools/libxen/src/xen_vdi.c b/tools/libxen/src/xen_vdi.c index 150d341b1b..2e50db9e80 100644 --- a/tools/libxen/src/xen_vdi.c +++ b/tools/libxen/src/xen_vdi.c @@ -409,22 +409,6 @@ xen_vdi_set_name_description(xen_session *session, xen_vdi vdi, char *descriptio } -bool -xen_vdi_set_sr(xen_session *session, xen_vdi vdi, xen_sr sr) -{ - abstract_value param_values[] = - { - { .type = &abstract_type_string, - .u.string_val = vdi }, - { .type = &abstract_type_string, - .u.string_val = sr } - }; - - xen_call_(session, "VDI.set_SR", param_values, 2, NULL, NULL); - return session->ok; -} - - bool xen_vdi_set_virtual_size(xen_session *session, xen_vdi vdi, int64_t virtual_size) { diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index 4ab6916b53..69ebb3f341 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -1754,13 +1754,13 @@ class XendAPI(object): # Xen API: Class VDI # ---------------------------------------------------------------- - VDI_attr_ro = ['VBDs', + VDI_attr_ro = ['SR', + 'VBDs', 'physical_utilisation', 'sector_size', 'type'] VDI_attr_rw = ['name_label', 'name_description', - 'SR', 'virtual_size', 'sharable', 'read_only'] @@ -1812,9 +1812,6 @@ class XendAPI(object): self._get_VDI(vdi_ref).name_description = value return xen_api_success_void() - def VDI_set_SR(self, session, vdi_ref, value): - return xen_api_error(XEND_ERROR_UNSUPPORTED) - def VDI_set_virtual_size(self, session, vdi_ref, value): return xen_api_error(XEND_ERROR_UNSUPPORTED) From 99598dfc8a2e394eee9448ede3d6bd5d7750973b Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Fri, 9 Mar 2007 01:59:59 +0000 Subject: [PATCH 018/170] Improve error message. Signed-off-by: Tom Wilkie --- tools/python/xen/xm/XenAPI.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/python/xen/xm/XenAPI.py b/tools/python/xen/xm/XenAPI.py index 8d58c3f7f6..e557b9ccb8 100644 --- a/tools/python/xen/xm/XenAPI.py +++ b/tools/python/xen/xm/XenAPI.py @@ -155,7 +155,7 @@ class Session(xen.util.xmlrpclib2.ServerProxy): def _parse_result(result): if type(result) != dict or 'Status' not in result: - raise xmlrpclib.Fault(500, 'Missing Status in response from server') + raise xmlrpclib.Fault(500, 'Missing Status in response from server' + result) if result['Status'] == 'Success': if 'Value' in result: return result['Value'] From 81c452f998a0cafbca47b350e521a62cc7014d6a Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Fri, 9 Mar 2007 02:32:52 +0000 Subject: [PATCH 019/170] Make the VTPM.destroy method return 'void' upon success and adapt the test case to reflect that. Signed-off-by: Stefan Berger --- tools/python/xen/xend/XendAPI.py | 2 +- tools/xm-test/tests/vtpm/09_vtpm-xapi.py | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index 69ebb3f341..c89f5467d0 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -1926,7 +1926,7 @@ class XendAPI(object): XendDomain.POWER_STATE_NAMES[dom.state]]) from xen.xend.server import tpmif tpmif.destroy_vtpmstate(dom.getName()) - return xen_api_success(True) + return xen_api_success_void() else: return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']]) diff --git a/tools/xm-test/tests/vtpm/09_vtpm-xapi.py b/tools/xm-test/tests/vtpm/09_vtpm-xapi.py index 6a17c51045..6de28805d3 100644 --- a/tools/xm-test/tests/vtpm/09_vtpm-xapi.py +++ b/tools/xm-test/tests/vtpm/09_vtpm-xapi.py @@ -113,7 +113,7 @@ if not re.search("PCR-00:",run["output"]): FAIL("1. Virtual TPM is not working correctly on /dev/vtpm on backend side: \n%s" % run["output"]) try: - rc = session.xenapi.VTPM.destroy(vtpm_uuid) + session.xenapi.VTPM.destroy(vtpm_uuid) #Should never get here FAIL("Could destroy vTPM while VM is running") except: @@ -124,7 +124,7 @@ if rc: FAIL("Could not suspend VM") try: - rc = session.xenapi.VTPM.destroy(vtpm_uuid) + session.xenapi.VTPM.destroy(vtpm_uuid) #May not throw an exception in 'suspend' state except: pass @@ -150,8 +150,9 @@ if not re.search("PCR-00:",run["output"]): domain.stop() -rc = session.xenapi.VTPM.destroy(vtpm_uuid) -if not rc: +try: + session.xenapi.VTPM.destroy(vtpm_uuid) +except: FAIL("Could NOT destroy vTPM while domain is halted.") domain.destroy() From f064d42ef8af59f9ae7378fe5b0ec8dd7f2a40ca Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 9 Mar 2007 09:21:31 +0000 Subject: [PATCH 020/170] pci back: Fix registration of of filters on subsections of config space. Found by Jambanuthan K. Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c index 9eee88cd07..14e69adeec 100644 --- a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c @@ -357,7 +357,7 @@ int pciback_config_add_field_offset(struct pci_dev *dev, void *tmp; /* silently ignore duplicate fields */ - if (pciback_field_is_dup(dev, field->offset)) + if (pciback_field_is_dup(dev, field->offset + offset)) goto out; cfg_entry = kmalloc(sizeof(*cfg_entry), GFP_KERNEL); From e35486cedec1a727e4cb53198fe42b93dfdcd270 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Fri, 9 Mar 2007 11:11:23 +0000 Subject: [PATCH 021/170] [HVM] Revert thinko from 14291 Signed-off-by: Tim Deegan --- xen/arch/x86/hvm/hvm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 09515203de..17d0cf25ee 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -446,7 +446,7 @@ static int __hvm_copy(void *buf, paddr_t addr, int size, int dir, int virt) if ( dir ) { memcpy(p, buf, count); /* dir == TRUE: *to* guest */ - mark_dirty(current->domain, gfn); + mark_dirty(current->domain, mfn); } else memcpy(buf, p, count); /* dir == FALSE: *from guest */ From e1bc13a960bab6c8efd73200138efeb31a5aa35f Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 9 Mar 2007 11:11:59 +0000 Subject: [PATCH 022/170] xm: New command 'debug-keys' to inject debug-key events into Xen. Signed-off-by: Keir Fraser --- tools/libxc/xc_misc.c | 19 ++++++++++++++++ tools/libxc/xenctrl.h | 2 ++ tools/python/xen/lowlevel/xc/xc.c | 24 ++++++++++++++++++++ tools/python/xen/xend/XendNode.py | 6 +++++ tools/python/xen/xend/server/XMLRPCServer.py | 2 +- tools/python/xen/xm/main.py | 8 ++++++- xen/common/keyhandler.c | 2 +- xen/common/sysctl.c | 15 ++++++++++++ xen/include/public/sysctl.h | 13 +++++++++++ 9 files changed, 88 insertions(+), 3 deletions(-) diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c index b2a648528a..987eb0eb13 100644 --- a/tools/libxc/xc_misc.c +++ b/tools/libxc/xc_misc.c @@ -33,6 +33,25 @@ int xc_readconsolering(int xc_handle, return ret; } +int xc_send_debug_keys(int xc_handle, char *keys) +{ + int ret, len = strlen(keys); + DECLARE_SYSCTL; + + sysctl.cmd = XEN_SYSCTL_debug_keys; + set_xen_guest_handle(sysctl.u.debug_keys.keys, keys); + sysctl.u.debug_keys.nr_keys = len; + + if ( (ret = lock_pages(keys, len)) != 0 ) + return ret; + + ret = do_sysctl(xc_handle, &sysctl); + + unlock_pages(keys, len); + + return ret; +} + int xc_physinfo(int xc_handle, xc_physinfo_t *put_info) { diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index 96ba314503..4b346a74f0 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -467,6 +467,8 @@ int xc_readconsolering(int xc_handle, unsigned int *pnr_chars, int clear); +int xc_send_debug_keys(int xc_handle, char *keys); + typedef xen_sysctl_physinfo_t xc_physinfo_t; int xc_physinfo(int xc_handle, xc_physinfo_t *info); diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c index 7da0288cbd..804adc3104 100644 --- a/tools/python/xen/lowlevel/xc/xc.c +++ b/tools/python/xen/lowlevel/xc/xc.c @@ -1007,6 +1007,24 @@ static PyObject *pyxc_domain_send_trigger(XcObject *self, return zero; } +static PyObject *pyxc_send_debug_keys(XcObject *self, + PyObject *args, + PyObject *kwds) +{ + char *keys; + + static char *kwd_list[] = { "keys", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "s", kwd_list, &keys) ) + return NULL; + + if ( xc_send_debug_keys(self->xc_handle, keys) != 0 ) + return pyxc_error_to_exception(); + + Py_INCREF(zero); + return zero; +} + static PyObject *dom_op(XcObject *self, PyObject *args, int (*fn)(int, uint32_t)) { @@ -1420,6 +1438,12 @@ static PyMethodDef pyxc_methods[] = { " vcpu [int]: VCPU to be sent trigger.\n" "Returns: [int] 0 on success; -1 on error.\n" }, + { "send_debug_keys", + (PyCFunction)pyxc_send_debug_keys, + METH_VARARGS | METH_KEYWORDS, "\n" + "Inject debug keys into Xen.\n" + " keys [str]: String of keys to inject.\n" }, + #ifdef __powerpc__ { "arch_alloc_real_mode_area", (PyCFunction)pyxc_alloc_real_mode_area, diff --git a/tools/python/xen/xend/XendNode.py b/tools/python/xen/xend/XendNode.py index 9d2a70dd9e..5976d80f39 100644 --- a/tools/python/xen/xend/XendNode.py +++ b/tools/python/xen/xend/XendNode.py @@ -453,6 +453,12 @@ class XendNode: return pif.network raise Exception('Bridge %s is not connected to a network' % bridge) + # + # Debug keys. + # + + def send_debug_keys(self, keys): + return self.xc.send_debug_keys(keys) # # Getting host information. diff --git a/tools/python/xen/xend/server/XMLRPCServer.py b/tools/python/xen/xend/server/XMLRPCServer.py index 7c3a2a1a9d..ed07811ff6 100644 --- a/tools/python/xen/xend/server/XMLRPCServer.py +++ b/tools/python/xen/xend/server/XMLRPCServer.py @@ -157,7 +157,7 @@ class XMLRPCServer: self.server.register_function(fn, "xend.domain.%s" % name[7:]) # Functions in XendNode and XendDmesg - for type, lst, n in [(XendNode, ['info'], 'node'), + for type, lst, n in [(XendNode, ['info', 'send_debug_keys'], 'node'), (XendDmesg, ['info', 'clear'], 'node.dmesg')]: inst = type.instance() for name in lst: diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 7075e95444..8fcc2bc525 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -133,6 +133,7 @@ SUBCOMMAND_HELP = { 'sched-credit': ('[-d [-w[=WEIGHT]|-c[=CAP]]]', 'Get/set credit scheduler parameters.'), 'sysrq' : (' ', 'Send a sysrq to a domain.'), + 'debug-keys' : ('', 'Send debug keys to Xen.'), 'trigger' : (' []', 'Send a trigger to a domain.'), 'vcpu-list' : ('[]', @@ -260,7 +261,6 @@ common_commands = [ "shutdown", "start", "suspend", - "trigger", "top", "unpause", "uptime", @@ -300,6 +300,7 @@ domain_commands = [ ] host_commands = [ + "debug-keys", "dmesg", "info", "log", @@ -1395,6 +1396,10 @@ def xm_trigger(args): server.xend.domain.send_trigger(dom, trigger, vcpu) +def xm_debug_keys(args): + arg_check(args, "debug-keys", 1) + server.xend.node.send_debug_keys(str(args[0])) + def xm_top(args): arg_check(args, "top", 0) @@ -1738,6 +1743,7 @@ commands = { "pause": xm_pause, "unpause": xm_unpause, # host commands + "debug-keys": xm_debug_keys, "dmesg": xm_dmesg, "info": xm_info, "log": xm_log, diff --git a/xen/common/keyhandler.c b/xen/common/keyhandler.c index b99d396399..da92b6fded 100644 --- a/xen/common/keyhandler.c +++ b/xen/common/keyhandler.c @@ -47,7 +47,7 @@ void handle_keypress(unsigned char key, struct cpu_user_regs *regs) { irq_keyhandler_t *h; - if ( key_table[key].flags & KEYHANDLER_IRQ_CALLBACK ) + if ( !in_irq() || (key_table[key].flags & KEYHANDLER_IRQ_CALLBACK) ) { console_start_log_everything(); if ( (h = key_table[key].u.irq_handler) != NULL ) diff --git a/xen/common/sysctl.c b/xen/common/sysctl.c index 789e643ff2..0cba2c1164 100644 --- a/xen/common/sysctl.c +++ b/xen/common/sysctl.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -121,6 +122,20 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl) break; #endif + case XEN_SYSCTL_debug_keys: + { + char c; + uint32_t i; + + for ( i = 0; i < op->u.debug_keys.nr_keys; i++ ) + { + if ( copy_from_guest_offset(&c, op->u.debug_keys.keys, i, 1) ) + return -EFAULT; + handle_keypress(c, guest_cpu_user_regs()); + } + } + break; + default: ret = arch_do_sysctl(op, u_sysctl); break; diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h index dcd7ee7d26..e18d7243f6 100644 --- a/xen/include/public/sysctl.h +++ b/xen/include/public/sysctl.h @@ -140,6 +140,18 @@ struct xen_sysctl_getdomaininfolist { typedef struct xen_sysctl_getdomaininfolist xen_sysctl_getdomaininfolist_t; DEFINE_XEN_GUEST_HANDLE(xen_sysctl_getdomaininfolist_t); +/* + * Inject debug keys into Xen. + */ +#define XEN_SYSCTL_debug_keys 7 +struct xen_sysctl_debug_keys { + /* IN variables. */ + XEN_GUEST_HANDLE_64(char) keys; + uint32_t nr_keys; +}; +typedef struct xen_sysctl_debug_keys xen_sysctl_debug_keys_t; +DEFINE_XEN_GUEST_HANDLE(xen_sysctl_debug_keys_t); + struct xen_sysctl { uint32_t cmd; uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */ @@ -150,6 +162,7 @@ struct xen_sysctl { struct xen_sysctl_sched_id sched_id; struct xen_sysctl_perfc_op perfc_op; struct xen_sysctl_getdomaininfolist getdomaininfolist; + struct xen_sysctl_debug_keys debug_keys; uint8_t pad[128]; } u; }; From 16ea519d6c90d07f9885f39f2e133f99204a54c5 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 9 Mar 2007 11:44:31 +0000 Subject: [PATCH 023/170] linux: Upgrade to latest Xen interface version (0x00030205). Signed-off-by: Keir Fraser --- buildconfigs/linux-defconfig_xen0_ia64 | 2 +- buildconfigs/linux-defconfig_xen0_x86_32 | 2 +- buildconfigs/linux-defconfig_xen0_x86_64 | 2 +- buildconfigs/linux-defconfig_xenU_ia64 | 2 +- buildconfigs/linux-defconfig_xenU_x86_32 | 2 +- buildconfigs/linux-defconfig_xenU_x86_64 | 2 +- buildconfigs/linux-defconfig_xen_ia64 | 2 +- buildconfigs/linux-defconfig_xen_x86_32 | 2 +- buildconfigs/linux-defconfig_xen_x86_64 | 2 +- .../arch/i386/kernel/cpu/mtrr/main-xen.c | 24 +++++++++---------- .../arch/i386/kernel/io_apic-xen.c | 4 ++-- .../arch/i386/kernel/ioport-xen.c | 2 +- .../arch/i386/kernel/microcode-xen.c | 6 ++--- .../arch/i386/kernel/process-xen.c | 3 ++- .../arch/i386/kernel/quirks-xen.c | 6 ++--- .../arch/i386/kernel/time-xen.c | 12 +++++----- .../arch/i386/mm/hypervisor.c | 4 ++-- .../arch/ia64/xen/xcom_hcall.c | 2 +- .../arch/ia64/xen/xcom_mini.c | 2 +- .../arch/ia64/xen/xcom_privcmd.c | 22 ++++++++--------- .../arch/x86_64/kernel/ioport-xen.c | 2 +- .../arch/x86_64/kernel/process-xen.c | 5 ++-- linux-2.6-xen-sparse/drivers/xen/Kconfig | 2 +- .../drivers/xen/core/machine_reboot.c | 1 - .../drivers/xen/privcmd/privcmd.c | 1 - .../include/asm-i386/mach-xen/asm/hypercall.h | 8 +++---- .../asm-i386/mach-xen/asm/hypervisor.h | 2 +- .../include/asm-ia64/hypercall.h | 4 ++-- .../include/asm-ia64/hypervisor.h | 2 +- .../asm-x86_64/mach-xen/asm/hypercall.h | 8 +++---- 30 files changed, 70 insertions(+), 70 deletions(-) diff --git a/buildconfigs/linux-defconfig_xen0_ia64 b/buildconfigs/linux-defconfig_xen0_ia64 index 9869aab066..e29682a58a 100644 --- a/buildconfigs/linux-defconfig_xen0_ia64 +++ b/buildconfigs/linux-defconfig_xen0_ia64 @@ -1619,7 +1619,7 @@ CONFIG_CRYPTO_DES=y CONFIG_XEN_BALLOON=y CONFIG_XEN_REBOOT=y # CONFIG_XEN_SMPBOOT is not set -CONFIG_XEN_INTERFACE_VERSION=0x00030203 +CONFIG_XEN_INTERFACE_VERSION=0x00030205 # # XEN diff --git a/buildconfigs/linux-defconfig_xen0_x86_32 b/buildconfigs/linux-defconfig_xen0_x86_32 index ad24086d00..be74277044 100644 --- a/buildconfigs/linux-defconfig_xen0_x86_32 +++ b/buildconfigs/linux-defconfig_xen0_x86_32 @@ -1384,7 +1384,7 @@ CONFIG_CRYPTO_CRC32C=m # # CONFIG_CRYPTO_DEV_PADLOCK is not set CONFIG_XEN=y -CONFIG_XEN_INTERFACE_VERSION=0x00030203 +CONFIG_XEN_INTERFACE_VERSION=0x00030205 # # XEN diff --git a/buildconfigs/linux-defconfig_xen0_x86_64 b/buildconfigs/linux-defconfig_xen0_x86_64 index ea1ec55f79..15cefeff06 100644 --- a/buildconfigs/linux-defconfig_xen0_x86_64 +++ b/buildconfigs/linux-defconfig_xen0_x86_64 @@ -1334,7 +1334,7 @@ CONFIG_CRYPTO_CRC32C=m # Hardware crypto devices # CONFIG_XEN=y -CONFIG_XEN_INTERFACE_VERSION=0x00030203 +CONFIG_XEN_INTERFACE_VERSION=0x00030205 # # XEN diff --git a/buildconfigs/linux-defconfig_xenU_ia64 b/buildconfigs/linux-defconfig_xenU_ia64 index ed518155e7..b98752bd44 100644 --- a/buildconfigs/linux-defconfig_xenU_ia64 +++ b/buildconfigs/linux-defconfig_xenU_ia64 @@ -1471,7 +1471,7 @@ CONFIG_CRYPTO_DES=y CONFIG_XEN_BALLOON=y CONFIG_XEN_REBOOT=y # CONFIG_XEN_SMPBOOT is not set -CONFIG_XEN_INTERFACE_VERSION=0x00030203 +CONFIG_XEN_INTERFACE_VERSION=0x00030205 # # XEN diff --git a/buildconfigs/linux-defconfig_xenU_x86_32 b/buildconfigs/linux-defconfig_xenU_x86_32 index 441f128a92..f9b364c2ec 100644 --- a/buildconfigs/linux-defconfig_xenU_x86_32 +++ b/buildconfigs/linux-defconfig_xenU_x86_32 @@ -904,7 +904,7 @@ CONFIG_CRYPTO_CRC32C=m # # CONFIG_CRYPTO_DEV_PADLOCK is not set CONFIG_XEN=y -CONFIG_XEN_INTERFACE_VERSION=0x00030203 +CONFIG_XEN_INTERFACE_VERSION=0x00030205 # # XEN diff --git a/buildconfigs/linux-defconfig_xenU_x86_64 b/buildconfigs/linux-defconfig_xenU_x86_64 index 1d7a46dba7..39c13af858 100644 --- a/buildconfigs/linux-defconfig_xenU_x86_64 +++ b/buildconfigs/linux-defconfig_xenU_x86_64 @@ -1200,7 +1200,7 @@ CONFIG_CRYPTO_CRC32C=m # Hardware crypto devices # CONFIG_XEN=y -CONFIG_XEN_INTERFACE_VERSION=0x00030203 +CONFIG_XEN_INTERFACE_VERSION=0x00030205 # # XEN diff --git a/buildconfigs/linux-defconfig_xen_ia64 b/buildconfigs/linux-defconfig_xen_ia64 index 25253bc891..fd7d951d2c 100644 --- a/buildconfigs/linux-defconfig_xen_ia64 +++ b/buildconfigs/linux-defconfig_xen_ia64 @@ -1619,7 +1619,7 @@ CONFIG_CRYPTO_DES=y CONFIG_XEN_BALLOON=y CONFIG_XEN_REBOOT=y # CONFIG_XEN_SMPBOOT is not set -CONFIG_XEN_INTERFACE_VERSION=0x00030203 +CONFIG_XEN_INTERFACE_VERSION=0x00030205 # # XEN diff --git a/buildconfigs/linux-defconfig_xen_x86_32 b/buildconfigs/linux-defconfig_xen_x86_32 index 8a793de380..834e990426 100644 --- a/buildconfigs/linux-defconfig_xen_x86_32 +++ b/buildconfigs/linux-defconfig_xen_x86_32 @@ -3242,7 +3242,7 @@ CONFIG_CRYPTO_TEST=m # # CONFIG_CRYPTO_DEV_PADLOCK is not set CONFIG_XEN=y -CONFIG_XEN_INTERFACE_VERSION=0x00030203 +CONFIG_XEN_INTERFACE_VERSION=0x00030205 # # XEN diff --git a/buildconfigs/linux-defconfig_xen_x86_64 b/buildconfigs/linux-defconfig_xen_x86_64 index a7269fbf88..afb8d949ff 100644 --- a/buildconfigs/linux-defconfig_xen_x86_64 +++ b/buildconfigs/linux-defconfig_xen_x86_64 @@ -3072,7 +3072,7 @@ CONFIG_CRYPTO_TEST=m # Hardware crypto devices # CONFIG_XEN=y -CONFIG_XEN_INTERFACE_VERSION=0x00030203 +CONFIG_XEN_INTERFACE_VERSION=0x00030205 # # XEN diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/cpu/mtrr/main-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/cpu/mtrr/main-xen.c index 380e20ec5b..6b0b18bbbf 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/cpu/mtrr/main-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/cpu/mtrr/main-xen.c @@ -14,11 +14,11 @@ static DEFINE_MUTEX(mtrr_mutex); void generic_get_mtrr(unsigned int reg, unsigned long *base, unsigned int *size, mtrr_type * type) { - dom0_op_t op; + struct xen_platform_op op; - op.cmd = DOM0_READ_MEMTYPE; + op.cmd = XENPF_read_memtype; op.u.read_memtype.reg = reg; - (void)HYPERVISOR_dom0_op(&op); + (void)HYPERVISOR_platform_op(&op); *size = op.u.read_memtype.nr_mfns; *base = op.u.read_memtype.mfn; @@ -36,12 +36,12 @@ unsigned int *usage_table; static void __init set_num_var_ranges(void) { - dom0_op_t op; + struct xen_platform_op op; for (num_var_ranges = 0; ; num_var_ranges++) { - op.cmd = DOM0_READ_MEMTYPE; + op.cmd = XENPF_read_memtype; op.u.read_memtype.reg = num_var_ranges; - if (HYPERVISOR_dom0_op(&op) != 0) + if (HYPERVISOR_platform_op(&op) != 0) break; } } @@ -64,15 +64,15 @@ int mtrr_add_page(unsigned long base, unsigned long size, unsigned int type, char increment) { int error; - dom0_op_t op; + struct xen_platform_op op; mutex_lock(&mtrr_mutex); - op.cmd = DOM0_ADD_MEMTYPE; + op.cmd = XENPF_add_memtype; op.u.add_memtype.mfn = base; op.u.add_memtype.nr_mfns = size; op.u.add_memtype.type = type; - error = HYPERVISOR_dom0_op(&op); + error = HYPERVISOR_platform_op(&op); if (error) { mutex_unlock(&mtrr_mutex); BUG_ON(error > 0); @@ -117,7 +117,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size) unsigned long lbase; unsigned int lsize; int error = -EINVAL; - dom0_op_t op; + struct xen_platform_op op; mutex_lock(&mtrr_mutex); @@ -141,10 +141,10 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size) goto out; } if (--usage_table[reg] < 1) { - op.cmd = DOM0_DEL_MEMTYPE; + op.cmd = XENPF_del_memtype; op.u.del_memtype.handle = 0; op.u.del_memtype.reg = reg; - error = HYPERVISOR_dom0_op(&op); + error = HYPERVISOR_platform_op(&op); if (error) { BUG_ON(error > 0); goto out; diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c index 023ec42582..8d50b28ddd 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c @@ -2510,10 +2510,10 @@ static int __init io_apic_bug_finalize(void) if(sis_apic_bug == -1) sis_apic_bug = 0; if (is_initial_xendomain()) { - dom0_op_t op = { .cmd = DOM0_PLATFORM_QUIRK }; + struct xen_platform_op op = { .cmd = XENPF_platform_quirk }; op.u.platform_quirk.quirk_id = sis_apic_bug ? QUIRK_IOAPIC_BAD_REGSEL : QUIRK_IOAPIC_GOOD_REGSEL; - HYPERVISOR_dom0_op(&op); + HYPERVISOR_platform_op(&op); } return 0; } diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/ioport-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/ioport-xen.c index 60ada981fb..1f704215e1 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/ioport-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/ioport-xen.c @@ -81,7 +81,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) t->io_bitmap_ptr = bitmap; set_thread_flag(TIF_IO_BITMAP); - set_iobitmap.bitmap = (char *)bitmap; + set_xen_guest_handle(set_iobitmap.bitmap, (char *)bitmap); set_iobitmap.nr_ports = IO_BITMAP_BITS; HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap, &set_iobitmap); } diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c index 55a416c885..15e30d1efb 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c @@ -71,12 +71,12 @@ static int do_microcode_update (const void __user *ubuf, size_t len) return -ENOMEM; if (copy_from_user(kbuf, ubuf, len) == 0) { - dom0_op_t op; + struct xen_platform_op op; - op.cmd = DOM0_MICROCODE; + op.cmd = XENPF_microcode_update; set_xen_guest_handle(op.u.microcode.data, kbuf); op.u.microcode.length = len; - err = HYPERVISOR_dom0_op(&op); + err = HYPERVISOR_platform_op(&op); } else err = -EFAULT; diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c index 2225fcc962..4ab9d16f65 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c @@ -606,7 +606,8 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas } if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) { - iobmp_op.bitmap = (char *)next->io_bitmap_ptr; + set_xen_guest_handle(iobmp_op.bitmap, + (char *)next->io_bitmap_ptr); iobmp_op.nr_ports = next->io_bitmap_ptr ? IO_BITMAP_BITS : 0; mcl->op = __HYPERVISOR_physdev_op; mcl->args[0] = PHYSDEVOP_set_iobitmap; diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/quirks-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/quirks-xen.c index 26b35341bd..85385ae6e1 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/quirks-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/quirks-xen.c @@ -30,11 +30,11 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev) raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word); if (!(word & (1 << 13))) { - dom0_op_t op; + struct xen_platform_op op; printk(KERN_INFO "Disabling irq balancing and affinity\n"); - op.cmd = DOM0_PLATFORM_QUIRK; + op.cmd = XENPF_platform_quirk; op.u.platform_quirk.quirk_id = QUIRK_NOIRQBALANCING; - (void)HYPERVISOR_dom0_op(&op); + (void)HYPERVISOR_platform_op(&op); } /* put back the original value for config space*/ diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c index b57ab9bdfe..4f2e155c7b 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c @@ -435,7 +435,7 @@ int do_settimeofday(struct timespec *tv) s64 nsec; unsigned int cpu; struct shadow_time_info *shadow; - dom0_op_t op; + struct xen_platform_op op; if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) return -EINVAL; @@ -460,11 +460,11 @@ int do_settimeofday(struct timespec *tv) __normalize_time(&sec, &nsec); if (is_initial_xendomain() && !independent_wallclock) { - op.cmd = DOM0_SETTIME; + op.cmd = XENPF_settime; op.u.settime.secs = sec; op.u.settime.nsecs = nsec; op.u.settime.system_time = shadow->system_timestamp; - HYPERVISOR_dom0_op(&op); + HYPERVISOR_platform_op(&op); update_wallclock(); } else if (independent_wallclock) { nsec -= shadow->system_timestamp; @@ -488,7 +488,7 @@ static void sync_xen_wallclock(unsigned long dummy) { time_t sec; s64 nsec; - dom0_op_t op; + struct xen_platform_op op; if (!ntp_synced() || independent_wallclock || !is_initial_xendomain()) return; @@ -499,11 +499,11 @@ static void sync_xen_wallclock(unsigned long dummy) nsec = xtime.tv_nsec + ((jiffies - wall_jiffies) * (u64)NS_PER_TICK); __normalize_time(&sec, &nsec); - op.cmd = DOM0_SETTIME; + op.cmd = XENPF_settime; op.u.settime.secs = sec; op.u.settime.nsecs = nsec; op.u.settime.system_time = processed_system_time; - HYPERVISOR_dom0_op(&op); + HYPERVISOR_platform_op(&op); update_wallclock(); diff --git a/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c b/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c index 7c9a60aace..1042f9c260 100644 --- a/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c +++ b/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c @@ -146,7 +146,7 @@ void xen_tlb_flush_mask(cpumask_t *mask) if ( cpus_empty(*mask) ) return; op.cmd = MMUEXT_TLB_FLUSH_MULTI; - op.arg2.vcpumask = mask->bits; + set_xen_guest_handle(op.arg2.vcpumask, mask->bits); BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0); } @@ -165,7 +165,7 @@ void xen_invlpg_mask(cpumask_t *mask, unsigned long ptr) return; op.cmd = MMUEXT_INVLPG_MULTI; op.arg1.linear_addr = ptr & PAGE_MASK; - op.arg2.vcpumask = mask->bits; + set_xen_guest_handle(op.arg2.vcpumask, mask->bits); BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0); } diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/xcom_hcall.c b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_hcall.c index 49f9ea6708..95588e7304 100644 --- a/linux-2.6-xen-sparse/arch/ia64/xen/xcom_hcall.c +++ b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_hcall.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/xcom_mini.c b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_mini.c index d4cafe06ba..c78f15355d 100644 --- a/linux-2.6-xen-sparse/arch/ia64/xen/xcom_mini.c +++ b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_mini.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c index e1e312d204..dc1012a0f6 100644 --- a/linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c +++ b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #define __XEN__ #include #include @@ -40,25 +40,25 @@ #define ROUND_DIV(v,s) (((v) + (s) - 1) / (s)) static int -xencomm_privcmd_dom0_op(privcmd_hypercall_t *hypercall) +xencomm_privcmd_platform_op(privcmd_hypercall_t *hypercall) { - dom0_op_t kern_op; - dom0_op_t __user *user_op = (dom0_op_t __user *)hypercall->arg[0]; + struct xen_platform_op kern_op; + struct xen_platform_op __user *user_op = (struct xen_platform_op __user *)hypercall->arg[0]; struct xencomm_handle *op_desc; struct xencomm_handle *desc = NULL; int ret = 0; - if (copy_from_user(&kern_op, user_op, sizeof(dom0_op_t))) + if (copy_from_user(&kern_op, user_op, sizeof(struct xen_platform_op))) return -EFAULT; - if (kern_op.interface_version != DOM0_INTERFACE_VERSION) + if (kern_op.interface_version != XENPF_INTERFACE_VERSION) return -EACCES; op_desc = xencomm_create_inline(&kern_op); switch (kern_op.cmd) { default: - printk("%s: unknown dom0 cmd %d\n", __func__, kern_op.cmd); + printk("%s: unknown platform cmd %d\n", __func__, kern_op.cmd); return -ENOSYS; } @@ -67,10 +67,10 @@ xencomm_privcmd_dom0_op(privcmd_hypercall_t *hypercall) return ret; } - ret = xencomm_arch_hypercall_dom0_op(op_desc); + ret = xencomm_arch_hypercall_platform_op(op_desc); /* FIXME: should we restore the handle? */ - if (copy_to_user(user_op, &kern_op, sizeof(dom0_op_t))) + if (copy_to_user(user_op, &kern_op, sizeof(struct xen_platform_op))) ret = -EFAULT; if (desc) @@ -638,8 +638,8 @@ int privcmd_hypercall(privcmd_hypercall_t *hypercall) { switch (hypercall->op) { - case __HYPERVISOR_dom0_op: - return xencomm_privcmd_dom0_op(hypercall); + case __HYPERVISOR_platform_op: + return xencomm_privcmd_platform_op(hypercall); case __HYPERVISOR_domctl: return xencomm_privcmd_domctl(hypercall); case __HYPERVISOR_sysctl: diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/ioport-xen.c b/linux-2.6-xen-sparse/arch/x86_64/kernel/ioport-xen.c index 1fcbb20839..a57442c698 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/ioport-xen.c +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/ioport-xen.c @@ -59,7 +59,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) memset(bitmap, 0xff, IO_BITMAP_BYTES); t->io_bitmap_ptr = bitmap; - set_iobitmap.bitmap = (char *)bitmap; + set_xen_guest_handle(set_iobitmap.bitmap, (char *)bitmap); set_iobitmap.nr_ports = IO_BITMAP_BITS; HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap, &set_iobitmap); } diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c b/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c index 6a7bf2ed37..a9e17cd564 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c @@ -50,7 +50,7 @@ #include #include #include -#include +#include #include #include #include @@ -540,7 +540,8 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) } if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) { - iobmp_op.bitmap = (char *)next->io_bitmap_ptr; + set_xen_guest_handle(iobmp_op.bitmap, + (char *)next->io_bitmap_ptr); iobmp_op.nr_ports = next->io_bitmap_ptr ? IO_BITMAP_BITS : 0; mcl->op = __HYPERVISOR_physdev_op; mcl->args[0] = PHYSDEVOP_set_iobitmap; diff --git a/linux-2.6-xen-sparse/drivers/xen/Kconfig b/linux-2.6-xen-sparse/drivers/xen/Kconfig index 019256771c..1f3e49f207 100644 --- a/linux-2.6-xen-sparse/drivers/xen/Kconfig +++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig @@ -13,7 +13,7 @@ config XEN if XEN config XEN_INTERFACE_VERSION hex - default 0x00030203 + default 0x00030205 menu "XEN" diff --git a/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c b/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c index 72efdce56f..1110e62888 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c index 46414068c1..0defc39d69 100644 --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c @@ -28,7 +28,6 @@ #include #include #include -#include #include static struct proc_dir_entry *privcmd_intf; diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h index c3ed3584b6..e50fd5a9a2 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h @@ -201,11 +201,11 @@ HYPERVISOR_set_timer_op( } static inline int -HYPERVISOR_dom0_op( - dom0_op_t *dom0_op) +HYPERVISOR_platform_op( + struct xen_platform_op *platform_op) { - dom0_op->interface_version = DOM0_INTERFACE_VERSION; - return _hypercall1(int, dom0_op, dom0_op); + platform_op->interface_version = XENPF_INTERFACE_VERSION; + return _hypercall1(int, platform_op, platform_op); } static inline int diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h index 5797dcc696..9bc4554b96 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h index 9ae66fe781..ee4d0ce604 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h @@ -120,9 +120,9 @@ HYPERVISOR_set_timer_op(u64 timeout) } static inline int -xencomm_arch_hypercall_dom0_op(struct xencomm_handle *op) +xencomm_arch_hypercall_platform_op(struct xencomm_handle *op) { - return _hypercall1(int, dom0_op, op); + return _hypercall1(int, platform_op, op); } static inline int diff --git a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h index 4cfea9a769..712778213d 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h @@ -51,7 +51,7 @@ extern int running_on_xen; #include #include #include -#include +#include #include #include #include diff --git a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h index 5c6c8deff6..9279217762 100644 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h @@ -204,11 +204,11 @@ HYPERVISOR_set_timer_op( } static inline int -HYPERVISOR_dom0_op( - dom0_op_t *dom0_op) +HYPERVISOR_platform_op( + struct xen_platform_op *platform_op) { - dom0_op->interface_version = DOM0_INTERFACE_VERSION; - return _hypercall1(int, dom0_op, dom0_op); + platform_op->interface_version = XENPF_INTERFACE_VERSION; + return _hypercall1(int, platform_op, platform_op); } static inline int From d696494d9bb04f3a8fef0ad33773731ffc92a571 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Fri, 9 Mar 2007 11:45:19 +0000 Subject: [PATCH 024/170] [SVM] Don't free HSA and root vmcb when disabling SVM since we're no longer allowed to free pages in an interrupt context. Signed-off-by: Tim Deegan --- xen/arch/x86/hvm/svm/svm.c | 22 ++++++---------------- xen/arch/x86/hvm/svm/vmcb.c | 5 ----- xen/include/asm-x86/hvm/svm/vmcb.h | 1 - 3 files changed, 6 insertions(+), 22 deletions(-) diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index 61380c606a..0766ca5de2 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -107,22 +107,10 @@ static inline void svm_inject_exception(struct vcpu *v, int trap, static void stop_svm(void) { u32 eax, edx; - int cpu = smp_processor_id(); - /* We turn off the EFER_SVME bit. */ rdmsr(MSR_EFER, eax, edx); eax &= ~EFER_SVME; wrmsr(MSR_EFER, eax, edx); - - /* release the HSA */ - free_host_save_area(hsa[cpu]); - hsa[cpu] = NULL; - wrmsr(MSR_K8_VM_HSAVE_PA, 0, 0 ); - - /* free up the root vmcb */ - free_vmcb(root_vmcb[cpu]); - root_vmcb[cpu] = NULL; - root_vmcb_pa[cpu] = 0; } static void svm_store_cpu_guest_regs( @@ -1058,8 +1046,9 @@ int start_svm(void) return 0; } - if (!(hsa[cpu] = alloc_host_save_area())) - return 0; + if (!hsa[cpu]) + if (!(hsa[cpu] = alloc_host_save_area())) + return 0; rdmsr(MSR_EFER, eax, edx); eax |= EFER_SVME; @@ -1074,8 +1063,9 @@ int start_svm(void) phys_hsa_hi = (u32) (phys_hsa >> 32); wrmsr(MSR_K8_VM_HSAVE_PA, phys_hsa_lo, phys_hsa_hi); - if (!(root_vmcb[cpu] = alloc_vmcb())) - return 0; + if (!root_vmcb[cpu]) + if (!(root_vmcb[cpu] = alloc_vmcb())) + return 0; root_vmcb_pa[cpu] = virt_to_maddr(root_vmcb[cpu]); if (cpu == 0) diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c index f2a220011e..1d9c1569c3 100644 --- a/xen/arch/x86/hvm/svm/vmcb.c +++ b/xen/arch/x86/hvm/svm/vmcb.c @@ -79,11 +79,6 @@ struct host_save_area *alloc_host_save_area(void) return hsa; } -void free_host_save_area(struct host_save_area *hsa) -{ - free_xenheap_page(hsa); -} - static int construct_vmcb(struct vcpu *v) { struct arch_svm_struct *arch_svm = &v->arch.hvm_svm; diff --git a/xen/include/asm-x86/hvm/svm/vmcb.h b/xen/include/asm-x86/hvm/svm/vmcb.h index 8551e8a479..9dff3e65af 100644 --- a/xen/include/asm-x86/hvm/svm/vmcb.h +++ b/xen/include/asm-x86/hvm/svm/vmcb.h @@ -460,7 +460,6 @@ struct arch_svm_struct { struct vmcb_struct *alloc_vmcb(void); struct host_save_area *alloc_host_save_area(void); void free_vmcb(struct vmcb_struct *vmcb); -void free_host_save_area(struct host_save_area *hsa); int svm_create_vmcb(struct vcpu *v); void svm_destroy_vmcb(struct vcpu *v); From 31a89e89bfbba1cae86e7ed813cff094a67b0cb9 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Fri, 9 Mar 2007 12:10:29 +0000 Subject: [PATCH 025/170] [XEN] Shadow: be more explicit in assuming that d->vcpu[0] is valid Signed-off-by: Tim Deegan --- xen/arch/x86/mm/shadow/common.c | 14 ++++++++++++-- xen/include/asm-x86/paging.h | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c index 92bcc001ab..c8829abc2a 100644 --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -802,7 +802,7 @@ void shadow_prealloc(struct domain *d, unsigned int order) v = current; if ( v->domain != d ) v = d->vcpu[0]; - ASSERT(v != NULL); + ASSERT(v != NULL); /* Shouldn't have enabled shadows if we've no vcpus */ /* Stage one: walk the list of pinned pages, unpinning them */ perfc_incrc(shadow_prealloc_1); @@ -861,7 +861,9 @@ static void shadow_blow_tables(struct domain *d) struct vcpu *v = d->vcpu[0]; mfn_t smfn; int i; - + + ASSERT(v != NULL); + /* Pass one: unpin all pinned pages */ list_for_each_backwards_safe(l,t, &d->arch.paging.shadow.pinned_shadows) { @@ -2384,6 +2386,7 @@ int shadow_enable(struct domain *d, u32 mode) /* Sanity check the arguments */ if ( (d == current->domain) || + d->vcpu[0] == NULL || shadow_mode_enabled(d) || ((mode & PG_translate) && !(mode & PG_refcounts)) || ((mode & PG_external) && !(mode & PG_translate)) ) @@ -2993,6 +2996,13 @@ int shadow_domctl(struct domain *d, return 0; } + if ( unlikely(d->vcpu[0] == NULL) ) + { + SHADOW_ERROR("Shadow op on a domain (%u) with no vcpus\n", + d->domain_id); + return -EINVAL; + } + switch ( sc->op ) { case XEN_DOMCTL_SHADOW_OP_OFF: diff --git a/xen/include/asm-x86/paging.h b/xen/include/asm-x86/paging.h index 249e206a5a..0a3b01ce85 100644 --- a/xen/include/asm-x86/paging.h +++ b/xen/include/asm-x86/paging.h @@ -273,7 +273,7 @@ static inline void paging_write_p2m_entry(struct domain *d, unsigned long gfn, struct vcpu *v = current; if ( v->domain != d ) v = d->vcpu[0]; - if ( likely(paging_mode_enabled(d) && v->arch.paging.mode != NULL) ) + if ( likely(v && paging_mode_enabled(d) && v->arch.paging.mode != NULL) ) { return v->arch.paging.mode->write_p2m_entry(v, gfn, p, new, level); } From 49ad34e4f41bc6e3691b07bae1c470fd7c2b8c1c Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Fri, 9 Mar 2007 12:16:21 +0000 Subject: [PATCH 026/170] [XEN] Don't let the tools take away all of a domain's vcpus. Signed-off-by: Weidong Han --- xen/common/domctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xen/common/domctl.c b/xen/common/domctl.c index 3a45586d65..b765964cb1 100644 --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -360,7 +360,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl) unsigned int i, max = op->u.max_vcpus.max, cpu; ret = -EINVAL; - if ( max > MAX_VIRT_CPUS ) + if ( max > MAX_VIRT_CPUS || max == 0 ) break; ret = -ESRCH; From 95ce7ffd2dd2ecbe6ce6c5ee3f987a22b52c3aa7 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Fri, 9 Mar 2007 12:28:37 +0000 Subject: [PATCH 027/170] [XEN] Fix 14315 We do need to be able to shadow_enable vcpu-less domains. Signed-off-by: Tim Deegan --- xen/arch/x86/mm/shadow/common.c | 1 - 1 file changed, 1 deletion(-) diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c index c8829abc2a..4907736299 100644 --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -2386,7 +2386,6 @@ int shadow_enable(struct domain *d, u32 mode) /* Sanity check the arguments */ if ( (d == current->domain) || - d->vcpu[0] == NULL || shadow_mode_enabled(d) || ((mode & PG_translate) && !(mode & PG_refcounts)) || ((mode & PG_external) && !(mode & PG_translate)) ) From 2f6d51b68b24e6e4c7799bc7abf594790bdc8833 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Fri, 9 Mar 2007 16:04:19 +0000 Subject: [PATCH 028/170] This patch fixes two problems with sending and receiving of (arrays of) structures. The first one allows to determine the size of a member when parsing a 'set'. The cast in the second part fixes the address calculation when serializing an array. Signed-off-by: Stefan Berger --- tools/libxen/src/xen_common.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/libxen/src/xen_common.c b/tools/libxen/src/xen_common.c index c6e2181850..5d72cab177 100644 --- a/tools/libxen/src/xen_common.c +++ b/tools/libxen/src/xen_common.c @@ -890,6 +890,9 @@ static size_t size_of_member(const abstract_type *type) case REF: return sizeof(arbitrary_record_opt *); + case STRUCT: + return type->struct_size; + default: assert(false); } @@ -1215,7 +1218,8 @@ add_struct_value(const struct abstract_type *type, void *value, for (size_t i = 0; i < set_val->size; i++) { - void *member_value = set_val->contents + (i * member_size); + void *member_value = (char *)set_val->contents + + (i * member_size); add_struct_value(member_type, member_value, add_unnamed_value, NULL, data_node); } From bc69003d96068102da46008481e5e449f2ef9b7d Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 9 Mar 2007 18:26:22 +0000 Subject: [PATCH 029/170] Revert 14316 -- no need to fix maxvcpu domctl. --- xen/common/domctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xen/common/domctl.c b/xen/common/domctl.c index b765964cb1..3a45586d65 100644 --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -360,7 +360,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl) unsigned int i, max = op->u.max_vcpus.max, cpu; ret = -EINVAL; - if ( max > MAX_VIRT_CPUS || max == 0 ) + if ( max > MAX_VIRT_CPUS ) break; ret = -ESRCH; From eb1a565927c0fdcd89be41f6d063c458539cca8d Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 9 Mar 2007 18:26:47 +0000 Subject: [PATCH 030/170] xen: New vcpu_op commands for setting periodic and single-shot timers. Signed-off-by: Keir Fraser --- xen/arch/ia64/xen/xensetup.c | 2 - xen/arch/powerpc/setup.c | 3 - xen/arch/x86/apic.c | 14 ++-- xen/arch/x86/setup.c | 8 +-- xen/common/compat/domain.c | 4 ++ xen/common/domain.c | 61 +++++++++++++++++ xen/common/page_alloc.c | 15 +++- xen/common/sched_credit.c | 38 +++++++++-- xen/common/schedule.c | 129 ++++++++++++++++++++--------------- xen/include/public/vcpu.h | 36 ++++++++-- xen/include/xen/mm.h | 5 ++ xen/include/xen/sched-if.h | 2 - xen/include/xen/sched.h | 8 ++- xen/include/xen/timer.h | 4 +- 14 files changed, 236 insertions(+), 93 deletions(-) diff --git a/xen/arch/ia64/xen/xensetup.c b/xen/arch/ia64/xen/xensetup.c index 4d88db400b..38a22b5e48 100644 --- a/xen/arch/ia64/xen/xensetup.c +++ b/xen/arch/ia64/xen/xensetup.c @@ -543,8 +543,6 @@ printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus); domain0_ready = 1; - schedulers_start(); - domain_unpause_by_systemcontroller(dom0); startup_cpu_idle_loop(); diff --git a/xen/arch/powerpc/setup.c b/xen/arch/powerpc/setup.c index c62380e1d7..314e1a6542 100644 --- a/xen/arch/powerpc/setup.c +++ b/xen/arch/powerpc/setup.c @@ -365,9 +365,6 @@ static void __init __start_xen(multiboot_info_t *mbi) kick_secondary_cpus(max_cpus); } - /* Secondary processors must be online before we call this. */ - schedulers_start(); - /* This cannot be called before secondary cpus are marked online. */ percpu_free_unused_areas(); diff --git a/xen/arch/x86/apic.c b/xen/arch/x86/apic.c index f6a79a7d2f..fbb8f30bab 100644 --- a/xen/arch/x86/apic.c +++ b/xen/arch/x86/apic.c @@ -1022,6 +1022,13 @@ int reprogram_timer(s_time_t timeout) s_time_t expire; u64 apic_tmict; + /* + * If we don't have local APIC then we just poll the timer list off the + * PIT interrupt. + */ + if ( !cpu_has_apic ) + return 1; + /* * We use this value because we don't trust zero (we think it may just * cause an immediate interrupt). At least this is guaranteed to hold it @@ -1044,13 +1051,6 @@ int reprogram_timer(s_time_t timeout) return 0; } - /* - * If we don't have local APIC then we just poll the timer list off the - * PIT interrupt. Cheesy but good enough to work on eg. VMware :-) - */ - if ( !cpu_has_apic ) - return 1; - /* conversion to bus units */ apic_tmict = (((u64)bus_scale) * expire)>>18; diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 61271bbee3..446c42f3d9 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -195,13 +195,13 @@ static void __init percpu_free_unused_areas(void) /* Find first unused CPU number. */ for ( i = 0; i < NR_CPUS; i++ ) - if ( !cpu_online(i) ) + if ( !cpu_possible(i) ) break; first_unused = i; - /* Check that there are no holes in cpu_online_map. */ + /* Check that there are no holes in cpu_possible_map. */ for ( ; i < NR_CPUS; i++ ) - BUG_ON(cpu_online(i)); + BUG_ON(cpu_possible(i)); #ifndef MEMORY_GUARD init_xenheap_pages(__pa(__per_cpu_start) + (first_unused << PERCPU_SHIFT), @@ -717,8 +717,6 @@ void __init __start_xen(multiboot_info_t *mbi) do_initcalls(); - schedulers_start(); - if ( opt_watchdog ) watchdog_enable(); diff --git a/xen/common/compat/domain.c b/xen/common/compat/domain.c index 3f54260316..12929122f6 100644 --- a/xen/common/compat/domain.c +++ b/xen/common/compat/domain.c @@ -55,6 +55,10 @@ int compat_vcpu_op(int cmd, int vcpuid, XEN_GUEST_HANDLE(void) arg) case VCPUOP_up: case VCPUOP_down: case VCPUOP_is_up: + case VCPUOP_set_periodic_timer: + case VCPUOP_stop_periodic_timer: + case VCPUOP_set_singleshot_timer: + case VCPUOP_stop_singleshot_timer: rc = do_vcpu_op(cmd, vcpuid, arg); break; diff --git a/xen/common/domain.c b/xen/common/domain.c index c1a1dc2b4e..74c997b952 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -102,6 +102,9 @@ struct vcpu *alloc_vcpu( v->runstate.state = is_idle_vcpu(v) ? RUNSTATE_running : RUNSTATE_offline; v->runstate.state_entry_time = NOW(); + /* VCPUs by default have a 100Hz ticker. */ + v->periodic_period = MILLISECS(10); + if ( (vcpu_id != 0) && !is_idle_domain(d) ) set_bit(_VCPUF_down, &v->vcpu_flags); @@ -267,6 +270,9 @@ void domain_kill(struct domain *d) domain_relinquish_resources(d); put_domain(d); + /* Kick page scrubbing after domain_relinquish_resources(). */ + page_scrub_kick(); + send_guest_global_virq(dom0, VIRQ_DOM_EXC); } @@ -589,6 +595,61 @@ long do_vcpu_op(int cmd, int vcpuid, XEN_GUEST_HANDLE(void) arg) break; } + case VCPUOP_set_periodic_timer: + { + struct vcpu_set_periodic_timer set; + + rc = -EFAULT; + if ( copy_from_guest(&set, arg, 1) ) + break; + + rc = -EINVAL; + if ( set.period_ns < MILLISECS(1) ) + break; + + v->periodic_period = set.period_ns; + vcpu_force_reschedule(v); + + break; + } + + case VCPUOP_stop_periodic_timer: + { + v->periodic_period = 0; + vcpu_force_reschedule(v); + break; + } + + case VCPUOP_set_singleshot_timer: + { + struct vcpu_set_singleshot_timer set; + + if ( v != current ) + return -EINVAL; + + if ( copy_from_guest(&set, arg, 1) ) + return -EFAULT; + + if ( v->singleshot_timer.cpu != smp_processor_id() ) + { + stop_timer(&v->singleshot_timer); + v->singleshot_timer.cpu = smp_processor_id(); + } + + set_timer(&v->singleshot_timer, set.timeout_abs_ns); + + break; + } + + case VCPUOP_stop_singleshot_timer: + { + if ( v != current ) + return -EINVAL; + + stop_timer(&v->singleshot_timer); + break; + } + default: rc = arch_do_vcpu_op(cmd, v, arg); break; diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c index dad5f071d9..2c01e73af4 100644 --- a/xen/common/page_alloc.c +++ b/xen/common/page_alloc.c @@ -970,6 +970,8 @@ __initcall(pagealloc_keyhandler_init); * PAGE SCRUBBING */ +static DEFINE_PER_CPU(struct timer, page_scrub_timer); + static void page_scrub_softirq(void) { struct list_head *ent; @@ -978,7 +980,7 @@ static void page_scrub_softirq(void) int i; s_time_t start = NOW(); - /* Aim to do 1ms of work (ten percent of a 10ms jiffy). */ + /* Aim to do 1ms of work every 10ms. */ do { spin_lock(&page_scrub_lock); @@ -1014,6 +1016,13 @@ static void page_scrub_softirq(void) free_heap_pages(pfn_dom_zone_type(page_to_mfn(pg)), pg, 0); } } while ( (NOW() - start) < MILLISECS(1) ); + + set_timer(&this_cpu(page_scrub_timer), NOW() + MILLISECS(10)); +} + +static void page_scrub_timer_fn(void *unused) +{ + page_scrub_schedule_work(); } unsigned long avail_scrub_pages(void) @@ -1049,6 +1058,10 @@ __initcall(register_heap_trigger); static __init int page_scrub_init(void) { + int cpu; + for_each_cpu ( cpu ) + init_timer(&per_cpu(page_scrub_timer, cpu), + page_scrub_timer_fn, NULL, cpu); open_softirq(PAGE_SCRUB_SOFTIRQ, page_scrub_softirq); return 0; } diff --git a/xen/common/sched_credit.c b/xen/common/sched_credit.c index 2ce83ace70..6bbbb7ae5b 100644 --- a/xen/common/sched_credit.c +++ b/xen/common/sched_credit.c @@ -186,6 +186,8 @@ struct csched_pcpu { struct list_head runq; uint32_t runq_sort_last; + struct timer ticker; + unsigned int tick; }; /* @@ -245,7 +247,7 @@ struct csched_private { */ static struct csched_private csched_priv; - +static void csched_tick(void *_cpu); static inline int __cycle_cpu(int cpu, const cpumask_t *mask) @@ -362,12 +364,13 @@ csched_pcpu_init(int cpu) if ( csched_priv.master >= csched_priv.ncpus ) csched_priv.master = cpu; + init_timer(&spc->ticker, csched_tick, (void *)(unsigned long)cpu, cpu); INIT_LIST_HEAD(&spc->runq); spc->runq_sort_last = csched_priv.runq_sort; per_cpu(schedule_data, cpu).sched_priv = spc; /* Start off idling... */ - BUG_ON( !is_idle_vcpu(per_cpu(schedule_data, cpu).curr) ); + BUG_ON(!is_idle_vcpu(per_cpu(schedule_data, cpu).curr)); cpu_set(cpu, csched_priv.idlers); spin_unlock_irqrestore(&csched_priv.lock, flags); @@ -1013,8 +1016,13 @@ csched_acct(void) } static void -csched_tick(unsigned int cpu) +csched_tick(void *_cpu) { + unsigned int cpu = (unsigned long)_cpu; + struct csched_pcpu *spc = CSCHED_PCPU(cpu); + + spc->tick++; + /* * Accounting for running VCPU */ @@ -1028,7 +1036,7 @@ csched_tick(unsigned int cpu) * we could distribute or at the very least cycle the duty. */ if ( (csched_priv.master == cpu) && - (per_cpu(schedule_data, cpu).tick % CSCHED_TICKS_PER_ACCT) == 0 ) + (spc->tick % CSCHED_TICKS_PER_ACCT) == 0 ) { csched_acct(); } @@ -1041,6 +1049,8 @@ csched_tick(unsigned int cpu) * once per accounting period (currently 30 milliseconds). */ csched_runq_sort(cpu); + + set_timer(&spc->ticker, NOW() + MILLISECS(CSCHED_MSECS_PER_TICK)); } static struct csched_vcpu * @@ -1248,8 +1258,7 @@ csched_dump_pcpu(int cpu) spc = CSCHED_PCPU(cpu); runq = &spc->runq; - printk(" tick=%lu, sort=%d, sibling=0x%lx, core=0x%lx\n", - per_cpu(schedule_data, cpu).tick, + printk(" sort=%d, sibling=0x%lx, core=0x%lx\n", spc->runq_sort_last, cpu_sibling_map[cpu].bits[0], cpu_core_map[cpu].bits[0]); @@ -1341,6 +1350,22 @@ csched_init(void) CSCHED_STATS_RESET(); } +/* Tickers cannot be kicked until SMP subsystem is alive. */ +static __init int csched_start_tickers(void) +{ + struct csched_pcpu *spc; + unsigned int cpu; + + for_each_online_cpu ( cpu ) + { + spc = CSCHED_PCPU(cpu); + set_timer(&spc->ticker, NOW() + MILLISECS(CSCHED_MSECS_PER_TICK)); + } + + return 0; +} +__initcall(csched_start_tickers); + struct scheduler sched_credit_def = { .name = "SMP Credit Scheduler", @@ -1359,7 +1384,6 @@ struct scheduler sched_credit_def = { .adjust = csched_dom_cntl, .pick_cpu = csched_cpu_pick, - .tick = csched_tick, .do_schedule = csched_schedule, .dump_cpu_state = csched_dump_pcpu, diff --git a/xen/common/schedule.c b/xen/common/schedule.c index 8ba192d0ac..447cc2744e 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -45,8 +45,8 @@ boolean_param("dom0_vcpus_pin", opt_dom0_vcpus_pin); /* Various timer handlers. */ static void s_timer_fn(void *unused); -static void t_timer_fn(void *unused); -static void vcpu_timer_fn(void *data); +static void vcpu_periodic_timer_fn(void *data); +static void vcpu_singleshot_timer_fn(void *data); static void poll_timer_fn(void *data); /* This is global for now so that private implementations can reach it */ @@ -66,9 +66,6 @@ static struct scheduler ops; (( ops.fn != NULL ) ? ops.fn( __VA_ARGS__ ) \ : (typeof(ops.fn(__VA_ARGS__)))0 ) -/* Per-CPU periodic timer sends an event to the currently-executing domain. */ -static DEFINE_PER_CPU(struct timer, t_timer); - static inline void vcpu_runstate_change( struct vcpu *v, int new_state, s_time_t new_entry_time) { @@ -114,8 +111,12 @@ int sched_init_vcpu(struct vcpu *v, unsigned int processor) cpus_setall(v->cpu_affinity); /* Initialise the per-domain timers. */ - init_timer(&v->timer, vcpu_timer_fn, v, v->processor); - init_timer(&v->poll_timer, poll_timer_fn, v, v->processor); + init_timer(&v->periodic_timer, vcpu_periodic_timer_fn, + v, v->processor); + init_timer(&v->singleshot_timer, vcpu_singleshot_timer_fn, + v, v->processor); + init_timer(&v->poll_timer, poll_timer_fn, + v, v->processor); /* Idle VCPUs are scheduled immediately. */ if ( is_idle_domain(d) ) @@ -132,7 +133,8 @@ int sched_init_vcpu(struct vcpu *v, unsigned int processor) void sched_destroy_vcpu(struct vcpu *v) { - kill_timer(&v->timer); + kill_timer(&v->periodic_timer); + kill_timer(&v->singleshot_timer); kill_timer(&v->poll_timer); SCHED_OP(destroy_vcpu, v); } @@ -223,10 +225,29 @@ static void vcpu_migrate(struct vcpu *v) vcpu_wake(v); } +/* + * Force a VCPU through a deschedule/reschedule path. + * For example, using this when setting the periodic timer period means that + * most periodic-timer state need only be touched from within the scheduler + * which can thus be done without need for synchronisation. + */ +void vcpu_force_reschedule(struct vcpu *v) +{ + vcpu_schedule_lock_irq(v); + if ( test_bit(_VCPUF_running, &v->vcpu_flags) ) + set_bit(_VCPUF_migrating, &v->vcpu_flags); + vcpu_schedule_unlock_irq(v); + + if ( test_bit(_VCPUF_migrating, &v->vcpu_flags) ) + { + vcpu_sleep_nosync(v); + vcpu_migrate(v); + } +} + int vcpu_set_affinity(struct vcpu *v, cpumask_t *affinity) { cpumask_t online_affinity; - unsigned long flags; if ( (v->domain->domain_id == 0) && opt_dom0_vcpus_pin ) return -EINVAL; @@ -235,13 +256,13 @@ int vcpu_set_affinity(struct vcpu *v, cpumask_t *affinity) if ( cpus_empty(online_affinity) ) return -EINVAL; - vcpu_schedule_lock_irqsave(v, flags); + vcpu_schedule_lock_irq(v); v->cpu_affinity = *affinity; if ( !cpu_isset(v->processor, v->cpu_affinity) ) set_bit(_VCPUF_migrating, &v->vcpu_flags); - vcpu_schedule_unlock_irqrestore(v, flags); + vcpu_schedule_unlock_irq(v); if ( test_bit(_VCPUF_migrating, &v->vcpu_flags) ) { @@ -458,7 +479,7 @@ long do_set_timer_op(s_time_t timeout) if ( timeout == 0 ) { - stop_timer(&v->timer); + stop_timer(&v->singleshot_timer); } else if ( unlikely(timeout < 0) || /* overflow into 64th bit? */ unlikely((offset > 0) && ((uint32_t)(offset >> 50) != 0)) ) @@ -474,14 +495,20 @@ long do_set_timer_op(s_time_t timeout) * timeout in this case can burn a lot of CPU. We therefore go for a * reasonable middleground of triggering a timer event in 100ms. */ - gdprintk(XENLOG_INFO, "Warning: huge timeout set by domain %d (vcpu %d):" - " %"PRIx64"\n", + gdprintk(XENLOG_INFO, "Warning: huge timeout set by domain %d " + "(vcpu %d): %"PRIx64"\n", v->domain->domain_id, v->vcpu_id, (uint64_t)timeout); - set_timer(&v->timer, NOW() + MILLISECS(100)); + set_timer(&v->singleshot_timer, NOW() + MILLISECS(100)); } else { - set_timer(&v->timer, timeout); + if ( v->singleshot_timer.cpu != smp_processor_id() ) + { + stop_timer(&v->singleshot_timer); + v->singleshot_timer.cpu = smp_processor_id(); + } + + set_timer(&v->singleshot_timer, timeout); } return 0; @@ -540,6 +567,28 @@ long sched_adjust(struct domain *d, struct xen_domctl_scheduler_op *op) return 0; } +static void vcpu_periodic_timer_work(struct vcpu *v) +{ + s_time_t now = NOW(); + uint64_t periodic_next_event; + + ASSERT(!active_timer(&v->periodic_timer)); + + if ( v->periodic_period == 0 ) + return; + + periodic_next_event = v->periodic_last_event + v->periodic_period; + if ( now > periodic_next_event ) + { + send_timer_event(v); + v->periodic_last_event = now; + periodic_next_event = now + v->periodic_period; + } + + v->periodic_timer.cpu = smp_processor_id(); + set_timer(&v->periodic_timer, periodic_next_event); +} + /* * The main function * - deschedule the current domain (scheduler independent). @@ -606,14 +655,13 @@ static void schedule(void) perfc_incrc(sched_ctx); - prev->sleep_tick = sd->tick; + stop_timer(&prev->periodic_timer); /* Ensure that the domain has an up-to-date time base. */ if ( !is_idle_vcpu(next) ) { update_vcpu_system_time(next); - if ( next->sleep_tick != sd->tick ) - send_timer_event(next); + vcpu_periodic_timer_work(next); } TRACE_4D(TRC_SCHED_SWITCH, @@ -631,13 +679,6 @@ void context_saved(struct vcpu *prev) vcpu_migrate(prev); } -/**************************************************************************** - * Timers: the scheduler utilises a number of timers - * - s_timer: per CPU timer for preemption and scheduling decisions - * - t_timer: per CPU periodic timer to send timer interrupt to current dom - * - dom_timer: per domain timer to specifiy timeout values - ****************************************************************************/ - /* The scheduler timer: force a run through the scheduler */ static void s_timer_fn(void *unused) { @@ -645,28 +686,15 @@ static void s_timer_fn(void *unused) perfc_incrc(sched_irq); } -/* Periodic tick timer: send timer event to current domain */ -static void t_timer_fn(void *unused) +/* Per-VCPU periodic timer function: sends a virtual timer interrupt. */ +static void vcpu_periodic_timer_fn(void *data) { - struct vcpu *v = current; - - this_cpu(schedule_data).tick++; - - if ( !is_idle_vcpu(v) ) - { - update_vcpu_system_time(v); - send_timer_event(v); - } - - page_scrub_schedule_work(); - - SCHED_OP(tick, smp_processor_id()); - - set_timer(&this_cpu(t_timer), NOW() + MILLISECS(10)); + struct vcpu *v = data; + vcpu_periodic_timer_work(v); } -/* Per-VCPU timer function: sends a virtual timer interrupt. */ -static void vcpu_timer_fn(void *data) +/* Per-VCPU single-shot timer function: sends a virtual timer interrupt. */ +static void vcpu_singleshot_timer_fn(void *data) { struct vcpu *v = data; send_timer_event(v); @@ -691,7 +719,6 @@ void __init scheduler_init(void) { spin_lock_init(&per_cpu(schedule_data, i).schedule_lock); init_timer(&per_cpu(schedule_data, i).s_timer, s_timer_fn, NULL, i); - init_timer(&per_cpu(t_timer, i), t_timer_fn, NULL, i); } for ( i = 0; schedulers[i] != NULL; i++ ) @@ -708,16 +735,6 @@ void __init scheduler_init(void) SCHED_OP(init); } -/* - * Start a scheduler for each CPU - * This has to be done *after* the timers, e.g., APICs, have been initialised - */ -void schedulers_start(void) -{ - t_timer_fn(0); - smp_call_function((void *)t_timer_fn, NULL, 1, 1); -} - void dump_runq(unsigned char key) { s_time_t now = NOW(); diff --git a/xen/include/public/vcpu.h b/xen/include/public/vcpu.h index 12df6dbe15..3d7d9587c0 100644 --- a/xen/include/public/vcpu.h +++ b/xen/include/public/vcpu.h @@ -42,13 +42,13 @@ * @extra_arg == pointer to vcpu_guest_context structure containing initial * state for the VCPU. */ -#define VCPUOP_initialise 0 +#define VCPUOP_initialise 0 /* * Bring up a VCPU. This makes the VCPU runnable. This operation will fail * if the VCPU has not been initialised (VCPUOP_initialise). */ -#define VCPUOP_up 1 +#define VCPUOP_up 1 /* * Bring down a VCPU (i.e., make it non-runnable). @@ -64,16 +64,16 @@ * practise to move a VCPU onto an 'idle' or default page table, LDT and * GDT before bringing it down. */ -#define VCPUOP_down 2 +#define VCPUOP_down 2 /* Returns 1 if the given VCPU is up. */ -#define VCPUOP_is_up 3 +#define VCPUOP_is_up 3 /* * Return information about the state and running time of a VCPU. * @extra_arg == pointer to vcpu_runstate_info structure. */ -#define VCPUOP_get_runstate_info 4 +#define VCPUOP_get_runstate_info 4 struct vcpu_runstate_info { /* VCPU's current state (RUNSTATE_*). */ int state; @@ -128,6 +128,32 @@ struct vcpu_register_runstate_memory_area { } addr; }; typedef struct vcpu_register_runstate_memory_area vcpu_register_runstate_memory_area_t; +DEFINE_XEN_GUEST_HANDLE(vcpu_register_runstate_memory_area_t); + +/* + * Set or stop a VCPU's periodic timer. Every VCPU has one periodic timer + * which can be set via these commands. Periods smaller than one millisecond + * may not be supported. + */ +#define VCPUOP_set_periodic_timer 6 /* arg == vcpu_set_periodic_timer_t */ +#define VCPUOP_stop_periodic_timer 7 /* arg == NULL */ +struct vcpu_set_periodic_timer { + uint64_t period_ns; +}; +typedef struct vcpu_set_periodic_timer vcpu_set_periodic_timer_t; +DEFINE_XEN_GUEST_HANDLE(vcpu_set_periodic_timer_t); + +/* + * Set or stop a VCPU's single-shot timer. Every VCPU has one single-shot + * timer which can be set via these commands. + */ +#define VCPUOP_set_singleshot_timer 8 /* arg == vcpu_set_singleshot_timer_t */ +#define VCPUOP_stop_singleshot_timer 9 /* arg == NULL */ +struct vcpu_set_singleshot_timer { + uint64_t timeout_abs_ns; +}; +typedef struct vcpu_set_singleshot_timer vcpu_set_singleshot_timer_t; +DEFINE_XEN_GUEST_HANDLE(vcpu_set_singleshot_timer_t); #endif /* __XEN_PUBLIC_VCPU_H__ */ diff --git a/xen/include/xen/mm.h b/xen/include/xen/mm.h index 8de9acaaab..a94d4efdb0 100644 --- a/xen/include/xen/mm.h +++ b/xen/include/xen/mm.h @@ -92,6 +92,11 @@ extern struct list_head page_scrub_list; if ( !list_empty(&page_scrub_list) ) \ raise_softirq(PAGE_SCRUB_SOFTIRQ); \ } while ( 0 ) +#define page_scrub_kick() \ + do { \ + if ( !list_empty(&page_scrub_list) ) \ + cpumask_raise_softirq(cpu_online_map, PAGE_SCRUB_SOFTIRQ); \ + } while ( 0 ) unsigned long avail_scrub_pages(void); #include diff --git a/xen/include/xen/sched-if.h b/xen/include/xen/sched-if.h index d506d7a589..f6ba9faa5c 100644 --- a/xen/include/xen/sched-if.h +++ b/xen/include/xen/sched-if.h @@ -16,7 +16,6 @@ struct schedule_data { struct vcpu *idle; /* idle task for this cpu */ void *sched_priv; struct timer s_timer; /* scheduling timer */ - unsigned long tick; /* current periodic 'tick' */ } __cacheline_aligned; DECLARE_PER_CPU(struct schedule_data, schedule_data); @@ -61,7 +60,6 @@ struct scheduler { unsigned int sched_id; /* ID for this scheduler */ void (*init) (void); - void (*tick) (unsigned int cpu); int (*init_domain) (struct domain *); void (*destroy_domain) (struct domain *); diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 0ab2874129..0653180fe7 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -79,8 +79,10 @@ struct vcpu struct vcpu *next_in_list; - struct timer timer; /* one-shot timer for timeout values */ - unsigned long sleep_tick; /* tick at which this vcpu started sleep */ + uint64_t periodic_period; + uint64_t periodic_last_event; + struct timer periodic_timer; + struct timer singleshot_timer; struct timer poll_timer; /* timeout for SCHEDOP_poll */ @@ -332,7 +334,6 @@ void __domain_crash_synchronous(void) __attribute__((noreturn)); #define set_current_state(_s) do { current->state = (_s); } while (0) void scheduler_init(void); -void schedulers_start(void); int sched_init_vcpu(struct vcpu *v, unsigned int processor); void sched_destroy_vcpu(struct vcpu *v); int sched_init_domain(struct domain *d); @@ -497,6 +498,7 @@ void domain_pause_by_systemcontroller(struct domain *d); void domain_unpause_by_systemcontroller(struct domain *d); void cpu_init(void); +void vcpu_force_reschedule(struct vcpu *v); int vcpu_set_affinity(struct vcpu *v, cpumask_t *affinity); void vcpu_runstate_get(struct vcpu *v, struct vcpu_runstate_info *runstate); diff --git a/xen/include/xen/timer.h b/xen/include/xen/timer.h index 495e81c4c3..4378f0f386 100644 --- a/xen/include/xen/timer.h +++ b/xen/include/xen/timer.h @@ -35,7 +35,7 @@ struct timer { * The timer must *previously* have been initialised by init_timer(), or its * structure initialised to all-zeroes. */ -static __inline__ int active_timer(struct timer *timer) +static inline int active_timer(struct timer *timer) { return (timer->heap_offset != 0); } @@ -46,7 +46,7 @@ static __inline__ int active_timer(struct timer *timer) * time (and multiple times) on an inactive timer. It must *never* execute * concurrently with any other operation on the same timer. */ -static __inline__ void init_timer( +static inline void init_timer( struct timer *timer, void (*function)(void *), void *data, From bde87bfe0eccc198a6fa6bc54ccbe37718a93182 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 9 Mar 2007 18:30:52 +0000 Subject: [PATCH 031/170] linux: fix condition for entering tickless state I noticed that timer interrupts were running at full rate regardless of whether the system was idle. softlockup_get_next_event() must return the maximum of zero and the delta to the next event, not the minimum (which is always zero or negative, yielding zero or a very large positive number as return value). Signed-off-by: Jan Beulich --- patches/linux-2.6.18/softlockup-no-idle-hz.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patches/linux-2.6.18/softlockup-no-idle-hz.patch b/patches/linux-2.6.18/softlockup-no-idle-hz.patch index 6799bfc4bf..d98edac8f2 100644 --- a/patches/linux-2.6.18/softlockup-no-idle-hz.patch +++ b/patches/linux-2.6.18/softlockup-no-idle-hz.patch @@ -34,7 +34,7 @@ diff -pruN ../orig-linux-2.6.18/kernel/softlockup.c ./kernel/softlockup.c + !per_cpu(watchdog_task, this_cpu)) + return MAX_JIFFY_OFFSET; + -+ return min_t(long, 0, touch_timestamp + HZ - jiffies); ++ return max_t(long, 0, touch_timestamp + HZ - jiffies); +} + /* From a5ca197fb5fb6996749d4954f17779b69ca9a7a2 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 9 Mar 2007 18:32:20 +0000 Subject: [PATCH 032/170] xen/x86: add allocation success checks. The necessary fix to arch_domain_create() was discovered by Gerd Hoffmann, but apparently not submitted so far. Also, adjust two error codes. Signed-off-by: Jan Beulich --- xen/arch/x86/domain.c | 6 ++++-- xen/arch/x86/domctl.c | 10 ++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 57fc717915..eee2c88197 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -457,8 +457,10 @@ int arch_domain_create(struct domain *d) fail: free_xenheap_page(d->shared_info); #ifdef __x86_64__ - free_domheap_page(virt_to_page(d->arch.mm_perdomain_l2)); - free_domheap_page(virt_to_page(d->arch.mm_perdomain_l3)); + if ( d->arch.mm_perdomain_l2 ) + free_domheap_page(virt_to_page(d->arch.mm_perdomain_l2)); + if ( d->arch.mm_perdomain_l3 ) + free_domheap_page(virt_to_page(d->arch.mm_perdomain_l3)); #endif free_xenheap_pages(d->arch.mm_perdomain_pt, pdpt_order); return rc; diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index d8ca0b0621..00bb202d57 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -145,6 +145,12 @@ long arch_do_domctl( } arr32 = alloc_xenheap_page(); + if ( !arr32 ) + { + ret = -ENOMEM; + put_domain(d); + break; + } ret = 0; for ( n = 0; n < num; ) @@ -157,7 +163,7 @@ long arch_do_domctl( domctl->u.getpageframeinfo2.array, n, k) ) { - ret = -EINVAL; + ret = -EFAULT; break; } @@ -201,7 +207,7 @@ long arch_do_domctl( if ( copy_to_guest_offset(domctl->u.getpageframeinfo2.array, n, arr32, k) ) { - ret = -EINVAL; + ret = -EFAULT; break; } From 4d42d7146cfbf731bc1ed7de1732f61004caa267 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 9 Mar 2007 18:33:36 +0000 Subject: [PATCH 033/170] dump-core: store .xen_p2m or .xen_pfn section in pfn ascending order. So far the order isn't specified and may be random in theory. But sorted array is requested by crash utility for efficient search. Fortunately it is the case except ia64 full virtualized domain. Update document such that those array must be sorted and fix the ia64 full virtualized domain case. Signed-off-by: Isaku Yamahata --- docs/misc/dump-core-format.txt | 8 ++++---- tools/libxc/xc_core_ia64.c | 24 ++++++++++++++++++++++++ tools/libxc/xc_ptrace_core.c | 1 - 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/docs/misc/dump-core-format.txt b/docs/misc/dump-core-format.txt index 99384ca94a..545740b6bd 100644 --- a/docs/misc/dump-core-format.txt +++ b/docs/misc/dump-core-format.txt @@ -80,8 +80,7 @@ Currently the following sections are defined. Some sections are optional. gmfn: machine physical frame number The size of arrays is stored in xch_nr_pages member of header note descriptor in .note.Xen note section. - There is no rule about the order. Analysis tools must no rely - on its order. + The entryies are stored in pfn-ascending order. This section must exist when the domain is non auto translated physmap mode. Currently x86 paravirtualized domain. @@ -94,8 +93,7 @@ Currently the following sections are defined. Some sections are optional. in .xen_pages section. The size of arrays is stored in xch_nr_pages member of header note descriptor in .note.Xen note section. - There is no rule about the order. Analysis tools must no rely - on its order. + The entries are stored in ascending order. This section must exist when the domain is auto translated physmap mode. Currently x86 full virtualized domain and ia64 domain. @@ -226,6 +224,8 @@ Currently only (major, minor) = (0, 1) is used. [When the format is changed, it would be described here.] (0, 1) update +- .xen_p2m, .xen_pfn section + Arrays must be in pfn ascending order for efficient looking up. - EI_CLASS member of elf header was changed to ELFCLASS64 independent of architecture. This is mainly for x86_32pae. The format version isn't bumped because analysis tools can distinguish it. diff --git a/tools/libxc/xc_core_ia64.c b/tools/libxc/xc_core_ia64.c index 455d532ee2..dff561b3d4 100644 --- a/tools/libxc/xc_core_ia64.c +++ b/tools/libxc/xc_core_ia64.c @@ -22,6 +22,28 @@ #include "xc_core.h" #include "xc_efi.h" #include "xc_dom.h" +#include + +static int +xc_memory_map_cmp(const void *lhs__, const void *rhs__) +{ + const struct xc_core_memory_map *lhs = + (const struct xc_core_memory_map *)lhs__; + const struct xc_core_memory_map *rhs = + (const struct xc_core_memory_map *)rhs__; + + if (lhs->addr < rhs->addr) + return -1; + if (lhs->addr > rhs->addr) + return 1; + + /* memory map overlap isn't allowed. complain */ + DPRINTF("duplicated addresses are detected " + "(0x%" PRIx64 ", 0x%" PRIx64 "), " + "(0x%" PRIx64 ", 0x%" PRIx64 ")\n", + lhs->addr, lhs->size, rhs->addr, rhs->size); + return 0; +} int xc_core_arch_auto_translated_physmap(const xc_dominfo_t *info) @@ -111,6 +133,7 @@ memory_map_get_old_hvm(int xc_handle, xc_dominfo_t *info, } *mapp = map; *nr_entries = i; + qsort(map, *nr_entries, sizeof(map[0]), &xc_memory_map_cmp); return 0; out: @@ -196,6 +219,7 @@ xc_core_arch_memory_map_get(int xc_handle, xc_dominfo_t *info, ret = 0; out: munmap(memmap_info, PAGE_SIZE); + qsort(map, *nr_entries, sizeof(map[0]), &xc_memory_map_cmp); return ret; old: diff --git a/tools/libxc/xc_ptrace_core.c b/tools/libxc/xc_ptrace_core.c index 82d06bb2d8..42d49cfcb7 100644 --- a/tools/libxc/xc_ptrace_core.c +++ b/tools/libxc/xc_ptrace_core.c @@ -390,7 +390,6 @@ map_gmfn_to_offset_elf(unsigned long gmfn) { /* * linear search - * There is no gurantee that those tables are sorted. */ unsigned long i; if (current_is_auto_translated_physmap) { From 4a0790cf997eaa1a00582c09510942f06fbc1c4f Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 9 Mar 2007 19:33:43 +0000 Subject: [PATCH 034/170] linux: fix build warnings Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c | 3 ++- linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c | 2 +- linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c index 4ab9d16f65..6c19ecc417 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c @@ -307,7 +307,8 @@ void exit_thread(void) if (unlikely(test_thread_flag(TIF_IO_BITMAP))) { struct task_struct *tsk = current; struct thread_struct *t = &tsk->thread; - struct physdev_set_iobitmap set_iobitmap = { 0 }; + struct physdev_set_iobitmap set_iobitmap; + memset(&set_iobitmap, 0, sizeof(set_iobitmap)); HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap, &set_iobitmap); kfree(t->io_bitmap_ptr); t->io_bitmap_ptr = NULL; diff --git a/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c b/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c index 4f72489800..28752922e3 100644 --- a/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c @@ -600,7 +600,7 @@ static void pgd_walk(pgd_t *pgd_base, pgprot_t flags) int g, u, m, rc; if (xen_feature(XENFEAT_auto_translated_physmap)) - return 0; + return; for (g = 0; g < USER_PTRS_PER_PGD; g++, pgd++) { if (pgd_none(*pgd)) diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c b/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c index a9e17cd564..41aa70ce63 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c @@ -304,7 +304,8 @@ void exit_thread(void) struct tss_struct *tss = &per_cpu(init_tss, get_cpu()); #endif #ifdef CONFIG_XEN - struct physdev_set_iobitmap iobmp_op = { 0 }; + struct physdev_set_iobitmap iobmp_op; + memset(&iobmp_op, 0, sizeof(iobmp_op)); #endif kfree(t->io_bitmap_ptr); From dbc6cbde5088caa22523a059fe18d90e457e084b Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 9 Mar 2007 19:34:52 +0000 Subject: [PATCH 035/170] xen: Debug 'q' key prints per-vcpu periodic timer info. Do not enable periodic timer by default for HVM guests. Signed-off-by: Keir Fraser --- xen/arch/x86/domain.c | 3 +++ xen/common/domain.c | 3 --- xen/common/keyhandler.c | 32 ++++++++++++++++++++++++-------- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index eee2c88197..2d6bdca72c 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -350,6 +350,9 @@ int vcpu_initialise(struct vcpu *v) } else { + /* PV guests by default have a 100Hz ticker. */ + v->periodic_period = MILLISECS(10); + /* PV guests get an emulated PIT too for video BIOSes to use. */ if ( !is_idle_domain(d) && (v->vcpu_id == 0) ) pit_init(v, cpu_khz); diff --git a/xen/common/domain.c b/xen/common/domain.c index 74c997b952..00ca0d7aa6 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -102,9 +102,6 @@ struct vcpu *alloc_vcpu( v->runstate.state = is_idle_vcpu(v) ? RUNSTATE_running : RUNSTATE_offline; v->runstate.state_entry_time = NOW(); - /* VCPUs by default have a 100Hz ticker. */ - v->periodic_period = MILLISECS(10); - if ( (vcpu_id != 0) && !is_idle_domain(d) ) set_bit(_VCPUF_down, &v->vcpu_flags); diff --git a/xen/common/keyhandler.c b/xen/common/keyhandler.c index da92b6fded..471642aec6 100644 --- a/xen/common/keyhandler.c +++ b/xen/common/keyhandler.c @@ -135,12 +135,25 @@ static void cpuset_print(char *set, int size, cpumask_t mask) *set++ = '\0'; } +static void periodic_timer_print(char *str, int size, uint64_t period) +{ + if ( period == 0 ) + { + strlcpy(str, "No periodic timer", size); + return; + } + + snprintf(str, size, + "%u Hz periodic timer (period %u ms)", + 1000000000/(int)period, (int)period/1000000); +} + static void dump_domains(unsigned char key) { struct domain *d; struct vcpu *v; s_time_t now = NOW(); - char cpuset[100]; + char tmpstr[100]; printk("'%c' pressed -> dumping domain info (now=0x%X:%08X)\n", key, (u32)(now>>32), (u32)now); @@ -150,11 +163,11 @@ static void dump_domains(unsigned char key) for_each_domain ( d ) { printk("General information for domain %u:\n", d->domain_id); - cpuset_print(cpuset, sizeof(cpuset), d->domain_dirty_cpumask); + cpuset_print(tmpstr, sizeof(tmpstr), d->domain_dirty_cpumask); printk(" flags=%lx refcnt=%d nr_pages=%d xenheap_pages=%d " "dirty_cpus=%s\n", d->domain_flags, atomic_read(&d->refcnt), - d->tot_pages, d->xenheap_pages, cpuset); + d->tot_pages, d->xenheap_pages, tmpstr); printk(" handle=%02x%02x%02x%02x-%02x%02x-%02x%02x-" "%02x%02x-%02x%02x%02x%02x%02x%02x vm_assist=%08lx\n", d->handle[ 0], d->handle[ 1], d->handle[ 2], d->handle[ 3], @@ -179,18 +192,21 @@ static void dump_domains(unsigned char key) v->vcpu_flags, vcpu_info(v, evtchn_upcall_pending), vcpu_info(v, evtchn_upcall_mask)); - cpuset_print(cpuset, sizeof(cpuset), v->vcpu_dirty_cpumask); - printk("dirty_cpus=%s ", cpuset); - cpuset_print(cpuset, sizeof(cpuset), v->cpu_affinity); - printk("cpu_affinity=%s\n", cpuset); + cpuset_print(tmpstr, sizeof(tmpstr), v->vcpu_dirty_cpumask); + printk("dirty_cpus=%s ", tmpstr); + cpuset_print(tmpstr, sizeof(tmpstr), v->cpu_affinity); + printk("cpu_affinity=%s\n", tmpstr); arch_dump_vcpu_info(v); + periodic_timer_print(tmpstr, sizeof(tmpstr), v->periodic_period); + printk(" %s\n", tmpstr); printk(" Notifying guest (virq %d, port %d, stat %d/%d/%d)\n", VIRQ_DEBUG, v->virq_to_evtchn[VIRQ_DEBUG], test_bit(v->virq_to_evtchn[VIRQ_DEBUG], shared_info_addr(d, evtchn_pending)), test_bit(v->virq_to_evtchn[VIRQ_DEBUG], shared_info_addr(d, evtchn_mask)), - test_bit(v->virq_to_evtchn[VIRQ_DEBUG]/BITS_PER_GUEST_LONG(d), + test_bit(v->virq_to_evtchn[VIRQ_DEBUG] / + BITS_PER_GUEST_LONG(d), vcpu_info_addr(v, evtchn_pending_sel))); send_guest_vcpu_virq(v, VIRQ_DEBUG); } From 04710d73b033070ab872960fcdda35b90b561278 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 9 Mar 2007 19:36:24 +0000 Subject: [PATCH 036/170] linux: Use new time hypercalls. Signed-off-by: Keir Fraser --- .../arch/i386/kernel/time-xen.c | 26 +++++++++++++++++-- linux-2.6-xen-sparse/drivers/xen/Kconfig | 7 +++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c index 4f2e155c7b..92971bcac6 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c @@ -907,6 +907,10 @@ static void setup_cpu0_timer_irq(void) BUG_ON(per_cpu(timer_irq, 0) < 0); } +static struct vcpu_set_periodic_timer xen_set_periodic_tick = { + .period_ns = NS_PER_TICK +}; + void __init time_init(void) { #ifdef CONFIG_HPET_TIMER @@ -919,6 +923,10 @@ void __init time_init(void) return; } #endif + + HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, 0, + &xen_set_periodic_tick); + get_time_values_from_xen(0); processed_system_time = per_cpu(shadow_time, 0).system_timestamp; @@ -976,8 +984,10 @@ EXPORT_SYMBOL(jiffies_to_st); */ static void stop_hz_timer(void) { + struct vcpu_set_singleshot_timer singleshot; unsigned int cpu = smp_processor_id(); unsigned long j; + int rc; cpu_set(cpu, nohz_cpu_mask); @@ -997,8 +1007,15 @@ static void stop_hz_timer(void) j = jiffies + 1; } - if (HYPERVISOR_set_timer_op(jiffies_to_st(j)) != 0) - BUG(); + singleshot.timeout_abs_ns = jiffies_to_st(j); + rc = HYPERVISOR_vcpu_op(VCPUOP_set_singleshot_timer, cpu, &singleshot); +#ifdef XEN_COMPAT_030004 + if (rc) { + BUG_ON(rc != -ENOSYS); + rc = HYPERVISOR_set_timer_op(singleshot.timeout_abs_ns); + } +#endif + BUG_ON(rc); } static void start_hz_timer(void) @@ -1030,6 +1047,8 @@ void time_resume(void) init_cpu_khz(); for_each_online_cpu(cpu) { + HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, cpu, + &xen_set_periodic_tick); get_time_values_from_xen(cpu); per_cpu(processed_system_time, cpu) = per_cpu(shadow_time, 0).system_timestamp; @@ -1050,6 +1069,9 @@ int local_setup_timer(unsigned int cpu) BUG_ON(cpu == 0); + HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, cpu, + &xen_set_periodic_tick); + do { seq = read_seqbegin(&xtime_lock); /* Use cpu0 timestamp: cpu's shadow is not initialised yet. */ diff --git a/linux-2.6-xen-sparse/drivers/xen/Kconfig b/linux-2.6-xen-sparse/drivers/xen/Kconfig index 1f3e49f207..71ba9f264d 100644 --- a/linux-2.6-xen-sparse/drivers/xen/Kconfig +++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig @@ -227,6 +227,9 @@ choice config XEN_COMPAT_030002_AND_LATER bool "3.0.2 and later" + config XEN_COMPAT_030004_AND_LATER + bool "3.0.4 and later" + config XEN_COMPAT_LATEST_ONLY bool "no compatibility code" @@ -236,6 +239,10 @@ config XEN_COMPAT_030002 bool default XEN_COMPAT_030002_AND_LATER +config XEN_COMPAT_030004 + bool + default XEN_COMPAT_030002_AND_LATER || XEN_COMPAT_030004_AND_LATER + endmenu config HAVE_IRQ_IGNORE_UNHANDLED From 04866d25fd0bba98d1d203b9065e2f54856c7eaa Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Sat, 10 Mar 2007 16:22:52 +0000 Subject: [PATCH 037/170] xen: Fix VCPUOP_set_periodic_timer return value. Clean up vcpu_op() code, and fix a couple of comments. Signed-off-by: Keir Fraser --- xen/common/domain.c | 20 ++++++++------------ xen/common/schedule.c | 4 ++-- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/xen/common/domain.c b/xen/common/domain.c index 00ca0d7aa6..7b4660fc91 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -546,16 +546,12 @@ long do_vcpu_op(int cmd, int vcpuid, XEN_GUEST_HANDLE(void) arg) { case VCPUOP_initialise: if ( (ctxt = xmalloc(struct vcpu_guest_context)) == NULL ) - { - rc = -ENOMEM; - break; - } + return -ENOMEM; if ( copy_from_guest(ctxt, arg, 1) ) { xfree(ctxt); - rc = -EFAULT; - break; + return -EFAULT; } LOCK_BIGLOCK(d); @@ -569,9 +565,11 @@ long do_vcpu_op(int cmd, int vcpuid, XEN_GUEST_HANDLE(void) arg) case VCPUOP_up: if ( !test_bit(_VCPUF_initialised, &v->vcpu_flags) ) - rc = -EINVAL; - else if ( test_and_clear_bit(_VCPUF_down, &v->vcpu_flags) ) + return -EINVAL; + + if ( test_and_clear_bit(_VCPUF_down, &v->vcpu_flags) ) vcpu_wake(v); + break; case VCPUOP_down: @@ -596,13 +594,11 @@ long do_vcpu_op(int cmd, int vcpuid, XEN_GUEST_HANDLE(void) arg) { struct vcpu_set_periodic_timer set; - rc = -EFAULT; if ( copy_from_guest(&set, arg, 1) ) - break; + return -EFAULT; - rc = -EINVAL; if ( set.period_ns < MILLISECS(1) ) - break; + return -EINVAL; v->periodic_period = set.period_ns; vcpu_force_reschedule(v); diff --git a/xen/common/schedule.c b/xen/common/schedule.c index 447cc2744e..f78319e381 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -110,7 +110,7 @@ int sched_init_vcpu(struct vcpu *v, unsigned int processor) else cpus_setall(v->cpu_affinity); - /* Initialise the per-domain timers. */ + /* Initialise the per-vcpu timers. */ init_timer(&v->periodic_timer, vcpu_periodic_timer_fn, v, v->processor); init_timer(&v->singleshot_timer, vcpu_singleshot_timer_fn, @@ -471,7 +471,7 @@ ret_t do_sched_op(int cmd, XEN_GUEST_HANDLE(void) arg) #ifndef COMPAT -/* Per-domain one-shot-timer hypercall. */ +/* Per-vcpu oneshot-timer hypercall. */ long do_set_timer_op(s_time_t timeout) { struct vcpu *v = current; From 505ef3ea86870bb8a35533ec9d446f98a6b61ea6 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Sat, 10 Mar 2007 16:58:11 +0000 Subject: [PATCH 038/170] Add flags field to VCPUOP_set_singlsehot_timer. Flag 'future' causes Xen to check if the timeout is in the past and return -ETIME if so. From: Jeremy Fitzhardinge Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c | 1 + xen/common/domain.c | 4 ++++ xen/include/public/vcpu.h | 8 +++++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c index 92971bcac6..a3ac4371a4 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c @@ -1008,6 +1008,7 @@ static void stop_hz_timer(void) } singleshot.timeout_abs_ns = jiffies_to_st(j); + singleshot.flags = 0; rc = HYPERVISOR_vcpu_op(VCPUOP_set_singleshot_timer, cpu, &singleshot); #ifdef XEN_COMPAT_030004 if (rc) { diff --git a/xen/common/domain.c b/xen/common/domain.c index 7b4660fc91..57fb9ade71 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -623,6 +623,10 @@ long do_vcpu_op(int cmd, int vcpuid, XEN_GUEST_HANDLE(void) arg) if ( copy_from_guest(&set, arg, 1) ) return -EFAULT; + if ( (set.flags & VCPU_SSHOTTMR_future) && + (set.timeout_abs_ns < NOW()) ) + return -ETIME; + if ( v->singleshot_timer.cpu != smp_processor_id() ) { stop_timer(&v->singleshot_timer); diff --git a/xen/include/public/vcpu.h b/xen/include/public/vcpu.h index 3d7d9587c0..7252d0b793 100644 --- a/xen/include/public/vcpu.h +++ b/xen/include/public/vcpu.h @@ -150,11 +150,17 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_set_periodic_timer_t); #define VCPUOP_set_singleshot_timer 8 /* arg == vcpu_set_singleshot_timer_t */ #define VCPUOP_stop_singleshot_timer 9 /* arg == NULL */ struct vcpu_set_singleshot_timer { - uint64_t timeout_abs_ns; + uint64_t timeout_abs_ns; /* Absolute system time value in nanoseconds. */ + uint32_t flags; /* VCPU_SSHOTTMR_??? */ }; typedef struct vcpu_set_singleshot_timer vcpu_set_singleshot_timer_t; DEFINE_XEN_GUEST_HANDLE(vcpu_set_singleshot_timer_t); +/* Flags to VCPUOP_set_singleshot_timer. */ + /* Require the timeout to be in the future (return -ETIME if it's passed). */ +#define _VCPU_SSHOTTMR_future (0) +#define VCPU_SSHOTTMR_future (1U << _VCPU_SSHOTTMR_future) + #endif /* __XEN_PUBLIC_VCPU_H__ */ /* From dce5dbf05162c7f1eee7cee49596d2b54424d318 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Sat, 10 Mar 2007 16:59:57 +0000 Subject: [PATCH 039/170] Simple fix to the man page for xm block-attach. It currently says to use "ro" or "rw" for the mode, when it seems, empirically, to take "r" or "w" for the mode, respectively. Update the man page to reflect that. Signed-off-by: Chris Lalancette --- docs/man/xm.pod.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/man/xm.pod.1 b/docs/man/xm.pod.1 index 3cd8b80ac6..90dab93d9a 100644 --- a/docs/man/xm.pod.1 +++ b/docs/man/xm.pod.1 @@ -619,7 +619,7 @@ devices, or by device id, such as 0x1400 (/dev/hdc device id in hex). =item I The access mode for the device from the guest domain. Supported modes -are I (read/write) or I (read-only). +are I (read/write) or I (read-only). =item I From ac4fb3c4ec67a8fc082e55e0771a2bc7fcffe79c Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Sat, 10 Mar 2007 17:01:21 +0000 Subject: [PATCH 040/170] pci back: Various fixes. - remove superfluous call to pciback_field_is_dup() - fix a variable type mismatch in pciback_field_is_dup() - make readability improvements by using the OFFSET macro - revises quirk data output via the sysfs quirks node so that - displayed offset information includes base_offset. Thanks to Jambunathan K. for giving such specific bug diagnosis. Signed-off-by: Chris Bookholt --- .../drivers/xen/pciback/conf_space.c | 13 +++++++------ .../drivers/xen/pciback/conf_space_quirks.c | 6 ++---- .../drivers/xen/pciback/conf_space_quirks.h | 2 +- linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c | 12 ++++-------- 4 files changed, 14 insertions(+), 19 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c index 14e69adeec..4c99534bb3 100644 --- a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c @@ -349,17 +349,13 @@ void pciback_config_free_dev(struct pci_dev *dev) int pciback_config_add_field_offset(struct pci_dev *dev, struct config_field *field, - unsigned int offset) + unsigned int base_offset) { int err = 0; struct pciback_dev_data *dev_data = pci_get_drvdata(dev); struct config_field_entry *cfg_entry; void *tmp; - /* silently ignore duplicate fields */ - if (pciback_field_is_dup(dev, field->offset + offset)) - goto out; - cfg_entry = kmalloc(sizeof(*cfg_entry), GFP_KERNEL); if (!cfg_entry) { err = -ENOMEM; @@ -368,7 +364,12 @@ int pciback_config_add_field_offset(struct pci_dev *dev, cfg_entry->data = NULL; cfg_entry->field = field; - cfg_entry->base_offset = offset; + cfg_entry->base_offset = base_offset; + + /* silently ignore duplicate fields */ + err = pciback_field_is_dup(dev,OFFSET(cfg_entry)); + if (err) + goto out; if (field->init) { tmp = field->init(dev, OFFSET(cfg_entry)); diff --git a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.c b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.c index 4ec0c78b89..525ec95c65 100644 --- a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.c +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.c @@ -32,16 +32,14 @@ static inline void register_quirk(struct pciback_config_quirk *quirk) list_add_tail(&quirk->quirks_list, &pciback_quirks); } -int pciback_field_is_dup(struct pci_dev *dev, int reg) +int pciback_field_is_dup(struct pci_dev *dev, unsigned int reg) { int ret = 0; struct pciback_dev_data *dev_data = pci_get_drvdata(dev); - struct config_field *field; struct config_field_entry *cfg_entry; list_for_each_entry(cfg_entry, &dev_data->config_fields, list) { - field = cfg_entry->field; - if (field->offset == reg) { + if ( OFFSET(cfg_entry) == reg) { ret = 1; break; } diff --git a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.h b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.h index 5c47e1269b..acd0e1ae8f 100644 --- a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.h +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.h @@ -30,6 +30,6 @@ void pciback_config_field_free(struct config_field *field); int pciback_config_quirk_release(struct pci_dev *dev); -int pciback_field_is_dup(struct pci_dev *dev, int reg); +int pciback_field_is_dup(struct pci_dev *dev, unsigned int reg); #endif diff --git a/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c b/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c index b33855932d..7d2118226b 100644 --- a/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c @@ -589,10 +589,6 @@ static int pcistub_reg_add(int domain, int bus, int slot, int func, int reg, } dev = psdev->dev; - /* check for duplicate field */ - if (pciback_field_is_dup(dev, reg)) - goto out; - field = kzalloc(sizeof(*field), GFP_ATOMIC); if (!field) { err = -ENOMEM; @@ -728,10 +724,10 @@ static ssize_t pcistub_quirk_show(struct device_driver *drv, char *buf) if (count >= PAGE_SIZE) goto out; - count += scnprintf(buf + count, PAGE_SIZE - - count, "\t\t%08x:%01x:%08x\n", - field->offset, field->size, - field->mask); + count += scnprintf(buf + count, PAGE_SIZE - count, + "\t\t%08x:%01x:%08x\n", + cfg_entry->base_offset + field->offset, + field->size, field->mask); } } From 5da174817b7b609fa35d1863375a89b42c08dd1e Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Sat, 10 Mar 2007 17:38:54 +0000 Subject: [PATCH 041/170] xen ppc: Guests need the default 100Hz ticker. Signed-off-by: Keir Fraser --- xen/arch/powerpc/domain.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xen/arch/powerpc/domain.c b/xen/arch/powerpc/domain.c index e129adbe0f..156b70ffd9 100644 --- a/xen/arch/powerpc/domain.c +++ b/xen/arch/powerpc/domain.c @@ -142,6 +142,8 @@ void free_vcpu_struct(struct vcpu *v) int vcpu_initialise(struct vcpu *v) { + /* Guests by default have a 100Hz ticker. */ + v->periodic_period = MILLISECS(10); return 0; } From c2bb72dfd1f6ce1c8740c128336602c125f39353 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Sat, 10 Mar 2007 14:16:52 +0000 Subject: [PATCH 042/170] Allow empty structs to represent empty Maps. Signed-off-by: Ewan Mellor --- tools/libxen/src/xen_common.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/libxen/src/xen_common.c b/tools/libxen/src/xen_common.c index 5d72cab177..b7774c8a27 100644 --- a/tools/libxen/src/xen_common.c +++ b/tools/libxen/src/xen_common.c @@ -666,8 +666,7 @@ static void parse_into(xen_session *s, xmlNode *value_node, { if (!is_container_node(value_node, "value") || value_node->children->type != XML_ELEMENT_NODE || - 0 != strcmp((char *)value_node->children->name, "struct") || - value_node->children->children == NULL) + 0 != strcmp((char *)value_node->children->name, "struct")) { server_error(s, "Expected Map from the server, but didn't get it"); From 8d7dee0b2af3a7e9612c6ee9eca8af0e27e32855 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Sat, 10 Mar 2007 14:41:06 +0000 Subject: [PATCH 043/170] Fix get_val_as_string so that it does not truncate integers. Signed-off-by: Ewan Mellor --- tools/libxen/src/xen_common.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tools/libxen/src/xen_common.c b/tools/libxen/src/xen_common.c index b7774c8a27..f2c9644521 100644 --- a/tools/libxen/src/xen_common.c +++ b/tools/libxen/src/xen_common.c @@ -110,7 +110,7 @@ parse_structmap_value(xen_session *, xmlNode *, const abstract_type *, static size_t size_of_member(const abstract_type *); static const char * -get_val_as_string(const struct abstract_type *, void *, char *); +get_val_as_string(const struct abstract_type *, void *, char *, size_t); void @@ -1185,7 +1185,8 @@ add_struct_value(const struct abstract_type *type, void *value, case INT: case ENUM: { - const char *val_as_string = get_val_as_string(type, value, buf); + const char *val_as_string = + get_val_as_string(type, value, buf, sizeof(buf)); adder(node, key, "string", val_as_string); } break; @@ -1257,7 +1258,7 @@ add_struct_value(const struct abstract_type *type, void *value, void *r_value = contents + (i * member_size) + r_offset; const char *l_value_as_string = - get_val_as_string(l_type, l_value, buf); + get_val_as_string(l_type, l_value, buf, sizeof(buf)); add_struct_value(r_type, r_value, add_struct_member, l_value_as_string, struct_node); @@ -1273,7 +1274,8 @@ add_struct_value(const struct abstract_type *type, void *value, static const char * -get_val_as_string(const struct abstract_type *type, void *value, char *buf) +get_val_as_string(const struct abstract_type *type, void *value, char *buf, + size_t bufsize) { switch (type->typename) { @@ -1307,7 +1309,7 @@ get_val_as_string(const struct abstract_type *type, void *value, char *buf) case INT: { int64_t val = *(int64_t *)value; - snprintf(buf, sizeof(buf), "%"PRId64, val); + snprintf(buf, bufsize, "%"PRId64, val); return buf; } break; From 6eb3760aa862241c16e9e91cbc3e341e85b00641 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Sat, 10 Mar 2007 14:57:11 +0000 Subject: [PATCH 044/170] Add vcpus_max and vcpus_at_startup values to the example VM creation. Signed-off-by: Ewan Mellor --- tools/libxen/test/test_bindings.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/libxen/test/test_bindings.c b/tools/libxen/test/test_bindings.c index 6a51cd3a05..8e89ee5356 100644 --- a/tools/libxen/test/test_bindings.c +++ b/tools/libxen/test/test_bindings.c @@ -375,6 +375,8 @@ static xen_vm create_new_vm(xen_session *session, bool hvm) .memory_static_min = 128, .vcpus_policy = "credit", .vcpus_params = vcpus_params, + .vcpus_max = 4, + .vcpus_at_startup = 2, .actions_after_shutdown = XEN_ON_NORMAL_EXIT_DESTROY, .actions_after_reboot = XEN_ON_NORMAL_EXIT_RESTART, .actions_after_crash = XEN_ON_CRASH_BEHAVIOUR_PRESERVE, From e07fd1a3da6da8fec617582a1c1a306ac255b0c4 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Sat, 10 Mar 2007 16:38:18 +0000 Subject: [PATCH 045/170] Improve xm shell tab completion. Signed-off-by: Ewan Mellor --- tools/python/xen/xm/main.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 8fcc2bc525..34289078e2 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -25,6 +25,7 @@ import atexit import cmd import os import pprint +import readline import shlex import sys import re @@ -558,6 +559,10 @@ class Shell(cmd.Cmd): for f in res: setattr(Shell, 'do_' + f, self.default) + def preloop(self): + cmd.Cmd.preloop(self) + readline.set_completer_delims(' ') + def default(self, line): words = shlex.split(line) if len(words) > 0 and words[0] == 'xm': @@ -577,9 +582,9 @@ class Shell(cmd.Cmd): return False def completedefault(self, text, line, begidx, endidx): - cmd = line.split(' ')[0] - clas, func = cmd.split('.') - if begidx != len(cmd) + 1 or \ + words = shlex.split(line[:begidx]) + clas, func = words[0].split('.') + if len(words) > 1 or \ func.startswith('get_by_') or \ func == 'get_all': return [] From 6c6d5f75de3fcc02f62a63eef27880807e0938c3 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Sat, 10 Mar 2007 19:57:35 +0000 Subject: [PATCH 046/170] Don't show the usage message for "domain does not exist" errors. Signed-off-by: Ewan Mellor --- tools/python/xen/xm/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 34289078e2..89dbfde9d1 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -1892,7 +1892,7 @@ def _run_cmd(cmd, cmd_name, args): err("Domain '%s' does not exist." % ex.faultString) else: err(ex.faultString) - _usage(cmd_name) + _usage(cmd_name) except xmlrpclib.ProtocolError, ex: if ex.errcode == -1: print >>sys.stderr, ( From 0549b0083435667e36d678d6c52feb796f05fd92 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Sat, 10 Mar 2007 20:18:17 +0000 Subject: [PATCH 047/170] Remove some excessive debug logging. Signed-off-by: Ewan Mellor --- tools/python/xen/xend/XendNode.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/python/xen/xend/XendNode.py b/tools/python/xen/xend/XendNode.py index 5976d80f39..3b261d8722 100644 --- a/tools/python/xen/xend/XendNode.py +++ b/tools/python/xen/xend/XendNode.py @@ -95,15 +95,12 @@ class XendNode: self.cpus[u] = {'uuid': u, 'number': i } for u in self.cpus.keys(): - log.error(self.cpus[u]) number = self.cpus[u]['number'] # We can run off the end of the cpuinfo list if domain0 does not # have #vcpus == #pcpus. In that case we just replicate one that's # in the hash table. if not cpuinfo.has_key(number): number = cpuinfo.keys()[0] - log.error(number) - log.error(cpuinfo) if arch.type == "x86": self.cpus[u].update( { 'host' : self.uuid, From e8943dc06db10da242ad9a344ba0f9c56667f952 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Sat, 10 Mar 2007 20:20:24 +0000 Subject: [PATCH 048/170] Fix "no such domain" error message from domain_lookup. Signed-off-by: Ewan Mellor --- tools/python/xen/xend/XendDomain.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py index 7e5f618870..4ec8334aa1 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -495,7 +495,7 @@ class XendDomain: self._refresh(refresh_shutdown = False) dom = self.domain_lookup_nr(domid) if not dom: - raise XendInvalidDomain("No domain named '%s'." % str(domid)) + raise XendInvalidDomain(str(domid)) return dom finally: self.domains_lock.release() From 9b9c64266be4dde043979b390d16b6eb964312df Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Sat, 10 Mar 2007 21:41:58 +0000 Subject: [PATCH 049/170] Fix VM.set_actions_after_{reboot,shutdown}. Signed-off-by: Ewan Mellor --- tools/python/xen/xend/XendAPI.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index c89f5467d0..d229d57df4 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -1284,12 +1284,12 @@ class XendAPI(object): return xen_api_todo() def VM_set_actions_after_shutdown(self, session, vm_ref, action): - if action not in XEN_API_ON_NORMAL_EXIST: + if action not in XEN_API_ON_NORMAL_EXIT: return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref]) return self.VM_set('actions_after_shutdown', session, vm_ref, action) def VM_set_actions_after_reboot(self, session, vm_ref, action): - if action not in XEN_API_ON_NORMAL_EXIST: + if action not in XEN_API_ON_NORMAL_EXIT: return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref]) return self.VM_set('actions_after_reboot', session, vm_ref, action) From f7f8f5e39d769e89852d9bdf4a6650bc5d9d8056 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Sat, 10 Mar 2007 21:43:07 +0000 Subject: [PATCH 050/170] Remove obsolete tpm_backend entry. Signed-off-by: Ewan Mellor --- tools/python/xen/xend/XendConfig.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index ec8a66fb7e..c945ced425 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -151,7 +151,6 @@ XENAPI_CFG_TYPES = { 'actions_after_shutdown': str, 'actions_after_reboot': str, 'actions_after_crash': str, - 'tpm_backend': int, 'PV_bootloader': str, 'PV_kernel': str, 'PV_ramdisk': str, From abc324d48f33530008131537e30ac5a344fbe9b6 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Sat, 10 Mar 2007 21:48:22 +0000 Subject: [PATCH 051/170] Replace VM.platform_{std_VGA,serial,localtime,clock_offset,enable_audio} with a single VM.platform String -> String Map. Propogate this change through to XendDomainInfo and image so that the backwards compatibility is handled by XendConfig. Make PCI_bus a read-write field. Added C bindings for these changes also. Signed-off-by: Ewan Mellor --- docs/xen-api/xenapi-datamodel.tex | 271 +++++------------------- tools/libxen/include/xen_vm.h | 62 ++---- tools/libxen/src/xen_vm.c | 136 ++---------- tools/python/xen/xend/XendAPI.py | 127 +++++------ tools/python/xen/xend/XendConfig.py | 267 +++++++---------------- tools/python/xen/xend/XendDomainInfo.py | 67 ++---- tools/python/xen/xend/image.py | 52 +++-- 7 files changed, 253 insertions(+), 729 deletions(-) diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex index 90d9abf875..08b831fdd5 100644 --- a/docs/xen-api/xenapi-datamodel.tex +++ b/docs/xen-api/xenapi-datamodel.tex @@ -1058,12 +1058,8 @@ $\mathit{RW}$ & {\tt PV/args} & string & kernel command-line arguments \\ $\mathit{RW}$ & {\tt PV/bootloader\_args} & string & miscellaneous arguments for the bootloader \\ $\mathit{RW}$ & {\tt HVM/boot\_policy} & string & HVM boot policy \\ $\mathit{RW}$ & {\tt HVM/boot\_params} & (string $\rightarrow$ string) Map & HVM boot params \\ -$\mathit{RW}$ & {\tt platform/std\_VGA} & bool & emulate standard VGA instead of cirrus logic \\ -$\mathit{RW}$ & {\tt platform/serial} & string & redirect serial port to pty \\ -$\mathit{RW}$ & {\tt platform/localtime} & bool & set RTC to local time \\ -$\mathit{RW}$ & {\tt platform/clock\_offset} & bool & timeshift applied to guest's clock \\ -$\mathit{RW}$ & {\tt platform/enable\_audio} & bool & emulate audio \\ -$\mathit{RO}_\mathit{ins}$ & {\tt PCI\_bus} & string & PCI bus path for pass-through devices \\ +$\mathit{RW}$ & {\tt platform} & (string $\rightarrow$ string) Map & platform-specific configuration \\ +$\mathit{RW}$ & {\tt PCI\_bus} & string & PCI bus path for pass-through devices \\ $\mathit{RW}$ & {\tt other\_config} & (string $\rightarrow$ string) Map & additional configuration \\ $\mathit{RO}_\mathit{run}$ & {\tt domid} & int & domain ID (if available, -1 otherwise) \\ $\mathit{RO}_\mathit{run}$ & {\tt is\_control\_domain} & bool & true if this is a control domain (domain 0 or a driver domain) \\ @@ -3407,13 +3403,13 @@ void \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} -\subsubsection{RPC name:~get\_platform\_std\_VGA} +\subsubsection{RPC name:~get\_platform} {\bf Overview:} -Get the platform/std\_VGA field of the given VM. +Get the platform field of the given VM. \noindent {\bf Signature:} -\begin{verbatim} bool get_platform_std_VGA (session_id s, VM ref self)\end{verbatim} +\begin{verbatim} ((string -> string) Map) get_platform (session_id s, VM ref self)\end{verbatim} \noindent{\bf Arguments:} @@ -3431,7 +3427,7 @@ Get the platform/std\_VGA field of the given VM. \noindent {\bf Return Type:} {\tt -bool +(string $\rightarrow$ string) Map } @@ -3439,13 +3435,13 @@ value of the field \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} -\subsubsection{RPC name:~set\_platform\_std\_VGA} +\subsubsection{RPC name:~set\_platform} {\bf Overview:} -Set the platform/std\_VGA field of the given VM. +Set the platform field of the given VM. \noindent {\bf Signature:} -\begin{verbatim} void set_platform_std_VGA (session_id s, VM ref self, bool value)\end{verbatim} +\begin{verbatim} void set_platform (session_id s, VM ref self, (string -> string) Map value)\end{verbatim} \noindent{\bf Arguments:} @@ -3457,7 +3453,7 @@ Set the platform/std\_VGA field of the given VM. {\bf type} & {\bf name} & {\bf description} \\ \hline {\tt VM ref } & self & reference to the object \\ \hline -{\tt bool } & value & New value to set \\ \hline +{\tt (string $\rightarrow$ string) Map } & value & New value to set \\ \hline \end{tabular} @@ -3473,13 +3469,13 @@ void \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} -\subsubsection{RPC name:~get\_platform\_serial} +\subsubsection{RPC name:~add\_to\_platform} {\bf Overview:} -Get the platform/serial field of the given VM. +Add the given key-value pair to the platform field of the given VM. \noindent {\bf Signature:} -\begin{verbatim} string get_platform_serial (session_id s, VM ref self)\end{verbatim} +\begin{verbatim} void add_to_platform (session_id s, VM ref self, string key, string value)\end{verbatim} \noindent{\bf Arguments:} @@ -3491,39 +3487,9 @@ Get the platform/serial field of the given VM. {\bf type} & {\bf name} & {\bf description} \\ \hline {\tt VM ref } & self & reference to the object \\ \hline -\end{tabular} +{\tt string } & key & Key to add \\ \hline -\vspace{0.3cm} - - \noindent {\bf Return Type:} -{\tt -string -} - - -value of the field -\vspace{0.3cm} -\vspace{0.3cm} -\vspace{0.3cm} -\subsubsection{RPC name:~set\_platform\_serial} - -{\bf Overview:} -Set the platform/serial field of the given VM. - - \noindent {\bf Signature:} -\begin{verbatim} void set_platform_serial (session_id s, VM ref self, string value)\end{verbatim} - - -\noindent{\bf Arguments:} - - -\vspace{0.3cm} -\begin{tabular}{|c|c|p{7cm}|} - \hline -{\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & reference to the object \\ \hline - -{\tt string } & value & New value to set \\ \hline +{\tt string } & value & Value to add \\ \hline \end{tabular} @@ -3539,13 +3505,14 @@ void \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} -\subsubsection{RPC name:~get\_platform\_localtime} +\subsubsection{RPC name:~remove\_from\_platform} {\bf Overview:} -Get the platform/localtime field of the given VM. +Remove the given key and its corresponding value from the platform field of +the given VM. If the key is not in that Map, then do nothing. \noindent {\bf Signature:} -\begin{verbatim} bool get_platform_localtime (session_id s, VM ref self)\end{verbatim} +\begin{verbatim} void remove_from_platform (session_id s, VM ref self, string key)\end{verbatim} \noindent{\bf Arguments:} @@ -3557,171 +3524,7 @@ Get the platform/localtime field of the given VM. {\bf type} & {\bf name} & {\bf description} \\ \hline {\tt VM ref } & self & reference to the object \\ \hline -\end{tabular} - -\vspace{0.3cm} - - \noindent {\bf Return Type:} -{\tt -bool -} - - -value of the field -\vspace{0.3cm} -\vspace{0.3cm} -\vspace{0.3cm} -\subsubsection{RPC name:~set\_platform\_localtime} - -{\bf Overview:} -Set the platform/localtime field of the given VM. - - \noindent {\bf Signature:} -\begin{verbatim} void set_platform_localtime (session_id s, VM ref self, bool value)\end{verbatim} - - -\noindent{\bf Arguments:} - - -\vspace{0.3cm} -\begin{tabular}{|c|c|p{7cm}|} - \hline -{\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & reference to the object \\ \hline - -{\tt bool } & value & New value to set \\ \hline - -\end{tabular} - -\vspace{0.3cm} - - \noindent {\bf Return Type:} -{\tt -void -} - - - -\vspace{0.3cm} -\vspace{0.3cm} -\vspace{0.3cm} -\subsubsection{RPC name:~get\_platform\_clock\_offset} - -{\bf Overview:} -Get the platform/clock\_offset field of the given VM. - - \noindent {\bf Signature:} -\begin{verbatim} bool get_platform_clock_offset (session_id s, VM ref self)\end{verbatim} - - -\noindent{\bf Arguments:} - - -\vspace{0.3cm} -\begin{tabular}{|c|c|p{7cm}|} - \hline -{\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & reference to the object \\ \hline - -\end{tabular} - -\vspace{0.3cm} - - \noindent {\bf Return Type:} -{\tt -bool -} - - -value of the field -\vspace{0.3cm} -\vspace{0.3cm} -\vspace{0.3cm} -\subsubsection{RPC name:~set\_platform\_clock\_offset} - -{\bf Overview:} -Set the platform/clock\_offset field of the given VM. - - \noindent {\bf Signature:} -\begin{verbatim} void set_platform_clock_offset (session_id s, VM ref self, bool value)\end{verbatim} - - -\noindent{\bf Arguments:} - - -\vspace{0.3cm} -\begin{tabular}{|c|c|p{7cm}|} - \hline -{\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & reference to the object \\ \hline - -{\tt bool } & value & New value to set \\ \hline - -\end{tabular} - -\vspace{0.3cm} - - \noindent {\bf Return Type:} -{\tt -void -} - - - -\vspace{0.3cm} -\vspace{0.3cm} -\vspace{0.3cm} -\subsubsection{RPC name:~get\_platform\_enable\_audio} - -{\bf Overview:} -Get the platform/enable\_audio field of the given VM. - - \noindent {\bf Signature:} -\begin{verbatim} bool get_platform_enable_audio (session_id s, VM ref self)\end{verbatim} - - -\noindent{\bf Arguments:} - - -\vspace{0.3cm} -\begin{tabular}{|c|c|p{7cm}|} - \hline -{\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & reference to the object \\ \hline - -\end{tabular} - -\vspace{0.3cm} - - \noindent {\bf Return Type:} -{\tt -bool -} - - -value of the field -\vspace{0.3cm} -\vspace{0.3cm} -\vspace{0.3cm} -\subsubsection{RPC name:~set\_platform\_enable\_audio} - -{\bf Overview:} -Set the platform/enable\_audio field of the given VM. - - \noindent {\bf Signature:} -\begin{verbatim} void set_platform_enable_audio (session_id s, VM ref self, bool value)\end{verbatim} - - -\noindent{\bf Arguments:} - - -\vspace{0.3cm} -\begin{tabular}{|c|c|p{7cm}|} - \hline -{\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & reference to the object \\ \hline - -{\tt bool } & value & New value to set \\ \hline +{\tt string } & key & Key to remove \\ \hline \end{tabular} @@ -3766,6 +3569,40 @@ string value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~set\_PCI\_bus} + +{\bf Overview:} +Set the PCI\_bus field of the given VM. + + \noindent {\bf Signature:} +\begin{verbatim} void set_PCI_bus (session_id s, VM ref self, string value)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline + +{\tt string } & value & New value to set \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +void +} + + + \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} diff --git a/tools/libxen/include/xen_vm.h b/tools/libxen/include/xen_vm.h index 947ecc6ac6..781e8ec8cd 100644 --- a/tools/libxen/include/xen_vm.h +++ b/tools/libxen/include/xen_vm.h @@ -106,11 +106,7 @@ typedef struct xen_vm_record char *pv_bootloader_args; char *hvm_boot_policy; xen_string_string_map *hvm_boot_params; - bool platform_std_vga; - char *platform_serial; - bool platform_localtime; - bool platform_clock_offset; - bool platform_enable_audio; + xen_string_string_map *platform; char *pci_bus; xen_string_string_map *other_config; int64_t domid; @@ -460,38 +456,10 @@ xen_vm_get_hvm_boot_params(xen_session *session, xen_string_string_map **result, /** - * Get the platform/std_VGA field of the given VM. + * Get the platform field of the given VM. */ extern bool -xen_vm_get_platform_std_vga(xen_session *session, bool *result, xen_vm vm); - - -/** - * Get the platform/serial field of the given VM. - */ -extern bool -xen_vm_get_platform_serial(xen_session *session, char **result, xen_vm vm); - - -/** - * Get the platform/localtime field of the given VM. - */ -extern bool -xen_vm_get_platform_localtime(xen_session *session, bool *result, xen_vm vm); - - -/** - * Get the platform/clock_offset field of the given VM. - */ -extern bool -xen_vm_get_platform_clock_offset(xen_session *session, bool *result, xen_vm vm); - - -/** - * Get the platform/enable_audio field of the given VM. - */ -extern bool -xen_vm_get_platform_enable_audio(xen_session *session, bool *result, xen_vm vm); +xen_vm_get_platform(xen_session *session, xen_string_string_map **result, xen_vm vm); /** @@ -732,38 +700,32 @@ xen_vm_remove_from_hvm_boot_params(xen_session *session, xen_vm vm, char *key); /** - * Set the platform/std_VGA field of the given VM. + * Set the platform field of the given VM. */ extern bool -xen_vm_set_platform_std_vga(xen_session *session, xen_vm vm, bool std_vga); +xen_vm_set_platform(xen_session *session, xen_vm vm, xen_string_string_map *platform); /** - * Set the platform/serial field of the given VM. + * Add the given key-value pair to the platform field of the given VM. */ extern bool -xen_vm_set_platform_serial(xen_session *session, xen_vm vm, char *serial); +xen_vm_add_to_platform(xen_session *session, xen_vm vm, char *key, char *value); /** - * Set the platform/localtime field of the given VM. + * Remove the given key and its corresponding value from the platform + * field of the given VM. If the key is not in that Map, then do nothing. */ extern bool -xen_vm_set_platform_localtime(xen_session *session, xen_vm vm, bool localtime); +xen_vm_remove_from_platform(xen_session *session, xen_vm vm, char *key); /** - * Set the platform/clock_offset field of the given VM. + * Set the PCI_bus field of the given VM. */ extern bool -xen_vm_set_platform_clock_offset(xen_session *session, xen_vm vm, bool clock_offset); - - -/** - * Set the platform/enable_audio field of the given VM. - */ -extern bool -xen_vm_set_platform_enable_audio(xen_session *session, xen_vm vm, bool enable_audio); +xen_vm_set_pci_bus(xen_session *session, xen_vm vm, char *pci_bus); /** diff --git a/tools/libxen/src/xen_vm.c b/tools/libxen/src/xen_vm.c index 910c9f8b31..64f04a3f8f 100644 --- a/tools/libxen/src/xen_vm.c +++ b/tools/libxen/src/xen_vm.c @@ -145,21 +145,9 @@ static const struct_member xen_vm_record_struct_members[] = { .key = "HVM_boot_params", .type = &abstract_type_string_string_map, .offset = offsetof(xen_vm_record, hvm_boot_params) }, - { .key = "platform_std_VGA", - .type = &abstract_type_bool, - .offset = offsetof(xen_vm_record, platform_std_vga) }, - { .key = "platform_serial", - .type = &abstract_type_string, - .offset = offsetof(xen_vm_record, platform_serial) }, - { .key = "platform_localtime", - .type = &abstract_type_bool, - .offset = offsetof(xen_vm_record, platform_localtime) }, - { .key = "platform_clock_offset", - .type = &abstract_type_bool, - .offset = offsetof(xen_vm_record, platform_clock_offset) }, - { .key = "platform_enable_audio", - .type = &abstract_type_bool, - .offset = offsetof(xen_vm_record, platform_enable_audio) }, + { .key = "platform", + .type = &abstract_type_string_string_map, + .offset = offsetof(xen_vm_record, platform) }, { .key = "PCI_bus", .type = &abstract_type_string, .offset = offsetof(xen_vm_record, pci_bus) }, @@ -217,7 +205,7 @@ xen_vm_record_free(xen_vm_record *record) free(record->pv_bootloader_args); free(record->hvm_boot_policy); xen_string_string_map_free(record->hvm_boot_params); - free(record->platform_serial); + xen_string_string_map_free(record->platform); free(record->pci_bus); xen_string_string_map_free(record->other_config); xen_vm_metrics_record_opt_free(record->metrics); @@ -825,7 +813,7 @@ xen_vm_get_hvm_boot_params(xen_session *session, xen_string_string_map **result, bool -xen_vm_get_platform_std_vga(xen_session *session, bool *result, xen_vm vm) +xen_vm_get_platform(xen_session *session, xen_string_string_map **result, xen_vm vm) { abstract_value param_values[] = { @@ -833,74 +821,10 @@ xen_vm_get_platform_std_vga(xen_session *session, bool *result, xen_vm vm) .u.string_val = vm } }; - abstract_type result_type = abstract_type_bool; - - XEN_CALL_("VM.get_platform_std_VGA"); - return session->ok; -} - - -bool -xen_vm_get_platform_serial(xen_session *session, char **result, xen_vm vm) -{ - abstract_value param_values[] = - { - { .type = &abstract_type_string, - .u.string_val = vm } - }; - - abstract_type result_type = abstract_type_string; + abstract_type result_type = abstract_type_string_string_map; *result = NULL; - XEN_CALL_("VM.get_platform_serial"); - return session->ok; -} - - -bool -xen_vm_get_platform_localtime(xen_session *session, bool *result, xen_vm vm) -{ - abstract_value param_values[] = - { - { .type = &abstract_type_string, - .u.string_val = vm } - }; - - abstract_type result_type = abstract_type_bool; - - XEN_CALL_("VM.get_platform_localtime"); - return session->ok; -} - - -bool -xen_vm_get_platform_clock_offset(xen_session *session, bool *result, xen_vm vm) -{ - abstract_value param_values[] = - { - { .type = &abstract_type_string, - .u.string_val = vm } - }; - - abstract_type result_type = abstract_type_bool; - - XEN_CALL_("VM.get_platform_clock_offset"); - return session->ok; -} - - -bool -xen_vm_get_platform_enable_audio(xen_session *session, bool *result, xen_vm vm) -{ - abstract_value param_values[] = - { - { .type = &abstract_type_string, - .u.string_val = vm } - }; - - abstract_type result_type = abstract_type_bool; - - XEN_CALL_("VM.get_platform_enable_audio"); + XEN_CALL_("VM.get_platform"); return session->ok; } @@ -1442,81 +1366,67 @@ xen_vm_remove_from_hvm_boot_params(xen_session *session, xen_vm vm, char *key) bool -xen_vm_set_platform_std_vga(xen_session *session, xen_vm vm, bool std_vga) +xen_vm_set_platform(xen_session *session, xen_vm vm, xen_string_string_map *platform) { abstract_value param_values[] = { { .type = &abstract_type_string, .u.string_val = vm }, - { .type = &abstract_type_bool, - .u.bool_val = std_vga } + { .type = &abstract_type_string_string_map, + .u.set_val = (arbitrary_set *)platform } }; - xen_call_(session, "VM.set_platform_std_VGA", param_values, 2, NULL, NULL); + xen_call_(session, "VM.set_platform", param_values, 2, NULL, NULL); return session->ok; } bool -xen_vm_set_platform_serial(xen_session *session, xen_vm vm, char *serial) +xen_vm_add_to_platform(xen_session *session, xen_vm vm, char *key, char *value) { abstract_value param_values[] = { { .type = &abstract_type_string, .u.string_val = vm }, { .type = &abstract_type_string, - .u.string_val = serial } + .u.string_val = key }, + { .type = &abstract_type_string, + .u.string_val = value } }; - xen_call_(session, "VM.set_platform_serial", param_values, 2, NULL, NULL); + xen_call_(session, "VM.add_to_platform", param_values, 3, NULL, NULL); return session->ok; } bool -xen_vm_set_platform_localtime(xen_session *session, xen_vm vm, bool localtime) +xen_vm_remove_from_platform(xen_session *session, xen_vm vm, char *key) { abstract_value param_values[] = { { .type = &abstract_type_string, .u.string_val = vm }, - { .type = &abstract_type_bool, - .u.bool_val = localtime } + { .type = &abstract_type_string, + .u.string_val = key } }; - xen_call_(session, "VM.set_platform_localtime", param_values, 2, NULL, NULL); + xen_call_(session, "VM.remove_from_platform", param_values, 2, NULL, NULL); return session->ok; } bool -xen_vm_set_platform_clock_offset(xen_session *session, xen_vm vm, bool clock_offset) +xen_vm_set_pci_bus(xen_session *session, xen_vm vm, char *pci_bus) { abstract_value param_values[] = { { .type = &abstract_type_string, .u.string_val = vm }, - { .type = &abstract_type_bool, - .u.bool_val = clock_offset } - }; - - xen_call_(session, "VM.set_platform_clock_offset", param_values, 2, NULL, NULL); - return session->ok; -} - - -bool -xen_vm_set_platform_enable_audio(xen_session *session, xen_vm vm, bool enable_audio) -{ - abstract_value param_values[] = - { { .type = &abstract_type_string, - .u.string_val = vm }, - { .type = &abstract_type_bool, - .u.bool_val = enable_audio } + .u.string_val = pci_bus } }; - xen_call_(session, "VM.set_platform_enable_audio", param_values, 2, NULL, NULL); + xen_call_(session, "VM.set_PCI_bus", param_values, 2, NULL, NULL); return session->ok; } diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index d229d57df4..bf5f9a8a2f 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -676,8 +676,9 @@ class XendAPI(object): return xen_api_success_void() def host_remove_from_other_config(self, session, host_ref, key): node = XendNode.instance() - del node.other_config[key] - node.save() + if key in node.other_config: + del node.other_config[key] + node.save() return xen_api_success_void() def host_get_API_version_major(self, _, ref): return xen_api_success(XEN_API_VERSION_MAJOR) @@ -998,7 +999,6 @@ class XendAPI(object): 'VIFs', 'VBDs', 'VTPMs', - 'PCI_bus', 'tools_version', 'domid', 'is_control_domain', @@ -1024,12 +1024,8 @@ class XendAPI(object): 'PV_bootloader_args', 'HVM_boot_policy', 'HVM_boot_params', - 'platform_std_VGA', - 'platform_serial', - 'platform_localtime', - 'platform_clock_offset', - 'platform_enable_audio', - 'platform_keymap', + 'platform', + 'PCI_bus', 'other_config'] VM_methods = [('clone', 'VM'), @@ -1042,6 +1038,10 @@ class XendAPI(object): ('hard_reboot', None), ('suspend', None), ('resume', None), + ('add_to_HVM_boot_params', None), + ('remove_from_HVM_boot_params', None), + ('add_to_platform', None), + ('remove_from_platform', None), ('add_to_other_config', None), ('remove_from_other_config', None)] @@ -1071,13 +1071,7 @@ class XendAPI(object): 'PV_bootloader_args', 'HVM_boot_policy', 'HVM_boot_params', - 'platform_std_VGA', - 'platform_serial', - 'platform_localtime', - 'platform_clock_offset', - 'platform_enable_audio', - 'platform_keymap', - 'grub_cmdline', + 'platform', 'PCI_bus', 'other_config'] @@ -1089,7 +1083,10 @@ class XendAPI(object): xd = XendDomain.instance() dominfo = xd.get_vm_by_uuid(vm_ref) dominfo.info[name] = value - xd.managed_config_save(dominfo) + return self._VM_save(dominfo) + + def _VM_save(self, dominfo): + XendDomain.instance().managed_config_save(dominfo) return xen_api_success_void() # attributes (ro) @@ -1136,10 +1133,6 @@ class XendAPI(object): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success(dom.get_consoles()) - def VM_get_PCI_bus(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return dom.get_pci_bus() - def VM_get_tools_version(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return dom.get_tools_version() @@ -1214,29 +1207,16 @@ class XendAPI(object): def VM_get_HVM_boot_params(self, session, vm_ref): return self.VM_get('HVM_boot_params', session, vm_ref) - def VM_get_platform_std_VGA(self, session, vm_ref): + def VM_get_platform(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_platform_std_vga()) + return xen_api_success(dom.get_platform()) - def VM_get_platform_serial(self, session, vm_ref): + def VM_get_PCI_bus(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_platform_serial()) + return dom.get_pci_bus() - def VM_get_platform_localtime(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_platform_localtime()) - - def VM_get_platform_clock_offset(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_platform_clock_offset()) - - def VM_get_platform_enable_audio(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_platform_enable_audio()) - - def VM_get_platform_keymap(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_platform_keymap()) + def VM_set_PCI_bus(self, session, vm_ref, val): + return self.VM_set('PCI_bus', session, vm_ref, val) def VM_get_other_config(self, session, vm_ref): return self.VM_get('other_config', session, vm_ref) @@ -1253,7 +1233,7 @@ class XendAPI(object): def VM_set_name_label(self, session, vm_ref, label): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) dom.setName(label) - return xen_api_success_void() + return self._VM_save(dom) def VM_set_name_description(self, session, vm_ref, desc): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) @@ -1319,14 +1299,16 @@ class XendAPI(object): if 'HVM_boot_params' not in dom.info: dom.info['HVM_boot_params'] = {} dom.info['HVM_boot_params'][key] = value - return xen_api_success_void() + return self._VM_save(dom) def VM_remove_from_HVM_boot_params(self, session, vm_ref, key): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) if 'HVM_boot_params' in dom.info \ and key in dom.info['HVM_boot_params']: del dom.info['HVM_boot_params'][key] - return xen_api_success_void() + return self._VM_save(dom) + else: + return xen_api_success_void() def VM_set_PV_bootloader(self, session, vm_ref, value): return self.VM_set('PV_bootloader', session, vm_ref, value) @@ -1343,40 +1325,42 @@ class XendAPI(object): def VM_set_PV_bootloader_args(self, session, vm_ref, value): return self.VM_set('PV_bootloader_args', session, vm_ref, value) - def VM_set_platform_std_VGA(self, session, vm_ref, value): - return self.VM_set('platform_std_vga', session, vm_ref, value) + def VM_set_platform(self, session, vm_ref, value): + return self.VM_set('platform', session, vm_ref, value) - def VM_set_platform_serial(self, session, vm_ref, value): - return self.VM_set('platform_serial', session, vm_ref, value) + def VM_add_to_platform(self, session, vm_ref, key, value): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + plat = dom.get_platform() + plat[key] = value + return self.VM_set_platform(session, vm_ref, plat) + + def VM_remove_from_platform(self, session, vm_ref, key): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + plat = dom.get_platform() + if key in plat: + del plat[key] + return self.VM_set_platform(session, vm_ref, plat) + else: + return xen_api_success_void() - def VM_set_platform_keymap(self, session, vm_ref, value): - return self.VM_set('platform_keymap', session, vm_ref, value) - - def VM_set_platform_localtime(self, session, vm_ref, value): - return self.VM_set('platform_localtime', session, vm_ref, value) - - def VM_set_platform_clock_offset(self, session, vm_ref, value): - return self.VM_set('platform_clock_offset', session, vm_ref, value) - - def VM_set_platform_enable_audio(self, session, vm_ref, value): - return self.VM_set('platform_enable_audio', session, vm_ref, value) - def VM_set_other_config(self, session, vm_ref, value): - return self.VM_set('otherconfig', session, vm_ref, value) + return self.VM_set('other_config', session, vm_ref, value) def VM_add_to_other_config(self, session, vm_ref, key, value): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - if dom and 'otherconfig' in dom.info: - dom.info['otherconfig'][key] = value - return xen_api_success_void() + if dom and 'other_config' in dom.info: + dom.info['other_config'][key] = value + return self._VM_save(dom) def VM_remove_from_other_config(self, session, vm_ref, key): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - if dom and 'otherconfig' in dom.info \ - and key in dom.info['otherconfig']: - del dom.info['otherconfig'][key] - return xen_api_success_void() - + if dom and 'other_config' in dom.info \ + and key in dom.info['other_config']: + del dom.info['other_config'][key] + return self._VM_save(dom) + else: + return xen_api_success_void() + # class methods def VM_get_all(self, session): refs = [d.get_uuid() for d in XendDomain.instance().list('all')] @@ -1437,12 +1421,7 @@ class XendAPI(object): 'PV_bootloader_args': xeninfo.info.get('PV_bootloader_args'), 'HVM_boot_policy': xeninfo.info.get('HVM_boot_policy'), 'HVM_boot_params': xeninfo.info.get('HVM_boot_params'), - 'platform_std_VGA': xeninfo.get_platform_std_vga(), - 'platform_serial': xeninfo.get_platform_serial(), - 'platform_localtime': xeninfo.get_platform_localtime(), - 'platform_clock_offset': xeninfo.get_platform_clock_offset(), - 'platform_enable_audio': xeninfo.get_platform_enable_audio(), - 'platform_keymap': xeninfo.get_platform_keymap(), + 'platform': xeninfo.get_platform(), 'PCI_bus': xeninfo.get_pci_bus(), 'tools_version': xeninfo.get_tools_version(), 'other_config': xeninfo.info.get('other_config', {}), diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index c945ced425..4dd1367c2d 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -12,7 +12,7 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #============================================================================ -# Copyright (C) 2006 XenSource Ltd +# Copyright (C) 2006-2007 XenSource Ltd #============================================================================ import logging @@ -111,22 +111,18 @@ XENAPI_CFG_TO_LEGACY_CFG = { 'actions_after_shutdown': 'on_poweroff', 'actions_after_reboot': 'on_reboot', 'actions_after_crash': 'on_crash', - 'platform_localtime': 'localtime', 'PV_bootloader': 'bootloader', 'PV_bootloader_args': 'bootloader_args', } LEGACY_CFG_TO_XENAPI_CFG = reverse_dict(XENAPI_CFG_TO_LEGACY_CFG) -# Mapping from XendConfig configuration keys to the old -# legacy configuration keys that are found in the 'image' -# SXP object. -XENAPI_HVM_CFG = { - 'platform_std_vga': 'stdvga', - 'platform_serial' : 'serial', - 'platform_localtime': 'localtime', - 'platform_keymap' : 'keymap' -} +# Platform configuration keys. +XENAPI_PLATFORM_CFG = [ 'acpi', 'apic', 'device_model', 'display', 'fda', + 'fdb', 'keymap', 'isa', 'localtime', 'nographic', + 'pae', 'serial', 'sdl', 'soundhw','stdvga', 'usb', + 'usbdevice', 'vnc', 'vncconsole', 'vncdisplay', + 'vnclisten', 'vncpasswd', 'vncunused', 'xauthority'] # List of XendConfig configuration keys that have no direct equivalent # in the old world. @@ -158,15 +154,10 @@ XENAPI_CFG_TYPES = { 'PV_bootloader_args': str, 'HVM_boot_policy': str, 'HVM_boot_params': dict, - 'platform_std_vga': bool0, - 'platform_serial': str, - 'platform_localtime': bool0, - 'platform_clock_offset': bool0, - 'platform_enable_audio': bool0, - 'platform_keymap': str, - 'pci_bus': str, + 'PCI_bus': str, + 'platform': dict, 'tools_version': dict, - 'otherconfig': dict, + 'other_config': dict, } # List of legacy configuration keys that have no equivalent in the @@ -236,44 +227,7 @@ LEGACY_XENSTORE_VM_PARAMS = [ 'on_xend_stop', ] -LEGACY_IMAGE_CFG = [ - ('root', str), - ('ip', str), - ('nographic', int), - ('vnc', int), - ('sdl', int), - ('vncdisplay', int), - ('vncunused', int), - ('vncpasswd', str), - ('vnclisten', str), -] - -LEGACY_IMAGE_HVM_CFG = [ - ('device_model', str), - ('display', str), - ('xauthority', str), - ('vncconsole', int), - ('pae', int), - ('apic', int), -] - -LEGACY_IMAGE_HVM_DEVICES_CFG = [ - ('acpi', int), - ('boot', str), - ('fda', str), - ('fdb', str), - ('isa', int), - ('keymap', str), - ('localtime', int), - ('serial', str), - ('stdvga', int), - ('soundhw', str), - ('usb', int), - ('usbdevice', str), - ('vcpus', int), -] - -LEGACY_DM = '/usr/lib/xen/bin/qemu-dm' +DEFAULT_DM = '/usr/lib/xen/bin/qemu-dm' ## ## Config Choices @@ -315,7 +269,6 @@ class XendConfig(dict): self._sxp_to_xapi_unsupported(sxp_obj) elif xapi: self.update_with_xenapi_config(xapi) - self._add_xapi_unsupported(xapi) elif dominfo: # output from xc.domain_getinfo self._dominfo_to_xapi(dominfo) @@ -362,7 +315,6 @@ class XendConfig(dict): 'memory_dynamic_max': 0, 'memory_actual': 0, 'devices': {}, - 'image': {}, 'security': None, 'on_xend_start': 'ignore', 'on_xend_stop': 'ignore', @@ -376,6 +328,7 @@ class XendConfig(dict): 'vbd_refs': [], 'vtpm_refs': [], 'other_config': {}, + 'platform': {} } return defaults @@ -416,12 +369,23 @@ class XendConfig(dict): if 'name_label' not in self: self['name_label'] = 'Domain-' + self['uuid'] + def _platform_sanity_check(self): + if self.is_hvm(): + if 'device_model' not in self['platform']: + self['platform']['device_model'] = DEFAULT_DM + + # Compatibility hack, can go away soon. + if 'soundhw' not in self['platform'] and \ + self['platform'].get('enable_audio'): + self['platform']['soundhw'] = 'sb16' + def validate(self): self._uuid_sanity_check() self._name_sanity_check() self._memory_sanity_check() self._actions_sanity_check() self._vcpus_sanity_check() + self._platform_sanity_check() def _dominfo_to_xapi(self, dominfo): self['domid'] = dominfo['domid'] @@ -497,6 +461,18 @@ class XendConfig(dict): log.warn("Unable to parse key %s: %s: %s" % (key, str(val), e)) + if 'platform' not in cfg: + cfg['platform'] = {} + localtime = sxp.child_value(sxp_cfg, 'localtime') + if localtime is not None: + cfg['platform']['localtime'] = localtime + + # Compatibility hack -- can go soon. + for key in XENAPI_PLATFORM_CFG: + val = sxp.child_value(sxp_cfg, "platform_" + key, None) + if val is not None: + self['platform'][key] = val + # Compatibility hack -- can go soon. boot_order = sxp.child_value(sxp_cfg, 'HVM_boot') if boot_order: @@ -651,10 +627,9 @@ class XendConfig(dict): self.update_with_image_sxp(image_sxp) # Convert Legacy HVM parameters to Xen API configuration - self['platform_std_vga'] = bool0(cfg.get('stdvga', 0)) - self['platform_serial'] = str(cfg.get('serial', '')) - self['platform_localtime'] = bool0(cfg.get('localtime', 0)) - self['platform_enable_audio'] = bool0(cfg.get('soundhw', 0)) + for key in XENAPI_PLATFORM_CFG: + if key in cfg: + self['platform'][key] = cfg[key] # make sure a sane maximum is set if self['memory_static_max'] <= 0: @@ -671,7 +646,7 @@ class XendConfig(dict): self['vtpm_refs'] = cfg.get('vtpm_refs', []) # coalesce hvm vnc frame buffer with vfb config - if self['image']['type'] == 'hvm' and self['image'].get('vnc', 0): + if self.is_hvm() and self['platform'].get('vnc', 0): # add vfb device if it isn't there already has_rfb = False for console_uuid in self['console_refs']: @@ -684,11 +659,11 @@ class XendConfig(dict): if not has_rfb: dev_config = ['vfb'] - # copy VNC related params from image config to vfb dev conf + # copy VNC related params from platform config to vfb dev conf for key in ['vncpasswd', 'vncunused', 'vncdisplay', 'vnclisten']: - if key in self['image']: - dev_config.append([key, self['image'][key]]) + if key in self['platform']: + dev_config.append([key, self['platform'][key]]) self.device_add('vfb', cfg_sxp = dev_config) @@ -705,39 +680,19 @@ class XendConfig(dict): # the image (as well as HVM images) image_sxp = sxp.child_value(sxp_cfg, 'image', []) if image_sxp: - image = {} - image['type'] = sxp.name(image_sxp) - for arg, conv in LEGACY_IMAGE_CFG: - val = sxp.child_value(image_sxp, arg, None) - if val != None: - image[arg] = conv(val) - - image_hvm = {} - for arg, conv in LEGACY_IMAGE_HVM_CFG: - val = sxp.child_value(image_sxp, arg, None) - if val != None: - image_hvm[arg] = conv(val) - - image_hvm_devices = {} - for arg, conv in LEGACY_IMAGE_HVM_DEVICES_CFG: - val = sxp.child_value(image_sxp, arg, None) - if val != None: - image_hvm_devices[arg] = conv(val) - - if image_hvm or image_hvm_devices: - image['hvm'] = image_hvm - image['hvm']['devices'] = image_hvm_devices - + image_type = sxp.name(image_sxp) + if image_type != 'hvm' and image_type != 'linux': + self['platform']['image_type'] = image_type + + for key in XENAPI_PLATFORM_CFG: + val = sxp.child_value(image_sxp, key, None) + if val is not None: + self['platform'][key] = val + notes = sxp.children(image_sxp, 'notes') if notes: - image['notes'] = self.notes_from_sxp(notes[0]) + self['notes'] = self.notes_from_sxp(notes[0]) - self['image'] = image - - for apikey, imgkey in XENAPI_HVM_CFG.items(): - val = sxp.child_value(image_sxp, imgkey, None) - if val != None: - self[apikey] = val self._hvm_boot_params_from_sxp(image_sxp) # extract backend value @@ -773,33 +728,6 @@ class XendConfig(dict): _set_cfg_if_exists('up_time') _set_cfg_if_exists('status') # TODO, deprecated - def _add_xapi_unsupported(self, xapi_dict): - """Updates the configuration object with entries that are not - officially supported by the Xen API but is required for - the rest of Xend to function. - """ - - # populate image - if 'image' in xapi_dict: - self['image'].update(xapi_dict['image']) - else: - hvm = self['HVM_boot_policy'] != '' - self['image']['type'] = hvm and 'hvm' or 'linux' - if hvm: - self['image']['hvm'] = {'devices': {}} - for xapi, cfgapi in XENAPI_HVM_CFG.items(): - if xapi in self: - self['image']['hvm']['devices'][cfgapi] = self[xapi] - - # currently unsupported options - self['image']['hvm']['device_model'] = LEGACY_DM - self['image']['vnc'] = 0 - self['image']['hvm']['pae'] = 1 - - if self['platform_enable_audio']: - self['image']['hvm']['devices']['soundhw'] = 'sb16' - - def _get_old_state_string(self): """Returns the old xm state string. @rtype: string @@ -889,9 +817,7 @@ class XendConfig(dict): if self.has_key(legacy) and self[legacy] not in (None, []): sxpr.append([legacy, self[legacy]]) - if 'image' in self and self['image']: - sxpr.append(['image', self.image_sxpr()]) - + sxpr.append(['image', self.image_sxpr()]) sxpr.append(['status', domain.state]) sxpr.append(['memory_dynamic_min', self.get('memory_dynamic_min')]) sxpr.append(['memory_dynamic_max', self.get('memory_dynamic_max')]) @@ -1338,7 +1264,7 @@ class XendConfig(dict): def image_sxpr(self): """Returns a backwards compatible image SXP expression that is used in xenstore's /vm//image value and xm list.""" - image = [self['image'].get('type', 'linux')] + image = [self.image_type()] if self.has_key('PV_kernel'): image.append(['kernel', self['PV_kernel']]) if self.has_key('PV_ramdisk') and self['PV_ramdisk']: @@ -1346,28 +1272,12 @@ class XendConfig(dict): if self.has_key('PV_args') and self['PV_args']: image.append(['args', self['PV_args']]) - for arg, conv in LEGACY_IMAGE_CFG: - if self['image'].has_key(arg): - image.append([arg, self['image'][arg]]) + for key in XENAPI_PLATFORM_CFG: + if key in self['platform']: + image.append([key, self['platform'][key]]) - if 'hvm' in self['image']: - for arg, conv in LEGACY_IMAGE_HVM_CFG: - if self['image']['hvm'].get(arg): - image.append([arg, conv(self['image']['hvm'][arg])]) - - if 'hvm' in self['image'] and 'devices' in self['image']['hvm']: - for arg, conv in LEGACY_IMAGE_HVM_DEVICES_CFG: - val = self['image']['hvm']['devices'].get(arg) - if val != None: - try: - if conv: val = conv(val) - except (ValueError, TypeError): - if type(val) == bool: val = int(val) - - image.append([arg, val]) - - if 'notes' in self['image']: - image.append(self.notes_sxp(self['image']['notes'])) + if 'notes' in self: + image.append(self.notes_sxp(self['notes'])) return image @@ -1398,57 +1308,24 @@ class XendConfig(dict): self['PV_ramdisk'] = sxp.child_value(image_sxp, 'ramdisk','') self['PV_args'] = kernel_args - # Store image SXP in python dictionary format - image = {} - image['type'] = sxp.name(image_sxp) - for arg, conv in LEGACY_IMAGE_CFG: - val = sxp.child_value(image_sxp, arg, None) - if val != None: - image[arg] = conv(val) - - image_hvm = {} - for arg, conv in LEGACY_IMAGE_HVM_CFG: - val = sxp.child_value(image_sxp, arg, None) - if val != None: - image_hvm[arg] = conv(val) - - image_hvm_devices = {} - for arg, conv in LEGACY_IMAGE_HVM_DEVICES_CFG: - val = sxp.child_value(image_sxp, arg, None) - if val != None: - try: - image_hvm_devices[arg] = conv(val) - except (ValueError, TypeError): - image_hvm_devices[arg] = val - - - if image_hvm or image_hvm_devices: - image['hvm'] = image_hvm - image['hvm']['devices'] = image_hvm_devices + for key in XENAPI_PLATFORM_CFG: + val = sxp.child_value(image_sxp, key, None) + if val is not None: + self['platform'][key] = val notes = sxp.children(image_sxp, 'notes') if notes: - image['notes'] = self.notes_from_sxp(notes[0]) + self['notes'] = self.notes_from_sxp(notes[0]) - self['image'] = image - - for apikey, imgkey in XENAPI_HVM_CFG.items(): - val = sxp.child_value(image_sxp, imgkey, None) - if val != None: - type_conv = XENAPI_CFG_TYPES[apikey] - if callable(type_conv): - self[apikey] = type_conv(val) - else: - self[apikey] = val self._hvm_boot_params_from_sxp(image_sxp) def set_notes(self, notes): 'Add parsed elfnotes to image' - self['image']['notes'] = notes + self['notes'] = notes def get_notes(self): try: - return self['image']['notes'] or {} + return self['notes'] or {} except KeyError: return {} @@ -1470,11 +1347,9 @@ class XendConfig(dict): self['HVM_boot_policy'] = 'BIOS order' self['HVM_boot_params'] = { 'order' : boot } + def is_hvm(self): + return self['HVM_boot_policy'] != '' -# -# debugging -# - -if __name__ == "__main__": - pass - + def image_type(self): + stored_type = self['platform'].get('image_type') + return stored_type or (self.is_hvm() and 'hvm' or 'linux') diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index c784c95f80..1842143d79 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -13,7 +13,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #============================================================================ # Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2005, 2006 XenSource Ltd +# Copyright (C) 2005-2007 XenSource Ltd #============================================================================ """Representation of a single domain. @@ -176,14 +176,8 @@ def recreate(info, priv): vm._storeVmDetails() vm._storeDomDetails() - if vm.info['image']: # Only dom0 should be without an image entry when - # recreating, but we cope with missing ones - # elsewhere just in case. - vm.image = image.create(vm, - vm.info, - vm.info['image'], - vm.info['devices']) - vm.image.recreate() + vm.image = image.create(vm, vm.info) + vm.image.recreate() vm._registerWatches() vm.refreshShutdown(xeninfo) @@ -448,9 +442,7 @@ class XendDomainInfo: self.storeDom("control/shutdown", reason) ## shutdown hypercall for hvm domain desides xenstore write - image_cfg = self.info.get('image', {}) - hvm = image_cfg.has_key('hvm') - if hvm: + if self.info.is_hvm(): for code in DOMAIN_SHUTDOWN_REASONS.keys(): if DOMAIN_SHUTDOWN_REASONS[code] == reason: break @@ -1389,9 +1381,7 @@ class XendDomainInfo: self.shutdownStartTime = None - image_cfg = self.info.get('image', {}) - hvm = image_cfg.has_key('hvm') - + hvm = self.info.is_hvm() if hvm: info = xc.xeninfo() if 'hvm' not in info['xen_caps']: @@ -1438,14 +1428,8 @@ class XendDomainInfo: self._configureBootloader() - if not self._infoIsSet('image'): - raise VmError('Missing image in configuration') - try: - self.image = image.create(self, - self.info, - self.info['image'], - self.info['devices']) + self.image = image.create(self, self.info) localtime = self.info.get('platform_localtime', False) if localtime: @@ -1507,7 +1491,8 @@ class XendDomainInfo: self._stateSet(DOM_STATE_RUNNING) except (RuntimeError, VmError), exn: log.exception("XendDomainInfo.initDomain: exception occurred") - self.image.cleanupBootloading() + if self.image: + self.image.cleanupBootloading() raise VmError(str(exn)) @@ -1574,13 +1559,8 @@ class XendDomainInfo: self.console_mfn = console_mfn self._introduceDomain() - image_cfg = self.info.get('image', {}) - hvm = image_cfg.has_key('hvm') - if hvm: - self.image = image.create(self, - self.info, - self.info['image'], - self.info['devices']) + if self.info.has_hvm(): + self.image = image.create(self, self.info) if self.image: self.image.createDeviceModel(True) self.image.register_shutdown_watch() @@ -1742,11 +1722,7 @@ class XendDomainInfo: if boot: # HVM booting. - self.info['image']['type'] = 'hvm' - if not 'devices' in self.info['image']: - self.info['image']['devices'] = {} - self.info['image']['devices']['boot'] = \ - self.info['HVM_boot_params'].get('order', 'dc') + pass elif not blexec and kernel: # Boot from dom0. Nothing left to do -- the kernel and ramdisk # will be picked up by image.py. @@ -1910,10 +1886,9 @@ class XendDomainInfo: if self._infoIsSet(info_key): to_store[key] = str(self.info[info_key]) - if self.info.get('image'): - image_sxpr = self.info.image_sxpr() - if image_sxpr: - to_store['image'] = sxp.to_string(image_sxpr) + image_sxpr = self.info.image_sxpr() + if image_sxpr: + to_store['image'] = sxp.to_string(image_sxpr) if self._infoIsSet('security'): secinfo = self.info['security'] @@ -2074,18 +2049,8 @@ class XendDomainInfo: return retval def get_power_state(self): return XEN_API_VM_POWER_STATE[self.state] - def get_platform_std_vga(self): - return self.info.get('platform_std_vga', False) - def get_platform_serial(self): - return self.info.get('platform_serial', '') - def get_platform_localtime(self): - return self.info.get('platform_localtime', False) - def get_platform_clock_offset(self): - return self.info.get('platform_clock_offset', False) - def get_platform_enable_audio(self): - return self.info.get('platform_enable_audio', False) - def get_platform_keymap(self): - return self.info.get('platform_keymap', '') + def get_platform(self): + return self.info.get('platform', {}) def get_pci_bus(self): return self.info.get('pci_bus', '') def get_tools_version(self): diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py index ec3ce1fe30..f39e842f2b 100644 --- a/tools/python/xen/xend/image.py +++ b/tools/python/xen/xend/image.py @@ -13,7 +13,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #============================================================================ # Copyright (C) 2005 Mike Wray -# Copyright (C) 2005 XenSource Ltd +# Copyright (C) 2005-2007 XenSource Ltd #============================================================================ @@ -36,13 +36,12 @@ xc = xen.lowlevel.xc.xc() MAX_GUEST_CMDLINE = 1024 -def create(vm, vmConfig, imageConfig, deviceConfig): +def create(vm, vmConfig): """Create an image handler for a vm. @return ImageHandler instance """ - return findImageHandlerClass(imageConfig)(vm, vmConfig, imageConfig, - deviceConfig) + return findImageHandlerClass(vmConfig)(vm, vmConfig) class ImageHandler: @@ -65,7 +64,7 @@ class ImageHandler: ostype = None - def __init__(self, vm, vmConfig, imageConfig, deviceConfig): + def __init__(self, vm, vmConfig): self.vm = vm self.bootloader = False @@ -73,9 +72,9 @@ class ImageHandler: self.ramdisk = None self.cmdline = None - self.configure(vmConfig, imageConfig, deviceConfig) + self.configure(vmConfig) - def configure(self, vmConfig, imageConfig, _): + def configure(self, vmConfig): """Config actions common to all unix-like domains.""" if '_temp_using_bootloader' in vmConfig: self.bootloader = True @@ -262,13 +261,13 @@ class HVMImageHandler(ImageHandler): ostype = "hvm" - def __init__(self, vm, vmConfig, imageConfig, deviceConfig): - ImageHandler.__init__(self, vm, vmConfig, imageConfig, deviceConfig) + def __init__(self, vm, vmConfig): + ImageHandler.__init__(self, vm, vmConfig) self.shutdownWatch = None self.rebootFeatureWatch = None - def configure(self, vmConfig, imageConfig, deviceConfig): - ImageHandler.configure(self, vmConfig, imageConfig, deviceConfig) + def configure(self, vmConfig): + ImageHandler.configure(self, vmConfig) if not self.kernel: self.kernel = '/usr/lib/xen/boot/hvmloader' @@ -279,13 +278,13 @@ class HVMImageHandler(ImageHandler): "supported by your CPU and enabled in your BIOS?") self.dmargs = self.parseDeviceModelArgs(vmConfig) - self.device_model = imageConfig['hvm'].get('device_model') + self.device_model = vmConfig['platform'].get('device_model') if not self.device_model: raise VmError("hvm: missing device model") - self.display = imageConfig['hvm'].get('display') - self.xauthority = imageConfig['hvm'].get('xauthority') - self.vncconsole = imageConfig['hvm'].get('vncconsole') + self.display = vmConfig['platform'].get('display') + self.xauthority = vmConfig['platform'].get('xauthority') + self.vncconsole = vmConfig['platform'].get('vncconsole') self.vm.storeVm(("image/dmargs", " ".join(self.dmargs)), ("image/device-model", self.device_model), @@ -293,9 +292,9 @@ class HVMImageHandler(ImageHandler): self.pid = None - self.pae = imageConfig['hvm'].get('pae', 0) - self.apic = imageConfig['hvm'].get('apic', 0) - self.acpi = imageConfig['hvm']['devices'].get('acpi', 0) + self.pae = int(vmConfig['platform'].get('pae', 0)) + self.apic = int(vmConfig['platform'].get('apic', 0)) + self.acpi = int(vmConfig['platform'].get('acpi', 0)) def buildDomain(self): @@ -331,11 +330,10 @@ class HVMImageHandler(ImageHandler): 'localtime', 'serial', 'stdvga', 'isa', 'acpi', 'usb', 'usbdevice', 'keymap' ] - hvmDeviceConfig = vmConfig['image']['hvm']['devices'] ret = ['-vcpus', str(self.vm.getVCpuCount())] for a in dmargs: - v = hvmDeviceConfig.get(a) + v = vmConfig['platform'].get(a) # python doesn't allow '-' in variable names if a == 'stdvga': a = 'std-vga' @@ -395,14 +393,14 @@ class HVMImageHandler(ImageHandler): # Find RFB console device, and if it exists, make QEMU enable # the VNC console. # - if vmConfig['image'].get('nographic'): + if vmConfig['platform'].get('nographic'): # skip vnc init if nographic is set ret.append('-nographic') return ret vnc_config = {} - has_vnc = int(vmConfig['image'].get('vnc', 0)) != 0 - has_sdl = int(vmConfig['image'].get('sdl', 0)) != 0 + has_vnc = int(vmConfig['platform'].get('vnc', 0)) != 0 + has_sdl = int(vmConfig['platform'].get('sdl', 0)) != 0 for dev_uuid in vmConfig['console_refs']: dev_type, dev_info = vmConfig['devices'][dev_uuid] if dev_type == 'vfb': @@ -414,8 +412,8 @@ class HVMImageHandler(ImageHandler): if not vnc_config: for key in ('vncunused', 'vnclisten', 'vncdisplay', 'vncpasswd'): - if key in vmConfig['image']: - vnc_config[key] = vmConfig['image'][key] + if key in vmConfig['platform']: + vnc_config[key] = vmConfig['platform'][key] if not vnc_config.get('vncunused', 0) and \ vnc_config.get('vncdisplay', 0): @@ -634,9 +632,7 @@ def findImageHandlerClass(image): @param image config @return ImageHandler subclass or None """ - image_type = image['type'] - if image_type is None: - raise VmError('missing image type') + image_type = image.image_type() try: return _handlers[arch.type][image_type] except KeyError: From 2cb49001bc68da3461a5250d609fbdf56e2afa83 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Sat, 10 Mar 2007 23:22:00 +0000 Subject: [PATCH 052/170] Added an VM_HVM_REQUIRED error code, and use it on VM.start. Signed-off-by: Ewan Mellor --- docs/xen-api/xenapi-datamodel.tex | 12 +++++++++++- tools/python/xen/xend/XendAPI.py | 11 +++++++---- tools/python/xen/xend/XendDomainInfo.py | 7 ++++++- tools/python/xen/xend/XendError.py | 7 +++++++ tools/python/xen/xend/image.py | 5 ++--- tools/python/xen/xm/messages/en/xen-xm.po | 5 ++++- 6 files changed, 37 insertions(+), 10 deletions(-) diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex index 08b831fdd5..ed6e0081b6 100644 --- a/docs/xen-api/xenapi-datamodel.tex +++ b/docs/xen-api/xenapi-datamodel.tex @@ -1141,7 +1141,8 @@ void \vspace{0.3cm} -\noindent{\bf Possible Error Codes:} {\tt VM\_BAD\_POWER\_STATE} +\noindent{\bf Possible Error Codes:} {\tt VM\_BAD\_POWER\_STATE}, {\tt +VM\_HVM\_REQUIRED} \vspace{0.6cm} \subsubsection{RPC name:~pause} @@ -13337,6 +13338,15 @@ expected and actual VM state at the time of the call. \begin{verbatim}VM_BAD_POWER_STATE(vm, expected, actual)\end{verbatim} \begin{center}\rule{10em}{0.1pt}\end{center} +\subsubsection{VM\_HVM\_REQUIRED} + +HVM is required for this operation + +\vspace{0.3cm} +{\bf Signature:} +\begin{verbatim}VM_HVM_REQUIRED(vm)\end{verbatim} +\begin{center}\rule{10em}{0.1pt}\end{center} + \newpage diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index bf5f9a8a2f..2d7a01bc1a 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -1465,10 +1465,13 @@ class XendAPI(object): start_paused = start_paused) def VM_start(self, session, vm_ref, start_paused): - return XendTask.log_progress(0, 100, do_vm_func, - "domain_start", vm_ref, - start_paused = start_paused) - + try: + return XendTask.log_progress(0, 100, do_vm_func, + "domain_start", vm_ref, + start_paused = start_paused) + except HVMRequired, exn: + return xen_api_error(['VM_HVM_REQUIRED', vm_ref]) + def VM_suspend(self, session, vm_ref): return XendTask.log_progress(0, 100, do_vm_func, "domain_suspend", vm_ref) diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 1842143d79..13a7a20f58 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -1489,7 +1489,12 @@ class XendDomainInfo: self.info['start_time'] = time.time() self._stateSet(DOM_STATE_RUNNING) - except (RuntimeError, VmError), exn: + except VmError, exn: + log.exception("XendDomainInfo.initDomain: exception occurred") + if self.image: + self.image.cleanupBootloading() + raise exn + except RuntimeError, exn: log.exception("XendDomainInfo.initDomain: exception occurred") if self.image: self.image.cleanupBootloading() diff --git a/tools/python/xen/xend/XendError.py b/tools/python/xen/xend/XendError.py index f1507c43dc..bbd5f4f6dd 100644 --- a/tools/python/xen/xend/XendError.py +++ b/tools/python/xen/xend/XendError.py @@ -13,6 +13,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #============================================================================ # Copyright (C) 2004, 2005 Mike Wray +# Copyright (c) 2006, 2007 XenSource Inc. #============================================================================ from xmlrpclib import Fault @@ -55,6 +56,12 @@ class VmError(XendError): """Vm construction error.""" pass +class HVMRequired(VmError): + def __init__(self): + XendError.__init__(self, + 'HVM guest support is unavailable: is VT/AMD-V ' + 'supported by your CPU and enabled in your BIOS?') + XEND_ERROR_AUTHENTICATION_FAILED = ('ELUSER', 'Authentication Failed') XEND_ERROR_SESSION_INVALID = ('EPERMDENIED', 'Session Invalid') diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py index f39e842f2b..33e1b1100b 100644 --- a/tools/python/xen/xend/image.py +++ b/tools/python/xen/xend/image.py @@ -24,7 +24,7 @@ import signal import xen.lowlevel.xc from xen.xend.XendConstants import REVERSE_DOMAIN_SHUTDOWN_REASONS -from xen.xend.XendError import VmError, XendError +from xen.xend.XendError import VmError, XendError, HVMRequired from xen.xend.XendLogging import log from xen.xend.XendOptions import instance as xenopts from xen.xend.server.netif import randomMAC @@ -274,8 +274,7 @@ class HVMImageHandler(ImageHandler): info = xc.xeninfo() if 'hvm' not in info['xen_caps']: - raise VmError("HVM guest support is unavailable: is VT/AMD-V " - "supported by your CPU and enabled in your BIOS?") + raise HVMRequired() self.dmargs = self.parseDeviceModelArgs(vmConfig) self.device_model = vmConfig['platform'].get('device_model') diff --git a/tools/python/xen/xm/messages/en/xen-xm.po b/tools/python/xen/xm/messages/en/xen-xm.po index 3ea171b2fa..6e289b4aa3 100644 --- a/tools/python/xen/xm/messages/en/xen-xm.po +++ b/tools/python/xen/xm/messages/en/xen-xm.po @@ -19,7 +19,7 @@ msgid "" msgstr "" "Project-Id-Version: Xen-xm 3.0\n" -"PO-Revision-Date: 2007-02-20 15:22+0000\n" +"PO-Revision-Date: 2007-03-10 23:17+0000\n" "Last-Translator: Ewan Mellor \n" "Language-Team: xen-devel \n" "MIME-Version: 1.0\n" @@ -61,3 +61,6 @@ msgstr "The VLAN tag you gave (%(1)s) is invalid -- it must be between 0 and 409 msgid "VM_BAD_POWER_STATE" msgstr "The VM must be %(2)s to perform the requested operation (it is currently %(3)s)." + +msgid "VM_HVM_REQUIRED" +msgstr "HVM guest support is unavailable: is VT/AMD-V supported by your CPU and enabled in your BIOS?" From 1ad66bcd45a71a721f5e4cb07d8cf16f5bb62e6e Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Sun, 11 Mar 2007 22:42:22 +0000 Subject: [PATCH 053/170] Fix typo in cset 14341:0affe03ee985 that broke migration. Signed-off-by: Ewan Mellor --- tools/python/xen/xend/XendDomainInfo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 13a7a20f58..e4f30fc6e4 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -1564,7 +1564,7 @@ class XendDomainInfo: self.console_mfn = console_mfn self._introduceDomain() - if self.info.has_hvm(): + if self.info.is_hvm(): self.image = image.create(self, self.info) if self.image: self.image.createDeviceModel(True) From 9ad19a00bdc36cf94aefd15692bfc9d65fa8e595 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Mon, 12 Mar 2007 09:44:34 +0000 Subject: [PATCH 054/170] [HVM] Speed up bulk p2m operations such as domain creation by not flushing the shadows more often than is needed. Signed-off-by: Tim Deegan --- xen/arch/x86/mm/shadow/common.c | 6 +++++- xen/arch/x86/mm/shadow/multi.c | 2 ++ xen/include/asm-x86/domain.h | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c index 4907736299..15ebf1d541 100644 --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -2813,7 +2813,11 @@ shadow_write_p2m_entry(struct vcpu *v, unsigned long gfn, l1_pgentry_t *p, This is pretty heavy handed, but this is a rare operation (it might happen a dozen times during boot and then never again), so it doesn't matter too much. */ - shadow_blow_tables(d); + if ( d->arch.paging.shadow.has_fast_mmio_entries ) + { + shadow_blow_tables(d); + d->arch.paging.shadow.has_fast_mmio_entries = 0; + } #endif shadow_unlock(d); diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c index 581ab45196..108c2e692d 100644 --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -660,6 +660,8 @@ _sh_propagate(struct vcpu *v, { /* Guest l1e maps MMIO space */ *sp = sh_l1e_mmio(guest_l1e_get_gfn(*gp), gflags); + if ( !d->arch.paging.shadow.has_fast_mmio_entries ) + d->arch.paging.shadow.has_fast_mmio_entries = 1; goto done; } diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index 94791f7a80..6c88e5abb0 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -79,6 +79,9 @@ struct shadow_domain { struct shadow_page_info **hash_table; int hash_walking; /* Some function is walking the hash table */ + /* Fast MMIO path heuristic */ + int has_fast_mmio_entries; + /* Shadow log-dirty bitmap */ unsigned long *dirty_bitmap; unsigned int dirty_bitmap_size; /* in pages, bit per page */ From a63bbc175b396bfe048d0f13197416ee6c2b8b36 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Mon, 12 Mar 2007 10:10:42 +0000 Subject: [PATCH 055/170] [HVM] Remove debugging printout of BIOS boot vector Signed-off-by: Tim Deegan --- tools/firmware/rombios/rombios.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/firmware/rombios/rombios.c b/tools/firmware/rombios/rombios.c index 7b6ef8062d..c8fbb92ab1 100644 --- a/tools/firmware/rombios/rombios.c +++ b/tools/firmware/rombios/rombios.c @@ -7792,10 +7792,11 @@ ASM_END bootdrv = (Bit8u)(status>>8); bootseg = read_word(ebda_seg,&EbdaData->cdemu.load_segment); - /* Canonicalize bootseg:bootip */ #if BX_TCGBIOS tcpa_add_bootdevice((Bit32u)1L, (Bit32u)0L); #endif + + /* Canonicalize bootseg:bootip */ bootip = (bootseg & 0x0fff) << 4; bootseg &= 0xf000; break; @@ -7812,8 +7813,6 @@ ASM_END #if BX_TCGBIOS tcpa_ipl((Bit32u)bootseg); /* specs: 8.2.3 steps 4 and 5 */ #endif - /* Debugging info */ - printf("Booting from %x:%x\n", bootseg, bootip); /* Jump to the boot vector */ ASM_START From d5788925b0b4576b614a7d16effc0fa4a67d28db Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Mon, 12 Mar 2007 11:00:44 +0000 Subject: [PATCH 056/170] xen: Fix emulator to use default segment SS for ESP/EBP references. Signed-off-by: Keir Fraser --- xen/arch/x86/x86_emulate.c | 74 ++++++++++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 19 deletions(-) diff --git a/xen/arch/x86/x86_emulate.c b/xen/arch/x86/x86_emulate.c index ac209cb61d..aecb36cf78 100644 --- a/xen/arch/x86/x86_emulate.c +++ b/xen/arch/x86/x86_emulate.c @@ -726,7 +726,7 @@ x86_emulate( uint8_t modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0; unsigned int op_bytes, def_op_bytes, ad_bytes, def_ad_bytes; unsigned int lock_prefix = 0, rep_prefix = 0; - int rc = X86EMUL_OKAY; + int override_seg = -1, rc = X86EMUL_OKAY; struct operand src, dst; /* Data operand effective address (usually computed from ModRM). */ @@ -758,22 +758,22 @@ x86_emulate( ad_bytes = def_ad_bytes ^ (mode_64bit() ? 12 : 6); break; case 0x2e: /* CS override */ - ea.mem.seg = x86_seg_cs; + override_seg = x86_seg_cs; break; case 0x3e: /* DS override */ - ea.mem.seg = x86_seg_ds; + override_seg = x86_seg_ds; break; case 0x26: /* ES override */ - ea.mem.seg = x86_seg_es; + override_seg = x86_seg_es; break; case 0x64: /* FS override */ - ea.mem.seg = x86_seg_fs; + override_seg = x86_seg_fs; break; case 0x65: /* GS override */ - ea.mem.seg = x86_seg_gs; + override_seg = x86_seg_gs; break; case 0x36: /* SS override */ - ea.mem.seg = x86_seg_ss; + override_seg = x86_seg_ss; break; case 0xf0: /* LOCK */ lock_prefix = 1; @@ -839,14 +839,35 @@ x86_emulate( /* 16-bit ModR/M decode. */ switch ( modrm_rm ) { - case 0: ea.mem.off = _regs.ebx + _regs.esi; break; - case 1: ea.mem.off = _regs.ebx + _regs.edi; break; - case 2: ea.mem.off = _regs.ebp + _regs.esi; break; - case 3: ea.mem.off = _regs.ebp + _regs.edi; break; - case 4: ea.mem.off = _regs.esi; break; - case 5: ea.mem.off = _regs.edi; break; - case 6: ea.mem.off = _regs.ebp; break; - case 7: ea.mem.off = _regs.ebx; break; + case 0: + ea.mem.off = _regs.ebx + _regs.esi; + break; + case 1: + ea.mem.off = _regs.ebx + _regs.edi; + break; + case 2: + ea.mem.seg = x86_seg_ss; + ea.mem.off = _regs.ebp + _regs.esi; + break; + case 3: + ea.mem.seg = x86_seg_ss; + ea.mem.off = _regs.ebp + _regs.edi; + break; + case 4: + ea.mem.off = _regs.esi; + break; + case 5: + ea.mem.off = _regs.edi; + break; + case 6: + if ( modrm_mod == 0 ) + break; + ea.mem.seg = x86_seg_ss; + ea.mem.off = _regs.ebp; + break; + case 7: + ea.mem.off = _regs.ebx; + break; } switch ( modrm_mod ) { @@ -876,10 +897,20 @@ x86_emulate( ea.mem.off <<= (sib >> 6) & 3; if ( (modrm_mod == 0) && ((sib_base & 7) == 5) ) ea.mem.off += insn_fetch_type(int32_t); - else if ( (sib_base == 4) && !twobyte && (b == 0x8f) ) - /* POP must have its EA calculated post increment. */ - ea.mem.off += _regs.esp + - ((mode_64bit() && (op_bytes == 4)) ? 8 : op_bytes); + else if ( sib_base == 4 ) + { + ea.mem.seg = x86_seg_ss; + ea.mem.off += _regs.esp; + if ( !twobyte && (b == 0x8f) ) + /* POP computes its EA post increment. */ + ea.mem.off += ((mode_64bit() && (op_bytes == 4)) + ? 8 : op_bytes); + } + else if ( sib_base == 5 ) + { + ea.mem.seg = x86_seg_ss; + ea.mem.off += _regs.ebp; + } else ea.mem.off += *(long*)decode_register(sib_base, &_regs, 0); } @@ -887,6 +918,8 @@ x86_emulate( { modrm_rm |= (rex_prefix & 1) << 3; ea.mem.off = *(long *)decode_register(modrm_rm, &_regs, 0); + if ( (modrm_rm == 5) && (modrm_mod != 0) ) + ea.mem.seg = x86_seg_ss; } switch ( modrm_mod ) { @@ -920,6 +953,9 @@ x86_emulate( } } + if ( override_seg != -1 ) + ea.mem.seg = override_seg; + /* Special instructions do their own operand decoding. */ if ( (d & DstMask) == ImplicitOps ) goto special_insn; From aca8807ff0b3134ec444ac0ff1c59cc0ec91a5cf Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Mon, 12 Mar 2007 11:03:07 +0000 Subject: [PATCH 057/170] Fix valid_phys_addr_range() prototype of xen /dev/mem. The second argument is size_t, not size_t *. Signed-off-by: Isaku Yamahata --- linux-2.6-xen-sparse/drivers/xen/char/mem.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/char/mem.c b/linux-2.6-xen-sparse/drivers/xen/char/mem.c index 4fba735afa..7e857b222e 100644 --- a/linux-2.6-xen-sparse/drivers/xen/char/mem.c +++ b/linux-2.6-xen-sparse/drivers/xen/char/mem.c @@ -27,7 +27,7 @@ #include #ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE -static inline int valid_phys_addr_range(unsigned long addr, size_t *count) +static inline int valid_phys_addr_range(unsigned long addr, size_t count) { return 1; } @@ -44,7 +44,7 @@ static ssize_t read_mem(struct file * file, char __user * buf, ssize_t read = 0, sz; void __iomem *v; - if (!valid_phys_addr_range(p, &count)) + if (!valid_phys_addr_range(p, count)) return -EFAULT; while (count > 0) { @@ -95,7 +95,7 @@ static ssize_t write_mem(struct file * file, const char __user * buf, ssize_t written = 0, sz; void __iomem *v; - if (!valid_phys_addr_range(p, &count)) + if (!valid_phys_addr_range(p, count)) return -EFAULT; while (count > 0) { From e260cd0a071fa16057f0e348f026e9a2f736bb3e Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Mon, 12 Mar 2007 11:04:34 +0000 Subject: [PATCH 058/170] The Xen console intercepts ^O and prevents it from propagating through to the guest. However, ^O is a useful key in bash and in Emacs. This patch changes the console to pass a single ^O through to the guest when it is pressed twice. Signed-off-by: Ben Pfaff --- linux-2.6-xen-sparse/drivers/xen/console/console.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/console/console.c b/linux-2.6-xen-sparse/drivers/xen/console/console.c index 78fbc79940..1053ef8ff1 100644 --- a/linux-2.6-xen-sparse/drivers/xen/console/console.c +++ b/linux-2.6-xen-sparse/drivers/xen/console/console.c @@ -348,8 +348,11 @@ void xencons_rx(char *buf, unsigned len, struct pt_regs *regs) #ifdef CONFIG_MAGIC_SYSRQ if (sysrq_enabled) { if (buf[i] == '\x0f') { /* ^O */ - sysrq_requested = jiffies; - continue; /* don't print the sysrq key */ + if (!sysrq_requested) { + sysrq_requested = jiffies; + continue; /* don't print sysrq key */ + } + sysrq_requested = 0; } else if (sysrq_requested) { unsigned long sysrq_timeout = sysrq_requested + HZ*2; From 506e6d7f5363ba691f81b65294c07061e48524c5 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Mon, 12 Mar 2007 11:15:56 +0000 Subject: [PATCH 059/170] AMD HVM: Exit hvmloader via a normal jump-to-realmode code sequence. Strip out all SVM-special hypercall code. Signed-off-by: Keir Fraser --- tools/firmware/hvmloader/hvmloader.c | 71 ++++++++++++++------------- xen/arch/x86/hvm/svm/svm.c | 69 +++----------------------- xen/include/asm-x86/hvm/svm/vmmcall.h | 44 ----------------- 3 files changed, 45 insertions(+), 139 deletions(-) delete mode 100644 xen/include/asm-x86/hvm/svm/vmmcall.h diff --git a/tools/firmware/hvmloader/hvmloader.c b/tools/firmware/hvmloader/hvmloader.c index bed26597ca..6b75303477 100644 --- a/tools/firmware/hvmloader/hvmloader.c +++ b/tools/firmware/hvmloader/hvmloader.c @@ -38,23 +38,47 @@ #define VMXASSIST_PHYSICAL_ADDRESS 0x000D0000 #define ROMBIOS_PHYSICAL_ADDRESS 0x000F0000 -/* invoke SVM's paged realmode support */ -#define SVM_VMMCALL_RESET_TO_REALMODE 0x80000001 - -/* - * C runtime start off - */ asm( " .text \n" " .globl _start \n" "_start: \n" + /* C runtime kickoff. */ " cld \n" " cli \n" - " lgdt gdt_desr \n" - " movl $stack_top, %esp \n" - " movl %esp, %ebp \n" + " movl $stack_top,%esp \n" + " movl %esp,%ebp \n" " call main \n" - " ud2 \n" + /* Relocate real-mode trampoline to 0x0. */ + " mov $trampoline_start,%esi \n" + " xor %edi,%edi \n" + " mov $trampoline_end,%ecx \n" + " sub %esi,%ecx \n" + " rep movsb \n" + /* Load real-mode compatible segment state (base 0x0000, limit 0xffff). */ + " lgdt gdt_desr \n" + " mov $0x0010,%ax \n" + " mov %ax,%ds \n" + " mov %ax,%es \n" + " mov %ax,%fs \n" + " mov %ax,%gs \n" + " mov %ax,%ss \n" + " ljmp $0x8,$0x0 \n" + /* Enter real mode, reload all segment registers and IDT. */ + "trampoline_start: .code16 \n" + " mov %cr0,%eax \n" + " and $0xfe,%al \n" + " mov %eax,%cr0 \n" + " ljmp $0,$1f-trampoline_start\n" + "1: xor %ax,%ax \n" + " mov %ax,%ds \n" + " mov %ax,%es \n" + " mov %ax,%fs \n" + " mov %ax,%gs \n" + " mov %ax,%ss \n" + " lidt 1f-trampoline_start \n" + " ljmp $0xf000,$0xfff0 \n" + "1: .word 0x3ff,0,0 \n" + "trampoline_end: .code32 \n" " \n" "gdt_desr: \n" " .word gdt_end - gdt - 1 \n" @@ -63,8 +87,8 @@ asm( " .align 8 \n" "gdt: \n" " .quad 0x0000000000000000 \n" - " .quad 0x00CF92000000FFFF \n" - " .quad 0x00CF9A000000FFFF \n" + " .quad 0x00009a000000ffff \n" /* Ring 0 code, base 0 limit 0xffff */ + " .quad 0x000092000000ffff \n" /* Ring 0 data, base 0 limit 0xffff */ "gdt_end: \n" " \n" " .bss \n" @@ -83,19 +107,6 @@ cirrus_check(void) return inb(0x3C5) == 0x12; } -static int -vmmcall(int function, int edi, int esi, int edx, int ecx, int ebx) -{ - int eax; - - __asm__ __volatile__ ( - ".byte 0x0F,0x01,0xD9" - : "=a" (eax) - : "a"(function), - "b"(ebx), "c"(ecx), "d"(edx), "D"(edi), "S"(esi) ); - return eax; -} - static int check_amd(void) { @@ -349,13 +360,7 @@ int main(void) ASSERT((ACPI_PHYSICAL_ADDRESS + acpi_sz) <= 0xF0000); } - if ( check_amd() ) - { - /* AMD implies this is SVM */ - printf("SVM go ...\n"); - vmmcall(SVM_VMMCALL_RESET_TO_REALMODE, 0, 0, 0, 0, 0); - } - else + if ( !check_amd() ) { printf("Loading VMXAssist ...\n"); memcpy((void *)VMXASSIST_PHYSICAL_ADDRESS, @@ -368,7 +373,7 @@ int main(void) ); } - printf("Failed to invoke ROMBIOS\n"); + printf("Invoking ROMBIOS ...\n"); return 0; } diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index 0766ca5de2..c6faddcd95 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -2591,65 +2590,6 @@ static int svm_do_vmmcall_reset_to_realmode(struct vcpu *v, } -/* - * svm_do_vmmcall - SVM VMMCALL handler - * - * returns 0 on success, non-zero otherwise - */ -static int svm_do_vmmcall(struct vcpu *v, struct cpu_user_regs *regs) -{ - struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - int inst_len; - - ASSERT(vmcb); - ASSERT(regs); - - inst_len = __get_instruction_length(v, INSTR_VMCALL, NULL); - ASSERT(inst_len > 0); - - HVMTRACE_1D(VMMCALL, v, regs->eax); - - if ( regs->eax & 0x80000000 ) - { - /* VMMCALL sanity check */ - if ( vmcb->cpl > get_vmmcall_cpl(regs->edi) ) - { - printk("VMMCALL CPL check failed\n"); - return -1; - } - - /* handle the request */ - switch ( regs->eax ) - { - case VMMCALL_RESET_TO_REALMODE: - if ( svm_do_vmmcall_reset_to_realmode(v, regs) ) - { - printk("svm_do_vmmcall_reset_to_realmode() failed\n"); - return -1; - } - /* since we just reset the VMCB, return without adjusting - * the eip */ - return 0; - - case VMMCALL_DEBUG: - printk("DEBUG features not implemented yet\n"); - break; - default: - break; - } - - hvm_print_line(v, regs->eax); /* provides the current domain */ - } - else - { - hvm_do_hypercall(regs); - } - - __update_guest_eip(vmcb, inst_len); - return 0; -} - - void svm_dump_inst(unsigned long eip) { u8 opcode[256]; @@ -3152,9 +3092,14 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs) svm_handle_invlpg(1, regs); break; - case VMEXIT_VMMCALL: - svm_do_vmmcall(v, regs); + case VMEXIT_VMMCALL: { + int inst_len = __get_instruction_length(v, INSTR_VMCALL, NULL); + ASSERT(inst_len > 0); + HVMTRACE_1D(VMMCALL, v, regs->eax); + __update_guest_eip(vmcb, inst_len); + hvm_do_hypercall(regs); break; + } case VMEXIT_CR0_READ: svm_cr_access(v, 0, TYPE_MOV_FROM_CR, regs); diff --git a/xen/include/asm-x86/hvm/svm/vmmcall.h b/xen/include/asm-x86/hvm/svm/vmmcall.h deleted file mode 100644 index 7587bab7c6..0000000000 --- a/xen/include/asm-x86/hvm/svm/vmmcall.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * vmmcall.h: VMMCALL instruction support - * - * Travis Betak, travis.betak@amd.com - * Copyright (c) 2005, AMD Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place - Suite 330, Boston, MA 02111-1307 USA. - * - */ - -#ifndef __ASM_X86_HVM_SVM_VMMCALL_H__ -#define __ASM_X86_HVM_SVM_VMMCALL_H__ - -/* VMMCALL command fields */ -#define VMMCALL_CODE_CPL_MASK 0x60000000 -#define VMMCALL_CODE_MBZ_MASK 0x1FFF0000 -#define VMMCALL_CODE_COMMAND_MASK 0x0000FFFF - -#define MAKE_VMMCALL_CODE(cpl,func) ((cpl << 29) | (func) | 0x80000000) - -/* CPL=0 VMMCALL Requests */ -#define VMMCALL_RESET_TO_REALMODE MAKE_VMMCALL_CODE(0,1) - -/* CPL=3 VMMCALL Requests */ -#define VMMCALL_DEBUG MAKE_VMMCALL_CODE(3,1) - -/* return the cpl required for the vmmcall cmd */ -static inline int get_vmmcall_cpl(int cmd) -{ - return (cmd & VMMCALL_CODE_CPL_MASK) >> 29; -} - -#endif /* __ASM_X86_HVM_SVM_VMMCALL_H__ */ From d5cbf3ec5835084badcad2e36d03fb4b30478e08 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Mon, 12 Mar 2007 13:53:43 +0000 Subject: [PATCH 060/170] x86: Add VGCF_onlien flag to vcpu_guest_context. Change common Xen code to start all VCPUs (except idle ones) offline. Change arch code to deal with this. Signed-off-by: Keir Fraser --- tools/libxc/xc_dom_x86.c | 4 ++-- tools/libxc/xc_hvm_build.c | 8 +++++++- tools/libxc/xc_linux_restore.c | 5 +++++ xen/arch/ia64/xen/domain.c | 8 ++++++-- xen/arch/powerpc/domain.c | 5 ++++- xen/arch/powerpc/domain_build.c | 1 + xen/arch/x86/domain.c | 7 ++++++- xen/arch/x86/domain_build.c | 1 + xen/common/domain.c | 2 +- xen/common/domctl.c | 18 +++++++----------- xen/include/public/arch-x86/xen.h | 2 ++ xen/include/public/foreign/structs.py | 2 ++ 12 files changed, 44 insertions(+), 19 deletions(-) diff --git a/tools/libxc/xc_dom_x86.c b/tools/libxc/xc_dom_x86.c index 19296daf10..a508775140 100644 --- a/tools/libxc/xc_dom_x86.c +++ b/tools/libxc/xc_dom_x86.c @@ -455,7 +455,7 @@ static int vcpu_x86_32(struct xc_dom_image *dom, void *ptr) ctxt->kernel_ss = ctxt->user_regs.ss; ctxt->kernel_sp = ctxt->user_regs.esp; - ctxt->flags = VGCF_in_kernel_X86_32; + ctxt->flags = VGCF_in_kernel_X86_32 | VGCF_online_X86_32; if ( dom->parms.pae == 2 /* extended_cr3 */ || dom->parms.pae == 3 /* bimodal */ ) ctxt->vm_assist |= (1UL << VMASST_TYPE_pae_extended_cr3); @@ -494,7 +494,7 @@ static int vcpu_x86_64(struct xc_dom_image *dom, void *ptr) ctxt->kernel_ss = ctxt->user_regs.ss; ctxt->kernel_sp = ctxt->user_regs.esp; - ctxt->flags = VGCF_in_kernel_X86_64; + ctxt->flags = VGCF_in_kernel_X86_64 | VGCF_online_X86_64; cr3_pfn = xc_dom_p2m_guest(dom, dom->pgtables_seg.pfn); ctxt->ctrlreg[3] = xen_pfn_to_cr3_x86_64(cr3_pfn); xc_dom_printf("%s: cr3: pfn 0x%" PRIpfn " mfn 0x%" PRIpfn "\n", diff --git a/tools/libxc/xc_hvm_build.c b/tools/libxc/xc_hvm_build.c index 2238d315bc..00f4624501 100644 --- a/tools/libxc/xc_hvm_build.c +++ b/tools/libxc/xc_hvm_build.c @@ -302,9 +302,15 @@ static int setup_guest(int xc_handle, /* Set [er]ip in the way that's right for Xen */ if ( strstr(caps, "x86_64") ) + { ctxt->c64.user_regs.rip = elf_uval(&elf, elf.ehdr, e_entry); + ctxt->c64.flags = VGCF_online; + } else + { ctxt->c32.user_regs.eip = elf_uval(&elf, elf.ehdr, e_entry); + ctxt->c32.flags = VGCF_online; + } return 0; @@ -344,7 +350,7 @@ static int xc_hvm_build_internal(int xc_handle, memset(&launch_domctl, 0, sizeof(launch_domctl)); launch_domctl.domain = (domid_t)domid; - launch_domctl.u.vcpucontext.vcpu = 0; + launch_domctl.u.vcpucontext.vcpu = 0; set_xen_guest_handle(launch_domctl.u.vcpucontext.ctxt, &ctxt.c); launch_domctl.cmd = XEN_DOMCTL_setvcpucontext; rc = xc_domctl(xc_handle, &launch_domctl); diff --git a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c index 6fa0388d3f..d3a87262a0 100644 --- a/tools/libxc/xc_linux_restore.c +++ b/tools/libxc/xc_linux_restore.c @@ -189,6 +189,7 @@ int xc_linux_restore(int xc_handle, int io_fd, uint64_t vcpumap = 1ULL; unsigned int max_vcpu_id = 0; + int new_ctxt_format = 0; max_pfn = nr_pfns; @@ -372,6 +373,7 @@ int xc_linux_restore(int xc_handle, int io_fd, } if (j == -2) { + new_ctxt_format = 1; if (!read_exact(io_fd, &max_vcpu_id, sizeof(int)) || (max_vcpu_id >= 64) || !read_exact(io_fd, &vcpumap, sizeof(uint64_t))) { @@ -797,6 +799,9 @@ int xc_linux_restore(int xc_handle, int io_fd, goto out; } + if ( !new_ctxt_format ) + ctxt.flags |= VGCF_online; + if (i == 0) { /* * Uncanonicalise the suspend-record frame number and poke diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index 631d8dfa09..2bb2ef8172 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -672,8 +672,11 @@ int arch_set_info_guest(struct vcpu *v, vcpu_guest_context_u c) /* This overrides some registers. */ vcpu_init_regs(v); - /* Don't redo final setup */ - set_bit(_VCPUF_initialised, &v->vcpu_flags); + /* Don't redo final setup. Auto-online VCPU0. */ + if (!test_and_set_bit(_VCPUF_initialised, &v->vcpu_flags) && + (v->vcpu_id == 0)) + clear_bit(_VCPUF_down, &v->vcpu_flags); + return 0; } @@ -1182,6 +1185,7 @@ int construct_dom0(struct domain *d, printk("Dom0: 0x%lx\n", (u64)dom0); set_bit(_VCPUF_initialised, &v->vcpu_flags); + clear_bit(_VCPUF_down, &v->vcpu_flags); /* Build firmware. Note: Linux kernel reserve memory used by start_info, so there is diff --git a/xen/arch/powerpc/domain.c b/xen/arch/powerpc/domain.c index 156b70ffd9..1ecf35a666 100644 --- a/xen/arch/powerpc/domain.c +++ b/xen/arch/powerpc/domain.c @@ -168,7 +168,10 @@ int arch_set_info_guest(struct vcpu *v, vcpu_guest_context_u c) d->shared_info->wc_nsec = dom0->shared_info->wc_nsec; d->shared_info->arch.boot_timebase = dom0->shared_info->arch.boot_timebase; - set_bit(_VCPUF_initialised, &v->vcpu_flags); + /* Auto-online VCPU0 when it is initialised. */ + if ( !test_and_set_bit(_VCPUF_initialised, &v->vcpu_flags) && + (v->vcpu_id == 0) ) + clear_bit(_VCPUF_down, &v->vcpu_flags); cpu_init_vcpu(v); diff --git a/xen/arch/powerpc/domain_build.c b/xen/arch/powerpc/domain_build.c index 08d53ff9dc..af7ad3db45 100644 --- a/xen/arch/powerpc/domain_build.c +++ b/xen/arch/powerpc/domain_build.c @@ -274,6 +274,7 @@ int construct_dom0(struct domain *d, ofd_dom0_fixup(d, *ofh_tree + rma, cmdline, shared_info_addr); set_bit(_VCPUF_initialised, &v->vcpu_flags); + clear_bit(_VCPUF_down, &v->vcpu_flags); rc = 0; diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 2d6bdca72c..ca82c12590 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -601,7 +601,7 @@ int arch_set_info_guest( } if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) ) - return 0; + goto out; memset(v->arch.guest_context.debugreg, 0, sizeof(v->arch.guest_context.debugreg)); @@ -706,6 +706,11 @@ int arch_set_info_guest( update_cr3(v); + out: + if ( flags & VGCF_online ) + clear_bit(_VCPUF_down, &v->vcpu_flags); + else + set_bit(_VCPUF_down, &v->vcpu_flags); return 0; #undef c } diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c index 5d7941ab5d..96215da601 100644 --- a/xen/arch/x86/domain_build.c +++ b/xen/arch/x86/domain_build.c @@ -902,6 +902,7 @@ int construct_dom0(struct domain *d, update_domain_wallclock_time(d); set_bit(_VCPUF_initialised, &v->vcpu_flags); + clear_bit(_VCPUF_down, &v->vcpu_flags); /* * Initial register values: diff --git a/xen/common/domain.c b/xen/common/domain.c index 57fb9ade71..3008a4cc90 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -102,7 +102,7 @@ struct vcpu *alloc_vcpu( v->runstate.state = is_idle_vcpu(v) ? RUNSTATE_running : RUNSTATE_offline; v->runstate.state_entry_time = NOW(); - if ( (vcpu_id != 0) && !is_idle_domain(d) ) + if ( !is_idle_domain(d) ) set_bit(_VCPUF_down, &v->vcpu_flags); if ( sched_init_vcpu(v, cpu_id) != 0 ) diff --git a/xen/common/domctl.c b/xen/common/domctl.c index 3a45586d65..6f2f351895 100644 --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -268,18 +268,14 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl) case XEN_DOMCTL_unpausedomain: { struct domain *d = rcu_lock_domain_by_id(op->domain); + ret = -ESRCH; - if ( d != NULL ) - { - ret = -EINVAL; - if ( (d != current->domain) && (d->vcpu[0] != NULL) && - test_bit(_VCPUF_initialised, &d->vcpu[0]->vcpu_flags) ) - { - domain_unpause_by_systemcontroller(d); - ret = 0; - } - rcu_unlock_domain(d); - } + if ( d == NULL ) + break; + + domain_unpause_by_systemcontroller(d); + rcu_unlock_domain(d); + ret = 0; } break; diff --git a/xen/include/public/arch-x86/xen.h b/xen/include/public/arch-x86/xen.h index f927130058..9fe0b76204 100644 --- a/xen/include/public/arch-x86/xen.h +++ b/xen/include/public/arch-x86/xen.h @@ -126,6 +126,8 @@ struct vcpu_guest_context { #define VGCF_failsafe_disables_events (1<<_VGCF_failsafe_disables_events) #define _VGCF_syscall_disables_events 4 #define VGCF_syscall_disables_events (1<<_VGCF_syscall_disables_events) +#define _VGCF_online 5 +#define VGCF_online (1<<_VGCF_online) unsigned long flags; /* VGCF_* flags */ struct cpu_user_regs user_regs; /* User-level CPU registers */ struct trap_info trap_ctxt[256]; /* Virtual IDT */ diff --git a/xen/include/public/foreign/structs.py b/xen/include/public/foreign/structs.py index 79eeab3b8e..6ecd1aa3dd 100644 --- a/xen/include/public/foreign/structs.py +++ b/xen/include/public/foreign/structs.py @@ -41,6 +41,8 @@ defines = [ "__i386__", "VGCF_failsafe_disables_events", "_VGCF_syscall_disables_events", "VGCF_syscall_disables_events", + "_VGCF_online", + "VGCF_online", # ia64 "VGCF_EXTRA_REGS", From a74bec1b38e68548d15db060457186049f3c9e5d Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Mon, 12 Mar 2007 14:11:07 +0000 Subject: [PATCH 061/170] xen: Set VGCF_online flag appropriately for getvcpucontext. Signed-off-by: Keir Fraser --- xen/arch/x86/domctl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index 00bb202d57..503b0000c7 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -450,6 +450,8 @@ void arch_get_info_guest(struct vcpu *v, vcpu_guest_context_u c) c(flags &= ~(VGCF_i387_valid|VGCF_in_kernel)); if ( test_bit(_VCPUF_fpu_initialised, &v->vcpu_flags) ) c(flags |= VGCF_i387_valid); + if ( !test_bit(_VCPUF_down, &v->vcpu_flags) ) + c(flags |= VGCF_online); if ( is_hvm_vcpu(v) ) { From 415ecbe777c95d1e076286af0485f758725d0033 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Mon, 12 Mar 2007 14:11:43 +0000 Subject: [PATCH 062/170] linux: No need to manually bring VCPUs online across 'fast' save/restore. Signed-off-by: Keir Fraser --- .../drivers/xen/core/machine_reboot.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c b/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c index 1110e62888..6f6ac97195 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c @@ -84,7 +84,7 @@ static void post_suspend(int suspend_cancelled) pfn_to_mfn(xen_start_info->console.domU.mfn); } else { #ifdef CONFIG_SMP - cpu_initialized_map = cpumask_of_cpu(0); + cpu_initialized_map = cpu_online_map; #endif } @@ -180,20 +180,6 @@ static int take_machine_down(void *p_fast_suspend) time_resume(); local_irq_enable(); - if (fast_suspend && !suspend_cancelled) { - /* - * In fast-suspend mode the APs may not be brought back online - * when we resume. In that case we do it here. - */ - for_each_online_cpu(cpu) { - if (cpu == 0) - continue; - cpu_set_initialized(cpu); - err = HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL); - BUG_ON(err); - } - } - return suspend_cancelled; } From 363f33fde24747a40a2682a155a6aeaafcbcf911 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Mon, 12 Mar 2007 14:47:00 +0000 Subject: [PATCH 063/170] x86: PAE linear page tables. While full linear page table support makes little sense (and would be more complicated to implement), partial linear page table support is almost identical to that in non-PAE, and is used (at least) by NetWare. Signed-off-by: Jan Beulich --- xen/arch/x86/domain.c | 28 ++++++++---- xen/arch/x86/mm.c | 100 +++++++++++++++++++++++------------------- 2 files changed, 74 insertions(+), 54 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index ca82c12590..6a543a3a1b 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -1386,7 +1386,8 @@ int hypercall_xlat_continuation(unsigned int *id, unsigned int mask, ...) } #endif -static void relinquish_memory(struct domain *d, struct list_head *list) +static void relinquish_memory(struct domain *d, struct list_head *list, + unsigned long type) { struct list_head *ent; struct page_info *page; @@ -1415,23 +1416,24 @@ static void relinquish_memory(struct domain *d, struct list_head *list) put_page(page); /* - * Forcibly invalidate base page tables at this point to break circular - * 'linear page table' references. This is okay because MMU structures - * are not shared across domains and this domain is now dead. Thus base - * tables are not in use so a non-zero count means circular reference. + * Forcibly invalidate top-most, still valid page tables at this point + * to break circular 'linear page table' references. This is okay + * because MMU structures are not shared across domains and this domain + * is now dead. Thus top-most valid tables are not in use so a non-zero + * count means circular reference. */ y = page->u.inuse.type_info; for ( ; ; ) { x = y; if ( likely((x & (PGT_type_mask|PGT_validated)) != - (PGT_base_page_table|PGT_validated)) ) + (type|PGT_validated)) ) break; y = cmpxchg(&page->u.inuse.type_info, x, x & ~PGT_validated); if ( likely(y == x) ) { - free_page_type(page, PGT_base_page_table); + free_page_type(page, type); break; } } @@ -1529,8 +1531,16 @@ void domain_relinquish_resources(struct domain *d) destroy_gdt(v); /* Relinquish every page of memory. */ - relinquish_memory(d, &d->xenpage_list); - relinquish_memory(d, &d->page_list); +#if CONFIG_PAGING_LEVELS >= 4 + relinquish_memory(d, &d->xenpage_list, PGT_l4_page_table); + relinquish_memory(d, &d->page_list, PGT_l4_page_table); +#endif +#if CONFIG_PAGING_LEVELS >= 3 + relinquish_memory(d, &d->xenpage_list, PGT_l3_page_table); + relinquish_memory(d, &d->page_list, PGT_l3_page_table); +#endif + relinquish_memory(d, &d->xenpage_list, PGT_l2_page_table); + relinquish_memory(d, &d->page_list, PGT_l2_page_table); /* Free page used by xen oprofile buffer */ free_xenoprof_pages(d); diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 81bea072c5..1bbff2293d 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -517,7 +517,6 @@ static int get_page_and_type_from_pagenr(unsigned long page_nr, return 1; } -#ifndef CONFIG_X86_PAE /* We do not support guest linear mappings on PAE. */ /* * We allow root tables to map each other (a.k.a. linear page tables). It * needs some special care with reference counts and access permissions: @@ -530,48 +529,54 @@ static int get_page_and_type_from_pagenr(unsigned long page_nr, * frame if it is mapped by a different root table. This is sufficient and * also necessary to allow validation of a root table mapping itself. */ -static int -get_linear_pagetable( - root_pgentry_t re, unsigned long re_pfn, struct domain *d) -{ - unsigned long x, y; - struct page_info *page; - unsigned long pfn; - - if ( (root_get_flags(re) & _PAGE_RW) ) - { - MEM_LOG("Attempt to create linear p.t. with write perms"); - return 0; - } - - if ( (pfn = root_get_pfn(re)) != re_pfn ) - { - /* Make sure the mapped frame belongs to the correct domain. */ - if ( unlikely(!get_page_from_pagenr(pfn, d)) ) - return 0; - - /* - * Make sure that the mapped frame is an already-validated L2 table. - * If so, atomically increment the count (checking for overflow). - */ - page = mfn_to_page(pfn); - y = page->u.inuse.type_info; - do { - x = y; - if ( unlikely((x & PGT_count_mask) == PGT_count_mask) || - unlikely((x & (PGT_type_mask|PGT_validated)) != - (PGT_root_page_table|PGT_validated)) ) - { - put_page(page); - return 0; - } - } - while ( (y = cmpxchg(&page->u.inuse.type_info, x, x + 1)) != x ); - } - - return 1; +#define define_get_linear_pagetable(name1, name2) \ +static int \ +get_##name1##_linear_pagetable( \ + name1##_pgentry_t pde, unsigned long pde_pfn, struct domain *d) \ +{ \ + unsigned long x, y; \ + struct page_info *page; \ + unsigned long pfn; \ + \ + if ( (name2##_get_flags(pde) & _PAGE_RW) ) \ + { \ + MEM_LOG("Attempt to create linear p.t. with write perms"); \ + return 0; \ + } \ + \ + if ( (pfn = name2##_get_pfn(pde)) != pde_pfn ) \ + { \ + /* Make sure the mapped frame belongs to the correct domain. */ \ + if ( unlikely(!get_page_from_pagenr(pfn, d)) ) \ + return 0; \ + \ + /* \ + * Ensure that the mapped frame is an already-validated page table. \ + * If so, atomically increment the count (checking for overflow). \ + */ \ + page = mfn_to_page(pfn); \ + y = page->u.inuse.type_info; \ + do { \ + x = y; \ + if ( unlikely((x & PGT_count_mask) == PGT_count_mask) || \ + unlikely((x & (PGT_type_mask|PGT_validated)) != \ + (PGT_##name1##_page_table|PGT_validated)) ) \ + { \ + put_page(page); \ + return 0; \ + } \ + } \ + while ( (y = cmpxchg(&page->u.inuse.type_info, x, x + 1)) != x ); \ + } \ + \ + return 1; \ } -#endif /* !CONFIG_X86_PAE */ +#if !defined(CONFIG_X86_PAE) +define_get_linear_pagetable(root,root) +#endif +#if defined(CONFIG_X86_PAE) || defined(CONFIG_X86_64) +define_get_linear_pagetable(l2,l2e) +#endif int get_page_from_l1e( @@ -649,10 +654,15 @@ get_page_from_l2e( } rc = get_page_and_type_from_pagenr(l2e_get_pfn(l2e), PGT_l1_page_table, d); -#if CONFIG_PAGING_LEVELS == 2 if ( unlikely(!rc) ) - rc = get_linear_pagetable(l2e, pfn, d); + { +#if CONFIG_PAGING_LEVELS == 2 + rc = get_root_linear_pagetable(l2e, pfn, d); +#else + rc = get_l2_linear_pagetable(l2e, pfn, d); #endif + } + return rc; } @@ -697,7 +707,7 @@ get_page_from_l4e( rc = get_page_and_type_from_pagenr(l4e_get_pfn(l4e), PGT_l3_page_table, d); if ( unlikely(!rc) ) - rc = get_linear_pagetable(l4e, pfn, d); + rc = get_root_linear_pagetable(l4e, pfn, d); return rc; } From d96438b30afa38bd08982b09b4ba03c13e1d078b Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Mon, 12 Mar 2007 14:52:11 +0000 Subject: [PATCH 064/170] xen: Generic linear pagetable support for x86 PV guests. Any linear mapping is permitted, except for L3-PAE-maps-L3-PAE, which makes no sense even on native. Signed-off-by: Keir Fraser --- xen/arch/x86/mm.c | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 1bbff2293d..b37ade4cb3 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -529,22 +529,22 @@ static int get_page_and_type_from_pagenr(unsigned long page_nr, * frame if it is mapped by a different root table. This is sufficient and * also necessary to allow validation of a root table mapping itself. */ -#define define_get_linear_pagetable(name1, name2) \ +#define define_get_linear_pagetable(level) \ static int \ -get_##name1##_linear_pagetable( \ - name1##_pgentry_t pde, unsigned long pde_pfn, struct domain *d) \ +get_##level##_linear_pagetable( \ + level##_pgentry_t pde, unsigned long pde_pfn, struct domain *d) \ { \ unsigned long x, y; \ struct page_info *page; \ unsigned long pfn; \ \ - if ( (name2##_get_flags(pde) & _PAGE_RW) ) \ + if ( (level##e_get_flags(pde) & _PAGE_RW) ) \ { \ MEM_LOG("Attempt to create linear p.t. with write perms"); \ return 0; \ } \ \ - if ( (pfn = name2##_get_pfn(pde)) != pde_pfn ) \ + if ( (pfn = level##e_get_pfn(pde)) != pde_pfn ) \ { \ /* Make sure the mapped frame belongs to the correct domain. */ \ if ( unlikely(!get_page_from_pagenr(pfn, d)) ) \ @@ -560,7 +560,7 @@ get_##name1##_linear_pagetable( \ x = y; \ if ( unlikely((x & PGT_count_mask) == PGT_count_mask) || \ unlikely((x & (PGT_type_mask|PGT_validated)) != \ - (PGT_##name1##_page_table|PGT_validated)) ) \ + (PGT_##level##_page_table|PGT_validated)) ) \ { \ put_page(page); \ return 0; \ @@ -571,12 +571,6 @@ get_##name1##_linear_pagetable( \ \ return 1; \ } -#if !defined(CONFIG_X86_PAE) -define_get_linear_pagetable(root,root) -#endif -#if defined(CONFIG_X86_PAE) || defined(CONFIG_X86_64) -define_get_linear_pagetable(l2,l2e) -#endif int get_page_from_l1e( @@ -638,7 +632,8 @@ get_page_from_l1e( /* NB. Virtual address 'l2e' maps to a machine address within frame 'pfn'. */ -static int +define_get_linear_pagetable(l2); +static int get_page_from_l2e( l2_pgentry_t l2e, unsigned long pfn, struct domain *d) { @@ -655,20 +650,15 @@ get_page_from_l2e( rc = get_page_and_type_from_pagenr(l2e_get_pfn(l2e), PGT_l1_page_table, d); if ( unlikely(!rc) ) - { -#if CONFIG_PAGING_LEVELS == 2 - rc = get_root_linear_pagetable(l2e, pfn, d); -#else rc = get_l2_linear_pagetable(l2e, pfn, d); -#endif - } return rc; } #if CONFIG_PAGING_LEVELS >= 3 -static int +define_get_linear_pagetable(l3); +static int get_page_from_l3e( l3_pgentry_t l3e, unsigned long pfn, struct domain *d) { @@ -684,12 +674,16 @@ get_page_from_l3e( } rc = get_page_and_type_from_pagenr(l3e_get_pfn(l3e), PGT_l2_page_table, d); + if ( unlikely(!rc) ) + rc = get_l3_linear_pagetable(l3e, pfn, d); + return rc; } #endif /* 3 level */ #if CONFIG_PAGING_LEVELS >= 4 -static int +define_get_linear_pagetable(l4); +static int get_page_from_l4e( l4_pgentry_t l4e, unsigned long pfn, struct domain *d) { @@ -705,9 +699,8 @@ get_page_from_l4e( } rc = get_page_and_type_from_pagenr(l4e_get_pfn(l4e), PGT_l3_page_table, d); - if ( unlikely(!rc) ) - rc = get_root_linear_pagetable(l4e, pfn, d); + rc = get_l4_linear_pagetable(l4e, pfn, d); return rc; } From 79ae7e51e1bed02e5c1036c6169113a457a38a06 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Mon, 12 Mar 2007 14:55:02 +0000 Subject: [PATCH 065/170] linux: Adjust memory allocation condition in netback to reduce memory pressure on Xen and avoid unnecessarily stalling receives. Signed-off-by: Jan Beulich --- linux-2.6-xen-sparse/drivers/xen/netback/netback.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c index b05e3000e3..7e0c340832 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c @@ -110,6 +110,7 @@ static unsigned int alloc_index = 0; static inline unsigned long alloc_mfn(void) { + BUG_ON(alloc_index == 0); return mfn_list[--alloc_index]; } @@ -552,6 +553,7 @@ static void net_rx_action(unsigned long unused) *(int *)skb->cb = nr_frags; if (!xen_feature(XENFEAT_auto_translated_physmap) && + !((netif_t *)netdev_priv(skb->dev))->copying_receiver && check_mfn(nr_frags + 1)) { /* Memory squeeze? Back off for an arbitrary while. */ if ( net_ratelimit() ) From cdc548f90c9c42d003b89b5b1226ecf473ae3ca9 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Mon, 12 Mar 2007 18:04:04 +0000 Subject: [PATCH 066/170] [HVM] Save/restore: update HVM detection in save/restore code in xend. Signed-off-by: Tim Deegan --- tools/python/xen/xend/XendCheckpoint.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/python/xen/xend/XendCheckpoint.py b/tools/python/xen/xend/XendCheckpoint.py index 92ba37d4fd..ba9ee645c7 100644 --- a/tools/python/xen/xend/XendCheckpoint.py +++ b/tools/python/xen/xend/XendCheckpoint.py @@ -73,13 +73,14 @@ def save(fd, dominfo, network, live, dst, checkpoint=False): write_exact(fd, config, "could not write guest state file: config") image_cfg = dominfo.info.get('image', {}) - hvm = image_cfg.has_key('hvm') + hvm = dominfo.info.is_hvm() stdvga = 0 if hvm: log.info("save hvm domain") - if image_cfg['hvm']['devices']['stdvga'] == 1: - stdvga = 1 + if dominfo.info['platform'].has_key('stdvga'): + if dominfo.info['platform']['stdvga'] == 1: + stdvga = 1 # xc_save takes three customization parameters: maxit, max_f, and # flags the last controls whether or not save is 'live', while the @@ -188,7 +189,7 @@ def restore(xd, fd, dominfo = None, paused = False): # if hvm, pass mem size to calculate the store_mfn image_cfg = dominfo.info.get('image', {}) - is_hvm = image_cfg.has_key('hvm') + is_hvm = dominfo.info.is_hvm() if is_hvm: hvm = dominfo.info['memory_static_min'] apic = dominfo.info['image']['hvm'].get('apic', 0) From f63d9525d58388171753cf71853d449646695964 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Tue, 13 Mar 2007 09:07:55 +0000 Subject: [PATCH 067/170] [LINUX] Fix typo so 3.0.4 compatability works. Signed-off-by: Ian Campbell --- linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c index a3ac4371a4..597deb733d 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c @@ -1010,7 +1010,7 @@ static void stop_hz_timer(void) singleshot.timeout_abs_ns = jiffies_to_st(j); singleshot.flags = 0; rc = HYPERVISOR_vcpu_op(VCPUOP_set_singleshot_timer, cpu, &singleshot); -#ifdef XEN_COMPAT_030004 +#ifdef CONFIG_XEN_COMPAT_030004 if (rc) { BUG_ON(rc != -ENOSYS); rc = HYPERVISOR_set_timer_op(singleshot.timeout_abs_ns); From 3bd39c408e936a3040dd89491cb3ea5f5ad06429 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Tue, 13 Mar 2007 09:52:11 +0000 Subject: [PATCH 068/170] docs: update some todo items. Signed-off-by: Stefan Berger --- docs/xen-api/todo.tex | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/docs/xen-api/todo.tex b/docs/xen-api/todo.tex index 6f679ca01e..b66dec0aba 100644 --- a/docs/xen-api/todo.tex +++ b/docs/xen-api/todo.tex @@ -91,17 +91,10 @@ same subnet. \end{itemize} -\item TPM +\item ACM \begin{itemize} -\item Would it not be better to have a class TPM and a member TPMs ((TPM ref) -Set) containing an array of zero or one references to TPMs? I assume that -an empty array would make it clear that no TPM is associated with the VM -instead of encoding its existence into TPM/instance or TPM/backend -somehow. The current members instance and backend could then be moved into -the TPM class. - -\item Also a Xen system can be running an access control policy where each +\item A Xen system can be running an access control policy where each VM's run-time access to resources is restricted by the label it has been given compared to those of the resources. Currently a VM's configuration file may contain a line like access\_control[policy='$<$name of the system's From f4575fb04ab7840022196ca55a27080ce1c67e23 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Tue, 13 Mar 2007 09:52:51 +0000 Subject: [PATCH 069/170] [XM-TEST] vTPM test changes Remove an uninitialized variable. For some reason the 'ps aux' command does not see the process anymore (since some time on the weekend). Need to add 'COLUMNS=n'. Signed-off-by: Stefan Berger --- tools/xm-test/tests/vtpm/09_vtpm-xapi.py | 2 +- tools/xm-test/tests/vtpm/vtpm_utils.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/xm-test/tests/vtpm/09_vtpm-xapi.py b/tools/xm-test/tests/vtpm/09_vtpm-xapi.py index 6de28805d3..15775801f6 100644 --- a/tools/xm-test/tests/vtpm/09_vtpm-xapi.py +++ b/tools/xm-test/tests/vtpm/09_vtpm-xapi.py @@ -91,7 +91,7 @@ if vtpm_uuid not in vm_vtpms: try: console = domain.start() except DomainError, e: - FAIL("Unable to create domain (%s)" % domName) + FAIL("Unable to create domain (%s)") try: console.sendInput("input") diff --git a/tools/xm-test/tests/vtpm/vtpm_utils.py b/tools/xm-test/tests/vtpm/vtpm_utils.py index 0af46574c9..da65aab5fb 100644 --- a/tools/xm-test/tests/vtpm/vtpm_utils.py +++ b/tools/xm-test/tests/vtpm/vtpm_utils.py @@ -8,7 +8,8 @@ from XmTestLib import * if ENABLE_HVM_SUPPORT: SKIP("vtpm tests not supported for HVM domains") -status, output = traceCommand("ps aux | grep vtpm_manager | grep -v grep") +status, output = traceCommand("COLUMNS=200 ; " + "ps aux | grep vtpm_manager | grep -v grep") if output == "": SKIP("virtual TPM manager must be started to run this test; might " "need /dev/tpm0") From f4f4172c69140f17ab850b8aa76bc14449956e23 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Tue, 13 Mar 2007 10:02:45 +0000 Subject: [PATCH 070/170] Update defconfigs for new XEN_COMPAT_300004 option. Signed-off-by: Ian Campbell --- buildconfigs/conf.linux-native/00_xen_to_native | 2 ++ buildconfigs/linux-defconfig_xen0_ia64 | 2 ++ buildconfigs/linux-defconfig_xen0_x86_32 | 2 ++ buildconfigs/linux-defconfig_xen0_x86_64 | 2 ++ buildconfigs/linux-defconfig_xenU_ia64 | 2 ++ buildconfigs/linux-defconfig_xenU_x86_32 | 2 ++ buildconfigs/linux-defconfig_xenU_x86_64 | 2 ++ buildconfigs/linux-defconfig_xen_ia64 | 2 ++ buildconfigs/linux-defconfig_xen_x86_32 | 2 ++ buildconfigs/linux-defconfig_xen_x86_64 | 2 ++ 10 files changed, 20 insertions(+) diff --git a/buildconfigs/conf.linux-native/00_xen_to_native b/buildconfigs/conf.linux-native/00_xen_to_native index 6f155024fc..024bc9bbca 100644 --- a/buildconfigs/conf.linux-native/00_xen_to_native +++ b/buildconfigs/conf.linux-native/00_xen_to_native @@ -74,8 +74,10 @@ CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_XEN_DISABLE_SERIAL is not set # CONFIG_XEN_SYSFS is not set # CONFIG_XEN_COMPAT_030002_AND_LATER is not set +# CONFIG_XEN_COMPAT_030004_AND_LATER is not set # CONFIG_XEN_COMPAT_LATEST_ONLY is not set # CONFIG_XEN_COMPAT_030002 is not set +# CONFIG_XEN_COMPAT_030004 is not set # CONFIG_HAVE_ARCH_ALLOC_SKB is not set # CONFIG_HAVE_ARCH_DEV_ALLOC_SKB is not set # CONFIG_NO_IDLE_HZ is not set diff --git a/buildconfigs/linux-defconfig_xen0_ia64 b/buildconfigs/linux-defconfig_xen0_ia64 index e29682a58a..ae4281e94c 100644 --- a/buildconfigs/linux-defconfig_xen0_ia64 +++ b/buildconfigs/linux-defconfig_xen0_ia64 @@ -1647,8 +1647,10 @@ CONFIG_XEN_NETDEV_FRONTEND=y CONFIG_XEN_DISABLE_SERIAL=y CONFIG_XEN_SYSFS=y CONFIG_XEN_COMPAT_030002_AND_LATER=y +# CONFIG_XEN_COMPAT_030004_AND_LATER is not set # CONFIG_XEN_COMPAT_LATEST_ONLY is not set CONFIG_XEN_COMPAT_030002=y +CONFIG_XEN_COMPAT_030004=y CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y CONFIG_NO_IDLE_HZ=y CONFIG_XEN_DEVMEM=y diff --git a/buildconfigs/linux-defconfig_xen0_x86_32 b/buildconfigs/linux-defconfig_xen0_x86_32 index be74277044..0ade353004 100644 --- a/buildconfigs/linux-defconfig_xen0_x86_32 +++ b/buildconfigs/linux-defconfig_xen0_x86_32 @@ -1411,8 +1411,10 @@ CONFIG_XEN_SCRUB_PAGES=y CONFIG_XEN_DISABLE_SERIAL=y CONFIG_XEN_SYSFS=y CONFIG_XEN_COMPAT_030002_AND_LATER=y +# CONFIG_XEN_COMPAT_030004_AND_LATER is not set # CONFIG_XEN_COMPAT_LATEST_ONLY is not set CONFIG_XEN_COMPAT_030002=y +CONFIG_XEN_COMPAT_030004=y CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y CONFIG_NO_IDLE_HZ=y CONFIG_XEN_UTIL=y diff --git a/buildconfigs/linux-defconfig_xen0_x86_64 b/buildconfigs/linux-defconfig_xen0_x86_64 index 15cefeff06..5d37ba6a0f 100644 --- a/buildconfigs/linux-defconfig_xen0_x86_64 +++ b/buildconfigs/linux-defconfig_xen0_x86_64 @@ -1361,8 +1361,10 @@ CONFIG_XEN_SCRUB_PAGES=y CONFIG_XEN_DISABLE_SERIAL=y CONFIG_XEN_SYSFS=y CONFIG_XEN_COMPAT_030002_AND_LATER=y +# CONFIG_XEN_COMPAT_030004_AND_LATER is not set # CONFIG_XEN_COMPAT_LATEST_ONLY is not set CONFIG_XEN_COMPAT_030002=y +CONFIG_XEN_COMPAT_030004=y CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y CONFIG_NO_IDLE_HZ=y CONFIG_XEN_UTIL=y diff --git a/buildconfigs/linux-defconfig_xenU_ia64 b/buildconfigs/linux-defconfig_xenU_ia64 index b98752bd44..7ef2d7ac84 100644 --- a/buildconfigs/linux-defconfig_xenU_ia64 +++ b/buildconfigs/linux-defconfig_xenU_ia64 @@ -1489,8 +1489,10 @@ CONFIG_XEN_KEYBOARD=y # CONFIG_XEN_DISABLE_SERIAL is not set CONFIG_XEN_SYSFS=y CONFIG_XEN_COMPAT_030002_AND_LATER=y +# CONFIG_XEN_COMPAT_030004_AND_LATER is not set # CONFIG_XEN_COMPAT_LATEST_ONLY is not set CONFIG_XEN_COMPAT_030002=y +CONFIG_XEN_COMPAT_030004=y CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y CONFIG_NO_IDLE_HZ=y CONFIG_XEN_DEVMEM=y diff --git a/buildconfigs/linux-defconfig_xenU_x86_32 b/buildconfigs/linux-defconfig_xenU_x86_32 index f9b364c2ec..f2bbb868ef 100644 --- a/buildconfigs/linux-defconfig_xenU_x86_32 +++ b/buildconfigs/linux-defconfig_xenU_x86_32 @@ -920,8 +920,10 @@ CONFIG_XEN_SCRUB_PAGES=y CONFIG_XEN_DISABLE_SERIAL=y CONFIG_XEN_SYSFS=y CONFIG_XEN_COMPAT_030002_AND_LATER=y +# CONFIG_XEN_COMPAT_030004_AND_LATER is not set # CONFIG_XEN_COMPAT_LATEST_ONLY is not set CONFIG_XEN_COMPAT_030002=y +CONFIG_XEN_COMPAT_030004=y CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y CONFIG_NO_IDLE_HZ=y CONFIG_XEN_UTIL=y diff --git a/buildconfigs/linux-defconfig_xenU_x86_64 b/buildconfigs/linux-defconfig_xenU_x86_64 index 39c13af858..69fedf944f 100644 --- a/buildconfigs/linux-defconfig_xenU_x86_64 +++ b/buildconfigs/linux-defconfig_xenU_x86_64 @@ -1216,8 +1216,10 @@ CONFIG_XEN_SCRUB_PAGES=y CONFIG_XEN_DISABLE_SERIAL=y CONFIG_XEN_SYSFS=y CONFIG_XEN_COMPAT_030002_AND_LATER=y +# CONFIG_XEN_COMPAT_030004_AND_LATER is not set # CONFIG_XEN_COMPAT_LATEST_ONLY is not set CONFIG_XEN_COMPAT_030002=y +CONFIG_XEN_COMPAT_030004=y CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y CONFIG_NO_IDLE_HZ=y CONFIG_XEN_UTIL=y diff --git a/buildconfigs/linux-defconfig_xen_ia64 b/buildconfigs/linux-defconfig_xen_ia64 index fd7d951d2c..58d97492ef 100644 --- a/buildconfigs/linux-defconfig_xen_ia64 +++ b/buildconfigs/linux-defconfig_xen_ia64 @@ -1648,8 +1648,10 @@ CONFIG_XEN_KEYBOARD=y CONFIG_XEN_DISABLE_SERIAL=y CONFIG_XEN_SYSFS=y CONFIG_XEN_COMPAT_030002_AND_LATER=y +# CONFIG_XEN_COMPAT_030004_AND_LATER is not set # CONFIG_XEN_COMPAT_LATEST_ONLY is not set CONFIG_XEN_COMPAT_030002=y +CONFIG_XEN_COMPAT_030004=y CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y CONFIG_NO_IDLE_HZ=y CONFIG_XEN_DEVMEM=y diff --git a/buildconfigs/linux-defconfig_xen_x86_32 b/buildconfigs/linux-defconfig_xen_x86_32 index 834e990426..1c949151cc 100644 --- a/buildconfigs/linux-defconfig_xen_x86_32 +++ b/buildconfigs/linux-defconfig_xen_x86_32 @@ -3271,8 +3271,10 @@ CONFIG_XEN_SCRUB_PAGES=y CONFIG_XEN_DISABLE_SERIAL=y CONFIG_XEN_SYSFS=y CONFIG_XEN_COMPAT_030002_AND_LATER=y +# CONFIG_XEN_COMPAT_030004_AND_LATER is not set # CONFIG_XEN_COMPAT_LATEST_ONLY is not set CONFIG_XEN_COMPAT_030002=y +CONFIG_XEN_COMPAT_030004=y CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y CONFIG_NO_IDLE_HZ=y CONFIG_XEN_UTIL=y diff --git a/buildconfigs/linux-defconfig_xen_x86_64 b/buildconfigs/linux-defconfig_xen_x86_64 index afb8d949ff..8ac68363f0 100644 --- a/buildconfigs/linux-defconfig_xen_x86_64 +++ b/buildconfigs/linux-defconfig_xen_x86_64 @@ -3101,8 +3101,10 @@ CONFIG_XEN_SCRUB_PAGES=y CONFIG_XEN_DISABLE_SERIAL=y CONFIG_XEN_SYSFS=y CONFIG_XEN_COMPAT_030002_AND_LATER=y +# CONFIG_XEN_COMPAT_030004_AND_LATER is not set # CONFIG_XEN_COMPAT_LATEST_ONLY is not set CONFIG_XEN_COMPAT_030002=y +CONFIG_XEN_COMPAT_030004=y CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y CONFIG_NO_IDLE_HZ=y CONFIG_XEN_UTIL=y From 1babae4d0c7a153211fe92a32199ded676f6e477 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Tue, 13 Mar 2007 10:32:52 +0000 Subject: [PATCH 071/170] hvmloader: Avoid compile warnings char vs. unsigned char. Avoid 'magic number' hardcoded string lengths. Signed-off-by: Keir Fraser --- tools/firmware/hvmloader/acpi/acpi2_0.h | 8 ++++---- tools/firmware/hvmloader/acpi/build.c | 26 +++++++++++++------------ 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/tools/firmware/hvmloader/acpi/acpi2_0.h b/tools/firmware/hvmloader/acpi/acpi2_0.h index 04824f5642..7dde528a48 100644 --- a/tools/firmware/hvmloader/acpi/acpi2_0.h +++ b/tools/firmware/hvmloader/acpi/acpi2_0.h @@ -49,8 +49,8 @@ struct acpi_header { uint32_t length; uint8_t revision; uint8_t checksum; - uint8_t oem_id[6]; - uint8_t oem_table_id[8]; + char oem_id[6]; + char oem_table_id[8]; uint32_t oem_revision; uint32_t creator_id; uint32_t creator_revision; @@ -90,7 +90,7 @@ struct acpi_20_generic_address { struct acpi_10_rsdp { uint64_t signature; uint8_t checksum; - uint8_t oem_id[6]; + char oem_id[6]; uint8_t reserved; uint32_t rsdt_address; }; @@ -101,7 +101,7 @@ struct acpi_10_rsdp { struct acpi_20_rsdp { uint64_t signature; uint8_t checksum; - uint8_t oem_id[6]; + char oem_id[6]; uint8_t revision; uint32_t rsdt_address; uint32_t length; diff --git a/tools/firmware/hvmloader/acpi/build.c b/tools/firmware/hvmloader/acpi/build.c index ff99160612..55a48d440e 100644 --- a/tools/firmware/hvmloader/acpi/build.c +++ b/tools/firmware/hvmloader/acpi/build.c @@ -22,7 +22,8 @@ #include "../util.h" #include -#define align16(sz) (((sz) + 15) & ~15) +#define align16(sz) (((sz) + 15) & ~15) +#define fixed_strcpy(d, s) strncpy((d), (s), sizeof(d)) extern struct acpi_20_rsdp Rsdp; extern struct acpi_20_rsdt Rsdt; @@ -57,8 +58,8 @@ int construct_madt(struct acpi_20_madt *madt) memset(madt, 0, sizeof(*madt)); madt->header.signature = ACPI_2_0_MADT_SIGNATURE; madt->header.revision = ACPI_2_0_MADT_REVISION; - strncpy(madt->header.oem_id, ACPI_OEM_ID, 6); - strncpy(madt->header.oem_table_id, ACPI_OEM_TABLE_ID, 8); + fixed_strcpy(madt->header.oem_id, ACPI_OEM_ID); + fixed_strcpy(madt->header.oem_table_id, ACPI_OEM_TABLE_ID); madt->header.oem_revision = ACPI_OEM_REVISION; madt->header.creator_id = ACPI_CREATOR_ID; madt->header.creator_revision = ACPI_CREATOR_REVISION; @@ -131,8 +132,8 @@ int construct_hpet(struct acpi_20_hpet *hpet) memset(hpet, 0, sizeof(*hpet)); hpet->header.signature = ACPI_2_0_HPET_SIGNATURE; hpet->header.revision = ACPI_2_0_HPET_REVISION; - strncpy(hpet->header.oem_id, ACPI_OEM_ID, 6); - strncpy(hpet->header.oem_table_id, ACPI_OEM_TABLE_ID, 8); + fixed_strcpy(hpet->header.oem_id, ACPI_OEM_ID); + fixed_strcpy(hpet->header.oem_table_id, ACPI_OEM_TABLE_ID); hpet->header.oem_revision = ACPI_OEM_REVISION; hpet->header.creator_id = ACPI_CREATOR_ID; hpet->header.creator_revision = ACPI_CREATOR_REVISION; @@ -150,6 +151,7 @@ int construct_processor_objects(uint8_t *buf) { static const char pdat[13] = { 0x5b, 0x83, 0x0b, 0x50, 0x52 }; static const char hex[] = "0123456789ABCDEF"; + static const char pr_scope[] = "\\_PR_"; unsigned int i, length, nr_cpus = get_vcpu_nr(); struct acpi_header *hdr; uint8_t *p = buf; @@ -161,8 +163,8 @@ int construct_processor_objects(uint8_t *buf) hdr = (struct acpi_header *)p; hdr->signature = ASCII32('S','S','D','T'); hdr->revision = 2; - strncpy(hdr->oem_id, ACPI_OEM_ID, 6); - strncpy(hdr->oem_table_id, ACPI_OEM_TABLE_ID, 8); + fixed_strcpy(hdr->oem_id, ACPI_OEM_ID); + fixed_strcpy(hdr->oem_table_id, ACPI_OEM_TABLE_ID); hdr->oem_revision = ACPI_OEM_REVISION; hdr->creator_id = ACPI_CREATOR_ID; hdr->creator_revision = ACPI_CREATOR_REVISION; @@ -176,7 +178,7 @@ int construct_processor_objects(uint8_t *buf) *p++ = 0x10; /* PkgLength (includes length bytes!). */ - length = 1 + 5 + (nr_cpus * sizeof(pdat)); + length = 1 + strlen(pr_scope) + (nr_cpus * sizeof(pdat)); if ( length <= 0x3f ) { *p++ = length; @@ -195,8 +197,8 @@ int construct_processor_objects(uint8_t *buf) } /* NameString */ - strncpy(p, "\\_PR_", 5); - p += 5; + strncpy(p, pr_scope, strlen(pr_scope)); + p += strlen(pr_scope); /* * 3. Processor Objects. @@ -263,8 +265,8 @@ int construct_secondary_tables(uint8_t *buf, unsigned long *table_ptrs) tcpa->header.signature = ACPI_2_0_TCPA_SIGNATURE; tcpa->header.length = sizeof(*tcpa); tcpa->header.revision = ACPI_2_0_TCPA_REVISION; - strncpy(tcpa->header.oem_id, ACPI_OEM_ID, 6); - strncpy(tcpa->header.oem_table_id, ACPI_OEM_TABLE_ID, 8); + fixed_strcpy(tcpa->header.oem_id, ACPI_OEM_ID); + fixed_strcpy(tcpa->header.oem_table_id, ACPI_OEM_TABLE_ID); tcpa->header.oem_revision = ACPI_OEM_REVISION; tcpa->header.creator_id = ACPI_CREATOR_ID; tcpa->header.creator_revision = ACPI_CREATOR_REVISION; From 26e24b46d174a0eb23f414bbeaa0f0da18836fb6 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Tue, 13 Mar 2007 13:28:26 +0000 Subject: [PATCH 072/170] linux: No need to force pcibios_scan_all_fns() on modern Xen. Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pci.h | 7 ------- linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pci.h | 7 ------- 2 files changed, 14 deletions(-) diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pci.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pci.h index 584f65e178..14c1d27629 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pci.h +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pci.h @@ -143,11 +143,4 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev, /* generic pci stuff */ #include -/* On Xen we have to scan all functions since Xen hides bridges from - * us. If a bridge is at fn=0 and that slot has a multifunction - * device, we won't find the additional devices without scanning all - * functions. */ -#undef pcibios_scan_all_fns -#define pcibios_scan_all_fns(a, b) 1 - #endif /* __i386_PCI_H */ diff --git a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pci.h b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pci.h index 8ec15d931e..764270fa4f 100644 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pci.h +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pci.h @@ -163,11 +163,4 @@ static inline void pcibios_add_platform_entries(struct pci_dev *dev) #include #endif -/* On Xen we have to scan all functions since Xen hides bridges from - * us. If a bridge is at fn=0 and that slot has a multifunction - * device, we won't find the additional devices without scanning all - * functions. */ -#undef pcibios_scan_all_fns -#define pcibios_scan_all_fns(a, b) 1 - #endif /* __x8664_PCI_H */ From 69461aa51d5c47a28ac2244d3014fc41295f2109 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Tue, 13 Mar 2007 14:04:31 +0000 Subject: [PATCH 073/170] xen/x86: Tweak #PF handler. Simplify gdbstub copy to/from guest. Signed-off-by: Keir Fraser --- xen/arch/x86/gdbstub.c | 28 +++------------------------- xen/arch/x86/traps.c | 7 ++++--- 2 files changed, 7 insertions(+), 28 deletions(-) diff --git a/xen/arch/x86/gdbstub.c b/xen/arch/x86/gdbstub.c index 8ed5e20298..a3af473ee2 100644 --- a/xen/arch/x86/gdbstub.c +++ b/xen/arch/x86/gdbstub.c @@ -73,38 +73,16 @@ gdb_arch_read_reg(unsigned long regnum, struct cpu_user_regs *regs, /* Like copy_from_user, but safe to call with interrupts disabled. Trust me, and don't look behind the curtain. */ -unsigned +unsigned int gdb_arch_copy_from_user(void *dest, const void *src, unsigned len) { - int __d0, __d1, __d2; - ASSERT(!local_irq_is_enabled()); - __asm__ __volatile__( - "1: rep; movsb\n" - "2:\n" - ".section .fixup,\"ax\"\n" - "3: addl $4, %%esp\n" - " jmp 2b\n" - ".previous\n" - ".section __pre_ex_table,\"a\"\n" - " "__FIXUP_ALIGN"\n" - " "__FIXUP_WORD" 1b,3b\n" - ".previous\n" - ".section __ex_table,\"a\"\n" - " "__FIXUP_ALIGN"\n" - " "__FIXUP_WORD" 1b,2b\n" - ".previous\n" - : "=c"(__d2), "=D" (__d0), "=S" (__d1) - : "0"(len), "1"(dest), "2"(src) - : "memory"); - ASSERT(!local_irq_is_enabled()); - return __d2; + return copy_from_user(dest, src, len); } unsigned int gdb_arch_copy_to_user(void *dest, const void *src, unsigned len) { - /* XXX */ - return len; + return copy_to_user(dest, src, len); } void diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index f6054857f4..2423ad5493 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -905,6 +905,10 @@ static int fixup_page_fault(unsigned long addr, struct cpu_user_regs *regs) struct vcpu *v = current; struct domain *d = v->domain; + /* No fixups in interrupt context or when interrupts are disabled. */ + if ( in_irq() || !(regs->eflags & X86_EFLAGS_IF) ) + return 0; + if ( unlikely(IN_HYPERVISOR_RANGE(addr)) ) { if ( paging_mode_external(d) && guest_mode(regs) ) @@ -915,9 +919,6 @@ static int fixup_page_fault(unsigned long addr, struct cpu_user_regs *regs) return 0; } - ASSERT(!in_irq()); - ASSERT(regs->eflags & X86_EFLAGS_IF); - if ( VM_ASSIST(d, VMASST_TYPE_writable_pagetables) && guest_kernel_mode(v, regs) && /* Do not check if access-protection fault since the page may From 60cf5b7783f542ea2a08d6c08a73d20105a7adea Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Tue, 13 Mar 2007 14:56:03 +0000 Subject: [PATCH 074/170] xm: Allow vcpu-pin to specify 'all' for CPU list. Signed-off-by: Masaki Kanno --- tools/python/xen/xm/main.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 89dbfde9d1..6c32e8529e 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -139,7 +139,7 @@ SUBCOMMAND_HELP = { 'Send a trigger to a domain.'), 'vcpu-list' : ('[]', 'List the VCPUs for a domain or all domains.'), - 'vcpu-pin' : (' ', + 'vcpu-pin' : (' ', 'Set which CPUs a VCPU can use.'), 'vcpu-set' : (' ', 'Set the number of active VCPUs for allowed for the' @@ -1084,7 +1084,10 @@ def xm_vcpu_pin(args): dom = args[0] vcpu = args[1] - cpumap = cpu_make_map(args[2]) + if args[2] == 'all': + cpumap = cpu_make_map('0-63') + else: + cpumap = cpu_make_map(args[2]) server.xend.domain.pincpu(dom, vcpu, cpumap) From bf8fc36917df0c5190548350a06bd6ff1f4a6ace Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Tue, 13 Mar 2007 15:55:37 +0000 Subject: [PATCH 075/170] [HVM] Save/restore: more state propagation in xend Signed-off-by: Tim Deegan --- tools/python/xen/xend/XendCheckpoint.py | 4 ++-- tools/python/xen/xend/XendConfig.py | 11 ++++++----- tools/python/xen/xend/image.py | 2 +- tools/python/xen/xend/server/vfbif.py | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/tools/python/xen/xend/XendCheckpoint.py b/tools/python/xen/xend/XendCheckpoint.py index ba9ee645c7..7881130092 100644 --- a/tools/python/xen/xend/XendCheckpoint.py +++ b/tools/python/xen/xend/XendCheckpoint.py @@ -192,8 +192,8 @@ def restore(xd, fd, dominfo = None, paused = False): is_hvm = dominfo.info.is_hvm() if is_hvm: hvm = dominfo.info['memory_static_min'] - apic = dominfo.info['image']['hvm'].get('apic', 0) - pae = dominfo.info['image']['hvm'].get('pae', 0) + apic = dominfo.info['platform'].get('apic', 0) + pae = dominfo.info['platform'].get('pae', 0) log.info("restore hvm domain %d, mem=%d, apic=%d, pae=%d", dominfo.domid, hvm, apic, pae) else: diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index 4dd1367c2d..bdf9370380 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -118,11 +118,12 @@ XENAPI_CFG_TO_LEGACY_CFG = { LEGACY_CFG_TO_XENAPI_CFG = reverse_dict(XENAPI_CFG_TO_LEGACY_CFG) # Platform configuration keys. -XENAPI_PLATFORM_CFG = [ 'acpi', 'apic', 'device_model', 'display', 'fda', - 'fdb', 'keymap', 'isa', 'localtime', 'nographic', - 'pae', 'serial', 'sdl', 'soundhw','stdvga', 'usb', - 'usbdevice', 'vnc', 'vncconsole', 'vncdisplay', - 'vnclisten', 'vncpasswd', 'vncunused', 'xauthority'] +XENAPI_PLATFORM_CFG = [ 'acpi', 'apic', 'boot', 'device_model', 'display', + 'fda', 'fdb', 'keymap', 'isa', 'localtime', + 'nographic', 'pae', 'serial', 'sdl', + 'soundhw','stdvga', 'usb', 'usbdevice', 'vnc', + 'vncconsole', 'vncdisplay', 'vnclisten', + 'vncpasswd', 'vncunused', 'xauthority'] # List of XendConfig configuration keys that have no direct equivalent # in the old world. diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py index 33e1b1100b..7b6102b557 100644 --- a/tools/python/xen/xend/image.py +++ b/tools/python/xen/xend/image.py @@ -392,7 +392,7 @@ class HVMImageHandler(ImageHandler): # Find RFB console device, and if it exists, make QEMU enable # the VNC console. # - if vmConfig['platform'].get('nographic'): + if int(vmConfig['platform'].get('nographic', 0)) != 0: # skip vnc init if nographic is set ret.append('-nographic') return ret diff --git a/tools/python/xen/xend/server/vfbif.py b/tools/python/xen/xend/server/vfbif.py index fb510de25f..cbef190248 100644 --- a/tools/python/xen/xend/server/vfbif.py +++ b/tools/python/xen/xend/server/vfbif.py @@ -46,7 +46,7 @@ class VfbifController(DevController): def createDevice(self, config): DevController.createDevice(self, config) - if self.vm.info.get('HVM_boot_policy'): + if self.vm.info.is_hvm(): # is HVM, so qemu-dm will handle the vfb. return From 618d247ec86f7b407a4f249132f8439d5c1103a3 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Wed, 14 Mar 2007 10:44:56 +0000 Subject: [PATCH 076/170] add usb device save/restore in qemu Signed-off-by: Zhai Edwin --- tools/ioemu/hw/usb-hid.c | 47 ++++++++++++++++++++++++++++++++++++++ tools/ioemu/hw/usb-ohci.c | 2 ++ tools/ioemu/hw/usb-uhci.c | 48 +++++++++++++++++++++++++++++++++++++++ tools/ioemu/hw/usb.c | 40 ++++++++++++++++++++++++++++++++ tools/ioemu/hw/usb.h | 6 +++++ tools/ioemu/vl.c | 19 ++++++++++++++++ 6 files changed, 162 insertions(+) diff --git a/tools/ioemu/hw/usb-hid.c b/tools/ioemu/hw/usb-hid.c index 60849a4ed0..c7af3d65ab 100644 --- a/tools/ioemu/hw/usb-hid.c +++ b/tools/ioemu/hw/usb-hid.c @@ -517,6 +517,49 @@ static void usb_mouse_handle_destroy(USBDevice *dev) qemu_free(s); } +void usb_mouse_save(QEMUFile *f, void *opaque) +{ + USBMouseState *s = (USBMouseState*)opaque; + + qemu_put_be32s(f, &s->dx); + qemu_put_be32s(f, &s->dy); + qemu_put_be32s(f, &s->dz); + qemu_put_be32s(f, &s->buttons_state); + qemu_put_be32s(f, &s->x); + qemu_put_be32s(f, &s->y); + qemu_put_be32s(f, &s->kind); + qemu_put_be32s(f, &s->mouse_grabbed); + qemu_put_be32s(f, &s->status_changed); + +} + +int usb_mouse_load(QEMUFile *f, void *opaque, int version_id) +{ + USBMouseState *s = (USBMouseState*)opaque; + + if (version_id != 1) + return -EINVAL; + + qemu_get_be32s(f, &s->dx); + qemu_get_be32s(f, &s->dy); + qemu_get_be32s(f, &s->dz); + qemu_get_be32s(f, &s->buttons_state); + qemu_get_be32s(f, &s->x); + qemu_get_be32s(f, &s->y); + qemu_get_be32s(f, &s->kind); + qemu_get_be32s(f, &s->mouse_grabbed); + qemu_get_be32s(f, &s->status_changed); + + if ( s->kind == USB_TABLET) { + fprintf(logfile, "usb_mouse_load:add usb_tablet_event.\n"); + qemu_add_mouse_event_handler(usb_tablet_event, s, 1); + } else if ( s->kind == USB_MOUSE) { + fprintf(logfile, "usb_mouse_load:add usb_mouse_event.\n"); + qemu_add_mouse_event_handler(usb_mouse_event, s, 0); + } +} + + USBDevice *usb_tablet_init(void) { USBMouseState *s; @@ -536,6 +579,8 @@ USBDevice *usb_tablet_init(void) pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet"); + register_savevm("USB tablet dev", 0, 1, usb_mouse_save, usb_mouse_load, s); + return (USBDevice *)s; } @@ -558,5 +603,7 @@ USBDevice *usb_mouse_init(void) pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse"); + register_savevm("USB mouse dev", 0, 1, usb_mouse_save, usb_mouse_load, s); + return (USBDevice *)s; } diff --git a/tools/ioemu/hw/usb-ohci.c b/tools/ioemu/hw/usb-ohci.c index e87d9da70a..a563262676 100644 --- a/tools/ioemu/hw/usb-ohci.c +++ b/tools/ioemu/hw/usb-ohci.c @@ -1186,5 +1186,7 @@ void usb_ohci_init(struct PCIBus *bus, int num_ports, int devfn) qemu_register_usb_port(&ohci->rhport[i].port, ohci, i, ohci_attach); } + register_savevm("OHCI USB", 0, 1, generic_pci_save, generic_pci_load, ohci); + ohci_reset(ohci); } diff --git a/tools/ioemu/hw/usb-uhci.c b/tools/ioemu/hw/usb-uhci.c index 7212c5e82d..46cff274cf 100644 --- a/tools/ioemu/hw/usb-uhci.c +++ b/tools/ioemu/hw/usb-uhci.c @@ -658,6 +658,50 @@ static void uhci_map(PCIDevice *pci_dev, int region_num, register_ioport_read(addr, 32, 1, uhci_ioport_readb, s); } +void uhci_usb_save(QEMUFile *f, void *opaque) +{ + int i; + UHCIState *s = (UHCIState*)opaque; + + qemu_put_be16s(f, &s->cmd); + qemu_put_be16s(f, &s->status); + qemu_put_be16s(f, &s->intr); + qemu_put_be16s(f, &s->frnum); + qemu_put_be32s(f, &s->fl_base_addr); + qemu_put_8s(f, &s->sof_timing); + qemu_put_8s(f, &s->status2); + + for(i = 0; i < NB_PORTS; i++) { + qemu_put_be16s(f, &s->ports[i].ctrl); + } + + qemu_put_timer(f, s->frame_timer); +} + +int uhci_usb_load(QEMUFile *f, void *opaque, int version_id) +{ + int i; + UHCIState *s = (UHCIState*)opaque; + + if (version_id != 1) + return -EINVAL; + + qemu_get_be16s(f, &s->cmd); + qemu_get_be16s(f, &s->status); + qemu_get_be16s(f, &s->intr); + qemu_get_be16s(f, &s->frnum); + qemu_get_be32s(f, &s->fl_base_addr); + qemu_get_8s(f, &s->sof_timing); + qemu_get_8s(f, &s->status2); + + for(i = 0; i < NB_PORTS; i++) { + qemu_get_be16s(f, &s->ports[i].ctrl); + } + + qemu_get_timer(f, s->frame_timer); + +} + void usb_uhci_init(PCIBus *bus, int devfn) { UHCIState *s; @@ -693,4 +737,8 @@ void usb_uhci_init(PCIBus *bus, int devfn) to rely on this. */ pci_register_io_region(&s->dev, 4, 0x20, PCI_ADDRESS_SPACE_IO, uhci_map); + + register_savevm("UHCI_usb_pci", 0, 1, generic_pci_save, generic_pci_load, s); + + register_savevm("UHCI usb controller", 0, 1, uhci_usb_save, uhci_usb_load, s); } diff --git a/tools/ioemu/hw/usb.c b/tools/ioemu/hw/usb.c index 34aac5fa9b..e4166518b0 100644 --- a/tools/ioemu/hw/usb.c +++ b/tools/ioemu/hw/usb.c @@ -191,3 +191,43 @@ int set_usb_string(uint8_t *buf, const char *str) } return q - buf; } + +void generic_usb_save(QEMUFile* f, void *opaque) +{ + USBDevice *s = (USBDevice*)opaque; + + qemu_put_be32s(f, &s->speed); + qemu_put_8s(f, &s->addr); + qemu_put_be32s(f, &s->state); + + qemu_put_buffer(f, s->setup_buf, 8); + qemu_put_buffer(f, s->data_buf, 1024); + + qemu_put_be32s(f, &s->remote_wakeup); + qemu_put_be32s(f, &s->setup_state); + qemu_put_be32s(f, &s->setup_len); + qemu_put_be32s(f, &s->setup_index); + +} + +int generic_usb_load(QEMUFile* f, void *opaque, int version_id) +{ + USBDevice *s = (USBDevice*)opaque; + + if (version_id != 1) + return -EINVAL; + + qemu_get_be32s(f, &s->speed); + qemu_get_8s(f, &s->addr); + qemu_get_be32s(f, &s->state); + + qemu_get_buffer(f, s->setup_buf, 8); + qemu_get_buffer(f, s->data_buf, 1024); + + qemu_get_be32s(f, &s->remote_wakeup); + qemu_get_be32s(f, &s->setup_state); + qemu_get_be32s(f, &s->setup_len); + qemu_get_be32s(f, &s->setup_index); + + return 0; +} diff --git a/tools/ioemu/hw/usb.h b/tools/ioemu/hw/usb.h index 98fde06569..9df69f8dc8 100644 --- a/tools/ioemu/hw/usb.h +++ b/tools/ioemu/hw/usb.h @@ -176,3 +176,9 @@ USBDevice *usb_tablet_init(void); /* usb-msd.c */ USBDevice *usb_msd_init(const char *filename); + +/* usb.c */ +void generic_usb_save(QEMUFile* f, void *opaque); +int generic_usb_load(QEMUFile* f, void *opaque, int version_id); + + diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index 0b78fa8650..6f9219fa40 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -841,10 +841,22 @@ void qemu_get_timer(QEMUFile *f, QEMUTimer *ts) #ifdef CONFIG_DM static void timer_save(QEMUFile *f, void *opaque) { + /* need timer for save/restoe qemu_timer in usb_uhci */ + if (cpu_ticks_enabled) { + hw_error("cannot save state if virtual timers are running"); + } + qemu_put_be64s(f, &cpu_clock_offset); } static int timer_load(QEMUFile *f, void *opaque, int version_id) { + if (version_id != 1) + return -EINVAL; + if (cpu_ticks_enabled) { + return -EINVAL; + } + + qemu_get_be64s(f, &cpu_clock_offset); return 0; } #else /* !CONFIG_DM */ @@ -3900,6 +3912,7 @@ static int usb_device_add(const char *devname) const char *p; USBDevice *dev; USBPort *port; + char usb_name[256] = "USB "; if (!free_usb_ports) return -1; @@ -3936,6 +3949,12 @@ static int usb_device_add(const char *devname) free_usb_ports = port->next; port->next = used_usb_ports; used_usb_ports = port; + + pstrcpy(usb_name + strlen(usb_name), + sizeof(usb_name) - strlen(usb_name), + devname); + register_savevm(usb_name, 0, 1, generic_usb_save, generic_usb_load, dev); + usb_attach(port, dev); return 0; } From bc510c7fd59ff4db07bc090e35a7307e799bd70a Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 14 Mar 2007 11:09:13 +0000 Subject: [PATCH 077/170] AMD HVM: Fix enter-realmode stub to initialise 32-bit GPRs. This fixes booting Ubuntu live ISO, which assumes the upper half of %esp is zero on entry. Signed-off-by: Keir Fraser --- tools/firmware/hvmloader/hvmloader.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/tools/firmware/hvmloader/hvmloader.c b/tools/firmware/hvmloader/hvmloader.c index 6b75303477..8bed54835a 100644 --- a/tools/firmware/hvmloader/hvmloader.c +++ b/tools/firmware/hvmloader/hvmloader.c @@ -62,15 +62,21 @@ asm( " mov %ax,%fs \n" " mov %ax,%gs \n" " mov %ax,%ss \n" - " ljmp $0x8,$0x0 \n" + /* Initialise all 32-bit GPRs to zero. */ + " xor %eax,%eax \n" + " xor %ebx,%ebx \n" + " xor %ecx,%ecx \n" + " xor %edx,%edx \n" + " xor %esp,%esp \n" + " xor %ebp,%ebp \n" + " xor %esi,%esi \n" + " xor %edi,%edi \n" /* Enter real mode, reload all segment registers and IDT. */ + " ljmp $0x8,$0x0 \n" "trampoline_start: .code16 \n" - " mov %cr0,%eax \n" - " and $0xfe,%al \n" " mov %eax,%cr0 \n" " ljmp $0,$1f-trampoline_start\n" - "1: xor %ax,%ax \n" - " mov %ax,%ds \n" + "1: mov %ax,%ds \n" " mov %ax,%es \n" " mov %ax,%fs \n" " mov %ax,%gs \n" From 3a02a4cff8bff768694c0e4e113b7cfdb35786f2 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 14 Mar 2007 11:22:59 +0000 Subject: [PATCH 078/170] hvm: Print bad DFR value for vlapic if a bad value is detected. Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/vlapic.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c index 2cc294ba36..af2d0bbe44 100644 --- a/xen/arch/x86/hvm/vlapic.c +++ b/xen/arch/x86/hvm/vlapic.c @@ -195,8 +195,9 @@ int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda) result = 1; break; default: - gdprintk(XENLOG_WARNING, "Bad DFR value for lapic of vcpu %d\n", - vlapic_vcpu(vlapic)->vcpu_id); + gdprintk(XENLOG_WARNING, "Bad DFR value for lapic of vcpu %d: %08x\n", + vlapic_vcpu(vlapic)->vcpu_id, + vlapic_get_reg(vlapic, APIC_DFR)); break; } From 8ff2288a9abae74f5e102f010ee34f9d4d13695e Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 14 Mar 2007 11:38:26 +0000 Subject: [PATCH 079/170] hvm: Add a revision 1 FADT in ACPI, and link the original revision-4 FADT only to XSDT. It avoids a buffer overflow in the initialization of Window 2000 ACPI HAL (pre ACPI 2.0 OS), and thus enables the installation and boot. This compatibility practice is also used in hardware, please refer to: http://www.acpi.info/presentations/S01USMOBS169_OS%20new.ppt Signed-off-by: Qing He --- tools/firmware/hvmloader/acpi/acpi2_0.h | 46 +++++++++++++++++++++++++ tools/firmware/hvmloader/acpi/build.c | 22 +++++++++++- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/tools/firmware/hvmloader/acpi/acpi2_0.h b/tools/firmware/hvmloader/acpi/acpi2_0.h index 7dde528a48..3e8424e138 100644 --- a/tools/firmware/hvmloader/acpi/acpi2_0.h +++ b/tools/firmware/hvmloader/acpi/acpi2_0.h @@ -142,6 +142,51 @@ struct acpi_20_tcpa { }; #define ACPI_2_0_TCPA_LAML_SIZE (64*1024) +/* + * Fixed ACPI Description Table Structure (FADT) in ACPI 1.0. + */ +struct acpi_10_fadt { + struct acpi_header header; + uint32_t firmware_ctrl; + uint32_t dsdt; + uint8_t reserved0; + uint8_t preferred_pm_profile; + uint16_t sci_int; + uint32_t smi_cmd; + uint8_t acpi_enable; + uint8_t acpi_disable; + uint8_t s4bios_req; + uint8_t pstate_cnt; + uint32_t pm1a_evt_blk; + uint32_t pm1b_evt_blk; + uint32_t pm1a_cnt_blk; + uint32_t pm1b_cnt_blk; + uint32_t pm2_cnt_blk; + uint32_t pm_tmr_blk; + uint32_t gpe0_blk; + uint32_t gpe1_blk; + uint8_t pm1_evt_len; + uint8_t pm1_cnt_len; + uint8_t pm2_cnt_len; + uint8_t pm_tmr_len; + uint8_t gpe0_blk_len; + uint8_t gpe1_blk_len; + uint8_t gpe1_base; + uint8_t cst_cnt; + uint16_t p_lvl2_lat; + uint16_t p_lvl3_lat; + uint16_t flush_size; + uint16_t flush_stride; + uint8_t duty_offset; + uint8_t duty_width; + uint8_t day_alrm; + uint8_t mon_alrm; + uint8_t century; + uint16_t iapc_boot_arch; + uint8_t reserved1; + uint32_t flags; +}; + /* * Fixed ACPI Description Table Structure (FADT). */ @@ -345,6 +390,7 @@ struct acpi_20_madt_intsrcovr { #define ACPI_2_0_XSDT_REVISION 0x01 #define ACPI_2_0_TCPA_REVISION 0x02 #define ACPI_2_0_HPET_REVISION 0x01 +#define ACPI_1_0_FADT_REVISION 0x01 #pragma pack () diff --git a/tools/firmware/hvmloader/acpi/build.c b/tools/firmware/hvmloader/acpi/build.c index 55a48d440e..3db71cabfe 100644 --- a/tools/firmware/hvmloader/acpi/build.c +++ b/tools/firmware/hvmloader/acpi/build.c @@ -293,6 +293,7 @@ int acpi_build_tables(uint8_t *buf) struct acpi_20_rsdt *rsdt; struct acpi_20_xsdt *xsdt; struct acpi_20_fadt *fadt; + struct acpi_10_fadt *fadt_10; struct acpi_20_facs *facs; unsigned char *dsdt; unsigned long secondary_tables[16]; @@ -306,6 +307,25 @@ int acpi_build_tables(uint8_t *buf) memcpy(dsdt, &AmlCode, DsdtLen); offset += align16(DsdtLen); + /* + * N.B. ACPI 1.0 operating systems may not handle FADT with revision 2 + * or above properly, notably Windows 2000, which tries to copy FADT + * into a 116 bytes buffer thus causing an overflow. The solution is to + * link the higher revision FADT with the XSDT only and introduce a + * compatible revision 1 FADT that is linked with the RSDT. Refer to: + * http://www.acpi.info/presentations/S01USMOBS169_OS%20new.ppt + */ + fadt_10 = (struct acpi_10_fadt *)&buf[offset]; + memcpy(fadt_10, &Fadt, sizeof(struct acpi_10_fadt)); + offset += align16(sizeof(struct acpi_10_fadt)); + fadt_10->header.length = sizeof(struct acpi_10_fadt); + fadt_10->header.revision = ACPI_1_0_FADT_REVISION; + fadt_10->dsdt = (unsigned long)dsdt; + fadt_10->firmware_ctrl = (unsigned long)facs; + set_checksum(fadt_10, + offsetof(struct acpi_header, checksum), + sizeof(struct acpi_10_fadt)); + fadt = (struct acpi_20_fadt *)&buf[offset]; memcpy(fadt, &Fadt, sizeof(struct acpi_20_fadt)); offset += align16(sizeof(struct acpi_20_fadt)); @@ -332,7 +352,7 @@ int acpi_build_tables(uint8_t *buf) rsdt = (struct acpi_20_rsdt *)&buf[offset]; memcpy(rsdt, &Rsdt, sizeof(struct acpi_header)); - rsdt->entry[0] = (unsigned long)fadt; + rsdt->entry[0] = (unsigned long)fadt_10; for ( i = 0; secondary_tables[i]; i++ ) rsdt->entry[i+1] = secondary_tables[i]; rsdt->header.length = sizeof(struct acpi_header) + (i+1)*sizeof(uint32_t); From 0bf25ed4be2e2d311874bc34d263c020510f8490 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Wed, 14 Mar 2007 12:49:40 +0000 Subject: [PATCH 080/170] [XEND] Mark save record fd close-on-exec after calling xc_restore so that qemu doesn't end up with an open fd on it Signed-off-by: Tim Deegan --- tools/python/xen/xend/XendCheckpoint.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/python/xen/xend/XendCheckpoint.py b/tools/python/xen/xend/XendCheckpoint.py index 7881130092..be8c299634 100644 --- a/tools/python/xen/xend/XendCheckpoint.py +++ b/tools/python/xen/xend/XendCheckpoint.py @@ -9,6 +9,7 @@ import os import re import string import threading +import fcntl from struct import pack, unpack, calcsize from xen.util.xpopen import xPopen3 @@ -230,6 +231,15 @@ def restore(xd, fd, dominfo = None, paused = False): forkHelper(cmd, fd, handler.handler, True) + # We don't want to pass this fd to any other children -- we + # might need to recover ths disk space that backs it. + try: + flags = fcntl.fcntl(fd, fcntl.F_GETFD) + flags |= fcntl.FD_CLOEXEC + fcntl.fcntl(fd, fcntl.F_SETFD, flags) + except: + pass + if handler.store_mfn is None: raise XendError('Could not read store MFN') From d04477b6028d4c10e880553e041705ca699c669f Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 14 Mar 2007 16:36:04 +0000 Subject: [PATCH 081/170] [XEN] 32on64 kexec: Make the compat page table cover the first 4G of physical memory. This gives the guest kernel more flexibility on where it places the control page. Signed-off-by: Ian Campbell --- xen/arch/x86/x86_64/compat_kexec.S | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/xen/arch/x86/x86_64/compat_kexec.S b/xen/arch/x86/x86_64/compat_kexec.S index c06db6fc7e..cc6f3d6fce 100644 --- a/xen/arch/x86/x86_64/compat_kexec.S +++ b/xen/arch/x86/x86_64/compat_kexec.S @@ -103,13 +103,13 @@ compat_page_list: /* * These compat page tables contain an identity mapping of the - * first 1G of the physical address space. + * first 4G of the physical address space. */ compat_pg_table: .long compat_pg_table_l2 + 0*PAGE_SIZE + 0x01 - __PAGE_OFFSET, 0 - .long 0, 0 - .long 0, 0 - .long 0, 0 + .long compat_pg_table_l2 + 1*PAGE_SIZE + 0x01 - __PAGE_OFFSET, 0 + .long compat_pg_table_l2 + 2*PAGE_SIZE + 0x01 - __PAGE_OFFSET, 0 + .long compat_pg_table_l2 + 3*PAGE_SIZE + 0x01 - __PAGE_OFFSET, 0 .align 4096,0 @@ -123,4 +123,7 @@ compat_pg_table_l2: .endif .endm - identmap + identmap 0x00000000 + identmap 0x40000000 + identmap 0x80000000 + identmap 0xc0000000 From a84c4f75e58ca86329372b6dcfd0bdcbc626c71f Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 14 Mar 2007 16:39:32 +0000 Subject: [PATCH 082/170] [LINUX] Kexec: Ensure that pages allocated for kexec have MFNs which are within the required limits. Previously we were lucky since most dom0 pages would be low enough but now Xen is more aggressive in giving out higher MFNs when it can. Signed-off-by: Ian Campbell --- linux-2.6-xen-sparse/kernel/kexec.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/linux-2.6-xen-sparse/kernel/kexec.c b/linux-2.6-xen-sparse/kernel/kexec.c index c46558f7da..a6e2120138 100644 --- a/linux-2.6-xen-sparse/kernel/kexec.c +++ b/linux-2.6-xen-sparse/kernel/kexec.c @@ -330,13 +330,27 @@ static int kimage_is_destination_range(struct kimage *image, return 0; } -static struct page *kimage_alloc_pages(gfp_t gfp_mask, unsigned int order) +static struct page *kimage_alloc_pages(gfp_t gfp_mask, unsigned int order, unsigned long limit) { struct page *pages; pages = alloc_pages(gfp_mask, order); if (pages) { unsigned int count, i; +#ifdef CONFIG_XEN + int address_bits; + + if (limit == ~0UL) + address_bits = BITS_PER_LONG; + else + address_bits = long_log2(limit); + + if (xen_create_contiguous_region((unsigned long)page_address(pages), + order, address_bits) < 0) { + __free_pages(pages, order); + return NULL; + } +#endif pages->mapping = NULL; set_page_private(pages, order); count = 1 << order; @@ -355,6 +369,9 @@ static void kimage_free_pages(struct page *page) count = 1 << order; for (i = 0; i < count; i++) ClearPageReserved(page + i); +#ifdef CONFIG_XEN + xen_destroy_contiguous_region((unsigned long)page_address(page), order); +#endif __free_pages(page, order); } @@ -400,7 +417,7 @@ static struct page *kimage_alloc_normal_control_pages(struct kimage *image, do { unsigned long pfn, epfn, addr, eaddr; - pages = kimage_alloc_pages(GFP_KERNEL, order); + pages = kimage_alloc_pages(GFP_KERNEL, order, KEXEC_CONTROL_MEMORY_LIMIT); if (!pages) break; pfn = kexec_page_to_pfn(pages); @@ -709,7 +726,7 @@ static struct page *kimage_alloc_page(struct kimage *image, kimage_entry_t *old; /* Allocate a page, if we run out of memory give up */ - page = kimage_alloc_pages(gfp_mask, 0); + page = kimage_alloc_pages(gfp_mask, 0, KEXEC_SOURCE_MEMORY_LIMIT); if (!page) return NULL; /* If the page cannot be used file it away */ From 8fafd2af0e7e434957ac8f6cadb2c04ba0062881 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 14 Mar 2007 16:58:30 +0000 Subject: [PATCH 083/170] [LINUX] 32on64 kdump: Allow a 32 bit kernel to read a 64 bit dump. Signed-off-by: Ian Campbell --- patches/linux-2.6.18/crash-kernel-32-on-64.patch | 11 +++++++++++ patches/linux-2.6.18/series | 1 + 2 files changed, 12 insertions(+) create mode 100644 patches/linux-2.6.18/crash-kernel-32-on-64.patch diff --git a/patches/linux-2.6.18/crash-kernel-32-on-64.patch b/patches/linux-2.6.18/crash-kernel-32-on-64.patch new file mode 100644 index 0000000000..8ea9378188 --- /dev/null +++ b/patches/linux-2.6.18/crash-kernel-32-on-64.patch @@ -0,0 +1,11 @@ +--- pristine-linux-2.6.18/include/asm-i386/elf.h 2006-09-20 04:42:06.000000000 +0100 ++++ linux-2.6.18-xen/include/asm-i386/elf.h 2007-03-14 16:42:30.000000000 +0000 +@@ -36,7 +36,7 @@ + * This is used to ensure we don't load something for the wrong architecture. + */ + #define elf_check_arch(x) \ +- (((x)->e_machine == EM_386) || ((x)->e_machine == EM_486)) ++ (((x)->e_machine == EM_386) || ((x)->e_machine == EM_486) || ((x)->e_machine == EM_X86_64)) + + /* + * These are used to set parameters in the core dumps. diff --git a/patches/linux-2.6.18/series b/patches/linux-2.6.18/series index 85bbae63e4..978fdacc42 100644 --- a/patches/linux-2.6.18/series +++ b/patches/linux-2.6.18/series @@ -19,3 +19,4 @@ x86-elfnote-as-preprocessor-macro.patch fixaddr-top.patch git-c06cb8b1c4d25e5b4d7a2d7c2462619de1e0dbc4.patch softlockup-no-idle-hz.patch +crash-kernel-32-on-64.patch From 1a2d69b0845acb9931421ebf77d3e73bd4067402 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Tue, 13 Mar 2007 22:12:18 +0000 Subject: [PATCH 084/170] In xm shell, add a space to the function names when tab-completing. Signed-off-by: Ewan Mellor --- tools/python/xen/xm/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 6c32e8529e..ad967d275e 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -557,7 +557,7 @@ class Shell(cmd.Cmd): if serverType == SERVER_XEN_API: res = server.xenapi._UNSUPPORTED_list_all_methods() for f in res: - setattr(Shell, 'do_' + f, self.default) + setattr(Shell, 'do_' + f + ' ', self.default) def preloop(self): cmd.Cmd.preloop(self) From 11392ee1b08ffd89ded3e4be89b3c197d9674a37 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Tue, 13 Mar 2007 22:13:40 +0000 Subject: [PATCH 085/170] Implement VM.{add_to,remove_from}_VCPUs_params. Signed-off-by: Ewan Mellor --- tools/python/xen/xend/XendAPI.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index 2d7a01bc1a..2c451b2b92 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -1040,6 +1040,8 @@ class XendAPI(object): ('resume', None), ('add_to_HVM_boot_params', None), ('remove_from_HVM_boot_params', None), + ('add_to_VCPUs_params', None), + ('remove_from_VCPUs_params', None), ('add_to_platform', None), ('remove_from_platform', None), ('add_to_other_config', None), @@ -1259,9 +1261,24 @@ class XendAPI(object): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_todo() - def VM_set_VCPUs_params(self, session, vm_ref, params): + def VM_set_VCPUs_params(self, session, vm_ref, value): + return self.VM_set('vcpus_params', session, vm_ref, value) + + def VM_add_to_VCPUs_params(self, session, vm_ref, key, value): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() + if 'vcpus_params' not in dom.info: + dom.info['vcpus_params'] = {} + dom.info['vcpus_params'][key] = value + return self._VM_save(dom) + + def VM_remove_from_VCPUs_params(self, session, vm_ref, key): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + if 'vcpus_params' in dom.info \ + and key in dom.info['vcpus_params']: + del dom.info['vcpus_params'][key] + return self._VM_save(dom) + else: + return xen_api_success_void() def VM_set_actions_after_shutdown(self, session, vm_ref, action): if action not in XEN_API_ON_NORMAL_EXIT: From de2105b78a3a05c891fbf92b2f671d6a302b55e3 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 14 Mar 2007 19:35:26 +0000 Subject: [PATCH 086/170] hvm: Firmware build requires dev86 (bcc) >= 0.16.14. Earlier versions (at least 0.16.0) generate incorrect code. Signed-off-by: Keir Fraser --- tools/firmware/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/firmware/Makefile b/tools/firmware/Makefile index 8091da46d3..b924fde793 100644 --- a/tools/firmware/Makefile +++ b/tools/firmware/Makefile @@ -14,10 +14,10 @@ SUBDIRS += hvmloader .PHONY: all all: - @set -e; if ! `which bcc 1>/dev/null 2>/dev/null`; then \ + @set -e; if [ $$((`bcc -v 2>&1 | grep version | cut -d' ' -f 3 | awk -F. '{ printf "0x%02x%02x%02x", $$1, $$2, $$3}'`)) -lt $$((0x00100e)) ] ; then \ echo "***********************************************************"; \ - echo "WARNING: Install dev86 package to build firmware!"; \ - echo " (http://www.cix.co.uk/~mayday)"; \ + echo "Require dev86 package version >= 0.16.14 to build firmware!"; \ + echo "(visit http://www.cix.co.uk/~mayday for more information)"; \ echo "***********************************************************"; \ else \ for subdir in $(SUBDIRS); do \ From 5fc295e4de74feac7d7641efaf942d0ae2f48141 Mon Sep 17 00:00:00 2001 From: Jake Wires Date: Wed, 14 Mar 2007 14:18:51 -0700 Subject: [PATCH 087/170] [BLKTAP] remove spurious error message Signed-off-by: Jake Wires --- linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c index 1b4bda2184..5fa4c31a9b 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c @@ -299,7 +299,9 @@ static void tap_backend_changed(struct xenbus_watch *watch, * and disk info to xenstore */ err = xenbus_gather(XBT_NIL, dev->nodename, "info", "%lu", &info, - NULL); + NULL); + if (XENBUS_EXIST_ERR(err)) + return; if (err) { xenbus_dev_error(dev, err, "getting info"); return; From 42b966d15c79506751bf53d49cc04d8d1966d9e9 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 14 Mar 2007 20:27:57 +0000 Subject: [PATCH 088/170] Added Xen-API support to xm shutdown. Signed-off-by: Tom Wilkie --- tools/python/xen/xm/shutdown.py | 37 ++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/tools/python/xen/xm/shutdown.py b/tools/python/xen/xm/shutdown.py index 88d36dfba1..8ada520e62 100644 --- a/tools/python/xen/xm/shutdown.py +++ b/tools/python/xen/xm/shutdown.py @@ -21,7 +21,8 @@ import time from xen.xend import sxp from opts import * -from main import server +from main import server, serverType, SERVER_XEN_API, get_single_vm +from xen.xend.XendAPIConstants import * gopts = Opts(use="""[options] [DOM] @@ -49,6 +50,9 @@ gopts.opt('reboot', short='R', use='Shutdown and reboot.') def wait_reboot(opts, doms, rcs): + if serverType == SERVER_XEN_API: + opts.err("Cannot wait for reboot w/ XenAPI (yet)") + while doms: alive = server.xend.domains(0) reboot = [] @@ -68,7 +72,12 @@ def wait_reboot(opts, doms, rcs): def wait_shutdown(opts, doms): while doms: - alive = server.xend.domains(0) + if serverType == SERVER_XEN_API: + alive = [dom for dom in server.xenapi.VM.get_all() + if server.xenapi.VM.get_power_state(dom) == + XEN_API_VM_POWER_STATE[XEN_API_VM_POWER_STATE_RUNNING]] + else: + alive = server.xend.domains(0) dead = [] for d in doms: if d in alive: continue @@ -82,8 +91,16 @@ def wait_shutdown(opts, doms): def shutdown(opts, doms, mode, wait): rcs = {} for d in doms: - rcs[d] = server.xend.domain.getRestartCount(d) - server.xend.domain.shutdown(d, mode) + if serverType == SERVER_XEN_API: + if mode == 'halt': + server.xenapi.VM.clean_shutdown(d) + if mode == 'reboot': + server.xenapi.VM.clean_reboot(d) + if mode == 'poweroff': + server.xenapi.VM.clean_shutdown(d) + else: + rcs[d] = server.xend.domain.getRestartCount(d) + server.xend.domain.shutdown(d, mode) if wait: if mode == 'reboot': @@ -103,9 +120,13 @@ def shutdown_mode(opts): return 'poweroff' def main_all(opts, args): - doms = server.xend.domains(0) - dom0_name = sxp.child_value(server.xend.domain(0), 'name') - doms.remove(dom0_name) + if serverType == SERVER_XEN_API: + doms = [dom for dom in server.xenapi.VM.get_all() + if not server.xenapi.VM.get_is_control_domain(dom)] + else: + doms = server.xend.domains(0) + dom0_name = sxp.child_value(server.xend.domain(0), 'name') + doms.remove(dom0_name) mode = shutdown_mode(opts) shutdown(opts, doms, mode, opts.vals.wait) @@ -113,6 +134,8 @@ def main_dom(opts, args): if len(args) == 0: opts.err('No domain parameter given') if len(args) > 1: opts.err('No multiple domain parameters allowed') dom = args[0] + if serverType == SERVER_XEN_API: + dom = get_single_vm(dom) mode = shutdown_mode(opts) shutdown(opts, [ dom ], mode, opts.vals.wait) From ae6780b241d8e6f389d5c25e4cac34a02e22a459 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 14 Mar 2007 20:41:56 +0000 Subject: [PATCH 089/170] Implement VM_metrics Xen-API class. Signed-off-by: Tom Wilkie Signed-off-by: Ewan Mellor --- tools/python/xen/xend/XendAPI.py | 55 ++++++++++++++++----- tools/python/xen/xend/XendDomainInfo.py | 10 ++++ tools/python/xen/xend/XendVMMetrics.py | 65 +++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 13 deletions(-) create mode 100644 tools/python/xen/xend/XendVMMetrics.py diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index 2c451b2b92..c1b13cb595 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -31,6 +31,7 @@ from xen.xend.XendError import * from xen.xend.XendClient import ERROR_INVALID_DOMAIN from xen.xend.XendLogging import log from xen.xend.XendTask import XendTask +from xen.xend.XendVMMetrics import XendVMMetrics from xen.xend.XendAPIConstants import * from xen.util.xmlrpclib2 import stringify @@ -192,6 +193,16 @@ def valid_vm(func): _check_ref(XendDomain.instance().is_valid_vm, 'VM', func, *args, **kwargs) +def valid_vm_metrics(func): + """Decorator to verify if vm_metrics_ref is valid before calling method. + + @param func: function with params: (self, session, vm_metrics_ref, ...) + @rtype: callable object + """ + return lambda *args, **kwargs: \ + _check_ref(XendVMMetrics.is_valid_vm_metrics, + 'VM_metrics', func, *args, **kwargs) + def valid_network(func): """Decorator to verify if network_ref is valid before calling method. @@ -400,6 +411,7 @@ class XendAPI(object): 'host_metrics' : valid_host_metrics, 'network' : valid_network, 'VM' : valid_vm, + 'VM_metrics' : valid_vm_metrics, 'VBD' : valid_vbd, 'VBD_metrics' : valid_vbd_metrics, 'VIF' : valid_vif, @@ -990,11 +1002,9 @@ class XendAPI(object): VM_attr_ro = ['power_state', 'resident_on', - 'memory_actual', 'memory_static_max', 'memory_static_min', 'VCPUs_number', - 'VCPUs_utilisation', 'consoles', 'VIFs', 'VBDs', @@ -1002,6 +1012,7 @@ class XendAPI(object): 'tools_version', 'domid', 'is_control_domain', + 'metrics' ] VM_attr_rw = ['name_label', @@ -1098,11 +1109,7 @@ class XendAPI(object): def VM_get_resident_on(self, session, vm_ref): return xen_api_success(XendNode.instance().uuid) - - def VM_get_memory_actual(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() # unsupported by xc - + def VM_get_memory_static_max(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success(dom.get_memory_static_max()) @@ -1115,10 +1122,6 @@ class XendAPI(object): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success(dom.getVCpuCount()) - def VM_get_VCPUs_utilisation(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_vcpus_util()) - def VM_get_VIFs(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_success(dom.get_vifs()) @@ -1139,6 +1142,10 @@ class XendAPI(object): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return dom.get_tools_version() + def VM_get_metrics(self, _, vm_ref): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + return xen_api_success(dom.get_metrics()) + # attributes (rw) def VM_get_name_label(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) @@ -1418,11 +1425,9 @@ class XendAPI(object): 'memory_static_max': xeninfo.get_memory_static_max(), 'memory_dynamic_min': xeninfo.get_memory_dynamic_min(), 'memory_dynamic_max': xeninfo.get_memory_dynamic_max(), - 'memory_actual': xeninfo.get_memory_static_min(), 'VCPUs_policy': xeninfo.get_vcpus_policy(), 'VCPUs_params': xeninfo.get_vcpus_params(), 'VCPUs_number': xeninfo.getVCpuCount(), - 'VCPUs_utilisation': xeninfo.get_vcpus_util(), 'actions_after_shutdown': xeninfo.get_on_shutdown(), 'actions_after_reboot': xeninfo.get_on_reboot(), 'actions_after_suspend': xeninfo.get_on_suspend(), @@ -1497,6 +1502,30 @@ class XendAPI(object): return XendTask.log_progress(0, 100, do_vm_func, "domain_unpause", vm_ref) + # Xen API: Class VM_metrics + # ---------------------------------------------------------------- + + VM_metrics_attr_ro = ['memory_actual', + 'vcpus_number', + 'vcpus_utilisation'] + VM_metrics_attr_rw = [] + VM_metrics_methods = [] + + def _VM_metrics_get(self, ref): + return XendVMMetrics.get_by_uuid(ref) + + def VM_metrics_get_record(self, _, ref): + return xen_api_success(self._VM_metrics_get(ref).get_record()) + + def VM_metrics_get_memory_actual(self, _, ref): + return xen_api_success(self._VM_metrics_get(ref).get_memory_actual()) + + def VM_metrics_get_vcpus_number(self, _, ref): + return xen_api_success(self._VM_metrics_get(ref).get_vcpus_number()) + + def VM_metrics_get_vcpus_utilisation(self, _, ref): + return xen_api_success(self._VM_metrics_get(ref).get_metrics_get_vcpus_utilisation()) + # Xen API: Class VBD # ---------------------------------------------------------------- diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index e4f30fc6e4..bec2c5ad2c 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -51,6 +51,8 @@ from xen.xend.xenstore.xswatch import xswatch from xen.xend.XendConstants import * from xen.xend.XendAPIConstants import * +from xen.xend.XendVMMetrics import XendVMMetrics + MIGRATE_TIMEOUT = 30.0 BOOTLOADER_LOOPBACK_DEVICE = '/dev/xvdp' @@ -369,6 +371,8 @@ class XendDomainInfo: self._augmentInfo(priv) self._checkName(self.info['name_label']) + + self.metrics = XendVMMetrics(uuid.createString(), self) # @@ -627,6 +631,10 @@ class XendDomainInfo: except RuntimeError, exn: raise XendError(str(exn)) + + def getDomInfo(self): + return dom_get(self.domid) + # # internal functions ... TODO: re-categorised # @@ -2060,6 +2068,8 @@ class XendDomainInfo: return self.info.get('pci_bus', '') def get_tools_version(self): return self.info.get('tools_version', {}) + def get_metrics(self): + return self.metrics.get_uuid(); def get_on_shutdown(self): after_shutdown = self.info.get('actions_after_shutdown') diff --git a/tools/python/xen/xend/XendVMMetrics.py b/tools/python/xen/xend/XendVMMetrics.py new file mode 100644 index 0000000000..8589e35171 --- /dev/null +++ b/tools/python/xen/xend/XendVMMetrics.py @@ -0,0 +1,65 @@ +#============================================================================ +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#============================================================================ +# Copyright (c) 2006-2007 Xensource Inc. +#============================================================================ + +from xen.xend.XendLogging import log + +instances = {} + +class XendVMMetrics: + """VM Metrics.""" + + def get_by_uuid(_, uuid): + return instances[uuid] + + get_by_uuid = classmethod(get_by_uuid) + + def is_valid_vm_metrics(_, uuid): + return uuid in instances + + is_valid_vm_metrics = classmethod(is_valid_vm_metrics) + + def __init__(self, uuid, xend_domain_instance): + self.uuid = uuid + self.xend_domain_instance = xend_domain_instance + instances[uuid] = self + + def get_uuid(self): + return self.uuid + + def get_memory_actual(self): + return self.get_record()["memory_actual"] + + def get_vcpus_number(self): + return self.get_record()["vcpus_number"] + + def get_vcpus_utilisation(self): + return self.xend_domain_instance.get_vcpus_util() + + def get_record(self): + domInfo = self.xend_domain_instance.getDomInfo() + if domInfo: + return { 'uuid' : self.uuid, + 'memory_actual' : domInfo["mem_kb"] * 1024, + 'vcpus_number' : domInfo["online_vcpus"], + 'vcpus_utilisation' : self.get_vcpus_utilisation() + } + else: + return { 'uuid' : self.uuid, + 'memory_actual' : 0, + 'vcpus_number' : 0, + 'vcpus_utilisation' : {} + } From eacb86fc1be2c6fb771e114a727c3976a2134496 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 14 Mar 2007 21:02:58 +0000 Subject: [PATCH 090/170] Added Xen-API features needed to implement xm info: host.sched_policy (replacing VM.VCPUs_policy, which never made sense), and host.cpu_configuration. Add other details into either host.software_version or host.other_config as appropriate. Implement xm info and the scheduler-detection check using this. Signed-off-by: Ewan Mellor Signed-off-by: Tom Wilkie --- tools/python/xen/xend/XendAPI.py | 32 +++---- tools/python/xen/xend/XendDomainInfo.py | 9 -- tools/python/xen/xend/XendNode.py | 53 +++++++++++- tools/python/xen/xm/main.py | 109 +++++++++++++++++++----- 4 files changed, 156 insertions(+), 47 deletions(-) diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index c1b13cb595..7aadf5f5b1 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -641,6 +641,7 @@ class XendAPI(object): host_attr_ro = ['software_version', 'resident_VMs', 'host_CPUs', + 'cpu_configuration', 'metrics', 'capabilities', 'supported_bootloaders', @@ -650,6 +651,7 @@ class XendAPI(object): 'API_version_vendor_implementation'] host_attr_rw = ['name_label', + 'sched_policy', 'name_description', 'other_config'] @@ -712,7 +714,13 @@ class XendAPI(object): return xen_api_success(XendNode.instance().get_capabilities()) def host_get_supported_bootloaders(self, session, host_ref): return xen_api_success(['pygrub']) - + def host_get_sched_policy(self, _, host_ref): + return xen_api_success(XendNode.instance().get_vcpus_policy()) + def host_set_sched_policy(self, _, host_ref, policy): + return xen_api_todo() + def host_get_cpu_configuration(self, _, host_ref): + return xen_api_success(XendNode.instance().get_cpu_configuration()) + # object methods def host_disable(self, session, host_ref): XendDomain.instance().set_allow_new_domains(False) @@ -747,9 +755,11 @@ class XendAPI(object): 'other_config': node.other_config, 'resident_VMs': dom.get_domain_refs(), 'host_CPUs': node.get_host_cpu_refs(), + 'cpu_configuration': node.get_cpu_configuration(), 'metrics': node.host_metrics_uuid, 'capabilities': node.get_capabilities(), - 'supported_bootloaders': 'pygrub'} + 'supported_bootloaders': 'pygrub', + 'sched_policy': node.get_vcpus_policy()} return xen_api_success(record) # class methods @@ -771,7 +781,8 @@ class XendAPI(object): 'modelname', 'stepping', 'flags', - 'utilisation'] + 'utilisation', + 'features'] # attributes def _host_cpu_get(self, ref, field): @@ -780,6 +791,8 @@ class XendAPI(object): def host_cpu_get_host(self, _, ref): return xen_api_success(XendNode.instance().uuid) + def host_cpu_get_features(self, _, ref): + return self._host_cpu_get(ref, 'features') def host_cpu_get_number(self, _, ref): return self._host_cpu_get(ref, 'number') def host_cpu_get_vendor(self, _, ref): @@ -1022,7 +1035,6 @@ class XendAPI(object): 'auto_power_on', 'memory_dynamic_max', 'memory_dynamic_min', - 'VCPUs_policy', 'VCPUs_params', 'actions_after_shutdown', 'actions_after_reboot', @@ -1071,7 +1083,6 @@ class XendAPI(object): 'memory_dynamic_max', 'memory_dynamic_min', 'memory_static_min', - 'VCPUs_policy', 'VCPUs_params', 'actions_after_shutdown', 'actions_after_reboot', @@ -1169,11 +1180,7 @@ class XendAPI(object): def VM_get_memory_dynamic_min(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_memory_dynamic_min()) - - def VM_get_VCPUs_policy(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_vcpus_policy()) + return xen_api_success(dom.get_memory_dynamic_min()) def VM_get_VCPUs_params(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) @@ -1264,10 +1271,6 @@ class XendAPI(object): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) return xen_api_todo() - def VM_set_VCPUs_policy(self, session, vm_ref, policy): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() - def VM_set_VCPUs_params(self, session, vm_ref, value): return self.VM_set('vcpus_params', session, vm_ref, value) @@ -1425,7 +1428,6 @@ class XendAPI(object): 'memory_static_max': xeninfo.get_memory_static_max(), 'memory_dynamic_min': xeninfo.get_memory_dynamic_min(), 'memory_dynamic_max': xeninfo.get_memory_dynamic_max(), - 'VCPUs_policy': xeninfo.get_vcpus_policy(), 'VCPUs_params': xeninfo.get_vcpus_params(), 'VCPUs_number': xeninfo.getVCpuCount(), 'actions_after_shutdown': xeninfo.get_on_shutdown(), diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index bec2c5ad2c..58af5f28ad 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -2045,15 +2045,6 @@ class XendDomainInfo: return self.info.get('memory_dynamic_max', 0) def get_memory_dynamic_min(self): return self.info.get('memory_dynamic_min', 0) - - def get_vcpus_policy(self): - sched_id = xc.sched_id_get() - if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF: - return 'sedf' - elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT: - return 'credit' - else: - return 'unknown' def get_vcpus_params(self): if self.getDomid() is None: return self.info['vcpus_params'] diff --git a/tools/python/xen/xend/XendNode.py b/tools/python/xen/xend/XendNode.py index 3b261d8722..954b57a2de 100644 --- a/tools/python/xen/xend/XendNode.py +++ b/tools/python/xen/xend/XendNode.py @@ -75,6 +75,11 @@ class XendNode: self.other_config = {} self.cpus = {} self.host_metrics_uuid = uuid.createString() + + # put some arbitrary params in other_config as this + # is directly exposed via XenAPI + self.other_config["xen_pagesize"] = self.xeninfo_dict()["xen_pagesize"] + self.other_config["platform_params"] = self.xeninfo_dict()["platform_params"] # load CPU UUIDs saved_cpus = self.state_store.load_state('cpu') @@ -353,14 +358,37 @@ class XendNode: def xen_version(self): info = self.xc.xeninfo() + try: from xen import VERSION - return {'Xen': '%(xen_major)d.%(xen_minor)d' % info, + info = {'Xen': '%(xen_major)d.%(xen_minor)d' % info, 'Xend': VERSION} except (ImportError, AttributeError): - return {'Xen': '%(xen_major)d.%(xen_minor)d' % info, + info = {'Xen': '%(xen_major)d.%(xen_minor)d' % info, 'Xend': '3.0.3'} + # Add xend_config_format + info.update(self.xendinfo_dict()) + + # Add version info about machine + info.update(self.nodeinfo_dict()) + + # Add specific xen version info + xeninfo_dict = self.xeninfo_dict() + + info.update({ + "xen_major": xeninfo_dict["xen_major"], + "xen_minor": xeninfo_dict["xen_minor"], + "xen_extra": xeninfo_dict["xen_extra"], + "cc_compiler": xeninfo_dict["cc_compiler"], + "cc_compile_by": xeninfo_dict["cc_compile_by"], + "cc_compile_domain": xeninfo_dict["cc_compile_domain"], + "cc_compile_date": xeninfo_dict["cc_compile_date"], + "xen_changeset": xeninfo_dict["xen_changeset"] + }) + + return info + def get_name(self): return self.name @@ -415,6 +443,27 @@ class XendNode: return 0.0 + def get_vcpus_policy(self): + sched_id = self.xc.sched_id_get() + if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF: + return 'sedf' + elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT: + return 'credit' + else: + return 'unknown' + + def get_cpu_configuration(self): + phys_info = self.physinfo_dict() + + cpu_info = { + "nr_nodes": phys_info["nr_nodes"], + "sockets_per_node": phys_info["sockets_per_node"], + "cores_per_socket": phys_info["cores_per_socket"], + "threads_per_core": phys_info["threads_per_core"] + } + + return cpu_info + # # Network Functions # diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index ad967d275e..40f9059853 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -750,11 +750,14 @@ def parse_doms_info(info): } def check_sched_type(sched): - current = 'unknown' - for x in server.xend.node.info()[1:]: - if len(x) > 1 and x[0] == 'xen_scheduler': - current = x[1] - break + if serverType == SERVER_XEN_API: + current = server.xenapi.host.get_sched_policy(server.xenapi.session.get_this_host()) + else: + current = 'unknown' + for x in server.xend.node.info()[1:]: + if len(x) > 1 and x[0] == 'xen_scheduler': + current = x[1] + break if sched != current: err("Xen is running with the %s scheduler" % current) sys.exit(1) @@ -1095,28 +1098,43 @@ def xm_mem_max(args): arg_check(args, "mem-max", 2) dom = args[0] - mem = int_unit(args[1], 'm') - server.xend.domain.maxmem_set(dom, mem) + if serverType == SERVER_XEN_API: + mem = int_unit(args[1], 'k') * 1024 + server.xenapi.VM.set_memory_static_max(get_single_vm(dom), mem) + else: + mem = int_unit(args[1], 'm') + server.xend.domain.maxmem_set(dom, mem) def xm_mem_set(args): arg_check(args, "mem-set", 2) dom = args[0] - mem_target = int_unit(args[1], 'm') - server.xend.domain.setMemoryTarget(dom, mem_target) + if serverType == SERVER_XEN_API: + mem_target = int_unit(args[1], 'k') * 1024 + server.xenapi.VM.set_memory_dynamic_max(get_single_vm(dom), mem_target) + server.xenapi.VM.set_memory_dynamic_min(get_single_vm(dom), mem_target) + else: + mem_target = int_unit(args[1], 'm') + server.xend.domain.setMemoryTarget(dom, mem_target) def xm_vcpu_set(args): arg_check(args, "vcpu-set", 2) - - server.xend.domain.setVCpuCount(args[0], int(args[1])) + dom = args[0] + vcpus = int(args[1]) + + if serverType == SERVER_XEN_API: + server.xenapi.VM.set_vcpus_live(get_single_vm(dom), vcpus) + else: + server.xend.domain.setVCpuCount(dom, vcpus) def xm_destroy(args): arg_check(args, "destroy", 1) dom = args[0] + if serverType == SERVER_XEN_API: server.xenapi.VM.hard_shutdown(get_single_vm(dom)) else: @@ -1135,9 +1153,12 @@ def xm_domname(args): arg_check(args, "domname", 1) name = args[0] - - dom = server.xend.domain(name) - print sxp.child_value(dom, 'name') + + if serverType == SERVER_XEN_API: + print server.xenapi.VM.get_domid(get_single_vm(dom)) + else: + dom = server.xend.domain(name) + print sxp.child_value(dom, 'name') def xm_sched_sedf(args): def ns_to_ms(val): @@ -1285,13 +1306,59 @@ def xm_sched_credit(args): def xm_info(args): arg_check(args, "info", 0) - info = server.xend.node.info() - - for x in info[1:]: - if len(x) < 2: - print "%-23s: (none)" % x[0] - else: - print "%-23s:" % x[0], x[1] + if serverType == SERVER_XEN_API: + + # Need to fake out old style xm info as people rely on parsing it + + host_record = server.xenapi.host.get_record( + server.xenapi.session.get_this_host()) + + host_cpu_records = map(server.xenapi.host_cpu.get_record, host_record["host_CPUs"]) + + host_metrics_record = server.xenapi.host_metrics.get_record(host_record["metrics"]) + + info = { + "host": host_record["name_label"], + "release": host_record["software_version"]["release"], + "version": host_record["software_version"]["version"], + "machine": host_record["software_version"]["machine"], + "nr_cpus": len(host_record["host_CPUs"]), + "nr_nodes": host_record["cpu_configuration"]["nr_nodes"], + "sockets_per_node": host_record["cpu_configuration"]["sockets_per_node"], + "cores_per_socket": host_record["cpu_configuration"]["cores_per_socket"], + "threads_per_core": host_record["cpu_configuration"]["threads_per_core"], + "cpu_mhz": sum([int(host_cpu_record["speed"]) for host_cpu_record in host_cpu_records]) + / len(host_cpu_records), + "hw_caps": host_cpu_records[0]["features"], + "total_memory": int(host_metrics_record["memory_total"])/1024/1024, + "free_memory": int(host_metrics_record["memory_free"])/1024/1024, + "xen_major": host_record["software_version"]["xen_major"], + "xen_minor": host_record["software_version"]["xen_minor"], + "xen_extra": host_record["software_version"]["xen_extra"], + "xen_caps": " ".join(host_record["capabilities"]), + "xen_scheduler": host_record["sched_policy"], + "xen_pagesize": host_record["other_config"]["xen_pagesize"], + "platform_params": host_record["other_config"]["platform_params"], + "xen_changeset": host_record["software_version"]["xen_changeset"], + "cc_compiler": host_record["software_version"]["cc_compiler"], + "cc_compile_by": host_record["software_version"]["cc_compile_by"], + "cc_compile_domain": host_record["software_version"]["cc_compile_domain"], + "cc_compile_date": host_record["software_version"]["cc_compile_date"], + "xend_config_format":host_record["software_version"]["xend_config_format"] + } + + sorted = info.items() + sorted.sort(lambda (x1,y1), (x2,y2): -cmp(x1,x2)) + + for (k, v) in sorted: + print "%-23s:" % k, v + else: + info = server.xend.node.info() + for x in info[1:]: + if len(x) < 2: + print "%-23s: (none)" % x[0] + else: + print "%-23s:" % x[0], x[1] def xm_console(args): arg_check(args, "console", 1, 2) From b0c9363ed88fa8e5baaa8d741f7744d75451011c Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 14 Mar 2007 21:04:04 +0000 Subject: [PATCH 091/170] Added VM_metrics.get_all. Signed-off-by: Tom Wilkie --- tools/python/xen/xend/XendAPI.py | 3 +++ tools/python/xen/xend/XendVMMetrics.py | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index 7aadf5f5b1..62f42e8e02 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -1516,6 +1516,9 @@ class XendAPI(object): def _VM_metrics_get(self, ref): return XendVMMetrics.get_by_uuid(ref) + def VM_metrics_get_all(self, _): + return xen_api_success(XendVMMetrics.get_all()) + def VM_metrics_get_record(self, _, ref): return xen_api_success(self._VM_metrics_get(ref).get_record()) diff --git a/tools/python/xen/xend/XendVMMetrics.py b/tools/python/xen/xend/XendVMMetrics.py index 8589e35171..d531411b30 100644 --- a/tools/python/xen/xend/XendVMMetrics.py +++ b/tools/python/xen/xend/XendVMMetrics.py @@ -31,6 +31,11 @@ class XendVMMetrics: return uuid in instances is_valid_vm_metrics = classmethod(is_valid_vm_metrics) + + def get_all(_): + return instances.keys() + + get_all = classmethod(get_all) def __init__(self, uuid, xend_domain_instance): self.uuid = uuid From 47123a36380ed5cf1c93d1c63043cee1da1223c1 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 14 Mar 2007 21:34:43 +0000 Subject: [PATCH 092/170] Fix typo. Signed-off-by: Tom Wilkie --- tools/python/xen/xm/addlabel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/python/xen/xm/addlabel.py b/tools/python/xen/xm/addlabel.py index af176da433..2d42d6702d 100644 --- a/tools/python/xen/xm/addlabel.py +++ b/tools/python/xen/xm/addlabel.py @@ -17,7 +17,7 @@ # Author: Bryan D. Payne #============================================================================ -"""Labeling a domain configuration file or a resoruce. +"""Labeling a domain configuration file or a resource. """ import os import sys From a72d446f86418dcfaf346ff13c3c25ea689724e1 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 14 Mar 2007 21:37:00 +0000 Subject: [PATCH 093/170] Fix typo in xm-test. Signed-off-by: Tom Wilkie --- tools/xm-test/tests/destroy/01_destroy_basic_pos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/xm-test/tests/destroy/01_destroy_basic_pos.py b/tools/xm-test/tests/destroy/01_destroy_basic_pos.py index 3d007b12a4..02e31d6aa8 100644 --- a/tools/xm-test/tests/destroy/01_destroy_basic_pos.py +++ b/tools/xm-test/tests/destroy/01_destroy_basic_pos.py @@ -37,4 +37,4 @@ if not re.search("proc", run["output"]): # destroy domain - positive test status, output = traceCommand("xm destroy %s" % domain.getName()) if status != 0: - FAIL("xm destroy returned invalud %i != 0" % status) + FAIL("xm destroy returned invalid %i != 0" % status) From efcaa9d8d3f050ecc03285f6215ab47d646162cc Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 14 Mar 2007 21:59:11 +0000 Subject: [PATCH 094/170] Match recent removal of VM.VCPUs_policy. Signed-off-by: Ewan Mellor --- docs/xen-api/xenapi-datamodel.tex | 67 ------------------------------- tools/libxen/include/xen_vm.h | 15 ------- tools/libxen/src/xen_vm.c | 37 ----------------- tools/libxen/test/test_bindings.c | 1 - 4 files changed, 120 deletions(-) diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex index ed6e0081b6..1b18834d03 100644 --- a/docs/xen-api/xenapi-datamodel.tex +++ b/docs/xen-api/xenapi-datamodel.tex @@ -1039,7 +1039,6 @@ $\mathit{RW}$ & {\tt memory/static\_max} & int & Statically-set (i.e. absolute) $\mathit{RW}$ & {\tt memory/dynamic\_max} & int & Dynamic maximum (bytes) \\ $\mathit{RW}$ & {\tt memory/dynamic\_min} & int & Dynamic minimum (bytes) \\ $\mathit{RW}$ & {\tt memory/static\_min} & int & Statically-set (i.e. absolute) mininum (bytes) \\ -$\mathit{RW}$ & {\tt VCPUs/policy} & string & the name of the VCPU scheduling policy to be applied \\ $\mathit{RW}$ & {\tt VCPUs/params} & (string $\rightarrow$ string) Map & configuration parameters for the selected VCPU policy \\ $\mathit{RW}$ & {\tt VCPUs/max} & int & Max number of VCPUs \\ $\mathit{RW}$ & {\tt VCPUs/at\_startup} & int & Boot number of VCPUs \\ @@ -2175,72 +2174,6 @@ void -\vspace{0.3cm} -\vspace{0.3cm} -\vspace{0.3cm} -\subsubsection{RPC name:~get\_VCPUs\_policy} - -{\bf Overview:} -Get the VCPUs/policy field of the given VM. - - \noindent {\bf Signature:} -\begin{verbatim} string get_VCPUs_policy (session_id s, VM ref self)\end{verbatim} - - -\noindent{\bf Arguments:} - - -\vspace{0.3cm} -\begin{tabular}{|c|c|p{7cm}|} - \hline -{\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & reference to the object \\ \hline - -\end{tabular} - -\vspace{0.3cm} - - \noindent {\bf Return Type:} -{\tt -string -} - - -value of the field -\vspace{0.3cm} -\vspace{0.3cm} -\vspace{0.3cm} -\subsubsection{RPC name:~set\_VCPUs\_policy} - -{\bf Overview:} -Set the VCPUs/policy field of the given VM. - - \noindent {\bf Signature:} -\begin{verbatim} void set_VCPUs_policy (session_id s, VM ref self, string value)\end{verbatim} - - -\noindent{\bf Arguments:} - - -\vspace{0.3cm} -\begin{tabular}{|c|c|p{7cm}|} - \hline -{\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VM ref } & self & reference to the object \\ \hline - -{\tt string } & value & New value to set \\ \hline - -\end{tabular} - -\vspace{0.3cm} - - \noindent {\bf Return Type:} -{\tt -void -} - - - \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} diff --git a/tools/libxen/include/xen_vm.h b/tools/libxen/include/xen_vm.h index 781e8ec8cd..ddce6a8d1d 100644 --- a/tools/libxen/include/xen_vm.h +++ b/tools/libxen/include/xen_vm.h @@ -87,7 +87,6 @@ typedef struct xen_vm_record int64_t memory_dynamic_max; int64_t memory_dynamic_min; int64_t memory_static_min; - char *vcpus_policy; xen_string_string_map *vcpus_params; int64_t vcpus_max; int64_t vcpus_at_startup; @@ -322,13 +321,6 @@ extern bool xen_vm_get_memory_static_min(xen_session *session, int64_t *result, xen_vm vm); -/** - * Get the VCPUs/policy field of the given VM. - */ -extern bool -xen_vm_get_vcpus_policy(xen_session *session, char **result, xen_vm vm); - - /** * Get the VCPUs/params field of the given VM. */ @@ -567,13 +559,6 @@ extern bool xen_vm_set_memory_static_min(xen_session *session, xen_vm vm, int64_t static_min); -/** - * Set the VCPUs/policy field of the given VM. - */ -extern bool -xen_vm_set_vcpus_policy(xen_session *session, xen_vm vm, char *policy); - - /** * Set the VCPUs/params field of the given VM. */ diff --git a/tools/libxen/src/xen_vm.c b/tools/libxen/src/xen_vm.c index 64f04a3f8f..f80916188e 100644 --- a/tools/libxen/src/xen_vm.c +++ b/tools/libxen/src/xen_vm.c @@ -88,9 +88,6 @@ static const struct_member xen_vm_record_struct_members[] = { .key = "memory_static_min", .type = &abstract_type_int, .offset = offsetof(xen_vm_record, memory_static_min) }, - { .key = "VCPUs_policy", - .type = &abstract_type_string, - .offset = offsetof(xen_vm_record, vcpus_policy) }, { .key = "VCPUs_params", .type = &abstract_type_string_string_map, .offset = offsetof(xen_vm_record, vcpus_params) }, @@ -191,7 +188,6 @@ xen_vm_record_free(xen_vm_record *record) free(record->name_description); xen_vdi_record_opt_free(record->suspend_vdi); xen_host_record_opt_free(record->resident_on); - free(record->vcpus_policy); xen_string_string_map_free(record->vcpus_params); xen_console_record_opt_set_free(record->consoles); xen_vif_record_opt_set_free(record->vifs); @@ -497,23 +493,6 @@ xen_vm_get_memory_static_min(xen_session *session, int64_t *result, xen_vm vm) } -bool -xen_vm_get_vcpus_policy(xen_session *session, char **result, xen_vm vm) -{ - abstract_value param_values[] = - { - { .type = &abstract_type_string, - .u.string_val = vm } - }; - - abstract_type result_type = abstract_type_string; - - *result = NULL; - XEN_CALL_("VM.get_VCPUs_policy"); - return session->ok; -} - - bool xen_vm_get_vcpus_params(xen_session *session, xen_string_string_map **result, xen_vm vm) { @@ -1073,22 +1052,6 @@ xen_vm_set_memory_static_min(xen_session *session, xen_vm vm, int64_t static_min } -bool -xen_vm_set_vcpus_policy(xen_session *session, xen_vm vm, char *policy) -{ - abstract_value param_values[] = - { - { .type = &abstract_type_string, - .u.string_val = vm }, - { .type = &abstract_type_string, - .u.string_val = policy } - }; - - xen_call_(session, "VM.set_VCPUs_policy", param_values, 2, NULL, NULL); - return session->ok; -} - - bool xen_vm_set_vcpus_params(xen_session *session, xen_vm vm, xen_string_string_map *params) { diff --git a/tools/libxen/test/test_bindings.c b/tools/libxen/test/test_bindings.c index 8e89ee5356..f18c5c5ac5 100644 --- a/tools/libxen/test/test_bindings.c +++ b/tools/libxen/test/test_bindings.c @@ -373,7 +373,6 @@ static xen_vm create_new_vm(xen_session *session, bool hvm) .memory_dynamic_max = 256, .memory_dynamic_min = 128, .memory_static_min = 128, - .vcpus_policy = "credit", .vcpus_params = vcpus_params, .vcpus_max = 4, .vcpus_at_startup = 2, From 3c924c8c4c2bc468e4056059d53e7945c9d6d336 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 14 Mar 2007 23:12:59 +0000 Subject: [PATCH 095/170] Trap bad return values from Xen-API method handlers, and return an internal error. Signed-off-by: Ewan Mellor --- tools/python/xen/util/xmlrpclib2.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tools/python/xen/util/xmlrpclib2.py b/tools/python/xen/util/xmlrpclib2.py index a77b61b5ee..0d0f3ade20 100644 --- a/tools/python/xen/util/xmlrpclib2.py +++ b/tools/python/xen/util/xmlrpclib2.py @@ -200,6 +200,18 @@ class TCPXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer): else: response = self._dispatch(method, params) + if self.xenapi and \ + (response is None or + not isinstance(response, dict) or + 'Status' not in response): + log.exception('Internal error handling %s: Invalid result %s', + method, response) + response = { "Status": "Failure", + "ErrorDescription": + ['INTERNAL_ERROR', + 'Invalid result %s handling %s' % + (response, method)]} + # With either Unicode or normal strings, we can only transmit # \t, \n, \r, \u0020-\ud7ff, \ue000-\ufffd, and \u10000-\u10ffff # in an XML document. xmlrpclib does not escape these values From 4438f722ec67c231255a8ecdd9576b7998824299 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 14 Mar 2007 23:13:37 +0000 Subject: [PATCH 096/170] Improve the performance of the Xend trace facility, and exclude XendMonitor and XendLogging from those classes that are traced. Signed-off-by: Ewan Mellor --- tools/python/xen/xend/server/SrvDaemon.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/python/xen/xend/server/SrvDaemon.py b/tools/python/xen/xend/server/SrvDaemon.py index 04f7a789a6..adb83b679c 100644 --- a/tools/python/xen/xend/server/SrvDaemon.py +++ b/tools/python/xen/xend/server/SrvDaemon.py @@ -276,9 +276,12 @@ class Daemon: if not m: return None modulename = m.group(1) - if re.search('sxp.py', modulename): - return None - if re.search('SrvServer.py', modulename): + if modulename.endswith('.pyc'): + modulename = modulename[:-1] + if modulename == 'sxp.py' or \ + modulename == 'XendLogging.py' or \ + modulename == 'XendMonitor.py' or \ + modulename == 'server/SrvServer.py': return None self.traceindent += 1 self.print_trace("> %s:%s\n" From 618ef9cd1c2946baef6a6faf23557d24796b5f67 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 14 Mar 2007 23:14:19 +0000 Subject: [PATCH 097/170] Fix error logging when we get a 500 response. Signed-off-by: Ewan Mellor --- tools/python/xen/xm/XenAPI.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/python/xen/xm/XenAPI.py b/tools/python/xen/xm/XenAPI.py index e557b9ccb8..ae2448eb71 100644 --- a/tools/python/xen/xm/XenAPI.py +++ b/tools/python/xen/xm/XenAPI.py @@ -155,7 +155,7 @@ class Session(xen.util.xmlrpclib2.ServerProxy): def _parse_result(result): if type(result) != dict or 'Status' not in result: - raise xmlrpclib.Fault(500, 'Missing Status in response from server' + result) + raise xmlrpclib.Fault(500, 'Missing Status in response from server: ' + str(result)) if result['Status'] == 'Success': if 'Value' in result: return result['Value'] From c57f40c62f264224610bb6287ea52036490178da Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 14 Mar 2007 23:16:59 +0000 Subject: [PATCH 098/170] Added the clear flag to host.dmesg, and added host.get_log. Use these to implement xm dmesg and xm log using the Xen-API. Signed-off-by: Tom Wilkie Signed-off-by: Ewan Mellor --- tools/python/xen/xend/XendAPI.py | 15 ++++++++++++--- tools/python/xen/xm/main.py | 26 +++++++++++++++++++++----- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index 62f42e8e02..7d3e29e693 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -661,7 +661,8 @@ class XendAPI(object): ('shutdown', None), ('add_to_other_config', None), ('remove_from_other_config', None), - ('dmesg', 'String')] + ('dmesg', 'String'), + ('get_log', 'String')] host_funcs = [('get_by_name_label', 'Set(host)')] @@ -737,8 +738,16 @@ class XendAPI(object): return xen_api_error(XEND_ERROR_HOST_RUNNING) return xen_api_error(XEND_ERROR_UNSUPPORTED) - def host_dmesg(self, session, host_ref): - return xen_api_success(XendDmesg.instance().info()) + def host_dmesg(self, session, host_ref, clear): + if clear: + return xen_api_success(XendDmesg.instance().clear()) + else: + return xen_api_success(XendDmesg.instance().info()) + + def host_get_log(self, session, host_ref): + log_file = open(XendLogging.getLogFilename()) + log_buffer = log_file.read() + return xen_api_success(log_buffer) def host_get_record(self, session, host_ref): node = XendNode.instance() diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 40f9059853..5b78f87530 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -1498,17 +1498,33 @@ def xm_dmesg(args): err("No parameter required") usage('dmesg') - if not use_clear: - print server.xend.node.dmesg.info() + if serverType == SERVER_XEN_API: + if not use_clear: + print server.xenapi.host.dmesg( + server.xenapi.session.get_this_host(),0) + else: + server.xenapi.host.dmesg( + server.xenapi.session.get_this_host(),1) else: - server.xend.node.dmesg.clear() + if not use_clear: + print server.xend.node.dmesg.info() + else: + server.xend.node.dmesg.clear() def xm_log(args): arg_check(args, "log", 0) - - print server.xend.node.log() + + if serverType == SERVER_XEN_API: + print server.xenapi.host.get_log( + server.xenapi.session.get_this_host()) + else: + print server.xend.node.log() def xm_serve(args): + if serverType == SERVER_XEN_API: + print "Not supported with XenAPI" + sys.exit(-1) + arg_check(args, "serve", 0) from fcntl import fcntl, F_SETFL From 71439ea4bbac92b0075bc1448a78cb52c36af58f Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Wed, 14 Mar 2007 23:26:33 +0000 Subject: [PATCH 099/170] Implement xm domid and xm console using the Xen-API, and fix xm domname. Signed-off-by: Tom Wilkie --- tools/python/xen/xm/main.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 5b78f87530..152c1a69f7 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -1140,14 +1140,16 @@ def xm_destroy(args): else: server.xend.domain.destroy(dom) - def xm_domid(args): arg_check(args, "domid", 1) name = args[0] - dom = server.xend.domain(name) - print sxp.child_value(dom, 'domid') + if serverType == SERVER_XEN_API: + print server.xenapi.VM.get_domid(get_single_vm(name)) + else: + dom = server.xend.domain(name) + print sxp.child_value(dom, 'domid') def xm_domname(args): arg_check(args, "domname", 1) @@ -1155,7 +1157,7 @@ def xm_domname(args): name = args[0] if serverType == SERVER_XEN_API: - print server.xenapi.VM.get_domid(get_single_vm(dom)) + print server.xenapi.VM.get_name_label(get_single_vm(name)) else: dom = server.xend.domain(name) print sxp.child_value(dom, 'name') @@ -1384,13 +1386,17 @@ def xm_console(args): dom = params[0] try: - info = server.xend.domain(dom) + if serverType == SERVER_XEN_API: + domid = int(server.xenapi.VM.get_domid(get_single_vm(dom))) + else: + info = server.xend.domain(dom) + domid = int(sxp.child_value(info, 'domid', '-1')) except: if quiet: sys.exit(1) else: raise - domid = int(sxp.child_value(info, 'domid', '-1')) + if domid == -1: if quiet: sys.exit(1) From 607ea0279756594ce1193daf5d0d67c19f96a43c Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 15 Mar 2007 10:33:32 +0000 Subject: [PATCH 100/170] Add boot option to allow console I/O to be placed into ring buffer This option allows console I/O to be placed into the hypervisor console ring buffer. When enabled, all output to the console device will be reflected in the ring buffer. When disabled (the default), only hypervisor output is available from the ring buffer. Signed-off-by: Ben Thomas --- docs/src/user.tex | 5 +++++ xen/drivers/char/console.c | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/docs/src/user.tex b/docs/src/user.tex index f71231d44c..6706a31acb 100644 --- a/docs/src/user.tex +++ b/docs/src/user.tex @@ -3179,6 +3179,11 @@ editing \path{grub.conf}. one of 80x25, 80x28, 80x30, 80x34, 80x43, 80x50, 80x60. \item[ keep ] Keep the VGA console even after domain 0 boots. \end{description} +\item [ console\_to\_ring ] Place guest console output into the + hypervisor console ring buffer. This is disabled by default. + When enabled, both hypervisor output and guest console output + is available from the ring buffer. This can be useful for logging + and/or remote presentation of console data. \item [ sync\_console ] Force synchronous console output. This is useful if you system fails unexpectedly before it has sent all available output to the console. In most cases Xen will diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index 927b47112f..ef11d735ba 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -48,6 +48,10 @@ string_param("conswitch", opt_conswitch); static int opt_sync_console; boolean_param("sync_console", opt_sync_console); +/* console_to_ring: send guest (incl. dom 0) console data to console ring. */ +static int opt_console_to_ring; +boolean_param("console_to_ring", opt_console_to_ring); + #define CONRING_SIZE 16384 #define CONRING_IDX_MASK(i) ((i)&(CONRING_SIZE-1)) static char conring[CONRING_SIZE]; @@ -329,7 +333,14 @@ static long guest_console_write(XEN_GUEST_HANDLE(char) buffer, int count) sercon_puts(kbuf); for ( kptr = kbuf; *kptr != '\0'; kptr++ ) + { vga_putchar(*kptr); + if ( opt_console_to_ring ) + putchar_console_ring(*kptr); + } + + if ( opt_console_to_ring ) + send_guest_global_virq(dom0, VIRQ_CON_RING); guest_handle_add_offset(buffer, kcount); count -= kcount; From e18371883e951959e8328e2f2ea780088afaf01c Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 15 Mar 2007 10:36:10 +0000 Subject: [PATCH 101/170] TCGBIOS fixes and cleanups. - Add a missing break into the switch statement - Simplify the code that switches from protected mode into real mode by letting it spill eax; this also fixes the case where the stack is above 0xffff. - reformat the source for 80 columns - remove some comments that were relevant when the TCG extensions were direct part of the real-mode Bochs BIOS Signed-off-by: Stefan Berger --- .../firmware/rombios/32bit/tcgbios/tcgbios.c | 64 +++++++------------ tools/firmware/rombios/32bitgateway.c | 27 +++----- tools/firmware/rombios/tcgbios.c | 4 ++ 3 files changed, 36 insertions(+), 59 deletions(-) diff --git a/tools/firmware/rombios/32bit/tcgbios/tcgbios.c b/tools/firmware/rombios/32bit/tcgbios/tcgbios.c index dc1a9e0d51..e4483982c4 100644 --- a/tools/firmware/rombios/32bit/tcgbios/tcgbios.c +++ b/tools/firmware/rombios/32bit/tcgbios/tcgbios.c @@ -95,13 +95,15 @@ struct ptti_cust *TCG_CommandList[] = { }; /* local function prototypes */ -static void sha1(const unsigned char *data, uint32_t length, unsigned char *hash); +static void sha1(const unsigned char *data, uint32_t length, + unsigned char *hash); static uint32_t TCG_ShutdownPreBootInterface(uint32_t ebx); static uint32_t HashAll32(struct hai *hai, unsigned char *hash, uint32_t magic, uint32_t ecx, uint32_t edx); static uint32_t HashLogExtendEvent32(struct hleei_short *hleei_s, struct hleeo *hleeo, - uint32_t magic, uint32_t ecx, uint32_t edx); + uint32_t magic, uint32_t ecx, + uint32_t edx); static uint32_t HashLogEvent32(struct hlei *hlei, struct hleo *hleo, uint32_t ebx, uint32_t ecx, uint32_t edx); static uint32_t PassThroughToTPM32(struct pttti *pttti, struct pttto *pttto, @@ -181,8 +183,7 @@ uint32_t MA_InitTPM(uint16_t startupcode) } static -uint32_t MA_Transmit(unsigned char *cmdbuffer, - unsigned char *respbuffer, +uint32_t MA_Transmit(unsigned char *cmdbuffer, unsigned char *respbuffer, uint32_t respbufferlen) { uint32_t rc = 0; @@ -289,15 +290,14 @@ void tcpa_acpi_init(void) uint32_t ctr = 0; /* get RSDT from RSDP */ rsdt = (struct acpi_20_rsdt *)rsdp->rsdt_address; - /* rsdt may be anywhere in 32bit space */ length = rsdt->header.length; off = 36; while ((off + 3) < length) { /* try all pointers to structures */ tcpa = (struct acpi_20_tcpa *)rsdt->entry[ctr]; /* valid TCPA ACPI table ? */ - if (ACPI_2_0_TCPA_SIGNATURE == tcpa->header.signature && - acpi_validate_entry(&tcpa->header) == 0) { + if (ACPI_2_0_TCPA_SIGNATURE == tcpa->header.signature + && acpi_validate_entry(&tcpa->header) == 0) { found = 1; break; } @@ -311,7 +311,6 @@ void tcpa_acpi_init(void) tcpa = 0; } - /* initialize the TCPA part of the EBDA with our data */ tcpa_acpi.tcpa_ptr = tcpa; tcpa_acpi.lasa_last_ptr = 0; tcpa_acpi.entry_count = 0; @@ -748,9 +747,7 @@ void tcpa_measure_post(Bit32u from, Bit32u to) } static -uint32_t SendCommand32(uint32_t idx, - struct pttto *pttto, - uint32_t size_ptto) +uint32_t SendCommand32(uint32_t idx, struct pttto *pttto, uint32_t size_ptto) { uint32_t rc = 0; struct pttti *pttti = (struct pttti *)TCG_CommandList[idx]; @@ -796,7 +793,8 @@ uint32_t tcpa_initialize_tpm(uint32_t physpres) uint32_t pttto_size = sizeof(_pttto); if (rc == 0) { - rc = SendCommand32(IDX_CMD_TPM_Startup_0x01, pttto, pttto_size); + rc = SendCommand32(IDX_CMD_TPM_Startup_0x01, pttto, + pttto_size); } if (rc == 0 && physpres != 0) { @@ -884,11 +882,8 @@ uint32_t _TCG_TPM_Extend(unsigned char *hash, uint32_t pcrindex) static -uint32_t HashLogExtendEvent32(struct hleei_short *hleei_s, - struct hleeo *hleeo, - uint32_t magic, - uint32_t ecx, - uint32_t edx) +uint32_t HashLogExtendEvent32(struct hleei_short *hleei_s, struct hleeo *hleeo, + uint32_t magic, uint32_t ecx, uint32_t edx) { uint32_t rc = 0; uint16_t size; @@ -978,11 +973,8 @@ uint32_t HashLogExtendEvent32(struct hleei_short *hleei_s, static -uint32_t PassThroughToTPM32(struct pttti *pttti, - struct pttto *pttto, - uint32_t magic, - uint32_t ecx, - uint32_t edx) +uint32_t PassThroughToTPM32(struct pttti *pttti, struct pttto *pttto, + uint32_t magic, uint32_t ecx, uint32_t edx) { uint32_t rc = 0; uint8_t *cmd32; @@ -1047,9 +1039,7 @@ uint32_t TCG_ShutdownPreBootInterface(uint32_t ebx) static uint32_t HashLogEvent32(struct hlei *hlei, struct hleo *hleo, - uint32_t ebx, - uint32_t ecx, - uint32_t edx) + uint32_t ebx, uint32_t ecx, uint32_t edx) { uint32_t rc = 0; uint16_t size; @@ -1144,9 +1134,7 @@ uint32_t HashLogEvent32(struct hlei *hlei, struct hleo *hleo, static uint32_t HashAll32(struct hai *hai, unsigned char *hash, - uint32_t magic, - uint32_t ecx, - uint32_t edx) + uint32_t magic, uint32_t ecx, uint32_t edx) { uint32_t rc = 0; @@ -1187,9 +1175,7 @@ uint32_t HashAll32(struct hai *hai, unsigned char *hash, static uint32_t TSS32(struct ti *ti, struct to *to, - uint32_t ebx, - uint32_t ecx, - uint32_t edx) + uint32_t ebx, uint32_t ecx, uint32_t edx) { uint32_t rc = 0; if (TCG_IsShutdownPreBootInterface() == 0) { @@ -1209,11 +1195,11 @@ uint32_t TSS32(struct ti *ti, struct to *to, static uint32_t CompactHashLogExtendEvent32(unsigned char *buffer, - uint32_t info, - uint32_t magic, - uint32_t length, - uint32_t pcrindex, - uint32_t *edx_ptr) + uint32_t info, + uint32_t magic, + uint32_t length, + uint32_t pcrindex, + uint32_t *edx_ptr) { uint32_t rc = 0; struct hleeo hleeo; @@ -1356,9 +1342,7 @@ void sha1_do(sha1_ctx *ctx, const unsigned char *data32, uint32_t length) /* treat data in 64-byte chunks */ for (offset = 0; length - offset >= 64; offset += 64) { - /* copy into the 'w' array */ memcpy(w, data32 + offset, 64); - /* hash the block in the 'w' array */ sha1_block((uint32_t *)w, ctx); bits += (64 * 8); } @@ -1408,7 +1392,8 @@ void sha1(const unsigned char *data, uint32_t length, unsigned char *hash) } -uint32_t TCGInterruptHandler(pushad_regs_t *regs, uint32_t esds, uint32_t flags_ptr) +uint32_t TCGInterruptHandler(pushad_regs_t *regs, uint32_t esds, + uint32_t flags_ptr) { uint16_t DS = esds >> 16; uint16_t ES = esds & 0xffff; @@ -1435,7 +1420,6 @@ uint32_t TCGInterruptHandler(pushad_regs_t *regs, uint32_t esds, uint32_t flags_ } } break; - case 0x01: regs->u.r32.eax = HashLogExtendEvent32((struct hleei_short*) diff --git a/tools/firmware/rombios/32bitgateway.c b/tools/firmware/rombios/32bitgateway.c index 98f61be6e4..4da5a39c45 100644 --- a/tools/firmware/rombios/32bitgateway.c +++ b/tools/firmware/rombios/32bitgateway.c @@ -153,26 +153,17 @@ realmode_gdtdesc: ;to be used in real mode switch_to_realmode: ; Implementation of switching from protected mode to real mode - ; restores all registers and prepares cs, es, ds, ss to be used - ; in real mode + ; prepares cs, es, ds, ss to be used in real mode + ; spills eax START_PM_CODE ; need to fix up the stack to return in 16 bit mode ; currently the 32 bit return address is on the stack - push bp ;pop@A1 - mov bp, sp - push eax ;pop@X + pop eax + push ax - mov eax, [bp] ; return address low 16bits - ; and 'bp' are being moved - mov 2[bp], eax - - pop eax ;@X - add sp, #2 ; adjust stack for 'lost' bytes - - push eax ;pop@1 - push bx ;pop@2 - push si ;pop@3 + push bx ;pop@1 + push si ;pop@2 call _ebda_ss_offset32 ; get the offset of the ss mov bx, ax ; entry within the ebda. @@ -229,10 +220,8 @@ switch_to_realmode_goon_2: sti ; allow interrupts - pop si ;@3 - pop bx ;@2 - pop eax ;@1 - pop bp ;@A1 + pop si ;@2 + pop bx ;@1 ret diff --git a/tools/firmware/rombios/tcgbios.c b/tools/firmware/rombios/tcgbios.c index c8f5af2853..de2066fd1d 100644 --- a/tools/firmware/rombios/tcgbios.c +++ b/tools/firmware/rombios/tcgbios.c @@ -228,6 +228,8 @@ int1a_function32(regs, ES, DS, FLAGS) { Bit16u rc; + BX_DEBUG_INT1A("int1a_32: AX=%04x\n", regs.u.r16.ax); + switch (regs.u.r8.ah) { case 0xbb: /* @@ -256,8 +258,10 @@ int1a_function32(regs, ES, DS, FLAGS) default: SET_CF(); } + break; default: SET_CF(); break; } + BX_DEBUG_INT1A("int1a_32: FLAGS=%04x\n", FLAGS); } From 11f0262cf24014d0f089f043018845f8f743822c Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 15 Mar 2007 10:38:06 +0000 Subject: [PATCH 102/170] hvmloader: Simplify 32bit-bios relocator. Signed-off-by: Stefan Berger --- tools/firmware/hvmloader/32bitbios_support.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tools/firmware/hvmloader/32bitbios_support.c b/tools/firmware/hvmloader/32bitbios_support.c index f9274090cc..bfde19577f 100644 --- a/tools/firmware/hvmloader/32bitbios_support.c +++ b/tools/firmware/hvmloader/32bitbios_support.c @@ -45,16 +45,11 @@ static int relocate_elf(unsigned char *elfarray) { return -1; } - for (i = 0; i < ehdr->e_shnum; i++) { - if (!(shdr[i]).sh_flags & SHF_ALLOC) { - shdr[i].sh_addr = 0; - continue; - } + for (i = 0; i < ehdr->e_shnum; i++) shdr[i].sh_addr = (Elf32_Addr)&elfarray[shdr[i].sh_offset]; - } for (i = 0; i < ehdr->e_shnum; i++) { - if (shdr[i].sh_type == SHT_REL && shdr[i].sh_addr != 0) { + if (shdr[i].sh_type == SHT_REL) { Elf32_Shdr *targetsec = (Elf32_Shdr *)&(shdr[shdr[i].sh_info]); Elf32_Shdr *symtabsec = (Elf32_Shdr *)&(shdr[shdr[i].sh_link]); Elf32_Sym *syms = (Elf32_Sym *)symtabsec->sh_addr; @@ -62,6 +57,10 @@ static int relocate_elf(unsigned char *elfarray) { unsigned char *code = (unsigned char *)targetsec->sh_addr; int j; + /* must not have been stripped */ + if (shdr[i].sh_size == 0) + return -6; + for (j = 0; j < shdr[i].sh_size / sizeof(Elf32_Rel); j++) { int idx = ELF32_R_SYM(rels[j].r_info); Elf32_Sym *symbol = &syms[idx]; From 462eb0fc0efe4b24088ef0c74916dd691dcd2db0 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 15 Mar 2007 10:38:58 +0000 Subject: [PATCH 103/170] x86: 32on64 oversight in update_va_mapping Signed-off-by: Jan Beulich --- xen/arch/x86/mm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index b37ade4cb3..1c65070d15 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -2768,7 +2768,9 @@ int do_update_va_mapping(unsigned long va, u64 val64, flush_tlb_one_mask(d->domain_dirty_cpumask, va); break; default: - if ( unlikely(get_user(vmask, (unsigned long *)bmap_ptr)) ) + if ( unlikely(!IS_COMPAT(d) ? + get_user(vmask, (unsigned long *)bmap_ptr) : + get_user(vmask, (unsigned int *)bmap_ptr)) ) rc = -EFAULT; pmask = vcpumask_to_pcpumask(d, vmask); flush_tlb_one_mask(pmask, va); From 8183fb7b82f01d079d146a6d98ac8943e2ad5fc6 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 15 Mar 2007 10:43:13 +0000 Subject: [PATCH 104/170] Add two arch hooks to gnttab_release_mappings(). Signed-off-by: Isaku Yamahata --- xen/common/grant_table.c | 6 ++---- xen/include/asm-ia64/grant_table.h | 3 +++ xen/include/asm-powerpc/grant_table.h | 13 +++++++++++++ xen/include/asm-x86/grant_table.h | 10 ++++++++++ 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c index 1af842a528..2ea6ff37eb 100644 --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -1392,8 +1392,7 @@ gnttab_release_mappings( { BUG_ON(!(act->pin & GNTPIN_hstr_mask)); act->pin -= GNTPIN_hstr_inc; - /* Done implicitly when page tables are destroyed. */ - /* put_page(mfn_to_page(act->frame)); */ + gnttab_release_put_page(mfn_to_page(act->frame)); } } else @@ -1409,8 +1408,7 @@ gnttab_release_mappings( { BUG_ON(!(act->pin & GNTPIN_hstw_mask)); act->pin -= GNTPIN_hstw_inc; - /* Done implicitly when page tables are destroyed. */ - /* put_page_and_type(mfn_to_page(act->frame)); */ + gnttab_release_put_page_and_type(mfn_to_page(act->frame)); } if ( (act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) == 0 ) diff --git a/xen/include/asm-ia64/grant_table.h b/xen/include/asm-ia64/grant_table.h index 45d7dac7e9..f10d92e419 100644 --- a/xen/include/asm-ia64/grant_table.h +++ b/xen/include/asm-ia64/grant_table.h @@ -64,4 +64,7 @@ static inline void gnttab_clear_flag(unsigned long nr, uint16_t *addr) clear_bit(nr, addr); } +#define gnttab_release_put_page(page) put_page((page)) +#define gnttab_release_put_page_and_type(page) put_page_and_type((page)) + #endif /* __ASM_GRANT_TABLE_H__ */ diff --git a/xen/include/asm-powerpc/grant_table.h b/xen/include/asm-powerpc/grant_table.h index 334a925cbb..e8ca87cbb4 100644 --- a/xen/include/asm-powerpc/grant_table.h +++ b/xen/include/asm-powerpc/grant_table.h @@ -69,4 +69,17 @@ static inline uint cpu_foreign_map_order(void) /* 16 GiB */ return 34 - PAGE_SHIFT; } + +#if 0 +/* + * without put_page()/put_page_and_type() page might be leaked. + * with put_page()/put_page_and_type() freed page might be accessed. + */ +#define gnttab_release_put_page(page) put_page((page)) +#define gnttab_release_put_page_and_type(page) put_page_and_type((page)) +#else +#define gnttab_release_put_page(page) do { } while (0) +#define gnttab_release_put_page_and_type(page) do { } while (0) +#endif + #endif /* __ASM_PPC_GRANT_TABLE_H__ */ diff --git a/xen/include/asm-x86/grant_table.h b/xen/include/asm-x86/grant_table.h index 32dc43b898..f0c49bac3b 100644 --- a/xen/include/asm-x86/grant_table.h +++ b/xen/include/asm-x86/grant_table.h @@ -38,4 +38,14 @@ static inline void gnttab_clear_flag(unsigned long nr, uint16_t *addr) clear_bit(nr, addr); } +#define gnttab_release_put_page(page) \ + do { \ + /* Done implicitly when page tables are destroyed. */ \ + } while (0) + +#define gnttab_release_put_page_and_type(page) \ + do { \ + /* Done implicitly when page tables are destroyed. */ \ + } while (0) + #endif /* __ASM_GRANT_TABLE_H__ */ From 4da77d5b3ff6ec26b384c972406140d50e127f70 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 15 Mar 2007 14:51:32 +0000 Subject: [PATCH 105/170] net back: Quieten loud error path. Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/drivers/xen/netback/netback.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c index 7e0c340832..98072726cb 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c @@ -1267,7 +1267,7 @@ static void net_tx_action(unsigned long unused) /* Check the remap error code. */ if (unlikely(netbk_tx_check_mop(skb, &mop))) { - printk(KERN_ALERT "#### netback grant fails\n"); + DPRINTK("netback grant failed.\n"); skb_shinfo(skb)->nr_frags = 0; kfree_skb(skb); continue; From 5f3c8af40d85f8112fa146a66adbc31a6a41ba2f Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 15 Mar 2007 15:27:08 +0000 Subject: [PATCH 106/170] minios: Fix an extern declaration and add an extra 'const' to definition of a constant set of constant error strings. Issues identified by Armand Puccetti. Signed-off-by: Keir Fraser --- extras/mini-os/arch/x86/mm.c | 4 ++-- extras/mini-os/gnttab.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/extras/mini-os/arch/x86/mm.c b/extras/mini-os/arch/x86/mm.c index d1508f8263..15ed4877a8 100644 --- a/extras/mini-os/arch/x86/mm.c +++ b/extras/mini-os/arch/x86/mm.c @@ -49,7 +49,7 @@ #endif unsigned long *phys_to_machine_mapping; -extern char *stack; +extern char stack[]; extern void page_walk(unsigned long virt_addr); void new_pt_frame(unsigned long *pt_pfn, unsigned long prev_l_mfn, @@ -453,7 +453,7 @@ void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p) printk(" _text: %p\n", &_text); printk(" _etext: %p\n", &_etext); printk(" _edata: %p\n", &_edata); - printk(" stack start: %p\n", &stack); + printk(" stack start: %p\n", stack); printk(" _end: %p\n", &_end); /* First page follows page table pages and 3 more pages (store page etc) */ diff --git a/extras/mini-os/gnttab.c b/extras/mini-os/gnttab.c index 4d75897a98..b22f51ceae 100644 --- a/extras/mini-os/gnttab.c +++ b/extras/mini-os/gnttab.c @@ -135,7 +135,7 @@ gnttab_alloc_and_grant(void **map) return gref; } -static const char *gnttabop_error_msgs[] = GNTTABOP_error_msgs; +static const char * const gnttabop_error_msgs[] = GNTTABOP_error_msgs; const char * gnttabop_error(int16_t status) From 8058cadb58d5cfdf63abdb55f805f8c00a438e02 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 15 Mar 2007 16:54:00 +0000 Subject: [PATCH 107/170] Replace tab with 4 whitespaces in xm/shutdown.py. Signed-off-by: Masaki Kanno --- tools/python/xen/xm/shutdown.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tools/python/xen/xm/shutdown.py b/tools/python/xen/xm/shutdown.py index 8ada520e62..8284a73bca 100644 --- a/tools/python/xen/xm/shutdown.py +++ b/tools/python/xen/xm/shutdown.py @@ -51,7 +51,7 @@ gopts.opt('reboot', short='R', def wait_reboot(opts, doms, rcs): if serverType == SERVER_XEN_API: - opts.err("Cannot wait for reboot w/ XenAPI (yet)") + opts.err("Cannot wait for reboot w/ XenAPI (yet)") while doms: alive = server.xend.domains(0) @@ -73,7 +73,7 @@ def wait_reboot(opts, doms, rcs): def wait_shutdown(opts, doms): while doms: if serverType == SERVER_XEN_API: - alive = [dom for dom in server.xenapi.VM.get_all() + alive = [dom for dom in server.xenapi.VM.get_all() if server.xenapi.VM.get_power_state(dom) == XEN_API_VM_POWER_STATE[XEN_API_VM_POWER_STATE_RUNNING]] else: @@ -91,16 +91,16 @@ def wait_shutdown(opts, doms): def shutdown(opts, doms, mode, wait): rcs = {} for d in doms: - if serverType == SERVER_XEN_API: - if mode == 'halt': - server.xenapi.VM.clean_shutdown(d) - if mode == 'reboot': - server.xenapi.VM.clean_reboot(d) - if mode == 'poweroff': - server.xenapi.VM.clean_shutdown(d) - else: - rcs[d] = server.xend.domain.getRestartCount(d) - server.xend.domain.shutdown(d, mode) + if serverType == SERVER_XEN_API: + if mode == 'halt': + server.xenapi.VM.clean_shutdown(d) + if mode == 'reboot': + server.xenapi.VM.clean_reboot(d) + if mode == 'poweroff': + server.xenapi.VM.clean_shutdown(d) + else: + rcs[d] = server.xend.domain.getRestartCount(d) + server.xend.domain.shutdown(d, mode) if wait: if mode == 'reboot': @@ -135,7 +135,7 @@ def main_dom(opts, args): if len(args) > 1: opts.err('No multiple domain parameters allowed') dom = args[0] if serverType == SERVER_XEN_API: - dom = get_single_vm(dom) + dom = get_single_vm(dom) mode = shutdown_mode(opts) shutdown(opts, [ dom ], mode, opts.vals.wait) From f918e26c26e5664e08dd82f6b3d45ba3936c828a Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Thu, 15 Mar 2007 21:44:20 +0000 Subject: [PATCH 108/170] Allow the xm configuration file location to be overridden with an environment variable. Signed-off-by: Ewan Mellor --- tools/python/xen/xm/main.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 152c1a69f7..5003ef16fe 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -60,7 +60,8 @@ import XenAPI if not hasattr(getopt, 'gnu_getopt'): getopt.gnu_getopt = getopt.getopt -XM_CONFIG_FILE = '/etc/xen/xm-config.xml' +XM_CONFIG_FILE_ENVVAR = 'XM_CONFIG_FILE' +XM_CONFIG_FILE_DEFAULT = '/etc/xen/xm-config.xml' # Supported types of server SERVER_LEGACY_XMLRPC = 'LegacyXMLRPC' @@ -351,13 +352,14 @@ all_commands = (domain_commands + host_commands + scheduler_commands + # Configuration File Parsing ## +xmConfigFile = os.getenv(XM_CONFIG_FILE_ENVVAR, XM_CONFIG_FILE_DEFAULT) config = None -if os.path.isfile(XM_CONFIG_FILE): +if os.path.isfile(xmConfigFile): try: - config = xml.dom.minidom.parse(XM_CONFIG_FILE) + config = xml.dom.minidom.parse(xmConfigFile) except: print >>sys.stderr, ('Ignoring invalid configuration file %s.' % - XM_CONFIG_FILE) + xmConfigFile) def parseServer(): if config: From 746900680c20cbfa285852e718690649b7651dbc Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Thu, 15 Mar 2007 21:59:34 +0000 Subject: [PATCH 109/170] Added a new Xen-API call VM.send_sysrq, and use that to implement xm sysrq through Xen-API. Signed-off-by: Tom Wilkie --- tools/python/xen/xend/XendAPI.py | 7 +++++++ tools/python/xen/xm/main.py | 5 ++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index 7d3e29e693..10024070a9 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -1070,6 +1070,7 @@ class XendAPI(object): ('hard_reboot', None), ('suspend', None), ('resume', None), + ('send_sysrq', None), ('add_to_HVM_boot_params', None), ('remove_from_HVM_boot_params', None), ('add_to_VCPUs_params', None), @@ -1513,6 +1514,12 @@ class XendAPI(object): return XendTask.log_progress(0, 100, do_vm_func, "domain_unpause", vm_ref) + def VM_send_sysrq(self, _, vm_ref, req): + xendom = XendDomain.instance() + xeninfo = xendom.get_vm_by_uuid(vm_ref) + xeninfo.send_sysrq(req) + return xen_api_success_void() + # Xen API: Class VM_metrics # ---------------------------------------------------------------- diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 5003ef16fe..ba1192e6c4 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -1466,7 +1466,10 @@ def xm_sysrq(args): arg_check(args, "sysrq", 2) dom = args[0] req = args[1] - server.xend.domain.send_sysrq(dom, req) + if serverType == SERVER_XEN_API: + server.xenapi.VM.send_sysrq(get_single_vm(dom), req) + else: + server.xend.domain.send_sysrq(dom, req) def xm_trigger(args): vcpu = 0 From 77afb8b283d2bfc7278f39c483dc5354fe87a70a Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Thu, 15 Mar 2007 22:15:12 +0000 Subject: [PATCH 110/170] Raise the VM_BAD_POWER_STATE error with VM.send_sysrq if the domain is not running. Signed-off-by: Ewan Mellor --- tools/python/xen/xend/XendAPI.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index 10024070a9..cb444f04d1 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -1515,11 +1515,16 @@ class XendAPI(object): "domain_unpause", vm_ref) def VM_send_sysrq(self, _, vm_ref, req): - xendom = XendDomain.instance() - xeninfo = xendom.get_vm_by_uuid(vm_ref) + xeninfo = XendDomain.instance().get_vm_by_uuid(vm_ref) + if xeninfo.state != XEN_API_VM_POWER_STATE_RUNNING: + return xen_api_error( + ['VM_BAD_POWER_STATE', vm_ref, + XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_RUNNING], + XendDomain.POWER_STATE_NAMES[xeninfo.state]]) xeninfo.send_sysrq(req) return xen_api_success_void() + # Xen API: Class VM_metrics # ---------------------------------------------------------------- From 194dd03ad642da3c267e3d032b3db0528a8e6156 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Thu, 15 Mar 2007 23:03:22 +0000 Subject: [PATCH 111/170] Implement xm list through the Xen-API. Signed-off-by: Tom Wilkie --- tools/python/xen/xm/main.py | 136 ++++++++++++++++++++++++++---------- 1 file changed, 99 insertions(+), 37 deletions(-) diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index ba1192e6c4..8c541e4b2c 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -49,11 +49,10 @@ from xen.xend.XendConstants import * from xen.xm.opts import OptionError, Opts, wrap, set_true from xen.xm import console -from xen.util import security from xen.util.xmlrpclib2 import ServerProxy - import XenAPI + # getopt.gnu_getopt is better, but only exists in Python 2.3+. Use # getopt.getopt if gnu_getopt is not available. This will mean that options # may only be specified before positional arguments. @@ -675,10 +674,42 @@ def xm_restore(args): def getDomains(domain_names, state, full = 0): - if domain_names: - return [server.xend.domain(dom, full) for dom in domain_names] + if serverType == SERVER_XEN_API: + def map2sxp(m): + return ["domain"] + [[k, m[k]] for k in m.keys()] + + doms_sxp = [] + doms_dict = [] + dom_refs = server.xenapi.VM.get_all() + for dom_ref in dom_refs: + dom_rec = server.xenapi.VM.get_record(dom_ref) + dom_metrics_ref = server.xenapi.VM.get_metrics(dom_ref) + dom_metrics = server.xenapi.VM_metrics.get_record(dom_metrics_ref) + dom_rec.update({'name': dom_rec['name_label'], + 'memory_actual': int(dom_metrics['memory_actual'])/1024, + 'vcpus': dom_metrics['vcpus_number'], + 'state': '-----', + 'cpu_time': dom_metrics['vcpus_utilisation']}) + + doms_sxp.append(map2sxp(dom_rec)) + doms_dict.append(dom_rec) + + if domain_names: + doms = [map2sxp(dom) for dom in doms_dict + if dom["name"] in domain_names] + + if len(doms) > 0: + return doms + else: + print "Error: no domains named '%s'" % domain_names + sys.exit(-1) + else: + return doms_sxp else: - return server.xend.domains_with_state(True, state, full) + if domain_names: + return [server.xend.domain(dom, full) for dom in domain_names] + else: + return server.xend.domains_with_state(True, state, full) def xm_list(args): @@ -737,20 +768,39 @@ def parse_doms_info(info): else: up_time = time.time() - start_time - return { + parsed_info = { 'domid' : get_info('domid', str, ''), 'name' : get_info('name', str, '??'), - 'mem' : get_info('memory_dynamic_min', int, 0), 'state' : get_info('state', str, ''), - 'cpu_time' : get_info('cpu_time', float, 0.0), + # VCPUs is the number online when the VM is up, or the number # configured otherwise. 'vcpus' : get_info('online_vcpus', int, get_info('vcpus', int, 0)), - 'up_time' : up_time, - 'seclabel' : security.get_security_printlabel(info), + 'up_time' : up_time } + # We're not supporting security stuff just yet via XenAPI + + if serverType != SERVER_XEN_API: + from xen.util import security + parsed_info['seclabel'] = security.get_security_printlabel(info) + else: + parsed_info['seclabel'] = "" + + if serverType == SERVER_XEN_API: + parsed_info['mem'] = get_info('memory_actual', int, 0) / 1024 + cpu_times = get_info('cpu_time', lambda x : (x), 0.0) + if sum(cpu_times.values()) > 0: + parsed_info['cpu_time'] = sum(cpu_times.values()) / float(len(cpu_times.values())) + else: + parsed_info['cpu_time'] = 0 + else: + parsed_info['mem'] = get_info('memory_dynamic_min', int,0) + parsed_info['cpu_time'] = get_info('cpu_time', float, 0.0) + + return parsed_info + def check_sched_type(sched): if serverType == SERVER_XEN_API: current = server.xenapi.host.get_sched_policy(server.xenapi.session.get_this_host()) @@ -799,17 +849,22 @@ def xm_label_list(doms): output = [] format = '%(name)-32s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s ' \ '%(cpu_time)8.1f %(seclabel)9s' - - for dom in doms: - d = parse_doms_info(dom) - if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']: - if not d['seclabel']: - d['seclabel'] = 'ERROR' - elif security.active_policy in ['DEFAULT']: - d['seclabel'] = 'DEFAULT' - else: - d['seclabel'] = 'INACTIVE' - output.append((format % d, d['seclabel'])) + + if serverType != SERVER_XEN_API: + from xen.util import security + + for dom in doms: + d = parse_doms_info(dom) + + if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']: + if not d['seclabel']: + d['seclabel'] = 'ERROR' + elif security.active_policy in ['DEFAULT']: + d['seclabel'] = 'DEFAULT' + else: + d['seclabel'] = 'INACTIVE' + + output.append((format % d, d['seclabel'])) #sort by labels output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower())) @@ -818,7 +873,6 @@ def xm_label_list(doms): def xm_vcpu_list(args): - if args: dominfo = map(server.xend.domain.getVCPUInfo, args) else: @@ -1114,7 +1168,7 @@ def xm_mem_set(args): dom = args[0] if serverType == SERVER_XEN_API: - mem_target = int_unit(args[1], 'k') * 1024 + mem_target = int_unit(args[1], 'm') * 1024 * 1024 server.xenapi.VM.set_memory_dynamic_max(get_single_vm(dom), mem_target) server.xenapi.VM.set_memory_dynamic_min(get_single_vm(dom), mem_target) else: @@ -1695,13 +1749,17 @@ def parse_block_configuration(args): if len(args) == 5: vbd.append(['backend', args[4]]) - # verify that policy permits attaching this resource - if security.on(): - dominfo = server.xend.domain(dom) - label = security.get_security_printlabel(dominfo) - else: - label = None - security.res_security_check(args[1], label) + if serverType != SERVER_XEN_API: + # verify that policy permits attaching this resource + from xen.util import security + + if security.on(): + dominfo = server.xend.domain(dom) + label = security.get_security_printlabel(dominfo) + else: + label = None + + security.res_security_check(args[1], label) return (dom, vbd) @@ -2006,13 +2064,17 @@ def _run_cmd(cmd, cmd_name, args): err(str(e)) _usage(cmd_name) print e.usage - except security.ACMError, e: - err(str(e)) - except: - print "Unexpected error:", sys.exc_info()[0] - print - print "Please report to xen-devel@lists.xensource.com" - raise + except Exception, e: + if serverType != SERVER_XEN_API: + from xen.util import security + if isinstance(e, security.ACMError): + err(str(e)) + return False, 1 + else: + print "Unexpected error:", sys.exc_info()[0] + print + print "Please report to xen-devel@lists.xensource.com" + raise return False, 1 From 41aa97afd746c712136cab8c13f0d47791044b24 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Fri, 16 Mar 2007 10:05:57 +0000 Subject: [PATCH 112/170] Fix the python type dismatch exception when HVM restore Signed-off-by: Zhai Edwin --- tools/python/xen/xend/XendCheckpoint.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/python/xen/xend/XendCheckpoint.py b/tools/python/xen/xend/XendCheckpoint.py index be8c299634..3982188016 100644 --- a/tools/python/xen/xend/XendCheckpoint.py +++ b/tools/python/xen/xend/XendCheckpoint.py @@ -193,8 +193,8 @@ def restore(xd, fd, dominfo = None, paused = False): is_hvm = dominfo.info.is_hvm() if is_hvm: hvm = dominfo.info['memory_static_min'] - apic = dominfo.info['platform'].get('apic', 0) - pae = dominfo.info['platform'].get('pae', 0) + apic = int(dominfo.info['platform'].get('apic', 0)) + pae = int(dominfo.info['platform'].get('pae', 0)) log.info("restore hvm domain %d, mem=%d, apic=%d, pae=%d", dominfo.domid, hvm, apic, pae) else: From 6b0c303dfec7e59ef0e245deae67dc977414441d Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Fri, 16 Mar 2007 10:24:56 +0000 Subject: [PATCH 113/170] [LINUX] Don't pin the initial page tables on x86_64 when XENFEAT_writable_page_tables. Signed-off-by: Ian Campbell --- linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c b/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c index de7c80dfb8..40bd5d235e 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c +++ b/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c @@ -597,8 +597,10 @@ void __init xen_init_pt(void) early_make_page_readonly(level2_kernel_pgt, XENFEAT_writable_page_tables); - xen_pgd_pin(__pa_symbol(init_level4_pgt)); - xen_pgd_pin(__pa_symbol(init_level4_user_pgt)); + if (!xen_feature(XENFEAT_writable_page_tables)) { + xen_pgd_pin(__pa_symbol(init_level4_pgt)); + xen_pgd_pin(__pa_symbol(init_level4_user_pgt)); + } set_pgd((pgd_t *)(init_level4_user_pgt + 511), mk_kernel_pgd(__pa_symbol(level3_user_pgt))); From f326023b8394296eb85a3bf2222edb1734c4cb6b Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 16 Mar 2007 10:42:25 +0000 Subject: [PATCH 114/170] xenbus: Clarify and simplify barrier usage. Signed-off-by: Keir Fraser --- .../drivers/xen/xenbus/xenbus_comms.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c index c00aaf7f6f..2521b8203d 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c @@ -110,7 +110,6 @@ int xb_write(const void *data, unsigned len) /* Read indexes, then verify. */ cons = intf->req_cons; prod = intf->req_prod; - mb(); if (!check_indexes(cons, prod)) { intf->req_cons = intf->req_prod = 0; return -EIO; @@ -122,15 +121,18 @@ int xb_write(const void *data, unsigned len) if (avail > len) avail = len; + /* Must write data /after/ reading the consumer index. */ + mb(); + memcpy(dst, data, avail); data += avail; len -= avail; - /* Other side must not see new header until data is there. */ + /* Other side must not see new producer until data is there. */ wmb(); intf->req_prod += avail; - /* This implies mb() before other side sees interrupt. */ + /* Implies mb(): other side will see the updated producer. */ notify_remote_via_evtchn(xen_store_evtchn); } @@ -165,7 +167,6 @@ int xb_read(void *data, unsigned len) /* Read indexes, then verify. */ cons = intf->rsp_cons; prod = intf->rsp_prod; - mb(); if (!check_indexes(cons, prod)) { intf->rsp_cons = intf->rsp_prod = 0; return -EIO; @@ -177,7 +178,7 @@ int xb_read(void *data, unsigned len) if (avail > len) avail = len; - /* We must read header before we read data. */ + /* Must read data /after/ reading the producer index. */ rmb(); memcpy(data, src, avail); @@ -190,7 +191,7 @@ int xb_read(void *data, unsigned len) pr_debug("Finished read of %i bytes (%i to go)\n", avail, len); - /* Implies mb(): they will see new header. */ + /* Implies mb(): other side will see the updated consumer. */ notify_remote_via_evtchn(xen_store_evtchn); } From da12f80b3e44e8941091048b3aea6c2d3f9c6713 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Fri, 16 Mar 2007 11:39:50 +0000 Subject: [PATCH 115/170] [HVM][QEMU] Save/restore: enable HVM live migration by getting page-dirtying bitmaps from qemu-dm as well as from xen. Signed-off-by: Tim Deegan --- tools/ioemu/target-i386-dm/exec-dm.c | 16 +++- tools/ioemu/xenstore.c | 127 ++++++++++++++++++++++++++ tools/libxc/Makefile | 2 +- tools/libxc/xc_hvm_save.c | 39 ++++++-- tools/libxc/xenguest.h | 6 +- tools/libxc/xg_private.c | 4 +- tools/xcutils/Makefile | 6 +- tools/xcutils/xc_save.c | 129 ++++++++++++++++++++++++++- 8 files changed, 314 insertions(+), 15 deletions(-) diff --git a/tools/ioemu/target-i386-dm/exec-dm.c b/tools/ioemu/target-i386-dm/exec-dm.c index 35891ed064..225f8b6f3a 100644 --- a/tools/ioemu/target-i386-dm/exec-dm.c +++ b/tools/ioemu/target-i386-dm/exec-dm.c @@ -450,6 +450,9 @@ static inline int paddr_is_ram(target_phys_addr_t addr) #define phys_ram_addr(x) (phys_ram_base + (x)) #endif +extern unsigned long *logdirty_bitmap; +extern unsigned long logdirty_bitmap_size; + void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, int len, int is_write) { @@ -485,9 +488,20 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, l = 1; } } else if (paddr_is_ram(addr)) { - /* Reading from RAM */ + /* Writing to RAM */ ptr = phys_ram_addr(addr); memcpy(ptr, buf, l); + if (logdirty_bitmap != NULL) { + /* Record that we have dirtied this frame */ + unsigned long pfn = addr >> TARGET_PAGE_BITS; + if (pfn / 8 >= logdirty_bitmap_size) { + fprintf(logfile, "dirtying pfn %x >= bitmap size %x\n", + pfn, logdirty_bitmap_size * 8); + } else { + logdirty_bitmap[pfn / HOST_LONG_BITS] + |= 1UL << pfn % HOST_LONG_BITS; + } + } #ifdef __ia64__ sync_icache(ptr, l); #endif diff --git a/tools/ioemu/xenstore.c b/tools/ioemu/xenstore.c index edaf741c3d..f1aa2f5e33 100644 --- a/tools/ioemu/xenstore.c +++ b/tools/ioemu/xenstore.c @@ -11,6 +11,11 @@ #include "vl.h" #include "block_int.h" #include +#include +#include +#include +#include +#include static struct xs_handle *xsh = NULL; static char *hd_filename[MAX_DISKS]; @@ -183,6 +188,13 @@ void xenstore_parse_domain_config(int domid) } } + /* Set a watch for log-dirty requests from the migration tools */ + if (pasprintf(&buf, "%s/logdirty/next-active", path) != -1) { + xs_watch(xsh, buf, "logdirty"); + fprintf(logfile, "Watching %s\n", buf); + } + + out: free(type); free(params); @@ -201,6 +213,116 @@ int xenstore_fd(void) return -1; } +unsigned long *logdirty_bitmap = NULL; +unsigned long logdirty_bitmap_size; +extern int vga_ram_size, bios_size; + +void xenstore_process_logdirty_event(void) +{ + char *act; + static char *active_path = NULL; + static char *next_active_path = NULL; + static char *seg = NULL; + unsigned int len; + int i; + + fprintf(logfile, "Triggered log-dirty buffer switch\n"); + + if (!seg) { + char *path, *p, *key_ascii, *key_terminated[17] = {0,}; + key_t key; + int shmid; + + /* Find and map the shared memory segment for log-dirty bitmaps */ + if (!(path = xs_get_domain_path(xsh, domid))) { + fprintf(logfile, "Log-dirty: can't get domain path in store\n"); + exit(1); + } + if (!(path = realloc(path, strlen(path) + + strlen("/logdirty/next-active") + 1))) { + fprintf(logfile, "Log-dirty: out of memory\n"); + exit(1); + } + strcat(path, "/logdirty/"); + p = path + strlen(path); + strcpy(p, "key"); + + key_ascii = xs_read(xsh, XBT_NULL, path, &len); + if (!key_ascii) { + /* No key yet: wait for the next watch */ + free(path); + return; + } + strncpy(key_terminated, key_ascii, 16); + free(key_ascii); + key = (key_t) strtoull(key_terminated, NULL, 16); + + /* Figure out how bit the log-dirty bitmaps are */ + logdirty_bitmap_size = ((phys_ram_size + 0x20 + - (vga_ram_size + bios_size)) + >> (TARGET_PAGE_BITS)); /* nr of bits in map*/ + if (logdirty_bitmap_size > HVM_BELOW_4G_MMIO_START >> TARGET_PAGE_BITS) + logdirty_bitmap_size += + HVM_BELOW_4G_MMIO_LENGTH >> TARGET_PAGE_BITS; /* still bits */ + logdirty_bitmap_size = ((logdirty_bitmap_size + HOST_LONG_BITS - 1) + / HOST_LONG_BITS); /* longs */ + logdirty_bitmap_size *= sizeof (unsigned long); /* bytes */ + + /* Map the shared-memory segment */ + if ((shmid = shmget(key, + 2 * logdirty_bitmap_size, + S_IRUSR|S_IWUSR)) == -1 + || (seg = shmat(shmid, NULL, 0)) == (void *)-1) { + fprintf(logfile, "Log-dirty: can't map segment %16.16llx (%s)\n", + (unsigned long long) key, strerror(errno)); + exit(1); + } + + fprintf(logfile, "Log-dirty: mapped segment at %p\n", seg); + + /* Double-check that the bitmaps are the size we expect */ + if (logdirty_bitmap_size != *(uint32_t *)seg) { + fprintf(logfile, "Log-dirty: got %lu, calc %lu\n", + *(uint32_t *)seg, logdirty_bitmap_size); + return; + } + + /* Remember the paths for the next-active and active entries */ + strcpy(p, "active"); + if (!(active_path = strdup(path))) { + fprintf(logfile, "Log-dirty: out of memory\n"); + exit(1); + } + strcpy(p, "next-active"); + if (!(next_active_path = strdup(path))) { + fprintf(logfile, "Log-dirty: out of memory\n"); + exit(1); + } + free(path); + } + + /* Read the required active buffer from the store */ + act = xs_read(xsh, XBT_NULL, next_active_path, &len); + if (!act) { + fprintf(logfile, "Log-dirty: can't read next-active\n"); + exit(1); + } + + /* Switch buffers */ + i = act[0] - '0'; + if (i != 0 && i != 1) { + fprintf(logfile, "Log-dirty: bad next-active entry: %s\n", act); + exit(1); + } + logdirty_bitmap = seg + i * logdirty_bitmap_size; + + /* Ack that we've switched */ + xs_write(xsh, XBT_NULL, active_path, act, len); + free(act); +} + + + void xenstore_process_event(void *opaque) { char **vec, *image = NULL; @@ -210,6 +332,11 @@ void xenstore_process_event(void *opaque) if (!vec) return; + if (!strcmp(vec[XS_WATCH_TOKEN], "logdirty")) { + xenstore_process_logdirty_event(); + goto out; + } + if (strncmp(vec[XS_WATCH_TOKEN], "hd", 2) || strlen(vec[XS_WATCH_TOKEN]) != 3) goto out; diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile index 6dc76ae782..04705086de 100644 --- a/tools/libxc/Makefile +++ b/tools/libxc/Makefile @@ -57,7 +57,7 @@ GUEST_SRCS-$(CONFIG_IA64) += xc_dom_compat_linux.c CFLAGS += -Werror -Wmissing-prototypes CFLAGS += -fno-strict-aliasing -CFLAGS += $(INCLUDES) -I. +CFLAGS += $(INCLUDES) -I. -I../xenstore # Needed for posix_fadvise64() in xc_linux.c CFLAGS-$(CONFIG_Linux) += -D_GNU_SOURCE diff --git a/tools/libxc/xc_hvm_save.c b/tools/libxc/xc_hvm_save.c index ac06db72a1..54a3897ce5 100644 --- a/tools/libxc/xc_hvm_save.c +++ b/tools/libxc/xc_hvm_save.c @@ -54,6 +54,11 @@ static unsigned long hvirt_start; /* #levels of page tables used by the current guest */ static unsigned int pt_levels; +/* Shared-memory bitmaps for getting log-dirty bits from qemu */ +static unsigned long *qemu_bitmaps[2]; +static int qemu_active; +static int qemu_non_active; + int xc_hvm_drain_io(int handle, domid_t dom) { DECLARE_HYPERCALL; @@ -77,7 +82,8 @@ int xc_hvm_drain_io(int handle, domid_t dom) */ #define BITS_PER_LONG (sizeof(unsigned long) * 8) -#define BITMAP_SIZE ((pfn_array_size + BITS_PER_LONG - 1) / 8) +#define BITS_TO_LONGS(bits) (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG) +#define BITMAP_SIZE (BITS_TO_LONGS(pfn_array_size) * sizeof(unsigned long)) #define BITMAP_ENTRY(_nr,_bmap) \ ((unsigned long *)(_bmap))[(_nr)/BITS_PER_LONG] @@ -124,6 +130,7 @@ static inline int permute( int i, int nr, int order_nr ) return i; } + static uint64_t tv_to_us(struct timeval *new) { return (new->tv_sec * 1000000) + new->tv_usec; @@ -277,7 +284,9 @@ static int suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd, } int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, - uint32_t max_factor, uint32_t flags, int (*suspend)(int)) + uint32_t max_factor, uint32_t flags, int (*suspend)(int), + void *(*init_qemu_maps)(int, unsigned), + void (*qemu_flip_buffer)(int, int)) { xc_dominfo_t info; @@ -392,8 +401,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, "nr_pages=0x%lx\n", info.max_memkb, max_mfn, info.nr_pages); if (live) { - ERROR("hvm domain doesn't support live migration now.\n"); - goto out; if (xc_shadow_control(xc_handle, dom, XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY, @@ -453,6 +460,15 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, to_skip = malloc(BITMAP_SIZE); + if (live) { + /* Get qemu-dm logging dirty pages too */ + void *seg = init_qemu_maps(dom, BITMAP_SIZE); + qemu_bitmaps[0] = seg; + qemu_bitmaps[1] = seg + BITMAP_SIZE; + qemu_active = 0; + qemu_non_active = 1; + } + hvm_buf_size = xc_domain_hvm_getcontext(xc_handle, dom, 0, 0); if ( hvm_buf_size == -1 ) { @@ -677,10 +693,23 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } + /* Pull in the dirty bits from qemu too */ + if (!last_iter) { + qemu_active = qemu_non_active; + qemu_non_active = qemu_active ? 0 : 1; + qemu_flip_buffer(dom, qemu_active); + for (j = 0; j < BITMAP_SIZE / sizeof(unsigned long); j++) { + to_send[j] |= qemu_bitmaps[qemu_non_active][j]; + qemu_bitmaps[qemu_non_active][j] = 0; + } + } else { + for (j = 0; j < BITMAP_SIZE / sizeof(unsigned long); j++) + to_send[j] |= qemu_bitmaps[qemu_active][j]; + } + sent_last_iter = sent_this_iter; print_stats(xc_handle, dom, sent_this_iter, &stats, 1); - } diff --git a/tools/libxc/xenguest.h b/tools/libxc/xenguest.h index 5b6e7c6d2a..76b7413f15 100644 --- a/tools/libxc/xenguest.h +++ b/tools/libxc/xenguest.h @@ -32,8 +32,10 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, * @return 0 on success, -1 on failure */ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, - uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */, - int (*suspend)(int domid)); + uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */, + int (*suspend)(int domid), + void *(*init_qemu_maps)(int, unsigned), + void (*qemu_flip_buffer)(int, int)); /** * This function will restore a saved domain running Linux. diff --git a/tools/libxc/xg_private.c b/tools/libxc/xg_private.c index 2332ef4c6c..1014131004 100644 --- a/tools/libxc/xg_private.c +++ b/tools/libxc/xg_private.c @@ -201,7 +201,9 @@ __attribute__((weak)) __attribute__((weak)) int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, uint32_t max_factor, uint32_t flags, - int (*suspend)(int domid)) + int (*suspend)(int domid), + void *(*init_qemu_maps)(int, unsigned), + void (*qemu_flip_buffer)(int, int)) { errno = ENOSYS; return -1; diff --git a/tools/xcutils/Makefile b/tools/xcutils/Makefile index 6022505577..f8ac92f7d9 100644 --- a/tools/xcutils/Makefile +++ b/tools/xcutils/Makefile @@ -13,7 +13,7 @@ include $(XEN_ROOT)/tools/Rules.mk PROGRAMS_INSTALL_DIR = /usr/$(LIBDIR)/xen/bin -INCLUDES += -I $(XEN_LIBXC) +INCLUDES += -I $(XEN_LIBXC) -I $(XEN_XENSTORE) CFLAGS += -Werror -fno-strict-aliasing CFLAGS += $(INCLUDES) @@ -22,9 +22,9 @@ CFLAGS += $(INCLUDES) CFLAGS += -Wp,-MD,.$(@F).d PROG_DEP = .*.d -PROGRAMS = xc_restore xc_save readnotes +PROGRAMS = xc_restore xc_save readnotes -LDLIBS = -L$(XEN_LIBXC) -lxenguest -lxenctrl +LDLIBS = -L$(XEN_LIBXC) -L$(XEN_XENSTORE) -lxenguest -lxenctrl -lxenstore .PHONY: all all: build diff --git a/tools/xcutils/xc_save.c b/tools/xcutils/xc_save.c index 0c9530da4d..2285af4b97 100644 --- a/tools/xcutils/xc_save.c +++ b/tools/xcutils/xc_save.c @@ -12,7 +12,13 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include #include @@ -31,6 +37,123 @@ static int suspend(int domid) !strncmp(ans, "done\n", 5)); } +/* For HVM guests, there are two sources of dirty pages: the Xen shadow + * log-dirty bitmap, which we get with a hypercall, and qemu's version. + * The protocol for getting page-dirtying data from qemu uses a + * double-buffered shared memory interface directly between xc_save and + * qemu-dm. + * + * xc_save calculates the size of the bitmaps and notifies qemu-dm + * through the store that it wants to share the bitmaps. qemu-dm then + * starts filling in the 'active' buffer. + * + * To change the buffers over, xc_save writes the other buffer number to + * the store and waits for qemu to acknowledge that it is now writing to + * the new active buffer. xc_save can then process and clear the old + * active buffer. */ + +static char *qemu_active_path; +static char *qemu_next_active_path; +static struct xs_handle *xs; + +/* Get qemu to change buffers. */ +static void qemu_flip_buffer(int domid, int next_active) +{ + char digit = '0' + next_active; + unsigned int len; + char *active_str, **watch; + struct timeval tv; + fd_set fdset; + + /* Tell qemu that we want it to start writing log-dirty bits to the + * other buffer */ + if (!xs_write(xs, XBT_NULL, qemu_next_active_path, &digit, 1)) { + errx(1, "can't write next-active to store path (%s)\n", + qemu_next_active_path); + exit(1); + } + + /* Wait a while for qemu to signal that it has switched to the new + * active buffer */ + read_again: + tv.tv_sec = 5; + tv.tv_usec = 0; + FD_ZERO(&fdset); + FD_SET(xs_fileno(xs), &fdset); + if ((select(xs_fileno(xs) + 1, &fdset, NULL, NULL, &tv)) != 1) { + errx(1, "timed out waiting for qemu to switch buffers\n"); + exit(1); + } + watch = xs_read_watch(xs, &len); + free(watch); + + active_str = xs_read(xs, XBT_NULL, qemu_active_path, &len); + if (active_str == NULL || active_str[0] - '0' != next_active) + /* Watch fired but value is not yet right */ + goto read_again; +} + +static void * init_qemu_maps(int domid, unsigned int bitmap_size) +{ + key_t key; + char key_ascii[17] = {0,}; + int shmid = -1; + void *seg; + char *path, *p; + + /* Make a shared-memory segment */ + while (shmid == -1) + { + key = rand(); /* No security, just a sequence of numbers */ + shmid = shmget(key, 2 * bitmap_size, + IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR); + if (shmid == -1 && errno != EEXIST) + errx(1, "can't get shmem to talk to qemu-dm"); + } + + /* Map it into our address space */ + seg = shmat(shmid, NULL, 0); + if (seg == (void *) -1) + errx(1, "can't map shmem to talk to qemu-dm"); + memset(seg, 0, 2 * bitmap_size); + + /* Write the size of it into the first 32 bits */ + *(uint32_t *)seg = bitmap_size; + + /* Tell qemu about it */ + if ((xs = xs_daemon_open()) == NULL) + errx(1, "Couldn't contact xenstore"); + if (!(path = xs_get_domain_path(xs, domid))) + errx(1, "can't get domain path in store"); + if (!(path = realloc(path, strlen(path) + + strlen("/logdirty/next-active") + 1))) + errx(1, "no memory for constructing xenstore path"); + strcat(path, "/logdirty/"); + p = path + strlen(path); + + strcpy(p, "key"); + snprintf(key_ascii, 17, "%16.16llx", (unsigned long long) key); + if (!xs_write(xs, XBT_NULL, path, key_ascii, 16)) + errx(1, "can't write key (%s) to store path (%s)\n", key_ascii, path); + + /* Watch for qemu's indication of the active buffer, and request it + * to start writing to buffer 0 */ + strcpy(p, "active"); + if (!xs_watch(xs, path, "qemu-active-buffer")) + errx(1, "can't set watch in store (%s)\n", path); + if (!(qemu_active_path = strdup(path))) + errx(1, "no memory for copying xenstore path"); + + strcpy(p, "next-active"); + if (!(qemu_next_active_path = strdup(path))) + errx(1, "no memory for copying xenstore path"); + + qemu_flip_buffer(domid, 0); + + free(path); + return seg; +} + int main(int argc, char **argv) @@ -52,9 +175,11 @@ main(int argc, char **argv) flags = atoi(argv[5]); if (flags & XCFLAGS_HVM) - ret = xc_hvm_save(xc_fd, io_fd, domid, maxit, max_f, flags, &suspend); + ret = xc_hvm_save(xc_fd, io_fd, domid, maxit, max_f, flags, + &suspend, &init_qemu_maps, &qemu_flip_buffer); else - ret = xc_linux_save(xc_fd, io_fd, domid, maxit, max_f, flags, &suspend); + ret = xc_linux_save(xc_fd, io_fd, domid, maxit, max_f, flags, + &suspend); xc_interface_close(xc_fd); From b897b26dbec0c6c19a80c9fc27ec4787e128bd4c Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Fri, 16 Mar 2007 11:41:10 +0000 Subject: [PATCH 116/170] [HVM][SVM] Save/restore: save the guest's versions of CR0 and EFER and recalculate the vmcb ones on restore Signed-off-by: Tim Deegan --- xen/arch/x86/hvm/svm/svm.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index c6faddcd95..e4268dafd7 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -449,6 +449,9 @@ int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c) vmcb->rflags = c->eflags; v->arch.hvm_svm.cpu_shadow_cr0 = c->cr0; + vmcb->cr0 = c->cr0 | X86_CR0_WP | X86_CR0_ET; + if ( !paging_mode_hap(v->domain) ) + vmcb->cr0 |= X86_CR0_PG; #ifdef HVM_DEBUG_SUSPEND printk("%s: cr3=0x%"PRIx64", cr0=0x%"PRIx64", cr4=0x%"PRIx64".\n", @@ -566,7 +569,7 @@ void svm_save_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data) data->msr_star = vmcb->star; data->msr_cstar = vmcb->cstar; data->msr_syscall_mask = vmcb->sfmask; - data->msr_efer = vmcb->efer; + data->msr_efer = v->arch.hvm_svm.cpu_shadow_efer; data->tsc = hvm_get_guest_time(v); } @@ -581,7 +584,12 @@ void svm_load_cpu_state(struct vcpu *v, struct hvm_hw_cpu *data) vmcb->star = data->msr_star; vmcb->cstar = data->msr_cstar; vmcb->sfmask = data->msr_syscall_mask; - vmcb->efer = data->msr_efer; + v->arch.hvm_svm.cpu_shadow_efer = data->msr_efer; + vmcb->efer = data->msr_efer | EFER_SVME; + /* VMCB's EFER.LME isn't set unless we're actually in long mode + * (see long_mode_do_msr_write()) */ + if ( !(vmcb->efer & EFER_LMA) ) + vmcb->efer &= ~EFER_LME; hvm_set_guest_time(v, data->tsc); } From 3a4b9dc8226a7f75a710661756bdb608fa2eaf8e Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 16 Mar 2007 15:18:33 +0000 Subject: [PATCH 117/170] Revert CONFIG_SPLIT_PTLOCK_CPUS change of 14209:1061c7bff38f3e6e66fee96c407977ad55b3f2f2. Jan Beulich points out that it's not safe against mm pinning and unpinning. Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/mm/Kconfig | 157 ++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 linux-2.6-xen-sparse/mm/Kconfig diff --git a/linux-2.6-xen-sparse/mm/Kconfig b/linux-2.6-xen-sparse/mm/Kconfig new file mode 100644 index 0000000000..14492aaa5b --- /dev/null +++ b/linux-2.6-xen-sparse/mm/Kconfig @@ -0,0 +1,157 @@ +config SELECT_MEMORY_MODEL + def_bool y + depends on EXPERIMENTAL || ARCH_SELECT_MEMORY_MODEL + +choice + prompt "Memory model" + depends on SELECT_MEMORY_MODEL + default DISCONTIGMEM_MANUAL if ARCH_DISCONTIGMEM_DEFAULT + default SPARSEMEM_MANUAL if ARCH_SPARSEMEM_DEFAULT + default FLATMEM_MANUAL + +config FLATMEM_MANUAL + bool "Flat Memory" + depends on !(ARCH_DISCONTIGMEM_ENABLE || ARCH_SPARSEMEM_ENABLE) || ARCH_FLATMEM_ENABLE + help + This option allows you to change some of the ways that + Linux manages its memory internally. Most users will + only have one option here: FLATMEM. This is normal + and a correct option. + + Some users of more advanced features like NUMA and + memory hotplug may have different options here. + DISCONTIGMEM is an more mature, better tested system, + but is incompatible with memory hotplug and may suffer + decreased performance over SPARSEMEM. If unsure between + "Sparse Memory" and "Discontiguous Memory", choose + "Discontiguous Memory". + + If unsure, choose this option (Flat Memory) over any other. + +config DISCONTIGMEM_MANUAL + bool "Discontiguous Memory" + depends on ARCH_DISCONTIGMEM_ENABLE + help + This option provides enhanced support for discontiguous + memory systems, over FLATMEM. These systems have holes + in their physical address spaces, and this option provides + more efficient handling of these holes. However, the vast + majority of hardware has quite flat address spaces, and + can have degraded performance from extra overhead that + this option imposes. + + Many NUMA configurations will have this as the only option. + + If unsure, choose "Flat Memory" over this option. + +config SPARSEMEM_MANUAL + bool "Sparse Memory" + depends on ARCH_SPARSEMEM_ENABLE + help + This will be the only option for some systems, including + memory hotplug systems. This is normal. + + For many other systems, this will be an alternative to + "Discontiguous Memory". This option provides some potential + performance benefits, along with decreased code complexity, + but it is newer, and more experimental. + + If unsure, choose "Discontiguous Memory" or "Flat Memory" + over this option. + +endchoice + +config DISCONTIGMEM + def_bool y + depends on (!SELECT_MEMORY_MODEL && ARCH_DISCONTIGMEM_ENABLE) || DISCONTIGMEM_MANUAL + +config SPARSEMEM + def_bool y + depends on SPARSEMEM_MANUAL + +config FLATMEM + def_bool y + depends on (!DISCONTIGMEM && !SPARSEMEM) || FLATMEM_MANUAL + +config FLAT_NODE_MEM_MAP + def_bool y + depends on !SPARSEMEM + +# +# Both the NUMA code and DISCONTIGMEM use arrays of pg_data_t's +# to represent different areas of memory. This variable allows +# those dependencies to exist individually. +# +config NEED_MULTIPLE_NODES + def_bool y + depends on DISCONTIGMEM || NUMA + +config HAVE_MEMORY_PRESENT + def_bool y + depends on ARCH_HAVE_MEMORY_PRESENT || SPARSEMEM + +# +# SPARSEMEM_EXTREME (which is the default) does some bootmem +# allocations when memory_present() is called. If this can not +# be done on your architecture, select this option. However, +# statically allocating the mem_section[] array can potentially +# consume vast quantities of .bss, so be careful. +# +# This option will also potentially produce smaller runtime code +# with gcc 3.4 and later. +# +config SPARSEMEM_STATIC + def_bool n + +# +# Architectecture platforms which require a two level mem_section in SPARSEMEM +# must select this option. This is usually for architecture platforms with +# an extremely sparse physical address space. +# +config SPARSEMEM_EXTREME + def_bool y + depends on SPARSEMEM && !SPARSEMEM_STATIC + +# eventually, we can have this option just 'select SPARSEMEM' +config MEMORY_HOTPLUG + bool "Allow for memory hot-add" + depends on SPARSEMEM && HOTPLUG && !SOFTWARE_SUSPEND && ARCH_ENABLE_MEMORY_HOTPLUG + depends on (IA64 || X86 || PPC64) + +comment "Memory hotplug is currently incompatible with Software Suspend" + depends on SPARSEMEM && HOTPLUG && SOFTWARE_SUSPEND + +# Heavily threaded applications may benefit from splitting the mm-wide +# page_table_lock, so that faults on different parts of the user address +# space can be handled with less contention: split it at this NR_CPUS. +# Default to 4 for wider testing, though 8 might be more appropriate. +# ARM's adjust_pte (unused if VIPT) depends on mm-wide page_table_lock. +# PA-RISC 7xxx's spinlock_t would enlarge struct page from 32 to 44 bytes. +# XEN on x86 architecture uses the mapping field on pagetable pages to store a +# pointer to the destructor. This conflicts with pte_lock_deinit(). +# +config SPLIT_PTLOCK_CPUS + int + default "4096" if ARM && !CPU_CACHE_VIPT + default "4096" if PARISC && !PA20 + default "4096" if X86_XEN || X86_64_XEN + default "4" + +# +# support for page migration +# +config MIGRATION + bool "Page migration" + def_bool y + depends on NUMA + help + Allows the migration of the physical location of pages of processes + while the virtual addresses are not changed. This is useful for + example on NUMA systems to put pages nearer to the processors accessing + the page. + +config RESOURCES_64BIT + bool "64 bit Memory and IO resources (EXPERIMENTAL)" if (!64BIT && EXPERIMENTAL) + default 64BIT + help + This option allows memory and IO resources to be 64 bit. From fbf7473b3a74f449736ec58e9dce5dda2ef8bc9d Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 16 Mar 2007 15:19:08 +0000 Subject: [PATCH 118/170] linux: Various cleanup and locking clarification (and fixing!) of mm pinning/unpinning logic. Signed-off-by: Keir Fraser --- .../arch/i386/mm/pgtable-xen.c | 14 ++- .../arch/x86_64/mm/pageattr-xen.c | 86 +++++++++++-------- 2 files changed, 62 insertions(+), 38 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c b/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c index 28752922e3..df20e591c1 100644 --- a/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c @@ -256,8 +256,9 @@ void pte_free(struct page *pte) unsigned long va = (unsigned long)__va(pfn << PAGE_SHIFT); if (!pte_write(*virt_to_ptep(va))) - BUG_ON(HYPERVISOR_update_va_mapping( - va, pfn_pte(pfn, PAGE_KERNEL), 0)); + if (HYPERVISOR_update_va_mapping( + va, pfn_pte(pfn, PAGE_KERNEL), 0)) + BUG(); } else clear_bit(PG_pinned, &pte->flags); @@ -672,14 +673,23 @@ void mm_unpin(struct mm_struct *mm) void mm_pin_all(void) { struct page *page; + unsigned long flags; if (xen_feature(XENFEAT_writable_page_tables)) return; + /* + * Allow uninterrupted access to the pgd_list. Also protects + * __pgd_pin() by disabling preemption. + * All other CPUs must be at a safe point (e.g., in stop_machine + * or offlined entirely). + */ + spin_lock_irqsave(&pgd_lock, flags); for (page = pgd_list; page; page = (struct page *)page->index) { if (!test_bit(PG_pinned, &page->flags)) __pgd_pin((pgd_t *)page_address(page)); } + spin_unlock_irqrestore(&pgd_lock, flags); } void _arch_dup_mmap(struct mm_struct *mm) diff --git a/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c b/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c index ae434e6be4..3b5fc26e84 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c +++ b/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c @@ -79,14 +79,17 @@ void mm_pin(struct mm_struct *mm) spin_lock(&mm->page_table_lock); mm_walk(mm, PAGE_KERNEL_RO); - BUG_ON(HYPERVISOR_update_va_mapping( - (unsigned long)mm->pgd, - pfn_pte(virt_to_phys(mm->pgd)>>PAGE_SHIFT, PAGE_KERNEL_RO), - UVMF_TLB_FLUSH)); - BUG_ON(HYPERVISOR_update_va_mapping( - (unsigned long)__user_pgd(mm->pgd), - pfn_pte(virt_to_phys(__user_pgd(mm->pgd))>>PAGE_SHIFT, PAGE_KERNEL_RO), - UVMF_TLB_FLUSH)); + if (HYPERVISOR_update_va_mapping( + (unsigned long)mm->pgd, + pfn_pte(virt_to_phys(mm->pgd)>>PAGE_SHIFT, PAGE_KERNEL_RO), + UVMF_TLB_FLUSH)) + BUG(); + if (HYPERVISOR_update_va_mapping( + (unsigned long)__user_pgd(mm->pgd), + pfn_pte(virt_to_phys(__user_pgd(mm->pgd))>>PAGE_SHIFT, + PAGE_KERNEL_RO), + UVMF_TLB_FLUSH)) + BUG(); xen_pgd_pin(__pa(mm->pgd)); /* kernel */ xen_pgd_pin(__pa(__user_pgd(mm->pgd))); /* user */ mm->context.pinned = 1; @@ -106,12 +109,15 @@ void mm_unpin(struct mm_struct *mm) xen_pgd_unpin(__pa(mm->pgd)); xen_pgd_unpin(__pa(__user_pgd(mm->pgd))); - BUG_ON(HYPERVISOR_update_va_mapping( - (unsigned long)mm->pgd, - pfn_pte(virt_to_phys(mm->pgd)>>PAGE_SHIFT, PAGE_KERNEL), 0)); - BUG_ON(HYPERVISOR_update_va_mapping( - (unsigned long)__user_pgd(mm->pgd), - pfn_pte(virt_to_phys(__user_pgd(mm->pgd))>>PAGE_SHIFT, PAGE_KERNEL), 0)); + if (HYPERVISOR_update_va_mapping( + (unsigned long)mm->pgd, + pfn_pte(virt_to_phys(mm->pgd)>>PAGE_SHIFT, PAGE_KERNEL), 0)) + BUG(); + if (HYPERVISOR_update_va_mapping( + (unsigned long)__user_pgd(mm->pgd), + pfn_pte(virt_to_phys(__user_pgd(mm->pgd))>>PAGE_SHIFT, + PAGE_KERNEL), 0)) + BUG(); mm_walk(mm, PAGE_KERNEL); xen_tlb_flush(); mm->context.pinned = 0; @@ -127,43 +133,50 @@ void mm_pin_all(void) if (xen_feature(XENFEAT_writable_page_tables)) return; + /* + * Allow uninterrupted access to the mm_unpinned list. We don't + * actually take the mm_unpinned_lock as it is taken inside mm_pin(). + * All other CPUs must be at a safe point (e.g., in stop_machine + * or offlined entirely). + */ + preempt_disable(); while (!list_empty(&mm_unpinned)) mm_pin(list_entry(mm_unpinned.next, struct mm_struct, context.unpinned)); + preempt_enable(); } void _arch_dup_mmap(struct mm_struct *mm) { - if (!mm->context.pinned) - mm_pin(mm); + if (!mm->context.pinned) + mm_pin(mm); } void _arch_exit_mmap(struct mm_struct *mm) { - struct task_struct *tsk = current; + struct task_struct *tsk = current; - task_lock(tsk); + task_lock(tsk); - /* - * We aggressively remove defunct pgd from cr3. We execute unmap_vmas() - * *much* faster this way, as no tlb flushes means bigger wrpt batches. - */ - if ( tsk->active_mm == mm ) - { - tsk->active_mm = &init_mm; - atomic_inc(&init_mm.mm_count); + /* + * We aggressively remove defunct pgd from cr3. We execute unmap_vmas() + * *much* faster this way, as no tlb flushes means bigger wrpt batches. + */ + if (tsk->active_mm == mm) { + tsk->active_mm = &init_mm; + atomic_inc(&init_mm.mm_count); - switch_mm(mm, &init_mm, tsk); + switch_mm(mm, &init_mm, tsk); - atomic_dec(&mm->mm_count); - BUG_ON(atomic_read(&mm->mm_count) == 0); - } + atomic_dec(&mm->mm_count); + BUG_ON(atomic_read(&mm->mm_count) == 0); + } - task_unlock(tsk); + task_unlock(tsk); - if ( mm->context.pinned && (atomic_read(&mm->mm_count) == 1) && - !mm->context.has_foreign_mappings ) - mm_unpin(mm); + if ( mm->context.pinned && (atomic_read(&mm->mm_count) == 1) && + !mm->context.has_foreign_mappings ) + mm_unpin(mm); } struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) @@ -183,8 +196,9 @@ void pte_free(struct page *pte) unsigned long va = (unsigned long)__va(page_to_pfn(pte)< Date: Fri, 16 Mar 2007 16:19:35 +0000 Subject: [PATCH 119/170] hvm vpic: Fix IRQ priority calculation in 8259 device model. The priority shift should be a right-rotation, not a left-rotation. From: Trolle Selander Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/vpic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/hvm/vpic.c b/xen/arch/x86/hvm/vpic.c index 3a5b2a16a8..5dfe1e4a6b 100644 --- a/xen/arch/x86/hvm/vpic.c +++ b/xen/arch/x86/hvm/vpic.c @@ -54,8 +54,8 @@ static int vpic_get_priority(struct hvm_hw_vpic *vpic, uint8_t mask) if ( mask == 0 ) return VPIC_PRIO_NONE; - /* prio = ffs(mask ROL vpic->priority_add); */ - asm ( "rol %%cl,%b1 ; bsf %1,%0" + /* prio = ffs(mask ROR vpic->priority_add); */ + asm ( "ror %%cl,%b1 ; bsf %1,%0" : "=r" (prio) : "r" ((uint32_t)mask), "c" (vpic->priority_add) ); return prio; } From aff27f6f5be9ebe2437ba3096c205b8e139f2751 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 16 Mar 2007 16:21:16 +0000 Subject: [PATCH 120/170] hvm mmio: two additional mmio ops that OS/2 needs emulated. From: Trolle Selander Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/platform.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/xen/arch/x86/hvm/platform.c b/xen/arch/x86/hvm/platform.c index 9ba8c3e4a3..185a7c2f55 100644 --- a/xen/arch/x86/hvm/platform.c +++ b/xen/arch/x86/hvm/platform.c @@ -415,6 +415,17 @@ static int mmio_decode(int address_bytes, unsigned char *opcode, GET_OP_SIZE_FOR_NONEBYTE(*op_size); return mem_reg(*op_size, opcode, mmio_op, rex); + case 0x08: /* or r8, m8 */ + mmio_op->instr = INSTR_OR; + *op_size = BYTE; + GET_OP_SIZE_FOR_BYTE(size_reg); + return reg_mem(size_reg, opcode, mmio_op, rex); + + case 0x09: /* or r32/16, m32/16 */ + mmio_op->instr = INSTR_OR; + GET_OP_SIZE_FOR_NONEBYTE(*op_size); + return reg_mem(*op_size, opcode, mmio_op, rex); + case 0x0A: /* or m8, r8 */ mmio_op->instr = INSTR_OR; *op_size = BYTE; From c4b2f8b295e2c1320349c5050cc9cc762813e83a Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 16 Mar 2007 16:22:29 +0000 Subject: [PATCH 121/170] hvm ioemu: Add support for IOREQ_TYPE_XCHG in qemu-dm. From: Trolle Selander Signed-off-by: Keir Fraser --- tools/ioemu/target-i386-dm/helper2.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tools/ioemu/target-i386-dm/helper2.c b/tools/ioemu/target-i386-dm/helper2.c index 7a5f3412c9..17261e632d 100644 --- a/tools/ioemu/target-i386-dm/helper2.c +++ b/tools/ioemu/target-i386-dm/helper2.c @@ -439,6 +439,18 @@ void cpu_ioreq_xor(CPUState *env, ioreq_t *req) req->data = tmp1; } +void cpu_ioreq_xchg(CPUState *env, ioreq_t *req) +{ + unsigned long tmp1; + + if (req->data_is_ptr != 0) + hw_error("expected scalar value"); + + read_physical(req->addr, req->size, &tmp1); + write_physical(req->addr, req->size, &req->data); + req->data = tmp1; +} + void __handle_ioreq(CPUState *env, ioreq_t *req) { if (!req->data_is_ptr && req->dir == IOREQ_WRITE && req->size != 4) @@ -463,6 +475,9 @@ void __handle_ioreq(CPUState *env, ioreq_t *req) case IOREQ_TYPE_XOR: cpu_ioreq_xor(env, req); break; + case IOREQ_TYPE_XCHG: + cpu_ioreq_xchg(env, req); + break; default: hw_error("Invalid ioreq type 0x%x\n", req->type); } From d4da3e95988a0ed6b442c800df49ed91bf5f4a89 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Fri, 16 Mar 2007 16:40:18 +0000 Subject: [PATCH 122/170] [QEMU] fix typo in 14405 Signe-off-by: Tim Deegan --- tools/ioemu/xenstore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ioemu/xenstore.c b/tools/ioemu/xenstore.c index f1aa2f5e33..4f549ac5e3 100644 --- a/tools/ioemu/xenstore.c +++ b/tools/ioemu/xenstore.c @@ -229,7 +229,7 @@ void xenstore_process_logdirty_event(void) fprintf(logfile, "Triggered log-dirty buffer switch\n"); if (!seg) { - char *path, *p, *key_ascii, *key_terminated[17] = {0,}; + char *path, *p, *key_ascii, key_terminated[17] = {0,}; key_t key; int shmid; From 96541d59b45a24e9fe31936724abbc4214c5f536 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Fri, 16 Mar 2007 18:06:43 +0000 Subject: [PATCH 123/170] Fix VM_metrics.get_vcpus_utilisation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix is due to Ingard MevÃ¥g . Signed-off-by: Ewan Mellor --- tools/python/xen/xend/XendAPI.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index cb444f04d1..ba91b06018 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -1550,7 +1550,7 @@ class XendAPI(object): return xen_api_success(self._VM_metrics_get(ref).get_vcpus_number()) def VM_metrics_get_vcpus_utilisation(self, _, ref): - return xen_api_success(self._VM_metrics_get(ref).get_metrics_get_vcpus_utilisation()) + return xen_api_success(self._VM_metrics_get(ref).get_vcpus_utilisation()) # Xen API: Class VBD # ---------------------------------------------------------------- From 6f672de82656c167805e132a0ee5072a28c5ef86 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 16 Mar 2007 18:59:28 +0000 Subject: [PATCH 124/170] libxc: Explicitly reserve space for special pages in HVM memmap. Signed-off-by: Keir Fraser --- tools/libxc/xc_hvm_build.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/libxc/xc_hvm_build.c b/tools/libxc/xc_hvm_build.c index 00f4624501..4b23e9fdb1 100644 --- a/tools/libxc/xc_hvm_build.c +++ b/tools/libxc/xc_hvm_build.c @@ -137,6 +137,12 @@ static void build_e820map(void *e820_page, unsigned long long mem_size) e820entry[nr_map].type = E820_RAM; nr_map++; + /* Explicitly reserve space for special pages (ioreq and xenstore). */ + e820entry[nr_map].addr = mem_size - PAGE_SIZE * 3; + e820entry[nr_map].size = PAGE_SIZE * 3; + e820entry[nr_map].type = E820_RESERVED; + nr_map++; + if ( extra_mem_size ) { e820entry[nr_map].addr = (1ULL << 32); From cdc48dd8423107978889f10e8789c69ea5bd8f5c Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 16 Mar 2007 18:59:55 +0000 Subject: [PATCH 125/170] rombios: Simplify memory-size bios calls and derive all results from the e820 map. Signed-off-by: Keir Fraser --- tools/firmware/rombios/rombios.c | 228 +++++++++---------------------- 1 file changed, 68 insertions(+), 160 deletions(-) diff --git a/tools/firmware/rombios/rombios.c b/tools/firmware/rombios/rombios.c index c8fbb92ab1..eb288a80fa 100644 --- a/tools/firmware/rombios/rombios.c +++ b/tools/firmware/rombios/rombios.c @@ -4196,178 +4196,86 @@ ASM_END case 0xe8: switch(regs.u.r8.al) { - case 0x20: // coded by osmaker aka K.J. - if(regs.u.r32.edx == 0x534D4150) /* SMAP */ - { -#ifdef HVMASSIST - if ((regs.u.r16.bx / 0x14) * 0x14 == regs.u.r16.bx) { - Bit16u e820_table_size = read_word(0xe000, 0x8) * 0x14; + case 0x20: { + Bit16u e820_table_size = read_word(0xe000, 0x8) * 0x14; - if (regs.u.r16.bx + 0x14 <= e820_table_size) { - memcpyb(ES, regs.u.r16.di, - 0xe000, 0x10 + regs.u.r16.bx, 0x14); - } - regs.u.r32.ebx += 0x14; - if ((regs.u.r32.ebx + 0x14 - 1) > e820_table_size) - regs.u.r32.ebx = 0; - regs.u.r32.eax = 0x534D4150; - regs.u.r32.ecx = 0x14; - CLEAR_CF(); - return; - } else if (regs.u.r16.bx == 1) { - extended_memory_size = inb_cmos(0x35); - extended_memory_size <<= 8; - extended_memory_size |= inb_cmos(0x34); - extended_memory_size *= 64; - if (extended_memory_size > 0x3bc000) // greater than EFF00000??? - { - extended_memory_size = 0x3bc000; // everything after this is reserved memory until we get to 0x100000000 - } - extended_memory_size *= 1024; - extended_memory_size += 15728640; // make up for the 16mb of memory that is chopped off + if (regs.u.r32.edx != 0x534D4150) /* SMAP */ + goto int15_unimplemented; - if (extended_memory_size <= 15728640) - { - extended_memory_size = inb_cmos(0x31); - extended_memory_size <<= 8; - extended_memory_size |= inb_cmos(0x30); - extended_memory_size *= 1024; - } - - write_word(ES, regs.u.r16.di, 0x0000); - write_word(ES, regs.u.r16.di+2, 0x0010); - write_word(ES, regs.u.r16.di+4, 0x0000); - write_word(ES, regs.u.r16.di+6, 0x0000); - - write_word(ES, regs.u.r16.di+8, extended_memory_size); - extended_memory_size >>= 16; - write_word(ES, regs.u.r16.di+10, extended_memory_size); - extended_memory_size >>= 16; - write_word(ES, regs.u.r16.di+12, extended_memory_size); - extended_memory_size >>= 16; - write_word(ES, regs.u.r16.di+14, extended_memory_size); - - write_word(ES, regs.u.r16.di+16, 0x1); - write_word(ES, regs.u.r16.di+18, 0x0); - - regs.u.r32.ebx = 0; - regs.u.r32.eax = 0x534D4150; - regs.u.r32.ecx = 0x14; - CLEAR_CF(); - return; - } else { /* AX=E820, DX=534D4150, BX unrecognized */ - goto int15_unimplemented; - } -#else - switch(regs.u.r16.bx) - { - case 0: - write_word(ES, regs.u.r16.di, 0x00); - write_word(ES, regs.u.r16.di+2, 0x00); - write_word(ES, regs.u.r16.di+4, 0x00); - write_word(ES, regs.u.r16.di+6, 0x00); - - write_word(ES, regs.u.r16.di+8, 0xFC00); - write_word(ES, regs.u.r16.di+10, 0x0009); - write_word(ES, regs.u.r16.di+12, 0x0000); - write_word(ES, regs.u.r16.di+14, 0x0000); - - write_word(ES, regs.u.r16.di+16, 0x1); - write_word(ES, regs.u.r16.di+18, 0x0); - - regs.u.r32.ebx = 1; - - regs.u.r32.eax = 0x534D4150; - regs.u.r32.ecx = 0x14; - CLEAR_CF(); - return; - break; - case 1: - extended_memory_size = inb_cmos(0x35); - extended_memory_size <<= 8; - extended_memory_size |= inb_cmos(0x34); - extended_memory_size *= 64; - if(extended_memory_size > 0x3bc000) // greater than EFF00000??? - { - extended_memory_size = 0x3bc000; // everything after this is reserved memory until we get to 0x100000000 - } - extended_memory_size *= 1024; - extended_memory_size += 15728640; // make up for the 16mb of memory that is chopped off - - if(extended_memory_size <= 15728640) - { - extended_memory_size = inb_cmos(0x31); - extended_memory_size <<= 8; - extended_memory_size |= inb_cmos(0x30); - extended_memory_size *= 1024; - } - - write_word(ES, regs.u.r16.di, 0x0000); - write_word(ES, regs.u.r16.di+2, 0x0010); - write_word(ES, regs.u.r16.di+4, 0x0000); - write_word(ES, regs.u.r16.di+6, 0x0000); - - write_word(ES, regs.u.r16.di+8, extended_memory_size); - extended_memory_size >>= 16; - write_word(ES, regs.u.r16.di+10, extended_memory_size); - extended_memory_size >>= 16; - write_word(ES, regs.u.r16.di+12, extended_memory_size); - extended_memory_size >>= 16; - write_word(ES, regs.u.r16.di+14, extended_memory_size); - - write_word(ES, regs.u.r16.di+16, 0x1); - write_word(ES, regs.u.r16.di+18, 0x0); - - regs.u.r32.ebx = 0; - regs.u.r32.eax = 0x534D4150; - regs.u.r32.ecx = 0x14; - CLEAR_CF(); - return; - break; - default: /* AX=E820, DX=534D4150, BX unrecognized */ - goto int15_unimplemented; + if ((regs.u.r16.bx / 0x14) * 0x14 == regs.u.r16.bx) { + if (regs.u.r16.bx + 0x14 <= e820_table_size) + memcpyb(ES, regs.u.r16.di, + 0xe000, 0x10 + regs.u.r16.bx, 0x14); + regs.u.r32.ebx += 0x14; + if ((regs.u.r32.ebx + 0x14 - 1) > e820_table_size) + regs.u.r32.ebx = 0; + } else if (regs.u.r16.bx == 1) { + Bit32u base, type; + Bit16u off; + for (off = 0; off < e820_table_size; off += 0x14) { + base = read_dword(0xe000, 0x10 + off); + type = read_dword(0xe000, 0x20 + off); + if ((base >= 0x100000) && (type == 1)) break; } -#endif - } else { - // if DX != 0x534D4150) - goto int15_unimplemented; - } + if (off == e820_table_size) { + SET_CF(); + break; + } + memcpyb(ES, regs.u.r16.di, 0xe000, 0x10 + off, 0x14); + regs.u.r32.ebx = 0; + } else { /* AX=E820, DX=534D4150, BX unrecognized */ + goto int15_unimplemented; + } + + regs.u.r32.eax = 0x534D4150; + regs.u.r32.ecx = 0x14; + CLEAR_CF(); break; + } - case 0x01: - // do we have any reason to fail here ? - CLEAR_CF(); + case 0x01: { + Bit16u off, e820_table_size = read_word(0xe000, 0x8) * 0x14; + Bit32u base, type, size; - // my real system sets ax and bx to 0 - // this is confirmed by Ralph Brown list - // but syslinux v1.48 is known to behave - // strangely if ax is set to 0 - // regs.u.r16.ax = 0; - // regs.u.r16.bx = 0; + // do we have any reason to fail here ? + CLEAR_CF(); - // Get the amount of extended memory (above 1M) - regs.u.r8.cl = inb_cmos(0x30); - regs.u.r8.ch = inb_cmos(0x31); + // Get the amount of extended memory (above 1M) + regs.u.r8.cl = inb_cmos(0x30); + regs.u.r8.ch = inb_cmos(0x31); - // limit to 15M - if(regs.u.r16.cx > 0x3c00) - { - regs.u.r16.cx = 0x3c00; - } + // limit to 15M + if (regs.u.r16.cx > (15*1024)) + regs.u.r16.cx = 15*1024; - // Get the amount of extended memory above 16M in 64k blocs - regs.u.r8.dl = inb_cmos(0x34); - regs.u.r8.dh = inb_cmos(0x35); + // Find first RAM E820 entry >= 1MB. + for (off = 0; off < e820_table_size; off += 0x14) { + base = read_dword(0xe000, 0x10 + off); + type = read_dword(0xe000, 0x20 + off); + if ((base >= 0x100000) && (type == 1)) + break; + } - // Set configured memory equal to extended memory - regs.u.r16.ax = regs.u.r16.cx; - regs.u.r16.bx = regs.u.r16.dx; - break; + // If there is RAM above 16MB, return amount in 64kB chunks. + regs.u.r16.dx = 0; + if (off != e820_table_size) { + size = base + read_dword(0xe000, 0x18 + off); + if (size > 0x1000000) { + size -= 0x1000000; + regs.u.r16.dx = (Bit16u)(size >> 16); + } + } + + // Set configured memory equal to extended memory + regs.u.r16.ax = regs.u.r16.cx; + regs.u.r16.bx = regs.u.r16.dx; + break; + } default: /* AH=0xE8?? but not implemented */ - goto int15_unimplemented; - } - break; + goto int15_unimplemented; + } + break; int15_unimplemented: // fall into the default default: From 31e57af5d6cbb22ef7d1379a5b9e2a2c45fc1bae Mon Sep 17 00:00:00 2001 From: Jake Wires Date: Fri, 16 Mar 2007 15:23:26 -0700 Subject: [PATCH 126/170] [TAPDISK] unlock sector on error case Signed-off-by: Jake Wires --- tools/blktap/drivers/block-qcow.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/blktap/drivers/block-qcow.c b/tools/blktap/drivers/block-qcow.c index 36f77e6f05..b0822f729d 100644 --- a/tools/blktap/drivers/block-qcow.c +++ b/tools/blktap/drivers/block-qcow.c @@ -1057,6 +1057,7 @@ int tdqcow_queue_write(struct disk_driver *dd, uint64_t sector, index_in_cluster+n); if (!cluster_offset) { DPRINTF("Ooops, no write cluster offset!\n"); + aio_unlock(s, sector); return cb(dd, -EIO, sector, nb_sectors, id, private); } From 93943bf038d7c752bd719400bed29e60aab03211 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Fri, 16 Mar 2007 23:33:44 +0000 Subject: [PATCH 127/170] Fix build when bcc is not installed. --- tools/firmware/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/firmware/Makefile b/tools/firmware/Makefile index b924fde793..38338471fd 100644 --- a/tools/firmware/Makefile +++ b/tools/firmware/Makefile @@ -14,7 +14,7 @@ SUBDIRS += hvmloader .PHONY: all all: - @set -e; if [ $$((`bcc -v 2>&1 | grep version | cut -d' ' -f 3 | awk -F. '{ printf "0x%02x%02x%02x", $$1, $$2, $$3}'`)) -lt $$((0x00100e)) ] ; then \ + @set -e; if [ $$((`( bcc -v 2>&1 | grep version || echo 0.0.0 ) | cut -d' ' -f 3 | awk -F. '{ printf "0x%02x%02x%02x", $$1, $$2, $$3}'`)) -lt $$((0x00100e)) ] ; then \ echo "***********************************************************"; \ echo "Require dev86 package version >= 0.16.14 to build firmware!"; \ echo "(visit http://www.cix.co.uk/~mayday for more information)"; \ From b54ada182dafe4daf08074aa54764236d4182a11 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Fri, 16 Mar 2007 23:34:24 +0000 Subject: [PATCH 128/170] General hvmloader cleanups and write memory fields of CMOS with correct values. Signed-off-by: Keir Fraser --- tools/firmware/hvmloader/32bitbios_support.c | 114 +++++++++---------- tools/firmware/hvmloader/acpi/build.c | 1 - tools/firmware/hvmloader/hvmloader.c | 65 ++++++++--- tools/firmware/hvmloader/smbios.c | 46 +++----- tools/firmware/hvmloader/util.c | 21 +++- tools/firmware/hvmloader/util.h | 10 +- 6 files changed, 140 insertions(+), 117 deletions(-) diff --git a/tools/firmware/hvmloader/32bitbios_support.c b/tools/firmware/hvmloader/32bitbios_support.c index bfde19577f..e835037d96 100644 --- a/tools/firmware/hvmloader/32bitbios_support.c +++ b/tools/firmware/hvmloader/32bitbios_support.c @@ -17,58 +17,64 @@ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307 USA. */ + #include #include #ifdef __sun__ #include #endif -#include #include "util.h" #include "config.h" #include "../rombios/32bit/32bitbios_flat.h" #include "../rombios/32bit/jumptable.h" - -/* - * relocate ELF file of type ET_REL - */ -static int relocate_elf(unsigned char *elfarray) { +/* Relocate ELF file of type ET_REL */ +static int relocate_elf(char *elfarray) +{ Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elfarray; Elf32_Shdr *shdr = (Elf32_Shdr *)&elfarray[ehdr->e_shoff]; int i; - if (ehdr->e_type != ET_REL) { + if ( ehdr->e_type != ET_REL ) + { printf("Not a relocatable BIOS object file. Has type %d, need %d\n", ehdr->e_type, ET_REL); return -1; } - for (i = 0; i < ehdr->e_shnum; i++) + for ( i = 0; i < ehdr->e_shnum; i++ ) shdr[i].sh_addr = (Elf32_Addr)&elfarray[shdr[i].sh_offset]; - for (i = 0; i < ehdr->e_shnum; i++) { - if (shdr[i].sh_type == SHT_REL) { + for ( i = 0; i < ehdr->e_shnum; i++ ) + { + if ( shdr[i].sh_type == SHT_RELA ) + return -2; + + if ( shdr[i].sh_type == SHT_REL ) + { Elf32_Shdr *targetsec = (Elf32_Shdr *)&(shdr[shdr[i].sh_info]); Elf32_Shdr *symtabsec = (Elf32_Shdr *)&(shdr[shdr[i].sh_link]); Elf32_Sym *syms = (Elf32_Sym *)symtabsec->sh_addr; Elf32_Rel *rels = (Elf32_Rel *)shdr[i].sh_addr; - unsigned char *code = (unsigned char *)targetsec->sh_addr; + char *code = (char *)targetsec->sh_addr; int j; /* must not have been stripped */ - if (shdr[i].sh_size == 0) + if ( shdr[i].sh_size == 0 ) return -6; - for (j = 0; j < shdr[i].sh_size / sizeof(Elf32_Rel); j++) { + for ( j = 0; j < shdr[i].sh_size / sizeof(Elf32_Rel); j++ ) + { int idx = ELF32_R_SYM(rels[j].r_info); Elf32_Sym *symbol = &syms[idx]; uint32_t *loc = (uint32_t *)&code[rels[j].r_offset]; uint32_t fix = shdr[symbol->st_shndx].sh_addr + symbol->st_value; - switch (ELF32_R_TYPE(rels[j].r_info)) { + switch ( ELF32_R_TYPE(rels[j].r_info) ) + { case R_386_PC32: *loc += (fix - (uint32_t)loc); break; @@ -78,96 +84,80 @@ static int relocate_elf(unsigned char *elfarray) { break; } } - } else if (shdr[i].sh_type == SHT_RELA) { - return -2; } } return 0; } -/* scan the rombios for the destination of the jumptable */ -static char* get_jump_table_start(void) +/* Scan the rombios for the destination of the jump table. */ +static char *get_jump_table_start(void) { char *bios_mem; for ( bios_mem = (char *)ROMBIOS_BEGIN; bios_mem != (char *)ROMBIOS_END; - bios_mem++ ) { - if (strncmp(bios_mem, "___JMPT", 7) == 0) + bios_mem++ ) + { + if ( strncmp(bios_mem, "___JMPT", 7) == 0 ) return bios_mem; } return NULL; } -/* copy relocated jumptable into the rombios */ -static int copy_jumptable(unsigned char *elfarray) +/* Copy relocated jumptable into the rombios. */ +static int copy_jumptable(char *elfarray) { - int rc = 0; Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elfarray; Elf32_Shdr *shdr = (Elf32_Shdr *)&elfarray[ehdr->e_shoff]; Elf32_Shdr *shdr_strings = (Elf32_Shdr *)&shdr[ehdr->e_shstrndx]; char *secstrings = (char *)&elfarray[shdr_strings->sh_offset]; uint32_t *rombiosjumptable = (uint32_t *)get_jump_table_start(); - uint32_t *biosjumptable = NULL; int i; - if (rombiosjumptable == NULL) { + if ( rombiosjumptable == NULL ) return -3; - } - /* find the section with the jump table and copy to lower BIOS memory */ - for (i = 0; i < ehdr->e_shnum; i++) { - if (!strcmp(JUMPTABLE_SECTION_NAME, secstrings + shdr[i].sh_name)) { - uint32_t biosjumptableentries; - biosjumptable = (uint32_t *)shdr[i].sh_addr; - biosjumptableentries = shdr[i].sh_size / 4; - for (int j = 0; j < biosjumptableentries; j++) { - rombiosjumptable[j] = biosjumptable[j]; - if (biosjumptable[j] == 0 && - j < (biosjumptableentries - 1)) { - printf("WARNING: jumptable entry %d is NULL!\n",j); - } - } + /* Find the section with the jump table and copy to lower BIOS memory. */ + for ( i = 0; i < ehdr->e_shnum; i++ ) + if ( !strcmp(JUMPTABLE_SECTION_NAME, secstrings + shdr[i].sh_name) ) break; - } + + if ( i == ehdr->e_shnum ) + { + printf("Could not find " JUMPTABLE_SECTION_NAME " section in file.\n"); + return -4; } - if (biosjumptable == NULL) { - printf("Could not find " JUMPTABLE_SECTION_NAME " section in file.\n"); - rc = -4; - } + memcpy(rombiosjumptable, (uint32_t *)shdr[i].sh_addr, shdr[i].sh_size); return 0; } -static int relocate_32bitbios(unsigned char *elfarray, uint32_t elfarraysize) +static int relocate_32bitbios(char *elfarray, uint32_t elfarraysize) { - int rc = 0; uint32_t mask = (64 * 1024) - 1; - uint32_t to_malloc = (elfarraysize + mask) & ~mask; /* round to 64kb */ - unsigned char *highbiosarea; + char *highbiosarea; + int rc; - highbiosarea = (unsigned char *)(long) - e820_malloc((uint64_t)to_malloc, - E820_RESERVED, - (uint64_t)0xffffffff); + highbiosarea = (char *)(long) + e820_malloc((elfarraysize + mask) & ~mask, /* round to 64kb */ + E820_RESERVED, + (uint64_t)0xffffffff); - if (highbiosarea != 0) { - memcpy(highbiosarea, elfarray, elfarraysize); - rc = relocate_elf(highbiosarea); - if (rc == 0) { - rc = copy_jumptable(highbiosarea); - } - } else { - rc = -5; - } + if ( highbiosarea == NULL ) + return -5; + + memcpy(highbiosarea, elfarray, elfarraysize); + rc = relocate_elf(highbiosarea); + if ( rc == 0 ) + rc = copy_jumptable(highbiosarea); return rc; } int highbios_setup(void) { - return relocate_32bitbios((unsigned char *)highbios_array, + return relocate_32bitbios((char *)highbios_array, sizeof(highbios_array)); } diff --git a/tools/firmware/hvmloader/acpi/build.c b/tools/firmware/hvmloader/acpi/build.c index 3db71cabfe..7be1ea4a71 100644 --- a/tools/firmware/hvmloader/acpi/build.c +++ b/tools/firmware/hvmloader/acpi/build.c @@ -20,7 +20,6 @@ #include "ssdt_tpm.h" #include "../config.h" #include "../util.h" -#include #define align16(sz) (((sz) + 15) & ~15) #define fixed_strcpy(d, s) strncpy((d), (s), sizeof(d)) diff --git a/tools/firmware/hvmloader/hvmloader.c b/tools/firmware/hvmloader/hvmloader.c index 8bed54835a..beabd06248 100644 --- a/tools/firmware/hvmloader/hvmloader.c +++ b/tools/firmware/hvmloader/hvmloader.c @@ -29,7 +29,6 @@ #include "pci_regs.h" #include #include -#include /* memory map */ #define HYPERCALL_PHYSICAL_ADDRESS 0x00080000 @@ -297,25 +296,57 @@ static void pci_setup(void) } } -static -int must_load_nic(void) +/* + * If the network card is in the boot order, load the Etherboot option ROM. + * Read the boot order bytes from CMOS and check if any of them are 0x4. + */ +static int must_load_nic(void) { - /* If the network card is in the boot order, load the Etherboot - * option ROM. Read the boot order bytes from CMOS and check - * if any of them are 0x4. */ uint8_t boot_order; - /* Read CMOS register 0x3d (boot choices 0 and 1) */ - outb(0x70, 0x3d); - boot_order = inb(0x71); - if ( (boot_order & 0xf) == 0x4 || (boot_order & 0xf0) == 0x40 ) + /* Read CMOS register 0x3d (boot choices 0 and 1). */ + boot_order = cmos_inb(0x3d); + if ( ((boot_order & 0xf) == 0x4) || ((boot_order & 0xf0) == 0x40) ) return 1; - /* Read CMOS register 0x38 (boot choice 2 and FDD test flag) */ - outb(0x70, 0x38); - boot_order = inb(0x71); - if ( (boot_order & 0xf0) == 0x40 ) - return 1; - return 0; + + /* Read CMOS register 0x38 (boot choice 2 and FDD test flag). */ + boot_order = cmos_inb(0x38); + return ((boot_order & 0xf0) == 0x40); +} + +/* Replace possibly erroneous memory-size CMOS fields with correct values. */ +static void cmos_write_memory_size(void) +{ + struct e820entry *map = E820_MAP; + int i, nr = *E820_MAP_NR; + uint32_t base_mem = 640, ext_mem = 0, alt_mem = 0; + + for ( i = 0; i < nr; i++ ) + if ( (map[i].addr >= 0x100000) && (map[i].type == E820_RAM) ) + break; + + if ( i != nr ) + { + alt_mem = ext_mem = map[i].addr + map[i].size; + ext_mem = (ext_mem > 0x0100000) ? (ext_mem - 0x0100000) >> 10 : 0; + if ( ext_mem > 0xffff ) + ext_mem = 0xffff; + alt_mem = (alt_mem > 0x1000000) ? (alt_mem - 0x1000000) >> 16 : 0; + } + + /* All BIOSes: conventional memory (640kB). */ + cmos_outb(0x15, (uint8_t)(base_mem >> 0)); + cmos_outb(0x16, (uint8_t)(base_mem >> 8)); + + /* All BIOSes: extended memory (1kB chunks above 1MB). */ + cmos_outb(0x17, (uint8_t)( ext_mem >> 0)); + cmos_outb(0x18, (uint8_t)( ext_mem >> 8)); + cmos_outb(0x30, (uint8_t)( ext_mem >> 0)); + cmos_outb(0x31, (uint8_t)( ext_mem >> 8)); + + /* Some BIOSes: alternative extended memory (64kB chunks above 16MB). */ + cmos_outb(0x34, (uint8_t)( alt_mem >> 0)); + cmos_outb(0x35, (uint8_t)( alt_mem >> 8)); } int main(void) @@ -366,6 +397,8 @@ int main(void) ASSERT((ACPI_PHYSICAL_ADDRESS + acpi_sz) <= 0xF0000); } + cmos_write_memory_size(); + if ( !check_amd() ) { printf("Loading VMXAssist ...\n"); diff --git a/tools/firmware/hvmloader/smbios.c b/tools/firmware/hvmloader/smbios.c index df25999c3a..c9a4992e4c 100644 --- a/tools/firmware/hvmloader/smbios.c +++ b/tools/firmware/hvmloader/smbios.c @@ -22,7 +22,6 @@ #include #include -#include #include "smbios.h" #include "smbios_types.h" #include "util.h" @@ -129,47 +128,32 @@ write_smbios_tables(void *start, return (size_t)((char *)p - (char *)start); } -/* This tries to figure out how much pseudo-physical memory (in MB) - is allocated to the current domU. - - It iterates through the e820 table, adding up the 'usable' and - 'reserved' entries and rounding up to the nearest MB. - - The e820map is not at e820 in hvmloader, so this uses the - E820_MAP_* constants from e820.h to pick it up where libxenguest - left it. - */ +/* Calculate how much pseudo-physical memory (in MB) is allocated to us. */ static uint64_t get_memsize(void) { - struct e820entry *map = NULL; - uint8_t num_entries = 0; + struct e820entry *map = E820_MAP; + uint8_t num_entries = *E820_MAP_NR; uint64_t memsize = 0; - uint8_t i; - - map = (struct e820entry *) (E820_MAP_PAGE + E820_MAP_OFFSET); - num_entries = *((uint8_t *) (E820_MAP_PAGE + E820_MAP_NR_OFFSET)); - - /* walk through e820map, ignoring any entries that aren't marked - as usable or reserved. */ + int i; + /* + * Walk through e820map, ignoring any entries that aren't marked + * as usable or reserved. + */ for ( i = 0; i < num_entries; i++ ) { - if (map->type == E820_RAM || map->type == E820_RESERVED) + if ( (map->type == E820_RAM) || (map->type == E820_RESERVED) ) memsize += map->size; map++; } - /* Round up to the nearest MB. The user specifies domU - pseudo-physical memory in megabytes, so not doing this - could easily lead to reporting one less MB than the user - specified. */ - if ( memsize & ((1<<20)-1) ) - memsize = (memsize >> 20) + 1; - else - memsize = (memsize >> 20); - - return memsize; + /* + * Round up to the nearest MB. The user specifies domU pseudo-physical + * memory in megabytes, so not doing this could easily lead to reporting + * one less MB than the user specified. + */ + return (memsize + (1 << 20) - 1) >> 20; } void diff --git a/tools/firmware/hvmloader/util.c b/tools/firmware/hvmloader/util.c index ce32a9001e..2f5f23d1e5 100644 --- a/tools/firmware/hvmloader/util.c +++ b/tools/firmware/hvmloader/util.c @@ -27,17 +27,17 @@ void outb(uint16_t addr, uint8_t val) { - __asm__ __volatile__ ( "outb %%al, %%dx" :: "d"(addr), "a"(val) ); + __asm__ __volatile__ ( "outb %%al, %%dx" : : "d" (addr), "a" (val) ); } void outw(uint16_t addr, uint16_t val) { - __asm__ __volatile__ ( "outw %%ax, %%dx" :: "d"(addr), "a"(val) ); + __asm__ __volatile__ ( "outw %%ax, %%dx" : : "d" (addr), "a" (val) ); } void outl(uint16_t addr, uint32_t val) { - __asm__ __volatile__ ( "outl %%eax, %%dx" :: "d"(addr), "a"(val) ); + __asm__ __volatile__ ( "outl %%eax, %%dx" : : "d" (addr), "a" (val) ); } uint8_t inb(uint16_t addr) @@ -61,6 +61,18 @@ uint32_t inl(uint16_t addr) return val; } +uint8_t cmos_inb(uint8_t idx) +{ + outb(0x70, idx); + return inb(0x71); +} + +void cmos_outb(uint8_t idx, uint8_t val) +{ + outb(0x70, idx); + outb(0x71, val); +} + char *itoa(char *a, unsigned int i) { unsigned int _i = i, x = 0; @@ -280,9 +292,6 @@ uuid_to_string(char *dest, uint8_t *uuid) *p = '\0'; } -#include -#define E820_MAP_NR ((unsigned char *)E820_MAP_PAGE + E820_MAP_NR_OFFSET) -#define E820_MAP ((struct e820entry *)(E820_MAP_PAGE + E820_MAP_OFFSET)) uint64_t e820_malloc(uint64_t size, uint32_t type, uint64_t mask) { uint64_t addr = 0; diff --git a/tools/firmware/hvmloader/util.h b/tools/firmware/hvmloader/util.h index 368f93ddda..5025748437 100644 --- a/tools/firmware/hvmloader/util.h +++ b/tools/firmware/hvmloader/util.h @@ -26,6 +26,10 @@ uint8_t inb(uint16_t addr); uint16_t inw(uint16_t addr); uint32_t inl(uint16_t addr); +/* CMOS access */ +uint8_t cmos_inb(uint8_t idx); +void cmos_outb(uint8_t idx, uint8_t val); + /* APIC access */ uint32_t ioapic_read(uint32_t reg); void ioapic_write(uint32_t reg, uint32_t val); @@ -78,10 +82,14 @@ int vprintf(const char *fmt, va_list ap); /* Allocate region of specified type in the e820 table. */ uint64_t e820_malloc(uint64_t size, uint32_t type, uint64_t mask); +/* General e820 access. */ +#include +#define E820_MAP_NR ((unsigned char *)E820_MAP_PAGE + E820_MAP_NR_OFFSET) +#define E820_MAP ((struct e820entry *)(E820_MAP_PAGE + E820_MAP_OFFSET)) + /* Prepare the 32bit BIOS */ int highbios_setup(void); - #define isdigit(c) ((c) >= '0' && (c) <= '9') #endif /* __HVMLOADER_UTIL_H__ */ From 36200329b198717624bfa37f410e3a650168a9c7 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Fri, 16 Mar 2007 23:56:26 +0000 Subject: [PATCH 129/170] hvmloader: More simplification of highmem bios relocation code. Signed-off-by: Keir Fraser --- tools/firmware/hvmloader/32bitbios_support.c | 108 ++++++++----------- tools/firmware/hvmloader/util.h | 2 +- 2 files changed, 46 insertions(+), 64 deletions(-) diff --git a/tools/firmware/hvmloader/32bitbios_support.c b/tools/firmware/hvmloader/32bitbios_support.c index e835037d96..7cb32a299d 100644 --- a/tools/firmware/hvmloader/32bitbios_support.c +++ b/tools/firmware/hvmloader/32bitbios_support.c @@ -31,18 +31,15 @@ #include "../rombios/32bit/jumptable.h" /* Relocate ELF file of type ET_REL */ -static int relocate_elf(char *elfarray) +static void relocate_elf(char *elfarray) { Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elfarray; Elf32_Shdr *shdr = (Elf32_Shdr *)&elfarray[ehdr->e_shoff]; - int i; - - if ( ehdr->e_type != ET_REL ) - { - printf("Not a relocatable BIOS object file. Has type %d, need %d\n", - ehdr->e_type, ET_REL); - return -1; - } + Elf32_Sym *syms, *sym; + Elf32_Rel *rels; + char *code; + uint32_t *loc, fix; + int i, j; for ( i = 0; i < ehdr->e_shnum; i++ ) shdr[i].sh_addr = (Elf32_Addr)&elfarray[shdr[i].sh_offset]; @@ -50,43 +47,33 @@ static int relocate_elf(char *elfarray) for ( i = 0; i < ehdr->e_shnum; i++ ) { if ( shdr[i].sh_type == SHT_RELA ) - return -2; + printf("Unsupported section type SHT_RELA\n"); - if ( shdr[i].sh_type == SHT_REL ) + if ( shdr[i].sh_type != SHT_REL ) + continue; + + syms = (Elf32_Sym *)shdr[shdr[i].sh_link].sh_addr; + rels = (Elf32_Rel *)shdr[i].sh_addr; + code = (char *)shdr[shdr[i].sh_info].sh_addr; + + for ( j = 0; j < shdr[i].sh_size / sizeof(Elf32_Rel); j++ ) { - Elf32_Shdr *targetsec = (Elf32_Shdr *)&(shdr[shdr[i].sh_info]); - Elf32_Shdr *symtabsec = (Elf32_Shdr *)&(shdr[shdr[i].sh_link]); - Elf32_Sym *syms = (Elf32_Sym *)symtabsec->sh_addr; - Elf32_Rel *rels = (Elf32_Rel *)shdr[i].sh_addr; - char *code = (char *)targetsec->sh_addr; - int j; + sym = &syms[ELF32_R_SYM(rels[j].r_info)]; + loc = (uint32_t *)&code[rels[j].r_offset]; + fix = shdr[sym->st_shndx].sh_addr + sym->st_value; - /* must not have been stripped */ - if ( shdr[i].sh_size == 0 ) - return -6; - - for ( j = 0; j < shdr[i].sh_size / sizeof(Elf32_Rel); j++ ) + switch ( ELF32_R_TYPE(rels[j].r_info) ) { - int idx = ELF32_R_SYM(rels[j].r_info); - Elf32_Sym *symbol = &syms[idx]; - uint32_t *loc = (uint32_t *)&code[rels[j].r_offset]; - uint32_t fix = shdr[symbol->st_shndx].sh_addr + - symbol->st_value; + case R_386_PC32: + *loc += fix - (uint32_t)loc; + break; - switch ( ELF32_R_TYPE(rels[j].r_info) ) - { - case R_386_PC32: - *loc += (fix - (uint32_t)loc); - break; - - case R_386_32: - *loc += fix; - break; - } + case R_386_32: + *loc += fix; + break; } } } - return 0; } /* Scan the rombios for the destination of the jump table. */ @@ -97,27 +84,21 @@ static char *get_jump_table_start(void) for ( bios_mem = (char *)ROMBIOS_BEGIN; bios_mem != (char *)ROMBIOS_END; bios_mem++ ) - { - if ( strncmp(bios_mem, "___JMPT", 7) == 0 ) + if ( !strncmp(bios_mem, "___JMPT", 7) ) return bios_mem; - } return NULL; } /* Copy relocated jumptable into the rombios. */ -static int copy_jumptable(char *elfarray) +static void copy_jumptable(char *elfarray) { Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elfarray; Elf32_Shdr *shdr = (Elf32_Shdr *)&elfarray[ehdr->e_shoff]; - Elf32_Shdr *shdr_strings = (Elf32_Shdr *)&shdr[ehdr->e_shstrndx]; - char *secstrings = (char *)&elfarray[shdr_strings->sh_offset]; - uint32_t *rombiosjumptable = (uint32_t *)get_jump_table_start(); + char *secstrings = &elfarray[shdr[ehdr->e_shstrndx].sh_offset]; + char *jump_table = get_jump_table_start(); int i; - if ( rombiosjumptable == NULL ) - return -3; - /* Find the section with the jump table and copy to lower BIOS memory. */ for ( i = 0; i < ehdr->e_shnum; i++ ) if ( !strcmp(JUMPTABLE_SECTION_NAME, secstrings + shdr[i].sh_name) ) @@ -126,38 +107,39 @@ static int copy_jumptable(char *elfarray) if ( i == ehdr->e_shnum ) { printf("Could not find " JUMPTABLE_SECTION_NAME " section in file.\n"); - return -4; + return; } - memcpy(rombiosjumptable, (uint32_t *)shdr[i].sh_addr, shdr[i].sh_size); + if ( jump_table == NULL ) + { + printf("Could not find jump table in file.\n"); + return; + } - return 0; + memcpy(jump_table, (char *)shdr[i].sh_addr, shdr[i].sh_size); } -static int relocate_32bitbios(char *elfarray, uint32_t elfarraysize) +static void relocate_32bitbios(char *elfarray, uint32_t elfarraysize) { uint32_t mask = (64 * 1024) - 1; char *highbiosarea; - int rc; highbiosarea = (char *)(long) e820_malloc((elfarraysize + mask) & ~mask, /* round to 64kb */ E820_RESERVED, (uint64_t)0xffffffff); - if ( highbiosarea == NULL ) - return -5; + { + printf("No available memory for BIOS high memory area\n"); + return; + } memcpy(highbiosarea, elfarray, elfarraysize); - rc = relocate_elf(highbiosarea); - if ( rc == 0 ) - rc = copy_jumptable(highbiosarea); - - return rc; + relocate_elf(highbiosarea); + copy_jumptable(highbiosarea); } -int highbios_setup(void) +void highbios_setup(void) { - return relocate_32bitbios((char *)highbios_array, - sizeof(highbios_array)); + relocate_32bitbios((char *)highbios_array, sizeof(highbios_array)); } diff --git a/tools/firmware/hvmloader/util.h b/tools/firmware/hvmloader/util.h index 5025748437..cc1f42dba9 100644 --- a/tools/firmware/hvmloader/util.h +++ b/tools/firmware/hvmloader/util.h @@ -88,7 +88,7 @@ uint64_t e820_malloc(uint64_t size, uint32_t type, uint64_t mask); #define E820_MAP ((struct e820entry *)(E820_MAP_PAGE + E820_MAP_OFFSET)) /* Prepare the 32bit BIOS */ -int highbios_setup(void); +void highbios_setup(void); #define isdigit(c) ((c) >= '0' && (c) <= '9') From cfcf0ae28495b1fff0f16981822b1a93b9336c7a Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Sat, 17 Mar 2007 12:04:48 +0000 Subject: [PATCH 130/170] Xen and tools now require gcc 3.4+ on x86. - gcc-3.2 cannot handle some multi-line assertions in the Xen sources. Noone noticed. - gcc-3.3 has problems with alignment constraints inside typedefs. gcc 3.4.0 is now three years old so I hope that everyone has an up-to-date compiler, or can obtain a more up-to-date package for their distribution. If not we may need to fall back to supporting gcc-3.3.x as well. Also clean up the way we do version checks, using the power of awk. Signed-off-by: Keir Fraser --- Config.mk | 6 ++++++ tools/Rules.mk | 5 +++++ xen/arch/x86/Rules.mk | 18 +++--------------- xen/common/perfc.c | 17 ++++------------- xen/include/public/arch-x86/xen-x86_32.h | 2 +- 5 files changed, 19 insertions(+), 29 deletions(-) diff --git a/Config.mk b/Config.mk index 6f9f970fe6..0181cc3ad1 100644 --- a/Config.mk +++ b/Config.mk @@ -36,6 +36,12 @@ endif cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \ /dev/null 2>&1`"; then echo "$(2)"; else echo "$(3)"; fi ;) +# cc-ver +# Usage: ifeq ($(call cc-ver,$(CC),0x030400),y) +cc-ver = $(shell if [ $$((`$(1) -dumpversion | awk -F. \ + '{ printf "0x%02x%02x%02x", $$1, $$2, $$3}'`)) -ge $$(($(2))) ]; \ + then echo y; else echo n; fi ;) + ifneq ($(debug),y) CFLAGS += -DNDEBUG else diff --git a/tools/Rules.mk b/tools/Rules.mk index df3b231a1a..3e13eceb55 100644 --- a/tools/Rules.mk +++ b/tools/Rules.mk @@ -23,6 +23,11 @@ LDFLAGS += $(shell getconf LFS_LDFLAGS) CFLAGS-$(CONFIG_X86_32) += $(call cc-option,$(CC),-mno-tls-direct-seg-refs) CFLAGS += $(CFLAGS-y) +# Require GCC v3.4+ (to avoid issues with alignment constraints in Xen headers) +ifeq ($(CONFIG_X86)$(call cc-ver,$(CC),0x030400),yn) +$(error Xen tools require at least gcc-3.4) +endif + %.opic: %.c $(CC) $(CPPFLAGS) -DPIC $(CFLAGS) -fPIC -c -o $@ $< diff --git a/xen/arch/x86/Rules.mk b/xen/arch/x86/Rules.mk index 899f28129c..86b9f33ab1 100644 --- a/xen/arch/x86/Rules.mk +++ b/xen/arch/x86/Rules.mk @@ -58,19 +58,7 @@ HDRS += $(wildcard $(BASEDIR)/include/asm-x86/hvm/*.h) HDRS += $(wildcard $(BASEDIR)/include/asm-x86/hvm/svm/*.h) HDRS += $(wildcard $(BASEDIR)/include/asm-x86/hvm/vmx/*.h) -# Test for at least GCC v3.2.x. -gcc-ver = $(shell $(CC) -dumpversion | sed -e 's/^\(.\)\.\(.\)\.\(.\)/\$(1)/') -ifeq ($(call gcc-ver,1),1) -$(error gcc-1.x.x unsupported - upgrade to at least gcc-3.2.x) -endif -ifeq ($(call gcc-ver,1),2) -$(error gcc-2.x.x unsupported - upgrade to at least gcc-3.2.x) -endif -ifeq ($(call gcc-ver,1),3) -ifeq ($(call gcc-ver,2),0) -$(error gcc-3.0.x unsupported - upgrade to at least gcc-3.2.x) -endif -ifeq ($(call gcc-ver,2),1) -$(error gcc-3.1.x unsupported - upgrade to at least gcc-3.2.x) -endif +# Require GCC v3.4+ (to avoid issues with alignment constraints in Xen headers) +ifneq ($(call cc-ver,$(CC),0x030400),y) +$(error Xen requires at least gcc-3.4) endif diff --git a/xen/common/perfc.c b/xen/common/perfc.c index d5bcd9b2e1..bbff5d7b5c 100644 --- a/xen/common/perfc.c +++ b/xen/common/perfc.c @@ -136,8 +136,8 @@ static xen_sysctl_perfc_desc_t perfc_d[NR_PERFCTRS]; static xen_sysctl_perfc_val_t *perfc_vals; static int perfc_nbr_vals; static int perfc_init = 0; -static int perfc_copy_info(XEN_GUEST_HANDLE(xen_sysctl_perfc_desc_t) desc, - XEN_GUEST_HANDLE(xen_sysctl_perfc_val_t) val) +static int perfc_copy_info(XEN_GUEST_HANDLE_64(xen_sysctl_perfc_desc_t) desc, + XEN_GUEST_HANDLE_64(xen_sysctl_perfc_val_t) val) { unsigned int i, j; unsigned int v = 0; @@ -217,29 +217,20 @@ static int perfc_copy_info(XEN_GUEST_HANDLE(xen_sysctl_perfc_desc_t) desc, int perfc_control(xen_sysctl_perfc_op_t *pc) { static DEFINE_SPINLOCK(lock); - XEN_GUEST_HANDLE(xen_sysctl_perfc_desc_t) desc; - XEN_GUEST_HANDLE(xen_sysctl_perfc_val_t) val; int rc; - /* - * 64 bit guest handles cannot be passed as parameters to - * functions so cast to a regular guest handle. - */ - desc = guest_handle_cast(pc->desc, xen_sysctl_perfc_desc_t); - val = guest_handle_cast(pc->val, xen_sysctl_perfc_val_t); - spin_lock(&lock); switch ( pc->cmd ) { case XEN_SYSCTL_PERFCOP_reset: - perfc_copy_info(desc, val); + perfc_copy_info(pc->desc, pc->val); perfc_reset(0); rc = 0; break; case XEN_SYSCTL_PERFCOP_query: - perfc_copy_info(desc, val); + perfc_copy_info(pc->desc, pc->val); rc = 0; break; diff --git a/xen/include/public/arch-x86/xen-x86_32.h b/xen/include/public/arch-x86/xen-x86_32.h index 2633ff082f..6728b818cd 100644 --- a/xen/include/public/arch-x86/xen-x86_32.h +++ b/xen/include/public/arch-x86/xen-x86_32.h @@ -103,7 +103,7 @@ (hnd).p = val; \ } while ( 0 ) #define uint64_aligned_t uint64_t __attribute__((aligned(8))) -#define XEN_GUEST_HANDLE_64(name) __guest_handle_64_ ## name __attribute__((aligned(8))) +#define XEN_GUEST_HANDLE_64(name) __guest_handle_64_ ## name #endif #ifndef __ASSEMBLY__ From c95d97855e1470874178e25f645a45ca7d9da1dc Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Sat, 17 Mar 2007 12:24:32 +0000 Subject: [PATCH 131/170] Fix up nosegneg vsyscall elfnote. Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/arch/i386/kernel/vsyscall-note-xen.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/vsyscall-note-xen.S b/linux-2.6-xen-sparse/arch/i386/kernel/vsyscall-note-xen.S index c2d6dbf159..019d9afb83 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/vsyscall-note-xen.S +++ b/linux-2.6-xen-sparse/arch/i386/kernel/vsyscall-note-xen.S @@ -28,5 +28,5 @@ #define NOTE_KERNELCAP_END ASM_ELF_NOTE_END NOTE_KERNELCAP_BEGIN(1, 1) -NOTE_KERNELCAP(1, "nosegneg") /* Change 1 back to 0 when glibc is fixed! */ +NOTE_KERNELCAP(0, "nosegneg") NOTE_KERNELCAP_END From 716d0617c936b721deb6fc2212add0acca58af32 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Sat, 17 Mar 2007 16:56:39 +0000 Subject: [PATCH 132/170] Work around bug in Python's inspect module -- catch an IndexError exception if the source-code lookup fails. Signed-off-by: Ewan Mellor --- tools/python/xen/xend/XendLogging.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tools/python/xen/xend/XendLogging.py b/tools/python/xen/xend/XendLogging.py index 6d6140188d..3d6b678f1d 100644 --- a/tools/python/xen/xend/XendLogging.py +++ b/tools/python/xen/xend/XendLogging.py @@ -59,6 +59,18 @@ if 'TRACE' not in logging.__dict__: return filename, frame[2] logging.Logger.findCaller = findCaller + # Work around a bug in Python's inspect module: findsource is supposed to + # raise IOError if it fails, with other functions in that module coping + # with that, but some people are seeing IndexError raised from there. + if hasattr(inspect, 'findsource'): + real_findsource = getattr(inspect, 'findsource') + def findsource(*args, **kwargs): + try: + return real_findsource(*args, **kwargs) + except IndexError, exn: + raise IOError(exn) + inspect.findsource = findsource + log = logging.getLogger("xend") From 98321440ec5681052fc4cadfaed5471b01cfd451 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Sat, 17 Mar 2007 23:55:03 +0000 Subject: [PATCH 133/170] Replace VDI.location with a more generic VDI.other_config map. Remove VDI.sector_size. Xend work by Tom Wilkie . Signed-off-by: Ewan Mellor --- docs/xen-api/xenapi-datamodel.tex | 171 +++++++++++++++++++----- tools/libxen/include/xen_vbd.h | 1 - tools/libxen/include/xen_vdi.h | 44 ++++-- tools/libxen/src/xen_vbd.c | 3 - tools/libxen/src/xen_vdi.c | 98 ++++++++++---- tools/libxen/test/test_bindings.c | 3 +- tools/python/scripts/test_hvm_create.py | 3 +- tools/python/scripts/test_vm_create.py | 6 +- tools/python/scripts/xapi.py | 11 +- tools/python/scripts/xapi.vdicfg.py | 3 +- tools/python/xen/xend/XendAPI.py | 19 ++- tools/python/xen/xend/XendVDI.py | 17 +-- 12 files changed, 272 insertions(+), 107 deletions(-) diff --git a/docs/xen-api/xenapi-datamodel.tex b/docs/xen-api/xenapi-datamodel.tex index 1b18834d03..4a11ef0d9b 100644 --- a/docs/xen-api/xenapi-datamodel.tex +++ b/docs/xen-api/xenapi-datamodel.tex @@ -9359,10 +9359,10 @@ $\mathit{RO}_\mathit{run}$ & {\tt VBDs} & (VBD ref) Set & list of vbds that ref $\mathit{RO}_\mathit{run}$ & {\tt crash\_dumps} & (crashdump ref) Set & list of crash dumps that refer to this disk \\ $\mathit{RW}$ & {\tt virtual\_size} & int & size of disk as presented to the guest (in bytes). Note that, depending on storage backend type, requested size may not be respected exactly \\ $\mathit{RO}_\mathit{run}$ & {\tt physical\_utilisation} & int & amount of physical space that the disk image is currently taking up on the storage repository (in bytes) \\ -$\mathit{RO}_\mathit{ins}$ & {\tt sector\_size} & int & sector size of VDI (in bytes) \\ $\mathit{RO}_\mathit{ins}$ & {\tt type} & vdi\_type & type of the VDI \\ $\mathit{RW}$ & {\tt sharable} & bool & true if this disk may be shared \\ $\mathit{RW}$ & {\tt read\_only} & bool & true if this disk may ONLY be mounted read-only \\ +$\mathit{RW}$ & {\tt other\_config} & (string $\rightarrow$ string) Map & additional configuration \\ \hline \end{longtable} \subsection{RPCs associated with class: VDI} @@ -9808,38 +9808,6 @@ int } -value of the field -\vspace{0.3cm} -\vspace{0.3cm} -\vspace{0.3cm} -\subsubsection{RPC name:~get\_sector\_size} - -{\bf Overview:} -Get the sector\_size field of the given VDI. - - \noindent {\bf Signature:} -\begin{verbatim} int get_sector_size (session_id s, VDI ref self)\end{verbatim} - - -\noindent{\bf Arguments:} - - -\vspace{0.3cm} -\begin{tabular}{|c|c|p{7cm}|} - \hline -{\bf type} & {\bf name} & {\bf description} \\ \hline -{\tt VDI ref } & self & reference to the object \\ \hline - -\end{tabular} - -\vspace{0.3cm} - - \noindent {\bf Return Type:} -{\tt -int -} - - value of the field \vspace{0.3cm} \vspace{0.3cm} @@ -10005,6 +9973,143 @@ void +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_other\_config} + +{\bf Overview:} +Get the other\_config field of the given VDI. + + \noindent {\bf Signature:} +\begin{verbatim} ((string -> string) Map) get_other_config (session_id s, VDI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VDI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +(string $\rightarrow$ string) Map +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~set\_other\_config} + +{\bf Overview:} +Set the other\_config field of the given VDI. + + \noindent {\bf Signature:} +\begin{verbatim} void set_other_config (session_id s, VDI ref self, (string -> string) Map value)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VDI ref } & self & reference to the object \\ \hline + +{\tt (string $\rightarrow$ string) Map } & value & New value to set \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +void +} + + + +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~add\_to\_other\_config} + +{\bf Overview:} +Add the given key-value pair to the other\_config field of the given VDI. + + \noindent {\bf Signature:} +\begin{verbatim} void add_to_other_config (session_id s, VDI ref self, string key, string value)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VDI ref } & self & reference to the object \\ \hline + +{\tt string } & key & Key to add \\ \hline + +{\tt string } & value & Value to add \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +void +} + + + +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~remove\_from\_other\_config} + +{\bf Overview:} +Remove the given key and its corresponding value from the other\_config +field of the given VDI. If the key is not in that Map, then do nothing. + + \noindent {\bf Signature:} +\begin{verbatim} void remove_from_other_config (session_id s, VDI ref self, string key)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VDI ref } & self & reference to the object \\ \hline + +{\tt string } & key & Key to remove \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +void +} + + + \vspace{0.3cm} \vspace{0.3cm} \vspace{0.3cm} diff --git a/tools/libxen/include/xen_vbd.h b/tools/libxen/include/xen_vbd.h index 7b36266a04..14a6685a95 100644 --- a/tools/libxen/include/xen_vbd.h +++ b/tools/libxen/include/xen_vbd.h @@ -72,7 +72,6 @@ typedef struct xen_vbd_record struct xen_vm_record_opt *vm; struct xen_vdi_record_opt *vdi; char *device; - char *image; bool bootable; enum xen_vbd_mode mode; enum xen_vbd_type type; diff --git a/tools/libxen/include/xen_vdi.h b/tools/libxen/include/xen_vdi.h index 26e147250e..9ebb8fd9ee 100644 --- a/tools/libxen/include/xen_vdi.h +++ b/tools/libxen/include/xen_vdi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, XenSource Inc. + * Copyright (c) 2006-2007, XenSource Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,6 +22,7 @@ #include "xen_common.h" #include "xen_crashdump_decl.h" #include "xen_sr_decl.h" +#include "xen_string_string_map.h" #include "xen_vbd_decl.h" #include "xen_vdi_decl.h" #include "xen_vdi_type.h" @@ -73,11 +74,10 @@ typedef struct xen_vdi_record struct xen_crashdump_record_opt_set *crash_dumps; int64_t virtual_size; int64_t physical_utilisation; - int64_t sector_size; - char *location; enum xen_vdi_type type; bool sharable; bool read_only; + xen_string_string_map *other_config; } xen_vdi_record; /** @@ -250,13 +250,6 @@ extern bool xen_vdi_get_physical_utilisation(xen_session *session, int64_t *result, xen_vdi vdi); -/** - * Get the sector_size field of the given VDI. - */ -extern bool -xen_vdi_get_sector_size(xen_session *session, int64_t *result, xen_vdi vdi); - - /** * Get the type field of the given VDI. */ @@ -278,6 +271,13 @@ extern bool xen_vdi_get_read_only(xen_session *session, bool *result, xen_vdi vdi); +/** + * Get the other_config field of the given VDI. + */ +extern bool +xen_vdi_get_other_config(xen_session *session, xen_string_string_map **result, xen_vdi vdi); + + /** * Set the name/label field of the given VDI. */ @@ -313,6 +313,30 @@ extern bool xen_vdi_set_read_only(xen_session *session, xen_vdi vdi, bool read_only); +/** + * Set the other_config field of the given VDI. + */ +extern bool +xen_vdi_set_other_config(xen_session *session, xen_vdi vdi, xen_string_string_map *other_config); + + +/** + * Add the given key-value pair to the other_config field of the given + * VDI. + */ +extern bool +xen_vdi_add_to_other_config(xen_session *session, xen_vdi vdi, char *key, char *value); + + +/** + * Remove the given key and its corresponding value from the + * other_config field of the given VDI. If the key is not in that Map, then + * do nothing. + */ +extern bool +xen_vdi_remove_from_other_config(xen_session *session, xen_vdi vdi, char *key); + + /** * Take an exact copy of the VDI; the snapshot lives in the same * Storage Repository as its parent. diff --git a/tools/libxen/src/xen_vbd.c b/tools/libxen/src/xen_vbd.c index 300f1d857d..893bf70958 100644 --- a/tools/libxen/src/xen_vbd.c +++ b/tools/libxen/src/xen_vbd.c @@ -54,9 +54,6 @@ static const struct_member xen_vbd_record_struct_members[] = { .key = "device", .type = &abstract_type_string, .offset = offsetof(xen_vbd_record, device) }, - { .key = "image", - .type = &abstract_type_string, - .offset = offsetof(xen_vbd_record, image) }, { .key = "bootable", .type = &abstract_type_bool, .offset = offsetof(xen_vbd_record, bootable) }, diff --git a/tools/libxen/src/xen_vdi.c b/tools/libxen/src/xen_vdi.c index 2e50db9e80..10f3fc4066 100644 --- a/tools/libxen/src/xen_vdi.c +++ b/tools/libxen/src/xen_vdi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, XenSource Inc. + * Copyright (c) 2006-2007, XenSource Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,6 +24,7 @@ #include "xen_crashdump.h" #include "xen_internal.h" #include "xen_sr.h" +#include "xen_string_string_map.h" #include "xen_vbd.h" #include "xen_vdi.h" #include "xen_vdi_type_internal.h" @@ -64,12 +65,6 @@ static const struct_member xen_vdi_record_struct_members[] = { .key = "physical_utilisation", .type = &abstract_type_int, .offset = offsetof(xen_vdi_record, physical_utilisation) }, - { .key = "sector_size", - .type = &abstract_type_int, - .offset = offsetof(xen_vdi_record, sector_size) }, - { .key = "location", - .type = &abstract_type_string, - .offset = offsetof(xen_vdi_record, location) }, { .key = "type", .type = &xen_vdi_type_abstract_type_, .offset = offsetof(xen_vdi_record, type) }, @@ -78,7 +73,10 @@ static const struct_member xen_vdi_record_struct_members[] = .offset = offsetof(xen_vdi_record, sharable) }, { .key = "read_only", .type = &abstract_type_bool, - .offset = offsetof(xen_vdi_record, read_only) } + .offset = offsetof(xen_vdi_record, read_only) }, + { .key = "other_config", + .type = &abstract_type_string_string_map, + .offset = offsetof(xen_vdi_record, other_config) } }; const abstract_type xen_vdi_record_abstract_type_ = @@ -105,6 +103,7 @@ xen_vdi_record_free(xen_vdi_record *record) xen_sr_record_opt_free(record->sr); xen_vbd_record_opt_set_free(record->vbds); xen_crashdump_record_opt_set_free(record->crash_dumps); + xen_string_string_map_free(record->other_config); free(record); } @@ -314,22 +313,6 @@ xen_vdi_get_physical_utilisation(xen_session *session, int64_t *result, xen_vdi } -bool -xen_vdi_get_sector_size(xen_session *session, int64_t *result, xen_vdi vdi) -{ - abstract_value param_values[] = - { - { .type = &abstract_type_string, - .u.string_val = vdi } - }; - - abstract_type result_type = abstract_type_int; - - XEN_CALL_("VDI.get_sector_size"); - return session->ok; -} - - bool xen_vdi_get_type(xen_session *session, enum xen_vdi_type *result, xen_vdi vdi) { @@ -377,6 +360,23 @@ xen_vdi_get_read_only(xen_session *session, bool *result, xen_vdi vdi) } +bool +xen_vdi_get_other_config(xen_session *session, xen_string_string_map **result, xen_vdi vdi) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vdi } + }; + + abstract_type result_type = abstract_type_string_string_map; + + *result = NULL; + XEN_CALL_("VDI.get_other_config"); + return session->ok; +} + + bool xen_vdi_set_name_label(xen_session *session, xen_vdi vdi, char *label) { @@ -457,6 +457,56 @@ xen_vdi_set_read_only(xen_session *session, xen_vdi vdi, bool read_only) } +bool +xen_vdi_set_other_config(xen_session *session, xen_vdi vdi, xen_string_string_map *other_config) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vdi }, + { .type = &abstract_type_string_string_map, + .u.set_val = (arbitrary_set *)other_config } + }; + + xen_call_(session, "VDI.set_other_config", param_values, 2, NULL, NULL); + return session->ok; +} + + +bool +xen_vdi_add_to_other_config(xen_session *session, xen_vdi vdi, char *key, char *value) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vdi }, + { .type = &abstract_type_string, + .u.string_val = key }, + { .type = &abstract_type_string, + .u.string_val = value } + }; + + xen_call_(session, "VDI.add_to_other_config", param_values, 3, NULL, NULL); + return session->ok; +} + + +bool +xen_vdi_remove_from_other_config(xen_session *session, xen_vdi vdi, char *key) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vdi }, + { .type = &abstract_type_string, + .u.string_val = key } + }; + + xen_call_(session, "VDI.remove_from_other_config", param_values, 2, NULL, NULL); + return session->ok; +} + + bool xen_vdi_snapshot(xen_session *session, xen_vdi *result, xen_vdi vdi) { diff --git a/tools/libxen/test/test_bindings.c b/tools/libxen/test/test_bindings.c index f18c5c5ac5..92f2d9b6ca 100644 --- a/tools/libxen/test/test_bindings.c +++ b/tools/libxen/test/test_bindings.c @@ -421,8 +421,7 @@ static xen_vm create_new_vm(xen_session *session, bool hvm) .name_label = "MyRootFS", .name_description = "MyRootFS description", .sr = &sr_record, - .virtual_size = (1 << 21), // 1GiB / 512 bytes/sector - .sector_size = 512, + .virtual_size = (INT64_C(1) << 30), // 1GiB .type = XEN_VDI_TYPE_SYSTEM, .sharable = false, .read_only = false diff --git a/tools/python/scripts/test_hvm_create.py b/tools/python/scripts/test_hvm_create.py index 7cae70539a..35abfe0396 100644 --- a/tools/python/scripts/test_hvm_create.py +++ b/tools/python/scripts/test_hvm_create.py @@ -39,14 +39,13 @@ vm_cfg = { local_vdi_cfg = { 'name_label': 'gentoo.hvm', 'name_description': '', - 'location': 'file:/root/gentoo.amd64.hvm.img', 'virtual_size': 0, - 'sector_size': 0, 'type': 'system', 'parent': '', 'SR_name': 'Local', 'sharable': False, 'read_only': False, + 'other_config': {'location': 'file:/root/gentoo.amd64.hvm.img'}, } local_vbd_cfg = { diff --git a/tools/python/scripts/test_vm_create.py b/tools/python/scripts/test_vm_create.py index e4d8f3023a..6575f153ea 100644 --- a/tools/python/scripts/test_vm_create.py +++ b/tools/python/scripts/test_vm_create.py @@ -39,8 +39,7 @@ vm_cfg = { vdi_cfg = { 'name_label': 'API_VDI', 'name_description': '', - 'virtual_size': 100 * 1024 * 1024, - 'sector_size': 1024, + 'virtual_size': 100 * 1024 * 1024 * 1024, 'type': 'system', 'parent': '', 'SR_name': 'QCoW', @@ -60,14 +59,13 @@ vbd_cfg = { local_vdi_cfg = { 'name_label': 'gentoo.amd64.img', 'name_description': '', - 'location': 'file:/root/gentoo.amd64.img', 'virtual_size': 0, - 'sector_size': 0, 'type': 'system', 'parent': '', 'SR_name': 'Local', 'sharable': False, 'read_only': False, + 'other_config': {'location': 'file:/root/gentoo.amd64.img'}, } local_vbd_cfg = { diff --git a/tools/python/scripts/xapi.py b/tools/python/scripts/xapi.py index 1e49f86d4c..1a07795212 100644 --- a/tools/python/scripts/xapi.py +++ b/tools/python/scripts/xapi.py @@ -40,8 +40,7 @@ VM_LIST_FORMAT = '%(name_label)-18s %(memory_actual)-5s %(VCPUs_number)-5s'\ ' %(power_state)-10s %(uuid)-36s' SR_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(physical_size)-10s' \ '%(type)-10s' -VDI_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(virtual_size)-8s '\ - '%(sector_size)-8s' +VDI_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(virtual_size)-8s' VBD_LIST_FORMAT = '%(device)-6s %(uuid)-36s %(VDI)-8s' TASK_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(status)-8s %(progress)-4s' VIF_LIST_FORMAT = '%(name)-8s %(device)-7s %(uuid)-36s %(MAC)-10s' @@ -96,12 +95,9 @@ OPTIONS = { 'vdi-create': [(('--name-label',), {'help': 'Name for VDI'}), (('--name-description',), {'help': 'Description for VDI'}), - (('--sector-size',), {'type': 'int', - 'help': 'Sector size', - 'default': 0}), (('--virtual-size',), {'type': 'int', 'default': 0, - 'help': 'Size of VDI in sectors'}), + 'help': 'Size of VDI in bytes'}), (('--type',), {'choices': ['system', 'user', 'ephemeral'], 'default': 'system', 'help': 'VDI type'}), @@ -569,8 +565,7 @@ def xapi_vdi_list(args, async = False): if not is_long: print VDI_LIST_FORMAT % {'name_label': 'VDI Label', 'uuid' : 'UUID', - 'virtual_size': 'Bytes', - 'sector_size': 'Sector Size'} + 'virtual_size': 'Bytes'} for vdi in vdis: vdi_struct = execute(server, 'VDI.get_record', (session, vdi)) diff --git a/tools/python/scripts/xapi.vdicfg.py b/tools/python/scripts/xapi.vdicfg.py index 86129bfae9..cb63653550 100644 --- a/tools/python/scripts/xapi.vdicfg.py +++ b/tools/python/scripts/xapi.vdicfg.py @@ -1,7 +1,6 @@ name_label = 'VDI 1' name_description = '' -virtual_size = 10 * 1024 * 1024 -sector_size = 1024 +virtual_size = 10 * 1024 * 1024 * 1024 type = 'system' sharable = False read_only = False diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index ba91b06018..fa790fa75c 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -1811,13 +1811,13 @@ class XendAPI(object): VDI_attr_ro = ['SR', 'VBDs', 'physical_utilisation', - 'sector_size', 'type'] VDI_attr_rw = ['name_label', 'name_description', 'virtual_size', 'sharable', - 'read_only'] + 'read_only', + 'other_config'] VDI_attr_inst = VDI_attr_ro + VDI_attr_rw VDI_methods = [('snapshot', 'VDI')] @@ -1832,10 +1832,7 @@ class XendAPI(object): def VDI_get_physical_utilisation(self, session, vdi_ref): return xen_api_success(self._get_VDI(vdi_ref). - get_physical_utilisation()) - - def VDI_get_sector_size(self, session, vdi_ref): - return xen_api_success(self._get_VDI(vdi_ref).sector_size) + get_physical_utilisation()) def VDI_get_type(self, session, vdi_ref): return xen_api_success(self._get_VDI(vdi_ref).type) @@ -1877,6 +1874,14 @@ class XendAPI(object): self._get_VDI(vdi_ref).read_only = bool(value) return xen_api_success_void() + def VDI_get_other_config(self, session, vdi_ref): + return xen_api_success( + self._get_VDI(vdi_ref).other_config) + + def VDI_set_other_config(self, session, vdi_ref, other_config): + self._get_VDI(vdi_ref).other_config = other_config + return xen_api_success_void() + # Object Methods def VDI_snapshot(self, session, vdi_ref): return xen_api_todo() @@ -1896,10 +1901,10 @@ class XendAPI(object): 'VBDs': [], # TODO 'virtual_size': image.virtual_size, 'physical_utilisation': image.physical_utilisation, - 'sector_size': image.sector_size, 'type': image.type, 'sharable': image.sharable, 'read_only': image.read_only, + 'other_config': image.other_config }) # Class Functions diff --git a/tools/python/xen/xend/XendVDI.py b/tools/python/xen/xend/XendVDI.py index f0dda203a8..dd1bc80385 100644 --- a/tools/python/xen/xend/XendVDI.py +++ b/tools/python/xen/xend/XendVDI.py @@ -54,7 +54,6 @@ class XendVDI(AutoSaveObject): SAVED_CFG = ['name_label', 'name_description', - 'sector_size', 'virtual_size', 'physical_utilisation', 'sharable', @@ -67,13 +66,12 @@ class XendVDI(AutoSaveObject): self.sr_uuid = sr_uuid self.name_label = "" self.name_description = "" - self.sector_size = 1024 self.virtual_size = 0 self.physical_utilisation = 0 self.sharable = False self.read_only = False self.type = "system" - self.location = '' + self.other_config = {} def load_config_dict(self, cfg): """Loads configuration into the object from a dict. @@ -144,11 +142,10 @@ class XendVDI(AutoSaveObject): 'name_description': self.name_description, 'virtual_size': self.virtual_size, 'physical_utilisation': self.physical_utilisation, - 'sector_size': self.sector_size, 'sharable': False, 'readonly': False, 'SR': self.sr_uuid, - 'location': self.get_location(), + 'other_config': self.other_config, 'VBDs': []} def get_location(self): @@ -163,12 +160,11 @@ class XendQCoWVDI(XendVDI): self.cfg_path = cfg_path self.physical_utilisation = psize self.virtual_size = vsize - self.sector_size = 512 self.auto_save = True - self.location = 'tap:qcow:%s' % self.qcow_path + self.other_config['location'] = 'tap:qcow:%s' % self.qcow_path def get_location(self): - return self.location + return self.other_config['location'] class XendLocalVDI(XendVDI): def __init__(self, vdi_struct): @@ -182,11 +178,10 @@ class XendLocalVDI(XendVDI): self.name_description = vdi_struct.get('name_description', '') self.physical_utilisation = 0 self.virtual_size = 0 - self.sector_size = 0 self.type = vdi_struct.get('type', '') self.sharable = vdi_struct.get('sharable', False) self.read_only = vdi_struct.get('read_only', False) - self.location = vdi_struct.get('location', 'file:/dev/null') + self.other_config = vdi_struct.get('other_config', {}) def get_location(self): - return self.location + return self.other_config['location'] From c0767e1cc9a2e1af82ec6d88487c01060ff7d863 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Sat, 17 Mar 2007 23:57:17 +0000 Subject: [PATCH 134/170] Fix xm list's printing of the memory target, when in legacy mode. Signed-off-by: Tom Wilkie --- tools/python/xen/xm/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 8c541e4b2c..77f442e8e3 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -796,7 +796,7 @@ def parse_doms_info(info): else: parsed_info['cpu_time'] = 0 else: - parsed_info['mem'] = get_info('memory_dynamic_min', int,0) + parsed_info['mem'] = get_info('memory', int,0) parsed_info['cpu_time'] = get_info('cpu_time', float, 0.0) return parsed_info From 61fd72f74805924868e7f6e99c699fa43fd397a9 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Sat, 17 Mar 2007 23:59:05 +0000 Subject: [PATCH 135/170] Support xm create through the Xen-API. Signed-off-by: Tom Wilkie --- tools/python/xen/xend/XendConfig.py | 105 ++-- tools/python/xen/xend/XendDomainInfo.py | 52 +- tools/python/xen/xend/XendNode.py | 3 +- tools/python/xen/xm/create.dtd | 118 +++++ tools/python/xen/xm/create.py | 82 ++- tools/python/xen/xm/new.py | 13 +- tools/python/xen/xm/xenapi_create.py | 634 ++++++++++++++++++++++++ 7 files changed, 939 insertions(+), 68 deletions(-) create mode 100644 tools/python/xen/xm/create.dtd create mode 100644 tools/python/xen/xm/xenapi_create.py diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index bdf9370380..36ababeb40 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -105,8 +105,6 @@ XENAPI_CFG_TO_LEGACY_CFG = { 'uuid': 'uuid', 'vcpus_number': 'vcpus', 'cpus': 'cpus', - 'memory_static_min': 'memory', - 'memory_static_max': 'maxmem', 'name_label': 'name', 'actions_after_shutdown': 'on_poweroff', 'actions_after_reboot': 'on_reboot', @@ -136,11 +134,10 @@ XENAPI_CFG_TYPES = { 'user_version': str, 'is_a_template': bool0, 'resident_on': str, - 'memory_static_min': int, + 'memory_static_min': int, # note these are stored in bytes, not KB! 'memory_static_max': int, 'memory_dynamic_min': int, 'memory_dynamic_max': int, - 'memory_actual': int, 'cpus': list, 'vcpus_policy': str, 'vcpus_params': dict, @@ -314,7 +311,6 @@ class XendConfig(dict): 'shadow_memory': 0, 'memory_static_max': 0, 'memory_dynamic_max': 0, - 'memory_actual': 0, 'devices': {}, 'security': None, 'on_xend_start': 'ignore', @@ -334,20 +330,39 @@ class XendConfig(dict): return defaults + # + # Here we assume these values exist in the dict. + # If they don't we have a bigger problem, lets not + # try and 'fix it up' but acutually fix the cause ;-) + # def _memory_sanity_check(self): - if self['memory_static_min'] == 0: - self['memory_static_min'] = self['memory_dynamic_min'] - - # If the static max is not set, let's set it to dynamic max. - # If the static max is smaller than static min, then fix it! - self['memory_static_max'] = max(self['memory_static_max'], - self['memory_dynamic_max'], - self['memory_static_min']) - - for mem_type in ('memory_static_min', 'memory_static_max'): - if self[mem_type] <= 0: - raise XendConfigError('Memory value too low for %s: %d' % - (mem_type, self[mem_type])) + log.debug("_memory_sanity_check memory_static_min: %s, " + "memory_static_max: %i, " + "memory_dynamic_min: %i, " + "memory_dynamic_max: %i", + self["memory_static_min"], + self["memory_static_max"], + self["memory_dynamic_min"], + self["memory_dynamic_max"]) + + if not self["memory_static_min"] <= self["memory_static_max"]: + raise XendConfigError("memory_static_min must be less " \ + "than or equal to memory_static_max") + if not self["memory_dynamic_min"] <= self["memory_dynamic_max"]: + raise XendConfigError("memory_dynamic_min must be less " \ + "than or equal to memory_dynamic_max") + if not self["memory_static_min"] <= self["memory_dynamic_min"]: + raise XendConfigError("memory_static_min must be less " \ + "than or equal to memory_dynamic_min") + if not self["memory_dynamic_max"] <= self["memory_static_max"]: + raise XendConfigError("memory_dynamic_max must be less " \ + "than or equal to memory_static_max") + if not self["memory_dynamic_max"] > 0: + raise XendConfigError("memory_dynamic_max must be greater " \ + "than zero") + if not self["memory_static_max"] > 0: + raise XendConfigError("memory_static_max must be greater " \ + "than zero") def _actions_sanity_check(self): for event in ['shutdown', 'reboot', 'crash']: @@ -392,8 +407,12 @@ class XendConfig(dict): self['domid'] = dominfo['domid'] self['online_vcpus'] = dominfo['online_vcpus'] self['vcpus_number'] = dominfo['max_vcpu_id'] + 1 - self['memory_dynamic_min'] = (dominfo['mem_kb'] + 1023)/1024 - self['memory_dynamic_max'] = (dominfo['maxmem_kb'] + 1023)/1024 + + self['memory_dynamic_min'] = dominfo['mem_kb'] * 1024 + self['memory_dynamic_max'] = dominfo['mem_kb'] * 1024 + self['memory_static_min'] = 0 + self['memory_static_max'] = dominfo['maxmem_kb'] * 1024 + self['cpu_time'] = dominfo['cpu_time']/1e9 # TODO: i don't know what the security stuff expects here if dominfo.get('ssidref'): @@ -447,6 +466,13 @@ class XendConfig(dict): log.warn('Ignoring unrecognised value for deprecated option:' 'restart = \'%s\'', restart) + # Handle memory, passed in as MiB + + if sxp.child_value(sxp_cfg, "memory") != None: + cfg["memory"] = int(sxp.child_value(sxp_cfg, "memory")) + if sxp.child_value(sxp_cfg, "maxmem") != None: + cfg["maxmem"] = int(sxp.child_value(sxp_cfg, "maxmem")) + # Only extract options we know about. extract_keys = LEGACY_UNSUPPORTED_BY_XENAPI_CFG extract_keys += XENAPI_CFG_TO_LEGACY_CFG.values() @@ -616,6 +642,21 @@ class XendConfig(dict): except KeyError: pass + # Lets try and handle memory correctly + + MiB = 1024 * 1024 + + if "memory" in cfg: + self["memory_static_min"] = 0 + self["memory_static_max"] = int(cfg["memory"]) * MiB + self["memory_dynamic_min"] = int(cfg["memory"]) * MiB + self["memory_dynamic_max"] = int(cfg["memory"]) * MiB + + if "maxmem" in cfg: + self["memory_static_max"] = int(cfg["maxmem"]) * MiB + + self._memory_sanity_check() + def update_with(n, o): if not self.get(n): self[n] = cfg.get(o, '') @@ -632,13 +673,6 @@ class XendConfig(dict): if key in cfg: self['platform'][key] = cfg[key] - # make sure a sane maximum is set - if self['memory_static_max'] <= 0: - self['memory_static_max'] = self['memory_static_min'] - - self['memory_dynamic_max'] = self['memory_static_max'] - self['memory_dynamic_min'] = self['memory_static_min'] - # set device references in the configuration self['devices'] = cfg.get('devices', {}) self['console_refs'] = cfg.get('console_refs', []) @@ -812,6 +846,21 @@ class XendConfig(dict): else: sxpr.append([legacy, self[xenapi]]) + MiB = 1024*1024 + + sxpr.append(["maxmem", int(self["memory_static_max"])/MiB]) + sxpr.append(["memory", int(self["memory_dynamic_max"])/MiB]) + + if not legacy_only: + sxpr.append(['memory_dynamic_min', + int(self.get('memory_dynamic_min'))]) + sxpr.append(['memory_dynamic_max', + int(self.get('memory_dynamic_max'))]) + sxpr.append(['memory_static_max', + int(self.get('memory_static_max'))]) + sxpr.append(['memory_static_min', + int(self.get('memory_static_min'))]) + for legacy in LEGACY_UNSUPPORTED_BY_XENAPI_CFG: if legacy in ('domid', 'uuid'): # skip these continue @@ -820,8 +869,6 @@ class XendConfig(dict): sxpr.append(['image', self.image_sxpr()]) sxpr.append(['status', domain.state]) - sxpr.append(['memory_dynamic_min', self.get('memory_dynamic_min')]) - sxpr.append(['memory_dynamic_max', self.get('memory_dynamic_max')]) if domain.getDomid() is not None: sxpr.append(['state', self._get_old_state_string()]) diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 58af5f28ad..78a97b3c45 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -576,7 +576,7 @@ class XendDomainInfo: if target <= 0: raise XendError('Invalid memory size') - self.info['memory_static_min'] = target + self.info['memory_static_min'] = target * 1024 * 1024 if self.domid >= 0: self.storeVm("memory", target) self.storeDom("memory/target", target << 10) @@ -664,6 +664,10 @@ class XendDomainInfo: if arg in XendConfig.LEGACY_CFG_TO_XENAPI_CFG: xapiarg = XendConfig.LEGACY_CFG_TO_XENAPI_CFG[arg] self.info[xapiarg] = val + elif arg == "memory": + self.info["static_memory_min"] = val + elif arg == "maxmem": + self.info["static_memory_max"] = val else: self.info[arg] = val @@ -780,7 +784,7 @@ class XendDomainInfo: 'vm': self.vmpath, 'name': self.info['name_label'], 'console/limit': str(xoptions.get_console_limit() * 1024), - 'memory/target': str(self.info['memory_static_min'] * 1024), + 'memory/target': str(self.info['memory_dynamic_max'] / 1024), } def f(n, v): @@ -864,7 +868,15 @@ class XendDomainInfo: xapiarg = XendConfig.LEGACY_CFG_TO_XENAPI_CFG[arg] if val != None and val != self.info[xapiarg]: self.info[xapiarg] = val - changed= True + changed = True + elif arg == "memory": + if val != None and val != self.info["static_memory_min"]: + self.info["static_memory_min"] = val + changed = True + elif arg == "maxmem": + if val != None and val != self.info["static_memory_max"]: + self.info["static_memory_max"] = val + changed = True # Check whether image definition has been updated image_sxp = self._readVm('image') @@ -969,11 +981,12 @@ class XendDomainInfo: def getMemoryTarget(self): """Get this domain's target memory size, in KB.""" - return self.info['memory_static_min'] * 1024 + return self.info['memory_static_min'] / 1024 def getMemoryMaximum(self): """Get this domain's maximum memory size, in KB.""" - return self.info['memory_static_max'] * 1024 + # remember, info now stores memory in bytes + return self.info['memory_static_max'] / 1024 def getResume(self): return str(self._resume) @@ -1455,13 +1468,14 @@ class XendDomainInfo: # Use architecture- and image-specific calculations to determine # the various headrooms necessary, given the raw configured # values. maxmem, memory, and shadow are all in KiB. + # but memory_static_max etc are all stored in bytes now. memory = self.image.getRequiredAvailableMemory( - self.info['memory_static_min'] * 1024) + self.info['memory_static_min'] / 1024) maxmem = self.image.getRequiredAvailableMemory( - self.info['memory_static_max'] * 1024) + self.info['memory_static_max'] / 1024) shadow = self.image.getRequiredShadowMemory( - self.info['shadow_memory'] * 1024, - self.info['memory_static_max'] * 1024) + self.info['shadow_memory'] / 1024, + self.info['memory_static_max'] / 1024) log.debug("_initDomain:shadow_memory=0x%x, memory_static_max=0x%x, memory_static_min=0x%x.", self.info['shadow_memory'], self.info['memory_static_max'], self.info['memory_static_min'],) # Round shadow up to a multiple of a MiB, as shadow_mem_control @@ -1650,7 +1664,18 @@ class XendDomainInfo: log.exception("XendDomainInfo.destroy: xc.domain_destroy failed.") from xen.xend import XendDomain - XendDomain.instance().remove_domain(self) + + if "transient" in self.info["other_config"]\ + and bool(self.info["other_config"]["transient"]): + xendDomainInstance = XendDomain.instance() + + xendDomainInstance.domains_lock.acquire() + xendDomainInstance._refresh(refresh_shutdown = False) + xendDomainInstance.domains_lock.release() + + xendDomainInstance.domain_delete(self.info["name_label"]) + else: + XendDomain.instance().remove_domain(self) self.cleanupDomain() self._cleanup_phantom_devs(paths) @@ -1833,7 +1858,7 @@ class XendDomainInfo: # 1MB per vcpu plus 4Kib/Mib of RAM. This is higher than # the minimum that Xen would allocate if no value were given. overhead_kb = self.info['vcpus_number'] * 1024 + \ - self.info['memory_static_max'] * 4 + (self.info['memory_static_max'] / 1024 / 1024) * 4 overhead_kb = ((overhead_kb + 1023) / 1024) * 1024 # The domain might already have some shadow memory overhead_kb -= xc.shadow_mem_control(self.domid) * 1024 @@ -1899,6 +1924,11 @@ class XendDomainInfo: if self._infoIsSet(info_key): to_store[key] = str(self.info[info_key]) + if self._infoIsSet("static_memory_min"): + to_store["memory"] = str(self.info["static_memory_min"]) + if self._infoIsSet("static_memory_max"): + to_store["maxmem"] = str(self.info["static_memory_max"]) + image_sxpr = self.info.image_sxpr() if image_sxpr: to_store['image'] = sxp.to_string(image_sxpr) diff --git a/tools/python/xen/xend/XendNode.py b/tools/python/xen/xend/XendNode.py index 954b57a2de..3917c8080c 100644 --- a/tools/python/xen/xend/XendNode.py +++ b/tools/python/xen/xend/XendNode.py @@ -530,7 +530,8 @@ class XendNode: info['cores_per_socket'] * info['threads_per_core']) info['cpu_mhz'] = info['cpu_khz'] / 1000 - # physinfo is in KiB + + # physinfo is in KiB, need it in MiB info['total_memory'] = info['total_memory'] / 1024 info['free_memory'] = info['free_memory'] / 1024 diff --git a/tools/python/xen/xm/create.dtd b/tools/python/xen/xm/create.dtd new file mode 100644 index 0000000000..b544edc5bd --- /dev/null +++ b/tools/python/xen/xm/create.dtd @@ -0,0 +1,118 @@ + +%HTMLlat1; + +%HTMLsymbol; + +%HTMLspecial; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index 450e3283d1..6a4795d2ed 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -28,12 +28,14 @@ import time import xmlrpclib from xen.xend import sxp -from xen.xend import PrettyPrint +from xen.xend import PrettyPrint as SXPPrettyPrint from xen.xend import osdep import xen.xend.XendClient from xen.xend.XendBootloader import bootloader from xen.util import blkif from xen.util import security +from xen.xm.main import serverType, SERVER_XEN_API, get_single_vm +from xen.xm.xenapi_create import sxp2xml, xenapi_create from xen.xm.opts import * @@ -98,6 +100,11 @@ gopts.opt('dryrun', short='n', use="Dry run - prints the resulting configuration in SXP but " "does not create the domain.") +gopts.opt('xmldryrun', short='x', + fn=set_true, default=0, + use="XML dry run - prints the resulting configuration in XML but " + "does not create the domain.") + gopts.opt('paused', short='p', fn=set_true, default=0, use='Leave the domain paused after it is created.') @@ -1241,34 +1248,57 @@ def main(argv): except IOError, exn: raise OptionError("Cannot read file %s: %s" % (config, exn[1])) + if serverType == SERVER_XEN_API: + sxp2xml_inst = sxp2xml() + doc = sxp2xml_inst.convert_sxp_to_xml(config, transient=True) + if opts.vals.dryrun: - PrettyPrint.prettyprint(config) + SXPPrettyPrint.prettyprint(config) + + if opts.vals.xmldryrun and serverType == SERVER_XEN_API: + from xml.dom.ext import PrettyPrint as XMLPrettyPrint + XMLPrettyPrint(doc) + + if opts.vals.dryrun or opts.vals.xmldryrun: + return + + if opts.vals.console_autoconnect: + do_console(sxp.child_value(config, 'name', -1)) + + if serverType == SERVER_XEN_API: + xenapi_create_inst = xenapi_create() + vm_refs = xenapi_create_inst.create(document = doc) + + map(lambda vm_ref: server.xenapi.VM.start(vm_ref, 0), vm_refs) else: if not create_security_check(config): - raise security.ACMError('Security Configuration prevents domain from starting') - else: - if opts.vals.console_autoconnect: - cpid = os.fork() - if cpid != 0: - for i in range(10): - # Catch failure of the create process - time.sleep(1) - (p, rv) = os.waitpid(cpid, os.WNOHANG) - if os.WIFEXITED(rv): - if os.WEXITSTATUS(rv) != 0: - sys.exit(os.WEXITSTATUS(rv)) - try: - # Acquire the console of the created dom - name = sxp.child_value(config, 'name', -1) - dom = server.xend.domain(name) - domid = int(sxp.child_value(dom, 'domid', '-1')) - console.execConsole(domid) - except: - pass - print("Could not start console\n"); - sys.exit(0) - dom = make_domain(opts, config) - + raise security.ACMError( + 'Security Configuration prevents domain from starting') + dom = make_domain(opts, config) + +def do_console(domain_name): + cpid = os.fork() + if cpid != 0: + for i in range(10): + # Catch failure of the create process + time.sleep(1) + (p, rv) = os.waitpid(cpid, os.WNOHANG) + if os.WIFEXITED(rv): + if os.WEXITSTATUS(rv) != 0: + sys.exit(os.WEXITSTATUS(rv)) + try: + # Acquire the console of the created dom + if serverType == SERVER_XEN_API: + domid = server.xenapi.VM.get_domid( + get_single_vm(domain_name)) + else: + dom = server.xend.domain(name) + domid = int(sxp.child_value(dom, 'domid', '-1')) + console.execConsole(domid) + except: + pass + print("Could not start console\n"); + sys.exit(0) if __name__ == '__main__': main(sys.argv) diff --git a/tools/python/xen/xm/new.py b/tools/python/xen/xm/new.py index 2c6cae84b6..742c7ff8fd 100644 --- a/tools/python/xen/xm/new.py +++ b/tools/python/xen/xm/new.py @@ -22,6 +22,9 @@ from xen.xend import PrettyPrint from xen.xend import sxp from xen.xend import XendClient +from xen.xm.main import serverType, SERVER_XEN_API +from xen.xm.xenapi_create import * + from opts import * from create import * @@ -65,7 +68,15 @@ def main(argv): if opts.vals.dryrun: PrettyPrint.prettyprint(config) - else: + return + + if serverType == SERVER_XEN_API: + sxp2xml_inst = sxp2xml() + doc = sxp2xml_inst.convert_sxp_to_xml(config) + + xenapi_create_inst = xenapi_create() + vm_refs = xenapi_create_inst.create(document = doc) + else: make_unstarted_domain(opts, config) if __name__ == '__main__': diff --git a/tools/python/xen/xm/xenapi_create.py b/tools/python/xen/xm/xenapi_create.py new file mode 100644 index 0000000000..498dbba4ae --- /dev/null +++ b/tools/python/xen/xm/xenapi_create.py @@ -0,0 +1,634 @@ +#!/usr/bin/python +#============================================================================ +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#============================================================================ +# Copyright (C) 2007 Tom Wilkie +#============================================================================ +"""Domain creation using new XenAPI +""" + +from xen.xm.main import server +from xml.dom.minidom import parse, getDOMImplementation +from xml.dom.ext import PrettyPrint +from xml.parsers.xmlproc import xmlproc, xmlval, xmldtd +from xen.xend import sxp +from xen.xend.XendAPIConstants import XEN_API_ON_NORMAL_EXIT, \ + XEN_API_ON_CRASH_BEHAVIOUR + + +import sys +import os +import traceback + +def log(_, msg): + #print "> " + msg + pass + +DEBUG = 0 + +def get_name_label(node): + name_node = node.getElementsByTagName("name")[0] + label_node = name_node.getElementsByTagName("label")[0] + return " ".join([child.nodeValue for child in label_node.childNodes]) + +def get_name_description(node): + name_node = node.getElementsByTagName("name")[0] + description_node = name_node.getElementsByTagName("description")[0] + return " ".join([child.nodeValue for child in description_node.childNodes]) + +def get_text_in_child_node(node, child): + tag_node = node.getElementsByTagName(child)[0] + return tag_node.nodeValue + +def get_child_node_attribute(node, child, attribute): + tag_node = node.getElementsByTagName(child)[0] + return tag_node.attributes[attribute].value + +def get_child_nodes_as_dict(node, child_name, + key_attribute_name, + value_attribute_name): + return dict([(child.attributes[key_attribute_name].value, + child.attributes[value_attribute_name].value) + for child in node.getElementsByTagName(child_name)]) + +def try_quietly(fn, *args): + try: + return fn(*args) + except: + return None + +class xenapi_create: + + def __init__(self): + self.DEFAULT_STORAGE_REPOSITORY = [sr_ref + for sr_ref in server.xenapi.SR.get_all() + if server.xenapi.SR.get_type(sr_ref) == "local"][0] + + self.dtd = "/usr/lib/python/xen/xm/create.dtd" + + def create(self, filename=None, document=None): + """ + Create a domain from an XML file or DOM tree + """ + if filename is not None: + self.check_dtd(file) + document = parse(file) + elif document is not None: + self.check_dom_against_dtd(document) + + self.check_doc(document) + + vdis = document.getElementsByTagName("vdi") + vdi_refs_dict = self.create_vdis(vdis) + + try: + vms = document.getElementsByTagName("vm") + return self.create_vms(vms, vdi_refs_dict) + except Exception, exn: + try_quietly(self.cleanup_vdis(vdi_refs_dict)) + raise exn + + # Methods to check xml file + # try to use dtd to check where possible + def check_dtd(self, file): + """ + Check file against DTD. + Use this if possible as it gives nice + error messages + """ + dtd = xmldtd.load_dtd(self.dtd) + parser = xmlproc.XMLProcessor() + parser.set_application(xmlval.ValidatingApp(dtd, parser)) + parser.dtd = dtd + parser.ent = dtd + parser.parse_resource(file) + + def check_dom_against_dtd(self, dom): + """ + Check DOM again DTD. + Doesn't give as nice error messages. + (no location info) + """ + dtd = xmldtd.load_dtd(self.dtd) + app = xmlval.ValidatingApp(dtd, self) + app.set_locator(self) + self.dom2sax(dom, app) + + # Get errors back from ValidatingApp + def report_error(self, number, args=None): + self.errors = xmlproc.errors.english + try: + msg = self.errors[number] + if args != None: + msg = msg % args + except KeyError: + msg = self.errors[4002] % number # Unknown err msg :-) + print msg + sys.exit(-1) + + # Here for compatibility with ValidatingApp + def get_line(self): + return -1 + + def get_column(self): + return -1 + + def dom2sax(self, dom, app): + """ + Take a dom tree and tarverse it, + issuing SAX calls to app. + """ + for child in dom.childNodes: + if child.nodeType == child.TEXT_NODE: + data = child.nodeValue + app.handle_data(data, 0, len(data)) + else: + app.handle_start_tag( + child.nodeName, + self.attrs_to_dict(child.attributes)) + self.dom2sax(child, app) + app.handle_end_tag(child.nodeName) + + def attrs_to_dict(self, attrs): + return dict(attrs.items()) + + # + # Checks which cannot be done with dtd + # + def check_doc(self, doc): + vms = doc.getElementsByTagName("vm") + self.check_vms(vms) + + def check_vms(self, vms): + map(self.check_vm, vms) + + def check_vm(self, vm): + vifs = vm.getElementsByTagName("vif") + self.check_vifs(vifs) + + def check_vifs(self, vifs): + map(self.check_vif, vifs) + + def check_vif(self, vif): + """ + Check that the vif has + either a bridge or network + name but not both + """ + if "bridge" in vif.attributes.keys() \ + and "network" in vif.attributes.keys(): + raise "You cannot specify both a bridge and\ + a network name." + + # Cleanup methods here + def cleanup_vdis(self, vdi_refs_dict): + map(self.cleanup_vdi, vdi_refs_dict.values()) + + def cleanup_vdi(self, vdi_ref): + server.xenapi.VDI.destroy(vdi_ref) + + def cleanup_vms(self, vm_refs): + map(self.cleanup_vm, vm_refs) + + def cleanup_vm(self, vm_ref): + server.xenapi.VM.destroy(vm_ref) + + # Create methods here + def create_vdis(self, vdis): + log(DEBUG, "create_vdis") + return dict(map(self.create_vdi, vdis)) + + def create_vdi(self, vdi): + log(DEBUG, "create_vdi") + + vdi_record = { + "name_label": get_name_label(vdi), + "name_description": get_name_description(vdi), + "SR": self.DEFAULT_STORAGE_REPOSITORY, + "virtual_size": vdi.attributes["size"].value, + "type": vdi.attributes["type"].value, + "shareable": vdi.attributes["shareable"].value, + "read_only": vdi.attributes["read_only"].value, + "other_config": {"location": + vdi.attributes["src"].value} + } + + key = vdi.attributes["name"].value + value = server.xenapi.VDI.create(vdi_record) + + return (key, value) + + def create_vms(self, vms, vdis): + log(DEBUG, "create_vms") + return map(lambda vm: self.create_vm(vm, vdis), vms) + + def create_vm(self, vm, vdis): + log(DEBUG, "create_vm") + + vm_record = { + "name_label": + get_name_label(vm), + "name_description": + get_name_description(vm), + "user_version": + get_text_in_child_node(vm, "version"), + "is_a_template": + vm.attributes["is_a_template"].value, + "auto_power_on": + vm.attributes["auto_power_on"].value, + "memory_static_max": + get_child_node_attribute(vm, "memory", "static_max"), + "memory_static_min": + get_child_node_attribute(vm, "memory", "static_min"), + "memory_dynamic_max": + get_child_node_attribute(vm, "memory", "dynamic_max"), + "memory_dynamic_min": + get_child_node_attribute(vm, "memory", "dynamic_min"), + "vcpus_params": + get_child_nodes_as_dict(vm, "vcpu_param", "key", "value"), + "vcpus_max": + vm.attributes["vcpus_max"].value, + "vcpus_at_startup": + vm.attributes["vcpus_at_startup"].value, + "actions_after_shutdown": + vm.attributes["actions_after_shutdown"].value, + "actions_after_reboot": + vm.attributes["actions_after_reboot"].value, + "actions_after_crash": + vm.attributes["actions_after_crash"].value, + "platform_std_VGA": + vm.attributes["platform_std_VGA"].value, + "platform_serial": + vm.attributes["platform_serial"].value, + "platform_localtime": + vm.attributes["platform_localtime"].value, + "platform_clock_offet": + vm.attributes["platform_clock_offet"].value, + "platform_enable_audio": + vm.attributes["platform_enable_audio"].value, + "PCI_bus": + vm.attributes["platform_enable_audio"].value, + "other_config": + get_child_nodes_as_dict(vm, "other_config", "key", "value") + } + + if len(vm.getElementsByTagName("pv")) > 0: + vm_record.update({ + "PV_bootloader": + get_child_node_attribute(vm, "pv", "bootloader"), + "PV_kernel": + get_child_node_attribute(vm, "pv", "kernel"), + "PV_ramdisk": + get_child_node_attribute(vm, "pv", "ramdisk"), + "PV_args": + get_child_node_attribute(vm, "pv", "args"), + "PV_bootloader_args": + get_child_node_attribute(vm, "pv", "bootloader_args") + }) + else: + hvm = vm.getElementsByTagName("hvm")[0] + vm_record.update({ + "HVM_boot_policy": + get_child_node_attribute(vm, "hvm", "boot_policy"), + "HVM_boot_params": + get_child_nodes_as_dict(hvm, "boot_params", "key", "value") + }) + try: + vm_ref = server.xenapi.VM.create(vm_record) + except: + traceback.print_exc() + sys.exit(-1) + + # Now create vbds + + vbds = vm.getElementsByTagName("vbd") + + self.create_vbds(vm_ref, vbds, vdis) + + # Now create vifs + + vifs = vm.getElementsByTagName("vif") + + self.create_vifs(vm_ref, vifs) + + return vm_ref + + def create_vbds(self, vm_ref, vbds, vdis): + log(DEBUG, "create_vbds") + return map(lambda vbd: self.create_vbd(vm_ref, vbd, vdis), vbds) + + def create_vbd(self, vm_ref, vbd, vdis): + log(DEBUG, "create_vbd") + + vbd_record = { + "VM": + vm_ref, + "VDI": + vdis[vbd.attributes["vdi"].value], + "device": + vbd.attributes["device"].value, + "bootable": + vbd.attributes["bootable"].value, + "mode": + vbd.attributes["mode"].value, + "type": + vbd.attributes["type"].value, + "qos_algorithm_type": + vbd.attributes["qos_algorithm_type"].value, + "qos_algorithm_params": + get_child_nodes_as_dict(vbd, + "qos_algorithm_param", "key", "value") + } + + return server.xenapi.VBD.create(vbd_record) + + def create_vifs(self, vm_ref, vifs): + log(DEBUG, "create_vifs") + return map(lambda vif: self.create_vif(vm_ref, vif), vifs) + + def create_vif(self, vm_ref, vif): + log(DEBUG, "create_vif") + + if "bridge" in vif.attributes.keys(): + raise "Not allowed to add by bridge just yet" + elif "network" in vif.attributes.keys(): + network = [network_ref + for network_ref in server.xenapi.network.get_all() + if server.xenapi.network.get_name_label(network_ref) + == vif.attributes["network"].value][0] + else: + network = self._get_network_ref() + + vif_record = { + "device": + vif.attributes["device"].value, + "network": + network, + "VM": + vm_ref, + "MAC": + vif.attributes["mac"].value, + "MTU": + vif.attributes["mtu"].value, + "qos_algorithm_type": + vif.attributes["qos_algorithm_type"].value, + "qos_algorithm_params": + get_child_nodes_as_dict(vif, + "qos_algorithm_param", "key", "value") + } + + return server.xenapi.VIF.create(vif_record) + + _network_refs = [] + + def _get_network_ref(self): + try: + return self._network_refs.pop(0) + except IndexError: + self._network_refs = server.xenapi.network.get_all() + return self._network_refs.pop(0) + +def get_child_by_name(exp, childname, default = None): + try: + return [child for child in sxp.children(exp) + if child[0] == childname][0][1] + except: + return default + +# Convert old sxp into new xml + +class sxp2xml: + + def convert_sxp_to_xml(self, config, transient=False): + + devices = [child for child in sxp.children(config) + if len(child) > 0 and child[0] == "device"] + + vbds_sxp = map(lambda x: x[1], [device for device in devices + if device[1][0] == "vbd"]) + + vifs_sxp = map(lambda x: x[1], [device for device in devices + if device[1][0] == "vif"]) + # Create XML Document + + impl = getDOMImplementation() + + document = impl.createDocument(None, "xm", None) + + # Lets make the VM tag.. + + vm = document.createElement("vm") + + # Some string compatibility + + actions_after_shutdown \ + = get_child_by_name(config, "on_poweroff", "destroy") + actions_after_reboot \ + = get_child_by_name(config, "on_reboot", "restart") + actions_after_crash \ + = get_child_by_name(config, "on_crash", "restart") + + def conv_chk(val, vals): + val.replace("-", "_") + if val not in vals: + raise "Invalid value: " + val + else: + return val + + actions_after_shutdown = conv_chk(actions_after_shutdown,\ + XEN_API_ON_NORMAL_EXIT) + actions_after_reboot = conv_chk(actions_after_reboot, \ + XEN_API_ON_NORMAL_EXIT) + actions_after_crash = conv_chk(actions_after_crash, \ + XEN_API_ON_CRASH_BEHAVIOUR) + # Flesh out tag attributes + + vm.attributes["is_a_template"] = "false" + vm.attributes["auto_power_on"] = "false" + vm.attributes["actions_after_shutdown"] \ + = actions_after_shutdown + vm.attributes["actions_after_reboot"] \ + = actions_after_reboot + vm.attributes["actions_after_crash"] \ + = actions_after_crash + vm.attributes["platform_std_VGA"] = "false" + vm.attributes["platform_serial"] = "" + vm.attributes["platform_localtime"] = "" + vm.attributes["platform_clock_offet"] = "" + vm.attributes["platform_enable_audio"] = "" + vm.attributes["PCI_bus"] = "" + + vm.attributes["vcpus_max"] \ + = str(get_child_by_name(config, "vcpus", 1)) + vm.attributes["vcpus_at_startup"] \ + = str(get_child_by_name(config, "vcpus", 1)) + + # Make the name tag + + vm.appendChild(self.make_name_tag( + get_child_by_name(config, "name"), document)) + + # Make version tag + + version = document.createElement("version") + version.appendChild(document.createTextNode("1.0")) + vm.appendChild(version) + + # Make pv or hvm tag + + image = get_child_by_name(config, "image") + + if image[0] == "linux": + pv = document.createElement("pv") + pv.attributes["kernel"] \ + = get_child_by_name(image, "kernel", "") + pv.attributes["bootloader"] = "" + pv.attributes["ramdisk"] \ + = get_child_by_name(image, "ramdisk", "") + pv.attributes["args"] \ + = "root=" + get_child_by_name(image, "root", "") \ + + " " + get_child_by_name(image, "args", "") + pv.attributes["bootloader_args"] = "" + + vm.appendChild(pv) + elif image[0] == "hvm": + hvm = document.createElement("hvm") + hvm.attributes["boot_policy"] = "" + + vm.appendChild(hvm) + + # Make memory tag + + memory = document.createElement("memory") + + memory_str = str(int( + get_child_by_name(config, "memory"))*1024*1024) + + memory.attributes["static_min"] = memory_str + memory.attributes["static_max"] = memory_str + memory.attributes["dynamic_min"] = memory_str + memory.attributes["dynamic_max"] = memory_str + + vm.appendChild(memory) + + # And now the vbds + + vbds = map(lambda vbd: self.extract_vbd(vbd, document), vbds_sxp) + + map(vm.appendChild, vbds) + + # And now the vifs + + vifs = map(lambda vif: self.extract_vif(vif, document), vifs_sxp) + + map(vm.appendChild, vifs) + + # transient? + + if transient: + other_config = document.createElement("other_config") + other_config.attributes["key"] = "transient" + other_config.attributes["value"] = "True" + vm.appendChild(other_config) + + # Add it to doc_root + + document.documentElement.appendChild(vm) + + # We want to pull out vdis + + vdis = map(lambda vdb: self.extract_vdi(vdb, document), vbds_sxp) + + map(document.documentElement.appendChild, vdis) + + return document + + def make_name_tag(self, label_text, document): + name = document.createElement("name") + + label = document.createElement("label") + label.appendChild(document.createTextNode(str(label_text))) + name.appendChild(label) + + description = document.createElement("description") + description.appendChild(document.createTextNode(" ")) + name.appendChild(description) + + return name + + def extract_vbd(self, vbd_sxp, document): + src = get_child_by_name(vbd_sxp, "uname") + name = str(src.__hash__()) + + vbd = document.createElement("vbd") + + vbd.attributes["name"] = "vdb" + name + vbd.attributes["vdi"] = "vdi" + name + vbd.attributes["mode"] \ + = get_child_by_name(vbd_sxp, "mode") != "w" \ + and "RO" or "RW" + vbd.attributes["device"] \ + = get_child_by_name(vbd_sxp, "dev") + vbd.attributes["bootable"] = "1" + vbd.attributes["type"] = "disk" + vbd.attributes["qos_algorithm_type"] = "" + + return vbd + + def extract_vdi(self, vbd_sxp, document): + src = get_child_by_name(vbd_sxp, "uname") + name = "vdi" + str(src.__hash__()) + path = src[src.find(":")+1:] + + vdi = document.createElement("vdi") + + vdi.attributes["src"] = src + vdi.attributes["read_only"] \ + = (get_child_by_name(vbd_sxp, "mode") != "w") \ + and "true" or "false" + vdi.attributes["size"] \ + = str(os.path.getsize(path)) + vdi.attributes["type"] = "system" + vdi.attributes["shareable"] = "false" + vdi.attributes["name"] = name + + vdi.appendChild(self.make_name_tag(name, document)) + + return vdi + + def extract_vif(self, vif_sxp, document): + + vif = document.createElement("vif") + + dev = get_child_by_name(vif_sxp, "vifname", "eth0") + + vif.attributes["name"] \ + = "vif" + str(dev.__hash__()) + vif.attributes["mac"] \ + = get_child_by_name(vif_sxp, "mac", "") + vif.attributes["mtu"] \ + = get_child_by_name(vif_sxp, "mtu", "") + vif.attributes["device"] = dev + vif.attributes["qos_algorithm_type"] = "" + + if get_child_by_name(vif_sxp, "bridge") is not None: + vif.attributes["bridge"] \ + = get_child_by_name(vif_sxp, "bridge") + + return vif + + + + + From 734d12f3111dc2184ef801a27f5bf7b5d9dd2b96 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Sun, 18 Mar 2007 12:06:01 +0000 Subject: [PATCH 136/170] Fix the signedness of a number of values demarshalled by xc.domain_getinfo, in particular mem_kb and maxmem_kb. Signed-off-by: Ewan Mellor --- tools/python/xen/lowlevel/xc/xc.c | 36 ++++++++++++++++--------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c index 804adc3104..3cb5c213ac 100644 --- a/tools/python/xen/lowlevel/xc/xc.c +++ b/tools/python/xen/lowlevel/xc/xc.c @@ -311,23 +311,25 @@ static PyObject *pyxc_domain_getinfo(XcObject *self, PyObject *pyhandle = PyList_New(sizeof(xen_domain_handle_t)); for ( j = 0; j < sizeof(xen_domain_handle_t); j++ ) PyList_SetItem(pyhandle, j, PyInt_FromLong(info[i].handle[j])); - info_dict = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i" - ",s:l,s:L,s:l,s:i,s:i}", - "domid", info[i].domid, - "online_vcpus", info[i].nr_online_vcpus, - "max_vcpu_id", info[i].max_vcpu_id, - "hvm", info[i].hvm, - "dying", info[i].dying, - "crashed", info[i].crashed, - "shutdown", info[i].shutdown, - "paused", info[i].paused, - "blocked", info[i].blocked, - "running", info[i].running, - "mem_kb", info[i].nr_pages*(XC_PAGE_SIZE/1024), - "cpu_time", info[i].cpu_time, - "maxmem_kb", info[i].max_memkb, - "ssidref", info[i].ssidref, - "shutdown_reason", info[i].shutdown_reason); + info_dict = Py_BuildValue( + "{s:i,s:I,s:I,s:i,s:i,s:i,s:i,s:i,s:i,s:i" + ",s:k,s:L,s:k,s:i,s:I}", + "domid", (int)info[i].domid, + "online_vcpus", info[i].nr_online_vcpus, + "max_vcpu_id", info[i].max_vcpu_id, + "hvm", info[i].hvm, + "dying", info[i].dying, + "crashed", info[i].crashed, + "shutdown", info[i].shutdown, + "paused", info[i].paused, + "blocked", info[i].blocked, + "running", info[i].running, + + "mem_kb", info[i].nr_pages*(XC_PAGE_SIZE/1024), + "cpu_time", (long long)info[i].cpu_time, + "maxmem_kb", info[i].max_memkb, + "ssidref", (int)info[i].ssidref, + "shutdown_reason", info[i].shutdown_reason); PyDict_SetItemString(info_dict, "handle", pyhandle); Py_DECREF(pyhandle); PyList_SetItem(list, i, info_dict); From 5515b59042adafae1c93548562ae53de755a676c Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Sun, 18 Mar 2007 12:06:50 +0000 Subject: [PATCH 137/170] Re-raise log level for XendConfig (accidentally changed it to DEBUG previously). Signed-off-by: Ewan Mellor --- tools/python/xen/xend/XendConfig.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index 36ababeb40..d8f5c3fe66 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -28,7 +28,7 @@ from xen.xend.PrettyPrint import prettyprintstring from xen.xend.XendConstants import DOM_STATE_HALTED log = logging.getLogger("xend.XendConfig") -log.setLevel(logging.DEBUG) +log.setLevel(logging.WARN) """ From 2cea532bee3c20beeb926357e96dce6e5377cb54 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Sun, 18 Mar 2007 16:49:52 +0000 Subject: [PATCH 138/170] xend: Fix Py_BuildValue() invocation (don't use I specifier). Various error-handlign cleanup and fix a reference leakage. Signed-off-by: Keir Fraser --- tools/python/xen/lowlevel/xc/xc.c | 42 +++++++++++++++++++------------ 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c index 3cb5c213ac..894ff7777c 100644 --- a/tools/python/xen/lowlevel/xc/xc.c +++ b/tools/python/xen/lowlevel/xc/xc.c @@ -50,17 +50,21 @@ static PyObject *pyxc_error_to_exception(void) const xc_error *err = xc_get_last_error(); const char *desc = xc_error_code_to_desc(err->code); - if (err->code == XC_ERROR_NONE) + if ( err->code == XC_ERROR_NONE ) return PyErr_SetFromErrno(xc_error_obj); - if (err->message[0] != '\0') + if ( err->message[0] != '\0' ) pyerr = Py_BuildValue("(iss)", err->code, desc, err->message); else pyerr = Py_BuildValue("(is)", err->code, desc); xc_clear_last_error(); - PyErr_SetObject(xc_error_obj, pyerr); + if ( pyerr != NULL ) + { + PyErr_SetObject(xc_error_obj, pyerr); + Py_DECREF(pyerr); + } return NULL; } @@ -70,13 +74,13 @@ static PyObject *pyxc_domain_dumpcore(XcObject *self, PyObject *args) uint32_t dom; char *corefile; - if (!PyArg_ParseTuple(args, "is", &dom, &corefile)) + if ( !PyArg_ParseTuple(args, "is", &dom, &corefile) ) return NULL; if ( (corefile == NULL) || (corefile[0] == '\0') ) return NULL; - if (xc_domain_dumpcore(self->xc_handle, dom, corefile) != 0) + if ( xc_domain_dumpcore(self->xc_handle, dom, corefile) != 0 ) return pyxc_error_to_exception(); Py_INCREF(zero); @@ -168,10 +172,10 @@ static PyObject *pyxc_domain_shutdown(XcObject *self, PyObject *args) { uint32_t dom, reason; - if (!PyArg_ParseTuple(args, "ii", &dom, &reason)) + if ( !PyArg_ParseTuple(args, "ii", &dom, &reason) ) return NULL; - if (xc_domain_shutdown(self->xc_handle, dom, reason) != 0) + if ( xc_domain_shutdown(self->xc_handle, dom, reason) != 0 ) return pyxc_error_to_exception(); Py_INCREF(zero); @@ -183,10 +187,10 @@ static PyObject *pyxc_domain_resume(XcObject *self, PyObject *args) uint32_t dom; int fast; - if (!PyArg_ParseTuple(args, "ii", &dom, &fast)) + if ( !PyArg_ParseTuple(args, "ii", &dom, &fast) ) return NULL; - if (xc_domain_resume(self->xc_handle, dom, fast) != 0) + if ( xc_domain_resume(self->xc_handle, dom, fast) != 0 ) return pyxc_error_to_exception(); Py_INCREF(zero); @@ -282,7 +286,7 @@ static PyObject *pyxc_domain_getinfo(XcObject *self, PyObject *args, PyObject *kwds) { - PyObject *list, *info_dict; + PyObject *list, *info_dict, *pyhandle; uint32_t first_dom = 0; int max_doms = 1024, nr_doms, i, j; @@ -308,12 +312,9 @@ static PyObject *pyxc_domain_getinfo(XcObject *self, list = PyList_New(nr_doms); for ( i = 0 ; i < nr_doms; i++ ) { - PyObject *pyhandle = PyList_New(sizeof(xen_domain_handle_t)); - for ( j = 0; j < sizeof(xen_domain_handle_t); j++ ) - PyList_SetItem(pyhandle, j, PyInt_FromLong(info[i].handle[j])); info_dict = Py_BuildValue( - "{s:i,s:I,s:I,s:i,s:i,s:i,s:i,s:i,s:i,s:i" - ",s:k,s:L,s:k,s:i,s:I}", + "{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i" + ",s:k,s:L,s:k,s:i,s:i}", "domid", (int)info[i].domid, "online_vcpus", info[i].nr_online_vcpus, "max_vcpu_id", info[i].max_vcpu_id, @@ -324,12 +325,21 @@ static PyObject *pyxc_domain_getinfo(XcObject *self, "paused", info[i].paused, "blocked", info[i].blocked, "running", info[i].running, - "mem_kb", info[i].nr_pages*(XC_PAGE_SIZE/1024), "cpu_time", (long long)info[i].cpu_time, "maxmem_kb", info[i].max_memkb, "ssidref", (int)info[i].ssidref, "shutdown_reason", info[i].shutdown_reason); + pyhandle = PyList_New(sizeof(xen_domain_handle_t)); + if ( (pyhandle == NULL) || (info_dict == NULL) ) + { + Py_DECREF(list); + if ( pyhandle != NULL ) { Py_DECREF(pyhandle); } + if ( info_dict != NULL ) { Py_DECREF(info_dict); } + return NULL; + } + for ( j = 0; j < sizeof(xen_domain_handle_t); j++ ) + PyList_SetItem(pyhandle, j, PyInt_FromLong(info[i].handle[j])); PyDict_SetItemString(info_dict, "handle", pyhandle); Py_DECREF(pyhandle); PyList_SetItem(list, i, info_dict); From 3baee98422887ad86001fb476df62e0a0ad33d39 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Sun, 18 Mar 2007 18:26:34 +0000 Subject: [PATCH 139/170] xend: Avoid use of 'k' specifier to Py_BuildValue(). Its implementation is broken until Python v2.4.3. Instead cast the C value to long long and use the 'L' specifier. Signed-off-by: Keir Fraser --- tools/python/xen/lowlevel/xc/xc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c index 894ff7777c..e3b3d4c0e6 100644 --- a/tools/python/xen/lowlevel/xc/xc.c +++ b/tools/python/xen/lowlevel/xc/xc.c @@ -314,7 +314,7 @@ static PyObject *pyxc_domain_getinfo(XcObject *self, { info_dict = Py_BuildValue( "{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i" - ",s:k,s:L,s:k,s:i,s:i}", + ",s:L,s:L,s:L,s:i,s:i}", "domid", (int)info[i].domid, "online_vcpus", info[i].nr_online_vcpus, "max_vcpu_id", info[i].max_vcpu_id, @@ -325,9 +325,9 @@ static PyObject *pyxc_domain_getinfo(XcObject *self, "paused", info[i].paused, "blocked", info[i].blocked, "running", info[i].running, - "mem_kb", info[i].nr_pages*(XC_PAGE_SIZE/1024), + "mem_kb", (long long)info[i].nr_pages*(XC_PAGE_SIZE/1024), "cpu_time", (long long)info[i].cpu_time, - "maxmem_kb", info[i].max_memkb, + "maxmem_kb", (long long)info[i].max_memkb, "ssidref", (int)info[i].ssidref, "shutdown_reason", info[i].shutdown_reason); pyhandle = PyList_New(sizeof(xen_domain_handle_t)); From ca039d02446698730d586df9ed3ba3fcd2c4bd98 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 19 Mar 2007 09:31:04 +0000 Subject: [PATCH 140/170] hvm: Fix platform-irq handling in presence of irqbalance daemon. The HVM guest did not respond when PV-on-HVM driver was tested on the following conditions. 1. RHEL4u4 2. vcpu 4 3. irqbalance on 4. pv-on-hvm driver used. Eventhandler did not work because IRQ was delivered to another vcpu by irqbalance. Signed-off-by: Tsunehisa Doi Signed-off-by: Tomonari Horikoshi --- unmodified_drivers/linux-2.6/platform-pci/evtchn.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/unmodified_drivers/linux-2.6/platform-pci/evtchn.c b/unmodified_drivers/linux-2.6/platform-pci/evtchn.c index 9063e37f17..0c19cf5cda 100644 --- a/unmodified_drivers/linux-2.6/platform-pci/evtchn.c +++ b/unmodified_drivers/linux-2.6/platform-pci/evtchn.c @@ -167,7 +167,8 @@ EXPORT_SYMBOL(notify_remote_via_irq); irqreturn_t evtchn_interrupt(int irq, void *dev_id, struct pt_regs *regs) { unsigned int l1i, port; - int cpu = smp_processor_id(); + /* XXX: All events are bound to vcpu0 but irq may be redirected. */ + int cpu = 0; /*smp_processor_id();*/ irqreturn_t(*handler) (int, void *, struct pt_regs *); shared_info_t *s = shared_info_area; vcpu_info_t *v = &s->vcpu_info[cpu]; From 569b0bb3b92ca539da34d41d092deb8edb7a81ce Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 19 Mar 2007 09:32:52 +0000 Subject: [PATCH 141/170] Add parentheses to trace_do_casts macro. The arguments to this macro didn't have parentheses around them where they were used. If a call to a TRACE macro included an expression as an argument, the cast to (unsigned long) could bind to just part of the expression and lead to unexpected results. Signed-off-by: Michael Vrable --- xen/include/xen/trace.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/xen/include/xen/trace.h b/xen/include/xen/trace.h index 4f3649a394..cd1422bc09 100644 --- a/xen/include/xen/trace.h +++ b/xen/include/xen/trace.h @@ -41,11 +41,11 @@ void trace(u32 event, unsigned long d1, unsigned long d2, do { \ if ( unlikely(tb_init_done) ) \ trace(e, \ - (unsigned long)d1, \ - (unsigned long)d2, \ - (unsigned long)d3, \ - (unsigned long)d4, \ - (unsigned long)d5); \ + (unsigned long)(d1), \ + (unsigned long)(d2), \ + (unsigned long)(d3), \ + (unsigned long)(d4), \ + (unsigned long)(d5)); \ } while ( 0 ) /* Convenience macros for calling the trace function. */ From f55d16fa21b0e87079c4075597c355251131ad16 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 19 Mar 2007 09:34:42 +0000 Subject: [PATCH 142/170] minios: Various small fixes. - Fixed type of variables in hypervisor.c. - Fixed not removing a waiter from watch_queue. - Make wait_for_watch() global accessible. Signed-off-by: Dietmar Hahn --- extras/mini-os/hypervisor.c | 4 ++-- extras/mini-os/include/wait.h | 7 +++++++ extras/mini-os/include/xenbus.h | 1 + extras/mini-os/xenbus/xenbus.c | 3 ++- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/extras/mini-os/hypervisor.c b/extras/mini-os/hypervisor.c index 2c2efa7e46..ed87845195 100644 --- a/extras/mini-os/hypervisor.c +++ b/extras/mini-os/hypervisor.c @@ -35,8 +35,8 @@ void do_hypervisor_callback(struct pt_regs *regs) { - u32 l1, l2; - unsigned int l1i, l2i, port; + unsigned long l1, l2, l1i, l2i; + unsigned int port; int cpu = 0; shared_info_t *s = HYPERVISOR_shared_info; vcpu_info_t *vcpu_info = &s->vcpu_info[cpu]; diff --git a/extras/mini-os/include/wait.h b/extras/mini-os/include/wait.h index f581db9109..d8338fbd8e 100644 --- a/extras/mini-os/include/wait.h +++ b/extras/mini-os/include/wait.h @@ -74,6 +74,13 @@ static inline void wake_up(struct wait_queue_head *head) local_irq_restore(flags); \ } while (0) +#define remove_waiter(w) do { \ + unsigned long flags; \ + local_irq_save(flags); \ + remove_wait_queue(&w); \ + local_irq_restore(flags); \ +} while (0) + #define wait_event(wq, condition) do{ \ unsigned long flags; \ if(condition) \ diff --git a/extras/mini-os/include/xenbus.h b/extras/mini-os/include/xenbus.h index 3866a8bbce..cd4e85d122 100644 --- a/extras/mini-os/include/xenbus.h +++ b/extras/mini-os/include/xenbus.h @@ -13,6 +13,7 @@ void init_xenbus(void); char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value); char *xenbus_watch_path(xenbus_transaction_t xbt, const char *path); +void wait_for_watch(void); char* xenbus_wait_for_value(const char*,const char*); /* Associates a value with a path. Returns a malloc'd error string on diff --git a/extras/mini-os/xenbus/xenbus.c b/extras/mini-os/xenbus/xenbus.c index f483211947..9433b22b02 100644 --- a/extras/mini-os/xenbus/xenbus.c +++ b/extras/mini-os/xenbus/xenbus.c @@ -72,11 +72,12 @@ static void memcpy_from_ring(const void *Ring, memcpy(dest + c1, ring, c2); } -static inline void wait_for_watch(void) +void wait_for_watch(void) { DEFINE_WAIT(w); add_waiter(w,watch_queue); schedule(); + remove_waiter(w); wake(current); } From ebcb37da0c665e5f997257b365d40357b2fac31c Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Mon, 19 Mar 2007 11:09:57 +0000 Subject: [PATCH 143/170] Fix memory size handling. These were by Tom Wilkie , and were dropped accidentally by me when merging. Signed-off-by: Ewan Mellor --- tools/python/xen/xend/XendDomainInfo.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 78a97b3c45..da3e5936a3 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -576,12 +576,14 @@ class XendDomainInfo: if target <= 0: raise XendError('Invalid memory size') - self.info['memory_static_min'] = target * 1024 * 1024 + MiB = 1024 * 1024 + self.info['memory_dynamic_min'] = target * MiB + self.info['memory_dynamic_max'] = target * MiB + if self.domid >= 0: self.storeVm("memory", target) self.storeDom("memory/target", target << 10) else: - self.info['memory_dynamic_min'] = target xen.xend.XendDomain.instance().managed_config_save(self) def setMemoryMaximum(self, limit): @@ -981,7 +983,7 @@ class XendDomainInfo: def getMemoryTarget(self): """Get this domain's target memory size, in KB.""" - return self.info['memory_static_min'] / 1024 + return self.info['memory_dynamic_max'] / 1024 def getMemoryMaximum(self): """Get this domain's maximum memory size, in KB.""" @@ -1470,7 +1472,7 @@ class XendDomainInfo: # values. maxmem, memory, and shadow are all in KiB. # but memory_static_max etc are all stored in bytes now. memory = self.image.getRequiredAvailableMemory( - self.info['memory_static_min'] / 1024) + self.info['memory_dynamic_max'] / 1024) maxmem = self.image.getRequiredAvailableMemory( self.info['memory_static_max'] / 1024) shadow = self.image.getRequiredShadowMemory( @@ -2018,7 +2020,11 @@ class XendDomainInfo: info = dom_get(self.domid) if not info: return - + + if info["maxmem_kb"] < 0: + info["maxmem_kb"] = XendNode.instance() \ + .physinfo_dict()['total_memory'] * 1024 + #manually update ssidref / security fields if security.on() and info.has_key('ssidref'): if (info['ssidref'] != 0) and self.info.has_key('security'): @@ -2402,7 +2408,7 @@ class XendDomainInfo: def __str__(self): return '' % \ (str(self.domid), self.info['name_label'], - str(self.info['memory_static_min']), DOM_STATES[self.state]) + str(self.info['memory_dynamic_max']), DOM_STATES[self.state]) __repr__ = __str__ From 90f0206fe9e1c47011c0985dc8445ba1686fea31 Mon Sep 17 00:00:00 2001 From: Christian Limpach Date: Mon, 19 Mar 2007 11:15:28 +0000 Subject: [PATCH 144/170] [ioemu] Cleanup media change code. Signed-off-by: Christian Limpach --- tools/ioemu/xenstore.c | 52 +++++++++++++++++------------------------- 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/tools/ioemu/xenstore.c b/tools/ioemu/xenstore.c index 4f549ac5e3..26063f5a93 100644 --- a/tools/ioemu/xenstore.c +++ b/tools/ioemu/xenstore.c @@ -18,7 +18,7 @@ #include static struct xs_handle *xsh = NULL; -static char *hd_filename[MAX_DISKS]; +static char *media_filename[MAX_DISKS]; static QEMUTimer *insert_timer = NULL; #define UWAIT_MAX (30*1000000) /* thirty seconds */ @@ -45,10 +45,10 @@ static void insert_media(void *opaque) int i; for (i = 0; i < MAX_DISKS; i++) { - if (hd_filename[i]) { - do_change(bs_table[i]->device_name, hd_filename[i]); - free(hd_filename[i]); - hd_filename[i] = NULL; + if (media_filename[i] && bs_table[i]) { + do_change(bs_table[i]->device_name, media_filename[i]); + free(media_filename[i]); + media_filename[i] = NULL; } } } @@ -87,7 +87,7 @@ void xenstore_parse_domain_config(int domid) unsigned int len, num, hd_index; for(i = 0; i < MAX_DISKS; i++) - hd_filename[i] = NULL; + media_filename[i] = NULL; xsh = xs_daemon_open(); if (xsh == NULL) { @@ -133,19 +133,12 @@ void xenstore_parse_domain_config(int domid) continue; free(type); type = xs_read(xsh, XBT_NULL, buf, &len); - /* read params to get the patch of the image -- read it last - * so that we have its path in buf when setting up the - * watch */ if (pasprintf(&buf, "%s/params", bpath) == -1) continue; free(params); params = xs_read(xsh, XBT_NULL, buf, &len); if (params == NULL) continue; - if (params[0]) { - hd_filename[hd_index] = params; /* strdup() */ - params = NULL; /* don't free params on re-use */ - } /* * check if device has a phantom vbd; the phantom is hooked * to the frontend device (for ease of cleanup), so lookup @@ -156,35 +149,32 @@ void xenstore_parse_domain_config(int domid) continue; free(fpath); fpath = xs_read(xsh, XBT_NULL, buf, &len); - if (fpath != NULL) { + if (fpath) { if (pasprintf(&buf, "%s/dev", fpath) == -1) continue; + free(params); params = xs_read(xsh, XBT_NULL, buf , &len); - if (params != NULL) { - free(hd_filename[hd_index]); - hd_filename[hd_index] = params; - params = NULL; /* don't free params on re-use */ + if (params) { /* * wait for device, on timeout silently fail because we will * fail to open below */ - waitForDevice(hd_filename[hd_index]); + waitForDevice(params); } } + bs_table[hd_index] = bdrv_new(dev); - /* re-establish buf */ - if (pasprintf(&buf, "%s/params", bpath) == -1) - continue; /* check if it is a cdrom */ if (type && !strcmp(type, "cdrom")) { bdrv_set_type_hint(bs_table[hd_index], BDRV_TYPE_CDROM); - xs_watch(xsh, buf, dev); + if (pasprintf(&buf, "%s/params", bpath) != -1) + xs_watch(xsh, buf, dev); } - if (hd_filename[hd_index]) { - if (bdrv_open(bs_table[hd_index], hd_filename[hd_index], - 0 /* snapshot */) < 0) + /* open device now if media present */ + if (params[0]) { + if (bdrv_open(bs_table[hd_index], params, 0 /* snapshot */) < 0) fprintf(stderr, "qemu: could not open hard disk image '%s'\n", - hd_filename[hd_index]); + params); } } @@ -347,13 +337,13 @@ void xenstore_process_event(void *opaque) do_eject(0, vec[XS_WATCH_TOKEN]); bs_table[hd_index]->filename[0] = 0; - if (hd_filename[hd_index]) { - free(hd_filename[hd_index]); - hd_filename[hd_index] = NULL; + if (media_filename[hd_index]) { + free(media_filename[hd_index]); + media_filename[hd_index] = NULL; } if (image[0]) { - hd_filename[hd_index] = strdup(image); + media_filename[hd_index] = strdup(image); xenstore_check_new_media_present(5000); } From 70fe04c768682d517d887d27f7dc195e616a38f5 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Mon, 19 Mar 2007 13:44:31 +0000 Subject: [PATCH 145/170] Use HOSTCFLAGS with HOSTCC. Signed-off-by: Jan Beulich --- xen/include/public/foreign/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xen/include/public/foreign/Makefile b/xen/include/public/foreign/Makefile index 7bf028e72a..c107c5ab7f 100644 --- a/xen/include/public/foreign/Makefile +++ b/xen/include/public/foreign/Makefile @@ -18,7 +18,7 @@ check-headers: checker ./checker > $(XEN_TARGET_ARCH).size diff -u reference.size $(XEN_TARGET_ARCH).size checker: checker.c $(headers) - $(HOSTCC) $(CFLAGS) -o $@ $< + $(HOSTCC) $(HOSTCFLAGS) -o $@ $< else check-headers: @echo "cross build: skipping check" From f8b68fe2dad1e6bf4f55483dd023561d3ee008cb Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Mon, 19 Mar 2007 13:48:00 +0000 Subject: [PATCH 146/170] hvm: Lower HPET frequency to 1/32 of the TSC. The frequency of HPET device model is defined to be the same as TSC's, but this doesn't work well with calibrate_tsc_hpet() in Linux kernel 2.6.16-33, causing some IA32 Linux HVM guests to failt o boot. Calibrate_tsc_hpet() tries to figure out how many HPET ticks a TSC cycle equals; it magnifies the result by scale of 2^32, trying to get a more accurate result since it assumes the frequency of HPET in real world is usually less than 1/100 of TSC, so the result of "(2^32 * hpet_freq) / tsc_freq" may exceed 32bits, then a "divide error (overflow)" would occur! The result doesn't overflow every time because hpet_freq/tsc_freq may less than 1.0 due to the little inaccuracy in the implementation of HVM timer virtualization. Signed-off-by: Dexuan Cui --- xen/arch/x86/hvm/hpet.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/xen/arch/x86/hvm/hpet.c b/xen/arch/x86/hvm/hpet.c index 419a886eba..b3fb6ffe29 100644 --- a/xen/arch/x86/hvm/hpet.c +++ b/xen/arch/x86/hvm/hpet.c @@ -29,6 +29,10 @@ #define S_TO_NS 1000000000ULL /* 1s = 10^9 ns */ #define S_TO_FS 1000000000000000ULL /* 1s = 10^15 fs */ +/* Frequency_of_TSC / frequency_of_HPET = 32 */ +#define TSC_PER_HPET_TICK 32 +#define guest_time_hpet(v) (hvm_get_guest_time(v) / TSC_PER_HPET_TICK) + #define HPET_ID 0x000 #define HPET_PERIOD 0x004 #define HPET_CFG 0x010 @@ -67,7 +71,9 @@ #define HPET_TN_INT_ROUTE_CAP_MASK (0xffffffffULL \ << HPET_TN_INT_ROUTE_CAP_SHIFT) -#define hpet_tick_to_ns(h, tick) ((s_time_t)(tick)*S_TO_NS/h->tsc_freq) +#define hpet_tick_to_ns(h, tick) ((s_time_t)(tick)* \ + (S_TO_NS*TSC_PER_HPET_TICK)/h->tsc_freq) + #define timer_config(h, n) (h->hpet.timers[n].config) #define timer_enabled(h, n) (timer_config(h, n) & HPET_TN_ENABLE) #define timer_is_periodic(h, n) (timer_config(h, n) & HPET_TN_PERIODIC) @@ -108,7 +114,7 @@ static inline int hpet_check_access_length( static inline uint64_t hpet_read_maincounter(HPETState *h) { if ( hpet_enabled(h) ) - return hvm_get_guest_time(h->vcpu) + h->mc_offset; + return guest_time_hpet(h->vcpu) + h->mc_offset; else return h->hpet.mc64; } @@ -144,7 +150,7 @@ static void hpet_stop_timer(HPETState *h, unsigned int tn) /* the number of HPET tick that stands for * 1/(2^10) second, namely, 0.9765625 milliseconds */ -#define HPET_TINY_TIME_SPAN (h->tsc_freq >> 10) +#define HPET_TINY_TIME_SPAN ((h->tsc_freq >> 10) / TSC_PER_HPET_TICK) static void hpet_set_timer(HPETState *h, unsigned int tn) { @@ -225,14 +231,14 @@ static void hpet_write( if ( !(old_val & HPET_CFG_ENABLE) && (new_val & HPET_CFG_ENABLE) ) { /* Enable main counter and interrupt generation. */ - h->mc_offset = h->hpet.mc64 - hvm_get_guest_time(h->vcpu); + h->mc_offset = h->hpet.mc64 - guest_time_hpet(h->vcpu); for ( i = 0; i < HPET_TIMER_NUM; i++ ) hpet_set_timer(h, i); } else if ( (old_val & HPET_CFG_ENABLE) && !(new_val & HPET_CFG_ENABLE) ) { /* Halt main counter and disable interrupt generation. */ - h->hpet.mc64 = h->mc_offset + hvm_get_guest_time(h->vcpu); + h->hpet.mc64 = h->mc_offset + guest_time_hpet(h->vcpu); for ( i = 0; i < HPET_TIMER_NUM; i++ ) hpet_stop_timer(h, i); } @@ -384,7 +390,7 @@ static int hpet_save(struct domain *d, hvm_domain_context_t *h) HPETState *hp = &d->arch.hvm_domain.pl_time.vhpet; /* Write the proper value into the main counter */ - hp->hpet.mc64 = hp->mc_offset + hvm_get_guest_time(hp->vcpu); + hp->hpet.mc64 = hp->mc_offset + guest_time_hpet(hp->vcpu); /* Save the HPET registers */ return hvm_save_entry(HPET, 0, h, &hp->hpet); @@ -400,7 +406,7 @@ static int hpet_load(struct domain *d, hvm_domain_context_t *h) return -EINVAL; /* Recalculate the offset between the main counter and guest time */ - hp->mc_offset = hp->hpet.mc64 - hvm_get_guest_time(hp->vcpu); + hp->mc_offset = hp->hpet.mc64 - guest_time_hpet(hp->vcpu); /* Restart the timers */ for ( i = 0; i < HPET_TIMER_NUM; i++ ) @@ -425,8 +431,8 @@ void hpet_init(struct vcpu *v) h->hpet.capability = 0x8086A201ULL; /* This is the number of femptoseconds per HPET tick. */ - /* Here we define HPET's frequency to be the same as the TSC's. */ - h->hpet.capability |= ((S_TO_FS/h->tsc_freq) << 32); + /* Here we define HPET's frequency to be 1/32 of the TSC's */ + h->hpet.capability |= ((S_TO_FS*TSC_PER_HPET_TICK/h->tsc_freq) << 32); for ( i = 0; i < HPET_TIMER_NUM; i++ ) { From 3b8a13159a7851752281ac82bef907093aea06da Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Mon, 19 Mar 2007 14:00:07 +0000 Subject: [PATCH 147/170] [LINUX] Update crash-kernel-32-on-64.patch with more sensible version from -mm. The previous version had side effects outside of the crash dump code. Signed-off-by: Ian Campbell --- linux-2.6-xen-sparse/include/asm-i386/kexec.h | 3 + ...h-kernels-to-handle-x86_64-dumps-fix.patch | 30 +++++++++ ...crash-kernels-to-handle-x86_64-dumps.patch | 66 +++++++++++++++++++ .../linux-2.6.18/crash-kernel-32-on-64.patch | 11 ---- patches/linux-2.6.18/series | 3 +- 5 files changed, 101 insertions(+), 12 deletions(-) create mode 100644 patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps-fix.patch create mode 100644 patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps.patch delete mode 100644 patches/linux-2.6.18/crash-kernel-32-on-64.patch diff --git a/linux-2.6-xen-sparse/include/asm-i386/kexec.h b/linux-2.6-xen-sparse/include/asm-i386/kexec.h index 4610897c78..abddf7b4d2 100644 --- a/linux-2.6-xen-sparse/include/asm-i386/kexec.h +++ b/linux-2.6-xen-sparse/include/asm-i386/kexec.h @@ -47,6 +47,9 @@ /* The native architecture */ #define KEXEC_ARCH KEXEC_ARCH_386 +/* We can also handle crash dumps from 64 bit kernel. */ +#define vmcore_elf_check_arch_cross(x) ((x)->e_machine == EM_X86_64) + #define MAX_NOTE_BYTES 1024 /* CPU does not save ss and esp on stack if execution is already diff --git a/patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps-fix.patch b/patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps-fix.patch new file mode 100644 index 0000000000..2d60059ca7 --- /dev/null +++ b/patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps-fix.patch @@ -0,0 +1,30 @@ +From: Andrew Morton + +In file included from arch/i386/kernel/setup.c:46: +include/linux/crash_dump.h:19:36: warning: extra tokens at end of #ifndef directive + +Cc: "Eric W. Biederman" +Cc: Andi Kleen +Cc: Horms +Cc: Ian Campbell +Cc: Magnus Damm +Cc: Vivek Goyal +Signed-off-by: Andrew Morton +--- + + include/linux/crash_dump.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff -puN include/linux/crash_dump.h~allow-i386-crash-kernels-to-handle-x86_64-dumps-fix include/linux/crash_dump.h +--- a/include/linux/crash_dump.h~allow-i386-crash-kernels-to-handle-x86_64-dumps-fix ++++ a/include/linux/crash_dump.h +@@ -16,7 +16,7 @@ extern struct proc_dir_entry *proc_vmcor + + /* Architecture code defines this if there are other possible ELF + * machine types, e.g. on bi-arch capable hardware. */ +-#ifndef vmcore_elf_check_arch_cross(x) ++#ifndef vmcore_elf_check_arch_cross + #define vmcore_elf_check_arch_cross(x) 0 + #endif + +_ diff --git a/patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps.patch b/patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps.patch new file mode 100644 index 0000000000..ad9eb93b3b --- /dev/null +++ b/patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps.patch @@ -0,0 +1,66 @@ +From: Ian Campbell + +The specific case I am encountering is kdump under Xen with a 64 bit +hypervisor and 32 bit kernel/userspace. The dump created is 64 bit due to +the hypervisor but the dump kernel is 32 bit for maximum compatibility. + +It's possibly less likely to be useful in a purely native scenario but I +see no reason to disallow it. + +Signed-off-by: Ian Campbell +Acked-by: Vivek Goyal +Cc: Horms +Cc: Magnus Damm +Cc: "Eric W. Biederman" +Cc: Andi Kleen +Signed-off-by: Andrew Morton +--- + + fs/proc/vmcore.c | 2 +- + include/asm-i386/kexec.h | 3 +++ + include/linux/crash_dump.h | 8 ++++++++ + 3 files changed, 12 insertions(+), 1 deletion(-) + +diff -puN fs/proc/vmcore.c~allow-i386-crash-kernels-to-handle-x86_64-dumps fs/proc/vmcore.c +--- a/fs/proc/vmcore.c~allow-i386-crash-kernels-to-handle-x86_64-dumps ++++ a/fs/proc/vmcore.c +@@ -514,7 +514,7 @@ static int __init parse_crash_elf64_head + /* Do some basic Verification. */ + if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 || + (ehdr.e_type != ET_CORE) || +- !elf_check_arch(&ehdr) || ++ !vmcore_elf_check_arch(&ehdr) || + ehdr.e_ident[EI_CLASS] != ELFCLASS64 || + ehdr.e_ident[EI_VERSION] != EV_CURRENT || + ehdr.e_version != EV_CURRENT || +diff -puN include/asm-i386/kexec.h~allow-i386-crash-kernels-to-handle-x86_64-dumps include/asm-i386/kexec.h +--- a/include/asm-i386/kexec.h~allow-i386-crash-kernels-to-handle-x86_64-dumps ++++ a/include/asm-i386/kexec.h +@@ -47,6 +47,9 @@ + /* The native architecture */ + #define KEXEC_ARCH KEXEC_ARCH_386 + ++/* We can also handle crash dumps from 64 bit kernel. */ ++#define vmcore_elf_check_arch_cross(x) ((x)->e_machine == EM_X86_64) ++ + #define MAX_NOTE_BYTES 1024 + + /* CPU does not save ss and esp on stack if execution is already +diff -puN include/linux/crash_dump.h~allow-i386-crash-kernels-to-handle-x86_64-dumps include/linux/crash_dump.h +--- a/include/linux/crash_dump.h~allow-i386-crash-kernels-to-handle-x86_64-dumps ++++ a/include/linux/crash_dump.h +@@ -14,5 +14,13 @@ extern ssize_t copy_oldmem_page(unsigned + extern const struct file_operations proc_vmcore_operations; + extern struct proc_dir_entry *proc_vmcore; + ++/* Architecture code defines this if there are other possible ELF ++ * machine types, e.g. on bi-arch capable hardware. */ ++#ifndef vmcore_elf_check_arch_cross(x) ++#define vmcore_elf_check_arch_cross(x) 0 ++#endif ++ ++#define vmcore_elf_check_arch(x) (elf_check_arch(x) || vmcore_elf_check_arch_cross(x)) ++ + #endif /* CONFIG_CRASH_DUMP */ + #endif /* LINUX_CRASHDUMP_H */ +_ diff --git a/patches/linux-2.6.18/crash-kernel-32-on-64.patch b/patches/linux-2.6.18/crash-kernel-32-on-64.patch deleted file mode 100644 index 8ea9378188..0000000000 --- a/patches/linux-2.6.18/crash-kernel-32-on-64.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- pristine-linux-2.6.18/include/asm-i386/elf.h 2006-09-20 04:42:06.000000000 +0100 -+++ linux-2.6.18-xen/include/asm-i386/elf.h 2007-03-14 16:42:30.000000000 +0000 -@@ -36,7 +36,7 @@ - * This is used to ensure we don't load something for the wrong architecture. - */ - #define elf_check_arch(x) \ -- (((x)->e_machine == EM_386) || ((x)->e_machine == EM_486)) -+ (((x)->e_machine == EM_386) || ((x)->e_machine == EM_486) || ((x)->e_machine == EM_X86_64)) - - /* - * These are used to set parameters in the core dumps. diff --git a/patches/linux-2.6.18/series b/patches/linux-2.6.18/series index 978fdacc42..a3597cd5a0 100644 --- a/patches/linux-2.6.18/series +++ b/patches/linux-2.6.18/series @@ -19,4 +19,5 @@ x86-elfnote-as-preprocessor-macro.patch fixaddr-top.patch git-c06cb8b1c4d25e5b4d7a2d7c2462619de1e0dbc4.patch softlockup-no-idle-hz.patch -crash-kernel-32-on-64.patch +allow-i386-crash-kernels-to-handle-x86_64-dumps.patch +allow-i386-crash-kernels-to-handle-x86_64-dumps-fix.patch From 0389938d6e1e0454c33e2a2f3c066f2ccefcb11d Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Mon, 19 Mar 2007 14:46:51 +0000 Subject: [PATCH 148/170] Only import xenapi_create when using the Xen-API server -- this has additional dependencies that we don't want to require in legacy mode. Signed-off-by: Ewan Mellor --- tools/python/xen/xm/create.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index 6a4795d2ed..1af0fbefd7 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -35,7 +35,6 @@ from xen.xend.XendBootloader import bootloader from xen.util import blkif from xen.util import security from xen.xm.main import serverType, SERVER_XEN_API, get_single_vm -from xen.xm.xenapi_create import sxp2xml, xenapi_create from xen.xm.opts import * @@ -1249,6 +1248,7 @@ def main(argv): raise OptionError("Cannot read file %s: %s" % (config, exn[1])) if serverType == SERVER_XEN_API: + from xen.xm.xenapi_create import sxp2xml sxp2xml_inst = sxp2xml() doc = sxp2xml_inst.convert_sxp_to_xml(config, transient=True) @@ -1266,6 +1266,7 @@ def main(argv): do_console(sxp.child_value(config, 'name', -1)) if serverType == SERVER_XEN_API: + from xen.xm.xenapi_create import xenapi_create xenapi_create_inst = xenapi_create() vm_refs = xenapi_create_inst.create(document = doc) From b81cb0e6ae47ee9885ac2bfc006c6e5162d76cae Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Mon, 19 Mar 2007 16:28:24 +0000 Subject: [PATCH 149/170] [SVM] Move vmcb setup code for AP bringup out of the launch path and into the earlier AP bringup code. This stops it from resetting the VCPUs of SMP guests into real mode on restore or migrate. Signed-off-by: Tim Deegan --- xen/arch/x86/hvm/svm/svm.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index e4268dafd7..2b5b735499 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -749,6 +749,14 @@ static void svm_set_tsc_offset(struct vcpu *v, u64 offset) static void svm_init_ap_context( struct vcpu_guest_context *ctxt, int vcpuid, int trampoline_vector) { + struct vcpu *v; + cpu_user_regs_t *regs; + u16 cs_sel; + + /* We know this is safe because hvm_bringup_ap() does it */ + v = current->domain->vcpu[vcpuid]; + regs = &v->arch.guest_context.user_regs; + memset(ctxt, 0, sizeof(*ctxt)); /* @@ -756,8 +764,19 @@ static void svm_init_ap_context( * passed to us is page alligned and is the physicall frame number for * the code. We will execute this code in real mode. */ + cs_sel = trampoline_vector << 8; ctxt->user_regs.eip = 0x0; - ctxt->user_regs.cs = (trampoline_vector << 8); + ctxt->user_regs.cs = cs_sel; + + /* + * This is the launch of an AP; set state so that we begin executing + * the trampoline code in real-mode. + */ + svm_do_vmmcall_reset_to_realmode(v, regs); + /* Adjust the vmcb's hidden register state. */ + v->arch.hvm_svm.vmcb->rip = 0; + v->arch.hvm_svm.vmcb->cs.sel = cs_sel; + v->arch.hvm_svm.vmcb->cs.base = (cs_sel << 4); } static void svm_init_hypercall_page(struct domain *d, void *hypercall_page) @@ -910,21 +929,6 @@ static void arch_svm_do_launch(struct vcpu *v) v->arch.hvm_svm.vmcb->h_cr3 = pagetable_get_paddr(v->domain->arch.phys_table); } - if ( v->vcpu_id != 0 ) - { - cpu_user_regs_t *regs = ¤t->arch.guest_context.user_regs; - u16 cs_sel = regs->cs; - /* - * This is the launch of an AP; set state so that we begin executing - * the trampoline code in real-mode. - */ - svm_do_vmmcall_reset_to_realmode(v, regs); - /* Adjust the state to execute the trampoline code.*/ - v->arch.hvm_svm.vmcb->rip = 0; - v->arch.hvm_svm.vmcb->cs.sel= cs_sel; - v->arch.hvm_svm.vmcb->cs.base = (cs_sel << 4); - } - reset_stack_and_jump(svm_asm_do_launch); } From 28f7888d7fc4aa75135ac1c566566eda1704db65 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Mon, 19 Mar 2007 16:48:24 +0000 Subject: [PATCH 150/170] hvm: Do not save/restore shared_info gpfn location. Instead of kludging a max_gpfn estimate in shared_info, add a new XENMEM command to discover the actual maximum gpfn value as known by the shadow code. This needs to be more robust when we support HVM ballooning in future anyway. One interesting point is that max_gpfn may be close to 4GB even for small-memory HVM guests since for example SVGA LFB is mapped into the I/O hole. We may need to special case the I/O hole somehow, or provide some finer-grained way to find out which parts of the GPFN space are actually used (e.g., get Xen to fill in a bitmap with 1 bit per 1024 pages, or similar). Signed-off-by: Keir Fraser --- tools/libxc/xc_core_x86.c | 24 +++++++++++------------- tools/libxc/xc_hvm_build.c | 1 - tools/libxc/xc_hvm_restore.c | 31 ------------------------------- tools/libxc/xc_hvm_save.c | 30 +----------------------------- tools/libxc/xc_private.c | 14 ++++++++++++++ xen/arch/x86/mm.c | 6 ++++++ xen/arch/x86/mm/shadow/common.c | 6 +++--- xen/common/compat/memory.c | 2 ++ xen/common/memory.c | 15 ++++++++++++++- xen/include/asm-ia64/mm.h | 2 ++ xen/include/asm-powerpc/mm.h | 2 ++ xen/include/asm-x86/mm.h | 1 + xen/include/public/memory.h | 5 +++++ 13 files changed, 61 insertions(+), 78 deletions(-) diff --git a/tools/libxc/xc_core_x86.c b/tools/libxc/xc_core_x86.c index 6ea775aef6..bd82110713 100644 --- a/tools/libxc/xc_core_x86.c +++ b/tools/libxc/xc_core_x86.c @@ -21,12 +21,15 @@ #include "xg_private.h" #include "xc_core.h" +static int max_gpfn(int xc_handle, domid_t domid) +{ + return xc_memory_op(xc_handle, XENMEM_maximum_gpfn, &domid); +} + int xc_core_arch_auto_translated_physmap(const xc_dominfo_t *info) { - if ( info->hvm ) - return 1; - return 0; + return info->hvm; } int @@ -35,14 +38,14 @@ xc_core_arch_memory_map_get(int xc_handle, xc_dominfo_t *info, xc_core_memory_map_t **mapp, unsigned int *nr_entries) { - unsigned long max_pfn = live_shinfo->arch.max_pfn; - xc_core_memory_map_t *map = NULL; + unsigned long max_pfn = max_gpfn(xc_handle, info->domid); + xc_core_memory_map_t *map; map = malloc(sizeof(*map)); - if ( !map ) + if ( map == NULL ) { PERROR("Could not allocate memory"); - goto out; + return -1; } map->addr = 0; @@ -51,11 +54,6 @@ xc_core_arch_memory_map_get(int xc_handle, xc_dominfo_t *info, *mapp = map; *nr_entries = 1; return 0; - -out: - if ( map ) - free(map); - return -1; } int @@ -67,7 +65,7 @@ xc_core_arch_map_p2m(int xc_handle, xc_dominfo_t *info, xen_pfn_t *live_p2m_frame_list_list = NULL; xen_pfn_t *live_p2m_frame_list = NULL; uint32_t dom = info->domid; - unsigned long max_pfn = live_shinfo->arch.max_pfn; + unsigned long max_pfn = max_gpfn(xc_handle, info->domid); int ret = -1; int err; diff --git a/tools/libxc/xc_hvm_build.c b/tools/libxc/xc_hvm_build.c index 4b23e9fdb1..751aa9cf7a 100644 --- a/tools/libxc/xc_hvm_build.c +++ b/tools/libxc/xc_hvm_build.c @@ -286,7 +286,6 @@ static int setup_guest(int xc_handle, /* NB. evtchn_upcall_mask is unused: leave as zero. */ memset(&shared_info->evtchn_mask[0], 0xff, sizeof(shared_info->evtchn_mask)); - shared_info->arch.max_pfn = page_array[nr_pages - 1]; munmap(shared_info, PAGE_SIZE); if ( v_end > HVM_BELOW_4G_RAM_END ) diff --git a/tools/libxc/xc_hvm_restore.c b/tools/libxc/xc_hvm_restore.c index 0dafa82874..4b54b0aaf5 100644 --- a/tools/libxc/xc_hvm_restore.c +++ b/tools/libxc/xc_hvm_restore.c @@ -70,9 +70,6 @@ int xc_hvm_restore(int xc_handle, int io_fd, { DECLARE_DOMCTL; - /* The new domain's shared-info frame number. */ - unsigned long shared_info_frame; - /* A copy of the CPU context of the guest. */ vcpu_guest_context_t ctxt; @@ -86,8 +83,6 @@ int xc_hvm_restore(int xc_handle, int io_fd, uint8_t *hvm_buf = NULL; unsigned long long v_end, memsize; unsigned long shared_page_nr; - shared_info_t *shared_info = NULL; - xen_pfn_t arch_max_pfn; unsigned long pfn; unsigned int prev_pc, this_pc; @@ -96,8 +91,6 @@ int xc_hvm_restore(int xc_handle, int io_fd, /* Types of the pfns in the current region */ unsigned long region_pfn_type[MAX_BATCH_SIZE]; - struct xen_add_to_physmap xatp; - /* Number of pages of memory the guest has. *Not* the same as max_pfn. */ unsigned long nr_pages; @@ -146,7 +139,6 @@ int xc_hvm_restore(int xc_handle, int io_fd, pfns[i] = i; for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < pfn_array_size; i++ ) pfns[i] += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT; - arch_max_pfn = pfns[max_pfn];/* used later */ /* Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. */ rc = xc_domain_memory_populate_physmap( @@ -350,29 +342,6 @@ int xc_hvm_restore(int xc_handle, int io_fd, goto out; } - /* Shared-info pfn */ - if (!read_exact(io_fd, &(shared_info_frame), sizeof(uint32_t)) ) { - ERROR("reading the shared-info pfn failed!\n"); - goto out; - } - /* Map the shared-info frame where it was before */ - xatp.domid = dom; - xatp.space = XENMAPSPACE_shared_info; - xatp.idx = 0; - xatp.gpfn = shared_info_frame; - if ( (rc = xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp)) != 0 ) { - ERROR("setting the shared-info pfn failed!\n"); - goto out; - } - if ( (xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp) != 0) || - ((shared_info = xc_map_foreign_range( - xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, - shared_info_frame)) == NULL) ) - goto out; - /* shared_info.arch.max_pfn is used by dump-core */ - shared_info->arch.max_pfn = arch_max_pfn; - munmap(shared_info, PAGE_SIZE); - rc = 0; goto out; diff --git a/tools/libxc/xc_hvm_save.c b/tools/libxc/xc_hvm_save.c index 54a3897ce5..75a017cf7c 100644 --- a/tools/libxc/xc_hvm_save.c +++ b/tools/libxc/xc_hvm_save.c @@ -302,9 +302,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, /* The size of an array big enough to contain all guest pfns */ unsigned long pfn_array_size; - /* The new domain's shared-info frame number. */ - unsigned long shared_info_frame; - /* Other magic frames: ioreqs and xenstore comms */ unsigned long ioreq_pfn, bufioreq_pfn, store_pfn; @@ -318,9 +315,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, uint32_t hvm_buf_size; uint8_t *hvm_buf = NULL; - /* Live mapping of shared info structure */ - shared_info_t *live_shinfo = NULL; - /* base of the region in which domain memory is mapped */ unsigned char *region_base = NULL; @@ -372,7 +366,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, ERROR("HVM:Could not get vcpu context"); goto out; } - shared_info_frame = info.shared_info_frame; /* cheesy sanity check */ if ((info.max_memkb >> (PAGE_SHIFT - 10)) > max_mfn) { @@ -381,13 +374,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } - /* Map the shared info frame */ - if(!(live_shinfo = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, - PROT_READ, shared_info_frame))) { - ERROR("HVM:Couldn't map live_shinfo"); - goto out; - } - if ( xc_get_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, &store_pfn) || xc_get_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, &ioreq_pfn) || xc_get_hvm_param(xc_handle, dom, @@ -525,13 +511,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, DPRINTF("Saving HVM domain memory pages: iter %d 0%%", iter); - if (last_iter && (max_pfn != live_shinfo->arch.max_pfn)) { - DPRINTF("calculated max_pfn as %#lx, shinfo says %#lx\n", - max_pfn, live_shinfo->arch.max_pfn); - ERROR("Max pfn doesn't match shared info"); - goto out; - } - while( N < pfn_array_size ){ unsigned int this_pc = (N * 100) / pfn_array_size; @@ -679,8 +658,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } - DPRINTF("SUSPEND shinfo %08lx eip %08lx edx %08lx\n", - info.shared_info_frame, + DPRINTF("SUSPEND eip %08lx edx %08lx\n", (unsigned long)ctxt.user_regs.eip, (unsigned long)ctxt.user_regs.edx); } @@ -768,12 +746,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, ERROR("write HVM info failed!\n"); } - /* Shared-info pfn */ - if (!write_exact(io_fd, &(shared_info_frame), sizeof(uint32_t)) ) { - ERROR("write shared-info pfn failed!\n"); - goto out; - } - /* Success! */ rc = 0; diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c index 3816b0a83b..3e2557e581 100644 --- a/tools/libxc/xc_private.c +++ b/tools/libxc/xc_private.c @@ -263,6 +263,15 @@ int xc_memory_op(int xc_handle, goto out1; } break; + case XENMEM_current_reservation: + case XENMEM_maximum_reservation: + case XENMEM_maximum_gpfn: + if ( lock_pages(arg, sizeof(domid_t)) ) + { + PERROR("Could not lock"); + goto out1; + } + break; } ret = do_xen_hypercall(xc_handle, &hypercall); @@ -287,6 +296,11 @@ int xc_memory_op(int xc_handle, case XENMEM_add_to_physmap: unlock_pages(arg, sizeof(struct xen_add_to_physmap)); break; + case XENMEM_current_reservation: + case XENMEM_maximum_reservation: + case XENMEM_maximum_gpfn: + unlock_pages(arg, sizeof(domid_t)); + break; } out1: diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 1c65070d15..e0590f33a2 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -108,6 +108,7 @@ #include #include #include +#include #include #define MEM_LOG(_f, _a...) gdprintk(XENLOG_WARNING , _f "\n" , ## _a) @@ -246,6 +247,11 @@ int memory_is_conventional_ram(paddr_t p) return 0; } +unsigned long domain_get_maximum_gpfn(struct domain *d) +{ + return is_hvm_domain(d) ? d->arch.p2m.max_mapped_pfn : arch_get_max_pfn(d); +} + void share_xen_page_with_guest( struct page_info *page, struct domain *d, int readonly) { diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c index 15ebf1d541..efabba8223 100644 --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -36,7 +36,6 @@ #include #include #include -#include #include "private.h" @@ -2672,7 +2671,7 @@ sh_alloc_log_dirty_bitmap(struct domain *d) { ASSERT(d->arch.paging.shadow.dirty_bitmap == NULL); d->arch.paging.shadow.dirty_bitmap_size = - (arch_get_max_pfn(d) + (BITS_PER_LONG - 1)) & + (domain_get_maximum_gpfn(d) + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1); d->arch.paging.shadow.dirty_bitmap = xmalloc_array(unsigned long, @@ -2682,7 +2681,8 @@ sh_alloc_log_dirty_bitmap(struct domain *d) d->arch.paging.shadow.dirty_bitmap_size = 0; return -ENOMEM; } - memset(d->arch.paging.shadow.dirty_bitmap, 0, d->arch.paging.shadow.dirty_bitmap_size/8); + memset(d->arch.paging.shadow.dirty_bitmap, 0, + d->arch.paging.shadow.dirty_bitmap_size/8); return 0; } diff --git a/xen/common/compat/memory.c b/xen/common/compat/memory.c index 1301e42f04..53628d7a35 100644 --- a/xen/common/compat/memory.c +++ b/xen/common/compat/memory.c @@ -170,6 +170,7 @@ int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE(void) compat) case XENMEM_current_reservation: case XENMEM_maximum_reservation: + case XENMEM_maximum_gpfn: { #define xen_domid_t domid_t #define compat_domid_t domid_compat_t @@ -325,6 +326,7 @@ int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE(void) compat) case XENMEM_maximum_ram_page: case XENMEM_current_reservation: case XENMEM_maximum_reservation: + case XENMEM_maximum_gpfn: break; case XENMEM_translate_gpfn_list: diff --git a/xen/common/memory.c b/xen/common/memory.c index f7e5efc0a5..edd2ebe8d5 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -584,6 +584,7 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg) case XENMEM_current_reservation: case XENMEM_maximum_reservation: + case XENMEM_maximum_gpfn: if ( copy_from_guest(&domid, arg, 1) ) return -EFAULT; @@ -594,7 +595,19 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg) else if ( (d = rcu_lock_domain_by_id(domid)) == NULL ) return -ESRCH; - rc = (op == XENMEM_current_reservation) ? d->tot_pages : d->max_pages; + switch ( op ) + { + case XENMEM_current_reservation: + rc = d->tot_pages; + break; + case XENMEM_maximum_reservation: + rc = d->max_pages; + break; + default: + ASSERT(op == XENMEM_maximum_gpfn); + rc = domain_get_maximum_gpfn(d); + break; + } if ( unlikely(domid != DOMID_SELF) ) rcu_unlock_domain(d); diff --git a/xen/include/asm-ia64/mm.h b/xen/include/asm-ia64/mm.h index fa0830d414..057f841c16 100644 --- a/xen/include/asm-ia64/mm.h +++ b/xen/include/asm-ia64/mm.h @@ -511,4 +511,6 @@ int steal_page( #define domain_clamp_alloc_bitsize(d, b) (b) +#define domain_get_maximum_gpfn(d) (-ENOSYS) + #endif /* __ASM_IA64_MM_H__ */ diff --git a/xen/include/asm-powerpc/mm.h b/xen/include/asm-powerpc/mm.h index e258d5eb1b..ed6a10c67b 100644 --- a/xen/include/asm-powerpc/mm.h +++ b/xen/include/asm-powerpc/mm.h @@ -278,4 +278,6 @@ extern int steal_page(struct domain *d, struct page_info *page, #define domain_clamp_alloc_bitsize(d, b) (b) +#define domain_get_maximum_gpfn(d) (-ENOSYS) + #endif diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h index b240e4b5ca..225605efd4 100644 --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -404,5 +404,6 @@ unsigned int domain_clamp_alloc_bitsize(struct domain *d, unsigned int bits); # define domain_clamp_alloc_bitsize(d, b) (b) #endif +unsigned long domain_get_maximum_gpfn(struct domain *d); #endif /* __ASM_X86_MM_H__ */ diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h index 97a6bbfea2..7b1ef44d32 100644 --- a/xen/include/public/memory.h +++ b/xen/include/public/memory.h @@ -128,6 +128,11 @@ DEFINE_XEN_GUEST_HANDLE(xen_memory_exchange_t); #define XENMEM_current_reservation 3 #define XENMEM_maximum_reservation 4 +/* + * Returns the maximum GPFN in use by the guest, or -ve errcode on failure. + */ +#define XENMEM_maximum_gpfn 14 + /* * Returns a list of MFN bases of 2MB extents comprising the machine_to_phys * mapping table. Architectures which do not have a m2p table do not implement From 49a55b0fb3319c7374ec5846f3f2e1fd2da46c16 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Mon, 19 Mar 2007 16:55:21 +0000 Subject: [PATCH 151/170] coredump: Allow mmap of shinfo to fail for any HVM guest (x86 or ia64). Signed-off-by: Keir Fraser --- tools/libxc/xc_core.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tools/libxc/xc_core.c b/tools/libxc/xc_core.c index 3dcf51e131..3c1ff185a6 100644 --- a/tools/libxc/xc_core.c +++ b/tools/libxc/xc_core.c @@ -349,11 +349,7 @@ xc_domain_dumpcore_via_callback(int xc_handle, /* Map the shared info frame */ live_shinfo = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, PROT_READ, info.shared_info_frame); - if ( !live_shinfo -#ifdef __ia64__ - && !info.hvm -#endif - ) + if ( !live_shinfo && !info.hvm ) { PERROR("Couldn't map live_shinfo"); goto out; From b43e569511ca459d28f0618e05d0ade762626555 Mon Sep 17 00:00:00 2001 From: Mark McLoughlin Date: Tue, 20 Mar 2007 11:10:52 +0000 Subject: [PATCH 152/170] Don't mount raw blktap disks for pygrub Currently, we mount all blktap disks for pygrub so that it can boot from e.g. QCOW images. However, since pygrub will handle a raw image just fine without mounting through blktap, we shouldn't bother in that case. Also, it looks like XendDomainInfo.create_vbd() takes the full disk uname rather than the image path. Signed-off-by: Mark McLoughlin --- tools/python/xen/util/blkif.py | 17 ++++++++++++----- tools/python/xen/xend/XendDomainInfo.py | 7 ++++--- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/tools/python/xen/util/blkif.py b/tools/python/xen/util/blkif.py index 363bd41dd2..15d20dde8c 100644 --- a/tools/python/xen/util/blkif.py +++ b/tools/python/xen/util/blkif.py @@ -66,16 +66,23 @@ def blkdev_segment(name): 'type' : 'Disk' } return val -def blkdev_uname_to_file(uname): - """Take a blkdev uname and return the corresponding filename.""" - fn = None +def _parse_uname(uname): + fn = taptype = None if uname.find(":") != -1: (typ, fn) = uname.split(":", 1) if typ == "phy" and not fn.startswith("/"): fn = "/dev/%s" %(fn,) if typ == "tap": - (typ, fn) = fn.split(":", 1) - return fn + (taptype, fn) = fn.split(":", 1) + return (fn, taptype) + +def blkdev_uname_to_file(uname): + """Take a blkdev uname and return the corresponding filename.""" + return _parse_uname(uname)[0] + +def blkdev_uname_to_taptype(uname): + """Take a blkdev uname and return the blktap type.""" + return _parse_uname(uname)[1] def mount_mode(name): mode = None diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index da3e5936a3..99c3ddd425 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -34,7 +34,7 @@ from types import StringTypes import xen.lowlevel.xc from xen.util import asserts -from xen.util.blkif import blkdev_uname_to_file +from xen.util.blkif import blkdev_uname_to_file, blkdev_uname_to_taptype from xen.util import security from xen.xend import balloon, sxp, uuid, image, arch, osdep @@ -1786,7 +1786,8 @@ class XendDomainInfo: disk = devinfo[1]['uname'] fn = blkdev_uname_to_file(disk) - mounted = devtype == 'tap' and not os.stat(fn).st_rdev + taptype = blkdev_uname_to_taptype(disk) + mounted = devtype == 'tap' and taptype != 'aio' and taptype != 'sync' and not os.stat(fn).st_rdev if mounted: # This is a file, not a device. pygrub can cope with a # file if it's raw, but if it's QCOW or other such formats @@ -1802,7 +1803,7 @@ class XendDomainInfo: from xen.xend import XendDomain dom0 = XendDomain.instance().privilegedDomain() - dom0._waitForDeviceUUID(dom0.create_vbd(vbd, fn)) + dom0._waitForDeviceUUID(dom0.create_vbd(vbd, disk)) fn = BOOTLOADER_LOOPBACK_DEVICE try: From 4a4e26f321bd83353175cedf8a35706e93c77b30 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Tue, 20 Mar 2007 11:28:45 +0000 Subject: [PATCH 153/170] svm: Remove special 'launch' scheduler tail function. Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/svm/svm.c | 52 +++++++++++------------------ xen/arch/x86/hvm/svm/vmcb.c | 14 ++------ xen/arch/x86/hvm/svm/x86_32/exits.S | 40 ++++++++-------------- xen/arch/x86/hvm/svm/x86_64/exits.S | 34 +++++++------------ xen/include/asm-x86/hvm/svm/svm.h | 2 -- xen/include/asm-x86/hvm/svm/vmcb.h | 2 +- 6 files changed, 48 insertions(+), 96 deletions(-) diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index 2b5b735499..abff76a2b8 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -485,7 +485,6 @@ int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c) * first. */ HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 c->cr3 = %"PRIx64"", c->cr3); - /* current!=vcpu as not called by arch_vmx_do_launch */ mfn = gmfn_to_mfn(v->domain, c->cr3 >> PAGE_SHIFT); if( !mfn_valid(mfn) || !get_page(mfn_to_page(mfn), v->domain) ) goto bad_cr3; @@ -921,17 +920,6 @@ static void svm_load_cpu_guest_regs( svm_load_cpu_user_regs(v, regs); } -static void arch_svm_do_launch(struct vcpu *v) -{ - svm_do_launch(v); - - if ( paging_mode_hap(v->domain) ) { - v->arch.hvm_svm.vmcb->h_cr3 = pagetable_get_paddr(v->domain->arch.phys_table); - } - - reset_stack_and_jump(svm_asm_do_launch); -} - static void svm_ctxt_switch_from(struct vcpu *v) { svm_save_dr(v); @@ -953,16 +941,30 @@ static void svm_ctxt_switch_to(struct vcpu *v) svm_restore_dr(v); } +static void arch_svm_do_resume(struct vcpu *v) +{ + if ( v->arch.hvm_svm.launch_core != smp_processor_id() ) + { + v->arch.hvm_svm.launch_core = smp_processor_id(); + hvm_migrate_timers(v); + } + + hvm_do_resume(v); + reset_stack_and_jump(svm_asm_do_resume); +} + static int svm_vcpu_initialise(struct vcpu *v) { int rc; - v->arch.schedule_tail = arch_svm_do_launch; + v->arch.schedule_tail = arch_svm_do_resume; v->arch.ctxt_switch_from = svm_ctxt_switch_from; v->arch.ctxt_switch_to = svm_ctxt_switch_to; v->arch.hvm_svm.saved_irq_vector = -1; + v->arch.hvm_svm.launch_core = -1; + if ( (rc = svm_create_vmcb(v)) != 0 ) { dprintk(XENLOG_WARNING, @@ -1026,10 +1028,12 @@ void svm_npt_detect(void) /* check CPUID for nested paging support */ cpuid(0x8000000A, &eax, &ebx, &ecx, &edx); - if ( edx & 0x01 ) { /* nested paging */ + if ( edx & 0x01 ) /* nested paging */ + { hap_capable_system = 1; } - else if ( opt_hap_enabled ) { + else if ( opt_hap_enabled ) + { printk(" nested paging is not supported by this CPU.\n"); hap_capable_system = 0; /* no nested paging, we disable flag. */ } @@ -1087,24 +1091,6 @@ int start_svm(void) return 1; } -void arch_svm_do_resume(struct vcpu *v) -{ - /* pinning VCPU to a different core? */ - if ( v->arch.hvm_svm.launch_core == smp_processor_id()) { - hvm_do_resume( v ); - reset_stack_and_jump( svm_asm_do_resume ); - } - else { - if (svm_dbg_on) - printk("VCPU core pinned: %d to %d\n", - v->arch.hvm_svm.launch_core, smp_processor_id() ); - v->arch.hvm_svm.launch_core = smp_processor_id(); - hvm_migrate_timers( v ); - hvm_do_resume( v ); - reset_stack_and_jump( svm_asm_do_resume ); - } -} - static int svm_do_nested_pgfault(paddr_t gpa, struct cpu_user_regs *regs) { if (mmio_space(gpa)) { diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c index 1d9c1569c3..446ddbb968 100644 --- a/xen/arch/x86/hvm/svm/vmcb.c +++ b/xen/arch/x86/hvm/svm/vmcb.c @@ -196,11 +196,13 @@ static int construct_vmcb(struct vcpu *v) arch_svm->vmcb->exception_intercepts = MONITOR_DEFAULT_EXCEPTION_BITMAP; - if ( paging_mode_hap(v->domain) ) { + if ( paging_mode_hap(v->domain) ) + { vmcb->cr0 = arch_svm->cpu_shadow_cr0; vmcb->np_enable = 1; /* enable nested paging */ vmcb->g_pat = 0x0007040600070406ULL; /* guest PAT */ vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_PG; + vmcb->h_cr3 = pagetable_get_paddr(v->domain->arch.phys_table); } return 0; @@ -247,16 +249,6 @@ void svm_destroy_vmcb(struct vcpu *v) arch_svm->vmcb = NULL; } -void svm_do_launch(struct vcpu *v) -{ - hvm_stts(v); - - /* current core is the one we intend to perform the VMRUN on */ - v->arch.hvm_svm.launch_core = smp_processor_id(); - - v->arch.schedule_tail = arch_svm_do_resume; -} - static void svm_dump_sel(char *name, svm_segment_register_t *s) { printk("%s: sel=0x%04x, attr=0x%04x, limit=0x%08x, base=0x%016llx\n", diff --git a/xen/arch/x86/hvm/svm/x86_32/exits.S b/xen/arch/x86/hvm/svm/x86_32/exits.S index c465e3b7fa..604fa94c9e 100644 --- a/xen/arch/x86/hvm/svm/x86_32/exits.S +++ b/xen/arch/x86/hvm/svm/x86_32/exits.S @@ -80,15 +80,24 @@ popl %eax; \ addl $(NR_SKIPPED_REGS*4), %esp - ALIGN - #define VMRUN .byte 0x0F,0x01,0xD8 #define VMLOAD .byte 0x0F,0x01,0xDA #define VMSAVE .byte 0x0F,0x01,0xDB #define STGI .byte 0x0F,0x01,0xDC #define CLGI .byte 0x0F,0x01,0xDD -ENTRY(svm_asm_do_launch) +ENTRY(svm_asm_do_resume) + GET_CURRENT(%ebx) + xorl %ecx,%ecx + notl %ecx + cli # tests must not race interrupts + movl VCPU_processor(%ebx),%eax + shl $IRQSTAT_shift,%eax + test %ecx,irq_stat(%eax,1) + jnz svm_process_softirqs + call svm_intr_assist + call svm_load_cr2 + CLGI sti GET_CURRENT(%ebx) @@ -134,31 +143,8 @@ svm_stgi_label: addl $4,%esp jmp svm_asm_do_resume - ALIGN - -ENTRY(svm_asm_do_resume) -svm_test_all_events: - GET_CURRENT(%ebx) -/*test_all_events:*/ - xorl %ecx,%ecx - notl %ecx - cli # tests must not race interrupts -/*test_softirqs:*/ - movl VCPU_processor(%ebx),%eax - shl $IRQSTAT_shift,%eax - test %ecx,irq_stat(%eax,1) - jnz svm_process_softirqs -svm_restore_all_guest: - call svm_intr_assist - call svm_load_cr2 - /* - * Check if we are going back to AMD-V based VM - * By this time, all the setups in the VMCB must be complete. - */ - jmp svm_asm_do_launch - ALIGN svm_process_softirqs: sti call do_softirq - jmp svm_test_all_events + jmp svm_asm_do_resume diff --git a/xen/arch/x86/hvm/svm/x86_64/exits.S b/xen/arch/x86/hvm/svm/x86_64/exits.S index 042cd6dc8e..cbff00cb5c 100644 --- a/xen/arch/x86/hvm/svm/x86_64/exits.S +++ b/xen/arch/x86/hvm/svm/x86_64/exits.S @@ -98,7 +98,17 @@ #define STGI .byte 0x0F,0x01,0xDC #define CLGI .byte 0x0F,0x01,0xDD -ENTRY(svm_asm_do_launch) +ENTRY(svm_asm_do_resume) + GET_CURRENT(%rbx) + cli # tests must not race interrupts + movl VCPU_processor(%rbx),%eax + shl $IRQSTAT_shift, %rax + leaq irq_stat(%rip), %rdx + testl $~0, (%rdx, %rax, 1) + jnz svm_process_softirqs + call svm_intr_assist + call svm_load_cr2 + CLGI sti GET_CURRENT(%rbx) @@ -150,28 +160,8 @@ svm_stgi_label: call svm_vmexit_handler jmp svm_asm_do_resume -ENTRY(svm_asm_do_resume) -svm_test_all_events: - GET_CURRENT(%rbx) -/*test_all_events:*/ - cli # tests must not race interrupts -/*test_softirqs:*/ - movl VCPU_processor(%rbx),%eax - shl $IRQSTAT_shift, %rax - leaq irq_stat(%rip), %rdx - testl $~0, (%rdx, %rax, 1) - jnz svm_process_softirqs -svm_restore_all_guest: - call svm_intr_assist - call svm_load_cr2 - /* - * Check if we are going back to AMD-V based VM - * By this time, all the setups in the VMCB must be complete. - */ - jmp svm_asm_do_launch - ALIGN svm_process_softirqs: sti call do_softirq - jmp svm_test_all_events + jmp svm_asm_do_resume diff --git a/xen/include/asm-x86/hvm/svm/svm.h b/xen/include/asm-x86/hvm/svm/svm.h index b72eff2bc9..12459c72ef 100644 --- a/xen/include/asm-x86/hvm/svm/svm.h +++ b/xen/include/asm-x86/hvm/svm/svm.h @@ -29,8 +29,6 @@ #include extern void svm_dump_vmcb(const char *from, struct vmcb_struct *vmcb); -extern void svm_do_launch(struct vcpu *v); -extern void arch_svm_do_resume(struct vcpu *v); extern u64 root_vmcb_pa[NR_CPUS]; diff --git a/xen/include/asm-x86/hvm/svm/vmcb.h b/xen/include/asm-x86/hvm/svm/vmcb.h index 9dff3e65af..efedf27ae9 100644 --- a/xen/include/asm-x86/hvm/svm/vmcb.h +++ b/xen/include/asm-x86/hvm/svm/vmcb.h @@ -447,7 +447,7 @@ struct arch_svm_struct { u32 *msrpm; u64 vmexit_tsc; /* tsc read at #VMEXIT. for TSC_OFFSET */ int saved_irq_vector; - u32 launch_core; + int launch_core; unsigned long flags; /* VMCB flags */ unsigned long cpu_shadow_cr0; /* Guest value for CR0 */ From 3e1b9525de43d644f132e0aa00cc519186c9f442 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Tue, 20 Mar 2007 14:33:15 +0000 Subject: [PATCH 154/170] [XEN] Implement faster int 0x80 handling for compat mode guests. Using the GPF handler to spot the software interrupt and pass it back to the guest increases the base syscall time by a factor of 2.7 compared with 32on32 using direct trap to ring 1. (0.3270->0.8680 microseconds, measured with lmbench lat_syscall). Since the 64 bit IDT can only contain 64 bit segment selectors we cannot trap directly to compat mode ring 1. However implementing a dedicated 64 bit ring 0 trap handler allows us to avoid much of the GPF handler overhead and reduces the overhead to 1.7 times (0.3270->0.5497 microseconds). Signed-off-by: Ian Campbell --- xen/arch/x86/x86_64/asm-offsets.c | 1 + xen/arch/x86/x86_64/compat/entry.S | 4 ++++ xen/arch/x86/x86_64/compat/traps.c | 4 ++++ xen/arch/x86/x86_64/entry.S | 30 ++++++++++++++++++++++++++++++ xen/arch/x86/x86_64/traps.c | 18 ++++++++++++++++++ xen/include/asm-x86/domain.h | 3 +++ xen/include/asm-x86/processor.h | 6 +++--- 7 files changed, 63 insertions(+), 3 deletions(-) diff --git a/xen/arch/x86/x86_64/asm-offsets.c b/xen/arch/x86/x86_64/asm-offsets.c index 001a781235..93a047db3a 100644 --- a/xen/arch/x86/x86_64/asm-offsets.c +++ b/xen/arch/x86/x86_64/asm-offsets.c @@ -59,6 +59,7 @@ void __dummy__(void) OFFSET(VCPU_domain, struct vcpu, domain); OFFSET(VCPU_vcpu_info, struct vcpu, vcpu_info); OFFSET(VCPU_trap_bounce, struct vcpu, arch.trap_bounce); + OFFSET(VCPU_int80_bounce, struct vcpu, arch.int80_bounce); OFFSET(VCPU_thread_flags, struct vcpu, arch.flags); OFFSET(VCPU_event_addr, struct vcpu, arch.guest_context.event_callback_eip); diff --git a/xen/arch/x86/x86_64/compat/entry.S b/xen/arch/x86/x86_64/compat/entry.S index 3f1d1b8d07..095bd61f73 100644 --- a/xen/arch/x86/x86_64/compat/entry.S +++ b/xen/arch/x86/x86_64/compat/entry.S @@ -187,6 +187,10 @@ ENTRY(compat_post_handle_exception) call compat_create_bounce_frame jmp compat_test_all_events +ENTRY(compat_int80_direct_trap) + call compat_create_bounce_frame + jmp compat_restore_all_guest + /* CREATE A BASIC EXCEPTION FRAME ON GUEST OS (RING-1) STACK: */ /* {[ERRCODE,] EIP, CS, EFLAGS, [ESP, SS]} */ /* %rdx: trap_bounce, %rbx: struct vcpu */ diff --git a/xen/arch/x86/x86_64/compat/traps.c b/xen/arch/x86/x86_64/compat/traps.c index a7f24cecf8..0172e846c4 100644 --- a/xen/arch/x86/x86_64/compat/traps.c +++ b/xen/arch/x86/x86_64/compat/traps.c @@ -1,6 +1,7 @@ #ifdef CONFIG_COMPAT #include +#include #include #include @@ -291,6 +292,9 @@ int compat_set_trap_table(XEN_GUEST_HANDLE(trap_info_compat_t) traps) XLAT_trap_info(dst + cur.vector, &cur); + if ( cur.vector == 0x80 ) + init_int80_direct_trap(current); + guest_handle_add_offset(traps, 1); } diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S index cffd89dced..17311c7242 100644 --- a/xen/arch/x86/x86_64/entry.S +++ b/xen/arch/x86/x86_64/entry.S @@ -222,6 +222,35 @@ bad_hypercall: movq $-ENOSYS,UREGS_rax(%rsp) jmp test_all_events +ENTRY(int80_direct_trap) + pushq $0 + SAVE_ALL + + GET_CURRENT(%rbx) + + /* Check that the callback is non-null. */ + leaq VCPU_int80_bounce(%rbx),%rdx + cmp $0, TRAPBOUNCE_flags(%rdx) + jz int80_slow_path + + movq VCPU_domain(%rbx),%rax + btl $_DOMF_compat,DOMAIN_domain_flags(%rax) + jc compat_int80_direct_trap + + call create_bounce_frame + jmp restore_all_guest + +int80_slow_path: + /* + * Setup entry vector and error code as if this was a GPF caused by an + * IDT entry with DPL==0. + */ + movl $((0x80 << 3) | 0x2),UREGS_error_code(%rsp) + movl $TRAP_gp_fault,UREGS_entry_vector(%rsp) + /* A GPF wouldn't have incremented the instruction pointer. */ + sub $2,UREGS_rip(%rsp) + jmp handle_exception_saved + /* CREATE A BASIC EXCEPTION FRAME ON GUEST OS STACK: */ /* { RCX, R11, [DS-GS,] [CR2,] [ERRCODE,] RIP, CS, RFLAGS, RSP, SS } */ /* %rdx: trap_bounce, %rbx: struct vcpu */ @@ -359,6 +388,7 @@ ENTRY(ret_from_intr) /* No special register assumptions. */ ENTRY(handle_exception) SAVE_ALL +handle_exception_saved: testb $X86_EFLAGS_IF>>8,UREGS_eflags+1(%rsp) jz exception_with_ints_disabled sti diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index 0c6ee1de35..7a255c291f 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -247,6 +247,7 @@ unsigned long do_iret(void) asmlinkage void syscall_enter(void); asmlinkage void compat_hypercall(void); +asmlinkage void int80_direct_trap(void); void __init percpu_traps_init(void) { char *stack_bottom, *stack; @@ -262,6 +263,7 @@ void __init percpu_traps_init(void) #ifdef CONFIG_COMPAT /* The hypercall entry vector is only accessible from ring 1. */ _set_gate(idt_table+HYPERCALL_VECTOR, 15, 1, &compat_hypercall); + _set_gate(idt_table+0x80, 15, 3, &int80_direct_trap); #endif } @@ -346,6 +348,22 @@ void __init percpu_traps_init(void) wrmsr(MSR_SYSCALL_MASK, EF_VM|EF_RF|EF_NT|EF_DF|EF_IE|EF_TF, 0U); } +void init_int80_direct_trap(struct vcpu *v) +{ + struct trap_info *ti = &v->arch.guest_context.trap_ctxt[0x80]; + struct trap_bounce *tb = &v->arch.int80_bounce; + + if ( !guest_gate_selector_okay(v->domain, ti->cs) ) + return; + + tb->flags = TBF_EXCEPTION; + tb->cs = ti->cs; + tb->eip = ti->address; + + if ( null_trap_bounce(v, tb) ) + tb->flags = 0; +} + static long register_guest_callback(struct callback_register *reg) { long ret = 0; diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index 6c88e5abb0..bdc2f16f12 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -248,6 +248,9 @@ struct arch_vcpu #ifdef CONFIG_X86_32 struct desc_struct int80_desc; #endif +#ifdef CONFIG_X86_64 + struct trap_bounce int80_bounce; +#endif /* Virtual Machine Extensions */ struct hvm_vcpu hvm_vcpu; diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h index 321219c853..a878d86303 100644 --- a/xen/include/asm-x86/processor.h +++ b/xen/include/asm-x86/processor.h @@ -455,16 +455,16 @@ extern idt_entry_t *idt_tables[]; extern struct tss_struct init_tss[NR_CPUS]; -#ifdef CONFIG_X86_32 - extern void init_int80_direct_trap(struct vcpu *v); + +#if defined(CONFIG_X86_32) + #define set_int80_direct_trap(_ed) \ (memcpy(idt_tables[(_ed)->processor] + 0x80, \ &((_ed)->arch.int80_desc), 8)) #else -#define init_int80_direct_trap(_ed) ((void)0) #define set_int80_direct_trap(_ed) ((void)0) #endif From a69027d8458a3fb770b9b26acff629fed0d9d524 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Tue, 20 Mar 2007 11:34:14 +0000 Subject: [PATCH 155/170] Improve the error diagnostics within xmlrpclib2 in order to be more defensive against internal errors. Signed-off-by: Tom Wilkie --- tools/python/xen/util/xmlrpclib2.py | 35 ++++++++++++++++------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/tools/python/xen/util/xmlrpclib2.py b/tools/python/xen/util/xmlrpclib2.py index 0d0f3ade20..bd3c2c98e6 100644 --- a/tools/python/xen/util/xmlrpclib2.py +++ b/tools/python/xen/util/xmlrpclib2.py @@ -227,24 +227,27 @@ class TCPXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer): response = xmlrpclib.dumps(response, methodresponse=1, allow_none=1) - except xmlrpclib.Fault, fault: - response = xmlrpclib.dumps(fault) except Exception, exn: - if self.xenapi: - if _is_not_supported(exn): - errdesc = ['MESSAGE_METHOD_UNKNOWN', method] + try: + if self.xenapi: + if _is_not_supported(exn): + errdesc = ['MESSAGE_METHOD_UNKNOWN', method] + else: + log.exception('Internal error handling %s', method) + errdesc = ['INTERNAL_ERROR', str(exn)] + + response = xmlrpclib.dumps( + ({ "Status": "Failure", + "ErrorDescription": errdesc },), + methodresponse = 1) else: log.exception('Internal error handling %s', method) - errdesc = ['INTERNAL_ERROR', str(exn)] - response = xmlrpclib.dumps( - ({ "Status": "Failure", - "ErrorDescription": errdesc },), - methodresponse = 1) - else: - log.exception('Internal error handling %s', method) - import xen.xend.XendClient - response = xmlrpclib.dumps( - xmlrpclib.Fault(xen.xend.XendClient.ERROR_INTERNAL, str(exn))) + import xen.xend.XendClient + response = xmlrpclib.dumps( + xmlrpclib.Fault(xen.xend.XendClient.ERROR_INTERNAL, str(exn))) + except: + log.exception('Internal error handling error') + return response @@ -253,7 +256,7 @@ def _is_not_supported(exn): try: m = notSupportedRE.search(exn[0]) return m is not None - except TypeError, e: + except: return False From ca1134470471220714c16e78149cdd10dab31966 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Tue, 20 Mar 2007 11:44:13 +0000 Subject: [PATCH 156/170] When creating a VBD, save the devid in the device info structure. If creation fails, remove the device config entry. Signed-off-by: Tom Wilkie --- tools/python/xen/xend/XendDomainInfo.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 99c3ddd425..a1d3c16f88 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -2301,12 +2301,21 @@ class XendDomainInfo: dev_control = None if vdi_image_path.startswith('tap'): - dev_control = self.getDeviceController('tap') + dev_control = self.getDeviceController('tap') else: dev_control = self.getDeviceController('vbd') - - config['devid'] = dev_control.createDevice(config) + try: + devid = dev_control.createDevice(config) + dev_control.waitForDevice(devid) + self.info.device_update(dev_uuid, + cfg_xenapi = {'devid': devid}) + except Exception, exn: + log.exception(exn) + del self.info['devices'][dev_uuid] + self.info['vbd_refs'].remove(dev_uuid) + raise + return dev_uuid def create_phantom_vbd_with_vdi(self, xenapi_vbd, vdi_image_path): From 26f758a7623083acd192f02b920b53f77738efb8 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Tue, 20 Mar 2007 11:45:44 +0000 Subject: [PATCH 157/170] Add VBD.runtime_properties dictionary, and use that to implement xm block-list through the Xen-API. Implement xm block-attach and xm block-detach also. Signed-off-by: Tom Wilkie --- tools/python/xen/xend/XendAPI.py | 61 +++++++++++++---- tools/python/xen/xend/XendVDI.py | 10 +++ tools/python/xen/xm/main.py | 99 +++++++++++++++++++++++----- tools/python/xen/xm/xenapi_create.py | 6 +- 4 files changed, 144 insertions(+), 32 deletions(-) diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index fa790fa75c..6d40c7f13b 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -36,6 +36,9 @@ from xen.xend.XendVMMetrics import XendVMMetrics from xen.xend.XendAPIConstants import * from xen.util.xmlrpclib2 import stringify +from xen.util.blkif import blkdev_name_to_number + + AUTH_NONE = 'none' AUTH_PAM = 'pam' @@ -1555,7 +1558,8 @@ class XendAPI(object): # Xen API: Class VBD # ---------------------------------------------------------------- - VBD_attr_ro = ['metrics'] + VBD_attr_ro = ['metrics', + 'runtime_properties'] VBD_attr_rw = ['VM', 'VDI', 'device', @@ -1596,23 +1600,28 @@ class XendAPI(object): # class methods def VBD_create(self, session, vbd_struct): xendom = XendDomain.instance() + xennode = XendNode.instance() + if not xendom.is_valid_vm(vbd_struct['VM']): return xen_api_error(['HANDLE_INVALID', 'VM', vbd_struct['VM']]) dom = xendom.get_vm_by_uuid(vbd_struct['VM']) - vbd_ref = '' + vdi = xennode.get_vdi_by_uuid(vbd_struct['VDI']) + if not vdi: + return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref]) + + # new VBD via VDI/SR + vdi_image = vdi.get_location() + try: - # new VBD via VDI/SR - vdi_ref = vbd_struct.get('VDI') - vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref) - if not vdi: - return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref]) - vdi_image = vdi.get_location() vbd_ref = XendTask.log_progress(0, 100, dom.create_vbd, vbd_struct, vdi_image) - except XendError: - return xen_api_todo() + except XendError, e: + log.exception("Error in VBD_create") + return xen_api_error(['INTERNAL_ERROR', str(e)]) + + vdi.addVBD(vbd_ref) xendom.managed_config_save(dom) return xen_api_success(vbd_ref) @@ -1624,7 +1633,14 @@ class XendAPI(object): if not vm: return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref]) + vdi_ref = XendDomain.instance()\ + .get_dev_property_by_uuid('vbd', vbd_ref, "VDI") + vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref) + XendTask.log_progress(0, 100, vm.destroy_vbd, vbd_ref) + + vdi.removeVBD(vbd_ref) + return xen_api_success_void() def _VBD_get(self, vbd_ref, prop): @@ -1636,6 +1652,26 @@ class XendAPI(object): def VBD_get_metrics(self, _, vbd_ref): return xen_api_success(vbd_ref) + def VBD_get_runtime_properties(self, _, vbd_ref): + xendom = XendDomain.instance() + dominfo = xendom.get_vm_with_dev_uuid('vbd', vbd_ref) + device = dominfo.get_dev_config_by_uuid('vbd', vbd_ref) + devid = int(device['id']) + device_sxps = dominfo.getDeviceSxprs('vbd') + + log.debug("VBD_get_runtime_properties devid: %i device_sxps: %s", + devid, device_sxps) + + device_dicts = [dict(device_sxp[1][1:]) for device_sxp in device_sxps] + + device_dict = [device_dict + for device_dict in device_dicts + if int(device_dict['virtual-device']) == devid][0] + + log.debug("VBD_get_runtime_properties device_dict: %s", device_dict) + + return xen_api_success(device_dict) + # attributes (rw) def VBD_get_VM(self, session, vbd_ref): return self._VBD_get(vbd_ref, 'VM') @@ -1828,7 +1864,8 @@ class XendAPI(object): return XendNode.instance().get_vdi_by_uuid(ref) def VDI_get_VBDs(self, session, vdi_ref): - return xen_api_todo() + vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref) + return xen_api_success(vdi.getVBDs()) def VDI_get_physical_utilisation(self, session, vdi_ref): return xen_api_success(self._get_VDI(vdi_ref). @@ -1898,7 +1935,7 @@ class XendAPI(object): 'name_label': image.name_label, 'name_description': image.name_description, 'SR': image.sr_uuid, - 'VBDs': [], # TODO + 'VBDs': image.getVBDs(), 'virtual_size': image.virtual_size, 'physical_utilisation': image.physical_utilisation, 'type': image.type, diff --git a/tools/python/xen/xend/XendVDI.py b/tools/python/xen/xend/XendVDI.py index dd1bc80385..140ca01226 100644 --- a/tools/python/xen/xend/XendVDI.py +++ b/tools/python/xen/xend/XendVDI.py @@ -72,6 +72,16 @@ class XendVDI(AutoSaveObject): self.read_only = False self.type = "system" self.other_config = {} + self.vbds = [] + + def addVBD(self, vbd_ref): + self.vbds.append(vbd_ref) + + def removeVBD(self, vbd_ref): + self.vbds.remove(vbd_ref) + + def getVBDs(self): + return self.vbds def load_config_dict(self, cfg): """Loads configuration into the object from a dict. diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 77f442e8e3..0293b4529c 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -33,7 +33,6 @@ import getopt import socket import traceback import xmlrpclib -import traceback import time import datetime from select import select @@ -50,6 +49,7 @@ from xen.xend.XendConstants import * from xen.xm.opts import OptionError, Opts, wrap, set_true from xen.xm import console from xen.util.xmlrpclib2 import ServerProxy + import XenAPI @@ -492,6 +492,14 @@ def usage(cmd = None): # #################################################################### +def get_default_SR(): + return [sr_ref + for sr_ref in server.xenapi.SR.get_all() + if server.xenapi.SR.get_type(sr_ref) == "local"][0] + +def map2sxp(m): + return [[k, m[k]] for k in m.keys()] + def arg_check(args, name, lo, hi = -1): n = len([i for i in args if i != '--']) @@ -675,9 +683,6 @@ def xm_restore(args): def getDomains(domain_names, state, full = 0): if serverType == SERVER_XEN_API: - def map2sxp(m): - return ["domain"] + [[k, m[k]] for k in m.keys()] - doms_sxp = [] doms_dict = [] dom_refs = server.xenapi.VM.get_all() @@ -691,11 +696,11 @@ def getDomains(domain_names, state, full = 0): 'state': '-----', 'cpu_time': dom_metrics['vcpus_utilisation']}) - doms_sxp.append(map2sxp(dom_rec)) + doms_sxp.append(['domain'] + map2sxp(dom_rec)) doms_dict.append(dom_rec) if domain_names: - doms = [map2sxp(dom) for dom in doms_dict + doms = [['domain'] + map2sxp(dom) for dom in doms_dict if dom["name"] in domain_names] if len(doms) > 0: @@ -1689,12 +1694,20 @@ def xm_block_list(args): (use_long, params) = arg_check_for_resource_list(args, "block-list") dom = params[0] - if use_long: + + if serverType == SERVER_XEN_API: + vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom)) + vbd_properties = \ + map(server.xenapi.VBD.get_runtime_properties, vbd_refs) + devs = map(lambda x: [x['virtual-device'], map2sxp(x)], vbd_properties) + else: devs = server.xend.domain.getDeviceSxprs(dom, 'vbd') + + if use_long: map(PrettyPrint.prettyprint, devs) else: hdr = 0 - for x in server.xend.domain.getDeviceSxprs(dom, 'vbd'): + for x in devs: if hdr == 0: print 'Vdev BE handle state evt-ch ring-ref BE-path' hdr = 1 @@ -1767,8 +1780,45 @@ def parse_block_configuration(args): def xm_block_attach(args): arg_check(args, 'block-attach', 4, 5) - (dom, vbd) = parse_block_configuration(args) - server.xend.domain.device_create(dom, vbd) + if serverType == SERVER_XEN_API: + dom = args[0] + uname = args[1] + dev = args[2] + mode = args[3] + + # First create new VDI + vdi_record = { + "name_label": "vdi" + str(uname.__hash__()), + "name_description": "", + "SR": get_default_SR(), + "virtual_size": 0, + "sector_size": 512, + "type": "system", + "sharable": False, + "read_only": mode!="w", + "other_config": {"location": uname} + } + + vdi_ref = server.xenapi.VDI.create(vdi_record) + + # Now create new VBD + + vbd_record = { + "VM": get_single_vm(dom), + "VDI": vdi_ref, + "device": dev, + "bootable": True, + "mode": mode=="w" and "RW" or "RO", + "type": "Disk", + "qos_algorithm_type": "", + "qos_algorithm_params": {} + } + + server.xenapi.VBD.create(vbd_record) + + else: + (dom, vbd) = parse_block_configuration(args) + server.xend.domain.device_create(dom, vbd) def xm_block_configure(args): @@ -1814,13 +1864,30 @@ def detach(args, command, deviceClass): def xm_block_detach(args): - try: - detach(args, 'block-detach', 'vbd') - return - except: - pass - detach(args, 'block-detach', 'tap') + if serverType == SERVER_XEN_API: + arg_check(args, "xm_block_detach", 2, 3) + dom = args[0] + dev = args[1] + vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom)) + vbd_refs = [vbd_ref for vbd_ref in vbd_refs + if server.xenapi.VBD.get_device(vbd_ref) == dev] + if len(vbd_refs) > 0: + vbd_ref = vbd_refs[0] + vdi_ref = server.xenapi.VBD.get_VDI(vbd_ref) + server.xenapi.VBD.destroy(vbd_ref) + + if len(server.xenapi.VDI.get_VBDs(vdi_ref)) <= 0: + server.xenapi.VDI.destroy(vdi_ref) + else: + print "Cannot find device '%s' in domain '%s'" % (dev,dom) + else: + try: + detach(args, 'block-detach', 'vbd') + return + except: + pass + detach(args, 'block-detach', 'tap') def xm_network_detach(args): detach(args, 'network-detach', 'vif') diff --git a/tools/python/xen/xm/xenapi_create.py b/tools/python/xen/xm/xenapi_create.py index 498dbba4ae..4795d514da 100644 --- a/tools/python/xen/xm/xenapi_create.py +++ b/tools/python/xen/xm/xenapi_create.py @@ -18,7 +18,7 @@ """Domain creation using new XenAPI """ -from xen.xm.main import server +from xen.xm.main import server, get_default_SR from xml.dom.minidom import parse, getDOMImplementation from xml.dom.ext import PrettyPrint from xml.parsers.xmlproc import xmlproc, xmlval, xmldtd @@ -71,9 +71,7 @@ def try_quietly(fn, *args): class xenapi_create: def __init__(self): - self.DEFAULT_STORAGE_REPOSITORY = [sr_ref - for sr_ref in server.xenapi.SR.get_all() - if server.xenapi.SR.get_type(sr_ref) == "local"][0] + self.DEFAULT_STORAGE_REPOSITORY = get_default_SR() self.dtd = "/usr/lib/python/xen/xm/create.dtd" From f5f96d3c4fa88a22cf6ef4057da968ff411012a0 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Tue, 20 Mar 2007 11:49:04 +0000 Subject: [PATCH 158/170] Fix xm create -c. Signed-off-by: Tom Wilkie --- tools/python/xen/xm/create.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index 1af0fbefd7..abdfa22031 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -1293,7 +1293,7 @@ def do_console(domain_name): domid = server.xenapi.VM.get_domid( get_single_vm(domain_name)) else: - dom = server.xend.domain(name) + dom = server.xend.domain(domain_name) domid = int(sxp.child_value(dom, 'domid', '-1')) console.execConsole(domid) except: From b5d7ad3a95dca1933380ee98ecff6eed1ec516fc Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Tue, 20 Mar 2007 14:04:27 +0000 Subject: [PATCH 159/170] Fix exception handling when xmlrpclib.Fault is raised, in legacy mode. Signed-off-by: Ewan Mellor --- tools/python/xen/util/xmlrpclib2.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/python/xen/util/xmlrpclib2.py b/tools/python/xen/util/xmlrpclib2.py index bd3c2c98e6..3bdd717de2 100644 --- a/tools/python/xen/util/xmlrpclib2.py +++ b/tools/python/xen/util/xmlrpclib2.py @@ -241,10 +241,13 @@ class TCPXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer): "ErrorDescription": errdesc },), methodresponse = 1) else: - log.exception('Internal error handling %s', method) import xen.xend.XendClient - response = xmlrpclib.dumps( - xmlrpclib.Fault(xen.xend.XendClient.ERROR_INTERNAL, str(exn))) + if isinstance(exn, xmlrpclib.Fault): + response = xmlrpclib.dumps(exn) + else: + log.exception('Internal error handling %s', method) + response = xmlrpclib.dumps( + xmlrpclib.Fault(xen.xend.XendClient.ERROR_INTERNAL, str(exn))) except: log.exception('Internal error handling error') From 1c3dce55cdd5c290b8965a6120d58bf9fa6aa8a5 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Tue, 20 Mar 2007 14:04:57 +0000 Subject: [PATCH 160/170] Fix parameter to XendInvalidDomain. Signed-off-by: Ewan Mellor --- tools/python/xen/xend/XendDomain.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py index 4ec8334aa1..18aad354b4 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -674,7 +674,7 @@ class XendDomain: else: return domid - raise XendInvalidDomain("Domain does not exist") + raise XendInvalidDomain(vm_uuid) finally: self.domains_lock.release() From 9e9090601cb8b62aef647107c1adfc3ae7d0fe76 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Tue, 20 Mar 2007 15:12:07 +0000 Subject: [PATCH 161/170] Add VIF.runtime_properties dictionary, and use that to implement xm network-list through the Xen-API. Implement xm network-attach and xm network-detach also. Signed-off-by: Tom Wilkie --- tools/python/xen/xend/XendAPI.py | 67 ++++++++++------ tools/python/xen/xend/XendDomainInfo.py | 20 +++-- tools/python/xen/xm/main.py | 101 +++++++++++++++++++++--- 3 files changed, 147 insertions(+), 41 deletions(-) diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index 6d40c7f13b..595e577901 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -1656,21 +1656,19 @@ class XendAPI(object): xendom = XendDomain.instance() dominfo = xendom.get_vm_with_dev_uuid('vbd', vbd_ref) device = dominfo.get_dev_config_by_uuid('vbd', vbd_ref) - devid = int(device['id']) - device_sxps = dominfo.getDeviceSxprs('vbd') - log.debug("VBD_get_runtime_properties devid: %i device_sxps: %s", - devid, device_sxps) - - device_dicts = [dict(device_sxp[1][1:]) for device_sxp in device_sxps] + try: + devid = int(device['id']) + device_sxps = dominfo.getDeviceSxprs('vbd') + device_dicts = [dict(device_sxp[1][1:]) for device_sxp in device_sxps] + device_dict = [device_dict + for device_dict in device_dicts + if int(device_dict['virtual-device']) == devid][0] - device_dict = [device_dict - for device_dict in device_dicts - if int(device_dict['virtual-device']) == devid][0] - - log.debug("VBD_get_runtime_properties device_dict: %s", device_dict) - - return xen_api_success(device_dict) + return xen_api_success(device_dict) + except Exception, exn: + log.exception(exn) + return xen_api_success({}) # attributes (rw) def VBD_get_VM(self, session, vbd_ref): @@ -1732,7 +1730,8 @@ class XendAPI(object): # Xen API: Class VIF # ---------------------------------------------------------------- - VIF_attr_ro = ['metrics'] + VIF_attr_ro = ['metrics', + 'runtime_properties'] VIF_attr_rw = ['device', 'network', 'VM', @@ -1769,18 +1768,17 @@ class XendAPI(object): # class methods def VIF_create(self, session, vif_struct): xendom = XendDomain.instance() - if xendom.is_valid_vm(vif_struct['VM']): - dom = xendom.get_vm_by_uuid(vif_struct['VM']) - try: - vif_ref = dom.create_vif(vif_struct) - xendom.managed_config_save(dom) - return xen_api_success(vif_ref) - except XendError: - return xen_api_error(XEND_ERROR_TODO) - else: + if not xendom.is_valid_vm(vif_struct['VM']): return xen_api_error(['HANDLE_INVALID', 'VM', vif_struct['VM']]) - + dom = xendom.get_vm_by_uuid(vif_struct['VM']) + try: + vif_ref = dom.create_vif(vif_struct) + xendom.managed_config_save(dom) + return xen_api_success(vif_ref) + except XendError: + return xen_api_error(XEND_ERROR_TODO) + def VIF_destroy(self, session, vif_ref): xendom = XendDomain.instance() vm = xendom.get_vm_with_dev_uuid('vif', vif_ref) @@ -1818,6 +1816,27 @@ class XendAPI(object): vifs = reduce(lambda x, y: x + y, vifs) return xen_api_success(vifs) + def VIF_get_runtime_properties(self, _, vif_ref): + xendom = XendDomain.instance() + dominfo = xendom.get_vm_with_dev_uuid('vif', vif_ref) + device = dominfo.get_dev_config_by_uuid('vif', vif_ref) + + try: + devid = int(device['id']) + + device_sxps = dominfo.getDeviceSxprs('vif') + device_dicts = [dict(device_sxp[1][1:]) + for device_sxp in device_sxps] + + device_dict = [device_dict + for device_dict in device_dicts + if int(device_dict['handle']) == devid][0] + + return xen_api_success(device_dict) + + except Exception, exn: + log.exception(exn) + return xen_api_success({}) # Xen API: Class VIF_metrics # ---------------------------------------------------------------- diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index a1d3c16f88..bd4c595797 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -2286,8 +2286,6 @@ class XendDomainInfo: @return: uuid of the device """ xenapi_vbd['image'] = vdi_image_path - log.debug('create_vbd: %s' % xenapi_vbd) - dev_uuid = '' if vdi_image_path.startswith('tap'): dev_uuid = self.info.device_add('tap', cfg_xenapi = xenapi_vbd) else: @@ -2297,8 +2295,8 @@ class XendDomainInfo: raise XendError('Failed to create device') if self.state == XEN_API_VM_POWER_STATE_RUNNING: + _, config = self.info['devices'][dev_uuid] - dev_control = None if vdi_image_path.startswith('tap'): dev_control = self.getDeviceController('tap') @@ -2349,9 +2347,21 @@ class XendDomainInfo: raise XendError('Failed to create device') if self.state == XEN_API_VM_POWER_STATE_RUNNING: - _, config = self.info['devices'][dev_uuid] - config['devid'] = self.getDeviceController('vif').createDevice(config) + _, config = self.info['devices'][dev_uuid] + dev_control = self.getDeviceController('vif') + + try: + devid = dev_control.createDevice(config) + dev_control.waitForDevice(devid) + self.info.device_update(dev_uuid, + cfg_xenapi = {'devid': devid}) + except Exception, exn: + log.exception(exn) + del self.info['devices'][dev_uuid] + self.info['vif_refs'].remove(dev_uuid) + raise + return dev_uuid def create_vtpm(self, xenapi_vtpm): diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 0293b4529c..d76f64ec6d 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -497,6 +497,10 @@ def get_default_SR(): for sr_ref in server.xenapi.SR.get_all() if server.xenapi.SR.get_type(sr_ref) == "local"][0] +def get_default_Network(): + return [network_ref + for network_ref in server.xenapi.network.get_all()][0] + def map2sxp(m): return [[k, m[k]] for k in m.keys()] @@ -1669,12 +1673,20 @@ def xm_network_list(args): (use_long, params) = arg_check_for_resource_list(args, "network-list") dom = params[0] - if use_long: + + if serverType == SERVER_XEN_API: + vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom)) + vif_properties = \ + map(server.xenapi.VIF.get_runtime_properties, vif_refs) + devs = map(lambda x: [x.get('handle'), map2sxp(x)], vif_properties) + else: devs = server.xend.domain.getDeviceSxprs(dom, 'vif') + + if use_long: map(PrettyPrint.prettyprint, devs) else: hdr = 0 - for x in server.xend.domain.getDeviceSxprs(dom, 'vif'): + for x in devs: if hdr == 0: print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path' hdr = 1 @@ -1699,7 +1711,7 @@ def xm_block_list(args): vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom)) vbd_properties = \ map(server.xenapi.VBD.get_runtime_properties, vbd_refs) - devs = map(lambda x: [x['virtual-device'], map2sxp(x)], vbd_properties) + devs = map(lambda x: [x.get('virtual-device'), map2sxp(x)], vbd_properties) else: devs = server.xend.domain.getDeviceSxprs(dom, 'vbd') @@ -1836,15 +1848,65 @@ def xm_network_attach(args): vif_params = ['type', 'mac', 'bridge', 'ip', 'script', \ 'backend', 'vifname', 'rate', 'model'] - for a in args[1:]: - vif_param = a.split("=") - if len(vif_param) != 2 or vif_param[1] == '' or \ - vif_param[0] not in vif_params: - err("Invalid argument: %s" % a) - usage('network-attach') - vif.append(vif_param) + if serverType == SERVER_XEN_API: + vif_record = { + "device": "eth0", + "network": get_default_Network(), + "VM": get_single_vm(dom), + "MAC": "", + "MTU": "", + "qos_algorithm_type": "", + "qos_algorithm_params": {}, + "other_config": {} + } - server.xend.domain.device_create(dom, vif) + def set(keys, val): + record = vif_record + for key in keys[:-1]: + record = record[key] + record[keys[-1]] = val + + vif_conv = { + 'type': + lambda x: None, + 'mac': + lambda x: set(['MAC'], x), + 'bridge': + lambda x: set(['network'], get_net_from_bridge(x)), + 'ip': + lambda x: set(['other_config', 'ip'], x), + 'script': + lambda x: set(['other_config', 'script'], x), + 'backend': + lambda x: set(['other_config', 'backend'], x), + 'vifname': + lambda x: set(['device'], x), + 'rate': + lambda x: set(['qos_algorithm_params', 'rate'], x), + 'model': + lambda x: None + } + + for a in args[1:]: + vif_param = a.split("=") + if len(vif_param) != 2 or vif_param[1] == '' or \ + vif_param[0] not in vif_params: + err("Invalid argument: %s" % a) + usage('network-attach') + else: + vif_conv[vif_param[0]](vif_param[1]) + + print str(vif_record) + server.xenapi.VIF.create(vif_record) + else: + for a in args[1:]: + vif_param = a.split("=") + if len(vif_param) != 2 or vif_param[1] == '' or \ + vif_param[0] not in vif_params: + err("Invalid argument: %s" % a) + usage('network-attach') + vif.append(vif_param) + server.xend.domain.device_create(dom, vif) def detach(args, command, deviceClass): @@ -1890,7 +1952,22 @@ def xm_block_detach(args): detach(args, 'block-detach', 'tap') def xm_network_detach(args): - detach(args, 'network-detach', 'vif') + if serverType == SERVER_XEN_API: + arg_check(args, "xm_block_detach", 2, 3) + dom = args[0] + devid = args[1] + vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom)) + vif_refs = [vif_ref for vif_ref in vif_refs + if server.xenapi.VIF.\ + get_runtime_properties(vif_ref)["handle"] == devid] + if len(vif_refs) > 0: + vif_ref = vif_refs[0] + + server.xenapi.VIF.destroy(vif_ref) + else: + print "Cannot find device '%s' in domain '%s'" % (devid,dom) + else: + detach(args, 'network-detach', 'vif') def xm_vnet_list(args): From f6c7de277c0629f4d28637b5ee7492bd3f3db638 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Tue, 20 Mar 2007 15:15:37 +0000 Subject: [PATCH 162/170] Fix sxp2xml translation to handle maxmem. Signed-off-by: Tom Wilkie --- tools/python/xen/xm/xenapi_create.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/python/xen/xm/xenapi_create.py b/tools/python/xen/xm/xenapi_create.py index 4795d514da..52d91e101b 100644 --- a/tools/python/xen/xm/xenapi_create.py +++ b/tools/python/xen/xm/xenapi_create.py @@ -513,11 +513,15 @@ class sxp2xml: memory_str = str(int( get_child_by_name(config, "memory"))*1024*1024) - memory.attributes["static_min"] = memory_str + memory.attributes["static_min"] = str(0) memory.attributes["static_max"] = memory_str memory.attributes["dynamic_min"] = memory_str memory.attributes["dynamic_max"] = memory_str + if get_child_by_name(config, "maxmem"): + memory.attributes["static_max"] = \ + str(int(get_child_by_name(config, "maxmem")*1024*1024)) + vm.appendChild(memory) # And now the vbds From 06979e1dc429e57bf1e46c88dc8603efb26c06d2 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Tue, 20 Mar 2007 16:52:33 +0000 Subject: [PATCH 163/170] Have xm-test wait for the network device to detach. This is an asynchronous process, so xm-test needs to poll. Signed-off-by: Tom Wilkie --- .../tests/network-attach/network_utils.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tools/xm-test/tests/network-attach/network_utils.py b/tools/xm-test/tests/network-attach/network_utils.py index 084b5ebd90..93fe72a811 100644 --- a/tools/xm-test/tests/network-attach/network_utils.py +++ b/tools/xm-test/tests/network-attach/network_utils.py @@ -12,6 +12,18 @@ def count_eth(console): FAIL(str(e)) return len(run['output'].splitlines()) +def get_state(domain_name, number): + s, o = traceCommand("xm network-list %s | awk '/^%d/ {print $5}'" % + (domain_name, number)) + print o + + if s != 0: + FAIL("network-list failed") + if o == "": + return 0 + else: + return int(o) + def network_attach(domain_name, console): eths_before = count_eth(console) status, output = traceCommand("xm network-attach %s" % domain_name) @@ -30,6 +42,13 @@ def network_detach(domain_name, console, num=0): if status != 0: return -1, "xm network-detach returned invalid %i != 0" % status + for i in range(10): + if get_state(domain_name, num) == 0: + break + time.sleep(1) + else: + FAIL("network-detach failed: device did not disappear") + eths_after = count_eth(console) if eths_after != (eths_before-1): return -2, "Network device was not actually disconnected from domU" From 9aa2765862058b235408be3f9392c9b538b8ecab Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Tue, 20 Mar 2007 16:55:29 +0000 Subject: [PATCH 164/170] Tidy the error message from getDomains when using the Xen-API and no domain is found. Signed-off-by: Ewan Mellor --- tools/python/xen/xm/main.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index d76f64ec6d..24ac41b877 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -710,7 +710,9 @@ def getDomains(domain_names, state, full = 0): if len(doms) > 0: return doms else: - print "Error: no domains named '%s'" % domain_names + print "Error: no domain%s named %s" % \ + (len(domain_names) > 1 and 's' or '', + ', '.join(domain_names)) sys.exit(-1) else: return doms_sxp From 282cd380d9da2e1fc7d57b2b49303e6e91dd5c7e Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Tue, 20 Mar 2007 17:26:05 +0000 Subject: [PATCH 165/170] Change the eyecatcher to be case-insensitive, so that "Internal error" is detected. Signed-off-by: Tom Wilkie --- .../tests/block-create/07_block_attach_baddevice_neg.py | 4 ++-- .../tests/block-create/08_block_attach_bad_filedevice_neg.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py b/tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py index 3e9f0f2514..5d435e27c6 100644 --- a/tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py +++ b/tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py @@ -32,10 +32,10 @@ except ConsoleError, e: status, output = traceCommand("xm block-attach %s phy:NOT-EXIST xvda1 w" % domain.getName()) eyecatcher = "Error" -where = output.find(eyecatcher) +where = re.compile(eyecatcher, re.IGNORECASE).search(output) if status == 0: FAIL("xm block-attach returned bad status, expected non 0, status is: %i" % status ) -elif where == -1: +elif where is None: FAIL("xm block-attach returned bad output, expected Error, output is: %s" % output ) try: diff --git a/tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py b/tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py index 802e101147..2fa482414a 100644 --- a/tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py +++ b/tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py @@ -31,10 +31,10 @@ except ConsoleError, e: status, output = traceCommand("xm block-attach %s file:/dev/NOT-EXIST xvda1 w" % domain.getName()) eyecatcher = "Error" -where = output.find(eyecatcher) +where = re.compile(eyecatcher, re.IGNORECASE).search(output) if status == 0: FAIL("xm block-attach returned bad status, expected non 0, status is: %i" % status ) -elif where == -1: +elif where is None: FAIL("xm block-attach returned bad output, expected Error, output is: %s" % output ) try: From 8ed7e86d162444de83614e98d8b74027046a64ba Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Tue, 20 Mar 2007 17:30:05 +0000 Subject: [PATCH 166/170] Make xm debug-keys talk XenAPI; Add send_debug_keys to host Signed-off-by: Tom Wilkie --- tools/python/xen/xend/XendAPI.py | 8 +++++++- tools/python/xen/xm/main.py | 10 +++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index 595e577901..70075c560b 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -665,7 +665,8 @@ class XendAPI(object): ('add_to_other_config', None), ('remove_from_other_config', None), ('dmesg', 'String'), - ('get_log', 'String')] + ('get_log', 'String'), + ('send_debug_keys', None)] host_funcs = [('get_by_name_label', 'Set(host)')] @@ -752,6 +753,11 @@ class XendAPI(object): log_buffer = log_file.read() return xen_api_success(log_buffer) + def host_send_debug_keys(self, _, host_ref, keys): + node = XendNode.instance() + node.send_debug_keys(keys) + return xen_api_success_void() + def host_get_record(self, session, host_ref): node = XendNode.instance() dom = XendDomain.instance() diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 24ac41b877..0ae9f97378 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -1549,7 +1549,15 @@ def xm_trigger(args): def xm_debug_keys(args): arg_check(args, "debug-keys", 1) - server.xend.node.send_debug_keys(str(args[0])) + + keys = str(args[0]) + + if serverType == SERVER_XEN_API: + server.xenapi.host.send_debug_keys( + server.xenapi.session.get_this_host(), + keys) + else: + server.xend.node.send_debug_keys(keys) def xm_top(args): arg_check(args, "top", 0) From 3d9330324c6a0f3c2e5eaf6fd6d171a21b61db83 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Tue, 20 Mar 2007 17:30:52 +0000 Subject: [PATCH 167/170] Make xm trigger talk XenAPI; add send_trigger to VM class. Signed-off-by: Tom Wilkie --- tools/python/xen/xend/XendAPI.py | 10 +++++++++- tools/python/xen/xm/main.py | 7 +++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index 70075c560b..a0f7c351b4 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -1087,7 +1087,8 @@ class XendAPI(object): ('add_to_platform', None), ('remove_from_platform', None), ('add_to_other_config', None), - ('remove_from_other_config', None)] + ('remove_from_other_config', None), + ('send_trigger', None)] VM_funcs = [('create', 'VM'), ('get_by_name_label', 'Set(VM)')] @@ -1534,6 +1535,13 @@ class XendAPI(object): return xen_api_success_void() + def VM_send_trigger(self, _, vm_ref, trigger, vcpu): + xendom = XendDomain.instance() + xeninfo = xendom.get_vm_by_uuid(vm_ref) + xendom.domain_send_trigger(xeninfo.getDomid(), trigger, vcpu) + return xen_api_success_void() + + # Xen API: Class VM_metrics # ---------------------------------------------------------------- diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 0ae9f97378..5f8449d376 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -1544,8 +1544,11 @@ def xm_trigger(args): trigger = args[1] if len(args) == 3: vcpu = int(args[2]) - - server.xend.domain.send_trigger(dom, trigger, vcpu) + + if serverType == SERVER_XEN_API: + server.xenapi.VM.send_trigger(get_single_vm(dom), trigger, vcpu) + else: + server.xend.domain.send_trigger(dom, trigger, vcpu) def xm_debug_keys(args): arg_check(args, "debug-keys", 1) From f7bff36895f3c96edb433221a40ee53b261a0068 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Tue, 20 Mar 2007 17:33:35 +0000 Subject: [PATCH 168/170] Fix xm block-list through the Xen-API for managed domains. Signed-off-by: Tom Wilkie --- tools/python/xen/xm/main.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 5f8449d376..c5b640ccec 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -37,6 +37,7 @@ import time import datetime from select import select import xml.dom.minidom +from xen.util.blkif import blkdev_name_to_number import warnings warnings.filterwarnings('ignore', category=FutureWarning) @@ -1724,7 +1725,12 @@ def xm_block_list(args): vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom)) vbd_properties = \ map(server.xenapi.VBD.get_runtime_properties, vbd_refs) - devs = map(lambda x: [x.get('virtual-device'), map2sxp(x)], vbd_properties) + vbd_devs = \ + map(server.xenapi.VBD.get_device, vbd_refs) + vbd_devids = \ + map(blkdev_name_to_number, vbd_devs) + devs = map(lambda (devid, prop): [devid, map2sxp(prop)], + zip(vbd_devids, vbd_properties)) else: devs = server.xend.domain.getDeviceSxprs(dom, 'vbd') From 5ce79470d85099a90c46a265b1f45e70aafd9841 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Tue, 20 Mar 2007 17:34:34 +0000 Subject: [PATCH 169/170] Fix xm network-list through the Xen-API for managed domains. Signed-off-by: Tom Wilkie --- tools/python/xen/xm/main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index c5b640ccec..a138afdd95 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -1692,7 +1692,8 @@ def xm_network_list(args): vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom)) vif_properties = \ map(server.xenapi.VIF.get_runtime_properties, vif_refs) - devs = map(lambda x: [x.get('handle'), map2sxp(x)], vif_properties) + devs = map(lambda (handle, properties): [handle, map2sxp(properties)], + zip(range(len(vif_properties)), vif_properties)) else: devs = server.xend.domain.getDeviceSxprs(dom, 'vif') From 5b3327347f83a473755b00a76ff1176dc6cda301 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Tue, 20 Mar 2007 17:36:18 +0000 Subject: [PATCH 170/170] Raise an exception in xm_block_detach if using Xen-API and it fails -- this ensures that the exit status properly set. Signed-off-by: Tom Wilkie --- tools/python/xen/xm/main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index a138afdd95..66a5951f7f 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -1962,7 +1962,8 @@ def xm_block_detach(args): if len(server.xenapi.VDI.get_VBDs(vdi_ref)) <= 0: server.xenapi.VDI.destroy(vdi_ref) else: - print "Cannot find device '%s' in domain '%s'" % (dev,dom) + raise OptionError("Cannot find device '%s' in domain '%s'" + % (dev,dom)) else: try: detach(args, 'block-detach', 'vbd')