[PATCH OLK-6.6 00/12] Add support for IPIv

Patch#1 Probe and configure IPIV capacity on HIP12 Patch#2 Allocate VM table and save vpeid in it Patch#3 Add support for ipiv direct mode Patch#4 Register ipiv exception interrupt Patch#5 Set base address of vm table and targe ITS when vpe schedule and deschedule Patch#6 Pre-allocate vpe id for direct mode Patch#7 Add interface KVM_CAP_ARM_IPIV_MODE Patch#8 Change ipiv irq type Patch#9 IPI performance benchmark Patch#10 Check GICD_CTLR_nASSGIreq when vpe schedule and deschedule Patch#11 Add a check before disabling ICC_SGI1R_EL1 trap Patch#12 use __GENKSYMS__ to revert the kabi change Xiang Chen (11): kvm: hisi_virt: Probe and configure IPIV capacity on HIP12 kvm: hisi_virt: Allocate VM table and save vpeid in it kvm: hisi_virt: Add support for ipiv direct mode kvm: hisi_virt: Register ipiv exception interrupt irqchip: gicv3-its: Set base address of vm table and targe ITS when vpe schedule and deschedule kvm: hisi_virt: Pre-allocate vpe id for direct mode kvm: arm64: Add interface KVM_CAP_ARM_IPIV_MODE kvm: hisi_virt: Change ipiv irq type IPI performance benchmark irqchip: gicv3-its: Check GICD_CTLR_nASSGIreq when vpe schedule and deschedule irqchip: gicv3-its: Add a check before disabling ICC_SGI1R_EL1 trap yangjinqian (1): irqchip: gicv3-its: use __GENKSYMS__ to revert the kabi change .../admin-guide/kernel-parameters.txt | 8 + arch/Kconfig | 10 ++ arch/arm64/include/asm/kvm_host.h | 1 + arch/arm64/kvm/arm.c | 23 +++ arch/arm64/kvm/hisilicon/hisi_virt.c | 41 ++++- arch/arm64/kvm/hisilicon/hisi_virt.h | 9 + arch/arm64/kvm/sys_regs.c | 33 +++- arch/arm64/kvm/vgic/vgic-init.c | 84 +++++++++- arch/arm64/kvm/vgic/vgic-mmio-v3.c | 2 + drivers/irqchip/irq-gic-v3-its.c | 121 +++++++++++++- drivers/irqchip/irq-gic-v3.c | 37 +++++ include/kvm/arm_vgic.h | 2 + include/linux/irqchip/arm-gic-v3.h | 23 +++ include/linux/irqchip/arm-gic-v4.h | 7 + include/uapi/linux/kvm.h | 2 + kernel/Makefile | 1 + kernel/ipi_benchmark.c | 155 ++++++++++++++++++ 17 files changed, 539 insertions(+), 20 deletions(-) create mode 100644 kernel/ipi_benchmark.c -- 2.33.0

