dde_linux: update usb_net driver to Linux 6.1.20

Driver for network-interface cards and LTE modems with MBIM support
connected via USB.

issue #4958
This commit is contained in:
Sebastian Sumpf 2023-07-05 18:01:10 +02:00 committed by Christian Helmuth
parent f668aea42a
commit d5cf77539a
25 changed files with 7550 additions and 0 deletions

View File

@ -0,0 +1,11 @@
MIRROR_FROM_REP_DIR := src/drivers/usb_net
content: $(MIRROR_FROM_REP_DIR)
$(MIRROR_FROM_REP_DIR):
$(mirror_from_rep_dir)
PORT_DIR := $(call port_dir,$(GENODE_DIR)/repos/dde_linux/ports/linux)
content: LICENSE
LICENSE:
cp $(PORT_DIR)/src/linux/COPYING $@

View File

@ -0,0 +1 @@
2023-07-11-p 9df48e239f9ca1d4233a198e4ec39a4ed571b366

View File

@ -0,0 +1,10 @@
base
genode_c_api
jitterentropy
nic_session
os
report_session
terminal_session
uplink_session
usb_session
virt_linux

View File

@ -0,0 +1,70 @@
USB NIC driver
Driver for network-interface cards and LTE modems with MBIM support connected via USB.
Current supported devices
=========================
* NICs containing an AX88179A chip
* NICs that support the NCM profile (e.g., RTL8156)
* NICs that the ECM profile
* LTE modems that support the MBIM configuration
NIC configuration
=================
Configuration snippet:
!<start name="usb_net_drv">
! <resource name="RAM" quantum="10M"/>
! <config mac="2e:60:90:0c:4e:01 configuration="2" />
! <route>
! <service name="Uplink"><child name="nic_router"/></service/>
! ....
! </route>
!</start>
The driver connects as an Uplink client to Genode's network infrastructure.
The 'mac' can be used to configure the hardware address on devices that support
setting it and for devices that do not offer a hardware address (a random
address will be used otherwise).
The 'configuration' attribute allows for setting the desired configuration
profile of the USB device in case there is more than one profile. In case it is
omitted or 0, the driver will choose a profile (first non-vendor specific).
LTE modem configuration
========================
Currently there is support for MBIM (Mobile Broadband Interface Model) devices.
Tested devices:
Huawai ME906s (P/V: 12d1:15c1) - "configuration=3" for 'usb_net_drv'
Fibocom L830-EB-00 (P/V: 2cb7:0210) - automatically detected
!<start name="usb_nic_drv">
! <resource name="RAM" quantum="10M"/>
! <provides>
! <service name="Terminal"/>
! </provides>
! <config mac="02:00:00:00:01:01" configuration="3"/>
! <route>
! <service name="Uplink"><child name="nic_router"/></service/>
! ....
! </route>
!</start>
In case the driver finds a MBIM capable device it will announce a terminal
session which is used as the control channel (wireless communication device
class - CDC WDM).
An example scenario can be found in Genode World
(_src/app/mbimcli_). Once a data connection is established via the Terminal
session, the Uplink session is used to transfer Ethernet frames.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,418 @@
/*
* \brief Dummy definitions of Linux Kernel functions
* \author Sebastian Sumpf
* \date 2023-07-11
*/
/*
* Copyright (C) 2023 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <lx_emul.h>
DEFINE_STATIC_KEY_FALSE(force_irqthreads_key);
DEFINE_STATIC_KEY_FALSE(bpf_stats_enabled_key);
DEFINE_STATIC_KEY_FALSE(bpf_master_redirect_enabled_key);
DEFINE_STATIC_KEY_FALSE(memalloc_socks_key);
unsigned long __FIXADDR_TOP = 0xfffff000;
bool arm64_use_ng_mappings = false;
const struct ipv6_stub *ipv6_stub;
#ifdef __i386__
asmlinkage __wsum csum_partial(const void * buff,int len,__wsum sum)
#else
__wsum csum_partial(const void * buff,int len,__wsum sum)
#endif
{
lx_emul_trace_and_stop(__func__);
}
#ifdef __arm__
#include <asm/uaccess.h>
unsigned long arm_copy_to_user(void *to, const void *from, unsigned long n)
{
lx_emul_trace_and_stop(__func__);
}
asmlinkage void __div0(void);
asmlinkage void __div0(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/dma-map-ops.h>
void arch_teardown_dma_ops(struct device * dev)
{
lx_emul_trace(__func__);
}
extern void arm_heavy_mb(void);
void arm_heavy_mb(void)
{
// FIXME: on Cortex A9 we potentially need to flush L2-cache
lx_emul_trace(__func__);
}
#else
#include <linux/timekeeper_internal.h>
void update_vsyscall(struct timekeeper * tk)
{
lx_emul_trace(__func__);
}
#endif
#include <linux/filter.h>
#include <linux/jump_label.h> /* for DEFINE_STATIC_KEY_FALSE */
void bpf_prog_change_xdp(struct bpf_prog *prev_prog, struct bpf_prog *prog)
{
lx_emul_trace(__func__);
}
#include <linux/rcutree.h>
void synchronize_rcu_expedited(void)
{
lx_emul_trace(__func__);
}
#include <linux/rcupdate.h>
void synchronize_rcu(void)
{
lx_emul_trace(__func__);
}
#include <net/net_namespace.h>
void __init net_ns_init(void)
{
lx_emul_trace(__func__);
}
#include <linux/kobject.h>
int kobject_uevent(struct kobject * kobj,enum kobject_action action)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/usb/hcd.h>
void __init usb_init_pool_max(void)
{
lx_emul_trace(__func__);
}
extern int usb_major_init(void);
int usb_major_init(void)
{
lx_emul_trace(__func__);
return 0;
}
extern int __init usb_devio_init(void);
int __init usb_devio_init(void)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/usb/hcd.h>
void usb_hcd_synchronize_unlinks(struct usb_device * udev)
{
lx_emul_trace(__func__);
}
#include <linux/usb.h>
struct urb * usb_get_from_anchor(struct usb_anchor * anchor)
{
lx_emul_trace(__func__);
return NULL;
}
extern char * usb_cache_string(struct usb_device * udev,int index);
char * usb_cache_string(struct usb_device * udev,int index)
{
lx_emul_trace(__func__);
return NULL;
}
void usb_kill_urb(struct urb * urb)
{
lx_emul_trace(__func__);
}
int usb_unlink_urb(struct urb * urb)
{
lx_emul_trace(__func__);
return 0;
}
void usb_poison_urb(struct urb * urb)
{
lx_emul_trace(__func__);
}
#include <linux/usb/hcd.h>
struct usb_hcd * usb_get_hcd(struct usb_hcd * hcd)
{
lx_emul_trace(__func__);
return hcd;
}
#include <linux/usb/hcd.h>
void usb_put_hcd(struct usb_hcd * hcd)
{
lx_emul_trace(__func__);
}
extern int __init netdev_kobject_init(void);
int __init netdev_kobject_init(void)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/netdevice.h>
void dev_add_offload(struct packet_offload * po)
{
lx_emul_trace(__func__);
}
#include <linux/syscore_ops.h>
void register_syscore_ops(struct syscore_ops * ops)
{
lx_emul_trace(__func__);
}
#include <linux/kernel.h>
bool parse_option_str(const char * str,const char * option)
{
lx_emul_trace(__func__);
return false;
}
#include <linux/rtnetlink.h>
int rtnl_lock_killable(void)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/rtnetlink.h>
void rtnl_lock(void)
{
lx_emul_trace(__func__);
}
#include <linux/rtnetlink.h>
int rtnl_is_locked(void)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/rtnetlink.h>
struct sk_buff * rtmsg_ifinfo_build_skb(int type,struct net_device * dev,unsigned int change,u32 event,gfp_t flags,int * new_nsid,int new_ifindex)
{
lx_emul_trace(__func__);
return NULL;
}
#include <linux/stringhash.h>
unsigned int full_name_hash(const void * salt,const char * name,unsigned int len)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/random.h>
void add_device_randomness(const void * buf,size_t len)
{
lx_emul_trace(__func__);
}
#include <linux/rtnetlink.h>
void rtnl_unlock(void)
{
lx_emul_trace(__func__);
}
#include <net/gen_stats.h>
void gnet_stats_basic_sync_init(struct gnet_stats_basic_sync * b)
{
lx_emul_trace(__func__);
}
#include <net/gen_stats.h>
void gen_kill_estimator(struct net_rate_estimator __rcu ** rate_est)
{
lx_emul_trace(__func__);
}
#include <asm-generic/softirq_stack.h>
void do_softirq_own_stack(void)
{
lx_emul_trace(__func__);
}
#include <linux/of_net.h>
#if defined(CONFIG_OF) && defined(CONFIG_NET)
int of_get_mac_address(struct device_node * np,u8 * addr)
{
lx_emul_trace(__func__);
return -1;
}
#endif
extern void software_node_notify(struct device * dev);
void software_node_notify(struct device * dev)
{
lx_emul_trace(__func__);
}
extern void software_node_notify_remove(struct device * dev);
void software_node_notify_remove(struct device * dev)
{
lx_emul_trace(__func__);
}
extern int usb_create_sysfs_dev_files(struct usb_device * udev);
int usb_create_sysfs_dev_files(struct usb_device * udev)
{
lx_emul_trace(__func__);
return 0;
}
extern void usb_remove_sysfs_dev_files(struct usb_device * udev);
void usb_remove_sysfs_dev_files(struct usb_device * udev)
{
lx_emul_trace(__func__);
}
extern void usb_remove_sysfs_intf_files(struct usb_interface * intf);
void usb_remove_sysfs_intf_files(struct usb_interface * intf)
{
lx_emul_trace(__func__);
}
extern void usb_create_sysfs_intf_files(struct usb_interface * intf);
void usb_create_sysfs_intf_files(struct usb_interface * intf)
{
lx_emul_trace(__func__);
}
extern void usb_notify_add_device(struct usb_device * udev);
void usb_notify_add_device(struct usb_device * udev)
{
lx_emul_trace(__func__);
}
extern void usb_notify_remove_device(struct usb_device * udev);
void usb_notify_remove_device(struct usb_device * udev)
{
lx_emul_trace(__func__);
}
extern int usb_create_ep_devs(struct device * parent,struct usb_host_endpoint * endpoint,struct usb_device * udev);
int usb_create_ep_devs(struct device * parent,struct usb_host_endpoint * endpoint,struct usb_device * udev)
{
lx_emul_trace(__func__);
return 0;
}
extern void usb_remove_ep_devs(struct usb_host_endpoint * endpoint);
void usb_remove_ep_devs(struct usb_host_endpoint * endpoint)
{
lx_emul_trace(__func__);
}
extern void usb_disable_interface(struct usb_device * dev,struct usb_interface * intf,bool reset_hardware);
void usb_disable_interface(struct usb_device * dev,struct usb_interface * intf,bool reset_hardware)
{
lx_emul_trace(__func__);
}
extern void netdev_unregister_kobject(struct net_device * ndev);
void netdev_unregister_kobject(struct net_device * ndev)
{
lx_emul_trace(__func__);
}

