lx_emul: adjust to Linux 6.6.47

Issue #5264
This commit is contained in:
Sebastian Sumpf 2024-06-27 11:48:24 +02:00 committed by Christian Helmuth
parent bb214af3eb
commit 92b34837cb
23 changed files with 293 additions and 25 deletions

View File

@ -1,7 +1,7 @@
/*
* \brief Dummy definitions of Linux Kernel functions
* \author Automatically generated file - do no edit
* \date 2024-07-16
* \date 2024-07-30
*/
#include <lx_emul.h>
@ -89,14 +89,6 @@ int _printk_deferred(const char * fmt,...)
}
#include <linux/spinlock_api_smp.h>
noinline int __lockfunc _raw_spin_trylock_bh(raw_spinlock_t * lock)
{
lx_emul_trace_and_stop(__func__);
}
#include <linux/mm.h>
atomic_long_t _totalram_pages;

View File

@ -15,6 +15,7 @@
#define __ASM_PGTABLE_H
#include <linux/const.h>
#include <linux/version.h>
#include <asm/proc-fns.h>
#include <asm-generic/pgtable-nopud.h>
#include <asm-generic/pgtable_uffd.h>
@ -26,7 +27,11 @@
extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
#define ZERO_PAGE(vaddr) ((void)(vaddr),virt_to_page(empty_zero_page))
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,5,0)
pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma);
#else
pte_t pte_mkwrite(pte_t pte);
#endif
int pte_none(pte_t pte);
int pte_present(pte_t pte);
@ -41,7 +46,7 @@ int pte_write(pte_t ptr);
#define __swp_entry(type, offset) ( lx_emul_trace_and_stop(__func__), (swp_entry_t) { 0 } )
#define __swp_entry_to_pte(swp) ((pte_t) { (swp).val })
#define pmd_page(pmd) NULL
struct page *pmd_page(pmd_t pmd);
#define PAGE_KERNEL 0UL

View File

@ -28,7 +28,16 @@
extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
#define ZERO_PAGE(vaddr) ((void)(vaddr),virt_to_page(empty_zero_page))
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,5,0)
struct vm_area_struct;
#ifndef pte_mkwrite
pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma);
#endif
#else
pte_t pte_mkwrite(pte_t pte);
#endif
pte_t pte_get(pte_t pte);
pte_t pte_wrprotect(pte_t pte);

View File

@ -0,0 +1,24 @@
/**
* \brief Shadow asm/bug.h for x86
* \author Sebastian Sumpf
* \date 2024-06-27
*/
/*
* This file shadows arch/x86/include/asm/bug.h to avoid HAVE_ARCH_BUG which
* inserts undefined instructions (ud2) and use our own BUG() implementation.
*/
#ifndef _LX_EMUL__SHADOW__ARCH__X86__INCLUDE__ASM__BUG_H_
#define _LX_EMUL__SHADOW__ARCH__X86__INCLUDE__ASM__BUG_H_
#define HAVE_ARCH_BUG
#define BUG() do { \
printk("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
while (1) { } \
} while (0);
#include <asm-generic/bug.h>
#endif /* _LX_EMUL__SHADOW__ARCH__X86__INCLUDE__ASM__BUG_H_ */

View File

@ -0,0 +1,52 @@
/*
* \brief Shadow copy of asm/current.h
* \author Sebastian Sumpf
* \date 2024-06-26
*/
#ifndef _LX_EMUL__SHADOW__ARCH__X86__INCLUDE__ASM__CURRENT_H_
#define _LX_EMUL__SHADOW__ARCH__X86__INCLUDE__ASM__CURRENT_H_
#include <linux/compiler.h>
#ifndef __ASSEMBLY__
#include <linux/build_bug.h>
#include <linux/version.h>
#include_next <asm/current.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,0)
struct task_struct;
struct pcpu_hot {
union {
struct {
struct task_struct *current_task;
int preempt_count;
int cpu_number;
#ifdef CONFIG_CALL_DEPTH_TRACKING
u64 call_depth;
#endif
unsigned long top_of_stack;
void *hardirq_stack_ptr;
u16 softirq_pending;
#ifdef CONFIG_X86_64
bool hardirq_stack_inuse;
#else
void *softirq_stack_ptr;
#endif
};
u8 pad[64];
};
};
static_assert(sizeof(struct pcpu_hot) == 64);
extern struct pcpu_hot pcpu_hot;
#endif /* LINUX_VERSION_CODE */
#endif /* __ASSEMBLY__ */
#endif /*_LX_EMUL__SHADOW__ARCH__X86__INCLUDE__ASM__CURRENT_H_ */

