xen/riscv: introduce minimal virtual APLIC (vAPLIC) infrastructure

At the current development stage, only domain vINTC init and deinit
operations are required, so implement those first.

Initialize vAPLIC's domaincfg to with the interrupt-enable bit set and
MSI delivery mode selected as the current solution is exepcted to have
always IMSIC, and initialize vintc->ops.

Other operations such as emulate_load(), emulate_store(), and is_access()
will be needed once guests are running and MMIO accesses to APLIC MMIO
range must be handled. These will be introduced separately later.

Introduce a structure to describe a virtual interrupt controller (vINTC)
and a vintc_ops structure, which provides operations to emulate load and
store accesses to interrupt controller MMIOs and to check whether a given
address falls within the MMIO range of a specific virtual interrupt
controller.
Note that already existed init_ops field in struct vintc will be init-ed
for APLIC in the follow up patch.

The vAPLIC implementation of these operations will be provided later
once guests can be run and these operations are actually needed.

Introduce these structures here as they are required for the implementation
of domain_vaplic_init() and domain_vaplic_alloc(). Also, introduce
vaplic_init() and init vintc_ops->vcpu_init() with it.

Co-developed-by: Romain Caritey <Romain.Caritey@microchip.com>
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
Oleksii Kurochko authored and Jan Beulich committed 2026-09-21 10:08:35 +02:00
1 parent bbbe70852a
commit 9164a97efb
7 files changed
+111 -10

No files matched your search

+1
View File
@@ -25,6 +25,7 @@ obj-y += smpboot.o
obj-y += stubs.o
obj-y += time.o
obj-y += traps.o
obj-y += vaplic.o
obj-y += vmid.o
obj-y += vm_event.o
obj-y += vsbi/
+3 -8
View File
@@ -11,6 +11,7 @@
#include <asm/bitops.h>
#include <asm/cpufeature.h>
#include <asm/csr.h>
#include <asm/intc.h>
#include <asm/riscv_encoding.h>
#include <asm/vtimer.h>
@@ -155,14 +156,8 @@ int arch_vcpu_create(struct vcpu *v)
if ( (rc = vcpu_vtimer_init(v)) )
goto fail;
/*
* As interrupt controller (IC) is not yet implemented,
* return an error.
*
* TODO: Drop this once IC is implemented.
*/
rc = -EOPNOTSUPP;
goto fail;
if ( (rc = v->domain->arch.vintc->ops->vcpu_init(v)) )
goto fail;
return rc;
+2 -2
View File
@@ -318,7 +318,7 @@ static int imsic_parse_node(const struct dt_device_node *node,
return 0;
}
int vcpu_imsic_init(struct vcpu *v)
int cf_check vcpu_imsic_init(struct vcpu *v)
{
struct vimsic_state *imsic_state;
@@ -342,7 +342,7 @@ int vcpu_imsic_init(struct vcpu *v)
return 0;
}
void vcpu_imsic_deinit(struct vcpu *v)
void cf_check vcpu_imsic_deinit(struct vcpu *v)
{
XVFREE(v->arch.vimsic_state);
}
+7
View File
@@ -15,8 +15,15 @@
#include <asm/imsic.h>
/*
* domaincfg read-only fields (AIA spec):
* - bits [31:24] -> read-only 0x80
* - bit 7 -> read-only 0
*/
#define APLIC_DOMAINCFG_RO (0x80U << 24)
#define APLIC_DOMAINCFG_IE BIT(8, U)
#define APLIC_DOMAINCFG_DM BIT(2, U)
#define APLIC_DOMAINCFG_BE BIT(0, U)
#define APLIC_SOURCECFG_SM_INACTIVE 0x0
#define APLIC_SOURCECFG_SM_DETACH 0x1
+12
View File
@@ -17,6 +17,7 @@ enum intc_variant {
struct cpu_user_regs;
struct irq_desc;
struct kernel_info;
struct vcpu;
struct intc_info {
enum intc_variant hw_variant;
@@ -53,8 +54,19 @@ struct vintc_init_ops {
int (*make_domu_dt_node)(struct kernel_info *kinfo);
};
struct vintc_ops {
/* Initialize some vINTC-related stuff for a vCPU */
int (*vcpu_init)(struct vcpu *v);
/* Deinitialize some vINTC-related stuff for a vCPU */
void (*vcpu_deinit)(struct vcpu *v);
};
struct vintc {
/* Callbacks invoked during domain construction only. */
const struct vintc_init_ops *init_ops;
/* Runtime callbacks used for the lifetime of the guest. */
const struct vintc_ops *ops;
};
void intc_preinit(void);
+34
View File
@@ -0,0 +1,34 @@
/* SPDX-License-Identifier: MIT */
/*
* xen/arch/riscv/vaplic.c
*
* Virtual RISC-V Advanced Platform-Level Interrupt Controller support
*
* Copyright (c) Microchip.
*/
#ifndef ASM__RISCV__VAPLIC_H
#define ASM__RISCV__VAPLIC_H
#include <xen/kernel.h>
#include <xen/types.h>
#include <asm/intc.h>
struct domain;
#define to_vaplic(d) container_of((d)->arch.vintc, struct vaplic, vintc)
struct vaplic_regs {
uint32_t domaincfg;
};
struct vaplic {
struct vintc vintc;
struct vaplic_regs regs;
};
int domain_vaplic_init(struct domain *d);
void domain_vaplic_deinit(struct domain *d);
#endif /* ASM__RISCV__VAPLIC_H */
+52
View File
@@ -0,0 +1,52 @@
/* SPDX-License-Identifier: MIT */
/*
* xen/arch/riscv/vaplic.c
*
* Virtual RISC-V Advanced Platform-Level Interrupt Controller support
*
* Copyright (c) Microchip.
* Copyright (c) Vates
*/
#include <xen/errno.h>
#include <xen/sched.h>
#include <xen/xvmalloc.h>
#include <asm/aia.h>
#include <asm/imsic.h>
#include <asm/intc.h>
#include <asm/vaplic.h>
#include "aplic-priv.h"
static const struct vintc_ops vintc_ops = {
.vcpu_init = vcpu_imsic_init,
.vcpu_deinit = vcpu_imsic_deinit,
};
int domain_vaplic_init(struct domain *d)
{
struct vaplic *vaplic = xvzalloc(struct vaplic);
if ( !vaplic )
return -ENOMEM;
d->arch.vintc = &vaplic->vintc;
d->arch.vintc->ops = &vintc_ops;
vaplic->regs.domaincfg = APLIC_DOMAINCFG_RO;
return 0;
}
void domain_vaplic_deinit(struct domain *d)
{
struct vaplic *vaplic;
if ( !d->arch.vintc )
return;
vaplic = to_vaplic(d);
d->arch.vintc = NULL;
xvfree(vaplic);
}
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.