View File

@ -0,0 +1,513 @@
/*
* \brief Implementation of driver specific Linux functions
* \author Sebastian Sumpf
* \date 2023-06-29
*/
/*
* Copyright (C) 2023 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <lx_emul.h>
pteval_t __default_kernel_pte_mask __read_mostly = ~0;
struct device_type usb_if_device_type = {
.name = "usb_interface"
};
struct usb_driver usbfs_driver = {
.name = "usbfs"
};
const struct attribute_group *usb_device_groups[] = { };
#include <linux/slab.h>
struct kmem_cache * kmem_cache_create_usercopy(const char * name,
unsigned int size,
unsigned int align,
slab_flags_t flags,
unsigned int useroffset,
unsigned int usersize,
void (* ctor)(void *))
{
return kmem_cache_create(name, size, align, flags, ctor);
}
#include <net/netfilter/nf_conntrack.h>
struct net init_net;
#include <net/net_namespace.h>
int register_pernet_subsys(struct pernet_operations *ops)
{
if (ops->init)
ops->init(&init_net);
return 0;
}
int register_pernet_device(struct pernet_operations *ops)
{
return register_pernet_subsys(ops);
}
#include <linux/rcutree.h>
/*
* taken from src/lib/wifi/lx_emul.c
*/
void kvfree_call_rcu(struct rcu_head * head, rcu_callback_t func)
{
void *ptr = (void *) head - (unsigned long) func;
kvfree(ptr);
}
#include <linux/gfp.h>
unsigned long get_zeroed_page(gfp_t gfp_mask)
{
return (unsigned long)kzalloc(PAGE_SIZE, GFP_KERNEL);
}
void free_pages(unsigned long addr,unsigned int order)
{
kfree((void *)addr);
}
#include <linux/gfp.h>
void * page_frag_alloc_align(struct page_frag_cache * nc, unsigned int fragsz,
gfp_t gfp_mask, unsigned int align_mask)
{
if (align_mask != ~0U) {
printk("page_frag_alloc_align: unsupported align_mask=%x\n", align_mask);
lx_emul_trace_and_stop(__func__);
}
return lx_emul_mem_alloc_aligned(fragsz, ARCH_KMALLOC_MINALIGN);
}
void page_frag_free(void * addr)
{
lx_emul_mem_free(addr);
}
#include <linux/uaccess.h>
#ifndef INLINE_COPY_TO_USER
unsigned long _copy_from_user(void * to,const void __user * from,unsigned long n)
{
memcpy(to, from, n);
return 0;
}
#else
unsigned long __must_check __arch_copy_from_user(void *to, const void __user *from, unsigned long n);
unsigned long __must_check __arch_copy_from_user(void *to, const void __user *from, unsigned long n)
{
memcpy(to, from, n);
return 0;
}
#endif
#ifndef INLINE_COPY_FROM_USER
unsigned long _copy_to_user(void __user * to,const void * from,unsigned long n)
{
memcpy(to, from, n);
return 0;
}
#else
unsigned long __must_check __arch_copy_to_user(void __user *to, const void *from, unsigned long n);
unsigned long __must_check __arch_copy_to_user(void __user *to, const void *from, unsigned long n)
{
memcpy(to, from, n);
return 0;
}
#endif
unsigned long arm_copy_from_user(void *to, const void *from, unsigned long n)
{
memcpy(to, from, n);
return 0;
}
/*
* custom MAC address
*/
bool use_mac_address;
unsigned char mac_address[6];
int netdev_register_kobject(struct net_device * ndev)
{
if (use_mac_address) eth_hw_addr_set(ndev, mac_address);
return 0;
}
/*
* core/message.c
*/
#include <linux/nls.h>
#include <linux/usb/quirks.h>
#include <linux/usb/cdc.h>
#include <linux/ctype.h>
int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr,
struct usb_interface *intf,
u8 *buffer,
int buflen)
{
/* duplicates are ignored */
struct usb_cdc_union_desc *union_header = NULL;
/* duplicates are not tolerated */
struct usb_cdc_header_desc *header = NULL;
struct usb_cdc_ether_desc *ether = NULL;
struct usb_cdc_mdlm_detail_desc *detail = NULL;
struct usb_cdc_mdlm_desc *desc = NULL;
unsigned int elength;
int cnt = 0;
memset(hdr, 0x00, sizeof(struct usb_cdc_parsed_header));
hdr->phonet_magic_present = false;
while (buflen > 0) {
elength = buffer[0];
if (!elength) {
dev_err(&intf->dev, "skipping garbage byte\n");
elength = 1;
goto next_desc;
}
if ((buflen < elength) || (elength < 3)) {
dev_err(&intf->dev, "invalid descriptor buffer length\n");
break;
}
if (buffer[1] != USB_DT_CS_INTERFACE) {
dev_err(&intf->dev, "skipping garbage\n");
goto next_desc;
}
switch (buffer[2]) {
case USB_CDC_UNION_TYPE: /* we've found it */
if (elength < sizeof(struct usb_cdc_union_desc))
goto next_desc;
if (union_header) {
dev_err(&intf->dev, "More than one union descriptor, skipping ...\n");
goto next_desc;
}
union_header = (struct usb_cdc_union_desc *)buffer;
break;
case USB_CDC_COUNTRY_TYPE:
if (elength < sizeof(struct usb_cdc_country_functional_desc))
goto next_desc;
hdr->usb_cdc_country_functional_desc =
(struct usb_cdc_country_functional_desc *)buffer;
break;
case USB_CDC_HEADER_TYPE:
if (elength != sizeof(struct usb_cdc_header_desc))
goto next_desc;
if (header)
return -EINVAL;
header = (struct usb_cdc_header_desc *)buffer;
break;
case USB_CDC_ACM_TYPE:
if (elength < sizeof(struct usb_cdc_acm_descriptor))
goto next_desc;
hdr->usb_cdc_acm_descriptor =
(struct usb_cdc_acm_descriptor *)buffer;
break;
case USB_CDC_ETHERNET_TYPE:
if (elength != sizeof(struct usb_cdc_ether_desc))
goto next_desc;
if (ether)
return -EINVAL;
ether = (struct usb_cdc_ether_desc *)buffer;
break;
case USB_CDC_CALL_MANAGEMENT_TYPE:
if (elength < sizeof(struct usb_cdc_call_mgmt_descriptor))
goto next_desc;
hdr->usb_cdc_call_mgmt_descriptor =
(struct usb_cdc_call_mgmt_descriptor *)buffer;
break;
case USB_CDC_DMM_TYPE:
if (elength < sizeof(struct usb_cdc_dmm_desc))
goto next_desc;
hdr->usb_cdc_dmm_desc =
(struct usb_cdc_dmm_desc *)buffer;
break;
case USB_CDC_MDLM_TYPE:
if (elength < sizeof(struct usb_cdc_mdlm_desc))
goto next_desc;
if (desc)
return -EINVAL;
desc = (struct usb_cdc_mdlm_desc *)buffer;
break;
case USB_CDC_MDLM_DETAIL_TYPE:
if (elength < sizeof(struct usb_cdc_mdlm_detail_desc))
goto next_desc;
if (detail)
return -EINVAL;
detail = (struct usb_cdc_mdlm_detail_desc *)buffer;
break;
case USB_CDC_NCM_TYPE:
if (elength < sizeof(struct usb_cdc_ncm_desc))
goto next_desc;
hdr->usb_cdc_ncm_desc = (struct usb_cdc_ncm_desc *)buffer;
break;
case USB_CDC_MBIM_TYPE:
if (elength < sizeof(struct usb_cdc_mbim_desc))
goto next_desc;
hdr->usb_cdc_mbim_desc = (struct usb_cdc_mbim_desc *)buffer;
break;
case USB_CDC_MBIM_EXTENDED_TYPE:
if (elength < sizeof(struct usb_cdc_mbim_extended_desc))
break;
hdr->usb_cdc_mbim_extended_desc =
(struct usb_cdc_mbim_extended_desc *)buffer;
break;
case CDC_PHONET_MAGIC_NUMBER:
hdr->phonet_magic_present = true;
break;
default:
/*
* there are LOTS more CDC descriptors that
* could legitimately be found here.
*/
dev_dbg(&intf->dev, "Ignoring descriptor: type %02x, length %ud\n",
buffer[2], elength);
goto next_desc;
}
cnt++;
next_desc:
buflen -= elength;
buffer += elength;
}
hdr->usb_cdc_union_desc = union_header;
hdr->usb_cdc_header_desc = header;
hdr->usb_cdc_mdlm_detail_desc = detail;
hdr->usb_cdc_mdlm_desc = desc;
hdr->usb_cdc_ether_desc = ether;
return cnt;
}
/**
* usb_get_string - gets a string descriptor
* @dev: the device whose string descriptor is being retrieved
* @langid: code for language chosen (from string descriptor zero)
* @index: the number of the descriptor
* @buf: where to put the string
* @size: how big is "buf"?
*
* Context: task context, might sleep.
*
* Retrieves a string, encoded using UTF-16LE (Unicode, 16 bits per character,
* in little-endian byte order).
* The usb_string() function will often be a convenient way to turn
* these strings into kernel-printable form.
*
* Strings may be referenced in device, configuration, interface, or other
* descriptors, and could also be used in vendor-specific ways.
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Return: The number of bytes received on success, or else the status code
* returned by the underlying usb_control_msg() call.
*/
static int usb_get_string(struct usb_device *dev, unsigned short langid,
unsigned char index, void *buf, int size)
{
int i;
int result;
if (size <= 0) /* No point in asking for no data */
return -EINVAL;
for (i = 0; i < 3; ++i) {
/* retry on length 0 or stall; some devices are flakey */
result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
(USB_DT_STRING << 8) + index, langid, buf, size,
USB_CTRL_GET_TIMEOUT);
if (result == 0 || result == -EPIPE)
continue;
if (result > 1 && ((u8 *) buf)[1] != USB_DT_STRING) {
result = -ENODATA;
continue;
}
break;
}
return result;
}
static void usb_try_string_workarounds(unsigned char *buf, int *length)
{
int newlength, oldlength = *length;
for (newlength = 2; newlength + 1 < oldlength; newlength += 2)
if (!isprint(buf[newlength]) || buf[newlength + 1])
break;
if (newlength > 2) {
buf[0] = newlength;
*length = newlength;
}
}
static int usb_string_sub(struct usb_device *dev, unsigned int langid,
unsigned int index, unsigned char *buf)
{
int rc;
/* Try to read the string descriptor by asking for the maximum
* possible number of bytes */
if (dev->quirks & USB_QUIRK_STRING_FETCH_255)
rc = -EIO;
else
rc = usb_get_string(dev, langid, index, buf, 255);
/* If that failed try to read the descriptor length, then
* ask for just that many bytes */
if (rc < 2) {
rc = usb_get_string(dev, langid, index, buf, 2);
if (rc == 2)
rc = usb_get_string(dev, langid, index, buf, buf[0]);
}
if (rc >= 2) {
if (!buf[0] && !buf[1])
usb_try_string_workarounds(buf, &rc);
/* There might be extra junk at the end of the descriptor */
if (buf[0] < rc)
rc = buf[0];
rc = rc - (rc & 1); /* force a multiple of two */
}
if (rc < 2)
rc = (rc < 0 ? rc : -EINVAL);
return rc;
}
static int usb_get_langid(struct usb_device *dev, unsigned char *tbuf)
{
int err;
if (dev->have_langid)
return 0;
if (dev->string_langid < 0)
return -EPIPE;
err = usb_string_sub(dev, 0, 0, tbuf);
/* If the string was reported but is malformed, default to english
* (0x0409) */
if (err == -ENODATA || (err > 0 && err < 4)) {
dev->string_langid = 0x0409;
dev->have_langid = 1;
dev_err(&dev->dev,
"language id specifier not provided by device, defaulting to English\n");
return 0;
}
/* In case of all other errors, we assume the device is not able to
* deal with strings at all. Set string_langid to -1 in order to
* prevent any string to be retrieved from the device */
if (err < 0) {
dev_info(&dev->dev, "string descriptor 0 read error: %d\n",
err);
dev->string_langid = -1;
return -EPIPE;
}
/* always use the first langid listed */
dev->string_langid = tbuf[2] | (tbuf[3] << 8);
dev->have_langid = 1;
dev_dbg(&dev->dev, "default language 0x%04x\n",
dev->string_langid);
return 0;
}
/**
* usb_string - returns UTF-8 version of a string descriptor
* @dev: the device whose string descriptor is being retrieved
* @index: the number of the descriptor
* @buf: where to put the string
* @size: how big is "buf"?
*
* Context: task context, might sleep.
*
* This converts the UTF-16LE encoded strings returned by devices, from
* usb_get_string_descriptor(), to null-terminated UTF-8 encoded ones
* that are more usable in most kernel contexts. Note that this function
* chooses strings in the first language supported by the device.
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Return: length of the string (>= 0) or usb_control_msg status (< 0).
*/
int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
{
unsigned char *tbuf;
int err;
if (dev->state == USB_STATE_SUSPENDED)
return -EHOSTUNREACH;
if (size <= 0 || !buf)
return -EINVAL;
buf[0] = 0;
if (index <= 0 || index >= 256)
return -EINVAL;
tbuf = kmalloc(256, GFP_NOIO);
if (!tbuf)
return -ENOMEM;
err = usb_get_langid(dev, tbuf);
if (err < 0)
goto errout;
err = usb_string_sub(dev, dev->string_langid, index, tbuf);
if (err < 0)
goto errout;
size--; /* leave room for trailing NULL char in output buffer */
err = utf16s_to_utf8s((wchar_t *) &tbuf[2], (err - 2) / 2,
UTF16_LITTLE_ENDIAN, buf, size);
buf[err] = 0;
if (tbuf[1] != USB_DT_STRING)
dev_dbg(&dev->dev,
"wrong descriptor type %02x for string %d (\"%s\")\n",
tbuf[1], index, buf);
errout:
kfree(tbuf);
return err;
}

