From 64912900aff0c603396b3997e72c12f8488ced05 Mon Sep 17 00:00:00 2001 From: Vikram Narayanan Date: Thu, 6 Apr 2017 11:25:23 -0600 Subject: [PATCH] lcd/ixgbe: Support netdev_ops for ixgbe Enable the following function pointers: * ndo_open * ndo_stop * ndo_start_xmit * ndo_set_rx_mode * ndo_validate_addr * ndo_set_mac_address * ndo_change_mtu * ndo_tx_timeout * ndo_set_tx_maxrate * ndo_get_stats64 Add missing dev_addr_add function as well. Remove VLAN features from ixgbe (to be explored in the future) Signed-off-by: Vikram Narayanan --- lcd-domains/test_mods/ixgbe/ixgbe_cap.c | 18 +- lcd-domains/test_mods/ixgbe/ixgbe_common.h | 17 +- .../test_mods/ixgbe/ixgbe_glue_helper.c | 45 +- .../test_mods/ixgbe/ixgbe_glue_helper.h | 22 + .../ixgbe/ixgbe_lcd/glue/ixgbe_caller.c | 563 +++++- .../ixgbe_lcd/glue/ixgbe_caller_dispatch.c | 70 + .../ixgbe/ixgbe_lcd/ixgbe/ixgbe_main.c | 44 +- .../test_mods/ixgbe/ixgbe_lcd/ixgbe_caller.h | 41 + .../ixgbe/net_klcd/glue/ixgbe_callee.c | 1727 ++++++++++++++++- .../ixgbe/net_klcd/glue/ixgbe_callee.lds.S | 10 + .../net_klcd/glue/ixgbe_callee_dispatch.c | 9 +- .../test_mods/ixgbe/net_klcd/ixgbe_callee.h | 4 + 12 files changed, 2487 insertions(+), 83 deletions(-) diff --git a/lcd-domains/test_mods/ixgbe/ixgbe_cap.c b/lcd-domains/test_mods/ixgbe/ixgbe_cap.c index 00e11446edad..a7a14e305c00 100644 --- a/lcd-domains/test_mods/ixgbe/ixgbe_cap.c +++ b/lcd-domains/test_mods/ixgbe/ixgbe_cap.c @@ -26,13 +26,14 @@ enum glue_type { GLUE_TYPE_DEVICE_CONTAINER, GLUE_TYPE_MODULE_CONTAINER, GLUE_TYPE_NET_DEVICE_CONTAINER, + GLUE_TYPE_NET_DEVICE_OPS_CONTAINER, GLUE_TYPE_PCI_BUS_CONTAINER, GLUE_TYPE_PCI_DEV_CONTAINER, GLUE_TYPE_PCI_DEVICE_ID_CONTAINER, GLUE_TYPE_PCI_DRIVER_CONTAINER, + GLUE_TYPE_RTNL_LINK_STATS64_CONTAINER, GLUE_TYPE_SK_BUFF_CONTAINER, GLUE_NR_TYPES, - }; static struct type_ops_id glue_libcap_type_ops[GLUE_NR_TYPES] = { @@ -57,6 +58,13 @@ static struct type_ops_id glue_libcap_type_ops[GLUE_NR_TYPES] = { .revoke = dummy_func, } }, + { + { + .name = "struct net_device_ops", + .delete = dummy_func, + .revoke = dummy_func, + } + }, { { .name = "struct pci_bus", @@ -85,6 +93,14 @@ static struct type_ops_id glue_libcap_type_ops[GLUE_NR_TYPES] = { .revoke = dummy_func, } }, + { + { + .name = "struct rtnl linkstats", + .delete = dummy_func, + .revoke = dummy_func, + } + }, + { { .name = "struct sk_buff", diff --git a/lcd-domains/test_mods/ixgbe/ixgbe_common.h b/lcd-domains/test_mods/ixgbe/ixgbe_common.h index 808f399c6248..ad5dc77399a8 100644 --- a/lcd-domains/test_mods/ixgbe/ixgbe_common.h +++ b/lcd-domains/test_mods/ixgbe/ixgbe_common.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -17,11 +18,12 @@ #include "ixgbe_glue_helper.h" #define PCI_REGIONS + enum dispatch_t { __PCI_REGISTER_DRIVER, PCI_UNREGISTER_DRIVER, ALLOC_ETHERDEV_MQS, - REGISTER_NETDEVICE, + REGISTER_NETDEV, ETHER_SETUP, ETH_MAC_ADDR, ETH_VALIDATE_ADDR, @@ -35,6 +37,7 @@ enum dispatch_t { CONSUME_SKB, UNREGISTER_NETDEV, ETH_PLATFORM_GET_MAC_ADDRESS, + DEV_ADDR_ADD, DEV_ADDR_DEL, DEVICE_SET_WAKEUP_ENABLE, ETH_GET_HEADLEN, @@ -52,9 +55,21 @@ enum dispatch_t { PCI_REQUEST_SELECTED_REGIONS_EXCLUSIVE, PCI_SET_MASTER, PCI_SAVE_STATE, + PCI_RESTORE_STATE, PCI_RELEASE_SELECTED_REGIONS, PCI_SELECT_BARS, PCI_WAKE_FROM_D3, + NDO_OPEN, + NDO_STOP, + NDO_START_XMIT, + NDO_SELECT_QUEUE, + NDO_SET_RX_MODE, + NDO_VALIDATE_ADDR, + NDO_SET_MAC_ADDRESS, + NDO_CHANGE_MTU, + NDO_TX_TIMEOUT, + NDO_SET_TX_MAXRATE, + NDO_GET_STATS64, PROBE, REMOVE, TRIGGER_EXIT, diff --git a/lcd-domains/test_mods/ixgbe/ixgbe_glue_helper.c b/lcd-domains/test_mods/ixgbe/ixgbe_glue_helper.c index fa253b2c2a36..db3921d9e662 100644 --- a/lcd-domains/test_mods/ixgbe/ixgbe_glue_helper.c +++ b/lcd-domains/test_mods/ixgbe/ixgbe_glue_helper.c @@ -1,4 +1,3 @@ - int glue_cap_insert_device_type(struct glue_cspace *cspace, struct device_container *device_container, struct cptr *c_out) @@ -65,6 +64,28 @@ int glue_cap_lookup_net_device_type(struct glue_cspace *cspace, } +int glue_cap_insert_net_device_ops_type(struct glue_cspace *cspace, + struct net_device_ops_container *net_device_ops_container, + struct cptr *c_out) +{ + return glue_cspace_insert(cspace, + net_device_ops_container, + glue_libcap_type_ops[ GLUE_TYPE_NET_DEVICE_OPS_CONTAINER ].libcap_type, + c_out); + +} + +int glue_cap_lookup_net_device_ops_type(struct glue_cspace *cspace, + struct cptr c, + struct net_device_ops_container **net_device_ops_container) +{ + return glue_cspace_lookup(cspace, + c, + glue_libcap_type_ops[ GLUE_TYPE_NET_DEVICE_OPS_CONTAINER ].libcap_type, + ( void ** )net_device_ops_container); + +} + int glue_cap_insert_pci_bus_type(struct glue_cspace *cspace, struct pci_bus_container *pci_bus_container, struct cptr *c_out) @@ -153,6 +174,28 @@ int glue_cap_lookup_pci_driver_type(struct glue_cspace *cspace, } +int glue_cap_insert_rtnl_link_stats64_type(struct glue_cspace *cspace, + struct rtnl_link_stats64_container *rtnl_link_stats64_container, + struct cptr *c_out) +{ + return glue_cspace_insert(cspace, + rtnl_link_stats64_container, + glue_libcap_type_ops[ GLUE_TYPE_RTNL_LINK_STATS64_CONTAINER ].libcap_type, + c_out); + +} + +int glue_cap_lookup_rtnl_link_stats64_type(struct glue_cspace *cspace, + struct cptr c, + struct rtnl_link_stats64_container **rtnl_link_stats64_container) +{ + return glue_cspace_lookup(cspace, + c, + glue_libcap_type_ops[ GLUE_TYPE_RTNL_LINK_STATS64_CONTAINER ].libcap_type, + ( void ** )rtnl_link_stats64_container); + +} + int glue_cap_insert_sk_buff_type(struct glue_cspace *cspace, struct sk_buff_container *sk_buff_container, struct cptr *c_out) diff --git a/lcd-domains/test_mods/ixgbe/ixgbe_glue_helper.h b/lcd-domains/test_mods/ixgbe/ixgbe_glue_helper.h index c0c941c93bd9..d991392a8bd5 100644 --- a/lcd-domains/test_mods/ixgbe/ixgbe_glue_helper.h +++ b/lcd-domains/test_mods/ixgbe/ixgbe_glue_helper.h @@ -16,6 +16,11 @@ struct net_device_container { struct cptr other_ref; struct cptr my_ref; }; +struct net_device_ops_container { + struct net_device_ops net_device_ops; + struct cptr other_ref; + struct cptr my_ref; +}; struct pci_bus_container { struct pci_bus pci_bus; struct cptr other_ref; @@ -36,6 +41,11 @@ struct pci_driver_container { struct cptr other_ref; struct cptr my_ref; }; +struct rtnl_link_stats64_container { + struct rtnl_link_stats64 rtnl_link_stats64; + struct cptr other_ref; + struct cptr my_ref; +}; struct sk_buff_container { struct sk_buff sk_buff; struct cptr other_ref; @@ -57,6 +67,9 @@ int glue_cap_insert_module_type(struct glue_cspace *cspace, int glue_cap_insert_net_device_type(struct glue_cspace *cspace, struct net_device_container *net_device_container, struct cptr *c_out); +int glue_cap_insert_net_device_ops_type(struct glue_cspace *cspace, + struct net_device_ops_container *net_device_ops_container, + struct cptr *c_out); int glue_cap_insert_pci_bus_type(struct glue_cspace *cspace, struct pci_bus_container *pci_bus_container, struct cptr *c_out); @@ -69,6 +82,9 @@ int glue_cap_insert_pci_device_id_type(struct glue_cspace *cspace, int glue_cap_insert_pci_driver_type(struct glue_cspace *cspace, struct pci_driver_container *pci_driver_container, struct cptr *c_out); +int glue_cap_insert_rtnl_link_stats64_type(struct glue_cspace *cspace, + struct rtnl_link_stats64_container *rtnl_link_stats64_container, + struct cptr *c_out); int glue_cap_insert_sk_buff_type(struct glue_cspace *cspace, struct sk_buff_container *sk_buff_container, struct cptr *c_out); @@ -81,6 +97,9 @@ int glue_cap_lookup_module_type(struct glue_cspace *cspace, int glue_cap_lookup_net_device_type(struct glue_cspace *cspace, struct cptr c, struct net_device_container **net_device_container); +int glue_cap_lookup_net_device_ops_type(struct glue_cspace *cspace, + struct cptr c, + struct net_device_ops_container **net_device_ops_container); int glue_cap_lookup_pci_bus_type(struct glue_cspace *cspace, struct cptr c, struct pci_bus_container **pci_bus_container); @@ -93,6 +112,9 @@ int glue_cap_lookup_pci_device_id_type(struct glue_cspace *cspace, int glue_cap_lookup_pci_driver_type(struct glue_cspace *cspace, struct cptr c, struct pci_driver_container **pci_driver_container); +int glue_cap_lookup_rtnl_link_stats64_type(struct glue_cspace *cspace, + struct cptr c, + struct rtnl_link_stats64_container **rtnl_link_stats64_container); int glue_cap_lookup_sk_buff_type(struct glue_cspace *cspace, struct cptr c, struct sk_buff_container **sk_buff_container); diff --git a/lcd-domains/test_mods/ixgbe/ixgbe_lcd/glue/ixgbe_caller.c b/lcd-domains/test_mods/ixgbe/ixgbe_lcd/glue/ixgbe_caller.c index 0b9d2d3b449a..5e2384900cba 100644 --- a/lcd-domains/test_mods/ixgbe/ixgbe_lcd/glue/ixgbe_caller.c +++ b/lcd-domains/test_mods/ixgbe/ixgbe_lcd/glue/ixgbe_caller.c @@ -11,6 +11,7 @@ struct cptr sync_ep; static struct glue_cspace *c_cspace; +extern struct glue_cspace *ixgbe_cspace; extern struct thc_channel *ixgbe_async; extern cptr_t ixgbe_sync_endpoint; extern cptr_t ixgbe_register_channel; @@ -28,6 +29,7 @@ int glue_ixgbe_init(void) LIBLCD_ERR("cap create"); goto fail2; } + ixgbe_cspace = c_cspace; return 0; fail2: glue_cap_exit(); @@ -575,7 +577,7 @@ int register_netdev(struct net_device *dev) goto fail_async; } async_msg_set_fn_type(_request, - REGISTER_NETDEVICE); + REGISTER_NETDEV); fipc_set_reg0(_request, dev_container->other_ref.cptr); fipc_set_reg1(_request, @@ -598,6 +600,7 @@ int register_netdev(struct net_device *dev) goto fail_ipc; } func_ret = fipc_get_reg1(_response); + dev->reg_state = fipc_get_reg2(_response); fipc_recv_msg_end(thc_channel_to_fipc(ixgbe_async), _response); return func_ret; @@ -685,7 +688,7 @@ int eth_mac_addr(struct net_device *dev, lcd_set_r0(ilog2(( p_mem_sz ) >> ( PAGE_SHIFT ))); lcd_set_r1(p_offset); lcd_set_cr0(p_cptr); - sync_ret = lcd_sync_send(sync_ep); + sync_ret = lcd_sync_send(ixgbe_sync_endpoint); lcd_set_cr0(CAP_CPTR_NULL); if (sync_ret) { LIBLCD_ERR("failed to send"); @@ -845,9 +848,13 @@ fail_ipc: void netif_device_attach(struct net_device *dev) { + struct net_device_container *dev_container; int ret; struct fipc_message *_request; struct fipc_message *_response; + dev_container = container_of(dev, + struct net_device_container, + net_device); ret = async_msg_blocking_send_start(ixgbe_async, &_request); if (ret) { @@ -856,6 +863,8 @@ void netif_device_attach(struct net_device *dev) } async_msg_set_fn_type(_request, NETIF_DEVICE_ATTACH); + fipc_set_reg1(_request, + dev_container->other_ref.cptr); ret = thc_ipc_call(ixgbe_async, _request, &_response); @@ -869,14 +878,17 @@ void netif_device_attach(struct net_device *dev) fail_async: fail_ipc: return; - } void netif_device_detach(struct net_device *dev) { + struct net_device_container *dev_container; int ret; struct fipc_message *_request; struct fipc_message *_response; + dev_container = container_of(dev, + struct net_device_container, + net_device); ret = async_msg_blocking_send_start(ixgbe_async, &_request); if (ret) { @@ -885,6 +897,8 @@ void netif_device_detach(struct net_device *dev) } async_msg_set_fn_type(_request, NETIF_DEVICE_DETACH); + fipc_set_reg1(_request, + dev_container->other_ref.cptr); ret = thc_ipc_call(ixgbe_async, _request, &_response); @@ -898,16 +912,19 @@ void netif_device_detach(struct net_device *dev) fail_async: fail_ipc: return; - } int netif_set_real_num_rx_queues(struct net_device *dev, unsigned int rxq) { + struct net_device_container *dev_container; int ret; struct fipc_message *_request; struct fipc_message *_response; int func_ret; + dev_container = container_of(dev, + struct net_device_container, + net_device); ret = async_msg_blocking_send_start(ixgbe_async, &_request); if (ret) { @@ -917,6 +934,8 @@ int netif_set_real_num_rx_queues(struct net_device *dev, async_msg_set_fn_type(_request, NETIF_SET_REAL_NUM_RX_QUEUES); fipc_set_reg1(_request, + dev_container->other_ref.cptr); + fipc_set_reg3(_request, rxq); ret = thc_ipc_call(ixgbe_async, _request, @@ -932,16 +951,19 @@ int netif_set_real_num_rx_queues(struct net_device *dev, fail_async: fail_ipc: return ret; - } int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq) { + struct net_device_container *dev_container; int ret; struct fipc_message *_request; struct fipc_message *_response; int func_ret; + dev_container = container_of(dev, + struct net_device_container, + net_device); ret = async_msg_blocking_send_start(ixgbe_async, &_request); if (ret) { @@ -951,6 +973,8 @@ int netif_set_real_num_tx_queues(struct net_device *dev, async_msg_set_fn_type(_request, NETIF_SET_REAL_NUM_TX_QUEUES); fipc_set_reg1(_request, + dev_container->other_ref.cptr); + fipc_set_reg3(_request, txq); ret = thc_ipc_call(ixgbe_async, _request, @@ -1082,10 +1106,77 @@ fail_ipc: return ret; } +int dev_addr_add(struct net_device *dev, + const unsigned char *addr, + unsigned char addr_type) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_request; + struct fipc_message *_response; + int sync_ret; + unsigned long addr_mem_sz; + unsigned long addr_offset; + cptr_t addr_cptr; + unsigned int request_cookie; + int func_ret; + dev_container = container_of(dev, + struct net_device_container, + net_device); + ret = async_msg_blocking_send_start(ixgbe_async, + &_request); + if (ret) { + LIBLCD_ERR("failed to get a send slot"); + goto fail_async; + } + async_msg_set_fn_type(_request, + DEV_ADDR_ADD); + sync_ret = lcd_virt_to_cptr(__gva(( unsigned long )addr), + &addr_cptr, + &addr_mem_sz, + &addr_offset); + if (sync_ret) { + LIBLCD_ERR("virt to cptr failed"); + lcd_exit(-1); + } + fipc_set_reg1(_request, + dev_container->other_ref.cptr); + fipc_set_reg3(_request, + addr_type); + ret = thc_ipc_send_request(ixgbe_async, + _request, + &request_cookie); + if (ret) { + LIBLCD_ERR("thc_ipc_send_request"); + goto fail_ipc; + } + lcd_set_r0(ilog2(( addr_mem_sz ) >> ( PAGE_SHIFT ))); + lcd_set_r1(addr_offset); + lcd_set_cr0(addr_cptr); + sync_ret = lcd_sync_send(ixgbe_sync_endpoint); + lcd_set_cr0(CAP_CPTR_NULL); + if (sync_ret) { + LIBLCD_ERR("failed to send"); + lcd_exit(-1); + } + ret = thc_ipc_recv_response(ixgbe_async, + request_cookie, + &_response); + func_ret = fipc_get_reg1(_response); + fipc_recv_msg_end(thc_channel_to_fipc(ixgbe_async), + _response); + return func_ret; +fail_async: +fail_ipc: + return ret; + +} + int dev_addr_del(struct net_device *dev, const unsigned char *addr, unsigned char addr_type) { + struct net_device_container *dev_container; int ret; struct fipc_message *_request; struct fipc_message *_response; @@ -1095,6 +1186,9 @@ int dev_addr_del(struct net_device *dev, cptr_t addr_cptr; unsigned int request_cookie; int func_ret; + dev_container = container_of(dev, + struct net_device_container, + net_device); ret = async_msg_blocking_send_start(ixgbe_async, &_request); if (ret) { @@ -1112,6 +1206,8 @@ int dev_addr_del(struct net_device *dev, lcd_exit(-1); } fipc_set_reg1(_request, + dev_container->other_ref.cptr); + fipc_set_reg3(_request, addr_type); ret = thc_ipc_send_request(ixgbe_async, _request, @@ -1123,7 +1219,7 @@ int dev_addr_del(struct net_device *dev, lcd_set_r0(ilog2(( addr_mem_sz ) >> ( PAGE_SHIFT ))); lcd_set_r1(addr_offset); lcd_set_cr0(addr_cptr); - sync_ret = lcd_sync_send(sync_ep); + sync_ret = lcd_sync_send(ixgbe_sync_endpoint); lcd_set_cr0(CAP_CPTR_NULL); if (sync_ret) { LIBLCD_ERR("failed to send"); @@ -1215,7 +1311,7 @@ unsigned int eth_get_headlen(void *data, lcd_set_r0(ilog2(( data_mem_sz ) >> ( PAGE_SHIFT ))); lcd_set_r1(data_offset); lcd_set_cr0(data_cptr); - sync_ret = lcd_sync_send(sync_ep); + sync_ret = lcd_sync_send(ixgbe_sync_endpoint); lcd_set_cr0(CAP_CPTR_NULL); if (sync_ret) { LIBLCD_ERR("failed to send"); @@ -1803,5 +1899,458 @@ int pci_wake_from_d3(struct pci_dev *dev, fail_async: fail_ipc: return func_ret; +} + +int ndo_open_callee(struct fipc_message *_request, + struct thc_channel *_channel, + struct glue_cspace *cspace, + struct cptr sync_ep) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_response; + unsigned int request_cookie; + int func_ret; + request_cookie = thc_get_request_cookie(_request); + ret = glue_cap_lookup_net_device_type(cspace, + __cptr(fipc_get_reg1(_request)), + &dev_container); + if (ret) { + LIBLCD_ERR("lookup"); + goto fail_lookup; + } + fipc_recv_msg_end(thc_channel_to_fipc(_channel), + _request); + func_ret = dev_container->net_device.netdev_ops->ndo_open(( &dev_container->net_device )); + if (async_msg_blocking_send_start(_channel, + &_response)) { + LIBLCD_ERR("error getting response msg"); + return -EIO; + } + fipc_set_reg1(_response, + func_ret); + thc_ipc_reply(_channel, + request_cookie, + _response); +fail_lookup: + return ret; +} + +int ndo_stop_callee(struct fipc_message *_request, + struct thc_channel *_channel, + struct glue_cspace *cspace, + struct cptr sync_ep) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_response; + unsigned int request_cookie; + int func_ret; + request_cookie = thc_get_request_cookie(_request); + ret = glue_cap_lookup_net_device_type(cspace, + __cptr(fipc_get_reg1(_request)), + &dev_container); + if (ret) { + LIBLCD_ERR("lookup"); + goto fail_lookup; + } + fipc_recv_msg_end(thc_channel_to_fipc(_channel), + _request); + func_ret = dev_container->net_device.netdev_ops->ndo_stop(( &dev_container->net_device )); + if (async_msg_blocking_send_start(_channel, + &_response)) { + LIBLCD_ERR("error getting response msg"); + return -EIO; + } + fipc_set_reg1(_response, + func_ret); + thc_ipc_reply(_channel, + request_cookie, + _response); +fail_lookup: + return ret; } + +int ndo_start_xmit_callee(struct fipc_message *_request, + struct thc_channel *_channel, + struct glue_cspace *cspace, + struct cptr sync_ep) +{ + struct sk_buff *skb; + struct net_device_container *dev_container; + int ret; + struct fipc_message *_response; + unsigned int request_cookie; + int func_ret; + cptr_t skb_cptr, skbd_cptr; + unsigned long skb_ord, skb_off; + unsigned long skbd_ord, skbd_off; + gva_t skb_gva, skbd_gva; + unsigned int data_off; + + request_cookie = thc_get_request_cookie(_request); + ret = glue_cap_lookup_net_device_type(cspace, + __cptr(fipc_get_reg1(_request)), + &dev_container); + if (ret) { + LIBLCD_ERR("lookup"); + goto fail_lookup; + } + fipc_recv_msg_end(thc_channel_to_fipc(_channel), + _request); + ret = lcd_cptr_alloc(&skb_cptr); + if (ret) { + LIBLCD_ERR("failed to get cptr"); + goto fail_sync; + } + ret = lcd_cptr_alloc(&skbd_cptr); + if (ret) { + LIBLCD_ERR("failed to get cptr"); + goto fail_sync; + } + + lcd_set_cr0(skb_cptr); + lcd_set_cr1(skbd_cptr); + ret = lcd_sync_recv(sync_ep); + lcd_set_cr0(CAP_CPTR_NULL); + lcd_set_cr1(CAP_CPTR_NULL); + if (ret) { + LIBLCD_ERR("failed to recv"); + goto fail_sync; + } + skb_ord = lcd_r0(); + skb_off = lcd_r1(); + skbd_ord = lcd_r2(); + skbd_off = lcd_r3(); + data_off = lcd_r4(); + + ret = lcd_map_virt(skb_cptr, skb_ord, &skb_gva); + if (ret) { + LIBLCD_ERR("failed to map void *addr"); + goto fail_sync; + } + + ret = lcd_map_virt(skbd_cptr, skbd_ord, &skbd_gva); + if (ret) { + LIBLCD_ERR("failed to map void *addr"); + goto fail_sync; + } + + skb = (void*)(gva_val(skb_gva) + skb_off); + skb->head = (void*)(gva_val(skbd_gva) + skbd_off); + skb->data = skb->head + data_off; + + func_ret = dev_container->net_device.netdev_ops->ndo_start_xmit(skb, + ( &dev_container->net_device )); + if (async_msg_blocking_send_start(_channel, + &_response)) { + LIBLCD_ERR("error getting response msg"); + return -EIO; + } + fipc_set_reg1(_response, + func_ret); + thc_ipc_reply(_channel, + request_cookie, + _response); +fail_lookup: +fail_sync: + return ret; + +} + +int ndo_set_rx_mode_callee(struct fipc_message *_request, + struct thc_channel *_channel, + struct glue_cspace *cspace, + struct cptr sync_ep) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_response; + unsigned int request_cookie; + request_cookie = thc_get_request_cookie(_request); + ret = glue_cap_lookup_net_device_type(cspace, + __cptr(fipc_get_reg1(_request)), + &dev_container); + if (ret) { + LIBLCD_ERR("lookup"); + goto fail_lookup; + } + fipc_recv_msg_end(thc_channel_to_fipc(_channel), + _request); + dev_container->net_device.netdev_ops->ndo_set_rx_mode(( &dev_container->net_device )); + if (async_msg_blocking_send_start(_channel, + &_response)) { + LIBLCD_ERR("error getting response msg"); + return -EIO; + } + thc_ipc_reply(_channel, + request_cookie, + _response); +fail_lookup: + return ret; + +} + +int ndo_validate_addr_callee(struct fipc_message *_request, + struct thc_channel *_channel, + struct glue_cspace *cspace, + struct cptr sync_ep) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_response; + unsigned int request_cookie; + int func_ret; + request_cookie = thc_get_request_cookie(_request); + ret = glue_cap_lookup_net_device_type(cspace, + __cptr(fipc_get_reg1(_request)), + &dev_container); + if (ret) { + LIBLCD_ERR("lookup"); + goto fail_lookup; + } + fipc_recv_msg_end(thc_channel_to_fipc(_channel), + _request); + func_ret = dev_container->net_device.netdev_ops->ndo_validate_addr(( &dev_container->net_device)); + if (async_msg_blocking_send_start(_channel, + &_response)) { + LIBLCD_ERR("error getting response msg"); + return -EIO; + } + fipc_set_reg1(_response, + func_ret); + thc_ipc_reply(_channel, + request_cookie, + _response); +fail_lookup: + return ret; + +} + +int ndo_set_mac_address_callee(struct fipc_message *_request, + struct thc_channel *_channel, + struct glue_cspace *cspace, + struct cptr sync_ep) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_response; + unsigned int request_cookie; + int func_ret; + int sync_ret; + unsigned long mem_order; + unsigned long addr_offset; + cptr_t addr_cptr; + gva_t addr_gva; + + request_cookie = thc_get_request_cookie(_request); + ret = glue_cap_lookup_net_device_type(cspace, + __cptr(fipc_get_reg1(_request)), + &dev_container); + if (ret) { + LIBLCD_ERR("lookup"); + goto fail_lookup; + } + fipc_recv_msg_end(thc_channel_to_fipc(_channel), + _request); + sync_ret = lcd_cptr_alloc(&addr_cptr); + if (sync_ret) { + LIBLCD_ERR("failed to get cptr"); + lcd_exit(-1); + } + lcd_set_cr0(addr_cptr); + sync_ret = lcd_sync_recv(sync_ep); + lcd_set_cr0(CAP_CPTR_NULL); + if (sync_ret) { + LIBLCD_ERR("failed to recv"); + lcd_exit(-1); + } + mem_order = lcd_r0(); + addr_offset = lcd_r1(); + sync_ret = lcd_map_virt(addr_cptr, + mem_order, + &addr_gva); + if (sync_ret) { + LIBLCD_ERR("failed to map void *addr"); + lcd_exit(-1); + } + func_ret = dev_container->net_device.netdev_ops->ndo_set_mac_address(( &dev_container->net_device ), + ( void * )( ( gva_val(addr_gva) ) + ( addr_offset ) )); + if (async_msg_blocking_send_start(_channel, + &_response)) { + LIBLCD_ERR("error getting response msg"); + return -EIO; + } + fipc_set_reg1(_response, + func_ret); + thc_ipc_reply(_channel, + request_cookie, + _response); +fail_lookup: + return ret; + +} + +int ndo_change_mtu_callee(struct fipc_message *_request, + struct thc_channel *_channel, + struct glue_cspace *cspace, + struct cptr sync_ep) +{ + struct net_device_container *dev_container; + int new_mtu; + int ret; + struct fipc_message *_response; + unsigned int request_cookie; + int func_ret; + request_cookie = thc_get_request_cookie(_request); + ret = glue_cap_lookup_net_device_type(cspace, + __cptr(fipc_get_reg1(_request)), + &dev_container); + if (ret) { + LIBLCD_ERR("lookup"); + goto fail_lookup; + } + fipc_recv_msg_end(thc_channel_to_fipc(_channel), + _request); + new_mtu = fipc_get_reg3(_request); + func_ret = dev_container->net_device.netdev_ops->ndo_change_mtu(( &dev_container->net_device ), + new_mtu); + if (async_msg_blocking_send_start(_channel, + &_response)) { + LIBLCD_ERR("error getting response msg"); + return -EIO; + } + fipc_set_reg1(_response, + func_ret); + thc_ipc_reply(_channel, + request_cookie, + _response); +fail_lookup: + return ret; + +} + +int ndo_tx_timeout_callee(struct fipc_message *_request, + struct thc_channel *_channel, + struct glue_cspace *cspace, + struct cptr sync_ep) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_response; + unsigned int request_cookie; + + request_cookie = thc_get_request_cookie(_request); + ret = glue_cap_lookup_net_device_type(cspace, + __cptr(fipc_get_reg1(_request)), + &dev_container); + if (ret) { + LIBLCD_ERR("lookup"); + goto fail_lookup; + } + fipc_recv_msg_end(thc_channel_to_fipc(_channel), + _request); + dev_container->net_device.netdev_ops->ndo_tx_timeout(( &dev_container->net_device )); + + if (async_msg_blocking_send_start(_channel, + &_response)) { + LIBLCD_ERR("error getting response msg"); + return -EIO; + } + + thc_ipc_reply(_channel, + request_cookie, + _response); +fail_lookup: + return ret; + +} + +int ndo_set_tx_maxrate_callee(struct fipc_message *_request, + struct thc_channel *_channel, + struct glue_cspace *cspace, + struct cptr sync_ep) +{ + struct net_device_container *dev_container; + int queue_index; + unsigned int maxrate; + int ret; + struct fipc_message *_response; + unsigned int request_cookie; + int func_ret; + request_cookie = thc_get_request_cookie(_request); + ret = glue_cap_lookup_net_device_type(cspace, + __cptr(fipc_get_reg1(_request)), + &dev_container); + if (ret) { + LIBLCD_ERR("lookup"); + goto fail_lookup; + } + fipc_recv_msg_end(thc_channel_to_fipc(_channel), + _request); + queue_index = fipc_get_reg3(_request); + maxrate = fipc_get_reg4(_request); + func_ret = dev_container->net_device.netdev_ops->ndo_set_tx_maxrate(( &dev_container->net_device ), + queue_index, + maxrate); + if (async_msg_blocking_send_start(_channel, + &_response)) { + LIBLCD_ERR("error getting response msg"); + return -EIO; + } + fipc_set_reg1(_response, + func_ret); + thc_ipc_reply(_channel, + request_cookie, + _response); +fail_lookup: + return ret; + +} + +int ndo_get_stats64_callee(struct fipc_message *_request, + struct thc_channel *_channel, + struct glue_cspace *cspace, + struct cptr sync_ep) +{ + struct net_device_container *dev_container; + struct rtnl_link_stats64 stats; + int ret; + struct fipc_message *_response; + unsigned int request_cookie; + + request_cookie = thc_get_request_cookie(_request); + ret = glue_cap_lookup_net_device_type(c_cspace, + __cptr(fipc_get_reg1(_request)), + &dev_container); + if (ret) { + LIBLCD_ERR("lookup"); + goto fail_lookup; + } + fipc_recv_msg_end(thc_channel_to_fipc(_channel), + _request); + + dev_container->net_device.netdev_ops->ndo_get_stats64(( &dev_container->net_device ), + &stats); + + if (async_msg_blocking_send_start(_channel, + &_response)) { + LIBLCD_ERR("error getting response msg"); + return -EIO; + } + fipc_set_reg1(_response, + stats.rx_packets); + fipc_set_reg2(_response, + stats.rx_bytes); + fipc_set_reg3(_response, + stats.tx_packets); + fipc_set_reg4(_response, + stats.tx_bytes); + thc_ipc_reply(_channel, + request_cookie, + _response); +fail_lookup: + return ret; +} + diff --git a/lcd-domains/test_mods/ixgbe/ixgbe_lcd/glue/ixgbe_caller_dispatch.c b/lcd-domains/test_mods/ixgbe/ixgbe_lcd/glue/ixgbe_caller_dispatch.c index 96dd0b216f09..cdd813399340 100644 --- a/lcd-domains/test_mods/ixgbe/ixgbe_lcd/glue/ixgbe_caller_dispatch.c +++ b/lcd-domains/test_mods/ixgbe/ixgbe_lcd/glue/ixgbe_caller_dispatch.c @@ -15,6 +15,76 @@ int dispatch_async_loop(struct thc_channel *_channel, int fn_type; fn_type = async_msg_get_fn_type(message); switch (fn_type) { + case NDO_OPEN: + trace(NDO_OPEN); + return ndo_open_callee(message, + _channel, + cspace, + sync_ep); + + case NDO_STOP: + trace(NDO_STOP); + return ndo_stop_callee(message, + _channel, + cspace, + sync_ep); + + case NDO_START_XMIT: + trace(NDO_START_XMIT); + return ndo_start_xmit_callee(message, + _channel, + cspace, + sync_ep); + + case NDO_SET_RX_MODE: + trace(NDO_SET_RX_MODE); + return ndo_set_rx_mode_callee(message, + _channel, + cspace, + sync_ep); + + case NDO_VALIDATE_ADDR: + trace(NDO_VALIDATE_ADDR); + return ndo_validate_addr_callee(message, + _channel, + cspace, + sync_ep); + + case NDO_SET_MAC_ADDRESS: + trace(NDO_SET_MAC_ADDRESS); + return ndo_set_mac_address_callee(message, + _channel, + cspace, + sync_ep); + + case NDO_CHANGE_MTU: + trace(NDO_CHANGE_MTU); + return ndo_change_mtu_callee(message, + _channel, + cspace, + sync_ep); + + case NDO_TX_TIMEOUT: + trace(NDO_TX_TIMEOUT); + return ndo_tx_timeout_callee(message, + _channel, + cspace, + sync_ep); + + case NDO_SET_TX_MAXRATE: + trace(NDO_SET_TX_MAXRATE); + return ndo_set_tx_maxrate_callee(message, + _channel, + cspace, + sync_ep); + + case NDO_GET_STATS64: + trace(NDO_GET_STATS64); + return ndo_get_stats64_callee(message, + _channel, + cspace, + sync_ep); + case PROBE: trace(PROBE); return probe_callee(message, diff --git a/lcd-domains/test_mods/ixgbe/ixgbe_lcd/ixgbe/ixgbe_main.c b/lcd-domains/test_mods/ixgbe/ixgbe_lcd/ixgbe/ixgbe_main.c index 1feaa3daebeb..e8272ed7fd63 100644 --- a/lcd-domains/test_mods/ixgbe/ixgbe_lcd/ixgbe/ixgbe_main.c +++ b/lcd-domains/test_mods/ixgbe/ixgbe_lcd/ixgbe/ixgbe_main.c @@ -4675,7 +4675,12 @@ static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter) for (q_idx = 0; q_idx < adapter->num_q_vectors; q_idx++) { ixgbe_qv_init_lock(adapter->q_vector[q_idx]); +#ifndef LCD_ISOLATE + /* FIXME: enabling this causes undefined instruction + * to be generated by the compiler. Disable it for now + */ napi_enable(&adapter->q_vector[q_idx]->napi); +#endif } } @@ -5515,8 +5520,12 @@ static void ixgbe_clean_tx_ring(struct ixgbe_ring *tx_ring) ixgbe_unmap_and_free_tx_resource(tx_ring, tx_buffer_info); } +#ifndef LCD_ISOLATE + /* FIXME: enabling this causes EPT violation + * this function calls clear_bit + */ netdev_tx_reset_queue(txring_txq(tx_ring)); - +#endif size = sizeof(struct ixgbe_tx_buffer) * tx_ring->count; memset(tx_ring->tx_buffer_info, 0, size); @@ -5594,7 +5603,19 @@ void ixgbe_down(struct ixgbe_adapter *adapter) /* call carrier off first to avoid false dev_watchdog timeouts */ netif_carrier_off(netdev); +#ifndef LCD_ISOLATE netif_tx_disable(netdev); +#else + /* netif_tx_disable does local_bh_disable/enable which translates + * to percpu macros that cause ept violation. So, pull out the + * below loop from that function and have it here in case of LCDs + */ + for (i = 0; i < netdev->num_tx_queues; i++) { + struct netdev_queue *txq = netdev_get_tx_queue(netdev, i); + + netif_tx_stop_queue(txq); + } +#endif /* disable any upper devices */ netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) { @@ -8161,7 +8182,6 @@ static int ixgbe_ioctl(struct net_device *netdev, struct ifreq *req, int cmd) } } -#ifndef LCD_ISOLATE /** * ixgbe_add_sanmac_netdev - Add the SAN MAC address to the corresponding * netdev->dev_addrs @@ -8206,7 +8226,6 @@ static int ixgbe_del_sanmac_netdev(struct net_device *dev) } return err; } -#endif /* LCD_ISOLATE */ #ifdef CONFIG_NET_POLL_CONTROLLER /* @@ -9694,9 +9713,11 @@ skip_sriov: /* copy netdev features into list of user selectable features */ netdev->hw_features |= netdev->features | +#ifndef LCD_ISOLATE NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX | +#endif NETIF_F_RXALL | NETIF_F_HW_L2FW_DOFFLOAD; @@ -9707,6 +9728,7 @@ skip_sriov: if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; +#ifndef LCD_ISOLATE netdev->vlan_features |= netdev->features | NETIF_F_TSO_MANGLEID; netdev->hw_enc_features |= netdev->vlan_features; netdev->mpls_features |= NETIF_F_HW_CSUM; @@ -9715,7 +9737,7 @@ skip_sriov: netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX; - +#endif netdev->priv_flags |= IFF_UNICAST_FLT; netdev->priv_flags |= IFF_SUPP_NOFCS; @@ -9793,11 +9815,13 @@ skip_sriov: INIT_WORK(&adapter->service_task, ixgbe_service_task); set_bit(__IXGBE_SERVICE_INITED, &adapter->state); clear_bit(__IXGBE_SERVICE_SCHED, &adapter->state); +#endif err = ixgbe_init_interrupt_scheme(adapter); if (err) goto err_sw_init; +#ifndef LCD_ISOLATE /* WOL not supported for all devices */ adapter->wol = 0; hw->eeprom.ops.read(hw, 0x2c, &adapter->eeprom_cap); @@ -9864,11 +9888,10 @@ skip_sriov: } strcpy(netdev->name, "eth%d"); -#ifndef LCD_ISOLATE err = register_netdev(netdev); if (err) goto err_register; -#endif + pci_set_drvdata(pdev, adapter); /* power down the optics for 82599 SFP+ fiber */ @@ -9900,9 +9923,7 @@ skip_sriov: 0xFF); /* add san mac addr to netdev */ -#ifndef LCD_ISOLATE ixgbe_add_sanmac_netdev(netdev); -#endif LIBLCD_MSG("%s\n", ixgbe_default_device_descr); @@ -9921,9 +9942,8 @@ skip_sriov: true); return 0; -#ifndef LCD_ISOLATE + err_register: -#endif ixgbe_release_hw_control(adapter); ixgbe_clear_interrupt_scheme(adapter); err_sw_init: @@ -9977,9 +9997,7 @@ static void ixgbe_remove(struct pci_dev *pdev) ixgbe_dbg_adapter_exit(adapter); #endif set_bit(__IXGBE_REMOVING, &adapter->state); -#ifdef LCD_ISOLATE cancel_work_sync(&adapter->service_task); -#endif #ifdef CONFIG_IXGBE_DCA if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) { @@ -9994,10 +10012,8 @@ static void ixgbe_remove(struct pci_dev *pdev) ixgbe_sysfs_exit(adapter); #endif /* CONFIG_IXGBE_HWMON */ -#ifndef LCD_ISOLATE /* remove the added san mac */ ixgbe_del_sanmac_netdev(netdev); -#endif #ifdef CONFIG_PCI_IOV ixgbe_disable_sriov(adapter); diff --git a/lcd-domains/test_mods/ixgbe/ixgbe_lcd/ixgbe_caller.h b/lcd-domains/test_mods/ixgbe/ixgbe_lcd/ixgbe_caller.h index f9b8ab73c854..6528c5620aca 100644 --- a/lcd-domains/test_mods/ixgbe/ixgbe_lcd/ixgbe_caller.h +++ b/lcd-domains/test_mods/ixgbe/ixgbe_lcd/ixgbe_caller.h @@ -10,6 +10,47 @@ int dispatch_async_loop(struct thc_channel *_channel, struct cptr sync_ep); int glue_ixgbe_init(void); void glue_ixgbe_exit(void); +int ndo_open_callee(struct fipc_message *_request, + struct thc_channel *_channel, + struct glue_cspace *cspace, + struct cptr sync_ep); +int ndo_stop_callee(struct fipc_message *_request, + struct thc_channel *_channel, + struct glue_cspace *cspace, + struct cptr sync_ep); +int ndo_start_xmit_callee(struct fipc_message *_request, + struct thc_channel *_channel, + struct glue_cspace *cspace, + struct cptr sync_ep); +int ndo_set_rx_mode_callee(struct fipc_message *_request, + struct thc_channel *_channel, + struct glue_cspace *cspace, + struct cptr sync_ep); +int ndo_validate_addr_callee(struct fipc_message *_request, + struct thc_channel *_channel, + struct glue_cspace *cspace, + struct cptr sync_ep); +int ndo_set_mac_address_callee(struct fipc_message *_request, + struct thc_channel *_channel, + struct glue_cspace *cspace, + struct cptr sync_ep); +int ndo_change_mtu_callee(struct fipc_message *_request, + struct thc_channel *_channel, + struct glue_cspace *cspace, + struct cptr sync_ep); +int ndo_tx_timeout_callee(struct fipc_message *_request, + struct thc_channel *_channel, + struct glue_cspace *cspace, + struct cptr sync_ep); +int ndo_set_tx_maxrate_callee(struct fipc_message *_request, + struct thc_channel *_channel, + struct glue_cspace *cspace, + struct cptr sync_ep); +int ndo_get_stats64_callee(struct fipc_message *_request, + struct thc_channel *_channel, + struct glue_cspace *cspace, + struct cptr sync_ep); + int probe_callee(struct fipc_message *_request, struct thc_channel *_channel, struct glue_cspace *cspace, diff --git a/lcd-domains/test_mods/ixgbe/net_klcd/glue/ixgbe_callee.c b/lcd-domains/test_mods/ixgbe/net_klcd/glue/ixgbe_callee.c index ccbee27056b3..40f776cdb7fe 100644 --- a/lcd-domains/test_mods/ixgbe/net_klcd/glue/ixgbe_callee.c +++ b/lcd-domains/test_mods/ixgbe/net_klcd/glue/ixgbe_callee.c @@ -183,6 +183,51 @@ fail1: return ret; } +int sync_setup_memory(void *data, size_t sz, unsigned long *order, cptr_t *data_cptr, unsigned long *data_offset) +{ + int ret; + struct page *p; + unsigned long data_len; + unsigned long mem_len; + /* + * Determine page that contains (start of) data + */ + p = virt_to_head_page(data); + if (!p) { + LIBLCD_ERR("failed to translate to page"); + ret = -EINVAL; + goto fail1; + } + data_len = sz; + mem_len = ALIGN(data + data_len - page_address(p), PAGE_SIZE); + *order = ilog2(roundup_pow_of_two(mem_len >> PAGE_SHIFT)); + /* + * Volunteer memory + */ + *data_offset = data - page_address(p); + ret = lcd_volunteer_pages(p, *order, data_cptr); + if (ret) { + LIBLCD_ERR("failed to volunteer memory"); + goto fail2; + } + /* + * Done + */ + return 0; +fail2: +fail1: + return ret; +} + +int grant_sync_ep(cptr_t *sync_end, cptr_t ha_sync_ep) +{ + int ret; + struct cspace *curr_cspace = get_current_cspace(current); + lcd_cptr_alloc(sync_end); + ret = cap_grant(klcd_cspace, ha_sync_ep, curr_cspace, *sync_end); + return ret; +} + LCD_TRAMPOLINE_DATA(probe_trampoline); int LCD_TRAMPOLINE_LINKAGE(probe_trampoline) probe_trampoline(struct pci_dev *dev, @@ -642,7 +687,1186 @@ void remove_user(struct pci_dev *dev, ret = thc_ipc_call(hidden_args->async_chnl, _request, &_response); - }, remove_user + }, remove_user + ); + } + ); + if (ret) { + LIBLCD_ERR("thc_ipc_call"); + goto fail_ipc; + } + fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl), + _response); + lcd_exit(0); + return; +fail_async: +fail_ipc: + return; +} + +void remove(struct pci_dev *dev, + struct trampoline_hidden_args *hidden_args) +{ + int ret; + struct fipc_message *_request; + struct fipc_message *_response; + if (!current->ptstate) { + LIBLCD_MSG("Calling from a non-LCD context! creating thc runtime!"); + LCD_MAIN({ + remove_user(dev, + hidden_args); + } + ); + return; + } + + ret = async_msg_blocking_send_start(hidden_args->async_chnl, + &_request); + if (ret) { + LIBLCD_ERR("failed to get a send slot"); + goto fail_async; + } + async_msg_set_fn_type(_request, + REMOVE); + + ret = thc_ipc_call(hidden_args->async_chnl, + _request, + &_response); + if (ret) { + LIBLCD_ERR("thc_ipc_call"); + goto fail_ipc; + } + fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl), + _response); + return; +fail_async: +fail_ipc: + return; +} + +int ndo_open_user(struct net_device *dev, + struct trampoline_hidden_args *hidden_args) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_request; + struct fipc_message *_response; + int func_ret; + dev_container = container_of(dev, + struct net_device_container, + net_device); + thc_init(); + ret = async_msg_blocking_send_start(hidden_args->async_chnl, + &_request); + if (ret) { + LIBLCD_ERR("failed to get a send slot"); + goto fail_async; + } + async_msg_set_fn_type(_request, + NDO_OPEN); + fipc_set_reg1(_request, + dev_container->other_ref.cptr); + DO_FINISH({ + ASYNC({ + ret = thc_ipc_call(hidden_args->async_chnl, + _request, + &_response); + } + ); + } + ); + if (ret) { + LIBLCD_ERR("thc_ipc_call"); + goto fail_ipc; + } + func_ret = fipc_get_reg1(_response); + fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl), + _response); + lcd_exit(0); + return func_ret; +fail_async: +fail_ipc: + return ret; +} + +int ndo_open(struct net_device *dev, + struct trampoline_hidden_args *hidden_args) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_request; + struct fipc_message *_response; + int func_ret; + if (!current->ptstate) { + LIBLCD_MSG("Calling from a non-LCD context! creating thc runtime!"); + LCD_MAIN({ + ret = ndo_open_user(dev, + hidden_args); + } + ); + return ret; + } + dev_container = container_of(dev, + struct net_device_container, + net_device); + ret = async_msg_blocking_send_start(hidden_args->async_chnl, + &_request); + if (ret) { + LIBLCD_ERR("failed to get a send slot"); + goto fail_async; + } + async_msg_set_fn_type(_request, + NDO_OPEN); + fipc_set_reg1(_request, + dev_container->other_ref.cptr); + ret = thc_ipc_call(hidden_args->async_chnl, + _request, + &_response); + if (ret) { + LIBLCD_ERR("thc_ipc_call"); + goto fail_ipc; + } + func_ret = fipc_get_reg1(_response); + fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl), + _response); + return func_ret; +fail_async: +fail_ipc: + return ret; + +} + +LCD_TRAMPOLINE_DATA(ndo_open_trampoline); +int LCD_TRAMPOLINE_LINKAGE(ndo_open_trampoline) +ndo_open_trampoline(struct net_device *dev) +{ + int ( *volatile ndo_open_fp )(struct net_device *, + struct trampoline_hidden_args *); + struct trampoline_hidden_args *hidden_args; + LCD_TRAMPOLINE_PROLOGUE(hidden_args, + ndo_open_trampoline); + ndo_open_fp = ndo_open; + return ndo_open_fp(dev, + hidden_args); + +} + +int ndo_stop_user(struct net_device *dev, + struct trampoline_hidden_args *hidden_args) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_request; + struct fipc_message *_response; + int func_ret; + dev_container = container_of(dev, + struct net_device_container, + net_device); + thc_init(); + ret = async_msg_blocking_send_start(hidden_args->async_chnl, + &_request); + if (ret) { + LIBLCD_ERR("failed to get a send slot"); + goto fail_async; + } + async_msg_set_fn_type(_request, + NDO_STOP); + fipc_set_reg1(_request, + dev_container->other_ref.cptr); + DO_FINISH({ + ASYNC_({ + ret = thc_ipc_call(hidden_args->async_chnl, + _request, + &_response); + }, ndo_stop + ); + } + ); + if (ret) { + LIBLCD_ERR("thc_ipc_call"); + goto fail_ipc; + } + func_ret = fipc_get_reg1(_response); + fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl), + _response); + lcd_exit(0); + return func_ret; +fail_async: +fail_ipc: + return ret; + +} + +int ndo_stop(struct net_device *dev, + struct trampoline_hidden_args *hidden_args) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_request; + struct fipc_message *_response; + int func_ret; + if (!current->ptstate) { + LIBLCD_MSG("Calling from a non-LCD context! creating thc runtime!"); + LCD_MAIN({ + ret = ndo_stop_user(dev, + hidden_args); + } + ); + return ret; + } + dev_container = container_of(dev, + struct net_device_container, + net_device); + ret = async_msg_blocking_send_start(hidden_args->async_chnl, + &_request); + if (ret) { + LIBLCD_ERR("failed to get a send slot"); + goto fail_async; + } + async_msg_set_fn_type(_request, + NDO_STOP); + fipc_set_reg1(_request, + dev_container->other_ref.cptr); + ret = thc_ipc_call(hidden_args->async_chnl, + _request, + &_response); + if (ret) { + LIBLCD_ERR("thc_ipc_call"); + goto fail_ipc; + } + func_ret = fipc_get_reg1(_response); + fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl), + _response); + return func_ret; +fail_async: +fail_ipc: + return ret; + +} + +LCD_TRAMPOLINE_DATA(ndo_stop_trampoline); +int LCD_TRAMPOLINE_LINKAGE(ndo_stop_trampoline) +ndo_stop_trampoline(struct net_device *dev) +{ + int ( *volatile ndo_stop_fp )(struct net_device *, + struct trampoline_hidden_args *); + struct trampoline_hidden_args *hidden_args; + LCD_TRAMPOLINE_PROLOGUE(hidden_args, + ndo_stop_trampoline); + ndo_stop_fp = ndo_stop; + return ndo_stop_fp(dev, + hidden_args); + +} + +int ndo_start_xmit_user(struct sk_buff *skb, + struct net_device *dev, + struct trampoline_hidden_args *hidden_args) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_request; + struct fipc_message *_response; + int func_ret; + unsigned int request_cookie; + + cptr_t sync_end; + unsigned long skb_ord, skb_off; + unsigned long skbd_ord, skbd_off; + cptr_t skb_cptr, skbd_cptr; + + dev_container = container_of(dev, + struct net_device_container, + net_device); + + thc_init(); + ret = grant_sync_ep(&sync_end, hidden_args->sync_ep); + + ret = sync_setup_memory(skb, sizeof(struct sk_buff), &skb_ord, &skb_cptr, &skb_off); + + ret = sync_setup_memory(skb->head, skb_end_offset(skb) + sizeof(struct skb_shared_info), &skbd_ord, &skbd_cptr, &skbd_off); + + ret = async_msg_blocking_send_start(hidden_args->async_chnl, + &_request); + if (ret) { + LIBLCD_ERR("failed to get a send slot"); + goto fail_async; + } + async_msg_set_fn_type(_request, + NDO_START_XMIT); + + fipc_set_reg1(_request, + dev_container->other_ref.cptr); + + ret = thc_ipc_send_request(hidden_args->async_chnl, _request, &request_cookie); + + if (ret) { + LIBLCD_ERR("thc_ipc_call"); + goto fail_ipc; + } + + //sync half + lcd_set_cr0(skb_cptr); + lcd_set_cr1(skbd_cptr); + lcd_set_r0(skb_ord); + lcd_set_r1(skb_off); + lcd_set_r2(skbd_ord); + lcd_set_r3(skbd_off); + lcd_set_r4(skb->data - skb->head); + + LIBLCD_MSG("r4 data_off 0x%X | %d", skb->data - skb->head); + ret = lcd_sync_send(sync_end); + lcd_set_cr0(CAP_CPTR_NULL); + lcd_set_cr1(CAP_CPTR_NULL); + if (ret) { + LIBLCD_ERR("failed to send"); + goto fail_sync; + } + + lcd_cap_delete(sync_end); + + DO_FINISH({ + ASYNC_({ + ret = thc_ipc_recv_response(hidden_args->async_chnl, request_cookie, &_response); + }, ndo_xmit + ); + } + ); + if (ret) { + LIBLCD_ERR("thc_ipc_call"); + goto fail_ipc; + } + func_ret = fipc_get_reg1(_response); + fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl), + _response); + +fail_sync: +fail_async: +fail_ipc: + lcd_exit(0); + return ret; + +} + +int ndo_start_xmit(struct sk_buff *skb, + struct net_device *dev, + struct trampoline_hidden_args *hidden_args) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_request; + struct fipc_message *_response; + int func_ret; + if (!current->ptstate) { + LIBLCD_MSG("Calling from a non-LCD context! creating thc runtime!"); + LCD_MAIN({ + ret = ndo_start_xmit_user(skb, + dev, + hidden_args); + } + ); + return ret; + } + dev_container = container_of(dev, + struct net_device_container, + net_device); + ret = async_msg_blocking_send_start(hidden_args->async_chnl, + &_request); + if (ret) { + LIBLCD_ERR("failed to get a send slot"); + goto fail_async; + } + async_msg_set_fn_type(_request, + NDO_START_XMIT); + fipc_set_reg1(_request, + dev_container->other_ref.cptr); + ret = thc_ipc_call(hidden_args->async_chnl, + _request, + &_response); + if (ret) { + LIBLCD_ERR("thc_ipc_call"); + goto fail_ipc; + } + func_ret = fipc_get_reg1(_response); + fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl), + _response); + return func_ret; +fail_async: +fail_ipc: + return ret; + +} + +LCD_TRAMPOLINE_DATA(ndo_start_xmit_trampoline); +int LCD_TRAMPOLINE_LINKAGE(ndo_start_xmit_trampoline) +ndo_start_xmit_trampoline(struct sk_buff *skb, + struct net_device *dev) +{ + int ( *volatile ndo_start_xmit_fp )(struct sk_buff *, + struct net_device *, + struct trampoline_hidden_args *); + struct trampoline_hidden_args *hidden_args; + LCD_TRAMPOLINE_PROLOGUE(hidden_args, + ndo_start_xmit_trampoline); + ndo_start_xmit_fp = ndo_start_xmit; + return ndo_start_xmit_fp(skb, + dev, + hidden_args); + +} + +void ndo_set_rx_mode_user(struct net_device *dev, + struct trampoline_hidden_args *hidden_args) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_request; + struct fipc_message *_response; + dev_container = container_of(dev, + struct net_device_container, + net_device); + thc_init(); + ret = async_msg_blocking_send_start(hidden_args->async_chnl, + &_request); + if (ret) { + LIBLCD_ERR("failed to get a send slot"); + goto fail_async; + } + async_msg_set_fn_type(_request, + NDO_SET_RX_MODE); + fipc_set_reg1(_request, + dev_container->other_ref.cptr); + DO_FINISH({ + ASYNC_({ + ret = thc_ipc_call(hidden_args->async_chnl, + _request, + &_response); + }, ndo_set_rx_mode + ); + } + ); + if (ret) { + LIBLCD_ERR("thc_ipc_call"); + goto fail_ipc; + } + fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl), + _response); + lcd_exit(0); + return; +fail_async: +fail_ipc: + return; + +} + +void ndo_set_rx_mode(struct net_device *dev, + struct trampoline_hidden_args *hidden_args) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_request; + struct fipc_message *_response; + if (!current->ptstate) { + LIBLCD_MSG("Calling from a non-LCD context! creating thc runtime!"); + LCD_MAIN({ + ndo_set_rx_mode_user(dev, + hidden_args); + } + ); + return; + } + dev_container = container_of(dev, + struct net_device_container, + net_device); + ret = async_msg_blocking_send_start(hidden_args->async_chnl, + &_request); + if (ret) { + LIBLCD_ERR("failed to get a send slot"); + goto fail_async; + } + async_msg_set_fn_type(_request, + NDO_SET_RX_MODE); + fipc_set_reg1(_request, + dev_container->other_ref.cptr); + ret = thc_ipc_call(hidden_args->async_chnl, + _request, + &_response); + if (ret) { + LIBLCD_ERR("thc_ipc_call"); + goto fail_ipc; + } + fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl), + _response); + return; +fail_async: +fail_ipc: + return; + +} + +LCD_TRAMPOLINE_DATA(ndo_set_rx_mode_trampoline); +void LCD_TRAMPOLINE_LINKAGE(ndo_set_rx_mode_trampoline) +ndo_set_rx_mode_trampoline(struct net_device *dev) +{ + void ( *volatile ndo_set_rx_mode_fp )(struct net_device *, + struct trampoline_hidden_args *); + struct trampoline_hidden_args *hidden_args; + LCD_TRAMPOLINE_PROLOGUE(hidden_args, + ndo_set_rx_mode_trampoline); + ndo_set_rx_mode_fp = ndo_set_rx_mode; + return ndo_set_rx_mode_fp(dev, + hidden_args); + +} + +int ndo_validate_addr_user(struct net_device *dev, + struct trampoline_hidden_args *hidden_args) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_request; + struct fipc_message *_response; + int func_ret; + dev_container = container_of(dev, + struct net_device_container, + net_device); + thc_init(); + ret = async_msg_blocking_send_start(hidden_args->async_chnl, + &_request); + if (ret) { + LIBLCD_ERR("failed to get a send slot"); + goto fail_async; + } + async_msg_set_fn_type(_request, + NDO_VALIDATE_ADDR); + fipc_set_reg1(_request, + dev_container->other_ref.cptr); + DO_FINISH({ + ASYNC_({ + ret = thc_ipc_call(hidden_args->async_chnl, + _request, + &_response); + }, ndo_validate_addr + ); + } + ); + if (ret) { + LIBLCD_ERR("thc_ipc_call"); + goto fail_ipc; + } + func_ret = fipc_get_reg1(_response); + fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl), + _response); + lcd_exit(0); + return func_ret; +fail_async: +fail_ipc: + return ret; +} + +int ndo_validate_addr(struct net_device *dev, + struct trampoline_hidden_args *hidden_args) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_request; + struct fipc_message *_response; + int func_ret; + if (!current->ptstate) { + LIBLCD_MSG("Calling from a non-LCD context! creating thc runtime!"); + LCD_MAIN({ + ret = ndo_validate_addr_user(dev, + hidden_args); + } + ); + return ret; + } + dev_container = container_of(dev, + struct net_device_container, + net_device); + ret = async_msg_blocking_send_start(hidden_args->async_chnl, + &_request); + if (ret) { + LIBLCD_ERR("failed to get a send slot"); + goto fail_async; + } + async_msg_set_fn_type(_request, + NDO_VALIDATE_ADDR); + fipc_set_reg1(_request, + dev_container->other_ref.cptr); + ret = thc_ipc_call(hidden_args->async_chnl, + _request, + &_response); + if (ret) { + LIBLCD_ERR("thc_ipc_call"); + goto fail_ipc; + } + func_ret = fipc_get_reg1(_response); + fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl), + _response); + return func_ret; +fail_async: +fail_ipc: + return ret; + +} + +LCD_TRAMPOLINE_DATA(ndo_validate_addr_trampoline); +int LCD_TRAMPOLINE_LINKAGE(ndo_validate_addr_trampoline) +ndo_validate_addr_trampoline(struct net_device *dev) +{ + int ( *volatile ndo_validate_addr_fp )(struct net_device *, + struct trampoline_hidden_args *); + struct trampoline_hidden_args *hidden_args; + LCD_TRAMPOLINE_PROLOGUE(hidden_args, + ndo_validate_addr_trampoline); + ndo_validate_addr_fp = ndo_validate_addr; + return ndo_validate_addr_fp(dev, + hidden_args); + +} + +int ndo_set_mac_address_user(struct net_device *dev, + void *addr, + struct trampoline_hidden_args *hidden_args) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_request; + struct fipc_message *_response; + int sync_ret; + unsigned long addr_mem_sz; + unsigned long addr_offset; + cptr_t addr_cptr; + unsigned int request_cookie; + int func_ret; + dev_container = container_of(dev, + struct net_device_container, + net_device); + thc_init(); + ret = async_msg_blocking_send_start(hidden_args->async_chnl, + &_request); + if (ret) { + LIBLCD_ERR("failed to get a send slot"); + goto fail_async; + } + async_msg_set_fn_type(_request, + NDO_SET_MAC_ADDRESS); + fipc_set_reg1(_request, + dev_container->other_ref.cptr); + sync_ret = lcd_virt_to_cptr(__gva(( unsigned long )addr), + &addr_cptr, + &addr_mem_sz, + &addr_offset); + if (sync_ret) { + LIBLCD_ERR("virt to cptr failed"); + lcd_exit(-1); + } + ret = thc_ipc_send_request(hidden_args->async_chnl, + _request, + &request_cookie); + + if (ret) { + LIBLCD_ERR("thc_ipc_send_request"); + goto fail_ipc; + } + lcd_set_r0(ilog2(( addr_mem_sz ) >> ( PAGE_SHIFT ))); + lcd_set_r1(addr_offset); + lcd_set_cr0(addr_cptr); + sync_ret = lcd_sync_send(sync_ep); + lcd_set_cr0(CAP_CPTR_NULL); + if (sync_ret) { + LIBLCD_ERR("failed to send"); + lcd_exit(-1); + } + DO_FINISH({ + ASYNC_({ + ret = thc_ipc_recv_response(hidden_args->async_chnl, + request_cookie, + &_response); + }, ndo_set_mac_addr + ); + }); + func_ret = fipc_get_reg1(_response); + fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl), + _response); + lcd_exit(0); + return func_ret; +fail_async: +fail_ipc: + return ret; + +} + +int ndo_set_mac_address(struct net_device *dev, + void *addr, + struct trampoline_hidden_args *hidden_args) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_request; + struct fipc_message *_response; + int sync_ret; + unsigned long addr_mem_sz; + unsigned long addr_offset; + cptr_t addr_cptr; + unsigned int request_cookie; + int func_ret; + if (!current->ptstate) { + LIBLCD_MSG("Calling from a non-LCD context! creating thc runtime!"); + LCD_MAIN({ + ret = ndo_set_mac_address_user(dev, + addr, + hidden_args); + } + ); + return ret; + } + dev_container = container_of(dev, + struct net_device_container, + net_device); + ret = async_msg_blocking_send_start(hidden_args->async_chnl, + &_request); + if (ret) { + LIBLCD_ERR("failed to get a send slot"); + goto fail_async; + } + async_msg_set_fn_type(_request, + NDO_SET_MAC_ADDRESS); + fipc_set_reg1(_request, + dev_container->other_ref.cptr); + sync_ret = lcd_virt_to_cptr(__gva(( unsigned long )addr), + &addr_cptr, + &addr_mem_sz, + &addr_offset); + if (sync_ret) { + LIBLCD_ERR("virt to cptr failed"); + lcd_exit(-1); + } + ret = thc_ipc_send_request(hidden_args->async_chnl, + _request, + &request_cookie); + if (ret) { + LIBLCD_ERR("thc_ipc_send_request"); + goto fail_ipc; + } + lcd_set_r0(ilog2(( addr_mem_sz ) >> ( PAGE_SHIFT ))); + lcd_set_r1(addr_offset); + lcd_set_cr0(addr_cptr); + sync_ret = lcd_sync_send(sync_ep); + lcd_set_cr0(CAP_CPTR_NULL); + if (sync_ret) { + LIBLCD_ERR("failed to send"); + lcd_exit(-1); + } + ret = thc_ipc_recv_response(hidden_args->async_chnl, + request_cookie, + &_response); + func_ret = fipc_get_reg1(_response); + fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl), + _response); + return func_ret; +fail_async: +fail_ipc: + return ret; + +} + +LCD_TRAMPOLINE_DATA(ndo_set_mac_address_trampoline); +int LCD_TRAMPOLINE_LINKAGE(ndo_set_mac_address_trampoline) +ndo_set_mac_address_trampoline(struct net_device *dev, + void *addr) +{ + int ( *volatile ndo_set_mac_address_fp )(struct net_device *, + void *, + struct trampoline_hidden_args *); + struct trampoline_hidden_args *hidden_args; + LCD_TRAMPOLINE_PROLOGUE(hidden_args, + ndo_set_mac_address_trampoline); + ndo_set_mac_address_fp = ndo_set_mac_address; + return ndo_set_mac_address_fp(dev, + addr, + hidden_args); + +} + +int ndo_change_mtu_user(struct net_device *dev, + int new_mtu, + struct trampoline_hidden_args *hidden_args) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_request; + struct fipc_message *_response; + int func_ret; + dev_container = container_of(dev, + struct net_device_container, + net_device); + thc_init(); + ret = async_msg_blocking_send_start(hidden_args->async_chnl, + &_request); + if (ret) { + LIBLCD_ERR("failed to get a send slot"); + goto fail_async; + } + async_msg_set_fn_type(_request, + NDO_CHANGE_MTU); + fipc_set_reg1(_request, + dev_container->other_ref.cptr); + fipc_set_reg3(_request, + new_mtu); + DO_FINISH({ + ASYNC_({ + ret = thc_ipc_call(hidden_args->async_chnl, + _request, + &_response); + }, ndo_change_mtu + ); + } + ); + if (ret) { + LIBLCD_ERR("thc_ipc_call"); + goto fail_ipc; + } + func_ret = fipc_get_reg1(_response); + fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl), + _response); + lcd_exit(0); + return func_ret; +fail_async: +fail_ipc: + return ret; + +} + +int ndo_change_mtu(struct net_device *dev, + int new_mtu, + struct trampoline_hidden_args *hidden_args) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_request; + struct fipc_message *_response; + int func_ret; + if (!current->ptstate) { + LIBLCD_MSG("Calling from a non-LCD context! creating thc runtime!"); + LCD_MAIN({ + ret = ndo_change_mtu_user(dev, + new_mtu, + hidden_args); + } + ); + return ret; + } + dev_container = container_of(dev, + struct net_device_container, + net_device); + ret = async_msg_blocking_send_start(hidden_args->async_chnl, + &_request); + if (ret) { + LIBLCD_ERR("failed to get a send slot"); + goto fail_async; + } + async_msg_set_fn_type(_request, + NDO_CHANGE_MTU); + fipc_set_reg1(_request, + dev_container->other_ref.cptr); + fipc_set_reg3(_request, + new_mtu); + ret = thc_ipc_call(hidden_args->async_chnl, + _request, + &_response); + if (ret) { + LIBLCD_ERR("thc_ipc_call"); + goto fail_ipc; + } + func_ret = fipc_get_reg1(_response); + fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl), + _response); + return func_ret; +fail_async: +fail_ipc: + return ret; + +} + +LCD_TRAMPOLINE_DATA(ndo_change_mtu_trampoline); +int LCD_TRAMPOLINE_LINKAGE(ndo_change_mtu_trampoline) +ndo_change_mtu_trampoline(struct net_device *dev, + int new_mtu) +{ + int ( *volatile ndo_change_mtu_fp )(struct net_device *, + int , + struct trampoline_hidden_args *); + struct trampoline_hidden_args *hidden_args; + LCD_TRAMPOLINE_PROLOGUE(hidden_args, + ndo_change_mtu_trampoline); + ndo_change_mtu_fp = ndo_change_mtu; + return ndo_change_mtu_fp(dev, + new_mtu, + hidden_args); + +} + +void ndo_tx_timeout_user(struct net_device *dev, + struct trampoline_hidden_args *hidden_args) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_request; + struct fipc_message *_response; + dev_container = container_of(dev, + struct net_device_container, + net_device); + thc_init(); + ret = async_msg_blocking_send_start(hidden_args->async_chnl, + &_request); + if (ret) { + LIBLCD_ERR("failed to get a send slot"); + goto fail_async; + } + async_msg_set_fn_type(_request, + NDO_TX_TIMEOUT); + fipc_set_reg1(_request, + dev_container->other_ref.cptr); + DO_FINISH({ + ASYNC_({ + ret = thc_ipc_call(hidden_args->async_chnl, + _request, + &_response); + }, ndo_tx_timeout + ); + } + ); + if (ret) { + LIBLCD_ERR("thc_ipc_call"); + goto fail_ipc; + } + fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl), + _response); + lcd_exit(0); + +fail_async: +fail_ipc: + return; + +} + +void ndo_tx_timeout(struct net_device *dev, + struct trampoline_hidden_args *hidden_args) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_request; + struct fipc_message *_response; + if (!current->ptstate) { + LIBLCD_MSG("Calling from a non-LCD context! creating thc runtime!"); + LCD_MAIN({ + ndo_tx_timeout_user(dev, + hidden_args); + } + ); + return; + } + dev_container = container_of(dev, + struct net_device_container, + net_device); + ret = async_msg_blocking_send_start(hidden_args->async_chnl, + &_request); + if (ret) { + LIBLCD_ERR("failed to get a send slot"); + goto fail_async; + } + async_msg_set_fn_type(_request, + NDO_TX_TIMEOUT); + fipc_set_reg1(_request, + dev_container->other_ref.cptr); + ret = thc_ipc_call(hidden_args->async_chnl, + _request, + &_response); + if (ret) { + LIBLCD_ERR("thc_ipc_call"); + goto fail_ipc; + } + fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl), + _response); +fail_async: +fail_ipc: + return; + +} + +LCD_TRAMPOLINE_DATA(ndo_tx_timeout_trampoline); +void LCD_TRAMPOLINE_LINKAGE(ndo_tx_timeout_trampoline) +ndo_tx_timeout_trampoline(struct net_device *dev) +{ + void ( *volatile ndo_tx_timeout_fp )(struct net_device *, + struct trampoline_hidden_args *); + struct trampoline_hidden_args *hidden_args; + LCD_TRAMPOLINE_PROLOGUE(hidden_args, + ndo_tx_timeout_trampoline); + ndo_tx_timeout_fp = ndo_tx_timeout; + ndo_tx_timeout_fp(dev, + hidden_args); + return; +} + +int ndo_set_tx_maxrate_user(struct net_device *dev, + int queue_index, + unsigned int maxrate, + struct trampoline_hidden_args *hidden_args) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_request; + struct fipc_message *_response; + int func_ret; + dev_container = container_of(dev, + struct net_device_container, + net_device); + thc_init(); + ret = async_msg_blocking_send_start(hidden_args->async_chnl, + &_request); + if (ret) { + LIBLCD_ERR("failed to get a send slot"); + goto fail_async; + } + async_msg_set_fn_type(_request, + NDO_SET_TX_MAXRATE); + fipc_set_reg1(_request, + dev_container->other_ref.cptr); + fipc_set_reg3(_request, + queue_index); + fipc_set_reg4(_request, + maxrate); + DO_FINISH({ + ASYNC_({ + ret = thc_ipc_call(hidden_args->async_chnl, + _request, + &_response); + }, ndo_set_tx_maxrate + ); + } + ); + if (ret) { + LIBLCD_ERR("thc_ipc_call"); + goto fail_ipc; + } + func_ret = fipc_get_reg1(_response); + fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl), + _response); + lcd_exit(0); + return func_ret; +fail_async: +fail_ipc: + return ret; + +} + +int ndo_set_tx_maxrate(struct net_device *dev, + int queue_index, + unsigned int maxrate, + struct trampoline_hidden_args *hidden_args) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_request; + struct fipc_message *_response; + int func_ret; + if (!current->ptstate) { + LIBLCD_MSG("Calling from a non-LCD context! creating thc runtime!"); + LCD_MAIN({ + ret = ndo_set_tx_maxrate_user(dev, + queue_index, + maxrate, + hidden_args); + } + ); + return ret; + } + dev_container = container_of(dev, + struct net_device_container, + net_device); + ret = async_msg_blocking_send_start(hidden_args->async_chnl, + &_request); + if (ret) { + LIBLCD_ERR("failed to get a send slot"); + goto fail_async; + } + async_msg_set_fn_type(_request, + NDO_SET_TX_MAXRATE); + fipc_set_reg1(_request, + dev_container->other_ref.cptr); + fipc_set_reg3(_request, + queue_index); + fipc_set_reg4(_request, + maxrate); + ret = thc_ipc_call(hidden_args->async_chnl, + _request, + &_response); + if (ret) { + LIBLCD_ERR("thc_ipc_call"); + goto fail_ipc; + } + func_ret = fipc_get_reg1(_response); + fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl), + _response); + return func_ret; +fail_async: +fail_ipc: + return ret; + +} + +LCD_TRAMPOLINE_DATA(ndo_set_tx_maxrate_trampoline); +int LCD_TRAMPOLINE_LINKAGE(ndo_set_tx_maxrate_trampoline) +ndo_set_tx_maxrate_trampoline(struct net_device *dev, + int queue_index, + unsigned int maxrate) +{ + int ( *volatile ndo_set_tx_maxrate_fp )(struct net_device *, + int , + unsigned int , + struct trampoline_hidden_args *); + struct trampoline_hidden_args *hidden_args; + LCD_TRAMPOLINE_PROLOGUE(hidden_args, + ndo_set_tx_maxrate_trampoline); + ndo_set_tx_maxrate_fp = ndo_set_tx_maxrate; + return ndo_set_tx_maxrate_fp(dev, + queue_index, + maxrate, + hidden_args); + +} + +struct rtnl_link_stats64 *ndo_get_stats64_user(struct net_device *dev, + struct rtnl_link_stats64 *stats, + struct trampoline_hidden_args *hidden_args) +{ + struct net_device_container *dev_container; + int ret; + struct fipc_message *_request; + struct fipc_message *_response; + dev_container = container_of(dev, + struct net_device_container, + net_device); + thc_init(); + ret = async_msg_blocking_send_start(hidden_args->async_chnl, + &_request); + if (ret) { + LIBLCD_ERR("failed to get a send slot"); + goto fail_async; + } + async_msg_set_fn_type(_request, + NDO_GET_STATS64); + fipc_set_reg1(_request, + dev_container->other_ref.cptr); + DO_FINISH({ + ASYNC_({ + ret = thc_ipc_call(hidden_args->async_chnl, + _request, + &_response); + }, ndo_get_stats ); } ); @@ -653,28 +1877,34 @@ void remove_user(struct pci_dev *dev, fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl), _response); lcd_exit(0); - return; + return stats; fail_async: fail_ipc: - return; + return stats; } -void remove(struct pci_dev *dev, +struct rtnl_link_stats64 *ndo_get_stats64(struct net_device *dev, + struct rtnl_link_stats64 *stats, struct trampoline_hidden_args *hidden_args) { + struct net_device_container *dev_container; int ret; struct fipc_message *_request; struct fipc_message *_response; + struct rtnl_link_stats64 *func_ret = stats; if (!current->ptstate) { LIBLCD_MSG("Calling from a non-LCD context! creating thc runtime!"); LCD_MAIN({ - remove_user(dev, - hidden_args); + func_ret = ndo_get_stats64_user(dev, + stats, + hidden_args); } ); - return; + return func_ret; } - + dev_container = container_of(dev, + struct net_device_container, + net_device); ret = async_msg_blocking_send_start(hidden_args->async_chnl, &_request); if (ret) { @@ -682,7 +1912,11 @@ void remove(struct pci_dev *dev, goto fail_async; } async_msg_set_fn_type(_request, - REMOVE); + NDO_GET_STATS64); + fipc_set_reg1(_request, + dev_container->other_ref.cptr); + + LIBLCD_MSG("netdev lcd_ref %lu", dev_container->other_ref.cptr); ret = thc_ipc_call(hidden_args->async_chnl, _request, @@ -691,11 +1925,275 @@ void remove(struct pci_dev *dev, LIBLCD_ERR("thc_ipc_call"); goto fail_ipc; } + stats->rx_packets = fipc_get_reg1(_response); + stats->rx_bytes = fipc_get_reg2(_response); + stats->tx_packets = fipc_get_reg3(_response); + stats->tx_bytes = fipc_get_reg4(_response); + fipc_recv_msg_end(thc_channel_to_fipc(hidden_args->async_chnl), _response); - return; + return func_ret; fail_async: fail_ipc: + return func_ret; +} + +LCD_TRAMPOLINE_DATA(ndo_get_stats64_trampoline); +struct rtnl_link_stats64 LCD_TRAMPOLINE_LINKAGE(ndo_get_stats64_trampoline) +*ndo_get_stats64_trampoline(struct net_device *dev, + struct rtnl_link_stats64 *stats) +{ + struct rtnl_link_stats64* ( *volatile ndo_get_stats64_fp )(struct net_device *, + struct rtnl_link_stats64 *, + struct trampoline_hidden_args *); + struct trampoline_hidden_args *hidden_args; + LCD_TRAMPOLINE_PROLOGUE(hidden_args, + ndo_get_stats64_trampoline); + ndo_get_stats64_fp = ndo_get_stats64; + return ndo_get_stats64_fp(dev, + stats, + hidden_args); + +} + + +void setup_netdev_ops(struct net_device_container *dev_c, + struct net_device_ops_container *netdev_ops_container, struct thc_channel *_channel, + struct cptr sync_ep) +{ + struct trampoline_hidden_args *dev_netdev_ops_ndo_open_hidden_args; + struct trampoline_hidden_args *dev_netdev_ops_ndo_stop_hidden_args; + struct trampoline_hidden_args *dev_netdev_ops_ndo_start_xmit_hidden_args; + struct trampoline_hidden_args *dev_netdev_ops_ndo_set_rx_mode_hidden_args; + struct trampoline_hidden_args *dev_netdev_ops_ndo_validate_addr_hidden_args; + struct trampoline_hidden_args *dev_netdev_ops_ndo_set_mac_address_hidden_args; + struct trampoline_hidden_args *dev_netdev_ops_ndo_change_mtu_hidden_args; + struct trampoline_hidden_args *dev_netdev_ops_ndo_tx_timeout_hidden_args; + struct trampoline_hidden_args *dev_netdev_ops_ndo_set_tx_maxrate_hidden_args; + struct trampoline_hidden_args *dev_netdev_ops_ndo_get_stats64_hidden_args; + int ret; + + dev_netdev_ops_ndo_open_hidden_args = kzalloc(sizeof( struct trampoline_hidden_args ), + GFP_KERNEL); + if (!dev_netdev_ops_ndo_open_hidden_args) { + LIBLCD_ERR("kzalloc hidden args"); + goto fail_alloc1; + } + dev_netdev_ops_ndo_open_hidden_args->t_handle = LCD_DUP_TRAMPOLINE(ndo_open_trampoline); + if (!dev_netdev_ops_ndo_open_hidden_args->t_handle) { + LIBLCD_ERR("duplicate trampoline"); + goto fail_dup1; + } + dev_netdev_ops_ndo_open_hidden_args->t_handle->hidden_args = dev_netdev_ops_ndo_open_hidden_args; + dev_netdev_ops_ndo_open_hidden_args->struct_container = netdev_ops_container; + dev_netdev_ops_ndo_open_hidden_args->cspace = c_cspace; + dev_netdev_ops_ndo_open_hidden_args->sync_ep = sync_ep; + dev_netdev_ops_ndo_open_hidden_args->async_chnl = _channel; + netdev_ops_container->net_device_ops.ndo_open = LCD_HANDLE_TO_TRAMPOLINE(dev_netdev_ops_ndo_open_hidden_args->t_handle); + ret = set_memory_x(( ( unsigned long )dev_netdev_ops_ndo_open_hidden_args->t_handle ) & ( PAGE_MASK ), + ( ALIGN(LCD_TRAMPOLINE_SIZE(ndo_open_trampoline), + PAGE_SIZE) ) >> ( PAGE_SHIFT )); + dev_netdev_ops_ndo_stop_hidden_args = kzalloc(sizeof( struct trampoline_hidden_args ), + GFP_KERNEL); + if (!dev_netdev_ops_ndo_stop_hidden_args) { + LIBLCD_ERR("kzalloc hidden args"); + goto fail_alloc2; + } + dev_netdev_ops_ndo_stop_hidden_args->t_handle = LCD_DUP_TRAMPOLINE(ndo_stop_trampoline); + if (!dev_netdev_ops_ndo_stop_hidden_args->t_handle) { + LIBLCD_ERR("duplicate trampoline"); + goto fail_dup2; + } + dev_netdev_ops_ndo_stop_hidden_args->t_handle->hidden_args = dev_netdev_ops_ndo_stop_hidden_args; + dev_netdev_ops_ndo_stop_hidden_args->struct_container = netdev_ops_container; + dev_netdev_ops_ndo_stop_hidden_args->cspace = c_cspace; + dev_netdev_ops_ndo_stop_hidden_args->sync_ep = sync_ep; + dev_netdev_ops_ndo_stop_hidden_args->async_chnl = _channel; + netdev_ops_container->net_device_ops.ndo_stop = LCD_HANDLE_TO_TRAMPOLINE(dev_netdev_ops_ndo_stop_hidden_args->t_handle); + ret = set_memory_x(( ( unsigned long )dev_netdev_ops_ndo_stop_hidden_args->t_handle ) & ( PAGE_MASK ), + ( ALIGN(LCD_TRAMPOLINE_SIZE(ndo_stop_trampoline), + PAGE_SIZE) ) >> ( PAGE_SHIFT )); + dev_netdev_ops_ndo_start_xmit_hidden_args = kzalloc(sizeof( struct trampoline_hidden_args ), + GFP_KERNEL); + if (!dev_netdev_ops_ndo_start_xmit_hidden_args) { + LIBLCD_ERR("kzalloc hidden args"); + goto fail_alloc3; + } + dev_netdev_ops_ndo_start_xmit_hidden_args->t_handle = LCD_DUP_TRAMPOLINE(ndo_start_xmit_trampoline); + if (!dev_netdev_ops_ndo_start_xmit_hidden_args->t_handle) { + LIBLCD_ERR("duplicate trampoline"); + goto fail_dup3; + } + dev_netdev_ops_ndo_start_xmit_hidden_args->t_handle->hidden_args = dev_netdev_ops_ndo_start_xmit_hidden_args; + dev_netdev_ops_ndo_start_xmit_hidden_args->struct_container = netdev_ops_container; + dev_netdev_ops_ndo_start_xmit_hidden_args->cspace = c_cspace; + dev_netdev_ops_ndo_start_xmit_hidden_args->sync_ep = sync_ep; + dev_netdev_ops_ndo_start_xmit_hidden_args->async_chnl = _channel; + netdev_ops_container->net_device_ops.ndo_start_xmit = LCD_HANDLE_TO_TRAMPOLINE(dev_netdev_ops_ndo_start_xmit_hidden_args->t_handle); + ret = set_memory_x(( ( unsigned long )dev_netdev_ops_ndo_start_xmit_hidden_args->t_handle ) & ( PAGE_MASK ), + ( ALIGN(LCD_TRAMPOLINE_SIZE(ndo_start_xmit_trampoline), + PAGE_SIZE) ) >> ( PAGE_SHIFT )); + + dev_netdev_ops_ndo_set_rx_mode_hidden_args = kzalloc(sizeof( struct trampoline_hidden_args ), + GFP_KERNEL); + if (!dev_netdev_ops_ndo_set_rx_mode_hidden_args) { + LIBLCD_ERR("kzalloc hidden args"); + goto fail_alloc5; + } + dev_netdev_ops_ndo_set_rx_mode_hidden_args->t_handle = LCD_DUP_TRAMPOLINE(ndo_set_rx_mode_trampoline); + if (!dev_netdev_ops_ndo_set_rx_mode_hidden_args->t_handle) { + LIBLCD_ERR("duplicate trampoline"); + goto fail_dup5; + } + dev_netdev_ops_ndo_set_rx_mode_hidden_args->t_handle->hidden_args = dev_netdev_ops_ndo_set_rx_mode_hidden_args; + dev_netdev_ops_ndo_set_rx_mode_hidden_args->struct_container = netdev_ops_container; + dev_netdev_ops_ndo_set_rx_mode_hidden_args->cspace = c_cspace; + dev_netdev_ops_ndo_set_rx_mode_hidden_args->sync_ep = sync_ep; + dev_netdev_ops_ndo_set_rx_mode_hidden_args->async_chnl = _channel; + netdev_ops_container->net_device_ops.ndo_set_rx_mode = LCD_HANDLE_TO_TRAMPOLINE(dev_netdev_ops_ndo_set_rx_mode_hidden_args->t_handle); + ret = set_memory_x(( ( unsigned long )dev_netdev_ops_ndo_set_rx_mode_hidden_args->t_handle ) & ( PAGE_MASK ), + ( ALIGN(LCD_TRAMPOLINE_SIZE(ndo_set_rx_mode_trampoline), + PAGE_SIZE) ) >> ( PAGE_SHIFT )); + dev_netdev_ops_ndo_validate_addr_hidden_args = kzalloc(sizeof( struct trampoline_hidden_args ), + GFP_KERNEL); + if (!dev_netdev_ops_ndo_validate_addr_hidden_args) { + LIBLCD_ERR("kzalloc hidden args"); + goto fail_alloc6; + } + dev_netdev_ops_ndo_validate_addr_hidden_args->t_handle = LCD_DUP_TRAMPOLINE(ndo_validate_addr_trampoline); + if (!dev_netdev_ops_ndo_validate_addr_hidden_args->t_handle) { + LIBLCD_ERR("duplicate trampoline"); + goto fail_dup6; + } + dev_netdev_ops_ndo_validate_addr_hidden_args->t_handle->hidden_args = dev_netdev_ops_ndo_validate_addr_hidden_args; + dev_netdev_ops_ndo_validate_addr_hidden_args->struct_container = netdev_ops_container; + dev_netdev_ops_ndo_validate_addr_hidden_args->cspace = c_cspace; + dev_netdev_ops_ndo_validate_addr_hidden_args->sync_ep = sync_ep; + dev_netdev_ops_ndo_validate_addr_hidden_args->async_chnl = _channel; + netdev_ops_container->net_device_ops.ndo_validate_addr = LCD_HANDLE_TO_TRAMPOLINE(dev_netdev_ops_ndo_validate_addr_hidden_args->t_handle); + ret = set_memory_x(( ( unsigned long )dev_netdev_ops_ndo_validate_addr_hidden_args->t_handle ) & ( PAGE_MASK ), + ( ALIGN(LCD_TRAMPOLINE_SIZE(ndo_validate_addr_trampoline), + PAGE_SIZE) ) >> ( PAGE_SHIFT )); + dev_netdev_ops_ndo_set_mac_address_hidden_args = kzalloc(sizeof( struct trampoline_hidden_args ), + GFP_KERNEL); + if (!dev_netdev_ops_ndo_set_mac_address_hidden_args) { + LIBLCD_ERR("kzalloc hidden args"); + goto fail_alloc7; + } + dev_netdev_ops_ndo_set_mac_address_hidden_args->t_handle = LCD_DUP_TRAMPOLINE(ndo_set_mac_address_trampoline); + if (!dev_netdev_ops_ndo_set_mac_address_hidden_args->t_handle) { + LIBLCD_ERR("duplicate trampoline"); + goto fail_dup7; + } + dev_netdev_ops_ndo_set_mac_address_hidden_args->t_handle->hidden_args = dev_netdev_ops_ndo_set_mac_address_hidden_args; + dev_netdev_ops_ndo_set_mac_address_hidden_args->struct_container = netdev_ops_container; + dev_netdev_ops_ndo_set_mac_address_hidden_args->cspace = c_cspace; + dev_netdev_ops_ndo_set_mac_address_hidden_args->sync_ep = sync_ep; + dev_netdev_ops_ndo_set_mac_address_hidden_args->async_chnl = _channel; + netdev_ops_container->net_device_ops.ndo_set_mac_address = LCD_HANDLE_TO_TRAMPOLINE(dev_netdev_ops_ndo_set_mac_address_hidden_args->t_handle); + ret = set_memory_x(( ( unsigned long )dev_netdev_ops_ndo_set_mac_address_hidden_args->t_handle ) & ( PAGE_MASK ), + ( ALIGN(LCD_TRAMPOLINE_SIZE(ndo_set_mac_address_trampoline), + PAGE_SIZE) ) >> ( PAGE_SHIFT )); + dev_netdev_ops_ndo_change_mtu_hidden_args = kzalloc(sizeof( struct trampoline_hidden_args ), + GFP_KERNEL); + if (!dev_netdev_ops_ndo_change_mtu_hidden_args) { + LIBLCD_ERR("kzalloc hidden args"); + goto fail_alloc8; + } + dev_netdev_ops_ndo_change_mtu_hidden_args->t_handle = LCD_DUP_TRAMPOLINE(ndo_change_mtu_trampoline); + if (!dev_netdev_ops_ndo_change_mtu_hidden_args->t_handle) { + LIBLCD_ERR("duplicate trampoline"); + goto fail_dup8; + } + dev_netdev_ops_ndo_change_mtu_hidden_args->t_handle->hidden_args = dev_netdev_ops_ndo_change_mtu_hidden_args; + dev_netdev_ops_ndo_change_mtu_hidden_args->struct_container = netdev_ops_container; + dev_netdev_ops_ndo_change_mtu_hidden_args->cspace = c_cspace; + dev_netdev_ops_ndo_change_mtu_hidden_args->sync_ep = sync_ep; + dev_netdev_ops_ndo_change_mtu_hidden_args->async_chnl = _channel; + netdev_ops_container->net_device_ops.ndo_change_mtu = LCD_HANDLE_TO_TRAMPOLINE(dev_netdev_ops_ndo_change_mtu_hidden_args->t_handle); + ret = set_memory_x(( ( unsigned long )dev_netdev_ops_ndo_change_mtu_hidden_args->t_handle ) & ( PAGE_MASK ), + ( ALIGN(LCD_TRAMPOLINE_SIZE(ndo_change_mtu_trampoline), + PAGE_SIZE) ) >> ( PAGE_SHIFT )); + dev_netdev_ops_ndo_tx_timeout_hidden_args = kzalloc(sizeof( struct trampoline_hidden_args), + GFP_KERNEL); + if (!dev_netdev_ops_ndo_tx_timeout_hidden_args) { + LIBLCD_ERR("kzalloc hidden args"); + goto fail_alloc9; + } + dev_netdev_ops_ndo_tx_timeout_hidden_args->t_handle = LCD_DUP_TRAMPOLINE(ndo_tx_timeout_trampoline); + if (!dev_netdev_ops_ndo_tx_timeout_hidden_args->t_handle) { + LIBLCD_ERR("duplicate trampoline"); + goto fail_dup9; + } + dev_netdev_ops_ndo_tx_timeout_hidden_args->t_handle->hidden_args = dev_netdev_ops_ndo_tx_timeout_hidden_args; + dev_netdev_ops_ndo_tx_timeout_hidden_args->struct_container = netdev_ops_container; + dev_netdev_ops_ndo_tx_timeout_hidden_args->cspace = c_cspace; + dev_netdev_ops_ndo_tx_timeout_hidden_args->sync_ep = sync_ep; + dev_netdev_ops_ndo_tx_timeout_hidden_args->async_chnl = _channel; + netdev_ops_container->net_device_ops.ndo_tx_timeout = LCD_HANDLE_TO_TRAMPOLINE(dev_netdev_ops_ndo_tx_timeout_hidden_args->t_handle); + ret = set_memory_x(( ( unsigned long )dev_netdev_ops_ndo_tx_timeout_hidden_args->t_handle ) & ( PAGE_MASK ), + ( ALIGN(LCD_TRAMPOLINE_SIZE(ndo_tx_timeout_trampoline), + PAGE_SIZE) ) >> ( PAGE_SHIFT )); + dev_netdev_ops_ndo_set_tx_maxrate_hidden_args = kzalloc(sizeof( struct trampoline_hidden_args ), + GFP_KERNEL); + if (!dev_netdev_ops_ndo_set_tx_maxrate_hidden_args) { + LIBLCD_ERR("kzalloc hidden args"); + goto fail_alloc10; + } + dev_netdev_ops_ndo_set_tx_maxrate_hidden_args->t_handle = LCD_DUP_TRAMPOLINE(ndo_set_tx_maxrate_trampoline); + if (!dev_netdev_ops_ndo_set_tx_maxrate_hidden_args->t_handle) { + LIBLCD_ERR("duplicate trampoline"); + goto fail_dup10; + } + dev_netdev_ops_ndo_set_tx_maxrate_hidden_args->t_handle->hidden_args = dev_netdev_ops_ndo_set_tx_maxrate_hidden_args; + dev_netdev_ops_ndo_set_tx_maxrate_hidden_args->struct_container = netdev_ops_container; + dev_netdev_ops_ndo_set_tx_maxrate_hidden_args->cspace = c_cspace; + dev_netdev_ops_ndo_set_tx_maxrate_hidden_args->sync_ep = sync_ep; + dev_netdev_ops_ndo_set_tx_maxrate_hidden_args->async_chnl = _channel; + netdev_ops_container->net_device_ops.ndo_set_tx_maxrate = LCD_HANDLE_TO_TRAMPOLINE(dev_netdev_ops_ndo_set_tx_maxrate_hidden_args->t_handle); + ret = set_memory_x(( ( unsigned long )dev_netdev_ops_ndo_set_tx_maxrate_hidden_args->t_handle ) & ( PAGE_MASK ), + ( ALIGN(LCD_TRAMPOLINE_SIZE(ndo_set_tx_maxrate_trampoline), + PAGE_SIZE) ) >> ( PAGE_SHIFT )); + dev_netdev_ops_ndo_get_stats64_hidden_args = kzalloc(sizeof( struct trampoline_hidden_args ), + GFP_KERNEL); + if (!dev_netdev_ops_ndo_get_stats64_hidden_args) { + LIBLCD_ERR("kzalloc hidden args"); + goto fail_alloc11; + } + dev_netdev_ops_ndo_get_stats64_hidden_args->t_handle = LCD_DUP_TRAMPOLINE(ndo_get_stats64_trampoline); + if (!dev_netdev_ops_ndo_get_stats64_hidden_args->t_handle) { + LIBLCD_ERR("duplicate trampoline"); + goto fail_dup11; + } + dev_netdev_ops_ndo_get_stats64_hidden_args->t_handle->hidden_args = dev_netdev_ops_ndo_get_stats64_hidden_args; + dev_netdev_ops_ndo_get_stats64_hidden_args->struct_container = netdev_ops_container; + dev_netdev_ops_ndo_get_stats64_hidden_args->cspace = c_cspace; + dev_netdev_ops_ndo_get_stats64_hidden_args->sync_ep = sync_ep; + dev_netdev_ops_ndo_get_stats64_hidden_args->async_chnl = _channel; + netdev_ops_container->net_device_ops.ndo_get_stats64 = LCD_HANDLE_TO_TRAMPOLINE(dev_netdev_ops_ndo_get_stats64_hidden_args->t_handle); + ret = set_memory_x(( ( unsigned long )dev_netdev_ops_ndo_get_stats64_hidden_args->t_handle ) & ( PAGE_MASK ), + ( ALIGN(LCD_TRAMPOLINE_SIZE(ndo_get_stats64_trampoline), + PAGE_SIZE) ) >> ( PAGE_SHIFT )); +fail_alloc1: +fail_dup1: +fail_alloc2: +fail_dup2: +fail_alloc3: +fail_dup3: +fail_alloc5: +fail_dup5: +fail_alloc6: +fail_dup6: +fail_alloc7: +fail_dup7: +fail_alloc8: +fail_dup8: +fail_alloc9: +fail_dup9: +fail_alloc10: +fail_dup10: +fail_alloc11: +fail_dup11: return; } @@ -705,11 +2203,14 @@ int register_netdev_callee(struct fipc_message *_request, struct cptr sync_ep) { struct net_device_container *dev_container; + struct net_device_ops_container *netdev_ops_container; struct net_device *dev; int ret; struct fipc_message *_response; unsigned int request_cookie; int func_ret; + u8 mac_addr[] = {0xa0, 0x36, 0x9f, 0x08, 0x1c, 0x4a}; + request_cookie = thc_get_request_cookie(_request); ret = glue_cap_lookup_net_device_type(cspace, __cptr(fipc_get_reg0(_request)), @@ -718,6 +2219,20 @@ int register_netdev_callee(struct fipc_message *_request, LIBLCD_ERR("lookup"); goto fail_lookup; } + netdev_ops_container = kzalloc(sizeof( struct net_device_ops_container ), + GFP_KERNEL); + if (!netdev_ops_container) { + LIBLCD_ERR("kzalloc"); + goto fail_alloc; + } + ret = glue_cap_insert_net_device_ops_type(c_cspace, + netdev_ops_container, + &netdev_ops_container->my_ref); + if (ret) { + LIBLCD_ERR("lcd insert"); + goto fail_insert; + } + dev_container->net_device.netdev_ops = &netdev_ops_container->net_device_ops; fipc_recv_msg_end(thc_channel_to_fipc(_channel), _request); dev = &dev_container->net_device; @@ -727,6 +2242,11 @@ int register_netdev_callee(struct fipc_message *_request, dev->hw_features = fipc_get_reg4(_request); dev->hw_enc_features = fipc_get_reg5(_request); dev->mpls_features = fipc_get_reg6(_request); + + memcpy(dev->dev_addr, mac_addr, ETH_ALEN); + /* setup netdev_ops */ + setup_netdev_ops(dev_container, netdev_ops_container, _channel, sync_ep); + func_ret = register_netdev(( &dev_container->net_device )); if (async_msg_blocking_send_start(_channel, &_response)) { @@ -735,11 +2255,15 @@ int register_netdev_callee(struct fipc_message *_request, } fipc_set_reg1(_response, func_ret); + fipc_set_reg2(_response, + dev->reg_state); thc_ipc_reply(_channel, request_cookie, _response); fail_lookup: +fail_insert: +fail_alloc: return ret; } @@ -980,20 +2504,21 @@ int netif_device_attach_callee(struct fipc_message *_request, struct glue_cspace *cspace, struct cptr sync_ep) { - struct net_device *dev; + struct net_device_container *dev_container; int ret; struct fipc_message *_response; unsigned int request_cookie; request_cookie = thc_get_request_cookie(_request); + ret = glue_cap_lookup_net_device_type(cspace, + __cptr(fipc_get_reg1(_request)), + &dev_container); + if (ret) { + LIBLCD_ERR("lookup"); + goto fail_lookup; + } fipc_recv_msg_end(thc_channel_to_fipc(_channel), _request); - dev = kzalloc(sizeof( *dev ), - GFP_KERNEL); - if (!dev) { - LIBLCD_ERR("kzalloc"); - goto fail_alloc; - } - netif_device_attach(dev); + netif_device_attach(( &dev_container->net_device )); if (async_msg_blocking_send_start(_channel, &_response)) { LIBLCD_ERR("error getting response msg"); @@ -1002,9 +2527,9 @@ int netif_device_attach_callee(struct fipc_message *_request, thc_ipc_reply(_channel, request_cookie, _response); -fail_alloc: return ret; - +fail_lookup: + return ret; } int netif_device_detach_callee(struct fipc_message *_request, @@ -1012,20 +2537,21 @@ int netif_device_detach_callee(struct fipc_message *_request, struct glue_cspace *cspace, struct cptr sync_ep) { - struct net_device *dev; + struct net_device_container *dev_container; int ret; struct fipc_message *_response; unsigned int request_cookie; request_cookie = thc_get_request_cookie(_request); + ret = glue_cap_lookup_net_device_type(cspace, + __cptr(fipc_get_reg1(_request)), + &dev_container); + if (ret) { + LIBLCD_ERR("lookup"); + goto fail_lookup; + } fipc_recv_msg_end(thc_channel_to_fipc(_channel), _request); - dev = kzalloc(sizeof( *dev ), - GFP_KERNEL); - if (!dev) { - LIBLCD_ERR("kzalloc"); - goto fail_alloc; - } - netif_device_detach(dev); + netif_device_detach(( &dev_container->net_device )); if (async_msg_blocking_send_start(_channel, &_response)) { LIBLCD_ERR("error getting response msg"); @@ -1034,9 +2560,9 @@ int netif_device_detach_callee(struct fipc_message *_request, thc_ipc_reply(_channel, request_cookie, _response); -fail_alloc: return ret; - +fail_lookup: + return ret; } int netif_set_real_num_rx_queues_callee(struct fipc_message *_request, @@ -1044,23 +2570,24 @@ int netif_set_real_num_rx_queues_callee(struct fipc_message *_request, struct glue_cspace *cspace, struct cptr sync_ep) { - struct net_device *dev; + struct net_device_container *dev_container; unsigned int rxq; int ret; struct fipc_message *_response; unsigned int request_cookie; int func_ret; request_cookie = thc_get_request_cookie(_request); + ret = glue_cap_lookup_net_device_type(cspace, + __cptr(fipc_get_reg1(_request)), + &dev_container); + if (ret) { + LIBLCD_ERR("lookup"); + goto fail_lookup; + } fipc_recv_msg_end(thc_channel_to_fipc(_channel), _request); - dev = kzalloc(sizeof( *dev ), - GFP_KERNEL); - if (!dev) { - LIBLCD_ERR("kzalloc"); - goto fail_alloc; - } - rxq = fipc_get_reg1(_request); - func_ret = netif_set_real_num_rx_queues(dev, + rxq = fipc_get_reg3(_request); + func_ret = netif_set_real_num_rx_queues(( &dev_container->net_device ), rxq); if (async_msg_blocking_send_start(_channel, &_response)) { @@ -1072,7 +2599,8 @@ int netif_set_real_num_rx_queues_callee(struct fipc_message *_request, thc_ipc_reply(_channel, request_cookie, _response); -fail_alloc: + return ret; +fail_lookup: return ret; } @@ -1082,24 +2610,29 @@ int netif_set_real_num_tx_queues_callee(struct fipc_message *_request, struct glue_cspace *cspace, struct cptr sync_ep) { - struct net_device *dev; + struct net_device_container *dev_container; unsigned int txq; int ret; struct fipc_message *_response; unsigned int request_cookie; int func_ret; request_cookie = thc_get_request_cookie(_request); + ret = glue_cap_lookup_net_device_type(cspace, + __cptr(fipc_get_reg1(_request)), + &dev_container); + if (ret) { + LIBLCD_ERR("lookup"); + goto fail_lookup; + } fipc_recv_msg_end(thc_channel_to_fipc(_channel), _request); - dev = kzalloc(sizeof( *dev ), - GFP_KERNEL); - if (!dev) { - LIBLCD_ERR("kzalloc"); - goto fail_alloc; - } - txq = fipc_get_reg1(_request); - func_ret = netif_set_real_num_tx_queues(dev, + txq = fipc_get_reg3(_request); + + LIBLCD_MSG("%s, txq %d | num_tx_queues %d", __func__, txq, dev_container->net_device.num_tx_queues); + + func_ret = netif_set_real_num_tx_queues(( &dev_container->net_device ), txq); + LIBLCD_MSG("netif_set_real_num_tx_queues returns %d", func_ret); if (async_msg_blocking_send_start(_channel, &_response)) { LIBLCD_ERR("error getting response msg"); @@ -1110,7 +2643,8 @@ int netif_set_real_num_tx_queues_callee(struct fipc_message *_request, thc_ipc_reply(_channel, request_cookie, _response); -fail_alloc: + return ret; +fail_lookup: return ret; } @@ -1228,12 +2762,13 @@ int eth_platform_get_mac_address_callee(struct fipc_message *_request, return ret; } -int dev_addr_del_callee(struct fipc_message *_request, +int dev_addr_add_callee(struct fipc_message *_request, struct thc_channel *_channel, struct glue_cspace *cspace, struct cptr sync_ep) { struct net_device *dev; + struct net_device_container *dev_container; unsigned char addr_type; int ret; struct fipc_message *_response; @@ -1246,14 +2781,89 @@ int dev_addr_del_callee(struct fipc_message *_request, gva_t addr_gva; request_cookie = thc_get_request_cookie(_request); + ret = glue_cap_lookup_net_device_type(cspace, + __cptr(fipc_get_reg1(_request)), + &dev_container); + if (ret) { + LIBLCD_ERR("lookup"); + goto fail_lookup; + } + dev = &dev_container->net_device; + addr_type = fipc_get_reg3(_request); fipc_recv_msg_end(thc_channel_to_fipc(_channel), _request); - dev = kzalloc(sizeof( *dev ), - GFP_KERNEL); - if (!dev) { - LIBLCD_ERR("kzalloc"); - goto fail_alloc; + + sync_ret = lcd_cptr_alloc(&addr_cptr); + if (sync_ret) { + LIBLCD_ERR("failed to get cptr"); + lcd_exit(-1); } + lcd_set_cr0(addr_cptr); + sync_ret = lcd_sync_recv(sync_ep); + lcd_set_cr0(CAP_CPTR_NULL); + if (sync_ret) { + LIBLCD_ERR("failed to recv"); + lcd_exit(-1); + } + mem_order = lcd_r0(); + addr_offset = lcd_r1(); + sync_ret = lcd_map_virt(addr_cptr, + mem_order, + &addr_gva); + if (sync_ret) { + LIBLCD_ERR("failed to map void *addr"); + lcd_exit(-1); + } + rtnl_lock(); + func_ret = dev_addr_add(dev, + ( void * )( ( gva_val(addr_gva) ) + ( addr_offset ) ), + addr_type); + rtnl_unlock(); + if (async_msg_blocking_send_start(_channel, + &_response)) { + LIBLCD_ERR("error getting response msg"); + return -EIO; + } + fipc_set_reg1(_response, + func_ret); + thc_ipc_reply(_channel, + request_cookie, + _response); +fail_lookup: + return ret; + +} + +int dev_addr_del_callee(struct fipc_message *_request, + struct thc_channel *_channel, + struct glue_cspace *cspace, + struct cptr sync_ep) +{ + struct net_device *dev; + struct net_device_container *dev_container; + unsigned char addr_type; + int ret; + struct fipc_message *_response; + unsigned int request_cookie; + int func_ret; + int sync_ret; + unsigned long mem_order; + unsigned long addr_offset; + cptr_t addr_cptr; + gva_t addr_gva; + + request_cookie = thc_get_request_cookie(_request); + ret = glue_cap_lookup_net_device_type(cspace, + __cptr(fipc_get_reg1(_request)), + &dev_container); + if (ret) { + LIBLCD_ERR("lookup"); + goto fail_lookup; + } + dev = &dev_container->net_device; + addr_type = fipc_get_reg3(_request); + fipc_recv_msg_end(thc_channel_to_fipc(_channel), + _request); sync_ret = lcd_cptr_alloc(&addr_cptr); if (sync_ret) { @@ -1276,10 +2886,11 @@ int dev_addr_del_callee(struct fipc_message *_request, LIBLCD_ERR("failed to map void *addr"); lcd_exit(-1); } - addr_type = fipc_get_reg1(_request); + rtnl_lock(); func_ret = dev_addr_del(dev, ( void * )( ( gva_val(addr_gva) ) + ( addr_offset ) ), addr_type); + rtnl_unlock(); if (async_msg_blocking_send_start(_channel, &_response)) { LIBLCD_ERR("error getting response msg"); @@ -1290,7 +2901,7 @@ int dev_addr_del_callee(struct fipc_message *_request, thc_ipc_reply(_channel, request_cookie, _response); -fail_alloc: +fail_lookup: return ret; } diff --git a/lcd-domains/test_mods/ixgbe/net_klcd/glue/ixgbe_callee.lds.S b/lcd-domains/test_mods/ixgbe/net_klcd/glue/ixgbe_callee.lds.S index 3ed1466ca97f..efbe79480b11 100644 --- a/lcd-domains/test_mods/ixgbe/net_klcd/glue/ixgbe_callee.lds.S +++ b/lcd-domains/test_mods/ixgbe/net_klcd/glue/ixgbe_callee.lds.S @@ -2,6 +2,16 @@ SECTIONS { + LCD_TRAMPOLINE_LINKER_SECTION(ndo_open_trampoline) + LCD_TRAMPOLINE_LINKER_SECTION(ndo_stop_trampoline) + LCD_TRAMPOLINE_LINKER_SECTION(ndo_start_xmit_trampoline) + LCD_TRAMPOLINE_LINKER_SECTION(ndo_set_rx_mode_trampoline) + LCD_TRAMPOLINE_LINKER_SECTION(ndo_validate_addr_trampoline) + LCD_TRAMPOLINE_LINKER_SECTION(ndo_set_mac_address_trampoline) + LCD_TRAMPOLINE_LINKER_SECTION(ndo_change_mtu_trampoline) + LCD_TRAMPOLINE_LINKER_SECTION(ndo_tx_timeout_trampoline) + LCD_TRAMPOLINE_LINKER_SECTION(ndo_set_tx_maxrate_trampoline) + LCD_TRAMPOLINE_LINKER_SECTION(ndo_get_stats64_trampoline) LCD_TRAMPOLINE_LINKER_SECTION(probe_trampoline) LCD_TRAMPOLINE_LINKER_SECTION(remove_trampoline) } diff --git a/lcd-domains/test_mods/ixgbe/net_klcd/glue/ixgbe_callee_dispatch.c b/lcd-domains/test_mods/ixgbe/net_klcd/glue/ixgbe_callee_dispatch.c index c74309a96be0..114d6cc4abdf 100644 --- a/lcd-domains/test_mods/ixgbe/net_klcd/glue/ixgbe_callee_dispatch.c +++ b/lcd-domains/test_mods/ixgbe/net_klcd/glue/ixgbe_callee_dispatch.c @@ -48,7 +48,7 @@ int dispatch_async_loop(struct thc_channel *_channel, cspace, sync_ep); - case REGISTER_NETDEVICE: + case REGISTER_NETDEV: trace(REGISTER_NETDEVICE); return register_netdev_callee(message, _channel, @@ -146,6 +146,13 @@ int dispatch_async_loop(struct thc_channel *_channel, cspace, sync_ep); + case DEV_ADDR_ADD: + trace(DEV_ADDR_ADD); + return dev_addr_add_callee(message, + _channel, + cspace, + sync_ep); + case DEV_ADDR_DEL: trace(DEV_ADDR_DEL); return dev_addr_del_callee(message, diff --git a/lcd-domains/test_mods/ixgbe/net_klcd/ixgbe_callee.h b/lcd-domains/test_mods/ixgbe/net_klcd/ixgbe_callee.h index 48e5dc3600ae..56e3672db25c 100644 --- a/lcd-domains/test_mods/ixgbe/net_klcd/ixgbe_callee.h +++ b/lcd-domains/test_mods/ixgbe/net_klcd/ixgbe_callee.h @@ -73,6 +73,10 @@ int eth_platform_get_mac_address_callee(struct fipc_message *_request, struct thc_channel *_channel, struct glue_cspace *cspace, struct cptr sync_ep); +int dev_addr_add_callee(struct fipc_message *_request, + struct thc_channel *_channel, + struct glue_cspace *cspace, + struct cptr sync_ep); int dev_addr_del_callee(struct fipc_message *_request, struct thc_channel *_channel, struct glue_cspace *cspace, -- GitLab