diff --git a/xen/arch/riscv/imsic.c b/xen/arch/riscv/imsic.c index 8da72c0072..4a2ef5069d 100644 --- a/xen/arch/riscv/imsic.c +++ b/xen/arch/riscv/imsic.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -56,6 +57,11 @@ do { \ csr_clear(CSR_SIREG, v); \ } while (0) +unsigned int vcpu_guest_file_id(const struct vcpu *v) +{ + return ACCESS_ONCE(v->arch.vimsic_state->guest_file_id); +} + void __init imsic_ids_local_delivery(bool enable) { if ( enable ) @@ -312,6 +318,35 @@ static int imsic_parse_node(const struct dt_device_node *node, return 0; } +int vcpu_imsic_init(struct vcpu *v) +{ + struct vimsic_state *imsic_state; + + /* Allocate IMSIC context */ + imsic_state = xvzalloc(struct vimsic_state); + if ( !imsic_state ) + return -ENOMEM; + + /* Setup IMSIC context */ + rwlock_init(&imsic_state->vsfile_lock); + + /* + * xvzalloc() already cleared the context, so guest_file_id == 0, i.e. the + * always-available s/w IMSIC VS-file. Only vsfile_cpu needs an explicit + * initializer as its s/w VS-file value is NR_CPUS rather than 0. + */ + imsic_state->vsfile_cpu = NR_CPUS; + + v->arch.vimsic_state = imsic_state; + + return 0; +} + +void vcpu_imsic_deinit(struct vcpu *v) +{ + XVFREE(v->arch.vimsic_state); +} + /* * Initialize the imsic_cfg structure based on the IMSIC DT node. * diff --git a/xen/arch/riscv/include/asm/domain.h b/xen/arch/riscv/include/asm/domain.h index bd43ed08c2..e035b33ddf 100644 --- a/xen/arch/riscv/include/asm/domain.h +++ b/xen/arch/riscv/include/asm/domain.h @@ -54,6 +54,8 @@ struct arch_vcpu { struct vtimer vtimer; + struct vimsic_state *vimsic_state; + register_t hcounteren; register_t hedeleg; register_t hideleg; diff --git a/xen/arch/riscv/include/asm/imsic.h b/xen/arch/riscv/include/asm/imsic.h index c6c59215df..5ee954bbf3 100644 --- a/xen/arch/riscv/include/asm/imsic.h +++ b/xen/arch/riscv/include/asm/imsic.h @@ -11,6 +11,7 @@ #ifndef ASM_RISCV_IMSIC_H #define ASM_RISCV_IMSIC_H +#include #include #include #include @@ -61,7 +62,24 @@ struct imsic_config { spinlock_t lock; }; +struct vimsic_state { + /* IMSIC VS-file */ + rwlock_t vsfile_lock; + /* + * s/w IMSIC VS-file -> guest_file_id == 0 + * h/w IMSIC VS-file -> guest_file_id > 0 + */ + unsigned int guest_file_id; + /* + * s/w IMSIC VS-file -> vsfile_cpu == NR_CPUS + * h/w IMSIC VS-file -> vsfile_cpu < NR_CPUS + */ + unsigned int vsfile_cpu; +}; + struct dt_device_node; +struct vcpu; + int imsic_init(const struct dt_device_node *node); const struct imsic_config *imsic_get_config(void); @@ -71,4 +89,8 @@ void imsic_irq_disable(unsigned int hwirq); void imsic_ids_local_delivery(bool enable); +int vcpu_imsic_init(struct vcpu *v); +void vcpu_imsic_deinit(struct vcpu *v); +unsigned int vcpu_guest_file_id(const struct vcpu *v); + #endif /* ASM_RISCV_IMSIC_H */