View File

@ -4,8 +4,8 @@
* \date 2022-06-29
*/
#ifndef _LX_EMUL__SHADOW__ARCH__X89__INCLUDE__ASM__IRQ_STACK_H_
#define _LX_EMUL__SHADOW__ARCH__X89__INCLUDE__ASM__IRQ_STACK_H_
#ifndef _LX_EMUL__SHADOW__ARCH__X86__INCLUDE__ASM__IRQ_STACK_H_
#define _LX_EMUL__SHADOW__ARCH__X86__INCLUDE__ASM__IRQ_STACK_H_
#include_next <asm/irq_stack.h>
@ -42,4 +42,4 @@
__do_softirq(); \
}
#endif /* _LX_EMUL__SHADOW__ARCH__X89__INCLUDE__ASM__IRQ_STACK_H_ */
#endif /* _LX_EMUL__SHADOW__ARCH__X86__INCLUDE__ASM__IRQ_STACK_H_ */

View File

@ -15,6 +15,7 @@
#define _ASM__X86__PGTABLE_H
#include <linux/mem_encrypt.h>
#include <linux/version.h>
#include <asm/page.h>
#include <asm/pgtable_types.h>
@ -40,7 +41,13 @@ static inline unsigned long pmd_pfn(pmd_t pmd)
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,5,0)
struct vm_area_struct;
static inline pte_t pte_mkwrite(pte_t pte, struct vm_area_struct *vma) {
return pte; }
#else
static inline pte_t pte_mkwrite(pte_t pte) { return pte; }
#endif
static inline bool __pkru_allows_pkey(u16 pkey, bool write)
{
@ -64,7 +71,7 @@ static inline int pud_none(pud_t pud)
#endif
#define pmd_page(pmd) NULL
struct page *pmd_page(pmd_t pmd);
#endif /*_ASM__X86__PGTABLE_H */

View File

@ -7,4 +7,7 @@
#ifndef _ASM__STRING_32_H_
#define _ASM__STRING_32_H_
#include <asm-generic/asm-prototypes.h>
extern int memcmp(const void *, const void *, size_t);
#endif /* _ASM__STRING_32_H_ */

View File

@ -12,4 +12,10 @@ unsigned long raw_copy_to_user(void *to, const void *from, unsigned long n);
int __copy_from_user_inatomic_nocache(void *dst, const void __user *src,
unsigned size);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,3,0)
unsigned long __must_check clear_user(void __user *mem, unsigned long len);
unsigned long __must_check __clear_user(void __user *mem, unsigned long len);
#endif
#endif /* _ASM__UACCESS_32_H_ */

View File

@ -9,6 +9,9 @@ void lx_emul_usb_client_init(void);
void lx_emul_usb_client_rom_update(void);
void lx_emul_usb_client_ticker(void);
struct usb_device;
void lx_emul_usb_client_device_unregister_callback(struct usb_device *);
#ifdef __cplusplus
} /* extern "C" */
#endif

View File

@ -79,7 +79,13 @@ static struct task_struct *led_task = NULL;
void lx_emul_input_leds_init(void)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,3,0)
int pid = kernel_thread(led_task_loop, &led_task, "led_task",
CLONE_FS | CLONE_FILES);
#else
int pid = kernel_thread(led_task_loop, &led_task, CLONE_FS | CLONE_FILES);
#endif
led_task = find_task_by_pid_ns(pid, NULL);
}

View File