View File

@ -0,0 +1,19 @@
/*
* \brief Dummy definitions of Linux Kernel functions
* \author Sebastian Sumpf
* \date 2023-07-11
*/
/*
* Copyright (C) 2023 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <lx_emul/debug.h>
#include <linux/init.h>
#include <linux/sched/debug.h>
#include <linux/usb.h>
struct usb_hub;

View File

@ -0,0 +1,353 @@
/*
* \brief Post kernel activity
* \author Christian Helmuth
* \author Sebastian Sumpf
* \date 2023-06-29
*/
/*
* Copyright (C) 2023 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <linux/kthread.h>
#include <linux/netdevice.h>
#include <linux/sched/task.h>
#include <linux/usb.h>
#include <lx_user/init.h>
#include <genode_c_api/uplink.h>
#include <genode_c_api/mac_address_reporter.h>
#include <usb_net.h>
struct task_struct *lx_user_new_usb_task(int (*func)(void*), void *args)
{
int pid = kernel_thread(func, args, CLONE_FS | CLONE_FILES);
return find_task_by_pid_ns(pid, NULL);
}
static struct genode_uplink *dev_genode_uplink(struct net_device *dev)
{
return (struct genode_uplink *)dev->ifalias;
}
struct genode_uplink_rx_context
{
struct net_device *dev;
};
struct genode_uplink_tx_packet_context
{
struct sk_buff *skb;
};
static unsigned long uplink_tx_packet_content(struct genode_uplink_tx_packet_context *ctx,
char *dst, unsigned long dst_len)
{
struct sk_buff * const skb = ctx->skb;
skb_push(skb, ETH_HLEN);
if (dst_len < skb->len) {
printk("uplink_tx_packet_content: packet exceeds uplink packet size\n");
memset(dst, 0, dst_len);
return 0;
}
skb_copy_from_linear_data(skb, dst, skb->len);
/* clear unused part of the destination buffer */
memset(dst + skb->len, 0, dst_len - skb->len);
return skb->len;
}
static rx_handler_result_t handle_rx(struct sk_buff **pskb)
{
struct sk_buff *skb = *pskb;
struct net_device *dev = skb->dev;
struct genode_uplink_tx_packet_context ctx = { .skb = skb };
/* if uplink still exists */
if (dev->ifalias) {
bool progress = genode_uplink_tx_packet(dev_genode_uplink(dev),
uplink_tx_packet_content,
&ctx);
if (!progress)
printk("handle_rx: uplink saturated, dropping packet\n");
}
kfree_skb(skb);
return RX_HANDLER_CONSUMED;
}
/**
* Create Genode uplink for given net device
*
* The uplink is registered at the dev->ifalias pointer.
*/
static void handle_create_uplink(struct net_device *dev)
{
struct genode_uplink_args args;
if (dev_genode_uplink(dev))
return;
if (!netif_carrier_ok(dev))
return;
printk("create uplink for net device %s\n", &dev->name[0]);
memset(&args, 0, sizeof(args));
if (dev->addr_len != sizeof(args.mac_address)) {
printk("error: net device has unexpected addr_len %u\n", dev->addr_len);
return;
}
{
unsigned i;
for (i = 0; i < dev->addr_len; i++)
args.mac_address[i] = dev->dev_addr[i];
}
args.label = &dev->name[0];
dev->ifalias = (struct dev_ifalias *)genode_uplink_create(&args);
}
static void handle_destroy_uplink(struct net_device *dev)
{
struct genode_uplink *uplink = dev_genode_uplink(dev);
if (!uplink)
return;
if (netif_carrier_ok(dev))
return;
printk("destroy uplink for net device %s\n", &dev->name[0]);
genode_uplink_destroy(uplink);
dev->ifalias = NULL;
}
static genode_uplink_rx_result_t uplink_rx_one_packet(struct genode_uplink_rx_context *ctx,
char const *ptr, unsigned long len)
{
struct sk_buff *skb = alloc_skb(len, GFP_KERNEL);
if (!skb) {
printk("alloc_skb failed\n");
return GENODE_UPLINK_RX_RETRY;
}
skb_copy_to_linear_data(skb, ptr, len);
skb_put(skb, len);
skb->dev = ctx->dev;
if (dev_queue_xmit(skb) < 0) {
printk("lx_user: failed to xmit packet\n");
return GENODE_UPLINK_RX_REJECTED;
}
return GENODE_UPLINK_RX_ACCEPTED;
}
static int user_task_function(void *arg)
{
for (;;) {
struct net_device *dev;
for_each_netdev(&init_net, dev) {
struct genode_mac_address dev_addr;
/* enable link sensing, repeated calls are handled by testing IFF_UP */
dev_open(dev, 0);
memcpy(dev_addr.addr, dev->dev_addr, sizeof(dev_addr));
genode_mac_address_register(dev->name, dev_addr);
/* install rx handler once */
if (!netdev_is_rx_handler_busy(dev))
netdev_rx_handler_register(dev, handle_rx, NULL);
/* respond to cable plug/unplug */
handle_create_uplink(dev);
handle_destroy_uplink(dev);
/* transmit packets received from the uplink session */
if (netif_carrier_ok(dev)) {
struct genode_uplink_rx_context ctx = { .dev = dev };
while (genode_uplink_rx(dev_genode_uplink(dev),
uplink_rx_one_packet,
&ctx));
}
};
/* block until lx_emul_task_unblock */
lx_emul_task_schedule(true);
}
return 0;
}
struct task_struct *user_task_struct_ptr; /* used by 'Device' for lx_emul_task_unblock */
void lx_user_init(void)
{
pid_t pid;
lx_user_main_task(NULL);
pid = kernel_thread(user_task_function, NULL, CLONE_FS | CLONE_FILES);
user_task_struct_ptr = find_task_by_pid_ns(pid, NULL);
}
#include <linux/rtnetlink.h>
/*
* Called whenever the link state changes
*/
bool force_uplink_destroy = false;
void rtmsg_ifinfo(int type, struct net_device * dev, unsigned int change, gfp_t flags)
{
/* trigger handle_create_uplink / handle_destroy_uplink */
if (user_task_struct_ptr)
lx_emul_task_unblock(user_task_struct_ptr);
if (force_uplink_destroy) {
struct genode_uplink *uplink = dev_genode_uplink(dev);
printk("force destroy uplink for net device %s\n", &dev->name[0]);
genode_uplink_destroy(uplink);
}
}
/*
* Handle WDM device class for MBIM-modems
*/
struct usb_class_driver *wdm_driver;
struct file wdm_file;
enum { WDM_MINOR = 8 };
int usb_register_dev(struct usb_interface *intf, struct usb_class_driver *class_driver)
{
if (strncmp(class_driver->name, "cdc-wdm", 7) == 0) {
wdm_driver = class_driver;
intf->usb_dev = &intf->dev;
intf->minor = WDM_MINOR;
lx_wdm_create_root();
return 0;
}
printk("%s:%d error: no device class for driver %s\n", __func__, __LINE__,
class_driver->name);
return -1;
}
void usb_deregister_dev(struct usb_interface * intf,struct usb_class_driver * class_driver)
{
lx_emul_trace(__func__);
}
int lx_wdm_read(void *args)
{
ssize_t length;
struct lx_wdm *wdm_data = (struct lx_wdm *)args;
lx_emul_task_schedule(true);
if (!wdm_driver) {
printk("%s:%d error: no WDM class driver\n", __func__, __LINE__);
return -1;
}
while (wdm_data->active) {
length = wdm_driver->fops->read(&wdm_file, wdm_data->buffer, 0x1000, NULL);
if (length > 0) {
*wdm_data->data_avail = length;
lx_wdm_signal_data_avail(wdm_data->handle);
}
lx_emul_task_schedule(true);
}
return 0;
}
int lx_wdm_write(void *args)
{
ssize_t length;
struct lx_wdm *wdm_data = (struct lx_wdm *)args;
lx_emul_task_schedule(true);
if (!wdm_driver) {
printk("%s:%d error: no WDM class driver\n", __func__, __LINE__);
return -1;
}
while (wdm_data->active) {
length = wdm_driver->fops->write(&wdm_file, wdm_data->buffer,
*wdm_data->data_avail, NULL);
if (length < 0) {
printk("WDM write error: %ld", (long)length);
}
lx_wdm_schedule_read(wdm_data->handle);
lx_emul_task_schedule(true);
}
return 0;
}
int lx_wdm_device(void *args)
{
int err = -1;
/* minor number for inode is 1 (see: ubs_register_dev above) */
struct inode inode;
inode.i_rdev = MKDEV(USB_DEVICE_MAJOR, WDM_MINOR);
if (!wdm_driver) {
printk("%s:%d error: no WDM class driver\n", __func__, __LINE__);
return err;
}
if ((err = wdm_driver->fops->open(&inode, &wdm_file))) {
printk("Could not open WDM device: %d", err);
return err;
}
lx_emul_task_schedule(true);
//XXX: close
return 0;
}

