pc: new usb host driver based on Linux 5.14.21

Original commit by Josef Soentgen.

Ref genodelabs/genode#4416
This commit is contained in:
Stefan Kalkowski 2022-02-11 14:56:09 +01:00 committed by Norman Feske
parent e72f39b484
commit 3edec0c6ca
23 changed files with 3720 additions and 0 deletions

View File

@ -0,0 +1,18 @@
MIRROR_FROM_REP_DIR := src/drivers/usb_host/pc \
src/lib/pc/lx_emul
MIRROR_FROM_OS_DIR := src/lib/genode_c_api/usb.cc
content: $(MIRROR_FROM_REP_DIR) $(MIRROR_FROM_OS_DIR)
$(MIRROR_FROM_REP_DIR):
$(mirror_from_rep_dir)
$(MIRROR_FROM_OS_DIR):
mkdir -p $(dir $@)
cp -r $(GENODE_DIR)/repos/os/$@ $@
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 @@
2022-02-11-k 8f4071962fba9898b47db526132e3c11456d890c

View File

@ -0,0 +1,8 @@
base
os
platform_session
timer_session
usb_session
report_session
genode_c_api
pc_linux

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,463 @@
/*
* \brief Dummy definitions of Linux Kernel functions - handled manually
* \author Josef Soentgen
* \date 2022-01-10
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <lx_emul.h>
#include <linux/cpuhotplug.h>
int __cpuhp_setup_state(enum cpuhp_state state,const char * name,bool invoke,int (* startup)(unsigned int cpu),int (* teardown)(unsigned int cpu),bool multi_instance)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/timekeeper_internal.h>
void update_vsyscall(struct timekeeper * tk)
{
lx_emul_trace(__func__);
}
#include <linux/clocksource.h>
void clocksource_arch_init(struct clocksource * cs)
{
lx_emul_trace(__func__);
}
#include <linux/sched/signal.h>
void ignore_signals(struct task_struct * t)
{
lx_emul_trace(__func__);
}
#include <linux/sched/loadavg.h>
void calc_global_load(void)
{
lx_emul_trace(__func__);
}
#include <linux/kernel_stat.h>
void account_process_tick(struct task_struct * p,int user_tick)
{
lx_emul_trace(__func__);
}
#include <linux/delay.h>
unsigned long lpj_fine = 0;
#include <linux/rcupdate.h>
void rcu_sched_clock_irq(int user)
{
lx_emul_trace(__func__);
}
#include <linux/sysfs.h>
int sysfs_create_bin_file(struct kobject * kobj,const struct bin_attribute * attr)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/sysfs.h>
int sysfs_create_dir_ns(struct kobject * kobj,const void * ns)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/sysfs.h>
int sysfs_create_file_ns(struct kobject * kobj,const struct attribute * attr,const void * ns)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/sysfs.h>
int sysfs_create_groups(struct kobject * kobj,const struct attribute_group ** groups)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/sysfs.h>
int sysfs_create_group(struct kobject * kobj,const struct attribute_group * grp)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/sysfs.h>
int sysfs_create_link(struct kobject * kobj,struct kobject * target,const char * name)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/sysfs.h>
void sysfs_remove_link(struct kobject * kobj,const char * name)
{
lx_emul_trace(__func__);
}
#include <linux/sysfs.h>
void sysfs_remove_file_ns(struct kobject * kobj,const struct attribute * attr,const void * ns)
{
lx_emul_trace(__func__);
}
#include <linux/sysfs.h>
void sysfs_remove_groups(struct kobject * kobj,const struct attribute_group ** groups)
{
lx_emul_trace(__func__);
}
#include <linux/sysfs.h>
void sysfs_remove_dir(struct kobject * kobj)
{
lx_emul_trace(__func__);
}
#include <linux/sysfs.h>
void sysfs_remove_bin_file(struct kobject * kobj,const struct bin_attribute * attr)
{
lx_emul_trace(__func__);
}
#include <linux/kernfs.h>
void kernfs_get(struct kernfs_node * kn)
{
lx_emul_trace(__func__);
}
#include <linux/kernfs.h>
void kernfs_put(struct kernfs_node * kn)
{
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/random.h>
int __must_check get_random_bytes_arch(void * buf,int nbytes)
{
lx_emul_trace(__func__);
printk("%s: leaving buffer unmodified!\n", __func__);
return 0;
}
#include <linux/random.h>
void get_random_bytes(void * buf,int nbytes)
{
lx_emul_trace(__func__);
printk("%s: leaving buffer unmodified!\n", __func__);
}
#include <linux/random.h>
int add_random_ready_callback(struct random_ready_callback * rdy)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/random.h>
void add_device_randomness(const void * buf,unsigned int size)
{
lx_emul_trace(__func__);
}
#include <linux/random.h>
void add_interrupt_randomness(int irq,int irq_flags)
{
lx_emul_trace(__func__);
}
extern bool irq_wait_for_poll(struct irq_desc * desc);
bool irq_wait_for_poll(struct irq_desc * desc)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/irq.h>
void note_interrupt(struct irq_desc * desc,irqreturn_t action_ret)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/fs.h>
int __register_chrdev(unsigned int major,unsigned int baseminor,unsigned int count,const char * name,const struct file_operations * fops)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/fs.h>
int register_chrdev_region(dev_t from,unsigned count,const char * name)
{
lx_emul_trace(__func__);
return 0;
}
extern void register_handler_proc(unsigned int irq,struct irqaction * action);
void register_handler_proc(unsigned int irq,struct irqaction * action)
{
lx_emul_trace(__func__);
}
extern void register_irq_proc(unsigned int irq,struct irq_desc * desc);
void register_irq_proc(unsigned int irq,struct irq_desc * desc)
{
lx_emul_trace(__func__);
}
#include <linux/cdev.h>
void cdev_init(struct cdev * cdev,const struct file_operations * fops)
{
lx_emul_trace(__func__);
}
#include <linux/cdev.h>
int cdev_add(struct cdev * p,dev_t dev,unsigned count)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/cdev.h>
void cdev_del(struct cdev * p)
{
lx_emul_trace(__func__);
}
#include <linux/syscore_ops.h>
void register_syscore_ops(struct syscore_ops * ops)
{
lx_emul_trace(__func__);
}
#include <linux/proc_fs.h>
struct proc_dir_entry { int dummy; };
struct proc_dir_entry * proc_create_seq_private(const char * name,umode_t mode,struct proc_dir_entry * parent,const struct seq_operations * ops,unsigned int state_size,void * data)
{
static struct proc_dir_entry ret;
lx_emul_trace(__func__);
return &ret;
}
#include <linux/property.h>
int software_node_notify(struct device * dev,unsigned long action)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/utsname.h>
#include <linux/user_namespace.h>
struct user_namespace init_user_ns;
struct uts_namespace init_uts_ns;
/*
* linux/seq_file.h depends on user_namespace being defined, add
* all dummies pulling in this header below here
*/
#include <linux/seq_file.h>
void seq_vprintf(struct seq_file * m,const char * f,va_list args)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/vt_kern.h>
void unblank_screen(void)
{
lx_emul_trace_and_stop(__func__);
}
extern void pci_allocate_vc_save_buffers(struct pci_dev * dev);
void pci_allocate_vc_save_buffers(struct pci_dev * dev)
{
lx_emul_trace(__func__);
}
extern void pci_vpd_init(struct pci_dev * dev);
void pci_vpd_init(struct pci_dev * dev)
{
lx_emul_trace(__func__);
}
extern int pci_proc_attach_device(struct pci_dev * dev);
int pci_proc_attach_device(struct pci_dev * dev)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/kernel.h>
bool parse_option_str(const char * str,const char * option)
{
lx_emul_trace(__func__);
return false;
}
extern bool pat_enabled(void);
bool pat_enabled(void)
{
lx_emul_trace(__func__);
return false;
}
#include <linux/mm.h>
bool is_vmalloc_addr(const void * x)
{
lx_emul_trace(__func__);
return false;
}
unsigned long init_stack[THREAD_SIZE / sizeof(unsigned long)];
extern int pci_dev_specific_acs_enabled(struct pci_dev * dev,u16 acs_flags);
int pci_dev_specific_acs_enabled(struct pci_dev * dev,u16 acs_flags)
{
lx_emul_trace(__func__);
return 0;
}
extern int pci_dev_specific_disable_acs_redir(struct pci_dev * dev);
int pci_dev_specific_disable_acs_redir(struct pci_dev * dev)
{
lx_emul_trace(__func__);
return 0;
}
extern int pci_dev_specific_enable_acs(struct pci_dev * dev);
int pci_dev_specific_enable_acs(struct pci_dev * dev)
{
lx_emul_trace(__func__);
return 0;
}
extern int pci_dev_specific_reset(struct pci_dev * dev,int probe);
int pci_dev_specific_reset(struct pci_dev * dev,int probe)
{
lx_emul_trace(__func__);
return 0;
}
#include <linux/pci.h>
void pci_fixup_device(enum pci_fixup_pass pass,struct pci_dev * dev)
{
lx_emul_trace(__func__);
}