@ -30,13 +30,19 @@
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wframe-larger-than="
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,3,0)
pid_t kernel_thread(int (* fn)(void *),void * arg, const char *name,
unsigned long flags)
#else
pid_t kernel_thread(int (* fn)(void *),void * arg,unsigned long flags)
#endif
{
static int pid_counter = FIRST_PID;
struct cred * cred;
struct task_struct * task;
struct signal_struct *signal;
char const *thread_name = "kthread";
cred = kzalloc(sizeof (struct cred), GFP_KERNEL);
if (!cred)
@ -79,6 +85,13 @@ pid_t kernel_thread(int (* fn)(void *),void * arg,unsigned long flags)
.signal = signal,
};
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,3,0)
if (name) {
strscpy_pad(task->comm, name, sizeof(task->comm));
thread_name = name;
}
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,17,0)
if (!set_kthread_struct(task)) {
kfree(task);
@ -96,7 +109,7 @@ pid_t kernel_thread(int (* fn)(void *),void * arg,unsigned long flags)
task_thread_info(task)->preempt_count = 0;
#endif
lx_emul_task_create(task, "kthread", task->pid, fn, arg);
lx_emul_task_create(task, thread_name, task->pid, fn, arg);
#ifdef CONFIG_THREAD_INFO_IN_TASK
task->stack = lx_emul_task_stack(task);

View File

@ -70,6 +70,19 @@ int __lockfunc _raw_spin_trylock(raw_spinlock_t * lock)
#endif
#ifndef CONFIG_INLINE_SPIN_TRYLOCK_BH
noinline int __lockfunc _raw_spin_trylock_bh(raw_spinlock_t *lock)
{
__local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
if (_raw_spin_trylock(lock))
return 1;
__local_bh_enable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET);
return 0;
}
#endif
#ifdef CONFIG_UNINLINE_SPIN_UNLOCK
void __lockfunc _raw_spin_unlock(raw_spinlock_t * lock)
{

View File

@ -12,7 +12,9 @@
*/
#include <linux/percpu.h>
#include <linux/slab.h>
#include <linux/srcu.h>
#include <linux/version.h>
int __srcu_read_lock(struct srcu_struct * ssp)
{
@ -25,6 +27,8 @@ void __srcu_read_unlock(struct srcu_struct * ssp, int idx) { }
#ifndef CONFIG_DEBUG_LOCK_ALLOC
#if LINUX_VERSION_CODE < KERNEL_VERSION(6,3,0)
int init_srcu_struct(struct srcu_struct * ssp)
{
mutex_init(&ssp->srcu_cb_mutex);
@ -42,4 +46,27 @@ int init_srcu_struct(struct srcu_struct * ssp)
smp_store_release(&ssp->srcu_gp_seq_needed, 0); /* Init done. */
return ssp->sda ? 0 : -ENOMEM;
}
#endif
#else
int init_srcu_struct(struct srcu_struct * ssp)
{
ssp->srcu_sup = kzalloc(sizeof(*ssp->srcu_sup), GFP_KERNEL);
if (!ssp->srcu_sup)
return -ENOMEM;
mutex_init(&ssp->srcu_sup->srcu_cb_mutex);
mutex_init(&ssp->srcu_sup->srcu_gp_mutex);
ssp->srcu_idx = 0;
ssp->srcu_sup->srcu_gp_seq = 0;
ssp->srcu_sup->srcu_barrier_seq = 0;
mutex_init(&ssp->srcu_sup->srcu_barrier_mutex);
atomic_set(&ssp->srcu_sup->srcu_barrier_cpu_cnt, 0);
/* INIT_DELAYED_WORK(&ssp->work, process_srcu); */
ssp->sda = alloc_percpu(struct srcu_data);
/* init_srcu_struct_nodes(ssp, false); */
ssp->srcu_sup->srcu_gp_seq_needed_exp = 0;
ssp->srcu_sup->srcu_last_gp_end = ktime_get_mono_fast_ns();
smp_store_release(&ssp->srcu_sup->srcu_gp_seq_needed, 0); /* Init done. */
return ssp->sda ? 0 : -ENOMEM;
}
#endif /* LINUX_VERSION_CODE */
#endif /* CONFIG_DEBUG_LOCK_ALLOC */

View File

@ -68,7 +68,7 @@ void call_rcu(struct rcu_head * head,
func(head);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(6,2,0)
void kvfree_call_rcu(struct rcu_head * head, rcu_callback_t func)
{
void *ptr;
@ -90,3 +90,21 @@ void kvfree_call_rcu(struct rcu_head * head, rcu_callback_t func)
}
kvfree(ptr);
}
#else
void kvfree_call_rcu(struct rcu_head * head, void *ptr)
{
/*
* (original Linux comment)
*
* Please note there is a limitation for the head-less
* variant, that is why there is a clear rule for such
* objects: it can be used from might_sleep() context
* only. For other places please embed an rcu_head to
* your data.
*/
if (!head)
might_sleep();
kvfree(ptr);
}
#endif

View File

@ -61,7 +61,7 @@ void set_user_nice(struct task_struct * p, long nice)
}
static int
int
try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
{
if (!p) lx_emul_trace_and_stop(__func__);
@ -190,7 +190,8 @@ int wake_up_state(struct task_struct * p, unsigned int state)
}
#ifdef CONFIG_SMP
/* Linux 6.4+ uses full-fat wait_task_inactive for the UP case */
#if defined CONFIG_SMP || LINUX_VERSION_CODE >= KERNEL_VERSION(6,4,0)
unsigned long wait_task_inactive(struct task_struct * p,
wait_task_inactive_match_state_t match_state)
{
@ -212,8 +213,9 @@ unsigned long wait_task_inactive(struct task_struct * p,
return 1;
}
#endif /* CONFIG_SMP || LINUX_VERSION_CODE */
#ifdef CONFIG_SMP
int set_cpus_allowed_ptr(struct task_struct * p,
const struct cpumask * new_mask)
{

View File

@ -30,6 +30,9 @@ EXPORT_SYMBOL(init_on_alloc);
DEFINE_STATIC_KEY_MAYBE(CONFIG_INIT_ON_FREE_DEFAULT_ON, init_on_free);
EXPORT_SYMBOL(init_on_free);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,4,0)
#include <../mm/internal.h>
#endif
static void prepare_compound_page(struct page *page, unsigned int order, gfp_t gfp)
{
@ -39,7 +42,17 @@ static void prepare_compound_page(struct page *page, unsigned int order, gfp_t g
return;
__SetPageHead(page);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,4,0)
if (!page_folio(page)) {
printk("BUG: %s:%d folio is NULL\n", __func__, __LINE__);
lx_emul_backtrace();
}
folio_set_order(page_folio(page), order);
#else
set_compound_order(page, order);
#endif
for (i = 1; i < compound_nr(page); i++)
set_compound_head(&page[i], page);
}

View File

@ -62,6 +62,9 @@ void * kmalloc_order(size_t size, gfp_t flags, unsigned int order)
}
size_t kmalloc_size_roundup(size_t size) { return size; }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,0) || defined(CONFIG_NUMA)
void * __kmalloc_node(size_t size, gfp_t flags, int node)
{
@ -109,3 +112,17 @@ void kmem_cache_destroy(struct kmem_cache *cache)
if (!cache->refcount)
kfree(cache);
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,0,0)
void *kmalloc_trace(struct kmem_cache *s, gfp_t gfpflags, size_t size)
{
return __kmalloc(size, gfpflags);
}
void *kmalloc_node_trace(struct kmem_cache *s, gfp_t gfpflags,
int node, size_t size)
{
return __kmalloc(size, gfpflags);
}
#endif

