From: marc.zyngier@arm.com (Marc Zyngier)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 23/33] KVM: arm/arm64: Replace the single rdist region by a list
Date: Fri, 1 Jun 2018 16:27:37 +0100 [thread overview]
Message-ID: <20180601152747.23613-24-marc.zyngier@arm.com> (raw)
In-Reply-To: <20180601152747.23613-1-marc.zyngier@arm.com>
From: Eric Auger <eric.auger@redhat.com>
At the moment KVM supports a single rdist region. We want to
support several separate rdist regions so let's introduce a list
of them. This patch currently only cares about a single
entry in this list as the functionality to register several redist
regions is not yet there. So this only translates the existing code
into something functionally similar using that new data struct.
The redistributor region handle is stored in the vgic_cpu structure
to allow later computation of the TYPER last bit.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Christoffer Dall <christoffer.dall@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
include/kvm/arm_vgic.h | 14 ++++++++---
virt/kvm/arm/vgic/vgic-init.c | 16 ++++++++++--
virt/kvm/arm/vgic/vgic-kvm-device.c | 13 ++++++++--
virt/kvm/arm/vgic/vgic-mmio-v3.c | 38 +++++++++++++++++++++++------
virt/kvm/arm/vgic/vgic-v3.c | 20 +++++++++------
5 files changed, 77 insertions(+), 24 deletions(-)
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index e7efe12a81bd..90e489f685ae 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -201,6 +201,14 @@ struct vgic_its {
struct vgic_state_iter;
+struct vgic_redist_region {
+ u32 index;
+ gpa_t base;
+ u32 count; /* number of redistributors or 0 if single region */
+ u32 free_index; /* index of the next free redistributor */
+ struct list_head list;
+};
+
struct vgic_dist {
bool in_kernel;
bool ready;
@@ -220,10 +228,7 @@ struct vgic_dist {
/* either a GICv2 CPU interface */
gpa_t vgic_cpu_base;
/* or a number of GICv3 redistributor regions */
- struct {
- gpa_t vgic_redist_base;
- gpa_t vgic_redist_free_offset;
- };
+ struct list_head rd_regions;
};
/* distributor enabled */
@@ -311,6 +316,7 @@ struct vgic_cpu {
*/
struct vgic_io_device rd_iodev;
struct vgic_io_device sgi_iodev;
+ struct vgic_redist_region *rdreg;
/* Contains the attributes and gpa of the LPI pending tables. */
u64 pendbaser;
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index 9a5aed7eecfd..8901b2d8fca1 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -167,8 +167,11 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
kvm->arch.vgic.vgic_model = type;
kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
- kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
- kvm->arch.vgic.vgic_redist_base = VGIC_ADDR_UNDEF;
+
+ if (type == KVM_DEV_TYPE_ARM_VGIC_V2)
+ kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
+ else
+ INIT_LIST_HEAD(&kvm->arch.vgic.rd_regions);
out_unlock:
for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) {
@@ -303,6 +306,7 @@ int vgic_init(struct kvm *kvm)
static void kvm_vgic_dist_destroy(struct kvm *kvm)
{
struct vgic_dist *dist = &kvm->arch.vgic;
+ struct vgic_redist_region *rdreg, *next;
dist->ready = false;
dist->initialized = false;
@@ -311,6 +315,14 @@ static void kvm_vgic_dist_destroy(struct kvm *kvm)
dist->spis = NULL;
dist->nr_spis = 0;
+ if (kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) {
+ list_for_each_entry_safe(rdreg, next, &dist->rd_regions, list) {
+ list_del(&rdreg->list);
+ kfree(rdreg);
+ }
+ INIT_LIST_HEAD(&dist->rd_regions);
+ }
+
if (vgic_supports_direct_msis(kvm))
vgic_v4_teardown(kvm);
}
diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 10ae6f394b71..76ab3691f7fe 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -66,6 +66,7 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
int r = 0;
struct vgic_dist *vgic = &kvm->arch.vgic;
phys_addr_t *addr_ptr, alignment;
+ u64 undef_value = VGIC_ADDR_UNDEF;
mutex_lock(&kvm->lock);
switch (type) {
@@ -84,7 +85,9 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
addr_ptr = &vgic->vgic_dist_base;
alignment = SZ_64K;
break;
- case KVM_VGIC_V3_ADDR_TYPE_REDIST:
+ case KVM_VGIC_V3_ADDR_TYPE_REDIST: {
+ struct vgic_redist_region *rdreg;
+
r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V3);
if (r)
break;
@@ -92,8 +95,14 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
r = vgic_v3_set_redist_base(kvm, *addr);
goto out;
}
- addr_ptr = &vgic->vgic_redist_base;
+ rdreg = list_first_entry(&vgic->rd_regions,
+ struct vgic_redist_region, list);
+ if (!rdreg)
+ addr_ptr = &undef_value;
+ else
+ addr_ptr = &rdreg->base;
break;
+ }
default:
r = -ENODEV;
}
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 671fe81f8e1d..d1aab183a1cc 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -580,8 +580,10 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu)
{
struct kvm *kvm = vcpu->kvm;
struct vgic_dist *vgic = &kvm->arch.vgic;
+ struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
struct vgic_io_device *rd_dev = &vcpu->arch.vgic_cpu.rd_iodev;
struct vgic_io_device *sgi_dev = &vcpu->arch.vgic_cpu.sgi_iodev;
+ struct vgic_redist_region *rdreg;
gpa_t rd_base, sgi_base;
int ret;
@@ -591,13 +593,17 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu)
* function for all VCPUs when the base address is set. Just return
* without doing any work for now.
*/
- if (IS_VGIC_ADDR_UNDEF(vgic->vgic_redist_base))
+ rdreg = list_first_entry(&vgic->rd_regions,
+ struct vgic_redist_region, list);
+ if (!rdreg)
return 0;
if (!vgic_v3_check_base(kvm))
return -EINVAL;
- rd_base = vgic->vgic_redist_base + vgic->vgic_redist_free_offset;
+ vgic_cpu->rdreg = rdreg;
+
+ rd_base = rdreg->base + rdreg->free_index * KVM_VGIC_V3_REDIST_SIZE;
sgi_base = rd_base + SZ_64K;
kvm_iodevice_init(&rd_dev->dev, &kvm_io_gic_ops);
@@ -631,7 +637,7 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu)
goto out;
}
- vgic->vgic_redist_free_offset += 2 * SZ_64K;
+ rdreg->free_index++;
out:
mutex_unlock(&kvm->slots_lock);
return ret;
@@ -673,19 +679,31 @@ static int vgic_register_all_redist_iodevs(struct kvm *kvm)
int vgic_v3_set_redist_base(struct kvm *kvm, u64 addr)
{
struct vgic_dist *vgic = &kvm->arch.vgic;
+ struct vgic_redist_region *rdreg;
int ret;
/* vgic_check_ioaddr makes sure we don't do this twice */
- ret = vgic_check_ioaddr(kvm, &vgic->vgic_redist_base, addr, SZ_64K);
+ if (!list_empty(&vgic->rd_regions))
+ return -EINVAL;
+
+ rdreg = kzalloc(sizeof(*rdreg), GFP_KERNEL);
+ if (!rdreg)
+ return -ENOMEM;
+
+ rdreg->base = VGIC_ADDR_UNDEF;
+
+ ret = vgic_check_ioaddr(kvm, &rdreg->base, addr, SZ_64K);
if (ret)
- return ret;
+ goto out;
- vgic->vgic_redist_base = addr;
+ rdreg->base = addr;
if (!vgic_v3_check_base(kvm)) {
- vgic->vgic_redist_base = VGIC_ADDR_UNDEF;
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
+ list_add(&rdreg->list, &vgic->rd_regions);
+
/*
* Register iodevs for each existing VCPU. Adding more VCPUs
* afterwards will register the iodevs when needed.
@@ -695,6 +713,10 @@ int vgic_v3_set_redist_base(struct kvm *kvm, u64 addr)
return ret;
return 0;
+
+out:
+ kfree(rdreg);
+ return ret;
}
int vgic_v3_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index c7423f3768e5..56e6e903d998 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -427,6 +427,9 @@ bool vgic_v3_check_base(struct kvm *kvm)
{
struct vgic_dist *d = &kvm->arch.vgic;
gpa_t redist_size = KVM_VGIC_V3_REDIST_SIZE;
+ struct vgic_redist_region *rdreg =
+ list_first_entry(&d->rd_regions,
+ struct vgic_redist_region, list);
redist_size *= atomic_read(&kvm->online_vcpus);
@@ -434,18 +437,17 @@ bool vgic_v3_check_base(struct kvm *kvm)
d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE < d->vgic_dist_base)
return false;
- if (!IS_VGIC_ADDR_UNDEF(d->vgic_redist_base) &&
- d->vgic_redist_base + redist_size < d->vgic_redist_base)
+ if (rdreg && (rdreg->base + redist_size < rdreg->base))
return false;
/* Both base addresses must be set to check if they overlap */
- if (IS_VGIC_ADDR_UNDEF(d->vgic_dist_base) ||
- IS_VGIC_ADDR_UNDEF(d->vgic_redist_base))
+ if (IS_VGIC_ADDR_UNDEF(d->vgic_dist_base) || !rdreg)
return true;
- if (d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE <= d->vgic_redist_base)
+ if (d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE <= rdreg->base)
return true;
- if (d->vgic_redist_base + redist_size <= d->vgic_dist_base)
+
+ if (rdreg->base + redist_size <= d->vgic_dist_base)
return true;
return false;
@@ -455,12 +457,14 @@ int vgic_v3_map_resources(struct kvm *kvm)
{
int ret = 0;
struct vgic_dist *dist = &kvm->arch.vgic;
+ struct vgic_redist_region *rdreg =
+ list_first_entry(&dist->rd_regions,
+ struct vgic_redist_region, list);
if (vgic_ready(kvm))
goto out;
- if (IS_VGIC_ADDR_UNDEF(dist->vgic_dist_base) ||
- IS_VGIC_ADDR_UNDEF(dist->vgic_redist_base)) {
+ if (IS_VGIC_ADDR_UNDEF(dist->vgic_dist_base) || !rdreg) {
kvm_err("Need to set vgic distributor addresses first\n");
ret = -ENXIO;
goto out;
--
2.17.1
next prev parent reply other threads:[~2018-06-01 15:27 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-06-01 15:27 [GIT PULL] KVM/ARM updates for 4.18 Marc Zyngier
2018-06-01 15:27 ` [PATCH 01/33] arm64: KVM: Use lm_alias() for kvm_ksym_ref() Marc Zyngier
2018-06-01 15:27 ` [PATCH 02/33] arm64: fpsimd: Fix TIF_FOREIGN_FPSTATE after invalidating cpu regs Marc Zyngier
2018-06-01 15:27 ` [PATCH 03/33] thread_info: Add update_thread_flag() helpers Marc Zyngier
2018-06-01 15:27 ` [PATCH 04/33] arm64: Use update{,_tsk}_thread_flag() Marc Zyngier
2018-06-01 15:27 ` [PATCH 05/33] KVM: arm/arm64: Introduce kvm_arch_vcpu_run_pid_change Marc Zyngier
2018-06-01 15:27 ` [PATCH 06/33] KVM: arm64: Convert lazy FPSIMD context switch trap to C Marc Zyngier
2018-06-01 15:27 ` [PATCH 07/33] arm64: fpsimd: Generalise context saving for non-task contexts Marc Zyngier
2018-06-01 15:27 ` [PATCH 08/33] arm64: fpsimd: Avoid FPSIMD context leakage for the init task Marc Zyngier
2018-06-01 15:27 ` [PATCH 09/33] arm64: fpsimd: Eliminate task->mm checks Marc Zyngier
2018-06-01 15:27 ` [PATCH 10/33] arm64/sve: Refactor user SVE trap maintenance for external use Marc Zyngier
2018-06-01 15:27 ` [PATCH 11/33] KVM: arm64: Repurpose vcpu_arch.debug_flags for general-purpose flags Marc Zyngier
2018-06-01 15:27 ` [PATCH 12/33] KVM: arm64: Optimise FPSIMD handling to reduce guest/host thrashing Marc Zyngier
2018-06-01 15:27 ` [PATCH 13/33] arm64/sve: Move read_zcr_features() out of cpufeature.h Marc Zyngier
2018-06-01 15:27 ` [PATCH 14/33] arm64/sve: Switch sve_pffr() argument from task to thread Marc Zyngier
2018-06-01 15:27 ` [PATCH 15/33] arm64/sve: Move sve_pffr() to fpsimd.h and make inline Marc Zyngier
2018-06-01 15:27 ` [PATCH 16/33] KVM: arm64: Save host SVE context as appropriate Marc Zyngier
2018-06-01 15:27 ` [PATCH 17/33] KVM: arm64: Remove eager host SVE state saving Marc Zyngier
2018-06-01 15:27 ` [PATCH 18/33] KVM: arm64: Remove redundant *exit_code changes in fpsimd_guest_exit() Marc Zyngier
2018-06-01 15:27 ` [PATCH 19/33] KVM: arm64: Fold redundant exit code checks out of fixup_guest_exit() Marc Zyngier
2018-06-01 15:27 ` [PATCH 20/33] KVM: arm64: Invoke FPSIMD context switch trap from C Marc Zyngier
2018-06-01 15:27 ` [PATCH 21/33] KVM: arm/arm64: Set dist->spis to NULL after kfree Marc Zyngier
2018-06-01 15:27 ` [PATCH 22/33] KVM: arm/arm64: Document KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION Marc Zyngier
2018-06-01 15:27 ` Marc Zyngier [this message]
2018-06-01 15:27 ` [PATCH 24/33] KVM: arm/arm64: Helper to locate free rdist index Marc Zyngier
2018-06-01 15:27 ` [PATCH 25/33] KVM: arm/arm64: Revisit Redistributor TYPER last bit computation Marc Zyngier
2018-06-01 15:27 ` [PATCH 26/33] KVM: arm/arm64: Adapt vgic_v3_check_base to multiple rdist regions Marc Zyngier
2018-06-01 15:27 ` [PATCH 27/33] KVM: arm/arm64: Helper to register a new redistributor region Marc Zyngier
2018-06-01 15:27 ` [PATCH 28/33] KVM: arm/arm64: Remove kvm_vgic_vcpu_early_init Marc Zyngier
2018-06-01 15:27 ` [PATCH 29/33] KVM: arm/arm64: Check vcpu redist base before registering an iodev Marc Zyngier
2018-06-01 15:27 ` [PATCH 30/33] KVM: arm/arm64: Check all vcpu redistributors are set on map_resources Marc Zyngier
2018-06-01 15:27 ` [PATCH 31/33] KVM: arm/arm64: Add KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION Marc Zyngier
2018-06-01 15:27 ` [PATCH 32/33] KVM: arm/arm64: Implement KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION Marc Zyngier
2018-06-01 15:27 ` [PATCH 33/33] KVM: arm/arm64: Bump VGIC_V3_MAX_CPUS to 512 Marc Zyngier
2018-06-01 17:18 ` [GIT PULL] KVM/ARM updates for 4.18 Paolo Bonzini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180601152747.23613-24-marc.zyngier@arm.com \
--to=marc.zyngier@arm.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox