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 600b37b075..3d4049eeb3 100644 --- a/repos/dde_linux/lib/import/import-lx_emul_common.inc +++ b/repos/dde_linux/lib/import/import-lx_emul_common.inc @@ -16,6 +16,7 @@ SRC_CC += lx_emul/log.cc SRC_CC += lx_emul/page_virt.cc SRC_CC += lx_emul/task.cc SRC_CC += lx_emul/time.cc +SRC_CC += lx_emul/irq_flags.cc SRC_C += lx_emul/clocksource.c SRC_C += lx_emul/shadow/fs/exec.c diff --git a/repos/dde_linux/src/include/lx_emul/irq.h b/repos/dde_linux/src/include/lx_emul/irq.h index e98a37b121..6914a8bc1e 100644 --- a/repos/dde_linux/src/include/lx_emul/irq.h +++ b/repos/dde_linux/src/include/lx_emul/irq.h @@ -34,6 +34,12 @@ extern void * lx_emul_irq_task_struct; unsigned int lx_emul_irq_last(void); int lx_emul_irq_init(struct device_node *node, struct device_node *parent); + +unsigned long lx_emul_irq_enable(void); +unsigned long lx_emul_irq_disable(void); +unsigned long lx_emul_irq_state(void); +void lx_emul_irq_restore(unsigned long); + #ifdef __cplusplus } #endif diff --git a/repos/dde_linux/src/include/lx_emul/shadow/arch/arm/include/asm/irqflags.h b/repos/dde_linux/src/include/lx_emul/shadow/arch/arm/include/asm/irqflags.h index c89f318fdb..84765be9a6 100644 --- a/repos/dde_linux/src/include/lx_emul/shadow/arch/arm/include/asm/irqflags.h +++ b/repos/dde_linux/src/include/lx_emul/shadow/arch/arm/include/asm/irqflags.h @@ -14,14 +14,25 @@ #ifndef __ASM_IRQFLAGS_H #define __ASM_IRQFLAGS_H -static inline unsigned long arch_local_save_flags(void) { - return 1; } +#include -static inline void arch_local_irq_restore(unsigned long flags) { } +#define arch_local_save_flags arch_local_save_flags +static inline unsigned long arch_local_save_flags(void) +{ + return lx_emul_irq_state(); +} + +#define arch_local_irq_restore arch_local_irq_restore +static inline void arch_local_irq_restore(unsigned long flags) +{ + lx_emul_irq_restore(flags); +} #define arch_irqs_disabled_flags arch_irqs_disabled_flags -static inline int arch_irqs_disabled_flags(unsigned long flags) { - return 1; } +static inline int arch_irqs_disabled_flags(unsigned long flags) +{ + return flags & 1; +} #define local_fiq_enable() ({}) #define local_fiq_disable() ({}) diff --git a/repos/dde_linux/src/include/lx_emul/shadow/arch/arm64/include/asm/irqflags.h b/repos/dde_linux/src/include/lx_emul/shadow/arch/arm64/include/asm/irqflags.h index 371143432f..125063ef0f 100644 --- a/repos/dde_linux/src/include/lx_emul/shadow/arch/arm64/include/asm/irqflags.h +++ b/repos/dde_linux/src/include/lx_emul/shadow/arch/arm64/include/asm/irqflags.h @@ -14,19 +14,36 @@ #ifndef __ASM_IRQFLAGS_H #define __ASM_IRQFLAGS_H -static inline void arch_local_irq_enable(void) { } +#include -static inline void arch_local_irq_disable(void) { } +static inline void arch_local_irq_enable(void) +{ + lx_emul_irq_enable(); +} -static inline unsigned long arch_local_save_flags(void) { - return 1; } +static inline void arch_local_irq_disable(void) +{ + lx_emul_irq_disable(); +} -static inline int arch_irqs_disabled_flags(unsigned long flags) { - return flags; } +static inline unsigned long arch_local_save_flags(void) +{ + return lx_emul_irq_state(); +} -static inline unsigned long arch_local_irq_save(void) { - return 1; } +static inline int arch_irqs_disabled_flags(unsigned long flags) +{ + return flags & 1; +} -static inline void arch_local_irq_restore(unsigned long flags) { } +static inline unsigned long arch_local_irq_save(void) +{ + return lx_emul_irq_disable(); +} + +static inline void arch_local_irq_restore(unsigned long flags) +{ + lx_emul_irq_restore(flags); +} #endif diff --git a/repos/dde_linux/src/include/lx_emul/shadow/arch/x86/include/asm/irqflags.h b/repos/dde_linux/src/include/lx_emul/shadow/arch/x86/include/asm/irqflags.h index 371143432f..125063ef0f 100644 --- a/repos/dde_linux/src/include/lx_emul/shadow/arch/x86/include/asm/irqflags.h +++ b/repos/dde_linux/src/include/lx_emul/shadow/arch/x86/include/asm/irqflags.h @@ -14,19 +14,36 @@ #ifndef __ASM_IRQFLAGS_H #define __ASM_IRQFLAGS_H -static inline void arch_local_irq_enable(void) { } +#include -static inline void arch_local_irq_disable(void) { } +static inline void arch_local_irq_enable(void) +{ + lx_emul_irq_enable(); +} -static inline unsigned long arch_local_save_flags(void) { - return 1; } +static inline void arch_local_irq_disable(void) +{ + lx_emul_irq_disable(); +} -static inline int arch_irqs_disabled_flags(unsigned long flags) { - return flags; } +static inline unsigned long arch_local_save_flags(void) +{ + return lx_emul_irq_state(); +} -static inline unsigned long arch_local_irq_save(void) { - return 1; } +static inline int arch_irqs_disabled_flags(unsigned long flags) +{ + return flags & 1; +} -static inline void arch_local_irq_restore(unsigned long flags) { } +static inline unsigned long arch_local_irq_save(void) +{ + return lx_emul_irq_disable(); +} + +static inline void arch_local_irq_restore(unsigned long flags) +{ + lx_emul_irq_restore(flags); +} #endif diff --git a/repos/dde_linux/src/lib/lx_emul/irq_flags.cc b/repos/dde_linux/src/lib/lx_emul/irq_flags.cc new file mode 100644 index 0000000000..ad08d7573e --- /dev/null +++ b/repos/dde_linux/src/lib/lx_emul/irq_flags.cc @@ -0,0 +1,45 @@ +/* + * \brief Lx_emul backend for interrupts + * \author Stefan Kalkowski + * \date 2021-04-22 + */ + +/* + * Copyright (C) 2021 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#include + +static unsigned long cpu_local_irq_flags = 0; + + +extern "C" unsigned long lx_emul_irq_enable(void) +{ + unsigned long ret = cpu_local_irq_flags; + cpu_local_irq_flags = 0; + return ret; +} + + +extern "C" unsigned long lx_emul_irq_disable(void) +{ + unsigned long ret = cpu_local_irq_flags; + cpu_local_irq_flags = 1; + return ret; +} + + +extern "C" unsigned long lx_emul_irq_state(void) +{ + return cpu_local_irq_flags; +} + + +extern "C" void lx_emul_irq_restore(unsigned long flags) +{ + cpu_local_irq_flags = flags; +} + diff --git a/repos/dde_linux/src/lib/lx_emul/spec/arm/irqchip.c b/repos/dde_linux/src/lib/lx_emul/spec/arm/irqchip.c index 7a35bbbe18..679683c028 100644 --- a/repos/dde_linux/src/lib/lx_emul/spec/arm/irqchip.c +++ b/repos/dde_linux/src/lib/lx_emul/spec/arm/irqchip.c @@ -165,6 +165,7 @@ IRQCHIP_DECLARE(dde_gic_400, "arm,gic-400", lx_emul_irq_init); int lx_emul_irq_task_function(void * data) { int irq; + unsigned long flags; for (;;) { lx_emul_task_schedule(true); @@ -172,6 +173,7 @@ int lx_emul_irq_task_function(void * data) if (!dde_irq_domain) continue; + local_irq_save(flags); irq_enter(); irq = irq_find_mapping(dde_irq_domain, lx_emul_irq_last()); @@ -184,6 +186,7 @@ int lx_emul_irq_task_function(void * data) } irq_exit(); + local_irq_restore(flags); } return 0; diff --git a/repos/dde_linux/src/lib/lx_emul/spec/x86/irqchip.c b/repos/dde_linux/src/lib/lx_emul/spec/x86/irqchip.c index a59c6c37f7..ebb5b94a57 100644 --- a/repos/dde_linux/src/lib/lx_emul/spec/x86/irqchip.c +++ b/repos/dde_linux/src/lib/lx_emul/spec/x86/irqchip.c @@ -47,11 +47,13 @@ struct irq_chip dde_irqchip_data_chip = { int lx_emul_irq_task_function(void * data) { + unsigned long flags; int irq; for (;;) { lx_emul_task_schedule(true); + local_irq_save(flags); irq_enter(); irq = lx_emul_irq_last(); @@ -66,6 +68,7 @@ int lx_emul_irq_task_function(void * data) } irq_exit(); + local_irq_restore(flags); } return 0;