SECTIONS
{
+
+ _lnx_exts :
+ {
+ __start__lnx_exts = .;
+ *(_lnx_exts);
+ __stop__lnx_exts = .;
+ }
_v3_devices :
{
__start__v3_devices = .;
__stop__v3_extensions = .;
}
- _lnx_exts :
- {
- __start__lnx_exts = .;
- *(_lnx_exts);
- __stop__lnx_exts = .;
- }
+
}
/*
* This is a place holder to ensure that the _lnx_exts section gets created by gcc
*/
+
+
static struct {} null_ext __attribute__((__used__)) \
- __attribute__((unused, __section__ ("_lnx_exts"), \
- aligned(sizeof(void *))));
+ __attribute__((unused, __section__ ("_lnx_exts"), \
+ aligned(sizeof(void *))));
+struct vm_ext {
+ struct linux_ext * impl;
+ void * vm_data;
+ struct list_head node;
+};
int init_vm_extensions(struct v3_guest * guest) {
- extern struct linux_ext * __start__lnx_exts;
- extern struct linux_ext * __stop__lnx_exts;
- struct linux_ext * tmp_ext = __start__lnx_exts;
+ extern struct linux_ext * __start__lnx_exts[];
+ extern struct linux_ext * __stop__lnx_exts[];
+ struct linux_ext * ext_impl = __start__lnx_exts[0];
int i = 0;
- while (tmp_ext != __stop__lnx_exts) {
- printk("Registering Linux Extension (%s)\n", tmp_ext->name);
- tmp_ext->init();
+ while (ext_impl != __stop__lnx_exts[0]) {
+ struct vm_ext * ext = NULL;
+
+ if (ext_impl->guest_init == NULL) {
+ // We can have global extensions without per guest state
+ continue;
+ }
+
+ printk("Registering Linux Extension (%s)\n", ext_impl->name);
+
+ ext = kmalloc(sizeof(struct vm_ext), GFP_KERNEL);
+
+ if (!ext) {
+ printk("Error allocating VM extension (%s)\n", ext_impl->name);
+ return -1;
+ }
- tmp_ext = &(__start__lnx_exts[++i]);
+ ext->impl = ext_impl;
+
+ ext_impl->guest_init(guest, &(ext->vm_data));
+
+ list_add(&(ext->node), &(guest->exts));
+
+ ext_impl = __start__lnx_exts[++i];
}
return 0;
+}
+
+int deinit_vm_extensions(struct v3_guest * guest) {
+ struct vm_ext * ext = NULL;
+ struct vm_ext * tmp = NULL;
+
+ list_for_each_entry_safe(ext, tmp, &(guest->exts), node) {
+ if (ext->impl->guest_deinit) {
+ ext->impl->guest_deinit(guest, ext->vm_data);
+ } else {
+ printk("WARNING: Extension %s, does not have a guest deinit function\n", ext->impl->name);
+ }
+
+ list_del(&(ext->node));
+ kfree(ext);
+ }
+
+ return 0;
}
int init_lnx_extensions( void ) {
- extern struct linux_ext * __start__lnx_exts;
- extern struct linux_ext * __stop__lnx_exts;
- struct linux_ext * tmp_ext = __start__lnx_exts;
+ extern struct linux_ext * __start__lnx_exts[];
+ extern struct linux_ext * __stop__lnx_exts[];
+ struct linux_ext * tmp_ext = __start__lnx_exts[0];
int i = 0;
- while (tmp_ext != __stop__lnx_exts) {
- printk("Registering Linux Extension (%s)\n", tmp_ext->name);
- tmp_ext->init();
+ while (tmp_ext != __stop__lnx_exts[0]) {
+
+ printk("tmp_ext=%p\n", tmp_ext);
+
+ if (tmp_ext->init != NULL) {
+ printk("Registering Linux Extension (%s)\n", tmp_ext->name);
+ tmp_ext->init();
+ }
- tmp_ext = &(__start__lnx_exts[++i]);
+ tmp_ext = __start__lnx_exts[++i];
}
return 0;
int deinit_lnx_extensions( void ) {
- extern struct linux_ext * __start__lnx_exts;
- extern struct linux_ext * __stop__lnx_exts;
- struct linux_ext * tmp_ext = __start__lnx_exts;
+ extern struct linux_ext * __start__lnx_exts[];
+ extern struct linux_ext * __stop__lnx_exts[];
+ struct linux_ext * tmp_ext = __start__lnx_exts[0];
int i = 0;
- while (tmp_ext != __stop__lnx_exts) {
+ while (tmp_ext != __stop__lnx_exts[0]) {
printk("Cleaning up Linux Extension (%s)\n", tmp_ext->name);
- tmp_ext->deinit();
+ if (tmp_ext->deinit != NULL) {
+ tmp_ext->deinit();
+ } else {
+ printk("WARNING: Extension %s does not have a global deinit function\n", tmp_ext->name);
+ }
- tmp_ext = &(__start__lnx_exts[++i]);
+ tmp_ext = __start__lnx_exts[++i];
}
return 0;
int (*deinit)( void );
int (*guest_init)(struct v3_guest * guest, void ** priv_data);
int (*guest_deinit)(struct v3_guest * guest, void * priv_data);
-} __attribute__((packed));
+};
#define register_extension(ext) \
static struct linux_ext * _lnx_ext \
__attribute__((used)) \
- __attribute__((unused, __section("_lnx_exts"), \
+ __attribute__((unused, __section__("_lnx_exts"), \
aligned(sizeof(void *)))) \
= ext;
#include <interfaces/vmm_console.h>
#include <palacios/vmm_host_events.h>
+#include "palacios-vm.h"
#include "palacios.h"
-#include "palacios-console.h"
#include "palacios-queue.h"
+#include "linux-exts.h"
typedef enum { CONSOLE_CURS_SET = 1,
CONSOLE_CHAR_SET = 2,
+struct palacios_console {
+ struct gen_queue * queue;
+ spinlock_t lock;
+
+ int open;
+ int connected;
+
+ wait_queue_head_t intr_queue;
+
+ unsigned int width;
+ unsigned int height;
+
+ struct v3_guest * guest;
+};
+
+
+
struct cursor_msg {
int x;
int y;
-int connect_console(struct v3_guest * guest) {
- struct palacios_console * cons = &(guest->console);
+static int console_connect(struct v3_guest * guest, unsigned int cmd,
+ unsigned long arg, void * priv_data) {
+ struct palacios_console * cons = priv_data;
int cons_fd = 0;
unsigned long flags;
static void * palacios_tty_open(void * private_data, unsigned int width, unsigned int height) {
struct v3_guest * guest = (struct v3_guest *)private_data;
- struct palacios_console * cons = &(guest->console);
+ struct palacios_console * cons = kmalloc(sizeof(struct palacios_console), GFP_KERNEL);
printk("Guest initialized virtual console (Guest=%s)\n", guest->name);
}
- cons->width = width;
- cons->height = height;
-
cons->queue = create_queue(CONSOLE_QUEUE_LEN);
spin_lock_init(&(cons->lock));
init_waitqueue_head(&(cons->intr_queue));
cons->guest = guest;
- cons->open = 1;
cons->connected = 0;
+ cons->width = width;
+ cons->height = height;
+ cons->open = 1;
+ add_guest_ctrl(guest, V3_VM_CONSOLE_CONNECT, console_connect, cons);
+
return cons;
}
-int palacios_init_console( void ) {
+
+
+
+static int console_init( void ) {
V3_Init_Console(&palacios_console_hooks);
return 0;
}
+
+
+
+
+static struct linux_ext console_ext = {
+ .name = "CONSOLE",
+ .init = console_init,
+ .deinit = NULL,
+ .guest_init = NULL,
+ .guest_deinit = NULL
+};
+
+
+register_extension(&console_ext);
+++ /dev/null
-/*
- * Palacios VM Stream Console interface
- * (c) Jack Lange, 2010
- */
-
-#ifndef __PALACIOS_CONSOLE_H__
-#define __PALACIOS_CONSOLE_H__
-
-
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-
-
-struct palacios_console {
- struct gen_queue * queue;
- spinlock_t lock;
-
- int open;
- int connected;
-
- wait_queue_head_t intr_queue;
-
- unsigned int width;
- unsigned int height;
-
- struct v3_guest * guest;
-};
-
-
-
-struct v3_guest;
-
-
-int connect_console(struct v3_guest * guest);
-
-int palacios_init_console( void );
-
-
-#endif
#include "palacios-vnet.h"
#include "palacios-packet.h"
+#include "linux-exts.h"
+
#ifdef V3_CONFIG_EXT_INSPECTOR
#include "palacios-inspector.h"
#endif
struct class * v3_class = NULL;
static struct cdev ctrl_dev;
-void * v3_base_addr = NULL;
-unsigned int v3_pages = 0;
-
static int register_vm( void ) {
int i, j = 0;
int avail = 0;
printk("Launching VM\n");
+ INIT_LIST_HEAD(&(guest->exts));
+
+
INIT_LIST_HEAD(&(guest->streams));
INIT_LIST_HEAD(&(guest->files));
INIT_LIST_HEAD(&(guest->sockets));
};
-extern unsigned int v3_pages;
-extern void * v3_base_addr;
static int __init v3_init(void) {
dev_t dev = MKDEV(0, 0); // We dynamicallly assign the major number
palacios_init_mm();
+
+ // Initialize Palacios
+
+ palacios_vmm_init();
+
+
+ // initialize extensions
+ init_lnx_extensions();
+
+
v3_class = class_create(THIS_MODULE, "vms");
if (IS_ERR(v3_class)) {
printk("Failed to register V3 VM device class\n");
goto failure1;
}
- if ((v3_pages > 0) && (v3_base_addr != NULL)) {
- add_palacios_memory(__pa(v3_base_addr), v3_pages);
- }
- // Initialize Palacios
-
- palacios_vmm_init();
#ifdef V3_CONFIG_STREAM
palacios_init_stream();
palacios_init_keyed_streams();
#endif
-#ifdef V3_CONFIG_CONSOLE
- palacios_init_console();
-#endif
-
#ifdef V3_CONFIG_GRAPHICS_CONSOLE
palacios_init_graphics_console();
#endif
#include "palacios-stream.h"
#endif
-#ifdef V3_CONFIG_CONSOLE
-#include "palacios-console.h"
-#endif
#ifdef V3_CONFIG_EXT_INSPECTOR
#include "palacios-inspector.h"
break;
}
- case V3_VM_CONSOLE_CONNECT: {
-#ifdef V3_CONFIG_CONSOLE
- return connect_console(guest);
-#else
- printk("Console support not available\n");
- return -EFAULT;
-#endif
- break;
- }
case V3_VM_STREAM_CONNECT: {
#ifdef V3_CONFIG_STREAM
}
// init linux extensions
+
+
#ifdef V3_CONFIG_EXT_INSPECTOR
inspect_vm(guest);
#endif
#include <linux/sched.h>
#include <linux/slab.h>
-#ifdef V3_CONFIG_CONSOLE
-#include "palacios-console.h"
-#endif
#ifdef V3_CONFIG_GRAPHICS_CONSOLE
#include "palacios-graphics-console.h"
struct list_head streams;
struct list_head sockets;
-#ifdef V3_CONFIG_CONSOLE
- struct palacios_console console;
-#endif
#ifdef V3_CONFIG_GRAPHICS_CONSOLE
struct palacios_graphics_console graphics_console;