Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Merge branch 'devel' of ssh://palacios@newskysaw.cs.northwestern.edu/home/palacios...
Lei Xia [Tue, 1 Dec 2009 05:47:46 +0000 (23:47 -0600)]
92 files changed:
Kconfig
Kconfig.template [deleted file]
palacios/include/devices/block_dev.h [deleted file]
palacios/include/devices/cga.h [deleted file]
palacios/include/devices/generic.h [deleted file]
palacios/include/devices/ide.h
palacios/include/devices/lnx_virtio_blk.h [deleted file]
palacios/include/devices/net_cd.h [deleted file]
palacios/include/devices/net_hd.h [deleted file]
palacios/include/devices/pci.h
palacios/include/devices/pci_passthrough.h [deleted file]
palacios/include/devices/ram_cd.h [deleted file]
palacios/include/devices/ram_hd.h [deleted file]
palacios/include/devices/telnet_cons.h [deleted file]
palacios/include/devices/vnet.h
palacios/include/palacios/svm.h
palacios/include/palacios/vm_guest.h
palacios/include/palacios/vmm.h
palacios/include/palacios/vmm_config.h
palacios/include/palacios/vmm_dev_mgr.h
palacios/include/palacios/vmm_mem.h
palacios/include/palacios/vmm_shadow_paging.h
palacios/include/palacios/vmm_sprintf.h
palacios/include/palacios/vmm_string.h
palacios/include/palacios/vmm_sym_iface.h
palacios/include/palacios/vmm_xml.h [new file with mode: 0644]
palacios/include/palacios/vmx.h
palacios/src/devices/8254.c
palacios/src/devices/8259a.c
palacios/src/devices/Kconfig
palacios/src/devices/Makefile
palacios/src/devices/apic.c
palacios/src/devices/ata.h
palacios/src/devices/atapi.h
palacios/src/devices/bochs_debug.c
palacios/src/devices/cga.c
palacios/src/devices/cirrus_gfx_card.c
palacios/src/devices/generic.c
palacios/src/devices/i440fx.c
palacios/src/devices/ide.c
palacios/src/devices/io_apic.c
palacios/src/devices/keyboard.c
palacios/src/devices/lnx_virtio_balloon.c
palacios/src/devices/lnx_virtio_blk.c
palacios/src/devices/lnx_virtio_sym.c
palacios/src/devices/net_cd.c [deleted file]
palacios/src/devices/netdisk.c [moved from palacios/src/devices/net_hd.c with 55% similarity]
palacios/src/devices/nvram.c
palacios/src/devices/os_debug.c
palacios/src/devices/para_net.c
palacios/src/devices/pci.c
palacios/src/devices/pci_passthrough.c
palacios/src/devices/piix3.c
palacios/src/devices/ram_cd.c [deleted file]
palacios/src/devices/ram_hd.c [deleted file]
palacios/src/devices/ramdisk.c [new file with mode: 0644]
palacios/src/devices/sym_swap.c
palacios/src/devices/telnet_cons.c
palacios/src/devices/tmpdisk.c [new file with mode: 0644]
palacios/src/palacios/Makefile
palacios/src/palacios/svm.c
palacios/src/palacios/svm_msr.c
palacios/src/palacios/vmm.c
palacios/src/palacios/vmm_config.c
palacios/src/palacios/vmm_config_class.h [new file with mode: 0644]
palacios/src/palacios/vmm_cpuid.c
palacios/src/palacios/vmm_ctrl_regs.c
palacios/src/palacios/vmm_dev_mgr.c
palacios/src/palacios/vmm_excp.c
palacios/src/palacios/vmm_host_events.c
palacios/src/palacios/vmm_hypercall.c
palacios/src/palacios/vmm_io.c
palacios/src/palacios/vmm_mem.c
palacios/src/palacios/vmm_shadow_paging.c
palacios/src/palacios/vmm_string.c
palacios/src/palacios/vmm_sym_iface.c
palacios/src/palacios/vmm_sym_swap.c
palacios/src/palacios/vmm_time.c
palacios/src/palacios/vmm_xml.c [new file with mode: 0644]
utils/binutils-2.16.91.0.7.tar.gz [deleted file]
utils/gcc-3.4.6.tar.gz [deleted file]
utils/guest_creator/Makefile [new file with mode: 0644]
utils/guest_creator/README [new file with mode: 0644]
utils/guest_creator/default.xml [new file with mode: 0644]
utils/guest_creator/ezxml.c [new file with mode: 0644]
utils/guest_creator/ezxml.h [new file with mode: 0644]
utils/guest_creator/ezxml.txt [new file with mode: 0644]
utils/guest_creator/main.c [new file with mode: 0644]
utils/guest_creator/out_format [new file with mode: 0644]
utils/nasm-0.98.39.tar.gz [deleted file]
utils/nasm-install.patch [deleted file]
utils/vmx.patch [deleted file]

diff --git a/Kconfig b/Kconfig
index d997eea..4f43d7d 100644 (file)
--- a/Kconfig
+++ b/Kconfig
@@ -130,6 +130,13 @@ config BUILT_IN_MEMCPY
        help 
          This enables Palacios' internal implementation of memcpy
 
+config BUILT_IN_MEMMOVE
+       bool "memmove()"
+       default n
+       depends on BUILT_IN_STDLIB
+       help 
+         This enables Palacios' internal implementation of memmove
+
 config BUILT_IN_MEMCMP
        bool "memcmp()"
        default n
@@ -159,6 +166,14 @@ config BUILT_IN_STRCMP
        help 
          This enables Palacios' internal implementation of strcmp
 
+
+config BUILT_IN_STRCASECMP
+       bool "strcasecmp()"
+       default n
+       depends on BUILT_IN_STDLIB
+       help
+         This enables Palacios' internal implementation of strcasecmp
+
 config BUILT_IN_STRNCMP
        bool "strncmp()"
        default n
@@ -166,6 +181,14 @@ config BUILT_IN_STRNCMP
        help 
          This enables Palacios' internal implementation of strncmp
 
+config BUILT_IN_STRNCASECMP
+       bool "strncasecmp()"
+       default n
+       depends on BUILT_IN_STDLIB
+       help
+         This enables Palacios' internal implementation of strncasecmp
+
+
 config BUILT_IN_STRCAT
        bool "strcat()"
        default n
@@ -201,6 +224,13 @@ config BUILT_IN_STRDUP
        help 
          This enables Palacios' internal implementation of strdup
 
+config BUILT_IN_STRSTR
+       bool "strstr()"
+       default n
+       depends on BUILT_IN_STDLIB
+       help
+         This enables Palacios internal implementation of strstr
+
 
 config BUILT_IN_ATOI
        bool "atoi()"
diff --git a/Kconfig.template b/Kconfig.template
deleted file mode 100644 (file)
index eb959b6..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-mainmenu "Palacios VMM Configuration"
-
-config x86_64
-       bool
-       default y
-       help
-         Support for the x86-64 architecture.
-
-
-menu "Target Configuration"
-
-choice
-       prompt "System Architecture"
-       default PC
-
-config V3_32BIT
-        bool "Compile a 32 bit library"
-        help
-         Support for 32 bit Operating Systems
-
-config V3_64BIT
-       bool "Compile a 64 bit library"
-       help 
-         Support for 64 bit Operating Systems
-endchoice
-
-config CRAY_XT
-        bool "Red Storm (Cray XT3/XT4)"
-         help
-         Support for Cray XT3 and XT4 systems.
-
-
-
-#
-# Define implied options from the CPU selection
-#
-
-config X86_L1_CACHE_BYTES
-        int
-        default "128" if GENERIC_CPU || MPSC
-        default "64" if MK8
-
-config X86_L1_CACHE_SHIFT
-        int
-        default "7" if GENERIC_CPU || MPSC
-        default "6" if MK8
-
-config X86_INTERNODE_CACHE_BYTES
-       int
-       default X86_L1_CACHE_BYTES
-
-config X86_INTERNODE_CACHE_SHIFT
-       int
-       default X86_L1_CACHE_SHIFT
-
-config NR_CPUS
-        int "Maximum number of CPUs (2-256)"
-        range 1 255
-        default "16"
-        help
-          This allows you to specify the maximum number of CPUs which this
-          kernel will support. Current maximum is 256 CPUs due to
-          APIC addressing limits. Less depending on the hardware.
-
-          This is purely to save memory - each supported CPU requires
-          memory in the static kernel configuration.
-
-#
-# Physical address where the kernel is loaded
-#
-config PHYSICAL_START
-       hex
-       default "0x200000"
-
-endmenu
-
-menu "Virtualization"
-
-config PALACIOS
-       bool "Include Palacios virtual machine monitor"
-       default "n"
-       help
-         Include the Palacios virtual machine monitor. This enables Kitten
-         to run guest operating systems alongside native applications.
-
-config PALACIOS_SOCKET
-       bool
-       depends on NETWORK && LWIP_TCP && LWIP_UDP && LWIP_SOCKET
-       default "y"
-
-config PALACIOS_PATH
-       string "Path to pre-built Palacios tree"
-       depends on PALACIOS
-       default "../palacios"
-       help
-         Path to a built Palacios source tree. This path is used to
-         find Palacios include files and libraries that need to be
-         linked with the Kitten kernel image.
-
-config GUEST_OS_ISOIMAGE_PATH
-       string "Path to guest OS ISO image"
-       depends on PALACIOS
-       default "/opt/vmm-tools/isos/puppy.iso"
-       help
-         Path to an ISO image to link with the example user/hello_world
-         init task.  The hello_world init task will use this ISO image
-         to spawn a guest OS virtual machine via Palacios.
-
-endmenu
-
-#source "net/Kconfig"
-
diff --git a/palacios/include/devices/block_dev.h b/palacios/include/devices/block_dev.h
deleted file mode 100644 (file)
index 574c5af..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-
-/* 
- * This file is part of the Palacios Virtual Machine Monitor developed
- * by the V3VEE Project with funding from the United States National 
- * Science Foundation and the Department of Energy.  
- *
- * The V3VEE Project is a joint project between Northwestern University
- * and the University of New Mexico.  You can find out more at 
- * http://www.v3vee.org
- *
- * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
- * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
- * All rights reserved.
- *
- * Author: Jack Lange <jarusl@cs.northwestern.edu>
- *
- * This is free software.  You are permitted to use,
- * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
- */
-
-#ifndef __DEVICES_BLOCK_DEV_H__
-#define __DEVICES_BLOCK_DEV_H__
-
-#ifdef __V3VEE__
-
-
-
-#define ATAPI_BLOCK_SIZE 2048
-#define HD_SECTOR_SIZE 512
-
-
-struct v3_hd_ops {
-    uint64_t (*get_capacity)(void * private_data);
-    // Reads always operate on 2048 byte blocks
-    int (*read)(uint8_t * buf, int sector_count, uint64_t lba, void * private_data);
-    int (*write)(uint8_t * buf, int sector_count, uint64_t lba, void * private_data);
-};
-
-
-
-struct v3_cd_ops {
-    uint32_t (*get_capacity)(void * private_data);
-    // Reads always operate on 2048 byte blocks
-    int (*read)(uint8_t * buf, int block_count, uint64_t lba, void * private_data);
-};
-
-
-typedef enum {BLOCK_NONE, BLOCK_DISK, BLOCK_CDROM} v3_block_type_t;
-
-
-
-static const char * block_dev_type_strs[] = {"NONE", "HARDDISK", "CDROM" };
-
-static inline const char * v3_block_type_to_str(v3_block_type_t type) {
-    if (type > BLOCK_CDROM) {
-       return NULL;
-    }
-    return block_dev_type_strs[type];
-}
-
-
-
-#endif
-
-
-#endif
diff --git a/palacios/include/devices/cga.h b/palacios/include/devices/cga.h
deleted file mode 100644 (file)
index b2c168c..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* 
- * This file is part of the Palacios Virtual Machine Monitor developed
- * by the V3VEE Project with funding from the United States National 
- * Science Foundation and the Department of Energy.  
- *
- * The V3VEE Project is a joint project between Northwestern University
- * and the University of New Mexico.  You can find out more at 
- * http://www.v3vee.org
- *
- * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
- * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
- * All rights reserved.
- *
- * Author: Jack Lange <jarusl@cs.northwestern.edu>
- *
- * This is free software.  You are permitted to use,
- * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
- */
-
-#ifndef __DEVICES_CGA_H__
-#define __DEVICES_CGA_H__
-
-#ifdef __V3VEE__
-
-#include <devices/console.h>
-
-
-int v3_console_register_cga(struct vm_device * cga_dev, struct v3_console_ops * ops, void * private_data);
-
-#endif
-
-#endif
diff --git a/palacios/include/devices/generic.h b/palacios/include/devices/generic.h
deleted file mode 100644 (file)
index 77d3822..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/* 
- * This file is part of the Palacios Virtual Machine Monitor developed
- * by the V3VEE Project with funding from the United States National 
- * Science Foundation and the Department of Energy.  
- *
- * The V3VEE Project is a joint project between Northwestern University
- * and the University of New Mexico.  You can find out more at 
- * http://www.v3vee.org
- *
- * Copyright (c) 2008, Peter Dinda <pdinda@northwestern.edu> 
- * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
- * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
- * All rights reserved.
- *
- * Author: Peter Dinda <pdinda@northwestern.edu>
- * Author: Jack Lange <jarusl@cs.northwestern.edu>
- *
- * This is free software.  You are permitted to use,
- * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
- */
-
-
-#ifndef __DEVICES_GENERIC_H__
-#define __DEVICES_GENERIC_H__
-
-#ifdef __V3VEE__
-
-#include <palacios/vmm_dev_mgr.h>
-
-
-//
-// The generic device simply hooks ranges of ports, addresses, and irqs
-// if they are not already hooked
-//
-// for each hooked port, it simply executes reads and writes and the same physical port,
-// for each hooked memory range, it simply executes reads and writes on the same
-//    physical memory addresses
-// for each hooked irq, it simply injects the irq into the VM
-//
-// These operations are also logged to serial (optionaly)
-//
-// If you attach a generic device *last*, you can capture all ops that are not
-// already hooked, and capture a log of VM activity with respect to them.
-//
-// The effects of using the generic device should be identical to 
-// doing passthrough I/O, but with logging, and, of course, slower
-//
-
-
-#define GENERIC_PRINT_AND_PASSTHROUGH 0
-#define GENERIC_PRINT_AND_IGNORE      1
-
-
-int v3_generic_add_port_range(struct vm_device * dev, uint_t start, uint_t end, uint_t type);
-
-
-
-#endif // ! __V3VEE__
-
-#endif
index b778f1e..8f8951d 100644 (file)
 
 #ifdef __V3VEE__
 
-#include <devices/block_dev.h>
-
-struct ide_cfg {
-    char pci[32];
-    char southbridge[32];
-};
-
-
-int v3_ide_register_cdrom(struct vm_device * ide, 
-                         uint_t bus_num, 
-                         uint_t drive_num, 
-                         char * drive_name,
-                         struct v3_cd_ops * ops, 
-                         void * private_data);
-
-int v3_ide_register_harddisk(struct vm_device * ide, 
-                            uint_t bus_num, 
-                            uint_t drive_num, 
-                            char * drive_name,
-                            struct v3_hd_ops * ops, 
-                            void * private_data);
-
-
-
 
 
 int v3_ide_get_geometry(struct vm_device * ide_dev, int channel_num, int drive_num, 
diff --git a/palacios/include/devices/lnx_virtio_blk.h b/palacios/include/devices/lnx_virtio_blk.h
deleted file mode 100644 (file)
index 1bcf08c..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/* 
- * This file is part of the Palacios Virtual Machine Monitor developed
- * by the V3VEE Project with funding from the United States National 
- * Science Foundation and the Department of Energy.  
- *
- * The V3VEE Project is a joint project between Northwestern University
- * and the University of New Mexico.  You can find out more at 
- * http://www.v3vee.org
- *
- * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
- * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
- * All rights reserved.
- *
- * Author: Jack Lange <jarusl@cs.northwestern.edu>
- *
- * This is free software.  You are permitted to use,
- * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
- */
-
-#ifndef __DEVICES_LNX_VIRTIO_BLK_H__
-#define __DEVICES_LNX_VIRTIO_BLK_H__
-
-#ifdef __V3VEE__
-
-#include <devices/block_dev.h>
-
-int v3_virtio_register_cdrom(struct vm_device * dev, 
-                            struct v3_cd_ops * ops, 
-                            void * private_data);
-
-
-int v3_virtio_register_harddisk(struct vm_device * dev, 
-                               struct v3_hd_ops * ops, 
-                               void * private_data);
-                            
-
-#endif
-
-
-#endif
diff --git a/palacios/include/devices/net_cd.h b/palacios/include/devices/net_cd.h
deleted file mode 100644 (file)
index d1f8a31..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 
- * This file is part of the Palacios Virtual Machine Monitor developed
- * by the V3VEE Project with funding from the United States National 
- * Science Foundation and the Department of Energy.  
- *
- * The V3VEE Project is a joint project between Northwestern University
- * and the University of New Mexico.  You can find out more at 
- * http://www.v3vee.org
- *
- * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
- * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
- * All rights reserved.
- *
- * Author: Jack Lange <jarusl@cs.northwestern.edu>
- *
- * This is free software.  You are permitted to use,
- * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
- */
-
-#ifndef __DEVICES_NET_CD_H__
-#define __DEVICES_NET_CD_H__
-
-#ifdef __V3VEE__
-
-
-struct net_cd_cfg {
-    char ide[32];
-    uint_t bus;
-    uint_t drive;
-    const char * ip_str;
-    uint16_t port;
-    const char * disk_tag;
-};
-
-
-
-#endif
-
-#endif
diff --git a/palacios/include/devices/net_hd.h b/palacios/include/devices/net_hd.h
deleted file mode 100644 (file)
index 2a57832..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/* 
- * This file is part of the Palacios Virtual Machine Monitor developed
- * by the V3VEE Project with funding from the United States National 
- * Science Foundation and the Department of Energy.  
- *
- * The V3VEE Project is a joint project between Northwestern University
- * and the University of New Mexico.  You can find out more at 
- * http://www.v3vee.org
- *
- * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
- * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
- * All rights reserved.
- *
- * Author: Jack Lange <jarusl@cs.northwestern.edu>
- *
- * This is free software.  You are permitted to use,
- * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
- */
-
-#ifndef __DEVICES_NET_HD_H__
-#define __DEVICES_NET_HD_H__
-
-#ifdef __V3VEE__
-
-
-
-struct net_hd_cfg {
-    char ide[32];
-    uint_t bus;
-    uint_t drive;
-    const char * ip_str; 
-    uint16_t port;
-    const char * disk_tag;
-};
-
-
-
-#endif
-
-#endif
index 41598d4..1da7102 100644 (file)
@@ -30,6 +30,8 @@
 
 #include <devices/pci_types.h>
 
+struct vm_device;
+
 
 typedef enum { PCI_BAR_IO, 
               PCI_BAR_MEM24, 
@@ -120,8 +122,6 @@ struct pci_device {
 
     char name[64];
 
-    struct vm_device * vm_dev;  //the corresponding virtual device
-
     int (*config_update)(uint_t reg_num, void * src, uint_t length, void * priv_data);
 
     int (*cmd_update)(struct pci_device * pci_dev, uchar_t io_enabled, uchar_t mem_enabled);
@@ -158,7 +158,7 @@ v3_pci_register_device(struct vm_device * pci,
                       int (*config_update)(uint_t reg_num, void * src, uint_t length, void * private_data),
                       int (*cmd_update)(struct pci_device *pci_dev, uchar_t io_enabled, uchar_t mem_enabled),
                       int (*ext_rom_update)(struct pci_device *pci_dev),
-                      struct vm_device * dev, void * priv_data);
+                      void * priv_data);
 
 
 struct pci_device * 
@@ -169,7 +169,6 @@ v3_pci_register_passthrough_device(struct vm_device * pci,
                                   const char * name,
                                   int (*config_write)(uint_t reg_num, void * src, uint_t length, void * private_data),
                                   int (*config_read)(uint_t reg_num, void * dst, uint_t length, void * private_data),
-                                  struct vm_device * dev, 
                                   void * private_data);
 
 
diff --git a/palacios/include/devices/pci_passthrough.h b/palacios/include/devices/pci_passthrough.h
deleted file mode 100644 (file)
index 8ac8580..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/* 
- * This file is part of the Palacios Virtual Machine Monitor developed
- * by the V3VEE Project with funding from the United States National 
- * Science Foundation and the Department of Energy.  
- *
- * The V3VEE Project is a joint project between Northwestern University
- * and the University of New Mexico.  You can find out more at 
- * http://www.v3vee.org
- *
- * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
- * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
- * All rights reserved.
- *
- * Author: Jack Lange <jarusl@cs.northwestern.edu>
- *
- * This is free software.  You are permitted to use,
- * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
- */
-
-#ifndef __DEVICES_PCI_PASSTHROUGH_H__
-#define __DEVICES_PCI_PASSTHROUGH_H__
-
-#ifdef __V3VEE__
-
-struct pci_passthrough_cfg {
-    char pci_bus_name[32];
-
-    char name[32];
-    uint16_t   vendor_id;
-    uint16_t   device_id;
-};
-
-
-#endif
-
-#endif
diff --git a/palacios/include/devices/ram_cd.h b/palacios/include/devices/ram_cd.h
deleted file mode 100644 (file)
index c105394..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 
- * This file is part of the Palacios Virtual Machine Monitor developed
- * by the V3VEE Project with funding from the United States National 
- * Science Foundation and the Department of Energy.  
- *
- * The V3VEE Project is a joint project between Northwestern University
- * and the University of New Mexico.  You can find out more at 
- * http://www.v3vee.org
- *
- * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
- * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
- * All rights reserved.
- *
- * Author: Jack Lange <jarusl@cs.northwestern.edu>
- *
- * This is free software.  You are permitted to use,
- * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
- */
-
-#ifndef __DEVICES_RAM_CD_H__
-#define __DEVICES_RAM_CD_H__
-
-#ifdef __V3VEE__
-
-
-
-struct ram_cd_cfg {
-    char ide[32]; 
-    uint_t bus;
-    uint_t drive;
-    addr_t ramdisk;
-    uint32_t size;
-};
-
-
-
-#endif
-
-#endif
diff --git a/palacios/include/devices/ram_hd.h b/palacios/include/devices/ram_hd.h
deleted file mode 100644 (file)
index 4c4fdad..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/* 
- * This file is part of the Palacios Virtual Machine Monitor developed
- * by the V3VEE Project with funding from the United States National 
- * Science Foundation and the Department of Energy.  
- *
- * The V3VEE Project is a joint project between Northwestern University
- * and the University of New Mexico.  You can find out more at 
- * http://www.v3vee.org
- *
- * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
- * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
- * All rights reserved.
- *
- * Author: Jack Lange <jarusl@cs.northwestern.edu>
- *
- * This is free software.  You are permitted to use,
- * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
- */
-
-#ifndef __DEVICES_RAM_HD_H__
-#define __DEVICES_RAM_HD_H__
-
-#ifdef __V3VEE__
-
-struct ram_hd_cfg {
-    char ide[32];
-    uint_t bus; 
-    uint_t drive;
-    addr_t ramdisk;
-    uint32_t size;
-};
-
-
-
-#endif
-
-#endif
diff --git a/palacios/include/devices/telnet_cons.h b/palacios/include/devices/telnet_cons.h
deleted file mode 100644 (file)
index afca897..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/* 
- * This file is part of the Palacios Virtual Machine Monitor developed
- * by the V3VEE Project with funding from the United States National 
- * Science Foundation and the Department of Energy.  
- *
- * The V3VEE Project is a joint project between Northwestern University
- * and the University of New Mexico.  You can find out more at 
- * http://www.v3vee.org
- *
- * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
- * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
- * All rights reserved.
- *
- * Author: Jack Lange <jarusl@cs.northwestern.edu>
- *
- * This is free software.  You are permitted to use,
- * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
- */
-
-#ifndef __DEVICES_TELNET_CONS_H__
-#define __DEVICES_TELNET_CONS_H__
-
-#ifdef __V3VEE__
-
-
-
-struct telnet_cons_cfg {
-    char frontend[32];
-    uint16_t port;
-};
-
-
-
-#endif
-
-#endif
index 01e387a..91cde55 100644 (file)
 #define ETHERNET_DATA_MAX   1500
 #define ETHERNET_PACKET_LEN (ETHERNET_HEADER_LEN + ETHERNET_DATA_MAX)
 
-#define TCP_TYPE 0
-#define UDP_TYPE 1
-
-#define TCP_STR "TCP"
-#define UDP_STR "UDP"
-
-
 //the routing entry
 struct routing {
     char src_mac[6];
index 3780b95..1a9ecfd 100644 (file)
 
 
 void v3_init_svm_cpu(int cpu_id);
-void v3_init_svm_hooks(struct v3_ctrl_ops * vmm_ops);
 int v3_is_svm_capable();
 
+int v3_init_svm_vmcb(struct guest_info * info, v3_vm_class_t vm_class);
+
 int v3_svm_enter(struct guest_info * info);
+int v3_start_svm_guest(struct guest_info *info);
 
 #endif
 
index b5d481c..6506658 100644 (file)
@@ -48,6 +48,8 @@
 
 
 
+
+
 struct v3_gprs {
     v3_reg_t rdi;
     v3_reg_t rsi;
@@ -124,6 +126,8 @@ struct v3_segments {
 #include <palacios/vmm_sym_iface.h>
 #endif
 
+#include <palacios/vmm_config.h>
+
 struct shadow_page_state;
 struct v3_intr_state;
 
@@ -147,6 +151,8 @@ struct guest_info {
     addr_t mem_size; // In bytes for now
     v3_shdw_map_t mem_map;
 
+    struct v3_config * cfg_data;
+    v3_vm_class_t vm_class;
 
     struct vm_time time_state;
 
index 6fbbe7d..87d50ed 100644 (file)
 #define __VMM_H__
 
 
-#include <palacios/vm_guest.h>
+//#include <palacios/vm_guest.h>
 #include <palacios/vmm_mem.h>
 #include <palacios/vmm_types.h>
 
+struct guest_info;
 
 
 #ifdef __V3VEE__
 
 
 
-#define VMM_INVALID_CPU 0
-#define VMM_VMX_CPU 1
-#define VMM_SVM_CPU 2
+
+typedef enum v3_vm_class {V3_INVALID_VM, V3_PC_VM, V3_CRAY_VM} v3_vm_class_t;
 
 
 // Maybe make this a define....
@@ -200,6 +200,11 @@ void v3_yield_cond(struct guest_info * info);
 
 void v3_interrupt_cpu(struct guest_info * vm, int logical_cpu);
 
+unsigned int v3_get_cpu_id();
+
+v3_cpu_arch_t v3_get_cpu_type(int cpu_id);
+
+
 int v3_vm_enter(struct guest_info * info);
 
 
@@ -238,6 +243,7 @@ struct v3_os_hooks {
     void (*mutex_lock)(void * mutex, int must_spin);
     void (*mutex_unlock)(void * mutex);
 
+    unsigned int (*get_cpu)(void);
     void (*interrupt_cpu)(struct guest_info * vm, int logical_cpu);
     void (*call_on_cpu)(int logical_cpu, void (*fn)(void * arg), void * arg);
     void (*start_thread_on_cpu)(int logical_cpu, int (*fn)(void * arg), void * arg, char * thread_name);
@@ -245,62 +251,6 @@ struct v3_os_hooks {
 
 
 
-typedef enum {NONE, HARDDRIVE, CDROM, VIRTIO} v3_disk_type_t;
-typedef enum {RAM, NETWORK} v3_disk_connection_t;
-
-union v3_disk_info {
-    struct {
-       void * data_ptr;
-       int size;
-    } ram;
-
-    struct {
-       char * ip_str;
-       int port;
-       char * disk_name;
-    } net;
-};
-
-struct v3_vm_config {
-
-    unsigned long mem_size; // in bytes, var should be natural size of cpu
-    // so we can specify maximum physical address size
-    // (We're screwed if we want to do 32 bit host/64 bit guest)
-
-    int enable_telemetry;
-    int enable_nested_paging;
-
-    int enable_pci;
-
-    int enable_swap;
-
-    int guest_cpu;
-
-    unsigned long schedule_freq; // in HZ
-
-    v3_disk_type_t pri_disk_type;
-    v3_disk_connection_t pri_disk_con;
-    union v3_disk_info pri_disk_info;
-   
-    v3_disk_type_t sec_disk_type;
-    v3_disk_connection_t sec_disk_con;
-    union v3_disk_info sec_disk_info;
-};
-
-
-
-/* This will contain Function pointers that control the VMs */
-struct v3_ctrl_ops {
-    struct guest_info *(*allocate_guest)(void);
-
-    int (*init_guest)(struct guest_info * info, struct v3_vm_config * config_ptr);
-    int (*start_guest)(struct guest_info * info);
-    //  int (*stop_vm)(uint_t vm_id);
-
-    int (*has_nested_paging)(void);
-
-    //  v3_cpu_arch_t (*get_cpu_arch)();
-};
 
 
 
@@ -320,7 +270,11 @@ struct v3_interrupt {
 
 
 
-void Init_V3(struct v3_os_hooks * hooks, struct v3_ctrl_ops * vmm_ops, int num_cpus);
+void Init_V3(struct v3_os_hooks * hooks,  int num_cpus);
+
+
+int v3_start_vm(struct guest_info * info, unsigned int cpu_mask);
+struct guest_info * v3_create_vm(void * cfg);
 
 int v3_deliver_irq(struct guest_info * vm, struct v3_interrupt * intr);
 
index 716e5b6..a719cf5 100644 (file)
 
 #ifdef __V3VEE__
 
-#include <palacios/vm_guest.h>
+//#include <palacios/vm_guest.h>
 #include <palacios/vmm.h>
+#include <palacios/vmm_xml.h>
+#include <palacios/vmm_list.h>
+#include <palacios/vmm_hashtable.h>
+//#include <palacios/svm.h>
 
 
-int v3_pre_config_guest(struct guest_info * info, struct v3_vm_config * config_ptr);
-int v3_post_config_guest(struct guest_info * info, struct v3_vm_config * config_ptr);
+struct guest_info;
 
+int v3_config_guest(struct guest_info * info, void * cfg_blob);
 
+struct v3_cfg_file {
+    void * data;
+    uint64_t size;
 
-#endif // ! __V3VEE__
+    char tag[256];
+
+    struct list_head file_node;
+};
+
+
+
+typedef struct v3_xml v3_cfg_tree_t;
+
+struct v3_config {
+    v3_cfg_tree_t * cfg;
 
+    struct list_head file_list;
+    struct hashtable * file_table;
 
+    void * blob;
+};
+
+
+struct v3_cfg_file * v3_cfg_get_file(struct guest_info * info, char * tag);
+
+char * v3_cfg_val(v3_cfg_tree_t * tree, char * tag);
+v3_cfg_tree_t * v3_cfg_subtree(v3_cfg_tree_t * tree, char * tag);
+v3_cfg_tree_t * v3_cfg_next_branch(v3_cfg_tree_t * tree);
+
+#endif // ! __V3VEE__
 
 #endif
index 9495861..dd62093 100644 (file)
@@ -26,6 +26,7 @@
 #include <palacios/vmm_list.h>
 #include <palacios/vmm_string.h>
 #include <palacios/vmm_hashtable.h>
+#include <palacios/vmm_config.h>
 
 
 struct guest_info;
@@ -53,14 +54,23 @@ struct vm_device {
 struct vmm_dev_mgr {
     uint_t num_devs;
     struct list_head dev_list;
-
     struct hashtable * dev_table;
+
+    struct list_head blk_list;
+    struct hashtable * blk_table;
+
+    struct list_head net_list;
+    struct hashtable * net_table;
+
+    struct list_head console_list;
+    struct hashtable * console_table;
+
 };
 
 
 
 
-int v3_create_device(struct guest_info * info, const char * dev_name, void * cfg_data);
+int v3_create_device(struct guest_info * info, const char * dev_name, v3_cfg_tree_t * cfg);
 void v3_free_device(struct vm_device * dev);
 
 
@@ -121,7 +131,7 @@ struct vm_device * v3_allocate_device(char * name, struct v3_device_ops * ops, v
 
 struct v3_device_info {
     char * name;
-    int (*init)(struct guest_info * info, void * cfg_data);
+    int (*init)(struct guest_info * info, v3_cfg_tree_t * cfg);
 };
 
 
@@ -136,11 +146,51 @@ struct v3_device_info {
 
 
 
-void PrintDebugDevMgr(struct guest_info * info);
-void PrintDebugDev(struct vm_device * dev);
+void v3_print_dev_mgr(struct guest_info * info);
+
 
+struct v3_dev_blk_ops {
+    uint64_t (*get_capacity)(void * private_data);
+    // Reads always operate on 2048 byte blocks
+    int (*read)(uint8_t * buf, uint64_t lba, uint64_t num_bytes, void * private_data);
+    int (*write)(uint8_t * buf, uint64_t lba, uint64_t num_bytes, void * private_data);
+};
+
+struct v3_dev_net_ops {
+
+};
+
+struct v3_dev_console_ops {
 
+};
 
+int v3_dev_add_blk_frontend(struct guest_info * info, 
+                           char * name, 
+                           int (*connect)(struct guest_info * info, 
+                                           void * frontend_data, 
+                                           struct v3_dev_blk_ops * ops, 
+                                           v3_cfg_tree_t * cfg, 
+                                           void * private_data), 
+                           void * priv_data);
+int v3_dev_connect_blk(struct guest_info * info, 
+                      char * frontend_name, 
+                      struct v3_dev_blk_ops * ops, 
+                      v3_cfg_tree_t * cfg, 
+                      void * private_data);
+
+int v3_dev_add_net_frontend(struct guest_info * info, 
+                           char * name, 
+                           int (*connect)(struct guest_info * info, 
+                                           void * frontend_data, 
+                                           struct v3_dev_net_ops * ops, 
+                                           v3_cfg_tree_t * cfg, 
+                                           void * private_data), 
+                           void * priv_data);
+int v3_dev_connect_net(struct guest_info * info, 
+                      char * frontend_name, 
+                      struct v3_dev_net_ops * ops, 
+                      v3_cfg_tree_t * cfg, 
+                      void * private_data);
 
 
 #endif // ! __V3VEE__
index 553497d..f6338df 100644 (file)
@@ -78,7 +78,7 @@ typedef struct v3_shdw_map {
 
 
 
-void v3_init_shadow_map(struct guest_info * info);
+int v3_init_shadow_map(struct guest_info * info);
 void v3_delete_shadow_map(struct guest_info * info);
 
 
index d7629a1..cd0cb7a 100644 (file)
@@ -31,9 +31,6 @@
 
 
 struct shadow_page_state {
-    // ugly optimization hack
-    v3_reg_t prev_guest_cr3;
-
 
     // virtualized control registers
     v3_reg_t guest_cr3;
index df8ac6f..9e30dc6 100644 (file)
 
 #ifdef __V3VEE__
 #include <palacios/vmm_types.h>
-
+#include <stdarg.h>
 
 int sprintf(char *buf, const char *cfmt, ...);
 //        __attribute__ ((format (printf, 1, 2)));
 //int vsprintf(char *buf, const char * cfmt, va_list ap);
 int snprintf(char *str, size_t size, const char * fmt, ...);
-//int vsnprintf(char *str, size_t size, const char * fmt, va_list ap);
+int vsnprintf(char *str, size_t size, const char * fmt, va_list ap);
 //int vsnrprintf(char *str, size_t size, int radix, const char * fmt, va_list ap);
 
 #define HD_COLUMN_MASK  0xff
index 2e57bf9..78c3cf0 100644 (file)
 #include <palacios/vmm_types.h>
 
 
-void* memset(void* s, int c, size_t n);
-void* memcpy(void *dst, const void* src, size_t n);
-//void *memmove(void *dst, const void *src, size_t n);
+void * memset(void* s, int c, size_t n);
+void * memcpy(void *dst, const void* src, size_t n);
+void * memmove(void *dst, const void *src, size_t n);
 int memcmp(const void *s1, const void *s2, size_t n);
 size_t strlen(const char* s);
 size_t strnlen(const char *s, size_t maxlen);
 int strcmp(const char* s1, const char* s2);
+int strcasecmp(const char* s1, const char* s2);
 int strncmp(const char* s1, const char* s2, size_t limit);
+int strncasecmp(const char* s1, const char* s2, size_t limit);
 char *strcat(char *s1, const char *s2);
 char *strncat(char *s1, const char *s2, size_t limit);
 char *strcpy(char *dest, const char *src);
 char *strncpy(char *dest, const char *src, size_t limit);
 char *strdup(const char *s1);
-int atoi(const char *buf);
+int atoi(const char * buf);
+uint64_t atox(const char * buf);
+int strtoi(const char * nptr, char ** endptr);
+uint64_t strtox(const char * nptr, char ** endptr);
 char *strchr(const char *s, int c);
 char *strrchr(const char *s, int c);
 char *strpbrk(const char *s, const char *accept);
 
+size_t strspn(const char * s, const char * accept);
+size_t strcspn(const char * s, const char * reject);
+char * strstr(const char * haystack, const char * needle);
 
+void str_tolower(char * s);
+void str_toupper(char * s);
 
 
 
-#define isspace(c)           (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
+#define isspace(c)      (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
 #define isascii(c)     (((c) & ~0x7f) == 0)
 #define isupper(c)     ((c) >= 'A' && (c) <= 'Z')
 #define islower(c)     ((c) >= 'a' && (c) <= 'z')
index 6c96dab..5de9720 100644 (file)
 
 #ifdef __V3VEE__
 
-#include <palacios/vm_guest.h>
-
 
 
 struct v3_sym_interface {
     uint64_t magic;
 
-
     union {
        uint32_t feature_flags;
        struct {
-           uint_t pci_map_valid          : 1;
+           uint_t pci_map_valid            : 1;
            uint32_t sym_call_enabled       : 1;
        } __attribute__((packed));
     } __attribute__((packed));
@@ -51,13 +48,12 @@ struct v3_sym_interface {
     
     uint8_t pci_pt_map[(4 * 256) / 8]; // we're hardcoding this: (4 busses, 256 max devs)
 
-
-
-
 } __attribute__((packed));
 
 
 
+#include <palacios/vm_guest.h>
+
 
 struct v3_sym_context {
     struct v3_gprs vm_regs;
@@ -71,7 +67,6 @@ struct v3_sym_context {
 };
 
 
-
 struct v3_sym_state {
     
     struct v3_sym_interface * sym_page;
@@ -97,6 +92,12 @@ struct v3_sym_state {
     uint64_t sym_call_fs;
 };
 
+
+
+
+
+
+
 int v3_init_sym_iface(struct guest_info * info);
 
 
diff --git a/palacios/include/palacios/vmm_xml.h b/palacios/include/palacios/vmm_xml.h
new file mode 100644 (file)
index 0000000..f45f804
--- /dev/null
@@ -0,0 +1,91 @@
+/* ezxml.h
+ *
+ * Copyright 2004-2006 Aaron Voisine <aaron@voisine.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* 
+ * Modified for Palacios by Jack Lange <jarusl@cs.northwestern.edu> 
+ */
+
+#ifndef __VMM_XML_H
+#define __VMM_XML_H
+
+#include <palacios/vmm.h>
+#include <palacios/vmm_types.h>
+
+
+struct v3_xml {
+    char *name;      // tag name
+    char **attr;     // tag attributes { name, value, name, value, ... NULL }
+    char *txt;       // tag character content, empty string if none
+    size_t off;      // tag offset from start of parent tag character content
+    struct v3_xml * next;    // next tag with same name in this section at this depth
+    struct v3_xml * sibling; // next tag with different name in same section and depth
+    struct v3_xml * ordered; // next tag, same section and depth, in original order
+    struct v3_xml * child;   // head of sub tag list, NULL if none
+    struct v3_xml * parent;  // parent tag, NULL if current tag is root tag
+    short flags;     // additional information
+};
+
+// Given a string of xml data and its length, parses it and creates an v3_xml
+// structure. For efficiency, modifies the data by adding null terminators
+// and decoding ampersand sequences. If you don't want this, copy the data and
+// pass in the copy. Returns NULL on failure.
+struct v3_xml * v3_xml_parse(char * buf);
+
+
+// returns the name of the given tag
+#define v3_xml_name(xml) ((xml) ? xml->name : NULL)
+
+// returns the given tag's character content or empty string if none
+#define v3_xml_txt(xml) ((xml) ? xml->txt : "")
+
+
+// returns the first child tag (one level deeper) with the given name or NULL
+// if not found
+struct v3_xml * v3_xml_child(struct v3_xml * xml, const char * name);
+
+// returns the next tag of the same name in the same section and depth or NULL
+// if not found
+#define v3_xml_next(xml) ((xml) ? xml->next : NULL)
+
+// Returns the Nth tag with the same name in the same section at the same depth
+// or NULL if not found. An index of 0 returns the tag given.
+struct v3_xml * v3_xml_idx(struct v3_xml * xml, int idx);
+
+// returns the value of the requested tag attribute, or NULL if not found
+const char *v3_xml_attr(struct v3_xml * xml, const char * attr);
+
+
+// Traverses the v3_xml sturcture to retrieve a specific subtag. Takes a
+// variable length list of tag names and indexes. The argument list must be
+// terminated by either an index of -1 or an empty string tag name. Example: 
+// title = v3_xml_get(library, "shelf", 0, "book", 2, "title", -1);
+// This retrieves the title of the 3rd book on the 1st shelf of library.
+// Returns NULL if not found.
+struct v3_xml * v3_xml_get(struct v3_xml * xml, ...);
+
+
+// frees the memory allocated for an v3_xml structure
+void v3_xml_free(struct v3_xml * xml);
+    
+#endif // __VMM_XML_H
index 67e546b..a34cd46 100644 (file)
@@ -1,4 +1,5 @@
 
+
 /* 
  * This file is part of the Palacios Virtual Machine Monitor developed
  * by the V3VEE Project with funding from the United States National 
@@ -230,7 +231,6 @@ struct vmx_data {
 };
 
 int v3_is_vmx_capable();
-void v3_init_vmx_hooks(struct v3_ctrl_ops * vm_ops);
 void v3_init_vmx_cpu(int cpu_id);
 
 
index c205752..4b2f4c0 100644 (file)
@@ -23,7 +23,7 @@
 #include <palacios/vmm_time.h>
 #include <palacios/vmm_util.h>
 #include <palacios/vmm_intr.h>
-
+#include <palacios/vmm_config.h>
 
 
 #ifndef CONFIG_DEBUG_PIT
@@ -631,9 +631,10 @@ static struct v3_device_ops dev_ops = {
 };
 
 
-static int pit_init(struct guest_info * info, void * cfg_data) {
+static int pit_init(struct guest_info * info, v3_cfg_tree_t * cfg) {
     struct pit * pit_state = NULL;
     struct vm_device * dev = NULL;
+    char * name = v3_cfg_val(cfg, "name");
 
     uint_t cpu_khz = V3_CPU_KHZ();
     ullong_t reload_val = (ullong_t)cpu_khz * 1000;
@@ -641,10 +642,10 @@ static int pit_init(struct guest_info * info, void * cfg_data) {
     pit_state = (struct pit *)V3_Malloc(sizeof(struct pit));
     V3_ASSERT(pit_state != NULL);
 
-    dev = v3_allocate_device("PIT", &dev_ops, pit_state);
+    dev = v3_allocate_device(name, &dev_ops, pit_state);
 
     if (v3_attach_device(info, dev) == -1) {
-       PrintError("Could not attach device %s\n", "PIT");
+       PrintError("Could not attach device %s\n", name);
        return -1;
     }
 
index d1944f6..443fb0a 100644 (file)
@@ -715,15 +715,17 @@ static struct v3_device_ops dev_ops = {
 
 
 
-static int pic_init(struct guest_info * vm, void * cfg_data) {
+static int pic_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
     struct pic_internal * state = NULL;
     state = (struct pic_internal *)V3_Malloc(sizeof(struct pic_internal));
+    char * name = v3_cfg_val(cfg, "name");
+
     V3_ASSERT(state != NULL);
 
-    struct vm_device * dev = v3_allocate_device("8259A", &dev_ops, state);
+    struct vm_device * dev = v3_allocate_device(name, &dev_ops, state);
 
     if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", "8259A");
+       PrintError("Could not attach device %s\n", name);
        return -1;
     }
 
index 6d1a568..1664821 100644 (file)
@@ -162,19 +162,7 @@ config DEBUG_NE2k
          Enable debugging for the NE2K
 
 
-config NET_CD
-       bool "Networked CD backend"
-       default y
-       depends on SOCKET && (IDE || LINUX_VIRTIO_BLOCK)
-       help 
-         Includes the Network CD backend
 
-config NET_HD
-       bool "Networked HD backend"
-       default y
-       depends on SOCKET && (IDE || LINUX_VIRTIO_BLOCK)
-       help 
-         Includes the Network HD backend
 
 
 config NVRAM
@@ -252,24 +240,27 @@ config DEBUG_PIT
          Enable debugging for the PIT  
 
 
-
-
-config RAM_CD
-       bool "RAM based CD backend"
+config NETDISK
+       bool "NETDISK storage backend"
        default y
-       depends on IDE || LINUX_VIRTIO_BLOCK
+       depends on SOCKET && (IDE || LINUX_VIRTIO_BLOCK)
        help 
-         Includes the RAM based CD backend
+         Includes the Network based disk backend
 
-config RAM_HD
-       bool "RAM based HD backend"
+config RAMDISK
+       bool "RAMDISK storage backend"
        default y
        depends on IDE || LINUX_VIRTIO_BLOCK
        help 
-         Includes the RAM based HD backend
-
+         Includes the RAM based disk backend
 
 
+config TMPDISK
+       bool "TMPDISK storage backend"
+       default y
+       depends on IDE || LINUX_VIRTIO_BLOCK
+       help 
+         Includes the temporary RAM disk 
 
 config SYM_SWAP
        bool "Symbiotic Swap disk"
index d83960a..81ecbf2 100644 (file)
@@ -15,14 +15,13 @@ obj-$(CONFIG_NVRAM) += nvram.o
 obj-$(CONFIG_OS_DEBUG) += os_debug.o
 obj-$(CONFIG_PCI) += pci.o
 obj-$(CONFIG_PIIX3) += piix3.o
-obj-$(CONFIG_RAM_CD) += ram_cd.o
-obj-$(CONFIG_RAM_HD) += ram_hd.o
-obj-$(CONFIG_SYM_SWAP) += sym_swap.o 
+obj-$(CONFIG_SYM_SWAP) += sym_swap.o
 
 obj-$(CONFIG_NE2K) += ne2k.o
 
-obj-$(CONFIG_NET_CD) += net_cd.o 
-obj-$(CONFIG_NET_HD) += net_hd.o 
+obj-$(CONFIG_TMPDISK) += tmpdisk.o
+obj-$(CONFIG_RAMDISK) += ramdisk.o 
+obj-$(CONFIG_NETDISK) += netdisk.o 
 
 obj-$(CONFIG_CGA) += cga.o
 obj-$(CONFIG_TELNET_CONSOLE) += telnet_cons.o
index bbef7e2..ccb89e3 100644 (file)
@@ -22,7 +22,7 @@
 #include <devices/apic_regs.h>
 #include <palacios/vmm.h>
 #include <palacios/vmm_msr.h>
-
+#include <palacios/vm_guest.h>
 
 #ifndef CONFIG_DEBUG_APIC
 #undef PrintDebug
@@ -1072,15 +1072,16 @@ static struct v3_device_ops dev_ops = {
 
 
 
-static int apic_init(struct guest_info * vm, void * cfg_data) {
+static int apic_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
     PrintDebug("Creating APIC\n");
+    char * name = v3_cfg_val(cfg, "name");
 
     struct apic_state * apic = (struct apic_state *)V3_Malloc(sizeof(struct apic_state));
 
-    struct vm_device * dev = v3_allocate_device("LAPIC", &dev_ops, apic);
+    struct vm_device * dev = v3_allocate_device(name, &dev_ops, apic);
 
     if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", "LAPIC");
+       PrintError("Could not attach device %s\n", name);
        return -1;
     }
 
index 5cdb737..4cf6cd2 100644 (file)
@@ -64,10 +64,10 @@ static void ata_identify_device(struct ide_drive * drive) {
     drive_id->lba_enable = 1;
     
     // Drive Capacity (28 bit LBA)
-    drive_id->lba_capacity = drive->hd_ops->get_capacity(drive->private_data);
+    drive_id->lba_capacity = drive->ops->get_capacity(drive->private_data);
     
     // Drive Capacity (48 bit LBA)
-    drive_id->lba_capacity_2 = drive->hd_ops->get_capacity(drive->private_data);
+    drive_id->lba_capacity_2 = drive->ops->get_capacity(drive->private_data);
 
 
     // lower byte is the maximum multiple sector size...
@@ -116,7 +116,7 @@ static int ata_read(struct vm_device * dev, struct ide_channel * channel, uint8_
 
     PrintDebug("Reading Drive LBA=%d (count=%d)\n", (uint32_t)(drive->current_lba), sect_cnt);
 
-    int ret = drive->hd_ops->read(dst, sect_cnt, drive->current_lba, drive->private_data);
+    int ret = drive->ops->read(dst, drive->current_lba * HD_SECTOR_SIZE, sect_cnt * HD_SECTOR_SIZE, drive->private_data);
     
     if (ret == -1) {
        PrintError("IDE: Error reading HD block (LBA=%p)\n", (void *)(addr_t)(drive->current_lba));
@@ -132,7 +132,7 @@ static int ata_write(struct vm_device * dev, struct ide_channel * channel, uint8
 
     PrintDebug("Writing Drive LBA=%d (count=%d)\n", (uint32_t)(drive->current_lba), sect_cnt);
 
-    int ret = drive->hd_ops->write(src, sect_cnt, drive->current_lba, drive->private_data);
+    int ret = drive->ops->write(src, drive->current_lba * HD_SECTOR_SIZE, sect_cnt * HD_SECTOR_SIZE, drive->private_data);
 
     if (ret == -1) {
        PrintError("IDE: Error writing HD block (LBA=%p)\n", (void *)(addr_t)(drive->current_lba));
@@ -168,11 +168,11 @@ static int ata_get_lba(struct vm_device * dev, struct ide_channel * channel, uin
 
 
     if ((lba_addr.addr + sect_cnt) > 
-       drive->hd_ops->get_capacity(drive->private_data)) {
+       drive->ops->get_capacity(drive->private_data)) {
        PrintError("IDE: request size exceeds disk capacity (lba=%d) (sect_cnt=%d) (ReadEnd=%d) (capacity=%p)\n", 
                   lba_addr.addr, sect_cnt, 
                   lba_addr.addr + (sect_cnt * HD_SECTOR_SIZE),
-                  (void *)(addr_t)(drive->hd_ops->get_capacity(drive->private_data)));
+                  (void *)(addr_t)(drive->ops->get_capacity(drive->private_data)));
        return -1;
     }
 
index 27bed29..ad03ee9 100644 (file)
@@ -128,7 +128,8 @@ static void atapi_cmd_nop(struct vm_device * dev, struct ide_channel * channel)
 static int atapi_read_chunk(struct vm_device * dev, struct ide_channel * channel) {
     struct ide_drive * drive = get_selected_drive(channel);
 
-    int ret = drive->cd_ops->read(drive->data_buf, 1, drive->current_lba, drive->private_data);
+    int ret = drive->ops->read(drive->data_buf, drive->current_lba * ATAPI_BLOCK_SIZE, ATAPI_BLOCK_SIZE, 
+drive->private_data);
     
     if (ret == -1) {
        PrintError("IDE: Error reading CD block (LBA=%p)\n", (void *)(addr_t)(drive->current_lba));
@@ -177,10 +178,10 @@ static int atapi_read10(struct vm_device * dev, struct ide_channel * channel) {
        return 0;
     }
     
-    if (lba + xfer_len > drive->cd_ops->get_capacity(drive->private_data)) {
+    if (lba + xfer_len > drive->ops->get_capacity(drive->private_data)) {
        PrintError("IDE: xfer len exceeded capacity (lba=%d) (xfer_len=%d) (ReadEnd=%d) (capacity=%d)\n", 
                   lba, xfer_len, lba + xfer_len, 
-                  drive->cd_ops->get_capacity(drive->private_data));
+                  (uint32_t)drive->ops->get_capacity(drive->private_data));
        atapi_cmd_error(dev, channel, ATAPI_SEN_ILL_REQ, ASC_LOG_BLK_OOR);
        ide_raise_irq(dev, channel);
        return 0;
@@ -238,7 +239,7 @@ static void atapi_req_sense(struct vm_device * dev, struct ide_channel * channel
 static int atapi_get_capacity(struct vm_device * dev, struct ide_channel * channel) {
     struct ide_drive * drive = get_selected_drive(channel);
     struct atapi_rd_capacity_resp * resp = (struct atapi_rd_capacity_resp *)(drive->data_buf);
-    uint32_t capacity = drive->cd_ops->get_capacity(drive->private_data);
+    uint32_t capacity = drive->ops->get_capacity(drive->private_data);
 
     resp->lba = le_to_be_32(capacity);
     resp->block_len = le_to_be_32(ATAPI_BLOCK_SIZE);
index 12f22c9..4c1ab08 100644 (file)
@@ -134,18 +134,19 @@ static struct v3_device_ops dev_ops = {
 
 
 
-static int debug_init(struct guest_info * vm, void * cfg_data) {
-   struct debug_state * state = NULL;
+static int debug_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
+    struct debug_state * state = NULL;
+    char * name = v3_cfg_val(cfg, "name");
 
     state = (struct debug_state *)V3_Malloc(sizeof(struct debug_state));
 
     V3_ASSERT(state != NULL);
 
     PrintDebug("Creating Bochs Debug Device\n");
-    struct vm_device * dev = v3_allocate_device("BOCHS_DEBUG", &dev_ops, state);
+    struct vm_device * dev = v3_allocate_device(name, &dev_ops, state);
 
     if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", "BOCHS_DEBUG");
+       PrintError("Could not attach device %s\n", name);
        return -1;
     }
 
index 3a77563..ee94f84 100644 (file)
@@ -310,18 +310,20 @@ static struct v3_device_ops dev_ops = {
     .stop = NULL,
 };
 
-static int cga_init(struct guest_info * vm, void * cfg_data) {
+static int cga_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
     struct video_internal * video_state = (struct video_internal *)V3_Malloc(sizeof(struct video_internal));
     addr_t frame_buf_pa = 0;
-    uint32_t enable_passthrough = (uint32_t)(addr_t)cfg_data;
+    int enable_passthrough = 0;
+    char * name = v3_cfg_val(cfg, "name");
 
+    enable_passthrough = (strcasecmp(v3_cfg_val(cfg, "passthrough"), "enable") == 0) ? 1 : 0;
 
     PrintDebug("video: init_device\n");
 
-    struct vm_device * dev = v3_allocate_device("CGA_VIDEO", &dev_ops, video_state);
+    struct vm_device * dev = v3_allocate_device(name, &dev_ops, video_state);
 
     if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", "CGA_VIDEO");
+       PrintError("Could not attach device %s\n", name);
        return -1;
     }
 
index a768007..25bf720 100644 (file)
@@ -420,9 +420,11 @@ static struct v3_device_ops dev_ops = {
     .stop = cirrus_gfx_card_stop_device,
 };
 
-static int cirrus_gfx_card_init(struct guest_info * vm, void * cfg_data){
+static int cirrus_gfx_card_init(struct guest_info * vm, v3_cfg_tree_t * cfg){
     struct video_internal * video_state = (struct video_internal *)V3_Malloc(sizeof(struct video_internal));
     struct vm_device * pci_bus = v3_find_dev(vm, (char *)cfg_data);
+    char * name = v3_cfg_val(cfg, "name");
+
     struct vm_device * dev = v3_allocate_device("TEXT_GFX_CARD", &dev_ops, video_state);
 
     if (v3_attach_device(vm, dev) == -1) {
index c6dd8d6..e4a00ff 100644 (file)
  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
  */
 
-#include <devices/generic.h>
 #include <palacios/vmm.h>
 #include <palacios/vmm_types.h>
 #include <palacios/vmm_list.h>
-
-
+#include <palacios/vmm_io.h>
+#include <palacios/vmm_dev_mgr.h>
 
 #ifndef CONFIG_DEBUG_GENERIC
 #undef PrintDebug
 #endif
 
 
+typedef enum {GENERIC_IGNORE, 
+             GENERIC_PASSTHROUGH, 
+             GENERIC_PRINT_AND_PASSTHROUGH, 
+             GENERIC_PRINT_AND_IGNORE} generic_mode_t;
+
 struct generic_internal {
     struct list_head port_list;
     uint_t num_port_ranges;
@@ -42,7 +46,7 @@ struct generic_internal {
 struct port_range {
     uint_t start;
     uint_t end;
-    uint_t type;
+    generic_mode_t mode;
     struct list_head range_link;
 };
 
@@ -211,26 +215,26 @@ static struct v3_device_ops dev_ops = {
 
 
 
-int v3_generic_add_port_range(struct vm_device * dev, uint_t start, uint_t end, uint_t type) {
+static int add_port_range(struct vm_device * dev, uint_t start, uint_t end, generic_mode_t mode) {
     struct generic_internal * state = (struct generic_internal *)(dev->private_data);
     struct port_range * range = (struct port_range *)V3_Malloc(sizeof(struct port_range));
     uint_t i = 0;
 
     range->start = start;
     range->end = end;
-    range->type = type;
+    range->mode = mode;
       
     PrintDebug("generic: Adding Port Range: 0x%x to 0x%x as %s\n", 
-              range->start, range->end, 
-              (range->type == GENERIC_PRINT_AND_PASSTHROUGH) ? "print-and-passthrough" : "print-and-ignore");
+              start, end, 
+              (mode == GENERIC_PRINT_AND_PASSTHROUGH) ? "print-and-passthrough" : "print-and-ignore");
     
     for (i = start; i <= end; i++) { 
-       if (type == GENERIC_PRINT_AND_PASSTHROUGH) { 
+       if (mode == GENERIC_PRINT_AND_PASSTHROUGH) { 
            if (v3_dev_hook_io(dev, i, &generic_read_port_passthrough, &generic_write_port_passthrough) == -1) { 
                PrintError("generic: can't hook port 0x%x (already hooked?)\n", i);
                return -1;
            }
-       } else if (type == GENERIC_PRINT_AND_IGNORE) { 
+       } else if (mode == GENERIC_PRINT_AND_IGNORE) { 
            if (v3_dev_hook_io(dev, i, &generic_read_port_ignore, &generic_write_port_ignore) == -1) { 
                PrintError("generic: can't hook port 0x%x (already hooked?)\n", i);
                return -1;
@@ -248,22 +252,52 @@ int v3_generic_add_port_range(struct vm_device * dev, uint_t start, uint_t end,
 
 
 
-static int generic_init(struct guest_info * vm, void * cfg_data) {
+static int generic_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
     struct generic_internal * state = (struct generic_internal *)V3_Malloc(sizeof(struct generic_internal));
-  
+    char * name = v3_cfg_val(cfg, "name");
+
+    v3_cfg_tree_t * port_cfg = v3_cfg_subtree(cfg, "ports");
+
+
     INIT_LIST_HEAD(&(state->port_list));
     state->num_port_ranges = 0;
+
     
-    struct vm_device * dev = v3_allocate_device("GENERIC", &dev_ops, state);
+    struct vm_device * dev = v3_allocate_device(name, &dev_ops, state);
 
     if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", "GENERIC");
+       PrintError("Could not attach device %s\n", name);
        return -1;
     }
 
     PrintDebug("generic: init_device\n");
     generic_reset_device(dev);
 
+    // scan port list....
+    while (port_cfg) {
+       uint16_t start = atox(v3_cfg_val(port_cfg, "start"));
+       uint16_t end = atox(v3_cfg_val(port_cfg, "end"));
+       char * mode_str = v3_cfg_val(port_cfg, "mode");
+       generic_mode_t mode = GENERIC_IGNORE;
+
+       if (strcasecmp(mode_str, "print_and_ignore") == 0) {
+           mode = GENERIC_PRINT_AND_IGNORE;
+       } else if (strcasecmp(mode_str, "print_and_passthrough") == 0) {
+           mode = GENERIC_PRINT_AND_PASSTHROUGH;
+       } else {
+           PrintError("Invalid Mode %s\n", mode_str);
+           return -1;
+       }
+       
+       if (add_port_range(dev, start, end, mode) == -1) {
+           PrintError("Could not add port range %d-%d\n", start, end);
+           return -1;
+       }
+
+       port_cfg = v3_cfg_next_branch(port_cfg);
+    }
+
+
     return 0;
 }
 
index da26d6b..ee4dc80 100644 (file)
@@ -57,12 +57,13 @@ static struct v3_device_ops dev_ops = {
 
 
 
-static int i440_init(struct guest_info * vm, void * cfg_data) {
+static int i440_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
     struct pci_device * pci_dev = NULL;
     struct v3_pci_bar bars[6];
     int i;
     struct i440_state * state = NULL;
-    struct vm_device * pci = v3_find_dev(vm, (char *)cfg_data);
+    struct vm_device * pci = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
+    char * name = v3_cfg_val(cfg, "name");
 
     if (!pci) {
        PrintError("could not find PCI Device\n");
@@ -73,10 +74,10 @@ static int i440_init(struct guest_info * vm, void * cfg_data) {
 
     state->pci = pci;
        
-    struct vm_device * dev = v3_allocate_device("i440FX", &dev_ops, state);
+    struct vm_device * dev = v3_allocate_device(name, &dev_ops, state);
 
     if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", "i440FX");
+       PrintError("Could not attach device %s\n", name);
        return -1;
     }
 
@@ -94,7 +95,7 @@ static int i440_init(struct guest_info * vm, void * cfg_data) {
 
     pci_dev = v3_pci_register_device(state->pci, PCI_STD_DEVICE, 
                                     0, 0, 0, "i440FX", bars,
-                                    NULL, NULL, NULL, dev, NULL);
+                                    NULL, NULL, NULL, dev);
 
     if (!pci_dev) {
        return -1;
index e8fbdc5..7b13e5b 100644 (file)
  */
 
 #include <palacios/vmm.h>
+#include <palacios/vmm_dev_mgr.h>
 #include <palacios/vm_guest_mem.h>
 #include <devices/ide.h>
 #include <devices/pci.h>
 #include <devices/southbridge.h>
-#include <devices/block_dev.h>
 #include "ide-types.h"
 #include "atapi-types.h"
 
 
 #define DATA_BUFFER_SIZE 2048
 
+#define ATAPI_BLOCK_SIZE 2048
+#define HD_SECTOR_SIZE 512
+
+
 static const char * ide_pri_port_strs[] = {"PRI_DATA", "PRI_FEATURES", "PRI_SECT_CNT", "PRI_SECT_NUM", 
                                          "PRI_CYL_LOW", "PRI_CYL_HIGH", "PRI_DRV_SEL", "PRI_CMD",
                                           "PRI_CTRL", "PRI_ADDR_REG"};
@@ -76,6 +80,7 @@ static const char * ide_dma_port_strs[] = {"DMA_CMD", NULL, "DMA_STATUS", NULL,
                                           "DMA_PRD0", "DMA_PRD1", "DMA_PRD2", "DMA_PRD3"};
 
 
+typedef enum {BLOCK_NONE, BLOCK_DISK, BLOCK_CDROM} v3_block_type_t;
 
 static inline const char * io_port_to_str(uint16_t port) {
     if ((port >= PRI_DATA_PORT) && (port <= PRI_CMD_PORT)) {
@@ -122,11 +127,7 @@ struct ide_drive {
 
     v3_block_type_t drive_type;
 
-    union {
-       struct v3_cd_ops * cd_ops;
-       struct v3_hd_ops * hd_ops;
-    };
-
+    struct v3_dev_blk_ops * ops;
 
     union {
        struct ide_cd_state cd_state;
@@ -1372,7 +1373,7 @@ static void init_drive(struct ide_drive * drive) {
     
 
     drive->private_data = NULL;
-    drive->cd_ops = NULL;
+    drive->ops = NULL;
 }
 
 static void init_channel(struct ide_channel * channel) {
@@ -1442,28 +1443,91 @@ static struct v3_device_ops dev_ops = {
 
 
 
-static int ide_init(struct guest_info * vm, void * cfg_data) {
-    struct ide_internal * ide  = (struct ide_internal *)V3_Malloc(sizeof(struct ide_internal));  
-    struct ide_cfg * cfg = (struct ide_cfg *)(cfg_data);
+
+static int connect_fn(struct guest_info * info, 
+                     void * frontend_data, 
+                     struct v3_dev_blk_ops * ops, 
+                     v3_cfg_tree_t * cfg, 
+                     void * private_data) {
+    struct ide_internal * ide  = (struct ide_internal *)(frontend_data);  
+    struct ide_channel * channel = NULL;
+    struct ide_drive * drive = NULL;
+
+    char * bus_str = v3_cfg_val(cfg, "bus_num");
+    char * drive_str = v3_cfg_val(cfg, "drive_num");
+    char * type_str = v3_cfg_val(cfg, "type");
+    char * model_str = v3_cfg_val(cfg, "model");
+    uint_t bus_num = 0;
+    uint_t drive_num = 0;
+
+
+    if ((!type_str) || (!drive_str) || (!bus_str)) {
+       PrintError("Incomplete IDE Configuration\n");
+       return -1;
+    }
+
+    bus_num = atoi(bus_str);
+    drive_num = atoi(drive_str);
+
+    channel = &(ide->channels[bus_num]);
+    drive = &(channel->drives[drive_num]);
+
+    if (drive->drive_type != BLOCK_NONE) {
+       PrintError("Device slot (bus=%d, drive=%d) already occupied\n", bus_num, drive_num);
+       return -1;
+    }
+
+    strncpy(drive->model, model_str, sizeof(drive->model) - 1);
     
+    if (strcasecmp(type_str, "cdrom") == 0) {
+       drive->drive_type = BLOCK_CDROM;
+
+       while (strlen((char *)(drive->model)) < 40) {
+           strcat((char*)(drive->model), " ");
+       }
+
+    } else if (strcasecmp(type_str, "hd") == 0) {
+       drive->drive_type = BLOCK_DISK;
+
+       drive->hd_state.accessed = 0;
+       drive->hd_state.mult_sector_num = 1;
+
+       drive->num_sectors = 63;
+       drive->num_heads = 16;
+       drive->num_cylinders = ops->get_capacity(private_data)  / (drive->num_sectors * drive->num_heads);
+    } else {
+       PrintError("invalid IDE drive type\n");
+       return -1;
+    }
+
+    drive->ops = ops;
+
+    if (ide->ide_pci) {
+       // Hardcode this for now, but its not a good idea....
+       ide->ide_pci->config_space[0x41 + (bus_num * 2)] = 0x80;
+    }
+    drive->private_data = private_data;
+
+    return 0;
+}
+
+
+
+
+static int ide_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
+    struct ide_internal * ide  = (struct ide_internal *)V3_Malloc(sizeof(struct ide_internal));  
+    char * name = v3_cfg_val(cfg, "name");
+
     PrintDebug("IDE: Initializing IDE\n");
     memset(ide, 0, sizeof(struct ide_internal));
 
 
-    if (cfg->pci != NULL) {
-       if (cfg->southbridge == NULL) {
-           PrintError("PCI Enabled BUT southbridge is NULL\n");
-           return -1;
-       }
-
-       ide->pci_bus = v3_find_dev(vm, (char *)cfg->pci);
-       
-       if (ide->pci_bus == NULL) {
-           PrintError("Could not find PCI device\n");
-           return -1;
-       }
+    ide->pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
 
-       struct vm_device * southbridge = v3_find_dev(vm, cfg->southbridge);
+    if (ide->pci_bus != NULL) {
+       struct vm_device * southbridge = v3_find_dev(vm, v3_cfg_val(cfg, "controller"));
 
        if (!southbridge) {
            PrintError("Could not find southbridge\n");
@@ -1473,17 +1537,15 @@ static int ide_init(struct guest_info * vm, void * cfg_data) {
        ide->southbridge = (struct v3_southbridge *)(southbridge->private_data);
     }
 
-
     PrintDebug("IDE: Creating IDE bus x 2\n");
 
-    struct vm_device * dev = v3_allocate_device("IDE", &dev_ops, ide);
+    struct vm_device * dev = v3_allocate_device(name, &dev_ops, ide);
 
     if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", "IDE");
+       PrintError("Could not attach device %s\n", name);
        return -1;
     }
 
-
     if (init_ide_state(dev) == -1) {
        PrintError("Failed to initialize IDE state\n");
        return -1;
@@ -1566,7 +1628,7 @@ static int ide_init(struct guest_info * vm, void * cfg_data) {
 
        pci_dev = v3_pci_register_device(ide->pci_bus, PCI_STD_DEVICE, 0, sb_pci->dev_num, 1, 
                                         "PIIX3_IDE", bars,
-                                        pci_config_update, NULL, NULL, dev, dev);
+                                        pci_config_update, NULL, NULL, dev);
 
        if (pci_dev == NULL) {
            PrintError("Failed to register IDE BUS %d with PCI\n", i); 
@@ -1595,6 +1657,12 @@ static int ide_init(struct guest_info * vm, void * cfg_data) {
 
     }
 
+    if (v3_dev_add_blk_frontend(vm, name, connect_fn, (void *)ide) == -1) {
+       PrintError("Could not register %s as frontend\n", name);
+       return -1;
+    }
+    
+
     PrintDebug("IDE Initialized\n");
 
     return 0;
@@ -1606,11 +1674,6 @@ device_register("IDE", ide_init)
 
 
 
-
-
-
-
-
 int v3_ide_get_geometry(struct vm_device * ide_dev, int channel_num, int drive_num, 
                        uint32_t * cylinders, uint32_t * heads, uint32_t * sectors) {
 
@@ -1631,98 +1694,3 @@ int v3_ide_get_geometry(struct vm_device * ide_dev, int channel_num, int drive_n
 
 
 
-
-int v3_ide_register_cdrom(struct vm_device * ide_dev, 
-                         uint_t bus_num, 
-                         uint_t drive_num,
-                         char * dev_name, 
-                         struct v3_cd_ops * ops, 
-                         void * private_data) {
-
-    struct ide_internal * ide  = (struct ide_internal *)(ide_dev->private_data);  
-    struct ide_channel * channel = NULL;
-    struct ide_drive * drive = NULL;
-
-    V3_ASSERT((bus_num >= 0) && (bus_num < 2));
-    V3_ASSERT((drive_num >= 0) && (drive_num < 2));
-
-    channel = &(ide->channels[bus_num]);
-    drive = &(channel->drives[drive_num]);
-    
-    if (drive->drive_type != BLOCK_NONE) {
-       PrintError("Device slot (bus=%d, drive=%d) already occupied\n", bus_num, drive_num);
-       return -1;
-    }
-
-    strncpy(drive->model, dev_name, sizeof(drive->model) - 1);
-
-    while (strlen((char *)(drive->model)) < 40) {
-       strcat((char*)(drive->model), " ");
-    }
-
-
-    drive->drive_type = BLOCK_CDROM;
-
-    drive->cd_ops = ops;
-
-    if (ide->ide_pci) {
-       // Hardcode this for now, but its not a good idea....
-       ide->ide_pci->config_space[0x41 + (bus_num * 2)] = 0x80;
-    }
-
-    drive->private_data = private_data;
-
-    return 0;
-}
-
-
-int v3_ide_register_harddisk(struct vm_device * ide_dev, 
-                            uint_t bus_num, 
-                            uint_t drive_num, 
-                            char * dev_name, 
-                            struct v3_hd_ops * ops, 
-                            void * private_data) {
-
-    struct ide_internal * ide  = (struct ide_internal *)(ide_dev->private_data);  
-    struct ide_channel * channel = NULL;
-    struct ide_drive * drive = NULL;
-
-    V3_ASSERT((bus_num >= 0) && (bus_num < 2));
-    V3_ASSERT((drive_num >= 0) && (drive_num < 2));
-
-    channel = &(ide->channels[bus_num]);
-    drive = &(channel->drives[drive_num]);
-    
-    if (drive->drive_type != BLOCK_NONE) {
-       PrintError("Device slot (bus=%d, drive=%d) already occupied\n", bus_num, drive_num);
-       return -1;
-    }
-
-    strncpy(drive->model, dev_name, sizeof(drive->model) - 1);
-
-    drive->drive_type = BLOCK_DISK;
-
-    drive->hd_state.accessed = 0;
-    drive->hd_state.mult_sector_num = 1;
-
-    drive->hd_ops = ops;
-
-    /* this is something of a hack... */
-    drive->num_sectors = 63;
-    drive->num_heads = 16;
-    drive->num_cylinders = ops->get_capacity(private_data)  / (drive->num_sectors * drive->num_heads);
-
-    if (ide->ide_pci) {
-       // Hardcode this for now, but its not a good idea....
-       ide->ide_pci->config_space[0x41 + (bus_num * 2)] = 0x80;
-    }
-
-
-
-    drive->private_data = private_data;
-
-    return 0;
-}
-
-
-
index 3bd5902..95392d0 100644 (file)
@@ -21,7 +21,7 @@
 #include <palacios/vmm.h>
 #include <palacios/vmm_dev_mgr.h>
 #include <devices/apic.h>
-
+#include <palacios/vm_guest.h>
 
 #ifndef CONFIG_DEBUG_IO_APIC
 #undef PrintDebug
@@ -319,11 +319,12 @@ static struct v3_device_ops dev_ops = {
 
 
 
-static int ioapic_init(struct guest_info * vm, void * cfg_data) {
-    struct vm_device * apic = v3_find_dev(vm, (char *)cfg_data);
+static int ioapic_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
+    struct vm_device * apic = v3_find_dev(vm, v3_cfg_val(cfg, "irq_bus"));
+    char * name = v3_cfg_val(cfg, "name");
 
     if (!apic) {
-       PrintError("Could not locate APIC device (%s)\n", (char *)cfg_data);
+       PrintError("Could not locate APIC device (%s)\n", v3_cfg_val(cfg, "irq_bus"));
        return -1;
     }
 
@@ -333,11 +334,11 @@ static int ioapic_init(struct guest_info * vm, void * cfg_data) {
 
     ioapic->apic = apic;
 
-    struct vm_device * dev = v3_allocate_device("IOAPIC", &dev_ops, ioapic);
+    struct vm_device * dev = v3_allocate_device(name, &dev_ops, ioapic);
 
 
     if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", "IOAPIC");
+       PrintError("Could not attach device %s\n", name);
        return -1;
     }
 
index c05b00e..cf61967 100644 (file)
@@ -23,6 +23,9 @@
 
 #include <palacios/vmm_ringbuffer.h>
 #include <palacios/vmm_lock.h>
+#include <palacios/vmm_intr.h>
+#include <palacios/vmm_host_events.h>
+#include <palacios/vm_guest.h>
 
 
 #ifndef CONFIG_DEBUG_KEYBOARD
@@ -981,9 +984,9 @@ static struct v3_device_ops dev_ops = {
 
 
 
-static int keyboard_init(struct guest_info * vm, void * cfg_data) {
+static int keyboard_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
     struct keyboard_internal * keyboard_state = NULL;
-
+    char * name = v3_cfg_val(cfg, "name");
 
     PrintDebug("keyboard: init_device\n");
 
@@ -999,10 +1002,10 @@ static int keyboard_init(struct guest_info * vm, void * cfg_data) {
 
     keyboard_state->mouse_enabled = 0;
 
-    struct vm_device * dev = v3_allocate_device("KEYBOARD", &dev_ops, keyboard_state);
+    struct vm_device * dev = v3_allocate_device(name, &dev_ops, keyboard_state);
 
     if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", "KEYBOARD");
+       PrintError("Could not attach device %s\n", name);
        return -1;
     }
 
index e7a18aa..088cea4 100644 (file)
@@ -415,10 +415,11 @@ static int handle_query_hcall(struct guest_info * info, uint_t hcall_id, void *
 
 
 
-static int virtio_init(struct guest_info * vm, void * cfg_data) {
-    struct vm_device * pci_bus = v3_find_dev(vm, (char *)cfg_data);
+static int virtio_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
+    struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
     struct virtio_balloon_state * virtio_state = NULL;
     struct pci_device * pci_dev = NULL;
+    char * name = v3_cfg_val(cfg, "name");
 
     PrintDebug("Initializing VIRTIO Balloon device\n");
 
@@ -432,9 +433,9 @@ static int virtio_init(struct guest_info * vm, void * cfg_data) {
     memset(virtio_state, 0, sizeof(struct virtio_balloon_state));
 
 
-    struct vm_device * dev = v3_allocate_device("LNX_VIRTIO_BALLOON", &dev_ops, virtio_state);
+    struct vm_device * dev = v3_allocate_device(name, &dev_ops, virtio_state);
     if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", "LNX_VIRTIO_BALLOON");
+       PrintError("Could not attach device %s\n", name);
        return -1;
     }
 
@@ -481,7 +482,7 @@ static int virtio_init(struct guest_info * vm, void * cfg_data) {
        pci_dev = v3_pci_register_device(pci_bus, PCI_STD_DEVICE, 
                                         0, PCI_AUTO_DEV_NUM, 0,
                                         "LNX_VIRTIO_BALLOON", bars,
-                                        NULL, NULL, NULL, dev, NULL);
+                                        NULL, NULL, NULL, dev);
 
        if (!pci_dev) {
            PrintError("Could not register PCI Device\n");
index 0059fb6..7bc41a6 100644 (file)
@@ -20,8 +20,6 @@
 #include <palacios/vmm.h>
 #include <palacios/vmm_dev_mgr.h>
 #include <devices/lnx_virtio_pci.h>
-#include <devices/lnx_virtio_blk.h>
-#include <devices/block_dev.h>
 #include <palacios/vm_guest_mem.h>
 
 #include <devices/pci.h>
@@ -78,26 +76,30 @@ struct blk_op_hdr {
 #define VIRTIO_LEGACY_GEOM   0x10       /* Indicates support of legacy geometry */
 
 
-
+struct virtio_dev_state {
+    struct vm_device * pci_bus;
+    struct list_head dev_list;
+    struct guest_info * vm;
+};
 
 struct virtio_blk_state {
+
+    struct pci_device * pci_dev;
     struct blk_config block_cfg;
     struct virtio_config virtio_cfg;
 
-    struct vm_device * pci_bus;
-    struct pci_device * pci_dev;
     
     struct virtio_queue queue;
 
-    union {
-       struct v3_cd_ops * cd_ops;
-       struct v3_hd_ops * hd_ops;
-    };
+    struct v3_dev_blk_ops * ops;
 
-    v3_block_type_t block_type;
     void * backend_data;
 
     int io_range_size;
+
+    struct virtio_dev_state * virtio_dev;
+
+    struct list_head dev_link;
 };
 
 
@@ -105,8 +107,7 @@ static int virtio_free(struct vm_device * dev) {
     return -1;
 }
 
-static int virtio_reset(struct vm_device * dev) {
-    struct virtio_blk_state * virtio = (struct virtio_blk_state *)dev->private_data;
+static int blk_reset(struct virtio_blk_state * virtio) {
 
     virtio->queue.ring_desc_addr = 0;
     virtio->queue.ring_avail_addr = 0;
@@ -116,58 +117,38 @@ static int virtio_reset(struct vm_device * dev) {
 
     virtio->virtio_cfg.status = 0;
     virtio->virtio_cfg.pci_isr = 0;
-
     return 0;
 }
 
-static int handle_read_op(struct vm_device * dev, uint8_t * buf, uint64_t * sector, uint32_t len) {
-    struct virtio_blk_state * virtio = (struct virtio_blk_state *)dev->private_data; 
-    int ret = -1;
-
-    if (virtio->block_type == BLOCK_DISK) {
-       if (len % HD_SECTOR_SIZE) {
-           PrintError("Write of something that is not a sector len %d, mod=%d\n", len, len % HD_SECTOR_SIZE);
-           return -1;
-       }
-
 
-       PrintDebug("Reading Disk\n");
-           
-       ret = virtio->hd_ops->read(buf, len / HD_SECTOR_SIZE, *sector, virtio->backend_data);
+static int virtio_reset(struct vm_device * dev) {
+    struct virtio_dev_state * dev_state = (struct virtio_dev_state *)(dev->private_data);
+    struct virtio_blk_state * blk_state = NULL;
 
-       *sector += len / HD_SECTOR_SIZE;
+    list_for_each_entry(blk_state, &(dev_state->dev_list), dev_link) {
+       blk_reset(blk_state);
+    }
 
-    } else if (virtio->block_type == BLOCK_CDROM) {
-       if (len % ATAPI_BLOCK_SIZE) {
-           PrintError("Write of something that is not an ATAPI block len %d, mod=%d\n", len, len % ATAPI_BLOCK_SIZE);
-           return -1;
-       }
+    return 0;
+}
 
-       ret = virtio->cd_ops->read(buf, len / ATAPI_BLOCK_SIZE, *sector , virtio->backend_data);
+static int handle_read_op(struct virtio_blk_state * blk_state, uint8_t * buf, uint64_t * sector, uint64_t len) {
+    int ret = -1;
 
-       *sector += len / ATAPI_BLOCK_SIZE;
-    }
+    PrintDebug("Reading Disk\n");
+    ret = blk_state->ops->read(buf, *sector, len, (void *)(blk_state->backend_data));
+    *sector += len;
 
     return ret;
 }
 
 
-static int handle_write_op(struct vm_device * dev, uint8_t * buf, uint64_t * sector, uint32_t len) {
-    struct virtio_blk_state * virtio = (struct virtio_blk_state *)dev->private_data; 
+static int handle_write_op(struct virtio_blk_state * blk_state, uint8_t * buf, uint64_t * sector, uint64_t len) {
     int ret = -1;
 
-    if (virtio->block_type == BLOCK_DISK) {
-       if (len % HD_SECTOR_SIZE) {
-           PrintError("Write of something that is not a sector len %d, mod=%d\n", len, len % HD_SECTOR_SIZE);
-           return -1;
-       }
-
-       PrintDebug("Writing Disk\n");
-
-       ret = virtio->hd_ops->write(buf, len / HD_SECTOR_SIZE, *sector, virtio->backend_data);
-
-       *sector += len / HD_SECTOR_SIZE;        
-    }
+    PrintDebug("Writing Disk\n");
+    ret = blk_state->ops->write(buf, *sector, len, (void *)(blk_state->backend_data));
+    *sector += len;
 
     return ret;
 }
@@ -176,56 +157,38 @@ static int handle_write_op(struct vm_device * dev, uint8_t * buf, uint64_t * sec
 
 // multiple block operations need to increment the sector 
 
-static int handle_block_op(struct vm_device * dev, struct blk_op_hdr * hdr, 
+static int handle_block_op(struct virtio_blk_state * blk_state, struct blk_op_hdr * hdr, 
                           struct vring_desc * buf_desc, uint8_t * status) {
-    struct virtio_blk_state * virtio = (struct virtio_blk_state *)dev->private_data;    
     uint8_t * buf = NULL;
 
     PrintDebug("Handling Block op\n");
-
-
-
-    if (guest_pa_to_host_va(dev->vm, buf_desc->addr_gpa, (addr_t *)&(buf)) == -1) {
+    if (guest_pa_to_host_va(blk_state->virtio_dev->vm, buf_desc->addr_gpa, (addr_t *)&(buf)) == -1) {
        PrintError("Could not translate buffer address\n");
        return -1;
     }
 
-
     PrintDebug("Sector=%p Length=%d\n", (void *)(addr_t)(hdr->sector), buf_desc->length);
 
     if (hdr->type == BLK_IN_REQ) {
-       if (virtio->block_type != BLOCK_NONE) {
-           if (handle_read_op(dev, buf, &(hdr->sector), buf_desc->length) == -1) {
-               *status = BLK_STATUS_ERR;
-               return -1;
-           } else {
-               *status = BLK_STATUS_OK;
-           }
+       if (handle_read_op(blk_state, buf, &(hdr->sector), buf_desc->length) == -1) {
+           *status = BLK_STATUS_ERR;
+           return -1;
        } else {
-           *status = BLK_STATUS_NOT_SUPPORTED;
+           *status = BLK_STATUS_OK;
        }
-
     } else if (hdr->type == BLK_OUT_REQ) {
-       if (virtio->block_type == BLOCK_DISK) {
-           if (handle_write_op(dev, buf, &(hdr->sector), buf_desc->length) == -1) {
-               *status = BLK_STATUS_ERR;
-               return -1;
-           } else {
-               *status = BLK_STATUS_OK;
-           }
-
+       if (handle_write_op(blk_state, buf, &(hdr->sector), buf_desc->length) == -1) {
+           *status = BLK_STATUS_ERR;
+           return -1;
        } else {
-           *status = BLK_STATUS_NOT_SUPPORTED;
+           *status = BLK_STATUS_OK;
        }
-
     } else if (hdr->type == BLK_SCSI_CMD) {
        PrintError("VIRTIO: SCSI Command Not supported!!!\n");
        *status = BLK_STATUS_NOT_SUPPORTED;
        return -1;
     }
 
-
-
     PrintDebug("Returning Status: %d\n", *status);
 
     return 0;
@@ -245,9 +208,8 @@ static int get_desc_count(struct virtio_queue * q, int index) {
 
 
 
-static int handle_kick(struct vm_device * dev) {
-    struct virtio_blk_state * virtio = (struct virtio_blk_state *)dev->private_data;    
-    struct virtio_queue * q = &(virtio->queue);
+static int handle_kick(struct virtio_blk_state * blk_state) {  
+    struct virtio_queue * q = &(blk_state->queue);
 
     PrintDebug("VIRTIO KICK: cur_index=%d (mod=%d), avail_index=%d\n", 
               q->cur_avail_idx, q->cur_avail_idx % QUEUE_SIZE, q->avail->index);
@@ -278,7 +240,7 @@ static int handle_kick(struct vm_device * dev) {
        PrintDebug("Header Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", hdr_desc, 
                   (void *)(hdr_desc->addr_gpa), hdr_desc->length, hdr_desc->flags, hdr_desc->next);    
 
-       if (guest_pa_to_host_va(dev->vm, hdr_desc->addr_gpa, &(hdr_addr)) == -1) {
+       if (guest_pa_to_host_va(blk_state->virtio_dev->vm, hdr_desc->addr_gpa, &(hdr_addr)) == -1) {
            PrintError("Could not translate block header address\n");
            return -1;
        }
@@ -298,7 +260,7 @@ static int handle_kick(struct vm_device * dev) {
            PrintDebug("Buffer Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", buf_desc, 
                       (void *)(buf_desc->addr_gpa), buf_desc->length, buf_desc->flags, buf_desc->next);
 
-           if (handle_block_op(dev, &hdr, buf_desc, &tmp_status) == -1) {
+           if (handle_block_op(blk_state, &hdr, buf_desc, &tmp_status) == -1) {
                PrintError("Error handling block operation\n");
                return -1;
            }
@@ -316,7 +278,7 @@ static int handle_kick(struct vm_device * dev) {
        PrintDebug("Status Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", status_desc, 
                   (void *)(status_desc->addr_gpa), status_desc->length, status_desc->flags, status_desc->next);
 
-       if (guest_pa_to_host_va(dev->vm, status_desc->addr_gpa, (addr_t *)&(status_ptr)) == -1) {
+       if (guest_pa_to_host_va(blk_state->virtio_dev->vm, status_desc->addr_gpa, (addr_t *)&(status_ptr)) == -1) {
            PrintError("Could not translate status address\n");
            return -1;
        }
@@ -332,18 +294,17 @@ static int handle_kick(struct vm_device * dev) {
     }
 
     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
-       PrintDebug("Raising IRQ %d\n",  virtio->pci_dev->config_header.intr_line);
-       v3_pci_raise_irq(virtio->pci_bus, 0, virtio->pci_dev);
-       virtio->virtio_cfg.pci_isr = 1;
+       PrintDebug("Raising IRQ %d\n",  blk_state->pci_dev->config_header.intr_line);
+       v3_pci_raise_irq(blk_state->virtio_dev->pci_bus, 0, blk_state->pci_dev);
+       blk_state->virtio_cfg.pci_isr = 1;
     }
 
     return 0;
 }
 
 static int virtio_io_write(uint16_t port, void * src, uint_t length, void * private_data) {
-    struct vm_device * dev = (struct vm_device *)private_data;
-    struct virtio_blk_state * virtio = (struct virtio_blk_state *)dev->private_data;
-    int port_idx = port % virtio->io_range_size;
+    struct virtio_blk_state * blk_state = (struct virtio_blk_state *)private_data;
+    int port_idx = port % blk_state->io_range_size;
 
 
     PrintDebug("VIRTIO BLOCK Write for port %d (index=%d) len=%d, value=%x\n", 
@@ -358,8 +319,8 @@ static int virtio_io_write(uint16_t port, void * src, uint_t length, void * priv
                return -1;
            }
            
-           virtio->virtio_cfg.guest_features = *(uint32_t *)src;
-           PrintDebug("Setting Guest Features to %x\n", virtio->virtio_cfg.guest_features);
+           blk_state->virtio_cfg.guest_features = *(uint32_t *)src;
+           PrintDebug("Setting Guest Features to %x\n", blk_state->virtio_cfg.guest_features);
 
            break;
        case VRING_PG_NUM_PORT:
@@ -368,41 +329,41 @@ static int virtio_io_write(uint16_t port, void * src, uint_t length, void * priv
                addr_t page_addr = (pfn << VIRTIO_PAGE_SHIFT);
 
 
-               virtio->queue.pfn = pfn;
+               blk_state->queue.pfn = pfn;
                
-               virtio->queue.ring_desc_addr = page_addr ;
-               virtio->queue.ring_avail_addr = page_addr + (QUEUE_SIZE * sizeof(struct vring_desc));
-               virtio->queue.ring_used_addr = ( virtio->queue.ring_avail_addr + \
+               blk_state->queue.ring_desc_addr = page_addr ;
+               blk_state->queue.ring_avail_addr = page_addr + (QUEUE_SIZE * sizeof(struct vring_desc));
+               blk_state->queue.ring_used_addr = ( blk_state->queue.ring_avail_addr + \
                                                 sizeof(struct vring_avail)    + \
                                                 (QUEUE_SIZE * sizeof(uint16_t)));
                
                // round up to next page boundary.
-               virtio->queue.ring_used_addr = (virtio->queue.ring_used_addr + 0xfff) & ~0xfff;
+               blk_state->queue.ring_used_addr = (blk_state->queue.ring_used_addr + 0xfff) & ~0xfff;
 
-               if (guest_pa_to_host_va(dev->vm, virtio->queue.ring_desc_addr, (addr_t *)&(virtio->queue.desc)) == -1) {
+               if (guest_pa_to_host_va(blk_state->virtio_dev->vm, blk_state->queue.ring_desc_addr, (addr_t *)&(blk_state->queue.desc)) == -1) {
                    PrintError("Could not translate ring descriptor address\n");
                    return -1;
                }
 
 
-               if (guest_pa_to_host_va(dev->vm, virtio->queue.ring_avail_addr, (addr_t *)&(virtio->queue.avail)) == -1) {
+               if (guest_pa_to_host_va(blk_state->virtio_dev->vm, blk_state->queue.ring_avail_addr, (addr_t *)&(blk_state->queue.avail)) == -1) {
                    PrintError("Could not translate ring available address\n");
                    return -1;
                }
 
 
-               if (guest_pa_to_host_va(dev->vm, virtio->queue.ring_used_addr, (addr_t *)&(virtio->queue.used)) == -1) {
+               if (guest_pa_to_host_va(blk_state->virtio_dev->vm, blk_state->queue.ring_used_addr, (addr_t *)&(blk_state->queue.used)) == -1) {
                    PrintError("Could not translate ring used address\n");
                    return -1;
                }
 
                PrintDebug("RingDesc_addr=%p, Avail_addr=%p, Used_addr=%p\n",
-                          (void *)(virtio->queue.ring_desc_addr),
-                          (void *)(virtio->queue.ring_avail_addr),
-                          (void *)(virtio->queue.ring_used_addr));
+                          (void *)(blk_state->queue.ring_desc_addr),
+                          (void *)(blk_state->queue.ring_avail_addr),
+                          (void *)(blk_state->queue.ring_used_addr));
 
                PrintDebug("RingDesc=%p, Avail=%p, Used=%p\n", 
-                          virtio->queue.desc, virtio->queue.avail, virtio->queue.used);
+                          blk_state->queue.desc, blk_state->queue.avail, blk_state->queue.used);
 
            } else {
                PrintError("Illegal write length for page frame number\n");
@@ -410,34 +371,34 @@ static int virtio_io_write(uint16_t port, void * src, uint_t length, void * priv
            }
            break;
        case VRING_Q_SEL_PORT:
-           virtio->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
+           blk_state->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
 
-           if (virtio->virtio_cfg.vring_queue_selector != 0) {
+           if (blk_state->virtio_cfg.vring_queue_selector != 0) {
                PrintError("Virtio Block device only uses 1 queue, selected %d\n", 
-                          virtio->virtio_cfg.vring_queue_selector);
+                          blk_state->virtio_cfg.vring_queue_selector);
                return -1;
            }
 
            break;
        case VRING_Q_NOTIFY_PORT:
            PrintDebug("Handling Kick\n");
-           if (handle_kick(dev) == -1) {
+           if (handle_kick(blk_state) == -1) {
                PrintError("Could not handle Block Notification\n");
                return -1;
            }
            break;
        case VIRTIO_STATUS_PORT:
-           virtio->virtio_cfg.status = *(uint8_t *)src;
+           blk_state->virtio_cfg.status = *(uint8_t *)src;
 
-           if (virtio->virtio_cfg.status == 0) {
+           if (blk_state->virtio_cfg.status == 0) {
                PrintDebug("Resetting device\n");
-               virtio_reset(dev);
+               blk_reset(blk_state);
            }
 
            break;
 
        case VIRTIO_ISR_PORT:
-           virtio->virtio_cfg.pci_isr = *(uint8_t *)src;
+           blk_state->virtio_cfg.pci_isr = *(uint8_t *)src;
            break;
        default:
            return -1;
@@ -449,9 +410,8 @@ static int virtio_io_write(uint16_t port, void * src, uint_t length, void * priv
 
 
 static int virtio_io_read(uint16_t port, void * dst, uint_t length, void * private_data) {
-    struct vm_device * dev = (struct vm_device *)private_data;
-    struct virtio_blk_state * virtio = (struct virtio_blk_state *)dev->private_data;
-    int port_idx = port % virtio->io_range_size;
+    struct virtio_blk_state * blk_state = (struct virtio_blk_state *)private_data;
+    int port_idx = port % blk_state->io_range_size;
 
 
     PrintDebug("VIRTIO BLOCK Read  for port %d (index =%d), length=%d\n", 
@@ -464,7 +424,7 @@ static int virtio_io_read(uint16_t port, void * dst, uint_t length, void * priva
                return -1;
            }
 
-           *(uint32_t *)dst = virtio->virtio_cfg.host_features;
+           *(uint32_t *)dst = blk_state->virtio_cfg.host_features;
        
            break;
        case VRING_PG_NUM_PORT:
@@ -473,7 +433,7 @@ static int virtio_io_read(uint16_t port, void * dst, uint_t length, void * priva
                return -1;
            }
 
-           *(uint32_t *)dst = virtio->queue.pfn;
+           *(uint32_t *)dst = blk_state->queue.pfn;
 
            break;
        case VRING_SIZE_PORT:
@@ -482,7 +442,7 @@ static int virtio_io_read(uint16_t port, void * dst, uint_t length, void * priva
                return -1;
            }
                
-           *(uint16_t *)dst = virtio->queue.queue_size;
+           *(uint16_t *)dst = blk_state->queue.queue_size;
 
            break;
 
@@ -492,20 +452,20 @@ static int virtio_io_read(uint16_t port, void * dst, uint_t length, void * priva
                return -1;
            }
 
-           *(uint8_t *)dst = virtio->virtio_cfg.status;
+           *(uint8_t *)dst = blk_state->virtio_cfg.status;
            break;
 
        case VIRTIO_ISR_PORT:
-           *(uint8_t *)dst = virtio->virtio_cfg.pci_isr;
-           virtio->virtio_cfg.pci_isr = 0;
-           v3_pci_lower_irq(virtio->pci_bus, 0, virtio->pci_dev);
+           *(uint8_t *)dst = blk_state->virtio_cfg.pci_isr;
+           blk_state->virtio_cfg.pci_isr = 0;
+           v3_pci_lower_irq(blk_state->virtio_dev->pci_bus, 0, blk_state->pci_dev);
            break;
 
        default:
            if ( (port_idx >= sizeof(struct virtio_config)) && 
                 (port_idx < (sizeof(struct virtio_config) + sizeof(struct blk_config))) ) {
                int cfg_offset = port_idx - sizeof(struct virtio_config);
-               uint8_t * cfg_ptr = (uint8_t *)&(virtio->block_cfg);
+               uint8_t * cfg_ptr = (uint8_t *)&(blk_state->block_cfg);
 
                memcpy(dst, cfg_ptr + cfg_offset, length);
                
@@ -525,7 +485,7 @@ static int virtio_io_read(uint16_t port, void * dst, uint_t length, void * priva
 
 static struct v3_device_ops dev_ops = {
     .free = virtio_free,
-    .reset = NULL,
+    .reset = virtio_reset,
     .start = NULL,
     .stop = NULL,
 };
@@ -533,142 +493,145 @@ static struct v3_device_ops dev_ops = {
 
 
 
-int v3_virtio_register_cdrom(struct vm_device * dev, struct v3_cd_ops * ops, void * private_data) {
-    struct virtio_blk_state * virtio = (struct virtio_blk_state *)dev->private_data;
-    
-    virtio->block_type = BLOCK_CDROM;
-    virtio->cd_ops = ops;
-    virtio->backend_data = private_data;
-
-    virtio->block_cfg.capacity = ops->get_capacity(private_data);
-
-    return 0;
-}
-
-
-int v3_virtio_register_harddisk(struct vm_device * dev, struct v3_hd_ops * ops, void * private_data) {
-    struct virtio_blk_state * virtio = (struct virtio_blk_state *)dev->private_data;
-
-    virtio->block_type = BLOCK_DISK;
-    virtio->hd_ops = ops;
-    virtio->backend_data = private_data;
-
-    virtio->block_cfg.capacity = ops->get_capacity(private_data);
-
-    PrintDebug("Virtio Capacity = %d -- 0x%p\n", (int)(virtio->block_cfg.capacity), 
-       (void *)(addr_t)(virtio->block_cfg.capacity));
-
-    return 0;
-}
-
-
 
-static int virtio_init(struct guest_info * vm, void * cfg_data) {
-    struct vm_device * pci_bus = v3_find_dev(vm, (char *)cfg_data);
-    struct virtio_blk_state * virtio_state = NULL;
+static int register_dev(struct virtio_dev_state * virtio, struct virtio_blk_state * blk_state) {
+    // initialize PCI
     struct pci_device * pci_dev = NULL;
+    struct v3_pci_bar bars[6];
+    int num_ports = sizeof(struct virtio_config) + sizeof(struct blk_config);
+    int tmp_ports = num_ports;
+    int i;
 
-    PrintDebug("Initializing VIRTIO Block device\n");
 
-    if (pci_bus == NULL) {
-       PrintError("VirtIO devices require a PCI Bus");
-       return -1;
-    }
 
+    // This gets the number of ports, rounded up to a power of 2
+    blk_state->io_range_size = 1; // must be a power of 2
     
-    virtio_state  = (struct virtio_blk_state *)V3_Malloc(sizeof(struct virtio_blk_state));
-    memset(virtio_state, 0, sizeof(struct virtio_blk_state));
-
-
-    struct vm_device * dev = v3_allocate_device("LNX_VIRTIO_BLK", &dev_ops, virtio_state);
-    if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", "LNX_VIRTIO_BLK");
+    while (tmp_ports > 0) {
+       tmp_ports >>= 1;
+       blk_state->io_range_size <<= 1;
+    }
+       
+    // this is to account for any low order bits being set in num_ports
+    // if there are none, then num_ports was already a power of 2 so we shift right to reset it
+    if ((num_ports & ((blk_state->io_range_size >> 1) - 1)) == 0) {
+       blk_state->io_range_size >>= 1;
+    }
+    
+    
+    for (i = 0; i < 6; i++) {
+       bars[i].type = PCI_BAR_NONE;
+    }
+    
+    PrintDebug("Virtio-BLK io_range_size = %d\n", blk_state->io_range_size);
+    
+    bars[0].type = PCI_BAR_IO;
+    bars[0].default_base_port = -1;
+    bars[0].num_ports = blk_state->io_range_size;
+    
+    bars[0].io_read = virtio_io_read;
+    bars[0].io_write = virtio_io_write;
+    bars[0].private_data = blk_state;
+    
+    pci_dev = v3_pci_register_device(virtio->pci_bus, PCI_STD_DEVICE, 
+                                    0, PCI_AUTO_DEV_NUM, 0,
+                                    "LNX_VIRTIO_BLK", bars,
+                                    NULL, NULL, NULL, blk_state);
+    
+    if (!pci_dev) {
+       PrintError("Could not register PCI Device\n");
        return -1;
     }
+    
+    pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
+    pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_ID;
+    
+    
+    pci_dev->config_header.device_id = VIRTIO_BLOCK_DEV_ID;
+    pci_dev->config_header.class = PCI_CLASS_STORAGE;
+    pci_dev->config_header.subclass = PCI_STORAGE_SUBCLASS_OTHER;
+    
+    pci_dev->config_header.subsystem_id = VIRTIO_BLOCK_SUBDEVICE_ID;
+    
+    
+    pci_dev->config_header.intr_pin = 1;
+    
+    pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
+    
+    
+    blk_state->pci_dev = pci_dev;
+    
+    /* Block configuration */
+    blk_state->virtio_cfg.host_features = VIRTIO_SEG_MAX;
+    blk_state->block_cfg.max_seg = QUEUE_SIZE - 2;
 
+    // Virtio Block only uses one queue
+    blk_state->queue.queue_size = QUEUE_SIZE;
 
-    // PCI initialization
-    {
-       struct v3_pci_bar bars[6];
-       int num_ports = sizeof(struct virtio_config) + sizeof(struct blk_config);
-       int tmp_ports = num_ports;
-       int i;
-
+    blk_state->virtio_dev = virtio;
 
+    blk_reset(blk_state);
 
-       // This gets the number of ports, rounded up to a power of 2
-       virtio_state->io_range_size = 1; // must be a power of 2
 
-       while (tmp_ports > 0) {
-           tmp_ports >>= 1;
-           virtio_state->io_range_size <<= 1;
-       }
-       
-       // this is to account for any low order bits being set in num_ports
-       // if there are none, then num_ports was already a power of 2 so we shift right to reset it
-       if ((num_ports & ((virtio_state->io_range_size >> 1) - 1)) == 0) {
-           virtio_state->io_range_size >>= 1;
-       }
+    return 0;
+}
 
 
-       for (i = 0; i < 6; i++) {
-           bars[i].type = PCI_BAR_NONE;
-       }
+static int connect_fn(struct guest_info * info, 
+                     void * frontend_data, 
+                     struct v3_dev_blk_ops * ops, 
+                     v3_cfg_tree_t * cfg, 
+                     void * private_data) {
 
-       PrintDebug("Virtio-BLK io_range_size = %d\n", virtio_state->io_range_size);
+    struct virtio_dev_state * virtio = (struct virtio_dev_state *)frontend_data;
 
-       bars[0].type = PCI_BAR_IO;
-       bars[0].default_base_port = -1;
-       bars[0].num_ports = virtio_state->io_range_size;
+    struct virtio_blk_state * blk_state  = (struct virtio_blk_state *)V3_Malloc(sizeof(struct virtio_blk_state));
+    memset(blk_state, 0, sizeof(struct virtio_blk_state));
 
-       bars[0].io_read = virtio_io_read;
-       bars[0].io_write = virtio_io_write;
-       bars[0].private_data = dev;
+    register_dev(virtio, blk_state);
 
-       pci_dev = v3_pci_register_device(pci_bus, PCI_STD_DEVICE, 
-                                        0, PCI_AUTO_DEV_NUM, 0,
-                                        "LNX_VIRTIO_BLK", bars,
-                                        NULL, NULL, NULL, dev, NULL);
+    blk_state->ops = ops;
+    blk_state->backend_data = private_data;
 
-       if (!pci_dev) {
-           PrintError("Could not register PCI Device\n");
-           return -1;
-       }
-       
-       pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
-       pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_ID;
-       
+    blk_state->block_cfg.capacity = ops->get_capacity(private_data);
 
-       pci_dev->config_header.device_id = VIRTIO_BLOCK_DEV_ID;
-       pci_dev->config_header.class = PCI_CLASS_STORAGE;
-       pci_dev->config_header.subclass = PCI_STORAGE_SUBCLASS_OTHER;
-    
-       pci_dev->config_header.subsystem_id = VIRTIO_BLOCK_SUBDEVICE_ID;
+    PrintDebug("Virtio Capacity = %d -- 0x%p\n", (int)(virtio->block_cfg.capacity), 
+              (void *)(addr_t)(virtio->block_cfg.capacity));
 
+    return 0;
+}
 
-       pci_dev->config_header.intr_pin = 1;
 
-       pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
+static int virtio_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
+    struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
+    struct virtio_dev_state * virtio_state = NULL;
+    char * name = v3_cfg_val(cfg, "name");
 
+    PrintDebug("Initializing VIRTIO Block device\n");
 
-       virtio_state->pci_dev = pci_dev;
-       virtio_state->pci_bus = pci_bus;
+    if (pci_bus == NULL) {
+       PrintError("VirtIO devices require a PCI Bus");
+       return -1;
     }
 
-    /* Block configuration */
-    virtio_state->virtio_cfg.host_features = VIRTIO_SEG_MAX;
-    virtio_state->block_cfg.max_seg = QUEUE_SIZE - 2;
 
-    // Virtio Block only uses one queue
-    virtio_state->queue.queue_size = QUEUE_SIZE;
-
-    virtio_reset(dev);
+    virtio_state  = (struct virtio_dev_state *)V3_Malloc(sizeof(struct virtio_dev_state));
+    memset(virtio_state, 0, sizeof(struct virtio_dev_state));
 
+    INIT_LIST_HEAD(&(virtio_state->dev_list));
+    virtio_state->pci_bus = pci_bus;
+    virtio_state->vm = vm;
 
+    struct vm_device * dev = v3_allocate_device(name, &dev_ops, virtio_state);
+    if (v3_attach_device(vm, dev) == -1) {
+       PrintError("Could not attach device %s\n", name);
+       return -1;
+    }
 
-    virtio_state->backend_data = NULL;
-    virtio_state->block_type = BLOCK_NONE;
-    virtio_state->hd_ops = NULL;
+    if (v3_dev_add_blk_frontend(vm, name, connect_fn, (void *)virtio_state) == -1) {
+       PrintError("Could not register %s as block frontend\n", name);
+       return -1;
+    }
 
     return 0;
 }
index ad5cbbd..d27429b 100644 (file)
@@ -351,10 +351,11 @@ static struct v3_device_ops dev_ops = {
 
 
 
-static int virtio_init(struct guest_info * vm, void * cfg_data) {
-    struct vm_device * pci_bus = v3_find_dev(vm, (char *)cfg_data);
+static int virtio_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
+    struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
     struct virtio_sym_state * virtio_state = NULL;
     struct pci_device * pci_dev = NULL;
+    char * name = v3_cfg_val(cfg, "name");
 
     PrintDebug("Initializing VIRTIO Symbiotic device\n");
 
@@ -368,9 +369,9 @@ static int virtio_init(struct guest_info * vm, void * cfg_data) {
     memset(virtio_state, 0, sizeof(struct virtio_sym_state));
 
 
-    struct vm_device * dev = v3_allocate_device("LNX_VIRTIO_SYM", &dev_ops, virtio_state);
+    struct vm_device * dev = v3_allocate_device(name, &dev_ops, virtio_state);
     if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", "LNX_VIRTIO_SYM");
+       PrintError("Could not attach device %s\n", name);
        return -1;
     }
 
@@ -414,7 +415,7 @@ static int virtio_init(struct guest_info * vm, void * cfg_data) {
        pci_dev = v3_pci_register_device(pci_bus, PCI_STD_DEVICE, 
                                         0, PCI_AUTO_DEV_NUM, 0,
                                         "LNX_VIRTIO_SYM", bars,
-                                        NULL, NULL, NULL, dev, NULL);
+                                        NULL, NULL, NULL, dev);
 
        if (!pci_dev) {
            PrintError("Could not register PCI Device\n");
diff --git a/palacios/src/devices/net_cd.c b/palacios/src/devices/net_cd.c
deleted file mode 100644 (file)
index f980bab..0000000
+++ /dev/null
@@ -1,277 +0,0 @@
-/* 
- * This file is part of the Palacios Virtual Machine Monitor developed
- * by the V3VEE Project with funding from the United States National 
- * Science Foundation and the Department of Energy.  
- *
- * The V3VEE Project is a joint project between Northwestern University
- * and the University of New Mexico.  You can find out more at 
- * http://www.v3vee.org
- *
- * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
- * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
- * All rights reserved.
- *
- * Author: Jack Lange <jarusl@cs.northwestern.edu>
- *
- * This is free software.  You are permitted to use,
- * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
- */
-
-#include <palacios/vmm.h>
-#include <devices/net_cd.h>
-#include <devices/ide.h>
-#include <palacios/vmm_socket.h>
-
-#ifndef CONFIG_DEBUG_IDE
-#undef PrintDebug
-#define PrintDebug(fmt, args...)
-#endif 
-
-
-#define NBD_READ_CMD 0x1
-#define NBD_WRITE_CMD 0x2
-#define NBD_CAPACITY_CMD 0x3
-
-#define NBD_STATUS_OK 0x00
-#define NBD_STATUS_ERR 0xff
-
-struct cd_state {
-    uint64_t capacity; // in bytes
-
-    int socket;
-
-    uint32_t ip_addr;
-    uint16_t port;
-
-    char disk_name[32];
-
-    struct vm_device * ide;
-
-    uint_t bus;
-    uint_t drive;
-};
-
-
-static int send_all(int socket, char * buf, int length) {
-    int bytes_sent = 0;
-    
-    PrintDebug("Sending %d bytes\n", length - bytes_sent);
-    while (bytes_sent < length) {
-       int tmp_bytes = V3_Send(socket, buf + bytes_sent, length - bytes_sent);
-       PrintDebug("Sent %d bytes\n", tmp_bytes);
-       
-       if (tmp_bytes == 0) {
-           PrintError("Connection Closed unexpectedly\n");
-           return -1;
-       }
-       
-       bytes_sent += tmp_bytes;
-    }
-    
-    return 0;
-}
-
-
-static int recv_all(int socket, char * buf, int length) {
-    int bytes_read = 0;
-    
-    PrintDebug("Reading %d bytes\n", length - bytes_read);
-    while (bytes_read < length) {
-       int tmp_bytes = V3_Recv(socket, buf + bytes_read, length - bytes_read);
-       PrintDebug("Received %d bytes\n", tmp_bytes);
-       
-       if (tmp_bytes == 0) {
-           PrintError("Connection Closed unexpectedly\n");
-           return -1;
-       }
-       
-       bytes_read += tmp_bytes;
-    }
-    
-    return 0;
-}
-
-// CDs always read 2048 byte blocks... ?
-static int cd_read(uint8_t * buf, int block_count, uint64_t lba,  void * private_data) {
-    struct vm_device * cd_dev = (struct vm_device *)private_data;
-    struct cd_state * cd = (struct cd_state *)(cd_dev->private_data);
-    uint64_t offset = lba * ATAPI_BLOCK_SIZE;
-    int length = block_count * ATAPI_BLOCK_SIZE;
-    uint8_t status;
-    uint32_t ret_len = 0;
-    char nbd_cmd[4] = {0,0,0,0};
-
-    nbd_cmd[0] = NBD_READ_CMD;
-    
-    if (send_all(cd->socket, nbd_cmd, 4) == -1) {
-       PrintError("Error sending capacity command\n");
-       return -1;
-    }
-    
-    if (send_all(cd->socket, (char *)&offset, 8) == -1) {
-       PrintError("Error sending read offset\n");
-       return -1;
-    }
-
-    if (send_all(cd->socket, (char *)&length, 4) == -1) {
-       PrintError("Error sending read length\n");
-       return -1;
-    }
-
-    if (recv_all(cd->socket, (char *)&status, 1) == -1) {
-       PrintError("Error receiving status\n");
-       return -1;
-    }
-
-    if (status != NBD_STATUS_OK) {
-       PrintError("NBD Error....\n");
-       return -1;
-    }
-
-    PrintDebug("Reading Data Ret Length\n");
-
-    if (recv_all(cd->socket, (char *)&ret_len, 4) == -1) {
-       PrintError("Error receiving Return read length\n");
-       return -1;
-    }
-
-    if (ret_len != length) {
-       PrintError("Read length mismatch (req=%d) (result=%d)\n", length, ret_len);
-       return -1;
-    }
-
-    PrintDebug("Reading Data (%d bytes)\n", ret_len);
-
-    if (recv_all(cd->socket, (char *)buf, ret_len) == -1) {
-       PrintError("Read Data Error\n");
-       return -1;
-    }
-    
-    return 0;
-}
-
-
-static uint32_t cd_get_capacity(void * private_data) {
-    struct vm_device * cd_dev = (struct vm_device *)private_data;
-    struct cd_state * cd = (struct cd_state *)(cd_dev->private_data);
-
-    return cd->capacity / ATAPI_BLOCK_SIZE;
-}
-
-static struct v3_cd_ops cd_ops = {
-    .read = cd_read, 
-    .get_capacity = cd_get_capacity,
-};
-
-
-
-
-static int cd_free(struct vm_device * dev) {
-    return 0;
-}
-
-static struct v3_device_ops dev_ops = {
-    .free = cd_free,
-    .reset = NULL,
-    .start = NULL,
-    .stop = NULL,
-};
-
-
-
-static int socket_init(struct cd_state * cd) {
-    char header[64];
-    
-    PrintDebug("Intializing Net CD\n");
-
-    cd->socket = V3_Create_TCP_Socket();
-
-    PrintDebug("CD socket: %d\n", cd->socket);
-    PrintDebug("Connecting to: %s:%d\n", v3_inet_ntoa(cd->ip_addr), cd->port);
-
-    V3_Connect_To_IP(cd->socket, v3_ntohl(cd->ip_addr), cd->port);
-
-
-    PrintDebug("Connected to NBD server\n");
-
-    //snprintf(header, 64, "V3_NBD_1 %s\n", cd->disk_name);
-    strcpy(header, "V3_NBD_1 ");
-    strncat(header, cd->disk_name, 32);
-    strncat(header, "\n", 1);
-
-
-    if (send_all(cd->socket, header, strlen(header)) == -1) {
-       PrintError("Error connecting to Network Block Device: %s\n", cd->disk_name);
-       return -1;
-    }
-
-    // Cache Capacity
-    {
-       char nbd_cmd[4] = {0,0,0,0};
-
-       nbd_cmd[0] = NBD_CAPACITY_CMD;
-       
-       if (send_all(cd->socket, nbd_cmd, 4) == -1) {
-           PrintError("Error sending capacity command\n");
-           return -1;
-       }
-
-       if (recv_all(cd->socket, (char *)&(cd->capacity), 8) == -1) {
-           PrintError("Error Receiving Capacity\n");
-           return -1;
-       }       
-
-       PrintDebug("Capacity: %p\n", (void *)(cd->capacity));
-    }
-
-    return 0;
-}
-
-static int cd_init(struct guest_info * vm, void * cfg_data) {
-    struct net_cd_cfg * cfg = (struct net_cd_cfg *)cfg_data;
-    struct cd_state * cd = (struct cd_state *)V3_Malloc(sizeof(struct cd_state));
-
-    PrintDebug("Registering Net CD at %s:%d disk=%s\n", cfg->ip_str, cfg->port, cfg->disk_tag);
-
-    strncpy(cd->disk_name, cfg->disk_tag, sizeof(cd->disk_name));
-    cd->ip_addr = v3_inet_addr(cfg->ip_str);
-    cd->port = cfg->port;
-
-    cd->ide = (struct vm_device * )v3_find_dev(vm, cfg->ide);
-
-    if (cd->ide == 0) {
-       PrintError("Could not find backend %s\n", cfg->ide);
-       return -1;
-    }
-
-    cd->bus = cfg->bus;
-    cd->drive = cfg->drive;
-       
-    struct vm_device * dev = v3_allocate_device("NET-CD", &dev_ops, cd);
-
-
-    if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", "NET-CD");
-       return -1;
-    }
-
-    if (socket_init(cd) == -1) {
-       PrintError("Could not initialize socket connection\n");
-       return -1;
-    }
-
-    PrintDebug("Registering CD\n");
-
-    if (v3_ide_register_cdrom(cd->ide, cd->bus, cd->drive, "NET-CD", &cd_ops, dev) == -1) {
-       return -1;
-    }
-
-    PrintDebug("intialization done\n");
-
-    return 0;
-}
-
-
-
-
-device_register("NET-CD", cd_init)
similarity index 55%
rename from palacios/src/devices/net_hd.c
rename to palacios/src/devices/netdisk.c
index 0894797..552de56 100644 (file)
@@ -18,8 +18,7 @@
  */
 
 #include <palacios/vmm.h>
-#include <devices/net_hd.h>
-#include <devices/ide.h>
+#include <palacios/vmm_dev_mgr.h>
 #include <palacios/vmm_socket.h>
 
 #ifndef CONFIG_DEBUG_IDE
@@ -36,7 +35,7 @@
 #define NBD_STATUS_ERR 0xff
 
 
-struct hd_state {
+struct disk_state {
     uint64_t capacity; // in bytes
 
     int socket;
@@ -46,10 +45,6 @@ struct hd_state {
 
     char disk_name[32];
 
-    struct vm_device * ide;
-
-    uint_t bus;
-    uint_t drive;
 };
 
 
@@ -94,33 +89,32 @@ static int recv_all(int socket, char * buf, int length) {
 
 
 // HDs always read 512 byte blocks... ?
-static int hd_read(uint8_t * buf, int sector_count, uint64_t lba,  void * private_data) {
-    struct vm_device * hd_dev = (struct vm_device *)private_data;
-    struct hd_state * hd = (struct hd_state *)(hd_dev->private_data);
-    int offset = lba * HD_SECTOR_SIZE;
-    int length = sector_count * HD_SECTOR_SIZE;
+static int read(uint8_t * buf, uint64_t lba, uint64_t num_bytes, void * private_data) {
+    struct disk_state * disk = (struct disk_state *)private_data ;
     uint8_t status;
     uint32_t ret_len = 0;
     char nbd_cmd[4] = {0,0,0,0};
+    uint64_t offset = lba;
+    uint64_t length = num_bytes;
 
     nbd_cmd[0] = NBD_READ_CMD;
     
-    if (send_all(hd->socket, nbd_cmd, 4) == -1) {
+    if (send_all(disk->socket, nbd_cmd, 4) == -1) {
        PrintError("Error sending read command\n");
        return -1;
     }
     
-    if (send_all(hd->socket, (char *)&offset, 8) == -1) {
+    if (send_all(disk->socket, (char *)&offset, 8) == -1) {
        PrintError("Error sending read offset\n");
        return -1;
     }
 
-    if (send_all(hd->socket, (char *)&length, 4) == -1) {
+    if (send_all(disk->socket, (char *)&length, 4) == -1) {
        PrintError("Error sending read length\n");
        return -1;
     }
 
-    if (recv_all(hd->socket, (char *)&status, 1) == -1) {
+    if (recv_all(disk->socket, (char *)&status, 1) == -1) {
        PrintError("Error receiving status\n");
        return -1;
     }
@@ -132,7 +126,7 @@ static int hd_read(uint8_t * buf, int sector_count, uint64_t lba,  void * privat
 
     PrintDebug("Reading Data Ret Length\n");
 
-    if (recv_all(hd->socket, (char *)&ret_len, 4) == -1) {
+    if (recv_all(disk->socket, (char *)&ret_len, 4) == -1) {
        PrintError("Error receiving Return read length\n");
        return -1;
     }
@@ -144,7 +138,7 @@ static int hd_read(uint8_t * buf, int sector_count, uint64_t lba,  void * privat
 
     PrintDebug("Reading Data (%d bytes)\n", ret_len);
 
-    if (recv_all(hd->socket, (char *)buf, ret_len) == -1) {
+    if (recv_all(disk->socket, (char *)buf, ret_len) == -1) {
        PrintError("Read Data Error\n");
        return -1;
     }
@@ -153,39 +147,38 @@ static int hd_read(uint8_t * buf, int sector_count, uint64_t lba,  void * privat
 }
 
 
-static int hd_write(uint8_t * buf, int sector_count, uint64_t lba, void * private_data) {
-    struct vm_device * hd_dev = (struct vm_device *)private_data;
-    struct hd_state * hd = (struct hd_state *)(hd_dev->private_data);
-    int offset = lba * HD_SECTOR_SIZE;
-    int length = sector_count * HD_SECTOR_SIZE;
+static int write(uint8_t * buf, uint64_t lba, uint64_t num_bytes, void * private_data) {
+    struct disk_state * disk = (struct disk_state *)private_data ;
+    uint64_t offset = lba;
+    int length = num_bytes;
     uint8_t status;
     char nbd_cmd[4] = {0,0,0,0};
 
     nbd_cmd[0] = NBD_WRITE_CMD;
 
-    if (send_all(hd->socket, nbd_cmd, 4) == -1) {
+    if (send_all(disk->socket, nbd_cmd, 4) == -1) {
        PrintError("Error sending write command\n");
        return -1;
     }
 
-    if (send_all(hd->socket, (char *)&offset, 8) == -1) {
+    if (send_all(disk->socket, (char *)&offset, 8) == -1) {
        PrintError("Error sending write offset\n");
        return -1;
     }
 
-    if (send_all(hd->socket, (char *)&length, 4) == -1) {
+    if (send_all(disk->socket, (char *)&length, 4) == -1) {
        PrintError("Error sending write length\n");
        return -1;
     }
 
     PrintDebug("Writing Data (%d bytes)\n", length);
 
-    if (send_all(hd->socket, (char *)buf, length) == -1) {
+    if (send_all(disk->socket, (char *)buf, length) == -1) {
        PrintError("Write Data Error\n");
        return -1;
     }
 
-    if (recv_all(hd->socket, (char *)&status, 1) == -1) {
+    if (recv_all(disk->socket, (char *)&status, 1) == -1) {
        PrintError("Error receiving status\n");
        return -1;
     }
@@ -199,77 +192,76 @@ static int hd_write(uint8_t * buf, int sector_count, uint64_t lba, void * privat
 }
 
 
-static uint64_t hd_get_capacity(void * private_data) {
-    struct vm_device * hd_dev = (struct vm_device *)private_data;
-    struct hd_state * hd = (struct hd_state *)(hd_dev->private_data);
+static uint64_t get_capacity(void * private_data) {
+    struct disk_state * disk = (struct disk_state *)private_data;
 
-    return hd->capacity / HD_SECTOR_SIZE;
+    return disk->capacity;
 }
 
-static struct v3_hd_ops hd_ops = {
-    .read = hd_read, 
-    .write = hd_write,
-    .get_capacity = hd_get_capacity,
+static struct v3_dev_blk_ops blk_ops = {
+    .read = read, 
+    .write = write,
+    .get_capacity = get_capacity,
 };
 
 
 
 
 
-static int hd_free(struct vm_device * dev) {
+static int disk_free(struct vm_device * dev) {
     return 0;
 }
 
 static struct v3_device_ops dev_ops = {
-    .free = hd_free,
+    .free = disk_free,
     .reset = NULL,
     .start = NULL,
     .stop = NULL,
 };
 
 
-static int socket_init(struct hd_state * hd) {
+static int socket_init(struct disk_state * disk) {
     char header[64];
     
-    PrintDebug("Intializing Net HD\n");
+    PrintDebug("Intializing Net Disk\n");
 
-    hd->socket = V3_Create_TCP_Socket();
+    disk->socket = V3_Create_TCP_Socket();
 
-    PrintDebug("HD socket: %d\n", hd->socket);
-    PrintDebug("Connecting to: %s:%d\n", v3_inet_ntoa(hd->ip_addr), hd->port);
+    PrintDebug("DISK socket: %d\n", disk->socket);
+    PrintDebug("Connecting to: %s:%d\n", v3_inet_ntoa(disk->ip_addr), disk->port);
 
-    V3_Connect_To_IP(hd->socket, v3_ntohl(hd->ip_addr), hd->port);
+    V3_Connect_To_IP(disk->socket, v3_ntohl(disk->ip_addr), disk->port);
 
     PrintDebug("Connected to NBD server\n");
 
     //snprintf(header, 64, "V3_NBD_1 %s\n", cd->disk_name);
     strcpy(header, "V3_NBD_1 ");
-    strncat(header, hd->disk_name, 32);
+    strncat(header, disk->disk_name, 32);
     strncat(header, "\n", 1);
 
 
-    if (send_all(hd->socket, header, strlen(header)) == -1) {
-       PrintError("Error connecting to Network Block Device: %s\n", hd->disk_name);
+    if (send_all(disk->socket, header, strlen(header)) == -1) {
+       PrintError("Error connecting to Network Block Device: %s\n", disk->disk_name);
        return -1;
     }
 
-    // Cache Capacity
+    // store local copy of capacity
     {
        char nbd_cmd[4] = {0,0,0,0};
 
        nbd_cmd[0] = NBD_CAPACITY_CMD;
        
-       if (send_all(hd->socket, nbd_cmd, 4) == -1) {
+       if (send_all(disk->socket, nbd_cmd, 4) == -1) {
            PrintError("Error sending capacity command\n");
            return -1;
        }
 
-       if (recv_all(hd->socket, (char *)&(hd->capacity), 8) == -1) {
+       if (recv_all(disk->socket, (char *)&(disk->capacity), 8) == -1) {
            PrintError("Error Receiving Capacity\n");
            return -1;
        }       
 
-       PrintDebug("Capacity: %p\n", (void *)(hd->capacity));
+       PrintDebug("Capacity: %p\n", (void *)(disk->capacity));
     }
 
 
@@ -278,49 +270,46 @@ static int socket_init(struct hd_state * hd) {
 }
 
 
-static int hd_init(struct guest_info * vm, void * cfg_data) {
-    struct hd_state * hd = (struct hd_state *)V3_Malloc(sizeof(struct hd_state));
-    struct net_hd_cfg * cfg = (struct net_hd_cfg *)cfg_data;
-
-    PrintDebug("Registering Net HD at %s:%d disk=%s\n", cfg->ip_str, cfg->port, cfg->disk_tag);
+static int disk_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
+    struct disk_state * disk = (struct disk_state *)V3_Malloc(sizeof(struct disk_state));
 
-    strncpy(hd->disk_name, cfg->disk_tag, sizeof(hd->disk_name));
-    hd->ip_addr = v3_inet_addr(cfg->ip_str);
-    hd->port = cfg->port;
+    char * ip_str = v3_cfg_val(cfg, "IP");
+    char * port_str = v3_cfg_val(cfg, "port");
+    char * disk_tag = v3_cfg_val(cfg, "tag");
+    char * name = v3_cfg_val(cfg, "name");
 
-    hd->ide = v3_find_dev(vm, cfg->ide);
+    v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend");
 
-    if (hd->ide == 0) {
-       PrintError("Could not find backend %s\n", cfg->ide);
-       return -1;
-    }
+    PrintDebug("Registering Net disk at %s:%s disk=%s\n", ip_str, port_str, disk_tag);
 
-    hd->bus = cfg->bus;
-    hd->drive = cfg->drive;
+    strncpy(disk->disk_name, disk_tag, sizeof(disk->disk_name));
+    disk->ip_addr = v3_inet_addr(ip_str);
+    disk->port = atoi(port_str);
        
-    struct vm_device * dev = v3_allocate_device("NET-HD", &dev_ops, hd);
+    struct vm_device * dev = v3_allocate_device(name, &dev_ops, disk);
 
     if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", "NET-HD");
+       PrintError("Could not attach device %s\n", name);
        return -1;
     }
 
-    if (socket_init(hd) == -1) {
+    if (socket_init(disk) == -1) {
        PrintError("could not initialize network connection\n");
        return -1;
     }
 
+    PrintDebug("Registering Disk\n");
 
-    PrintDebug("Registering HD\n");
-
-    if (v3_ide_register_harddisk(hd->ide, hd->bus, hd->drive, "V3-NET-HD", &hd_ops, dev) == -1) {
+    if (v3_dev_connect_blk(vm, v3_cfg_val(frontend_cfg, "tag"), 
+                          &blk_ops, frontend_cfg, disk) == -1) {
+       PrintError("Could not connect %s to frontend\n", name);
        return -1;
     }
-    
+
     PrintDebug("intialization done\n");
 
     return 0;
 }
 
 
-device_register("NET-HD", hd_init)
+device_register("NETDISK", disk_init)
index 36da2aa..565c183 100644 (file)
@@ -25,6 +25,9 @@
 #include <palacios/vmm_lock.h>
 
 #include <devices/ide.h>
+#include <palacios/vmm_intr.h>
+#include <palacios/vmm_host_events.h>
+#include <palacios/vm_guest.h>
 
 #ifndef CONFIG_DEBUG_NVRAM
 #undef PrintDebug
@@ -791,9 +794,10 @@ static struct v3_device_ops dev_ops = {
 
 
 
-static int nvram_init(struct guest_info * vm, void * cfg_data) {
+static int nvram_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
     struct nvram_internal * nvram_state = NULL;
-    struct vm_device * ide = v3_find_dev(vm, (char *)cfg_data);
+    struct vm_device * ide = v3_find_dev(vm, v3_cfg_val(cfg, "storage"));
+    char * name = v3_cfg_val(cfg, "name");
 
     if (!ide) {
        PrintError("Could not find IDE device\n");
@@ -807,11 +811,11 @@ static int nvram_init(struct guest_info * vm, void * cfg_data) {
 
     nvram_state->ide = ide;
 
-    struct vm_device * dev = v3_allocate_device("NVRAM", &dev_ops, nvram_state);
+    struct vm_device * dev = v3_allocate_device(name, &dev_ops, nvram_state);
 
 
     if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", "NVRAM");
+       PrintError("Could not attach device %s\n", name);
        return -1;
     }
 
index 7abdeb0..a51dc19 100644 (file)
@@ -103,18 +103,19 @@ static struct v3_device_ops dev_ops = {
 
 
 
-static int debug_init(struct guest_info * vm, void * cfg_data) {
+static int debug_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
     struct debug_state * state = NULL;
+    char * name = v3_cfg_val(cfg, "name");
 
     state = (struct debug_state *)V3_Malloc(sizeof(struct debug_state));
 
     PrintDebug("Creating OS Debug Device\n");
 
-    struct vm_device * dev = v3_allocate_device("OS_DEBUG", &dev_ops, state);
+    struct vm_device * dev = v3_allocate_device(name, &dev_ops, state);
 
 
     if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", "OS_DEBUG");
+       PrintError("Could not attach device %s\n", name);
        return -1;
     }
 
index 13c5524..0bb7698 100644 (file)
@@ -100,17 +100,18 @@ static struct v3_device_ops dev_ops = {
 
 
 
-static int net_init(struct guest_info * vm, void * cfg_data) {
+static int net_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
     struct nic_state * state = NULL;
+    char * name = v3_cfg_val(cfg, "name");
 
     state = (struct nic_state *)V3_Malloc(sizeof(struct nic_state));
 
     PrintDebug("Creating VMNet Device\n");
 
-    struct vm_device * dev = v3_allocate_device("VMNET", &dev_ops, state);
+    struct vm_device * dev = v3_allocate_device(name, &dev_ops, state);
 
     if (v3_attach_device(vm, dev) == -1) {
-        PrintError("Could not attach device %s\n", "VMNET");
+        PrintError("Could not attach device %s\n", name);
         return -1;
     }
 
index 49ed5d5..06ccb6b 100644 (file)
@@ -7,15 +7,15 @@
  * and the University of New Mexico.  You can find out more at 
  * http://www.v3vee.org
  *
+ * Copyright (c) 2009, Jack Lange <jarusl@cs.northwestern.edu>
  * Copyright (c) 2009, Lei Xia <lxia@northwestern.edu>
  * Copyright (c) 2009, Chang Seok Bae <jhuell@gmail.com>
- * Copyright (c) 2009, Jack Lange <jarusl@cs.northwestern.edu>
  * Copyright (c) 2009, The V3VEE Project <http://www.v3vee.org> 
  * All rights reserved.
  *
- * Author:  Lei Xia <lxia@northwestern.edu>
+ * Author:  Jack Lange <jarusl@cs.northwestern.edu>
+ *          Lei Xia <lxia@northwestern.edu>
  *          Chang Seok Bae <jhuell@gmail.com>
- *          Jack Lange <jarusl@cs.northwestern.edu>
  *
  * This is free software.  You are permitted to use,
  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
 #include <palacios/vmm_io.h>
 #include <palacios/vmm_intr.h>
 #include <palacios/vmm_rbtree.h>
+#include <palacios/vmm_dev_mgr.h>
 
 #include <devices/pci.h>
 #include <devices/pci_types.h>
 
+
+
 #ifndef CONFIG_DEBUG_PCI
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
@@ -391,7 +394,7 @@ static inline int is_cfg_reg_writable(uchar_t header_type, int reg_num) {
 }
 
 
-static int bar_update(struct pci_device * pci, int bar_num, uint32_t new_val) {
+static int bar_update(struct guest_info * info, struct pci_device * pci, int bar_num, uint32_t new_val) {
     struct v3_pci_bar * bar = &(pci->bar[bar_num]);
 
     PrintDebug("Updating BAR Register  (Dev=%s) (bar=%d) (old_val=0x%x) (new_val=0x%x)\n", 
@@ -415,15 +418,15 @@ static int bar_update(struct pci_device * pci, int bar_num, uint32_t new_val) {
                PrintDebug("Rehooking PCI IO port (old port=%u) (new port=%u)\n",  
                           PCI_IO_BASE(bar->val) + i, PCI_IO_BASE(new_val) + i);
 
-               v3_unhook_io_port(pci->vm_dev->vm, PCI_IO_BASE(bar->val) + i);
+               v3_unhook_io_port(info, PCI_IO_BASE(bar->val) + i);
 
-               if (v3_hook_io_port(pci->vm_dev->vm, PCI_IO_BASE(new_val) + i, 
+               if (v3_hook_io_port(info, PCI_IO_BASE(new_val) + i, 
                                    bar->io_read, bar->io_write, 
                                    bar->private_data) == -1) {
 
                    PrintError("Could not hook PCI IO port (old port=%u) (new port=%u)\n",  
                               PCI_IO_BASE(bar->val) + i, PCI_IO_BASE(new_val) + i);
-                   v3_print_io_map(pci->vm_dev->vm);
+                   v3_print_io_map(info);
                    return -1;
                }
            }
@@ -433,12 +436,12 @@ static int bar_update(struct pci_device * pci, int bar_num, uint32_t new_val) {
            break;
        }
        case PCI_BAR_MEM32: {
-           v3_unhook_mem(pci->vm_dev->vm, (addr_t)(bar->val));
+           v3_unhook_mem(info, (addr_t)(bar->val));
            
            if (bar->mem_read) {
-               v3_hook_full_mem(pci->vm_dev->vm, PCI_MEM32_BASE(new_val), 
+               v3_hook_full_mem(info, PCI_MEM32_BASE(new_val), 
                                 PCI_MEM32_BASE(new_val) + (bar->num_pages * PAGE_SIZE_4KB),
-                                bar->mem_read, bar->mem_write, pci->vm_dev);
+                                bar->mem_read, bar->mem_write, pci->priv_data);
            } else {
                PrintError("Write hooks not supported for PCI\n");
                return -1;
@@ -570,7 +573,7 @@ static int data_port_write(ushort_t port, void * src, uint_t length, struct vm_d
                    // check special flags....
 
                    // bar_update
-                   if (bar_update(pci_dev, i, *(uint32_t *)(pci_dev->config_space + bar_offset)) == -1) {
+                   if (bar_update(vmdev->vm, pci_dev, i, *(uint32_t *)(pci_dev->config_space + bar_offset)) == -1) {
                        PrintError("PCI Device %s: Bar update Error Bar=%d\n", pci_dev->name, i);
                        return -1;
                    }
@@ -648,16 +651,17 @@ static struct v3_device_ops dev_ops = {
 
 
 
-static int pci_init(struct guest_info * vm, void * cfg_data) {
+static int pci_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
     struct pci_internal * pci_state = V3_Malloc(sizeof(struct pci_internal));
     int i = 0;
+    char * name = v3_cfg_val(cfg, "name");
     
     PrintDebug("PCI internal at %p\n",(void *)pci_state);
     
-    struct vm_device * dev = v3_allocate_device("PCI", &dev_ops, pci_state);
+    struct vm_device * dev = v3_allocate_device(name, &dev_ops, pci_state);
     
     if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", "PCI");
+       PrintError("Could not attach device %s\n", name);
        return -1;
     }
 
@@ -681,7 +685,7 @@ static int pci_init(struct guest_info * vm, void * cfg_data) {
 device_register("PCI", pci_init)
 
 
-static inline int init_bars(struct pci_device * pci_dev) {
+static inline int init_bars(struct guest_info * info, struct pci_device * pci_dev) {
     int i = 0;
 
     for (i = 0; i < 6; i++) {
@@ -702,7 +706,7 @@ static inline int init_bars(struct pci_device * pci_dev) {
            for (j = 0; j < pci_dev->bar[i].num_ports; j++) {
                // hook IO
                if (pci_dev->bar[i].default_base_port != 0xffff) {
-                   if (v3_hook_io_port(pci_dev->vm_dev->vm, pci_dev->bar[i].default_base_port + j,
+                   if (v3_hook_io_port(info, pci_dev->bar[i].default_base_port + j,
                                        pci_dev->bar[i].io_read, pci_dev->bar[i].io_write, 
                                        pci_dev->bar[i].private_data) == -1) {
                        PrintError("Could not hook default io port %x\n", pci_dev->bar[i].default_base_port + j);
@@ -726,9 +730,9 @@ static inline int init_bars(struct pci_device * pci_dev) {
            // hook memory
            if (pci_dev->bar[i].mem_read) {
                // full hook
-               v3_hook_full_mem(pci_dev->vm_dev->vm, pci_dev->bar[i].default_base_addr,
+               v3_hook_full_mem(info, pci_dev->bar[i].default_base_addr,
                                 pci_dev->bar[i].default_base_addr + (pci_dev->bar[i].num_pages * PAGE_SIZE_4KB),
-                                pci_dev->bar[i].mem_read, pci_dev->bar[i].mem_write, pci_dev->vm_dev);
+                                pci_dev->bar[i].mem_read, pci_dev->bar[i].mem_write, pci_dev->priv_data);
            } else if (pci_dev->bar[i].mem_write) {
                // write hook
                PrintError("Write hooks not supported for PCI devices\n");
@@ -807,7 +811,7 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci,
                                           int (*config_update)(uint_t reg_num, void * src, uint_t length, void * priv_data),
                                           int (*cmd_update)(struct pci_device *pci_dev, uchar_t io_enabled, uchar_t mem_enabled),
                                           int (*ext_rom_update)(struct pci_device * pci_dev),
-                                          struct vm_device * dev, void * priv_data) {
+                                          void * priv_data) {
 
     struct pci_internal * pci_state = (struct pci_internal *)pci->private_data;
     struct pci_bus * bus = &(pci_state->bus_list[bus_num]);
@@ -867,7 +871,6 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci,
     pci_dev->fn_num = fn_num;
 
     strncpy(pci_dev->name, name, sizeof(pci_dev->name));
-    pci_dev->vm_dev = dev;
     pci_dev->priv_data = priv_data;
 
     // register update callbacks
@@ -911,7 +914,7 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci,
        }
     }
 
-    if (init_bars(pci_dev) == -1) {
+    if (init_bars(pci->vm, pci_dev) == -1) {
        PrintError("could not initialize bar registers\n");
        return NULL;
     }
@@ -936,7 +939,6 @@ struct pci_device * v3_pci_register_passthrough_device(struct vm_device * pci,
                                                       const char * name,
                                                       int (*config_write)(uint_t reg_num, void * src, uint_t length, void * private_data),
                                                       int (*config_read)(uint_t reg_num, void * dst, uint_t length, void * private_data),
-                                                      struct vm_device * dev,
                                                       void * private_data) {
 
     struct pci_internal * pci_state = (struct pci_internal *)pci->private_data;
@@ -979,7 +981,6 @@ struct pci_device * v3_pci_register_passthrough_device(struct vm_device * pci,
     pci_dev->fn_num = fn_num;
 
     strncpy(pci_dev->name, name, sizeof(pci_dev->name));
-    pci_dev->vm_dev = dev;
     pci_dev->priv_data = private_data;
 
     // register update callbacks
index fd3f4ee..ce4b334 100644 (file)
 #include <palacios/vmm_dev_mgr.h>
 #include <palacios/vmm_sprintf.h>
 #include <palacios/vmm_lowlevel.h>
+#include <palacios/vm_guest.h> // must include this to avoid dependency issue
 #include <palacios/vmm_sym_iface.h>
 
 #include <devices/pci.h>
 #include <devices/pci_types.h>
-#include <devices/pci_passthrough.h>
 
 
 // Hardcoded... Are these standard??
@@ -506,7 +506,7 @@ static int setup_virt_pci_dev(struct guest_info * info, struct vm_device * dev)
                                     bus_num, -1, 0, 
                                     state->name, bars,
                                     pt_config_update, NULL, NULL, 
-                                    dev, dev);
+                                    dev);
     
     // This will overwrite the bar registers.. but that should be ok.
     memcpy(pci_dev->config_space, (uint8_t *)&(state->real_hdr), sizeof(struct pci_config_header));
@@ -545,12 +545,11 @@ static int irq_handler(struct guest_info * info, struct v3_interrupt * intr, voi
 
 
 
-static int passthrough_init(struct guest_info * info, void * cfg_data) {
-    struct pci_passthrough_cfg * cfg = (struct pci_passthrough_cfg *)cfg_data;
+static int passthrough_init(struct guest_info * info, v3_cfg_tree_t * cfg) {
     struct pt_dev_state * state = V3_Malloc(sizeof(struct pt_dev_state));
     struct vm_device * dev = NULL;
-    struct vm_device * pci = v3_find_dev(info, cfg->pci_bus_name);
-    
+    struct vm_device * pci = v3_find_dev(info, v3_cfg_val(cfg, "bus"));
+    char * name = v3_cfg_val(cfg, "name");    
 
     memset(state, 0, sizeof(struct pt_dev_state));
 
@@ -560,28 +559,30 @@ static int passthrough_init(struct guest_info * info, void * cfg_data) {
     }
     
     state->pci_bus = pci;
-    strncpy(state->name, cfg->name, 32);
-
-
+    strncpy(state->name, name, 32);
 
 
-    dev = v3_allocate_device("PCI_PASSTHROUGH", &dev_ops, state);
+    dev = v3_allocate_device(name, &dev_ops, state);
 
     if (v3_attach_device(info, dev) == -1) {
-       PrintError("Could not attach device %s\n", "PCI_PASSTHROUGH");
+       PrintError("Could not attach device %s\n", name);
        return -1;
     }
 
 
-    if (find_real_pci_dev(cfg->vendor_id, cfg->device_id, state) == -1) {
-       PrintError("Could not find PCI Device %x:%x\n", cfg->vendor_id, cfg->device_id);
+    if (find_real_pci_dev(atox(v3_cfg_val(cfg, "vendor_id")), 
+                         atox(v3_cfg_val(cfg, "device_id")), 
+                         state) == -1) {
+       PrintError("Could not find PCI Device %s:%s\n", 
+                  v3_cfg_val(cfg, "vendor_id"), 
+                  v3_cfg_val(cfg, "device_id"));
        return 0;
     }
 
     setup_virt_pci_dev(info, dev);
 
-    v3_hook_irq(info, 59, irq_handler, dev);
-    v3_hook_irq(info, 64, irq_handler, dev);
+    v3_hook_irq(info, atoi(v3_cfg_val(cfg, "irq")), irq_handler, dev);
+    //    v3_hook_irq(info, 64, irq_handler, dev);
 
     return 0;
 }
index 44a00ed..377c845 100644 (file)
  
 
 #include <palacios/vmm.h>
+#include <palacios/vmm_dev_mgr.h>
+#include <palacios/vmm_intr.h>
+
 #include <devices/pci.h>
 #include <devices/southbridge.h>
 
+
 struct iort_reg {
     union {
        uint8_t value;
@@ -421,7 +425,7 @@ static int setup_pci(struct vm_device * dev) {
     pci_dev = v3_pci_register_device(piix3->pci_bus, PCI_MULTIFUNCTION, 
                                     bus_num, -1, 0, 
                                     "PIIX3", bars, 
-                                    NULL, NULL, NULL, dev, NULL);
+                                    NULL, NULL, NULL, dev);
     if (pci_dev == NULL) {
        PrintError("Could not register PCI Device for PIIX3\n");
        return -1;
@@ -441,10 +445,11 @@ static int setup_pci(struct vm_device * dev) {
     return 0;
 }
 
-static int piix3_init(struct guest_info * vm, void * cfg_data) {
+static int piix3_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
     struct v3_southbridge * piix3 = (struct v3_southbridge *)V3_Malloc(sizeof(struct v3_southbridge));
     struct vm_device * dev = NULL;
-    struct vm_device * pci = v3_find_dev(vm, (char *)cfg_data);
+    struct vm_device * pci = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
+    char * name = v3_cfg_val(cfg, "name");
 
     if (!pci) {
        PrintError("Could not find PCI device\n");
@@ -454,10 +459,10 @@ static int piix3_init(struct guest_info * vm, void * cfg_data) {
     piix3->pci_bus = pci;
     piix3->type = V3_SB_PIIX3;
     
-    dev = v3_allocate_device("PIIX3", &dev_ops, piix3);
+    dev = v3_allocate_device(name, &dev_ops, piix3);
 
     if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", "PIIX3");
+       PrintError("Could not attach device %s\n", name);
        return -1;
     }
 
diff --git a/palacios/src/devices/ram_cd.c b/palacios/src/devices/ram_cd.c
deleted file mode 100644 (file)
index 4a3baac..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/* 
- * This file is part of the Palacios Virtual Machine Monitor developed
- * by the V3VEE Project with funding from the United States National 
- * Science Foundation and the Department of Energy.  
- *
- * The V3VEE Project is a joint project between Northwestern University
- * and the University of New Mexico.  You can find out more at 
- * http://www.v3vee.org
- *
- * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
- * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
- * All rights reserved.
- *
- * Author: Jack Lange <jarusl@cs.northwestern.edu>
- *
- * This is free software.  You are permitted to use,
- * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
- */
-
-#include <palacios/vmm.h>
-#include <devices/ram_cd.h>
-#include <palacios/vmm_dev_mgr.h>
-#include <devices/ide.h>
-
-#ifndef CONFIG_DEBUG_IDE
-#undef PrintDebug
-#define PrintDebug(fmt, args...)
-#endif
-
-
-struct cd_state {
-    addr_t disk_image;
-    uint32_t capacity; // in bytes
-
-    struct vm_device * ide;
-
-    uint_t bus;
-    uint_t drive;
-};
-
-
-// CDs always read 2048 byte blocks... ?
-static int cd_read(uint8_t * buf, int block_count, uint64_t lba,  void * private_data) {
-    struct vm_device * cd_dev = (struct vm_device *)private_data;
-    struct cd_state * cd = (struct cd_state *)(cd_dev->private_data);
-    int offset = lba * ATAPI_BLOCK_SIZE;
-    int length = block_count * ATAPI_BLOCK_SIZE;
-
-    PrintDebug("Reading RAM CD at (LBA=%d) offset %d (length=%d)\n", (uint32_t)lba, offset, length);
-
-    memcpy(buf, (uint8_t *)(cd->disk_image + offset), length);
-
-    return 0;
-}
-
-
-static uint32_t cd_get_capacity(void * private_data) {
-    struct vm_device * cd_dev = (struct vm_device *)private_data;
-    struct cd_state * cd = (struct cd_state *)(cd_dev->private_data);
-    PrintDebug("Querying RAM CD capacity (bytes=%d) (ret = %d)\n", 
-              cd->capacity, cd->capacity  / ATAPI_BLOCK_SIZE);
-    return cd->capacity / ATAPI_BLOCK_SIZE;
-}
-
-static struct v3_cd_ops cd_ops = {
-    .read = cd_read, 
-    .get_capacity = cd_get_capacity,
-};
-
-
-
-
-static int cd_free(struct vm_device * dev) {
-    return 0;
-}
-
-static struct v3_device_ops dev_ops = {
-    .free = cd_free,
-    .reset = NULL,
-    .start = NULL,
-    .stop = NULL,
-};
-
-
-static int cd_init(struct guest_info * vm, void * cfg_data) {
-    struct cd_state * cd = NULL;
-    struct ram_cd_cfg * cfg = (struct ram_cd_cfg *)cfg_data;
-
-    if (cfg->size % ATAPI_BLOCK_SIZE) {
-       PrintError("CD image must be an integral of block size (ATAPI_BLOCK_SIZE=%d)\n", ATAPI_BLOCK_SIZE);
-       return -1;
-    }
-
-    cd = (struct cd_state *)V3_Malloc(sizeof(struct cd_state));
-
-    PrintDebug("Registering Ram CD at %p (size=%d)\n", (void *)cfg->ramdisk, cfg->size);
-
-  
-    cd->disk_image = cfg->ramdisk;
-    cd->capacity = cfg->size;
-
-    cd->ide = v3_find_dev(vm, cfg->ide);
-
-    if (cd->ide == 0) {
-       PrintError("Could not find backend %s\n", cfg->ide);
-       return -1;
-    }
-
-    cd->bus = cfg->bus;
-    cd->drive = cfg->drive;
-       
-    struct vm_device * dev = v3_allocate_device("RAM-CD", &dev_ops, cd);
-
-    if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", "RAM-CD");
-       return -1;
-    }
-
-
-    if (v3_ide_register_cdrom(cd->ide, cd->bus, cd->drive, "RAM-CD", &cd_ops, dev) == -1) {
-       return -1;
-    }
-    
-    return 0;
-}
-
-
-device_register("RAM-CD", cd_init)
diff --git a/palacios/src/devices/ram_hd.c b/palacios/src/devices/ram_hd.c
deleted file mode 100644 (file)
index c90e5be..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/* 
- * This file is part of the Palacios Virtual Machine Monitor developed
- * by the V3VEE Project with funding from the United States National 
- * Science Foundation and the Department of Energy.  
- *
- * The V3VEE Project is a joint project between Northwestern University
- * and the University of New Mexico.  You can find out more at 
- * http://www.v3vee.org
- *
- * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
- * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
- * All rights reserved.
- *
- * Author: Jack Lange <jarusl@cs.northwestern.edu>
- *
- * This is free software.  You are permitted to use,
- * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
- */
-
-#include <palacios/vmm.h>
-#include <devices/ram_hd.h>
-#include <devices/ide.h>
-
-
-
-#ifndef CONFIG_DEBUG_IDE
-#undef PrintDebug
-#define PrintDebug(fmt, args...)
-#endif
-
-struct hd_state {
-    addr_t disk_image;
-    uint32_t capacity; // in bytes
-
-    struct vm_device * ide;
-
-    uint_t bus;
-    uint_t drive;
-};
-
-
-// HDs always read 512 byte blocks... ?
-static int hd_read(uint8_t * buf, int sector_count, uint64_t lba,  void * private_data) {
-    struct vm_device * hd_dev = (struct vm_device *)private_data;
-    struct hd_state * hd = (struct hd_state *)(hd_dev->private_data);
-    int offset = lba * HD_SECTOR_SIZE;
-    int length = sector_count * HD_SECTOR_SIZE;
-
-    //    PrintDebug("Reading RAM HD at (LBA=%d) offset %d (length=%d)\n", (uint32_t)lba, offset, length);
-
-    memcpy(buf, (uint8_t *)(hd->disk_image + offset), length);
-
-    return 0;
-}
-
-
-static int hd_write(uint8_t * buf, int sector_count, uint64_t lba, void * private_data) {
-    struct vm_device * hd_dev = (struct vm_device *)private_data;
-    struct hd_state * hd = (struct hd_state *)(hd_dev->private_data);
-    int offset = lba * HD_SECTOR_SIZE;
-    int length = sector_count * HD_SECTOR_SIZE;
-
-    memcpy((uint8_t *)(hd->disk_image + offset), buf, length);
-
-    return 0;
-}
-
-
-static uint64_t hd_get_capacity(void * private_data) {
-    struct vm_device * hd_dev = (struct vm_device *)private_data;
-    struct hd_state * hd = (struct hd_state *)(hd_dev->private_data);
-    PrintDebug("Querying RAM HD capacity (bytes=%d) (ret = %d)\n", 
-              hd->capacity, hd->capacity  / HD_SECTOR_SIZE);
-    return hd->capacity / HD_SECTOR_SIZE;
-}
-
-static struct v3_hd_ops hd_ops = {
-    .read = hd_read, 
-    .write = hd_write,
-    .get_capacity = hd_get_capacity,
-};
-
-
-
-
-static int hd_free(struct vm_device * dev) {
-    return 0;
-}
-
-static struct v3_device_ops dev_ops = {
-    .free = hd_free,
-    .reset = NULL,
-    .start = NULL,
-    .stop = NULL,
-};
-
-
-
-
-static int hd_init(struct guest_info * vm, void * cfg_data) {
-    struct hd_state * hd = NULL;
-    struct ram_hd_cfg * cfg = (struct ram_hd_cfg *)cfg_data;
-
-    if (cfg->size % HD_SECTOR_SIZE) {
-       PrintError("HD image must be an integral of sector size (HD_SECTOR_SIZE=%d)\n", HD_SECTOR_SIZE);
-       return -1;
-    }
-
-    hd = (struct hd_state *)V3_Malloc(sizeof(struct hd_state));
-
-    PrintDebug("Registering Ram HDD at %p (size=%d)\n", (void *)cfg->ramdisk, cfg->size);
-
-    hd->disk_image = cfg->ramdisk;
-    hd->capacity = cfg->size;
-
-    hd->ide = v3_find_dev(vm, cfg->ide);
-
-    if (hd->ide == 0) {
-       PrintError("Could not find backend %s\n", cfg->ide);
-       return -1;
-    }
-
-    hd->bus = cfg->bus;
-    hd->drive = cfg->drive;
-       
-    struct vm_device * dev = v3_allocate_device("RAM-HD", &dev_ops, hd);
-
-    if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", "RAM-HD");
-       return -1;
-    }
-
-
-    if (v3_ide_register_harddisk(hd->ide, hd->bus, hd->drive, "RAM-HD", &hd_ops, dev) == -1) {
-       return -1;
-    }
-    
-    return 0;
-}
-
-
-device_register("RAM-HD", hd_init)
diff --git a/palacios/src/devices/ramdisk.c b/palacios/src/devices/ramdisk.c
new file mode 100644 (file)
index 0000000..9a2e716
--- /dev/null
@@ -0,0 +1,137 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <palacios/vmm.h>
+#include <palacios/vmm_dev_mgr.h>
+
+
+#ifndef CONFIG_DEBUG_RAMDISK
+#undef PrintDebug
+#define PrintDebug(fmt, args...)
+#endif
+
+struct disk_state {
+    uint8_t * disk_image;
+    uint32_t capacity; // in bytes
+};
+
+
+static int read(uint8_t * buf, uint64_t lba, uint64_t num_bytes, void * private_data) {
+    struct disk_state * disk = (struct disk_state *)private_data;
+
+    PrintDebug("Reading %d bytes from %p to %p\n", (uint32_t)num_bytes, (uint8_t *)(disk->disk_image + lba), buf);
+
+    memcpy(buf, (uint8_t *)(disk->disk_image + lba), num_bytes);
+
+    return 0;
+}
+
+
+static int write(uint8_t * buf, uint64_t lba, uint64_t num_bytes, void * private_data) {
+    struct disk_state * disk = (struct disk_state *)private_data;
+
+    PrintDebug("Writing %d bytes from %p to %p\n", (uint32_t)num_bytes,  buf, (uint8_t *)(disk->disk_image + lba));
+
+    memcpy((uint8_t *)(disk->disk_image + lba), buf, num_bytes);
+
+    return 0;
+}
+
+
+static uint64_t get_capacity(void * private_data) {
+    struct disk_state * disk = (struct disk_state *)private_data;
+
+    PrintDebug("Querying RAMDISK capacity %d\n", 
+              (uint32_t)(disk->capacity));
+
+    return disk->capacity;
+}
+
+static struct v3_dev_blk_ops blk_ops = {
+    .read = read, 
+    .write = write,
+    .get_capacity = get_capacity,
+};
+
+
+
+
+static int disk_free(struct vm_device * dev) {
+    return 0;
+}
+
+static struct v3_device_ops dev_ops = {
+    .free = disk_free,
+    .reset = NULL,
+    .start = NULL,
+    .stop = NULL,
+};
+
+
+
+
+static int disk_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
+    struct disk_state * disk = NULL;
+    struct v3_cfg_file * file = NULL;
+    char * name = v3_cfg_val(cfg, "name");
+    char * filename = v3_cfg_val(cfg, "file");
+
+    v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend");
+
+    disk = (struct disk_state *)V3_Malloc(sizeof(struct disk_state));
+    memset(disk, 0, sizeof(struct disk_state));
+
+
+    if (!filename) {
+       PrintError("Missing filename (%s) for %s\n", filename, name);
+       return -1;
+    }
+
+    file = v3_cfg_get_file(vm, filename);
+
+    if (!file) {
+       PrintError("Invalid ramdisk file: %s\n", filename);
+       return -1;
+    }
+
+    disk->disk_image = file->data;
+    disk->capacity = file->size;
+    PrintDebug("Registering RAMDISK at %p (size=%d)\n", 
+              (void *)file->data, (uint32_t)file->size);
+
+    struct vm_device * dev = v3_allocate_device(name, &dev_ops, disk);
+
+    if (v3_attach_device(vm, dev) == -1) {
+       PrintError("Could not attach device %s\n", name);
+       return -1;
+    }
+
+    if (v3_dev_connect_blk(vm, v3_cfg_val(frontend_cfg, "tag"), 
+                          &blk_ops, frontend_cfg, disk) == -1) {
+       PrintError("Could not connect %s to frontend %s\n", 
+                  name, v3_cfg_val(frontend_cfg, "tag"));
+       return -1;
+    }
+    
+
+    return 0;
+}
+
+
+device_register("RAMDISK", disk_init)
index d6740c4..dad0419 100644 (file)
 
 #include <palacios/vmm.h>
 #include <palacios/vmm_dev_mgr.h>
-#include <devices/lnx_virtio_blk.h>
 #include <palacios/vmm_sym_swap.h>
 
-#define SWAP_CAPACITY (150 * 1024 * 1024)
 
 #ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
 #include <palacios/vmm_telemetry.h>
@@ -55,8 +53,6 @@ union swap_header {
 struct swap_state {
     int active;
 
-    struct vm_device * blk_dev;
-
     uint_t swapped_pages;
     uint_t unswapped_pages;
 
@@ -134,7 +130,7 @@ static uint64_t swap_get_capacity(void * private_data) {
 
     PrintDebug("SymSwap: Getting Capacity %d\n", (uint32_t)(swap->capacity));
 
-    return swap->capacity / HD_SECTOR_SIZE;
+    return swap->capacity;
 }
 
 
@@ -144,11 +140,11 @@ static struct v3_swap_ops swap_ops = {
 
 
 
-static int swap_read(uint8_t * buf, int sector_count, uint64_t lba,  void * private_data) {
+static int swap_read(uint8_t * buf, uint64_t lba, uint64_t num_bytes, void * private_data) {
     struct vm_device * dev = (struct vm_device *)private_data;
     struct swap_state * swap = (struct swap_state *)(dev->private_data);
-    uint32_t offset = lba * HD_SECTOR_SIZE;
-    uint32_t length = sector_count * HD_SECTOR_SIZE;
+    uint32_t offset = lba;
+    uint32_t length = num_bytes;
 
   
     /*  
@@ -184,11 +180,11 @@ static int swap_read(uint8_t * buf, int sector_count, uint64_t lba,  void * priv
 
 
 
-static int swap_write(uint8_t * buf, int sector_count, uint64_t lba, void * private_data) {
+static int swap_write(uint8_t * buf,  uint64_t lba, uint64_t num_bytes, void * private_data) {
     struct vm_device * dev = (struct vm_device *)private_data;
     struct swap_state * swap = (struct swap_state *)(dev->private_data);
-    uint32_t offset = lba * HD_SECTOR_SIZE;
-    uint32_t length = sector_count * HD_SECTOR_SIZE;
+    uint32_t offset = lba;
+    uint32_t length = num_bytes;
 
     /*
       PrintDebug("SymSwap: Writing %d bytes to %p from %p\n", length, 
@@ -242,7 +238,7 @@ static int swap_free(struct vm_device * dev) {
 }
 
 
-static struct v3_hd_ops hd_ops = {
+static struct v3_dev_blk_ops blk_ops = {
     .read = swap_read, 
     .write = swap_write, 
     .get_capacity = swap_get_capacity,
@@ -274,26 +270,22 @@ static void telemetry_cb(struct guest_info * info, void * private_data, char * h
 
 
 
-static int swap_init(struct guest_info * vm, void * cfg_data) {
+static int swap_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
     struct swap_state * swap = NULL;
-    struct vm_device * virtio_blk = v3_find_dev(vm, (char *)cfg_data);
+    v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend");
+    uint32_t capacity = atoi(v3_cfg_val(cfg, "size")) * 1024 * 1024;
+    char * name = v3_cfg_val(cfg, "name");
 
-    if (!virtio_blk) {
-       PrintError("could not find Virtio backend\n");
+    if (!frontend_cfg) {
+       PrintError("Initializing sym swap without a frontend device\n");
        return -1;
     }
 
     PrintDebug("Creating Swap Device\n");
 
-    if (virtio_blk == NULL) {
-       PrintError("Swap device requires a virtio block device\n");
-       return -1;
-    }
-
-    swap = (struct swap_state *)V3_Malloc(sizeof(struct swap_state) + ((SWAP_CAPACITY / 4096) / 8));
+    swap = (struct swap_state *)V3_Malloc(sizeof(struct swap_state) + ((capacity / 4096) / 8));
 
-    swap->blk_dev = virtio_blk;
-    swap->capacity = SWAP_CAPACITY;
+    swap->capacity = capacity;
 
     swap->swapped_pages = 0;
     swap->unswapped_pages = 0;
@@ -301,22 +293,25 @@ static int swap_init(struct guest_info * vm, void * cfg_data) {
     swap->active = 0;
     swap->hdr = (union swap_header *)swap;
 
-
     swap->swap_base_addr = (addr_t)V3_AllocPages(swap->capacity / 4096);
     swap->swap_space = (uint8_t *)V3_VAddr((void *)(swap->swap_base_addr));
-    memset(swap->swap_space, 0, SWAP_CAPACITY);
+    memset(swap->swap_space, 0, swap->capacity);
 
-    memset(swap->usage_map, 0, ((SWAP_CAPACITY / 4096) / 8));
+    memset(swap->usage_map, 0, ((swap->capacity / 4096) / 8));
 
-    struct vm_device * dev = v3_allocate_device("SYM_SWAP", &dev_ops, swap);
+    struct vm_device * dev = v3_allocate_device(name, &dev_ops, swap);
 
     if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", "SYM_SWAP");
+       PrintError("Could not attach device %s\n", name);
        return -1;
     }
 
-
-    v3_virtio_register_harddisk(virtio_blk, &hd_ops, dev);
+    if (v3_dev_connect_blk(vm, v3_cfg_val(frontend_cfg, "tag"), 
+                          &blk_ops, frontend_cfg, swap) == -1) {
+       PrintError("Could not connect %s to frontend %s\n", 
+                  name, v3_cfg_val(frontend_cfg, "tag"));
+       return -1;
+    }
 
 #ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
     if (vm->enable_telemetry) {
index 4abe5a0..30e07d1 100644 (file)
@@ -519,23 +519,24 @@ static int cons_server(void * arg) {
 }
 
 
-static int cons_init(struct guest_info * vm, void * cfg_data) {
-    struct telnet_cons_cfg * cfg = (struct telnet_cons_cfg *)cfg_data;
+static int cons_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
     struct cons_state * state = (struct cons_state *)V3_Malloc(sizeof(struct cons_state));
-    struct vm_device * frontend = v3_find_dev(vm, cfg->frontend);
+    v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend");
+    struct vm_device * frontend = v3_find_dev(vm, v3_cfg_val(frontend_cfg, "id"));
+    char * name = v3_cfg_val(cfg, "name");
 
 
     state->server_fd = 0;
     state->client_fd = 0;
     state->frontend_dev = frontend;
-    state->port = cfg->port;
+    state->port = atoi(v3_cfg_val(cfg, "port"));
     v3_lock_init(&(state->cons_lock));
 
 
-    struct vm_device * dev = v3_allocate_device("TELNET_CONS", &dev_ops, state);
+    struct vm_device * dev = v3_allocate_device(name, &dev_ops, state);
 
     if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", "TELNET_CONS");
+       PrintError("Could not attach device %s\n", name);
        return -1;
     }
 
diff --git a/palacios/src/devices/tmpdisk.c b/palacios/src/devices/tmpdisk.c
new file mode 100644 (file)
index 0000000..a40aa55
--- /dev/null
@@ -0,0 +1,126 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <palacios/vmm.h>
+#include <palacios/vmm_dev_mgr.h>
+
+
+struct blk_state {
+    uint64_t capacity;
+    uint8_t * blk_space;
+    addr_t blk_base_addr;
+};
+
+
+
+static uint64_t blk_get_capacity(void * private_data) {
+    struct blk_state * blk = (struct blk_state *)private_data;
+
+    PrintDebug("SymBlk: Getting Capacity %d\n", (uint32_t)(blk->capacity));
+
+    return blk->capacity;
+}
+
+
+
+static int blk_read(uint8_t * buf, uint64_t lba, uint64_t num_bytes, void * private_data) {
+    struct blk_state * blk = (struct blk_state *)private_data;
+
+    memcpy(buf, blk->blk_space + lba, num_bytes);
+
+    return 0;
+}
+
+
+
+
+static int blk_write(uint8_t * buf,  uint64_t lba, uint64_t num_bytes, void * private_data) {
+    struct blk_state * blk = (struct blk_state *)private_data;
+
+    memcpy(blk->blk_space + lba, buf, num_bytes);
+
+    return 0;
+}
+
+
+static int blk_free(struct vm_device * dev) {
+    return -1;
+}
+
+
+static struct v3_dev_blk_ops blk_ops = {
+    .read = blk_read, 
+    .write = blk_write, 
+    .get_capacity = blk_get_capacity,
+};
+
+
+
+static struct v3_device_ops dev_ops = {
+    .free = blk_free,
+    .reset = NULL,
+    .start = NULL,
+    .stop = NULL,
+};
+
+
+
+
+static int blk_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
+    struct blk_state * blk = NULL;
+    v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend");
+    char * name = v3_cfg_val(cfg, "name");
+    uint64_t capacity = atoi(v3_cfg_val(cfg, "size"));
+    
+    if (!frontend_cfg) {
+       PrintError("Frontend Configuration not present\n");
+       return -1;
+    }
+
+    PrintDebug("Creating Blk Device\n");
+
+
+    blk = (struct blk_state *)V3_Malloc(sizeof(struct blk_state) + ((capacity / 4096) / 8));
+
+    blk->capacity = capacity;
+
+    blk->blk_base_addr = (addr_t)V3_AllocPages(capacity / 4096);
+    blk->blk_space = (uint8_t *)V3_VAddr((void *)(blk->blk_base_addr));
+    memset(blk->blk_space, 0, capacity);
+
+
+    struct vm_device * dev = v3_allocate_device(name, &dev_ops, blk);
+
+    if (v3_attach_device(vm, dev) == -1) {
+       PrintError("Could not attach device %s\n", name);
+       return -1;
+    }
+
+    if (v3_dev_connect_blk(vm, v3_cfg_val(frontend_cfg, "tag"), 
+                          &blk_ops, frontend_cfg, blk) == -1) {
+       PrintError("Could not connect %s to frontend %s\n", 
+                  name, v3_cfg_val(frontend_cfg, "tag"));
+       return -1;
+    }
+
+
+    return 0;
+}
+
+device_register("TMPDISK", blk_init)
index 7dacc0f..c669cd0 100644 (file)
@@ -31,7 +31,7 @@ obj-y := \
        vmm_xed.o \
        vmm_binaries.o \
        vmm_cpuid.o \
-
+       vmm_xml.o 
 
 obj-$(CONFIG_SVM) +=    svm.o \
                        svm_io.o \
index ba7f5b3..09fe744 100644 (file)
@@ -39,7 +39,6 @@
 #include <palacios/vmm_direct_paging.h>
 
 #include <palacios/vmm_ctrl_regs.h>
-#include <palacios/vmm_config.h>
 #include <palacios/svm_io.h>
 
 #include <palacios/vmm_sprintf.h>
@@ -267,18 +266,18 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * vm_info) {
 }
 
 
-static int init_svm_guest(struct guest_info * info, struct v3_vm_config * config_ptr) {
-
-
-    v3_pre_config_guest(info, config_ptr);
+int v3_init_svm_vmcb(struct guest_info * info, v3_vm_class_t vm_class) {
 
     PrintDebug("Allocating VMCB\n");
     info->vmm_data = (void*)Allocate_VMCB();
-
-    PrintDebug("Initializing VMCB (addr=%p)\n", (void *)info->vmm_data);
-    Init_VMCB_BIOS((vmcb_t*)(info->vmm_data), info);
-
-    v3_post_config_guest(info, config_ptr);
+    
+    if (vm_class == V3_PC_VM) {
+       PrintDebug("Initializing VMCB (addr=%p)\n", (void *)info->vmm_data);
+       Init_VMCB_BIOS((vmcb_t*)(info->vmm_data), info);
+    } else {
+       PrintError("Invalid VM class\n");
+       return -1;
+    }
 
     return 0;
 }
@@ -530,7 +529,7 @@ int v3_svm_enter(struct guest_info * info) {
 }
 
 
-static int start_svm_guest(struct guest_info *info) {
+int v3_start_svm_guest(struct guest_info *info) {
     //    vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t*)(info->vmm_data));
     //  vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
 
@@ -690,15 +689,6 @@ void v3_init_svm_cpu(int cpu_id) {
 }
 
 
-void v3_init_svm_hooks(struct v3_ctrl_ops * vmm_ops) {
-
-    // Setup the SVM specific vmm operations
-    vmm_ops->init_guest = &init_svm_guest;
-    vmm_ops->start_guest = &start_svm_guest;
-    vmm_ops->has_nested_paging = &has_svm_nested_paging;
-
-    return;
-}
 
 
 
index 82614f1..dabe82d 100644 (file)
@@ -21,7 +21,7 @@
 #include <palacios/vmm_msr.h>
 #include <palacios/vmm_sprintf.h>
 #include <palacios/vmm_list.h>
-
+#include <palacios/vm_guest.h>
 
 #define PENTIUM_MSRS_START            0x00000000
 #define PENTIUM_MSRS_END              0x00001fff
index 1571c48..0a53a7f 100644 (file)
@@ -38,6 +38,9 @@ struct v3_os_hooks * os_hooks = NULL;
 
 
 
+
+
+
 static struct guest_info * allocate_guest() {
     void * info = V3_Malloc(sizeof(struct guest_info));
     memset(info, 0, sizeof(struct guest_info));
@@ -45,24 +48,14 @@ static struct guest_info * allocate_guest() {
 }
 
 
-struct vmm_init_arg {
-    int cpu_id;
-    struct v3_ctrl_ops * vmm_ops;
-};
-
 static void init_cpu(void * arg) {
-    struct vmm_init_arg * vmm_arg = (struct vmm_init_arg *)arg;
-    int cpu_id = vmm_arg->cpu_id;
-    struct v3_ctrl_ops * vmm_ops = vmm_arg->vmm_ops;
+    uint32_t cpu_id = (uint32_t)(addr_t)arg;
 
 #ifdef CONFIG_SVM
     if (v3_is_svm_capable()) {
         PrintDebug("Machine is SVM Capable\n");
         v3_init_svm_cpu(cpu_id);
        
-       if (cpu_id == 0) {
-           v3_init_svm_hooks(vmm_ops);
-       }
     } else 
 #endif
 #ifdef CONFIG_VMX
@@ -70,9 +63,6 @@ static void init_cpu(void * arg) {
        PrintDebug("Machine is VMX Capable\n");
        v3_init_vmx_cpu(cpu_id);
 
-       if (cpu_id == 0) {
-           v3_init_vmx_hooks(vmm_ops);
-       }       
     } else 
 #endif
     {
@@ -82,10 +72,10 @@ static void init_cpu(void * arg) {
 
 
 
-void Init_V3(struct v3_os_hooks * hooks, struct v3_ctrl_ops * vmm_ops, int num_cpus) {
+
+
+void Init_V3(struct v3_os_hooks * hooks, int num_cpus) {
     int i;
-    struct vmm_init_arg arg;
-    arg.vmm_ops = vmm_ops;    
 
     // Set global variables. 
     os_hooks = hooks;
@@ -97,27 +87,68 @@ void Init_V3(struct v3_os_hooks * hooks, struct v3_ctrl_ops * vmm_ops, int num_c
     // Register all the possible device types
     v3_init_devices();
 
-
 #ifdef INSTRUMENT_VMM
     v3_init_instrumentation();
 #endif
 
-    vmm_ops->allocate_guest = &allocate_guest;
-
-
     if ((hooks) && (hooks->call_on_cpu)) {
 
        for (i = 0; i < num_cpus; i++) {
-           arg.cpu_id = i;
 
            V3_Print("Initializing VMM extensions on cpu %d\n", i);
-           hooks->call_on_cpu(i, &init_cpu, &arg);
+           hooks->call_on_cpu(i, &init_cpu, (void *)(addr_t)i);
        }
     }
+}
+
+v3_cpu_arch_t v3_get_cpu_type(int cpu_id) {
+    return v3_cpu_types[cpu_id];
+}
 
 
+struct guest_info * v3_create_vm(void * cfg) {
+    struct guest_info * info = allocate_guest();
+    
+    if (!info) {
+       PrintError("Could not allocate Guest\n");
+       return NULL;
+    }
+
+    if (v3_config_guest(info, cfg) == -1) {
+       PrintError("Could not configure guest\n");
+       return NULL;
+    }
+
+    return info;
 }
 
+int v3_start_vm(struct guest_info * info, unsigned int cpu_mask) {
+    
+    info->cpu_id = v3_get_cpu_id();
+
+    V3_Print("V3 --  Starting VM\n");
+
+    switch (v3_cpu_types[info->cpu_id]) {
+#ifdef CONFIG_SVM
+       case V3_SVM_CPU:
+       case V3_SVM_REV3_CPU:
+           return v3_start_svm_guest(info);
+           break;
+#endif
+#if CONFIG_VMX && 0
+       case V3_VMX_CPU:
+       case V3_VMX_EPT_CPU:
+           return v3_start_vmx_guest(info);
+           break;
+#endif
+       default:
+           PrintError("Attemping to enter a guest on an invalid CPU\n");
+           return -1;
+    }
+
+
+    return 0;
+}
 
 
 #ifdef __V3_32BIT__
@@ -199,6 +230,21 @@ void v3_interrupt_cpu(struct guest_info * info, int logical_cpu) {
 
 
 
+unsigned int v3_get_cpu_id() {
+    extern struct v3_os_hooks * os_hooks;
+    unsigned int ret = (unsigned int)-1;
+
+    if ((os_hooks) && (os_hooks)->get_cpu) {
+       ret = os_hooks->get_cpu();
+    }
+
+    return ret;
+}
+
+
+
+
+
 int v3_vm_enter(struct guest_info * info) {
     switch (v3_cpu_types[info->cpu_id]) {
 #ifdef CONFIG_SVM
@@ -218,3 +264,6 @@ int v3_vm_enter(struct guest_info * info) {
            return -1;
     }
 }
+
+
+
index 136213d..627bb84 100644 (file)
 #include <palacios/vmm_hypercall.h>
 #include <palacios/vmm_dev_mgr.h>
 #include <palacios/vmm_cpuid.h>
+#include <palacios/vmm_xml.h>
+
+#include <palacios/svm.h>
+#include <palacios/vmx.h>
 
 #ifdef CONFIG_SYMBIOTIC
 #include <palacios/vmm_sym_iface.h>
 
 #endif
 
-#include <devices/generic.h>
-#include <devices/ide.h>
-#include <devices/ram_cd.h>
-#include <devices/net_cd.h>
-#include <devices/ram_hd.h>
-#include <devices/net_hd.h>
 
-#include <devices/telnet_cons.h>
-#include <devices/pci_passthrough.h>
+#include <palacios/vmm_host_events.h>
+#include <palacios/vmm_socket.h>
 
+#include "vmm_config_class.h"
 
+// This is used to access the configuration file index table
+struct file_hdr {
+    uint32_t index;
+    uint32_t size;
+    uint64_t offset;
+};
 
+struct file_idx_table {
+    uint64_t num_files;
+    struct file_hdr hdrs[0];
+};
 
-#include <palacios/vmm_host_events.h>
 
 
 
-#include <palacios/vmm_socket.h>
+static int setup_memory_map(struct guest_info * info, struct v3_config * config_ptr);
+static int setup_devices(struct guest_info * info, struct v3_config * config_ptr);
+
+
+char * v3_cfg_val(v3_cfg_tree_t * tree, char * tag) {
+    char * attrib = (char *)v3_xml_attr(tree, tag);
+    v3_cfg_tree_t * child_entry = v3_xml_child(tree, tag);
+    char * val = NULL;
+
+    if ((child_entry != NULL) && (attrib != NULL)) {
+       PrintError("Duplicate Configuration parameters present for %s\n", tag);
+       return NULL;
+    }
+
+    val = (attrib == NULL) ? v3_xml_txt(child_entry): attrib;
 
+    return val; 
+}
+
+v3_cfg_tree_t * v3_cfg_subtree(v3_cfg_tree_t * tree, char * tag) {
+    return v3_xml_child(tree, tag);
+}
+
+v3_cfg_tree_t * v3_cfg_next_branch(v3_cfg_tree_t * tree) {
+    return v3_xml_next(tree);
+}
 
-static int setup_memory_map(struct guest_info * info, struct v3_vm_config * config_ptr);
-static int setup_devices(struct guest_info * info, struct v3_vm_config * config_ptr);
-static int configure_generic(struct guest_info * info, struct v3_vm_config * config_ptr);
 
 
+struct v3_cfg_file * v3_cfg_get_file(struct guest_info * info, char * tag) {
+    struct v3_cfg_file * file = NULL;
 
-#ifdef CONFIG_PASSTHROUGH_VIDEO
-static int passthrough_mem_write(addr_t guest_addr, void * src, uint_t length, void * priv_data) {
+    file = (struct v3_cfg_file *)v3_htable_search(info->cfg_data->file_table, (addr_t)tag);
+
+    return file;
+}
+
+
+static uint_t file_hash_fn(addr_t key) {
+    char * name = (char *)key;
+    return v3_hash_buffer((uchar_t *)name, strlen(name));
+}
 
-    return length;
-    //  memcpy((void*)guest_addr, src, length);
-    PrintDebug("Write of %d bytes to %p\n", length, (void *)guest_addr);
-    PrintDebug("Write Value = %p\n", (void *)*(addr_t *)src);
+static int file_eq_fn(addr_t key1, addr_t key2) {
+    char * name1 = (char *)key1;
+    char * name2 = (char *)key2;
+
+    return (strcmp(name1, name2) == 0);
+}
+
+static struct v3_config * parse_config(void * cfg_blob) {
+    struct v3_config * cfg = NULL;
+    int offset = 0;
+    uint_t xml_len = 0; 
+    struct file_idx_table * files = NULL;
+    v3_cfg_tree_t * file_tree = NULL;
+
+    V3_Print("cfg data at %p\n", cfg_blob);
+
+    if (memcmp(cfg_blob, "v3vee\0\0\0", 8) != 0) {
+       PrintError("Invalid Configuration Header\n");
+       return NULL;
+    }
+
+    offset += 8;
+
+    cfg = (struct v3_config *)V3_Malloc(sizeof(struct v3_config));
+    memset(cfg, 0, sizeof(struct v3_config));
+
+    cfg->blob = cfg_blob;
+    INIT_LIST_HEAD(&(cfg->file_list));
+    cfg->file_table = v3_create_htable(0, file_hash_fn, file_eq_fn);
     
-    return length;
+    xml_len = *(uint32_t *)(cfg_blob + offset);
+    offset += 4;
+
+    cfg->cfg = (v3_cfg_tree_t *)v3_xml_parse((uint8_t *)(cfg_blob + offset));
+    offset += xml_len;
+   
+    offset += 8;
+
+    files = (struct file_idx_table *)(cfg_blob + offset);
+
+    V3_Print("Number of files in cfg: %d\n", (uint32_t)(files->num_files));
+
+    file_tree = v3_cfg_subtree(v3_cfg_subtree(cfg->cfg, "files"), "file");
+
+    while (file_tree) {
+       char * id = v3_cfg_val(file_tree, "id");
+       char * index = v3_cfg_val(file_tree, "index");
+       int idx = atoi(index);
+       struct file_hdr * hdr = &(files->hdrs[idx]);
+       struct v3_cfg_file * file = NULL;
+
+       file = (struct v3_cfg_file *)V3_Malloc(sizeof(struct v3_cfg_file));
+       
+       if (!file) {
+           PrintError("Could not allocate file structure\n");
+           return NULL;
+       }
+
+
+       V3_Print("File index=%d id=%s\n", idx, id);
+
+       strncpy(file->tag, id, 256);
+       file->size = hdr->size;
+       file->data = cfg_blob + hdr->offset;
+
+       V3_Print("Storing file data offset = %d, size=%d\n", (uint32_t)hdr->offset, hdr->size);
+       V3_Print("file data at %p\n", file->data);
+       list_add( &(file->file_node), &(cfg->file_list));
+
+       V3_Print("Keying file to name\n");
+       v3_htable_insert(cfg->file_table, (addr_t)(file->tag), (addr_t)(file));
+
+       V3_Print("Iterating to next file\n");
+
+       file_tree = v3_cfg_next_branch(file_tree);
+    }
+
+    V3_Print("Configuration parsed successfully\n");
+
+    return cfg;
 }
-#endif
 
-int v3_pre_config_guest(struct guest_info * info, struct v3_vm_config * config_ptr) {
-   extern v3_cpu_arch_t v3_cpu_types[];
 
-    // Amount of ram the Guest will have, rounded to a 4K page boundary
-    info->mem_size = config_ptr->mem_size & ~(addr_t)0xfff;
+static int pre_config_guest(struct guest_info * info, struct v3_config * config_ptr) {
+    extern v3_cpu_arch_t v3_cpu_types[];
+    char * memory_str = v3_cfg_val(config_ptr->cfg, "memory");
+    char * paging = v3_cfg_val(config_ptr->cfg, "paging");
+    char * schedule_hz_str = v3_cfg_val(config_ptr->cfg, "schedule_hz");
+    char * vm_class = v3_cfg_val(config_ptr->cfg, "class");
+    uint32_t sched_hz = 100;   // set the schedule frequency to 100 HZ
+    
+    if (!memory_str) {
+       PrintError("Memory is a required configuration parameter\n");
+       return -1;
+    }
+    
+    PrintDebug("Memory=%s\n", memory_str);
+
+    // Amount of ram the Guest will have, always in MB
+    info->mem_size = atoi(memory_str) * 1024 * 1024;
+    
+    if (strcasecmp(vm_class, "PC") == 0) {
+       info->vm_class = V3_PC_VM;
+    } else {
+       PrintError("Invalid VM class\n");
+       return -1;
+    }
 
-    info->cpu_id = config_ptr->guest_cpu;
 
     /*
      * Initialize the subsystem data strutures
      */
 #ifdef CONFIG_TELEMETRY
-    // This should go first, because other subsystems will depend on the guest_info flag
-    if (config_ptr->enable_telemetry) {
-       info->enable_telemetry = 1;
-       v3_init_telemetry(info);
-    } else {
-       info->enable_telemetry = 0;
+    {
+       char * telemetry = v3_cfg_val(config_ptr->cfg, "telemetry");
+
+       // This should go first, because other subsystems will depend on the guest_info flag    
+       if ((telemetry) && (strcasecmp(telemetry, "enable") == 0)) {
+           info->enable_telemetry = 1;
+           v3_init_telemetry(info);
+       } else {
+           info->enable_telemetry = 0;
+       }
     }
 #endif
 
@@ -103,10 +238,13 @@ int v3_pre_config_guest(struct guest_info * info, struct v3_vm_config * config_p
     v3_init_host_events(info);
 
     // Initialize the memory map
-    v3_init_shadow_map(info);
+    if (v3_init_shadow_map(info) == -1) {
+       PrintError("Could not initialize shadow map\n");
+       return -1;
+    }
     
     if ((v3_cpu_types[info->cpu_id] == V3_SVM_REV3_CPU) && 
-       (config_ptr->enable_nested_paging == 1)) {
+       (paging) && (strcasecmp(paging, "nested") == 0)) {
        PrintDebug("Guest Page Mode: NESTED_PAGING\n");
        info->shdw_pg_mode = NESTED_PAGING;
     } else {
@@ -130,25 +268,22 @@ int v3_pre_config_guest(struct guest_info * info, struct v3_vm_config * config_p
     v3_init_sym_swap(info);
 #endif
 
-
-    if (config_ptr->schedule_freq == 0) {
-       // set the schedule frequency to 100 HZ
-       config_ptr->schedule_freq = 100;
+    if (schedule_hz_str) {
+       sched_hz = atoi(schedule_hz_str);
     }
 
-    PrintDebug("CPU_KHZ = %d, schedule_freq=%p\n", V3_CPU_KHZ(), (void *)config_ptr->schedule_freq);
+    PrintDebug("CPU_KHZ = %d, schedule_freq=%p\n", V3_CPU_KHZ(), 
+              (void *)(addr_t)sched_hz);
 
-    info->yield_cycle_period = (V3_CPU_KHZ() * 1000) / config_ptr->schedule_freq;
+    info->yield_cycle_period = (V3_CPU_KHZ() * 1000) / sched_hz;
     
-    // Initial CPU operating mode
-    info->cpu_mode = REAL;
-    info->mem_mode = PHYSICAL_MEM;
+
 
     return 0;
 }
 
 
-int v3_post_config_guest(struct guest_info * info, struct v3_vm_config * config_ptr) {
+static int post_config_guest(struct guest_info * info, struct v3_config * config_ptr) {
 
     // Configure the memory map for the guest
     if (setup_memory_map(info, config_ptr) == -1) {
@@ -168,333 +303,134 @@ int v3_post_config_guest(struct guest_info * info, struct v3_vm_config * config_
 
     info->run_state = VM_STOPPED;
 
-    info->vm_regs.rdi = 0;
-    info->vm_regs.rsi = 0;
-    info->vm_regs.rbp = 0;
-    info->vm_regs.rsp = 0;
-    info->vm_regs.rbx = 0;
-    info->vm_regs.rdx = 0;
-    info->vm_regs.rcx = 0;
-    info->vm_regs.rax = 0;
-
-    return 0;
-}
-
-
-
-
-
-/* TODO:
- * The amount of guest memory is stored in info->mem_size
- * We need to make sure the memory map extends to cover it
- */
-static int setup_memory_map(struct guest_info * info, struct v3_vm_config * config_ptr) {
-
-#ifdef CONFIG_PASSTHROUGH_VIDEO
-    PrintDebug("Setting up memory map (memory size=%dMB)\n", (uint_t)(info->mem_size / (1024 * 1024)));
-    
-    // VGA frame buffer
-    if (1) {
-       if (v3_add_shadow_mem(info, 0xa0000, 0xc0000, 0xa0000) == -1) {
-           PrintError("Could not map VGA framebuffer\n");
+    if (info->vm_class == V3_PC_VM) {
+       if (post_config_pc(info, config_ptr) == -1) {
+           PrintError("PC Post configuration failure\n");
            return -1;
        }
     } else {
-       v3_hook_write_mem(info, 0xa0000, 0xc0000, 0xa0000,  passthrough_mem_write, NULL);
-    }
-#endif
-
-#define VGABIOS_START 0x000c0000
-#define ROMBIOS_START 0x000f0000
-
-    /* layout vgabios */
-    {
-       extern uint8_t v3_vgabios_start[];
-       extern uint8_t v3_vgabios_end[];
-
-       addr_t vgabios_dst = v3_get_shadow_addr(&(info->mem_map.base_region), VGABIOS_START);
-       memcpy(V3_VAddr((void *)vgabios_dst), v3_vgabios_start, v3_vgabios_end - v3_vgabios_start);     
-    }
-    
-    /* layout rombios */
-    {
-       extern uint8_t v3_rombios_start[];
-       extern uint8_t v3_rombios_end[];
-
-       addr_t rombios_dst = v3_get_shadow_addr(&(info->mem_map.base_region), ROMBIOS_START);
-       memcpy(V3_VAddr((void *)rombios_dst), v3_rombios_start, v3_rombios_end - v3_rombios_start);
-    }
-
-#ifdef CONFIG_CRAY_XT
-    {
-#define SEASTAR_START 0xffe00000 
-#define SEASTAR_END 0xffffffff 
-       // Map the Seastar straight through
-       if (v3_add_shadow_mem(info, SEASTAR_START, SEASTAR_END, SEASTAR_START) == -1) {
-           PrintError("Could not map through the seastar\n");
-           return -1;
-       }
+       PrintError("Invalid VM Class\n");
+       return -1;
     }
-#endif
 
-    v3_print_mem_map(info);
 
     return 0;
 }
 
 
 
-static int setup_devices(struct guest_info * info, struct v3_vm_config * config_ptr) {
-
-    v3_create_device(info, "8259A", NULL);
-    v3_create_device(info, "KEYBOARD", NULL);
-    v3_create_device(info, "8254_PIT", NULL); 
-    v3_create_device(info, "BOCHS_DEBUG", NULL);
-    v3_create_device(info, "OS_DEBUG", NULL);
-    v3_create_device(info, "LAPIC", NULL);
-    v3_create_device(info, "IOAPIC", "LAPIC");
-    v3_create_device(info, "VMNET", NULL);
-    
+int v3_config_guest(struct guest_info * info, void * cfg_blob) {
+    v3_cpu_arch_t cpu_type = v3_get_cpu_type(v3_get_cpu_id());
 
-    v3_create_device(info, "CGA_VIDEO", (void *)1);
-    {
-       struct telnet_cons_cfg cons_cfg = {"CGA_VIDEO", 19997};
-       v3_create_device(info, "TELNET_CONSOLE", &cons_cfg);
+    if (cpu_type == V3_INVALID_CPU) {
+       PrintError("Configuring guest on invalid CPU\n");
+       return -1;
     }
 
-    if (config_ptr->enable_pci == 1) {
-       struct ide_cfg ide_config = {"PCI", "PIIX3"};
-       struct pci_passthrough_cfg pci_qemu_pt_cfg = {"PCI", "E1000", 0x8086, 0x100e};
-       struct pci_passthrough_cfg pci_hw_pt_cfg = {"PCI", "E1000", 0x8086, 0x107c};
-       
-       v3_create_device(info, "PCI", NULL);
-       v3_create_device(info, "i440FX", "PCI");
-       v3_create_device(info, "PIIX3", "PCI");
-       
+    info->cfg_data = parse_config(cfg_blob);
 
-       v3_create_device(info, "LNX_VIRTIO_SYM", "PCI");
-       v3_create_device(info, "LNX_VIRTIO_BLK", "PCI");
-       v3_create_device(info, "LNX_VIRTIO_BALLOON", "PCI");
-       v3_create_device(info, "SYM_SWAP", "LNX_VIRTIO_BLK");
-
-       v3_create_device(info, "IDE", &ide_config);
-       
-       v3_create_device(info, "PCI_PASSTHROUGH", &pci_qemu_pt_cfg);
-       v3_create_device(info, "PCI_PASSTHROUGH", &pci_hw_pt_cfg);
+    if (!info->cfg_data) {
+       PrintError("Could not parse configuration\n");
+       return -1;
+    }
 
+    V3_Print("Preconfiguration\n");
 
-    } else {
-       v3_create_device(info, "IDE", NULL);
+    if (pre_config_guest(info, info->cfg_data) == -1) {
+       PrintError("Error in preconfiguration\n");
+       return -1;
     }
 
+    V3_Print("Arch dependent configuration\n");
 
-    if (config_ptr->pri_disk_type != NONE) {
-       if (config_ptr->pri_disk_type == CDROM) {
-           if (config_ptr->pri_disk_con == RAM) {
-               struct ram_cd_cfg cfg = {"IDE", 0, 0, 
-                                        (addr_t)(config_ptr->pri_disk_info.ram.data_ptr), 
-                                        config_ptr->pri_disk_info.ram.size};
-
-               PrintDebug("Creating RAM CD\n");
-
-               v3_create_device(info, "RAM-CD", &cfg);
-           } else if (config_ptr->pri_disk_con == NETWORK) {
-               struct net_cd_cfg cfg = {"IDE", 0, 0, 
-                                        config_ptr->pri_disk_info.net.ip_str,
-                                        config_ptr->pri_disk_info.net.port, 
-                                        config_ptr->pri_disk_info.net.disk_name};
-               PrintDebug("Creating NET CD\n");
-
-               v3_create_device(info, "NET-CD", &cfg);
-           }
-       } else if (config_ptr->pri_disk_type == HARDDRIVE) {
-           if (config_ptr->pri_disk_con == RAM) {
-               struct ram_hd_cfg cfg = {"IDE", 0, 0, 
-                                        (addr_t)(config_ptr->pri_disk_info.ram.data_ptr), 
-                                        config_ptr->pri_disk_info.ram.size};
-
-               PrintDebug("Creating RAM HD\n");
-
-               v3_create_device(info, "RAM-HD", &cfg);
-           } else if (config_ptr->pri_disk_con == NETWORK) {
-               struct net_hd_cfg cfg  = {"IDE", 0, 0, 
-                                         config_ptr->pri_disk_info.net.ip_str,
-                                         config_ptr->pri_disk_info.net.port, 
-                                         config_ptr->pri_disk_info.net.disk_name};
-               PrintDebug("Creating NET HD\n");
-               v3_create_device(info, "NET-HD", &cfg);
-           }
+    // init SVM/VMX
+#ifdef CONFIG_SVM
+    if ((cpu_type == V3_SVM_CPU) || (cpu_type == V3_SVM_REV3_CPU)) {
+       if (v3_init_svm_vmcb(info, info->vm_class) == -1) {
+           PrintError("Error in SVM initialization\n");
+           return -1;
+       }
+    } 
+#endif
+#ifdef CONFIG_VMX
+    else if ((cpu_type == V3_VMX_CPU) || (cpu_type == V3_VMX_EPT_CPU)) {
+       if (v3_init_vmx_vmcs(info, info->vm_class) == -1) {
+           PrintError("Error in VMX initialization\n");
+           return -1;
        }
     }
+#endif
+    else {
+       PrintError("Invalid CPU Type\n");
+       return -1;
+    }
 
+    V3_Print("Post Configuration\n");
 
-
-    if (config_ptr->sec_disk_type != NONE) {
-       if (config_ptr->sec_disk_type == CDROM) {
-           if (config_ptr->sec_disk_con == RAM) {
-               struct ram_cd_cfg cfg = {"IDE", 0, 1, 
-                                        (addr_t)(config_ptr->sec_disk_info.ram.data_ptr), 
-                                        config_ptr->sec_disk_info.ram.size};
-
-               PrintDebug("Creating RAM CD\n");
-               v3_create_device(info, "RAM-CD", &cfg);
-           } else if (config_ptr->sec_disk_con == NETWORK) {
-               struct net_cd_cfg cfg = {"IDE", 0, 1, 
-                                        config_ptr->sec_disk_info.net.ip_str,
-                                        config_ptr->sec_disk_info.net.port, 
-                                        config_ptr->sec_disk_info.net.disk_name};
-
-               PrintDebug("Creating NET CD\n");
-               v3_create_device(info, "NET-CD", &cfg);    
-           }
-       } else if (config_ptr->sec_disk_type == HARDDRIVE) {
-           if (config_ptr->sec_disk_con == RAM) {
-               struct ram_hd_cfg cfg = {"IDE", 0, 1, 
-                                        (addr_t)(config_ptr->sec_disk_info.ram.data_ptr), 
-                                        config_ptr->sec_disk_info.ram.size};
-               PrintDebug("Creating RAM HD\n");
-               v3_create_device(info, "RAM-HD", &cfg);
-           } else if (config_ptr->sec_disk_con == NETWORK) {
-               struct net_hd_cfg cfg = {"IDE", 0, 1, 
-                                        config_ptr->sec_disk_info.net.ip_str,
-                                        config_ptr->sec_disk_info.net.port, 
-                                        config_ptr->sec_disk_info.net.disk_name};
-               PrintDebug("Creating NET HD\n");
-               v3_create_device(info, "NET-HD", &cfg);
-           }
-       }
+    if (post_config_guest(info, info->cfg_data) == -1) {
+       PrintError("Error in postconfiguration\n");
+       return -1;
     }
 
+    V3_Print("Configuration successfull\n");
 
+    return 0;
+}
 
-#ifdef CONFIG_GENERIC
-       configure_generic(info, config_ptr);
-#endif
 
-    // This should go last because it requires information about the Harddrives
-    v3_create_device(info, "NVRAM", "IDE");
-    
-    PrintDebugDevMgr(info);
 
-    return 0;
-}
 
 
+static int setup_memory_map(struct guest_info * info, struct v3_config * config_ptr) {
+    v3_cfg_tree_t * mem_region = v3_cfg_subtree(v3_cfg_subtree(config_ptr->cfg, "memmap"), "region");
 
-#ifdef CONFIG_GENERIC
-static int configure_generic(struct guest_info * info, struct v3_vm_config * config_ptr) {
-    PrintDebug("Creating Generic Device\n");
-    v3_create_device(info, "GENERIC", NULL);
-    
+    while (mem_region) {
+       addr_t start_addr = atox(v3_cfg_val(mem_region, "start"));
+       addr_t end_addr = atox(v3_cfg_val(mem_region, "end"));
+       addr_t host_addr = atox(v3_cfg_val(mem_region, "host_addr"));
 
-    struct vm_device * generic = v3_find_dev(info, "GENERIC");
+    
+       if (v3_add_shadow_mem(info, start_addr, end_addr, host_addr) == -1) {
+           PrintError("Could not map memory region: %p-%p => %p\n", 
+                      (void *)start_addr, (void *)end_addr, (void *)host_addr);
+           return -1;
+       }
 
-    if (!generic) {
-       PrintError("Could not find generic device\n");
-       return -1;
+       mem_region = v3_cfg_next_branch(mem_region);
     }
 
-    // port 0x92: A20 enable/disable (bit 2) (This causes an MMU flush)
-
-
-    // Make the DMA controller invisible
-    v3_generic_add_port_range(generic, 0x00, 0x07, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channels 0,1,2,3 (address, counter)
-    v3_generic_add_port_range(generic, 0xc0, 0xc7, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channels 4,5,6,7 (address, counter)
-    v3_generic_add_port_range(generic, 0x87, 0x87, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 0 page register
-    v3_generic_add_port_range(generic, 0x83, 0x83, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 1 page register
-    v3_generic_add_port_range(generic, 0x81, 0x81, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 2 page register
-    v3_generic_add_port_range(generic, 0x82, 0x82, GENERIC_PRINT_AND_IGNORE);   // DMA 1 channel 3 page register
-    v3_generic_add_port_range(generic, 0x8f, 0x8f, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 4 page register
-    v3_generic_add_port_range(generic, 0x8b, 0x8b, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 5 page register
-    v3_generic_add_port_range(generic, 0x89, 0x89, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 6 page register
-    v3_generic_add_port_range(generic, 0x8a, 0x8a, GENERIC_PRINT_AND_IGNORE);   // DMA 2 channel 7 page register
-    v3_generic_add_port_range(generic, 0x08, 0x0f, GENERIC_PRINT_AND_IGNORE);   // DMA 1 misc registers (csr, req, smask,mode,clearff,reset,enable,mmask)
-    v3_generic_add_port_range(generic, 0xd0, 0xde, GENERIC_PRINT_AND_IGNORE);   // DMA 2 misc registers
-    
-    
-    
-    
-    // Make the Serial ports invisible 
-    
-    v3_generic_add_port_range(generic, 0x3f8, 0x3f8+7, GENERIC_PRINT_AND_IGNORE);      // COM 1
-    v3_generic_add_port_range(generic, 0x2f8, 0x2f8+7, GENERIC_PRINT_AND_IGNORE);      // COM 2
-    
+    return 0;
+}
 
-      
 
-    v3_generic_add_port_range(generic, 0x3e8, 0x3e8+7, GENERIC_PRINT_AND_IGNORE);      // COM 3
-    v3_generic_add_port_range(generic, 0x2e8, 0x2e8+7, GENERIC_PRINT_AND_IGNORE);      // COM 4
 
-      
-      
 
-    // Make the PCI bus invisible (at least it's configuration)
-    
-    //v3_generic_add_port_range(generic, 0xcf8, 0xcf8, GENERIC_PRINT_AND_IGNORE); // PCI Config Address
-    //v3_generic_add_port_range(generic, 0xcfc, 0xcfc, GENERIC_PRINT_AND_IGNORE); // PCI Config Data
-    
-    
-    
-#if 0
-    if (!use_ramdisk) {
-       // Monitor the IDE controllers (very slow)
-       v3_generic_add_port_range(generic, 0x170, 0x178, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 1
-       v3_generic_add_port_range(generic, 0x376, 0x377, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 1
-    }
-      
 
-    v3_generic_add_port_range(generic, 0x1f0, 0x1f8, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 0
-    v3_generic_add_port_range(generic, 0x3f6, 0x3f7, GENERIC_PRINT_AND_PASSTHROUGH); // IDE 0
-#endif
-      
-      
-#if 0
-    
-    // Make the floppy controllers invisible
-    
-    v3_generic_add_port_range(generic, 0x3f0, 0x3f2, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (base,statusa/statusb,DOR)
-    v3_generic_add_port_range(generic, 0x3f4, 0x3f5, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (mainstat/datarate,data)
-    v3_generic_add_port_range(generic, 0x3f7, 0x3f7, GENERIC_PRINT_AND_IGNORE); // Primary floppy controller (DIR)
-    v3_generic_add_port_range(generic, 0x370, 0x372, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (base,statusa/statusb,DOR)
-    v3_generic_add_port_range(generic, 0x374, 0x375, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (mainstat/datarate,data)
-    v3_generic_add_port_range(generic, 0x377, 0x377, GENERIC_PRINT_AND_IGNORE); // Secondary floppy controller (DIR)
-    
-#endif
 
-#if 1
 
-    // Make the parallel port invisible
-      
-    v3_generic_add_port_range(generic, 0x378, 0x37f, GENERIC_PRINT_AND_IGNORE);
 
-#endif
 
-#ifdef CONFIG_PASTHROUGH_VIDEO
+static int setup_devices(struct guest_info * info, struct v3_config * config_ptr) {
+    v3_cfg_tree_t * device = v3_cfg_subtree(v3_cfg_subtree(config_ptr->cfg, "devices"), "device");
 
-    // Monitor graphics card operations
     
-    v3_generic_add_port_range(generic, 0x3b0, 0x3bb, GENERIC_PRINT_AND_PASSTHROUGH);
-    v3_generic_add_port_range(generic, 0x3c0, 0x3df, GENERIC_PRINT_AND_PASSTHROUGH);
-      
-#endif
+    while (device) {
+       char * id = v3_cfg_val(device, "id");
 
+       V3_Print("configuring device %s\n", id);
 
-#if 1
-    // Make the ISA PNP features invisible
-    
-    v3_generic_add_port_range(generic, 0x274, 0x277, GENERIC_PRINT_AND_IGNORE);
-    v3_generic_add_port_range(generic, 0x279, 0x279, GENERIC_PRINT_AND_IGNORE);
-    v3_generic_add_port_range(generic, 0xa79, 0xa79, GENERIC_PRINT_AND_IGNORE);
-#endif
+       if (v3_create_device(info, id, device) == -1) {
+           PrintError("Error creating device %s\n", id);
+           return -1;
+       }
+       
+       device = v3_cfg_next_branch(device);
+    }
 
 
-#if 1
-    // Monitor any network card (realtek ne2000) operations 
-    v3_generic_add_port_range(generic, 0xc100, 0xc1ff, GENERIC_PRINT_AND_PASSTHROUGH);
-#endif
+   v3_print_dev_mgr(info);
 
-    //  v3_generic_add_port_range(generic, 0x378, 0x400, GENERIC_PRINT_AND_IGNORE);
-    
     return 0;
 }
-#endif
+
+
diff --git a/palacios/src/palacios/vmm_config_class.h b/palacios/src/palacios/vmm_config_class.h
new file mode 100644 (file)
index 0000000..36fee9b
--- /dev/null
@@ -0,0 +1,63 @@
+ /* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+
+static int post_config_pc(struct guest_info * info, struct v3_config * config_ptr) {
+
+
+    info->cpu_mode = REAL;
+    info->mem_mode = PHYSICAL_MEM;
+
+
+    info->vm_regs.rdi = 0;
+    info->vm_regs.rsi = 0;
+    info->vm_regs.rbp = 0;
+    info->vm_regs.rsp = 0;
+    info->vm_regs.rbx = 0;
+    info->vm_regs.rdx = 0;
+    info->vm_regs.rcx = 0;
+    info->vm_regs.rax = 0;
+
+
+#define VGABIOS_START 0x000c0000
+#define ROMBIOS_START 0x000f0000
+    
+    /* layout vgabios */
+    {
+       extern uint8_t v3_vgabios_start[];
+       extern uint8_t v3_vgabios_end[];
+       
+       addr_t vgabios_dst = v3_get_shadow_addr(&(info->mem_map.base_region), VGABIOS_START);
+       memcpy(V3_VAddr((void *)vgabios_dst), v3_vgabios_start, v3_vgabios_end - v3_vgabios_start);     
+    }
+    
+    /* layout rombios */
+    {
+       extern uint8_t v3_rombios_start[];
+       extern uint8_t v3_rombios_end[];
+
+       addr_t rombios_dst = v3_get_shadow_addr(&(info->mem_map.base_region), ROMBIOS_START);
+       memcpy(V3_VAddr((void *)rombios_dst), v3_rombios_start, v3_rombios_end - v3_rombios_start);
+    }
+
+    v3_print_mem_map(info);
+
+    return 0;
+}
+
index d0c3a32..34040d8 100644 (file)
@@ -20,7 +20,7 @@
 #include <palacios/vmm.h>
 #include <palacios/vmm_cpuid.h>
 #include <palacios/vmm_lowlevel.h>
-
+#include <palacios/vm_guest.h>
 
 
 void v3_init_cpuid_map(struct guest_info * info) {
index bbeaf4c..d3e9360 100644 (file)
@@ -324,21 +324,6 @@ int v3_handle_cr3_write(struct guest_info * info) {
            }
 
 
-#ifdef CONFIG_CRAY_XT
-           
-           // If Paging is enabled in the guest then we need to change the shadow page tables
-           if (info->mem_mode == VIRTUAL_MEM) {
-               if (info->shdw_pg_state.prev_guest_cr3 != info->shdw_pg_state.guest_cr3) {
-                   if (v3_activate_shadow_pt(info) == -1) {
-                       PrintError("Failed to activate 32 bit shadow page table\n");
-                       return -1;
-                   }
-               }
-           }
-
-           info->shdw_pg_state.prev_guest_cr3 = info->shdw_pg_state.guest_cr3;
-#else 
-
            // If Paging is enabled in the guest then we need to change the shadow page tables
            if (info->mem_mode == VIRTUAL_MEM) {
                if (v3_activate_shadow_pt(info) == -1) {
@@ -346,9 +331,6 @@ int v3_handle_cr3_write(struct guest_info * info) {
                    return -1;
                }
            }
-
-#endif
-
            
            PrintDebug("New Shadow CR3=%p; New Guest CR3=%p\n", 
                       (void *)(addr_t)(info->ctrl_regs.cr3), 
index c212958..c7a8f95 100644 (file)
@@ -94,6 +94,14 @@ int v3_init_dev_mgr(struct guest_info * info) {
 
     mgr->dev_table = v3_create_htable(0, dev_hash_fn, dev_eq_fn);
 
+    INIT_LIST_HEAD(&(mgr->blk_list));
+    INIT_LIST_HEAD(&(mgr->net_list));
+    INIT_LIST_HEAD(&(mgr->console_list));
+
+    mgr->blk_table = v3_create_htable(0, dev_hash_fn, dev_eq_fn);
+    mgr->net_table = v3_create_htable(0, dev_hash_fn, dev_eq_fn);
+    mgr->console_table = v3_create_htable(0, dev_hash_fn, dev_eq_fn);
+    
     return 0;
 }
 
@@ -113,7 +121,7 @@ int v3_dev_mgr_deinit(struct guest_info * info) {
 
 
 
-int v3_create_device(struct guest_info * info, const char * dev_name, void * cfg_data) {
+int v3_create_device(struct guest_info * info, const char * dev_name, v3_cfg_tree_t * cfg) {
     int (*dev_init)(struct guest_info * info, void * cfg_data);
 
     dev_init = (void *)v3_htable_search(master_dev_table, (addr_t)dev_name);
@@ -124,7 +132,7 @@ int v3_create_device(struct guest_info * info, const char * dev_name, void * cfg
     }
 
 
-    if (dev_init(info, cfg_data) == -1) {
+    if (dev_init(info, cfg) == -1) {
        PrintError("Could not initialize Device %s\n", dev_name);
        return -1;
     }
@@ -142,6 +150,10 @@ void v3_free_device(struct vm_device * dev) {
 struct vm_device * v3_find_dev(struct guest_info * info, const char * dev_name) {
     struct vmm_dev_mgr * mgr = &(info->dev_mgr);
 
+    if (!dev_name) {
+       return NULL;
+    }
+
     return (struct vm_device *)v3_htable_search(mgr->dev_table, (addr_t)dev_name);
 }
 
@@ -213,31 +225,81 @@ int v3_attach_device(struct guest_info * vm, struct vm_device * dev ) {
 }
 
 
-#ifdef CONFIG_DEBUG_DEV_MGR
 
-void PrintDebugDevMgr(struct guest_info * info) {
+void v3_print_dev_mgr(struct guest_info * info) {
     struct vmm_dev_mgr * mgr = &(info->dev_mgr);
     struct vm_device * dev;
 
-    PrintDebug("%d devices registered with manager\n", mgr->num_devs);
+    V3_Print("%d devices registered with manager\n", mgr->num_devs);
 
     list_for_each_entry(dev, &(mgr->dev_list), dev_link) {
-       PrintDebugDev(dev);
-       PrintDebug("next..\n");
+       V3_Print("Device: %s\n", dev->name);
     }
 
     return;
 }
 
 
-void PrintDebugDev(struct vm_device * dev) {
-    PrintDebug("Device: %s\n", dev->name);
+
+
+struct blk_frontend {
+    int (*connect)(struct guest_info * info, 
+                   void * frontend_data, 
+                   struct v3_dev_blk_ops * ops, 
+                   v3_cfg_tree_t * cfg, 
+                   void * priv_data);
+       
+
+    struct list_head blk_node;
+
+    void * priv_data;
+};
+
+
+
+int v3_dev_add_blk_frontend(struct guest_info * info, 
+                           char * name, 
+                           int (*connect)(struct guest_info * info, 
+                                           void * frontend_data, 
+                                           struct v3_dev_blk_ops * ops, 
+                                           v3_cfg_tree_t * cfg, 
+                                           void * priv_data), 
+                           void * priv_data) {
+
+    struct blk_frontend * frontend = NULL;
+
+    frontend = (struct blk_frontend *)V3_Malloc(sizeof(struct blk_frontend));
+    memset(frontend, 0, sizeof(struct blk_frontend));
+    
+    frontend->connect = connect;
+    frontend->priv_data = priv_data;
+       
+    list_add(&(frontend->blk_node), &(info->dev_mgr.blk_list));
+    v3_htable_insert(info->dev_mgr.blk_table, (addr_t)(name), (addr_t)frontend);
+
+    return 0;
 }
 
+int v3_dev_connect_blk(struct guest_info * info, 
+                      char * frontend_name, 
+                      struct v3_dev_blk_ops * ops, 
+                      v3_cfg_tree_t * cfg, 
+                      void * private_data) {
+
+    struct blk_frontend * frontend = NULL;
 
+    frontend = (struct blk_frontend *)v3_htable_search(info->dev_mgr.blk_table,
+                                                      (addr_t)frontend_name);
+    
+    if (frontend == NULL) {
+       PrintError("Could not find frontend blk device %s\n", frontend_name);
+       return 0;
+    }
 
+    if (frontend->connect(info, frontend->priv_data, ops, cfg, private_data) == -1) {
+       PrintError("Error connecting to block frontend %s\n", frontend_name);
+       return -1;
+    }
 
-#else 
-void PrintDebugDevMgr(struct guest_info * info) {}
-void PrintDebugDev(struct vm_device * dev) {}
-#endif
+    return 0;
+}
index 61a1a6f..f1f9411 100644 (file)
@@ -20,6 +20,7 @@
 #include <palacios/vmm_excp.h>
 #include <palacios/vmm.h>
 #include <palacios/vmm_types.h>
+#include <palacios/vm_guest.h>
 
 void v3_init_exception_state(struct guest_info * info) {
     info->excp_state.excp_pending = 0;
index 90eb032..791898c 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <palacios/vmm.h>
 #include <palacios/vmm_host_events.h>
-
+#include <palacios/vm_guest.h>
 
 int v3_init_host_events(struct guest_info * info) {
     struct v3_host_events * host_evts = &(info->host_event_hooks);
index 3dc49f2..65749c1 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <palacios/vmm_hypercall.h>
 #include <palacios/vmm.h>
-
+#include <palacios/vm_guest.h>
 
 void v3_init_hypercall_map(struct guest_info * info) {
     info->hcall_map.rb_node = NULL;
index 77308d9..0211b99 100644 (file)
@@ -20,7 +20,7 @@
 #include <palacios/vmm_io.h>
 #include <palacios/vmm_string.h>
 #include <palacios/vmm.h>
-
+#include <palacios/vm_guest.h>
 
 
 
index b012bc3..4248845 100644 (file)
 #include <palacios/vmm.h>
 #include <palacios/vmm_util.h>
 #include <palacios/vmm_emulator.h>
+#include <palacios/vm_guest.h>
 
 #include <palacios/vmm_shadow_paging.h>
 #include <palacios/vmm_direct_paging.h>
 
-
 #define MEM_OFFSET_HCALL 0x1000
 
 
@@ -41,7 +41,7 @@ static int mem_offset_hypercall(struct guest_info * info, uint_t hcall_id, void
 }
 
 
-void v3_init_shadow_map(struct guest_info * info) {
+int v3_init_shadow_map(struct guest_info * info) {
     v3_shdw_map_t * map = &(info->mem_map);
     addr_t mem_pages = info->mem_size >> 12;
 
@@ -56,9 +56,17 @@ void v3_init_shadow_map(struct guest_info * info) {
     map->base_region.host_type = SHDW_REGION_ALLOCATED;
     map->base_region.host_addr = (addr_t)V3_AllocPages(mem_pages);
 
+
+    if ((void *)map->base_region.host_addr == NULL) {
+       PrintError("Could not allocate Guest memory\n");
+       return -1;
+    }
+       
     //memset(V3_VAddr((void *)map->base_region.host_addr), 0xffffffff, map->base_region.guest_end);
 
     v3_register_hypercall(info, MEM_OFFSET_HCALL, mem_offset_hypercall, NULL);
+
+    return 0;
 }
 
 void v3_delete_shadow_map(struct guest_info * info) {
index abe6d88..0afc383 100644 (file)
@@ -81,8 +81,6 @@ static void telemetry_cb(struct guest_info * info, void * private_data, char * h
 int v3_init_shadow_page_state(struct guest_info * info) {
     struct shadow_page_state * state = &(info->shdw_pg_state);
   
-    state->prev_guest_cr3 = 0;
-
     state->guest_cr3 = 0;
     state->guest_cr0 = 0;
     state->guest_efer.value = 0x0LL;
index c286a6d..effaf32 100644 (file)
@@ -68,6 +68,18 @@ void * memcpy(void * dst, const void * src, size_t n) {
 }
 #endif
 
+#ifdef CONFIG_BUILT_IN_MEMMOVE
+void * memmove(void * dst, const void * src, size_t n) {
+    uint8_t * tmp = (uint8_t *)V3_Malloc(n);
+    
+    memcpy(tmp, src, n);
+    memcpy(dst, tmp, n);
+    
+    V3_Free(tmp);
+    return dst;
+}
+#endif
+
 
 #ifdef CONFIG_BUILT_IN_MEMCMP
 int memcmp(const void * s1_, const void * s2_, size_t n) {
@@ -140,6 +152,22 @@ int strcmp(const char * s1, const char * s2) {
 }
 #endif
 
+#ifdef CONFIG_BUILT_IN_STRCASECMP
+int strcasecmp(const char * s1, const char * s2) {
+    while (1) {
+       int cmp = (tolower(*s1) - tolower(*s2));
+
+       if ((cmp != 0) || (*s1 == '\0') || (*s2 == '\0')) {
+           return cmp;
+       }
+
+       ++s1;
+       ++s2;
+    }
+}
+
+#endif
+
 
 #ifdef CONFIG_BUILT_IN_STRNCMP
 int strncmp(const char * s1, const char * s2, size_t limit) {
@@ -162,6 +190,26 @@ int strncmp(const char * s1, const char * s2, size_t limit) {
 }
 #endif
 
+#ifdef CONFIG_BUILT_IN_STRNCASECMP
+int strncasecmp(const char * s1, const char * s2, size_t limit) {
+    size_t i = 0;
+
+    while (i < limit) {
+       int cmp = (tolower(*s1) - tolower(*s2));
+
+       if ((cmp != 0) || (*s1 == '\0') || (*s2 == '\0')) {
+           return cmp;
+       }
+
+       ++s1;
+       ++s2;
+       ++i;
+    }
+
+    return 0;
+}
+#endif
+
 
 #ifdef CONFIG_BUILT_IN_STRCAT
 char * strcat(char * s1, const char * s2) {
@@ -261,6 +309,76 @@ int atoi(const char * buf) {
 #endif
 
 
+int strtoi(const char * nptr, char ** endptr) {
+    int ret = 0;
+    char * buf = (char *)nptr;
+
+    while ((*buf >= '0') && (*buf <= '9')) {
+       ret *= 10;
+       ret += (*buf - '0');
+
+       buf++;
+
+       if (endptr) {
+           *endptr = buf;
+       }
+    }
+
+    return ret;
+}
+
+uint64_t atox(const char * buf) {
+    uint64_t ret = 0;
+
+    if (*(buf + 1) == 'x') {
+       buf += 2;
+    }
+
+    while (isxdigit(*buf)) {
+       ret <<= 4;
+       
+       if (isdigit(*buf)) {
+           ret += (*buf - '0');
+       } else {
+           ret += tolower(*buf) - 'a' + 10;
+       }
+
+       buf++;
+    }
+
+    return ret;
+}
+
+uint64_t strtox(const char * nptr, char ** endptr) {
+    uint64_t ret = 0;
+    char * buf = (char *)nptr;
+
+    if (*(buf + 1) == 'x') {
+       buf += 2;
+    }
+
+    while (isxdigit(*buf)) {
+       ret <<= 4;
+       
+       if (isdigit(*buf)) {
+           ret += (*buf - '0');
+       } else {
+           ret += tolower(*buf) - 'a' + 10;
+       }
+
+       buf++;
+
+       if (endptr) {
+           *endptr = buf;
+       }
+    }
+
+    return ret;
+
+}
+
+
+
 #ifdef CONFIG_BUILT_IN_STRCHR
 char * strchr(const char * s, int c) {
     while (*s != '\0') {
@@ -307,3 +425,87 @@ char * strpbrk(const char * s, const char * accept) {
 }
 #endif
 
+#ifdef CONFIG_BUILT_IN_STRSPN
+size_t strspn(const char * s, const char * accept) {
+    int match = 1;
+    int cnt = 0;
+    int i = 0;
+    int accept_len = strlen(accept);
+
+    while (match) {
+       match = 0;
+
+       for (i = 0; i < accept_len; i++) {
+           if (s[cnt] == accept[i]) {
+               match = 1;
+               cnt++;
+               break;
+           }
+       }
+    }
+
+    return cnt;
+}
+#endif
+
+
+#ifdef CONFIG_BUILT_IN_STRCSPN
+size_t strcspn(const char * s, const char * reject) {
+    int match = 0;
+    int cnt = 0;
+    int i = 0;
+    int reject_len = strlen(reject);
+
+    while (!match) {
+       for (i = 0; i < reject_len; i++) {
+           if (s[cnt] == reject[i]) {
+               match = 1;
+               cnt++;
+               break;
+           }
+       }
+    }
+
+    return cnt;
+}
+#endif
+
+
+#ifdef CONFIG_BUILT_IN_STRSTR
+char *strstr(const char *haystack, const char *needle)
+{
+        int l1, l2;
+
+        l2 = strlen(s2);
+        if (!l2)
+                return (char *)s1;
+        l1 = strlen(s1);
+        while (l1 >= l2) {
+                l1--;
+                if (!memcmp(s1, s2, l2))
+                        return (char *)s1;
+                s1++;
+        }
+        return NULL;
+}
+#endif
+
+
+void str_tolower(char * s) {
+    while (isalpha(*s)) {
+       if (!islower(*s)) {
+           *s = tolower(*s);
+       }
+       s++;
+    }
+}
+
+
+void str_toupper(char * s) {
+    while (isalpha(*s)) {
+       if (!isupper(*s)) {
+           *s = toupper(*s);
+       }
+       s++;
+    }
+}
index 2a3caf0..1242cb4 100644 (file)
@@ -22,6 +22,7 @@
 #include <palacios/vmm_msr.h>
 #include <palacios/vmm_mem.h>
 #include <palacios/vmm_hypercall.h>
+#include <palacios/vm_guest.h>
 
 #define SYM_PAGE_MSR 0x535
 
index a4117b8..5c8cad8 100644 (file)
@@ -21,7 +21,7 @@
 
 #include <palacios/vmm_sym_swap.h>
 #include <palacios/vmm_list.h>
-
+#include <palacios/vm_guest.h>
 
 #ifdef CONFIG_SYMBIOTIC_SWAP_TELEMETRY
 #include <palacios/vmm_telemetry.h>
index 86eaa02..319d158 100644 (file)
@@ -17,9 +17,9 @@
  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
  */
 
-#include "palacios/vmm_time.h"
-#include "palacios/vmm.h"
-
+#include <palacios/vmm_time.h>
+#include <palacios/vmm.h>
+#include <palacios/vm_guest.h>
 
 void v3_init_time(struct guest_info * info) {
     struct vm_time * time_state = &(info->time_state);
diff --git a/palacios/src/palacios/vmm_xml.c b/palacios/src/palacios/vmm_xml.c
new file mode 100644 (file)
index 0000000..e632a4f
--- /dev/null
@@ -0,0 +1,900 @@
+/* ezxml.c
+ *
+ * Copyright 2004-2006 Aaron Voisine <aaron@voisine.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* 
+ * Modified for Palacios by Jack Lange <jarusl@cs.northwestern.edu> 
+ */
+
+
+
+#include <palacios/vmm_xml.h>
+#include <palacios/vmm_sprintf.h>
+#include <stdarg.h>
+#include <palacios/vmm.h>
+
+#define V3_XML_BUFSIZE 1024 // size of internal memory buffers
+
+// Flags for struct v3_xml 
+#define V3_XML_NAMEM   0x80 // name is malloced
+#define V3_XML_TXTM    0x40 // txt is malloced
+#define V3_XML_DUP     0x20 // attribute name and value are strduped
+//
+
+
+#define V3_XML_WS   "\t\r\n "  // whitespace
+#define V3_XML_ERRL 128        // maximum error string length
+
+struct v3_xml_root {       // additional data for the root tag
+    struct v3_xml xml;     // is a super-struct built on top of v3_xml struct
+    struct v3_xml * cur;          // current xml tree insertion point
+    char *str_ptr;         // original xml string
+    char *tmp_start;              // start of work area
+    char *tmp_end;              // end of work area
+    char **ent;           // general entities (ampersand sequences)
+    char ***attr;         // default attributes
+    short standalone;     // non-zero if <?xml standalone="yes"?>
+    char err[V3_XML_ERRL]; // error string
+};
+
+static char * empty_attrib_list[] = { NULL }; // empty, null terminated array of strings
+
+
+static void * tmp_realloc(void * old_ptr, uint_t old_size, uint_t new_size) {
+    void * new_buf = V3_Malloc(new_size);
+
+    if (new_buf == NULL) {
+        return NULL;
+    }
+
+    memcpy(new_buf, old_ptr, old_size);
+    V3_Free(old_ptr);
+
+    return new_buf;
+}
+
+
+
+
+
+// set an error string and return root
+static void v3_xml_err(struct v3_xml_root * root, char * xml_str, const char * err, ...) {
+    va_list ap;
+    int line = 1;
+    char * tmp;
+    char fmt[V3_XML_ERRL];
+    
+    for (tmp = root->tmp_start; tmp < xml_str; tmp++) {
+       if (*tmp == '\n') {
+           line++;
+       }
+    }
+
+    snprintf(fmt, V3_XML_ERRL, "[error near line %d]: %s", line, err);
+
+    va_start(ap, err);
+    vsnprintf(root->err, V3_XML_ERRL, fmt, ap);
+    va_end(ap);
+
+    PrintError("XML Error: %s\n", root->err);
+
+    // free memory
+    v3_xml_free(&(root->xml));
+
+    return;
+}
+
+
+
+// returns the first child tag with the given name or NULL if not found
+struct v3_xml * v3_xml_child(struct v3_xml * xml, const char * name) {
+    struct v3_xml * child = NULL;
+
+    if (xml != NULL) {
+       child = xml->child;
+    }
+
+    while ((child) && (strcasecmp(name, child->name) != 0)) {
+       child = child->sibling;
+    }
+
+    return child;
+}
+
+// returns the Nth tag with the same name in the same subsection or NULL if not
+// found
+struct v3_xml * v3_xml_idx(struct v3_xml * xml, int idx) {
+    for (; xml && idx; idx--) {
+       xml = xml->next;
+    }
+
+    return xml;
+}
+
+// returns the value of the requested tag attribute or NULL if not found
+const char * v3_xml_attr(struct v3_xml * xml, const char * attr) {
+    int i = 0;
+    int j = 1;
+    struct v3_xml_root * root = (struct v3_xml_root *)xml;
+
+    if ((!xml) || (!xml->attr)) {
+       return NULL;
+    }
+
+    while ((xml->attr[i]) && (strcasecmp(attr, xml->attr[i]) != 0)) {
+       i += 2;
+    }
+
+    if (xml->attr[i] != NULL) {
+       return xml->attr[i + 1]; // found attribute
+    }
+
+    while (root->xml.parent != NULL) {
+       root = (struct v3_xml_root *)root->xml.parent; // root tag
+    }
+
+    for (i = 0; 
+        ( (root->attr[i] != NULL) && 
+          (strcasecmp(xml->name, root->attr[i][0]) != 0) ); 
+        i++);
+
+    if (! root->attr[i]) {
+       return NULL; // no matching default attributes
+    }
+
+    while ((root->attr[i][j] != NULL) && (strcasecmp(attr, root->attr[i][j]) != 0)) {
+       j += 3;
+    }
+
+    return (root->attr[i][j] != NULL) ? root->attr[i][j + 1] : NULL; // found default
+}
+
+// same as v3_xml_get but takes an already initialized va_list
+static struct v3_xml * v3_xml_vget(struct v3_xml * xml, va_list ap) {
+    char * name = va_arg(ap, char *);
+    int idx = -1;
+
+    if ((name != NULL) && (*name != 0)) {
+        idx = va_arg(ap, int);    
+        xml = v3_xml_child(xml, name);
+    }
+    return (idx < 0) ? xml : v3_xml_vget(v3_xml_idx(xml, idx), ap);
+}
+
+// Traverses the xml tree to retrieve a specific subtag. Takes a variable
+// length list of tag names and indexes. The argument list must be terminated
+// by either an index of -1 or an empty string tag name. Example: 
+// title = v3_xml_get(library, "shelf", 0, "book", 2, "title", -1);
+// This retrieves the title of the 3rd book on the 1st shelf of library.
+// Returns NULL if not found.
+struct v3_xml * v3_xml_get(struct v3_xml * xml, ...) {
+    va_list ap;
+    struct v3_xml * r;
+
+    va_start(ap, xml);
+    r = v3_xml_vget(xml, ap);
+    va_end(ap);
+    return r;
+}
+
+
+// sets a flag for the given tag and returns the tag
+static struct v3_xml * v3_xml_set_flag(struct v3_xml * xml, short flag)
+{
+    if (xml) xml->flags |= flag;
+    return xml;
+}
+
+
+
+
+
+// Recursively decodes entity and character references and normalizes new lines
+// ent is a null terminated array of alternating entity names and values. set t
+// to '&' for general entity decoding, '%' for parameter entity decoding, 'c'
+// for cdata sections, ' ' for attribute normalization, or '*' for non-cdata
+// attribute normalization. Returns s, or if the decoded string is longer than
+// s, returns a malloced string that must be freed.
+static char * v3_xml_decode(char * s, char ** ent, char t) {
+    char * e;
+    char * r = s;
+    char * m = s;
+    long b, c, d, l;
+
+    // normalize line endings
+    for (; *s; s++) { 
+        while (*s == '\r') {
+            *(s++) = '\n';
+
+            if (*s == '\n') {
+               memmove(s, (s + 1), strlen(s));
+           }
+        }
+    }
+    
+    for (s = r; ; ) {
+
+        while ( (*s) && 
+               (*s != '&') && 
+               ( (*s != '%') || 
+                 (t != '%')) && 
+               (!isspace(*s))) {
+           s++;
+       }
+
+        if (*s == '\0') {
+           break;
+       }
+
+       if ((t != 'c') && (strncmp(s, "&#", 2) == 0)) { // character reference
+            if (s[2] == 'x') {
+               c = strtox(s + 3, &e); // base 16
+           } else {
+               c = strtoi(s + 2, &e); // base 10
+           }
+
+            if ((!c) || (*e != ';')) { 
+               // not a character ref
+               s++; 
+               continue;
+           }
+
+           *(s++) = c; 
+
+            memmove(s, strchr(s, ';') + 1, strlen(strchr(s, ';')));
+        } else if ( ( (*s == '&') && 
+                     ((t == '&') || (t == ' ') || (t == '*'))) ||
+                   ( (*s == '%') && (t == '%'))) { 
+           // entity reference`
+
+            for ( (b = 0); 
+                 (ent[b]) && (strncmp(s + 1, ent[b], strlen(ent[b])) != 0);
+                 (b += 2)); // find entity in entity list
+
+            if (ent[b++]) { // found a match
+                if (((c = strlen(ent[b])) - 1) > ((e = strchr(s, ';')) - s)) {
+                    l = (d = (s - r)) + c + strlen(e); // new length
+                    r = ((r == m) ? strcpy(V3_Malloc(l), r) : tmp_realloc(r, strlen(r), l));
+                    e = strchr((s = r + d), ';'); // fix up pointers
+                }
+
+                memmove(s + c, e + 1, strlen(e)); // shift rest of string
+                strncpy(s, ent[b], c); // copy in replacement text
+            } else {
+               // not a known entity
+               s++;
+           }
+        } else if ( ( (t == ' ') || (t == '*')) && 
+                   (isspace(*s))) {
+           *(s++) = ' ';
+       } else {
+           // no decoding needed
+           s++;
+       }
+    }
+
+    if (t == '*') { 
+       // normalize spaces for non-cdata attributes
+        for (s = r; *s; s++) {
+            if ((l = strspn(s, " "))) {
+               memmove(s, s + l, strlen(s + l) + 1);
+           }
+
+            while ((*s) && (*s != ' ')) {
+               s++;
+           }
+        }
+
+        if ((--s >= r) && (*s == ' ')) {
+           // trim any trailing space
+           *s = '\0'; 
+       }
+    }
+    return r;
+}
+
+
+
+// called when parser finds character content between open and closing tag
+static void v3_xml_char_content(struct v3_xml_root * root, char * s, size_t len, char t) {
+    struct v3_xml * xml = root->cur;
+    char * m = s;
+    size_t l = 0;
+
+    if ((xml == NULL) || (xml->name == NULL) || (len == 0)) {
+       // sanity check
+       return;
+    }
+
+    s[len] = '\0'; // null terminate text (calling functions anticipate this)
+    len = strlen(s = v3_xml_decode(s, root->ent, t)) + 1;
+
+    if (! *(xml->txt)) {
+       // initial character content
+       xml->txt = s;
+    } else { 
+       // allocate our own memory and make a copy
+        xml->txt = (xml->flags & V3_XML_TXTM) ? 
+           (tmp_realloc(xml->txt, strlen(xml->txt), (l = strlen(xml->txt)) + len)) : 
+           (strcpy(V3_Malloc((l = strlen(xml->txt)) + len), xml->txt));
+
+        strcpy(xml->txt + l, s); // add new char content
+       
+        if (s != m) {
+           V3_Free(s); // free s if it was malloced by v3_xml_decode()
+       }
+    }
+
+    if (xml->txt != m) {
+       v3_xml_set_flag(xml, V3_XML_TXTM);
+    }
+}
+
+// called when parser finds closing tag
+static int v3_xml_close_tag(struct v3_xml_root * root, char * name, char * s) {
+    if ( (root->cur == NULL) || 
+        (root->cur->name == NULL) || 
+        (strcasecmp(name, root->cur->name))) {
+       v3_xml_err(root, s, "unexpected closing tag </%s>", name);
+       return -1;
+    }
+
+    root->cur = root->cur->parent;
+    return 0;
+}
+
+// checks for circular entity references, returns non-zero if no circular
+// references are found, zero otherwise
+static int v3_xml_ent_ok(char * name, char * s, char ** ent) {
+    int i;
+
+    for (; ; s++) {
+        while ((*s != '\0') && (*s != '&')) {
+           // find next entity reference
+           s++; 
+       }
+
+        if (*s == '\0') {
+           return 1;
+       }
+
+        if (strncmp(s + 1, name, strlen(name)) == 0) {
+           // circular ref.
+           return 0;
+       }
+
+        for (i = 0; (ent[i]) && (strncmp(ent[i], s + 1, strlen(ent[i]))); i += 2);
+
+        if ((ent[i] != NULL) && (v3_xml_ent_ok(name, ent[i + 1], ent) == 0)) {
+           return 0;
+       }
+    }
+}
+
+
+
+// frees a tag attribute list
+static void v3_xml_free_attr(char **attr) {
+    int i = 0;
+    char * m;
+    
+    if ((attr == NULL) || (attr == empty_attrib_list)) {
+       // nothing to free
+       return; 
+    }
+
+    while (attr[i]) {
+       // find end of attribute list
+       i += 2;
+    }
+
+    m = attr[i + 1]; // list of which names and values are malloced
+
+    for (i = 0; m[i]; i++) {
+        if (m[i] & V3_XML_NAMEM) {
+           V3_Free(attr[i * 2]);
+       }
+
+        if (m[i] & V3_XML_TXTM) {
+           V3_Free(attr[(i * 2) + 1]);
+       }
+    }
+
+    V3_Free(m);
+    V3_Free(attr);
+}
+
+
+
+
+
+
+// returns a new empty v3_xml structure with the given root tag name
+static struct v3_xml * v3_xml_new(const char * name) {
+    static char * ent[] = { "lt;", "&#60;", "gt;", "&#62;", "quot;", "&#34;",
+                           "apos;", "&#39;", "amp;", "&#38;", NULL };
+
+    struct v3_xml_root * root = (struct v3_xml_root *)V3_Malloc(sizeof(struct v3_xml_root));
+    memset(root, 0, sizeof(struct v3_xml_root));
+
+    root->xml.name = (char *)name;
+    root->cur = &root->xml;
+    root->xml.txt = "";
+    memset(root->err, 0, V3_XML_ERRL);
+
+    root->ent = V3_Malloc(sizeof(ent));
+    memcpy(root->ent, ent, sizeof(ent));
+
+    root->xml.attr = empty_attrib_list;
+    root->attr = (char ***)(empty_attrib_list);
+
+    return &root->xml;
+}
+
+// inserts an existing tag into an v3_xml structure
+static struct v3_xml * v3_xml_insert(struct v3_xml * xml, struct v3_xml * dest, size_t off) {
+    struct v3_xml * cur, * prev, * head;
+
+    xml->next = NULL;
+    xml->sibling = NULL;
+    xml->ordered = NULL;
+    
+    xml->off = off;
+    xml->parent = dest;
+
+    if ((head = dest->child)) { 
+       // already have sub tags
+
+        if (head->off <= off) {
+           // not first subtag
+
+            for (cur = head; 
+                ((cur->ordered) && (cur->ordered->off <= off));
+                 cur = cur->ordered);
+
+            xml->ordered = cur->ordered;
+            cur->ordered = xml;
+        } else { 
+           // first subtag
+            xml->ordered = head;
+            dest->child = xml;
+        }
+
+       // find tag type
+        for (cur = head, prev = NULL; 
+            ((cur) && (strcasecmp(cur->name, xml->name) != 0));
+             prev = cur, cur = cur->sibling); 
+
+
+        if (cur && cur->off <= off) { 
+           // not first of type
+            
+           while (cur->next && cur->next->off <= off) {
+               cur = cur->next;
+           }
+
+            xml->next = cur->next;
+            cur->next = xml;
+        } else { 
+           // first tag of this type
+           
+            if (prev && cur) {
+               // remove old first
+               prev->sibling = cur->sibling;
+           }
+
+            xml->next = cur; // old first tag is now next
+
+           // new sibling insert point
+            for (cur = head, prev = NULL; 
+                ((cur) && (cur->off <= off));
+                 prev = cur, cur = cur->sibling);
+           
+            xml->sibling = cur;
+
+            if (prev) {
+               prev->sibling = xml;
+           }
+        }
+    } else {
+       // only sub tag
+       dest->child = xml;
+    }
+
+    return xml;
+}
+
+
+// Adds a child tag. off is the offset of the child tag relative to the start
+// of the parent tag's character content. Returns the child tag.
+static struct v3_xml * v3_xml_add_child(struct v3_xml * xml, const char * name, size_t off) {
+    struct v3_xml * child;
+
+    if (xml == NULL) {
+       return NULL;
+    }
+
+    child = (struct v3_xml *)V3_Malloc(sizeof(struct v3_xml));
+    memset(child, 0, sizeof(struct v3_xml));
+
+    child->name = (char *)name;
+    child->attr = empty_attrib_list;
+    child->txt = "";
+
+    return v3_xml_insert(child, xml, off);
+}
+
+
+// called when parser finds start of new tag
+static void v3_xml_open_tag(struct v3_xml_root * root, char * name, char ** attr) {
+    struct v3_xml * xml = root->cur;
+    
+    if (xml->name) {
+       xml = v3_xml_add_child(xml, name, strlen(xml->txt));
+    } else {
+       // first open tag
+       xml->name = name; 
+    }
+
+    xml->attr = attr;
+    root->cur = xml; // update tag insertion point
+}
+
+
+
+
+
+
+
+// parse the given xml string and return an v3_xml structure
+static struct v3_xml * parse_str(char * buf, size_t len) {
+    struct v3_xml_root * root = (struct v3_xml_root *)v3_xml_new(NULL);
+    char quote_char;
+    char last_char; 
+    char * tag_ptr;
+    char ** attr; 
+    char ** tmp_attr = NULL; // initialize a to avoid compile warning
+    int attr_idx;
+    int i, j;
+
+    root->str_ptr = buf;
+
+    if (len == 0) {
+       v3_xml_err(root, NULL, "Empty XML String\n");
+       return NULL;
+    }
+
+    root->tmp_start = buf;
+    root->tmp_end = buf + len; // record start and end of work area
+    
+    last_char = buf[len - 1]; // save end char
+    buf[len - 1] = '\0'; // turn end char into null terminator
+
+    while ((*buf) && (*buf != '<')) {
+       // find first tag
+       buf++; 
+    }
+
+    if (*buf == '\0') {
+       v3_xml_err(root, buf, "root tag missing");
+       return NULL;
+    }
+
+    for (; ; ) {
+        attr = (char **)empty_attrib_list;
+        tag_ptr = ++buf; // skip first '<'
+        
+        if (isalpha(*buf) || (*buf == '_') || (*buf == ':') || (*buf < '\0')) {
+           // new tag
+
+            if (root->cur == NULL) {
+                v3_xml_err(root, tag_ptr, "markup outside of root element");
+               return NULL;
+           }
+
+            buf += strcspn(buf, V3_XML_WS "/>");
+
+            while (isspace(*buf)) {
+               // null terminate tag name, 
+               // this writes '\0' to spaces after first tag 
+               *(buf++) = '\0';
+           }
+
+           // check if attribute follows tag
+            if ((*buf) && (*buf != '/') && (*buf != '>')) {
+               // there is an attribute
+               // find attributes for correct tag
+                for ((i = 0); 
+                    ((tmp_attr = root->attr[i]) && 
+                     (strcasecmp(tmp_attr[0], tag_ptr) != 0)); 
+                    (i++)) ;
+               
+               // 'tmp_attr' now points to the attribute list associated with 'tag_ptr'
+           }
+
+           // attributes are name value pairs, 
+           //     2nd to last entry is null  (end of list)
+           //     last entry points to a string map marking whether values have been malloced...
+           // loop through attributes until hitting the closing bracket
+            for (attr_idx = 0; 
+                (*buf) && (*buf != '/') && (*buf != '>'); 
+                attr_idx += 2) {
+               // buf is incremented later on
+               // new attrib
+               int attr_cnt = (attr_idx / 2) + 1;
+               int val_idx = attr_idx + 1;
+               int term_idx = attr_idx + 2;
+               int last_idx = attr_idx + 3;
+
+               // attr = allocated space
+               // attr[val_idx] = mem for list of maloced vals
+               if (attr_cnt > 1) {
+                   attr = tmp_realloc(attr,
+                                      (((attr_cnt - 1) * (2 * sizeof(char *))) + 
+                                       (2 * sizeof(char *))), 
+                                      ((attr_cnt * (2 * sizeof(char *))) + 
+                                       (2 * sizeof(char *))));
+               
+                   attr[last_idx] = tmp_realloc(attr[last_idx - 2], 
+                                                attr_cnt,
+                                                (attr_cnt + 1)); 
+               } else {
+                   attr = V3_Malloc(4 * sizeof(char *)); 
+                   attr[last_idx] = V3_Malloc(2);
+               }
+               
+
+                attr[attr_idx] = buf; // set attribute name
+                attr[val_idx] = ""; // temporary attribute value
+                attr[term_idx] = NULL; // null terminate list
+                strcpy(attr[last_idx] + attr_cnt, " "); // value is not malloc'd, offset into the stringmap
+
+                buf += strcspn(buf, V3_XML_WS "=/>");
+
+                if ((*buf == '=') || isspace(*buf)) {
+                    
+                   *(buf++) = '\0'; // null terminate tag attribute name
+                   
+                   // eat whitespace (and more multiple '=' ?)
+                   buf += strspn(buf, V3_XML_WS "=");
+
+                   quote_char = *buf;
+
+                   if ((quote_char == '"') || (quote_char == '\'')) { // attribute value
+                        attr[val_idx] = ++buf;
+
+                        while ((*buf) && (*buf != quote_char)) {
+                           buf++;
+                       }
+
+                        if (*buf) {
+                           // null terminate attribute val
+                           *(buf++) = '\0';
+                       } else {
+                            v3_xml_free_attr(attr);
+                            v3_xml_err(root, tag_ptr, "missing %c", quote_char);
+                           return NULL;
+                        }
+
+                        for (j = 1; 
+                            ( (tmp_attr) && (tmp_attr[j]) && 
+                              (strcasecmp(tmp_attr[j], attr[attr_idx]) != 0)); 
+                            j += 3);
+
+                        attr[val_idx] = v3_xml_decode(attr[val_idx], root->ent, 
+                                                     ((tmp_attr && tmp_attr[j]) ? 
+                                                      *tmp_attr[j + 2] : 
+                                                      ' '));
+                       
+                        if ( (attr[val_idx] < tag_ptr) || 
+                            (attr[val_idx] > buf) ) {
+                            attr[last_idx][attr_cnt - 1] = V3_XML_TXTM; // value malloced
+                       }
+                    }
+                }
+
+                while (isspace(*buf)) {
+                   buf++;
+               }
+            }
+
+            if (*buf == '/') { 
+               // self closing tag
+                *(buf++) = '\0';
+                
+               if ( ((*buf) && (*buf != '>')) || 
+                    ((!*buf) && (last_char != '>'))) {
+
+                    if (attr_idx > 0) {
+                       v3_xml_free_attr(attr);
+                   }
+                   v3_xml_err(root, tag_ptr, "missing >");
+                   return NULL;
+                }
+                v3_xml_open_tag(root, tag_ptr, attr);
+                v3_xml_close_tag(root, tag_ptr, buf);
+            } else if (((quote_char = *buf) == '>') || 
+                      ((!*buf) && (last_char == '>'))) {
+               // open tag
+                *buf = '\0'; // temporarily null terminate tag name
+                v3_xml_open_tag(root, tag_ptr, attr);
+                *buf = quote_char;
+            } else {
+                if (attr_idx > 0) {
+                   v3_xml_free_attr(attr);
+               }
+               v3_xml_err(root, tag_ptr, "missing >"); 
+               return NULL;
+            }
+        } else if (*buf == '/') { 
+           // close tag
+            
+           buf += strcspn(tag_ptr = buf + 1, V3_XML_WS ">") + 1;
+            
+           quote_char = *buf;
+           if ((*buf == '\0') && (last_char != '>')) {
+               v3_xml_err(root, tag_ptr, "missing >");
+               return NULL;
+            }
+
+           *buf = '\0'; // temporarily null terminate tag name
+            
+           if (v3_xml_close_tag(root, tag_ptr, buf) == -1) {
+               return NULL;
+           }
+
+           *buf = quote_char;
+            if (isspace(*buf)) {
+               buf += strspn(buf, V3_XML_WS);
+           }
+        } else if (strncmp(buf, "!--", 3) == 0) {
+           // xml comment
+            if ( ((buf = strstr(buf + 3, "--")) == 0) || 
+                ((*(buf += 2) != '>') && (*buf)) ||
+                ((!*buf) && (last_char != '>'))) {
+               v3_xml_err(root, tag_ptr, "unclosed <!--");
+               return NULL;
+           }
+        } else if (! strncmp(buf, "![CDATA[", 8)) { 
+           // cdata
+            if ((buf = strstr(buf, "]]>"))) {
+                v3_xml_char_content(root, tag_ptr + 8, (buf += 2) - tag_ptr - 10, 'c');
+           } else {
+               v3_xml_err(root, tag_ptr, "unclosed <![CDATA[");
+               return NULL;
+           }
+       } else {
+           v3_xml_err(root, tag_ptr, "unexpected <");
+           return NULL;
+        }
+
+        if (! buf || ! *buf) {
+           break;
+       }
+
+        *buf = '\0';
+        tag_ptr = ++buf;
+
+        if (*buf && (*buf != '<')) { 
+           // tag character content
+            while (*buf && (*buf != '<')) {
+               buf++;
+           }
+
+            if (*buf) { 
+               v3_xml_char_content(root, tag_ptr, buf - tag_ptr, '&');
+           } else {
+               break;
+           }
+        } else if (*buf == '\0') {
+           break;
+       }
+    }
+
+    if (root->cur == NULL) {
+       return &root->xml;
+    } else if (root->cur->name == NULL) {
+       v3_xml_err(root, tag_ptr, "root tag missing");
+       return NULL;
+    } else {
+       v3_xml_err(root, tag_ptr, "unclosed tag <%s>", root->cur->name);
+       return NULL;
+    }
+}
+
+
+struct v3_xml * v3_xml_parse(char * buf) {
+    int str_len = 0;
+    char * xml_buf = NULL;
+
+    if (!buf) {
+       return NULL;
+    }
+
+    str_len = strlen(buf);
+    xml_buf = (char *)V3_Malloc(str_len + 1);
+    strcpy(xml_buf, buf);
+
+    return parse_str(xml_buf, str_len);
+}
+
+
+
+// free the memory allocated for the v3_xml structure
+void v3_xml_free(struct v3_xml * xml) {
+    struct v3_xml_root * root = (struct v3_xml_root *)xml;
+    int i, j;
+    char **a, *s;
+
+    if (xml == NULL) {
+        return;
+    }
+
+    v3_xml_free(xml->child);
+    v3_xml_free(xml->ordered);
+
+    if (xml->parent == NULL) { 
+       // free root tag allocations
+        
+       for (i = 10; root->ent[i]; i += 2) {
+           // 0 - 9 are default entites (<>&"')
+            if ((s = root->ent[i + 1]) < root->tmp_start || s > root->tmp_end) {
+               V3_Free(s);
+           }
+       }
+
+       V3_Free(root->ent); // free list of general entities
+
+        for (i = 0; (a = root->attr[i]); i++) {
+            for (j = 1; a[j++]; j += 2) {
+               // free malloced attribute values
+                if (a[j] && (a[j] < root->tmp_start || a[j] > root->tmp_end)) {
+                   V3_Free(a[j]);
+               }
+           }
+            V3_Free(a);
+        }
+
+        if (root->attr[0]) {
+           // free default attribute list
+           V3_Free(root->attr);
+       }
+
+       V3_Free(root->str_ptr); // malloced xml data
+    }
+
+    v3_xml_free_attr(xml->attr); // tag attributes
+
+    if ((xml->flags & V3_XML_TXTM)) {
+       // character content
+       V3_Free(xml->txt); 
+    }
+
+    if ((xml->flags & V3_XML_NAMEM)) {
+       // tag name
+       V3_Free(xml->name);
+    }
+
+    V3_Free(xml);
+}
+
diff --git a/utils/binutils-2.16.91.0.7.tar.gz b/utils/binutils-2.16.91.0.7.tar.gz
deleted file mode 100644 (file)
index 32209e2..0000000
Binary files a/utils/binutils-2.16.91.0.7.tar.gz and /dev/null differ
diff --git a/utils/gcc-3.4.6.tar.gz b/utils/gcc-3.4.6.tar.gz
deleted file mode 100644 (file)
index b6bc0f3..0000000
Binary files a/utils/gcc-3.4.6.tar.gz and /dev/null differ
diff --git a/utils/guest_creator/Makefile b/utils/guest_creator/Makefile
new file mode 100644 (file)
index 0000000..0bc5172
--- /dev/null
@@ -0,0 +1,16 @@
+
+CC = gcc
+CFLAGS = -Wall -g 
+LDFLAGS = 
+
+
+OBJS = main.c ezxml.c
+
+all: builder
+
+
+builder: $(OBJS)
+       $(CC) $(CFLAGS) $(OBJS) -o build_vm
+
+clean:         
+       rm -f *.o build_vm
\ No newline at end of file
diff --git a/utils/guest_creator/README b/utils/guest_creator/README
new file mode 100644 (file)
index 0000000..80e4e88
--- /dev/null
@@ -0,0 +1,20 @@
+Copyright 2004-2006 Aaron Voisine <aaron@voisine.org>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/utils/guest_creator/default.xml b/utils/guest_creator/default.xml
new file mode 100644 (file)
index 0000000..9d8414a
--- /dev/null
@@ -0,0 +1,229 @@
+
+<!-- This defines a PC VM. The class defines the initial cpu/memory state of the VM. This drives the initialization of CPU registers, as well as BIOS memory mappings.-->
+<vm class="PC"> 
+
+       <!-- Memory in MB -->
+       <memory>1024</memory> 
+
+       <!-- Basic VMM system flags -->
+       <telemetry>enable</telemetry>
+       <paging>nested</paging>
+       <schedule_hz>100</schedule_hz>
+
+
+       <!-- Memory redirections -->
+       <!-- Redirects a guest's memory region to a host physical address -->
+       <memmap>
+               <!-- This region maps the VGA framebuffer to the host's framebuffer -->
+               <region>
+                       <start>0xa0000</start>
+                       <end>0xc0000</end>
+                       <host_addr>0xa0000</host_addr>
+               </region>
+       </memmap>
+
+
+       <!-- List of binary files to include with configuration -->
+       <!-- This is where you add disk images -->
+       <files>
+               <!-- The file 'id' is used as a reference for other configuration components -->
+               <file id="boot-cd" filename="/home/jarusl/image.iso" />
+               <!--<file id="harddisk" filename="firefox.img" />-->
+       </files>
+
+
+       <!-- List of devices attached to guest -->
+       <!-- The device 'ID' is the device name in the global device registry -->
+       <!-- The device 'name' is the reference to the device instance associated with a VM -->
+       <!--    The name can be used as a reference by other devices -->
+       <devices>
+               <device id="8259A" name="PIC"/>
+               <device id="KEYBOARD" name="keyboard"/>
+               <device id="8254_PIT" name="PIC" />
+               <device id="BOCHS_DEBUG" name="bochs debug"/>
+               <device id="OS_DEBUG" name="os debug" />
+               <device id="LAPIC" name="apic"/>
+               <device id="IOAPIC" name="ioapic">
+                       <irq_bus>apic</irq_bus>
+               </device>
+
+<!--
+               <device id="CGA_VIDEO" name="cga" passthrough="enable" />
+               <device id="TELNET_CONSOLE" name="telnet console">
+                       <frontend tag="CGA_VIDEO" />
+                       <port>19997</port>
+               </device>
+-->
+               <device id="PCI" name="pci0" />
+
+               <device id="i440FX" name="northbridge">
+                       <bus>pci0</bus>
+               </device>
+
+               <device id="PIIX3" name="southbridge">
+                       <bus>pci0</bus>
+               </device>
+
+               <device id="LNX_VIRTIO_SYM" name="sym_pci">
+                       <bus>pci0</bus>
+               </device>
+
+               <device id="LNX_VIRTIO_BLK" name="blk_virtio">
+                       <bus>pci0</bus>
+               </device>
+
+               <device id="LNX_VIRTIO_BALLOON" name="balloon">
+                       <bus>pci0</bus>
+               </device>
+
+               <device id="IDE" name="ide">
+                       <bus>pci0</bus>
+                       <controller>southbridge</controller>
+               </device>
+
+               <device id="PCI_PASSTHROUGH" name="e1000">
+                       <bus>pci0</bus>
+                       <vendor_id>0x8086</vendor_id>
+                       <device_id>0x100e</device_id>
+               </device>
+
+               <device id="PCI_PASSTHROUGH" name="e1000-hw">
+                       <bus>pci0</bus>
+                       <vendor_id>0x8086</vendor_id>
+                       <device_id>0x107c</device_id>
+                       <irq>59</irq>
+               </device>
+
+
+               <!-- This is a Storage Backend that connects to a frontend -->
+               <!-- The frontend section is passed to the frontend when the backend connects -->
+               <!-- The file tag refers to an 'id' already listed in the file list section above -->
+               <device id="RAMDISK" name="CD0">
+                       <file>boot-cd</file>
+                       <frontend tag="ide">
+                               <model>V3Vee CDROM</model>
+                               <type>CDROM</type>
+                               <bus_num>0</bus_num>
+                               <drive_num>0</drive_num>
+                       </frontend>
+               </device>
+
+               <device id="SYM_SWAP" name="sym swap">
+                       <frontend tag="blk_virtio" />
+                       <size>150</size>
+               </device>
+
+
+<!--
+               <device id="RAMDISK" name="HD0">
+                       <file>harddisk</file>
+                       <frontend tag="blk_virtio" />
+               </device>
+-->
+
+               <device id="NVRAM" name="nvram">
+                       <storage>ide</storage>
+               </device>
+
+               <device id="GENERIC" name="generic">
+                       <ports>
+                               <start>0x00</start>
+                               <end>0x07</end>
+                               <mode>PRINT_AND_IGNORE</mode>
+                       </ports>
+                       <ports>
+                               <start>0xc0</start>
+                               <end>0xc7</end>
+                               <mode>PRINT_AND_IGNORE</mode>
+                       </ports>
+                       <ports>
+                               <!-- DMA 1 page registers -->
+                               <start>0x81</start>
+                               <end>0x87</end>
+                               <mode>PRINT_AND_IGNORE</mode>
+                       </ports>
+                       <ports>
+                               <!-- DMA 2 page registers -->
+                               <start>0x88</start>
+                               <end>0x8f</end>
+                               <mode>PRINT_AND_IGNORE</mode>
+                       </ports>
+                       <ports>
+                               <!-- DMA 1 Misc Registers -->
+                               <start>0x08</start>
+                               <end>0x0f</end>
+                               <mode>PRINT_AND_IGNORE</mode>
+                       </ports>
+                       <ports>
+                               <!-- DMA 2 Misc Registers -->
+                               <start>0xd0</start>
+                               <end>0xde</end>
+                               <mode>PRINT_AND_IGNORE</mode>
+                       </ports>
+                       <ports>
+                               <!-- Serial COM 1 -->
+                               <start>0x3f8</start>
+                               <end>0x3ff</end>
+                               <mode>PRINT_AND_IGNORE</mode>
+                       </ports>
+                       <ports>
+                               <!-- Serial COM 2 -->
+                               <start>0x2f8</start>
+                               <end>0x2ff</end>
+                               <mode>PRINT_AND_IGNORE</mode>
+                       </ports>
+                       <ports>
+                               <!-- Serial COM 3 -->
+                               <start>0x3e8</start>
+                               <end>0x3ef</end>
+                               <mode>PRINT_AND_IGNORE</mode>
+                       </ports>
+                       <ports>
+                               <!-- Serial COM 4 -->
+                               <start>0x2e8</start>
+                               <end>0x2ef</end>
+                               <mode>PRINT_AND_IGNORE</mode>
+                       </ports>
+                       <ports>
+                               <!-- Parallel Port -->
+                               <start>0x378</start>
+                               <end>0x37f</end>
+                               <mode>PRINT_AND_IGNORE</mode>
+                       </ports>
+                       <ports>
+                               <!-- Graphics Card modeerations -->
+                               <start>0x3b0</start>
+                               <end>0x3bb</end>
+                               <mode>PRINT_AND_PASSTHROUGH</mode>
+                       </ports>
+                       <ports>
+                               <!-- Graphics Card modeerations -->
+                               <start>0x3c0</start>
+                               <end>0x3df</end>
+                               <mode>PRINT_AND_PASSTHROUGH</mode>
+                       </ports>
+                       <ports>
+                               <!-- ISA PNP -->
+                               <start>0x274</start>
+                               <end>0x277</end>
+                               <mode>PRINT_AND_IGNORE</mode>
+                       </ports>
+                       <ports>
+                               <!-- ISA PNP -->
+                               <start>0x279</start>
+                               <end>0x279</end>
+                               <mode>PRINT_AND_IGNORE</mode>
+                       </ports>
+                       <ports>
+                               <!-- ISA PNP -->
+                               <start>0xa79</start>
+                               <end>0xa79</end>
+                               <mode>PRINT_AND_IGNORE</mode>
+                       </ports>
+               </device>
+       </devices>
+
+
+</vm>
+
+
diff --git a/utils/guest_creator/ezxml.c b/utils/guest_creator/ezxml.c
new file mode 100644 (file)
index 0000000..82b11fb
--- /dev/null
@@ -0,0 +1,1015 @@
+/* ezxml.c
+ *
+ * Copyright 2004-2006 Aaron Voisine <aaron@voisine.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <sys/types.h>
+#ifndef EZXML_NOMMAP
+#include <sys/mman.h>
+#endif // EZXML_NOMMAP
+#include <sys/stat.h>
+#include "ezxml.h"
+
+#define EZXML_WS   "\t\r\n "  // whitespace
+#define EZXML_ERRL 128        // maximum error string length
+
+typedef struct ezxml_root *ezxml_root_t;
+struct ezxml_root {       // additional data for the root tag
+    struct ezxml xml;     // is a super-struct built on top of ezxml struct
+    ezxml_t cur;          // current xml tree insertion point
+    char *m;              // original xml string
+    size_t len;           // length of allocated memory for mmap, -1 for malloc
+    char *u;              // UTF-8 conversion of string if original was UTF-16
+    char *s;              // start of work area
+    char *e;              // end of work area
+    char **ent;           // general entities (ampersand sequences)
+    char ***attr;         // default attributes
+    char ***pi;           // processing instructions
+    short standalone;     // non-zero if <?xml standalone="yes"?>
+    char err[EZXML_ERRL]; // error string
+};
+
+char *EZXML_NIL[] = { NULL }; // empty, null terminated array of strings
+
+// returns the first child tag with the given name or NULL if not found
+ezxml_t ezxml_child(ezxml_t xml, const char *name)
+{
+    xml = (xml) ? xml->child : NULL;
+    while (xml && strcmp(name, xml->name)) xml = xml->sibling;
+    return xml;
+}
+
+// returns the Nth tag with the same name in the same subsection or NULL if not
+// found
+ezxml_t ezxml_idx(ezxml_t xml, int idx)
+{
+    for (; xml && idx; idx--) xml = xml->next;
+    return xml;
+}
+
+// returns the value of the requested tag attribute or NULL if not found
+const char *ezxml_attr(ezxml_t xml, const char *attr)
+{
+    int i = 0, j = 1;
+    ezxml_root_t root = (ezxml_root_t)xml;
+
+    if (! xml || ! xml->attr) return NULL;
+    while (xml->attr[i] && strcmp(attr, xml->attr[i])) i += 2;
+    if (xml->attr[i]) return xml->attr[i + 1]; // found attribute
+
+    while (root->xml.parent) root = (ezxml_root_t)root->xml.parent; // root tag
+    for (i = 0; root->attr[i] && strcmp(xml->name, root->attr[i][0]); i++);
+    if (! root->attr[i]) return NULL; // no matching default attributes
+    while (root->attr[i][j] && strcmp(attr, root->attr[i][j])) j += 3;
+    return (root->attr[i][j]) ? root->attr[i][j + 1] : NULL; // found default
+}
+
+// same as ezxml_get but takes an already initialized va_list
+ezxml_t ezxml_vget(ezxml_t xml, va_list ap)
+{
+    char *name = va_arg(ap, char *);
+    int idx = -1;
+
+    if (name && *name) {
+        idx = va_arg(ap, int);    
+        xml = ezxml_child(xml, name);
+    }
+    return (idx < 0) ? xml : ezxml_vget(ezxml_idx(xml, idx), ap);
+}
+
+// Traverses the xml tree to retrieve a specific subtag. Takes a variable
+// length list of tag names and indexes. The argument list must be terminated
+// by either an index of -1 or an empty string tag name. Example: 
+// title = ezxml_get(library, "shelf", 0, "book", 2, "title", -1);
+// This retrieves the title of the 3rd book on the 1st shelf of library.
+// Returns NULL if not found.
+ezxml_t ezxml_get(ezxml_t xml, ...)
+{
+    va_list ap;
+    ezxml_t r;
+
+    va_start(ap, xml);
+    r = ezxml_vget(xml, ap);
+    va_end(ap);
+    return r;
+}
+
+// returns a null terminated array of processing instructions for the given
+// target
+const char **ezxml_pi(ezxml_t xml, const char *target)
+{
+    ezxml_root_t root = (ezxml_root_t)xml;
+    int i = 0;
+
+    if (! root) return (const char **)EZXML_NIL;
+    while (root->xml.parent) root = (ezxml_root_t)root->xml.parent; // root tag
+    while (root->pi[i] && strcmp(target, root->pi[i][0])) i++; // find target
+    return (const char **)((root->pi[i]) ? root->pi[i] + 1 : EZXML_NIL);
+}
+
+// set an error string and return root
+ezxml_t ezxml_err(ezxml_root_t root, char *s, const char *err, ...)
+{
+    va_list ap;
+    int line = 1;
+    char *t, fmt[EZXML_ERRL];
+    
+    for (t = root->s; t < s; t++) if (*t == '\n') line++;
+    snprintf(fmt, EZXML_ERRL, "[error near line %d]: %s", line, err);
+
+    va_start(ap, err);
+    vsnprintf(root->err, EZXML_ERRL, fmt, ap);
+    va_end(ap);
+
+    return &root->xml;
+}
+
+// Recursively decodes entity and character references and normalizes new lines
+// ent is a null terminated array of alternating entity names and values. set t
+// to '&' for general entity decoding, '%' for parameter entity decoding, 'c'
+// for cdata sections, ' ' for attribute normalization, or '*' for non-cdata
+// attribute normalization. Returns s, or if the decoded string is longer than
+// s, returns a malloced string that must be freed.
+char *ezxml_decode(char *s, char **ent, char t)
+{
+    char *e, *r = s, *m = s;
+    long b, c, d, l;
+
+    for (; *s; s++) { // normalize line endings
+        while (*s == '\r') {
+            *(s++) = '\n';
+            if (*s == '\n') memmove(s, (s + 1), strlen(s));
+        }
+    }
+    
+    for (s = r; ; ) {
+        while (*s && *s != '&' && (*s != '%' || t != '%') && !isspace(*s)) s++;
+
+        if (! *s) break;
+        else if (t != 'c' && ! strncmp(s, "&#", 2)) { // character reference
+            if (s[2] == 'x') c = strtol(s + 3, &e, 16); // base 16
+            else c = strtol(s + 2, &e, 10); // base 10
+            if (! c || *e != ';') { s++; continue; } // not a character ref
+
+            if (c < 0x80) *(s++) = c; // US-ASCII subset
+            else { // multi-byte UTF-8 sequence
+                for (b = 0, d = c; d; d /= 2) b++; // number of bits in c
+                b = (b - 2) / 5; // number of bytes in payload
+                *(s++) = (0xFF << (7 - b)) | (c >> (6 * b)); // head
+                while (b) *(s++) = 0x80 | ((c >> (6 * --b)) & 0x3F); // payload
+            }
+
+            memmove(s, strchr(s, ';') + 1, strlen(strchr(s, ';')));
+        }
+        else if ((*s == '&' && (t == '&' || t == ' ' || t == '*')) ||
+                 (*s == '%' && t == '%')) { // entity reference
+            for (b = 0; ent[b] && strncmp(s + 1, ent[b], strlen(ent[b]));
+                 b += 2); // find entity in entity list
+
+            if (ent[b++]) { // found a match
+                if ((c = strlen(ent[b])) - 1 > (e = strchr(s, ';')) - s) {
+                    l = (d = (s - r)) + c + strlen(e); // new length
+                    r = (r == m) ? strcpy(malloc(l), r) : realloc(r, l);
+                    e = strchr((s = r + d), ';'); // fix up pointers
+                }
+
+                memmove(s + c, e + 1, strlen(e)); // shift rest of string
+                strncpy(s, ent[b], c); // copy in replacement text
+            }
+            else s++; // not a known entity
+        }
+        else if ((t == ' ' || t == '*') && isspace(*s)) *(s++) = ' ';
+        else s++; // no decoding needed
+    }
+
+    if (t == '*') { // normalize spaces for non-cdata attributes
+        for (s = r; *s; s++) {
+            if ((l = strspn(s, " "))) memmove(s, s + l, strlen(s + l) + 1);
+            while (*s && *s != ' ') s++;
+        }
+        if (--s >= r && *s == ' ') *s = '\0'; // trim any trailing space
+    }
+    return r;
+}
+
+// called when parser finds start of new tag
+void ezxml_open_tag(ezxml_root_t root, char *name, char **attr)
+{
+    ezxml_t xml = root->cur;
+    
+    if (xml->name) xml = ezxml_add_child(xml, name, strlen(xml->txt));
+    else xml->name = name; // first open tag
+
+    xml->attr = attr;
+    root->cur = xml; // update tag insertion point
+}
+
+// called when parser finds character content between open and closing tag
+void ezxml_char_content(ezxml_root_t root, char *s, size_t len, char t)
+{
+    ezxml_t xml = root->cur;
+    char *m = s;
+    size_t l;
+
+    if (! xml || ! xml->name || ! len) return; // sanity check
+
+    s[len] = '\0'; // null terminate text (calling functions anticipate this)
+    len = strlen(s = ezxml_decode(s, root->ent, t)) + 1;
+
+    if (! *(xml->txt)) xml->txt = s; // initial character content
+    else { // allocate our own memory and make a copy
+        xml->txt = (xml->flags & EZXML_TXTM) // allocate some space
+                   ? realloc(xml->txt, (l = strlen(xml->txt)) + len)
+                   : strcpy(malloc((l = strlen(xml->txt)) + len), xml->txt);
+        strcpy(xml->txt + l, s); // add new char content
+        if (s != m) free(s); // free s if it was malloced by ezxml_decode()
+    }
+
+    if (xml->txt != m) ezxml_set_flag(xml, EZXML_TXTM);
+}
+
+// called when parser finds closing tag
+ezxml_t ezxml_close_tag(ezxml_root_t root, char *name, char *s)
+{
+    if (! root->cur || ! root->cur->name || strcmp(name, root->cur->name))
+        return ezxml_err(root, s, "unexpected closing tag </%s>", name);
+
+    root->cur = root->cur->parent;
+    return NULL;
+}
+
+// checks for circular entity references, returns non-zero if no circular
+// references are found, zero otherwise
+int ezxml_ent_ok(char *name, char *s, char **ent)
+{
+    int i;
+
+    for (; ; s++) {
+        while (*s && *s != '&') s++; // find next entity reference
+        if (! *s) return 1;
+        if (! strncmp(s + 1, name, strlen(name))) return 0; // circular ref.
+        for (i = 0; ent[i] && strncmp(ent[i], s + 1, strlen(ent[i])); i += 2);
+        if (ent[i] && ! ezxml_ent_ok(name, ent[i + 1], ent)) return 0;
+    }
+}
+
+// called when the parser finds a processing instruction
+void ezxml_proc_inst(ezxml_root_t root, char *s, size_t len)
+{
+    int i = 0, j = 1;
+    char *target = s;
+
+    s[len] = '\0'; // null terminate instruction
+    if (*(s += strcspn(s, EZXML_WS))) {
+        *s = '\0'; // null terminate target
+        s += strspn(s + 1, EZXML_WS) + 1; // skip whitespace after target
+    }
+
+    if (! strcmp(target, "xml")) { // <?xml ... ?>
+        if ((s = strstr(s, "standalone")) && ! strncmp(s + strspn(s + 10,
+            EZXML_WS "='\"") + 10, "yes", 3)) root->standalone = 1;
+        return;
+    }
+
+    if (! root->pi[0]) *(root->pi = malloc(sizeof(char **))) = NULL; //first pi
+
+    while (root->pi[i] && strcmp(target, root->pi[i][0])) i++; // find target
+    if (! root->pi[i]) { // new target
+        root->pi = realloc(root->pi, sizeof(char **) * (i + 2));
+        root->pi[i] = malloc(sizeof(char *) * 3);
+        root->pi[i][0] = target;
+        root->pi[i][1] = (char *)(root->pi[i + 1] = NULL); // terminate pi list
+        root->pi[i][2] = strdup(""); // empty document position list
+    }
+
+    while (root->pi[i][j]) j++; // find end of instruction list for this target
+    root->pi[i] = realloc(root->pi[i], sizeof(char *) * (j + 3));
+    root->pi[i][j + 2] = realloc(root->pi[i][j + 1], j + 1);
+    strcpy(root->pi[i][j + 2] + j - 1, (root->xml.name) ? ">" : "<");
+    root->pi[i][j + 1] = NULL; // null terminate pi list for this target
+    root->pi[i][j] = s; // set instruction
+}
+
+// called when the parser finds an internal doctype subset
+short ezxml_internal_dtd(ezxml_root_t root, char *s, size_t len)
+{
+    char q, *c, *t, *n = NULL, *v, **ent, **pe;
+    int i, j;
+    
+    pe = memcpy(malloc(sizeof(EZXML_NIL)), EZXML_NIL, sizeof(EZXML_NIL));
+
+    for (s[len] = '\0'; s; ) {
+        while (*s && *s != '<' && *s != '%') s++; // find next declaration
+
+        if (! *s) break;
+        else if (! strncmp(s, "<!ENTITY", 8)) { // parse entity definitions
+            c = s += strspn(s + 8, EZXML_WS) + 8; // skip white space separator
+            n = s + strspn(s, EZXML_WS "%"); // find name
+            *(s = n + strcspn(n, EZXML_WS)) = ';'; // append ; to name
+
+            v = s + strspn(s + 1, EZXML_WS) + 1; // find value
+            if ((q = *(v++)) != '"' && q != '\'') { // skip externals
+                s = strchr(s, '>');
+                continue;
+            }
+
+            for (i = 0, ent = (*c == '%') ? pe : root->ent; ent[i]; i++);
+            ent = realloc(ent, (i + 3) * sizeof(char *)); // space for next ent
+            if (*c == '%') pe = ent;
+            else root->ent = ent;
+
+            *(++s) = '\0'; // null terminate name
+            if ((s = strchr(v, q))) *(s++) = '\0'; // null terminate value
+            ent[i + 1] = ezxml_decode(v, pe, '%'); // set value
+            ent[i + 2] = NULL; // null terminate entity list
+            if (! ezxml_ent_ok(n, ent[i + 1], ent)) { // circular reference
+                if (ent[i + 1] != v) free(ent[i + 1]);
+                ezxml_err(root, v, "circular entity declaration &%s", n);
+                break;
+            }
+            else ent[i] = n; // set entity name
+        }
+        else if (! strncmp(s, "<!ATTLIST", 9)) { // parse default attributes
+            t = s + strspn(s + 9, EZXML_WS) + 9; // skip whitespace separator
+            if (! *t) { ezxml_err(root, t, "unclosed <!ATTLIST"); break; }
+            if (*(s = t + strcspn(t, EZXML_WS ">")) == '>') continue;
+            else *s = '\0'; // null terminate tag name
+            for (i = 0; root->attr[i] && strcmp(n, root->attr[i][0]); i++);
+
+            while (*(n = ++s + strspn(s, EZXML_WS)) && *n != '>') {
+                if (*(s = n + strcspn(n, EZXML_WS))) *s = '\0'; // attr name
+                else { ezxml_err(root, t, "malformed <!ATTLIST"); break; }
+
+                s += strspn(s + 1, EZXML_WS) + 1; // find next token
+                c = (strncmp(s, "CDATA", 5)) ? "*" : " "; // is it cdata?
+                if (! strncmp(s, "NOTATION", 8))
+                    s += strspn(s + 8, EZXML_WS) + 8;
+                s = (*s == '(') ? strchr(s, ')') : s + strcspn(s, EZXML_WS);
+                if (! s) { ezxml_err(root, t, "malformed <!ATTLIST"); break; }
+
+                s += strspn(s, EZXML_WS ")"); // skip white space separator
+                if (! strncmp(s, "#FIXED", 6))
+                    s += strspn(s + 6, EZXML_WS) + 6;
+                if (*s == '#') { // no default value
+                    s += strcspn(s, EZXML_WS ">") - 1;
+                    if (*c == ' ') continue; // cdata is default, nothing to do
+                    v = NULL;
+                }
+                else if ((*s == '"' || *s == '\'')  &&  // default value
+                         (s = strchr(v = s + 1, *s))) *s = '\0';
+                else { ezxml_err(root, t, "malformed <!ATTLIST"); break; }
+
+                if (! root->attr[i]) { // new tag name
+                    root->attr = (! i) ? malloc(2 * sizeof(char **))
+                                       : realloc(root->attr,
+                                                 (i + 2) * sizeof(char **));
+                    root->attr[i] = malloc(2 * sizeof(char *));
+                    root->attr[i][0] = t; // set tag name
+                    root->attr[i][1] = (char *)(root->attr[i + 1] = NULL);
+                }
+
+                for (j = 1; root->attr[i][j]; j += 3); // find end of list
+                root->attr[i] = realloc(root->attr[i],
+                                        (j + 4) * sizeof(char *));
+
+                root->attr[i][j + 3] = NULL; // null terminate list
+                root->attr[i][j + 2] = c; // is it cdata?
+                root->attr[i][j + 1] = (v) ? ezxml_decode(v, root->ent, *c)
+                                           : NULL;
+                root->attr[i][j] = n; // attribute name 
+            }
+        }
+        else if (! strncmp(s, "<!--", 4)) s = strstr(s + 4, "-->"); // comments
+        else if (! strncmp(s, "<?", 2)) { // processing instructions
+            if ((s = strstr(c = s + 2, "?>")))
+                ezxml_proc_inst(root, c, s++ - c);
+        }
+        else if (*s == '<') s = strchr(s, '>'); // skip other declarations
+        else if (*(s++) == '%' && ! root->standalone) break;
+    }
+
+    free(pe);
+    return ! *root->err;
+}
+
+// Converts a UTF-16 string to UTF-8. Returns a new string that must be freed
+// or NULL if no conversion was needed.
+char *ezxml_str2utf8(char **s, size_t *len)
+{
+    char *u;
+    size_t l = 0, sl, max = *len;
+    long c, d;
+    int b, be = (**s == '\xFE') ? 1 : (**s == '\xFF') ? 0 : -1;
+
+    if (be == -1) return NULL; // not UTF-16
+
+    u = malloc(max);
+    for (sl = 2; sl < *len - 1; sl += 2) {
+        c = (be) ? (((*s)[sl] & 0xFF) << 8) | ((*s)[sl + 1] & 0xFF)  //UTF-16BE
+                 : (((*s)[sl + 1] & 0xFF) << 8) | ((*s)[sl] & 0xFF); //UTF-16LE
+        if (c >= 0xD800 && c <= 0xDFFF && (sl += 2) < *len - 1) { // high-half
+            d = (be) ? (((*s)[sl] & 0xFF) << 8) | ((*s)[sl + 1] & 0xFF)
+                     : (((*s)[sl + 1] & 0xFF) << 8) | ((*s)[sl] & 0xFF);
+            c = (((c & 0x3FF) << 10) | (d & 0x3FF)) + 0x10000;
+        }
+
+        while (l + 6 > max) u = realloc(u, max += EZXML_BUFSIZE);
+        if (c < 0x80) u[l++] = c; // US-ASCII subset
+        else { // multi-byte UTF-8 sequence
+            for (b = 0, d = c; d; d /= 2) b++; // bits in c
+            b = (b - 2) / 5; // bytes in payload
+            u[l++] = (0xFF << (7 - b)) | (c >> (6 * b)); // head
+            while (b) u[l++] = 0x80 | ((c >> (6 * --b)) & 0x3F); // payload
+        }
+    }
+    return *s = realloc(u, *len = l);
+}
+
+// frees a tag attribute list
+void ezxml_free_attr(char **attr) {
+    int i = 0;
+    char *m;
+    
+    if (! attr || attr == EZXML_NIL) return; // nothing to free
+    while (attr[i]) i += 2; // find end of attribute list
+    m = attr[i + 1]; // list of which names and values are malloced
+    for (i = 0; m[i]; i++) {
+        if (m[i] & EZXML_NAMEM) free(attr[i * 2]);
+        if (m[i] & EZXML_TXTM) free(attr[(i * 2) + 1]);
+    }
+    free(m);
+    free(attr);
+}
+
+// parse the given xml string and return an ezxml structure
+ezxml_t ezxml_parse_str(char *s, size_t len)
+{
+    ezxml_root_t root = (ezxml_root_t)ezxml_new(NULL);
+    char q, e, *d, **attr, **a = NULL; // initialize a to avoid compile warning
+    int l, i, j;
+
+    root->m = s;
+    if (! len) return ezxml_err(root, NULL, "root tag missing");
+    root->u = ezxml_str2utf8(&s, &len); // convert utf-16 to utf-8
+    root->e = (root->s = s) + len; // record start and end of work area
+    
+    e = s[len - 1]; // save end char
+    s[len - 1] = '\0'; // turn end char into null terminator
+
+    while (*s && *s != '<') s++; // find first tag
+    if (! *s) return ezxml_err(root, s, "root tag missing");
+
+    for (; ; ) {
+        attr = (char **)EZXML_NIL;
+        d = ++s;
+        
+        if (isalpha(*s) || *s == '_' || *s == ':' || *s < '\0') { // new tag
+            if (! root->cur)
+                return ezxml_err(root, d, "markup outside of root element");
+
+            s += strcspn(s, EZXML_WS "/>");
+            while (isspace(*s)) *(s++) = '\0'; // null terminate tag name
+  
+            if (*s && *s != '/' && *s != '>') // find tag in default attr list
+                for (i = 0; (a = root->attr[i]) && strcmp(a[0], d); i++);
+
+            for (l = 0; *s && *s != '/' && *s != '>'; l += 2) { // new attrib
+                attr = (l) ? realloc(attr, (l + 4) * sizeof(char *))
+                           : malloc(4 * sizeof(char *)); // allocate space
+                attr[l + 3] = (l) ? realloc(attr[l + 1], (l / 2) + 2)
+                                  : malloc(2); // mem for list of maloced vals
+                strcpy(attr[l + 3] + (l / 2), " "); // value is not malloced
+                attr[l + 2] = NULL; // null terminate list
+                attr[l + 1] = ""; // temporary attribute value
+                attr[l] = s; // set attribute name
+
+                s += strcspn(s, EZXML_WS "=/>");
+                if (*s == '=' || isspace(*s)) { 
+                    *(s++) = '\0'; // null terminate tag attribute name
+                    q = *(s += strspn(s, EZXML_WS "="));
+                    if (q == '"' || q == '\'') { // attribute value
+                        attr[l + 1] = ++s;
+                        while (*s && *s != q) s++;
+                        if (*s) *(s++) = '\0'; // null terminate attribute val
+                        else {
+                            ezxml_free_attr(attr);
+                            return ezxml_err(root, d, "missing %c", q);
+                        }
+
+                        for (j = 1; a && a[j] && strcmp(a[j], attr[l]); j +=3);
+                        attr[l + 1] = ezxml_decode(attr[l + 1], root->ent, (a
+                                                   && a[j]) ? *a[j + 2] : ' ');
+                        if (attr[l + 1] < d || attr[l + 1] > s)
+                            attr[l + 3][l / 2] = EZXML_TXTM; // value malloced
+                    }
+                }
+                while (isspace(*s)) s++;
+            }
+
+            if (*s == '/') { // self closing tag
+                *(s++) = '\0';
+                if ((*s && *s != '>') || (! *s && e != '>')) {
+                    if (l) ezxml_free_attr(attr);
+                    return ezxml_err(root, d, "missing >");
+                }
+                ezxml_open_tag(root, d, attr);
+                ezxml_close_tag(root, d, s);
+            }
+            else if ((q = *s) == '>' || (! *s && e == '>')) { // open tag
+                *s = '\0'; // temporarily null terminate tag name
+                ezxml_open_tag(root, d, attr);
+                *s = q;
+            }
+            else {
+                if (l) ezxml_free_attr(attr);
+                return ezxml_err(root, d, "missing >"); 
+            }
+        }
+        else if (*s == '/') { // close tag
+            s += strcspn(d = s + 1, EZXML_WS ">") + 1;
+            if (! (q = *s) && e != '>') return ezxml_err(root, d, "missing >");
+            *s = '\0'; // temporarily null terminate tag name
+            if (ezxml_close_tag(root, d, s)) return &root->xml;
+            if (isspace(*s = q)) s += strspn(s, EZXML_WS);
+        }
+        else if (! strncmp(s, "!--", 3)) { // xml comment
+            if (! (s = strstr(s + 3, "--")) || (*(s += 2) != '>' && *s) ||
+                (! *s && e != '>')) return ezxml_err(root, d, "unclosed <!--");
+        }
+        else if (! strncmp(s, "![CDATA[", 8)) { // cdata
+            if ((s = strstr(s, "]]>")))
+                ezxml_char_content(root, d + 8, (s += 2) - d - 10, 'c');
+            else return ezxml_err(root, d, "unclosed <![CDATA[");
+        }
+        else if (! strncmp(s, "!DOCTYPE", 8)) { // dtd
+            for (l = 0; *s && ((! l && *s != '>') || (l && (*s != ']' || 
+                 *(s + strspn(s + 1, EZXML_WS) + 1) != '>')));
+                 l = (*s == '[') ? 1 : l) s += strcspn(s + 1, "[]>") + 1;
+            if (! *s && e != '>')
+                return ezxml_err(root, d, "unclosed <!DOCTYPE");
+            d = (l) ? strchr(d, '[') + 1 : d;
+            if (l && ! ezxml_internal_dtd(root, d, s++ - d)) return &root->xml;
+        }
+        else if (*s == '?') { // <?...?> processing instructions
+            do { s = strchr(s, '?'); } while (s && *(++s) && *s != '>');
+            if (! s || (! *s && e != '>')) 
+                return ezxml_err(root, d, "unclosed <?");
+            else ezxml_proc_inst(root, d + 1, s - d - 2);
+        }
+        else return ezxml_err(root, d, "unexpected <");
+        
+        if (! s || ! *s) break;
+        *s = '\0';
+        d = ++s;
+        if (*s && *s != '<') { // tag character content
+            while (*s && *s != '<') s++;
+            if (*s) ezxml_char_content(root, d, s - d, '&');
+            else break;
+        }
+        else if (! *s) break;
+    }
+
+    if (! root->cur) return &root->xml;
+    else if (! root->cur->name) return ezxml_err(root, d, "root tag missing");
+    else return ezxml_err(root, d, "unclosed tag <%s>", root->cur->name);
+}
+
+// Wrapper for ezxml_parse_str() that accepts a file stream. Reads the entire
+// stream into memory and then parses it. For xml files, use ezxml_parse_file()
+// or ezxml_parse_fd()
+ezxml_t ezxml_parse_fp(FILE *fp)
+{
+    ezxml_root_t root;
+    size_t l, len = 0;
+    char *s;
+
+    if (! (s = malloc(EZXML_BUFSIZE))) return NULL;
+    do {
+        len += (l = fread((s + len), 1, EZXML_BUFSIZE, fp));
+        if (l == EZXML_BUFSIZE) s = realloc(s, len + EZXML_BUFSIZE);
+    } while (s && l == EZXML_BUFSIZE);
+
+    if (! s) return NULL;
+    root = (ezxml_root_t)ezxml_parse_str(s, len);
+    root->len = -1; // so we know to free s in ezxml_free()
+    return &root->xml;
+}
+
+// A wrapper for ezxml_parse_str() that accepts a file descriptor. First
+// attempts to mem map the file. Failing that, reads the file into memory.
+// Returns NULL on failure.
+ezxml_t ezxml_parse_fd(int fd)
+{
+    ezxml_root_t root;
+    struct stat st;
+    size_t l;
+    void *m;
+
+    if (fd < 0) return NULL;
+    fstat(fd, &st);
+
+#ifndef EZXML_NOMMAP
+    l = (st.st_size + sysconf(_SC_PAGESIZE) - 1) & ~(sysconf(_SC_PAGESIZE) -1);
+    if ((m = mmap(NULL, l, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0)) !=
+        MAP_FAILED) {
+        madvise(m, l, MADV_SEQUENTIAL); // optimize for sequential access
+        root = (ezxml_root_t)ezxml_parse_str(m, st.st_size);
+        madvise(m, root->len = l, MADV_NORMAL); // put it back to normal
+    }
+    else { // mmap failed, read file into memory
+#endif // EZXML_NOMMAP
+        l = read(fd, m = malloc(st.st_size), st.st_size);
+        root = (ezxml_root_t)ezxml_parse_str(m, l);
+        root->len = -1; // so we know to free s in ezxml_free()
+#ifndef EZXML_NOMMAP
+    }
+#endif // EZXML_NOMMAP
+    return &root->xml;
+}
+
+// a wrapper for ezxml_parse_fd that accepts a file name
+ezxml_t ezxml_parse_file(const char *file)
+{
+    int fd = open(file, O_RDONLY, 0);
+    ezxml_t xml = ezxml_parse_fd(fd);
+    
+    if (fd >= 0) close(fd);
+    return xml;
+}
+
+// Encodes ampersand sequences appending the results to *dst, reallocating *dst
+// if length excedes max. a is non-zero for attribute encoding. Returns *dst
+char *ezxml_ampencode(const char *s, size_t len, char **dst, size_t *dlen,
+                      size_t *max, short a)
+{
+    const char *e;
+    
+    for (e = s + len; s != e; s++) {
+        while (*dlen + 10 > *max) *dst = realloc(*dst, *max += EZXML_BUFSIZE);
+
+        switch (*s) {
+        case '\0': return *dst;
+        case '&': *dlen += sprintf(*dst + *dlen, "&amp;"); break;
+        case '<': *dlen += sprintf(*dst + *dlen, "&lt;"); break;
+        case '>': *dlen += sprintf(*dst + *dlen, "&gt;"); break;
+        case '"': *dlen += sprintf(*dst + *dlen, (a) ? "&quot;" : "\""); break;
+        case '\n': *dlen += sprintf(*dst + *dlen, (a) ? "&#xA;" : "\n"); break;
+        case '\t': *dlen += sprintf(*dst + *dlen, (a) ? "&#x9;" : "\t"); break;
+        case '\r': *dlen += sprintf(*dst + *dlen, "&#xD;"); break;
+        default: (*dst)[(*dlen)++] = *s;
+        }
+    }
+    return *dst;
+}
+
+// Recursively converts each tag to xml appending it to *s. Reallocates *s if
+// its length excedes max. start is the location of the previous tag in the
+// parent tag's character content. Returns *s.
+char *ezxml_toxml_r(ezxml_t xml, char **s, size_t *len, size_t *max,
+                    size_t start, char ***attr)
+{
+    int i, j;
+    char *txt = (xml->parent) ? xml->parent->txt : "";
+    size_t off = 0;
+
+    // parent character content up to this tag
+    *s = ezxml_ampencode(txt + start, xml->off - start, s, len, max, 0);
+
+    while (*len + strlen(xml->name) + 4 > *max) // reallocate s
+        *s = realloc(*s, *max += EZXML_BUFSIZE);
+
+    *len += sprintf(*s + *len, "<%s", xml->name); // open tag
+    for (i = 0; xml->attr[i]; i += 2) { // tag attributes
+        if (ezxml_attr(xml, xml->attr[i]) != xml->attr[i + 1]) continue;
+        while (*len + strlen(xml->attr[i]) + 7 > *max) // reallocate s
+            *s = realloc(*s, *max += EZXML_BUFSIZE);
+
+        *len += sprintf(*s + *len, " %s=\"", xml->attr[i]);
+        ezxml_ampencode(xml->attr[i + 1], -1, s, len, max, 1);
+        *len += sprintf(*s + *len, "\"");
+    }
+
+    for (i = 0; attr[i] && strcmp(attr[i][0], xml->name); i++);
+    for (j = 1; attr[i] && attr[i][j]; j += 3) { // default attributes
+        if (! attr[i][j + 1] || ezxml_attr(xml, attr[i][j]) != attr[i][j + 1])
+            continue; // skip duplicates and non-values
+        while (*len + strlen(attr[i][j]) + 7 > *max) // reallocate s
+            *s = realloc(*s, *max += EZXML_BUFSIZE);
+
+        *len += sprintf(*s + *len, " %s=\"", attr[i][j]);
+        ezxml_ampencode(attr[i][j + 1], -1, s, len, max, 1);
+        *len += sprintf(*s + *len, "\"");
+    }
+    *len += sprintf(*s + *len, ">");
+
+    *s = (xml->child) ? ezxml_toxml_r(xml->child, s, len, max, 0, attr) //child
+                      : ezxml_ampencode(xml->txt, -1, s, len, max, 0);  //data
+    
+    while (*len + strlen(xml->name) + 4 > *max) // reallocate s
+        *s = realloc(*s, *max += EZXML_BUFSIZE);
+
+    *len += sprintf(*s + *len, "</%s>", xml->name); // close tag
+
+    while (txt[off] && off < xml->off) off++; // make sure off is within bounds
+    return (xml->ordered) ? ezxml_toxml_r(xml->ordered, s, len, max, off, attr)
+                          : ezxml_ampencode(txt + off, -1, s, len, max, 0);
+}
+
+// Converts an ezxml structure back to xml. Returns a string of xml data that
+// must be freed.
+char *ezxml_toxml(ezxml_t xml)
+{
+    ezxml_t p = (xml) ? xml->parent : NULL, o = (xml) ? xml->ordered : NULL;
+    ezxml_root_t root = (ezxml_root_t)xml;
+    size_t len = 0, max = EZXML_BUFSIZE;
+    char *s = strcpy(malloc(max), ""), *t, *n;
+    int i, j, k;
+
+    if (! xml || ! xml->name) return realloc(s, len + 1);
+    while (root->xml.parent) root = (ezxml_root_t)root->xml.parent; // root tag
+
+    for (i = 0; ! p && root->pi[i]; i++) { // pre-root processing instructions
+        for (k = 2; root->pi[i][k - 1]; k++);
+        for (j = 1; (n = root->pi[i][j]); j++) {
+            if (root->pi[i][k][j - 1] == '>') continue; // not pre-root
+            while (len + strlen(t = root->pi[i][0]) + strlen(n) + 7 > max)
+                s = realloc(s, max += EZXML_BUFSIZE);
+            len += sprintf(s + len, "<?%s%s%s?>\n", t, *n ? " " : "", n);
+        }
+    }
+
+    xml->parent = xml->ordered = NULL;
+    s = ezxml_toxml_r(xml, &s, &len, &max, 0, root->attr);
+    xml->parent = p;
+    xml->ordered = o;
+
+    for (i = 0; ! p && root->pi[i]; i++) { // post-root processing instructions
+        for (k = 2; root->pi[i][k - 1]; k++);
+        for (j = 1; (n = root->pi[i][j]); j++) {
+            if (root->pi[i][k][j - 1] == '<') continue; // not post-root
+            while (len + strlen(t = root->pi[i][0]) + strlen(n) + 7 > max)
+                s = realloc(s, max += EZXML_BUFSIZE);
+            len += sprintf(s + len, "\n<?%s%s%s?>", t, *n ? " " : "", n);
+        }
+    }
+    return realloc(s, len + 1);
+}
+
+// free the memory allocated for the ezxml structure
+void ezxml_free(ezxml_t xml)
+{
+    ezxml_root_t root = (ezxml_root_t)xml;
+    int i, j;
+    char **a, *s;
+
+    if (! xml) return;
+    ezxml_free(xml->child);
+    ezxml_free(xml->ordered);
+
+    if (! xml->parent) { // free root tag allocations
+        for (i = 10; root->ent[i]; i += 2) // 0 - 9 are default entites (<>&"')
+            if ((s = root->ent[i + 1]) < root->s || s > root->e) free(s);
+        free(root->ent); // free list of general entities
+
+        for (i = 0; (a = root->attr[i]); i++) {
+            for (j = 1; a[j++]; j += 2) // free malloced attribute values
+                if (a[j] && (a[j] < root->s || a[j] > root->e)) free(a[j]);
+            free(a);
+        }
+        if (root->attr[0]) free(root->attr); // free default attribute list
+
+        for (i = 0; root->pi[i]; i++) {
+            for (j = 1; root->pi[i][j]; j++);
+            free(root->pi[i][j + 1]);
+            free(root->pi[i]);
+        }            
+        if (root->pi[0]) free(root->pi); // free processing instructions
+
+        if (root->len == -1) free(root->m); // malloced xml data
+#ifndef EZXML_NOMMAP
+        else if (root->len) munmap(root->m, root->len); // mem mapped xml data
+#endif // EZXML_NOMMAP
+        if (root->u) free(root->u); // utf8 conversion
+    }
+
+    ezxml_free_attr(xml->attr); // tag attributes
+    if ((xml->flags & EZXML_TXTM)) free(xml->txt); // character content
+    if ((xml->flags & EZXML_NAMEM)) free(xml->name); // tag name
+    free(xml);
+}
+
+// return parser error message or empty string if none
+const char *ezxml_error(ezxml_t xml)
+{
+    while (xml && xml->parent) xml = xml->parent; // find root tag
+    return (xml) ? ((ezxml_root_t)xml)->err : "";
+}
+
+// returns a new empty ezxml structure with the given root tag name
+ezxml_t ezxml_new(const char *name)
+{
+    static char *ent[] = { "lt;", "&#60;", "gt;", "&#62;", "quot;", "&#34;",
+                           "apos;", "&#39;", "amp;", "&#38;", NULL };
+    ezxml_root_t root = (ezxml_root_t)memset(malloc(sizeof(struct ezxml_root)), 
+                                             '\0', sizeof(struct ezxml_root));
+    root->xml.name = (char *)name;
+    root->cur = &root->xml;
+    strcpy(root->err, root->xml.txt = "");
+    root->ent = memcpy(malloc(sizeof(ent)), ent, sizeof(ent));
+    root->attr = root->pi = (char ***)(root->xml.attr = EZXML_NIL);
+    return &root->xml;
+}
+
+// inserts an existing tag into an ezxml structure
+ezxml_t ezxml_insert(ezxml_t xml, ezxml_t dest, size_t off)
+{
+    ezxml_t cur, prev, head;
+
+    xml->next = xml->sibling = xml->ordered = NULL;
+    xml->off = off;
+    xml->parent = dest;
+
+    if ((head = dest->child)) { // already have sub tags
+        if (head->off <= off) { // not first subtag
+            for (cur = head; cur->ordered && cur->ordered->off <= off;
+                 cur = cur->ordered);
+            xml->ordered = cur->ordered;
+            cur->ordered = xml;
+        }
+        else { // first subtag
+            xml->ordered = head;
+            dest->child = xml;
+        }
+
+        for (cur = head, prev = NULL; cur && strcmp(cur->name, xml->name);
+             prev = cur, cur = cur->sibling); // find tag type
+        if (cur && cur->off <= off) { // not first of type
+            while (cur->next && cur->next->off <= off) cur = cur->next;
+            xml->next = cur->next;
+            cur->next = xml;
+        }
+        else { // first tag of this type
+            if (prev && cur) prev->sibling = cur->sibling; // remove old first
+            xml->next = cur; // old first tag is now next
+            for (cur = head, prev = NULL; cur && cur->off <= off;
+                 prev = cur, cur = cur->sibling); // new sibling insert point
+            xml->sibling = cur;
+            if (prev) prev->sibling = xml;
+        }
+    }
+    else dest->child = xml; // only sub tag
+
+    return xml;
+}
+
+// Adds a child tag. off is the offset of the child tag relative to the start
+// of the parent tag's character content. Returns the child tag.
+ezxml_t ezxml_add_child(ezxml_t xml, const char *name, size_t off)
+{
+    ezxml_t child;
+
+    if (! xml) return NULL;
+    child = (ezxml_t)memset(malloc(sizeof(struct ezxml)), '\0',
+                            sizeof(struct ezxml));
+    child->name = (char *)name;
+    child->attr = EZXML_NIL;
+    child->txt = "";
+
+    return ezxml_insert(child, xml, off);
+}
+
+// sets the character content for the given tag and returns the tag
+ezxml_t ezxml_set_txt(ezxml_t xml, const char *txt)
+{
+    if (! xml) return NULL;
+    if (xml->flags & EZXML_TXTM) free(xml->txt); // existing txt was malloced
+    xml->flags &= ~EZXML_TXTM;
+    xml->txt = (char *)txt;
+    return xml;
+}
+
+// Sets the given tag attribute or adds a new attribute if not found. A value
+// of NULL will remove the specified attribute. Returns the tag given.
+ezxml_t ezxml_set_attr(ezxml_t xml, const char *name, const char *value)
+{
+    int l = 0, c;
+
+    if (! xml) return NULL;
+    while (xml->attr[l] && strcmp(xml->attr[l], name)) l += 2;
+    if (! xml->attr[l]) { // not found, add as new attribute
+        if (! value) return xml; // nothing to do
+        if (xml->attr == EZXML_NIL) { // first attribute
+            xml->attr = malloc(4 * sizeof(char *));
+            xml->attr[1] = strdup(""); // empty list of malloced names/vals
+        }
+        else xml->attr = realloc(xml->attr, (l + 4) * sizeof(char *));
+
+        xml->attr[l] = (char *)name; // set attribute name
+        xml->attr[l + 2] = NULL; // null terminate attribute list
+        xml->attr[l + 3] = realloc(xml->attr[l + 1],
+                                   (c = strlen(xml->attr[l + 1])) + 2);
+        strcpy(xml->attr[l + 3] + c, " "); // set name/value as not malloced
+        if (xml->flags & EZXML_DUP) xml->attr[l + 3][c] = EZXML_NAMEM;
+    }
+    else if (xml->flags & EZXML_DUP) free((char *)name); // name was strduped
+
+    for (c = l; xml->attr[c]; c += 2); // find end of attribute list
+    if (xml->attr[c + 1][l / 2] & EZXML_TXTM) free(xml->attr[l + 1]); //old val
+    if (xml->flags & EZXML_DUP) xml->attr[c + 1][l / 2] |= EZXML_TXTM;
+    else xml->attr[c + 1][l / 2] &= ~EZXML_TXTM;
+
+    if (value) xml->attr[l + 1] = (char *)value; // set attribute value
+    else { // remove attribute
+        if (xml->attr[c + 1][l / 2] & EZXML_NAMEM) free(xml->attr[l]);
+        memmove(xml->attr + l, xml->attr + l + 2, (c - l + 2) * sizeof(char*));
+        xml->attr = realloc(xml->attr, (c + 2) * sizeof(char *));
+        memmove(xml->attr[c + 1] + (l / 2), xml->attr[c + 1] + (l / 2) + 1,
+                (c / 2) - (l / 2)); // fix list of which name/vals are malloced
+    }
+    xml->flags &= ~EZXML_DUP; // clear strdup() flag
+    return xml;
+}
+
+// sets a flag for the given tag and returns the tag
+ezxml_t ezxml_set_flag(ezxml_t xml, short flag)
+{
+    if (xml) xml->flags |= flag;
+    return xml;
+}
+
+// removes a tag along with its subtags without freeing its memory
+ezxml_t ezxml_cut(ezxml_t xml)
+{
+    ezxml_t cur;
+
+    if (! xml) return NULL; // nothing to do
+    if (xml->next) xml->next->sibling = xml->sibling; // patch sibling list
+
+    if (xml->parent) { // not root tag
+        cur = xml->parent->child; // find head of subtag list
+        if (cur == xml) xml->parent->child = xml->ordered; // first subtag
+        else { // not first subtag
+            while (cur->ordered != xml) cur = cur->ordered;
+            cur->ordered = cur->ordered->ordered; // patch ordered list
+
+            cur = xml->parent->child; // go back to head of subtag list
+            if (strcmp(cur->name, xml->name)) { // not in first sibling list
+                while (strcmp(cur->sibling->name, xml->name))
+                    cur = cur->sibling;
+                if (cur->sibling == xml) { // first of a sibling list
+                    cur->sibling = (xml->next) ? xml->next
+                                               : cur->sibling->sibling;
+                }
+                else cur = cur->sibling; // not first of a sibling list
+            }
+
+            while (cur->next && cur->next != xml) cur = cur->next;
+            if (cur->next) cur->next = cur->next->next; // patch next list
+        }        
+    }
+    xml->ordered = xml->sibling = xml->next = NULL;
+    return xml;
+}
+
+#ifdef EZXML_TEST // test harness
+int main(int argc, char **argv)
+{
+    ezxml_t xml;
+    char *s;
+    int i;
+
+    if (argc != 2) return fprintf(stderr, "usage: %s xmlfile\n", argv[0]);
+
+    xml = ezxml_parse_file(argv[1]);
+    printf("%s\n", (s = ezxml_toxml(xml)));
+    free(s);
+    i = fprintf(stderr, "%s", ezxml_error(xml));
+    ezxml_free(xml);
+    return (i) ? 1 : 0;
+}
+#endif // EZXML_TEST
diff --git a/utils/guest_creator/ezxml.h b/utils/guest_creator/ezxml.h
new file mode 100644 (file)
index 0000000..3e02078
--- /dev/null
@@ -0,0 +1,167 @@
+/* ezxml.h
+ *
+ * Copyright 2004-2006 Aaron Voisine <aaron@voisine.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _EZXML_H
+#define _EZXML_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <fcntl.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define EZXML_BUFSIZE 1024 // size of internal memory buffers
+#define EZXML_NAMEM   0x80 // name is malloced
+#define EZXML_TXTM    0x40 // txt is malloced
+#define EZXML_DUP     0x20 // attribute name and value are strduped
+
+typedef struct ezxml *ezxml_t;
+struct ezxml {
+    char *name;      // tag name
+    char **attr;     // tag attributes { name, value, name, value, ... NULL }
+    char *txt;       // tag character content, empty string if none
+    size_t off;      // tag offset from start of parent tag character content
+    ezxml_t next;    // next tag with same name in this section at this depth
+    ezxml_t sibling; // next tag with different name in same section and depth
+    ezxml_t ordered; // next tag, same section and depth, in original order
+    ezxml_t child;   // head of sub tag list, NULL if none
+    ezxml_t parent;  // parent tag, NULL if current tag is root tag
+    short flags;     // additional information
+};
+
+// Given a string of xml data and its length, parses it and creates an ezxml
+// structure. For efficiency, modifies the data by adding null terminators
+// and decoding ampersand sequences. If you don't want this, copy the data and
+// pass in the copy. Returns NULL on failure.
+ezxml_t ezxml_parse_str(char *s, size_t len);
+
+// A wrapper for ezxml_parse_str() that accepts a file descriptor. First
+// attempts to mem map the file. Failing that, reads the file into memory.
+// Returns NULL on failure.
+ezxml_t ezxml_parse_fd(int fd);
+
+// a wrapper for ezxml_parse_fd() that accepts a file name
+ezxml_t ezxml_parse_file(const char *file);
+    
+// Wrapper for ezxml_parse_str() that accepts a file stream. Reads the entire
+// stream into memory and then parses it. For xml files, use ezxml_parse_file()
+// or ezxml_parse_fd()
+ezxml_t ezxml_parse_fp(FILE *fp);
+
+// returns the first child tag (one level deeper) with the given name or NULL
+// if not found
+ezxml_t ezxml_child(ezxml_t xml, const char *name);
+
+// returns the next tag of the same name in the same section and depth or NULL
+// if not found
+#define ezxml_next(xml) ((xml) ? xml->next : NULL)
+
+// Returns the Nth tag with the same name in the same section at the same depth
+// or NULL if not found. An index of 0 returns the tag given.
+ezxml_t ezxml_idx(ezxml_t xml, int idx);
+
+// returns the name of the given tag
+#define ezxml_name(xml) ((xml) ? xml->name : NULL)
+
+// returns the given tag's character content or empty string if none
+#define ezxml_txt(xml) ((xml) ? xml->txt : "")
+
+// returns the value of the requested tag attribute, or NULL if not found
+const char *ezxml_attr(ezxml_t xml, const char *attr);
+
+// Traverses the ezxml sturcture to retrieve a specific subtag. Takes a
+// variable length list of tag names and indexes. The argument list must be
+// terminated by either an index of -1 or an empty string tag name. Example: 
+// title = ezxml_get(library, "shelf", 0, "book", 2, "title", -1);
+// This retrieves the title of the 3rd book on the 1st shelf of library.
+// Returns NULL if not found.
+ezxml_t ezxml_get(ezxml_t xml, ...);
+
+// Converts an ezxml structure back to xml. Returns a string of xml data that
+// must be freed.
+char *ezxml_toxml(ezxml_t xml);
+
+// returns a NULL terminated array of processing instructions for the given
+// target
+const char **ezxml_pi(ezxml_t xml, const char *target);
+
+// frees the memory allocated for an ezxml structure
+void ezxml_free(ezxml_t xml);
+    
+// returns parser error message or empty string if none
+const char *ezxml_error(ezxml_t xml);
+
+// returns a new empty ezxml structure with the given root tag name
+ezxml_t ezxml_new(const char *name);
+
+// wrapper for ezxml_new() that strdup()s name
+#define ezxml_new_d(name) ezxml_set_flag(ezxml_new(strdup(name)), EZXML_NAMEM)
+
+// Adds a child tag. off is the offset of the child tag relative to the start
+// of the parent tag's character content. Returns the child tag.
+ezxml_t ezxml_add_child(ezxml_t xml, const char *name, size_t off);
+
+// wrapper for ezxml_add_child() that strdup()s name
+#define ezxml_add_child_d(xml, name, off) \
+    ezxml_set_flag(ezxml_add_child(xml, strdup(name), off), EZXML_NAMEM)
+
+// sets the character content for the given tag and returns the tag
+ezxml_t ezxml_set_txt(ezxml_t xml, const char *txt);
+
+// wrapper for ezxml_set_txt() that strdup()s txt
+#define ezxml_set_txt_d(xml, txt) \
+    ezxml_set_flag(ezxml_set_txt(xml, strdup(txt)), EZXML_TXTM)
+
+// Sets the given tag attribute or adds a new attribute if not found. A value
+// of NULL will remove the specified attribute. Returns the tag given.
+ezxml_t ezxml_set_attr(ezxml_t xml, const char *name, const char *value);
+
+// Wrapper for ezxml_set_attr() that strdup()s name/value. Value cannot be NULL
+#define ezxml_set_attr_d(xml, name, value) \
+    ezxml_set_attr(ezxml_set_flag(xml, EZXML_DUP), strdup(name), strdup(value))
+
+// sets a flag for the given tag and returns the tag
+ezxml_t ezxml_set_flag(ezxml_t xml, short flag);
+
+// removes a tag along with its subtags without freeing its memory
+ezxml_t ezxml_cut(ezxml_t xml);
+
+// inserts an existing tag into an ezxml structure
+ezxml_t ezxml_insert(ezxml_t xml, ezxml_t dest, size_t off);
+
+// Moves an existing tag to become a subtag of dest at the given offset from
+// the start of dest's character content. Returns the moved tag.
+#define ezxml_move(xml, dest, off) ezxml_insert(ezxml_cut(xml), dest, off)
+
+// removes a tag along with all its subtags
+#define ezxml_remove(xml) ezxml_free(ezxml_cut(xml))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _EZXML_H
diff --git a/utils/guest_creator/ezxml.txt b/utils/guest_creator/ezxml.txt
new file mode 100644 (file)
index 0000000..1dcd5ad
--- /dev/null
@@ -0,0 +1,84 @@
+ezXML - XML Parsing C Library
+version 0.8.5
+
+ezXML is a C library for parsing XML documents inspired by simpleXML for PHP.
+As the name implies, it's easy to use. It's ideal for parsing XML configuration
+files or REST web service responses. It's also fast and lightweight (less than
+20k compiled). The latest verions is available here:
+http://prdownloads.sf.net/ezxml/ezxml-0.8.6.tar.gz?download
+
+Example Usage
+
+Given the following example XML document:
+
+<?xml version="1.0"?>
+<formula1>
+  <team name="McLaren">
+    <driver>
+      <name>Kimi Raikkonen</name>
+      <points>112</points>
+    </driver>
+    <driver>
+      <name>Juan Pablo Montoya</name>
+      <points>60</points>
+    </driver>
+  </team>
+</formula1>
+
+This code snippet prints out a list of drivers, which team they drive for,
+and how many championship points they have:
+
+ezxml_t f1 = ezxml_parse_file("formula1.xml"), team, driver;
+const char *teamname;
+
+for (team = ezxml_child(f1, "team"); team; team = team->next) {
+    teamname = ezxml_attr(team, "name");
+    for (driver = ezxml_child(team, "driver"); driver; driver = driver->next) {
+        printf("%s, %s: %s\n", ezxml_child(driver, "name")->txt, teamname,
+               ezxml_child(driver, "points")->txt);
+    }
+}
+ezxml_free(f1);
+
+Alternately, the following would print out the name of the second driver on the
+first team:
+
+ezxml_t f1 = ezxml_parse_file("formula1.xml");
+
+printf("%s\n", ezxml_get(f1, "team", 0, "driver", 1, "name", -1)->txt);
+ezxml_free(f1);
+
+The -1 indicates the end of the argument list. That's pretty much all
+there is to it. Complete API documentation can be found in ezxml.h.
+
+Known Limitations
+
+- ezXML is not a validating parser
+
+- Loads the entire XML document into memory at once and does not allow for
+  documents to be passed in a chunk at a time. Large XML files can still be
+  handled though through ezxml_parse_file() and ezxml_parse_fd(), which use mmap
+  to map the file to a virtual address space and rely on the virtual memory
+  system to page in data as needed.
+
+- Does not currently recognize all possible well-formedness errors. It should
+  correctly handle all well-formed XML documents and will either ignore or halt
+  XML processing on well-formedness errors. More well-formedness checking will
+  be added in subsiquent releases.
+
+- In making the character content of tags easy to access, there is no way
+  provided to keep track of the location of sub tags relative to the character
+  data. Example:
+
+  <doc>line one<br/>
+  line two</doc>
+
+  The character content of the doc tag is reported as "line one\nline two", and
+  <br/> is reported as a sub tag, but the location of <br/> within the
+  character data is not. The function ezxml_toxml() will convert an ezXML
+  structure back to XML with sub tag locations intact.
+
+Licensing
+
+ezXML was written by Aaron Voisine <aaron@voisine.org> and is distributed under
+the terms of the MIT license, described in license.txt.
diff --git a/utils/guest_creator/main.c b/utils/guest_creator/main.c
new file mode 100644 (file)
index 0000000..2255adf
--- /dev/null
@@ -0,0 +1,230 @@
+#include "ezxml.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#define MAX_FILES 256
+
+struct file_info {
+    int size;
+    char id[256];
+    char * data;
+    unsigned long long * offset_ptr;
+};
+
+int num_files = 0;
+struct file_info files[MAX_FILES];
+
+
+int parse_config_input(ezxml_t cfg_input);
+int write_output(char * filename, ezxml_t cfg_output);
+
+void usage() {
+    printf("Usage: build_vm <infile> [-o outfile]\n");
+}
+
+int main(int argc, char ** argv) {
+    int c;
+    char * outfile = NULL;
+    char * infile = NULL;
+
+    memset((char *)files, 0, sizeof(files));
+
+    opterr = 0;
+
+    while ((c = getopt(argc, argv, "ho:")) != -1) {
+       switch (c) {
+           case 'o':
+               outfile = optarg;
+               break;
+           case 'h':
+               usage();
+               return 1;
+           default:
+               abort();
+       }
+    }
+
+    if (optind >= argc) {
+       usage();
+       return 1;
+    }
+
+    infile = argv[optind];
+
+
+    printf("Reading Input file: %s\n", infile);
+
+    ezxml_t cfg_input = ezxml_parse_file(infile);
+
+    if (cfg_input == NULL) {
+       printf("Could not open configuration input file: %s\n", infile);
+       return 1;
+    }
+
+
+
+
+    // parse input
+    if (parse_config_input(cfg_input) == -1) {
+       printf("Error parsing configuration input\n");
+       return 1;
+    }
+
+    printf("xml : %s\n", ezxml_toxml(cfg_input));
+
+
+
+    // write output
+
+    if (outfile == NULL) {
+       char * endptr = rindex(infile, '.');
+
+       outfile = malloc(strlen(infile) + strlen(".dat") + 1);
+
+       if (endptr) {
+           *endptr = '\0';
+       }
+
+       sprintf(outfile, "%s.dat", infile);
+    }
+
+
+    write_output(outfile, cfg_input);
+
+
+    return 0;
+}
+
+char * get_val(ezxml_t cfg, char * tag) {
+    char * attrib = (char *)ezxml_attr(cfg, tag);
+    ezxml_t txt = ezxml_child(cfg, tag);
+
+    if ((txt != NULL) && (attrib != NULL)) {
+       printf("Invalid Cfg file: Duplicate value for %s (attr=%s, txt=%s)\n", 
+              tag, attrib, ezxml_txt(txt));
+       exit(-1);
+    }
+
+    return (attrib == NULL) ? ezxml_txt(txt) : attrib;
+}
+
+
+int write_output(char * filename, ezxml_t cfg_output) {
+    FILE * data_file = fopen(filename, "w+");
+    char * new_cfg_str = ezxml_toxml(cfg_output);
+    unsigned int cfg_len = strlen(new_cfg_str);
+    unsigned long long zero = 0;
+    int i = 0;
+    unsigned long long offset = 0;
+    unsigned long long file_cnt = num_files;
+
+    fwrite("v3vee\0\0\0", 8, 1, data_file);
+    offset += 8;
+
+    //  printf("New config: \n%s\n", new_cfg_str);
+    
+    fwrite(&cfg_len, sizeof(unsigned int), 1, data_file);
+    offset += sizeof(unsigned int);
+
+    fwrite(new_cfg_str, cfg_len, 1, data_file);
+    offset += cfg_len;
+
+    fwrite(&zero, 1, 8, data_file);
+    offset += 8;
+
+    printf("setting number of files to %llu\n", file_cnt);
+    printf("sizeof(file_cnt)=%d \n", sizeof(file_cnt));
+
+    fwrite(&file_cnt, 8, 1, data_file);
+    offset += 8;
+
+    // each index entry is 16 bytes long plus end padding
+    offset += (16 * num_files) + 8;
+
+    for (i = 0; i < num_files; i++) {
+       fwrite(&i, 4, 1, data_file);
+       fwrite(&(files[i].size), 4, 1, data_file);
+       fwrite(&offset, 8, 1, data_file);
+
+       offset += files[i].size;
+    }
+
+    fwrite(&zero, 1, 8, data_file);
+
+    for (i = 0; i < num_files; i++) {
+       if (fwrite(files[i].data, 1, files[i].size, data_file) != files[i].size) {
+           printf("Error writing data file contents");
+           exit(-1);
+       }       
+    }
+    
+
+
+    fclose(data_file);
+
+    return 0;
+}
+
+
+
+int parse_config_input(ezxml_t cfg_input) {
+    ezxml_t file_tags = NULL;
+    ezxml_t tmp_file_tag = NULL;
+
+    // files are transformed into blobs that are slapped to the end of the file
+        
+    file_tags = ezxml_child(cfg_input, "files");
+
+    tmp_file_tag = ezxml_child(file_tags, "file");
+
+    while (tmp_file_tag) {
+       char * filename = get_val(tmp_file_tag, "filename");
+       struct stat file_stats;
+       FILE * data_file = NULL;
+       char * id = get_val(tmp_file_tag, "id");
+       char index_buf[256];
+
+       snprintf(index_buf, 256, "%d", num_files);
+
+
+       strncpy(files[num_files].id, ezxml_attr(tmp_file_tag, "id"), 256);
+
+       printf("file id=%s, name=%s\n", 
+              id,
+              filename);
+       
+
+       if (stat(filename, &file_stats) != 0) {
+           perror(filename);
+           exit(-1);
+       }
+
+       files[num_files].size = (unsigned int)file_stats.st_size;
+       printf("file size = %d\n", files[num_files].size);
+
+       files[num_files].data = malloc(files[num_files].size);
+
+       data_file = fopen(filename, "r");
+
+       if (fread(files[num_files].data, files[num_files].size, 1, data_file) == 0) {
+           printf("Error reading data file %s\n", filename);
+           exit(-1);
+       }
+
+       fclose(data_file);
+
+
+       ezxml_set_attr_d(tmp_file_tag, "index", index_buf);
+
+       num_files++;
+       tmp_file_tag = ezxml_next(tmp_file_tag);
+    }
+
+
+    return 0;
+}
diff --git a/utils/guest_creator/out_format b/utils/guest_creator/out_format
new file mode 100644 (file)
index 0000000..f9a5fe7
--- /dev/null
@@ -0,0 +1,17 @@
+v3vee\0\0\0        : 8 bytes
+<length of xml>    : 4 bytes
+<xml>              : xml configuration string
+<zero's>           : 8 bytes of zeroes
+
+<num files>        : 8 bytes
+
+<index>            : 4 bytes
+<size>             : 4 bytes
+<offset>           : 8 bytes
+... other files ...
+
+<zero's>           : 8 bytes of zeroes
+
+<file>             : raw file data
+
+... other raw file data ...
diff --git a/utils/nasm-0.98.39.tar.gz b/utils/nasm-0.98.39.tar.gz
deleted file mode 100644 (file)
index 303daa8..0000000
Binary files a/utils/nasm-0.98.39.tar.gz and /dev/null differ
diff --git a/utils/nasm-install.patch b/utils/nasm-install.patch
deleted file mode 100644 (file)
index 6aa52fd..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
---- Makefile.in        2005-01-14 17:05:31.000000000 -0600
-+++ ../Makefile.in     2008-01-08 18:57:47.861088072 -0600
-@@ -20,7 +20,7 @@
- LIBS          = @LIBS@
- PERL          = perl
--INSTALL               = @INSTALL@
-+INSTALL               = @INSTALL@ -D
- INSTALL_PROGRAM       = @INSTALL_PROGRAM@
- INSTALL_DATA  = @INSTALL_DATA@
diff --git a/utils/vmx.patch b/utils/vmx.patch
deleted file mode 100644 (file)
index 8bbb471..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-Index: insns.dat
-===================================================================
-RCS file: /home/jarusl/nasm-0.98.39-vmx/insns.dat
-retrieving revision 1.46
-diff -u -p -w -r1.46 insns.dat
---- insns.dat  2 Sep 2003 21:38:48 -0000       1.46
-+++ insns.dat  28 Feb 2006 00:43:59 -0000
-@@ -1673,3 +1673,17 @@ MOVSHDUP        xmmreg,mem              \301\3\xF3\x0F\x16\
- MOVSHDUP      xmmreg,xmmreg           \3\xF3\x0F\x16\110              PRESCOTT,SSE3
- MOVSLDUP      xmmreg,mem              \301\3\xF3\x0F\x12\110          PRESCOTT,SSE3
- MOVSLDUP      xmmreg,xmmreg           \3\xF3\x0F\x12\110              PRESCOTT,SSE3
-+
-+; VMX Instructions
-+VMCALL                void                    \3\x0F\x01\xC1                  VMX
-+VMCLEAR               mem                     \3\x66\x0F\xC7\206              VMX
-+VMLAUNCH      void                    \3\x0F\x01\xC2                  VMX
-+VMPTRLD               mem                     \2\x0F\xC7\206                  VMX
-+VMPTRST               mem                     \2\x0F\xC7\207                  VMX
-+VMREAD                mem,reg32               \2\x0F\x78\101                  VMX
-+VMREAD                reg32,reg32             \2\x0F\x78\101                  VMX
-+VMRESUME      void                    \3\x0F\x01\xC3                  VMX
-+VMWRITE               reg32,mem               \2\x0F\x79\110                  VMX
-+VMWRITE               reg32,reg32             \2\x0F\x79\110                  VMX
-+VMXOFF                void                    \3\x0F\x01\xC4                  VMX
-+VMXON         mem                     \3\xF3\x0F\xC7\206              VMX
-Index: insns.h
-===================================================================
-RCS file: /home/jarusl/nasm-0.98.39-vmx/insns.h
-retrieving revision 1.31
-diff -u -p -w -r1.31 insns.h
---- insns.h    15 Jan 2005 22:15:51 -0000      1.31
-+++ insns.h    28 Feb 2006 00:43:59 -0000
-@@ -78,6 +78,7 @@ struct itemplate {
- #define IF_SSE    0x00010000UL  /* it's a SSE (KNI, MMX2) instruction */
- #define IF_SSE2   0x00020000UL  /* it's a SSE2 instruction */
- #define IF_SSE3   0x00040000UL  /* it's a SSE3 (PNI) instruction */
-+#define IF_VMX          0x00080000UL  /* it's a VMX instruction */
- #define IF_PMASK  0xFF000000UL  /* the mask for processor types */
- #define IF_PLEVEL 0x0F000000UL  /* the mask for processor instr. level */
-                                         /* also the highest possible processor */
-