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
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
+++ /dev/null
-
-/*
- * 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
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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
#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,
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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
#include <devices/pci_types.h>
+struct vm_device;
+
typedef enum { PCI_BAR_IO,
PCI_BAR_MEM24,
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- * 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
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
+
+
struct v3_gprs {
v3_reg_t rdi;
v3_reg_t rsi;
#include <palacios/vmm_sym_iface.h>
#endif
+#include <palacios/vmm_config.h>
+
struct shadow_page_state;
struct v3_intr_state;
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;
#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....
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);
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);
-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)();
-};
-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);
#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
#include <palacios/vmm_list.h>
#include <palacios/vmm_string.h>
#include <palacios/vmm_hashtable.h>
+#include <palacios/vmm_config.h>
struct guest_info;
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);
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);
};
-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__
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);
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')
#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));
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;
};
-
struct v3_sym_state {
struct v3_sym_interface * sym_page;
uint64_t sym_call_fs;
};
+
+
+
+
+
+
int v3_init_sym_iface(struct guest_info * info);
+
/*
* This file is part of the Palacios Virtual Machine Monitor developed
* by the V3VEE Project with funding from the United States National
};
int v3_is_vmx_capable();
-void v3_init_vmx_hooks(struct v3_ctrl_ops * vm_ops);
void v3_init_vmx_cpu(int cpu_id);
#include <palacios/vmm_time.h>
#include <palacios/vmm_util.h>
#include <palacios/vmm_intr.h>
-
+#include <palacios/vmm_config.h>
#ifndef CONFIG_DEBUG_PIT
};
-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;
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;
}
-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;
}
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
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"
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 tmp_blk.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
#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
-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;
}
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...
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));
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));
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;
}
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));
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;
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);
-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;
}
.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;
}
.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) {
* 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;
struct port_range {
uint_t start;
uint_t end;
- uint_t type;
+ generic_mode_t mode;
struct list_head range_link;
};
-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;
-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;
}
-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");
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;
}
*/
#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"};
"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)) {
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;
drive->private_data = NULL;
- drive->cd_ops = NULL;
+ drive->ops = NULL;
}
static void init_channel(struct ide_channel * channel) {
-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");
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;
}
+ 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;
-
-
-
-
-
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) {
-
-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;
-}
-
-
-
#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
-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;
}
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;
}
#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
-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");
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;
}
-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");
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;
}
#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>
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;
return 0;
}
-static int handle_read_op(struct virtio_blk_state * blk_state, uint8_t * buf, uint64_t * sector, uint32_t len) {
+static int handle_read_op(struct virtio_blk_state * blk_state, uint8_t * buf, uint64_t * sector, uint64_t len) {
int ret = -1;
- if (blk_state->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 = blk_state->hd_ops->read(buf, len / HD_SECTOR_SIZE, *sector, blk_state->backend_data);
-
- *sector += len / HD_SECTOR_SIZE;
-
- } else if (blk_state->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;
- }
-
- ret = blk_state->cd_ops->read(buf, len / ATAPI_BLOCK_SIZE, *sector , blk_state->backend_data);
-
- *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 virtio_blk_state * blk_state, uint8_t * buf, uint64_t * sector, uint32_t len) {
+static int handle_write_op(struct virtio_blk_state * blk_state, uint8_t * buf, uint64_t * sector, uint64_t len) {
int ret = -1;
- if (blk_state->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 = blk_state->hd_ops->write(buf, len / HD_SECTOR_SIZE, *sector, blk_state->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;
}
uint8_t * buf = NULL;
PrintDebug("Handling Block op\n");
-
-
-
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 (blk_state->block_type != BLOCK_NONE) {
- if (handle_read_op(blk_state, 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 (blk_state->block_type == BLOCK_DISK) {
- if (handle_write_op(blk_state, 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;
}
-int v3_virtio_register_cdrom(struct vm_device * dev, struct v3_cd_ops * ops, void * private_data) {
- struct virtio_dev_state * virtio = (struct virtio_dev_state *)dev->private_data;
- 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));
-
- register_dev(virtio, blk_state);
-
- blk_state->block_type = BLOCK_CDROM;
- blk_state->cd_ops = ops;
- blk_state->backend_data = private_data;
-
- blk_state->block_cfg.capacity = ops->get_capacity(private_data);
-
- return 0;
-}
+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 virtio_dev_state * virtio = (struct virtio_dev_state *)frontend_data;
-int v3_virtio_register_harddisk(struct vm_device * dev, struct v3_hd_ops * ops, void * private_data) {
- struct virtio_dev_state * virtio = (struct virtio_dev_state *)dev->private_data;
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));
register_dev(virtio, blk_state);
- blk_state->block_type = BLOCK_DISK;
- blk_state->hd_ops = ops;
+ blk_state->ops = ops;
blk_state->backend_data = private_data;
blk_state->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));
+ (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);
+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_bus = pci_bus;
virtio_state->vm = vm;
- struct vm_device * dev = v3_allocate_device("LNX_VIRTIO_BLK", &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_BLK");
+ PrintError("Could not attach device %s\n", name);
+ return -1;
+ }
+
+ 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;
}
-
-
device_register("LNX_VIRTIO_BLK", virtio_init)
-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");
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;
}
+++ /dev/null
-/*
- * 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)
*/
#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
#define NBD_STATUS_ERR 0xff
-struct hd_state {
+struct disk_state {
uint64_t capacity; // in bytes
int socket;
char disk_name[32];
- 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;
+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;
}
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;
}
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;
}
}
-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;
}
}
-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));
}
}
-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)
#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
-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");
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;
}
-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;
}
-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;
}
#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...)
-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;
}
#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??
-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));
}
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;
}
#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;
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");
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;
}
+++ /dev/null
-/*
- * 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)
+++ /dev/null
-/*
- * 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)
--- /dev/null
+/*
+ * 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)
#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>
struct swap_state {
int active;
- struct vm_device * blk_dev;
-
uint_t swapped_pages;
uint_t unswapped_pages;
PrintDebug("SymSwap: Getting Capacity %d\n", (uint32_t)(swap->capacity));
- return swap->capacity / HD_SECTOR_SIZE;
+ return swap->capacity;
}
-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;
/*
-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,
}
-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,
-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;
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) {
}
-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;
}
+++ /dev/null
-/*
- * 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>
-#include <devices/lnx_virtio_blk.h>
-
-
-#define BLK_CAPACITY (500 * 1024 * 1024)
-
-
-
-
-struct blk_state {
-
- struct vm_device * blk_dev;
-
- uint64_t capacity;
- uint8_t * blk_space;
- addr_t blk_base_addr;
-};
-
-
-
-static uint64_t blk_get_capacity(void * private_data) {
- struct vm_device * dev = (struct vm_device *)private_data;
- struct blk_state * blk = (struct blk_state *)(dev->private_data);
-
- PrintDebug("SymBlk: Getting Capacity %d\n", (uint32_t)(blk->capacity));
-
- return blk->capacity / HD_SECTOR_SIZE;
-}
-
-
-
-static int blk_read(uint8_t * buf, int sector_count, uint64_t lba, void * private_data) {
- struct vm_device * dev = (struct vm_device *)private_data;
- struct blk_state * blk = (struct blk_state *)(dev->private_data);
- uint32_t offset = lba * HD_SECTOR_SIZE;
- uint32_t length = sector_count * HD_SECTOR_SIZE;
-
- memcpy(buf, blk->blk_space + offset, length);
-
- return 0;
-}
-
-
-
-
-static int blk_write(uint8_t * buf, int sector_count, uint64_t lba, void * private_data) {
- struct vm_device * dev = (struct vm_device *)private_data;
- struct blk_state * blk = (struct blk_state *)(dev->private_data);
- uint32_t offset = lba * HD_SECTOR_SIZE;
- uint32_t length = sector_count * HD_SECTOR_SIZE;
-
- memcpy(blk->blk_space + offset, buf, length);
-
- return 0;
-}
-
-
-static int blk_free(struct vm_device * dev) {
- return -1;
-}
-
-
-static struct v3_hd_ops hd_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, void * cfg_data) {
- struct blk_state * blk = NULL;
- struct vm_device * virtio_blk = v3_find_dev(vm, (char *)cfg_data);
-
- if (!virtio_blk) {
- PrintError("could not find Virtio backend\n");
- return -1;
- }
-
- PrintDebug("Creating Blk Device\n");
-
- if (virtio_blk == NULL) {
- PrintError("Blk device requires a virtio block device\n");
- return -1;
- }
-
- blk = (struct blk_state *)V3_Malloc(sizeof(struct blk_state) + ((BLK_CAPACITY / 4096) / 8));
-
- blk->blk_dev = virtio_blk;
- blk->capacity = BLK_CAPACITY;
-
- blk->blk_base_addr = (addr_t)V3_AllocPages(blk->capacity / 4096);
- blk->blk_space = (uint8_t *)V3_VAddr((void *)(blk->blk_base_addr));
- memset(blk->blk_space, 0, BLK_CAPACITY);
-
-
- struct vm_device * dev = v3_allocate_device("TMP_BLK", &dev_ops, blk);
-
- if (v3_attach_device(vm, dev) == -1) {
- PrintError("Could not attach device %s\n", "TMP_BLK");
- return -1;
- }
-
-
- v3_virtio_register_harddisk(virtio_blk, &hd_ops, dev);
-
-
- return 0;
-}
-
-device_register("TMP_BLK", blk_init)
--- /dev/null
+/*
+ * 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)
#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>
}
-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;
}
}
-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));
}
-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;
-}
#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
+
+
+
static struct guest_info * allocate_guest() {
void * info = V3_Malloc(sizeof(struct guest_info));
memset(info, 0, sizeof(struct guest_info));
}
-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
PrintDebug("Machine is VMX Capable\n");
v3_init_vmx_cpu(cpu_id);
- if (cpu_id == 0) {
- v3_init_vmx_hooks(vmm_ops);
- }
} else
#endif
{
-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;
// 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__
+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
return -1;
}
}
+
+
+
#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"
-/*
-static const char * test_cfg_xml = \
-"<root>\n \
-<memory>2048</memory>\n\
-<devices>\n\
-<device id=\"PCI\" />\n\
-<device id=\"IDE\" />\n\
-</devices>\n\
-</root>";
-*/
+// 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>
+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);
-#include <palacios/vmm_socket.h>
+
+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;
+ 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));
+}
-#ifdef CONFIG_PASSTHROUGH_VIDEO
-static int passthrough_mem_write(addr_t guest_addr, void * src, uint_t length, void * priv_data) {
+static int file_eq_fn(addr_t key1, addr_t key2) {
+ char * name1 = (char *)key1;
+ char * name2 = (char *)key2;
- 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);
+ 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[];
-
-
- /*
- {
- struct v3_xml * cfg = v3_xml_parse((char *)test_cfg_xml);
- struct v3_xml * devs = NULL;
- struct v3_xml * tmp = NULL;
- PrintError("Parsed XML COnfig %s\n", v3_xml_name(cfg));
-
- PrintError("memory=%s\n", v3_xml_txt(v3_xml_child(cfg, "memory")));
-
- devs = v3_xml_child(cfg, "devices");
-
- for (tmp = v3_xml_child(devs, "device"); tmp; tmp = v3_xml_next(tmp)) {
- PrintError("Device: %s, id=%s\n",
- v3_xml_name(tmp),
- v3_xml_attr(tmp, "id"));
- }
- v3_xml_free(cfg);
-
- return -1;
- }
- */
-
- // Amount of ram the Guest will have, rounded to a 4K page boundary
- info->mem_size = config_ptr->mem_size & ~(addr_t)0xfff;
-
- info->cpu_id = config_ptr->guest_cpu;
+
+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;
+ }
+
/*
* 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
}
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 {
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) {
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");
-
-
- 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, "TMP_BLK", "LNX_VIRTIO_BLK");
+ info->cfg_data = parse_config(cfg_blob);
- 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);
- }
-
- } else if (config_ptr->pri_disk_type == VIRTIO) {
- if (config_ptr->pri_disk_con == RAM) {
- struct ram_hd_cfg cfg = {"LNX_VIRTIO_BLK", 0, 0,
- (addr_t)(config_ptr->pri_disk_info.ram.data_ptr),
- config_ptr->pri_disk_info.ram.size};
-
- PrintDebug("Creating Virtio RAM HD\n");
-
- v3_create_device(info, "RAM-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
+
+
--- /dev/null
+ /*
+ * 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;
+}
+
#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) {
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;
}
-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);
}
- if (dev_init(info, cfg_data) == -1) {
+ if (dev_init(info, cfg) == -1) {
PrintError("Could not initialize Device %s\n", dev_name);
return -1;
}
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);
}
}
-#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;
+}
#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;
#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);
#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;
#include <palacios/vmm_io.h>
#include <palacios/vmm_string.h>
#include <palacios/vmm.h>
-
+#include <palacios/vm_guest.h>
#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
}
#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) {
}
#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) {
uint64_t atox(const char * buf) {
uint64_t ret = 0;
+ if (*(buf + 1) == 'x') {
+ buf += 2;
+ }
+
while (isxdigit(*buf)) {
ret <<= 4;
uint64_t ret = 0;
char * buf = (char *)nptr;
+ if (*(buf + 1) == 'x') {
+ buf += 2;
+ }
+
while (isxdigit(*buf)) {
ret <<= 4;
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++;
+ }
+}
#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
#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>
* 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);
if (xml != NULL) {
child = xml->child;
- }
+ }
- if (child != NULL) {
- while (strcmp(name, child->name) != 0) {
- child = child->sibling;
- }
+ while ((child) && (strcasecmp(name, child->name) != 0)) {
+ child = child->sibling;
}
return child;
return NULL;
}
- while ((xml->attr[i]) && (strcmp(attr, xml->attr[i]) != 0)) {
+ while ((xml->attr[i]) && (strcasecmp(attr, xml->attr[i]) != 0)) {
i += 2;
}
for (i = 0;
( (root->attr[i] != NULL) &&
- (strcmp(xml->name, root->attr[i][0]) != 0) );
+ (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) && (strcmp(attr, root->attr[i][j]) != 0)) {
+ while ((root->attr[i][j] != NULL) && (strcasecmp(attr, root->attr[i][j]) != 0)) {
j += 3;
}
static int v3_xml_close_tag(struct v3_xml_root * root, char * name, char * s) {
if ( (root->cur == NULL) ||
(root->cur->name == NULL) ||
- (strcmp(name, root->cur->name))) {
+ (strcasecmp(name, root->cur->name))) {
v3_xml_err(root, s, "unexpected closing tag </%s>", name);
return -1;
}
// find tag type
for (cur = head, prev = NULL;
- ((cur) && (strcmp(cur->name, xml->name) != 0));
+ ((cur) && (strcasecmp(cur->name, xml->name) != 0));
prev = cur, cur = cur->sibling);
// find attributes for correct tag
for ((i = 0);
((tmp_attr = root->attr[i]) &&
- (strcmp(tmp_attr[0], tag_ptr) != 0));
+ (strcasecmp(tmp_attr[0], tag_ptr) != 0));
(i++)) ;
// 'tmp_attr' now points to the attribute list associated with 'tag_ptr'
for (j = 1;
( (tmp_attr) && (tmp_attr[j]) &&
- (strcmp(tmp_attr[j], attr[attr_idx]) != 0));
+ (strcasecmp(tmp_attr[j], attr[attr_idx]) != 0));
j += 3);
attr[val_idx] = v3_xml_decode(attr[val_idx], root->ent,