diff --git a/xen/arch/riscv/Makefile b/xen/arch/riscv/Makefile index 8e7a6370ee..fcd73c7a2d 100644 --- a/xen/arch/riscv/Makefile +++ b/xen/arch/riscv/Makefile @@ -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/ diff --git a/xen/arch/riscv/domain.c b/xen/arch/riscv/domain.c index c993314759..45712d3059 100644 --- a/xen/arch/riscv/domain.c +++ b/xen/arch/riscv/domain.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -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; diff --git a/xen/arch/riscv/imsic.c b/xen/arch/riscv/imsic.c index 4a2ef5069d..809f29af86 100644 --- a/xen/arch/riscv/imsic.c +++ b/xen/arch/riscv/imsic.c @@ -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); } diff --git a/xen/arch/riscv/include/asm/aplic.h b/xen/arch/riscv/include/asm/aplic.h index b0724fe6f3..5a7fcb6ec4 100644 --- a/xen/arch/riscv/include/asm/aplic.h +++ b/xen/arch/riscv/include/asm/aplic.h @@ -15,8 +15,15 @@ #include +/* + * 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 diff --git a/xen/arch/riscv/include/asm/intc.h b/xen/arch/riscv/include/asm/intc.h index a4e678fad9..8757288852 100644 --- a/xen/arch/riscv/include/asm/intc.h +++ b/xen/arch/riscv/include/asm/intc.h @@ -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); diff --git a/xen/arch/riscv/include/asm/vaplic.h b/xen/arch/riscv/include/asm/vaplic.h new file mode 100644 index 0000000000..96080bfbc2 --- /dev/null +++ b/xen/arch/riscv/include/asm/vaplic.h @@ -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 +#include + +#include + +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 */ diff --git a/xen/arch/riscv/vaplic.c b/xen/arch/riscv/vaplic.c new file mode 100644 index 0000000000..c9f188b989 --- /dev/null +++ b/xen/arch/riscv/vaplic.c @@ -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 +#include +#include + +#include +#include +#include +#include + +#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); +}