View File

@ -23,6 +23,14 @@ unsigned long long sched_clock(void)
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,4,0)
unsigned long long sched_clock_noinstr(void)
{
return sched_clock();
}
#endif
void time_init(void)
{
lx_emul_time_init(); /* replaces timer_probe() */

View File

@ -25,6 +25,7 @@
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/slab.h>
#include <linux/sched/clock.h>
#include <linux/tick.h>
#include <linux/of.h>
#include <linux/of_clk.h>
@ -32,6 +33,8 @@
#include <linux/version.h>
#include <net/net_namespace.h>
#include <../mm/slab.h>
/* definitions in drivers/base/base.h */
extern int devices_init(void);
extern int buses_init(void);
@ -135,6 +138,11 @@ int lx_emul_init_task_function(void * dtb)
kmem_cache_init();
wait_bit_init();
radix_tree_init();
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,2,0)
maple_tree_init();
#endif
workqueue_init_early();
skb_init();
@ -155,9 +163,16 @@ int lx_emul_init_task_function(void * dtb)
net_ns_init();
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,3,0)
kernel_thread(kernel_init, NULL, "init", CLONE_FS);
kernel_thread(kernel_idle, NULL, "idle", CLONE_FS);
pid = kernel_thread(kthreadd, NULL, "kthreadd", CLONE_FS | CLONE_FILES);
#else
kernel_thread(kernel_init, NULL, CLONE_FS);
kernel_thread(kernel_idle, NULL, CLONE_FS);
pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
#endif
kthreadd_task = find_task_by_pid_ns(pid, NULL);;
system_state = SYSTEM_SCHEDULING;

