From: Patrick G. Bridges Date: Tue, 1 Nov 2011 16:51:24 +0000 (-0600) Subject: Merge branch 'devel' of ssh://newskysaw.cs.northwestern.edu/home/palacios/palacios... X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=840121eda3c81889ddeba5374bd5bd2005e572ed;hp=d71b19cdb18342f2b761f6d9aac7ec175486e1ba Merge branch 'devel' of ssh://newskysaw.cs.northwestern.edu/home/palacios/palacios into devel --- diff --git a/linux_module/iface-packet.c b/linux_module/iface-packet.c index b067987..c03d628 100644 --- a/linux_module/iface-packet.c +++ b/linux_module/iface-packet.c @@ -17,32 +17,41 @@ #include #include -#include -#include - - -#define __V3VEE__ -#include #include -#undef __V3VEE__ #include "palacios.h" +#include "util-hashtable.h" #include "linux-exts.h" +#include "vm.h" + -struct palacios_packet_state { +/* there is one for each host nic */ +struct raw_interface { + char eth_dev[126]; /* host nic name "eth0" ... */ + struct socket * raw_sock; uint8_t inited; - - struct hashtable * mac_vm_cache; - struct task_struct * server_thread; + + struct list_head brdcast_recvers; + struct hashtable * mac_to_recver; + + struct task_struct * recv_thread; + + struct list_head node; +}; + +struct palacios_packet_state{ + spinlock_t lock; + + struct list_head open_interfaces; }; -static struct palacios_packet_state packet_state; +struct palacios_packet_state packet_state; static inline uint_t hash_fn(addr_t hdr_ptr) { uint8_t * hdr_buf = (uint8_t *)hdr_ptr; - return v3_hash_buffer(hdr_buf, ETH_ALEN); + return palacios_hash_buffer(hdr_buf, ETH_ALEN); } static inline int hash_eq(addr_t key1, addr_t key2) { @@ -50,237 +59,311 @@ static inline int hash_eq(addr_t key1, addr_t key2) { } -static int palacios_packet_add_recver(const char * mac, - struct v3_vm_info * vm){ - char * key; - - key = (char *)kmalloc(ETH_ALEN, GFP_KERNEL); - memcpy(key, mac, ETH_ALEN); - - if (v3_htable_insert(packet_state.mac_vm_cache, (addr_t)key, (addr_t)vm) == 0) { - printk("Palacios Packet: Failed to insert new mac entry to the hash table\n"); +static int +recv_pkt(struct socket * raw_sock, unsigned char * pkt, unsigned int len) { + struct msghdr msg; + struct iovec iov; + mm_segment_t oldfs; + unsigned int size = 0; + + if (raw_sock == NULL) { return -1; } - printk("Packet: Add MAC: %2x:%2x:%2x:%2x:%2x:%2x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + iov.iov_base = pkt; + iov.iov_len = len; - return 0; + msg.msg_flags = 0; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = NULL; + + oldfs = get_fs(); + set_fs(KERNEL_DS); + size = sock_recvmsg(raw_sock, &msg, len, msg.msg_flags); + set_fs(oldfs); + + return size; } -static int palacios_packet_del_recver(const char * mac, - struct v3_vm_info * vm){ - return 0; -} - -static int init_raw_socket(const char * eth_dev){ +static int +init_socket(struct raw_interface * iface, const char * eth_dev){ int err; struct sockaddr_ll sock_addr; struct ifreq if_req; - int dev_idx; - - err = sock_create(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL), &(packet_state.raw_sock)); + err = sock_create(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL), &(iface->raw_sock)); if (err < 0) { printk(KERN_WARNING "Could not create a PF_PACKET Socket, err %d\n", err); return -1; } - if (eth_dev == NULL){ - eth_dev = "eth0"; /* default "eth0" */ - } - memset(&if_req, 0, sizeof(if_req)); - strncpy(if_req.ifr_name, eth_dev, IFNAMSIZ); //sizeof(if_req.ifr_name)); - - err = packet_state.raw_sock->ops->ioctl(packet_state.raw_sock, SIOCGIFINDEX, (long)&if_req); + strncpy(if_req.ifr_name, eth_dev, sizeof(if_req.ifr_name)); + err = iface->raw_sock->ops->ioctl(iface->raw_sock, SIOCGIFINDEX, (long)&if_req); if (err < 0){ printk(KERN_WARNING "Palacios Packet: Unable to get index for device %s, error %d\n", if_req.ifr_name, err); - dev_idx = 2; /* match ALL 2:"eth0" */ - } else { - dev_idx = if_req.ifr_ifindex; - } - printk(KERN_INFO "Palacios Packet: bind to device index: %d\n", dev_idx); + sock_release(iface->raw_sock); + return -1; + } memset(&sock_addr, 0, sizeof(sock_addr)); sock_addr.sll_family = PF_PACKET; sock_addr.sll_protocol = htons(ETH_P_ALL); - sock_addr.sll_ifindex = dev_idx; + sock_addr.sll_ifindex = if_req.ifr_ifindex; - err = packet_state.raw_sock->ops->bind(packet_state.raw_sock, - (struct sockaddr *)&sock_addr, - sizeof(sock_addr)); + err = iface->raw_sock->ops->bind(iface->raw_sock, + (struct sockaddr *)&sock_addr, + sizeof(sock_addr)); if (err < 0){ printk(KERN_WARNING "Error binding raw packet to device %s, %d\n", eth_dev, err); + sock_release(iface->raw_sock); + return -1; } - printk(KERN_INFO "Bind palacios raw packet interface to device %s\n", eth_dev); + printk(KERN_INFO "Bind a palacios raw packet interface to device %s, device index %d\n", + if_req.ifr_name, if_req.ifr_ifindex); return 0; } -static int -palacios_packet_send(const char * pkt, unsigned int len, void * private_data) { - struct msghdr msg; - struct iovec iov; - mm_segment_t oldfs; - int size = 0; - - iov.iov_base = (void *)pkt; - iov.iov_len = (__kernel_size_t)len; +static inline int +is_multicast_ethaddr(const unsigned char * addr) +{ + return (0x01 & addr[0]); +} - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_flags = 0; +static inline int +is_broadcast_ethaddr(const unsigned char * addr) +{ + unsigned char ret = 0xff; + int i; + + for(i=0; ieth_dev); + while (!kthread_should_stop()) { + size = recv_pkt(iface->raw_sock, pkt, ETHERNET_PACKET_LEN); + + if (size < 0) { + printk(KERN_WARNING "Palacios raw packet receive error, Server terminated\n"); + break; + } -static struct v3_packet_hooks palacios_packet_hooks = { - .send = palacios_packet_send, - .add_recver = palacios_packet_add_recver, - .del_recver = palacios_packet_del_recver, -}; + if(is_broadcast_ethaddr(pkt)) { + /* Broadcast */ + + list_for_each_entry(recver_state, &(iface->brdcast_recvers), node) { + recver_state->input(recver_state, pkt, size); + } + + } else if(is_multicast_ethaddr(pkt)) { + /* MultiCast */ + + } else { + recver_state = (struct v3_packet *)palacios_htable_search(iface->mac_to_recver, + (addr_t)pkt); + if(recver_state != NULL) { + recver_state->input(recver_state, pkt, size); + } + } + } + + return 0; +} static int -recv_pkt(char * pkt, int len) { - struct msghdr msg; - struct iovec iov; - mm_segment_t oldfs; - int size = 0; - - if (packet_state.raw_sock == NULL) { +init_raw_interface(struct raw_interface * iface, const char * eth_dev){ + + memcpy(iface->eth_dev, eth_dev, V3_ETHINT_NAMELEN); + if(init_socket(iface, eth_dev) !=0) { + printk("packet: fails to initiate raw socket\n"); return -1; } - - iov.iov_base = pkt; - iov.iov_len = len; - msg.msg_flags = 0; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = NULL; - oldfs = get_fs(); - set_fs(KERNEL_DS); - size = sock_recvmsg(packet_state.raw_sock, &msg, len, msg.msg_flags); - set_fs(oldfs); + INIT_LIST_HEAD(&(iface->brdcast_recvers)); + iface->mac_to_recver = palacios_create_htable(0, &hash_fn, &hash_eq); + iface->recv_thread = kthread_run(packet_recv_thread, (void *)iface, "bridge-recver"); - return size; + iface->inited = 1; + + return 0; } +static void inline +deinit_raw_interface(struct raw_interface * iface){ + struct v3_packet * recver_state; -static void -send_raw_packet_to_palacios(char * pkt, - int len, - struct v3_vm_info * vm) { - struct v3_packet_event event; - char data[ETHERNET_PACKET_LEN]; - - /* one memory copy */ - memcpy(data, pkt, len); - event.pkt = data; - event.size = len; - - v3_deliver_packet_event(vm, &event); + kthread_stop(iface->recv_thread); + sock_release(iface->raw_sock); + palacios_free_htable(iface->mac_to_recver, 0, 0); + + list_for_each_entry(recver_state, &(iface->brdcast_recvers), node) { + kfree(recver_state); + } } -static int packet_server(void * arg) { - char pkt[ETHERNET_PACKET_LEN]; - int size; - struct v3_vm_info *vm; - - printk("Palacios Raw Packet Bridge: Staring receiving server\n"); - - while (!kthread_should_stop()) { - size = recv_pkt(pkt, ETHERNET_PACKET_LEN); - if (size < 0) { - printk(KERN_WARNING "Palacios raw packet receive error, Server terminated\n"); - break; +static inline struct raw_interface * +find_interface(const char * eth_dev) { + struct raw_interface * iface; + + list_for_each_entry(iface, &(packet_state.open_interfaces), node) { + if (strncmp(iface->eth_dev, eth_dev, V3_ETHINT_NAMELEN) == 0) { + return iface; } + } + return NULL; +} - /* if VNET is enabled, send to VNET */ - // ... - - - /* if it is broadcast or multicase packet */ - // ... - - - vm = (struct v3_vm_info *)v3_htable_search(packet_state.mac_vm_cache, (addr_t)pkt); - if (vm != NULL){ - printk("Find destinated VM 0x%p\n", vm); - send_raw_packet_to_palacios(pkt, size, vm); +static int +palacios_packet_connect(struct v3_packet * packet, + const char * host_nic, + void * host_vm_data) { + struct raw_interface * iface; + unsigned long flags; + + spin_lock_irqsave(&(packet_state.lock), flags); + + iface = find_interface(host_nic); + if(iface == NULL){ + iface = (struct raw_interface *)kmalloc(sizeof(struct raw_interface), GFP_KERNEL); + if(init_raw_interface(iface, host_nic) != 0) { + printk("Palacios Packet Interface: Fails to initiate an raw interface on device %s\n", host_nic); + kfree(iface); + spin_unlock_irqrestore(&(packet_state.lock), flags); + + return -1; } + + list_add(&(iface->node), &(packet_state.open_interfaces)); } - + + spin_unlock_irqrestore(&(packet_state.lock), flags); + + packet->host_packet_data = iface; + + list_add(&(packet->node), &(iface->brdcast_recvers)); + palacios_htable_insert(iface->mac_to_recver, + (addr_t)packet->dev_mac, + (addr_t)packet); + + printk(KERN_INFO "Packet: Add Receiver MAC to ethernet device %s: %2x:%2x:%2x:%2x:%2x:%2x\n", + iface->eth_dev, + packet->dev_mac[0], packet->dev_mac[1], + packet->dev_mac[2], packet->dev_mac[3], + packet->dev_mac[4], packet->dev_mac[5]); + return 0; } +static int +palacios_packet_send(struct v3_packet * packet, + unsigned char * pkt, + unsigned int len) { + struct raw_interface * iface = (struct raw_interface *)packet->host_packet_data; + struct msghdr msg; + struct iovec iov; + mm_segment_t oldfs; + int size = 0; + + if(iface->inited == 0 || + iface->raw_sock == NULL){ + printk("Palacios Packet Interface: Send fails due to inapproriate interface\n"); + + return -1; + } + + iov.iov_base = (void *)pkt; + iov.iov_len = (__kernel_size_t)len; + + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_flags = 0; -static int packet_init( void ) { + oldfs = get_fs(); + set_fs(KERNEL_DS); + size = sock_sendmsg(iface->raw_sock, &msg, len); + set_fs(oldfs); - const char * eth_dev = NULL; + return size; +} - if (packet_state.inited == 0){ - packet_state.inited = 1; - if (init_raw_socket(eth_dev) == -1){ - printk("Error to initiate palacios packet interface\n"); - return -1; - } - - V3_Init_Packet(&palacios_packet_hooks); +static void +palacios_packet_close(struct v3_packet * packet) { + struct raw_interface * iface = (struct raw_interface *)packet->host_packet_data; + + list_del(&(packet->node)); + palacios_htable_remove(iface->mac_to_recver, (addr_t)(packet->dev_mac), 0); + + packet->host_packet_data = NULL; +} - packet_state.mac_vm_cache = v3_create_htable(0, &hash_fn, &hash_eq); - packet_state.server_thread = kthread_run(packet_server, NULL, "raw-packet-server"); - } - +static struct v3_packet_hooks palacios_packet_hooks = { + .connect = palacios_packet_connect, + .send = palacios_packet_send, + .close = palacios_packet_close, +}; +static int packet_init( void ) { + V3_Init_Packet(&palacios_packet_hooks); + + memset(&packet_state, 0, sizeof(struct palacios_packet_state)); + spin_lock_init(&(packet_state.lock)); + INIT_LIST_HEAD(&(packet_state.open_interfaces)); + // REGISTER GLOBAL CONTROL to add interfaces... return 0; } static int packet_deinit( void ) { - - - kthread_stop(packet_state.server_thread); - packet_state.raw_sock->ops->release(packet_state.raw_sock); - v3_free_htable(packet_state.mac_vm_cache, 0, 1); - packet_state.inited = 0; - + struct raw_interface * iface; + + list_for_each_entry(iface, &(packet_state.open_interfaces), node) { + deinit_raw_interface(iface); + kfree(iface); + } + return 0; } - - static struct linux_ext pkt_ext = { .name = "PACKET_INTERFACE", .init = packet_init, diff --git a/palacios/include/interfaces/vmm_packet.h b/palacios/include/interfaces/vmm_packet.h index a4ba3e5..812cc11 100644 --- a/palacios/include/interfaces/vmm_packet.h +++ b/palacios/include/interfaces/vmm_packet.h @@ -24,19 +24,35 @@ #include #include +#define V3_ETHINT_NAMELEN 126 + +struct v3_packet { + void * host_packet_data; + void * guest_packet_data; + + char dev_mac[ETH_ALEN]; + int (*input)(struct v3_packet * packet, uint8_t * buf, uint32_t len); + + struct list_head node; +}; + #ifdef __V3VEE__ +#include -int V3_send_raw(const char * pkt, uint32_t len); -int V3_packet_add_recver(const char * mac, struct v3_vm_info * vm); -int V3_packet_del_recver(const char * mac, struct v3_vm_info * vm); +struct v3_packet * v3_packet_connect(struct v3_vm_info * vm, const char * host_nic, + const char * mac, + int (*input)(struct v3_packet * packet, uint8_t * buf, uint32_t len), + void * guest_packet_data); + +int v3_packet_send(struct v3_packet * packet, uint8_t * buf, uint32_t len); +void v3_packet_close(struct v3_packet * packet); #endif struct v3_packet_hooks { - - int (*send)(const char * pkt, unsigned int size, void * private_data); - int (*add_recver)(const char * mac, struct v3_vm_info * vm); - int (*del_recver)(const char * mac, struct v3_vm_info * vm); + int (*connect)(struct v3_packet * packet, const char * host_nic, void * host_vm_data); + int (*send)(struct v3_packet * packet, uint8_t * buf, uint32_t len); + void (*close)(struct v3_packet * packet); }; extern void V3_Init_Packet(struct v3_packet_hooks * hooks); diff --git a/palacios/include/palacios/vmm_host_events.h b/palacios/include/palacios/vmm_host_events.h index 15bcb7d..47c6715 100644 --- a/palacios/include/palacios/vmm_host_events.h +++ b/palacios/include/palacios/vmm_host_events.h @@ -58,8 +58,7 @@ typedef enum { HOST_KEYBOARD_EVT, HOST_MOUSE_EVT, HOST_TIMER_EVT, HOST_CONSOLE_EVT, - HOST_SERIAL_EVT, - HOST_PACKET_EVT} v3_host_evt_type_t; + HOST_SERIAL_EVT} v3_host_evt_type_t; union v3_host_event_handler { @@ -68,7 +67,6 @@ union v3_host_event_handler { int (*timer_handler)(struct v3_vm_info * vm, struct v3_timer_event * evt, void * priv_data); int (*serial_handler)(struct v3_vm_info * vm, struct v3_serial_event * evt, void * priv_data); int (*console_handler)(struct v3_vm_info * vm, struct v3_console_event * evt, void * priv_data); - int (*packet_handler)(struct v3_vm_info * vm, struct v3_packet_event * evt, void * priv_data); }; @@ -86,7 +84,6 @@ struct v3_host_events { struct list_head timer_events; struct list_head serial_events; struct list_head console_events; - struct list_head packet_events; }; @@ -110,7 +107,6 @@ int v3_deliver_mouse_event(struct v3_vm_info * vm, struct v3_mouse_event * evt); int v3_deliver_timer_event(struct v3_vm_info * vm, struct v3_timer_event * evt); int v3_deliver_serial_event(struct v3_vm_info * vm, struct v3_serial_event * evt); int v3_deliver_console_event(struct v3_vm_info * vm, struct v3_console_event * evt); -int v3_deliver_packet_event(struct v3_vm_info * vm, struct v3_packet_event * evt); #endif diff --git a/palacios/include/palacios/vmm_msr.h b/palacios/include/palacios/vmm_msr.h index 87a8a7e..f8cbd4e 100644 --- a/palacios/include/palacios/vmm_msr.h +++ b/palacios/include/palacios/vmm_msr.h @@ -93,6 +93,9 @@ int v3_hook_msr(struct v3_vm_info * vm, uint32_t msr, void * priv_data); +int v3_msr_unhandled_read(struct guest_info * core, uint32_t msr, struct v3_msr * dst, void * priv_data); +int v3_msr_unhandled_write(struct guest_info * core, uint32_t msr, struct v3_msr src, void * priv_data); + struct v3_msr_hook * v3_get_msr_hook(struct v3_vm_info * vm, uint32_t msr); void v3_refresh_msr_map(struct v3_vm_info * vm); @@ -100,7 +103,6 @@ void v3_refresh_msr_map(struct v3_vm_info * vm); void v3_print_msr_map(struct v3_vm_info * vm); int v3_handle_msr_write(struct guest_info * info); - int v3_handle_msr_read(struct guest_info * info); diff --git a/palacios/src/devices/lnx_virtio_nic.c b/palacios/src/devices/lnx_virtio_nic.c index 8032b13..400cb0c 100644 --- a/palacios/src/devices/lnx_virtio_nic.c +++ b/palacios/src/devices/lnx_virtio_nic.c @@ -199,7 +199,7 @@ static int tx_one_pkt(struct guest_info * core, PrintDebug("Could not translate buffer address\n"); return -1; } - + V3_Net_Print(2, "Virtio-NIC: virtio_tx: size: %d\n", len); if(net_debug >= 4){ v3_hexdump(buf, len, NULL, 0); @@ -209,10 +209,10 @@ static int tx_one_pkt(struct guest_info * core, virtio->stats.tx_dropped ++; return -1; } - + virtio->stats.tx_pkts ++; virtio->stats.tx_bytes += len; - + return 0; } @@ -226,7 +226,7 @@ static inline int copy_data_to_desc(struct guest_info * core, uint_t dst_offset){ uint32_t len; uint8_t * desc_buf = NULL; - + if (v3_gpa_to_hva(core, desc->addr_gpa, (addr_t *)&(desc_buf)) == -1) { PrintDebug("Could not translate buffer address\n"); return -1; @@ -301,17 +301,19 @@ static int handle_pkt_tx(struct guest_info * core, /* here we assumed that one ethernet pkt is not splitted into multiple buffer */ struct vring_desc * buf_desc = &(q->desc[desc_idx]); if (tx_one_pkt(core, virtio_state, buf_desc) == -1) { - PrintError("Virtio NIC: Error handling nic operation\n"); - goto exit_error; + PrintError("Virtio NIC: Fails to send packet\n"); } if(buf_desc->next & VIRTIO_NEXT_FLAG){ PrintError("Virtio NIC: TX more buffer need to read\n"); } - - q->used->ring[q->used->index % q->queue_size].id = q->avail->ring[q->cur_avail_idx % q->queue_size]; - q->used->ring[q->used->index % q->queue_size].length = buf_desc->length; /* What do we set this to???? */ - q->used->index ++; + q->used->ring[q->used->index % q->queue_size].id = + q->avail->ring[q->cur_avail_idx % q->queue_size]; + + q->used->ring[q->used->index % q->queue_size].length = + buf_desc->length; /* What do we set this to???? */ + + q->used->index ++; q->cur_avail_idx ++; if(++txed >= quote && quote > 0){ @@ -319,9 +321,9 @@ static int handle_pkt_tx(struct guest_info * core, break; } } - + v3_unlock_irqrestore(virtio_state->tx_lock, flags); - + if (txed && !(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) { v3_pci_raise_irq(virtio_state->virtio_dev->pci_bus, 0, virtio_state->pci_dev); @@ -334,9 +336,9 @@ static int handle_pkt_tx(struct guest_info * core, } return left; - -exit_error: - + + exit_error: + v3_unlock_irqrestore(virtio_state->tx_lock, flags); return -1; } diff --git a/palacios/src/devices/nic_bridge.c b/palacios/src/devices/nic_bridge.c index 518fa75..1033b52 100644 --- a/palacios/src/devices/nic_bridge.c +++ b/palacios/src/devices/nic_bridge.c @@ -33,44 +33,43 @@ struct nic_bridge_state { struct v3_vm_info * vm; struct v3_dev_net_ops net_ops; + struct v3_packet * packet_state; }; static int bridge_send(uint8_t * buf, uint32_t len, - int synchronize, void * private_data) { - + struct nic_bridge_state * bridge = (struct nic_bridge_state *)private_data; + #ifdef V3_CONFIG_DEBUG_NIC_BRIDGE { PrintDebug("NIC Bridge: send pkt size: %d\n", len); v3_hexdump(buf, len, NULL, 0); } #endif - - return V3_send_raw(buf, len); + + return v3_packet_send(bridge->packet_state, buf, len); } -static int packet_input(struct v3_vm_info * vm, - struct v3_packet_event * evt, - void * private_data) { - struct nic_bridge_state * bridge = (struct nic_bridge_state *)private_data; - +static int packet_input(struct v3_packet * packet_state, uint8_t * pkt, uint32_t size) { + struct nic_bridge_state * bridge = (struct nic_bridge_state *)packet_state->guest_packet_data; + #ifdef V3_CONFIG_DEBUG_NIC_BRIDGE { - PrintDebug("NIC Bridge: recv pkt size: %d\n", evt->size); - v3_hexdump(evt->pkt, evt->size, NULL, 0); + PrintDebug("NIC Bridge: recv pkt size: %d\n", size); + v3_hexdump(pkt, size, NULL, 0); } #endif - - return bridge->net_ops.recv(evt->pkt, - evt->size, - bridge->net_ops.frontend_data); + + return bridge->net_ops.recv(pkt, + size, + bridge->net_ops.config.frontend_data); } static int nic_bridge_free(struct nic_bridge_state * bridge) { - - /*detach from front device */ - + /*TODO: detach from front device */ + + v3_packet_close(bridge->packet_state); V3_Free(bridge); return 0; @@ -78,29 +77,36 @@ static int nic_bridge_free(struct nic_bridge_state * bridge) { static struct v3_device_ops dev_ops = { .free = (int (*)(void *))nic_bridge_free, - + }; static int nic_bridge_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { struct nic_bridge_state * bridge = NULL; char * dev_id = v3_cfg_val(cfg, "ID"); - + char * host_nic; + v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend"); - + + v3_cfg_tree_t * hostnic_cfg = v3_cfg_subtree(cfg, "hostnic"); + host_nic = v3_cfg_val(hostnic_cfg, "name"); + if(host_nic == NULL) { + host_nic = "eth0"; + } + bridge = (struct nic_bridge_state *)V3_Malloc(sizeof(struct nic_bridge_state)); memset(bridge, 0, sizeof(struct nic_bridge_state)); - + struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, bridge); - + if (dev == NULL) { PrintError("Could not attach device %s\n", dev_id); V3_Free(bridge); return -1; } - + bridge->net_ops.send = bridge_send; bridge->vm = vm; - + if (v3_dev_connect_net(vm, v3_cfg_val(frontend_cfg, "tag"), &(bridge->net_ops), frontend_cfg, bridge) == -1) { PrintError("Could not connect %s to frontend %s\n", @@ -108,14 +114,20 @@ static int nic_bridge_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { v3_remove_device(dev); return -1; } - + PrintDebug("NIC-Bridge: Connect %s to frontend %s\n", - dev_id, v3_cfg_val(frontend_cfg, "tag")); - - - V3_packet_add_recver(bridge->net_ops.fnt_mac, vm); - v3_hook_host_event(vm, HOST_PACKET_EVT, V3_HOST_EVENT_HANDLER(packet_input), bridge); - + dev_id, v3_cfg_val(frontend_cfg, "tag")); + + bridge->packet_state = v3_packet_connect(vm, host_nic, + bridge->net_ops.config.fnt_mac, + packet_input, + (void *)bridge); + + if(bridge->packet_state == NULL){ + PrintError("NIC-Bridge: Error to connect to host ethernet device\n"); + return -1; + } + return 0; } diff --git a/palacios/src/interfaces/vmm_packet.c b/palacios/src/interfaces/vmm_packet.c index 10bdbda..b46325e 100644 --- a/palacios/src/interfaces/vmm_packet.c +++ b/palacios/src/interfaces/vmm_packet.c @@ -16,7 +16,6 @@ * This is free software. You are permitted to use, * redistribute, and modify it as specified in the file "V3VEE_LICENSE". */ - #include #include #include @@ -25,35 +24,49 @@ static struct v3_packet_hooks * packet_hooks = 0; -int V3_send_raw(const char * pkt, uint32_t len) { - if(packet_hooks != NULL && packet_hooks->send != NULL){ - return packet_hooks->send(pkt, len, NULL); - } +void V3_Init_Packet(struct v3_packet_hooks * hooks) { + packet_hooks = hooks; + PrintDebug("V3 raw packet interface inited\n"); - return -1; + return; } +struct v3_packet * v3_packet_connect(struct v3_vm_info * vm, + const char * host_nic, + const char * vm_mac, + int (*input)(struct v3_packet * packet, uint8_t * buf, uint32_t len), + void * guest_packet_data) { + struct v3_packet * packet = NULL; -int V3_packet_add_recver(const char * mac, struct v3_vm_info * vm){ - if(packet_hooks != NULL && packet_hooks->add_recver != NULL){ - return packet_hooks->add_recver(mac, vm); - } - - return -1; -} + V3_ASSERT(packet_hooks != NULL); + V3_ASSERT(packet_hooks->connect != NULL); + packet = V3_Malloc(sizeof(struct v3_packet)); -int V3_packet_del_recver(const char * mac, struct v3_vm_info * vm){ - if(packet_hooks != NULL && packet_hooks->del_recver != NULL){ - return packet_hooks->del_recver(mac, vm); + memcpy(packet->dev_mac, vm_mac, ETH_ALEN); + packet->input = input; + packet->guest_packet_data = guest_packet_data; + if(packet_hooks->connect(packet, host_nic, vm->host_priv_data) != 0){ + V3_Free(packet); + return NULL; } - return -1; + return packet; } -void V3_Init_Packet(struct v3_packet_hooks * hooks) { - packet_hooks = hooks; - PrintDebug("V3 raw packet interface inited\n"); +int v3_packet_send(struct v3_packet * packet, uint8_t * buf, uint32_t len) { + V3_ASSERT(packet_hooks != NULL); + V3_ASSERT(packet_hooks->send != NULL); + + return packet_hooks->send(packet, buf, len); +} - return; +void v3_packet_close(struct v3_packet * packet) { + V3_ASSERT(packet_hooks != NULL); + V3_ASSERT(packet_hooks->close != NULL); + + packet_hooks->close(packet); + V3_Free(packet); } + + diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index d583657..95d9e6c 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -314,6 +314,8 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) { { +#define INT_PENDING_AMD_MSR 0xc0010055 + v3_hook_msr(core->vm_info, IA32_STAR_MSR, NULL, NULL, NULL); v3_hook_msr(core->vm_info, IA32_LSTAR_MSR, NULL, NULL, NULL); v3_hook_msr(core->vm_info, IA32_FMASK_MSR, NULL, NULL, NULL); @@ -323,6 +325,13 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) { v3_hook_msr(core->vm_info, SYSENTER_CS_MSR, NULL, NULL, NULL); v3_hook_msr(core->vm_info, SYSENTER_ESP_MSR, NULL, NULL, NULL); v3_hook_msr(core->vm_info, SYSENTER_EIP_MSR, NULL, NULL, NULL); + + + v3_hook_msr(core->vm_info, FS_BASE_MSR, NULL, NULL, NULL); + v3_hook_msr(core->vm_info, GS_BASE_MSR, NULL, NULL, NULL); + + // Passthrough read operations are ok. + v3_hook_msr(core->vm_info, INT_PENDING_AMD_MSR, NULL, v3_msr_unhandled_write, NULL); } } @@ -669,6 +678,12 @@ int v3_start_svm_guest(struct guest_info * info) { PrintDebug("SVM core %u (on %u): Waiting for core initialization\n", info->vcpu_id, info->pcpu_id); while (info->core_run_state == CORE_STOPPED) { + + if (info->vm_info->run_state == VM_STOPPED) { + // The VM was stopped before this core was initialized. + return 0; + } + v3_yield(info); //PrintDebug("SVM core %u: still waiting for INIT\n", info->vcpu_id); } diff --git a/palacios/src/palacios/vmm_host_events.c b/palacios/src/palacios/vmm_host_events.c index 3e6d09b..28543f7 100644 --- a/palacios/src/palacios/vmm_host_events.c +++ b/palacios/src/palacios/vmm_host_events.c @@ -29,7 +29,6 @@ int v3_init_host_events(struct v3_vm_info * vm) { INIT_LIST_HEAD(&(host_evts->timer_events)); INIT_LIST_HEAD(&(host_evts->serial_events)); INIT_LIST_HEAD(&(host_evts->console_events)); - INIT_LIST_HEAD(&(host_evts->packet_events)); return 0; } @@ -67,12 +66,6 @@ int v3_deinit_host_events(struct v3_vm_info * vm) { V3_Free(hook); } - - list_for_each_entry_safe(hook, tmp, &(host_evts->packet_events), link) { - list_del(&(hook->link)); - V3_Free(hook); - } - return 0; } @@ -110,9 +103,6 @@ int v3_hook_host_event(struct v3_vm_info * vm, case HOST_CONSOLE_EVT: list_add(&(hook->link), &(host_evts->console_events)); break; - case HOST_PACKET_EVT: - list_add(&(hook->link), &(host_evts->packet_events)); - break; } return 0; @@ -228,27 +218,3 @@ int v3_deliver_console_event(struct v3_vm_info * vm, return 0; } - -int v3_deliver_packet_event(struct v3_vm_info * vm, - struct v3_packet_event * evt) { - struct v3_host_events * host_evts = NULL; - struct v3_host_event_hook * hook = NULL; - - - host_evts = &(vm->host_event_hooks); - - if (vm->run_state != VM_RUNNING) { - return -1; - } - - list_for_each_entry(hook, &(host_evts->packet_events), link) { - if (hook->cb.packet_handler(vm, evt, hook->private_data) == -1) { - return -1; - } - } - - return 0; -} - - - diff --git a/palacios/src/palacios/vmm_msr.c b/palacios/src/palacios/vmm_msr.c index 290398e..bb1b062 100644 --- a/palacios/src/palacios/vmm_msr.c +++ b/palacios/src/palacios/vmm_msr.c @@ -59,7 +59,7 @@ int v3_handle_msr_write(struct guest_info * info) { hook = v3_get_msr_hook(info->vm_info, msr_num); if (hook == NULL) { - PrintError("Write to unhooked MSR 0x%x\n", msr_num); + v3_msr_unhandled_write(info, msr_num, msr_val, NULL); } else { msr_val.lo = info->vm_regs.rax; msr_val.hi = info->vm_regs.rdx; @@ -86,7 +86,7 @@ int v3_handle_msr_read(struct guest_info * info) { hook = v3_get_msr_hook(info->vm_info, msr_num); if (hook == NULL) { - PrintError("Read from unhooked MSR 0x%x\n", msr_num); + v3_msr_unhandled_read(info, msr_num, &msr_val, NULL); } else { if (hook->read(info, msr_num, &msr_val, hook->priv_data) == -1) { PrintError("Error in MSR hook Read\n"); @@ -101,6 +101,19 @@ int v3_handle_msr_read(struct guest_info * info) { return 0; } + + +int v3_msr_unhandled_read(struct guest_info * core, uint32_t msr, struct v3_msr * dst, void * priv_data) { + V3_Print("Palacios: Unhandled MSR Read (MSR=0x%x)\n", msr); + return 0; +} + +int v3_msr_unhandled_write(struct guest_info * core, uint32_t msr, struct v3_msr src, void * priv_data) { + V3_Print("Palacios: Unhandled MSR Write (MSR=0x%x)\n", msr); + return 0; +} + + int v3_hook_msr(struct v3_vm_info * vm, uint32_t msr, int (*read)(struct guest_info * core, uint32_t msr, struct v3_msr * dst, void * priv_data), int (*write)(struct guest_info * core, uint32_t msr, struct v3_msr src, void * priv_data), @@ -134,6 +147,10 @@ int v3_hook_msr(struct v3_vm_info * vm, uint32_t msr, return 0; } + + + + static int free_hook(struct v3_vm_info * vm, struct v3_msr_hook * hook) { list_del(&(hook->link)); diff --git a/palacios/src/palacios/vmx.c b/palacios/src/palacios/vmx.c index 73b5af9..bc45c9b 100644 --- a/palacios/src/palacios/vmx.c +++ b/palacios/src/palacios/vmx.c @@ -411,6 +411,11 @@ static int init_vmcs_bios(struct guest_info * core, struct vmx_data * vmx_state) v3_hook_msr(core->vm_info, SYSENTER_CS_MSR, NULL, NULL, NULL); v3_hook_msr(core->vm_info, SYSENTER_ESP_MSR, NULL, NULL, NULL); v3_hook_msr(core->vm_info, SYSENTER_EIP_MSR, NULL, NULL, NULL); + + v3_hook_msr(core->vm_info, FS_BASE_MSR, NULL, NULL, NULL); + v3_hook_msr(core->vm_info, GS_BASE_MSR, NULL, NULL, NULL); + + } /* Sanity check ctrl/reg fields against hw_defaults */ @@ -915,6 +920,12 @@ int v3_start_vmx_guest(struct guest_info * info) { PrintDebug("VMX core %u: Waiting for core initialization\n", info->vcpu_id); while (info->core_run_state == CORE_STOPPED) { + + if (info->vm_info->run_state == VM_STOPPED) { + // The VM was stopped before this core was initialized. + return 0; + } + v3_yield(info); //PrintDebug("VMX core %u: still waiting for INIT\n",info->vcpu_id); }