View File

@ -0,0 +1,234 @@
/*
* \brief C++ initialization, session, and client handling
* \author Sebastian Sumpf
* \date 2023-07-11
*/
/*
* Copyright (C) 2023 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <base/attached_rom_dataspace.h>
#include <base/component.h>
#include <base/env.h>
#include <genode_c_api/uplink.h>
#include <genode_c_api/mac_address_reporter.h>
#include <nic_session/nic_session.h>
#include <lx_kit/env.h>
#include <lx_emul/task.h>
#include <lx_emul/init.h>
/* C-interface */
#include <usb_net.h>
using namespace Genode;
extern task_struct *user_task_struct_ptr;
extern bool force_uplink_destroy;
extern bool use_mac_address;
extern unsigned char mac_address[6];
struct Device
{
Env &env;
Attached_rom_dataspace config_rom { env, "config" };
unsigned long usb_config { 0 };
/*
* Dedicated allocator per device to notice dangling
* allocations on device destruction.
*/
Allocator_avl alloc { &Lx_kit::env().heap };
task_struct *state_task { lx_user_new_usb_task(state_task_entry, this) };
task_struct *urb_task { lx_user_new_usb_task(urb_task_entry, this) };
Signal_handler<Device> task_state_handler { env.ep(), *this, &Device::handle_task_state };
Signal_handler<Device> urb_handler { env.ep(), *this, &Device::handle_urb };
genode_usb_client_handle_t usb_handle {
genode_usb_client_create(genode_env_ptr(env),
genode_allocator_ptr(Lx_kit::env().heap),
genode_range_allocator_ptr(alloc),
"",
genode_signal_handler_ptr(task_state_handler)) };
Signal_handler<Device> nic_handler { env.ep(), *this, &Device::handle_nic };
Signal_handler<Device> config_handler { env.ep(), *this, &Device::handle_config };
bool registered { false };
void *lx_device_handle { nullptr };
Device(Env &env)
:
env(env)
{
genode_usb_client_sigh_ack_avail(usb_handle,
genode_signal_handler_ptr(urb_handler));
genode_mac_address_reporter_init(env, Lx_kit::env().heap);
genode_uplink_init(genode_env_ptr(env),
genode_allocator_ptr(Lx_kit::env().heap),
genode_signal_handler_ptr(nic_handler));
config_rom.sigh(config_handler);
handle_config();
}
/* non-copyable */
Device(const Device&) = delete;
Device & operator=(const Device&) = delete;
void register_device()
{
registered = true;
lx_device_handle = lx_emul_usb_client_register_device(usb_handle, "usb_nic");
if (!lx_device_handle) {
registered = false;
return;
}
if (usb_config != 0)
lx_emul_usb_client_set_configuration(usb_handle, lx_device_handle, usb_config);
}
void unregister_device()
{
force_uplink_destroy = true;
lx_emul_usb_client_unregister_device(usb_handle, lx_device_handle);
registered = false;
force_uplink_destroy = false;
}
void handle_task_state()
{
lx_emul_task_unblock(state_task);
Lx_kit::env().scheduler.execute();
}
void handle_urb()
{
lx_emul_task_unblock(urb_task);
Lx_kit::env().scheduler.execute();
genode_uplink_notify_peers();
}
void handle_nic()
{
if (!user_task_struct_ptr)
return;
lx_emul_task_unblock(user_task_struct_ptr);
Lx_kit::env().scheduler.execute();
}
void handle_config()
{
config_rom.update();
genode_mac_address_reporter_config(config_rom.xml());
/* read USB configuration setting */
unsigned long config = config_rom.xml().attribute_value("configuration", 0ul);
if (registered && config != 0 && config != usb_config)
lx_emul_usb_client_set_configuration(usb_handle, lx_device_handle, config);
usb_config = config;
/* retrieve possible MAC */
Nic::Mac_address mac;
try {
Xml_node::Attribute mac_node = config_rom.xml().attribute("mac");
mac_node.value(mac);
mac.copy(mac_address);
use_mac_address = true;
log("Trying to use configured mac: ", mac);
} catch (...) {
use_mac_address = false;
}
}
/**********
** Task **
**********/
static int state_task_entry(void *arg)
{
Device &device = *reinterpret_cast<Device *>(arg);
while (true) {
if (genode_usb_client_plugged(device.usb_handle) && !device.registered)
device.register_device();
if (!genode_usb_client_plugged(device.usb_handle) && device.registered)
device.unregister_device();
lx_emul_task_schedule(true);
}
return 0;
}
static int urb_task_entry(void *arg)
{
Device &device = *reinterpret_cast<Device *>(arg);
while (true) {
if (device.registered) {
genode_usb_client_execute_completions(device.usb_handle);
}
lx_emul_task_schedule(true);
}
return 0;
}
};
struct Main
{
Env &env;
Signal_handler<Main> signal_handler { env.ep(), *this, &Main::handle_signal };
Main(Env &env) : env(env) { }
void handle_signal()
{
Lx_kit::env().scheduler.execute();
}
};
void Component::construct(Env & env)
{
static Main main { env };
Lx_kit::initialize(env, main.signal_handler);
env.exec_static_constructors();
lx_emul_start_kernel(nullptr);
}
/**********
** Task **
**********/
int lx_user_main_task(void *)
{
/* one device only */
static Device dev(Lx_kit::env().env);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,87 @@
arch/arm/lib/clearbit.S
arch/arm/lib/div64.S
arch/arm/lib/findbit.S
arch/arm/lib/setbit.S
arch/arm/lib/strchr.S
arch/arm/lib/testclearbit.S
arch/arm/lib/testsetbit.S
drivers/base/bus.c
drivers/base/core.c
drivers/base/class.c
drivers/base/devres.c
drivers/base/driver.c
drivers/base/dd.c
drivers/base/property.c
drivers/net/mii.c
drivers/net/usb/asix_common.c
drivers/net/usb/asix_devices.c
drivers/net/usb/asix.h
drivers/net/usb/ax88172a.c
drivers/net/usb/ax88179_178a.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/cdc_mbim.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/usbnet.c
drivers/usb/class/cdc-wdm.c
drivers/usb/core/config.c
drivers/usb/core/driver.c
drivers/usb/core/generic.c
drivers/usb/core/hub.c
drivers/usb/core/quirks.c
drivers/usb/core/usb.c
fs/nls/nls_base.c
kernel/kthread.c
kernel/locking/mutex.c
kernel/locking/osq_lock.c
kernel/locking/rwsem.c
kernel/notifier.c
kernel/sched/build_utility.c
kernel/smpboot.c
kernel/softirq.c
kernel/time/clockevents.c
kernel/time/clocksource.c
kernel/time/hrtimer.c
kernel/time/jiffies.c
kernel/time/ntp.c
kernel/time/tick-broadcast.c
kernel/time/tick-broadcast-hrtimer.c
kernel/time/tick-common.c
kernel/time/tick-oneshot.c
kernel/time/tick-sched.c
kernel/time/time.c
kernel/time/timeconv.c
kernel/time/timecounter.c
kernel/time/timekeeping.c
kernel/time/timer.c
kernel/time/timer_list.c
kernel/workqueue.c
lib/bitmap.c
lib/crc16.c
lib/crc32.c
lib/ctype.c
lib/find_bit.c
lib/hexdump.c
lib/hweight.c
lib/idr.c
lib/kasprintf.c
lib/klist.c
lib/kobject.c
lib/kstrtox.c
lib/radix-tree.c
lib/rhashtable.c
lib/rbtree.c
lib/xarray.c
lib/siphash.c
lib/string.c
lib/string_helpers.c
lib/timerqueue.c
lib/vsprintf.c
mm/util.c
net/core/dev.c
net/core/dev_addr_lists.c
net/core/link_watch.c
net/core/skbuff.c
net/core/xdp.c
net/ethernet/eth.c
net/ethtool/common.c
net/sched/sch_generic.c

View File

@ -0,0 +1,3 @@
REQUIRES := arm
include $(PRG_DIR)/../../target.inc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,86 @@
arch/arm64/lib/memcmp.S
arch/arm64/lib/strchr.S
arch/arm64/lib/strcmp.S
arch/arm64/lib/strlen.S
arch/arm64/lib/strncmp.S
arch/arm64/lib/strnlen.S
drivers/base/bus.c
drivers/base/core.c
drivers/base/class.c
drivers/base/devres.c
drivers/base/driver.c
drivers/base/dd.c
drivers/base/property.c
drivers/net/mii.c
drivers/net/usb/asix_common.c
drivers/net/usb/asix_devices.c
drivers/net/usb/asix.h
drivers/net/usb/ax88172a.c
drivers/net/usb/ax88179_178a.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/cdc_mbim.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/usbnet.c
drivers/usb/class/cdc-wdm.c
drivers/usb/core/config.c
drivers/usb/core/driver.c
drivers/usb/core/generic.c
drivers/usb/core/hub.c
drivers/usb/core/quirks.c
drivers/usb/core/usb.c
fs/nls/nls_base.c
kernel/kthread.c
kernel/locking/mutex.c
kernel/locking/osq_lock.c
kernel/locking/rwsem.c
kernel/notifier.c
kernel/sched/build_utility.c
kernel/smpboot.c
kernel/softirq.c
kernel/time/clockevents.c
kernel/time/clocksource.c
kernel/time/hrtimer.c
kernel/time/jiffies.c
kernel/time/ntp.c
kernel/time/tick-broadcast.c
kernel/time/tick-broadcast-hrtimer.c
kernel/time/tick-common.c
kernel/time/tick-oneshot.c
kernel/time/tick-sched.c
kernel/time/time.c
kernel/time/timeconv.c
kernel/time/timecounter.c
kernel/time/timekeeping.c
kernel/time/timer.c
kernel/time/timer_list.c
kernel/workqueue.c
lib/bitmap.c
lib/crc16.c
lib/crc32.c
lib/ctype.c
lib/find_bit.c
lib/hexdump.c
lib/hweight.c
lib/idr.c
lib/kasprintf.c
lib/klist.c
lib/kobject.c
lib/kstrtox.c
lib/radix-tree.c
lib/rhashtable.c
lib/rbtree.c
lib/xarray.c
lib/siphash.c
lib/string.c
lib/string_helpers.c
lib/timerqueue.c
lib/vsprintf.c
mm/util.c
net/core/dev.c
net/core/dev_addr_lists.c
net/core/link_watch.c
net/core/skbuff.c
net/core/xdp.c
net/ethernet/eth.c
net/ethtool/common.c
net/sched/sch_generic.c

View File

@ -0,0 +1,5 @@
REQUIRES := arm_64
SRC_C += lx_emul/shadow/arch/arm64/kernel/smp.c
include $(PRG_DIR)/../../target.inc

View File

@ -0,0 +1,948 @@
/*
* \brief Dummy definitions of Linux Kernel functions
* \author Automatically generated file - do no edit
* \date 2023-08-18
*/
#include <lx_emul.h>
#include <linux/gfp.h>
struct page * __alloc_pages(gfp_t gfp,unsigned int order,int preferred_nid,nodemask_t * nodemask)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/cpumask.h>
struct cpumask __cpu_active_mask;
#include <linux/phy.h>
int __devm_mdiobus_register(struct device * dev,struct mii_bus * bus,struct module * owner)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/mm.h>
void __folio_put(struct folio * folio)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/ipv6.h>
int __ipv6_addr_type(const struct in6_addr * addr)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
int __mdiobus_register(struct mii_bus * bus,struct module * owner)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/printk.h>
int __printk_ratelimit(const char * func)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/printk.h>
void __printk_safe_enter(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/printk.h>
void __printk_safe_exit(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sched/task.h>
void __put_task_struct(struct task_struct * tsk)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/skbuff.h>
void __skb_get_hash(struct sk_buff * skb)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/vmalloc.h>
void * __vmalloc_node_range(unsigned long size,unsigned long align,unsigned long start,unsigned long end,gfp_t gfp_mask,pgprot_t prot,unsigned long vm_flags,int node,const void * caller)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/printk.h>
int _printk_deferred(const char * fmt,...)
{
lx_emul_trace_and_stop(__func__);
}
extern void ack_bad_irq(unsigned int irq);
void ack_bad_irq(unsigned int irq)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/kobject.h>
int add_uevent_var(struct kobj_uevent_env * env,const char * format,...)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/async.h>
async_cookie_t async_schedule_node(async_func_t func,void * data,int node)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/async.h>
void async_synchronize_full(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/filter.h>
void bpf_warn_invalid_xdp_action(struct net_device * dev,struct bpf_prog * prog,u32 act)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/bitrev.h>
u8 const byte_rev_table[256] = {};
#include <linux/context_tracking_irq.h>
noinstr void ct_irq_enter(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/context_tracking_irq.h>
noinstr void ct_irq_exit(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
struct mii_bus * devm_mdiobus_alloc_size(struct device * dev,int sizeof_priv)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/math64.h>
u64 div64_u64(u64 dividend,u64 divisor)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/math64.h>
u64 div64_u64_rem(u64 dividend,u64 divisor,u64 * remainder)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/math64.h>
s64 div_s64_rem(s64 dividend,s32 divisor,s32 * remainder)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netlink.h>
void do_trace_netlink_extack(const char * msg)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/dst.h>
void dst_release(struct dst_entry * dst)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/printk.h>
asmlinkage __visible void dump_stack(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/ethtool.h>
void ethtool_convert_legacy_u32_to_link_mode(unsigned long * dst,u32 legacy_u32)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/ethtool.h>
bool ethtool_convert_link_mode_to_legacy_u32(u32 * legacy_u32,const unsigned long * src)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/ethtool.h>
u32 ethtool_op_get_link(struct net_device * dev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/ethtool.h>
int ethtool_op_get_ts_info(struct net_device * dev,struct ethtool_ts_info * info)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/capability.h>
bool file_ns_capable(const struct file * file,struct user_namespace * ns,int cap)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/rcuwait.h>
void finish_rcuwait(struct rcuwait * w)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
int genphy_resume(struct phy_device * phydev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/gfp.h>
bool gfp_pfmemalloc_allowed(gfp_t gfp_mask)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netdevice.h>
struct packet_offload * gro_find_complete_by_type(__be16 type)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netdevice.h>
struct packet_offload * gro_find_receive_by_type(__be16 type)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/uuid.h>
const u8 guid_index[16] = {};
#include <linux/mm.h>
void * high_memory;
#include <net/addrconf.h>
void in6_dev_finish_destroy(struct inet6_dev * idev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sched.h>
unsigned long init_stack[THREAD_SIZE / sizeof(unsigned long)] = {};
#include <linux/utsname.h>
struct user_namespace init_user_ns;
#include <linux/init.h>
bool initcall_debug;
#include <linux/sched.h>
void __sched io_schedule(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sched.h>
void io_schedule_finish(int token)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sched.h>
int io_schedule_prepare(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sched.h>
long __sched io_schedule_timeout(long timeout)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/interrupt.h>
int irq_can_set_affinity(unsigned int irq)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/interrupt.h>
int irq_set_affinity(unsigned int irq,const struct cpumask * cpumask)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/irq_work.h>
void irq_work_tick(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/slab.h>
int kmem_cache_alloc_bulk(struct kmem_cache * s,gfp_t flags,size_t nr,void ** p)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/slab.h>
void * kmem_cache_alloc_lru(struct kmem_cache * cachep,struct list_lru * lru,gfp_t flags)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/slab.h>
void kmem_cache_free_bulk(struct kmem_cache * s,size_t nr,void ** p)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/kobject.h>
int kobject_synth_uevent(struct kobject * kobj,const char * buf,size_t count)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/kobject.h>
int kobject_uevent_env(struct kobject * kobj,enum kobject_action action,char * envp_ext[])
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netdevice.h>
struct pernet_operations __net_initdata loopback_net_ops;
#include <linux/phy.h>
struct mii_bus * mdiobus_alloc_size(size_t size)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
void mdiobus_free(struct mii_bus * bus)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/mdio.h>
struct phy_device * mdiobus_get_phy(struct mii_bus * bus,int addr)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
void mdiobus_unregister(struct mii_bus * bus)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/preempt.h>
void migrate_disable(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/preempt.h>
void migrate_enable(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/sch_generic.h>
struct Qdisc_ops mq_qdisc_ops;
#include <linux/netdevice.h>
void napi_gro_flush(struct napi_struct * napi,bool flush_old)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/net.h>
int net_ratelimit(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/selftests.h>
void net_selftest(struct net_device * ndev,struct ethtool_test * etest,u64 * buf)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/selftests.h>
int net_selftest_get_count(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/selftests.h>
void net_selftest_get_strings(u8 * data)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/netlink.h>
int nla_put(struct sk_buff * skb,int attrtype,int attrlen,const void * data)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/fs.h>
loff_t noop_llseek(struct file * file,loff_t offset,int whence)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/moduleparam.h>
int param_set_copystring(const char * val,const struct kernel_param * kp)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
void phy_attached_info(struct phy_device * phydev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
struct phy_device * phy_connect(struct net_device * dev,const char * bus_id,void (* handler)(struct net_device *),phy_interface_t interface)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
void phy_disconnect(struct phy_device * phydev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
int phy_do_ioctl_running(struct net_device * dev,struct ifreq * ifr,int cmd)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
int phy_ethtool_get_link_ksettings(struct net_device * ndev,struct ethtool_link_ksettings * cmd)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
int phy_ethtool_nway_reset(struct net_device * ndev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
int phy_ethtool_set_link_ksettings(struct net_device * ndev,const struct ethtool_link_ksettings * cmd)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
void phy_print_status(struct phy_device * phydev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
void phy_start(struct phy_device * phydev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
void phy_stop(struct phy_device * phydev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
int phy_suspend(struct phy_device * phydev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phylink.h>
int phylink_connect_phy(struct phylink * pl,struct phy_device * phy)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phylink.h>
struct phylink * phylink_create(struct phylink_config * config,struct fwnode_handle * fwnode,phy_interface_t iface,const struct phylink_mac_ops * mac_ops)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phylink.h>
void phylink_destroy(struct phylink * pl)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phylink.h>
void phylink_disconnect_phy(struct phylink * pl)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phylink.h>
void phylink_ethtool_get_pauseparam(struct phylink * pl,struct ethtool_pauseparam * pause)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phylink.h>
int phylink_ethtool_set_pauseparam(struct phylink * pl,struct ethtool_pauseparam * pause)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phylink.h>
void phylink_generic_validate(struct phylink_config * config,unsigned long * supported,struct phylink_link_state * state)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phylink.h>
void phylink_resume(struct phylink * pl)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phylink.h>
void phylink_start(struct phylink * pl)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phylink.h>
void phylink_stop(struct phylink * pl)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phylink.h>
void phylink_suspend(struct phylink * pl,bool mac_wol)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/refcount.h>
void refcount_warn_saturate(refcount_t * r,enum refcount_saturation_type t)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/rtnetlink.h>
void rtmsg_ifinfo_send(struct sk_buff * skb,struct net_device * dev,gfp_t flags)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/scatterlist.h>
void sg_init_table(struct scatterlist * sgl,unsigned int nents)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/sock.h>
void sk_error_report(struct sock * sk)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netdevice.h>
struct sk_buff * skb_mac_gso_segment(struct sk_buff * skb,netdev_features_t features)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/smp.h>
void smp_call_function_many(const struct cpumask * mask,smp_call_func_t func,void * info,bool wait)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/smp.h>
int smp_call_function_single(int cpu,smp_call_func_t func,void * info,int wait)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/sock.h>
void sock_edemux(struct sk_buff * skb)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/jump_label.h>
bool static_key_initialized;
#include <net/sock.h>
int sysctl_tstamp_allow_data;
#include <linux/tcp.h>
struct sk_buff * tcp_get_timestamping_opt_stats(const struct sock * sk,const struct sk_buff * orig_skb,const struct sk_buff * ack_skb)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/usb.h>
int usb_clear_halt(struct usb_device * dev,int pipe)
{
lx_emul_trace_and_stop(__func__);
}
extern void usb_devio_cleanup(void);
void usb_devio_cleanup(void)
{
lx_emul_trace_and_stop(__func__);
}
extern void usb_disable_endpoint(struct usb_device * dev,unsigned int epaddr,bool reset_hardware);
void usb_disable_endpoint(struct usb_device * dev,unsigned int epaddr,bool reset_hardware)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/usb.h>
int usb_free_streams(struct usb_interface * interface,struct usb_host_endpoint ** eps,unsigned int num_eps,gfp_t mem_flags)
{
lx_emul_trace_and_stop(__func__);
}
extern int usb_get_device_descriptor(struct usb_device * dev,unsigned int size);
int usb_get_device_descriptor(struct usb_device * dev,unsigned int size)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/usb.h>
int usb_get_status(struct usb_device * dev,int recip,int type,int target,void * data)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/usb/hcd.h>
int usb_hcd_alloc_bandwidth(struct usb_device * udev,struct usb_host_config * new_config,struct usb_host_interface * cur_alt,struct usb_host_interface * new_alt)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/usb/hcd.h>
int usb_hcd_find_raw_port_number(struct usb_hcd * hcd,int port1)
{
lx_emul_trace_and_stop(__func__);
}
extern int usb_hub_create_port_device(struct usb_hub * hub,int port1);
int usb_hub_create_port_device(struct usb_hub * hub,int port1)
{
lx_emul_trace_and_stop(__func__);
}
extern void usb_hub_remove_port_device(struct usb_hub * hub,int port1);
void usb_hub_remove_port_device(struct usb_hub * hub,int port1)
{
lx_emul_trace_and_stop(__func__);
}
extern void usb_major_cleanup(void);
void usb_major_cleanup(void)
{
lx_emul_trace_and_stop(__func__);
}
extern int usb_set_isoch_delay(struct usb_device * dev);
int usb_set_isoch_delay(struct usb_device * dev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/usb/ch9.h>
const char * usb_speed_string(enum usb_device_speed speed)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/usb.h>
void usb_unpoison_urb(struct urb * urb)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/uuid.h>
const u8 uuid_index[16] = {};
#include <linux/sched/wake_q.h>
void wake_q_add_safe(struct wake_q_head * head,struct task_struct * task)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/filter.h>
int xdp_do_generic_redirect(struct net_device * dev,struct sk_buff * skb,struct xdp_buff * xdp,struct bpf_prog * xdp_prog)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/filter.h>
u32 xdp_master_redirect(struct xdp_buff * xdp)
{
lx_emul_trace_and_stop(__func__);
}

View File

@ -0,0 +1,79 @@
arch/x86/lib/hweight.S
drivers/base/bus.c
drivers/base/core.c
drivers/base/class.c
drivers/base/devres.c
drivers/base/driver.c
drivers/base/dd.c
drivers/base/property.c
drivers/net/mii.c
drivers/net/usb/asix_common.c
drivers/net/usb/asix_devices.c
drivers/net/usb/asix.h
drivers/net/usb/ax88172a.c
drivers/net/usb/ax88179_178a.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/cdc_mbim.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/usbnet.c
drivers/usb/class/cdc-wdm.c
drivers/usb/core/config.c
drivers/usb/core/driver.c
drivers/usb/core/generic.c
drivers/usb/core/hub.c
drivers/usb/core/quirks.c
drivers/usb/core/usb.c
fs/nls/nls_base.c
kernel/kthread.c
kernel/locking/mutex.c
kernel/locking/osq_lock.c
kernel/locking/rwsem.c
kernel/notifier.c
kernel/sched/build_utility.c
kernel/smpboot.c
kernel/softirq.c
kernel/time/clockevents.c
kernel/time/clocksource.c
kernel/time/hrtimer.c
kernel/time/jiffies.c
kernel/time/ntp.c
kernel/time/tick-broadcast.c
kernel/time/tick-common.c
kernel/time/tick-oneshot.c
kernel/time/tick-sched.c
kernel/time/time.c
kernel/time/timeconv.c
kernel/time/timecounter.c
kernel/time/timekeeping.c
kernel/time/timer.c
kernel/time/timer_list.c
kernel/workqueue.c
lib/bitmap.c
lib/crc16.c
lib/crc32.c
lib/ctype.c
lib/find_bit.c
lib/hexdump.c
lib/idr.c
lib/kasprintf.c
lib/klist.c
lib/kobject.c
lib/kstrtox.c
lib/radix-tree.c
lib/rhashtable.c
lib/rbtree.c
lib/xarray.c
lib/siphash.c
lib/string.c
lib/string_helpers.c
lib/timerqueue.c
lib/vsprintf.c
mm/util.c
net/core/dev.c
net/core/dev_addr_lists.c
net/core/link_watch.c
net/core/skbuff.c
net/core/xdp.c
net/ethernet/eth.c
net/ethtool/common.c
net/sched/sch_generic.c

View File

@ -0,0 +1,3 @@
REQUIRES := x86_32
include $(PRG_DIR)/../../target.inc

View File

@ -0,0 +1,921 @@
/*
* \brief Dummy definitions of Linux Kernel functions
* \author Automatically generated file - do no edit
* \date 2023-07-17
*/
#include <lx_emul.h>
#include <linux/gfp.h>
struct page * __alloc_pages(gfp_t gfp,unsigned int order,int preferred_nid,nodemask_t * nodemask)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/cpumask.h>
struct cpumask __cpu_active_mask;
#include <linux/phy.h>
int __devm_mdiobus_register(struct device * dev,struct mii_bus * bus,struct module * owner)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/mm.h>
void __folio_put(struct folio * folio)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/ipv6.h>
int __ipv6_addr_type(const struct in6_addr * addr)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
int __mdiobus_register(struct mii_bus * bus,struct module * owner)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/printk.h>
int __printk_ratelimit(const char * func)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/printk.h>
void __printk_safe_enter(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/printk.h>
void __printk_safe_exit(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sched/task.h>
void __put_task_struct(struct task_struct * tsk)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/skbuff.h>
void __skb_get_hash(struct sk_buff * skb)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/vmalloc.h>
void * __vmalloc_node_range(unsigned long size,unsigned long align,unsigned long start,unsigned long end,gfp_t gfp_mask,pgprot_t prot,unsigned long vm_flags,int node,const void * caller)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/printk.h>
int _printk_deferred(const char * fmt,...)
{
lx_emul_trace_and_stop(__func__);
}
extern void ack_bad_irq(unsigned int irq);
void ack_bad_irq(unsigned int irq)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/kobject.h>
int add_uevent_var(struct kobj_uevent_env * env,const char * format,...)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/async.h>
async_cookie_t async_schedule_node(async_func_t func,void * data,int node)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/async.h>
void async_synchronize_full(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/filter.h>
void bpf_warn_invalid_xdp_action(struct net_device * dev,struct bpf_prog * prog,u32 act)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/bitrev.h>
u8 const byte_rev_table[256] = {};
#include <linux/context_tracking_irq.h>
noinstr void ct_irq_enter(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/context_tracking_irq.h>
noinstr void ct_irq_exit(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
struct mii_bus * devm_mdiobus_alloc_size(struct device * dev,int sizeof_priv)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netlink.h>
void do_trace_netlink_extack(const char * msg)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/dst.h>
void dst_release(struct dst_entry * dst)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/printk.h>
asmlinkage __visible void dump_stack(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/ethtool.h>
void ethtool_convert_legacy_u32_to_link_mode(unsigned long * dst,u32 legacy_u32)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/ethtool.h>
bool ethtool_convert_link_mode_to_legacy_u32(u32 * legacy_u32,const unsigned long * src)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/ethtool.h>
u32 ethtool_op_get_link(struct net_device * dev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/ethtool.h>
int ethtool_op_get_ts_info(struct net_device * dev,struct ethtool_ts_info * info)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/capability.h>
bool file_ns_capable(const struct file * file,struct user_namespace * ns,int cap)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/rcuwait.h>
void finish_rcuwait(struct rcuwait * w)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
int genphy_resume(struct phy_device * phydev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/gfp.h>
bool gfp_pfmemalloc_allowed(gfp_t gfp_mask)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netdevice.h>
struct packet_offload * gro_find_complete_by_type(__be16 type)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netdevice.h>
struct packet_offload * gro_find_receive_by_type(__be16 type)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/uuid.h>
const u8 guid_index[16] = {};
#include <net/addrconf.h>
void in6_dev_finish_destroy(struct inet6_dev * idev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/utsname.h>
struct user_namespace init_user_ns;
#include <linux/init.h>
bool initcall_debug;
#include <linux/sched.h>
void __sched io_schedule(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sched.h>
void io_schedule_finish(int token)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sched.h>
int io_schedule_prepare(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sched.h>
long __sched io_schedule_timeout(long timeout)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/swiotlb.h>
struct io_tlb_mem io_tlb_default_mem;
#include <linux/interrupt.h>
int irq_can_set_affinity(unsigned int irq)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/interrupt.h>
int irq_set_affinity(unsigned int irq,const struct cpumask * cpumask)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/irq_work.h>
void irq_work_tick(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/slab.h>
int kmem_cache_alloc_bulk(struct kmem_cache * s,gfp_t flags,size_t nr,void ** p)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/slab.h>
void * kmem_cache_alloc_lru(struct kmem_cache * cachep,struct list_lru * lru,gfp_t flags)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/slab.h>
void kmem_cache_free_bulk(struct kmem_cache * s,size_t nr,void ** p)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/kobject.h>
int kobject_synth_uevent(struct kobject * kobj,const char * buf,size_t count)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/kobject.h>
int kobject_uevent_env(struct kobject * kobj,enum kobject_action action,char * envp_ext[])
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netdevice.h>
struct pernet_operations __net_initdata loopback_net_ops;
#include <linux/phy.h>
struct mii_bus * mdiobus_alloc_size(size_t size)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
void mdiobus_free(struct mii_bus * bus)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/mdio.h>
struct phy_device * mdiobus_get_phy(struct mii_bus * bus,int addr)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
void mdiobus_unregister(struct mii_bus * bus)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/preempt.h>
void migrate_disable(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/preempt.h>
void migrate_enable(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/sch_generic.h>
struct Qdisc_ops mq_qdisc_ops;
#include <linux/netdevice.h>
void napi_gro_flush(struct napi_struct * napi,bool flush_old)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/net.h>
int net_ratelimit(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/selftests.h>
void net_selftest(struct net_device * ndev,struct ethtool_test * etest,u64 * buf)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/selftests.h>
int net_selftest_get_count(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/selftests.h>
void net_selftest_get_strings(u8 * data)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/netlink.h>
int nla_put(struct sk_buff * skb,int attrtype,int attrlen,const void * data)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/fs.h>
loff_t noop_llseek(struct file * file,loff_t offset,int whence)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/moduleparam.h>
int param_set_copystring(const char * val,const struct kernel_param * kp)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
void phy_attached_info(struct phy_device * phydev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
struct phy_device * phy_connect(struct net_device * dev,const char * bus_id,void (* handler)(struct net_device *),phy_interface_t interface)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
void phy_disconnect(struct phy_device * phydev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
int phy_do_ioctl_running(struct net_device * dev,struct ifreq * ifr,int cmd)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
int phy_ethtool_get_link_ksettings(struct net_device * ndev,struct ethtool_link_ksettings * cmd)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
int phy_ethtool_nway_reset(struct net_device * ndev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
int phy_ethtool_set_link_ksettings(struct net_device * ndev,const struct ethtool_link_ksettings * cmd)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
void phy_print_status(struct phy_device * phydev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
void phy_start(struct phy_device * phydev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
void phy_stop(struct phy_device * phydev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phy.h>
int phy_suspend(struct phy_device * phydev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phylink.h>
int phylink_connect_phy(struct phylink * pl,struct phy_device * phy)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phylink.h>
struct phylink * phylink_create(struct phylink_config * config,struct fwnode_handle * fwnode,phy_interface_t iface,const struct phylink_mac_ops * mac_ops)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phylink.h>
void phylink_destroy(struct phylink * pl)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phylink.h>
void phylink_disconnect_phy(struct phylink * pl)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phylink.h>
void phylink_ethtool_get_pauseparam(struct phylink * pl,struct ethtool_pauseparam * pause)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phylink.h>
int phylink_ethtool_set_pauseparam(struct phylink * pl,struct ethtool_pauseparam * pause)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phylink.h>
void phylink_generic_validate(struct phylink_config * config,unsigned long * supported,struct phylink_link_state * state)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phylink.h>
void phylink_resume(struct phylink * pl)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phylink.h>
void phylink_start(struct phylink * pl)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phylink.h>
void phylink_stop(struct phylink * pl)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/phylink.h>
void phylink_suspend(struct phylink * pl,bool mac_wol)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/refcount.h>
void refcount_warn_saturate(refcount_t * r,enum refcount_saturation_type t)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/rtnetlink.h>
void rtmsg_ifinfo_send(struct sk_buff * skb,struct net_device * dev,gfp_t flags)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/scatterlist.h>
void sg_init_table(struct scatterlist * sgl,unsigned int nents)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/sock.h>
void sk_error_report(struct sock * sk)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/netdevice.h>
struct sk_buff * skb_mac_gso_segment(struct sk_buff * skb,netdev_features_t features)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/smp.h>
void smp_call_function_many(const struct cpumask * mask,smp_call_func_t func,void * info,bool wait)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/smp.h>
int smp_call_function_single(int cpu,smp_call_func_t func,void * info,int wait)
{
lx_emul_trace_and_stop(__func__);
}
#include <net/sock.h>
void sock_edemux(struct sk_buff * skb)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/jump_label.h>
bool static_key_initialized;
#include <net/sock.h>
int sysctl_tstamp_allow_data;
#include <linux/tcp.h>
struct sk_buff * tcp_get_timestamping_opt_stats(const struct sock * sk,const struct sk_buff * orig_skb,const struct sk_buff * ack_skb)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/usb.h>
int usb_clear_halt(struct usb_device * dev,int pipe)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/usb.h>
extern void usb_devio_cleanup(void);
void usb_devio_cleanup(void)
{
lx_emul_trace_and_stop(__func__);
}
extern void usb_disable_endpoint(struct usb_device * dev,unsigned int epaddr,bool reset_hardware);
void usb_disable_endpoint(struct usb_device * dev,unsigned int epaddr,bool reset_hardware)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/usb.h>
int usb_free_streams(struct usb_interface * interface,struct usb_host_endpoint ** eps,unsigned int num_eps,gfp_t mem_flags)
{
lx_emul_trace_and_stop(__func__);
}
extern int usb_get_device_descriptor(struct usb_device * dev,unsigned int size);
int usb_get_device_descriptor(struct usb_device * dev,unsigned int size)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/usb.h>
int usb_get_status(struct usb_device * dev,int recip,int type,int target,void * data)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/usb/hcd.h>
int usb_hcd_alloc_bandwidth(struct usb_device * udev,struct usb_host_config * new_config,struct usb_host_interface * cur_alt,struct usb_host_interface * new_alt)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/usb/hcd.h>
int usb_hcd_find_raw_port_number(struct usb_hcd * hcd,int port1)
{
lx_emul_trace_and_stop(__func__);
}
extern int usb_hub_create_port_device(struct usb_hub * hub,int port1);
int usb_hub_create_port_device(struct usb_hub * hub,int port1)
{
lx_emul_trace_and_stop(__func__);
}
extern void usb_hub_remove_port_device(struct usb_hub * hub,int port1);
void usb_hub_remove_port_device(struct usb_hub * hub,int port1)
{
lx_emul_trace_and_stop(__func__);
}
extern void usb_major_cleanup(void);
void usb_major_cleanup(void)
{
lx_emul_trace_and_stop(__func__);
}
extern int usb_set_isoch_delay(struct usb_device * dev);
int usb_set_isoch_delay(struct usb_device * dev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/usb/ch9.h>
const char * usb_speed_string(enum usb_device_speed speed)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/usb.h>
void usb_unpoison_urb(struct urb * urb)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/uuid.h>
const u8 uuid_index[16] = {};
#include <linux/sched/wake_q.h>
void wake_q_add_safe(struct wake_q_head * head,struct task_struct * task)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/filter.h>
int xdp_do_generic_redirect(struct net_device * dev,struct sk_buff * skb,struct xdp_buff * xdp,struct bpf_prog * xdp_prog)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/filter.h>
u32 xdp_master_redirect(struct xdp_buff * xdp)
{
lx_emul_trace_and_stop(__func__);
}

View File

@ -0,0 +1,79 @@
arch/x86/lib/hweight.S
drivers/base/bus.c
drivers/base/core.c
drivers/base/class.c
drivers/base/devres.c
drivers/base/driver.c
drivers/base/dd.c
drivers/base/property.c
drivers/net/mii.c
drivers/net/usb/asix_common.c
drivers/net/usb/asix_devices.c
drivers/net/usb/asix.h
drivers/net/usb/ax88172a.c
drivers/net/usb/ax88179_178a.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/cdc_mbim.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/usbnet.c
drivers/usb/class/cdc-wdm.c
drivers/usb/core/config.c
drivers/usb/core/driver.c
drivers/usb/core/generic.c
drivers/usb/core/hub.c
drivers/usb/core/quirks.c
drivers/usb/core/usb.c
fs/nls/nls_base.c
kernel/kthread.c
kernel/locking/mutex.c
kernel/locking/osq_lock.c
kernel/locking/rwsem.c
kernel/notifier.c
kernel/sched/build_utility.c
kernel/smpboot.c
kernel/softirq.c
kernel/time/clockevents.c
kernel/time/clocksource.c
kernel/time/hrtimer.c
kernel/time/jiffies.c
kernel/time/ntp.c
kernel/time/tick-broadcast.c
kernel/time/tick-common.c
kernel/time/tick-oneshot.c
kernel/time/tick-sched.c
kernel/time/time.c
kernel/time/timeconv.c
kernel/time/timecounter.c
kernel/time/timekeeping.c
kernel/time/timer.c
kernel/time/timer_list.c
kernel/workqueue.c
lib/bitmap.c
lib/crc16.c
lib/crc32.c
lib/ctype.c
lib/find_bit.c
lib/hexdump.c
lib/idr.c
lib/kasprintf.c
lib/klist.c
lib/kobject.c
lib/kstrtox.c
lib/radix-tree.c
lib/rhashtable.c
lib/rbtree.c
lib/xarray.c
lib/siphash.c
lib/string.c
lib/string_helpers.c
lib/timerqueue.c
lib/vsprintf.c
mm/util.c
net/core/dev.c
net/core/dev_addr_lists.c
net/core/link_watch.c
net/core/skbuff.c
net/core/xdp.c
net/ethernet/eth.c
net/ethtool/common.c
net/sched/sch_generic.c

View File

@ -0,0 +1,3 @@
REQUIRES := x86_64
include $(PRG_DIR)/../../target.inc

View File

@ -0,0 +1,36 @@
TARGET = usb_net_drv
LIBS = base jitterentropy virt_lx_emul
INC_DIR = $(PRG_DIR)/../..
SRC_C += dummies.c \
generated_dummies.c \
lx_emul.c \
lx_user.c
SRC_C += lx_emul/virt/shadow/drivers/usb/core/message.c \
lx_emul/virt/shadow/drivers/usb/core/urb.c \
lx_emul/virt/usb_client.c
SRC_CC = main.cc \
wdm_terminal.cc
SRC_CC += lx_emul/random.cc
SRC_CC += genode_c_api/mac_address_reporter.cc \
genode_c_api/usb_client.cc \
genode_c_api/uplink.cc
vpath %.c $(PRG_DIR)
vpath %.c $(PRG_DIR)/../..
vpath %.cc $(PRG_DIR)/../..
vpath %.c $(REP_DIR)/src/lib
C_API = $(dir $(call select_from_repositories,src/lib/genode_c_api))
vpath genode_c_api/mac_address_reporter.cc $(C_API)
vpath genode_c_api/uplink.cc $(C_API)
vpath genode_c_api/usb_client.cc $(C_API)
# vim: set ft=make :

View File

@ -0,0 +1,45 @@
/*
* \brief C/C++ interface for this driver
* \author Sebastian Sumpf
* \date 2023-07-11
*/
/*
* Copyright (C) 2023 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <lx_emul/usb_client.h>
#ifdef __cplusplus
extern "C" {
#endif
struct task_struct;
int lx_user_main_task(void *);
struct task_struct *lx_user_new_usb_task(int (*func)(void*), void *args);
struct lx_wdm
{
unsigned long *data_avail;
void *buffer;
void *handle;
unsigned active;
};
int lx_wdm_read(void *args);
int lx_wdm_write(void *args);
int lx_wdm_device(void *args);
void lx_wdm_create_root(void);
void lx_wdm_schedule_read(void *handle);
void lx_wdm_signal_data_avail(void *handle);
#ifdef __cplusplus
} /* extern "C" */
#endif

View File

@ -0,0 +1,214 @@
/*
* \brief Service providing the 'Terminal_session' interface for cdc-wdm file
* \author Sebastian Sumpf
* \date 2023-08-16
*/
/*
* Copyright (C) 2023 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#include <base/attached_ram_dataspace.h>
#include <base/log.h>
#include <os/session_policy.h>
#include <root/component.h>
#include <terminal_session/terminal_session.h>
#include <lx_emul/task.h>
#include <lx_kit/env.h>
#include <usb_net.h>
namespace Terminal {
class Session_component;
class Root;
}
class Terminal::Session_component : public Genode::Rpc_object<Session, Session_component>
{
using size_t = Genode::size_t;
private:
enum State { WRITE, READ };
Genode::Attached_ram_dataspace _io_buffer;
Genode::Signal_context_capability _read_avail_sigh { };
State _state { WRITE };
size_t _data_avail { 0 };
struct lx_wdm _wdm_data { &_data_avail, buffer(), this, 1 };
task_struct *_write_task { lx_user_new_usb_task(lx_wdm_write, &_wdm_data) };
task_struct *_read_task { lx_user_new_usb_task(lx_wdm_read, &_wdm_data) };
task_struct *_device_task { lx_user_new_usb_task(lx_wdm_device, nullptr) };
/* non-copyable */
Session_component(const Session_component&) = delete;
Session_component & operator=(const Session_component&) = delete;
public:
Session_component(Genode::Env &env,
Genode::size_t io_buffer_size)
:
_io_buffer(env.ram(), env.rm(), io_buffer_size)
{ }
void schedule_read()
{
lx_emul_task_unblock(_read_task);
}
void schedule_write()
{
lx_emul_task_unblock(_write_task);
}
/********************************
** Terminal session interface **
********************************/
Size size() override { return Size(0, 0); }
bool avail() override
{
return _data_avail > 0;
}
Genode::size_t _read(Genode::size_t dst_len)
{
if (_state != READ) return 0;
size_t length = Genode::min(dst_len, _data_avail);
if (dst_len < _data_avail)
Genode::warning("dst_len < data_avail (", dst_len, " < ", _data_avail, ") not supported");
_data_avail -= length;
if (_data_avail == 0) {
_state = WRITE;
schedule_read();
}
return length;
}
Genode::size_t _write(Genode::size_t num_bytes)
{
if (_state == READ) return 0;
_data_avail = num_bytes;
_state = WRITE;
schedule_write();
Lx_kit::env().scheduler.execute();
return 0;
}
Genode::Dataspace_capability _dataspace()
{
return _io_buffer.cap();
}
void read_avail_sigh(Genode::Signal_context_capability sigh) override
{
_read_avail_sigh = sigh;
}
void connected_sigh(Genode::Signal_context_capability sigh) override
{
Genode::Signal_transmitter(sigh).submit();
}
void size_changed_sigh(Genode::Signal_context_capability) override { }
size_t read(void *, size_t) override { return 0; }
size_t write(void const *, size_t) override { return 0; }
void *buffer() { return _io_buffer.local_addr<void>(); }
void signal_data_avail()
{
if (_read_avail_sigh.valid() == false) return;
_state = READ;
Genode::Signal_transmitter(_read_avail_sigh).submit();
}
};
class Terminal::Root : public Genode::Root_component<Session_component, Genode::Single_client>
{
private:
Genode::Env &_env;
task_struct *_create_task { lx_user_new_usb_task(_create_session, this) };
Genode::Constructible<Session_component> _session { };
static int _create_session(void *arg)
{
Root *root = static_cast<Root *>(arg);
Genode::size_t const io_buffer_size = 4096ul;
while (true) {
lx_emul_task_schedule(true);
if (!root->_session.constructed())
root->_session.construct(root->_env, io_buffer_size);
}
}
/* non-copyable */
Root(const Root&) = delete;
Root & operator=(const Root&) = delete;
protected:
Session_component *_create_session(const char *) override
{
if (!_session.constructed()) {
lx_emul_task_unblock(_create_task);
Lx_kit::env().scheduler.execute();
}
return &*_session;
}
public:
Root(Genode::Env &env,
Genode::Allocator &md_alloc)
:
Genode::Root_component<Session_component, Genode::Single_client>(&env.ep().rpc_ep(), &md_alloc),
_env(env)
{
_env.parent().announce(_env.ep().manage(*this));
}
};
void lx_wdm_schedule_read(void *handle)
{
using namespace Terminal;
Session_component *session = static_cast<Session_component *>(handle);
session->schedule_read();
}
void lx_wdm_signal_data_avail(void *handle)
{
using namespace Terminal;
Session_component *session = static_cast<Session_component *>(handle);
session->signal_data_avail();
}
void lx_wdm_create_root(void)
{
new (Lx_kit::env().heap) Terminal::Root(Lx_kit::env().env, Lx_kit::env().heap);
}