View File

@ -92,7 +92,14 @@ static void open_usb_dev(struct usb_device * udev)
data = kmalloc(sizeof(struct usb_per_dev_data), GFP_KERNEL);
data->dev = udev;
data->kill_task = false;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,3,0)
pid = kernel_thread(poll_usb_device, data, "poll_device",
CLONE_FS | CLONE_FILES);
#else
pid = kernel_thread(poll_usb_device, data, CLONE_FS | CLONE_FILES);
#endif
data->task = find_task_by_pid_ns(pid, NULL);
init_usb_anchor(&data->submitted);
dev_set_drvdata(&udev->dev, data);
@ -458,8 +465,13 @@ void lx_user_handle_io(void)
void lx_user_init(void)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,3,0)
int pid = kernel_thread(usb_poll_empty_sessions, NULL,
"usb_poll", CLONE_FS | CLONE_FILES);
#else
int pid = kernel_thread(usb_poll_empty_sessions, NULL,
CLONE_FS | CLONE_FILES);
#endif
lx_user_task = find_task_by_pid_ns(pid, NULL);
}

View File

@ -134,6 +134,15 @@ void ignore_signals(struct task_struct * t)
}
#include <linux/random.h>
int __cold execute_with_initialized_rng(struct notifier_block * nb)
{
lx_emul_trace(__func__);
return 0;
}
#ifdef CONFIG_TREE_SRCU
#include <linux/srcu.h>
@ -142,3 +151,7 @@ void synchronize_srcu(struct srcu_struct * ssp)
lx_emul_trace_and_stop(__func__);
}
#endif
extern void __init maple_tree_init(void);
void __init maple_tree_init(void) { }

View File

@ -46,6 +46,7 @@ static void * register_device(genode_usb_client_dev_handle_t handle,
int err;
static int num = 0;
struct usb_device * udev;
struct usb_device_descriptor *descr = NULL;
udev = usb_alloc_dev(NULL, &dummy_hc_device()->self, 0);
if (!udev) {
@ -87,13 +88,18 @@ static void * register_device(genode_usb_client_dev_handle_t handle,
dev_set_name(&udev->dev, "%s", label);
device_set_wakeup_capable(&udev->dev, 1);
udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
err = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
if (err < 0) {
dev_err(&udev->dev, "can't read device descriptor: %d\n", err);
descr = usb_get_device_descriptor(udev);
if (PTR_ERR(descr) < 0) {
dev_err(&udev->dev, "can't read device descriptor: %ld\n", PTR_ERR(descr));
kfree(descr);
usb_put_dev(udev);
return NULL;
}
udev->descriptor = *descr;
kfree(descr);
err = usb_new_device(udev);
if (err) {
printk("error: usb_new_device failed %d\n", err);
@ -160,6 +166,10 @@ static void unregister_device(genode_usb_client_dev_handle_t handle, void *data)
struct usb_device *udev = (struct usb_device *)data;
genode_usb_client_device_update(urb_out, urb_in, isoc_urb_out,
isoc_urb_in, urb_complete);
/* inform driver about ongoing unregister before disconnection */
lx_emul_usb_client_device_unregister_callback(udev);
udev->filelist.prev = NULL;
usb_disconnect(&udev);
usb_put_dev(udev);
@ -200,10 +210,10 @@ void lx_emul_usb_client_init(void)
{
pid_t pid;
pid = kernel_thread(usb_rom_loop, NULL, CLONE_FS | CLONE_FILES);
pid = kernel_thread(usb_rom_loop, NULL, "usb_rom_task", CLONE_FS | CLONE_FILES);
usb_rom_task = find_task_by_pid_ns(pid, NULL);
pid = kernel_thread(usb_loop, NULL, CLONE_FS | CLONE_FILES);
pid = kernel_thread(usb_loop, NULL, "usb_task", CLONE_FS | CLONE_FILES);
usb_task = find_task_by_pid_ns(pid, NULL);
}