lx_emul: track irq state changes

To be able to check for interrupts being on or off,
the enabling and disabling is tracked in lx_emul.
When interrupts get received, they have to be turned off.

Ref genodelabs/genode#4778
This commit is contained in:
Stefan Kalkowski 2023-03-02 11:50:07 +01:00 committed by Christian Helmuth
parent eba2c8cf2f
commit c90b61f571
8 changed files with 126 additions and 23 deletions

View File

@ -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

View File

@ -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

View File

@ -14,14 +14,25 @@
#ifndef __ASM_IRQFLAGS_H
#define __ASM_IRQFLAGS_H
static inline unsigned long arch_local_save_flags(void) {
return 1; }
#include <lx_emul/irq.h>
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() ({})

View File

@ -14,19 +14,36 @@
#ifndef __ASM_IRQFLAGS_H
#define __ASM_IRQFLAGS_H
static inline void arch_local_irq_enable(void) { }
#include <lx_emul/irq.h>
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

View File

@ -14,19 +14,36 @@
#ifndef __ASM_IRQFLAGS_H
#define __ASM_IRQFLAGS_H
static inline void arch_local_irq_enable(void) { }
#include <lx_emul/irq.h>
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

View File

@ -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 <lx_emul/irq.h>
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;
}

View File

@ -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;

View File

@ -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;