From: Xiang Chen <chenxiang66@hisilicon.com> virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBPH85 ------------------------------------------------------------------------ IPIV is an virtualization extension on HIP12, which allows IPIs on guest directly sending by hardware to other vcpu stead of trapping to EL2. It will bring IPI interrupt optimization on guest. Introduce the method to detect and enable the feature, and also add a kernel command parameter "kvm-arm.ipiv_enabled" (default is 0) so that users can disable or enable the feature. The feature is based on GICv4p1. Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com> Signed-off-by: Jinqian Yang <yangjinqian1@huawei.com> --- .../admin-guide/kernel-parameters.txt | 3 ++ arch/arm64/include/asm/kvm_host.h | 1 + arch/arm64/kvm/arm.c | 5 +++ arch/arm64/kvm/hisilicon/hisi_virt.c | 32 ++++++++++++++++++- arch/arm64/kvm/hisilicon/hisi_virt.h | 9 ++++++ arch/arm64/kvm/vgic/vgic-mmio-v3.c | 1 + drivers/irqchip/irq-gic-v3.c | 20 ++++++++++++ include/linux/irqchip/arm-gic-v3.h | 3 ++ 8 files changed, 73 insertions(+), 1 deletion(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index b68b08ef13bd..459323983fa9 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -2709,6 +2709,9 @@ [KVM,ARM] Allow use of GICv4 for direct injection of LPIs. + kvm-arm.ipiv_enabled= + [KVM,ARM] Allow use of HiSilicon ipiv on GICv4.1 + kvm-arm.dvmbm_enabled= [KVM,ARM] Allow use of HiSilicon DVMBM capability. Default: 0 diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index ac4e59256f8e..bf884f95e6e6 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -1286,5 +1286,6 @@ bool kvm_arm_vcpu_stopped(struct kvm_vcpu *vcpu); extern bool force_wfi_trap; extern bool kvm_ncsnp_support; extern bool kvm_dvmbm_support; +extern bool kvm_ipiv_support; #endif /* __ARM64_KVM_HOST_H__ */ diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index c0126a9203ae..5115df307ab9 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -67,6 +67,9 @@ bool kvm_ncsnp_support; /* Capability of DVMBM */ bool kvm_dvmbm_support; +/* Capability of IPIV */ +bool kvm_ipiv_support; + static DEFINE_PER_CPU(unsigned char, kvm_hyp_initialized); bool is_kvm_arm_initialised(void) @@ -2693,8 +2696,10 @@ static __init int kvm_arm_init(void) probe_hisi_cpu_type(); kvm_ncsnp_support = hisi_ncsnp_supported(); kvm_dvmbm_support = hisi_dvmbm_supported(); + kvm_ipiv_support = hisi_ipiv_supported(); kvm_info("KVM ncsnp %s\n", kvm_ncsnp_support ? "enabled" : "disabled"); kvm_info("KVM dvmbm %s\n", kvm_dvmbm_support ? "enabled" : "disabled"); + kvm_info("KVM ipiv %s\n", kvm_ipiv_support ? "enabled" : "disabled"); if (kvm_dvmbm_support) kvm_get_pg_cfg(); diff --git a/arch/arm64/kvm/hisilicon/hisi_virt.c b/arch/arm64/kvm/hisilicon/hisi_virt.c index ea6ab834a46e..642aff5ff7d8 100644 --- a/arch/arm64/kvm/hisilicon/hisi_virt.c +++ b/arch/arm64/kvm/hisilicon/hisi_virt.c @@ -12,6 +12,7 @@ static enum hisi_cpu_type cpu_type = UNKNOWN_HI_TYPE; static bool dvmbm_enabled; +static bool ipiv_enabled; static const char * const hisi_cpu_type_str[] = { "Hisi1612", @@ -20,6 +21,7 @@ static const char * const hisi_cpu_type_str[] = { "HIP09", "HIP10", "HIP10C", + "HIP12", "Unknown" }; @@ -30,7 +32,8 @@ static const char * const oem_str[] = { "HIP08 ", /* Hisi 1620 */ "HIP09 ", /* HIP09 */ "HIP10 ", /* HIP10 */ - "HIP10C " /* HIP10C */ + "HIP10C ", /* HIP10C */ + "HIP12 " /* HIP12 */ }; /* @@ -155,6 +158,33 @@ static void hardware_disable_dvmbm(void *data) write_sysreg_s(val, SYS_LSUDVM_CTRL_EL2); } +static int __init early_ipiv_enable(char *buf) +{ + return strtobool(buf, &ipiv_enabled); +} +early_param("kvm-arm.ipiv_enabled", early_ipiv_enable); + +bool hisi_ipiv_supported(void) +{ + /* Determine whether IPIV is supported by the hardware */ + if (!(read_sysreg(aidr_el1) & AIDR_EL1_IPIV_MASK)) { + kvm_info("Hisi ipiv not supported by the hardware\n"); + return false; + } else + kvm_info("Hisi ipiv detected on the hardware\n"); + + /* User provided kernel command-line parameter */ + if (!ipiv_enabled || !is_kernel_in_hyp_mode()) + return false; + + /* Enable IPIV feature if necessary */ + if (!gic_dist_enable_ipiv()) { + kvm_info("Need to enable GICv4p1!\n"); + return false; + } + return true; +} + bool hisi_dvmbm_supported(void) { if (cpu_type != HI_IP10 && cpu_type != HI_IP10C) diff --git a/arch/arm64/kvm/hisilicon/hisi_virt.h b/arch/arm64/kvm/hisilicon/hisi_virt.h index e3b006343ead..ca37cc163cc7 100644 --- a/arch/arm64/kvm/hisilicon/hisi_virt.h +++ b/arch/arm64/kvm/hisilicon/hisi_virt.h @@ -14,9 +14,12 @@ enum hisi_cpu_type { HI_IP09, HI_IP10, HI_IP10C, + HI_IP12, UNKNOWN_HI_TYPE }; +/* HIP12 */ +#define AIDR_EL1_IPIV_MASK GENMASK_ULL(17, 16) /* HIP10 */ #define AIDR_EL1_DVMBM_MASK GENMASK_ULL(13, 12) #define SYS_LSUDVM_CTRL_EL2 sys_reg(3, 4, 15, 7, 4) @@ -67,6 +70,7 @@ enum hisi_cpu_type { void probe_hisi_cpu_type(void); bool hisi_ncsnp_supported(void); bool hisi_dvmbm_supported(void); +bool hisi_ipiv_supported(void); void kvm_get_pg_cfg(void); int kvm_sched_affinity_vcpu_init(struct kvm_vcpu *vcpu); @@ -86,6 +90,10 @@ static inline bool hisi_dvmbm_supported(void) { return false; } +static inline bool hisi_ipiv_supported(void) +{ + return false; +} static inline void kvm_get_pg_cfg(void) {} static inline int kvm_sched_affinity_vcpu_init(struct kvm_vcpu *vcpu) @@ -103,4 +111,5 @@ static inline void kvm_tlbi_dvmbm_vcpu_put(struct kvm_vcpu *vcpu) {} static inline void kvm_hisi_reload_lsudvmbm(struct kvm *kvm) {} #endif /* CONFIG_KVM_HISI_VIRT */ +extern bool gic_dist_enable_ipiv(void); #endif /* __HISI_VIRT_H__ */ diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c index 961c3a79f41d..e4c48e0baa6f 100644 --- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c +++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c @@ -341,6 +341,7 @@ static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu, u64 value; value = (u64)(mpidr & GENMASK(23, 0)) << 32; + value |= MPIDR_AFFINITY_LEVEL(mpidr, 3) << 56; value |= ((target_vcpu_id & 0xffff) << 8); if (vgic_has_its(vcpu->kvm)) diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 4cc8b95d533f..da44f67f8df7 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -111,6 +111,9 @@ static DEFINE_STATIC_KEY_FALSE(supports_pseudo_nmis); DEFINE_STATIC_KEY_FALSE(gic_nonsecure_priorities); EXPORT_SYMBOL(gic_nonsecure_priorities); +DEFINE_STATIC_KEY_FALSE(ipiv_enable); +EXPORT_SYMBOL(ipiv_enable); + /* * When the Non-secure world has access to group 0 interrupts (as a * consequence of SCR_EL3.FIQ == 0), reading the ICC_RPR_EL1 register will @@ -1511,6 +1514,23 @@ static int gic_dist_supports_lpis(void) !gicv3_nolpi); } +bool gic_dist_enable_ipiv(void) +{ + u32 val; + + /* feature ipiv is based on GICv4p1 */ + if (!gic_data.rdists.has_rvpeid) + return false; + + val = readl_relaxed(gic_data.dist_base + GICD_MISC_CTRL); + val |= GICD_MISC_CTRL_CFG_IPIV_EN; + writel_relaxed(val, gic_data.dist_base + GICD_MISC_CTRL); + static_branch_enable(&ipiv_enable); + + return true; +} +EXPORT_SYMBOL(gic_dist_enable_ipiv); + static void gic_cpu_init(void) { void __iomem *rbase; diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h index 548b8a5c46cf..00845d1a5a00 100644 --- a/include/linux/irqchip/arm-gic-v3.h +++ b/include/linux/irqchip/arm-gic-v3.h @@ -113,6 +113,9 @@ #define GIC_PAGE_SIZE_64K 2ULL #define GIC_PAGE_SIZE_MASK 3ULL +#define GICD_MISC_CTRL 0x2084 +#define GICD_MISC_CTRL_CFG_IPIV_EN (1U << 19) + /* * Re-Distributor registers, offsets from RD_base */ -- 2.33.0

From: Xiang Chen <chenxiang66@hisilicon.com> virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBPH85 ------------------------------------------------------------------------ When guest access register ICC_SGI1R_EL1, GIC will access VM table to get the vpeid of vcpu for IPIV feature. So when IPIV feature is enabled, allocate VM table and save vpeid in it. The index of the entries in VM table is vcpu id. Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com> Signed-off-by: Jinqian Yang <yangjinqian1@huawei.com> --- drivers/irqchip/irq-gic-v3-its.c | 49 ++++++++++++++++++++++++++++-- include/linux/irqchip/arm-gic-v3.h | 3 ++ include/linux/irqchip/arm-gic-v4.h | 1 + 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 49a60999f661..9e318335b034 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -388,6 +388,8 @@ static int alloc_devid_from_rsv_pools(struct rsv_devid_pool **devid_pool, #define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base) #define gic_data_rdist_vlpi_base() (gic_data_rdist_rd_base() + SZ_128K) +extern struct static_key_false ipiv_enable; + #ifdef CONFIG_VIRT_PLAT_DEV /* * Currently we only build *one* devid pool. @@ -4566,8 +4568,18 @@ static void its_vpe_4_1_schedule(struct its_vpe *vpe, struct its_cmd_info *info) { void __iomem *vlpi_base = gic_data_rdist_vlpi_base(); + struct its_vm *vm = vpe->its_vm; + unsigned long vpe_addr; u64 val = 0; + if (static_branch_unlikely(&ipiv_enable)) { + vpe_addr = virt_to_phys(page_address(vm->vpe_page)); + writeq_relaxed(vpe_addr & 0xffffffff, + vlpi_base + GICR_VM_TABLE_BAR_L); + writeq_relaxed((vpe_addr >> 32) & 0xffffffff, + vlpi_base + GICR_VM_TABLE_BAR_H); + } + /* Schedule the VPE */ val |= GICR_VPENDBASER_Valid; val |= info->g0en ? GICR_VPENDBASER_4_1_VGRP0EN : 0; @@ -4612,6 +4624,11 @@ static void its_vpe_4_1_deschedule(struct its_vpe *vpe, GICR_VPENDBASER_PendingLast); vpe->pending_last = true; } + + if (static_branch_unlikely(&ipiv_enable)) { + writeq_relaxed(0, vlpi_base + GICR_VM_TABLE_BAR_L); + writeq_relaxed(0, vlpi_base + GICR_VM_TABLE_BAR_H); + } } static void its_vpe_4_1_invall(struct its_vpe *vpe) @@ -5014,6 +5031,10 @@ static void its_vpe_irq_domain_free(struct irq_domain *domain, if (bitmap_empty(vm->db_bitmap, vm->nr_db_lpis)) { its_lpi_free(vm->db_bitmap, vm->db_lpi_base, vm->nr_db_lpis); its_free_prop_table(vm->vprop_page); + if (static_branch_unlikely(&ipiv_enable)) { + free_pages((unsigned long)page_address(vm->vpe_page), + get_order(nr_irqs * 2)); + } } } @@ -5023,8 +5044,10 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq struct irq_chip *irqchip = &its_vpe_irq_chip; struct its_vm *vm = args; unsigned long *bitmap; - struct page *vprop_page; + struct page *vprop_page, *vpe_page; int base, nr_ids, i, err = 0; + void *vpe_table_va; + u16 *vpe_entry; bitmap = its_lpi_alloc(roundup_pow_of_two(nr_irqs), &base, &nr_ids); if (!bitmap) @@ -5047,14 +5070,29 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq vm->vprop_page = vprop_page; raw_spin_lock_init(&vm->vmapp_lock); - if (gic_rdists->has_rvpeid) + if (gic_rdists->has_rvpeid) { irqchip = &its_vpe_4_1_irq_chip; + if (static_branch_unlikely(&ipiv_enable)) { + vpe_page = alloc_pages(GFP_KERNEL, get_order(nr_irqs * 2)); + if (!vpe_page) { + its_lpi_free(vm->db_bitmap, vm->db_lpi_base, vm->nr_db_lpis); + its_free_prop_table(vm->vprop_page); + return -ENOMEM; + } + vm->vpe_page = vpe_page; + vpe_table_va = page_address(vm->vpe_page); + } + } for (i = 0; i < nr_irqs; i++) { vm->vpes[i]->vpe_db_lpi = base + i; err = its_vpe_init(vm->vpes[i]); if (err) break; + if (static_branch_unlikely(&ipiv_enable)) { + vpe_entry = (u16 *)vpe_table_va + i; + *(u16 *)vpe_entry = vm->vpes[i]->vpe_id; + } err = its_irq_gic_domain_alloc(domain, virq + i, vm->vpes[i]->vpe_db_lpi); if (err) @@ -5065,8 +5103,13 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq irqd_set_resend_when_in_progress(irq_get_irq_data(virq + i)); } - if (err) + if (err) { its_vpe_irq_domain_free(domain, virq, i); + if (static_branch_unlikely(&ipiv_enable)) { + free_pages((unsigned long)page_address(vm->vpe_page), + get_order(nr_irqs * 2)); + } + } return err; } diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h index 00845d1a5a00..904d788eed74 100644 --- a/include/linux/irqchip/arm-gic-v3.h +++ b/include/linux/irqchip/arm-gic-v3.h @@ -365,6 +365,9 @@ #define GICR_VSGIPENDR_BUSY (1U << 31) #define GICR_VSGIPENDR_PENDING GENMASK(15, 0) +#define GICR_VM_TABLE_BAR_L 0x140 +#define GICR_VM_TABLE_BAR_H 0x144 + /* * ITS registers, offsets from ITS_base */ diff --git a/include/linux/irqchip/arm-gic-v4.h b/include/linux/irqchip/arm-gic-v4.h index 2d6f41001a46..d3281506af9c 100644 --- a/include/linux/irqchip/arm-gic-v4.h +++ b/include/linux/irqchip/arm-gic-v4.h @@ -20,6 +20,7 @@ struct its_vm { struct fwnode_handle *fwnode; struct irq_domain *domain; struct page *vprop_page; + struct page *vpe_page; struct its_vpe **vpes; int nr_vpes; irq_hw_number_t db_lpi_base; -- 2.33.0

From: Xiang Chen <chenxiang66@hisilicon.com> virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBPH85 ------------------------------------------------------------------------ There are two modes for IPIV feature: - indirect mode, access vm table to retrieve vpeid; - direct mode, directly calcute vpeid according to mpidr; Add support for ipiv direct mode. Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com> Signed-off-by: Jinqian Yang <yangjinqian1@huawei.com> --- .../admin-guide/kernel-parameters.txt | 5 ++++ arch/arm64/kvm/hisilicon/hisi_virt.c | 11 ++++++- arch/arm64/kvm/hisilicon/hisi_virt.h | 2 +- arch/arm64/kvm/sys_regs.c | 30 ++++++++++++++----- drivers/irqchip/irq-gic-v3-its.c | 19 ++++++++---- drivers/irqchip/irq-gic-v3.c | 12 +++++++- include/linux/irqchip/arm-gic-v3.h | 3 ++ 7 files changed, 65 insertions(+), 17 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 459323983fa9..000b990876fe 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -2712,6 +2712,11 @@ kvm-arm.ipiv_enabled= [KVM,ARM] Allow use of HiSilicon ipiv on GICv4.1 + kvm-arm.ipiv_direct= + [KVM,ARM] Use different modes of ipiv if ipiv enabled + Default is 0 which using vmtable in memory to retrieve aff-vpeid + Directly calculate vpeid according to aff if set 1 + kvm-arm.dvmbm_enabled= [KVM,ARM] Allow use of HiSilicon DVMBM capability. Default: 0 diff --git a/arch/arm64/kvm/hisilicon/hisi_virt.c b/arch/arm64/kvm/hisilicon/hisi_virt.c index 642aff5ff7d8..89f488d4cbc6 100644 --- a/arch/arm64/kvm/hisilicon/hisi_virt.c +++ b/arch/arm64/kvm/hisilicon/hisi_virt.c @@ -13,6 +13,7 @@ static enum hisi_cpu_type cpu_type = UNKNOWN_HI_TYPE; static bool dvmbm_enabled; static bool ipiv_enabled; +static bool ipiv_direct; static const char * const hisi_cpu_type_str[] = { "Hisi1612", @@ -164,6 +165,12 @@ static int __init early_ipiv_enable(char *buf) } early_param("kvm-arm.ipiv_enabled", early_ipiv_enable); +static int __init early_ipiv_direct(char *buf) +{ + return kstrtobool(buf, &ipiv_direct); +} +early_param("kvm-arm.ipiv_direct", early_ipiv_direct); + bool hisi_ipiv_supported(void) { /* Determine whether IPIV is supported by the hardware */ @@ -178,10 +185,12 @@ bool hisi_ipiv_supported(void) return false; /* Enable IPIV feature if necessary */ - if (!gic_dist_enable_ipiv()) { + if (!gic_dist_enable_ipiv(ipiv_direct)) { kvm_info("Need to enable GICv4p1!\n"); return false; } + + kvm_info("Enable Hisi ipiv with %s mode\n", ipiv_direct ? "direct" : "indirect"); return true; } diff --git a/arch/arm64/kvm/hisilicon/hisi_virt.h b/arch/arm64/kvm/hisilicon/hisi_virt.h index ca37cc163cc7..c99a6fbe1412 100644 --- a/arch/arm64/kvm/hisilicon/hisi_virt.h +++ b/arch/arm64/kvm/hisilicon/hisi_virt.h @@ -111,5 +111,5 @@ static inline void kvm_tlbi_dvmbm_vcpu_put(struct kvm_vcpu *vcpu) {} static inline void kvm_hisi_reload_lsudvmbm(struct kvm *kvm) {} #endif /* CONFIG_KVM_HISI_VIRT */ -extern bool gic_dist_enable_ipiv(void); +extern bool gic_dist_enable_ipiv(bool direct); #endif /* __HISI_VIRT_H__ */ diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 0cfa8d93e2ee..69cbc11f5ff7 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -711,20 +711,34 @@ static u64 reset_actlr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) return actlr; } +extern struct static_key_false ipiv_enable; +extern struct static_key_false ipiv_direct; + static u64 reset_mpidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { + struct its_vpe *vpe = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe; u64 mpidr; /* - * Map the vcpu_id into the first three affinity level fields of - * the MPIDR. We limit the number of VCPUs in level 0 due to a - * limitation to 16 CPUs in that level in the ICC_SGIxR registers - * of the GICv3 to be able to address each CPU directly when - * sending IPIs. + * For direct ipiv mode, use vpeid as aff2/aff3 + * For indirect ipiv mode, use vcpu_id to index vpeid. To + * avoid sending multi-SGIs in guest OS, make aff1/aff2 unique */ - mpidr = (vcpu->vcpu_id & 0x0f) << MPIDR_LEVEL_SHIFT(0); - mpidr |= ((vcpu->vcpu_id >> 4) & 0xff) << MPIDR_LEVEL_SHIFT(1); - mpidr |= ((vcpu->vcpu_id >> 12) & 0xff) << MPIDR_LEVEL_SHIFT(2); + if (static_branch_unlikely(&ipiv_enable)) { + if (static_branch_unlikely(&ipiv_direct)) { + u64 vpe_id_aff3 = (vpe->vpe_id >> 8) & 0xff; + + mpidr |= ((vpe->vpe_id & 0xff) << MPIDR_LEVEL_SHIFT(2)); + mpidr |= vpe_id_aff3 << MPIDR_LEVEL_SHIFT(3); + } else { + mpidr = (vcpu->vcpu_id & 0x0f) << MPIDR_LEVEL_SHIFT(1); + mpidr |= ((vcpu->vcpu_id >> 4) & 0xff) << MPIDR_LEVEL_SHIFT(2); + } + } else { + mpidr = (vcpu->vcpu_id & 0x0f) << MPIDR_LEVEL_SHIFT(0); + mpidr |= ((vcpu->vcpu_id >> 4) & 0xff) << MPIDR_LEVEL_SHIFT(1); + mpidr |= ((vcpu->vcpu_id >> 12) & 0xff) << MPIDR_LEVEL_SHIFT(2); + } mpidr |= (1ULL << 31); vcpu_write_sys_reg(vcpu, mpidr, MPIDR_EL1); diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 9e318335b034..8ec6fd61b59d 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -389,6 +389,7 @@ static int alloc_devid_from_rsv_pools(struct rsv_devid_pool **devid_pool, #define gic_data_rdist_vlpi_base() (gic_data_rdist_rd_base() + SZ_128K) extern struct static_key_false ipiv_enable; +extern struct static_key_false ipiv_direct; #ifdef CONFIG_VIRT_PLAT_DEV /* @@ -4572,7 +4573,8 @@ static void its_vpe_4_1_schedule(struct its_vpe *vpe, unsigned long vpe_addr; u64 val = 0; - if (static_branch_unlikely(&ipiv_enable)) { + if (static_branch_unlikely(&ipiv_enable) && + !static_branch_unlikely(&ipiv_direct)) { vpe_addr = virt_to_phys(page_address(vm->vpe_page)); writeq_relaxed(vpe_addr & 0xffffffff, vlpi_base + GICR_VM_TABLE_BAR_L); @@ -4625,7 +4627,8 @@ static void its_vpe_4_1_deschedule(struct its_vpe *vpe, vpe->pending_last = true; } - if (static_branch_unlikely(&ipiv_enable)) { + if (static_branch_unlikely(&ipiv_enable) && + !static_branch_unlikely(&ipiv_direct)) { writeq_relaxed(0, vlpi_base + GICR_VM_TABLE_BAR_L); writeq_relaxed(0, vlpi_base + GICR_VM_TABLE_BAR_H); } @@ -5031,7 +5034,8 @@ static void its_vpe_irq_domain_free(struct irq_domain *domain, if (bitmap_empty(vm->db_bitmap, vm->nr_db_lpis)) { its_lpi_free(vm->db_bitmap, vm->db_lpi_base, vm->nr_db_lpis); its_free_prop_table(vm->vprop_page); - if (static_branch_unlikely(&ipiv_enable)) { + if (static_branch_unlikely(&ipiv_enable) && + !static_branch_unlikely(&ipiv_direct)) { free_pages((unsigned long)page_address(vm->vpe_page), get_order(nr_irqs * 2)); } @@ -5072,7 +5076,8 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq if (gic_rdists->has_rvpeid) { irqchip = &its_vpe_4_1_irq_chip; - if (static_branch_unlikely(&ipiv_enable)) { + if (static_branch_unlikely(&ipiv_enable) && + !static_branch_unlikely(&ipiv_direct)) { vpe_page = alloc_pages(GFP_KERNEL, get_order(nr_irqs * 2)); if (!vpe_page) { its_lpi_free(vm->db_bitmap, vm->db_lpi_base, vm->nr_db_lpis); @@ -5089,7 +5094,8 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq err = its_vpe_init(vm->vpes[i]); if (err) break; - if (static_branch_unlikely(&ipiv_enable)) { + if (static_branch_unlikely(&ipiv_enable) && + !static_branch_unlikely(&ipiv_direct)) { vpe_entry = (u16 *)vpe_table_va + i; *(u16 *)vpe_entry = vm->vpes[i]->vpe_id; } @@ -5105,7 +5111,8 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq if (err) { its_vpe_irq_domain_free(domain, virq, i); - if (static_branch_unlikely(&ipiv_enable)) { + if (static_branch_unlikely(&ipiv_enable) & + !static_branch_unlikely(&ipiv_direct)) { free_pages((unsigned long)page_address(vm->vpe_page), get_order(nr_irqs * 2)); } diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index da44f67f8df7..a24160eabc1a 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -114,6 +114,9 @@ EXPORT_SYMBOL(gic_nonsecure_priorities); DEFINE_STATIC_KEY_FALSE(ipiv_enable); EXPORT_SYMBOL(ipiv_enable); +DEFINE_STATIC_KEY_FALSE(ipiv_direct); +EXPORT_SYMBOL(ipiv_direct); + /* * When the Non-secure world has access to group 0 interrupts (as a * consequence of SCR_EL3.FIQ == 0), reading the ICC_RPR_EL1 register will @@ -1514,7 +1517,7 @@ static int gic_dist_supports_lpis(void) !gicv3_nolpi); } -bool gic_dist_enable_ipiv(void) +bool gic_dist_enable_ipiv(bool direct) { u32 val; @@ -1527,6 +1530,13 @@ bool gic_dist_enable_ipiv(void) writel_relaxed(val, gic_data.dist_base + GICD_MISC_CTRL); static_branch_enable(&ipiv_enable); + val = readl_relaxed(gic_data.dist_base + GICD_IPIV_CTRL); + if (direct) { + val |= GICD_IPIV_CTRL_AFF_DIRECT_VPEID; + static_branch_enable(&ipiv_direct); + } + writel_relaxed(val, gic_data.dist_base + GICD_IPIV_CTRL); + return true; } EXPORT_SYMBOL(gic_dist_enable_ipiv); diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h index 904d788eed74..bc96a5b66ee9 100644 --- a/include/linux/irqchip/arm-gic-v3.h +++ b/include/linux/irqchip/arm-gic-v3.h @@ -116,6 +116,9 @@ #define GICD_MISC_CTRL 0x2084 #define GICD_MISC_CTRL_CFG_IPIV_EN (1U << 19) +#define GICD_IPIV_CTRL 0xc05c +#define GICD_IPIV_CTRL_AFF_DIRECT_VPEID (1U << 4) + /* * Re-Distributor registers, offsets from RD_base */ -- 2.33.0

From: Xiang Chen <chenxiang66@hisilicon.com> virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBPH85 ------------------------------------------------------------------------ When the index of VM table exceeds the supported range or guest sends SGI with IRM=1, it triggers a exception interrupt (PPI interrupt). Just printk exception info in interrupt handler. Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com> Signed-off-by: Jinqian Yang <yangjinqian1@huawei.com> --- arch/arm64/kvm/vgic/vgic-init.c | 45 +++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c index db5db9402c3a..ec0965f26d70 100644 --- a/arch/arm64/kvm/vgic/vgic-init.c +++ b/arch/arm64/kvm/vgic/vgic-init.c @@ -3,6 +3,7 @@ * Copyright (C) 2015, 2016 ARM Ltd. */ +#include <linux/acpi.h> #include <linux/uaccess.h> #include <linux/interrupt.h> #include <linux/cpu.h> @@ -531,17 +532,30 @@ int kvm_vgic_map_resources(struct kvm *kvm) return ret; } +extern struct static_key_false ipiv_enable; +static int ipiv_irq; + /* GENERIC PROBE */ void kvm_vgic_cpu_up(void) { enable_percpu_irq(kvm_vgic_global_state.maint_irq, 0); + if (static_branch_unlikely(&ipiv_enable)) + enable_percpu_irq(ipiv_irq, 0); } void kvm_vgic_cpu_down(void) { disable_percpu_irq(kvm_vgic_global_state.maint_irq); + if (static_branch_unlikely(&ipiv_enable)) + disable_percpu_irq(ipiv_irq); +} + +static irqreturn_t vgic_ipiv_irq_handler(int irq, void *data) +{ + kvm_info("IPIV irq handler!\n"); + return IRQ_HANDLED; } static irqreturn_t vgic_maintenance_handler(int irq, void *data) @@ -615,6 +629,16 @@ int kvm_vgic_hyp_init(void) kvm_vgic_global_state.no_hw_deactivation = true; } + if (static_branch_unlikely(&ipiv_enable)) { + /* FIXME: need to check irq type */ + ipiv_irq = acpi_register_gsi(NULL, 18, ACPI_LEVEL_SENSITIVE, + ACPI_ACTIVE_HIGH); + if (ipiv_irq < 0) { + kvm_err("No ipiv exception irq\n"); + return -ENXIO; + } + } + kvm_vgic_global_state.flags = gic_kvm_info->flags; switch (gic_kvm_info->type) { case GIC_V2: @@ -637,7 +661,7 @@ int kvm_vgic_hyp_init(void) gic_kvm_info = NULL; if (ret) - return ret; + goto out_unregister_gsi; if (!has_mask && !kvm_vgic_global_state.maint_irq) return 0; @@ -648,9 +672,26 @@ int kvm_vgic_hyp_init(void) if (ret) { kvm_err("Cannot register interrupt %d\n", kvm_vgic_global_state.maint_irq); - return ret; + goto out_unregister_gsi; } kvm_info("vgic interrupt IRQ%d\n", kvm_vgic_global_state.maint_irq); + + if (static_branch_unlikely(&ipiv_enable)) { + ret = request_percpu_irq(ipiv_irq, vgic_ipiv_irq_handler, + "ipiv exception", kvm_get_running_vcpus()); + if (ret) { + kvm_err("Cannot register interrupt %d\n", ipiv_irq); + goto out_free_irq; + } + } + return 0; +out_free_irq: + free_percpu_irq(kvm_vgic_global_state.maint_irq, + kvm_get_running_vcpus()); +out_unregister_gsi: + if (static_branch_unlikely(&ipiv_enable)) + acpi_unregister_gsi(18); + return ret; } -- 2.33.0

From: Xiang Chen <chenxiang66@hisilicon.com> virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBPH85 ------------------------------------------------------------------------ Set the base address of vm table and target ITS when vpe schedule and deschedule. Also need to make sure IPIV is not busy before setting them. Disable ICC_SGI1R_EL1 trap when vpe schedule, and enable the trap when vpe deschedule. Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com> Signed-off-by: Nianyao Tang <tangnianyao@huawei.com> Signed-off-by: Jinqian Yang <yangjinqian1@huawei.com> --- drivers/irqchip/irq-gic-v3-its.c | 58 ++++++++++++++++++++++++------ drivers/irqchip/irq-gic-v3.c | 9 ++++- include/linux/irqchip/arm-gic-v3.h | 14 ++++++++ 3 files changed, 69 insertions(+), 12 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 8ec6fd61b59d..1bf16c1f9a92 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -4572,18 +4572,44 @@ static void its_vpe_4_1_schedule(struct its_vpe *vpe, struct its_vm *vm = vpe->its_vm; unsigned long vpe_addr; u64 val = 0; - - if (static_branch_unlikely(&ipiv_enable) && - !static_branch_unlikely(&ipiv_direct)) { - vpe_addr = virt_to_phys(page_address(vm->vpe_page)); - writeq_relaxed(vpe_addr & 0xffffffff, + u32 nr_vpes; + + if (static_branch_unlikely(&ipiv_enable)) { + /* wait gicr_ipiv_busy */ + WARN_ON_ONCE(readl_relaxed_poll_timeout_atomic( + vlpi_base + GICR_IPIV_ST, + val, + !(val & GICR_IPIV_ST_IPIV_BUSY), + 1, 500)); + if (!static_branch_unlikely(&ipiv_direct)) { + /* setup vm table */ + vpe_addr = virt_to_phys(page_address(vm->vpe_page)); + writel_relaxed(vpe_addr & 0xffffffff, vlpi_base + GICR_VM_TABLE_BAR_L); - writeq_relaxed((vpe_addr >> 32) & 0xffffffff, + writel_relaxed((vpe_addr >> 32) & 0xffffffff, vlpi_base + GICR_VM_TABLE_BAR_H); + + /* setup gicr_vcpu_entry_num_max and gicr_ipiv_its_ta_sel */ + nr_vpes = vpe->its_vm->nr_vpes; + val = ((nr_vpes - 1) << GICR_IPIV_CTRL_VCPU_ENTRY_NUM_MAX_SHIFT) | + (0 << GICR_IPIV_CTRL_IPIV_ITS_TA_SEL_SHIFT); + writel_relaxed(val, vlpi_base + GICR_IPIV_CTRL); + } else { + /* setup gicr_ipiv_its_ta_sel */ + val = (0 << GICR_IPIV_CTRL_IPIV_ITS_TA_SEL_SHIFT); + writel_relaxed(val, vlpi_base + GICR_IPIV_CTRL); + } + + /* disable guest access ICC_SGI1R_EL1 trap */ + asm volatile("mrs %0, s3_4_c15_c7_2" : "=r" (val)); + val |= 1ULL; + asm volatile("msr s3_4_c15_c7_2, %0" : : "r" (val)); + asm volatile("mrs %0, s3_4_c15_c7_2" : "=r" (val)); + } /* Schedule the VPE */ - val |= GICR_VPENDBASER_Valid; + val = GICR_VPENDBASER_Valid; val |= info->g0en ? GICR_VPENDBASER_4_1_VGRP0EN : 0; val |= info->g1en ? GICR_VPENDBASER_4_1_VGRP1EN : 0; val |= FIELD_PREP(GICR_VPENDBASER_4_1_VPEID, vpe->vpe_id); @@ -4627,10 +4653,20 @@ static void its_vpe_4_1_deschedule(struct its_vpe *vpe, vpe->pending_last = true; } - if (static_branch_unlikely(&ipiv_enable) && - !static_branch_unlikely(&ipiv_direct)) { - writeq_relaxed(0, vlpi_base + GICR_VM_TABLE_BAR_L); - writeq_relaxed(0, vlpi_base + GICR_VM_TABLE_BAR_H); + if (static_branch_unlikely(&ipiv_enable)) { + if (!static_branch_unlikely(&ipiv_direct)) { + + /* wait gicr_ipiv_busy */ + WARN_ON_ONCE(readl_relaxed_poll_timeout_atomic(vlpi_base + GICR_IPIV_ST, + val, !(val & GICR_IPIV_ST_IPIV_BUSY), 1, 500)); + writel_relaxed(0, vlpi_base + GICR_VM_TABLE_BAR_L); + writel_relaxed(0, vlpi_base + GICR_VM_TABLE_BAR_H); + } + /* enable guest access ICC_SGI1R_EL1 trap, disable ipiv */ + asm volatile("mrs %0, s3_4_c15_c7_2" : "=r" (val)); + val &= ~1UL; + asm volatile("msr s3_4_c15_c7_2, %0" : : "r" (val)); + asm volatile("mrs %0, s3_4_c15_c7_2" : "=r" (val)); } } diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index a24160eabc1a..d5c4d0993436 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -1534,9 +1534,16 @@ bool gic_dist_enable_ipiv(bool direct) if (direct) { val |= GICD_IPIV_CTRL_AFF_DIRECT_VPEID; static_branch_enable(&ipiv_direct); + } else { + val = (0 << GICD_IPIV_CTRL_AFF_DIRECT_VPEID_SHIFT) | + (0 << GICD_IPIV_CTRL_AFF1_LEFT_SHIFT_SHIFT) | + (4 << GICD_IPIV_CTRL_AFF2_LEFT_SHIFT_SHIFT) | + (7 << GICD_IPIV_CTRL_VM_TABLE_INNERCACHE_SHIFT) | + (2 << GICD_IPIV_CTRL_VM_TABLE_SHAREABILITY_SHIFT); } writel_relaxed(val, gic_data.dist_base + GICD_IPIV_CTRL); - + /* Set target ITS address of IPIV feature */ + writel_relaxed(0x4880, gic_data.dist_base + GICD_IPIV_ITS_TA_BASE); return true; } EXPORT_SYMBOL(gic_dist_enable_ipiv); diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h index bc96a5b66ee9..dbdaf5457a5f 100644 --- a/include/linux/irqchip/arm-gic-v3.h +++ b/include/linux/irqchip/arm-gic-v3.h @@ -118,7 +118,13 @@ #define GICD_IPIV_CTRL 0xc05c #define GICD_IPIV_CTRL_AFF_DIRECT_VPEID (1U << 4) +#define GICD_IPIV_CTRL_AFF_DIRECT_VPEID_SHIFT 4 +#define GICD_IPIV_CTRL_AFF1_LEFT_SHIFT_SHIFT 8 +#define GICD_IPIV_CTRL_AFF2_LEFT_SHIFT_SHIFT 12 +#define GICD_IPIV_CTRL_VM_TABLE_INNERCACHE_SHIFT 16 +#define GICD_IPIV_CTRL_VM_TABLE_SHAREABILITY_SHIFT 19 +#define GICD_IPIV_ITS_TA_BASE 0xc010 /* * Re-Distributor registers, offsets from RD_base */ @@ -371,6 +377,14 @@ #define GICR_VM_TABLE_BAR_L 0x140 #define GICR_VM_TABLE_BAR_H 0x144 +#define GICR_IPIV_CTRL 0x148 +#define GICR_IPIV_CTRL_VCPU_ENTRY_NUM_MAX_SHIFT 8 +#define GICR_IPIV_CTRL_IPIV_ITS_TA_SEL_SHIFT 4 + +#define GICR_IPIV_ST 0x14c +#define GICR_IPIV_ST_IPIV_BUSY_SHIFT 0 +#define GICR_IPIV_ST_IPIV_BUSY (1 << GICR_IPIV_ST_IPIV_BUSY_SHIFT) + /* * ITS registers, offsets from ITS_base */ -- 2.33.0

From: Xiang Chen <chenxiang66@hisilicon.com> virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBPH85 ------------------------------------------------------------------------ For direct mode, need to use vpe id, so need to pre-allocate vpe id before reset_mpidr. Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com> Signed-off-by: Nianyao Tang <tangnianyao@huawei.com> Signed-off-by: Jinqian Yang <yangjinqian1@huawei.com> --- arch/arm64/kvm/arm.c | 6 +++++ arch/arm64/kvm/sys_regs.c | 7 ++++-- arch/arm64/kvm/vgic/vgic-init.c | 40 ++++++++++++++++++++++++++++++ drivers/irqchip/irq-gic-v3-its.c | 18 ++++++++++---- include/kvm/arm_vgic.h | 2 ++ include/linux/irqchip/arm-gic-v4.h | 1 + 6 files changed, 67 insertions(+), 7 deletions(-) diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 5115df307ab9..6bc313fcf1da 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -514,6 +514,10 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) if (err) return err; + err = kvm_vgic_vpe_id_alloc(vcpu); + if (err) + return err; + return kvm_share_hyp(vcpu, vcpu + 1); } @@ -530,6 +534,8 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) kvm_arm_vcpu_destroy(vcpu); kvm_sched_affinity_vcpu_destroy(vcpu); + + kvm_vgic_vpe_id_free(vcpu); } void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 69cbc11f5ff7..bc30ef0e1824 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -726,9 +726,12 @@ static u64 reset_mpidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) */ if (static_branch_unlikely(&ipiv_enable)) { if (static_branch_unlikely(&ipiv_direct)) { - u64 vpe_id_aff3 = (vpe->vpe_id >> 8) & 0xff; + u64 vpe_id_aff3, vpe_id_aff2; - mpidr |= ((vpe->vpe_id & 0xff) << MPIDR_LEVEL_SHIFT(2)); + vpe_id_aff2 = (vpe->vpe_id >> 8) & 0xff; + vpe_id_aff3 = (vpe->vpe_id & 0xff); + + mpidr |= vpe_id_aff2 << MPIDR_LEVEL_SHIFT(2); mpidr |= vpe_id_aff3 << MPIDR_LEVEL_SHIFT(3); } else { mpidr = (vcpu->vcpu_id & 0x0f) << MPIDR_LEVEL_SHIFT(1); diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c index ec0965f26d70..ba944bef7235 100644 --- a/arch/arm64/kvm/vgic/vgic-init.c +++ b/arch/arm64/kvm/vgic/vgic-init.c @@ -695,3 +695,43 @@ int kvm_vgic_hyp_init(void) acpi_unregister_gsi(18); return ret; } + +extern int its_vpe_id_alloc(void); +extern void its_vpe_id_free(u16 id); +int kvm_vgic_vpe_id_alloc(struct kvm_vcpu *vcpu) +{ + struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; + int vpe_id; + + if (vgic_cpu->vgic_v3.its_vpe.vpe_id_allocated) { + kvm_err("[%s]vpe_id already allocated\n", __func__); + return -1; + } + + vpe_id = its_vpe_id_alloc(); + if (vpe_id < 0) { + kvm_err("[%s]alloc vpe id fail: vpe_id=%d\n", __func__, vpe_id); + return vpe_id; + } + + vgic_cpu->vgic_v3.its_vpe.vpe_id = vpe_id; + vgic_cpu->vgic_v3.its_vpe.vpe_id_allocated = true; + + return 0; +} + +int kvm_vgic_vpe_id_free(struct kvm_vcpu *vcpu) +{ + struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; + int vpe_id; + + vpe_id = vgic_cpu->vgic_v3.its_vpe.vpe_id; + + if (!vgic_cpu->vgic_v3.its_vpe.vpe_id_allocated) + return 0; + + its_vpe_id_free(vpe_id); + vgic_cpu->vgic_v3.its_vpe.vpe_id_allocated = false; + + return 0; +} diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 1bf16c1f9a92..72fe63f78952 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -4996,15 +4996,17 @@ static const struct irq_domain_ops its_sgi_domain_ops = { .deactivate = its_sgi_irq_domain_deactivate, }; -static int its_vpe_id_alloc(void) +int its_vpe_id_alloc(void) { return ida_simple_get(&its_vpeid_ida, 0, ITS_MAX_VPEID, GFP_KERNEL); } +EXPORT_SYMBOL(its_vpe_id_alloc); -static void its_vpe_id_free(u16 id) +void its_vpe_id_free(u16 id) { ida_simple_remove(&its_vpeid_ida, id); } +EXPORT_SYMBOL(its_vpe_id_free); static int its_vpe_init(struct its_vpe *vpe) { @@ -5012,9 +5014,13 @@ static int its_vpe_init(struct its_vpe *vpe) int vpe_id; /* Allocate vpe_id */ - vpe_id = its_vpe_id_alloc(); - if (vpe_id < 0) - return vpe_id; + if (!vpe->vpe_id_allocated) { + vpe_id = its_vpe_id_alloc(); + if (vpe_id < 0) + return vpe_id; + } else { + vpe_id = vpe->vpe_id; + } /* Allocate VPT */ vpt_page = its_allocate_pending_table(GFP_KERNEL); @@ -5031,6 +5037,7 @@ static int its_vpe_init(struct its_vpe *vpe) raw_spin_lock_init(&vpe->vpe_lock); vpe->vpe_id = vpe_id; + vpe->vpe_id_allocated = true; vpe->vpt_page = vpt_page; atomic_set(&vpe->vmapp_count, 0); if (!gic_rdists->has_rvpeid) @@ -5043,6 +5050,7 @@ static void its_vpe_teardown(struct its_vpe *vpe) { its_vpe_db_proxy_unmap(vpe); its_vpe_id_free(vpe->vpe_id); + vpe->vpe_id_allocated = false; its_free_pending_table(vpe->vpt_page); } diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index 0b734d6f3d21..460d226450af 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h @@ -454,6 +454,8 @@ void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu); int kvm_vgic_map_resources(struct kvm *kvm); int kvm_vgic_hyp_init(void); void kvm_vgic_init_cpu_hardware(void); +int kvm_vgic_vpe_id_alloc(struct kvm_vcpu *vcpu); +int kvm_vgic_vpe_id_free(struct kvm_vcpu *vcpu); int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid, bool level, void *owner); diff --git a/include/linux/irqchip/arm-gic-v4.h b/include/linux/irqchip/arm-gic-v4.h index d3281506af9c..ea29e773d139 100644 --- a/include/linux/irqchip/arm-gic-v4.h +++ b/include/linux/irqchip/arm-gic-v4.h @@ -92,6 +92,7 @@ struct its_vpe { u16 col_idx; /* Unique (system-wide) VPE identifier */ u16 vpe_id; + bool vpe_id_allocated; /* Pending VLPIs on schedule out? */ bool pending_last; }; -- 2.33.0

From: Xiang Chen <chenxiang66@hisilicon.com> virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBPH85 ------------------------------------------------------------------------ Before IPIV feature, it gets mpidr from vcpu id, but after the feature, we need to know which IPIV mode is used. vpeid is not set at that time, so need to consider how to get vpeid for direct mode later. Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com> Signed-off-by: Jinqian Yang <yangjinqian1@huawei.com> --- arch/arm64/kvm/arm.c | 12 ++++++++++++ include/uapi/linux/kvm.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 6bc313fcf1da..4f78bbe2d0e6 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -315,6 +315,8 @@ void kvm_arch_destroy_vm(struct kvm *kvm) #endif } +extern struct static_key_false ipiv_enable; +extern struct static_key_false ipiv_direct; int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) { int r; @@ -439,6 +441,16 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) r = static_key_enabled(&virtcca_cvm_is_available); break; #endif + case KVM_CAP_ARM_IPIV_MODE: + if (static_branch_unlikely(&ipiv_enable)) { + if (static_branch_unlikely(&ipiv_direct)) + r = 2; /* direct mode */ + else + r = 1; /* indirect mode */ + } else { + r = 0; /* don't enable IPIV */ + } + break; default: r = 0; } diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index f97ab651ccbb..d1086d4acfca 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1201,6 +1201,8 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE 228 #define KVM_CAP_ARM_SUPPORTED_BLOCK_SIZES 229 +#define KVM_CAP_ARM_IPIV_MODE 301 /* ipiv mode */ + #define KVM_CAP_SEV_ES_GHCB 500 #define KVM_CAP_HYGON_COCO_EXT 501 /* support userspace to request firmware to build CSV3 guest's memory space */ -- 2.33.0

From: Xiang Chen <chenxiang66@hisilicon.com> virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBPH85 ------------------------------------------------------------------------ For ipiv irq, its type is edge sensitive not level sensitive. So do some changes for corresponding update. Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com> Signed-off-by: Jinqian Yang <yangjinqian1@huawei.com> --- arch/arm64/kvm/vgic/vgic-init.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c index ba944bef7235..1be6c9a4970a 100644 --- a/arch/arm64/kvm/vgic/vgic-init.c +++ b/arch/arm64/kvm/vgic/vgic-init.c @@ -630,8 +630,7 @@ int kvm_vgic_hyp_init(void) } if (static_branch_unlikely(&ipiv_enable)) { - /* FIXME: need to check irq type */ - ipiv_irq = acpi_register_gsi(NULL, 18, ACPI_LEVEL_SENSITIVE, + ipiv_irq = acpi_register_gsi(NULL, 18, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_HIGH); if (ipiv_irq < 0) { kvm_err("No ipiv exception irq\n"); -- 2.33.0

From: Xiang Chen <chenxiang66@hisilicon.com> virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBPH85 ------------------------------------------------------------------------ This benchmark sends many IPIs in different modes and measures time for IPI delivery (first column), and total time, ie including time to acknowledge the receive by sender (second column). The scenarios are: Dry-run: do everything except actually sending IPI. Useful to estimate system overhead. Self-IPI: Send IPI to self CPU. Normal IPI: Send IPI to some other CPU. Broadcast IPI: Send broadcast IPI to all online CPUs. Broadcast lock: Send broadcast IPI to all online CPUs and force them acquire/release spinlock. The raw output looks like this: [ 155.363374] Dry-run: 0, 2999696 ns [ 155.429162] Self-IPI: 30385328, 65589392 ns [ 156.060821] Normal IPI: 566914128, 631453008 ns [ 158.384427] Broadcast IPI: 0, 2323368720 ns [ 160.831850] Broadcast lock: 0, 2447000544 ns For virtualized guests, sending and reveiving IPIs causes guest exit. I used this test to measure performance impact on KVM subsystem of Christoffer Dall's series "Optimize KVM/ARM for VHE systems" [1]. Test machine is ThunderX2, 112 online CPUs. Below the results normalized to host dry-run time, broadcast lock results omitted. Smaller - better. Host, v4.14: Dry-run: 0 1 Self-IPI: 9 18 Normal IPI: 81 110 Broadcast IPI: 0 2106 Guest, v4.14: Dry-run: 0 1 Self-IPI: 10 18 Normal IPI: 305 525 Broadcast IPI: 0 9729 Guest, v4.14 + [1]: Dry-run: 0 1 Self-IPI: 9 18 Normal IPI: 176 343 Broadcast IPI: 0 9885 [1] https://www.spinics.net/lists/kvm/msg156755.html v2: added broadcast lock test; added example raw output in patch description; CC: Andrew Morton <akpm@linux-foundation.org> CC: Ashish Kalra <Ashish.Kalra@cavium.com> CC: Christoffer Dall <christoffer.dall@linaro.org> CC: Geert Uytterhoeven <geert@linux-m68k.org> CC: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> CC: Linu Cherian <Linu.Cherian@cavium.com> CC: Shih-Wei Li <shihwei@cs.columbia.edu> CC: Sunil Goutham <Sunil.Goutham@cavium.com> Signed-off-by: Yury Norov <ynorov@caviumnetworks.com> Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com> Signed-off-by: Jinqian Yang <yangjinqian1@huawei.com> --- arch/Kconfig | 10 +++ kernel/Makefile | 1 + kernel/ipi_benchmark.c | 155 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+) create mode 100644 kernel/ipi_benchmark.c diff --git a/arch/Kconfig b/arch/Kconfig index a4ed5d338dad..43958c65e76f 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -97,6 +97,16 @@ config JUMP_LABEL ( On 32-bit x86, the necessary options added to the compiler flags may increase the size of the kernel slightly. ) +config IPI_BENCHMARK + tristate "Test IPI performance on SMP systems" + depends on SMP + help + Test IPI performance on SMP systems. If system has only one online + CPU, sending IPI to other CPU is obviously not possible, and ENOENT + is returned for corresponding test. + + If unsure, say N. + config STATIC_KEYS_SELFTEST bool "Static key selftest" depends on JUMP_LABEL diff --git a/kernel/Makefile b/kernel/Makefile index 1fe46db40806..f48134b8e29d 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -115,6 +115,7 @@ obj-$(CONFIG_HAVE_STATIC_CALL) += static_call.o obj-$(CONFIG_HAVE_STATIC_CALL_INLINE) += static_call_inline.o obj-$(CONFIG_CFI_CLANG) += cfi.o obj-$(CONFIG_PGO_CLANG) += pgo/ +obj-$(CONFIG_IPI_BENCHMARK) += ipi_benchmark.o obj-$(CONFIG_PERF_EVENTS) += events/ diff --git a/kernel/ipi_benchmark.c b/kernel/ipi_benchmark.c new file mode 100644 index 000000000000..8853ccb264ca --- /dev/null +++ b/kernel/ipi_benchmark.c @@ -0,0 +1,155 @@ +/* + * Performance test for IPI on SMP machines. + * + * Copyright (c) 2017 Cavium Networks. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/ktime.h> + +#define NTIMES 100000 + +#define POKE_ANY 0 +#define DRY_RUN 1 +#define POKE_SELF 2 +#define POKE_ALL 3 +#define POKE_ALL_LOCK 4 + +static void __init handle_ipi_spinlock(void *t) +{ + spinlock_t *lock = (spinlock_t *) t; + + spin_lock(lock); + spin_unlock(lock); +} + +static void __init handle_ipi(void *t) +{ + ktime_t *time = (ktime_t *) t; + + if (time) + *time = ktime_get() - *time; +} + +static ktime_t __init send_ipi(int flags) +{ + ktime_t time = 0; + DEFINE_SPINLOCK(lock); + unsigned int cpu = get_cpu(); + + switch (flags) { + case DRY_RUN: + /* Do everything except actually sending IPI. */ + break; + case POKE_ALL: + /* If broadcasting, don't force all CPUs to update time. */ + smp_call_function_many(cpu_online_mask, handle_ipi, NULL, 1); + break; + case POKE_ALL_LOCK: + smp_call_function_many(cpu_online_mask, + handle_ipi_spinlock, &lock, 1); + break; + case POKE_ANY: + cpu = cpumask_any_but(cpu_online_mask, cpu); + if (cpu >= nr_cpu_ids) { + time = -ENOENT; + break; + } + time = ktime_get(); + smp_call_function_single(cpu, handle_ipi, &time, 1); + break; + case POKE_SELF: + time = ktime_get(); + smp_call_function_single(cpu, handle_ipi, &time, 1); + break; + default: + time = -EINVAL; + } + + put_cpu(); + return time; +} + +static int __init __bench_ipi(unsigned long i, ktime_t *time, int flags) +{ + ktime_t t; + + *time = 0; + while (i--) { + t = send_ipi(flags); + if ((int) t < 0) + return (int) t; + + *time += t; + } + + return 0; +} + +static int __init bench_ipi(unsigned long times, int flags, + ktime_t *ipi, ktime_t *total) +{ + int ret; + + *total = ktime_get(); + ret = __bench_ipi(times, ipi, flags); + if (unlikely(ret)) + return ret; + + *total = ktime_get() - *total; + + return 0; +} + +static int __init init_bench_ipi(void) +{ + ktime_t ipi, total; + int ret; + + ret = bench_ipi(NTIMES, DRY_RUN, &ipi, &total); + if (ret) + pr_err("Dry-run FAILED: %d\n", ret); + else + pr_err("Dry-run: %18llu, %18llu ns\n", ipi, total); + + ret = bench_ipi(NTIMES, POKE_SELF, &ipi, &total); + if (ret) + pr_err("Self-IPI FAILED: %d\n", ret); + else + pr_err("Self-IPI: %18llu, %18llu ns\n", ipi, total); + + ret = bench_ipi(NTIMES, POKE_ANY, &ipi, &total); + if (ret) + pr_err("Normal IPI FAILED: %d\n", ret); + else + pr_err("Normal IPI: %18llu, %18llu ns\n", ipi, total); + + ret = bench_ipi(NTIMES, POKE_ALL, &ipi, &total); + if (ret) + pr_err("Broadcast IPI FAILED: %d\n", ret); + else + pr_err("Broadcast IPI: %18llu, %18llu ns\n", ipi, total); + + ret = bench_ipi(NTIMES, POKE_ALL_LOCK, &ipi, &total); + if (ret) + pr_err("Broadcast lock FAILED: %d\n", ret); + else + pr_err("Broadcast lock: %18llu, %18llu ns\n", ipi, total); + + /* Return error to avoid annoying rmmod. */ + return -EINVAL; +} +module_init(init_bench_ipi); + +MODULE_LICENSE("GPL"); -- 2.33.0

From: Xiang Chen <chenxiang66@hisilicon.com> virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBPH85 ------------------------------------------------------------------------ Only disable ICC_SGI1R_EL1 trap when enabled ipiv and set GICD_CTLR_nASSGIreq for register GICD_CTLR of virtual machine. Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com> Signed-off-by: Jinqian Yang <yangjinqian1@huawei.com> --- arch/arm64/kvm/vgic/vgic-mmio-v3.c | 1 + drivers/irqchip/irq-gic-v3-its.c | 13 +++++++++++-- include/linux/irqchip/arm-gic-v4.h | 1 + 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c index e4c48e0baa6f..0edea419baf3 100644 --- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c +++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c @@ -136,6 +136,7 @@ static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu, /* Switching HW SGIs? */ dist->nassgireq = val & GICD_CTLR_nASSGIreq; + dist->its_vm.nassgireq = dist->nassgireq; if (is_hwsgi != dist->nassgireq) vgic_v4_configure_vsgis(vcpu->kvm); diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 72fe63f78952..49a2b3b050c5 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -4574,7 +4574,8 @@ static void its_vpe_4_1_schedule(struct its_vpe *vpe, u64 val = 0; u32 nr_vpes; - if (static_branch_unlikely(&ipiv_enable)) { + if (static_branch_unlikely(&ipiv_enable) && + vm->nassgireq) { /* wait gicr_ipiv_busy */ WARN_ON_ONCE(readl_relaxed_poll_timeout_atomic( vlpi_base + GICR_IPIV_ST, @@ -4606,6 +4607,12 @@ static void its_vpe_4_1_schedule(struct its_vpe *vpe, asm volatile("msr s3_4_c15_c7_2, %0" : : "r" (val)); asm volatile("mrs %0, s3_4_c15_c7_2" : "=r" (val)); + } else { + /* enable guest access ICC_SGI1R_EL1 trap, disable ipiv */ + asm volatile("mrs %0, s3_4_c15_c7_2" : "=r" (val)); + val &= ~1UL; + asm volatile("msr s3_4_c15_c7_2, %0" : : "r" (val)); + asm volatile("mrs %0, s3_4_c15_c7_2" : "=r" (val)); } /* Schedule the VPE */ @@ -4621,6 +4628,7 @@ static void its_vpe_4_1_deschedule(struct its_vpe *vpe, struct its_cmd_info *info) { void __iomem *vlpi_base = gic_data_rdist_vlpi_base(); + struct its_vm *vm = vpe->its_vm; u64 val; if (info->req_db) { @@ -4653,7 +4661,8 @@ static void its_vpe_4_1_deschedule(struct its_vpe *vpe, vpe->pending_last = true; } - if (static_branch_unlikely(&ipiv_enable)) { + if (static_branch_unlikely(&ipiv_enable) && + vm->nassgireq) { if (!static_branch_unlikely(&ipiv_direct)) { /* wait gicr_ipiv_busy */ diff --git a/include/linux/irqchip/arm-gic-v4.h b/include/linux/irqchip/arm-gic-v4.h index ea29e773d139..20a1f6b8f2ea 100644 --- a/include/linux/irqchip/arm-gic-v4.h +++ b/include/linux/irqchip/arm-gic-v4.h @@ -35,6 +35,7 @@ struct its_vm { */ raw_spinlock_t vmapp_lock; u32 vlpi_count[GICv4_ITS_LIST_MAX]; + bool nassgireq; }; /* Embedded in kvm_vcpu.arch */ -- 2.33.0

From: Xiang Chen <chenxiang66@hisilicon.com> virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBPH85 ------------------------------------------------------------------------ For ESL or other platforms which don't enable IPIV, system register s3_4_c15_c7_2 may be not defined, so need to check it before operating it. Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com> Signed-off-by: Jinqian Yang <yangjinqian1@huawei.com> --- drivers/irqchip/irq-gic-v3-its.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 49a2b3b050c5..7c1416537dd1 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -4607,7 +4607,7 @@ static void its_vpe_4_1_schedule(struct its_vpe *vpe, asm volatile("msr s3_4_c15_c7_2, %0" : : "r" (val)); asm volatile("mrs %0, s3_4_c15_c7_2" : "=r" (val)); - } else { + } else if (static_branch_unlikely(&ipiv_enable)) { /* enable guest access ICC_SGI1R_EL1 trap, disable ipiv */ asm volatile("mrs %0, s3_4_c15_c7_2" : "=r" (val)); val &= ~1UL; -- 2.33.0

virt inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IBPH85 ------------------------------------------------------------------------ Signed-off-by: Jinqian Yang <yangjinqian1@huawei.com> --- include/linux/irqchip/arm-gic-v4.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/linux/irqchip/arm-gic-v4.h b/include/linux/irqchip/arm-gic-v4.h index 20a1f6b8f2ea..993f94546a50 100644 --- a/include/linux/irqchip/arm-gic-v4.h +++ b/include/linux/irqchip/arm-gic-v4.h @@ -20,7 +20,6 @@ struct its_vm { struct fwnode_handle *fwnode; struct irq_domain *domain; struct page *vprop_page; - struct page *vpe_page; struct its_vpe **vpes; int nr_vpes; irq_hw_number_t db_lpi_base; @@ -35,7 +34,10 @@ struct its_vm { */ raw_spinlock_t vmapp_lock; u32 vlpi_count[GICv4_ITS_LIST_MAX]; +#ifndef __GENKSYMS__ + struct page *vpe_page; bool nassgireq; +#endif }; /* Embedded in kvm_vcpu.arch */ @@ -93,9 +95,11 @@ struct its_vpe { u16 col_idx; /* Unique (system-wide) VPE identifier */ u16 vpe_id; - bool vpe_id_allocated; /* Pending VLPIs on schedule out? */ bool pending_last; +#ifndef __GENKSYMS__ + bool vpe_id_allocated; +#endif }; /* -- 2.33.0

反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/15258 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/7HA... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/15258 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/7HA...
participants (2)
-
patchwork bot
-
yangjinqian