arch/riscv/kvm/aia_aplic.c

Source file repositories/reference/linux-study-clean/arch/riscv/kvm/aia_aplic.c

File Facts

System
Linux kernel
Corpus path
arch/riscv/kvm/aia_aplic.c
Extension
.c
Size
16320 bytes
Lines
637
Domain
Architecture Layer
Bucket
arch/riscv
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

struct aplic_irq {
	raw_spinlock_t lock;
	u32 sourcecfg;
	u32 state;
#define APLIC_IRQ_STATE_PENDING		BIT(0)
#define APLIC_IRQ_STATE_ENABLED		BIT(1)
#define APLIC_IRQ_STATE_ENPEND		(APLIC_IRQ_STATE_PENDING | \
					 APLIC_IRQ_STATE_ENABLED)
#define APLIC_IRQ_STATE_INPUT		BIT(8)
	u32 target;
};

struct aplic {
	struct kvm_io_device iodev;

	u32 domaincfg;
	u32 genmsi;

	u32 nr_irqs;
	u32 nr_words;
	struct aplic_irq irqs[] __counted_by(nr_irqs);
};

static u32 aplic_read_sourcecfg(struct aplic *aplic, u32 irq)
{
	u32 ret;
	unsigned long flags;
	struct aplic_irq *irqd;

	if (!irq || aplic->nr_irqs <= irq)
		return 0;
	irqd = &aplic->irqs[array_index_nospec(irq, aplic->nr_irqs)];

	raw_spin_lock_irqsave(&irqd->lock, flags);
	ret = irqd->sourcecfg;
	raw_spin_unlock_irqrestore(&irqd->lock, flags);

	return ret;
}

static void aplic_write_sourcecfg(struct aplic *aplic, u32 irq, u32 val)
{
	unsigned long flags;
	struct aplic_irq *irqd;

	if (!irq || aplic->nr_irqs <= irq)
		return;
	irqd = &aplic->irqs[array_index_nospec(irq, aplic->nr_irqs)];

	if (val & APLIC_SOURCECFG_D)
		val = 0;
	else
		val &= APLIC_SOURCECFG_SM_MASK;

	raw_spin_lock_irqsave(&irqd->lock, flags);
	irqd->sourcecfg = val;
	raw_spin_unlock_irqrestore(&irqd->lock, flags);
}

static u32 aplic_read_target(struct aplic *aplic, u32 irq)
{
	u32 ret;
	unsigned long flags;
	struct aplic_irq *irqd;

	if (!irq || aplic->nr_irqs <= irq)
		return 0;
	irqd = &aplic->irqs[array_index_nospec(irq, aplic->nr_irqs)];

	raw_spin_lock_irqsave(&irqd->lock, flags);
	ret = irqd->target;
	raw_spin_unlock_irqrestore(&irqd->lock, flags);

	return ret;
}

static void aplic_write_target(struct aplic *aplic, u32 irq, u32 val)
{
	unsigned long flags;
	struct aplic_irq *irqd;

	if (!irq || aplic->nr_irqs <= irq)
		return;
	irqd = &aplic->irqs[array_index_nospec(irq, aplic->nr_irqs)];

	val &= APLIC_TARGET_EIID_MASK |
	       (APLIC_TARGET_HART_IDX_MASK << APLIC_TARGET_HART_IDX_SHIFT) |
	       (APLIC_TARGET_GUEST_IDX_MASK << APLIC_TARGET_GUEST_IDX_SHIFT);

	raw_spin_lock_irqsave(&irqd->lock, flags);

Annotation

Implementation Notes