#include <asm/msr.h>
#include <interfaces/vmm_packet.h>
-#include <palacios/vmm_host_events.h>
-#include <vnet/vnet.h>
-
-
-#define __V3VEE__
-#include <palacios/vmm_hashtable.h>
#include <palacios/vmm_ethernet.h>
-#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) {
}
-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; i<ETH_ALEN; i++) {
+ ret &= addr[i];
+ }
+
+ return (ret == 0xff);
+}
- oldfs = get_fs();
- set_fs(KERNEL_DS);
- size = sock_sendmsg(packet_state.raw_sock, &msg, len);
- set_fs(oldfs);
+static int packet_recv_thread( void * arg ) {
+ unsigned char * pkt;
+ int size;
+ struct v3_packet * recver_state;
+ struct raw_interface * iface = (struct raw_interface *)arg;
+ pkt = (unsigned char *)kmalloc(ETHERNET_PACKET_LEN, GFP_KERNEL);
- return size;
-}
+ printk("Palacios Raw Packet Bridge: Staring receiving on ethernet device %s\n",
+ iface->eth_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,
#include <palacios/vmm.h>
#include <palacios/vmm_ethernet.h>
+#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 <palacios/vmm.h>
-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);
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 {
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);
};
struct list_head timer_events;
struct list_head serial_events;
struct list_head console_events;
- struct list_head packet_events;
};
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
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);
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);
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);
virtio->stats.tx_dropped ++;
return -1;
}
-
+
virtio->stats.tx_pkts ++;
virtio->stats.tx_bytes += len;
-
+
return 0;
}
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;
/* 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){
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);
}
return left;
-
-exit_error:
-
+
+ exit_error:
+
v3_unlock_irqrestore(virtio_state->tx_lock, flags);
return -1;
}
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;
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",
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;
}
* 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_debug.h>
#include <palacios/vmm_types.h>
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);
}
+
+
{
+#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);
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);
}
}
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);
}
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;
}
V3_Free(hook);
}
-
- list_for_each_entry_safe(hook, tmp, &(host_evts->packet_events), link) {
- list_del(&(hook->link));
- V3_Free(hook);
- }
-
return 0;
}
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;
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;
-}
-
-
-
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;
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");
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),
return 0;
}
+
+
+
+
static int free_hook(struct v3_vm_info * vm, struct v3_msr_hook * hook) {
list_del(&(hook->link));
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 */
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);
}