lx_emul: shadow cpu_relax to update jiffies

There are rare use-cases where cpu_relax is used inside a busy loop
(i2c bus functions), which only will break when the jiffies counter
reaches a specific value.
Because of the cooperative scheduling done in lx_emul, no timer
interrupt will break such a loop. As a workaround, we check for
necessary jiffies updates inside cpu_relax if interrupts are enabled.

Ref genodelabs/genode#4778
This commit is contained in:
Stefan Kalkowski 2023-03-02 14:01:41 +01:00 committed by Christian Helmuth
parent 7e2c546d8e
commit 50541c68ec
5 changed files with 93 additions and 39 deletions

View File

@ -0,0 +1,35 @@
/**
* \brief Shadow copy of asm/vdso/processor.h
* \author Stefan Kalkowski
* \date 2023-03-02
*/
#ifndef _LX_EMUL__SHADOW__ARCH__ARM__INCLUDE__ASM__VDSO__PROCESSOR_H_
#define _LX_EMUL__SHADOW__ARCH__ARM__INCLUDE__ASM__VDSO__PROCESSOR_H_
#include <asm/barrier.h>
#include_next <asm/vdso/processor.h>
static inline void __original_linux_cpu_relax(void)
{
cpu_relax();
}
#undef cpu_relax
#include <lx_emul/irq.h>
#include <lx_emul/time.h>
static inline void cpu_relax(void)
{
__original_linux_cpu_relax();
/*
* When irqs are enabled, update jiffies to break potential
* endless busy loops like:
* - slchi() in drivers/i2c/algos/i2c-algo-bit.c
*/
if (!lx_emul_irq_state()) lx_emul_time_update_jiffies();
}
#endif /* _LX_EMUL__SHADOW__ARCH__ARM__INCLUDE__ASM__VDSO__PROCESSOR_H_ */

View File

@ -0,0 +1,29 @@
/**
* \brief Shadow copy of asm/vdso/processor.h
* \author Stefan Kalkowski
* \date 2023-03-02
*/
#ifndef _LX_EMUL__SHADOW__ARCH__ARM64__INCLUDE__ASM__VDSO__PROCESSOR_H_
#define _LX_EMUL__SHADOW__ARCH__ARM64__INCLUDE__ASM__VDSO__PROCESSOR_H_
#define cpu_relax __original_linux_cpu_relax
#include_next <asm/vdso/processor.h>
#undef cpu_relax
#include <lx_emul/irq.h>
#include <lx_emul/time.h>
static __always_inline void cpu_relax(void)
{
__original_linux_cpu_relax();
/*
* When irqs are enabled, update jiffies to break potential
* endless busy loops like:
* - slchi() in drivers/i2c/algos/i2c-algo-bit.c
*/
if (!lx_emul_irq_state()) lx_emul_time_update_jiffies();
}
#endif /* _LX_EMUL__SHADOW__ARCH__ARM64__INCLUDE__ASM__VDSO__PROCESSOR_H_ */

View File

@ -0,0 +1,29 @@
/**
* \brief Shadow copy of asm/vdso/processor.h
* \author Stefan Kalkowski
* \date 2023-03-02
*/
#ifndef _LX_EMUL__SHADOW__ARCH__X86__INCLUDE__ASM__VDSO__PROCESSOR_H_
#define _LX_EMUL__SHADOW__ARCH__X86__INCLUDE__ASM__VDSO__PROCESSOR_H_
#define cpu_relax __original_linux_cpu_relax
#include_next <asm/vdso/processor.h>
#undef cpu_relax
#include <lx_emul/irq.h>
#include <lx_emul/time.h>
static __always_inline void cpu_relax(void)
{
__original_linux_cpu_relax();
/*
* When irqs are enabled, update jiffies to break potential
* endless busy loops like:
* - slchi() in drivers/i2c/algos/i2c-algo-bit.c
*/
if (!lx_emul_irq_state()) lx_emul_time_update_jiffies();
}
#endif /* _LX_EMUL__SHADOW__ARCH__X86__INCLUDE__ASM__VDSO__PROCESSOR_H_ */

View File

@ -1,38 +0,0 @@
/**
* \brief Shadow copy of asm/vdso/processor.h
* \author Alexander Boettcher
* \date 2022-03-23
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __ASM_VDSO_PROCESSOR_H
#define __ASM_VDSO_PROCESSOR_H
#ifndef __ASSEMBLY__
#include <linux/delay.h>
static __always_inline void rep_nop(void)
{
asm volatile("rep; nop" ::: "memory");
}
static __always_inline void cpu_relax(void)
{
/* break busy loop of slchi() in drivers/i2c/algos/i2c-algo-bit.c */
__udelay(100);
}
#endif /* __ASSEMBLY__ */
#endif /* __ASM_VDSO_PROCESSOR_H */

View File

@ -6,7 +6,6 @@ TARGET := pc_intel_fb_drv
LIBS := base pc_lx_emul blit jitterentropy
INC_DIR += $(REL_PRG_DIR)
INC_DIR += $(REL_PRG_DIR)/shadow
SRC_CC += main.cc
SRC_CC += emul.cc