From 6a7a30ceaac2a84b0d01406c89fac3e7607e69f9 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Thu, 2 Mar 2023 12:43:15 +0100 Subject: [PATCH] lx_emul: unify udelay implementation Implement udelay for all architectures within common lx_emul code, remove driver-specific version. Always do busy looping in udelay and use cpu_relax() like the original Linux code. Thereby, we profit from architecture specific instructions (cpu cool down), and jiffies are updated if irqs are on. Ref genodelabs/genode#4778 --- .../lib/import/import-lx_emul_common.inc | 1 + .../shadow/arch/arm/include/asm/delay.h | 25 +++++++ .../src/lib/lx_emul/shadow/lib/delay.c | 38 +++++++++++ repos/pc/lib/import/import-pc_lx_emul.mk | 1 - repos/pc/lib/mk/wifi.inc | 1 - .../drivers/framebuffer/intel/pc/lx_emul.h | 2 - .../drivers/framebuffer/intel/pc/target.inc | 1 - .../src/drivers/framebuffer/intel/pc/time.cc | 25 ------- repos/pc/src/drivers/usb_host/pc/lx_emul.h | 10 --- repos/pc/src/drivers/usb_host/pc/target.inc | 1 - repos/pc/src/drivers/usb_host/pc/time.cc | 25 ------- repos/pc/src/lib/pc/lx_emul/delay.c | 68 ------------------- repos/pc/src/lib/wifi/lx_emul.h | 2 - repos/pc/src/lib/wifi/time.cc | 25 ------- repos/pc/src/test/driver_time/lx_emul.h | 11 --- repos/pc/src/test/driver_time/target.mk | 2 +- repos/pc/src/test/driver_time/time.cc | 25 ------- 17 files changed, 65 insertions(+), 198 deletions(-) create mode 100644 repos/dde_linux/src/include/lx_emul/shadow/arch/arm/include/asm/delay.h create mode 100644 repos/dde_linux/src/lib/lx_emul/shadow/lib/delay.c delete mode 100644 repos/pc/src/drivers/framebuffer/intel/pc/time.cc delete mode 100644 repos/pc/src/drivers/usb_host/pc/time.cc delete mode 100644 repos/pc/src/lib/pc/lx_emul/delay.c delete mode 100644 repos/pc/src/lib/wifi/time.cc delete mode 100644 repos/pc/src/test/driver_time/time.cc diff --git a/repos/dde_linux/lib/import/import-lx_emul_common.inc b/repos/dde_linux/lib/import/import-lx_emul_common.inc index 3d4049eeb3..da786556a1 100644 --- a/repos/dde_linux/lib/import/import-lx_emul_common.inc +++ b/repos/dde_linux/lib/import/import-lx_emul_common.inc @@ -37,6 +37,7 @@ SRC_C += lx_emul/shadow/kernel/sched/sched.c SRC_C += lx_emul/shadow/kernel/smp.c SRC_C += lx_emul/shadow/kernel/stop_machine.c SRC_C += lx_emul/shadow/lib/cpumask.c +SRC_C += lx_emul/shadow/lib/delay.c SRC_C += lx_emul/shadow/mm/percpu.c SRC_C += lx_emul/shadow/mm/slab_common.c SRC_C += lx_emul/shadow/mm/slub.c diff --git a/repos/dde_linux/src/include/lx_emul/shadow/arch/arm/include/asm/delay.h b/repos/dde_linux/src/include/lx_emul/shadow/arch/arm/include/asm/delay.h new file mode 100644 index 0000000000..1f993b308c --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/shadow/arch/arm/include/asm/delay.h @@ -0,0 +1,25 @@ +/* + * \brief Shadows Linux kernel arch/arm/include/asm/delay.h + * \author Stefan Kalkowski + * \date 2023-03-03 + */ + +/* + * Copyright (C) 2023 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef __ASM_DELAY_H +#define __ASM_DELAY_H + +/* + * We shadow the original arm variant and use the generic version instead, + * like x86 and arm64. Thereby, we can simply use one and the same backend + * function for udelay, which is part of our emulation codebase anyway. + */ +#include + +#endif + diff --git a/repos/dde_linux/src/lib/lx_emul/shadow/lib/delay.c b/repos/dde_linux/src/lib/lx_emul/shadow/lib/delay.c new file mode 100644 index 0000000000..3a80f3b117 --- /dev/null +++ b/repos/dde_linux/src/lib/lx_emul/shadow/lib/delay.c @@ -0,0 +1,38 @@ +/* + * \brief Supplement for emulation for arch-specific lib/delay.c + * \author Stefan Kalkowski + * \date 2023-03-02 + */ + +/* + * Copyright (C) 2023 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + + +#include +#include +#include + +#include +#include + + +void __const_udelay(unsigned long xloops) +{ + unsigned long const usecs = xloops / 0x10C7UL; + __udelay(usecs); +} + + +void __udelay(unsigned long usecs) +{ + /* + * if interrupts are open, jiffies get updated implicitely + * by call of cpu_relax() + */ + unsigned long long end = lx_emul_time_counter() + usecs; + while (lx_emul_time_counter() < end) cpu_relax(); +} diff --git a/repos/pc/lib/import/import-pc_lx_emul.mk b/repos/pc/lib/import/import-pc_lx_emul.mk index d67b81aee7..f737db844e 100644 --- a/repos/pc/lib/import/import-pc_lx_emul.mk +++ b/repos/pc/lib/import/import-pc_lx_emul.mk @@ -48,7 +48,6 @@ SRC_C += lx_emul/mapping.c SRC_C += lx_emul/page_alloc.c SRC_C += lx_emul/sched_core.c SRC_C += lx_emul/vmalloc.c -SRC_C += lx_emul/delay.c SRC_C += lx_emul/shadow/fs/libfs.c SRC_C += lx_emul/shadow/lib/logic_iomem.c diff --git a/repos/pc/lib/mk/wifi.inc b/repos/pc/lib/mk/wifi.inc index c032a9fa16..acb2739ac2 100644 --- a/repos/pc/lib/mk/wifi.inc +++ b/repos/pc/lib/mk/wifi.inc @@ -12,7 +12,6 @@ SRC_CC += wlan.cc SRC_CC += firmware.cc SRC_CC += socket_call.cc SRC_CC += lx_emul/random.cc -SRC_CC += time.cc SRC_C += dummies.c SRC_C += lx_emul.c diff --git a/repos/pc/src/drivers/framebuffer/intel/pc/lx_emul.h b/repos/pc/src/drivers/framebuffer/intel/pc/lx_emul.h index a8be1f2e07..97cc1d2c06 100644 --- a/repos/pc/src/drivers/framebuffer/intel/pc/lx_emul.h +++ b/repos/pc/src/drivers/framebuffer/intel/pc/lx_emul.h @@ -26,8 +26,6 @@ extern "C" { struct dma_fence_work; struct dma_fence_work_ops; -void lx_emul_time_udelay(unsigned long usec); - void *emul_alloc_shmem_file_buffer(unsigned long); void emul_free_shmem_file_buffer(void *); diff --git a/repos/pc/src/drivers/framebuffer/intel/pc/target.inc b/repos/pc/src/drivers/framebuffer/intel/pc/target.inc index 39db2b89cd..50556f5af7 100644 --- a/repos/pc/src/drivers/framebuffer/intel/pc/target.inc +++ b/repos/pc/src/drivers/framebuffer/intel/pc/target.inc @@ -9,7 +9,6 @@ INC_DIR += $(REL_PRG_DIR) SRC_CC += main.cc SRC_CC += emul.cc -SRC_CC += time.cc SRC_CC += opregion_io_mem.cc SRC_C += dummies.c SRC_C += pci.c diff --git a/repos/pc/src/drivers/framebuffer/intel/pc/time.cc b/repos/pc/src/drivers/framebuffer/intel/pc/time.cc deleted file mode 100644 index 0f8f40ad69..0000000000 --- a/repos/pc/src/drivers/framebuffer/intel/pc/time.cc +++ /dev/null @@ -1,25 +0,0 @@ -/* - * \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 -#include - -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)) { ; } -} diff --git a/repos/pc/src/drivers/usb_host/pc/lx_emul.h b/repos/pc/src/drivers/usb_host/pc/lx_emul.h index 2b25b75d96..b2b78b51fb 100644 --- a/repos/pc/src/drivers/usb_host/pc/lx_emul.h +++ b/repos/pc/src/drivers/usb_host/pc/lx_emul.h @@ -19,13 +19,3 @@ /* fix for missing include in linux/dynamic_debug.h */ #include - -#ifdef __cplusplus -extern "C" { -#endif - -void lx_emul_time_udelay(unsigned long usec); - -#ifdef __cplusplus -} -#endif diff --git a/repos/pc/src/drivers/usb_host/pc/target.inc b/repos/pc/src/drivers/usb_host/pc/target.inc index d9c11ce49e..e6ca4b8df5 100644 --- a/repos/pc/src/drivers/usb_host/pc/target.inc +++ b/repos/pc/src/drivers/usb_host/pc/target.inc @@ -7,7 +7,6 @@ LIBS := base pc_lx_emul jitterentropy INC_DIR += $(REL_PRG_DIR) SRC_CC += main.cc -SRC_CC += time.cc SRC_CC += lx_emul/shared_dma_buffer.cc SRC_C += dummies.c SRC_C += lx_emul.c diff --git a/repos/pc/src/drivers/usb_host/pc/time.cc b/repos/pc/src/drivers/usb_host/pc/time.cc deleted file mode 100644 index 0f8f40ad69..0000000000 --- a/repos/pc/src/drivers/usb_host/pc/time.cc +++ /dev/null @@ -1,25 +0,0 @@ -/* - * \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 -#include - -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)) { ; } -} diff --git a/repos/pc/src/lib/pc/lx_emul/delay.c b/repos/pc/src/lib/pc/lx_emul/delay.c deleted file mode 100644 index febbbd9a1e..0000000000 --- a/repos/pc/src/lib/pc/lx_emul/delay.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * \brief Supplement for emulation for linux/include/asm-generic/delay.h - * \author Josef Soentgen - * \author Alexander Boettcher - * \date 2022-05-05 - */ - -/* - * Copyright (C) 2022 Genode Labs GmbH - * - * This file is distributed under the terms of the GNU General Public License - * version 2. - */ - - -#include -#include -#include - -#include - - -void __const_udelay(unsigned long xloops) -{ - unsigned long const usecs = xloops / 0x10C7UL; - __udelay(usecs); -} - - -void __udelay(unsigned long usecs) -{ - /* - * Account for delays summing up to equivalent of 1 jiffie during - * jiffies_64 stays same. When 1 jiffie is reached in sum, - * increase jiffie_64 to break endless loops, seen in - * * intel_fb - cpu_relax(void) emulation used by - * busy loop of slchi() in drivers/i2c/algos/i2c-algo-bit.c - * * wifi_drv - net/wireless/intel/iwlwif* code during error code handling - */ - static uint64_t last_jiffie = 0; - static unsigned long delayed_sum = 0; - - if (jiffies_64 == last_jiffie) { - delayed_sum += usecs; - } else { - last_jiffie = jiffies_64; - delayed_sum = usecs; - } - - if (usecs < 100) - lx_emul_time_udelay(usecs); - else { - unsigned long slept = 0; - while (slept < usecs) { - lx_emul_time_udelay(100); - slept += 100; - } - } - - /* - * When delays sum up to the equivalent of 1 jiffie, - * increase it to break endless loops. - */ - if (delayed_sum >= jiffies_to_usecs(1)) { - jiffies_64 ++; - delayed_sum = 0; - } -} diff --git a/repos/pc/src/lib/wifi/lx_emul.h b/repos/pc/src/lib/wifi/lx_emul.h index 8d1e9bb67c..7d4ccf12e0 100644 --- a/repos/pc/src/lib/wifi/lx_emul.h +++ b/repos/pc/src/lib/wifi/lx_emul.h @@ -24,8 +24,6 @@ extern "C" { #endif -void lx_emul_time_udelay(unsigned long usec); - int lx_emul_rfkill_get_any(void); void lx_emul_rfkill_switch_all(int blocked); diff --git a/repos/pc/src/lib/wifi/time.cc b/repos/pc/src/lib/wifi/time.cc deleted file mode 100644 index 0f8f40ad69..0000000000 --- a/repos/pc/src/lib/wifi/time.cc +++ /dev/null @@ -1,25 +0,0 @@ -/* - * \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 -#include - -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)) { ; } -} diff --git a/repos/pc/src/test/driver_time/lx_emul.h b/repos/pc/src/test/driver_time/lx_emul.h index acee561257..4c60a2f777 100644 --- a/repos/pc/src/test/driver_time/lx_emul.h +++ b/repos/pc/src/test/driver_time/lx_emul.h @@ -10,14 +10,3 @@ * This file is distributed under the terms of the GNU General Public License * version 2. */ - - -#ifdef __cplusplus -extern "C" { -#endif - -void lx_emul_time_udelay(unsigned long usec); - -#ifdef __cplusplus -} -#endif diff --git a/repos/pc/src/test/driver_time/target.mk b/repos/pc/src/test/driver_time/target.mk index ba7f8e5769..4a4beeb3c4 100644 --- a/repos/pc/src/test/driver_time/target.mk +++ b/repos/pc/src/test/driver_time/target.mk @@ -3,7 +3,7 @@ REQUIRES := x86_64 TARGET := test-driver_time LIBS := base pc_lx_emul jitterentropy -SRC_CC += main.cc time.cc +SRC_CC += main.cc SRC_C += lx_user.c SRC_C += dummies.c SRC_C += generated_dummies.c diff --git a/repos/pc/src/test/driver_time/time.cc b/repos/pc/src/test/driver_time/time.cc deleted file mode 100644 index 0f8f40ad69..0000000000 --- a/repos/pc/src/test/driver_time/time.cc +++ /dev/null @@ -1,25 +0,0 @@ -/* - * \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 -#include - -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)) { ; } -}