mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
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:
1 parent
bbbe70852a
commit
9164a97efb
7 files changed
+111
-10
No files matched your search
@@ -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/
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
@@ -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);
|
||||
}
|
||||