-
-#define V3_SYMMOD_INV (0x00000000)
-#define V3_SYMMOD_LNX (0x00000001)
-#define V3_SYMMOD_MOD (0x00000002)
-#define V3_SYMMOD_SEC (0x00000003)
-union v3_symmod_flags {
- uint32_t flags;
- struct {
- uint8_t type;
- } __attribute__((packed));
-} __attribute__((packed));
-
-
-struct v3_sym_module {
+struct v3_sym_capsule {
char * name;
void * start_addr;
- void * end_addr;
- uint32_t flags; // see 'struct v3_symmod_flags'
-} __attribute__((packed));
+ uint32_t size;
+ uint32_t guest_size;
+
+ union {
+ uint32_t flags;
+ struct {
+#define V3_SYMMOD_INV (0x00)
+#define V3_SYMMOD_LNX (0x01)
+#define V3_SYMMOD_MOD (0x02)
+#define V3_SYMMOD_SEC (0x03)
+ uint8_t type;
+
+#define V3_SYMMOD_ARCH_INV (0x00)
+#define V3_SYMMOD_ARCH_i386 (0x01)
+#define V3_SYMMOD_ARCH_x86_64 (0x02)
+ uint8_t arch;
+ uint16_t rsvd;
+ } __attribute__((packed));
+ } __attribute__((packed));
+
+ void * capsule_data;
+
+ struct list_head node;
+};
struct v3_symmod_loader_ops {
- int (*load_module)(struct v3_vm_info * vm, struct v3_sym_module * mod, void * priv_data);
+ int (*load_capsule)(struct v3_vm_info * vm, struct v3_sym_capsule * mod, void * priv_data);
};
struct v3_symmod_loader_ops * loader_ops;
void * loader_data;
- struct hashtable * module_table;
+ uint32_t num_avail_capsules;
+ uint32_t num_loaded_capsules;
+
+ struct hashtable * capsule_table;
/* List containing V3 symbols */
/* (defined in vmm_symmod.c) */
int v3_set_symmod_loader(struct v3_vm_info * vm, struct v3_symmod_loader_ops * ops, void * priv_data);
-int v3_load_sym_module(struct v3_vm_info * vm, char * mod_name);
+int v3_load_sym_capsule(struct v3_vm_info * vm, char * mod_name);
int v3_init_symmod_vm(struct v3_vm_info * vm, v3_cfg_tree_t * cfg);
-struct v3_sym_module * v3_get_sym_module(struct v3_vm_info * vm, char * name);
-
-
-
-
-
+struct v3_sym_capsule * v3_get_sym_capsule(struct v3_vm_info * vm, char * name);
-#define register_module(name, start, end, flags) \
- static char v3_module_name[] = name; \
- static struct v3_sym_module _v3_module \
- __attribute__((__used__)) \
- __attribute__((unused, __section__ ("_v3_modules"), \
- aligned(sizeof(addr_t)))) \
- = {v3_module_name, start, end, flags};
int V3_init_symmod();
#endif
#ifdef CONFIG_SYMMOD
else if (evt->scan_code == 0x40) { // F6 Test symmod load
- v3_load_sym_module(vm, "test_32");
+ v3_load_sym_capsule(vm, "lnx_test");
}
#endif
#include <palacios/vm_guest_mem.h>
#include <devices/lnx_virtio_pci.h>
#include <palacios/vmm_symmod.h>
+#include <palacios/vmm_hashtable.h>
#include <devices/pci.h>
#define NUM_QUEUES 2
struct sym_config {
+ uint32_t avail_mods;
+ uint32_t loaded_mods;
} __attribute__((packed));
struct vm_device * pci_bus;
struct pci_device * pci_dev;
-
+ struct v3_vm_info * vm;
+ struct v3_symmod_state * symmod_state;
+
#define NOTIFY_QUEUE 0
#define LOADER_QUEUE 1
+struct symmod_cmd {
+#define CMD_INV 0
+#define CMD_LOAD 1
+#define CMD_LIST 2
+ uint32_t cmd;
+ uint32_t num_cmds;
+} __attribute__((packed));
+
+
// structure of the symmod notifier ring structures
struct symmod_hdr {
uint32_t num_bytes;
char name[32];
+ union {
+ uint32_t flags;
+ struct {
+#define V3_SYMMOD_INV (0x00)
+#define V3_SYMMOD_LNX (0x01)
+#define V3_SYMMOD_MOD (0x02)
+#define V3_SYMMOD_SEC (0x03)
+ uint8_t type;
+
+#define V3_SYMMOD_ARCH_INV (0x00)
+#define V3_SYMMOD_ARCH_i386 (0x01)
+#define V3_SYMMOD_ARCH_x86_64 (0x02)
+ uint8_t arch;
+
+#define V3_SYMMOD_ACT_INV (0x00)
+#define V3_SYMMOD_ACT_ADVERTISE (0x01)
+#define V3_SYMMOD_ACT_LOAD (0x02)
+ uint8_t action;
+
+ uint8_t rsvd;
+ } __attribute__((packed));
+ } __attribute__((packed));
} __attribute__((packed));
virtio->queue[1].queue_size = QUEUE_SIZE;
- memset(&(virtio->sym_cfg), 0, sizeof(struct sym_config));
+ virtio->sym_cfg.avail_mods = virtio->symmod_state->num_avail_capsules;
+ virtio->sym_cfg.loaded_mods = virtio->symmod_state->num_loaded_capsules;
return 0;
}
PrintDebug("SYMMOD: VIRTIO SYMMOD Kick on loader queue\n");
while (q->cur_avail_idx != q->avail->index) {
- struct vring_desc * hdr_desc = NULL;
- struct vring_desc * buf_desc = NULL;
- struct vring_desc * status_desc = NULL;
+ struct vring_desc * cmd_desc = NULL;
+ struct symmod_cmd * cmd = NULL;
uint16_t desc_idx = q->avail->ring[q->cur_avail_idx % QUEUE_SIZE];
uint16_t desc_cnt = get_desc_count(q, desc_idx);
- struct symmod_hdr * hdr = NULL;
- int i;
- uint32_t xfer_len = 0;
+ struct vring_desc * status_desc = NULL;
uint8_t status = 0;
uint8_t * status_ptr = NULL;
- struct v3_sym_module * module = NULL;
- uint32_t offset = 0;
-
-
- PrintDebug("Descriptor Count=%d, index=%d\n", desc_cnt, q->cur_avail_idx % QUEUE_SIZE);
+ int i;
+ uint32_t xfer_len = 0;
- if (desc_cnt < 3) {
- PrintError("Symmod loads must include at least 3 descriptors (cnt=%d)\n", desc_cnt);
- return -1;
- }
+ cmd_desc = &(q->desc[desc_idx]);
- hdr_desc = &(q->desc[desc_idx]);
-
- if (guest_pa_to_host_va(core, hdr_desc->addr_gpa, (addr_t *)&hdr) == -1) {
+ if (guest_pa_to_host_va(core, cmd_desc->addr_gpa, (addr_t *)&cmd) == -1) {
PrintError("Could not translate SYMMOD header address\n");
return -1;
}
- desc_idx = hdr_desc->next;
-
- module = v3_get_sym_module(core->vm_info, hdr->name);
+ desc_idx = cmd_desc->next;
- for (i = 0; i < desc_cnt - 2; i++) {
- uint8_t tmp_status = 0;
- uint8_t * buf = NULL;
+ if (cmd->cmd == CMD_LOAD) {
+ struct vring_desc * name_desc = NULL;
+ struct vring_desc * buf_desc = NULL;
+ char * name = NULL;
+ struct v3_sym_capsule * capsule = NULL;
+ uint32_t offset = 0;
+
- buf_desc = &(q->desc[desc_idx]);
+ PrintDebug("Descriptor Count=%d, index=%d\n", desc_cnt, q->cur_avail_idx % QUEUE_SIZE);
+
+ if (desc_cnt < 3) {
+ PrintError("Symmod loads must include at least 3 descriptors (cnt=%d)\n", desc_cnt);
+ return -1;
+ }
+
+ name_desc = &(q->desc[desc_idx]);
- if (guest_pa_to_host_va(core, buf_desc->addr_gpa, (addr_t *)&(buf)) == -1) {
- PrintError("Could not translate buffer address\n");
+ if (guest_pa_to_host_va(core, name_desc->addr_gpa, (addr_t *)&name) == -1) {
+ PrintError("Could not translate SYMMOD header address\n");
return -1;
}
- memcpy(buf, module->start_addr + offset, buf_desc->length);
- PrintDebug("Copying module to virtio buffers: SRC=%p, DST=%p, len=%d\n",
- (void *)(module->start_addr + offset), (void *)buf, buf_desc->length);
+ desc_idx = name_desc->next;
- if (tmp_status != 0) {
- PrintError("Error loading module segment\n");
- status = tmp_status;
- }
+ capsule = v3_get_sym_capsule(core->vm_info, name);
+ for (i = 0; i < desc_cnt - 3; i++) {
+ uint8_t tmp_status = 0;
+ uint8_t * buf = NULL;
- offset += buf_desc->length;
- xfer_len += buf_desc->length;
- desc_idx = buf_desc->next;
+ buf_desc = &(q->desc[desc_idx]);
+
+ if (guest_pa_to_host_va(core, buf_desc->addr_gpa, (addr_t *)&(buf)) == -1) {
+ PrintError("Could not translate buffer address\n");
+ return -1;
+ }
+
+ memcpy(buf, capsule->start_addr + offset, buf_desc->length);
+ PrintDebug("Copying module to virtio buffers: SRC=%p, DST=%p, len=%d\n",
+ (void *)(capsule->start_addr + offset), (void *)buf, buf_desc->length);
+
+ if (tmp_status != 0) {
+ PrintError("Error loading module segment\n");
+ status = tmp_status;
+ }
+
+
+ offset += buf_desc->length;
+ xfer_len += buf_desc->length;
+ desc_idx = buf_desc->next;
+ }
+ } else {
+ PrintError("Invalid SYMMOD Loader command\n");
+ return -1;
}
status_desc = &(q->desc[desc_idx]);
q->used->index++;
q->cur_avail_idx++;
+
}
}
+
+
+static int handle_notification_kick(struct guest_info * core, struct virtio_sym_state * sym_state) {
+ // struct virtio_queue * q = sym_state->cur_queue;
+ struct virtio_queue * q = &(sym_state->queue[NOTIFY_QUEUE]);
+ struct hashtable_iter * capsule_iter = NULL;
+
+ PrintDebug("SYMMOD: VIRTIO SYMMOD Kick on notification queue\n");
+
+ capsule_iter = v3_create_htable_iter(sym_state->symmod_state->capsule_table);
+
+ do {
+ uint16_t desc_idx = q->avail->ring[q->cur_avail_idx % q->queue_size];
+ struct vring_desc * hdr_desc = NULL;
+ struct symmod_hdr * hdr = NULL;
+ struct v3_sym_capsule * capsule = NULL;
+
+
+ capsule = (struct v3_sym_capsule *)v3_htable_get_iter_value(capsule_iter);
+
+
+ PrintDebug("SYMMOD: Advertising Capsule %s\n", capsule->name);
+
+ if (capsule->type != V3_SYMMOD_LNX) {
+ continue;
+ }
+
+
+
+ if (q->cur_avail_idx == q->avail->index) {
+ PrintError("Notification Queue Too SMALL\n");
+ return -1;
+ }
+
+ hdr_desc = &(q->desc[desc_idx]);
+
+ if (guest_pa_to_host_va(core, hdr_desc->addr_gpa, (addr_t *)&hdr) == -1) {
+ PrintError("Could not translate SYMMOD header address\n");
+ return -1;
+ }
+
+ memset(hdr, 0, sizeof(struct symmod_hdr));
+
+
+ memcpy(hdr->name, capsule->name, strlen(capsule->name));
+ hdr->num_bytes = capsule->size;
+ hdr->flags = capsule->flags;
+ hdr->action = V3_SYMMOD_ACT_ADVERTISE;
+
+ q->used->ring[q->used->index % QUEUE_SIZE].id = q->avail->ring[q->cur_avail_idx % QUEUE_SIZE];
+ q->used->ring[q->used->index % QUEUE_SIZE].length = sizeof(struct symmod_hdr) ; // set to total inbound xfer length
+
+ q->used->index++;
+ q->cur_avail_idx++;
+
+ } while (v3_htable_iter_advance(capsule_iter));
+
+
+ if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
+ PrintDebug("Raising IRQ %d\n", sym_state->pci_dev->config_header.intr_line);
+ v3_pci_raise_irq(sym_state->pci_bus, 0, sym_state->pci_dev);
+ sym_state->virtio_cfg.pci_isr = 1;
+ }
+
+
+ return 0;
+}
+
+
static int virtio_io_write(struct guest_info * core, uint16_t port, void * src, uint_t length, void * private_data) {
struct virtio_sym_state * sym_state = (struct virtio_sym_state *)private_data;
int port_idx = port % sym_state->io_range_size;
break;
case VRING_Q_NOTIFY_PORT: {
uint16_t queue_idx = *(uint16_t *)src;
-
+
PrintDebug("SYMMOD: Handling Kick\n");
-
+
if (queue_idx == 0) {
+ if (handle_notification_kick(core, sym_state) == -1) {
+ PrintError("Could not handle Notification Kick\n");
+ return -1;
+ }
+
sym_state->notifier_active = 1;
-
+
} else if (queue_idx == 1) {
if (handle_xfer_kick(core, sym_state) == -1) {
PrintError("Could not handle Symbiotic Notification\n");
PrintError("Kick on invalid queue (%d)\n", queue_idx);
return -1;
}
-
+
break;
}
case VIRTIO_STATUS_PORT:
uint8_t * cfg_ptr = (uint8_t *)&(sym_state->sym_cfg);
memcpy(dst, cfg_ptr + cfg_offset, length);
+
+ V3_Print("Reading SymConfig at idx %d (val=%x)\n", cfg_offset, *(uint32_t *)cfg_ptr);
} else {
PrintError("Read of Unhandled Virtio Read\n");
-static int virtio_load_module(struct v3_vm_info * vm, struct v3_sym_module * mod, void * priv_data) {
+static int virtio_load_capsule(struct v3_vm_info * vm, struct v3_sym_capsule * mod, void * priv_data) {
struct virtio_sym_state * virtio = (struct virtio_sym_state *)priv_data;
// struct virtio_queue * q = virtio->cur_queue;
struct virtio_queue * q = &(virtio->queue[NOTIFY_QUEUE]);
- uint32_t mod_size = mod->end_addr - mod->start_addr;
+
if (strlen(mod->name) >= 32) {
- PrintError("Module name is too long... (%d bytes) limit is 32\n", (uint32_t)strlen(mod->name));
+ PrintError("Capsule name is too long... (%d bytes) limit is 32\n", (uint32_t)strlen(mod->name));
return -1;
}
- PrintDebug("SYMMOD: VIRTIO SYMMOD Loader: Loading Module (size=%d)\n", mod_size);
+ PrintDebug("SYMMOD: VIRTIO SYMMOD Loader: Loading Capsule (size=%d)\n", mod->size);
//queue is not set yet
if (q->ring_avail_addr == 0) {
// clear the notifier
memset(notifier, 0, sizeof(struct symmod_hdr));
- // set the module name
+ // set the capsule name
memcpy(notifier->name, mod->name, strlen(mod->name));
- // set module length
- notifier->num_bytes = mod_size;
+ // set capsule length
+ notifier->num_bytes = mod->size;
+ notifier->flags = mod->flags;
+ notifier->action = V3_SYMMOD_ACT_LOAD;
q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size];
static struct v3_symmod_loader_ops loader_ops = {
- .load_module = virtio_load_module,
+ .load_capsule = virtio_load_capsule,
};
static int virtio_init(struct v3_vm_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 v3_symmod_state * symmod_state = &(vm->sym_vm_state.symmod_state);
struct pci_device * pci_dev = NULL;
char * name = v3_cfg_val(cfg, "name");
virtio_state = (struct virtio_sym_state *)V3_Malloc(sizeof(struct virtio_sym_state));
memset(virtio_state, 0, sizeof(struct virtio_sym_state));
+ virtio_state->vm = vm;
+ virtio_state->symmod_state = symmod_state;
+
+
+
+
struct vm_device * dev = v3_allocate_device(name, &dev_ops, virtio_state);
if (v3_attach_device(vm, dev) == -1) {
virtio_state->pci_dev = pci_dev;
virtio_state->pci_bus = pci_bus;
}
+
+
+
+ V3_Print("SYMMOD: %d available sym modules\n", virtio_state->sym_cfg.avail_mods);
virtio_reset(virtio_state);
#include <palacios/vmm_symmod.h>
#include <palacios/vmm_symbiotic.h>
#include <palacios/vm_guest.h>
+#include <palacios/vmm_list.h>
+
+static struct hashtable * capsule_table = NULL;
+static LIST_HEAD(capsule_list);
-static struct hashtable * master_mod_table = NULL;
/*
- * This is a place holder to ensure that the _v3_modules section gets created
+ * This is a place holder to ensure that the _v3_modules section gets created by gcc
*/
static struct {} null_mod __attribute__((__used__)) \
- __attribute__((unused, __section__ ("_v3_modules"), \
+ __attribute__((unused, __section__ ("_v3_capsules"), \
aligned(sizeof(addr_t))));
static uint_t mod_hash_fn(addr_t key) {
}
+struct capsule_def {
+ char * name;
+ addr_t start_addr;
+ addr_t end_addr;
+ uint32_t flags; // see 'struct v3_symmod_flags'
+} __attribute__((packed));
+
+
int V3_init_symmod() {
- extern struct v3_sym_module __start__v3_modules[];
- extern struct v3_sym_module __stop__v3_modules[];
- struct v3_sym_module * tmp_mod = __start__v3_modules;
+ extern struct capsule_def __start__v3_capsules[];
+ extern struct capsule_def __stop__v3_capsules[];
+ struct capsule_def * tmp_def = __start__v3_capsules;
int i = 0;
- if (tmp_mod == __stop__v3_modules) {
- PrintDebug("No Symbiotic modules found\n");
+ if (tmp_def == __stop__v3_capsules) {
+ PrintDebug("No Symbiotic capsules found\n");
return 0;
}
- master_mod_table = v3_create_htable(0, mod_hash_fn, mod_eq_fn);
+ capsule_table = v3_create_htable(0, mod_hash_fn, mod_eq_fn);
- while (tmp_mod != __stop__v3_modules) {
+ while (tmp_def != __stop__v3_capsules) {
+ struct v3_sym_capsule * capsule = NULL;
- if (v3_htable_search(master_mod_table, (addr_t)(tmp_mod->name))) {
- PrintError("Multiple instances of Module (%s)\n", tmp_mod->name);
+ if (v3_htable_search(capsule_table, (addr_t)(tmp_def->name))) {
+ PrintError("Multiple instances of Module (%s)\n", tmp_def->name);
return -1;
}
- PrintDebug("Registering Symbiotic Module (%s)\n", tmp_mod->name);
- if (v3_htable_insert(master_mod_table,
- (addr_t)(tmp_mod->name),
- (addr_t)(tmp_mod)) == 0) {
- PrintError("Could not insert module %s to master list\n", tmp_mod->name);
+ capsule = V3_Malloc(sizeof(struct v3_sym_capsule));
+ memset(capsule, 0, sizeof(struct v3_sym_capsule));
+
+ capsule->name = tmp_def->name;
+ capsule->start_addr = (void *)(tmp_def->start_addr);
+ capsule->size = tmp_def->end_addr - tmp_def->start_addr;
+ capsule->flags = tmp_def->flags;
+
+
+
+ if (capsule->type == V3_SYMMOD_MOD) {
+ // parse module
+ // capsule->capsule_data = v3_sym_module...
+ // capsule->guest_size = size of linked module
+ } else if (capsule->type == V3_SYMMOD_LNX) {
+ capsule->guest_size = capsule->size;
+ capsule->capsule_data = NULL;
+ } else {
+ return -1;
+ }
+
+ PrintDebug("Registering Symbiotic Module (%s)\n", tmp_def->name);
+
+ if (v3_htable_insert(capsule_table,
+ (addr_t)(tmp_def->name),
+ (addr_t)(capsule)) == 0) {
+ PrintError("Could not insert module %s to master list\n", tmp_def->name);
return -1;
}
- tmp_mod = &(__start__v3_modules[++i]);
+ list_add(&(capsule->node), &capsule_list);
+
+ tmp_def = &(__start__v3_capsules[++i]);
}
return 0;
uint32_t value;
} __attribute__((packed));
+struct v3_symbol_def64 {
+ uint64_t name_gva;
+ uint64_t value;
+} __attribute__((packed));
+
+
+
struct v3_symbol {
char name[256];
uint64_t linkage;
int v3_init_symmod_vm(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
struct v3_symmod_state * symmod_state = &(vm->sym_vm_state.symmod_state);
struct v3_symspy_global_page * sym_page = v3_sym_get_symspy_vm(vm);
+ struct v3_sym_capsule * tmp_capsule = NULL;
+ symmod_state->capsule_table = v3_create_htable(0, mod_hash_fn, mod_eq_fn);
+
+
+ // Add modules to local hash table, should be keyed to config
+ list_for_each_entry(tmp_capsule, &capsule_list, node) {
+ V3_Print("Adding %s to local module table\n", tmp_capsule->name);
+ if (v3_htable_insert(symmod_state->capsule_table,
+ (addr_t)(tmp_capsule->name),
+ (addr_t)(tmp_capsule)) == 0) {
+ PrintError("Could not insert module %s to vm local list\n", tmp_capsule->name);
+ return -1;
+ }
+ symmod_state->num_avail_capsules++;
+ }
+
+ symmod_state->num_loaded_capsules = 0;
sym_page->symmod_enabled = 1;
v3_register_hypercall(vm, SYMMOD_SYMS_HCALL, symbol_hcall_handler, NULL);
-int v3_load_sym_module(struct v3_vm_info * vm, char * mod_name) {
+int v3_load_sym_capsule(struct v3_vm_info * vm, char * name) {
struct v3_symmod_state * symmod_state = &(vm->sym_vm_state.symmod_state);
- struct v3_sym_module * mod = (struct v3_sym_module *)v3_htable_search(master_mod_table, (addr_t)mod_name);
+ struct v3_sym_capsule * capsule = (struct v3_sym_capsule *)v3_htable_search(capsule_table, (addr_t)name);
- if (!mod) {
- PrintError("Could not find module %s\n", mod_name);
+ if (!capsule) {
+ PrintError("Could not find capsule %s\n", name);
return -1;
}
- PrintDebug("Loading Module (%s)\n", mod_name);
+ PrintDebug("Loading Capsule (%s)\n", name);
- return symmod_state->loader_ops->load_module(vm, mod, symmod_state->loader_data);
+ return symmod_state->loader_ops->load_capsule(vm, capsule, symmod_state->loader_data);
}
+struct list_head * v3_get_sym_capsule_list() {
+ return &(capsule_list);
+}
+
-struct v3_sym_module * v3_get_sym_module(struct v3_vm_info * vm, char * name) {
- struct v3_sym_module * mod = (struct v3_sym_module *)v3_htable_search(master_mod_table, (addr_t)name);
+struct v3_sym_capsule * v3_get_sym_capsule(struct v3_vm_info * vm, char * name) {
+ struct v3_sym_capsule * mod = (struct v3_sym_capsule *)v3_htable_search(capsule_table, (addr_t)name);
if (!mod) {
PrintError("Could not find module %s\n", name);
ifeq ($(MOD_TYPE),V3_LINUX_MOD)
- MOD_IDX := 1
+ TYPE_IDX := 1
else ifeq ($(MOD_TYPE),V3_SYM_MOD)
- MOD_IDX := 2
-else ifeq($(MOD_TYPE),V3_SEC_MOD)
- MOD_IDX := 3
+ TYPE_IDX := 2
+else ifeq ($(MOD_TYPE),V3_SEC_MOD)
+ TYPE_IDX := 3
+else
+ TYPE_IDX := 0
+endif
+
+ifeq ($(MOD_ARCH),i386)
+ ARCH_IDX := 1
+else ifeq ($(MOD_ARCH),x86_64)
+ ARCH_IDX := 2
+else
+ ARCH_IDX := 0
endif
DEFS := -DMOD_NAME=$(MOD_NAME) \
-DMOD_DIR=$(MOD_DIR) \
-DMOD_OBJ=$(MOD_OBJ) \
- -DMOD_TYPE=$(MOD_IDX)
+ -DMOD_TYPE=$(TYPE_IDX) \
+ -DMOD_ARCH=$(ARCH_IDX)
# cpp -undef $(DEFS) binary.S -o $(MOD_DIR)/.tmp.binary.S
#define MOD_NM(name) TOSTR(name)
-
-
-.globl mod_start
mod_start:
.incbin MOD_PATH(MOD_DIR,MOD_OBJ)
mod_stop:
.ascii MOD_NM(MOD_NAME)
-.section _v3_modules, "a"
+.section _v3_capsules, "a"
IDENT(#ifdef __x86_64__)
.quad mod_name
.quad mod_start
.quad mod_stop
-.long MOD_TYPE
+.byte MOD_TYPE
+.byte MOD_ARCH
+.space 2
IDENT(#else)
.long mod_name
.space 4
.space 4
.long mod_stop
.space 4
-.long MOD_TYPE
+.byte MOD_TYPE
+.byte MOD_ARCH
+.space 2
IDENT(#endif)
# First the linux module is compiled via the target kernels build system
# Second, the module is encapsulated for the Palacios VMM
-V3_MOD_NAME := test
+V3_MOD_NAME := lnx_test
V3_MOD_OBJ := test.ko
LINUX_MOD_OBJ := test.o
# This is the target used by the Linux build process
ifneq ($(KERNELRELEASE),)
obj-m := $(LINUX_MOD_OBJ)
-else
+else
+
# These are configuration values to be set
KERNELDIR := /home/jarusl/linux-2.6.30.y
PWD := $(shell pwd)
- PALACIOSDIR := $(PWD)/../../capsule
+ PALACIOSDIR := $(PWD)/../../..
+ CAPSULEDIR := $(PALACIOSDIR)/symmods/capsule
V3_MOD_TYPE := V3_LINUX_MOD
-
+ V3_MOD_ARCH := i386
linux: FORCE
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
capsule: FORCE
- $(MAKE) -C $(PALACIOSDIR) MOD_NAME=$(V3_MOD_NAME) MOD_DIR=$(PWD) \
- MOD_OBJ=$(V3_MOD_OBJ) MOD_TYPE=$(V3_MOD_TYPE)
+ $(MAKE) -C $(CAPSULEDIR) MOD_NAME=$(V3_MOD_NAME) MOD_DIR=$(PWD) \
+ MOD_OBJ=$(V3_MOD_OBJ) MOD_TYPE=$(V3_MOD_TYPE) \
+ MOD_ARCH=$(V3_MOD_ARCH)
default: linux capsule
+install:
+ cp $(V3_MOD_NAME).vo $(PALACIOSDIR)/modules/
+
FORCE:
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".
+ */
+
+
+struct v3_mod_info {
+ int (*init)(char * args);
+ int (*exit)();
+} __attribute__((packed));
+
+
+#define register_module(init_fn, exit_fn) \
+ static struct v3_mod_info _v3_mod \
+ __attribute__((used)) \
+ __attribute__((unused, __section__(".v3_linkage"), \
+ aligned(8))) \
+ = {init_fn, exit_fn};
+
+
+/*
+ * Module interface API
+ */
+
+
+int v3_mod_test(void);
+int v3_var_test;
+
+int v3_printk(const char * fmt, ...);