[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-3.0.5-testing] Merge.
# HG changeset patch # User Steven Smith <ssmith@xxxxxxxxxxxxx> # Date 1177677069 -3600 # Node ID 3c352bbc894dad767255a3103bf9d81594354736 # Parent 491bed0350f1f813951f6e45c291512bb58b0632 # Parent 499e50c3115f0e7fd62bedb083119edb76cdb18c Merge. --- tools/firmware/hvmloader/smbios.h | 38 - tools/xm-test/tests/network-attach/network_utils.py | 56 - xen/common/compat/acm_ops.c | 47 - docs/man/xm.pod.1 | 18 tools/blktap/drivers/block-qcow.c | 67 + tools/firmware/hvmloader/acpi/acpi2_0.h | 2 tools/firmware/hvmloader/config.h | 9 tools/firmware/hvmloader/hvmloader.c | 58 + tools/firmware/hvmloader/hypercall.h | 11 tools/firmware/hvmloader/smbios.c | 14 tools/firmware/hvmloader/util.c | 1 tools/firmware/hvmloader/util.h | 1 tools/firmware/rombios/rombios.c | 12 tools/ioemu/hw/pc.c | 11 tools/libxc/xc_core_x86.c | 8 tools/libxc/xc_dom_core.c | 4 tools/libxc/xc_domain_save.c | 2 tools/libxc/xc_hvm_build.c | 15 tools/python/xen/xend/XendAPI.py | 343 ++------- tools/python/xen/xend/XendAPIStore.py | 59 + tools/python/xen/xend/XendBase.py | 126 +++ tools/python/xen/xend/XendConfig.py | 7 tools/python/xen/xend/XendDomain.py | 6 tools/python/xen/xend/XendDomainInfo.py | 13 tools/python/xen/xend/XendError.py | 120 +++ tools/python/xen/xend/XendNetwork.py | 175 ++++ tools/python/xen/xend/XendNode.py | 269 +++---- tools/python/xen/xend/XendPBD.py | 108 +- tools/python/xen/xend/XendPIF.py | 372 +++++++--- tools/python/xen/xend/XendPIFMetrics.py | 40 - tools/python/xen/xend/XendQCoWStorageRepo.py | 2 tools/python/xen/xend/XendStateStore.py | 65 - tools/python/xen/xend/XendStorageRepository.py | 2 tools/python/xen/xend/XendVMMetrics.py | 55 - tools/python/xen/xend/server/SrvServer.py | 2 tools/python/xen/xm/create.dtd | 9 tools/python/xen/xm/main.py | 108 ++ tools/python/xen/xm/messages/en/xen-xm.po | 24 tools/python/xen/xm/xenapi_create.py | 69 + tools/xm-test/lib/XmTestLib/network_utils.py | 60 + tools/xm-test/tests/network-attach/01_network_attach_pos.py | 2 tools/xm-test/tests/network-attach/02_network_attach_detach_pos.py | 2 tools/xm-test/tests/network-attach/03_network_attach_detach_multiple_pos.py | 2 tools/xm-test/tests/xapi/03_xapi-network_pos.py | 71 + tools/xm-test/tests/xapi/Makefile.am | 3 xen/acm/acm_policy.c | 8 xen/arch/x86/domain.c | 40 - xen/arch/x86/hvm/vmx/intr.c | 3 xen/arch/x86/hvm/vmx/vmcs.c | 86 +- xen/arch/x86/mm.c | 5 xen/arch/x86/mm/shadow/common.c | 14 xen/arch/x86/mm/shadow/multi.c | 35 xen/arch/x86/x86_32/entry.S | 11 xen/arch/x86/x86_64/compat/entry.S | 26 xen/arch/x86/x86_64/entry.S | 22 xen/arch/x86/x86_64/traps.c | 3 xen/common/Makefile | 1 xen/common/acm_ops.c | 49 - xen/include/Makefile | 2 xen/include/acm/acm_core.h | 8 xen/include/asm-x86/domain.h | 21 xen/include/asm-x86/hvm/vmx/vmcs.h | 2 xen/include/asm-x86/shadow.h | 10 xen/include/public/hvm/save.h | 7 xen/include/xlat.lst | 1 65 files changed, 1735 insertions(+), 1107 deletions(-) diff -r 491bed0350f1 -r 3c352bbc894d docs/man/xm.pod.1 --- a/docs/man/xm.pod.1 Fri Apr 27 13:25:58 2007 +0100 +++ b/docs/man/xm.pod.1 Fri Apr 27 13:31:09 2007 +0100 @@ -555,29 +555,29 @@ I<normal EDF (20ms/5ms):> I<normal EDF (20ms/5ms):> xm sched-sedf <dom-id> 20000000 5000000 0 0 0 - + I<best-effort domains (i.e. non-realtime):> xm sched-sedf <dom-id> 20000000 0 0 1 0 - + I<normal EDF (20ms/5ms) + share of extra-time:> - + xm sched-sedf <dom-id> 20000000 5000000 0 1 0 I<4 domains with weights 2:3:4:2> xm sched-sedf <d1> 0 0 0 0 2 - xm sched-sedf <d2> 0 0 0 0 3 - xm sched-sedf <d3> 0 0 0 0 4 - xm sched-sedf <d4> 0 0 0 0 2 + xm sched-sedf <d2> 0 0 0 0 3 + xm sched-sedf <d3> 0 0 0 0 4 + xm sched-sedf <d4> 0 0 0 0 2 I<1 fully-specified (10ms/3ms) domain, 3 other domains share available rest in 2:7:3 ratio:> - xm sched-sedf <d1> 10000000 3000000 0 0 0 - xm sched-sedf <d2> 0 0 0 0 2 + xm sched-sedf <d1> 10000000 3000000 0 0 0 + xm sched-sedf <d2> 0 0 0 0 2 xm sched-sedf <d3> 0 0 0 0 7 - xm sched-sedf <d4> 0 0 0 0 3 + xm sched-sedf <d4> 0 0 0 0 3 =back diff -r 491bed0350f1 -r 3c352bbc894d tools/blktap/drivers/block-qcow.c --- a/tools/blktap/drivers/block-qcow.c Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/blktap/drivers/block-qcow.c Fri Apr 27 13:31:09 2007 +0100 @@ -55,7 +55,6 @@ /******AIO DEFINES******/ #define REQUEST_ASYNC_FD 1 -#define MAX_AIO_REQS (MAX_REQUESTS * MAX_SEGMENTS_PER_REQ) struct pending_aio { td_callback_t cb; @@ -146,18 +145,37 @@ struct tdqcow_state { AES_KEY aes_encrypt_key; /*AES key*/ AES_KEY aes_decrypt_key; /*AES key*/ /* libaio state */ - io_context_t aio_ctx; - struct iocb iocb_list [MAX_AIO_REQS]; - struct iocb *iocb_free [MAX_AIO_REQS]; - struct pending_aio pending_aio[MAX_AIO_REQS]; - int iocb_free_count; - struct iocb *iocb_queue[MAX_AIO_REQS]; - int iocb_queued; - int poll_fd; /* NB: we require aio_poll support */ - struct io_event aio_events[MAX_AIO_REQS]; + io_context_t aio_ctx; + int max_aio_reqs; + struct iocb *iocb_list; + struct iocb **iocb_free; + struct pending_aio *pending_aio; + int iocb_free_count; + struct iocb **iocb_queue; + int iocb_queued; + int poll_fd; /* NB: we require aio_poll support */ + struct io_event *aio_events; }; static int decompress_cluster(struct tdqcow_state *s, uint64_t cluster_offset); + +static void free_aio_state(struct disk_driver *dd) +{ + struct tdqcow_state *s = (struct tdqcow_state *)dd->private; + + if (s->sector_lock) + free(s->sector_lock); + if (s->iocb_list) + free(s->iocb_list); + if (s->pending_aio) + free(s->pending_aio); + if (s->aio_events) + free(s->aio_events); + if (s->iocb_free) + free(s->iocb_free); + if (s->iocb_queue) + free(s->iocb_queue); +} static int init_aio_state(struct disk_driver *dd) { @@ -166,6 +184,12 @@ static int init_aio_state(struct disk_dr struct tdqcow_state *s = (struct tdqcow_state *)dd->private; long ioidx; + s->iocb_list = NULL; + s->pending_aio = NULL; + s->aio_events = NULL; + s->iocb_free = NULL; + s->iocb_queue = NULL; + /*Initialize Locking bitmap*/ s->sector_lock = calloc(1, bs->size); @@ -174,13 +198,26 @@ static int init_aio_state(struct disk_dr goto fail; } + /* A segment (i.e. a page) can span multiple clusters */ + s->max_aio_reqs = (getpagesize() / s->cluster_size) + 1; + /* Initialize AIO */ - s->iocb_free_count = MAX_AIO_REQS; + s->iocb_free_count = s->max_aio_reqs; s->iocb_queued = 0; + + if (!(s->iocb_list = malloc(sizeof(struct iocb) * s->max_aio_reqs)) || + !(s->pending_aio = malloc(sizeof(struct pending_aio) * s->max_aio_reqs)) || + !(s->aio_events = malloc(sizeof(struct io_event) * s->max_aio_reqs)) || + !(s->iocb_free = malloc(sizeof(struct iocb *) * s->max_aio_reqs)) || + !(s->iocb_queue = malloc(sizeof(struct iocb *) * s->max_aio_reqs))) { + DPRINTF("Failed to allocate AIO structs (max_aio_reqs = %d)\n", + s->max_aio_reqs); + goto fail; + } /*Signal kernel to create Poll FD for Asyc completion events*/ s->aio_ctx = (io_context_t) REQUEST_ASYNC_FD; - s->poll_fd = io_setup(MAX_AIO_REQS, &s->aio_ctx); + s->poll_fd = io_setup(s->max_aio_reqs, &s->aio_ctx); if (s->poll_fd < 0) { if (s->poll_fd == -EAGAIN) { @@ -198,7 +235,7 @@ static int init_aio_state(struct disk_dr goto fail; } - for (i=0;i<MAX_AIO_REQS;i++) + for (i=0;i<s->max_aio_reqs;i++) s->iocb_free[i] = &s->iocb_list[i]; DPRINTF("AIO state initialised\n"); @@ -946,6 +983,7 @@ int tdqcow_open (struct disk_driver *dd, end_xenhdr: if (init_aio_state(dd)!=0) { DPRINTF("Unable to initialise AIO state\n"); + free_aio_state(dd); goto fail; } init_fds(dd); @@ -962,6 +1000,7 @@ int tdqcow_open (struct disk_driver *dd, fail: DPRINTF("QCOW Open failed\n"); + free_aio_state(dd); free(s->l1_table); free(s->l2_cache); free(s->cluster_cache); @@ -1145,7 +1184,7 @@ int tdqcow_do_callbacks(struct disk_driv if (sid > MAX_IOFD) return 1; /* Non-blocking test for completed io. */ - ret = io_getevents(prv->aio_ctx, 0, MAX_AIO_REQS, prv->aio_events, + ret = io_getevents(prv->aio_ctx, 0, prv->max_aio_reqs, prv->aio_events, NULL); for (ep = prv->aio_events, i = ret; i-- > 0; ep++) { diff -r 491bed0350f1 -r 3c352bbc894d tools/firmware/hvmloader/acpi/acpi2_0.h --- a/tools/firmware/hvmloader/acpi/acpi2_0.h Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/firmware/hvmloader/acpi/acpi2_0.h Fri Apr 27 13:31:09 2007 +0100 @@ -394,8 +394,6 @@ struct acpi_20_madt_intsrcovr { #pragma pack () -#define ACPI_PHYSICAL_ADDRESS 0xEA000 - int acpi_build_tables(uint8_t *); #endif /* _ACPI_2_0_H_ */ diff -r 491bed0350f1 -r 3c352bbc894d tools/firmware/hvmloader/config.h --- a/tools/firmware/hvmloader/config.h Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/firmware/hvmloader/config.h Fri Apr 27 13:31:09 2007 +0100 @@ -17,5 +17,14 @@ #define ROMBIOS_MAXOFFSET 0x0000FFFF #define ROMBIOS_END (ROMBIOS_BEGIN + ROMBIOS_SIZE) +/* Memory map. */ +#define HYPERCALL_PHYSICAL_ADDRESS 0x00080000 +#define VGABIOS_PHYSICAL_ADDRESS 0x000C0000 +#define ETHERBOOT_PHYSICAL_ADDRESS 0x000C8000 +#define VMXASSIST_PHYSICAL_ADDRESS 0x000D0000 +#define SMBIOS_PHYSICAL_ADDRESS 0x000E9000 +#define SMBIOS_MAXIMUM_SIZE 0x00001000 +#define ACPI_PHYSICAL_ADDRESS 0x000EA000 +#define ROMBIOS_PHYSICAL_ADDRESS 0x000F0000 #endif /* __HVMLOADER_CONFIG_H__ */ diff -r 491bed0350f1 -r 3c352bbc894d tools/firmware/hvmloader/hvmloader.c --- a/tools/firmware/hvmloader/hvmloader.c Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/firmware/hvmloader/hvmloader.c Fri Apr 27 13:31:09 2007 +0100 @@ -19,23 +19,16 @@ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307 USA. */ + #include "roms.h" -#include "acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */ +#include "acpi/acpi2_0.h" #include "hypercall.h" #include "util.h" -#include "smbios.h" #include "config.h" #include "apic_regs.h" #include "pci_regs.h" #include <xen/version.h> #include <xen/hvm/params.h> - -/* memory map */ -#define HYPERCALL_PHYSICAL_ADDRESS 0x00080000 -#define VGABIOS_PHYSICAL_ADDRESS 0x000C0000 -#define ETHERBOOT_PHYSICAL_ADDRESS 0x000C8000 -#define VMXASSIST_PHYSICAL_ADDRESS 0x000D0000 -#define ROMBIOS_PHYSICAL_ADDRESS 0x000F0000 asm( " .text \n" @@ -103,7 +96,8 @@ asm( "stack_top: \n" ); -extern void create_mp_tables(void); +void create_mp_tables(void); +int hvm_write_smbios_tables(void); static int cirrus_check(void) @@ -351,17 +345,20 @@ static void cmos_write_memory_size(void) int main(void) { - int acpi_sz; + int acpi_sz = 0, vgabios_sz = 0, etherboot_sz = 0, rombios_sz, smbios_sz; printf("HVM Loader\n"); init_hypercalls(); printf("Writing SMBIOS tables ...\n"); - hvm_write_smbios_tables(); + smbios_sz = hvm_write_smbios_tables(); printf("Loading ROMBIOS ...\n"); - memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, sizeof(rombios)); + rombios_sz = sizeof(rombios); + if ( rombios_sz > 0x10000 ) + rombios_sz = 0x10000; + memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, rombios_sz); highbios_setup(); apic_setup(); @@ -375,12 +372,14 @@ int main(void) printf("Loading Cirrus VGABIOS ...\n"); memcpy((void *)VGABIOS_PHYSICAL_ADDRESS, vgabios_cirrusvga, sizeof(vgabios_cirrusvga)); + vgabios_sz = sizeof(vgabios_cirrusvga); } else { printf("Loading Standard VGABIOS ...\n"); memcpy((void *)VGABIOS_PHYSICAL_ADDRESS, vgabios_stdvga, sizeof(vgabios_stdvga)); + vgabios_sz = sizeof(vgabios_stdvga); } if ( must_load_nic() ) @@ -388,9 +387,10 @@ int main(void) printf("Loading ETHERBOOT ...\n"); memcpy((void *)ETHERBOOT_PHYSICAL_ADDRESS, etherboot, sizeof(etherboot)); - } - - if ( get_acpi_enabled() != 0 ) + etherboot_sz = sizeof(etherboot); + } + + if ( get_acpi_enabled() ) { printf("Loading ACPI ...\n"); acpi_sz = acpi_build_tables((uint8_t *)ACPI_PHYSICAL_ADDRESS); @@ -398,6 +398,32 @@ int main(void) } cmos_write_memory_size(); + + printf("BIOS map:\n"); + if ( vgabios_sz ) + printf(" %05x-%05x: VGA BIOS\n", + VGABIOS_PHYSICAL_ADDRESS, + VGABIOS_PHYSICAL_ADDRESS + vgabios_sz - 1); + if ( etherboot_sz ) + printf(" %05x-%05x: Etherboot ROM\n", + ETHERBOOT_PHYSICAL_ADDRESS, + ETHERBOOT_PHYSICAL_ADDRESS + etherboot_sz - 1); + if ( !check_amd() ) + printf(" %05x-%05x: VMXAssist\n", + VMXASSIST_PHYSICAL_ADDRESS, + VMXASSIST_PHYSICAL_ADDRESS + sizeof(vmxassist) - 1); + if ( smbios_sz ) + printf(" %05x-%05x: SMBIOS tables\n", + SMBIOS_PHYSICAL_ADDRESS, + SMBIOS_PHYSICAL_ADDRESS + smbios_sz - 1); + if ( acpi_sz ) + printf(" %05x-%05x: ACPI tables\n", + ACPI_PHYSICAL_ADDRESS, + ACPI_PHYSICAL_ADDRESS + acpi_sz - 1); + if ( rombios_sz ) + printf(" %05x-%05x: Main BIOS\n", + ROMBIOS_PHYSICAL_ADDRESS, + ROMBIOS_PHYSICAL_ADDRESS + rombios_sz - 1); if ( !check_amd() ) { diff -r 491bed0350f1 -r 3c352bbc894d tools/firmware/hvmloader/hypercall.h --- a/tools/firmware/hvmloader/hypercall.h Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/firmware/hvmloader/hypercall.h Fri Apr 27 13:31:09 2007 +0100 @@ -31,17 +31,18 @@ #ifndef __HVMLOADER_HYPERCALL_H__ #define __HVMLOADER_HYPERCALL_H__ +#include <stdint.h> #include <xen/xen.h> +#include "config.h" + +#define __STR(...) #__VA_ARGS__ +#define STR(...) __STR(__VA_ARGS__) /* * NB. Hypercall address needs to be relative to a linkage symbol for * some version of ld to relocate the relative calls properly. - * Keep this in sync with HYPERCALL_PHYSICAL_ADDRESS in hvmloader.c! */ -#define hypercall_pa "_start - 0x80000" - -#define __STR(x) #x -#define STR(x) __STR(x) +#define hypercall_pa "_start - " STR(HYPERCALL_PHYSICAL_ADDRESS) #define _hypercall0(type, name) \ ({ \ diff -r 491bed0350f1 -r 3c352bbc894d tools/firmware/hvmloader/smbios.c --- a/tools/firmware/hvmloader/smbios.c Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/firmware/hvmloader/smbios.c Fri Apr 27 13:31:09 2007 +0100 @@ -22,12 +22,11 @@ #include <stdint.h> #include <xen/version.h> -#include "smbios.h" #include "smbios_types.h" #include "util.h" #include "hypercall.h" -static size_t +static int write_smbios_tables(void *start, uint32_t vcpus, uint64_t memsize, uint8_t uuid[16], char *xen_version, @@ -82,7 +81,7 @@ get_cpu_manufacturer(char *buf, int len) strncpy(buf, "unknown", len); } -static size_t +static int write_smbios_tables(void *start, uint32_t vcpus, uint64_t memsize, uint8_t uuid[16], char *xen_version, @@ -125,7 +124,7 @@ write_smbios_tables(void *start, SMBIOS_PHYSICAL_ADDRESS + sizeof(struct smbios_entry_point), nr_structs); - return (size_t)((char *)p - (char *)start); + return ((char *)p - (char *)start); } /* Calculate how much pseudo-physical memory (in MB) is allocated to us. */ @@ -156,7 +155,7 @@ get_memsize(void) return (memsize + (1 << 20) - 1) >> 20; } -void +int hvm_write_smbios_tables(void) { uint8_t uuid[16]; /* ** This will break if xen_domain_handle_t is @@ -221,16 +220,17 @@ hvm_write_smbios_tables(void) get_vcpu_nr(), get_memsize(), uuid, xen_version_str, xen_major_version, xen_minor_version); - if ( len > SMBIOS_SIZE_LIMIT ) + if ( len > SMBIOS_MAXIMUM_SIZE ) goto error_out; /* Okay, not too large: copy out of scratch to final location. */ memcpy((void *)SMBIOS_PHYSICAL_ADDRESS, (void *)0xC0000, len); - return; + return len; error_out: printf("Could not write SMBIOS tables, error in hvmloader.c:" "hvm_write_smbios_tables()\n"); + return 0; } diff -r 491bed0350f1 -r 3c352bbc894d tools/firmware/hvmloader/smbios.h --- a/tools/firmware/hvmloader/smbios.h Fri Apr 27 13:25:58 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/* - * smbios.h - interface for Xen HVM SMBIOS generation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 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. - * - * Copyright (C) IBM Corporation, 2006 - * - * Authors: Andrew D. Ball <aball@xxxxxxxxxx> - */ - -#ifndef SMBIOS_H -#define SMBIOS_H - -#include <stdint.h> -#include <stdlib.h> - -/* These constants must agree with the ACPI e820 memory map as defined - in tools/libxc/xc_hvm_build.c and the address the ROMBIOS pulls the - SMBIOS entry point from in the smbios_init subroutine. - */ -#define SMBIOS_PHYSICAL_ADDRESS 0x9f000 -#define SMBIOS_SIZE_LIMIT 0x800 - -void hvm_write_smbios_tables(void); - -#endif /* SMBIOS_H */ diff -r 491bed0350f1 -r 3c352bbc894d tools/firmware/hvmloader/util.c --- a/tools/firmware/hvmloader/util.c Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/firmware/hvmloader/util.c Fri Apr 27 13:31:09 2007 +0100 @@ -18,7 +18,6 @@ * Place - Suite 330, Boston, MA 02111-1307 USA. */ -#include "acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */ #include "util.h" #include "config.h" #include <stdint.h> diff -r 491bed0350f1 -r 3c352bbc894d tools/firmware/hvmloader/util.h --- a/tools/firmware/hvmloader/util.h Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/firmware/hvmloader/util.h Fri Apr 27 13:31:09 2007 +0100 @@ -2,6 +2,7 @@ #define __HVMLOADER_UTIL_H__ #include <stdarg.h> +#include <stdint.h> #undef offsetof #define offsetof(t, m) ((unsigned long)&((t *)0)->m) diff -r 491bed0350f1 -r 3c352bbc894d tools/firmware/rombios/rombios.c --- a/tools/firmware/rombios/rombios.c Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/firmware/rombios/rombios.c Fri Apr 27 13:31:09 2007 +0100 @@ -25,6 +25,8 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // ROM BIOS for use with Bochs/Plex x86 emulation environment + +#include "../hvmloader/config.h" #define HVMASSIST #undef HVMTEST @@ -9409,9 +9411,9 @@ rom_scan_increment: #ifdef HVMASSIST -; Copy the SMBIOS entry point over from 0x9f000, where hvmloader left it. +; Copy the SMBIOS entry point from where hvmloader left it. ; The entry point must be somewhere in 0xf0000-0xfffff on a 16-byte boundary, -; but the tables themeselves can be elsewhere. +; but the tables themselves can be elsewhere. smbios_init: push ax push cx @@ -9424,9 +9426,9 @@ smbios_init: mov ax, #0xf000 mov es, ax ; destination segment is 0xf0000 mov di, #smbios_entry_point ; destination offset - mov ax, #0x9f00 - mov ds, ax ; source segment is 0x9f000 - mov si, #0x0000 ; source offset is 0 + mov ax, #(SMBIOS_PHYSICAL_ADDRESS>>4) + mov ds, ax + mov si, #(SMBIOS_PHYSICAL_ADDRESS&15) cld rep movsb diff -r 491bed0350f1 -r 3c352bbc894d tools/ioemu/hw/pc.c --- a/tools/ioemu/hw/pc.c Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/ioemu/hw/pc.c Fri Apr 27 13:31:09 2007 +0100 @@ -922,12 +922,13 @@ static void pc_init1(uint64_t ram_size, #endif #else if (pci_enabled) { - void *scsi; - - scsi = lsi_scsi_init(pci_bus, -1); + void *scsi = NULL; for (i = 0; i < MAX_SCSI_DISKS ; i++) { - if (bs_table[i + MAX_DISKS]) - lsi_scsi_attach(scsi, bs_table[i + MAX_DISKS], -1); + if (!bs_table[i + MAX_DISKS]) + continue; + if (!scsi) + scsi = lsi_scsi_init(pci_bus, -1); + lsi_scsi_attach(scsi, bs_table[i + MAX_DISKS], -1); } } #endif /* !CONFIG_DM */ diff -r 491bed0350f1 -r 3c352bbc894d tools/libxc/xc_core_x86.c --- a/tools/libxc/xc_core_x86.c Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/libxc/xc_core_x86.c Fri Apr 27 13:31:09 2007 +0100 @@ -21,9 +21,9 @@ #include "xg_private.h" #include "xc_core.h" -static int max_gpfn(int xc_handle, domid_t domid) +static int nr_gpfns(int xc_handle, domid_t domid) { - return xc_memory_op(xc_handle, XENMEM_maximum_gpfn, &domid); + return xc_memory_op(xc_handle, XENMEM_maximum_gpfn, &domid) + 1; } int @@ -38,7 +38,7 @@ xc_core_arch_memory_map_get(int xc_handl xc_core_memory_map_t **mapp, unsigned int *nr_entries) { - unsigned long p2m_size = max_gpfn(xc_handle, info->domid); + unsigned long p2m_size = nr_gpfns(xc_handle, info->domid); xc_core_memory_map_t *map; map = malloc(sizeof(*map)); @@ -65,7 +65,7 @@ xc_core_arch_map_p2m(int xc_handle, xc_d xen_pfn_t *live_p2m_frame_list_list = NULL; xen_pfn_t *live_p2m_frame_list = NULL; uint32_t dom = info->domid; - unsigned long p2m_size = max_gpfn(xc_handle, info->domid); + unsigned long p2m_size = nr_gpfns(xc_handle, info->domid); int ret = -1; int err; diff -r 491bed0350f1 -r 3c352bbc894d tools/libxc/xc_dom_core.c --- a/tools/libxc/xc_dom_core.c Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/libxc/xc_dom_core.c Fri Apr 27 13:31:09 2007 +0100 @@ -209,13 +209,13 @@ size_t xc_dom_check_gzip(void *blob, siz unsigned char *gzlen; size_t unziplen; - if (strncmp(blob, "\037\213", 2)) + if ( strncmp(blob, "\037\213", 2) ) /* not gzipped */ return 0; gzlen = blob + ziplen - 4; unziplen = gzlen[3] << 24 | gzlen[2] << 16 | gzlen[1] << 8 | gzlen[0]; - if ( (unziplen < ziplen) || (unziplen > (ziplen * 8)) ) + if ( (unziplen < 0) || (unziplen > (1024*1024*1024)) ) /* 1GB limit */ { xc_dom_printf ("%s: size (zip %zd, unzip %zd) looks insane, skip gunzip\n", diff -r 491bed0350f1 -r 3c352bbc894d tools/libxc/xc_domain_save.c --- a/tools/libxc/xc_domain_save.c Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/libxc/xc_domain_save.c Fri Apr 27 13:31:09 2007 +0100 @@ -870,7 +870,7 @@ int xc_domain_save(int xc_handle, int io } /* Get the size of the P2M table */ - p2m_size = xc_memory_op(xc_handle, XENMEM_maximum_gpfn, &dom); + p2m_size = xc_memory_op(xc_handle, XENMEM_maximum_gpfn, &dom) + 1; /* Domain is still running at this point */ if ( live ) diff -r 491bed0350f1 -r 3c352bbc894d tools/libxc/xc_hvm_build.c --- a/tools/libxc/xc_hvm_build.c Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/libxc/xc_hvm_build.c Fri Apr 27 13:31:09 2007 +0100 @@ -47,20 +47,15 @@ static void build_e820map(void *e820_pag mem_size = HVM_BELOW_4G_RAM_END; } - /* 0x0-0x9F000: Ordinary RAM. */ + /* 0x0-0x9FC00: Ordinary RAM. */ e820entry[nr_map].addr = 0x0; - e820entry[nr_map].size = 0x9F000; + e820entry[nr_map].size = 0x9FC00; e820entry[nr_map].type = E820_RAM; nr_map++; - /* - * 0x9F000-0x9F800: SMBIOS tables. - * 0x9FC00-0xA0000: Extended BIOS Data Area (EBDA). - * TODO: SMBIOS tables should be moved higher (>=0xE0000). - * They are unusually low in our memory map: could cause problems? - */ - e820entry[nr_map].addr = 0x9F000; - e820entry[nr_map].size = 0x1000; + /* 0x9FC00-0xA0000: Extended BIOS Data Area (EBDA). */ + e820entry[nr_map].addr = 0x9FC00; + e820entry[nr_map].size = 0x400; e820entry[nr_map].type = E820_RESERVED; nr_map++; diff -r 491bed0350f1 -r 3c352bbc894d tools/python/xen/xend/XendAPI.py --- a/tools/python/xen/xend/XendAPI.py Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/python/xen/xend/XendAPI.py Fri Apr 27 13:31:09 2007 +0100 @@ -27,7 +27,7 @@ import xmlrpclib import xmlrpclib import XendDomain, XendDomainInfo, XendNode, XendDmesg -import XendLogging, XendTaskManager +import XendLogging, XendTaskManager, XendAPIStore from XendAPIVersion import * from XendAuthSessions import instance as auth_manager @@ -38,8 +38,8 @@ from XendTask import XendTask from XendTask import XendTask from XendPIFMetrics import XendPIFMetrics from XendVMMetrics import XendVMMetrics - -import XendPBD +from XendPIF import XendPIF +from XendPBD import XendPBD from XendAPIConstants import * from xen.util.xmlrpclib2 import stringify @@ -237,6 +237,8 @@ def catch_typeerror(func): finally: del tb raise + except XendAPIError, exn: + return xen_api_error(exn.get_api_error()) return f @@ -307,26 +309,6 @@ 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. - - @param func: function with params: (self, session, network_ref, ...) - @rtype: callable object - """ - return lambda *args, **kwargs: \ - _check_ref(XendNode.instance().is_valid_network, - 'network', func, *args, **kwargs) - def valid_vbd(func): """Decorator to verify if vbd_ref is valid before calling method. @@ -409,39 +391,6 @@ def valid_sr(func): _check_ref(lambda r: XendNode.instance().is_valid_sr, 'SR', func, *args, **kwargs) -def valid_pbd(func): - """Decorator to verify if pbd_ref is valid before calling - method. - - @param func: function with params: (self, session, pbd_ref) - @rtype: callable object - """ - return lambda *args, **kwargs: \ - _check_ref(lambda r: r in XendPBD.get_all_refs(), - 'PBD', func, *args, **kwargs) - -def valid_pif(func): - """Decorator to verify if pif_ref is valid before calling - method. - - @param func: function with params: (self, session, pif_ref) - @rtype: callable object - """ - return lambda *args, **kwargs: \ - _check_ref(lambda r: r in XendNode.instance().pifs, - 'PIF', func, *args, **kwargs) - -def valid_pif_metrics(func): - """Decorator to verify if pif_metrics_ref is valid before calling - method. - - @param func: function with params: (self, session, pif_metrics_ref) - @rtype: callable object - """ - return lambda *args, **kwargs: \ - _check_ref(lambda r: r in XendNode.instance().pif_metrics, - 'PIF_metrics', func, *args, **kwargs) - def valid_task(func): """Decorator to verify if task_ref is valid before calling method. @@ -463,6 +412,20 @@ def valid_debug(func): return lambda *args, **kwargs: \ _check_ref(lambda r: r in XendAPI._debug, 'debug', func, *args, **kwargs) + + +def valid_object(class_name): + """Decorator to verify if object is valid before calling + method. + + @param func: function with params: (self, session, pif_ref) + @rtype: callable object + """ + return lambda func: \ + lambda *args, **kwargs: \ + _check_ref(lambda r: \ + XendAPIStore.get(r, class_name) is not None, + 'PIF', func, *args, **kwargs) # ----------------------------- # Bridge to Legacy XM API calls @@ -494,9 +457,7 @@ classes = { 'host' : valid_host, 'host_cpu' : valid_host_cpu, '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, @@ -505,20 +466,22 @@ classes = { 'VTPM' : valid_vtpm, 'console' : valid_console, 'SR' : valid_sr, - 'PBD' : valid_pbd, - 'PIF' : valid_pif, - 'PIF_metrics' : valid_pif_metrics, 'task' : valid_task, 'debug' : valid_debug, + 'network' : valid_object("network"), + 'PIF' : valid_object("PIF"), + 'VM_metrics' : valid_object("VM_metrics"), + 'PBD' : valid_object("PBD"), + 'PIF_metrics' : valid_object("PIF_metrics") } autoplug_classes = { 'network' : XendNetwork, + 'PIF' : XendPIF, 'VM_metrics' : XendVMMetrics, - 'PBD' : XendPBD.XendPBD, + 'PBD' : XendPBD, 'PIF_metrics' : XendPIFMetrics, } - class XendAPI(object): """Implementation of the Xen-API in Xend. Expects to be @@ -570,7 +533,9 @@ class XendAPI(object): # all get_by_uuid() methods. for api_cls in classes.keys(): - if api_cls == 'session': + # We'll let the autoplug classes implement these functions + # themselves - its much cleaner to do it in the base class + if api_cls == 'session' or api_cls in autoplug_classes.keys(): continue get_by_uuid = '%s_get_by_uuid' % api_cls @@ -599,34 +564,48 @@ class XendAPI(object): # -------------------- # These have all of their methods grabbed out from the implementation # class, and wrapped up to be compatible with the Xen-API. + + def getter(ref, type): + return XendAPIStore.get(ref, type) for api_cls, impl_cls in autoplug_classes.items(): - def doit(n): - getter = getattr(cls, '_%s_get' % api_cls) + def doit(n): dot_n = '%s.%s' % (api_cls, n) full_n = '%s_%s' % (api_cls, n) if not hasattr(cls, full_n): f = getattr(impl_cls, n) argcounts[dot_n] = f.func_code.co_argcount + 1 - setattr(cls, full_n, + g = lambda api_cls: \ + setattr(cls, full_n, \ lambda s, session, ref, *args: \ xen_api_success( \ - f(getter(s, session, ref), *args))) - - ro_attrs = getattr(cls, '%s_attr_ro' % api_cls, []) - rw_attrs = getattr(cls, '%s_attr_rw' % api_cls, []) - methods = getattr(cls, '%s_methods' % api_cls, []) - funcs = getattr(cls, '%s_funcs' % api_cls, []) + f(getter(ref, api_cls), *args))) + g(api_cls) # Force api_cls to be captured + + def doit_func(n): + dot_n = '%s.%s' % (api_cls, n) + full_n = '%s_%s' % (api_cls, n) + if not hasattr(cls, full_n): + f = getattr(impl_cls, n) + argcounts[dot_n] = f.func_code.co_argcount + setattr(cls, full_n, \ + lambda s, session, *args: \ + xen_api_success( \ + f(*args))) + + ro_attrs = impl_cls.getAttrRO() + rw_attrs = impl_cls.getAttrRW() + methods = impl_cls.getMethods() + funcs = impl_cls.getFuncs() for attr_name in ro_attrs + rw_attrs: doit('get_%s' % attr_name) - for attr_name in rw_attrs + cls.Base_attr_rw: + for attr_name in rw_attrs: doit('set_%s' % attr_name) - for method_name, return_type in methods + cls.Base_methods: - doit('%s' % method_name) - for func_name, return_type in funcs + cls.Base_funcs: - doit('%s' % func_name) - + for method in methods: + doit('%s' % method) + for func in funcs: + doit_func('%s' % func) def wrap_method(name, new_f): try: @@ -692,31 +671,42 @@ class XendAPI(object): except AttributeError: log.warn("API call: %s not found" % n) - - ro_attrs = getattr(cls, '%s_attr_ro' % api_cls, []) - rw_attrs = getattr(cls, '%s_attr_rw' % api_cls, []) - methods = getattr(cls, '%s_methods' % api_cls, []) - funcs = getattr(cls, '%s_funcs' % api_cls, []) + if api_cls in autoplug_classes.keys(): + impl_cls = autoplug_classes[api_cls] + ro_attrs = impl_cls.getAttrRO() + rw_attrs = impl_cls.getAttrRW() + methods = map(lambda x: (x, ""), impl_cls.getMethods()) + funcs = map(lambda x: (x, ""), impl_cls.getFuncs()) + else: + ro_attrs = getattr(cls, '%s_attr_ro' % api_cls, []) \ + + cls.Base_attr_ro + rw_attrs = getattr(cls, '%s_attr_rw' % api_cls, []) \ + + cls.Base_attr_rw + methods = getattr(cls, '%s_methods' % api_cls, []) \ + + cls.Base_methods + funcs = getattr(cls, '%s_funcs' % api_cls, []) \ + + cls.Base_funcs # wrap validators around readable class attributes - for attr_name in ro_attrs + rw_attrs + cls.Base_attr_ro: + for attr_name in ro_attrs + rw_attrs: doit('%s.get_%s' % (api_cls, attr_name), True, async_support = False) # wrap validators around writable class attrributes - for attr_name in rw_attrs + cls.Base_attr_rw: + for attr_name in rw_attrs: doit('%s.set_%s' % (api_cls, attr_name), True, async_support = False) setter_event_wrapper(api_cls, attr_name) # wrap validators around methods - for method_name, return_type in methods + cls.Base_methods: + for method_name, return_type in methods: doit('%s.%s' % (api_cls, method_name), True, async_support = True) # wrap validators around class functions - for func_name, return_type in funcs + cls.Base_funcs: - doit('%s.%s' % (api_cls, func_name), False, async_support = True, + for func_name, return_type in funcs: + doit('%s.%s' % (api_cls, func_name), False, + async_support = True, return_type = return_type) ctor_event_wrapper(api_cls) @@ -952,7 +942,7 @@ class XendAPI(object): def host_get_resident_VMs(self, session, host_ref): return xen_api_success(XendDomain.instance().get_domain_refs()) def host_get_PBDs(self, _, ref): - return xen_api_success(XendPBD.get_all_refs()) + return xen_api_success(XendPBD.get_all()) def host_get_PIFs(self, session, ref): return xen_api_success(XendNode.instance().get_PIF_refs()) def host_get_host_CPUs(self, session, host_ref): @@ -1130,130 +1120,6 @@ class XendAPI(object): def _host_metrics_get_memory_free(self): node = XendNode.instance() return node.xc.physinfo()['free_memory'] * 1024 - - - # Xen API: Class network - # ---------------------------------------------------------------- - - network_attr_ro = ['VIFs', 'PIFs'] - network_attr_rw = ['name_label', - 'name_description', - 'other_config'] - network_methods = [('add_to_other_config', None), - ('remove_from_other_config', None), - ('destroy', None)] - network_funcs = [('create', None)] - - def _network_get(self, _, ref): - return XendNode.instance().get_network(ref) - - def network_get_all(self, _): - return xen_api_success(XendNode.instance().get_network_refs()) - - def network_create(self, _, record): - return xen_api_success(XendNode.instance().network_create(record)) - - def network_destroy(self, _, ref): - return xen_api_success(XendNode.instance().network_destroy(ref)) - - - # Xen API: Class PIF - # ---------------------------------------------------------------- - - PIF_attr_ro = ['network', - 'host', - 'metrics'] - PIF_attr_rw = ['device', - 'MAC', - 'MTU', - 'VLAN'] - - PIF_attr_inst = PIF_attr_rw - - PIF_methods = [('create_VLAN', 'int'), ('destroy', None)] - - def _get_PIF(self, ref): - return XendNode.instance().pifs[ref] - - def PIF_destroy(self, _, ref): - try: - return xen_api_success(XendNode.instance().PIF_destroy(ref)) - except PIFIsPhysical, exn: - return xen_api_error(['PIF_IS_PHYSICAL', ref]) - - # object methods - def PIF_get_record(self, _, ref): - return xen_api_success(self._get_PIF(ref).get_record()) - - def PIF_get_all(self, _): - return xen_api_success(XendNode.instance().pifs.keys()) - - def PIF_get_metrics(self, _, ref): - return xen_api_success(self._get_PIF(ref).metrics.uuid) - - def PIF_get_device(self, _, ref): - return xen_api_success(self._get_PIF(ref).device) - - def PIF_get_network(self, _, ref): - return xen_api_success(self._get_PIF(ref).network.uuid) - - def PIF_get_host(self, _, ref): - return xen_api_success(self._get_PIF(ref).host.uuid) - - def PIF_get_MAC(self, _, ref): - return xen_api_success(self._get_PIF(ref).mac) - - def PIF_get_MTU(self, _, ref): - return xen_api_success(self._get_PIF(ref).mtu) - - def PIF_get_VLAN(self, _, ref): - return xen_api_success(self._get_PIF(ref).vlan) - - def PIF_set_device(self, _, ref, device): - return xen_api_success(self._get_PIF(ref).set_device(device)) - - def PIF_set_MAC(self, _, ref, mac): - return xen_api_success(self._get_PIF(ref).set_mac(mac)) - - def PIF_set_MTU(self, _, ref, mtu): - return xen_api_success(self._get_PIF(ref).set_mtu(mtu)) - - def PIF_create_VLAN(self, _, ref, network, vlan): - try: - vlan = int(vlan) - except: - return xen_api_error(['VLAN_TAG_INVALID', vlan]) - - try: - node = XendNode.instance() - - if _is_valid_ref(network, node.is_valid_network): - return xen_api_success( - node.PIF_create_VLAN(ref, network, vlan)) - else: - return xen_api_error(['HANDLE_INVALID', 'network', network]) - except NetworkAlreadyConnected, exn: - return xen_api_error(['NETWORK_ALREADY_CONNECTED', - network, exn.pif_uuid]) - except VLANTagInvalid: - return xen_api_error(['VLAN_TAG_INVALID', vlan]) - - - # Xen API: Class PIF_metrics - # ---------------------------------------------------------------- - - PIF_metrics_attr_ro = ['io_read_kbs', - 'io_write_kbs', - 'last_updated'] - PIF_metrics_attr_rw = [] - PIF_metrics_methods = [] - - def PIF_metrics_get_all(self, _): - return xen_api_success(XendNode.instance().pif_metrics.keys()) - - def _PIF_metrics_get(self, _, ref): - return XendNode.instance().pif_metrics[ref] - # Xen API: Class VM # ---------------------------------------------------------------- @@ -1865,28 +1731,6 @@ class XendAPI(object): return xen_api_success_void() - # Xen API: Class VM_metrics - # ---------------------------------------------------------------- - - VM_metrics_attr_ro = ['memory_actual', - 'VCPUs_number', - 'VCPUs_utilisation', - 'VCPUs_CPU', - 'VCPUs_flags', - 'VCPUs_params', - 'state', - 'start_time', - 'last_updated'] - VM_metrics_attr_rw = [] - VM_metrics_methods = [] - - 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()) - - # Xen API: Class VBD # ---------------------------------------------------------------- @@ -2570,33 +2414,6 @@ class XendAPI(object): return xen_api_success_void() - # Xen API: Class PBD - # ---------------------------------------------------------------- - - PBD_attr_ro = ['host', - 'SR', - 'device_config', - 'currently_attached'] - PBD_attr_rw = [] - PBD_methods = [('destroy', None)] - PBD_funcs = [('create', None)] - - def PBD_get_all(self, _): - return xen_api_success(XendPBD.get_all_refs()) - - def _PBD_get(self, _, ref): - return XendPBD.get(ref) - - def PBD_create(self, _, record): - if 'uuid' in record: - return xen_api_error(['VALUE_NOT_SUPPORTED', - 'uuid', record['uuid'], - 'You may not specify a UUID on creation']) - new_uuid = XendPBD.XendPBD(record).get_uuid() - XendNode.instance().save() - return xen_api_success(new_uuid) - - # Xen API: Class event # ---------------------------------------------------------------- diff -r 491bed0350f1 -r 3c352bbc894d tools/python/xen/xend/XendAPIStore.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/xend/XendAPIStore.py Fri Apr 27 13:31:09 2007 +0100 @@ -0,0 +1,59 @@ +#============================================================================ +# 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 <tom.wilkie@xxxxxxxxx> +#============================================================================ +""" +This is a place to put instances of XenAPI objects, +instead of just holding them in arbitrary places. + +All objects which subclass XendBase should use this +mechanism. + +You must register both the uuid and type, and get objects +by type, to ensure safety +""" + +__classes = {} + +def register(uuid, type, inst): + __classes[(uuid, type)] = inst + return inst + +def deregister(uuid, type): + old = get(uuid, type) + del __classes[(uuid, type)] + return old + +def get(uuid, type): + """ + Get the instances by uuid and type + """ + return __classes.get((uuid, type), None) + +def get_all(all_type): + """ + Get all instances by type + """ + return [inst + for ((uuid, t), inst) in __classes.items() + if t == all_type] + +def get_all_uuid(all_type): + """ + Get all uuids by type + """ + return [uuid + for (uuid, t) in __classes.keys() + if t == all_type] diff -r 491bed0350f1 -r 3c352bbc894d tools/python/xen/xend/XendBase.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/xend/XendBase.py Fri Apr 27 13:31:09 2007 +0100 @@ -0,0 +1,126 @@ +#!/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 <tom.wilkie@xxxxxxxxx> +#============================================================================ +""" +Base class for all XenAPI classes +""" + +from xen.xend.XendError import * +from xen.xend import XendAPIStore + +class XendBase: + # + # These functions describe the object, and what is exposed via the API + # + def getClass(self): + return "Base" + + def getAttrRO(self): + return ['uuid'] + + def getAttrRW(self): + return [] + + def getAttrInst(self): + return [] + + def getMethods(self): + return ["get_record"] + + def getFuncs(self): + return ["get_all", "get_by_uuid", "get_all_records"] + + getClass = classmethod(getClass) + getAttrRO = classmethod(getAttrRO) + getAttrRW = classmethod(getAttrRW) + getAttrInst = classmethod(getAttrInst) + getMethods = classmethod(getMethods) + getFuncs = classmethod(getFuncs) + + def __init__(self, uuid, record): + self.__uuid = uuid + + # First check this class implements all the correct methods: + for attr_ro in self.getAttrRO() + self.getAttrRW(): + if not hasattr(self, "get_%s" % attr_ro): + raise ImplementationError(self.getClass(), + "get_%s" % attr_ro) + + for attr_rw in self.getAttrRW(): + if not hasattr(self, "set_%s" % attr_rw): + raise ImplementationError(self.getClass(), + "set_%s" % attr_rw) + + for method in self.getMethods(): + if not hasattr(self, method): + raise ImplementationError(self.getClass(), + method) + + for func in self.getFuncs(): + if not hasattr(self.__class__, func): + raise ImplementationError(self.getClass(), + func) + + # Next check that the class is being created with the correct + # parameters + if not isinstance(record, dict): + raise CreateUnspecifiedAttributeError( + "record" , self.getClass()) + + for attr_inst in self.getAttrInst(): + if attr_inst not in record: + raise CreateUnspecifiedAttributeError( + attr_inst, self.getClass()) + setattr(self, attr_inst, record[attr_inst]) + + # Finally register it + XendAPIStore.register(uuid, self.getClass(), self) + + def destroy(self): + XendAPIStore.deregister(self.get_uuid(), self.getClass()) + + def get_uuid(self): + return self.__uuid + + def get_record(self): + keys = self.getAttrRO() + self.getAttrRW() + return dict([(key, getattr(self, "get_%s" % key)()) + for key in keys]) + + # + # Class methods + # + + def get_all(cls): + return XendAPIStore.get_all_uuid(cls.getClass()) + + def get_by_uuid(cls, uuid): + # Sanity check the uuid is one of us + me = XendAPIStore.get(uuid, cls.getClass()) + if me is not None and me.getClass() == cls.getClass(): + # In OSS, ref == uuid + return uuid + else: + raise "Big Error.. TODO!" + + def get_all_records(cls): + return [inst.get_record() + for inst in XendAPIStore.get_all(cls.getClass())] + + get_all = classmethod(get_all) + get_by_uuid = classmethod(get_by_uuid) + get_all_records = classmethod(get_all_records) diff -r 491bed0350f1 -r 3c352bbc894d tools/python/xen/xend/XendConfig.py --- a/tools/python/xen/xend/XendConfig.py Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/python/xen/xend/XendConfig.py Fri Apr 27 13:31:09 2007 +0100 @@ -22,6 +22,7 @@ import types from xen.xend import sxp from xen.xend import uuid +from xen.xend import XendAPIStore from xen.xend.XendError import VmError from xen.xend.XendDevices import XendDevices from xen.xend.PrettyPrint import prettyprintstring @@ -341,7 +342,7 @@ class XendConfig(dict): # try and 'fix it up' but acutually fix the cause ;-) # def _memory_sanity_check(self): - log.debug("_memory_sanity_check memory_static_min: %s, " + log.trace("_memory_sanity_check memory_static_min: %s, " "memory_static_max: %i, " "memory_dynamic_min: %i, " "memory_dynamic_max: %i", @@ -1049,6 +1050,10 @@ class XendConfig(dict): dev_info['type'] = cfg_xenapi.get('type') if cfg_xenapi.get('name'): dev_info['name'] = cfg_xenapi.get('name') + if cfg_xenapi.get('network'): + network = XendAPIStore.get( + cfg_xenapi.get('network'), 'network') + dev_info['bridge'] = network.get_name_label() dev_uuid = cfg_xenapi.get('uuid', None) if not dev_uuid: diff -r 491bed0350f1 -r 3c352bbc894d tools/python/xen/xend/XendDomain.py --- a/tools/python/xen/xend/XendDomain.py Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/python/xen/xend/XendDomain.py Fri Apr 27 13:31:09 2007 +0100 @@ -293,10 +293,12 @@ class XendDomain: width = 78) finally: f.close() + try: - os.rename(fn, self._managed_config_path(dom_uuid)) + shutil.move(fn, self._managed_config_path(dom_uuid)) except: - log.exception("Renaming %s" % fn) + log.exception("Renaming %s to %s", fn, + self._managed_config_path(dom_uuid)) os.remove(fn) except: log.exception("Error occurred saving configuration file " + diff -r 491bed0350f1 -r 3c352bbc894d tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/python/xen/xend/XendDomainInfo.py Fri Apr 27 13:31:09 2007 +0100 @@ -1820,7 +1820,7 @@ class XendDomainInfo: log.info("Unmounting %s from %s." % (fn, BOOTLOADER_LOOPBACK_DEVICE)) - dom0.destroyDevice('tap', '/dev/xvdp') + dom0.destroyDevice('tap', BOOTLOADER_LOOPBACK_DEVICE) if blcfg is None: msg = "Had a bootloader specified, but can't find disk" @@ -2246,9 +2246,18 @@ class XendDomainInfo: if not config.has_key('network'): try: + bridge = config.get('bridge', None) + if bridge is None: + from xen.util import Brctl + if_to_br = dict([(i,b) + for (b,ifs) in Brctl.get_state().items() + for i in ifs]) + vifname = "vif%s.%s" % (self.getDomid(), + config.get('id')) + bridge = if_to_br.get(vifname, None) config['network'] = \ XendNode.instance().bridge_to_network( - config.get('bridge')).uuid + config.get('bridge')).get_uuid() except Exception: log.exception('bridge_to_network') # Ignore this for now -- it may happen if the device diff -r 491bed0350f1 -r 3c352bbc894d tools/python/xen/xend/XendError.py --- a/tools/python/xen/xend/XendError.py Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/python/xen/xend/XendError.py Fri Apr 27 13:31:09 2007 +0100 @@ -48,10 +48,6 @@ class PIFIsPhysical(XendError): def __init__(self): XendError.__init__(self, 'PIF is physical') -class VLANTagInvalid(XendError): - def __init__(self): - XendError.__init__(self, 'VLAN tag invalid') - class VmError(XendError): """Vm construction error.""" pass @@ -62,7 +58,123 @@ class HVMRequired(VmError): 'HVM guest support is unavailable: is VT/AMD-V ' 'supported by your CPU and enabled in your BIOS?') +class XendAPIError(XendError): + """Extend this class for all error thrown by + autoplugged classes""" + def __init__(self): + XendError.__init__(self, 'XendAPI Error: You should never see this' + ' message; this class need to be overidden') + def get_api_error(self): + return ['INTERNAL_ERROR', 'You should never see this message; ' + 'this method needs to be overidden'] + +class CreateUnspecifiedAttributeError(XendAPIError): + def __init__(self, attr_name, class_name): + XendAPIError.__init__(self) + self.attr_name = attr_name + self.class_name = class_name + + def get_api_error(self): + return ['CREATE_UNSPECIFIED_ATTRIBUTE', self.attr_name, + self.class_name] + + def __str__(self): + return "CREATE_UNSPECIFIED_ATTRIBUTE: %s, %s" % (self.attr_name, + self.class_name) + +class UnmanagedNetworkError(XendAPIError): + def __init__(self, attr_name): + XendAPIError.__init__(self) + self.attr_name = attr_name + + def get_api_error(self): + return ['UNMANAGED_NETWORK_ERROR', self.attr_name] + + def __str__(self): + return "UNMANAGED_NETWORK_ERROR: %s" % self.attr_name + +class UniqueNameError(XendAPIError): + def __init__(self, name, class_name): + XendAPIError.__init__(self) + self.name = name + self.class_name = class_name + + def get_api_error(self): + return ['UNIQUE_NAME_ERROR', self.name, self.class_name] + + def __str__(self): + return 'UNIQUE_NAME_ERROR: %s, %s' % (self.name, self.class_name) + +class InvalidDeviceError(XendAPIError): + def __init__(self, dev): + XendAPIError.__init__(self) + self.dev = dev + + def get_api_error(self): + return ['INVALID_DEVICE_ERROR', self.dev] + + def __str__(self): + return 'INVALID_DEVICE_ERROR: %s' % self.dev + +class DeviceExistsError(XendAPIError): + def __init__(self, dev): + XendAPIError.__init__(self) + self.dev = dev + + def get_api_error(self): + return ['DEVICE_EXISTS_ERROR', self.dev] + + def __str__(self): + return 'DEVICE_EXISTS_ERROR: %s' % self.dev + +class InvalidHandleError(XendAPIError): + def __init__(self, klass, handle): + XendAPIError.__init__(self) + self.klass = klass + self.handle = handle + + def get_api_error(self): + return ['HANDLE_INVALID', self.klass, self.handle] + + def __str__(self): + return 'HANDLE_INVALID: %s %s' % (self.klass, self.handle) + +class ImplementationError(XendAPIError): + def __init__(self, klass, func): + XendAPIError.__init__(self) + self.klass = klass + self.func = func + + def get_api_error(self): + return ['IMPLEMENTATION_ERROR', self.klass, self.func] + + def __str__(self): + return 'IMPLEMENTATION_ERROR: %s %s' % (self.klass, self.func) + +class VLANTagInvalid(XendAPIError): + def __init__(self, vlan): + XendAPIError.__init__(self) + self.vlan = vlan + + def get_api_error(self): + return ['VLAN_TAG_INVALID', self.vlan] + + def __str__(self): + return 'VLAN_TAG_INVALID: %s' % self.vlan + +class NetworkError(XendAPIError): + def __init__(self, error, network): + XendAPIError.__init__(self) + self.network = network + self.error = error + + def get_api_error(self): + return ['NETWORK_ERROR', self.error, self.network] + + def __str__(self): + return 'NETWORK_ERROR: %s %s' % (self.error, self.network) + XEND_ERROR_AUTHENTICATION_FAILED = ('ELUSER', 'Authentication Failed') XEND_ERROR_SESSION_INVALID = ('EPERMDENIED', 'Session Invalid') XEND_ERROR_DOMAIN_INVALID = ('EINVALIDDOMAIN', 'Domain Invalid') diff -r 491bed0350f1 -r 3c352bbc894d tools/python/xen/xend/XendNetwork.py --- a/tools/python/xen/xend/XendNetwork.py Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/python/xen/xend/XendNetwork.py Fri Apr 27 13:31:09 2007 +0100 @@ -24,15 +24,139 @@ import XendDomain import XendDomain import XendNode from XendLogging import log +from xen.xend import uuid as genuuid +from xen.xend.XendBase import XendBase +from xen.xend.XendError import * +from xen.util import Brctl +from xen.xend import XendAPIStore IP_ROUTE_RE = r'^default via ([\d\.]+) dev (\w+)' -class XendNetwork: - def __init__(self, uuid, record): - self.uuid = uuid - self.name_label = record.get('name_label', '') - self.name_description = record.get('name_description', '') - self.other_config = record.get('other_config', {}) +def bridge_exists(name): + return name in Brctl.get_state().keys() + +class XendNetwork(XendBase): + """We're going to assert that the name_label of this + network is just the name of the bridge""" + + def getClass(self): + return "network" + + def getAttrRW(self): + attrRW = ['name_label', + 'name_description', + 'other_config', + 'default_gateway', + 'default_netmask'] + return XendBase.getAttrRW() + attrRW + + def getAttrRO(self): + attrRO = ['VIFs', + 'PIFs'] + return XendBase.getAttrRO() + attrRO + + def getAttrInst(self): + return XendBase.getAttrInst() + self.getAttrRW() + + def getMethods(self): + methods = ['add_to_other_config', + 'remove_from_other_config', + 'destroy'] + return XendBase.getMethods() + methods + + def getFuncs(self): + funcs = ['create'] + return XendBase.getFuncs() + funcs + + getClass = classmethod(getClass) + getAttrRO = classmethod(getAttrRO) + getAttrRW = classmethod(getAttrRW) + getAttrInst = classmethod(getAttrInst) + getMethods = classmethod(getMethods) + getFuncs = classmethod(getFuncs) + + def create_phy(self, name): + """ + Called when a new bridge is found on xend start + """ + # Create new uuids + uuid = genuuid.createString() + + # Create instance + record = { + 'name_label': name, + 'name_description': '', + 'other_config': {}, + 'default_gateway': '', + 'default_netmask': '' + } + network = XendNetwork(record, uuid) + + return uuid + + def recreate(self, record, uuid): + """ + Called on xend start / restart, or machine + restart, when read from saved config. + Needs to check network exists, create it otherwise + """ + + # Create instance (do this first, to check record) + network = XendNetwork(record, uuid) + + # Create network if it doesn't already exist + if not bridge_exists(network.name_label): + Brctl.bridge_create(network.name_label) + + return uuid + + def create(self, record): + """ + Called from API, to create a new network + """ + # Create new uuids + uuid = genuuid.createString() + + # Create instance (do this first, to check record) + network = XendNetwork(record, uuid) + + # Check network doesn't already exist + name_label = network.name_label + if bridge_exists(name_label): + del network + raise UniqueNameError(name_label, "network") + + # Create the bridge + Brctl.bridge_create(network.name_label) + + XendNode.instance().save_networks() + + return uuid + + create_phy = classmethod(create_phy) + recreate = classmethod(recreate) + create = classmethod(create) + + def __init__(self, record, uuid): + XendBase.__init__(self, uuid, record) + + # + # XenAPI Mehtods + # + + def destroy(self): + # check no VIFs or PIFs attached + if len(self.get_VIFs()) > 0: + raise NetworkError("Cannot destroy network with VIFs attached", + self.get_name_label()) + + if len(self.get_PIFs()) > 0: + raise NetworkError("Cannot destroy network with PIFs attached", + self.get_name_label()) + + XendBase.destroy(self) + Brctl.bridge_del(self.get_name_label()) + XendNode.instance().save_networks() def get_name_label(self): return self.name_label @@ -41,9 +165,8 @@ class XendNetwork: return self.name_description def set_name_label(self, new_name): - self.name_label = new_name - XendNode.instance().save_networks() - + pass + def set_name_description(self, new_desc): self.name_description = new_desc XendNode.instance().save_networks() @@ -55,13 +178,14 @@ class XendNetwork: vifs = vm.get_vifs() for vif in vifs: vif_cfg = vm.get_dev_xenapi_config('vif', vif) - if vif_cfg.get('network') == self.uuid: + if vif_cfg.get('network') == self.get_uuid(): result.append(vif) return result def get_PIFs(self): - return [x.uuid for x in XendNode.instance().pifs.values() - if x.network == self] + pifs = XendAPIStore.get_all("PIF") + return [pif.get_uuid() for pif in pifs + if pif.get_network() == self.get_uuid()] def get_other_config(self): return self.other_config @@ -79,17 +203,16 @@ class XendNetwork: del self.other_config[key] XendNode.instance().save_networks() - def get_record(self): - return self.get_record_internal(True) - - def get_record_internal(self, transient): - result = { - 'uuid': self.uuid, - 'name_label': self.name_label, - 'name_description': self.name_description, - 'other_config' : self.other_config, - } - if transient: - result['VIFs'] = self.get_VIFs() - result['PIFs'] = self.get_PIFs() - return result + def get_default_gateway(self): + return self.default_gateway + + def set_default_gateway(self, gateway): + self.default_gateway = gateway + XendNode.instance().save_networks() + + def get_default_netmask(self): + return self.default_netmask + + def set_default_netmask(self, netmask): + self.default_netmask = netmask + XendNode.instance().save_networks() diff -r 491bed0350f1 -r 3c352bbc894d tools/python/xen/xend/XendNode.py --- a/tools/python/xen/xend/XendNode.py Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/python/xen/xend/XendNode.py Fri Apr 27 13:31:09 2007 +0100 @@ -21,9 +21,10 @@ import xen.lowlevel.xc import xen.lowlevel.xc from xen.util import Brctl +from xen.xend import XendAPIStore import uuid, arch -import XendPBD +from XendPBD import XendPBD from XendError import * from XendOptions import instance as xendoptions from XendQCoWStorageRepo import XendQCoWStorageRepo @@ -34,7 +35,7 @@ from XendNetwork import * from XendNetwork import * from XendStateStore import XendStateStore from XendMonitor import XendMonitor - + class XendNode: """XendNode - Represents a Domain 0 Host.""" @@ -133,70 +134,78 @@ class XendNode: 'features' : cpu_features, }) - self.pifs = {} - self.pif_metrics = {} - self.networks = {} self.srs = {} - - # initialise networks + + # Initialise networks + # First configure ones off disk saved_networks = self.state_store.load_state('network') if saved_networks: for net_uuid, network in saved_networks.items(): - self.network_create(network, False, net_uuid) - else: - bridges = Brctl.get_state().keys() - for bridge in bridges: - self.network_create({'name_label' : bridge }, False) + try: + XendNetwork.recreate(network, net_uuid) + except CreateUnspecifiedAttributeError: + log.warn("Error recreating network %s", net_uuid) - # Get a mapping from interface to bridge - - if_to_br = dict([(i,b) - for (b,ifs) in Brctl.get_state().items() - for i in ifs]) - - # initialise PIFs + # Next discover any existing bridges and check + # they are not already configured + bridges = Brctl.get_state().keys() + configured_bridges = [XendAPIStore.get( + network_uuid, "network") + .get_name_label() + for network_uuid in XendNetwork.get_all()] + unconfigured_bridges = [bridge + for bridge in bridges + if bridge not in configured_bridges] + for unconfigured_bridge in unconfigured_bridges: + XendNetwork.create_phy(unconfigured_bridge) + + # Initialise PIFs + # First configure ones off disk saved_pifs = self.state_store.load_state('pif') if saved_pifs: for pif_uuid, pif in saved_pifs.items(): - if pif.get('network') in self.networks: - network = self.networks[pif['network']] - try: - if 'device' not in pif and 'name' in pif: - # Compatibility hack, can go pretty soon. - pif['device'] = pif['name'] - if 'metrics' not in pif: - # Compatibility hack, can go pretty soon. - pif['metrics'] = uuid.createString() - - try: - pif['VLAN'] = int(pif.get('VLAN', -1)) - except (ValueError, TypeError): - pif['VLAN'] = -1 - - self._PIF_create(pif['device'], pif['MTU'], - pif['VLAN'], - pif['MAC'], network, False, pif_uuid, - pif['metrics']) - except NetworkAlreadyConnected, exn: - log.error('Cannot load saved PIF %s, as network %s ' + - 'is already connected to PIF %s', - pif_uuid, pif['network'], exn.pif_uuid) - else: - for name, mtu, mac in linux_get_phy_ifaces(): - bridge_name = if_to_br.get(name, None) - if bridge_name is not None: - networks = [network for - network in self.networks.values() - if network.get_name_label() == bridge_name] - if len(networks) > 0: - network = networks[0] - self._PIF_create(name, mtu, -1, mac, network, False) - + try: + XendPIF.recreate(pif, pif_uuid) + except CreateUnspecifiedAttributeError: + log.warn("Error recreating PIF %s", pif_uuid) + + # Next discover any existing PIFs and check + # they are not already configured + configured_pifs = [XendAPIStore.get( + pif_uuid, "PIF") + .get_interface_name() + for pif_uuid in XendPIF.get_all()] + unconfigured_pifs = [(name, mtu, mac) + for name, mtu, mac in linux_get_phy_ifaces() + if name not in configured_pifs] + + # Get a mapping from interface to bridge + if_to_br = dict([(i,b) + for (b,ifs) in Brctl.get_state().items() + for i in ifs]) + + for name, mtu, mac in unconfigured_pifs: + # Check PIF is on bridge + # if not, ignore + bridge_name = if_to_br.get(name, None) + if bridge_name is not None: + # Translate bridge name to network uuid + for network_uuid in XendNetwork.get_all(): + network = XendAPIStore.get( + network_uuid, 'network') + if network.get_name_label() == bridge_name: + XendPIF.create_phy(network_uuid, name, + mtu, mac) + break + else: + log.debug("Cannot find network for bridge %s " + "when configuring PIF %s", + (bridge_name, name)) + # initialise storage saved_srs = self.state_store.load_state('sr') if saved_srs: for sr_uuid, sr_cfg in saved_srs.items(): - log.error("SAved SRS %s %s", sr_uuid, sr_cfg['type']) if sr_cfg['type'] == 'qcow_file': self.srs[sr_uuid] = XendQCoWStorageRepo(sr_uuid) elif sr_cfg['type'] == 'local': @@ -214,69 +223,50 @@ class XendNode: saved_pbds = self.state_store.load_state('pbd') if saved_pbds: for pbd_uuid, pbd_cfg in saved_pbds.items(): - pbd_cfg['uuid'] = pbd_uuid - XendPBD.XendPBD(pbd_cfg) - - - def network_create(self, record, persist = True, net_uuid = None): - if net_uuid is None: - net_uuid = uuid.createString() - self.networks[net_uuid] = XendNetwork(net_uuid, record) - if persist: - self.save_networks() - return net_uuid - - - def network_destroy(self, net_uuid): - del self.networks[net_uuid] - self.save_networks() - - - def get_PIF_refs(self): - return self.pifs.keys() - - - def _PIF_create(self, name, mtu, vlan, mac, network, persist = True, - pif_uuid = None, metrics_uuid = None): - for pif in self.pifs.values(): - if pif.network == network: - raise NetworkAlreadyConnected(pif.uuid) - - if pif_uuid is None: - pif_uuid = uuid.createString() - if metrics_uuid is None: - metrics_uuid = uuid.createString() - - metrics = XendPIFMetrics(metrics_uuid) - pif = XendPIF(pif_uuid, metrics, name, mtu, vlan, mac, network, self) - metrics.set_PIF(pif) - - self.pif_metrics[metrics_uuid] = metrics - self.pifs[pif_uuid] = pif - - if persist: - self.save_PIFs() - self.refreshBridges() - return pif_uuid - - - def PIF_create_VLAN(self, pif_uuid, network_uuid, vlan): - if vlan < 0 or vlan >= 4096: - raise VLANTagInvalid() - - pif = self.pifs[pif_uuid] - network = self.networks[network_uuid] - return self._PIF_create(pif.device, pif.mtu, vlan, pif.mac, network) - - - def PIF_destroy(self, pif_uuid): - pif = self.pifs[pif_uuid] - - if pif.vlan == -1: - raise PIFIsPhysical() - - del self.pifs[pif_uuid] - self.save_PIFs() + try: + XendPBD.recreate(pbd_uuid, pbd_cfg) + except CreateUnspecifiedAttributeError: + log.warn("Error recreating PBD %s", pbd_uuid) + +## def network_destroy(self, net_uuid): + ## del self.networks[net_uuid] + ## self.save_networks() + + +## def get_PIF_refs(self): +## return self.pifs[:] + +## def _PIF_create(self, name, mtu, vlan, mac, network, persist = True, +## pif_uuid = None, metrics_uuid = None): +## for pif in self.pifs.values(): +## if pif.network == network: +## raise NetworkAlreadyConnected(pif.uuid) + +## if pif_uuid is None: +## pif_uuid = uuid.createString() +## if metrics_uuid is None: +## metrics_uuid = uuid.createString() + +## metrics = XendPIFMetrics(metrics_uuid) +## pif = XendPIF(pif_uuid, metrics, name, mtu, vlan, mac, network, self) +## metrics.set_PIF(pif) + +## self.pif_metrics[metrics_uuid] = metrics +## self.pifs[pif_uuid] = pif + +## if persist: +## self.save_PIFs() +## self.refreshBridges() +## return pif_uuid + +## def PIF_destroy(self, pif_uuid): +## pif = self.pifs[pif_uuid] + +## if pif.vlan == -1: +## raise PIFIsPhysical() + +## del self.pifs[pif_uuid] +## self.save_PIFs() def save(self): @@ -284,7 +274,7 @@ class XendNode: host_record = {self.uuid: {'name_label':self.name, 'name_description':self.desc, 'metrics_uuid': self.host_metrics_uuid, - 'other_config': repr(self.other_config)}} + 'other_config': self.other_config}} self.state_store.save_state('host',host_record) self.state_store.save_state('cpu', self.cpus) self.save_PIFs() @@ -293,18 +283,21 @@ class XendNode: self.save_SRs() def save_PIFs(self): - pif_records = dict([(k, v.get_record()) - for k, v in self.pifs.items()]) + pif_records = dict([(pif_uuid, XendAPIStore.get( + pif_uuid, "PIF").get_record()) + for pif_uuid in XendPIF.get_all()]) self.state_store.save_state('pif', pif_records) def save_networks(self): - net_records = dict([(k, v.get_record_internal(False)) - for k, v in self.networks.items()]) + net_records = dict([(network_uuid, XendAPIStore.get( + network_uuid, "network").get_record()) + for network_uuid in XendNetwork.get_all()]) self.state_store.save_state('network', net_records) def save_PBDs(self): - pbd_records = dict([(v.get_uuid(), v.get_record()) - for v in XendPBD.get_all()]) + pbd_records = dict([(pbd_uuid, XendAPIStore.get( + pbd_uuid, "PBD").get_record()) + for pbd_uuid in XendPBD.get_all()]) self.state_store.save_state('pbd', pbd_records) def save_SRs(self): @@ -330,9 +323,6 @@ class XendNode: def is_valid_cpu(self, cpu_ref): return (cpu_ref in self.cpus) - - def is_valid_network(self, network_ref): - return (network_ref in self.networks) def is_valid_sr(self, sr_ref): return (sr_ref in self.srs) @@ -495,12 +485,6 @@ class XendNode: # Network Functions # - def get_network_refs(self): - return self.networks.keys() - - def get_network(self, network_ref): - return self.networks[network_ref] - def bridge_to_network(self, bridge): """ Determine which network a particular bridge is attached to. @@ -518,13 +502,12 @@ class XendNode: raise Exception( 'Could not find default bridge, and none was specified') - bridges = Brctl.get_state() - if bridge not in bridges: - raise Exception('Bridge %s is not up' % bridge) - for pif in self.pifs.values(): - if pif.interface_name() in bridges[bridge]: - return pif.network - raise Exception('Bridge %s is not connected to a network' % bridge) + for network_uuid in XendNetwork.get_all(): + network = XendAPIStore.get(network_uuid, "network") + if network.get_name_label() == bridge: + return network + else: + raise Exception('Cannot find network for bridge %s' % bridge) # # Debug keys. @@ -641,12 +624,6 @@ class XendNode: return dict(self.physinfo()) def info_dict(self): return dict(self.info()) - - - def refreshBridges(self): - for pif in self.pifs.values(): - pif.refresh(Brctl.get_state()) - def parse_proc_cpuinfo(): cpuinfo = {} diff -r 491bed0350f1 -r 3c352bbc894d tools/python/xen/xend/XendPBD.py --- a/tools/python/xen/xend/XendPBD.py Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/python/xen/xend/XendPBD.py Fri Apr 27 13:31:09 2007 +0100 @@ -18,62 +18,82 @@ import uuid from XendLogging import log +from xen.xend.XendBase import XendBase +from xen.xend import XendAPIStore +class XendPBD(XendBase): + """Physical block devices.""" -attr_inst = ['uuid', - 'host', - 'SR', - 'device_config'] -attr_ro = attr_inst + ['currently_attached'] + def getClass(self): + return "PBD" + + def getAttrRO(self): + attrRO = ['host', + 'SR', + 'device_config', + 'currently_attached'] + return XendBase.getAttrRO() + attrRO + def getAttrRW(self): + attrRW = [] + return XendBase.getAttrRW() + attrRW -_all = {} + def getAttrInst(self): + return ['uuid', + 'host', + 'SR', + 'device_config'] + def getMethods(self): + methods = ['destroy'] + return XendBase.getMethods() + methods -def get(ref): - return _all[ref] + def getFuncs(self): + funcs = ['create', + 'get_by_SR'] + return XendBase.getFuncs() + funcs + getClass = classmethod(getClass) + getAttrRO = classmethod(getAttrRO) + getAttrRW = classmethod(getAttrRW) + getAttrInst = classmethod(getAttrInst) + getMethods = classmethod(getMethods) + getFuncs = classmethod(getFuncs) -def get_all(): - return _all.values() + def recreate(uuid, record): + pbd = XendPBD(uuid, record) + return uuid + + def create(cls, record): + uuid = genuuid.createString() + pbd = XendPBD(uuid, record) + return uuid + create = classmethod(create) + + def __init__(self, uuid, record): + XendBase.__init__(self, uuid, record) + this.currently_attached = True -def get_all_refs(): - return _all.keys() + def get_host(self): + return this.host + + def get_SR(self): + return this.SR + def get_device_config(self): + return this.device_config -def get_by_SR(sr_ref): - return [k for (k, v) in _all.items() if v.get_SR() == sr_ref] - - -class XendPBD: - """Physical block devices.""" - - def __init__(self, record): - if 'uuid' not in record: - record['uuid'] = uuid.createString() - - import XendAPI - for v in attr_inst: - setattr(self, v, record[v]) - self.currently_attached = True - _all[record['uuid']] = self - + def get_currently_attached(self): + return this.currently_attached def destroy(self): - if self.uuid in _all: - del _all[self.uuid] + pass + + def get_by_SR(cls, sr_ref): + pbds = XendAPIStore.get_all("PBD") + return [pbd.get_uuid() + for pbd in pbds + if pbd.get_SR() == sr_ref] - - def get_record(self): - import XendAPI - result = {} - for v in attr_ro: - result[v] = getattr(self, v) - return result - - -for v in attr_ro: - def f(v_): - setattr(XendPBD, 'get_' + v_, lambda s: getattr(s, v_)) - f(v) + get_by_SR = classmethod(get_by_SR) diff -r 491bed0350f1 -r 3c352bbc894d tools/python/xen/xend/XendPIF.py --- a/tools/python/xen/xend/XendPIF.py Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/python/xen/xend/XendPIF.py Fri Apr 27 13:31:09 2007 +0100 @@ -19,11 +19,14 @@ import logging import logging import os import re - +from xen.xend import uuid as genuuid +from xen.xend import XendAPIStore +from xen.xend.XendBase import XendBase +from xen.xend.XendPIFMetrics import XendPIFMetrics +from xen.xend.XendError import * log = logging.getLogger("xend.XendPIF") log.setLevel(logging.TRACE) - MAC_RE = re.compile(':'.join(['[0-9a-f]{2}'] * 6)) IP_IFACE_RE = re.compile(r'^\d+: (\w+):.*mtu (\d+) .* link/\w+ ([0-9a-f:]+)') @@ -87,106 +90,279 @@ def linux_set_mtu(iface, mtu): except ValueError: return False -class XendPIF: +def _create_VLAN(dev, vlan): + rc, _ = commands.getstatusoutput('vconfig add %s %d' % + (dev, vlan)) + if rc != 0: + return False + + rc, _ = commands.getstatusoutput('ifconfig %s.%d up' % + (dev, vlan)) + return rc == 0 + +def _destroy_VLAN(dev, vlan): + rc, _ = commands.getstatusoutput('ifconfig %s.%d down' % + (dev, vlan)) + if rc != 0: + return False + + rc, _ = commands.getstatusoutput('vconfig rem %s.%d' % + (dev, vlan)) + return rc == 0 + +class XendPIF(XendBase): """Representation of a Physical Network Interface.""" - - def __init__(self, uuid, metrics, device, mtu, vlan, mac, network, - host): - self.uuid = uuid - self.metrics = metrics - self.device = device - self.mac = mac - self.mtu = mtu - self.vlan = vlan - self.network = network - self.host = host - - def set_device(self, new_device): - self.device = new_device - - def set_mac(self, new_mac): - success = linux_set_mac(new_mac) + + def getClass(self): + return "PIF" + + def getAttrRO(self): + attrRO = ['network', + 'host', + 'metrics', + 'device', + 'VLAN'] + return XendBase.getAttrRO() + attrRO + + def getAttrRW(self): + attrRW = ['MAC', + 'MTU'] + return XendBase.getAttrRW() + attrRW + + def getAttrInst(self): + attrInst = ['network', + 'device', + 'MAC', + 'MTU', + 'VLAN'] + return attrInst + + def getMethods(self): + methods = ['plug', + 'unplug', + 'destroy'] + return XendBase.getMethods() + methods + + def getFuncs(self): + funcs = ['create_VLAN'] + return XendBase.getFuncs() + funcs + + getClass = classmethod(getClass) + getAttrRO = classmethod(getAttrRO) + getAttrRW = classmethod(getAttrRW) + getAttrInst = classmethod(getAttrInst) + getMethods = classmethod(getMethods) + getFuncs = classmethod(getFuncs) + + def create_phy(self, network_uuid, device, + MAC, MTU): + """ + Called when a new physical PIF is found + Could be a VLAN... + """ + # Create new uuids + pif_uuid = genuuid.createString() + metrics_uuid = genuuid.createString() + + # Create instances + metrics = XendPIFMetrics(metrics_uuid, pif_uuid) + + # Is this a VLAN? + VLANdot = device.split(".") + VLANcolon = device.split(":") + + if len(VLANdot) > 1: + VLAN = VLANdot[1] + device = VLANdot[0] + elif len(VLANcolon) > 1: + VLAN = VLANcolon[1] + device = VLANcolon[0] + else: + VLAN = -1 + + record = { + 'network': network_uuid, + 'device': device, + 'MAC': MAC, + 'MTU': MTU, + 'VLAN': VLAN + } + pif = XendPIF(record, pif_uuid, metrics_uuid) + + return pif_uuid + + def recreate(self, record, uuid): + """Called on xend start / restart""" + pif_uuid = uuid + metrics_uuid = record['metrics'] + + # Create instances + metrics = XendPIFMetrics(metrics_uuid, pif_uuid) + pif = XendPIF(record, pif_uuid, metrics_uuid) + + # If physical PIF, check exists + # If VLAN, create if not exist + ifs = [dev for dev, _1, _2 in linux_get_phy_ifaces()] + if pif.get_VLAN() == -1: + if pif.get_device() not in ifs: + pif.destroy() + metrics.destroy() + return None + else: + if pif.get_interface_name() not in ifs: + _create_VLAN(pif.get_device(), pif.get_VLAN()) + pif.plug() + + return pif_uuid + + def create_VLAN(self, device, network_uuid, host_ref, vlan): + """Exposed via API - create a new VLAN from existing VIF""" + + ifs = [name for name, _, _ in linux_get_phy_ifaces()] + + vlan = int(vlan) + + # Check VLAN tag is valid + if vlan < 0 or vlan >= 4096: + raise VLANTagInvalid(vlan) + + # Check device exists + if device not in ifs: + raise InvalidDeviceError(device) + + # Check VLAN doesn't already exist + if "%s.%d" % (device, vlan) in ifs: + raise DeviceExistsError("%s.%d" % (device, vlan)) + + # Check network ref is valid + from XendNetwork import XendNetwork + if network_uuid not in XendNetwork.get_all(): + raise InvalidHandleError("Network", network_uuid) + + # Check host_ref is this host + import XendNode + if host_ref != XendNode.instance().get_uuid(): + raise InvalidHandleError("Host", host_ref) + + # Create the VLAN + _create_VLAN(device, vlan) + + # Create new uuids + pif_uuid = genuuid.createString() + metrics_uuid = genuuid.createString() + + # Create the record + record = { + "device": device, + "MAC": '', + "MTU": '', + "network": network_uuid, + "VLAN": vlan + } + + # Create instances + metrics = XendPIFMetrics(metrics_uuid, pif_uuid) + pif = XendPIF(record, pif_uuid, metrics_uuid) + + # Not sure if they should be created plugged or not... + pif.plug() + + XendNode.instance().save_PIFs() + return pif_uuid + + create_phy = classmethod(create_phy) + recreate = classmethod(recreate) + create_VLAN = classmethod(create_VLAN) + + def __init__(self, record, uuid, metrics_uuid): + XendBase.__init__(self, uuid, record) + self.metrics = metrics_uuid + + def plug(self): + """Plug the PIF into the network""" + network = XendAPIStore.get(self.network, + "network") + bridge_name = network.get_name_label() + + from xen.util import Brctl + Brctl.vif_bridge_add({ + "bridge": bridge_name, + "vif": self.get_interface_name() + }) + + def unplug(self): + """Unplug the PIF from the network""" + network = XendAPIStore.get(self.network, + "network") + bridge_name = network.get_name_label() + + from xen.util import Brctl + Brctl.vif_bridge_rem({ + "bridge": bridge_name, + "vif": self.get_interface_name() + }) + + def destroy(self): + # Figure out if this is a physical device + if self.get_interface_name() == \ + self.get_device(): + raise PIFIsPhysical(self.get_uuid()) + + self.unplug() + + if _destroy_VLAN(self.get_device(), self.get_VLAN()): + XendBase.destroy(self) + import XendNode + XendNode.instance().save_PIFs() + else: + raise NetworkError("Unable to delete VLAN", self.get_uuid()) + + def get_interface_name(self): + if self.get_VLAN() == -1: + return self.get_device() + else: + return "%s.%d" % (self.get_device(), self.get_VLAN()) + + def get_device(self): + """ + This is the base interface. + For phy if (VLAN == -1) this is same as + if name. + For VLANs, this it the bit before the period + """ + return self.device + + def get_network(self): + return self.network + + def get_host(self): + from xen.xend import XendNode + return XendNode.instance().get_uuid() + + def get_metrics(self): + return self.metrics + + def get_MAC(self): + return self.MAC + + def set_MAC(self, new_mac): + success = linux_set_mac(self.device, new_mac) if success: - self.mac = new_mac + self.MAC = new_mac + import XendNode + XendNode.instance().save_PIFs() return success - def set_mtu(self, new_mtu): - success = linux_set_mtu(new_mtu) + def get_MTU(self): + return self.MTU + + def set_MTU(self, new_mtu): + success = linux_set_mtu(self.device, new_mtu) if success: - self.mtu = new_mtu + self.MTU = new_mtu + import XendNode + XendNode.instance().save_PIFs() return success - def get_record(self): - return {'uuid': self.uuid, - 'device': self.device, - 'MAC': self.mac, - 'MTU': self.mtu, - 'VLAN': self.vlan, - 'host': self.host.uuid, - 'network': self.network.uuid, - 'metrics': self.metrics.uuid} - - def refresh(self, bridges): - ifname = self.interface_name() - rc, _ = _cmd('ip link show %s', ifname) - if rc != 0: - # Interface does not exist. If it's a physical interface, then - # there's nothing we can do -- this should have been set up with - # the network script. Otherwise, we can use vconfig to derive - # a subinterface. - if self.vlan == -1: - return - - rc, _ = _cmd('vconfig add %s %d', self.device, self.vlan) - if rc != 0: - log.error('Could not refresh VLAN for interface %s', ifname) - return - - log.info('Created network interface %s', ifname) - - for brname, nics in bridges.items(): - if ifname in nics: - log.debug('%s is already attached to %s', ifname, brname) - return - - # The interface is not attached to a bridge. Create one, and attach - # the interface to it. - brname = _new_bridge_name(bridges) - rc, _ = _cmd('brctl addbr %s', brname) - if rc != 0: - log.error('Could not create bridge %s for interface %s', brname, - ifname) - return - log.info('Created network bridge %s', brname) - - rc, _ = _cmd('brctl addif %s %s', brname, ifname) - if rc != 0: - log.error('Could not add %s to %s', ifname, brname) - return - log.info('Added network interface %s to bridge %s', ifname, brname) - - - def interface_name(self): - if self.vlan != -1: - return '%s.%d' % (self.device, self.vlan) - else: - return self.device - - -def _cmd(cmd, *args): - if len(args) > 0: - cmd = cmd % args - rc, output = commands.getstatusoutput(cmd) - if rc != 0: - log.debug('%s failed with code %d' % (cmd, rc)) - log.trace('%s: %s' % (cmd, output)) - return rc, output - - -def _new_bridge_name(bridges): - n = 0 - while True: - brname = 'xenbr%d' % n - if brname not in bridges: - return brname - n += 1 + def get_VLAN(self): + return self.VLAN diff -r 491bed0350f1 -r 3c352bbc894d tools/python/xen/xend/XendPIFMetrics.py --- a/tools/python/xen/xend/XendPIFMetrics.py Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/python/xen/xend/XendPIFMetrics.py Fri Apr 27 13:31:09 2007 +0100 @@ -15,15 +15,30 @@ # Copyright (c) 2006-2007 Xensource Inc. #============================================================================ +from XendBase import XendBase -class XendPIFMetrics: +class XendPIFMetrics(XendBase): """PIF Metrics.""" + + def getClass(self): + return "PIF_metrics" - def __init__(self, uuid): - self.uuid = uuid + def getAttrRO(self): + attrRO = ['io_read_kbs', + 'io_write_kbs', + 'last_updated', + 'pif'] + return XendBase.getAttrRO() + attrRO - def set_PIF(self, pif): - self.pif = pif + getClass = classmethod(getClass) + getAttrRO = classmethod(getAttrRO) + + def __init__(self, uuid, pif_uuid): + XendBase.__init__(self, uuid, {}) + self.pif_uuid = pif_uuid + + def get_pif(self): + return self.pif_uuid def get_io_read_kbs(self): return self._get_stat(0) @@ -33,19 +48,12 @@ class XendPIFMetrics: def _get_stat(self, n): from xen.xend.XendNode import instance as xennode - pifname = self.pif.device - pifs_util = xennode().monitor.get_pifs_util() - if pifname in pifs_util: - return pifs_util[pifname][n] + #pifname = self.pif.device + #pifs_util = xennode().monitor.get_pifs_util() + #if pifname in pifs_util: + # return pifs_util[pifname][n] return 0.0 def get_last_updated(self): import xen.xend.XendAPI as XendAPI return XendAPI.now() - - def get_record(self): - return {'uuid' : self.uuid, - 'io_read_kbs' : self.get_io_read_kbs(), - 'io_write_kbs' : self.get_io_write_kbs(), - 'last_updated' : self.get_last_updated(), - } diff -r 491bed0350f1 -r 3c352bbc894d tools/python/xen/xend/XendQCoWStorageRepo.py --- a/tools/python/xen/xend/XendQCoWStorageRepo.py Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/python/xen/xend/XendQCoWStorageRepo.py Fri Apr 27 13:31:09 2007 +0100 @@ -30,7 +30,7 @@ import struct from xen.util import mkdir import uuid -import XendPBD +from XendPBD import XendPBD from XendError import XendError from XendVDI import * from XendTask import XendTask diff -r 491bed0350f1 -r 3c352bbc894d tools/python/xen/xend/XendStateStore.py --- a/tools/python/xen/xend/XendStateStore.py Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/python/xen/xend/XendStateStore.py Fri Apr 27 13:31:09 2007 +0100 @@ -57,10 +57,12 @@ class XendStateStore: <hosts> <host uuid='49c01812-3c28-1ad4-a59d-2a3f81b13ec2'> - <name type='string'>norwich</name> - <description type='string'>Test Xen Host</description> - <cpu uuid='6fc2d1ed-7eb0-4c9d-8006-3657d5483ae0' /> - <cpu uuid='669df3b8-62be-4e61-800b-bbe8ee63a760' /> + <name type='string'>norwich</name> + <description type='string'>Test Xen Host</description> + <cpu type='dict'> + <item uuid='6fc2d1ed-7eb0-4c9d-8006-3657d5483ae0' /> + <item uuid='669df3b8-62be-4e61-800b-bbe8ee63a760' /> + </cpu> </host> </hosts> @@ -121,18 +123,20 @@ class XendStateStore: if val_elem.firstChild: val_text = val_elem.firstChild.nodeValue.strip() - if val_type == '' and val_uuid != '': - # this is a reference - if val_name not in cls_dict: - cls_dict[val_name] = {} - cls_dict[val_name][val_uuid] = None - elif val_type == '': - # dictionary - k = val_elem.getAttribute('key').encode('utf8') - v = val_elem.getAttribute('value').encode('utf8') - if val_name not in cls_dict: - cls_dict[val_name] = {} - cls_dict[val_name][k] = v + if val_type == 'list': + cls_dict[val_name] = [] + for item in val_elem.childNodes: + if item.nodeType != Node.ELEMENT_NODE: + continue # skip non element nodes + cls_dict[val_name].append(item.getAttribute('uuid')) + elif val_type == 'dict': + cls_dict[val_name] = {} + for item in val_elem.childNodes: + if item.nodeType != Node.ELEMENT_NODE: + continue # skip non element nodes + k = item.getAttribute('key').encode('utf8') + v = item.getAttribute('value').encode('utf8') + cls_dict[val_name][k] = v elif val_type == 'string': cls_dict[val_name] = val_text.encode('utf8') elif val_type == 'float': @@ -158,8 +162,7 @@ class XendStateStore: @param state: a Xen API struct of the state of the class. @type state: dict @rtype: None - """ - + """ xml_path = self._xml_file(cls) doc = minidom.getDOMImplementation().createDocument(None, @@ -191,7 +194,7 @@ class XendStateStore: store_val = str(int(val)) store_type = 'bool' - if store_type != None: + if store_type is not None: val_node = doc.createElement(key) val_node.setAttribute('type', store_type) node.appendChild(val_node) @@ -202,19 +205,25 @@ class XendStateStore: # deal with dicts and lists if type(val) == dict: - for val_uuid in val.keys(): - val_node = doc.createElement(key) + val_node = doc.createElement(key) + val_node.setAttribute('type', 'dict') + for val_item in val.keys(): + tmp = doc.createElement("item") if key in ['other_config', 'device_config']: - val_node.setAttribute('key', str(val_uuid)) - val_node.setAttribute('value', str(val[val_uuid])) + tmp.setAttribute('key', str(val_item)) + tmp.setAttribute('value', str(val[val_item])) else: - val_node.setAttribute('uuid', val_uuid) - node.appendChild(val_node) + tmp.setAttribute('uuid', val_uuid) + val_node.appendChild(tmp) + node.appendChild(val_node) elif type(val) in (list, tuple): + val_node = doc.createElement(key) + val_node.setAttribute('type', 'list') for val_uuid in val: - val_node = doc.createElement(key) - val_node.setAttribute('uuid', val_uuid) - node.appendChild(val_node) + tmp = doc.createElement("item") + tmp.setAttribute('uuid', val_uuid) + val_node.appendChild(tmp) + node.appendChild(val_node) open(xml_path, 'w').write(doc.toprettyxml()) diff -r 491bed0350f1 -r 3c352bbc894d tools/python/xen/xend/XendStorageRepository.py --- a/tools/python/xen/xend/XendStorageRepository.py Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/python/xen/xend/XendStorageRepository.py Fri Apr 27 13:31:09 2007 +0100 @@ -24,7 +24,7 @@ import sys from XendError import XendError from XendVDI import * -import XendPBD +from XendPBD import XendPBD XEND_STORAGE_NO_MAXIMUM = sys.maxint diff -r 491bed0350f1 -r 3c352bbc894d tools/python/xen/xend/XendVMMetrics.py --- a/tools/python/xen/xend/XendVMMetrics.py Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/python/xen/xend/XendVMMetrics.py Fri Apr 27 13:31:09 2007 +0100 @@ -17,38 +17,36 @@ #============================================================================ from xen.xend.XendLogging import log +from xen.xend.XendBase import XendBase import xen.lowlevel.xc xc = xen.lowlevel.xc.xc() -instances = {} - -class XendVMMetrics: +class XendVMMetrics(XendBase): """VM Metrics.""" - def get_by_uuid(_, uuid): - return instances[uuid] + def getClass(self): + return "VM_metrics" + + def getAttrRO(self): + attrRO = ['memory_actual', + 'VCPUs_number', + 'VCPUs_utilisation', + 'VCPUs_CPU', + 'VCPUs_flags', + 'VCPUs_params', + 'state', + 'start_time', + 'last_updated'] + return XendBase.getAttrRO() + attrRO - get_by_uuid = classmethod(get_by_uuid) + getClass = classmethod(getClass) + getAttrRO = classmethod(getAttrRO) - def is_valid_vm_metrics(_, uuid): - 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 + XendBase.__init__(self, uuid, {}) self.xend_domain_instance = xend_domain_instance - instances[uuid] = self - - def get_uuid(self): - return self.uuid - + def get_memory_actual(self): domInfo = self.xend_domain_instance.getDomInfo() if domInfo: @@ -145,16 +143,3 @@ class XendVMMetrics: def get_last_updated(self): import xen.xend.XendAPI as XendAPI return XendAPI.now() - - def get_record(self): - return { 'uuid' : self.uuid, - 'memory_actual' : self.get_memory_actual(), - 'VCPUs_number' : self.get_VCPUs_number(), - 'VCPUs_utilisation' : self.get_VCPUs_utilisation(), - 'VCPUs_CPU' : self.get_VCPUs_CPU(), - 'VCPUs_flags' : self.get_VCPUs_flags(), - 'VCPUs_params' : self.get_VCPUs_params(), - 'start_time' : self.get_start_time(), - 'state' : self.get_state(), - 'last_updated' : self.get_last_updated(), - } diff -r 491bed0350f1 -r 3c352bbc894d tools/python/xen/xend/server/SrvServer.py --- a/tools/python/xen/xend/server/SrvServer.py Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/python/xen/xend/server/SrvServer.py Fri Apr 27 13:31:09 2007 +0100 @@ -109,8 +109,6 @@ class XendServers: signal.signal(signal.SIGHUP, self.reloadConfig) while True: - XendNode.instance().refreshBridges() - threads = [] for server in self.servers: if server.ready: diff -r 491bed0350f1 -r 3c352bbc894d tools/python/xen/xm/create.dtd --- a/tools/python/xen/xm/create.dtd Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/python/xen/xm/create.dtd Fri Apr 27 13:31:09 2007 +0100 @@ -27,7 +27,8 @@ | crashdump )"> <!ELEMENT xm (vm*, - vdi*)> + vdi*, + network*)> <!ELEMENT version (#PCDATA)> @@ -98,6 +99,12 @@ sharable CDATA #REQUIRED read_only CDATA #REQUIRED> +<!ELEMENT network (name, + other_config*)> +<!ATTLIST network %NAMEID; + default_gateway CDATA #REQUIRED + default_netmask CDATA #REQUIRED> + <!ELEMENT name (label, description)> diff -r 491bed0350f1 -r 3c352bbc894d tools/python/xen/xm/main.py --- a/tools/python/xen/xm/main.py Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/python/xen/xm/main.py Fri Apr 27 13:31:09 2007 +0100 @@ -510,6 +510,10 @@ def xenapi_unsupported(): if serverType == SERVER_XEN_API: raise XenAPIUnsupportedException, "This function is not supported by Xen-API" +def xenapi_only(): + if serverType != SERVER_XEN_API: + raise XenAPIUnsupportedException, "This function is only supported by Xen-API" + def map2sxp(m): return [[k, m[k]] for k in m.keys()] @@ -2070,8 +2074,14 @@ def xm_network_attach(args): record[keys[-1]] = val def get_net_from_bridge(bridge): - raise "Not supported just yet" - + # In OSS, we just assert network.name_label == bridge name + networks = dict([(record['name_label'], record['uuid']) + for record in server.xenapi.network + .get_all_records()]) + if bridge not in networks.keys(): + raise "Unknown bridge name!" + return networks[bridge] + vif_conv = { 'type': lambda x: None, @@ -2102,7 +2112,6 @@ def xm_network_attach(args): 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:]: @@ -2222,6 +2231,93 @@ def xm_vnet_delete(args): vnet = args[0] server.xend_vnet_delete(vnet) +def xm_network_new(args): + xenapi_only() + arg_check(args, "network-new", 1) + network = args[0] + + record = { + "name_label": network, + "name_description": "", + "other_config": {}, + "default_gateway": "", + "default_netmask": "" + } + + server.xenapi.network.create(record) + +def xm_network_del(args): + xenapi_only() + arg_check(args, "network-del", 1) + network = args[0] + + networks = dict([(record['name_label'], record['uuid']) + for record in + server.xenapi.network.get_all_records()]) + + if network not in networks.keys(): + raise ValueError("'%s' is not a valid network name" % network) + + server.xenapi.network.destroy(networks[network]) + +def uuid_dict_trans(records): + return dict([(record['uuid'], record) + for record in records]) + +def xm_network_show(args): + xenapi_only() + arg_check(args, "network-show", 0) + + networks = server.xenapi.network.get_all_records() + pifs = uuid_dict_trans( + server.xenapi.PIF.get_all_records()) + vifs = uuid_dict_trans( + server.xenapi.VIF.get_all_records()) + + print '%-20s %-40s %-10s' % \ + ('Name', 'VIFs', 'PIFs') + + format2 = "%(name_label)-20s %(vif)-40s %(pif)-10s" + + for network in networks: + for i in range(max(len(network['PIFs']), + len(network['VIFs']), 1)): + if i < len(network['PIFs']): + pif_uuid = network['PIFs'][i] + else: + pif_uuid = None + + if i < len(network['VIFs']): + vif_uuid = network['VIFs'][i] + else: + vif_uuid = None + + pif = pifs.get(pif_uuid, {'device':''}) + vif = vifs.get(vif_uuid, None) + + if vif: + dom_name = server.xenapi.VM.get_name_label(vif['VM']) + vif = "%s.%s" % (dom_name, vif['device']) + else: + vif = '' + + if pif: + if int(pif['VLAN']) > -1: + pif = '%s.%s' % (pif['device'], pif['VLAN']) + else: + pif = pif['device'] + else: + pif = '' + + if i == 0: + r = {'name_label':network['name_label'], + 'vif':vif, 'pif':pif} + else: + r = {'name_label':'', 'vif':vif, 'pif':pif} + + print format2 % r + + commands = { "shell": xm_shell, "event-monitor": xm_event_monitor, @@ -2271,10 +2367,14 @@ commands = { "block-detach": xm_block_detach, "block-list": xm_block_list, "block-configure": xm_block_configure, - # network + # network (AKA vifs) "network-attach": xm_network_attach, "network-detach": xm_network_detach, "network-list": xm_network_list, + # network (as in XenAPI) + "network-new": xm_network_new, + "network-del": xm_network_del, + "network-show": xm_network_show, # vnet "vnet-list": xm_vnet_list, "vnet-create": xm_vnet_create, diff -r 491bed0350f1 -r 3c352bbc894d tools/python/xen/xm/messages/en/xen-xm.po --- a/tools/python/xen/xm/messages/en/xen-xm.po Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/python/xen/xm/messages/en/xen-xm.po Fri Apr 27 13:31:09 2007 +0100 @@ -67,3 +67,27 @@ msgstr "HVM guest support is unavailable msgid "SESSION_NOT_REGISTERED" msgstr "This session is not registered to receive events. You must call event.register before event.next. (Session handle is %(1)s.)" + +msgid "CREATE_UNSPECIFIED_ATTRIBUTE" +msgstr "You need to specify %s when creating a new %s" + +msgid "UNMANAGED_NETWORK_ERROR" +msgstr "Cannot change %s on an unmanaged network" + +msgid "UNIQUE_NAME_ERROR" +msgstr "Name %s for class %s is not unique" + +msgid "INVALID_DEVICE_ERROR" +msgstr "Invalid device %s" + +msgid "DEVICE_EXISTS_ERROR" +msgstr "Device already exists %s" + +msgid "IMPLEMENTATION_ERROR" +msgstr "Class %s does not implement %s" + +msgid "VLAN_TAG_INVALID" +msgstr "VLAN tag invalid %s" + +msgid "NETWORK_ERROR" +msgstr "Network Error: %s - %s" \ No newline at end of file diff -r 491bed0350f1 -r 3c352bbc894d tools/python/xen/xm/xenapi_create.py --- a/tools/python/xen/xm/xenapi_create.py Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/python/xen/xm/xenapi_create.py Fri Apr 27 13:31:09 2007 +0100 @@ -93,10 +93,13 @@ class xenapi_create: vdis = document.getElementsByTagName("vdi") vdi_refs_dict = self.create_vdis(vdis) + + networks = document.getElementsByTagName("network") + network_refs_dict = self.create_networks(networks) try: vms = document.getElementsByTagName("vm") - return self.create_vms(vms, vdi_refs_dict) + return self.create_vms(vms, vdi_refs_dict, network_refs_dict) except Exception, exn: try_quietly(self.cleanup_vdis(vdi_refs_dict)) raise exn @@ -223,11 +226,33 @@ class xenapi_create: return (key, value) - def create_vms(self, vms, vdis): + def create_networks(self, networks): + log(DEBUG, "create_networks") + return dict(map(self.create_network, networks)) + + def create_network(self, network): + log(DEBUG, "create_network") + + network_record = { + "name_label": get_name_label(network), + "name_description": get_name_description(network), + "other_config": + get_child_nodes_as_dict(network, "other_config", + "key", "value"), + "default_netmask": network.attributes["default_netmask"].value, + "default_gateway": network.attributes["default_gateway"].value + } + + key = network.attributes["name"].value + value = server.xenapi.network.create(network_record) + + return (key, value) + + def create_vms(self, vms, vdis, networks): log(DEBUG, "create_vms") - return map(lambda vm: self.create_vm(vm, vdis), vms) - - def create_vm(self, vm, vdis): + return map(lambda vm: self.create_vm(vm, vdis, networks), vms) + + def create_vm(self, vm, vdis, networks): log(DEBUG, "create_vm") vm_record = { @@ -321,7 +346,7 @@ class xenapi_create: vifs = vm.getElementsByTagName("vif") - self.create_vifs(vm_ref, vifs) + self.create_vifs(vm_ref, vifs, networks) # Now create consoles @@ -363,31 +388,35 @@ class xenapi_create: return server.xenapi.VBD.create(vbd_record) - def create_vifs(self, vm_ref, vifs): + def create_vifs(self, vm_ref, vifs, networks): log(DEBUG, "create_vifs") - return map(lambda vif: self.create_vif(vm_ref, vif), vifs) - - def create_vif(self, vm_ref, vif): + return map(lambda vif: self.create_vif(vm_ref, vif, networks), vifs) + + def create_vif(self, vm_ref, vif, networks): log(DEBUG, "create_vif") - if "network" in vif.attributes.keys(): - networks = [network_ref - for network_ref in server.xenapi.network.get_all() - if server.xenapi.network.get_name_label(network_ref) - == vif.attributes["network"].value] - if len(networks) > 0: - network = networks[0] + if 'network' in vif.attributes.keys(): + network_name = vif.attributes['network'].value + + if network_name in networks.keys(): + network_uuid = networks[network_name] else: - raise OptionError("Network %s doesn't exist" + networks = dict([(record['name_label'], record['uuid']) + for record in + server.xenapi.network.get_all_records()]) + if network_name in networks.keys(): + network_uuid = networks[network_name] + else: + raise OptionError("Network %s doesn't exist" % vif.attributes["network"].value) else: - network = self._get_network_ref() + network_uuid = self._get_network_ref() vif_record = { "device": vif.attributes["device"].value, "network": - network, + network_uuid, "VM": vm_ref, "MAC": diff -r 491bed0350f1 -r 3c352bbc894d tools/xm-test/lib/XmTestLib/network_utils.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/xm-test/lib/XmTestLib/network_utils.py Fri Apr 27 13:31:09 2007 +0100 @@ -0,0 +1,60 @@ +#!/usr/bin/python + +# Copyright (C) International Business Machines Corp., 2005 +# Author: Murillo F. Bernardes <mfb@xxxxxxxxxx> + +from XmTestLib import * + +def count_eth(console): + try: + run = console.runCmd("ifconfig -a | grep eth") + except ConsoleError, e: + 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, bridge=None): + eths_before = count_eth(console) + if bridge: + status, output = traceCommand("xm network-attach %s bridge=%s" + % (domain_name, bridge)) + else: + status, output = traceCommand("xm network-attach %s" % domain_name) + if status != 0: + return -1, "xm network-attach returned invalid %i != 0" % status + + eths_after = count_eth(console) + if (eths_after != (eths_before+1)): + return -2, "Network device is not actually connected to domU" + + return 0, None + +def network_detach(domain_name, console, num=0): + eths_before = count_eth(console) + status, output = traceCommand("xm network-detach %s %d" % (domain_name, num)) + 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" + + return 0, None diff -r 491bed0350f1 -r 3c352bbc894d tools/xm-test/tests/network-attach/01_network_attach_pos.py --- a/tools/xm-test/tests/network-attach/01_network_attach_pos.py Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/xm-test/tests/network-attach/01_network_attach_pos.py Fri Apr 27 13:31:09 2007 +0100 @@ -6,7 +6,7 @@ import sys import sys from XmTestLib import * -from network_utils import * +from XmTestLib.network_utils import * if ENABLE_HVM_SUPPORT: SKIP("Network-attach not supported for HVM domains") diff -r 491bed0350f1 -r 3c352bbc894d tools/xm-test/tests/network-attach/02_network_attach_detach_pos.py --- a/tools/xm-test/tests/network-attach/02_network_attach_detach_pos.py Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/xm-test/tests/network-attach/02_network_attach_detach_pos.py Fri Apr 27 13:31:09 2007 +0100 @@ -8,7 +8,7 @@ import time import time from XmTestLib import * -from network_utils import * +from XmTestLib.network_utils import * if ENABLE_HVM_SUPPORT: SKIP("Network-attach not supported for HVM domains") diff -r 491bed0350f1 -r 3c352bbc894d tools/xm-test/tests/network-attach/03_network_attach_detach_multiple_pos.py --- a/tools/xm-test/tests/network-attach/03_network_attach_detach_multiple_pos.py Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/xm-test/tests/network-attach/03_network_attach_detach_multiple_pos.py Fri Apr 27 13:31:09 2007 +0100 @@ -8,7 +8,7 @@ import time import time from XmTestLib import * -from network_utils import * +from XmTestLib.network_utils import * if ENABLE_HVM_SUPPORT: SKIP("Network-attach not supported for HVM domains") diff -r 491bed0350f1 -r 3c352bbc894d tools/xm-test/tests/network-attach/network_utils.py --- a/tools/xm-test/tests/network-attach/network_utils.py Fri Apr 27 13:25:58 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -#!/usr/bin/python - -# Copyright (C) International Business Machines Corp., 2005 -# Author: Murillo F. Bernardes <mfb@xxxxxxxxxx> - -from XmTestLib import * - -def count_eth(console): - try: - run = console.runCmd("ifconfig -a | grep eth") - except ConsoleError, e: - 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) - if status != 0: - return -1, "xm network-attach returned invalid %i != 0" % status - - eths_after = count_eth(console) - if (eths_after != (eths_before+1)): - return -2, "Network device is not actually connected to domU" - - return 0, None - -def network_detach(domain_name, console, num=0): - eths_before = count_eth(console) - status, output = traceCommand("xm network-detach %s %d" % (domain_name, num)) - 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" - - return 0, None diff -r 491bed0350f1 -r 3c352bbc894d tools/xm-test/tests/xapi/03_xapi-network_pos.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/xm-test/tests/xapi/03_xapi-network_pos.py Fri Apr 27 13:31:09 2007 +0100 @@ -0,0 +1,71 @@ +#!/usr/bin/python + +# Try and create two VMs and a private network betwene the two + +import sys + +from XmTestLib import * +from XmTestLib.network_utils import * + +# Create two domains (default XmTestDomain, with our ramdisk) +try: + domain1 = XmTestDomain() + console1 = domain1.start() + domain2 = XmTestDomain() + console2 = domain2.start() +except DomainError, e: + if verbose: + print "Failed to create test domain because:" + print e.extra + FAIL(str(e)) + +# Create a network + +status, ouptut = traceCommand("xm network-new xapi-network") +if status: + FAIL(output) + +# Attach two domains to it +status, msg = network_attach(domain1.getName(), + console1, bridge='xapi-network') +if status: + FAIL(msg) + +status, msg = network_attach(domain2.getName(), + console2, bridge='xapi-network') +if status: + FAIL(msg) + +# Configure IP addresses on two domains +try: + # Run 'ls' + run = console1.runCmd("ifconfig eth0 192.168.0.1 netmask 255.255.255.0 up") + run = console2.runCmd("ifconfig eth0 192.168.0.2 netmask 255.255.255.0 up") +except ConsoleError, e: + saveLog(console.getHistory()) + FAIL(str(e)) + +# Now ping... +try: + run = console1.runCmd("ping -c 4 192.168.0.2") + if run['return'] > 0: + FAIL("Could not ping other host") + run = console2.runCmd("ping -c 4 192.168.0.1") + if run['return'] > 0: + FAIL("Could not pint other host") +except ConsoleError, e: + saveLog(console.getHistory()) + FAIL(str(e)) + +status, msg = network_detach(domain1.getName(), console1) +status, msg = network_detach(domain2.getName(), console2) + +# Clean up +domain1.closeConsole() +domain1.stop() +domain2.closeConsole() +domain2.stop() + +status, ouptut = traceCommand("xm network-del xapi-network") +if status: + FAIL(output) diff -r 491bed0350f1 -r 3c352bbc894d tools/xm-test/tests/xapi/Makefile.am --- a/tools/xm-test/tests/xapi/Makefile.am Fri Apr 27 13:25:58 2007 +0100 +++ b/tools/xm-test/tests/xapi/Makefile.am Fri Apr 27 13:31:09 2007 +0100 @@ -1,7 +1,8 @@ SUBDIRS = SUBDIRS = TESTS = 01_xapi-vm_basic.test \ - 02_xapi-vbd_basic.test + 02_xapi-vbd_basic.test \ + 03_xapi-network_pos.test XFAIL_TESTS = diff -r 491bed0350f1 -r 3c352bbc894d xen/acm/acm_policy.c --- a/xen/acm/acm_policy.c Fri Apr 27 13:25:58 2007 +0100 +++ b/xen/acm/acm_policy.c Fri Apr 27 13:31:09 2007 +0100 @@ -46,7 +46,7 @@ static ssidref_t oldssid_to_newssid(cons int -acm_set_policy(XEN_GUEST_HANDLE(void) buf, u32 buf_size) +acm_set_policy(XEN_GUEST_HANDLE_64(void) buf, u32 buf_size) { u8 *policy_buffer = NULL; int ret = -EFAULT; @@ -213,7 +213,7 @@ do_acm_set_policy(void *buf, u32 buf_siz } int -acm_get_policy(XEN_GUEST_HANDLE(void) buf, u32 buf_size) +acm_get_policy(XEN_GUEST_HANDLE_64(void) buf, u32 buf_size) { u8 *policy_buffer; int ret; @@ -278,7 +278,7 @@ acm_get_policy(XEN_GUEST_HANDLE(void) bu } int -acm_dump_statistics(XEN_GUEST_HANDLE(void) buf, u16 buf_size) +acm_dump_statistics(XEN_GUEST_HANDLE_64(void) buf, u16 buf_size) { /* send stats to user space */ u8 *stats_buffer; @@ -324,7 +324,7 @@ acm_dump_statistics(XEN_GUEST_HANDLE(voi int -acm_get_ssid(ssidref_t ssidref, XEN_GUEST_HANDLE(void) buf, u16 buf_size) +acm_get_ssid(ssidref_t ssidref, XEN_GUEST_HANDLE_64(void) buf, u16 buf_size) { /* send stats to user space */ u8 *ssid_buffer; diff -r 491bed0350f1 -r 3c352bbc894d xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Fri Apr 27 13:25:58 2007 +0100 +++ b/xen/arch/x86/domain.c Fri Apr 27 13:31:09 2007 +0100 @@ -237,7 +237,8 @@ static int setup_compat_l4(struct vcpu * l4tab[l4_table_offset(LINEAR_PT_VIRT_START)] = l4e_from_page(pg, __PAGE_HYPERVISOR); l4tab[l4_table_offset(PERDOMAIN_VIRT_START)] = - l4e_from_paddr(__pa(v->domain->arch.mm_perdomain_l3), __PAGE_HYPERVISOR); + l4e_from_paddr(__pa(v->domain->arch.mm_perdomain_l3), + __PAGE_HYPERVISOR); v->arch.guest_table = pagetable_from_page(pg); v->arch.guest_table_user = v->arch.guest_table; @@ -259,7 +260,7 @@ static void release_compat_l4(struct vcp static inline int may_switch_mode(struct domain *d) { - return (d->tot_pages == 0); + return (!is_hvm_domain(d) && (d->tot_pages == 0)); } int switch_native(struct domain *d) @@ -371,15 +372,12 @@ int vcpu_initialise(struct vcpu *v) v->arch.perdomain_ptes = d->arch.mm_perdomain_pt + (v->vcpu_id << GDT_LDT_VCPU_SHIFT); - if ( IS_COMPAT(d) && (rc = setup_compat_l4(v)) != 0 ) - return rc; - - return 0; + return (pv_32on64_vcpu(v) ? setup_compat_l4(v) : 0); } void vcpu_destroy(struct vcpu *v) { - if ( IS_COMPAT(v->domain) ) + if ( pv_32on64_vcpu(v) ) release_compat_l4(v); } @@ -491,7 +489,7 @@ void arch_domain_destroy(struct domain * free_domheap_page(virt_to_page(d->arch.mm_perdomain_l3)); #endif - if ( IS_COMPAT(d) ) + if ( pv_32on64_domain(d) ) release_arg_xlat_area(d); free_xenheap_page(d->shared_info); @@ -508,7 +506,7 @@ int arch_set_info_guest( /* The context is a compat-mode one if the target domain is compat-mode; * we expect the tools to DTRT even in compat-mode callers. */ - compat = IS_COMPAT(d); + compat = pv_32on64_domain(d); #ifdef CONFIG_COMPAT #define c(fld) (compat ? (c.cmp->fld) : (c.nat->fld)) @@ -1268,7 +1266,7 @@ unsigned long hypercall_create_continuat else #endif { - if ( supervisor_mode_kernel || is_hvm_vcpu(current) ) + if ( supervisor_mode_kernel ) regs->eip &= ~31; /* re-execute entire hypercall entry stub */ for ( i = 0; *p != '\0'; i++ ) @@ -1449,14 +1447,11 @@ static void vcpu_destroy_pagetables(stru struct domain *d = v->domain; unsigned long pfn; -#ifdef CONFIG_COMPAT - if ( IS_COMPAT(d) ) - { - if ( is_hvm_vcpu(v) ) - pfn = pagetable_get_pfn(v->arch.guest_table); - else - pfn = l4e_get_pfn(*(l4_pgentry_t *) - __va(pagetable_get_paddr(v->arch.guest_table))); +#ifdef __x86_64__ + if ( pv_32on64_vcpu(v) ) + { + pfn = l4e_get_pfn(*(l4_pgentry_t *) + __va(pagetable_get_paddr(v->arch.guest_table))); if ( pfn != 0 ) { @@ -1466,12 +1461,9 @@ static void vcpu_destroy_pagetables(stru put_page_and_type(mfn_to_page(pfn)); } - if ( is_hvm_vcpu(v) ) - v->arch.guest_table = pagetable_null(); - else - l4e_write( - (l4_pgentry_t *) __va(pagetable_get_paddr(v->arch.guest_table)), - l4e_empty()); + l4e_write( + (l4_pgentry_t *)__va(pagetable_get_paddr(v->arch.guest_table)), + l4e_empty()); v->arch.cr3 = 0; return; diff -r 491bed0350f1 -r 3c352bbc894d xen/arch/x86/hvm/vmx/intr.c --- a/xen/arch/x86/hvm/vmx/intr.c Fri Apr 27 13:25:58 2007 +0100 +++ b/xen/arch/x86/hvm/vmx/intr.c Fri Apr 27 13:31:09 2007 +0100 @@ -71,6 +71,9 @@ static void update_tpr_threshold(struct static void update_tpr_threshold(struct vlapic *vlapic) { int max_irr, tpr; + + if ( !cpu_has_vmx_tpr_shadow ) + return; if ( !vlapic_enabled(vlapic) || ((max_irr = vlapic_find_highest_irr(vlapic)) == -1) ) diff -r 491bed0350f1 -r 3c352bbc894d xen/arch/x86/hvm/vmx/vmcs.c --- a/xen/arch/x86/hvm/vmx/vmcs.c Fri Apr 27 13:25:58 2007 +0100 +++ b/xen/arch/x86/hvm/vmx/vmcs.c Fri Apr 27 13:31:09 2007 +0100 @@ -38,16 +38,16 @@ #include <asm/shadow.h> /* Dynamic (run-time adjusted) execution control flags. */ -u32 vmx_pin_based_exec_control; -u32 vmx_cpu_based_exec_control; -u32 vmx_vmexit_control; -u32 vmx_vmentry_control; - -static u32 vmcs_revision_id; - -static u32 adjust_vmx_controls(u32 ctl_min, u32 ctl_max, u32 msr) -{ - u32 vmx_msr_low, vmx_msr_high, ctl = ctl_max; +u32 vmx_pin_based_exec_control __read_mostly; +u32 vmx_cpu_based_exec_control __read_mostly; +u32 vmx_vmexit_control __read_mostly; +u32 vmx_vmentry_control __read_mostly; + +static u32 vmcs_revision_id __read_mostly; + +static u32 adjust_vmx_controls(u32 ctl_min, u32 ctl_opt, u32 msr) +{ + u32 vmx_msr_low, vmx_msr_high, ctl = ctl_min | ctl_opt; rdmsr(msr, vmx_msr_low, vmx_msr_high); @@ -56,46 +56,55 @@ static u32 adjust_vmx_controls(u32 ctl_m /* Ensure minimum (required) set of control bits are supported. */ BUG_ON(ctl_min & ~ctl); - BUG_ON(ctl_min & ~ctl_max); return ctl; } void vmx_init_vmcs_config(void) { - u32 vmx_msr_low, vmx_msr_high, min, max; + u32 vmx_msr_low, vmx_msr_high, min, opt; u32 _vmx_pin_based_exec_control; u32 _vmx_cpu_based_exec_control; u32 _vmx_vmexit_control; u32 _vmx_vmentry_control; - min = max = PIN_BASED_EXT_INTR_MASK | PIN_BASED_NMI_EXITING; + min = PIN_BASED_EXT_INTR_MASK | PIN_BASED_NMI_EXITING; + opt = 0; _vmx_pin_based_exec_control = adjust_vmx_controls( - min, max, MSR_IA32_VMX_PINBASED_CTLS_MSR); - - min = max = (CPU_BASED_HLT_EXITING | - CPU_BASED_INVDPG_EXITING | - CPU_BASED_MWAIT_EXITING | - CPU_BASED_MOV_DR_EXITING | - CPU_BASED_ACTIVATE_IO_BITMAP | - CPU_BASED_USE_TSC_OFFSETING); + min, opt, MSR_IA32_VMX_PINBASED_CTLS_MSR); + + min = (CPU_BASED_HLT_EXITING | + CPU_BASED_INVDPG_EXITING | + CPU_BASED_MWAIT_EXITING | + CPU_BASED_MOV_DR_EXITING | + CPU_BASED_ACTIVATE_IO_BITMAP | + CPU_BASED_USE_TSC_OFFSETING); + opt = CPU_BASED_ACTIVATE_MSR_BITMAP; #ifdef __x86_64__ - min = max |= CPU_BASED_CR8_LOAD_EXITING | CPU_BASED_CR8_STORE_EXITING; -#endif - max |= CPU_BASED_ACTIVATE_MSR_BITMAP; + opt |= CPU_BASED_TPR_SHADOW; +#endif _vmx_cpu_based_exec_control = adjust_vmx_controls( - min, max, MSR_IA32_VMX_PROCBASED_CTLS_MSR); - - min = max = VM_EXIT_ACK_INTR_ON_EXIT; + min, opt, MSR_IA32_VMX_PROCBASED_CTLS_MSR); #ifdef __x86_64__ - min = max |= VM_EXIT_IA32E_MODE; + if ( !(_vmx_cpu_based_exec_control & CPU_BASED_TPR_SHADOW) ) + { + min |= CPU_BASED_CR8_LOAD_EXITING | CPU_BASED_CR8_STORE_EXITING; + _vmx_cpu_based_exec_control = adjust_vmx_controls( + min, opt, MSR_IA32_VMX_PROCBASED_CTLS_MSR); + } +#endif + + min = VM_EXIT_ACK_INTR_ON_EXIT; + opt = 0; +#ifdef __x86_64__ + min |= VM_EXIT_IA32E_MODE; #endif _vmx_vmexit_control = adjust_vmx_controls( - min, max, MSR_IA32_VMX_EXIT_CTLS_MSR); - - min = max = 0; + min, opt, MSR_IA32_VMX_EXIT_CTLS_MSR); + + min = opt = 0; _vmx_vmentry_control = adjust_vmx_controls( - min, max, MSR_IA32_VMX_ENTRY_CTLS_MSR); + min, opt, MSR_IA32_VMX_ENTRY_CTLS_MSR); rdmsr(MSR_IA32_VMX_BASIC_MSR, vmx_msr_low, vmx_msr_high); @@ -414,13 +423,12 @@ static void construct_vmcs(struct vcpu * #ifdef __x86_64__ /* VLAPIC TPR optimisation. */ - v->arch.hvm_vcpu.u.vmx.exec_control |= CPU_BASED_TPR_SHADOW; - v->arch.hvm_vcpu.u.vmx.exec_control &= - ~(CPU_BASED_CR8_STORE_EXITING | CPU_BASED_CR8_LOAD_EXITING); - __vmwrite(CPU_BASED_VM_EXEC_CONTROL, v->arch.hvm_vcpu.u.vmx.exec_control); - __vmwrite(VIRTUAL_APIC_PAGE_ADDR, - page_to_maddr(vcpu_vlapic(v)->regs_page)); - __vmwrite(TPR_THRESHOLD, 0); + if ( cpu_has_vmx_tpr_shadow ) + { + __vmwrite(VIRTUAL_APIC_PAGE_ADDR, + page_to_maddr(vcpu_vlapic(v)->regs_page)); + __vmwrite(TPR_THRESHOLD, 0); + } #endif __vmwrite(GUEST_LDTR_SELECTOR, 0); diff -r 491bed0350f1 -r 3c352bbc894d xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Fri Apr 27 13:25:58 2007 +0100 +++ b/xen/arch/x86/mm.c Fri Apr 27 13:31:09 2007 +0100 @@ -249,7 +249,10 @@ int memory_is_conventional_ram(paddr_t p 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); + if ( is_hvm_domain(d) ) + return d->arch.p2m.max_mapped_pfn; + /* NB. PV guests specify nr_pfns rather than max_pfn so we adjust here. */ + return arch_get_max_pfn(d) - 1; } void share_xen_page_with_guest( diff -r 491bed0350f1 -r 3c352bbc894d xen/arch/x86/mm/shadow/common.c --- a/xen/arch/x86/mm/shadow/common.c Fri Apr 27 13:25:58 2007 +0100 +++ b/xen/arch/x86/mm/shadow/common.c Fri Apr 27 13:31:09 2007 +0100 @@ -1577,9 +1577,7 @@ void sh_destroy_shadow(struct vcpu *v, m t == SH_type_fl1_pae_shadow || t == SH_type_fl1_64_shadow || t == SH_type_monitor_table || -#ifdef CONFIG_COMPAT - (IS_COMPAT(v->domain) && t == SH_type_l4_64_shadow) || -#endif + (pv_32on64_vcpu(v) && t == SH_type_l4_64_shadow) || (page_get_owner(mfn_to_page(_mfn(sp->backpointer))) == v->domain)); @@ -1622,7 +1620,7 @@ void sh_destroy_shadow(struct vcpu *v, m SHADOW_INTERNAL_NAME(sh_destroy_l1_shadow, 4, 4)(v, smfn); break; case SH_type_l2h_64_shadow: - ASSERT( IS_COMPAT(v->domain) ); + ASSERT(pv_32on64_vcpu(v)); /* Fall through... */ case SH_type_l2_64_shadow: SHADOW_INTERNAL_NAME(sh_destroy_l2_shadow, 4, 4)(v, smfn); @@ -2668,8 +2666,7 @@ sh_alloc_log_dirty_bitmap(struct domain { ASSERT(d->arch.paging.shadow.dirty_bitmap == NULL); d->arch.paging.shadow.dirty_bitmap_size = - (domain_get_maximum_gpfn(d) + (BITS_PER_LONG - 1)) & - ~(BITS_PER_LONG - 1); + (domain_get_maximum_gpfn(d) + BITS_PER_LONG) & ~(BITS_PER_LONG - 1); d->arch.paging.shadow.dirty_bitmap = xmalloc_array(unsigned long, d->arch.paging.shadow.dirty_bitmap_size / BITS_PER_LONG); @@ -2717,7 +2714,10 @@ static int shadow_log_dirty_enable(struc } #if (SHADOW_OPTIMIZATIONS & SHOPT_LINUX_L3_TOPLEVEL) - if ( IS_COMPAT(d) ) + /* 32bit PV guests on 64bit xen behave like older 64bit linux: they + * change an l4e instead of cr3 to switch tables. Give them the + * same optimization */ + if ( pv_32on64_domain(d) ) d->arch.paging.shadow.opt_flags = SHOPT_LINUX_L3_TOPLEVEL; #endif diff -r 491bed0350f1 -r 3c352bbc894d xen/arch/x86/mm/shadow/multi.c --- a/xen/arch/x86/mm/shadow/multi.c Fri Apr 27 13:25:58 2007 +0100 +++ b/xen/arch/x86/mm/shadow/multi.c Fri Apr 27 13:31:09 2007 +0100 @@ -134,9 +134,8 @@ set_shadow_status(struct vcpu *v, mfn_t d->domain_id, v->vcpu_id, mfn_x(gmfn), shadow_type, mfn_x(smfn)); -#ifdef CONFIG_COMPAT - if ( !IS_COMPAT(d) || shadow_type != SH_type_l4_64_shadow ) -#endif + /* 32-on-64 PV guests don't own their l4 pages so can't get_page them */ + if ( !pv_32on64_vcpu(v) || shadow_type != SH_type_l4_64_shadow ) { res = get_page(mfn_to_page(gmfn), d); ASSERT(res == 1); @@ -162,9 +161,8 @@ delete_shadow_status(struct vcpu *v, mfn v->domain->domain_id, v->vcpu_id, mfn_x(gmfn), shadow_type, mfn_x(smfn)); shadow_hash_delete(v, mfn_x(gmfn), shadow_type, smfn); -#ifdef CONFIG_COMPAT - if ( !IS_COMPAT(v->domain) || shadow_type != SH_type_l4_64_shadow ) -#endif + /* 32-on-64 PV guests don't own their l4 pages; see set_shadow_status */ + if ( !pv_32on64_vcpu(v) || shadow_type != SH_type_l4_64_shadow ) put_page(mfn_to_page(gmfn)); } @@ -746,7 +744,8 @@ _sh_propagate(struct vcpu *v, // PV guests in 64-bit mode use two different page tables for user vs // supervisor permissions, making the guest's _PAGE_USER bit irrelevant. // It is always shadowed as present... - if ( (GUEST_PAGING_LEVELS == 4) && !IS_COMPAT(d) && !is_hvm_domain(d) ) + if ( (GUEST_PAGING_LEVELS == 4) && !pv_32on64_domain(d) + && !is_hvm_domain(d) ) { sflags |= _PAGE_USER; } @@ -1300,7 +1299,7 @@ do { for ( _i = 0; _i < SHADOW_L2_PAGETABLE_ENTRIES; _i++ ) \ { \ if ( (!(_xen)) \ - || !IS_COMPAT(_dom) \ + || !pv_32on64_domain(_dom) \ || mfn_to_shadow_page(_sl2mfn)->type != SH_type_l2h_64_shadow \ || (_i < COMPAT_L2_PAGETABLE_FIRST_XEN_SLOT(_dom)) ) \ { \ @@ -1411,7 +1410,7 @@ void sh_install_xen_entries_in_l4(struct __PAGE_HYPERVISOR); } - if ( IS_COMPAT(v->domain) ) + if ( pv_32on64_domain(v->domain) ) { /* install compat arg xlat entry */ sl4e[shadow_l4_table_offset(COMPAT_ARG_XLAT_VIRT_BASE)] = @@ -1437,7 +1436,7 @@ static void sh_install_xen_entries_in_l2 int i; #else - if ( !pv_32bit_guest(v) ) + if ( !pv_32on64_vcpu(v) ) return; #endif @@ -1622,9 +1621,6 @@ sh_make_shadow(struct vcpu *v, mfn_t gmf #endif #if CONFIG_PAGING_LEVELS >= 3 && GUEST_PAGING_LEVELS >= 3 case SH_type_l2h_shadow: -#ifdef CONFIG_COMPAT - ASSERT( IS_COMPAT(v->domain) ); -#endif sh_install_xen_entries_in_l2h(v, smfn); break; #endif #if CONFIG_PAGING_LEVELS == 2 && GUEST_PAGING_LEVELS == 2 @@ -1685,7 +1681,7 @@ sh_make_monitor_table(struct vcpu *v) l4e = sh_map_domain_page(m4mfn); l4e[0] = l4e_from_pfn(mfn_x(m3mfn), __PAGE_HYPERVISOR); sh_unmap_domain_page(l4e); - if ( pv_32bit_guest(v) ) + if ( pv_32on64_vcpu(v) ) { // Install a monitor l2 table in slot 3 of the l3 table. // This is used for all Xen entries. @@ -1840,13 +1836,12 @@ static shadow_l2e_t * shadow_get_and_cre shadow_l3e_t new_sl3e; unsigned int t = SH_type_l2_shadow; -#ifdef CONFIG_COMPAT /* Tag compat L2 containing hypervisor (m2p) mappings */ - if ( IS_COMPAT(v->domain) && + if ( pv_32on64_domain(v->domain) && guest_l4_table_offset(gw->va) == 0 && guest_l3_table_offset(gw->va) == 3 ) t = SH_type_l2h_shadow; -#endif + /* No l2 shadow installed: find and install it. */ *sl2mfn = get_shadow_status(v, gw->l2mfn, t); if ( !mfn_valid(*sl2mfn) ) @@ -2111,7 +2106,7 @@ void sh_destroy_monitor_table(struct vcp l4_pgentry_t *l4e = sh_map_domain_page(mmfn); ASSERT(l4e_get_flags(l4e[0]) & _PAGE_PRESENT); m3mfn = _mfn(l4e_get_pfn(l4e[0])); - if ( pv_32bit_guest(v) ) + if ( pv_32on64_vcpu(v) ) { /* Need to destroy the l2 monitor page in slot 3 too */ l3_pgentry_t *l3e = sh_map_domain_page(m3mfn); @@ -3474,7 +3469,7 @@ sh_update_cr3(struct vcpu *v, int do_loc (unsigned long)pagetable_get_pfn(v->arch.guest_table)); #if GUEST_PAGING_LEVELS == 4 - if ( !(v->arch.flags & TF_kernel_mode) && !IS_COMPAT(v->domain) ) + if ( !(v->arch.flags & TF_kernel_mode) && !pv_32on64_vcpu(v) ) gmfn = pagetable_get_mfn(v->arch.guest_table_user); else #endif @@ -4285,7 +4280,7 @@ int sh_audit_l3_table(struct vcpu *v, mf mfn = shadow_l3e_get_mfn(*sl3e); gmfn = get_shadow_status(v, audit_gfn_to_mfn(v, gfn, gl3mfn), ((GUEST_PAGING_LEVELS == 3 || - IS_COMPAT(v->domain)) + pv_32on64_vcpu(v)) && !shadow_mode_external(v->domain) && (guest_index(gl3e) % 4) == 3) ? SH_type_l2h_shadow diff -r 491bed0350f1 -r 3c352bbc894d xen/arch/x86/x86_32/entry.S --- a/xen/arch/x86/x86_32/entry.S Fri Apr 27 13:25:58 2007 +0100 +++ b/xen/arch/x86/x86_32/entry.S Fri Apr 27 13:31:09 2007 +0100 @@ -75,6 +75,7 @@ ALIGN restore_all_guest: + ASSERT_INTERRUPTS_DISABLED testl $X86_EFLAGS_VM,UREGS_eflags(%esp) jnz restore_all_vm86 #ifdef CONFIG_X86_SUPERVISOR_MODE_KERNEL @@ -129,10 +130,10 @@ failsafe_callback: movl %eax,TRAPBOUNCE_eip(%edx) movl VCPU_failsafe_sel(%ebx),%eax movw %ax,TRAPBOUNCE_cs(%edx) - movw $TBF_FAILSAFE,TRAPBOUNCE_flags(%edx) + movb $TBF_FAILSAFE,TRAPBOUNCE_flags(%edx) bt $_VGCF_failsafe_disables_events,VCPU_guest_context_flags(%ebx) jnc 1f - orw $TBF_INTERRUPT,TRAPBOUNCE_flags(%edx) + orb $TBF_INTERRUPT,TRAPBOUNCE_flags(%edx) 1: call create_bounce_frame xorl %eax,%eax movl %eax,UREGS_ds(%esp) @@ -247,7 +248,7 @@ test_guest_events: movl %eax,TRAPBOUNCE_eip(%edx) movl VCPU_event_sel(%ebx),%eax movw %ax,TRAPBOUNCE_cs(%edx) - movw $TBF_INTERRUPT,TRAPBOUNCE_flags(%edx) + movb $TBF_INTERRUPT,TRAPBOUNCE_flags(%edx) call create_bounce_frame jmp test_all_events @@ -270,7 +271,7 @@ process_nmi: leal VCPU_trap_bounce(%ebx),%edx movl %eax,TRAPBOUNCE_eip(%edx) movw $FLAT_KERNEL_CS,TRAPBOUNCE_cs(%edx) - movw $TBF_INTERRUPT,TRAPBOUNCE_flags(%edx) + movb $TBF_INTERRUPT,TRAPBOUNCE_flags(%edx) call create_bounce_frame jmp test_all_events @@ -383,7 +384,6 @@ 2: testl $X86_EFLAGS_VM,UREGS_eflag movl %eax,UREGS_cs+4(%esp) movl TRAPBOUNCE_eip(%edx),%eax movl %eax,UREGS_eip+4(%esp) - movb $0,TRAPBOUNCE_flags(%edx) ret .section __ex_table,"a" .long .Lft6,domain_crash_synchronous , .Lft7,domain_crash_synchronous @@ -441,6 +441,7 @@ 1: xorl %eax,%eax testb $TBF_EXCEPTION,TRAPBOUNCE_flags(%edx) jz test_all_events call create_bounce_frame + movb $0,TRAPBOUNCE_flags(%edx) jmp test_all_events exception_with_ints_disabled: diff -r 491bed0350f1 -r 3c352bbc894d xen/arch/x86/x86_64/compat/entry.S --- a/xen/arch/x86/x86_64/compat/entry.S Fri Apr 27 13:25:58 2007 +0100 +++ b/xen/arch/x86/x86_64/compat/entry.S Fri Apr 27 13:31:09 2007 +0100 @@ -101,8 +101,8 @@ compat_test_guest_events: movl VCPU_event_addr(%rbx),%eax movl %eax,TRAPBOUNCE_eip(%rdx) movl VCPU_event_sel(%rbx),%eax - movl %eax,TRAPBOUNCE_cs(%rdx) - movw $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx) + movw %ax,TRAPBOUNCE_cs(%rdx) + movb $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx) call compat_create_bounce_frame jmp compat_test_all_events @@ -126,8 +126,8 @@ compat_process_nmi: sti leaq VCPU_trap_bounce(%rbx),%rdx movl %eax,TRAPBOUNCE_eip(%rdx) - movl $FLAT_COMPAT_KERNEL_CS,TRAPBOUNCE_cs(%rdx) - movw $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx) + movw $FLAT_COMPAT_KERNEL_CS,TRAPBOUNCE_cs(%rdx) + movb $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx) call compat_create_bounce_frame jmp compat_test_all_events @@ -164,13 +164,12 @@ compat_failsafe_callback: movl VCPU_failsafe_addr(%rbx),%eax movl %eax,TRAPBOUNCE_eip(%rdx) movl VCPU_failsafe_sel(%rbx),%eax - movl %eax,TRAPBOUNCE_cs(%rdx) - movw $TBF_FAILSAFE,TRAPBOUNCE_flags(%rdx) + movw %ax,TRAPBOUNCE_cs(%rdx) + movb $TBF_FAILSAFE,TRAPBOUNCE_flags(%rdx) btq $_VGCF_failsafe_disables_events,VCPU_guest_context_flags(%rbx) jnc 1f - orw $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx) -1: - call compat_create_bounce_frame + orb $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx) +1: call compat_create_bounce_frame jmp compat_test_all_events .previous .section __pre_ex_table,"a" @@ -185,6 +184,7 @@ ENTRY(compat_post_handle_exception) testb $TBF_EXCEPTION,TRAPBOUNCE_flags(%rdx) jz compat_test_all_events call compat_create_bounce_frame + movb $0,TRAPBOUNCE_flags(%rdx) jmp compat_test_all_events ENTRY(compat_int80_direct_trap) @@ -194,7 +194,7 @@ ENTRY(compat_int80_direct_trap) /* CREATE A BASIC EXCEPTION FRAME ON GUEST OS (RING-1) STACK: */ /* {[ERRCODE,] EIP, CS, EFLAGS, [ESP, SS]} */ /* %rdx: trap_bounce, %rbx: struct vcpu */ -/* On return only %rbx is guaranteed non-clobbered. */ +/* On return only %rbx and %rdx are guaranteed non-clobbered. */ compat_create_bounce_frame: ASSERT_INTERRUPTS_ENABLED mov %fs,%edi @@ -253,7 +253,6 @@ 2: 2: /* Rewrite our stack frame and return to guest-OS mode. */ /* IA32 Ref. Vol. 3: TF, VM, RF and NT flags are cleared on trap. */ - movl $TRAP_syscall,UREGS_entry_vector+8(%rsp) andl $~(X86_EFLAGS_VM|X86_EFLAGS_RF|\ X86_EFLAGS_NT|X86_EFLAGS_TF),UREGS_eflags+8(%rsp) mov %fs,UREGS_ss+8(%rsp) @@ -266,7 +265,6 @@ 2: movl %eax,UREGS_cs+8(%rsp) movl TRAPBOUNCE_eip(%rdx),%eax movl %eax,UREGS_rip+8(%rsp) - movb $0,TRAPBOUNCE_flags(%rdx) ret .section .fixup,"ax" .Lfx13: @@ -333,7 +331,7 @@ ENTRY(compat_hypercall_table) .quad compat_vcpu_op .quad compat_ni_hypercall /* 25 */ .quad compat_mmuext_op - .quad compat_acm_op + .quad do_acm_op .quad compat_nmi_op .quad compat_sched_op .quad compat_callback_op /* 30 */ @@ -376,7 +374,7 @@ ENTRY(compat_hypercall_args_table) .byte 3 /* compat_vcpu_op */ .byte 0 /* compat_ni_hypercall */ /* 25 */ .byte 4 /* compat_mmuext_op */ - .byte 1 /* compat_acm_op */ + .byte 1 /* do_acm_op */ .byte 2 /* compat_nmi_op */ .byte 2 /* compat_sched_op */ .byte 2 /* compat_callback_op */ /* 30 */ diff -r 491bed0350f1 -r 3c352bbc894d xen/arch/x86/x86_64/entry.S --- a/xen/arch/x86/x86_64/entry.S Fri Apr 27 13:25:58 2007 +0100 +++ b/xen/arch/x86/x86_64/entry.S Fri Apr 27 13:31:09 2007 +0100 @@ -29,10 +29,10 @@ switch_to_kernel: leaq VCPU_trap_bounce(%rbx),%rdx movq VCPU_syscall_addr(%rbx),%rax movq %rax,TRAPBOUNCE_eip(%rdx) - movw $0,TRAPBOUNCE_flags(%rdx) + movb $0,TRAPBOUNCE_flags(%rdx) bt $_VGCF_syscall_disables_events,VCPU_guest_context_flags(%rbx) jnc 1f - orw $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx) + movb $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx) 1: call create_bounce_frame jmp test_all_events @@ -80,10 +80,10 @@ failsafe_callback: leaq VCPU_trap_bounce(%rbx),%rdx movq VCPU_failsafe_addr(%rbx),%rax movq %rax,TRAPBOUNCE_eip(%rdx) - movw $TBF_FAILSAFE,TRAPBOUNCE_flags(%rdx) + movb $TBF_FAILSAFE,TRAPBOUNCE_flags(%rdx) bt $_VGCF_failsafe_disables_events,VCPU_guest_context_flags(%rbx) jnc 1f - orw $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx) + orb $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx) 1: call create_bounce_frame jmp test_all_events .previous @@ -191,7 +191,7 @@ test_guest_events: leaq VCPU_trap_bounce(%rbx),%rdx movq VCPU_event_addr(%rbx),%rax movq %rax,TRAPBOUNCE_eip(%rdx) - movw $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx) + movb $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx) call create_bounce_frame jmp test_all_events @@ -215,7 +215,7 @@ process_nmi: sti leaq VCPU_trap_bounce(%rbx),%rdx movq %rax,TRAPBOUNCE_eip(%rdx) - movw $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx) + movb $TBF_INTERRUPT,TRAPBOUNCE_flags(%rdx) call create_bounce_frame jmp test_all_events @@ -231,7 +231,7 @@ ENTRY(int80_direct_trap) /* Check that the callback is non-null. */ leaq VCPU_int80_bounce(%rbx),%rdx - cmp $0,TRAPBOUNCE_flags(%rdx) + cmpb $0,TRAPBOUNCE_flags(%rdx) jz int80_slow_path movq VCPU_domain(%rbx),%rax @@ -249,13 +249,13 @@ int80_slow_path: 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) + subq $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 */ -/* On return only %rbx is guaranteed non-clobbered. */ +/* %rdx: trap_bounce, %rbx: struct vcpu */ +/* On return only %rbx and %rdx are guaranteed non-clobbered. */ create_bounce_frame: ASSERT_INTERRUPTS_ENABLED testb $TF_kernel_mode,VCPU_thread_flags(%rbx) @@ -336,7 +336,6 @@ 2: subq $16,%rsi testq %rax,%rax jz domain_crash_synchronous movq %rax,UREGS_rip+8(%rsp) - movb $0,TRAPBOUNCE_flags(%rdx) ret .section __ex_table,"a" .quad .Lft2,domain_crash_synchronous , .Lft3,domain_crash_synchronous @@ -401,6 +400,7 @@ 1: movq %rsp,%rdi testb $TBF_EXCEPTION,TRAPBOUNCE_flags(%rdx) jz test_all_events call create_bounce_frame + movb $0,TRAPBOUNCE_flags(%rdx) jmp test_all_events /* No special register assumptions. */ diff -r 491bed0350f1 -r 3c352bbc894d xen/arch/x86/x86_64/traps.c --- a/xen/arch/x86/x86_64/traps.c Fri Apr 27 13:25:58 2007 +0100 +++ b/xen/arch/x86/x86_64/traps.c Fri Apr 27 13:31:09 2007 +0100 @@ -357,9 +357,6 @@ void init_int80_direct_trap(struct vcpu 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; diff -r 491bed0350f1 -r 3c352bbc894d xen/common/Makefile --- a/xen/common/Makefile Fri Apr 27 13:25:58 2007 +0100 +++ b/xen/common/Makefile Fri Apr 27 13:31:09 2007 +0100 @@ -43,7 +43,6 @@ version.o: $(BASEDIR)/include/xen/compil ifeq ($(CONFIG_COMPAT),y) # extra dependencies -acm_ops.o: compat/acm_ops.c grant_table.o: compat/grant_table.c kexec.o: compat/kexec.c schedule.o: compat/schedule.c diff -r 491bed0350f1 -r 3c352bbc894d xen/common/acm_ops.c --- a/xen/common/acm_ops.c Fri Apr 27 13:25:58 2007 +0100 +++ b/xen/common/acm_ops.c Fri Apr 27 13:31:09 2007 +0100 @@ -12,10 +12,8 @@ * License. * * Process acm command requests from guest OS. - * */ -#ifndef COMPAT #include <xen/config.h> #include <xen/types.h> #include <xen/lib.h> @@ -29,38 +27,25 @@ #include <xen/guest_access.h> #include <acm/acm_hooks.h> -typedef long ret_t; - -#endif /* !COMPAT */ - #ifndef ACM_SECURITY - long do_acm_op(int cmd, XEN_GUEST_HANDLE(void) arg) { return -ENOSYS; } - #else - -#ifndef COMPAT int acm_authorize_acm_ops(struct domain *d) { - /* currently, policy management functions are restricted to privileged domains */ - if (!IS_PRIV(d)) - return -EPERM; - return 0; -} -#endif - - -ret_t do_acm_op(int cmd, XEN_GUEST_HANDLE(void) arg) -{ - ret_t rc = -EFAULT; - - if (acm_authorize_acm_ops(current->domain)) + return (IS_PRIV(d) ? 0 : -EPERM); +} + +long do_acm_op(int cmd, XEN_GUEST_HANDLE(void) arg) +{ + long rc = -EFAULT; + + if ( acm_authorize_acm_ops(current->domain) ) return -EPERM; switch ( cmd ) @@ -226,11 +211,9 @@ ret_t do_acm_op(int cmd, XEN_GUEST_HANDL rc = acm_change_policy(&chgpolicy); - if (rc == 0) { - if (copy_to_guest(arg, &chgpolicy, 1) != 0) { + if (rc == 0) + if (copy_to_guest(arg, &chgpolicy, 1) != 0) rc = -EFAULT; - } - } break; } @@ -244,11 +227,9 @@ ret_t do_acm_op(int cmd, XEN_GUEST_HANDL rc = acm_relabel_domains(&relabeldoms); - if (rc == 0) { - if (copy_to_guest(arg, &relabeldoms, 1) != 0) { + if (rc == 0) + if (copy_to_guest(arg, &relabeldoms, 1) != 0) rc = -EFAULT; - } - } break; } @@ -260,11 +241,7 @@ ret_t do_acm_op(int cmd, XEN_GUEST_HANDL return rc; } -#endif - -#if defined(CONFIG_COMPAT) && !defined(COMPAT) -#include "compat/acm_ops.c" -#endif +#endif /* defined(ACM_SECURITY) */ /* * Local variables: diff -r 491bed0350f1 -r 3c352bbc894d xen/common/compat/acm_ops.c --- a/xen/common/compat/acm_ops.c Fri Apr 27 13:25:58 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -/****************************************************************************** - * compat/acm_ops.c - */ - -#include <compat/acm.h> -#include <compat/acm_ops.h> - -#define COMPAT -#define ret_t int - -#define do_acm_op compat_acm_op - -static inline XEN_GUEST_HANDLE(void) acm_xlat_handle(COMPAT_HANDLE(void) cmp) -{ - XEN_GUEST_HANDLE(void) nat; - - guest_from_compat_handle(nat, cmp); - return nat; -} - -#define acm_setpolicy compat_acm_setpolicy -#define acm_set_policy(h, sz) acm_set_policy(acm_xlat_handle(h), sz) - -#define acm_getpolicy compat_acm_getpolicy -#define acm_get_policy(h, sz) acm_get_policy(acm_xlat_handle(h), sz) - -#define acm_dumpstats compat_acm_dumpstats -#define acm_dump_statistics(h, sz) acm_dump_statistics(acm_xlat_handle(h), sz) - -#define acm_getssid compat_acm_getssid -#define acm_get_ssid(r, h, sz) acm_get_ssid(r, acm_xlat_handle(h), sz) - -#define xen_acm_getdecision acm_getdecision -CHECK_acm_getdecision; -#undef xen_acm_getdecision - -#include "../acm_ops.c" - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff -r 491bed0350f1 -r 3c352bbc894d xen/include/Makefile --- a/xen/include/Makefile Fri Apr 27 13:25:58 2007 +0100 +++ b/xen/include/Makefile Fri Apr 27 13:31:09 2007 +0100 @@ -3,8 +3,6 @@ compat-arch-$(CONFIG_X86) := x86_32 compat-arch-$(CONFIG_X86) := x86_32 headers-y := \ - compat/acm.h \ - compat/acm_ops.h \ compat/callback.h \ compat/elfnote.h \ compat/event_channel.h \ diff -r 491bed0350f1 -r 3c352bbc894d xen/include/acm/acm_core.h --- a/xen/include/acm/acm_core.h Fri Apr 27 13:25:58 2007 +0100 +++ b/xen/include/acm/acm_core.h Fri Apr 27 13:31:09 2007 +0100 @@ -155,13 +155,13 @@ int acm_init_domain_ssid_new(struct doma int acm_init_domain_ssid_new(struct domain *, ssidref_t ssidref); void acm_free_domain_ssid(struct acm_ssid_domain *ssid); int acm_init_binary_policy(u32 policy_code); -int acm_set_policy(XEN_GUEST_HANDLE(void) buf, u32 buf_size); +int acm_set_policy(XEN_GUEST_HANDLE_64(void) buf, u32 buf_size); int do_acm_set_policy(void *buf, u32 buf_size, int is_bootpolicy, struct acm_sized_buffer *, struct acm_sized_buffer *, struct acm_sized_buffer *); -int acm_get_policy(XEN_GUEST_HANDLE(void) buf, u32 buf_size); -int acm_dump_statistics(XEN_GUEST_HANDLE(void) buf, u16 buf_size); -int acm_get_ssid(ssidref_t ssidref, XEN_GUEST_HANDLE(void) buf, u16 buf_size); +int acm_get_policy(XEN_GUEST_HANDLE_64(void) buf, u32 buf_size); +int acm_dump_statistics(XEN_GUEST_HANDLE_64(void) buf, u16 buf_size); +int acm_get_ssid(ssidref_t ssidref, XEN_GUEST_HANDLE_64(void) buf, u16 buf_size); int acm_get_decision(ssidref_t ssidref1, ssidref_t ssidref2, u32 hook); int acm_set_policy_reference(u8 * buf, u32 buf_size); int acm_dump_policy_reference(u8 *buf, u32 buf_size); diff -r 491bed0350f1 -r 3c352bbc894d xen/include/asm-x86/domain.h --- a/xen/include/asm-x86/domain.h Fri Apr 27 13:25:58 2007 +0100 +++ b/xen/include/asm-x86/domain.h Fri Apr 27 13:31:09 2007 +0100 @@ -7,11 +7,24 @@ #include <asm/hvm/domain.h> #include <asm/e820.h> +#ifdef __x86_64__ +#define pv_32bit_vcpu(v) (!is_hvm_vcpu(v) && IS_COMPAT((v)->domain)) +#define pv_32bit_domain(d) (!is_hvm_domain(d) && IS_COMPAT(d)) +#define pv_32on64_vcpu(v) (pv_32bit_vcpu(v)) +#define pv_32on64_domain(d) (pv_32bit_domain(d)) +#else +#define pv_32bit_vcpu(v) (!is_hvm_vcpu(v)) +#define pv_32bit_domain(d) (!is_hvm_domain(d)) +#define pv_32on64_vcpu(v) (0) +#define pv_32on64_domain(d) (0) +#endif + + struct trap_bounce { - unsigned long error_code; - unsigned short flags; /* TBF_ */ - unsigned short cs; - unsigned long eip; + uint32_t error_code; + uint8_t flags; /* TBF_ */ + uint16_t cs; + unsigned long eip; }; #define MAPHASH_ENTRIES 8 diff -r 491bed0350f1 -r 3c352bbc894d xen/include/asm-x86/hvm/vmx/vmcs.h --- a/xen/include/asm-x86/hvm/vmx/vmcs.h Fri Apr 27 13:25:58 2007 +0100 +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h Fri Apr 27 13:31:09 2007 +0100 @@ -119,6 +119,8 @@ extern u32 vmx_vmexit_control; #define VM_ENTRY_DEACT_DUAL_MONITOR 0x00000800 extern u32 vmx_vmentry_control; +#define cpu_has_vmx_tpr_shadow \ + (vmx_cpu_based_exec_control & CPU_BASED_TPR_SHADOW) #define cpu_has_vmx_msr_bitmap \ (vmx_cpu_based_exec_control & CPU_BASED_ACTIVATE_MSR_BITMAP) extern char *vmx_msr_bitmap; diff -r 491bed0350f1 -r 3c352bbc894d xen/include/asm-x86/shadow.h --- a/xen/include/asm-x86/shadow.h Fri Apr 27 13:25:58 2007 +0100 +++ b/xen/include/asm-x86/shadow.h Fri Apr 27 13:31:09 2007 +0100 @@ -48,16 +48,6 @@ * not yet supported */ #define shadow_mode_trap_reads(_d) ({ (void)(_d); 0; }) -/* - * 32on64 support - */ -#ifdef __x86_64__ -#define pv_32bit_guest(_v) (!is_hvm_vcpu(_v) && IS_COMPAT((_v)->domain)) -#else -#define pv_32bit_guest(_v) (!is_hvm_vcpu(_v)) -#endif - - /***************************************************************************** * Entry points into the shadow code */ diff -r 491bed0350f1 -r 3c352bbc894d xen/include/public/hvm/save.h --- a/xen/include/public/hvm/save.h Fri Apr 27 13:25:58 2007 +0100 +++ b/xen/include/public/hvm/save.h Fri Apr 27 13:31:09 2007 +0100 @@ -32,7 +32,8 @@ /* * Structures in this header *must* have the same layout in 32bit * and 64bit environments: this means that all fields must be explicitly - * sized types and aligned to their sizes. + * sized types and aligned to their sizes, and the structs must be + * a multiple of eight bytes long. * * Only the state necessary for saving and restoring (i.e. fields * that are analogous to actual hardware state) should go in this file. @@ -77,6 +78,7 @@ struct hvm_save_header { uint32_t version; /* File format version */ uint64_t changeset; /* Version of Xen that saved this file */ uint32_t cpuid; /* CPUID[0x01][%eax] on the saving machine */ + uint32_t pad0; }; DECLARE_HVM_SAVE_TYPE(HEADER, 1, struct hvm_save_header); @@ -340,6 +342,7 @@ struct hvm_hw_pci_link { * The router provides a programmable mapping from each link to a GSI. */ uint8_t route[4]; + uint8_t pad0[4]; }; DECLARE_HVM_SAVE_TYPE(PCI_LINK, 9, struct hvm_hw_pci_link); @@ -364,6 +367,7 @@ struct hvm_hw_pit { uint8_t gate; /* timer start */ } channels[3]; /* 3 x 16 bytes */ uint32_t speaker_data_on; + uint32_t pad0; }; DECLARE_HVM_SAVE_TYPE(PIT, 10, struct hvm_hw_pit); @@ -379,6 +383,7 @@ struct hvm_hw_rtc { uint8_t cmos_data[RTC_CMOS_SIZE]; /* Index register for 2-part operations */ uint8_t cmos_index; + uint8_t pad0; }; DECLARE_HVM_SAVE_TYPE(RTC, 11, struct hvm_hw_rtc); diff -r 491bed0350f1 -r 3c352bbc894d xen/include/xlat.lst --- a/xen/include/xlat.lst Fri Apr 27 13:25:58 2007 +0100 +++ b/xen/include/xlat.lst Fri Apr 27 13:31:09 2007 +0100 @@ -9,7 +9,6 @@ ! cpu_user_regs arch-x86/xen-@arch@.h ! trap_info arch-x86/xen.h ! vcpu_guest_context arch-x86/xen.h -? acm_getdecision acm_ops.h ? evtchn_alloc_unbound event_channel.h ? evtchn_bind_interdomain event_channel.h ? evtchn_bind_ipi event_channel.h _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |