6 #include <linux/errno.h>
7 #include <linux/percpu.h>
8 #include <linux/sched.h>
9 #include <linux/uaccess.h>
12 #include <interfaces/vmm_stream.h>
13 #include "linux-exts.h"
14 #include "palacios-ringbuffer.h"
15 #include "palacios-vm.h"
17 #define STREAM_BUF_SIZE 1024
18 #define STREAM_NAME_LEN 128
22 static struct list_head global_streams;
24 struct stream_buffer {
25 char name[STREAM_NAME_LEN];
28 wait_queue_head_t intr_queue;
31 struct v3_guest * guest;
32 struct list_head stream_node;
36 // Currently just the list of open streams
37 struct vm_stream_state {
38 struct list_head open_streams;
41 static int stream_enqueue(struct stream_buffer * stream, char * buf, int len) {
44 bytes = ringbuf_write(stream->buf, buf, len);
50 static int stream_dequeue(struct stream_buffer * stream, char * buf, int len) {
53 bytes = ringbuf_read(stream->buf, buf, len);
58 static int stream_datalen(struct stream_buffer * stream){
59 return ringbuf_data_len(stream->buf);
66 static struct stream_buffer * find_stream_by_name(struct v3_guest * guest, const char * name) {
67 struct stream_buffer * stream = NULL;
68 struct list_head * stream_list = NULL;
69 struct vm_stream_state * vm_state = NULL;
73 stream_list = &global_streams;
75 vm_state = get_vm_ext_data(guest, "STREAM_INTERFACE");
77 if (vm_state == NULL) {
78 printk("ERROR: Could not locate vm stream state for extension STREAM_INTERFACE\n");
82 stream_list = &(vm_state->open_streams);
85 list_for_each_entry(stream, stream_list, stream_node) {
86 if (strncmp(stream->name, name, STREAM_NAME_LEN) == 0) {
95 static void * palacios_stream_open(const char * name, void * private_data) {
96 struct v3_guest * guest = (struct v3_guest *)private_data;
97 struct stream_buffer * stream = NULL;
98 struct vm_stream_state * vm_state = NULL;
101 vm_state = get_vm_ext_data(guest, "STREAM_INTERFACE");
103 if (vm_state == NULL) {
104 printk("ERROR: Could not locate vm stream state for extension STREAM_INTERFACE\n");
109 if (find_stream_by_name(guest, name) != NULL) {
110 printk("Stream already exists\n");
114 stream = kmalloc(sizeof(struct stream_buffer), GFP_KERNEL);
116 stream->buf = create_ringbuf(STREAM_BUF_SIZE);
117 stream->guest = guest;
119 strncpy(stream->name, name, STREAM_NAME_LEN - 1);
121 init_waitqueue_head(&(stream->intr_queue));
122 spin_lock_init(&(stream->lock));
125 list_add(&(stream->stream_node), &(global_streams));
127 list_add(&(stream->stream_node), &(vm_state->open_streams));
134 static int palacios_stream_write(void * stream_ptr, char * buf, int len) {
135 struct stream_buffer * stream = (struct stream_buffer *)stream_ptr;
138 ret = stream_enqueue(stream, buf, len);
141 wake_up_interruptible(&(stream->intr_queue));
148 static void palacios_stream_close(void * stream_ptr) {
149 struct stream_buffer * stream = (struct stream_buffer *)stream_ptr;
151 free_ringbuf(stream->buf);
152 list_del(&(stream->stream_node));
157 static struct v3_stream_hooks palacios_stream_hooks = {
158 .open = palacios_stream_open,
159 .write = palacios_stream_write,
160 .close = palacios_stream_close,
164 static int stream_init( void ) {
165 INIT_LIST_HEAD(&(global_streams));
166 V3_Init_Stream(&palacios_stream_hooks);
172 static int stream_deinit( void ) {
173 if (!list_empty(&(global_streams))) {
174 printk("Error removing module with open streams\n");
180 static int stream_connect(struct v3_guest * guest, unsigned int cmd, unsigned long arg, void * priv_data) {
181 void __user * argp = (void __user *)arg;
182 char path_name[STREAM_NAME_LEN];
184 if (copy_from_user(path_name, argp, STREAM_NAME_LEN)) {
185 printk("%s(%d): copy from user error...\n", __FILE__, __LINE__);
189 printk("ERROR: Opening Streams is currently not implemented...\n");
195 static int guest_stream_init(struct v3_guest * guest, void ** vm_data) {
196 struct vm_stream_state * state = kmalloc(sizeof(struct vm_stream_state), GFP_KERNEL);
198 INIT_LIST_HEAD(&(state->open_streams));
202 add_guest_ctrl(guest, V3_VM_STREAM_CONNECT, stream_connect, state);
208 static int guest_stream_deinit(struct v3_guest * guest, void * vm_data) {
209 struct vm_stream_state * state = vm_data;
210 if (!list_empty(&(state->open_streams))) {
211 printk("Error shutting down VM with open streams\n");
219 static struct linux_ext stream_ext = {
220 .name = "STREAM_INTERFACE",
222 .deinit = stream_deinit,
223 .guest_init = guest_stream_init,
224 .guest_deinit = guest_stream_deinit
228 register_extension(&stream_ext);