View File

@ -0,0 +1,678 @@
/*
* \brief Dummy definitions of Linux Kernel functions
* \author Automatically generated file - do no edit
* \date 2022-02-03
*/
#include <lx_emul.h>
#include <linux/proc_fs.h>
void * PDE_DATA(const struct inode * inode)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/ratelimit_types.h>
int ___ratelimit(struct ratelimit_state * rs,const char * func)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/clk-provider.h>
const char * __clk_get_name(const struct clk * clk)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/gfp.h>
unsigned long __get_free_pages(gfp_t gfp_mask,unsigned int order)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/printk.h>
int __printk_ratelimit(const char * func)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/cred.h>
void __put_cred(struct cred * cred)
{
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/srcu.h>
void __srcu_read_unlock(struct srcu_struct * ssp,int idx)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/fs.h>
void __unregister_chrdev(unsigned int major,unsigned int baseminor,unsigned int count,const char * name)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/uaccess.h>
unsigned long _copy_from_user(void * to,const void __user * from,unsigned long n)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/uaccess.h>
unsigned long _copy_to_user(void __user * to,const void * from,unsigned long n)
{
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/fs.h>
struct timespec64 current_time(struct inode * inode)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/property.h>
int device_create_managed_software_node(struct device * dev,const struct property_entry * properties,const struct software_node * parent)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/dma-mapping.h>
int dma_mmap_attrs(struct device * dev,struct vm_area_struct * vma,void * cpu_addr,dma_addr_t dma_addr,size_t size,unsigned long attrs)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/dmapool.h>
void dma_pool_destroy(struct dma_pool * pool)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/printk.h>
asmlinkage __visible void dump_stack(void)
{
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/gfp.h>
void free_pages(unsigned long addr,unsigned int order)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/property.h>
void fwnode_remove_software_node(struct fwnode_handle * fwnode)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/genalloc.h>
void * gen_pool_dma_alloc(struct gen_pool * pool,size_t size,dma_addr_t * dma)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/genalloc.h>
void * gen_pool_dma_alloc_align(struct gen_pool * pool,size_t size,dma_addr_t * dma,int align)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/genalloc.h>
void * gen_pool_dma_zalloc_align(struct gen_pool * pool,size_t size,dma_addr_t * dma,int align)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/genalloc.h>
void gen_pool_free_owner(struct gen_pool * pool,unsigned long addr,size_t size,void ** owner)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/kernel.h>
int get_option(char ** str,int * pint)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/uuid.h>
const u8 guid_index[16] = {};
#include <linux/pseudo_fs.h>
struct pseudo_fs_context * init_pseudo(struct fs_context * fc,unsigned long magic)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/init.h>
bool initcall_debug;
#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/irq_work.h>
void irq_work_tick(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/property.h>
bool is_software_node(const struct fwnode_handle * fwnode)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/kobject.h>
struct kobject *kernel_kobj;
#include <linux/fs.h>
void kill_anon_super(struct super_block * sb)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sched/signal.h>
int kill_pid_usb_asyncio(int sig,int errno,sigval_t addr,struct pid * pid,const struct cred * cred)
{
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 <asm-generic/logic_io.h>
void memcpy_fromio(void * to,const volatile void __iomem * from,size_t n)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/kernel.h>
unsigned long long memparse(const char * ptr,char ** retptr)
{
lx_emul_trace_and_stop(__func__);
}
extern void native_io_delay(void);
void native_io_delay(void)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/irq.h>
struct irq_chip no_irq_chip;
#include <linux/fs.h>
loff_t no_seek_end_llseek(struct file * file,loff_t offset,int whence)
{
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/pci.h>
void pci_assign_unassigned_bridge_resources(struct pci_dev * bridge)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/pci.h>
void pci_assign_unassigned_bus_resources(struct pci_bus * bus)
{
lx_emul_trace_and_stop(__func__);
}
extern unsigned long pci_cardbus_resource_alignment(struct resource * res);
unsigned long pci_cardbus_resource_alignment(struct resource * res)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/pci.h>
unsigned int pci_flags;
extern int pci_idt_bus_quirk(struct pci_bus * bus,int devfn,u32 * l,int timeout);
int pci_idt_bus_quirk(struct pci_bus * bus,int devfn,u32 * l,int timeout)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/pci.h>
int pci_mmap_resource_range(struct pci_dev * pdev,int bar,struct vm_area_struct * vma,enum pci_mmap_state mmap_state,int write_combine)
{
lx_emul_trace_and_stop(__func__);
}
extern void __init pci_realloc_get_opt(char * str);
void __init pci_realloc_get_opt(char * str)
{
lx_emul_trace_and_stop(__func__);
}
extern void pci_restore_vc_state(struct pci_dev * dev);
void pci_restore_vc_state(struct pci_dev * dev)
{
lx_emul_trace_and_stop(__func__);
}
extern int pci_save_vc_state(struct pci_dev * dev);
int pci_save_vc_state(struct pci_dev * dev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/pci.h>
void pci_stop_and_remove_bus_device_locked(struct pci_dev * dev)
{
lx_emul_trace_and_stop(__func__);
}
extern void pci_vpd_release(struct pci_dev * dev);
void pci_vpd_release(struct pci_dev * dev)
{
lx_emul_trace_and_stop(__func__);
}
extern unsigned int pcibios_assign_all_busses(void);
unsigned int pcibios_assign_all_busses(void)
{
lx_emul_trace_and_stop(__func__);
}
extern void pcie_aspm_init_link_state(struct pci_dev * pdev);
void pcie_aspm_init_link_state(struct pci_dev * pdev)
{
lx_emul_trace_and_stop(__func__);
}
extern void pcie_aspm_pm_state_change(struct pci_dev * pdev);
void pcie_aspm_pm_state_change(struct pci_dev * pdev)
{
lx_emul_trace_and_stop(__func__);
}
extern void pcie_aspm_powersave_config_link(struct pci_dev * pdev);
void pcie_aspm_powersave_config_link(struct pci_dev * pdev)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/printk.h>
int printk_deferred(const char * fmt,...)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/pid.h>
void put_pid(struct pid * pid)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/pci.h>
int raw_pci_read(unsigned int domain,unsigned int bus,unsigned int devfn,int reg,int len,u32 * val)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/refcount.h>
bool refcount_dec_not_one(refcount_t * r)
{
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/mm.h>
int remap_pfn_range(struct vm_area_struct * vma,unsigned long addr,unsigned long pfn,unsigned long size,pgprot_t prot)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sched.h>
void sched_set_fifo(struct task_struct * p)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/seq_file.h>
void seq_printf(struct seq_file * m,const char * f,...)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/smp.h>
int smp_call_function_single(int cpu,void (* func)(void * info),void * info,int wait)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/srcutiny.h>
void srcu_drive_gp(struct work_struct * wp)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/jump_label.h>
bool static_key_initialized;
#include <linux/string_helpers.h>
int string_escape_mem(const char * src,size_t isz,char * dst,size_t osz,unsigned int flags,const char * only)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/srcutiny.h>
void synchronize_srcu(struct srcu_struct * ssp)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sysfs.h>
void sysfs_delete_link(struct kobject * kobj,struct kobject * targ,const char * name)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sysfs.h>
int sysfs_emit(char * buf,const char * fmt,...)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sysfs.h>
int sysfs_emit_at(char * buf,int at,const char * fmt,...)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sysfs.h>
void sysfs_notify(struct kobject * kobj,const char * dir,const char * attr)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sysfs.h>
bool sysfs_remove_file_self(struct kobject * kobj,const struct attribute * attr)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/sysfs.h>
void sysfs_remove_group(struct kobject * kobj,const struct attribute_group * grp)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/task_work.h>
int task_work_add(struct task_struct * task,struct callback_head * work,enum task_work_notify_mode notify)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/task_work.h>
struct callback_head * task_work_cancel(struct task_struct * task,task_work_func_t func)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/fs.h>
void unregister_chrdev_region(dev_t from,unsigned count)
{
lx_emul_trace_and_stop(__func__);
}
extern void unregister_handler_proc(unsigned int irq,struct irqaction * action);
void unregister_handler_proc(unsigned int irq,struct irqaction * action)
{
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__);
}

View File

@ -0,0 +1,205 @@
/*
* \brief Linux emulation environment specific to this driver
* \author Stefan Kalkowski
* \date 2021-08-31
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <lx_emul.h>
#include <linux/slab.h>
#include <lx_emul/alloc.h>
#include <lx_emul/io_mem.h>
#include <asm-generic/delay.h>
#include <linux/delay.h>
void __const_udelay(unsigned long xloops)
{
unsigned long usecs = xloops / 0x10C7UL;
if (usecs < 100)
lx_emul_time_udelay(usecs);
else
usleep_range(usecs, usecs * 10);
}
void __udelay(unsigned long usecs)
{
lx_emul_time_udelay(usecs);
}
#include <linux/cpumask.h>
atomic_t __num_online_cpus = ATOMIC_INIT(1);
#include <linux/dma-mapping.h>
dma_addr_t dma_map_page_attrs(struct device * dev,
struct page * page,
size_t offset,
size_t size,
enum dma_data_direction dir,
unsigned long attrs)
{
dma_addr_t const dma_addr = page_to_phys(page);
unsigned long const virt_addr = (unsigned long)page_to_virt(page);
lx_emul_mem_cache_clean_invalidate((void *)(virt_addr + offset), size);
return dma_addr + offset;
}
#include <linux/dmapool.h>
struct dma_pool { size_t size; };
void * dma_pool_alloc(struct dma_pool * pool, gfp_t mem_flags, dma_addr_t * handle)
{
void * ret =
lx_emul_mem_alloc_aligned_uncached(pool->size, PAGE_SIZE);
*handle = lx_emul_mem_dma_addr(ret);
return ret;
}
struct dma_pool * dma_pool_create(const char * name,
struct device * dev,
size_t size,
size_t align,
size_t boundary)
{
struct dma_pool * pool = kmalloc(sizeof(struct dma_pool), GFP_KERNEL);
pool->size = size;
return pool;
}
void dma_pool_free(struct dma_pool * pool,void * vaddr,dma_addr_t dma)
{
lx_emul_mem_free(vaddr);
}
#include <linux/dma-mapping.h>
int dma_supported(struct device * dev,u64 mask)
{
lx_emul_trace(__func__);
return 1;
}
#include <linux/dma-mapping.h>
void dma_unmap_page_attrs(struct device * dev,
dma_addr_t addr,
size_t size,
enum dma_data_direction dir,
unsigned long attrs)
{
unsigned long const virt_addr = lx_emul_mem_virt_addr((void*)addr);
if (!virt_addr)
return;
if (dir == DMA_FROM_DEVICE)
lx_emul_mem_cache_invalidate((void *)virt_addr, size);
}
#include <linux/slab.h>
void * kmalloc_order(size_t size, gfp_t flags, unsigned int order)
{
return kmalloc(size, flags);
}
#include <linux/fs.h>
#include <linux/mount.h>
#include <linux/slab.h>
int simple_pin_fs(struct file_system_type * type, struct vfsmount ** mount, int * count)
{
*mount = kmalloc(sizeof(struct vfsmount), GFP_KERNEL);
return 0;
}
#include <linux/fs.h>
void simple_release_fs(struct vfsmount ** mount,int * count)
{
kfree(*mount);
}
#include <linux/fs.h>
struct inode * alloc_anon_inode(struct super_block * s)
{
return kmalloc(sizeof(struct inode), GFP_KERNEL);
}
#include <linux/interrupt.h>
void tasklet_setup(struct tasklet_struct * t,
void (* callback)(struct tasklet_struct *))
{
t->next = NULL;
t->state = 0;
atomic_set(&t->count, 0);
t->callback = callback;
t->use_callback = true;
t->data = 0;
}
void __tasklet_schedule(struct tasklet_struct * t)
{
if (test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
t->callback(t);
}
void __tasklet_hi_schedule(struct tasklet_struct * t)
{
if (test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
t->callback(t);
}
#include <linux/rcupdate.h>
void call_rcu(struct rcu_head * head,rcu_callback_t func)
{
lx_emul_trace(__func__);
func(head);
}
#include <asm-generic/logic_io.h>
void __iomem * ioremap(resource_size_t phys_addr, unsigned long size)
{
return lx_emul_io_mem_map(phys_addr, size);
}
#include <asm-generic/logic_io.h>
void iounmap(volatile void __iomem * addr)
{
(void)addr;
}

View File

@ -0,0 +1,33 @@
/**
* \brief Dummy definitions of Linux Kernel functions
* \author Stefan Kalkowski
* \date 2021-03-16
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Needed to trace and stop */
#include <lx_emul/debug.h>
/* fix for wait_for_completion_timeout where the __sched include is missing */
#include <linux/sched/debug.h>
/* fix for missing include in linux/dynamic_debug.h */
#include <linux/compiler_attributes.h>
#ifdef __cplusplus
extern "C" {
#endif
void lx_backtrace(void);
void lx_emul_time_udelay(unsigned long usec);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,166 @@
/*
* \brief Array defining order of Linux Kernel initcalls
* \author Automatically generated file - do no edit
* \date 2022-01-13
*/
#pragma once
static const char * lx_emul_initcall_order[] = {
"__initcall_init_hw_perf_eventsearly",
"__initcall_start",
"__initcall_init_real_modeearly",
"__initcall_validate_x2apicearly",
"__initcall_register_nmi_cpu_backtrace_handlerearly",
"__initcall_spawn_ksoftirqdearly",
"__initcall_static_call_initearly",
"__initcall_init_zero_pfnearly",
"__initcall_initialize_ptr_randomearly",
"__initcall_init_mmap_min_addr0",
"__initcall_pci_realloc_setup_params0",
"__initcall_reboot_init1",
"__initcall_wq_sysfs_init1",
"__initcall_ksysfs_init1",
"__initcall_rcu_set_runtime_mode1",
"__initcall_init_jiffies_clocksource1",
"__initcall_init_script_binfmt1",
"__initcall_init_elf_binfmt1",
"__initcall_prandom_init_early1",
"__initcall_irq_sysfs_init2",
"__initcall_bdi_class_init2",
"__initcall_mm_sysfs_init2",
"__initcall_init_per_zone_wmark_min2",
"__initcall_pcibus_class_init2",
"__initcall_pci_driver_init2",
"__initcall_tty_class_init2",
"__initcall_vtconsole_class_init2",
"__initcall_devlink_class_init2",
"__initcall_software_node_init2",
"__initcall_amd_postcore_init2",
"__initcall_bts_init3",
"__initcall_pt_init3",
"__initcall_boot_params_ksysfs_init3",
"__initcall_sbf_init3",
"__initcall_arch_kdebugfs_init3",
"__initcall_intel_pconfig_init3",
"__initcall_pci_arch_init3",
"__initcall_init_vdso4",
"__initcall_fixup_ht_bug4",
"__initcall_topology_init4",
"__initcall_uid_cache_init4",
"__initcall_param_sysfs_init4",
"__initcall_user_namespace_sysctl_init4",
"__initcall_oom_init4",
"__initcall_default_bdi_init4",
"__initcall_percpu_enable_async4",
"__initcall_init_user_reserve4",
"__initcall_init_admin_reserve4",
"__initcall_init_reserve_notifier4",
"__initcall_pci_slot_init4",
"__initcall_misc_init4",
"__initcall_vga_arb_device_init4",
"__initcall_usb_common_init4",
"__initcall_usb_init4",
"__initcall_serio_init4",
"__initcall_input_init4",
"__initcall_pci_subsys_init4",
"__initcall_nmi_warning_debugfs5",
"__initcall_hpet_late_init5",
"__initcall_init_amd_nbs5",
"__initcall_iomem_init_inode5",
"__initcall_clocksource_done_booting5",
"__initcall_init_pipe_fs5",
"__initcall_anon_inode_init5",
"__initcall_proc_cmdline_init5",
"__initcall_proc_consoles_init5",
"__initcall_proc_cpuinfo_init5",
"__initcall_proc_devices_init5",
"__initcall_proc_interrupts_init5",
"__initcall_proc_loadavg_init5",
"__initcall_proc_meminfo_init5",
"__initcall_proc_stat_init5",
"__initcall_proc_uptime_init5",
"__initcall_proc_version_init5",
"__initcall_proc_softirqs_init5",
"__initcall_proc_kmsg_init5",
"__initcall_proc_page_init5",
"__initcall_init_ramfs_fs5",
"__initcall_chr_dev_init5",
"__initcall_pcibios_assign_resources5",
"__initcall_pci_apply_final_quirks5s",
"__initcall_populate_rootfsrootfs",
"__initcall_pci_iommu_initrootfs",
"__initcall_rapl_pmu_init6",
"__initcall_amd_uncore_init6",
"__initcall_amd_ibs_init6",
"__initcall_msr_init6",
"__initcall_intel_uncore_init6",
"__initcall_cstate_pmu_init6",
"__initcall_register_kernel_offset_dumper6",
"__initcall_i8259A_init_ops6",
"__initcall_init_tsc_clocksource6",
"__initcall_add_rtc_cmos6",
"__initcall_umwait_init6",
"__initcall_ioapic_init_ops6",
"__initcall_sysfb_init6",
"__initcall_proc_execdomains_init6",
"__initcall_ioresources_init6",
"__initcall_timekeeping_init_ops6",
"__initcall_init_clocksource_sysfs6",
"__initcall_init_timer_list_procfs6",
"__initcall_alarmtimer_init6",
"__initcall_clockevents_init_sysfs6",
"__initcall_utsname_sysctl_init6",
"__initcall_perf_event_sysfs_init6",
"__initcall_kswapd_init6",
"__initcall_workingset_init6",
"__initcall_proc_vmalloc_init6",
"__initcall_fcntl_init6",
"__initcall_proc_filesystems_init6",
"__initcall_start_dirtytime_writeback6",
"__initcall_init_devpts_fs6",
"__initcall_pci_proc_init6",
"__initcall_gpio_clk_driver_init6",
"__initcall_plt_clk_driver_init6",
"__initcall_n_null_init6",
"__initcall_pty_init6",
"__initcall_serial8250_init6",
"__initcall_serial_pci_driver_init6",
"__initcall_exar_pci_driver_init6",
"__initcall_lpss8250_pci_driver_init6",
"__initcall_mid8250_pci_driver_init6",
"__initcall_topology_sysfs_init6",
"__initcall_cacheinfo_sysfs_init6",
"__initcall_ehci_hcd_init6",
"__initcall_ehci_pci_init6",
"__initcall_ohci_hcd_mod_init6",
"__initcall_ohci_pci_init6",
"__initcall_xhci_hcd_init6",
"__initcall_xhci_pci_init6",
"__initcall_i8042_init6",
"__initcall_serport_init6",
"__initcall_atkbd_init6",
"__initcall_psmouse_init6",
"__initcall_pmc_atom_init6",
"__initcall_usbnet_init6",
"__initcall_update_mp_table7",
"__initcall_lapic_insert_resource7",
"__initcall_print_ICs7",
"__initcall_create_tlb_single_page_flush_ceiling7",
"__initcall_init_oops_id7",
"__initcall_reboot_ksysfs_init7",
"__initcall_sched_clock_init_late7",
"__initcall_sched_init_debug7",
"__initcall_printk_late_init7",
"__initcall_check_early_ioremap_leak7",
"__initcall_prandom_init_late7",
"__initcall_pci_resource_alignment_sysfs_init7",
"__initcall_pci_sysfs_init7",
"__initcall_sync_state_resume_initcall7",
"__initcall_deferred_probe_initcall7",
"__initcall_clk_disable_unused7s",
"__initcall_con_initcon",
"__initcall_end",
"__initcall_univ8250_console_initcon",
"END_OF_INITCALL_ORDER_ARRAY_DUMMY_ENTRY"
};

View File

@ -0,0 +1,22 @@
/**
* \brief PCI fixup calls to execute
* \author Josef Soentgen
* \date 2022-02-07
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _LX_EMUL__PCI_FIXUPS_H_
#define _LX_EMUL__PCI_FIXUPS_H_
static const char * lx_emul_pci_final_fixups[] = {
"__pci_fixup_final_quirk_usb_early_handoff",
"END_OF_PCI_FIXUPS"
};
#endif /* _LX_EMUL__PCI_FIXUPS_H_ */

View File

@ -0,0 +1,113 @@
/*
* \brief i.MX8 USB-card driver Linux port
* \author Stefan Kalkowski
* \date 2021-06-29
*/
/*
* Copyright (C) 2021 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 <lx_emul/init.h>
#include <lx_emul/page_virt.h>
#include <lx_kit/env.h>
#include <lx_kit/init.h>
#include <lx_user/io.h>
#include <usb.h>
using namespace Genode;
extern "C" struct genode_attached_dataspace *
genode_usb_allocate_peer_buffer(unsigned long size)
{
Attached_dataspace & ds = Lx_kit::env().memory.alloc_dataspace(size);
/*
* We have to call virt_to_pages eagerly here,
* to get contingous page objects registered
*/
lx_emul_virt_to_pages(ds.local_addr<void>(), size >> 12);
return genode_attached_dataspace_ptr(ds);
}
extern "C" void genode_usb_free_peer_buffer(struct genode_attached_dataspace * ptr)
{
Attached_dataspace *ds = static_cast<Attached_dataspace*>(ptr);
lx_emul_forget_pages(ds->local_addr<void>(), ds->size());
Lx_kit::env().memory.free_dataspace(ds->local_addr<void>());
}
static bool _bios_handoff;
extern "C" int inhibit_pci_fixup(char const *name)
{
if (_bios_handoff)
return 0;
char const *handoff = "__pci_fixup_final_quirk_usb_early_handoff";
size_t length = Genode::min(Genode::strlen(name),
Genode::strlen(handoff));
return Genode::strcmp(handoff, name, length) == 0;
}
struct Main : private Entrypoint::Io_progress_handler
{
Env & env;
Signal_handler<Main> signal_handler { env.ep(), *this,
&Main::handle_signal };
Sliced_heap sliced_heap { env.ram(), env.rm() };
Attached_rom_dataspace config_rom { env, "config" };
/**
* Entrypoint::Io_progress_handler
*/
void handle_io_progress() override
{
genode_usb_notify_peers();
}
void handle_signal()
{
lx_user_handle_io();
Lx_kit::env().scheduler.schedule();
}
Main(Env & env) : env(env)
{
_bios_handoff = config_rom.xml().attribute_value("bios_handoff", true);
Lx_kit::initialize(env);
genode_usb_init(genode_env_ptr(env),
genode_allocator_ptr(sliced_heap),
genode_signal_handler_ptr(signal_handler),
&genode_usb_rpc_callbacks_obj);
lx_emul_start_kernel(nullptr);
env.ep().register_io_progress_handler(*this);
}
};
void Component::construct(Env & env)
{
static Main main(env);
}

View File

@ -0,0 +1,20 @@
/*
* \brief Misc
* \author Josef Soentgen
* \date 2022-01-20
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <os/backtrace.h>
extern "C" void lx_backtrace(void)
{
Genode::backtrace();
}

View File

@ -0,0 +1,14 @@
arch/x86/include/asm/checksum_32.h
arch/x86/include/asm/cmpxchg_32.h
arch/x86/include/asm/page_32.h
arch/x86/include/asm/page_32_types.h
arch/x86/include/asm/pgtable-2level_types.h
arch/x86/include/asm/pgtable_32_areas.h
arch/x86/include/asm/pgtable_32_types.h
arch/x86/include/asm/uaccess_32.h
arch/x86/include/asm/user_32.h
arch/x86/include/uapi/asm/posix_types_32.h
include/asm-generic/bitops/fls64.h
include/asm-generic/pgtable-nopmd.h
include/asm-generic/pgtable-nopud.h

View File

@ -0,0 +1,116 @@
arch/x86/pci/legacy.c
drivers/base/bus.c
drivers/base/class.c
drivers/base/component.c
drivers/base/core.c
drivers/base/dd.c
drivers/base/devres.c
drivers/base/driver.c
drivers/base/platform.c
drivers/base/property.c
drivers/clk/clk-devres.c
drivers/pci/access.c
drivers/pci/bus.c
drivers/pci/host-bridge.c
drivers/pci/msi.c
drivers/pci/pci.c
drivers/pci/pci-driver.c
drivers/pci/pci-sysfs.c
drivers/pci/probe.c
drivers/pci/rom.c
drivers/pci/search.c
drivers/pci/setup-res.c
drivers/pci/slot.c
drivers/usb/common/common.c
drivers/usb/common/debug.c
drivers/usb/core/buffer.c
drivers/usb/core/config.c
drivers/usb/core/devices.c
drivers/usb/core/devio.c
drivers/usb/core/driver.c
drivers/usb/core/endpoint.c
drivers/usb/core/file.c
drivers/usb/core/generic.c
drivers/usb/core/hcd-pci.c
drivers/usb/core/hcd.c
drivers/usb/core/hub.c
drivers/usb/core/message.c
drivers/usb/core/notify.c
drivers/usb/core/phy.c
drivers/usb/core/port.c
drivers/usb/core/quirks.c
drivers/usb/core/sysfs.c
drivers/usb/core/urb.c
drivers/usb/core/usb.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-pci.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-pci.c
drivers/usb/host/pci-quirks.c
drivers/usb/host/xhci-dbg.c
drivers/usb/host/xhci-ext-caps.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci-trace.c
drivers/usb/host/xhci.c
fs/nls/nls_base.c
kernel/irq/chip.c
kernel/irq/devres.c
kernel/irq/handle.c
kernel/irq/irqdesc.c
kernel/irq/manage.c
kernel/irq/resend.c
kernel/kthread.c
kernel/locking/mutex.c
kernel/locking/osq_lock.c
kernel/locking/rwsem.c
kernel/notifier.c
kernel/panic.c
kernel/resource.c
kernel/sched/clock.c
kernel/sched/completion.c
kernel/sched/swait.c
kernel/sched/wait.c
kernel/smpboot.c
kernel/time/clockevents.c
kernel/time/clocksource.c
kernel/time/hrtimer.c
kernel/time/jiffies.c
kernel/time/ntp.c
kernel/time/tick-common.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/crc32.c
lib/ctype.c
lib/debug_locks.c
lib/find_bit.c
lib/hexdump.c
lib/idr.c
lib/iomap.c
lib/irq_regs.c
lib/kasprintf.c
lib/klist.c
lib/kobject.c
lib/kstrtox.c
lib/list_sort.c
lib/math/div64.c
lib/pci_iomap.c
lib/radix-tree.c
lib/rbtree.c
lib/scatterlist.c
lib/siphash.c
lib/sort.c
lib/string.c
lib/timerqueue.c
lib/vsprintf.c
lib/xarray.c
mm/mempool.c
mm/util.c

View File

@ -0,0 +1,5 @@
include $(REP_DIR)/src/drivers/usb_host/pc/target.inc
REQUIRES += 32bit
SRC_C += lx_emul/spec/x86_32/atomic64_32.c

View File

@ -0,0 +1,14 @@
arch/x86/include/asm/atomic64_64.h
arch/x86/include/asm/checksum_64.h
arch/x86/include/asm/cmpxchg_64.h
arch/x86/include/asm/kaslr.h
arch/x86/include/asm/page_64.h
arch/x86/include/asm/page_64_types.h
arch/x86/include/asm/pgtable_64_types.h
arch/x86/include/asm/sparsemem.h
arch/x86/include/asm/string_64.h
arch/x86/include/asm/uaccess_64.h
arch/x86/include/asm/user_64.h
arch/x86/include/uapi/asm/posix_types_64.h
arch/x86/include/uapi/asm/vsyscall.h
include/asm-generic/div64.h

View File

@ -0,0 +1,117 @@
arch/x86/pci/legacy.c
drivers/base/bus.c
drivers/base/class.c
drivers/base/component.c
drivers/base/core.c
drivers/base/dd.c
drivers/base/devres.c
drivers/base/driver.c
drivers/base/platform.c
drivers/base/property.c
drivers/clk/clk-devres.c
drivers/pci/access.c
drivers/pci/bus.c
drivers/pci/host-bridge.c
drivers/pci/msi.c
drivers/pci/pci.c
drivers/pci/pci-driver.c
drivers/pci/pci-sysfs.c
drivers/pci/probe.c
drivers/pci/rom.c
drivers/pci/search.c
drivers/pci/setup-res.c
drivers/pci/slot.c
drivers/usb/common/common.c
drivers/usb/common/debug.c
drivers/usb/core/buffer.c
drivers/usb/core/config.c
drivers/usb/core/devices.c
drivers/usb/core/devio.c
drivers/usb/core/driver.c
drivers/usb/core/endpoint.c
drivers/usb/core/file.c
drivers/usb/core/generic.c
drivers/usb/core/hcd-pci.c
drivers/usb/core/hcd.c
drivers/usb/core/hub.c
drivers/usb/core/message.c
drivers/usb/core/notify.c
drivers/usb/core/phy.c
drivers/usb/core/port.c
drivers/usb/core/quirks.c
drivers/usb/core/sysfs.c
drivers/usb/core/urb.c
drivers/usb/core/usb.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-pci.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-pci.c
drivers/usb/host/pci-quirks.c
drivers/usb/host/xhci-dbg.c
drivers/usb/host/xhci-ext-caps.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci-trace.c
drivers/usb/host/xhci.c
fs/nls/nls_base.c
kernel/irq/chip.c
kernel/irq/devres.c
kernel/irq/handle.c
kernel/irq/irqdesc.c
kernel/irq/irqdomain.c
kernel/irq/manage.c
kernel/irq/resend.c
kernel/kthread.c
kernel/locking/mutex.c
kernel/locking/osq_lock.c
kernel/locking/rwsem.c
kernel/notifier.c
kernel/panic.c
kernel/resource.c
kernel/sched/clock.c
kernel/sched/completion.c
kernel/sched/swait.c
kernel/sched/wait.c
kernel/smpboot.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/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/crc32.c
lib/ctype.c
lib/debug_locks.c
lib/find_bit.c
lib/hexdump.c
lib/idr.c
lib/irq_regs.c
lib/kasprintf.c
lib/klist.c
lib/kobject.c
lib/kstrtox.c
lib/list_sort.c
lib/iomap.c
lib/pci_iomap.c
lib/radix-tree.c
lib/rbtree.c
lib/scatterlist.c
lib/siphash.c
lib/sort.c
lib/string.c
lib/timerqueue.c
lib/vsprintf.c
lib/xarray.c
mm/mempool.c
mm/util.c

View File

@ -0,0 +1,3 @@
include $(REP_DIR)/src/drivers/usb_host/pc/target.inc
REQUIRES += 64bit

View File

@ -0,0 +1,28 @@
REQUIRES := x86
REL_PRG_DIR := $(PRG_DIR)/../..
TARGET := pc_usb_host_drv
LIBS := base pc_lx_emul
INC_DIR := $(REL_PRG_DIR)
SRC_CC += main.cc
SRC_CC += misc.cc
SRC_CC += time.cc
SRC_C += dummies.c
SRC_C += lx_emul.c
SRC_C += usb.c
SRC_C += $(notdir $(wildcard $(REL_PRG_DIR)/generated_dummies.c))
SRC_C += common_dummies.c
SRC_C += lx_emul/spec/x86/pci.c
vpath %.c $(REL_PRG_DIR)
vpath %.cc $(REL_PRG_DIR)
vpath common_dummies.c $(REP_DIR)/src/lib/pc/lx_emul
#
# Genode C-API backends
#
SRC_CC += genode_c_api/usb.cc
vpath genode_c_api/usb.cc $(subst /genode_c_api,,$(call select_from_repositories,src/lib/genode_c_api))

View File

@ -0,0 +1,25 @@
/*
* \brief Lx_emul udelay function for very short delays
* \author Stefan Kalkowski
* \date 2021-07-10
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <base/log.h>
#include <lx_kit/env.h>
extern "C" void lx_emul_time_udelay(unsigned long usec);
extern "C" void lx_emul_time_udelay(unsigned long usec)
{
if (usec > 100)
Genode::error("Cannot delay that long ", usec, " microseconds");
unsigned long long start = Lx_kit::env().timer.curr_time().trunc_to_plain_us().value;
while (Lx_kit::env().timer.curr_time().trunc_to_plain_us().value < (start + usec)) { ; }
}

View File

@ -0,0 +1,573 @@
/*
* \brief Post kernel userland activity
* \author Stefan Kalkowski
* \date 2021-07-14
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include <lx_emul/task.h>
#include <lx_user/init.h>
#include <lx_user/io.h>
#include <usb.h>
struct usb_find_request {
genode_usb_bus_num_t bus;
genode_usb_dev_num_t dev;
struct usb_device * ret;
};
static int check_usb_device(struct usb_device *usb_dev, void * data)
{
struct usb_find_request * req = (struct usb_find_request *) data;
if (usb_dev->devnum == req->dev && usb_dev->bus->busnum == req->bus)
req->ret = usb_dev;
return 0;
}
static struct usb_device * find_usb_device(genode_usb_bus_num_t bus,
genode_usb_dev_num_t dev)
{
struct usb_find_request req = { bus, dev, NULL };
usb_for_each_dev(&req, check_usb_device);
return req.ret;
}
static struct usb_interface * interface(genode_usb_bus_num_t bus,
genode_usb_dev_num_t dev,
unsigned index)
{
struct usb_device * udev = find_usb_device(bus, dev);
if (!udev)
return NULL;
if (!udev->actconfig)
return NULL;
if (index >= udev->actconfig->desc.bNumInterfaces)
return NULL;
return udev->actconfig->interface[index];
}
static unsigned config_descriptor(genode_usb_bus_num_t bus,
genode_usb_dev_num_t dev,
void * dev_desc, void *conf_desc)
{
struct usb_device * udev = find_usb_device(bus, dev);
if (!udev)
return 0;
memcpy(dev_desc, &udev->descriptor, sizeof(struct usb_device_descriptor));
if (udev->actconfig)
memcpy(conf_desc, &udev->actconfig->desc,
sizeof(struct usb_config_descriptor));
else
memset(conf_desc, 0, sizeof(struct usb_config_descriptor));
return udev->speed;
}
static int alt_settings(genode_usb_bus_num_t bus, genode_usb_dev_num_t dev,
unsigned index)
{
struct usb_interface * iface = interface(bus, dev, index);
return (iface) ? iface->num_altsetting : -1;
}
static int interface_descriptor(genode_usb_bus_num_t bus,
genode_usb_dev_num_t dev,
unsigned index, unsigned setting,
void * buf, unsigned long size, int * active)
{
struct usb_interface * iface = interface(bus, dev, index);
if (!iface)
return -1;
memcpy(buf, &iface->altsetting[setting].desc,
min(sizeof(struct usb_interface_descriptor), size));
*active = &iface->altsetting[setting] == iface->cur_altsetting;
return 0;
}
static int interface_extra(genode_usb_bus_num_t bus,
genode_usb_dev_num_t dev,
unsigned index, unsigned setting,
void * buf, unsigned long size)
{
struct usb_interface * iface = interface(bus, dev, index);
unsigned long len;
if (!iface)
return -1;
len = min((unsigned long)iface->altsetting[setting].extralen, size);
memcpy(buf, iface->altsetting[setting].extra, len);
return len;
}
static int endpoint_descriptor(genode_usb_bus_num_t bus,
genode_usb_dev_num_t dev,
unsigned iface_num, unsigned setting,
unsigned endp, void * buf, unsigned long size)
{
struct usb_device * udev = find_usb_device(bus, dev);
struct usb_interface * iface;
struct usb_host_endpoint * ep;
if (!udev)
return -1;
iface = usb_ifnum_to_if(udev, iface_num);
if (!iface)
return -2;
ep = &iface->altsetting[setting].endpoint[endp];
if (!ep)
return -3;
memcpy(buf, &ep->desc,
min(sizeof(struct usb_endpoint_descriptor), size));
return 0;
}
struct genode_usb_rpc_callbacks genode_usb_rpc_callbacks_obj = {
.alloc_fn = genode_usb_allocate_peer_buffer,
.free_fn = genode_usb_free_peer_buffer,
.cfg_desc_fn = config_descriptor,
.alt_settings_fn = alt_settings,
.iface_desc_fn = interface_descriptor,
.iface_extra_fn = interface_extra,
.endp_desc_fn = endpoint_descriptor,
};
static genode_usb_request_ret_t
handle_ctrl_request(struct genode_usb_request_control * req,
void * buf, unsigned long size, void * data)
{
struct usb_device * udev = (struct usb_device *) data;
int pipe = (req->request_type & 0x80)
? usb_rcvctrlpipe(udev, 0) : usb_sndctrlpipe(udev, 0);
int err = usb_control_msg(udev, pipe, req->request, req->request_type,
req->value, req->index, buf, size, req->timeout);
if (err >= 0) {
req->actual_size = err;
return NO_ERROR;
}
req->actual_size = 0;
switch (err) {
case -ENOENT: return INTERFACE_OR_ENDPOINT_ERROR;
case -ENODEV: return NO_DEVICE_ERROR;
case -ESHUTDOWN: return NO_DEVICE_ERROR;
case -EPROTO: return PROTOCOL_ERROR;
case -EILSEQ: return PROTOCOL_ERROR;
case -EPIPE: return STALL_ERROR;
case -ETIMEDOUT: return TIMEOUT_ERROR;
}
return UNKNOWN_ERROR;
}
static genode_usb_request_ret_t
handle_string_request(struct genode_usb_request_string * req,
void * buf, unsigned long size, void * data)
{
struct usb_device * udev = (struct usb_device *) data;
int length = usb_string(udev, req->index, buf, size);
if (length < 0) {
printk("Could not read string descriptor index: %u\n", req->index);
req->length = 0;
} else {
/* returned length is in bytes (char) */
req->length = length / 2;
return NO_ERROR;
}
return UNKNOWN_ERROR;
}
static genode_usb_request_ret_t
handle_altsetting_request(unsigned iface, unsigned alt_setting, void * data)
{
struct usb_device * udev = (struct usb_device *) data;
return (usb_set_interface(udev, iface, alt_setting)) ? NO_ERROR
: UNKNOWN_ERROR;
}
static genode_usb_request_ret_t
handle_config_request(unsigned cfg_idx, void * data)
{
struct usb_device * udev = (struct usb_device *) data;
return (usb_set_configuration(udev, cfg_idx)) ? UNKNOWN_ERROR : NO_ERROR;
}
static genode_usb_request_ret_t
handle_flush_request(unsigned char ep, void * data)
{
struct usb_device * udev = (struct usb_device *) data;
struct usb_host_endpoint * endpoint =
ep & USB_DIR_IN ? udev->ep_in[ep & 0xf]
: udev->ep_out[ep & 0xf];
if (!endpoint)
return INTERFACE_OR_ENDPOINT_ERROR;
usb_hcd_flush_endpoint(udev, endpoint);
return NO_ERROR;
}
static genode_usb_request_ret_t
handle_transfer_response(struct genode_usb_request_transfer * req,
void * data)
{
struct urb * urb = (struct urb *) data;
int i;
if (urb->status == 0) {
req->actual_size = urb->actual_length;
if (usb_pipein(urb->pipe))
for (i = 0; i < urb->number_of_packets; i++)
req->actual_packet_size[i] = urb->iso_frame_desc[i].actual_length;
return NO_ERROR;
}
switch (urb->status) {
case -ESHUTDOWN: return NO_DEVICE_ERROR;
case -EPROTO: return PROTOCOL_ERROR;
case -EILSEQ: return PROTOCOL_ERROR;
case -EPIPE: return STALL_ERROR;
};
return UNKNOWN_ERROR;
}
static void async_complete(struct urb *urb)
{
unsigned long handle = (unsigned long)urb->context;
genode_usb_session_handle_t session =
(genode_usb_session_handle_t) (handle >> 16);
genode_usb_request_handle_t request =
(genode_usb_request_handle_t) (handle & 0xffff);
genode_usb_ack_request(session, request,
handle_transfer_response, (void*)urb);
usb_free_urb(urb);
lx_user_handle_io();
}
static int fill_bulk_urb(struct usb_device * udev,
struct genode_usb_request_transfer * req,
unsigned long handle,
void * buf,
unsigned long size,
int read,
struct urb ** urb)
{
int pipe = (read)
? usb_rcvbulkpipe(udev, req->ep) : usb_sndbulkpipe(udev, req->ep);
*urb = usb_alloc_urb(0, GFP_KERNEL);
if (!*urb)
return -ENOMEM;
usb_fill_bulk_urb(*urb, udev, pipe, buf, size,
async_complete, (void*)handle);
return 0;
}
static int fill_irq_urb(struct usb_device * udev,
struct genode_usb_request_transfer * req,
unsigned long handle,
void * buf,
unsigned long size,
int read,
struct urb ** urb)
{
int polling_interval;
int pipe = (read)
? usb_rcvintpipe(udev, req->ep) : usb_sndintpipe(udev, req->ep);
*urb = usb_alloc_urb(0, GFP_KERNEL);
if (!*urb)
return -ENOMEM;
if (req->polling_interval == -1) {
struct usb_host_endpoint *ep = (req->ep & USB_DIR_IN) ?
udev->ep_in[req->ep & 0xf] : udev->ep_out[req->ep & 0xf];
if (!ep)
return -ENOENT;
polling_interval = ep->desc.bInterval;
} else
polling_interval = req->polling_interval;
usb_fill_int_urb(*urb, udev, pipe, buf, size,
async_complete, (void*)handle, polling_interval);
return 0;
}
static int fill_isoc_urb(struct usb_device * udev,
struct genode_usb_request_transfer * req,
unsigned long handle,
void * buf,
unsigned long size,
int read,
struct urb ** urb)
{
int i;
unsigned offset = 0;
int pipe = (read)
? usb_rcvisocpipe(udev, req->ep) : usb_sndisocpipe(udev, req->ep);
struct usb_host_endpoint * ep =
req->ep & USB_DIR_IN ? udev->ep_in[req->ep & 0xf]
: udev->ep_out[req->ep & 0xf];
*urb = usb_alloc_urb(req->number_of_packets, GFP_KERNEL);
if (!*urb)
return -ENOMEM;
(*urb)->dev = udev;
(*urb)->pipe = pipe;
(*urb)->start_frame = -1;
(*urb)->stream_id = 0;
(*urb)->transfer_buffer = buf;
(*urb)->transfer_buffer_length = size;
(*urb)->number_of_packets = req->number_of_packets;
(*urb)->interval = 1 << min(15, ep->desc.bInterval - 1);
(*urb)->context = (void *)handle;
(*urb)->transfer_flags = URB_ISO_ASAP | (read ? URB_DIR_IN : URB_DIR_OUT);
(*urb)->complete = async_complete;
for (i = 0; i < req->number_of_packets; i++) {
(*urb)->iso_frame_desc[i].offset = offset;
(*urb)->iso_frame_desc[i].length = req->packet_size[i];
offset += req->packet_size[i];
}
return 0;
}
static genode_usb_request_ret_t
handle_transfer_request(struct genode_usb_request_transfer * req,
genode_usb_transfer_type_t type,
genode_usb_session_handle_t session_handle,
genode_usb_request_handle_t request_handle,
void * buf, unsigned long size, void * data)
{
struct usb_device * udev = (struct usb_device *) data;
int err = 0;
int read = (req->ep & 0x80);
unsigned long handle = session_handle << 16 | request_handle;
struct urb * urb;
switch (type) {
case BULK:
err = fill_bulk_urb(udev, req, handle, buf, size, read, &urb);
break;
case IRQ:
err = fill_irq_urb(udev, req, handle, buf, size, read, &urb);
break;
case ISOC:
err = fill_isoc_urb(udev, req, handle, buf, size, read, &urb);
break;
default:
printk("Unknown USB transfer request!\n");
return UNKNOWN_ERROR;
};
if (!err) {
err = usb_submit_urb(urb, GFP_KERNEL);
if (!err)
return NO_ERROR;
usb_free_urb(urb);
}
switch (err) {
case -ENOENT: return INTERFACE_OR_ENDPOINT_ERROR;
case -ENODEV: return NO_DEVICE_ERROR;
case -ESHUTDOWN: return NO_DEVICE_ERROR;
case -ENOSPC: return STALL_ERROR;
case -ENOMEM: return MEMORY_ERROR;
}
return UNKNOWN_ERROR;
}
static struct genode_usb_request_callbacks request_callbacks = {
.control_fn = handle_ctrl_request,
.transfer_fn = handle_transfer_request,
.string_fn = handle_string_request,
.altsetting_fn = handle_altsetting_request,
.config_fn = handle_config_request,
.flush_fn = handle_flush_request,
};
static int poll_usb_device(struct usb_device *udev, void * data)
{
genode_usb_session_handle_t session =
genode_usb_session_by_bus_dev(udev->bus->busnum, udev->devnum);
int * work_done = (int *) data;
if (!session)
return 0;
for (;;) {
if (!genode_usb_request_by_session(session, &request_callbacks,
(void*)udev))
break;
*work_done = true;
}
return 0;
}
static int usb_poll_sessions(void * data)
{
for (;;) {
int work_done = false;
usb_for_each_dev(&work_done, poll_usb_device);
if (work_done)
continue;
lx_emul_task_schedule(true);
}
return 0;
}
static struct task_struct * lx_user_task = NULL;
void lx_user_handle_io(void)
{
if (lx_user_task)
lx_emul_task_unblock(lx_user_task);
}
void lx_user_init(void)
{
int pid = kernel_thread(usb_poll_sessions, NULL, CLONE_FS | CLONE_FILES);
lx_user_task = find_task_by_pid_ns(pid, NULL);;
}
static int raw_notify(struct notifier_block *nb, unsigned long action, void *data)
{
struct usb_device *udev = (struct usb_device*) data;
switch (action) {
case USB_DEVICE_ADD:
{
/**
* Register pseudo device class of USB device
*
* The registered value expresses the type of USB device.
* If the device has at least one HID interface, the value
* is USB_CLASS_HID. Otherwise, the class of the first interface
* is interpreted as device type.
*
* Note this classification of USB devices is meant as an interim
* solution only to assist the implementation of access-control
* policies.
*/
unsigned long class;
unsigned i;
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
struct usb_interface * iface = udev->actconfig->interface[i];
if (!iface || !iface->cur_altsetting) continue;
if (i == 0 ||
iface->cur_altsetting->desc.bInterfaceClass ==
USB_CLASS_HID)
class = iface->cur_altsetting->desc.bInterfaceClass;
}
genode_usb_announce_device(udev->descriptor.idVendor,
udev->descriptor.idProduct,
class,
udev->bus->busnum,
udev->devnum);
break;
}
case USB_DEVICE_REMOVE:
{
genode_usb_discontinue_device(udev->bus->busnum, udev->devnum);
break;
}
case USB_BUS_ADD:
break;
case USB_BUS_REMOVE:
break;
}
return NOTIFY_OK;
}
struct notifier_block usb_nb =
{
.notifier_call = raw_notify
};
static int usbnet_init(void)
{
usb_register_notify(&usb_nb);
return 0;
}
/**
* Let's hook into the usbnet initcall, so we do not need to register
* an additional one
*/
module_init(usbnet_init);

View File

@ -0,0 +1,32 @@
/**
* \brief USB related definitions for kernel/genode c-api
* \author Stefan Kalkowski
* \date 2021-09-17
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <genode_c_api/usb.h>
struct usb_interface;
#ifdef __cplusplus
extern "C" {
#endif
struct genode_attached_dataspace *
genode_usb_allocate_peer_buffer(unsigned long size);
void genode_usb_free_peer_buffer(struct genode_attached_dataspace * ptr);
extern struct genode_usb_rpc_callbacks genode_usb_rpc_callbacks_obj;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,62 @@
/*
* \brief Dummy definitions of Linux Kernel functions - handled manually
* \author Josef Soentgen
* \date 2022-02-04
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <lx_emul.h>
#include <asm-generic/sections.h>
char __start_rodata[] = {};
char __end_rodata[] = {};
#include <asm/preempt.h>
int __preempt_count = 0;
#include <linux/bitops.h>
unsigned int __sw_hweight32(__u32 w)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/bitops.h>
unsigned long __sw_hweight64(__u64 w)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/prandom.h>
unsigned long net_rand_noise;
#include <linux/tracepoint-defs.h>
const struct trace_print_flags gfpflag_names[] = { {0,NULL}};
#include <linux/tracepoint-defs.h>
const struct trace_print_flags vmaflag_names[] = { {0,NULL}};
#include <linux/tracepoint-defs.h>
const struct trace_print_flags pageflag_names[] = { {0,NULL}};
#include <linux/kernel_stat.h>
struct kernel_stat kstat;