[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v2 03/17] xen/riscv: introduce guest domain's VMID allocation and manegement
Implementation is based on Arm code with some minor changes: - Re-define INVALID_VMID. - Re-define MAX_VMID. - Add TLB flushing when VMID is re-used. Also, as a part of this path structure p2m_domain is introduced with vmid member inside it. It is necessary for VMID management functions. Add a bitmap-based allocator to manage VMID space, supporting up to 127 VMIDs on RV32 and 16,383 on RV64 platforms, in accordance with the architecture's hgatp VMID field (RV32 - 7 bit long, others - 14 bit long). Reserve the highest VMID as INVALID_VMID to ensure it's not reused. Implement p2m_alloc_vmid() and p2m_free_vmid() for dynamic allocation and release of VMIDs per domain. Integrate VMID initialization into p2m_init() and ensured domain-specific TLB flushes on VMID release using sbi_remote_hfence_gvma_vmid(). Signed-off-by: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx> --- Changes in V2: - New patch. --- xen/arch/riscv/Makefile | 1 + xen/arch/riscv/include/asm/domain.h | 4 + xen/arch/riscv/include/asm/p2m.h | 14 ++++ xen/arch/riscv/p2m.c | 115 ++++++++++++++++++++++++++++ xen/arch/riscv/setup.c | 3 + 5 files changed, 137 insertions(+) create mode 100644 xen/arch/riscv/p2m.c diff --git a/xen/arch/riscv/Makefile b/xen/arch/riscv/Makefile index a1c145c506..1034f2c9cd 100644 --- a/xen/arch/riscv/Makefile +++ b/xen/arch/riscv/Makefile @@ -6,6 +6,7 @@ obj-y += intc.o obj-y += irq.o obj-y += mm.o obj-y += pt.o +obj-y += p2m.o obj-$(CONFIG_RISCV_64) += riscv64/ obj-y += sbi.o obj-y += setup.o diff --git a/xen/arch/riscv/include/asm/domain.h b/xen/arch/riscv/include/asm/domain.h index c3d965a559..b9a03e91c5 100644 --- a/xen/arch/riscv/include/asm/domain.h +++ b/xen/arch/riscv/include/asm/domain.h @@ -5,6 +5,8 @@ #include <xen/xmalloc.h> #include <public/hvm/params.h> +#include <asm/p2m.h> + struct hvm_domain { uint64_t params[HVM_NR_PARAMS]; @@ -18,6 +20,8 @@ struct arch_vcpu { struct arch_domain { struct hvm_domain hvm; + + struct p2m_domain p2m; }; #include <xen/sched.h> diff --git a/xen/arch/riscv/include/asm/p2m.h b/xen/arch/riscv/include/asm/p2m.h index 28f57a74f2..359408e1be 100644 --- a/xen/arch/riscv/include/asm/p2m.h +++ b/xen/arch/riscv/include/asm/p2m.h @@ -3,11 +3,21 @@ #define ASM__RISCV__P2M_H #include <xen/errno.h> +#include <xen/types.h> #include <asm/page-bits.h> #define paddr_bits PADDR_BITS +/* Get host p2m table */ +#define p2m_get_hostp2m(d) (&(d)->arch.p2m) + +/* Per-p2m-table state */ +struct p2m_domain { + /* Current VMID in use */ + uint16_t vmid; +}; + /* * List of possible type for each page in the p2m entry. * The number of available bit per page in the pte for this purpose is 2 bits. @@ -93,6 +103,10 @@ static inline void p2m_altp2m_check(struct vcpu *v, uint16_t idx) /* Not supported on RISCV. */ } +void p2m_vmid_allocator_init(void); + +int p2m_init(struct domain *d); + #endif /* ASM__RISCV__P2M_H */ /* diff --git a/xen/arch/riscv/p2m.c b/xen/arch/riscv/p2m.c new file mode 100644 index 0000000000..9f7fd8290a --- /dev/null +++ b/xen/arch/riscv/p2m.c @@ -0,0 +1,115 @@ +#include <xen/bitops.h> +#include <xen/lib.h> +#include <xen/sched.h> +#include <xen/spinlock.h> +#include <xen/xvmalloc.h> + +#include <asm/p2m.h> +#include <asm/sbi.h> + +static spinlock_t vmid_alloc_lock = SPIN_LOCK_UNLOCKED; + +/* + * hgatp's VMID field is 7 or 14 bits. RV64 may support 14-bit VMID. + * Using a bitmap here limits us to 127 (2^7 - 1) or 16383 (2^14 - 1) + * concurrent domains. The bitmap space will be allocated dynamically + * based on whether 7 or 14 bit VMIDs are supported. + */ +static unsigned long *vmid_mask; +static unsigned long *vmid_flushing_needed; + +/* + * -2 here because: + * - -1 is needed to get the maximal possible VMID + * - -1 is reserved for beinng used as INVALID_VMID + */ +#ifdef CONFIG_RISCV_32 +#define MAX_VMID (BIT(7, U) - 2) +#else +#define MAX_VMID (BIT(14, U) - 2) +#endif + +/* Reserve the max possible VMID to be INVALID. */ +#define INVALID_VMID (MAX_VMID + 1) + +void p2m_vmid_allocator_init(void) +{ + /* + * Allocate space for vmid_mask and vmid_flushing_needed + * based on INVALID_VMID as it is the max possible VMID which just + * was reserved to be INVALID_VMID. + */ + vmid_mask = xvzalloc_array(unsigned long, BITS_TO_LONGS(INVALID_VMID)); + vmid_flushing_needed = + xvzalloc_array(unsigned long, BITS_TO_LONGS(INVALID_VMID)); + + if ( !vmid_mask || !vmid_flushing_needed ) + panic("Could not allocate VMID bitmap space or VMID flushing map\n"); + + set_bit(INVALID_VMID, vmid_mask); +} + +int p2m_alloc_vmid(struct domain *d) +{ + struct p2m_domain *p2m = p2m_get_hostp2m(d); + + int rc, nr; + + spin_lock(&vmid_alloc_lock); + + nr = find_first_zero_bit(vmid_mask, MAX_VMID); + + ASSERT(nr != INVALID_VMID); + + if ( nr == MAX_VMID ) + { + rc = -EBUSY; + printk(XENLOG_ERR "p2m.c: dom%d: VMID pool exhausted\n", d->domain_id); + goto out; + } + + set_bit(nr, vmid_mask); + + if ( test_bit(p2m->vmid, vmid_flushing_needed) ) + { + clear_bit(p2m->vmid, vmid_flushing_needed); + sbi_remote_hfence_gvma_vmid(d->dirty_cpumask, 0, 0, p2m->vmid); + } + + p2m->vmid = nr; + + rc = 0; + +out: + spin_unlock(&vmid_alloc_lock); + return rc; +} + +void p2m_free_vmid(struct domain *d) +{ + struct p2m_domain *p2m = p2m_get_hostp2m(d); + + spin_lock(&vmid_alloc_lock); + + if ( p2m->vmid != INVALID_VMID ) + { + clear_bit(p2m->vmid, vmid_mask); + set_bit(p2m->vmid, vmid_flushing_needed); + } + + spin_unlock(&vmid_alloc_lock); +} + +int p2m_init(struct domain *d) +{ + struct p2m_domain *p2m = p2m_get_hostp2m(d); + int rc; + + p2m->vmid = INVALID_VMID; + + rc = p2m_alloc_vmid(d); + if ( rc ) + return rc; + + return 0; +} diff --git a/xen/arch/riscv/setup.c b/xen/arch/riscv/setup.c index 8bcd19218d..aa8f5646ea 100644 --- a/xen/arch/riscv/setup.c +++ b/xen/arch/riscv/setup.c @@ -19,6 +19,7 @@ #include <asm/early_printk.h> #include <asm/fixmap.h> #include <asm/intc.h> +#include <asm/p2m.h> #include <asm/sbi.h> #include <asm/setup.h> #include <asm/traps.h> @@ -134,6 +135,8 @@ void __init noreturn start_xen(unsigned long bootcpu_id, intc_preinit(); + p2m_vmid_allocator_init(); + printk("All set up\n"); machine_halt(); -- 2.49.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |