* [PATCH 2/3] KVM: arm/arm64: vgic: Prevent access to invalid SPIs
From: Marc Zyngier @ 2016-11-04 18:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161104183638.28137-1-marc.zyngier@arm.com>
From: Andre Przywara <andre.przywara@arm.com>
In our VGIC implementation we limit the number of SPIs to a number
that the userland application told us. Accordingly we limit the
allocation of memory for virtual IRQs to that number.
However in our MMIO dispatcher we didn't check if we ever access an
IRQ beyond that limit, leading to out-of-bound accesses.
Add a test against the number of allocated SPIs in check_region().
Adjust the VGIC_ADDR_TO_INT macro to avoid an actual division, which
is not implemented on ARM(32).
[maz: cleaned-up original patch]
Cc: stable at vger.kernel.org
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
virt/kvm/arm/vgic/vgic-mmio.c | 41 +++++++++++++++++++++++++++--------------
virt/kvm/arm/vgic/vgic-mmio.h | 14 +++++++-------
2 files changed, 34 insertions(+), 21 deletions(-)
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index e18b30ddcdce..ebe1b9fa3c4d 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -453,17 +453,33 @@ struct vgic_io_device *kvm_to_vgic_iodev(const struct kvm_io_device *dev)
return container_of(dev, struct vgic_io_device, dev);
}
-static bool check_region(const struct vgic_register_region *region,
+static bool check_region(const struct kvm *kvm,
+ const struct vgic_register_region *region,
gpa_t addr, int len)
{
- if ((region->access_flags & VGIC_ACCESS_8bit) && len == 1)
- return true;
- if ((region->access_flags & VGIC_ACCESS_32bit) &&
- len == sizeof(u32) && !(addr & 3))
- return true;
- if ((region->access_flags & VGIC_ACCESS_64bit) &&
- len == sizeof(u64) && !(addr & 7))
- return true;
+ int flags, nr_irqs = kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
+
+ switch (len) {
+ case sizeof(u8):
+ flags = VGIC_ACCESS_8bit;
+ break;
+ case sizeof(u32):
+ flags = VGIC_ACCESS_32bit;
+ break;
+ case sizeof(u64):
+ flags = VGIC_ACCESS_64bit;
+ break;
+ default:
+ return false;
+ }
+
+ if ((region->access_flags & flags) && IS_ALIGNED(addr, len)) {
+ if (!region->bits_per_irq)
+ return true;
+
+ /* Do we access a non-allocated IRQ? */
+ return VGIC_ADDR_TO_INTID(addr, region->bits_per_irq) < nr_irqs;
+ }
return false;
}
@@ -477,7 +493,7 @@ static int dispatch_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
addr - iodev->base_addr);
- if (!region || !check_region(region, addr, len)) {
+ if (!region || !check_region(vcpu->kvm, region, addr, len)) {
memset(val, 0, len);
return 0;
}
@@ -510,10 +526,7 @@ static int dispatch_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
addr - iodev->base_addr);
- if (!region)
- return 0;
-
- if (!check_region(region, addr, len))
+ if (!region || !check_region(vcpu->kvm, region, addr, len))
return 0;
switch (iodev->iodev_type) {
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 4c34d39d44a0..84961b4e4422 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -50,15 +50,15 @@ extern struct kvm_io_device_ops kvm_io_gic_ops;
#define VGIC_ADDR_IRQ_MASK(bits) (((bits) * 1024 / 8) - 1)
/*
- * (addr & mask) gives us the byte offset for the INT ID, so we want to
- * divide this with 'bytes per irq' to get the INT ID, which is given
- * by '(bits) / 8'. But we do this with fixed-point-arithmetic and
- * take advantage of the fact that division by a fraction equals
- * multiplication with the inverted fraction, and scale up both the
- * numerator and denominator with 8 to support at most 64 bits per IRQ:
+ * (addr & mask) gives us the _byte_ offset for the INT ID.
+ * We multiply this by 8 the get the _bit_ offset, then divide this by
+ * the number of bits to learn the actual INT ID.
+ * But instead of a division (which requires a "long long div" implementation),
+ * we shift by the binary logarithm of <bits>.
+ * This assumes that <bits> is a power of two.
*/
#define VGIC_ADDR_TO_INTID(addr, bits) (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \
- 64 / (bits) / 8)
+ 8 >> ilog2(bits))
/*
* Some VGIC registers store per-IRQ information, with a different number
--
2.10.1
^ permalink raw reply related
* [PATCH 1/3] arm/arm64: KVM: Perform local TLB invalidation when multiplexing vcpus on a single CPU
From: Marc Zyngier @ 2016-11-04 18:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161104183638.28137-1-marc.zyngier@arm.com>
Architecturally, TLBs are private to the (physical) CPU they're
associated with. But when multiple vcpus from the same VM are
being multiplexed on the same CPU, the TLBs are not private
to the vcpus (and are actually shared across the VMID).
Let's consider the following scenario:
- vcpu-0 maps PA to VA
- vcpu-1 maps PA' to VA
If run on the same physical CPU, vcpu-1 can hit TLB entries generated
by vcpu-0 accesses, and access the wrong physical page.
The solution to this is to keep a per-VM map of which vcpu ran last
on each given physical CPU, and invalidate local TLBs when switching
to a different vcpu from the same VM.
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/include/asm/kvm_asm.h | 1 +
arch/arm/include/asm/kvm_host.h | 3 +++
arch/arm/include/asm/kvm_hyp.h | 1 +
arch/arm/kvm/arm.c | 27 ++++++++++++++++++++++++++-
arch/arm/kvm/hyp/tlb.c | 15 +++++++++++++++
arch/arm64/include/asm/kvm_asm.h | 1 +
arch/arm64/include/asm/kvm_host.h | 3 +++
arch/arm64/include/asm/kvm_mmu.h | 2 +-
arch/arm64/kvm/hyp/tlb.c | 15 +++++++++++++++
9 files changed, 66 insertions(+), 2 deletions(-)
diff --git a/arch/arm/include/asm/kvm_asm.h b/arch/arm/include/asm/kvm_asm.h
index d7ea6bcb29bf..8ef05381984b 100644
--- a/arch/arm/include/asm/kvm_asm.h
+++ b/arch/arm/include/asm/kvm_asm.h
@@ -66,6 +66,7 @@ extern char __kvm_hyp_vector[];
extern void __kvm_flush_vm_context(void);
extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
extern void __kvm_tlb_flush_vmid(struct kvm *kvm);
+extern void __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu);
extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 2d19e02d03fd..d5423ab15ed5 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -57,6 +57,9 @@ struct kvm_arch {
/* VTTBR value associated with below pgd and vmid */
u64 vttbr;
+ /* The last vcpu id that ran on each physical CPU */
+ int __percpu *last_vcpu_ran;
+
/* Timer */
struct arch_timer_kvm timer;
diff --git a/arch/arm/include/asm/kvm_hyp.h b/arch/arm/include/asm/kvm_hyp.h
index 343135ede5fa..58508900c4bb 100644
--- a/arch/arm/include/asm/kvm_hyp.h
+++ b/arch/arm/include/asm/kvm_hyp.h
@@ -71,6 +71,7 @@
#define ICIALLUIS __ACCESS_CP15(c7, 0, c1, 0)
#define ATS1CPR __ACCESS_CP15(c7, 0, c8, 0)
#define TLBIALLIS __ACCESS_CP15(c8, 0, c3, 0)
+#define TLBIALL __ACCESS_CP15(c8, 0, c7, 0)
#define TLBIALLNSNHIS __ACCESS_CP15(c8, 4, c3, 4)
#define PRRR __ACCESS_CP15(c10, 0, c2, 0)
#define NMRR __ACCESS_CP15(c10, 0, c2, 1)
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 08bb84f2ad58..19b5f5c1c0ff 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -114,11 +114,18 @@ void kvm_arch_check_processor_compat(void *rtn)
*/
int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
{
- int ret = 0;
+ int ret, cpu;
if (type)
return -EINVAL;
+ kvm->arch.last_vcpu_ran = alloc_percpu(typeof(*kvm->arch.last_vcpu_ran));
+ if (!kvm->arch.last_vcpu_ran)
+ return -ENOMEM;
+
+ for_each_possible_cpu(cpu)
+ *per_cpu_ptr(kvm->arch.last_vcpu_ran, cpu) = -1;
+
ret = kvm_alloc_stage2_pgd(kvm);
if (ret)
goto out_fail_alloc;
@@ -141,6 +148,8 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
out_free_stage2_pgd:
kvm_free_stage2_pgd(kvm);
out_fail_alloc:
+ free_percpu(kvm->arch.last_vcpu_ran);
+ kvm->arch.last_vcpu_ran = NULL;
return ret;
}
@@ -168,6 +177,9 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
{
int i;
+ free_percpu(kvm->arch.last_vcpu_ran);
+ kvm->arch.last_vcpu_ran = NULL;
+
for (i = 0; i < KVM_MAX_VCPUS; ++i) {
if (kvm->vcpus[i]) {
kvm_arch_vcpu_free(kvm->vcpus[i]);
@@ -312,6 +324,19 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
{
+ int *last_ran;
+
+ last_ran = this_cpu_ptr(vcpu->kvm->arch.last_vcpu_ran);
+
+ /*
+ * We might get preempted before the vCPU actually runs, but
+ * over-invalidation doesn't affect correctness.
+ */
+ if (*last_ran != vcpu->vcpu_id) {
+ kvm_call_hyp(__kvm_tlb_flush_local_vmid, vcpu);
+ *last_ran = vcpu->vcpu_id;
+ }
+
vcpu->cpu = cpu;
vcpu->arch.host_cpu_context = this_cpu_ptr(kvm_host_cpu_state);
diff --git a/arch/arm/kvm/hyp/tlb.c b/arch/arm/kvm/hyp/tlb.c
index 729652854f90..6d810af2d9fd 100644
--- a/arch/arm/kvm/hyp/tlb.c
+++ b/arch/arm/kvm/hyp/tlb.c
@@ -55,6 +55,21 @@ void __hyp_text __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
__kvm_tlb_flush_vmid(kvm);
}
+void __hyp_text __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu)
+{
+ struct kvm *kvm = kern_hyp_va(kern_hyp_va(vcpu)->kvm);
+
+ /* Switch to requested VMID */
+ write_sysreg(kvm->arch.vttbr, VTTBR);
+ isb();
+
+ write_sysreg(0, TLBIALL);
+ dsb(nsh);
+ isb();
+
+ write_sysreg(0, VTTBR);
+}
+
void __hyp_text __kvm_flush_vm_context(void)
{
write_sysreg(0, TLBIALLNSNHIS);
diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index 18f746551bf6..ec3553eb9349 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -54,6 +54,7 @@ extern char __kvm_hyp_vector[];
extern void __kvm_flush_vm_context(void);
extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
extern void __kvm_tlb_flush_vmid(struct kvm *kvm);
+extern void __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu);
extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index bd94e6766759..e5050388e062 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -62,6 +62,9 @@ struct kvm_arch {
/* VTTBR value associated with above pgd and vmid */
u64 vttbr;
+ /* The last vcpu id that ran on each physical CPU */
+ int __percpu *last_vcpu_ran;
+
/* The maximum number of vCPUs depends on the used GIC model */
int max_vcpus;
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index a79b969c26fc..6f72fe8b0e3e 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -128,7 +128,7 @@ static inline unsigned long __kern_hyp_va(unsigned long v)
return v;
}
-#define kern_hyp_va(v) (typeof(v))(__kern_hyp_va((unsigned long)(v)))
+#define kern_hyp_va(v) ((typeof(v))(__kern_hyp_va((unsigned long)(v))))
/*
* We currently only support a 40bit IPA.
diff --git a/arch/arm64/kvm/hyp/tlb.c b/arch/arm64/kvm/hyp/tlb.c
index 9cc0ea784ae6..88e2f2b938f0 100644
--- a/arch/arm64/kvm/hyp/tlb.c
+++ b/arch/arm64/kvm/hyp/tlb.c
@@ -64,6 +64,21 @@ void __hyp_text __kvm_tlb_flush_vmid(struct kvm *kvm)
write_sysreg(0, vttbr_el2);
}
+void __hyp_text __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu)
+{
+ struct kvm *kvm = kern_hyp_va(kern_hyp_va(vcpu)->kvm);
+
+ /* Switch to requested VMID */
+ write_sysreg(kvm->arch.vttbr, vttbr_el2);
+ isb();
+
+ asm volatile("tlbi vmalle1" : : );
+ dsb(nsh);
+ isb();
+
+ write_sysreg(0, vttbr_el2);
+}
+
void __hyp_text __kvm_flush_vm_context(void)
{
dsb(ishst);
--
2.10.1
^ permalink raw reply related
* [PULL 0/3] KVM/ARM updates for v4.9-rc4
From: Marc Zyngier @ 2016-11-04 18:36 UTC (permalink / raw)
To: linux-arm-kernel
Paolo, Radim,
Please find below the KVM/ARM updates for v4.9-rc4 (or later if we've
already missed the boat).
Thanks,
M.
The following changes since commit 07d9a380680d1c0eb51ef87ff2eab5c994949e69:
Linux 4.9-rc2 (2016-10-23 17:10:14 -0700)
are available in the git repository at:
git://git.kernel.org:/pub/scm/linux/kernel/git/kvmarm/kvmarm.git tags/kvm-arm-for-v4.9-rc4
for you to fetch changes up to d42c79701a3ee5c38fbbc82f98a140420bd40134:
KVM: arm/arm64: vgic: Kick VCPUs when queueing already pending IRQs (2016-11-04 17:56:56 +0000)
----------------------------------------------------------------
KVM/ARM updates for v4.9-rc4
- Kick the vcpu when a pending interrupt becomes pending again
- Prevent access to invalid interrupt registers
- Invalid TLBs when two vcpus from the same VM share a CPU
----------------------------------------------------------------
Andre Przywara (1):
KVM: arm/arm64: vgic: Prevent access to invalid SPIs
Marc Zyngier (1):
arm/arm64: KVM: Perform local TLB invalidation when multiplexing vcpus on a single CPU
Shih-Wei Li (1):
KVM: arm/arm64: vgic: Kick VCPUs when queueing already pending IRQs
arch/arm/include/asm/kvm_asm.h | 1 +
arch/arm/include/asm/kvm_host.h | 3 +++
arch/arm/include/asm/kvm_hyp.h | 1 +
arch/arm/kvm/arm.c | 27 +++++++++++++++++++++++++-
arch/arm/kvm/hyp/tlb.c | 15 ++++++++++++++
arch/arm64/include/asm/kvm_asm.h | 1 +
arch/arm64/include/asm/kvm_host.h | 3 +++
arch/arm64/include/asm/kvm_mmu.h | 2 +-
arch/arm64/kvm/hyp/tlb.c | 15 ++++++++++++++
virt/kvm/arm/vgic/vgic-mmio.c | 41 ++++++++++++++++++++++++++-------------
virt/kvm/arm/vgic/vgic-mmio.h | 14 ++++++-------
virt/kvm/arm/vgic/vgic.c | 12 ++++++++++++
12 files changed, 112 insertions(+), 23 deletions(-)
^ permalink raw reply
* [PATCH v3 2/6] arm64: arch_timer: Introduce a generic erratum handing mechanism for fsl-a008585
From: Scott Wood @ 2016-11-04 18:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478264794-14652-2-git-send-email-dingtianhong@huawei.com>
On Fri, Nov 04, 2016 at 09:06:30PM +0800, Ding Tianhong wrote:
> The workaround for hisilicon,161601 will check the return value of the system counter
> by different way, in order to distinguish with the fsl-a008585 workaround, introduce
> a new generic erratum handing mechanism for fsl-a008585 and rename some functions.
>
> v2: Introducing a new generic erratum handling mechanism for fsl erratum a008585.
>
> v3: Introducing the erratum_workaround_set_sne generic function for fsl erratum a008585
> and make the #define __fsl_a008585_read_reg to be private to the .c file instead of
> being globally visible. After discussion with Marc and Will, a consensus decision was
> made to remove the commandline parameter for enabling fsl,erratum-a008585 erratum,
> and make some generic name more specific, export timer_unstable_counter_workaround
> for module access.
The command line paramter was added at Marc's request to provide a way of
enbaling the workaround in a KVM guest, until API is added to allow QEMU to
discover the need to set the property in the guest device tree. Is there an
alternative?
-Scott
^ permalink raw reply
* [PATCH] arm64: percpu: kill off final ACCESS_ONCE() uses
From: Mark Rutland @ 2016-11-04 18:17 UTC (permalink / raw)
To: linux-arm-kernel
For several reasons it is preferable to use {READ,WRITE}_ONCE() rather than
ACCESS_ONCE(). For example, these handle aggregate types, result in shorter
source code, and better document the intended access (which may be useful for
instrumentation features such as the upcoming KTSAN).
Over a number of patches, most uses of ACCESS_ONCE() in arch/arm64 have been
migrated to {READ,WRITE}_ONCE(). For consistency, and the above reasons, this
patch migrates the final remaining uses.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Will Deacon <will.deacon@arm.com>
---
arch/arm64/include/asm/percpu.h | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/arch/arm64/include/asm/percpu.h b/arch/arm64/include/asm/percpu.h
index 5394c84..4afb6fc 100644
--- a/arch/arm64/include/asm/percpu.h
+++ b/arch/arm64/include/asm/percpu.h
@@ -101,16 +101,16 @@ static inline unsigned long __percpu_read(void *ptr, int size)
switch (size) {
case 1:
- ret = ACCESS_ONCE(*(u8 *)ptr);
+ ret = READ_ONCE(*(u8 *)ptr);
break;
case 2:
- ret = ACCESS_ONCE(*(u16 *)ptr);
+ ret = READ_ONCE(*(u16 *)ptr);
break;
case 4:
- ret = ACCESS_ONCE(*(u32 *)ptr);
+ ret = READ_ONCE(*(u32 *)ptr);
break;
case 8:
- ret = ACCESS_ONCE(*(u64 *)ptr);
+ ret = READ_ONCE(*(u64 *)ptr);
break;
default:
BUILD_BUG();
@@ -123,16 +123,16 @@ static inline void __percpu_write(void *ptr, unsigned long val, int size)
{
switch (size) {
case 1:
- ACCESS_ONCE(*(u8 *)ptr) = (u8)val;
+ WRITE_ONCE(*(u8 *)ptr, (u8)val);
break;
case 2:
- ACCESS_ONCE(*(u16 *)ptr) = (u16)val;
+ WRITE_ONCE(*(u16 *)ptr, (u16)val);
break;
case 4:
- ACCESS_ONCE(*(u32 *)ptr) = (u32)val;
+ WRITE_ONCE(*(u32 *)ptr, (u32)val);
break;
case 8:
- ACCESS_ONCE(*(u64 *)ptr) = (u64)val;
+ WRITE_ONCE(*(u64 *)ptr, (u64)val);
break;
default:
BUILD_BUG();
--
2.7.4
^ permalink raw reply related
* [RFC PATCH v2 8/8] arm64: Wire up and expose the new compat vDSO
From: Kevin Brodsky @ 2016-11-04 17:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161104164743.c35wxhgzs6uigv6j@localhost>
On 04/11/2016 10:47, Catalin Marinas wrote:
> On Fri, Nov 04, 2016 at 10:30:08AM -0600, Kevin Brodsky wrote:
>> On 04/11/2016 09:50, Catalin Marinas wrote:
>>> On Thu, Oct 27, 2016 at 05:30:58PM +0100, Kevin Brodsky wrote:
>>>> * The vDSO page replaces the vector page. The vDSO provides its own
>>>> sigreturn trampolines, replacing those in the vector page, but the
>>>> kuser helpers are gone. As a result enabling the compat vDSO will
>>>> break userspace programs relying on the kuser helpers.
>>> I think vDSO and vectors page should not exclude each other. If you want
>>> to disable the vectors page, let's make it an independent config option
>>> like the KUSER_HELPERS in arch/arm64/mm/Kconfig. But I would very much
>>> like to be able to have both the vDSO and the vectors page at the same
>>> time.
>> Indeed, I've had exactly the same feedback from Google yesterday (apparently
>> many Android apps with native libs still target ARMv6....). I'll add the
>> option to keep the kuser helpers.
>>
>> There's a small problem though: how to ensure that the kuser helpers +
>> sigreturn trampolines are always included if the compat vDSO is not built? I
>> can enforce CONFIG_KUSER_HELPERS if !CONFIG_VDSO32 (directly in the
>> code/Makefiles), but the dependency cannot be expressed in Kconfig.
> Or you could insert a separate "sigpage" as arm32 does. This could leave
> independently of vDSO or vectors page.
Yeah I thought about this too. It's a bit more work but probably cleaner and more
flexible, that would also allow to disable the kuser helpers independently of the
compat vDSO.
Thanks,
Kevin
^ permalink raw reply
* [PATCH V3 0/6] ARM64: Uprobe support added
From: Catalin Marinas @ 2016-11-04 17:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1478068479.git.panand@redhat.com>
On Wed, Nov 02, 2016 at 02:40:40PM +0530, Pratyush Anand wrote:
> Pratyush Anand (6):
> arm64: kprobe: protect/rename few definitions to be reused by uprobe
> arm64: kgdb_step_brk_fn: ignore other's exception
> arm64: Handle TRAP_TRACE for user mode as well
> arm64: Handle TRAP_BRKPT for user mode as well
> arm64: introduce mm context flag to keep 32 bit task information
> arm64: Add uprobe support
I queued the patches for 4.10. I will push them into -next sometime next
week once I do some testing (I'm currently at the LPC).
Thanks.
--
Catalin
^ permalink raw reply
* [PATCH] ARM: dts: imx6: Add support for Logic PD SOM and Baseboard
From: Adam Ford @ 2016-11-04 17:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160809082400.GR4678@tiger>
On Tue, Aug 9, 2016 at 3:24 AM, Shawn Guo <shawnguo@kernel.org> wrote:
> On Wed, Jul 20, 2016 at 11:06:26AM -0500, aford173 at gmail.com wrote:
>> From: Adam Ford <adam.ford@logicpd.com>
>>
>> The system on module (SOM) specific portions are in the .dtsi
>> while the baseboard specific portions are in the .dts file.
>>
>> Signed-off-by: Adam Ford <aford173@gmail.com>
>>
>> diff --git a/arch/arm/boot/dts/imx6q-logicpd.dts b/arch/arm/boot/dts/imx6q-logicpd.dts
>> new file mode 100644
>> index 0000000..6f1663e
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/imx6q-logicpd.dts
>> @@ -0,0 +1,389 @@
>> +/*
>> + * Copyright 2016 Logic PD
>> + * This file is adapted from imx6qdl-sabresd.dts.
>> + * Copyright 2012 Freescale Semiconductor, Inc.
>> + * Copyright 2011 Linaro Ltd.
>> + *
>> + * The code contained herein is licensed under the GNU General Public
>> + * License. You may obtain a copy of the GNU General Public License
>> + * Version 2 or later at the following locations:
>> + *
>> + * http://www.opensource.org/licenses/gpl-license.html
>> + * http://www.gnu.org/copyleft/gpl.html
>> + */
>
> Please consider to use X11/GPL dual license. There are a lot of
> examples in arch/arm/boot/dts.
>
Not a problem. I found another example and I integrated it in.
>> +
>> +/dts-v1/;
>> +
>> +
>
> Drop one newline.
>
>> +#include "imx6qdl-logicpd.dtsi"
>> +
>> +/ {
>> + model = "Logic PD Acuity SOM";
>> + compatible = "fsl,imx6q";
>> +
>> + aliases {
>> + display = &lcd_display;
>> + };
>> +
>> + leds {
>> + compatible = "gpio-leds";
>
> Have a new line between property list and sub-node.
>
>> + gen_led0 {
>> + label = "cpu0";
>> + gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>;
>> + linux,default-trigger = "cpu0";
>> + };
>
> Have a new line between nodes.
>
>> + gen_led1 {
>> + label = "cpu1";
>> + gpios = <&gpio3 20 GPIO_ACTIVE_HIGH>;
>> + linux,default-trigger = "cpu1";
>> + };
>> + gen_led2 {
>> + label = "heartbeat";
>> + gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
>> + linux,default-trigger = "heartbeat";
>> + };
>> + gen_led3 {
>> + label = "Always On";
>> + gpios = <&gpio3 22 GPIO_ACTIVE_HIGH>;
>> + linux,default-trigger = "default-on";
>> + };
>> + };
>> +
>> + regulators {
>> + compatible = "simple-bus";
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>
> Please drop this container node and put the fixed regulator nodes
> directly under root, with following naming schema:
>
> reg_xxx: regulator-xxx {
> ...
> };
>
I renamed the regulators using your schema, however any attempts to
remove the connector and placing the regulator directly under the root
fail upon boot and the #address cells, #size-cells also seem important
and fail when removed.
>> +
>> + reg_usb_otg_vbus: regulator at 0 {
>> + compatible = "regulator-fixed";
>> + reg = <0>;
>> + regulator-name = "usb_otg_vbus";
>> + regulator-min-microvolt = <5000000>;
>> + regulator-max-microvolt = <5000000>;
>> + gpio = <&gpio4 15 GPIO_ACTIVE_HIGH>;
>> + enable-active-high;
>> + };
>> +
>> + reg_usb_h1_vbus: regulator at 1 {
>> + compatible = "regulator-fixed";
>> + reg = <1>;
>> + regulator-name = "usb_h1_vbus";
>> + regulator-min-microvolt = <5000000>;
>> + regulator-max-microvolt = <5000000>;
>> + enable-active-high;
>> + regulator-always-on;
>> + gpio = <&gpio1 0 GPIO_ACTIVE_HIGH>;
>> + };
>> +
>> + reg_3v3: regulator at 2 {
>> + compatible = "regulator-fixed";
>> + reg = <2>;
>> + regulator-name = "reg_3v3";
>> + regulator-min-microvolt = <3300000>;
>> + regulator-max-microvolt = <3300000>;
>> + };
>> + };
>> +
>> + gpio-keys {
>> + compatible = "gpio-keys";
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&pinctrl_gpio_keys>;
>
> Bad indentation.
>
>> +
>> + power {
>> + label = "Power Button";
>> + gpios = <&gpio3 28 GPIO_ACTIVE_LOW>;
>> + wakeup-source;
>> + linux,code = <KEY_POWER>;
>> + };
>> +
>> + volume-up {
>> + label = "Volume Up";
>> + gpios = <&gpio3 29 GPIO_ACTIVE_LOW>;
>> + wakeup-source;
>> + linux,code = <KEY_VOLUMEUP>;
>> + };
>> +
>> + volume-down {
>> + label = "Volume Down";
>> + gpios = <&gpio3 30 GPIO_ACTIVE_LOW>;
>> + wakeup-source;
>> + linux,code = <KEY_VOLUMEDOWN>;
>> + };
>> +
>> + recovery-button {
>> + label = "Recover";
>> + gpios = <&gpio3 31 GPIO_ACTIVE_LOW>;
>> + wakeup-source;
>> + linux,code = <0x198>;
>
> No KEY_XXX code for this one?
I copy-pasted some random key stuff. Since I don't have an explicit
use for the keys, I'll just remove them from the device tree until we
have a better use. I was more using them to test when the keys were
pressed.
>> + };
>> + };
>> +
>> + backlight_lcd: backlight-lcd {
>> + compatible = "pwm-backlight";
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&pinctrl_backlight>;
>> + enable-gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>;
>> + pwms = <&pwm3 0 5000000>;
>> + brightness-levels = <0 4 8 16 32 64 128 255>;
>> + default-brightness-level = <6>;
>> + };
>> +
>> +
>> + lcd_display: display at di0 {
>> + compatible = "fsl,imx-parallel-display";
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> + interface-pix-fmt = "rgb565";
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&pinctrl_lcd>;
>> + status = "okay";
>
> Have a newline here.
>
>> + display-timings {
>> + native-mode = <&type15_timing>;
>> + type15_timing: type_15 {
>> + clock-frequency = <9000000>;
>> + hactive = <480>;
>> + vactive = <272>;
>> + hfront-porch = <3>;
>> + hback-porch = <2>;
>> + hsync-len = <42>;
>> + vback-porch = <3>;
>> + vfront-porch = <2>;
>> + vsync-len = <11>;
>> + hsync-active = <1>;
>> + vsync-active = <1>;
>> + de-active = <1>;
>> + pixelclk-active = <0>;
>> + };
>> + };
>> +
>> + port at 0 {
>> + reg = <0>;
>> + display_in: endpoint {
>> + remote-endpoint = <&ipu1_di0_disp0>;
>> + };
>> + };
>
> Ditto
>
>> + port at 1 {
>> + reg = <1>;
>> + display_out: endpoint {
>> + remote-endpoint = <&panel_in>;
>> + };
>> + };
>> + };
>> +
>> + panel: panel {
>> + compatible = "innolux,at043tn24", "simple-panel";
>> + enable-gpios = <&gpio4 17 GPIO_ACTIVE_HIGH>;
>> + backlight = <&backlight_lcd>;
>> + port {
>> + panel_in: endpoint {
>> + remote-endpoint = <&display_out>;
>> + };
>> + };
>> + };
>> +};
>> +
>> +&ipu1_di0_disp0 {
>> + remote-endpoint = <&display_in>;
>> +};
>> +
>> +&pwm3 {
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&pinctrl_pwm3>;
>> + status = "okay";
>> +};
>> +
>> +
>> +&uart3 {
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&pinctrl_uart3>;
>> + status = "okay";
>> +};
>> +
>> +&usbh1 {
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&pinctrl_usbh1>;
>> + vbus-supply = <®_usb_h1_vbus>;
>> + status = "okay";
>> +};
>> +
>> +&usbh2 {
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&pinctrl_usbh2>;
>> + phy_type = "hsic";
>> + disable-over-current;
>> + status = "okay";
>> +};
>> +
>> +&usbotg {
>> + vbus-supply = <®_usb_otg_vbus>;
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&pinctrl_usbotg>;
>> + disable-over-current;
>> + status = "okay";
>> +};
>> +
>> +&fec {
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&pinctrl_enet>;
>> + /* TODO: Initialize Ref clock at 50MHz so the reset can work */
>> + /*phy-reset-gpios = <&gpio4 9 GPIO_ACTIVE_HIGH>; */
>
> The fec driver ignores the polarity flags of the references in
> phy-reset-gpios and assumes them to be active low unless there is a
> property phy-reset-active-high. So if the reset is truly active high,
> you should have a phy-reset-active-high property here.
>
>> + /* phy-reset-duration = <2>; */
>> + phy-mode = "rmii";
>> + status = "okay";
>> +};
>> +
>> +&usdhc2 {
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&pinctrl_usdhc2>;
>> + cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
>> + no-1-8-v;
>> + keep-power-in-suspend;
>> + status = "okay";
>> +};
>> +
>> +&i2c3 {
>> + touchscreen: tsc2004 at 48 {
>> + compatible = "ti,tsc2004";
>> + vio-supply = <®_3v3>;
>> + reg = <0x48>;
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&pinctrl_touchscreen>;
>> + reset-gpios = <&gpio4 10 GPIO_ACTIVE_HIGH>;
>> + interrupts-extended = <&gpio1 6 IRQ_TYPE_EDGE_RISING>;
>> +
>
> Drop this newline.
>
>> + touchscreen-fuzz-x = <4>;
>> + touchscreen-fuzz-y = <7>;
>> + touchscreen-fuzz-pressure = <2>;
>> + touchscreen-size-x = <4096>;
>> + touchscreen-size-y = <4096>;
>> + touchscreen-max-pressure = <2048>;
>> +
>
> Ditto
>
>> + ti,x-plate-ohms = <280>;
>> + ti,esd-recovery-timeout-ms = <8000>;
>> + };
>> +};
>> +
>> +&iomuxc {
>> + imx6qdl-logicpd-baseboard {
>> +
>
> Drop this container node and put the following pinctrl nodes directly
> under &iomuxc.
>
Like the regulators above, if I remove this connector, the system
won't boot. I compared both the regulator and the iomuxc containers
in this device tree with other imx6q boards, and I seem to be
consistent with what other boards are doing.
>> + pinctrl_uart3: uart3grp {
>> + fsl,pins = <
>> + MX6QDL_PAD_EIM_D23__UART3_CTS_B 0x1b0b1
>> + MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
>> + MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
>> + MX6QDL_PAD_EIM_EB3__UART3_RTS_B 0x1b0b1
>> + >;
>> + };
>> +
>> + pinctrl_usbotg: usbotggrp {
>> + fsl,pins = <
>> + MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
>> + MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x130b0 /* USB_OTG_PWR_EN */
>> + >;
>
> Bad indentation.
>
>> + };
>> +
>> + pinctrl_usbh1: usbh1grp {
>> + fsl,pins = <
>> + MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x1b0b0 /* USB_H1_PWR_EN */
>> + >;
>> + };
>> +
>> + pinctrl_usbh2: usbh2grp {
>> + fsl,pins = <
>> + MX6QDL_PAD_RGMII_TXC__USB_H2_DATA 0x13030
>> + MX6QDL_PAD_RGMII_TX_CTL__USB_H2_STROBE 0x17030
>> + >;
>> + };
>> +
>> + pinctrl_usdhc2: usdhc2grp {
>> + fsl,pins = <
>> + MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
>> + MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
>> + MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
>> + MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
>> + MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
>> + MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
>> + >;
>> + };
>> +
>> + pinctrl_enet: enetgrp {
>
> Please sort these pinctrl entries alphabetically in node name.
>
>> + fsl,pins = <
>> + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
>> + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
>> + MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN 0x1b0b0
>> + MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0
>> + MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0 0x1b0b0
>> + MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1 0x1b0b0
>> + MX6QDL_PAD_ENET_RX_ER__ENET_RX_ER 0x1b0b0
>> + MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0 0x1b0b0
>> + MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1 0x1b0b0
>> + MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
>> + MX6QDL_PAD_KEY_ROW1__GPIO4_IO09 0x1b0b0 /* Ethernet Reset */
>> + >;
>> + };
>> +
>> + pinctrl_gpio_leds: gpioledsgrp {
>> + fsl,pins = <
>> + MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x130b0
>> + MX6QDL_PAD_EIM_D20__GPIO3_IO20 0x130b0
>> + MX6QDL_PAD_EIM_D21__GPIO3_IO21 0x130b0
>> + MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x130b0
>> + >;
>> + };
>> +
>> + pinctrl_gpio_keys: gpio_keysgrp {
>
> No underscore in the node name, and use hyphen instead. In this
> particular case, gpiokeysgrp should be fine.
>
>> + fsl,pins = <
>> + MX6QDL_PAD_EIM_D28__GPIO3_IO28 0x1b0b0
>> + MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x1b0b0
>> + MX6QDL_PAD_EIM_D30__GPIO3_IO30 0x1b0b0
>> + MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x1b0b0
>> + >;
>> + };
>> +
>> + pinctrl_touchscreen: touchscreengrp {
>> + fsl,pins = <
>> + MX6QDL_PAD_KEY_COL2__GPIO4_IO10 0x1b0b0
>> + MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x1b0b0
>> + >;
>> + };
>> +
>> + pinctrl_lcd: lcdgrp {
>> + fsl,pins = <
>> + MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10 /* R_LCD_DCLK */
>> + MX6QDL_PAD_DI0_PIN15__GPIO4_IO17 0x100b0 /* R_LCD_PANEL_PWR */
>> + MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x10 /* R_LCD_HSYNC */
>> + MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x10 /* R_LCD_VSYNC */
>> + MX6QDL_PAD_DI0_PIN4__IPU1_DI0_PIN04 0x10 /* R_LCD_MDISP */
>> + MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x10
>> + MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x10
>> + MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x10
>> + MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x10
>> + MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x10
>> + MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x10
>> + MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x10
>> + MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x10
>> + MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x10
>> + MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x10
>> + MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x10
>> + MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x10
>> + MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x10
>> + MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x10
>> + MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x10
>> + MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x10
>> + >;
>> + };
>> +
>> + pinctrl_backlight: backlightgrp {
>> + fsl,pins = <
>> + MX6QDL_PAD_SD4_DAT2__GPIO2_IO10 0x100b0 /* R_LCD_BACKLIGHT_PWR */
>> + >;
>> + };
>> +
>> + pinctrl_pwm3: pwm3grp {
>> + fsl,pins = <
>> + MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b0b1
>> + >;
>> + };
>> + };
>> +};
>> +
>> diff --git a/arch/arm/boot/dts/imx6qdl-logicpd.dtsi b/arch/arm/boot/dts/imx6qdl-logicpd.dtsi
>> new file mode 100644
>> index 0000000..dc28925
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/imx6qdl-logicpd.dtsi
>> @@ -0,0 +1,452 @@
>> +/*
>> + * Copyright 2016 Logic PD
>> + * This file is adapted from imx6qdl-sabresd.dtsi.
>> + * Copyright 2012 Freescale Semiconductor, Inc.
>> + * Copyright 2011 Linaro Ltd.
>> + *
>> + * The code contained herein is licensed under the GNU General Public
>> + * License. You may obtain a copy of the GNU General Public License
>> + * Version 2 or later at the following locations:
>> + *
>> + * http://www.opensource.org/licenses/gpl-license.html
>> + * http://www.gnu.org/copyleft/gpl.html
>> + */
>> +
>> +#include <dt-bindings/gpio/gpio.h>
>> +#include <dt-bindings/input/input.h>
>> +#include "imx6q.dtsi"
>> +
>> +/ {
>> + chosen {
>> + stdout-path = &uart1;
>> + };
>> +
>> + memory {
>> + reg = <0x10000000 0x80000000>;
>> + };
>> +
>> +
>> +};
>> +
>> +/* Reroute power feeding the CPU to come from the external PMIC */
>> +&cpu0 {
>> + arm-supply = <&sw1a_reg>;
>> + soc-supply = <&sw1c_reg>;
>> +};
>> +
>> +®_arm
>> +{
>> + vin-supply = <&sw1a_reg>;
>> +};
>> +
>> +®_soc
>> +{
>> + vin-supply = <&sw1c_reg>;
>> +};
>> +
>> +&clks {
>> + assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
>> + <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
>> + assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>,
>> + <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
>> +};
>> +
>> +&gpmi {
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&pinctrl_gpmi_nand>;
>> + status = "okay";
>> +};
>> +
>> +&i2c3 {
>> + clock-frequency = <100000>;
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&pinctrl_i2c3>;
>> + status = "okay";
>> +
>> + pmic: pfuze100 at 08 {
>> + compatible = "fsl,pfuze100";
>> + reg = <0x08>;
>> +
>> + regulators {
>> +
>
> Drop this newline.
>
>> + sw1a_reg: sw1ab {
>> + regulator-min-microvolt = <725000>;
>> + regulator-max-microvolt = <1450000>;
>> + regulator-name = "vddcore";
>> + regulator-boot-on;
>> + regulator-always-on;
>> + regulator-ramp-delay = <6250>;
>> + };
>> +
>> + sw1c_reg: sw1c {
>> + regulator-min-microvolt = <725000>;
>> + regulator-max-microvolt = <1450000>;
>> + regulator-name = "vddsoc";
>> + regulator-boot-on;
>> + regulator-always-on;
>> + regulator-ramp-delay = <6250>;
>> + };
>> +
>> + sw2_reg: sw2 {
>> + regulator-min-microvolt = <3300000>;
>> + regulator-max-microvolt = <3300000>;
>> + regulator-name = "gen_3v3";
>> + regulator-boot-on;
>> + regulator-always-on;
>> + };
>> +
>> + sw3a_reg: sw3a {
>> + regulator-min-microvolt = <400000>;
>> + regulator-max-microvolt = <1975000>;
>> + regulator-name = "sw3a_vddr";
>> + regulator-boot-on;
>> + regulator-always-on;
>> + };
>> +
>> +
>
> One newline is good enough.
>
>> + sw3b_reg: sw3b {
>> + regulator-min-microvolt = <400000>;
>> + regulator-max-microvolt = <1975000>;
>> + regulator-name = "sw3b_vddr";
>> + regulator-boot-on;
>> + regulator-always-on;
>> + };
>> +
>> + sw4_reg: sw4 {
>> + regulator-min-microvolt = <800000>;
>> + regulator-max-microvolt = <3300000>;
>> + regulator-name = "gen_rgmii";
>> + };
>> +
>> +
>> + swbst_reg: swbst {
>> + regulator-min-microvolt = <5000000>;
>> + regulator-max-microvolt = <5150000>;
>> + regulator-name = "gen_5v0";
>> + };
>> +
>> +
>
> Ditto
>
>> + snvs_reg: vsnvs {
>> + regulator-min-microvolt = <1000000>;
>> + regulator-max-microvolt = <3000000>;
>> + regulator-name = "gen_vsns";
>> + regulator-boot-on;
>> + regulator-always-on;
>> + };
>> +
>> +
>
> Ditto
>
>> + vref_reg: vrefddr {
>> + regulator-boot-on;
>> + regulator-always-on;
>> + };
>> +
>> + vgen1_reg: vgen1 {
>> + regulator-min-microvolt = <1500000>;
>> + regulator-max-microvolt = <1500000>;
>> + regulator-name = "gen_1v5";
>> + };
>> +
>> + vgen2_reg: vgen2 {
>> + regulator-name = "vgen2";
>> + regulator-min-microvolt = <800000>;
>> + regulator-max-microvolt = <1550000>;
>> + };
>> +
>> + vgen3_reg: vgen3 {
>> + regulator-name = "gen_vadj_0";
>> + regulator-min-microvolt = <3000000>;
>> + regulator-max-microvolt = <3000000>;
>> + };
>> +
>> + vgen4_reg: vgen4 {
>> + regulator-name = "gen_1v8";
>> + regulator-min-microvolt = <1800000>;
>> + regulator-max-microvolt = <1800000>;
>> + regulator-always-on;
>> + };
>> +
>> + vgen5_reg: vgen5 {
>> + regulator-name = "gen_adj_1";
>> + regulator-min-microvolt = <3300000>;
>> + regulator-max-microvolt = <3300000>;
>> + regulator-always-on;
>> + };
>> +
>> + vgen6_reg: vgen6 {
>> + regulator-name = "gen_2v5";
>> + regulator-min-microvolt = <2500000>;
>> + regulator-max-microvolt = <2500000>;
>> + regulator-always-on;
>> + };
>> + };
>> + };
>> +
>> + user_eeprom: at24 at 52 {
>> + compatible = "atmel,24c64";
>> + pagesize = <32>;
>> + reg = <0x52>;
>> + };
>> +
>> + mfg_eeprom: at24 at 51 {
>> + compatible = "atmel,24c64";
>> + pagesize = <32>;
>> + read-only;
>> + reg = <0x51>;
>> + };
>
> Please sort the devices on I2C bus in order of slave address.
>
>> +
>> + temp_sense0: tmp102 at 4a {
>> + compatible = "ti,tmp102";
>> + reg = <0x4a>;
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&pinctrl_tempsense>;
>> + interrupt-parent = <&gpio6>;
>> + interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
>> + #thermal-sensor-cells = <1>;
>> + };
>> +
>> + temp_sense1: tmp102 at 40 {
>> + compatible = "ti,tmp102";
>> + reg = <0x49>;
>
> 'reg' doesn't match unit-address of node name.
>
>> + interrupt-parent = <&gpio6>;
>> + interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
>> + #thermal-sensor-cells = <1>;
>> + };
>> +
>> +};
>> +
>> +&iomuxc {
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&pinctrl_hog>;
>> +
>> + imx6qdl-acuity {
>
> Drop this container node.
>
>> + pinctrl_hog: hoggrp {
>> + fsl,pins = <
>
> The hog group should be used limitedly to pins that do not have a clear
> owner. Most of pins are used by particular client device, and should be
> set up in client device's pinctrl entry.
>
>> + MX6QDL_PAD_CSI0_MCLK__ARM_TRACE_CTL 0x1b0b0
>> + MX6QDL_PAD_CSI0_DATA_EN__ARM_TRACE_CLK 0x1b0b0
>> + MX6QDL_PAD_CSI0_VSYNC__ARM_TRACE00 0x1b0b0
>> + MX6QDL_PAD_CSI0_DAT4__ARM_TRACE01 0x1b0b0
>> + MX6QDL_PAD_CSI0_DAT5__ARM_TRACE02 0x1b0b0
>> + MX6QDL_PAD_CSI0_DAT6__ARM_TRACE03 0x1b0b0
>> + MX6QDL_PAD_CSI0_DAT7__ARM_TRACE04 0x1b0b0
>> + MX6QDL_PAD_CSI0_DAT8__ARM_TRACE05 0x1b0b0
>> + MX6QDL_PAD_CSI0_DAT9__ARM_TRACE06 0x1b0b0
>> + MX6QDL_PAD_CSI0_DAT10__ARM_TRACE07 0x1b0b0
>> + MX6QDL_PAD_CSI0_DAT11__ARM_TRACE08 0x1b0b0
>> + MX6QDL_PAD_CSI0_DAT12__ARM_TRACE09 0x1b0b0
>> + MX6QDL_PAD_CSI0_DAT13__ARM_TRACE10 0x1b0b0
>> + MX6QDL_PAD_CSI0_DAT14__ARM_TRACE11 0x1b0b0
>> + MX6QDL_PAD_CSI0_DAT15__ARM_TRACE12 0x1b0b0
>> + MX6QDL_PAD_CSI0_DAT16__ARM_TRACE13 0x1b0b0
>> + MX6QDL_PAD_CSI0_DAT17__ARM_TRACE14 0x1b0b0
>> + MX6QDL_PAD_CSI0_DAT18__ARM_TRACE15 0x1b0b0
>> + MX6QDL_PAD_CSI0_DAT19__GPIO6_IO05 0x1b0b0
>> +
>> + MX6QDL_PAD_EIM_LBA__GPIO2_IO27 0x80000000
>> + MX6QDL_PAD_EIM_OE__GPIO2_IO25 0x80000000
>> + MX6QDL_PAD_EIM_RW__GPIO2_IO26 0x80000000
>> + MX6QDL_PAD_EIM_CS0__GPIO2_IO23 0x80000000
>> + MX6QDL_PAD_EIM_CS1__GPIO2_IO24 0x80000000
>> + MX6QDL_PAD_EIM_A16__GPIO2_IO22 0x80000000
>> + MX6QDL_PAD_EIM_A17__GPIO2_IO21 0x80000000
>> + MX6QDL_PAD_EIM_A18__GPIO2_IO20 0x80000000
>> + MX6QDL_PAD_EIM_A19__GPIO2_IO19 0x80000000
>> + MX6QDL_PAD_EIM_A20__GPIO2_IO18 0x80000000
>> + MX6QDL_PAD_EIM_A21__GPIO2_IO17 0x80000000
>> + MX6QDL_PAD_EIM_A22__GPIO2_IO16 0x80000000
>> + MX6QDL_PAD_EIM_A23__GPIO6_IO06 0x80000000
>> + MX6QDL_PAD_EIM_A24__GPIO5_IO04 0x80000000
>> + MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x80000000
>> + MX6QDL_PAD_EIM_DA0__GPIO3_IO00 0x80000000
>> + MX6QDL_PAD_EIM_DA1__GPIO3_IO01 0x80000000
>> + MX6QDL_PAD_EIM_DA2__GPIO3_IO02 0x80000000
>> + MX6QDL_PAD_EIM_DA3__GPIO3_IO03 0x80000000
>> + MX6QDL_PAD_EIM_DA4__GPIO3_IO04 0x80000000
>> + MX6QDL_PAD_EIM_DA5__GPIO3_IO05 0x80000000
>> + MX6QDL_PAD_EIM_DA6__GPIO3_IO06 0x80000000
>> + MX6QDL_PAD_EIM_DA7__GPIO3_IO07 0x80000000
>> + MX6QDL_PAD_EIM_DA8__GPIO3_IO08 0x80000000
>> + MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x80000000
>> + MX6QDL_PAD_EIM_DA10__GPIO3_IO10 0x80000000
>> + MX6QDL_PAD_EIM_DA11__GPIO3_IO11 0x80000000
>> + MX6QDL_PAD_EIM_DA12__GPIO3_IO12 0x80000000
>> + MX6QDL_PAD_EIM_DA13__GPIO3_IO13 0x80000000
>> + MX6QDL_PAD_EIM_DA14__GPIO3_IO14 0x80000000
>> + MX6QDL_PAD_EIM_DA15__GPIO3_IO15 0x80000000
>> + MX6QDL_PAD_EIM_D16__GPIO3_IO16 0x80000000
>> + MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x80000000
>> + MX6QDL_PAD_EIM_D20__GPIO3_IO20 0x80000000
>> + MX6QDL_PAD_EIM_D21__GPIO3_IO21 0x80000000
>> + MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000
>> + MX6QDL_PAD_EIM_D26__GPIO3_IO26 0x80000000
>> + MX6QDL_PAD_EIM_D27__GPIO3_IO27 0x80000000
>
> Do not rely on bootloader or reset value, and please use a proper config
> value instead.
>
>> +
>> +
>> +
>> +
>
> Drop these newlines.
>
>> + MX6QDL_PAD_EIM_EB0__GPIO2_IO28 0x80000000
>> + MX6QDL_PAD_EIM_EB1__GPIO2_IO29 0x80000000
>> + MX6QDL_PAD_EIM_EB2__GPIO2_IO30 0x80000000
>> + MX6QDL_PAD_EIM_BCLK__GPIO6_IO31 0x80000000
>> + MX6QDL_PAD_EIM_WAIT__GPIO5_IO00 0x80000000
>> +
>> +
>
> Ditto
>
>> + MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000
>> + MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x80000000
>> +
>
> Ditto
>
>> + MX6QDL_PAD_GPIO_7__GPIO1_IO07 0x80000000
>> + MX6QDL_PAD_GPIO_8__GPIO1_IO08 0x80000000
>> + MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x80000000
>> + MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000
>> + MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x80000000
>> + MX6QDL_PAD_GPIO_19__GPIO4_IO05 0x80000000
>> +
>
> Ditto
>
>> + MX6QDL_PAD_KEY_COL0__GPIO4_IO06 0x80000000
>> + MX6QDL_PAD_KEY_ROW0__GPIO4_IO07 0x80000000
>> + MX6QDL_PAD_KEY_COL1__GPIO4_IO08 0x80000000
>> +
>> +
>> +
>> +
>
> Ditto
>
>> + MX6QDL_PAD_NANDF_CS1__GPIO6_IO14 0x80000000
>> + MX6QDL_PAD_NANDF_CS3__GPIO6_IO16 0x80000000
>> +
>
> Ditto
>
>> + MX6QDL_PAD_RGMII_TD0__GPIO6_IO20 0x80000000
>> + MX6QDL_PAD_RGMII_TD1__GPIO6_IO21 0x80000000
>> + MX6QDL_PAD_RGMII_TD2__GPIO6_IO22 0x80000000
>> + MX6QDL_PAD_RGMII_TD3__GPIO6_IO23 0x80000000
>> + MX6QDL_PAD_RGMII_RD0__GPIO6_IO25 0x80000000
>> + MX6QDL_PAD_RGMII_RD1__GPIO6_IO27 0x80000000
>> + MX6QDL_PAD_RGMII_RD2__GPIO6_IO28 0x80000000
>> + MX6QDL_PAD_RGMII_RD3__GPIO6_IO29 0x80000000
>> +
>
> Ditto
>
>> + MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1f0b0 /* WL_IRQ */
>> + MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1f0b0 /* WLAN_EN */
>> + MX6QDL_PAD_SD3_RST__GPIO7_IO08 0x1f0b0 /* BT_EN */
>> + MX6QDL_PAD_SD4_DAT0__GPIO2_IO08 0x80000000
>> + MX6QDL_PAD_SD4_DAT3__GPIO2_IO11 0x80000000
>> + >;
>> + };
>> +
>> + pinctrl_gpmi_nand: gpminandgrp {
>> + fsl,pins = <
>> + MX6QDL_PAD_NANDF_CLE__NAND_CLE 0x0b0b1
>> + MX6QDL_PAD_NANDF_ALE__NAND_ALE 0x0b0b1
>> + MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0x0b0b1
>> + MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0x0b000
>> + MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0x0b0b1
>> + MX6QDL_PAD_SD4_CMD__NAND_RE_B 0x0b0b1
>> + MX6QDL_PAD_SD4_CLK__NAND_WE_B 0x0b0b1
>> + MX6QDL_PAD_NANDF_D0__NAND_DATA00 0x0b0b1
>> + MX6QDL_PAD_NANDF_D1__NAND_DATA01 0x0b0b1
>> + MX6QDL_PAD_NANDF_D2__NAND_DATA02 0x0b0b1
>> + MX6QDL_PAD_NANDF_D3__NAND_DATA03 0x0b0b1
>> + MX6QDL_PAD_NANDF_D4__NAND_DATA04 0x0b0b1
>> + MX6QDL_PAD_NANDF_D5__NAND_DATA05 0x0b0b1
>> + MX6QDL_PAD_NANDF_D6__NAND_DATA06 0x0b0b1
>> + MX6QDL_PAD_NANDF_D7__NAND_DATA07 0x0b0b1
>> + >;
>> + };
>> +
>> +
>> + pinctrl_i2c3: i2c3grp {
>> + fsl,pins = <
>> + MX6QDL_PAD_EIM_D17__I2C3_SCL 0x4001b8b1
>> + MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
>> + >;
>> + };
>> +
>> + pinctrl_uart1: uart1grp {
>> + fsl,pins = <
>> + MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
>> + MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
>> + >;
>> + };
>> +
>> + pinctrl_uart2: uart2grp {
>> + fsl,pins = <
>> + MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1
>> + MX6QDL_PAD_SD4_DAT5__UART2_RTS_B 0x1b0b1
>> + MX6QDL_PAD_SD4_DAT6__UART2_CTS_B 0x1b0b1
>> + MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1
>> + >;
>> + };
>> +
>> +
>> +
>
> One newline is good enough.
>
>> + pinctrl_usdhc1: usdhc1grp {
>> + fsl,pins = <
>> + MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17071
>> + MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10071
>> + MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17071
>> + MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17071
>> + MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17071
>> + MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17071
>> + >;
>> + };
>> +
>> +
>> +
>
> Ditto
>
>> + pinctrl_usdhc3: usdhc3grp {
>> + fsl,pins = <
>> + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
>> + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
>> + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
>> + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
>> + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
>> + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
>> + >;
>> + };
>> +
>> + pinctrl_tempsense: tempsensegrp {
>> + fsl,pins = <
>> + MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x1b0b0 /* Temp Sense Alert */
>> + >;
>> + };
>> + };
>> +};
>> +
>> +&snvs_poweroff {
>> + status = "okay";
>> +};
>> +
>> +
>
> Ditto
>
>> +&uart1 {
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&pinctrl_uart1>;
>> + status = "okay";
>> +};
>> +
>> +&uart2 {
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&pinctrl_uart2>;
>> + status = "okay";
>> +};
>> +
>> +&usdhc1 {
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&pinctrl_usdhc1>;
>> + cd-gpios = <&gpio6 16 GPIO_ACTIVE_HIGH>;
>> + keep-power-in-suspend;
>> + enable-sdio-wakeup;
>
> Property enable-sdio-wakeup is deprecated. Use wakeup-source instead.
>
>> + status = "okay";
>> +};
>> +
>> +&usdhc3 {
>> + pinctrl-names = "default";
>> + pinctrl-0 = <&pinctrl_usdhc3>;
>> + non-removable;
>> + keep-power-in-suspend;
>> + enable-sdio-wakeup;
>
> Ditto
>
>> + vmmc-supply = <&sw2_reg>;
>> + status = "okay";
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>
> Have a new line between property list and child node. Also, we
> generally end the property list with property 'status'.
>
>> + wlcore: wlcore at 0 {
>> + compatible = "ti,wl1837";
>> + reg = <2>;
>
> 'reg' doesn't match the unit-address in node name.
>
> Shawn
>
Thank you for all your feedback. I'll post an update in the next few
days once I hear your feedback to my questions.
adam
>> + interrupt-parent = <&gpio7>;
>> + interrupts = <1 GPIO_ACTIVE_HIGH>;
>> + };
>> +};
>> +
>> +
>> --
>> 2.7.4
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v7 03/15] irq: move IRQ routing into irq.c
From: Andre Przywara @ 2016-11-04 17:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <002e16f4-34d2-b783-90c5-4c79a427c8bc@arm.com>
Hi Jean-Philippe,
On 02/11/16 14:37, Jean-Philippe Brucker wrote:
> On 20/07/16 18:04, Andre Przywara wrote:
>> The current IRQ routing code in x86/irq.c is mostly implementing a
>> generic KVM interface which other architectures may use too.
>> Move the code to set up an MSI route into the generic irq.c file and
>> guard it with the KVM_CAP_IRQ_ROUTING capability to return an error
>> if the kernel does not support interrupt routing.
>> This also removes the dummy implementations for all other
>> architectures and only leaves the x86 specific code in x86/irq.c.
>>
>> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
>> ---
>> Makefile | 4 +--
>> arm/irq.c | 9 ------
>> hw/pci-shmem.c | 2 ++
>> include/kvm/irq.h | 5 ++++
>> irq.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> mips/irq.c | 10 -------
>> powerpc/irq.c | 31 ---------------------
>> virtio/pci.c | 21 +++++++++-----
>> x86/irq.c | 45 ++++--------------------------
>> 9 files changed, 110 insertions(+), 100 deletions(-)
>> delete mode 100644 arm/irq.c
>> delete mode 100644 mips/irq.c
>> delete mode 100644 powerpc/irq.c
>>
>> diff --git a/Makefile b/Makefile
>> index e4a4002..8ca887f 100644
>> --- a/Makefile
>> +++ b/Makefile
>> @@ -138,7 +138,6 @@ ifeq ($(ARCH), powerpc)
>> DEFINES += -DCONFIG_PPC
>> OBJS += powerpc/boot.o
>> OBJS += powerpc/ioport.o
>> - OBJS += powerpc/irq.o
>> OBJS += powerpc/kvm.o
>> OBJS += powerpc/cpu_info.o
>> OBJS += powerpc/kvm-cpu.o
>> @@ -153,7 +152,7 @@ ifeq ($(ARCH), powerpc)
>> endif
>>
>> # ARM
>> -OBJS_ARM_COMMON := arm/fdt.o arm/gic.o arm/ioport.o arm/irq.o \
>> +OBJS_ARM_COMMON := arm/fdt.o arm/gic.o arm/ioport.o \
>> arm/kvm.o arm/kvm-cpu.o arm/pci.o arm/timer.o \
>> arm/pmu.o
>> HDRS_ARM_COMMON := arm/include
>> @@ -186,7 +185,6 @@ ifeq ($(ARCH),mips)
>> ARCH_INCLUDE := mips/include
>> OBJS += mips/kvm.o
>> OBJS += mips/kvm-cpu.o
>> - OBJS += mips/irq.o
>> endif
>> ###
>>
>> diff --git a/arm/irq.c b/arm/irq.c
>> deleted file mode 100644
>> index d8f44df..0000000
>> --- a/arm/irq.c
>> +++ /dev/null
>> @@ -1,9 +0,0 @@
>> -#include "kvm/irq.h"
>> -#include "kvm/kvm.h"
>> -#include "kvm/util.h"
>> -
>> -int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg)
>> -{
>> - die(__FUNCTION__);
>> - return 0;
>> -}
>> diff --git a/hw/pci-shmem.c b/hw/pci-shmem.c
>> index a1c5ab7..7ce98cb 100644
>> --- a/hw/pci-shmem.c
>> +++ b/hw/pci-shmem.c
>> @@ -136,6 +136,8 @@ int pci_shmem__get_local_irqfd(struct kvm *kvm)
>>
>> if (pci_shmem_pci_device.msix.ctrl & cpu_to_le16(PCI_MSIX_FLAGS_ENABLE)) {
>> gsi = irq__add_msix_route(kvm, &msix_table[0].msg);
>> + if (gsi < 0)
>> + return gsi;
>> } else {
>> gsi = pci_shmem_pci_device.irq_line;
>> }
>> diff --git a/include/kvm/irq.h b/include/kvm/irq.h
>> index 8a78e43..bb71521 100644
>> --- a/include/kvm/irq.h
>> +++ b/include/kvm/irq.h
>> @@ -10,11 +10,16 @@
>>
>> struct kvm;
>>
>> +extern struct kvm_irq_routing *irq_routing;
>> +extern int next_gsi;
>> +
>> int irq__alloc_line(void);
>> int irq__get_nr_allocated_lines(void);
>>
>> int irq__init(struct kvm *kvm);
>> int irq__exit(struct kvm *kvm);
>> +
>> +int irq__allocate_routing_entry(void);
>> int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg);
>>
>> #endif
>> diff --git a/irq.c b/irq.c
>> index 71eaa05..c4b481c 100644
>> --- a/irq.c
>> +++ b/irq.c
>> @@ -1,7 +1,19 @@
>> +#include <stdlib.h>
>> +#include <sys/ioctl.h>
>> +#include <linux/types.h>
>> +#include <linux/kvm.h>
>> +#include <errno.h>
>> +
>> +#include "kvm/kvm.h"
>> #include "kvm/irq.h"
>> #include "kvm/kvm-arch.h"
>>
>> static u8 next_line = KVM_IRQ_OFFSET;
>> +static int allocated_gsis = 0;
>> +
>> +int next_gsi;
>> +
>> +struct kvm_irq_routing *irq_routing = NULL;
>>
>> int irq__alloc_line(void)
>> {
>> @@ -12,3 +24,74 @@ int irq__get_nr_allocated_lines(void)
>> {
>> return next_line - KVM_IRQ_OFFSET;
>> }
>> +
>> +int irq__allocate_routing_entry(void)
>> +{
>> + size_t table_size = sizeof(struct kvm_irq_routing);
>> + int nr_entries = 0;
>> +
>> + if (irq_routing)
>> + nr_entries = irq_routing->nr;
>> +
>> + if (nr_entries < allocated_gsis)
>> + return 0;
>> +
>> + allocated_gsis = ALIGN(nr_entries + 1, 32);
>> + table_size += sizeof(struct kvm_irq_routing_entry) * allocated_gsis;
>> + irq_routing = realloc(irq_routing, table_size);
>> +
>> + if (irq_routing == NULL)
>> + return ENOMEM;
>
> This should be -ENOMEM. Otherwise when allocate_routing_entry fails,
> add_msix_route will return this positive value, which the caller will
> confuse with a GSI number.
Nice catch! Thanks for that.
I fixed the patch and sent out a v8 (which has one or two more fixes).
Cheers,
Andre.
>> +
>> + irq_routing->nr = nr_entries;
>> +
>> + return 0;
>> +}
>> +
>> +static bool check_for_irq_routing(struct kvm *kvm)
>> +{
>> + static int has_irq_routing = 0;
>> +
>> + if (has_irq_routing == 0) {
>> + if (kvm__supports_extension(kvm, KVM_CAP_IRQ_ROUTING))
>> + has_irq_routing = 1;
>> + else
>> + has_irq_routing = -1;
>> + }
>> +
>> + return has_irq_routing > 0;
>> +}
>> +
>> +int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg)
>> +{
>> + int r;
>> +
>> + if (!check_for_irq_routing(kvm))
>> + return -ENXIO;
>> +
>> + r = irq__allocate_routing_entry();
>> + if (r)
>> + return r;
>> +
>> + irq_routing->entries[irq_routing->nr++] =
>> + (struct kvm_irq_routing_entry) {
>> + .gsi = next_gsi,
>> + .type = KVM_IRQ_ROUTING_MSI,
>> + .u.msi.address_hi = msg->address_hi,
>> + .u.msi.address_lo = msg->address_lo,
>> + .u.msi.data = msg->data,
>> + };
>> +
>> + r = ioctl(kvm->vm_fd, KVM_SET_GSI_ROUTING, irq_routing);
>> + if (r)
>> + return r;
>> +
>> + return next_gsi++;
>> +}
>> +
>> +int __attribute__((weak)) irq__exit(struct kvm *kvm)
>> +{
>> + free(irq_routing);
>> + return 0;
>> +}
>> +dev_base_exit(irq__exit);
>> diff --git a/mips/irq.c b/mips/irq.c
>> deleted file mode 100644
>> index c1ff6bb..0000000
>> --- a/mips/irq.c
>> +++ /dev/null
>> @@ -1,10 +0,0 @@
>> -#include "kvm/irq.h"
>> -#include "kvm/kvm.h"
>> -
>> -#include <stdlib.h>
>> -
>> -int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg)
>> -{
>> - pr_warning("irq__add_msix_route");
>> - return 1;
>> -}
>> diff --git a/powerpc/irq.c b/powerpc/irq.c
>> deleted file mode 100644
>> index 03f2fe7..0000000
>> --- a/powerpc/irq.c
>> +++ /dev/null
>> @@ -1,31 +0,0 @@
>> -/*
>> - * PPC64 IRQ routines
>> - *
>> - * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
>> - *
>> - * This program is free software; you can redistribute it and/or modify it
>> - * under the terms of the GNU General Public License version 2 as published
>> - * by the Free Software Foundation.
>> - */
>> -
>> -#include "kvm/devices.h"
>> -#include "kvm/irq.h"
>> -#include "kvm/kvm.h"
>> -#include "kvm/util.h"
>> -
>> -#include <linux/types.h>
>> -#include <linux/rbtree.h>
>> -#include <linux/list.h>
>> -#include <linux/kvm.h>
>> -#include <sys/ioctl.h>
>> -
>> -#include <stddef.h>
>> -#include <stdlib.h>
>> -
>> -#include "kvm/pci.h"
>> -
>> -int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg)
>> -{
>> - die(__FUNCTION__);
>> - return 0;
>> -}
>> diff --git a/virtio/pci.c b/virtio/pci.c
>> index 90fcd64..072e5b7 100644
>> --- a/virtio/pci.c
>> +++ b/virtio/pci.c
>> @@ -156,7 +156,8 @@ static bool virtio_pci__specific_io_out(struct kvm *kvm, struct virtio_device *v
>> void *data, int size, int offset)
>> {
>> struct virtio_pci *vpci = vdev->virtio;
>> - u32 config_offset, gsi, vec;
>> + u32 config_offset, vec;
>> + int gsi;
>> int type = virtio__get_dev_specific_field(offset - 20, virtio_pci__msix_enabled(vpci),
>> &config_offset);
>> if (type == VIRTIO_PCI_O_MSIX) {
>> @@ -166,21 +167,27 @@ static bool virtio_pci__specific_io_out(struct kvm *kvm, struct virtio_device *v
>> if (vec == VIRTIO_MSI_NO_VECTOR)
>> break;
>>
>> - gsi = irq__add_msix_route(kvm, &vpci->msix_table[vec].msg);
>> -
>> - vpci->config_gsi = gsi;
>> + gsi = irq__add_msix_route(kvm,
>> + &vpci->msix_table[vec].msg);
>> + if (gsi >= 0)
>> + vpci->config_gsi = gsi;
>> break;
>> case VIRTIO_MSI_QUEUE_VECTOR:
>> - vec = vpci->vq_vector[vpci->queue_selector] = ioport__read16(data);
>> + vec = ioport__read16(data);
>> + vpci->vq_vector[vpci->queue_selector] = vec;
>>
>> if (vec == VIRTIO_MSI_NO_VECTOR)
>> break;
>>
>> - gsi = irq__add_msix_route(kvm, &vpci->msix_table[vec].msg);
>> + gsi = irq__add_msix_route(kvm,
>> + &vpci->msix_table[vec].msg);
>> + if (gsi < 0)
>> + break;
>> vpci->gsis[vpci->queue_selector] = gsi;
>> if (vdev->ops->notify_vq_gsi)
>> vdev->ops->notify_vq_gsi(kvm, vpci->dev,
>> - vpci->queue_selector, gsi);
>> + vpci->queue_selector,
>> + gsi);
>> break;
>> };
>>
>> diff --git a/x86/irq.c b/x86/irq.c
>> index 72177e7..db465a1 100644
>> --- a/x86/irq.c
>> +++ b/x86/irq.c
>> @@ -11,20 +11,15 @@
>> #include <stddef.h>
>> #include <stdlib.h>
>>
>> -#define IRQ_MAX_GSI 64
>> #define IRQCHIP_MASTER 0
>> #define IRQCHIP_SLAVE 1
>> #define IRQCHIP_IOAPIC 2
>>
>> -/* First 24 GSIs are routed between IRQCHIPs and IOAPICs */
>> -static u32 gsi = 24;
>> -
>> -struct kvm_irq_routing *irq_routing;
>> -
>> static int irq__add_routing(u32 gsi, u32 type, u32 irqchip, u32 pin)
>> {
>> - if (gsi >= IRQ_MAX_GSI)
>> - return -ENOSPC;
>> + int r = irq__allocate_routing_entry();
>> + if (r)
>> + return r;
>>
>> irq_routing->entries[irq_routing->nr++] =
>> (struct kvm_irq_routing_entry) {
>> @@ -41,11 +36,6 @@ int irq__init(struct kvm *kvm)
>> {
>> int i, r;
>>
>> - irq_routing = calloc(sizeof(struct kvm_irq_routing) +
>> - IRQ_MAX_GSI * sizeof(struct kvm_irq_routing_entry), 1);
>> - if (irq_routing == NULL)
>> - return -ENOMEM;
>> -
>> /* Hook first 8 GSIs to master IRQCHIP */
>> for (i = 0; i < 8; i++)
>> if (i != 2)
>> @@ -69,33 +59,8 @@ int irq__init(struct kvm *kvm)
>> return errno;
>> }
>>
>> - return 0;
>> -}
>> -dev_base_init(irq__init);
>> + next_gsi = i;
>>
>> -int irq__exit(struct kvm *kvm)
>> -{
>> - free(irq_routing);
>> return 0;
>> }
>> -dev_base_exit(irq__exit);
>> -
>> -int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg)
>> -{
>> - int r;
>> -
>> - irq_routing->entries[irq_routing->nr++] =
>> - (struct kvm_irq_routing_entry) {
>> - .gsi = gsi,
>> - .type = KVM_IRQ_ROUTING_MSI,
>> - .u.msi.address_hi = msg->address_hi,
>> - .u.msi.address_lo = msg->address_lo,
>> - .u.msi.data = msg->data,
>> - };
>> -
>> - r = ioctl(kvm->vm_fd, KVM_SET_GSI_ROUTING, irq_routing);
>> - if (r)
>> - return r;
>> -
>> - return gsi++;
>> -}
>> +dev_base_init(irq__init);
>>
>
^ permalink raw reply
* [PATCH v8 16/16] arm: add support for vGICv3 and vITS
From: Andre Przywara @ 2016-11-04 17:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161104173203.21168-1-andre.przywara@arm.com>
From: Vladimir Murzin <vladimir.murzin@arm.com>
KVM/arm got support for vGICv3 and vITS recently, so make use of it.
Signed-off-by: Vladimir Murzin <vladimir.murzin@arm.com>
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
arm/aarch32/arm-cpu.c | 2 +-
arm/aarch32/include/kvm/kvm-arch.h | 3 ---
arm/aarch64/include/kvm/kvm-arch.h | 3 ---
arm/include/arm-common/kvm-arch.h | 2 ++
4 files changed, 3 insertions(+), 7 deletions(-)
diff --git a/arm/aarch32/arm-cpu.c b/arm/aarch32/arm-cpu.c
index 27a8e17..16bba55 100644
--- a/arm/aarch32/arm-cpu.c
+++ b/arm/aarch32/arm-cpu.c
@@ -12,7 +12,7 @@ static void generate_fdt_nodes(void *fdt, struct kvm *kvm)
{
int timer_interrupts[4] = {13, 14, 11, 10};
- gic__generate_fdt_nodes(fdt, IRQCHIP_GICV2);
+ gic__generate_fdt_nodes(fdt, kvm->cfg.arch.irqchip);
timer__generate_fdt_nodes(fdt, kvm, timer_interrupts);
}
diff --git a/arm/aarch32/include/kvm/kvm-arch.h b/arm/aarch32/include/kvm/kvm-arch.h
index 1632e3c..cd31e72 100644
--- a/arm/aarch32/include/kvm/kvm-arch.h
+++ b/arm/aarch32/include/kvm/kvm-arch.h
@@ -1,9 +1,6 @@
#ifndef KVM__KVM_ARCH_H
#define KVM__KVM_ARCH_H
-#define ARM_GIC_DIST_SIZE 0x1000
-#define ARM_GIC_CPUI_SIZE 0x2000
-
#define ARM_KERN_OFFSET(...) 0x8000
#define ARM_MAX_MEMORY(...) ARM_LOMAP_MAX_MEMORY
diff --git a/arm/aarch64/include/kvm/kvm-arch.h b/arm/aarch64/include/kvm/kvm-arch.h
index 4925736..9de623a 100644
--- a/arm/aarch64/include/kvm/kvm-arch.h
+++ b/arm/aarch64/include/kvm/kvm-arch.h
@@ -1,9 +1,6 @@
#ifndef KVM__KVM_ARCH_H
#define KVM__KVM_ARCH_H
-#define ARM_GIC_DIST_SIZE 0x10000
-#define ARM_GIC_CPUI_SIZE 0x20000
-
#define ARM_KERN_OFFSET(kvm) ((kvm)->cfg.arch.aarch32_guest ? \
0x8000 : \
0x80000)
diff --git a/arm/include/arm-common/kvm-arch.h b/arm/include/arm-common/kvm-arch.h
index 0f5fb7f..c83c45f 100644
--- a/arm/include/arm-common/kvm-arch.h
+++ b/arm/include/arm-common/kvm-arch.h
@@ -18,6 +18,8 @@
#define ARM_GIC_DIST_BASE (ARM_AXI_AREA - ARM_GIC_DIST_SIZE)
#define ARM_GIC_CPUI_BASE (ARM_GIC_DIST_BASE - ARM_GIC_CPUI_SIZE)
#define ARM_GIC_SIZE (ARM_GIC_DIST_SIZE + ARM_GIC_CPUI_SIZE)
+#define ARM_GIC_DIST_SIZE 0x10000
+#define ARM_GIC_CPUI_SIZE 0x20000
#define ARM_IOPORT_SIZE (ARM_MMIO_AREA - ARM_IOPORT_AREA)
#define ARM_VIRTIO_MMIO_SIZE (ARM_AXI_AREA - (ARM_MMIO_AREA + ARM_GIC_SIZE))
--
2.9.0
^ permalink raw reply related
* [PATCH v8 15/16] arm64: enable GICv3-ITS emulation
From: Andre Przywara @ 2016-11-04 17:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161104173203.21168-1-andre.przywara@arm.com>
With everything in place for the ITS emulation add a new option to the
--irqchip parameter to allow the user to specify --irqchip=gicv3-its
to enable the ITS emulation.
This will trigger creating the FDT node and an ITS register frame to
tell the kernel we want ITS emulation in the guest.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
arm/gic.c | 2 ++
arm/include/arm-common/kvm-config-arch.h | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/arm/gic.c b/arm/gic.c
index c422e36..cd4f518 100644
--- a/arm/gic.c
+++ b/arm/gic.c
@@ -43,6 +43,8 @@ int irqchip_parser(const struct option *opt, const char *arg, int unset)
*type = IRQCHIP_GICV2;
} else if (!strcmp(arg, "gicv3")) {
*type = IRQCHIP_GICV3;
+ } else if (!strcmp(arg, "gicv3-its")) {
+ *type = IRQCHIP_GICV3_ITS;
} else {
pr_err("irqchip: unknown type \"%s\"\n", arg);
return -1;
diff --git a/arm/include/arm-common/kvm-config-arch.h b/arm/include/arm-common/kvm-config-arch.h
index ed626b5..b48e720 100644
--- a/arm/include/arm-common/kvm-config-arch.h
+++ b/arm/include/arm-common/kvm-config-arch.h
@@ -27,7 +27,7 @@ int irqchip_parser(const struct option *opt, const char *arg, int unset);
"Force virtio devices to use PCI as their default " \
"transport"), \
OPT_CALLBACK('\0', "irqchip", &(cfg)->irqchip, \
- "[gicv2|gicv3]", \
+ "[gicv2|gicv3|gicv3-its]", \
"Type of interrupt controller to emulate in the guest", \
irqchip_parser, NULL),
--
2.9.0
^ permalink raw reply related
* [PATCH v8 14/16] extend GSI IRQ routing to take a device ID
From: Andre Przywara @ 2016-11-04 17:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161104173203.21168-1-andre.przywara@arm.com>
For ITS emulation we need the device ID along with the MSI payload
and doorbell address to identify an MSI, so we need to put it in the
GSI IRQ routing table too.
There is a per-VM capability by which the kernel signals the need for
a device ID, so check this and put the device ID into the routing
table if needed.
For PCI devices we take the bus/device/function triplet and and that
to the routing setup call.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
hw/pci-shmem.c | 3 ++-
include/kvm/irq.h | 2 +-
irq.c | 24 ++++++++++++++++++++++--
virtio/pci.c | 6 ++++--
4 files changed, 29 insertions(+), 6 deletions(-)
diff --git a/hw/pci-shmem.c b/hw/pci-shmem.c
index 7ce98cb..512b5b0 100644
--- a/hw/pci-shmem.c
+++ b/hw/pci-shmem.c
@@ -135,7 +135,8 @@ int pci_shmem__get_local_irqfd(struct kvm *kvm)
return fd;
if (pci_shmem_pci_device.msix.ctrl & cpu_to_le16(PCI_MSIX_FLAGS_ENABLE)) {
- gsi = irq__add_msix_route(kvm, &msix_table[0].msg);
+ gsi = irq__add_msix_route(kvm, &msix_table[0].msg,
+ pci_shmem_device.dev_num << 3);
if (gsi < 0)
return gsi;
} else {
diff --git a/include/kvm/irq.h b/include/kvm/irq.h
index f35eb7e..ee059e3 100644
--- a/include/kvm/irq.h
+++ b/include/kvm/irq.h
@@ -20,7 +20,7 @@ int irq__init(struct kvm *kvm);
int irq__exit(struct kvm *kvm);
int irq__allocate_routing_entry(void);
-int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg);
+int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg, u32 device_id);
void irq__update_msix_route(struct kvm *kvm, u32 gsi, struct msi_msg *msg);
#endif
diff --git a/irq.c b/irq.c
index 895e5eb..4c2721a 100644
--- a/irq.c
+++ b/irq.c
@@ -66,7 +66,21 @@ static bool check_for_irq_routing(struct kvm *kvm)
return has_irq_routing > 0;
}
-int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg)
+static bool check_for_msi_devid(struct kvm *kvm)
+{
+ static int needs_devid = 0;
+
+ if (needs_devid == 0) {
+ if (kvm__supports_vm_extension(kvm, KVM_CAP_MSI_DEVID))
+ needs_devid = 1;
+ else
+ needs_devid = -1;
+ }
+
+ return needs_devid > 0;
+}
+
+int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg, u32 device_id)
{
int r;
@@ -77,7 +91,7 @@ int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg)
if (r)
return r;
- irq_routing->entries[irq_routing->nr++] =
+ irq_routing->entries[irq_routing->nr] =
(struct kvm_irq_routing_entry) {
.gsi = next_gsi,
.type = KVM_IRQ_ROUTING_MSI,
@@ -86,6 +100,12 @@ int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg)
.u.msi.data = msg->data,
};
+ if (check_for_msi_devid(kvm)) {
+ irq_routing->entries[irq_routing->nr].flags = KVM_MSI_VALID_DEVID;
+ irq_routing->entries[irq_routing->nr].u.msi.devid = device_id;
+ }
+ irq_routing->nr++;
+
r = ioctl(kvm->vm_fd, KVM_SET_GSI_ROUTING, irq_routing);
if (r)
return r;
diff --git a/virtio/pci.c b/virtio/pci.c
index e9f81f7..da9a555 100644
--- a/virtio/pci.c
+++ b/virtio/pci.c
@@ -192,7 +192,8 @@ static bool virtio_pci__specific_io_out(struct kvm *kvm, struct virtio_device *v
break;
gsi = irq__add_msix_route(kvm,
- &vpci->msix_table[vec].msg);
+ &vpci->msix_table[vec].msg,
+ vpci->dev_hdr.dev_num << 3);
if (gsi >= 0) {
vpci->config_gsi = gsi;
break;
@@ -210,7 +211,8 @@ static bool virtio_pci__specific_io_out(struct kvm *kvm, struct virtio_device *v
break;
gsi = irq__add_msix_route(kvm,
- &vpci->msix_table[vec].msg);
+ &vpci->msix_table[vec].msg,
+ vpci->dev_hdr.dev_num << 3);
if (gsi < 0) {
if (gsi == -ENXIO &&
vpci->features & VIRTIO_PCI_F_SIGNAL_MSI)
--
2.9.0
^ permalink raw reply related
* [PATCH v8 13/16] arm: setup SPI IRQ routing tables
From: Andre Przywara @ 2016-11-04 17:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161104173203.21168-1-andre.przywara@arm.com>
Since we soon start using GSI routing on ARM platforms too, we have
to setup the initial SPI routing table. Before the first call to
KVM_SET_GSI_ROUTING, the kernel holds this table internally, but this
is overwritten with the ioctl, so we have to explicitly set it up
here.
The routing is actually not used for IRQs triggered by KVM_IRQ_LINE,
but it needs to be here anyway. We use a simple 1:1 mapping.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
arm/gic.c | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/arm/gic.c b/arm/gic.c
index 44f9365..c422e36 100644
--- a/arm/gic.c
+++ b/arm/gic.c
@@ -27,6 +27,8 @@
#define KVM_VGIC_V3_ITS_SIZE (2 * SZ_64K)
#endif
+#define IRQCHIP_GIC 0
+
static int gic_fd = -1;
static u64 gic_redists_base;
static u64 gic_redists_size;
@@ -49,6 +51,34 @@ int irqchip_parser(const struct option *opt, const char *arg, int unset)
return 0;
}
+static int irq__routing_init(struct kvm *kvm)
+{
+ int r;
+ int irqlines = ALIGN(irq__get_nr_allocated_lines(), 32);
+
+ /*
+ * This describes the default routing that the kernel uses without
+ * any routing explicitly set up via KVM_SET_GSI_ROUTING. So we
+ * don't need to commit these setting right now. The first actual
+ * user (MSI routing) will engage these mappings then.
+ */
+ for (next_gsi = 0; next_gsi < irqlines; next_gsi++) {
+ r = irq__allocate_routing_entry();
+ if (r)
+ return r;
+
+ irq_routing->entries[irq_routing->nr++] =
+ (struct kvm_irq_routing_entry) {
+ .gsi = next_gsi,
+ .type = KVM_IRQ_ROUTING_IRQCHIP,
+ .u.irqchip.irqchip = IRQCHIP_GIC,
+ .u.irqchip.pin = next_gsi,
+ };
+ }
+
+ return 0;
+}
+
static int gic__create_its_frame(struct kvm *kvm, u64 its_frame_addr)
{
struct kvm_create_device its_device = {
@@ -255,6 +285,8 @@ static int gic__init_gic(struct kvm *kvm)
return ret;
}
+ irq__routing_init(kvm);
+
if (!ioctl(gic_fd, KVM_HAS_DEVICE_ATTR, &vgic_init_attr)) {
ret = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &vgic_init_attr);
if (ret)
--
2.9.0
^ permalink raw reply related
* [PATCH v8 12/16] PCI: inject PCI device ID on MSI injection
From: Andre Przywara @ 2016-11-04 17:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161104173203.21168-1-andre.przywara@arm.com>
The ITS emulation requires a unique device ID to be passed along the
MSI payload when kvmtool wants to trigger an MSI in the guest.
According to the proposed changes to the interface add the PCI
bus/device/function triple to the structure passed with the ioctl.
Check the respective capability before actually adding the device ID
to the kvm_msi struct.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
virtio/pci.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/virtio/pci.c b/virtio/pci.c
index 604b9ec..e9f81f7 100644
--- a/virtio/pci.c
+++ b/virtio/pci.c
@@ -318,14 +318,28 @@ static void virtio_pci__msix_mmio_callback(struct kvm_cpu *vcpu,
update_msix_map(vpci, table, (addr - offset) / 16);
}
-static void virtio_pci__signal_msi(struct kvm *kvm, struct virtio_pci *vpci, int vec)
+static void virtio_pci__signal_msi(struct kvm *kvm, struct virtio_pci *vpci,
+ int vec)
{
+ static int needs_devid = 0;
struct kvm_msi msi = {
.address_lo = vpci->msix_table[vec].msg.address_lo,
.address_hi = vpci->msix_table[vec].msg.address_hi,
.data = vpci->msix_table[vec].msg.data,
};
+ if (needs_devid == 0) {
+ if (kvm__supports_vm_extension(kvm, KVM_CAP_MSI_DEVID))
+ needs_devid = 1;
+ else
+ needs_devid = -1;
+ }
+
+ if (needs_devid > 0) {
+ msi.flags = KVM_MSI_VALID_DEVID;
+ msi.devid = vpci->dev_hdr.dev_num << 3;
+ }
+
ioctl(kvm->vm_fd, KVM_SIGNAL_MSI, &msi);
}
--
2.9.0
^ permalink raw reply related
* [PATCH v8 11/16] add kvm__check_vm_capability
From: Andre Przywara @ 2016-11-04 17:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161104173203.21168-1-andre.przywara@arm.com>
KVM capabilities can be per-VM, in this case the ioctl should be
issued on the VM file descriptor, not on the system fd.
Since this feature is guarded by a (system) capability itself, wrap
the call into a function of its own.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
include/kvm/kvm.h | 1 +
kvm.c | 28 ++++++++++++++++++++++++++++
2 files changed, 29 insertions(+)
diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h
index 4a76ec2..a76a25d 100644
--- a/include/kvm/kvm.h
+++ b/include/kvm/kvm.h
@@ -129,6 +129,7 @@ static inline bool host_ptr_in_ram(struct kvm *kvm, void *p)
}
bool kvm__supports_extension(struct kvm *kvm, unsigned int extension);
+bool kvm__supports_vm_extension(struct kvm *kvm, unsigned int extension);
static inline void kvm__set_thread_name(const char *name)
{
diff --git a/kvm.c b/kvm.c
index 7fa76f7..665ed14 100644
--- a/kvm.c
+++ b/kvm.c
@@ -93,6 +93,34 @@ const char *kvm__get_dir(void)
return kvm_dir;
}
+bool kvm__supports_vm_extension(struct kvm *kvm, unsigned int extension)
+{
+ static int supports_vm_ext_check = 0;
+ int ret;
+
+ switch (supports_vm_ext_check) {
+ case 0:
+ ret = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION,
+ KVM_CAP_CHECK_EXTENSION_VM);
+ if (ret <= 0) {
+ supports_vm_ext_check = -1;
+ return false;
+ }
+ supports_vm_ext_check = 1;
+ /* fall through */
+ case 1:
+ break;
+ case -1:
+ return false;
+ }
+
+ ret = ioctl(kvm->vm_fd, KVM_CHECK_EXTENSION, extension);
+ if (ret < 0)
+ return false;
+
+ return ret;
+}
+
bool kvm__supports_extension(struct kvm *kvm, unsigned int extension)
{
int ret;
--
2.9.0
^ permalink raw reply related
* [PATCH v8 10/16] arm: FDT: create MSI controller DT node
From: Andre Przywara @ 2016-11-04 17:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161104173203.21168-1-andre.przywara@arm.com>
The ARM GICv3 ITS requires a separate device tree node to describe
the ITS. Add this as a child to the GIC interrupt controller node
to let a guest discover and use the ITS if the user requests it.
Since we now need to specify #address-cells for the GIC node, we
have to add two zeroes to the interrupt map to match that.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
arm/gic.c | 23 ++++++++++++++++++++++-
arm/pci.c | 12 ++++++++++--
include/kvm/fdt.h | 2 +-
3 files changed, 33 insertions(+), 4 deletions(-)
diff --git a/arm/gic.c b/arm/gic.c
index ed9016d..44f9365 100644
--- a/arm/gic.c
+++ b/arm/gic.c
@@ -267,7 +267,8 @@ late_init(gic__init_gic)
void gic__generate_fdt_nodes(void *fdt, enum irqchip_type type)
{
- const char *compatible;
+ const char *compatible, *msi_compatible = NULL;
+ u64 msi_prop[2];
u64 reg_prop[] = {
cpu_to_fdt64(ARM_GIC_DIST_BASE), cpu_to_fdt64(ARM_GIC_DIST_SIZE),
0, 0, /* to be filled */
@@ -279,6 +280,9 @@ void gic__generate_fdt_nodes(void *fdt, enum irqchip_type type)
reg_prop[2] = cpu_to_fdt64(ARM_GIC_CPUI_BASE);
reg_prop[3] = cpu_to_fdt64(ARM_GIC_CPUI_SIZE);
break;
+ case IRQCHIP_GICV3_ITS:
+ msi_compatible = "arm,gic-v3-its";
+ /* fall-through */
case IRQCHIP_GICV3:
compatible = "arm,gic-v3";
reg_prop[2] = cpu_to_fdt64(gic_redists_base);
@@ -294,6 +298,23 @@ void gic__generate_fdt_nodes(void *fdt, enum irqchip_type type)
_FDT(fdt_property(fdt, "interrupt-controller", NULL, 0));
_FDT(fdt_property(fdt, "reg", reg_prop, sizeof(reg_prop)));
_FDT(fdt_property_cell(fdt, "phandle", fdt__get_phandle(PHANDLE_GIC)));
+ _FDT(fdt_property_cell(fdt, "#address-cells", 2));
+ _FDT(fdt_property_cell(fdt, "#size-cells", 2));
+
+ if (msi_compatible) {
+ _FDT(fdt_property(fdt, "ranges", NULL, 0));
+
+ _FDT(fdt_begin_node(fdt, "msic"));
+ _FDT(fdt_property_string(fdt, "compatible", msi_compatible));
+ _FDT(fdt_property(fdt, "msi-controller", NULL, 0));
+ _FDT(fdt_property_cell(fdt, "phandle",
+ fdt__get_phandle(PHANDLE_MSI)));
+ msi_prop[0] = cpu_to_fdt64(gic_msi_base);
+ msi_prop[1] = cpu_to_fdt64(gic_msi_size);
+ _FDT(fdt_property(fdt, "reg", msi_prop, sizeof(msi_prop)));
+ _FDT(fdt_end_node(fdt));
+ }
+
_FDT(fdt_end_node(fdt));
}
diff --git a/arm/pci.c b/arm/pci.c
index 9630657..104349a 100644
--- a/arm/pci.c
+++ b/arm/pci.c
@@ -18,6 +18,8 @@ struct of_gic_irq {
struct of_interrupt_map_entry {
struct of_pci_irq_mask pci_irq_mask;
u32 gic_phandle;
+ u32 gic_addr_hi;
+ u32 gic_addr_lo;
struct of_gic_irq gic_irq;
} __attribute__((packed));
@@ -26,7 +28,7 @@ void pci__generate_fdt_nodes(void *fdt)
struct device_header *dev_hdr;
struct of_interrupt_map_entry irq_map[OF_PCI_IRQ_MAP_MAX];
unsigned nentries = 0;
- u32 gic_phandle = fdt__get_phandle(PHANDLE_GIC);
+ u32 phandle;
/* Bus range */
u32 bus_range[] = { cpu_to_fdt32(0), cpu_to_fdt32(1), };
/* Configuration Space */
@@ -65,7 +67,11 @@ void pci__generate_fdt_nodes(void *fdt)
_FDT(fdt_property(fdt, "bus-range", bus_range, sizeof(bus_range)));
_FDT(fdt_property(fdt, "reg", &cfg_reg_prop, sizeof(cfg_reg_prop)));
_FDT(fdt_property(fdt, "ranges", ranges, sizeof(ranges)));
+ phandle = fdt__get_phandle(PHANDLE_MSI);
+ if (FDT_IS_VALID_PHANDLE(phandle))
+ _FDT(fdt_property_cell(fdt, "msi-parent", phandle));
+ phandle = fdt__get_phandle(PHANDLE_GIC);
/* Generate the interrupt map ... */
dev_hdr = device__first_dev(DEVICE_BUS_PCI);
while (dev_hdr && nentries < ARRAY_SIZE(irq_map)) {
@@ -84,7 +90,9 @@ void pci__generate_fdt_nodes(void *fdt)
},
.pci_pin = cpu_to_fdt32(pin),
},
- .gic_phandle = cpu_to_fdt32(gic_phandle),
+ .gic_phandle = cpu_to_fdt32(phandle),
+ .gic_addr_hi = 0,
+ .gic_addr_lo = 0,
.gic_irq = {
.type = cpu_to_fdt32(GIC_FDT_IRQ_TYPE_SPI),
.num = cpu_to_fdt32(irq - GIC_SPI_IRQ_BASE),
diff --git a/include/kvm/fdt.h b/include/kvm/fdt.h
index cd2bb72..8006e8f 100644
--- a/include/kvm/fdt.h
+++ b/include/kvm/fdt.h
@@ -11,7 +11,7 @@
#define FDT_INVALID_PHANDLE 0
#define FDT_IS_VALID_PHANDLE(phandle) ((phandle) != FDT_INVALID_PHANDLE)
-enum phandles {PHANDLE_GIC, PHANDLES_MAX};
+enum phandles {PHANDLE_GIC, PHANDLE_MSI, PHANDLES_MAX};
/* Those definitions are generic FDT values for specifying IRQ
* types and are used in the Linux kernel internally as well as in
--
2.9.0
^ permalink raw reply related
* [PATCH v8 09/16] arm: allow creation of an MSI register frame region
From: Andre Przywara @ 2016-11-04 17:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161104173203.21168-1-andre.przywara@arm.com>
The GICv3 ITS expects a separate 64K page to hold ITS registers.
Add a function to reserve such a page in the guest's I/O memory and
use that for the ITS vGIC type.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
arm/gic.c | 63 ++++++++++++++++++++++++++++++++++++++++++++
arm/include/arm-common/gic.h | 1 +
2 files changed, 64 insertions(+)
diff --git a/arm/gic.c b/arm/gic.c
index 4d12f31..ed9016d 100644
--- a/arm/gic.c
+++ b/arm/gic.c
@@ -8,6 +8,7 @@
#include <linux/byteorder.h>
#include <linux/kernel.h>
#include <linux/kvm.h>
+#include <linux/sizes.h>
/* Those names are not defined for ARM (yet) */
#ifndef KVM_VGIC_V3_ADDR_TYPE_DIST
@@ -29,6 +30,8 @@
static int gic_fd = -1;
static u64 gic_redists_base;
static u64 gic_redists_size;
+static u64 gic_msi_base;
+static u64 gic_msi_size = 0;
int irqchip_parser(const struct option *opt, const char *arg, int unset)
{
@@ -46,6 +49,56 @@ int irqchip_parser(const struct option *opt, const char *arg, int unset)
return 0;
}
+static int gic__create_its_frame(struct kvm *kvm, u64 its_frame_addr)
+{
+ struct kvm_create_device its_device = {
+ .type = KVM_DEV_TYPE_ARM_VGIC_ITS,
+ .flags = 0,
+ };
+ struct kvm_device_attr its_attr = {
+ .group = KVM_DEV_ARM_VGIC_GRP_ADDR,
+ .attr = KVM_VGIC_ITS_ADDR_TYPE,
+ .addr = (u64)(unsigned long)&its_frame_addr,
+ };
+ struct kvm_device_attr its_init_attr = {
+ .group = KVM_DEV_ARM_VGIC_GRP_CTRL,
+ .attr = KVM_DEV_ARM_VGIC_CTRL_INIT,
+ };
+ int err;
+
+ err = ioctl(kvm->vm_fd, KVM_CREATE_DEVICE, &its_device);
+ if (err) {
+ fprintf(stderr,
+ "GICv3 ITS requested, but kernel does not support it.\n");
+ fprintf(stderr, "Try --irqchip=gicv3 instead\n");
+ return err;
+ }
+
+ err = ioctl(its_device.fd, KVM_HAS_DEVICE_ATTR, &its_attr);
+ if (err) {
+ close(its_device.fd);
+ its_device.fd = -1;
+ return err;
+ }
+
+ err = ioctl(its_device.fd, KVM_SET_DEVICE_ATTR, &its_attr);
+ if (err)
+ return err;
+
+ return ioctl(its_device.fd, KVM_SET_DEVICE_ATTR, &its_init_attr);
+}
+
+static int gic__create_msi_frame(struct kvm *kvm, enum irqchip_type type,
+ u64 msi_frame_addr)
+{
+ switch (type) {
+ case IRQCHIP_GICV3_ITS:
+ return gic__create_its_frame(kvm, msi_frame_addr);
+ default: /* No MSI frame needed */
+ return 0;
+ }
+}
+
static int gic__create_device(struct kvm *kvm, enum irqchip_type type)
{
int err;
@@ -75,6 +128,7 @@ static int gic__create_device(struct kvm *kvm, enum irqchip_type type)
dist_attr.attr = KVM_VGIC_V2_ADDR_TYPE_DIST;
break;
case IRQCHIP_GICV3:
+ case IRQCHIP_GICV3_ITS:
gic_device.type = KVM_DEV_TYPE_ARM_VGIC_V3;
dist_attr.attr = KVM_VGIC_V3_ADDR_TYPE_DIST;
break;
@@ -90,6 +144,7 @@ static int gic__create_device(struct kvm *kvm, enum irqchip_type type)
case IRQCHIP_GICV2:
err = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &cpu_if_attr);
break;
+ case IRQCHIP_GICV3_ITS:
case IRQCHIP_GICV3:
err = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &redist_attr);
break;
@@ -101,6 +156,10 @@ static int gic__create_device(struct kvm *kvm, enum irqchip_type type)
if (err)
goto out_err;
+ err = gic__create_msi_frame(kvm, type, gic_msi_base);
+ if (err)
+ goto out_err;
+
return 0;
out_err:
@@ -144,9 +203,13 @@ int gic__create(struct kvm *kvm, enum irqchip_type type)
switch (type) {
case IRQCHIP_GICV2:
break;
+ case IRQCHIP_GICV3_ITS:
+ gic_msi_size = KVM_VGIC_V3_ITS_SIZE;
+ /* fall through */
case IRQCHIP_GICV3:
gic_redists_size = kvm->cfg.nrcpus * ARM_GIC_REDIST_SIZE;
gic_redists_base = ARM_GIC_DIST_BASE - gic_redists_size;
+ gic_msi_base = gic_redists_base - gic_msi_size;
break;
default:
return -ENODEV;
diff --git a/arm/include/arm-common/gic.h b/arm/include/arm-common/gic.h
index b43a180..433dd23 100644
--- a/arm/include/arm-common/gic.h
+++ b/arm/include/arm-common/gic.h
@@ -24,6 +24,7 @@
enum irqchip_type {
IRQCHIP_GICV2,
IRQCHIP_GICV3,
+ IRQCHIP_GICV3_ITS,
};
struct kvm;
--
2.9.0
^ permalink raw reply related
* [PATCH v8 08/16] arm: gic: allow 32-bit compilation
From: Andre Przywara @ 2016-11-04 17:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161104173203.21168-1-andre.przywara@arm.com>
The ARM GIC code is shared between ARM and arm64, though the header
files from the Linux kernel are actually different, reflecting the
different level of GIC emulation support between the two architectures.
Since it is conceivable that ARM will gain GICv3 (and possibly ITS)
emulation support too, lets conditionally define those missing
symbols in the source file until an upcoming ARM header update eventually
includes those.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
arm/gic.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/arm/gic.c b/arm/gic.c
index 2c1a547..4d12f31 100644
--- a/arm/gic.c
+++ b/arm/gic.c
@@ -18,6 +18,14 @@
#define KVM_VGIC_V3_ADDR_TYPE_REDIST 3
#endif
+#ifndef KVM_VGIC_ITS_ADDR_TYPE
+#define KVM_VGIC_ITS_ADDR_TYPE 4
+#endif
+
+#ifndef KVM_VGIC_V3_ITS_SIZE
+#define KVM_VGIC_V3_ITS_SIZE (2 * SZ_64K)
+#endif
+
static int gic_fd = -1;
static u64 gic_redists_base;
static u64 gic_redists_size;
--
2.9.0
^ permalink raw reply related
* [PATCH v8 07/16] update public Linux headers for GICv3 ITS emulation
From: Andre Przywara @ 2016-11-04 17:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161104173203.21168-1-andre.przywara@arm.com>
The GICv3 ITS emulation brings some additions to the headers, so
lets update kvmtool's version of the headers to Linux' v4.8-rc2.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
arm/aarch32/include/asm/kvm.h | 4 ++--
arm/aarch64/include/asm/kvm.h | 2 ++
include/linux/kvm.h | 19 +++++++++++++++++--
x86/include/asm/kvm.h | 6 +++---
4 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/arm/aarch32/include/asm/kvm.h b/arm/aarch32/include/asm/kvm.h
index df3f60c..a2b3eb3 100644
--- a/arm/aarch32/include/asm/kvm.h
+++ b/arm/aarch32/include/asm/kvm.h
@@ -139,8 +139,8 @@ struct kvm_arch_memory_slot {
#define ARM_CP15_REG64(...) __ARM_CP15_REG64(__VA_ARGS__)
#define KVM_REG_ARM_TIMER_CTL ARM_CP15_REG32(0, 14, 3, 1)
-#define KVM_REG_ARM_TIMER_CNT ARM_CP15_REG64(1, 14)
-#define KVM_REG_ARM_TIMER_CVAL ARM_CP15_REG64(3, 14)
+#define KVM_REG_ARM_TIMER_CNT ARM_CP15_REG64(1, 14)
+#define KVM_REG_ARM_TIMER_CVAL ARM_CP15_REG64(3, 14)
/* Normal registers are mapped as coprocessor 16. */
#define KVM_REG_ARM_CORE (0x0010 << KVM_REG_ARM_COPROC_SHIFT)
diff --git a/arm/aarch64/include/asm/kvm.h b/arm/aarch64/include/asm/kvm.h
index f209ea1..3051f86 100644
--- a/arm/aarch64/include/asm/kvm.h
+++ b/arm/aarch64/include/asm/kvm.h
@@ -87,9 +87,11 @@ struct kvm_regs {
/* Supported VGICv3 address types */
#define KVM_VGIC_V3_ADDR_TYPE_DIST 2
#define KVM_VGIC_V3_ADDR_TYPE_REDIST 3
+#define KVM_VGIC_ITS_ADDR_TYPE 4
#define KVM_VGIC_V3_DIST_SIZE SZ_64K
#define KVM_VGIC_V3_REDIST_SIZE (2 * SZ_64K)
+#define KVM_VGIC_V3_ITS_SIZE (2 * SZ_64K)
#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */
#define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index a7f1f80..300ef25 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -865,6 +865,11 @@ struct kvm_ppc_smmu_info {
#define KVM_CAP_SPAPR_TCE_64 125
#define KVM_CAP_ARM_PMU_V3 126
#define KVM_CAP_VCPU_ATTRIBUTES 127
+#define KVM_CAP_MAX_VCPU_ID 128
+#define KVM_CAP_X2APIC_API 129
+#define KVM_CAP_S390_USER_INSTR0 130
+#define KVM_CAP_MSI_DEVID 131
+#define KVM_CAP_PPC_HTM 132
#ifdef KVM_CAP_IRQ_ROUTING
@@ -877,7 +882,10 @@ struct kvm_irq_routing_msi {
__u32 address_lo;
__u32 address_hi;
__u32 data;
- __u32 pad;
+ union {
+ __u32 pad;
+ __u32 devid;
+ };
};
struct kvm_irq_routing_s390_adapter {
@@ -1023,12 +1031,14 @@ struct kvm_one_reg {
__u64 addr;
};
+#define KVM_MSI_VALID_DEVID (1U << 0)
struct kvm_msi {
__u32 address_lo;
__u32 address_hi;
__u32 data;
__u32 flags;
- __u8 pad[16];
+ __u32 devid;
+ __u8 pad[12];
};
struct kvm_arm_device_addr {
@@ -1073,6 +1083,8 @@ enum kvm_device_type {
#define KVM_DEV_TYPE_FLIC KVM_DEV_TYPE_FLIC
KVM_DEV_TYPE_ARM_VGIC_V3,
#define KVM_DEV_TYPE_ARM_VGIC_V3 KVM_DEV_TYPE_ARM_VGIC_V3
+ KVM_DEV_TYPE_ARM_VGIC_ITS,
+#define KVM_DEV_TYPE_ARM_VGIC_ITS KVM_DEV_TYPE_ARM_VGIC_ITS
KVM_DEV_TYPE_MAX,
};
@@ -1312,4 +1324,7 @@ struct kvm_assigned_msix_entry {
__u16 padding[3];
};
+#define KVM_X2APIC_API_USE_32BIT_IDS (1ULL << 0)
+#define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK (1ULL << 1)
+
#endif /* __LINUX_KVM_H */
diff --git a/x86/include/asm/kvm.h b/x86/include/asm/kvm.h
index cd54147..739c0c5 100644
--- a/x86/include/asm/kvm.h
+++ b/x86/include/asm/kvm.h
@@ -216,9 +216,9 @@ struct kvm_cpuid_entry2 {
__u32 padding[3];
};
-#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX BIT(0)
-#define KVM_CPUID_FLAG_STATEFUL_FUNC BIT(1)
-#define KVM_CPUID_FLAG_STATE_READ_NEXT BIT(2)
+#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX (1 << 0)
+#define KVM_CPUID_FLAG_STATEFUL_FUNC (1 << 1)
+#define KVM_CPUID_FLAG_STATE_READ_NEXT (1 << 2)
/* for KVM_SET_CPUID2 */
struct kvm_cpuid2 {
--
2.9.0
^ permalink raw reply related
* [PATCH v8 06/16] PCI: Only allocate IRQ routing entry when available
From: Andre Przywara @ 2016-11-04 17:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161104173203.21168-1-andre.przywara@arm.com>
If we need to inject an MSI into the guest, we rely at the moment on a
working GSI MSI routing functionality. However we can get away without
IRQ routing, if the host supports MSI injection via the KVM_SIGNAL_MSI
ioctl.
So we try the GSI routing first, but if that fails due to a missing
IRQ routing functionality, we fall back to KVM_SIGNAL_MSI (if that is
supported).
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
virtio/pci.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/virtio/pci.c b/virtio/pci.c
index b3b4aac..604b9ec 100644
--- a/virtio/pci.c
+++ b/virtio/pci.c
@@ -193,8 +193,14 @@ static bool virtio_pci__specific_io_out(struct kvm *kvm, struct virtio_device *v
gsi = irq__add_msix_route(kvm,
&vpci->msix_table[vec].msg);
- if (gsi >= 0)
+ if (gsi >= 0) {
vpci->config_gsi = gsi;
+ break;
+ }
+ if (gsi == -ENXIO &&
+ vpci->features & VIRTIO_PCI_F_SIGNAL_MSI)
+ break;
+ die("failed to configure MSIs");
break;
case VIRTIO_MSI_QUEUE_VECTOR:
vec = ioport__read16(data);
@@ -205,8 +211,14 @@ static bool virtio_pci__specific_io_out(struct kvm *kvm, struct virtio_device *v
gsi = irq__add_msix_route(kvm,
&vpci->msix_table[vec].msg);
- if (gsi < 0)
+ if (gsi < 0) {
+ if (gsi == -ENXIO &&
+ vpci->features & VIRTIO_PCI_F_SIGNAL_MSI)
+ break;
+
+ die("failed to configure MSIs");
break;
+ }
vpci->gsis[vpci->queue_selector] = gsi;
if (vdev->ops->notify_vq_gsi)
vdev->ops->notify_vq_gsi(kvm, vpci->dev,
--
2.9.0
^ permalink raw reply related
* [PATCH v8 05/16] virtio: fix endianness check for vhost support
From: Andre Przywara @ 2016-11-04 17:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161104173203.21168-1-andre.przywara@arm.com>
Currently we deny any VHOST_* functionality if the architecture
supports guests with different endianness than the host. Most of the
time even on those architectures the endianness of guest and host are
the same, though, so we are denying the glory of VHOST needlessly.
Switch from compile time determination to a run time scheme, which
takes the actual endianness of the guest into account.
For this we change the semantics of VIRTIO_ENDIAN_HOST to return the
actual endianness of the host (the endianness of kvmtool at compile
time, really). The actual check in vhost_net now compares this against
the guest endianness.
This enables vhost support on ARM and ARM64.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
include/kvm/virtio.h | 9 +++++++--
virtio/net.c | 2 +-
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/include/kvm/virtio.h b/include/kvm/virtio.h
index 768ee96..66530fd 100644
--- a/include/kvm/virtio.h
+++ b/include/kvm/virtio.h
@@ -17,10 +17,15 @@
#define VIRTIO_PCI_O_CONFIG 0
#define VIRTIO_PCI_O_MSIX 1
-#define VIRTIO_ENDIAN_HOST 0
#define VIRTIO_ENDIAN_LE (1 << 0)
#define VIRTIO_ENDIAN_BE (1 << 1)
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define VIRTIO_ENDIAN_HOST VIRTIO_ENDIAN_LE
+#else
+#define VIRTIO_ENDIAN_HOST VIRTIO_ENDIAN_BE
+#endif
+
struct virt_queue {
struct vring vring;
u32 pfn;
@@ -40,7 +45,7 @@ struct virt_queue {
#define VIRTIO_RING_ENDIAN VIRTIO_ENDIAN_HOST
#endif
-#if (VIRTIO_RING_ENDIAN & (VIRTIO_ENDIAN_LE | VIRTIO_ENDIAN_BE))
+#if VIRTIO_RING_ENDIAN != VIRTIO_ENDIAN_HOST
static inline __u16 __virtio_g2h_u16(u16 endian, __u16 val)
{
diff --git a/virtio/net.c b/virtio/net.c
index 6d1be65..e94e37a 100644
--- a/virtio/net.c
+++ b/virtio/net.c
@@ -531,7 +531,7 @@ static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 page_size, u32 align,
}
if (queue->endian != VIRTIO_ENDIAN_HOST)
- die_perror("VHOST requires VIRTIO_ENDIAN_HOST");
+ die_perror("VHOST requires the same endianness in guest and host");
state.num = queue->vring.num;
r = ioctl(ndev->vhost_fd, VHOST_SET_VRING_NUM, &state);
--
2.9.0
^ permalink raw reply related
* [PATCH v8 04/16] MSI-X: update GSI routing after changed MSI-X configuration
From: Andre Przywara @ 2016-11-04 17:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161104173203.21168-1-andre.przywara@arm.com>
When we set up GSI routing to map MSIs to KVM's GSI numbers, we
write the current device's MSI setup into the kernel routing table.
However the device driver in the guest can use PCI configuration space
accesses to change the MSI configuration (address and/or payload data).
Whenever this happens after we have setup the routing table already,
we must amend the previously sent data.
So when MSI-X PCI config space accesses write address or payload,
find the associated GSI number and the matching routing table entry
and update the kernel routing table (only if the data has changed).
This fixes vhost-net, where the queue's IRQFD was setup before the
MSI vectors.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
include/kvm/irq.h | 1 +
irq.c | 31 +++++++++++++++++++++++++++++++
virtio/pci.c | 36 +++++++++++++++++++++++++++++++++---
3 files changed, 65 insertions(+), 3 deletions(-)
diff --git a/include/kvm/irq.h b/include/kvm/irq.h
index bb71521..f35eb7e 100644
--- a/include/kvm/irq.h
+++ b/include/kvm/irq.h
@@ -21,5 +21,6 @@ int irq__exit(struct kvm *kvm);
int irq__allocate_routing_entry(void);
int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg);
+void irq__update_msix_route(struct kvm *kvm, u32 gsi, struct msi_msg *msg);
#endif
diff --git a/irq.c b/irq.c
index a742aa2..895e5eb 100644
--- a/irq.c
+++ b/irq.c
@@ -93,6 +93,37 @@ int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg)
return next_gsi++;
}
+static bool update_data(u32 *ptr, u32 newdata)
+{
+ if (*ptr == newdata)
+ return false;
+
+ *ptr = newdata;
+ return true;
+}
+
+void irq__update_msix_route(struct kvm *kvm, u32 gsi, struct msi_msg *msg)
+{
+ struct kvm_irq_routing_msi *entry;
+ unsigned int i;
+ bool changed;
+
+ for (i = 0; i < irq_routing->nr; i++)
+ if (gsi == irq_routing->entries[i].gsi)
+ break;
+ if (i == irq_routing->nr)
+ return;
+
+ entry = &irq_routing->entries[i].u.msi;
+
+ changed = update_data(&entry->address_hi, msg->address_hi);
+ changed |= update_data(&entry->address_lo, msg->address_lo);
+ changed |= update_data(&entry->data, msg->data);
+
+ if (changed)
+ ioctl(kvm->vm_fd, KVM_SET_GSI_ROUTING, irq_routing);
+}
+
int __attribute__((weak)) irq__exit(struct kvm *kvm)
{
free(irq_routing);
diff --git a/virtio/pci.c b/virtio/pci.c
index 072e5b7..b3b4aac 100644
--- a/virtio/pci.c
+++ b/virtio/pci.c
@@ -152,6 +152,30 @@ static bool virtio_pci__io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 p
return ret;
}
+static void update_msix_map(struct virtio_pci *vpci,
+ struct msix_table *msix_entry, u32 vecnum)
+{
+ u32 gsi, i;
+
+ /* Find the GSI number used for that vector */
+ if (vecnum == vpci->config_vector) {
+ gsi = vpci->config_gsi;
+ } else {
+ for (i = 0; i < VIRTIO_PCI_MAX_VQ; i++)
+ if (vpci->vq_vector[i] == vecnum)
+ break;
+ if (i == VIRTIO_PCI_MAX_VQ)
+ return;
+ gsi = vpci->gsis[i];
+ }
+
+ if (gsi == 0)
+ return;
+
+ msix_entry = &msix_entry[vecnum];
+ irq__update_msix_route(vpci->kvm, gsi, &msix_entry->msg);
+}
+
static bool virtio_pci__specific_io_out(struct kvm *kvm, struct virtio_device *vdev, u16 port,
void *data, int size, int offset)
{
@@ -270,10 +294,16 @@ static void virtio_pci__msix_mmio_callback(struct kvm_cpu *vcpu,
offset = vpci->msix_io_block;
}
- if (is_write)
- memcpy(table + addr - offset, data, len);
- else
+ if (!is_write) {
memcpy(data, table + addr - offset, len);
+ return;
+ }
+
+ memcpy(table + addr - offset, data, len);
+
+ /* Did we just update the address or payload? */
+ if (addr % 0x10 < 0xc)
+ update_msix_map(vpci, table, (addr - offset) / 16);
}
static void virtio_pci__signal_msi(struct kvm *kvm, struct virtio_pci *vpci, int vec)
--
2.9.0
^ permalink raw reply related
* [PATCH v8 03/16] irq: move IRQ routing into irq.c
From: Andre Przywara @ 2016-11-04 17:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161104173203.21168-1-andre.przywara@arm.com>
The current IRQ routing code in x86/irq.c is mostly implementing a
generic KVM interface which other architectures may use too.
Move the code to set up an MSI route into the generic irq.c file and
guard it with the KVM_CAP_IRQ_ROUTING capability to return an error
if the kernel does not support interrupt routing.
This also removes the dummy implementations for all other
architectures and only leaves the x86 specific code in x86/irq.c.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
Makefile | 4 +--
arm/irq.c | 9 ------
hw/pci-shmem.c | 2 ++
include/kvm/irq.h | 5 ++++
irq.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
mips/irq.c | 10 -------
powerpc/irq.c | 31 --------------------
virtio/pci.c | 21 +++++++++-----
x86/irq.c | 45 ++++------------------------
9 files changed, 114 insertions(+), 100 deletions(-)
delete mode 100644 arm/irq.c
delete mode 100644 mips/irq.c
delete mode 100644 powerpc/irq.c
diff --git a/Makefile b/Makefile
index e4a4002..8ca887f 100644
--- a/Makefile
+++ b/Makefile
@@ -138,7 +138,6 @@ ifeq ($(ARCH), powerpc)
DEFINES += -DCONFIG_PPC
OBJS += powerpc/boot.o
OBJS += powerpc/ioport.o
- OBJS += powerpc/irq.o
OBJS += powerpc/kvm.o
OBJS += powerpc/cpu_info.o
OBJS += powerpc/kvm-cpu.o
@@ -153,7 +152,7 @@ ifeq ($(ARCH), powerpc)
endif
# ARM
-OBJS_ARM_COMMON := arm/fdt.o arm/gic.o arm/ioport.o arm/irq.o \
+OBJS_ARM_COMMON := arm/fdt.o arm/gic.o arm/ioport.o \
arm/kvm.o arm/kvm-cpu.o arm/pci.o arm/timer.o \
arm/pmu.o
HDRS_ARM_COMMON := arm/include
@@ -186,7 +185,6 @@ ifeq ($(ARCH),mips)
ARCH_INCLUDE := mips/include
OBJS += mips/kvm.o
OBJS += mips/kvm-cpu.o
- OBJS += mips/irq.o
endif
###
diff --git a/arm/irq.c b/arm/irq.c
deleted file mode 100644
index d8f44df..0000000
--- a/arm/irq.c
+++ /dev/null
@@ -1,9 +0,0 @@
-#include "kvm/irq.h"
-#include "kvm/kvm.h"
-#include "kvm/util.h"
-
-int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg)
-{
- die(__FUNCTION__);
- return 0;
-}
diff --git a/hw/pci-shmem.c b/hw/pci-shmem.c
index a1c5ab7..7ce98cb 100644
--- a/hw/pci-shmem.c
+++ b/hw/pci-shmem.c
@@ -136,6 +136,8 @@ int pci_shmem__get_local_irqfd(struct kvm *kvm)
if (pci_shmem_pci_device.msix.ctrl & cpu_to_le16(PCI_MSIX_FLAGS_ENABLE)) {
gsi = irq__add_msix_route(kvm, &msix_table[0].msg);
+ if (gsi < 0)
+ return gsi;
} else {
gsi = pci_shmem_pci_device.irq_line;
}
diff --git a/include/kvm/irq.h b/include/kvm/irq.h
index 8a78e43..bb71521 100644
--- a/include/kvm/irq.h
+++ b/include/kvm/irq.h
@@ -10,11 +10,16 @@
struct kvm;
+extern struct kvm_irq_routing *irq_routing;
+extern int next_gsi;
+
int irq__alloc_line(void);
int irq__get_nr_allocated_lines(void);
int irq__init(struct kvm *kvm);
int irq__exit(struct kvm *kvm);
+
+int irq__allocate_routing_entry(void);
int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg);
#endif
diff --git a/irq.c b/irq.c
index 71eaa05..a742aa2 100644
--- a/irq.c
+++ b/irq.c
@@ -1,7 +1,19 @@
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <linux/types.h>
+#include <linux/kvm.h>
+#include <errno.h>
+
+#include "kvm/kvm.h"
#include "kvm/irq.h"
#include "kvm/kvm-arch.h"
static u8 next_line = KVM_IRQ_OFFSET;
+static int allocated_gsis = 0;
+
+int next_gsi;
+
+struct kvm_irq_routing *irq_routing = NULL;
int irq__alloc_line(void)
{
@@ -12,3 +24,78 @@ int irq__get_nr_allocated_lines(void)
{
return next_line - KVM_IRQ_OFFSET;
}
+
+int irq__allocate_routing_entry(void)
+{
+ size_t table_size = sizeof(struct kvm_irq_routing);
+ size_t old_size = table_size;
+ int nr_entries = 0;
+
+ if (irq_routing)
+ nr_entries = irq_routing->nr;
+
+ if (nr_entries < allocated_gsis)
+ return 0;
+
+ old_size += sizeof(struct kvm_irq_routing_entry) * allocated_gsis;
+ allocated_gsis = ALIGN(nr_entries + 1, 32);
+ table_size += sizeof(struct kvm_irq_routing_entry) * allocated_gsis;
+ irq_routing = realloc(irq_routing, table_size);
+
+ if (irq_routing == NULL)
+ return -ENOMEM;
+ memset((void *)irq_routing + old_size, 0, table_size - old_size);
+
+ irq_routing->nr = nr_entries;
+ irq_routing->flags = 0;
+
+ return 0;
+}
+
+static bool check_for_irq_routing(struct kvm *kvm)
+{
+ static int has_irq_routing = 0;
+
+ if (has_irq_routing == 0) {
+ if (kvm__supports_extension(kvm, KVM_CAP_IRQ_ROUTING))
+ has_irq_routing = 1;
+ else
+ has_irq_routing = -1;
+ }
+
+ return has_irq_routing > 0;
+}
+
+int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg)
+{
+ int r;
+
+ if (!check_for_irq_routing(kvm))
+ return -ENXIO;
+
+ r = irq__allocate_routing_entry();
+ if (r)
+ return r;
+
+ irq_routing->entries[irq_routing->nr++] =
+ (struct kvm_irq_routing_entry) {
+ .gsi = next_gsi,
+ .type = KVM_IRQ_ROUTING_MSI,
+ .u.msi.address_hi = msg->address_hi,
+ .u.msi.address_lo = msg->address_lo,
+ .u.msi.data = msg->data,
+ };
+
+ r = ioctl(kvm->vm_fd, KVM_SET_GSI_ROUTING, irq_routing);
+ if (r)
+ return r;
+
+ return next_gsi++;
+}
+
+int __attribute__((weak)) irq__exit(struct kvm *kvm)
+{
+ free(irq_routing);
+ return 0;
+}
+dev_base_exit(irq__exit);
diff --git a/mips/irq.c b/mips/irq.c
deleted file mode 100644
index c1ff6bb..0000000
--- a/mips/irq.c
+++ /dev/null
@@ -1,10 +0,0 @@
-#include "kvm/irq.h"
-#include "kvm/kvm.h"
-
-#include <stdlib.h>
-
-int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg)
-{
- pr_warning("irq__add_msix_route");
- return 1;
-}
diff --git a/powerpc/irq.c b/powerpc/irq.c
deleted file mode 100644
index 03f2fe7..0000000
--- a/powerpc/irq.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * PPC64 IRQ routines
- *
- * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- */
-
-#include "kvm/devices.h"
-#include "kvm/irq.h"
-#include "kvm/kvm.h"
-#include "kvm/util.h"
-
-#include <linux/types.h>
-#include <linux/rbtree.h>
-#include <linux/list.h>
-#include <linux/kvm.h>
-#include <sys/ioctl.h>
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "kvm/pci.h"
-
-int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg)
-{
- die(__FUNCTION__);
- return 0;
-}
diff --git a/virtio/pci.c b/virtio/pci.c
index 90fcd64..072e5b7 100644
--- a/virtio/pci.c
+++ b/virtio/pci.c
@@ -156,7 +156,8 @@ static bool virtio_pci__specific_io_out(struct kvm *kvm, struct virtio_device *v
void *data, int size, int offset)
{
struct virtio_pci *vpci = vdev->virtio;
- u32 config_offset, gsi, vec;
+ u32 config_offset, vec;
+ int gsi;
int type = virtio__get_dev_specific_field(offset - 20, virtio_pci__msix_enabled(vpci),
&config_offset);
if (type == VIRTIO_PCI_O_MSIX) {
@@ -166,21 +167,27 @@ static bool virtio_pci__specific_io_out(struct kvm *kvm, struct virtio_device *v
if (vec == VIRTIO_MSI_NO_VECTOR)
break;
- gsi = irq__add_msix_route(kvm, &vpci->msix_table[vec].msg);
-
- vpci->config_gsi = gsi;
+ gsi = irq__add_msix_route(kvm,
+ &vpci->msix_table[vec].msg);
+ if (gsi >= 0)
+ vpci->config_gsi = gsi;
break;
case VIRTIO_MSI_QUEUE_VECTOR:
- vec = vpci->vq_vector[vpci->queue_selector] = ioport__read16(data);
+ vec = ioport__read16(data);
+ vpci->vq_vector[vpci->queue_selector] = vec;
if (vec == VIRTIO_MSI_NO_VECTOR)
break;
- gsi = irq__add_msix_route(kvm, &vpci->msix_table[vec].msg);
+ gsi = irq__add_msix_route(kvm,
+ &vpci->msix_table[vec].msg);
+ if (gsi < 0)
+ break;
vpci->gsis[vpci->queue_selector] = gsi;
if (vdev->ops->notify_vq_gsi)
vdev->ops->notify_vq_gsi(kvm, vpci->dev,
- vpci->queue_selector, gsi);
+ vpci->queue_selector,
+ gsi);
break;
};
diff --git a/x86/irq.c b/x86/irq.c
index 72177e7..db465a1 100644
--- a/x86/irq.c
+++ b/x86/irq.c
@@ -11,20 +11,15 @@
#include <stddef.h>
#include <stdlib.h>
-#define IRQ_MAX_GSI 64
#define IRQCHIP_MASTER 0
#define IRQCHIP_SLAVE 1
#define IRQCHIP_IOAPIC 2
-/* First 24 GSIs are routed between IRQCHIPs and IOAPICs */
-static u32 gsi = 24;
-
-struct kvm_irq_routing *irq_routing;
-
static int irq__add_routing(u32 gsi, u32 type, u32 irqchip, u32 pin)
{
- if (gsi >= IRQ_MAX_GSI)
- return -ENOSPC;
+ int r = irq__allocate_routing_entry();
+ if (r)
+ return r;
irq_routing->entries[irq_routing->nr++] =
(struct kvm_irq_routing_entry) {
@@ -41,11 +36,6 @@ int irq__init(struct kvm *kvm)
{
int i, r;
- irq_routing = calloc(sizeof(struct kvm_irq_routing) +
- IRQ_MAX_GSI * sizeof(struct kvm_irq_routing_entry), 1);
- if (irq_routing == NULL)
- return -ENOMEM;
-
/* Hook first 8 GSIs to master IRQCHIP */
for (i = 0; i < 8; i++)
if (i != 2)
@@ -69,33 +59,8 @@ int irq__init(struct kvm *kvm)
return errno;
}
- return 0;
-}
-dev_base_init(irq__init);
+ next_gsi = i;
-int irq__exit(struct kvm *kvm)
-{
- free(irq_routing);
return 0;
}
-dev_base_exit(irq__exit);
-
-int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg)
-{
- int r;
-
- irq_routing->entries[irq_routing->nr++] =
- (struct kvm_irq_routing_entry) {
- .gsi = gsi,
- .type = KVM_IRQ_ROUTING_MSI,
- .u.msi.address_hi = msg->address_hi,
- .u.msi.address_lo = msg->address_lo,
- .u.msi.data = msg->data,
- };
-
- r = ioctl(kvm->vm_fd, KVM_SET_GSI_ROUTING, irq_routing);
- if (r)
- return r;
-
- return gsi++;
-}
+dev_base_init(irq__init);
--
2.9.0
^ permalink raw reply related
* [PATCH v8 02/16] arm: use new phandle allocation functions
From: Andre Przywara @ 2016-11-04 17:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161104173203.21168-1-andre.przywara@arm.com>
To refer to the GIC FDT node, we used to pass the GIC phandle to most
of the functions dealing with FDT nodes.
Since we now have a global phandle reference, use that to refer to the
GIC handle in various places and get rid of the now unneeded parameter
passing.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
arm/aarch32/arm-cpu.c | 4 ++--
arm/aarch64/arm-cpu.c | 5 +++--
arm/fdt.c | 6 +++---
arm/gic.c | 2 +-
arm/include/arm-common/gic.h | 2 +-
arm/include/arm-common/kvm-cpu-arch.h | 3 +--
arm/include/arm-common/pci.h | 2 +-
arm/pci.c | 3 ++-
8 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/arm/aarch32/arm-cpu.c b/arm/aarch32/arm-cpu.c
index d8d6293..27a8e17 100644
--- a/arm/aarch32/arm-cpu.c
+++ b/arm/aarch32/arm-cpu.c
@@ -8,11 +8,11 @@
#include <linux/byteorder.h>
#include <linux/types.h>
-static void generate_fdt_nodes(void *fdt, struct kvm *kvm, u32 gic_phandle)
+static void generate_fdt_nodes(void *fdt, struct kvm *kvm)
{
int timer_interrupts[4] = {13, 14, 11, 10};
- gic__generate_fdt_nodes(fdt, gic_phandle, IRQCHIP_GICV2);
+ gic__generate_fdt_nodes(fdt, IRQCHIP_GICV2);
timer__generate_fdt_nodes(fdt, kvm, timer_interrupts);
}
diff --git a/arm/aarch64/arm-cpu.c b/arm/aarch64/arm-cpu.c
index c21c0bb..d7572b7 100644
--- a/arm/aarch64/arm-cpu.c
+++ b/arm/aarch64/arm-cpu.c
@@ -10,10 +10,11 @@
#include <linux/byteorder.h>
#include <linux/types.h>
-static void generate_fdt_nodes(void *fdt, struct kvm *kvm, u32 gic_phandle)
+static void generate_fdt_nodes(void *fdt, struct kvm *kvm)
{
int timer_interrupts[4] = {13, 14, 11, 10};
- gic__generate_fdt_nodes(fdt, gic_phandle, kvm->cfg.arch.irqchip);
+
+ gic__generate_fdt_nodes(fdt, kvm->cfg.arch.irqchip);
timer__generate_fdt_nodes(fdt, kvm, timer_interrupts);
pmu__generate_fdt_nodes(fdt, kvm);
}
diff --git a/arm/fdt.c b/arm/fdt.c
index 8bcfffb..f6c8a4c 100644
--- a/arm/fdt.c
+++ b/arm/fdt.c
@@ -125,7 +125,7 @@ static int setup_fdt(struct kvm *kvm)
kvm->arch.dtb_guest_start);
void (*generate_mmio_fdt_nodes)(void *, struct device_header *,
void (*)(void *, u8, enum irq_type));
- void (*generate_cpu_peripheral_fdt_nodes)(void *, struct kvm *, u32)
+ void (*generate_cpu_peripheral_fdt_nodes)(void *, struct kvm *)
= kvm->cpus[0]->generate_fdt_nodes;
/* Create new tree without a reserve map */
@@ -166,7 +166,7 @@ static int setup_fdt(struct kvm *kvm)
/* CPU and peripherals (interrupt controller, timers, etc) */
generate_cpu_nodes(fdt, kvm);
if (generate_cpu_peripheral_fdt_nodes)
- generate_cpu_peripheral_fdt_nodes(fdt, kvm, gic_phandle);
+ generate_cpu_peripheral_fdt_nodes(fdt, kvm);
/* Virtio MMIO devices */
dev_hdr = device__first_dev(DEVICE_BUS_MMIO);
@@ -185,7 +185,7 @@ static int setup_fdt(struct kvm *kvm)
}
/* PCI host controller */
- pci__generate_fdt_nodes(fdt, gic_phandle);
+ pci__generate_fdt_nodes(fdt);
/* PSCI firmware */
_FDT(fdt_begin_node(fdt, "psci"));
diff --git a/arm/gic.c b/arm/gic.c
index b60437e..2c1a547 100644
--- a/arm/gic.c
+++ b/arm/gic.c
@@ -194,7 +194,7 @@ static int gic__init_gic(struct kvm *kvm)
}
late_init(gic__init_gic)
-void gic__generate_fdt_nodes(void *fdt, u32 phandle, enum irqchip_type type)
+void gic__generate_fdt_nodes(void *fdt, enum irqchip_type type)
{
const char *compatible;
u64 reg_prop[] = {
diff --git a/arm/include/arm-common/gic.h b/arm/include/arm-common/gic.h
index 4fde5ac..b43a180 100644
--- a/arm/include/arm-common/gic.h
+++ b/arm/include/arm-common/gic.h
@@ -30,6 +30,6 @@ struct kvm;
int gic__alloc_irqnum(void);
int gic__create(struct kvm *kvm, enum irqchip_type type);
-void gic__generate_fdt_nodes(void *fdt, u32 phandle, enum irqchip_type type);
+void gic__generate_fdt_nodes(void *fdt, enum irqchip_type type);
#endif /* ARM_COMMON__GIC_H */
diff --git a/arm/include/arm-common/kvm-cpu-arch.h b/arm/include/arm-common/kvm-cpu-arch.h
index 8a6a6e7..923d2c4 100644
--- a/arm/include/arm-common/kvm-cpu-arch.h
+++ b/arm/include/arm-common/kvm-cpu-arch.h
@@ -25,8 +25,7 @@ struct kvm_cpu {
struct kvm_coalesced_mmio_ring *ring;
- void (*generate_fdt_nodes)(void *fdt, struct kvm* kvm,
- u32 gic_phandle);
+ void (*generate_fdt_nodes)(void *fdt, struct kvm* kvm);
};
struct kvm_arm_target {
diff --git a/arm/include/arm-common/pci.h b/arm/include/arm-common/pci.h
index ee87725..9008a0e 100644
--- a/arm/include/arm-common/pci.h
+++ b/arm/include/arm-common/pci.h
@@ -1,6 +1,6 @@
#ifndef ARM_COMMON__PCI_H
#define ARM_COMMON__PCI_H
-void pci__generate_fdt_nodes(void *fdt, u32 gic_phandle);
+void pci__generate_fdt_nodes(void *fdt);
#endif /* ARM_COMMON__PCI_H */
diff --git a/arm/pci.c b/arm/pci.c
index 99a8130..9630657 100644
--- a/arm/pci.c
+++ b/arm/pci.c
@@ -21,11 +21,12 @@ struct of_interrupt_map_entry {
struct of_gic_irq gic_irq;
} __attribute__((packed));
-void pci__generate_fdt_nodes(void *fdt, u32 gic_phandle)
+void pci__generate_fdt_nodes(void *fdt)
{
struct device_header *dev_hdr;
struct of_interrupt_map_entry irq_map[OF_PCI_IRQ_MAP_MAX];
unsigned nentries = 0;
+ u32 gic_phandle = fdt__get_phandle(PHANDLE_GIC);
/* Bus range */
u32 bus_range[] = { cpu_to_fdt32(0), cpu_to_fdt32(1), };
/* Configuration Space */
--
2.9.0
^ permalink raw reply related
* [PATCH v8 01/16] FDT: introduce global phandle allocation
From: Andre Przywara @ 2016-11-04 17:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161104173203.21168-1-andre.przywara@arm.com>
Allocating an FDT phandle (a unique identifier) using a static
variable in a static inline function defined in a header file works
only if all users are in the same source file. So trying to allocate
a handle from two different compilation units fails.
Introduce global phandle allocation and reference code to properly
allocate unique phandles.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
Makefile | 1 +
arm/fdt.c | 2 +-
arm/gic.c | 2 +-
include/kvm/fdt.h | 10 +++++-----
kvm-fdt.c | 26 ++++++++++++++++++++++++++
5 files changed, 34 insertions(+), 7 deletions(-)
create mode 100644 kvm-fdt.c
diff --git a/Makefile b/Makefile
index 1f0196f..e4a4002 100644
--- a/Makefile
+++ b/Makefile
@@ -98,6 +98,7 @@ OBJS += kvm-ipc.o
OBJS += builtin-sandbox.o
OBJS += virtio/mmio.o
OBJS += hw/i8042.o
+OBJS += kvm-fdt.o
# Translate uname -m into ARCH string
ARCH ?= $(shell uname -m | sed -e s/i.86/i386/ -e s/ppc.*/powerpc/ \
diff --git a/arm/fdt.c b/arm/fdt.c
index 381d48f..8bcfffb 100644
--- a/arm/fdt.c
+++ b/arm/fdt.c
@@ -114,7 +114,7 @@ static int setup_fdt(struct kvm *kvm)
{
struct device_header *dev_hdr;
u8 staging_fdt[FDT_MAX_SIZE];
- u32 gic_phandle = fdt__alloc_phandle();
+ u32 gic_phandle = fdt__get_phandle(PHANDLE_GIC);
u64 mem_reg_prop[] = {
cpu_to_fdt64(kvm->arch.memory_guest_start),
cpu_to_fdt64(kvm->ram_size),
diff --git a/arm/gic.c b/arm/gic.c
index d6d6dd0..b60437e 100644
--- a/arm/gic.c
+++ b/arm/gic.c
@@ -222,7 +222,7 @@ void gic__generate_fdt_nodes(void *fdt, u32 phandle, enum irqchip_type type)
_FDT(fdt_property_cell(fdt, "#interrupt-cells", GIC_FDT_IRQ_NUM_CELLS));
_FDT(fdt_property(fdt, "interrupt-controller", NULL, 0));
_FDT(fdt_property(fdt, "reg", reg_prop, sizeof(reg_prop)));
- _FDT(fdt_property_cell(fdt, "phandle", phandle));
+ _FDT(fdt_property_cell(fdt, "phandle", fdt__get_phandle(PHANDLE_GIC)));
_FDT(fdt_end_node(fdt));
}
diff --git a/include/kvm/fdt.h b/include/kvm/fdt.h
index 53d85a4..cd2bb72 100644
--- a/include/kvm/fdt.h
+++ b/include/kvm/fdt.h
@@ -8,6 +8,10 @@
#include <linux/types.h>
#define FDT_MAX_SIZE 0x10000
+#define FDT_INVALID_PHANDLE 0
+#define FDT_IS_VALID_PHANDLE(phandle) ((phandle) != FDT_INVALID_PHANDLE)
+
+enum phandles {PHANDLE_GIC, PHANDLES_MAX};
/* Those definitions are generic FDT values for specifying IRQ
* types and are used in the Linux kernel internally as well as in
@@ -33,10 +37,6 @@ enum irq_type {
} \
} while (0)
-static inline u32 fdt__alloc_phandle(void)
-{
- static u32 phandle = 0;
- return ++phandle;
-}
+u32 fdt__get_phandle(enum phandles phandle);
#endif /* KVM__FDT_H */
diff --git a/kvm-fdt.c b/kvm-fdt.c
new file mode 100644
index 0000000..d05f3fe
--- /dev/null
+++ b/kvm-fdt.c
@@ -0,0 +1,26 @@
+/*
+ * Commonly used FDT functions.
+ */
+
+#include <stdio.h>
+#include "kvm/fdt.h"
+#include "kvm/util.h"
+
+u32 phandles[PHANDLES_MAX] = {};
+u32 next_phandle = 1;
+
+u32 fdt__get_phandle(enum phandles phandle)
+{
+ u32 ret;
+
+ if (phandle >= PHANDLES_MAX)
+ return FDT_INVALID_PHANDLE;
+
+ ret = phandles[phandle];
+ if (ret == FDT_INVALID_PHANDLE) {
+ ret = next_phandle++;
+ phandles[phandle] = ret;
+ }
+
+ return ret;
+}
--
2.9.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox