Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] KVM: arm/arm64: timer: Fix hw sync for user space irqchip path
From: Alexander Graf @ 2016-09-16  5:16 UTC (permalink / raw)
  To: linux-arm-kernel

While adding the new vgic implementation, apparently nobody tested
the non-vgic path where user space controls the vgic, so two functions
slipped through the cracks that get called in generic code but don't
check whether hardware support is enabled.

This patch guards them with proper checks to ensure we only try to
use vgic data structures if they are available. Without this, I get
a stack trace:

[   74.363037] Unable to handle kernel paging request at virtual address ffffffffffffffe8
[...]
[   74.929654] [<ffff000008824bcc>] _raw_spin_lock+0x1c/0x58
[   74.935133] [<ffff0000080b7f20>] kvm_vgic_flush_hwstate+0x88/0x288
[   74.941406] [<ffff0000080ab0b4>] kvm_arch_vcpu_ioctl_run+0xfc/0x630
[   74.947766] [<ffff0000080a15bc>] kvm_vcpu_ioctl+0x2f4/0x710
[   74.953420] [<ffff0000082788a8>] do_vfs_ioctl+0xb0/0x728
[   74.958807] [<ffff000008278fb4>] SyS_ioctl+0x94/0xa8
[   74.963844] [<ffff000008083744>] el0_svc_naked+0x38/0x3c

Fixes: 0919e84c0
Cc: stable at vger.kernel.org
Signed-off-by: Alexander Graf <agraf@suse.de>
---
 virt/kvm/arm/vgic/vgic.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index e83b7fe..9f312ba 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -645,6 +645,9 @@ next:
 /* Sync back the hardware VGIC state into our emulation after a guest's run. */
 void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
 {
+	if (!vcpu->kvm->arch.vgic.enabled)
+		return;
+
 	vgic_process_maintenance_interrupt(vcpu);
 	vgic_fold_lr_state(vcpu);
 	vgic_prune_ap_list(vcpu);
@@ -653,6 +656,9 @@ void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
 /* Flush our emulation state into the GIC hardware before entering the guest. */
 void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
 {
+	if (!vcpu->kvm->arch.vgic.enabled)
+		return;
+
 	spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
 	vgic_flush_lr_state(vcpu);
 	spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
-- 
2.6.6

^ permalink raw reply related

* [PATCH v2] KVM: arm/arm64: Route vtimer events to user space
From: Alexander Graf @ 2016-09-16  5:09 UTC (permalink / raw)
  To: linux-arm-kernel

We have 2 modes for dealing with interrupts in the ARM world. We can either
handle them all using hardware acceleration through the vgic or we can emulate
a gic in user space and only drive CPU IRQ pins from there.

Unfortunately, when driving IRQs from user space, we never tell user space
about timer events that may result in interrupt line state changes, so we
lose out on timer events if we run with user space gic emulation.

This patch set fixes that by routing vtimer expiration events to user space.
With this patch I can successfully run edk2 and Linux with user space gic
emulation.

Signed-off-by: Alexander Graf <agraf@suse.de>

---

A branch with WIP QEMU code can be found here:

  https://github.com/agraf/qemu.git no-kvm-irqchip

v1 -> v2:

  - Add back curly brace that got lost (and is very stubborn, sorry for
    the resubmit to actually add it back for real)
---
 Documentation/virtual/kvm/api.txt |  28 ++++++++-
 arch/arm/include/asm/kvm_host.h   |   3 +
 arch/arm/kvm/arm.c                |  47 +++++++++++---
 arch/arm64/include/asm/kvm_host.h |   3 +
 include/uapi/linux/kvm.h          |  14 +++++
 virt/kvm/arm/arch_timer.c         | 126 ++++++++++++++++++++++++++++----------
 6 files changed, 178 insertions(+), 43 deletions(-)

diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 739db9a..6a64c53 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -997,7 +997,9 @@ documentation when it pops into existence).
 
 Capability: KVM_CAP_ENABLE_CAP, KVM_CAP_ENABLE_CAP_VM
 Architectures: x86 (only KVM_CAP_ENABLE_CAP_VM),
-	       mips (only KVM_CAP_ENABLE_CAP), ppc, s390
+	       mips (only KVM_CAP_ENABLE_CAP), ppc, s390,
+	       arm (only KVM_CAP_ENABLE_CAP),
+	       arm64 (only only KVM_CAP_ENABLE_CAP)
 Type: vcpu ioctl, vm ioctl (with KVM_CAP_ENABLE_CAP_VM)
 Parameters: struct kvm_enable_cap (in)
 Returns: 0 on success; -1 on error
@@ -3200,8 +3202,10 @@ struct kvm_run {
 	/* in */
 	__u8 request_interrupt_window;
 
-Request that KVM_RUN return when it becomes possible to inject external
+[x86] Request that KVM_RUN return when it becomes possible to inject external
 interrupts into the guest.  Useful in conjunction with KVM_INTERRUPT.
+[arm*] Bits set to 1 in here mask IRQ lines that would otherwise potentially
+trigger forever. Useful with KVM_CAP_ARM_TIMER.
 
 	__u8 padding1[7];
 
@@ -3517,6 +3521,16 @@ Hyper-V SynIC state change. Notification is used to remap SynIC
 event/message pages and to enable/disable SynIC messages/events processing
 in userspace.
 
+		/* KVM_EXIT_ARM_TIMER */
+		struct {
+			__u8 timesource;
+		} arm_timer;
+
+Indicates that a timer triggered that user space needs to handle and
+potentially mask with vcpu->run->request_interrupt_window to allow the
+guest to proceed. This only happens for timers that got enabled through
+KVM_CAP_ARM_TIMER.
+
 		/* Fix the size of the union. */
 		char padding[256];
 	};
@@ -3737,6 +3751,16 @@ Once this is done the KVM_REG_MIPS_VEC_* and KVM_REG_MIPS_MSA_* registers can be
 accessed, and the Config5.MSAEn bit is accessible via the KVM API and also from
 the guest.
 
+6.11 KVM_CAP_ARM_TIMER
+
+Architectures: arm, arm64
+Target: vcpu
+Parameters: args[0] contains a bitmap of timers to enable
+
+This capability allows to route per-core timers into user space. When it's
+enabled, the enabled timers trigger KVM_EXIT_ARM_TIMER guest exits when they
+are pending, unless masked by vcpu->run->request_interrupt_window.
+
 7. Capabilities that can be enabled on VMs
 ------------------------------------------
 
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index de338d9..77d1f73 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -180,6 +180,9 @@ struct kvm_vcpu_arch {
 
 	/* Detect first run of a vcpu */
 	bool has_run_once;
+
+	/* User space wants timer notifications */
+	bool user_space_arm_timers;
 };
 
 struct kvm_vm_stat {
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 75f130e..57bdb71 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -187,6 +187,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 	case KVM_CAP_ARM_PSCI_0_2:
 	case KVM_CAP_READONLY_MEM:
 	case KVM_CAP_MP_STATE:
+	case KVM_CAP_ARM_TIMER:
 		r = 1;
 		break;
 	case KVM_CAP_COALESCED_MMIO:
@@ -474,13 +475,7 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
 			return ret;
 	}
 
-	/*
-	 * Enable the arch timers only if we have an in-kernel VGIC
-	 * and it has been properly initialized, since we cannot handle
-	 * interrupts from the virtual timer with a userspace gic.
-	 */
-	if (irqchip_in_kernel(kvm) && vgic_initialized(kvm))
-		ret = kvm_timer_enable(vcpu);
+	ret = kvm_timer_enable(vcpu);
 
 	return ret;
 }
@@ -601,6 +596,13 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
 			run->exit_reason = KVM_EXIT_INTR;
 		}
 
+		if (kvm_check_request(KVM_REQ_PENDING_TIMER, vcpu)) {
+			/* Tell user space about the pending vtimer */
+			ret = 0;
+			run->exit_reason = KVM_EXIT_ARM_TIMER;
+			run->arm_timer.timesource = KVM_ARM_TIMER_VTIMER;
+		}
+
 		if (ret <= 0 || need_new_vmid_gen(vcpu->kvm) ||
 			vcpu->arch.power_off || vcpu->arch.pause) {
 			local_irq_enable();
@@ -878,6 +880,29 @@ static int kvm_arm_vcpu_has_attr(struct kvm_vcpu *vcpu,
 	return ret;
 }
 
+static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
+				     struct kvm_enable_cap *cap)
+{
+	int r;
+
+	if (cap->flags)
+		return -EINVAL;
+
+	switch (cap->cap) {
+	case KVM_CAP_ARM_TIMER:
+		r = 0;
+		if (cap->args[0] != KVM_ARM_TIMER_VTIMER)
+			return -EINVAL;
+		vcpu->arch.user_space_arm_timers = true;
+		break;
+	default:
+		r = -EINVAL;
+		break;
+	}
+
+	return r;
+}
+
 long kvm_arch_vcpu_ioctl(struct file *filp,
 			 unsigned int ioctl, unsigned long arg)
 {
@@ -941,6 +966,14 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
 			return -EFAULT;
 		return kvm_arm_vcpu_has_attr(vcpu, &attr);
 	}
+	case KVM_ENABLE_CAP:
+	{
+		struct kvm_enable_cap cap;
+
+		if (copy_from_user(&cap, argp, sizeof(cap)))
+			return -EFAULT;
+		return kvm_vcpu_ioctl_enable_cap(vcpu, &cap);
+	}
 	default:
 		return -EINVAL;
 	}
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 3eda975..3d01481 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -270,6 +270,9 @@ struct kvm_vcpu_arch {
 
 	/* Detect first run of a vcpu */
 	bool has_run_once;
+
+	/* User space wants timer notifications */
+	bool user_space_arm_timers;
 };
 
 #define vcpu_gp_regs(v)		(&(v)->arch.ctxt.gp_regs)
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 300ef25..00f4948 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -205,6 +205,7 @@ struct kvm_hyperv_exit {
 #define KVM_EXIT_S390_STSI        25
 #define KVM_EXIT_IOAPIC_EOI       26
 #define KVM_EXIT_HYPERV           27
+#define KVM_EXIT_ARM_TIMER        28
 
 /* For KVM_EXIT_INTERNAL_ERROR */
 /* Emulate instruction failed. */
@@ -361,6 +362,10 @@ struct kvm_run {
 		} eoi;
 		/* KVM_EXIT_HYPERV */
 		struct kvm_hyperv_exit hyperv;
+		/* KVM_EXIT_ARM_TIMER */
+		struct {
+			__u8 timesource;
+		} arm_timer;
 		/* Fix the size of the union. */
 		char padding[256];
 	};
@@ -870,6 +875,7 @@ struct kvm_ppc_smmu_info {
 #define KVM_CAP_S390_USER_INSTR0 130
 #define KVM_CAP_MSI_DEVID 131
 #define KVM_CAP_PPC_HTM 132
+#define KVM_CAP_ARM_TIMER 133
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1327,4 +1333,12 @@ struct kvm_assigned_msix_entry {
 #define KVM_X2APIC_API_USE_32BIT_IDS            (1ULL << 0)
 #define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK  (1ULL << 1)
 
+/* Available with KVM_CAP_ARM_TIMER */
+
+/* Bits for run->request_interrupt_window */
+#define KVM_IRQWINDOW_VTIMER		(1 << 0)
+
+/* Bits for run->arm_timer.timesource */
+#define KVM_ARM_TIMER_VTIMER		(1 << 0)
+
 #endif /* __LINUX_KVM_H */
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 4309b60..d0e999d 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -24,6 +24,7 @@
 
 #include <clocksource/arm_arch_timer.h>
 #include <asm/arch_timer.h>
+#include <asm/kvm_emulate.h>
 
 #include <kvm/arm_vgic.h>
 #include <kvm/arm_arch_timer.h>
@@ -170,16 +171,45 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level)
 {
 	int ret;
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+	struct kvm_run *run = vcpu->run;
 
-	BUG_ON(!vgic_initialized(vcpu->kvm));
+	BUG_ON(irqchip_in_kernel(vcpu->kvm) && !vgic_initialized(vcpu->kvm));
 
 	timer->active_cleared_last = false;
 	timer->irq.level = new_level;
-	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->irq.irq,
+	trace_kvm_timer_update_irq(vcpu->vcpu_id, host_vtimer_irq,
 				   timer->irq.level);
-	ret = kvm_vgic_inject_mapped_irq(vcpu->kvm, vcpu->vcpu_id,
-					 timer->irq.irq,
-					 timer->irq.level);
+
+	if (irqchip_in_kernel(vcpu->kvm) && vgic_initialized(vcpu->kvm)) {
+		/* Fire the timer in the VGIC */
+
+		ret = kvm_vgic_inject_mapped_irq(vcpu->kvm, vcpu->vcpu_id,
+						 timer->irq.irq,
+						 timer->irq.level);
+	} else if (!vcpu->arch.user_space_arm_timers) {
+		/* User space has not activated timer use */
+		ret = 0;
+	} else {
+		/*
+		 * Set PENDING_TIMER so that user space can handle the event if
+		 *
+		 *   1) Level is high
+		 *   2) The vtimer is not suppressed by user space
+		 *   3) We are not in the timer trigger exit path
+		 */
+		if (new_level &&
+		    !(run->request_interrupt_window & KVM_IRQWINDOW_VTIMER) &&
+		    (run->exit_reason != KVM_EXIT_ARM_TIMER)) {
+			/* KVM_REQ_PENDING_TIMER means vtimer triggered */
+			kvm_make_request(KVM_REQ_PENDING_TIMER, vcpu);
+		}
+
+		/* Force a new level high check on next entry */
+		timer->irq.level = 0;
+
+		ret = 0;
+	}
+
 	WARN_ON(ret);
 }
 
@@ -197,7 +227,8 @@ static int kvm_timer_update_state(struct kvm_vcpu *vcpu)
 	 * because the guest would never see the interrupt.  Instead wait
 	 * until we call this function from kvm_timer_flush_hwstate.
 	 */
-	if (!vgic_initialized(vcpu->kvm) || !timer->enabled)
+	if ((irqchip_in_kernel(vcpu->kvm) && !vgic_initialized(vcpu->kvm)) ||
+	    !timer->enabled)
 		return -ENODEV;
 
 	if (kvm_timer_should_fire(vcpu) != timer->irq.level)
@@ -275,35 +306,57 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
 	* to ensure that hardware interrupts from the timer triggers a guest
 	* exit.
 	*/
-	phys_active = timer->irq.level ||
-			kvm_vgic_map_is_active(vcpu, timer->irq.irq);
-
-	/*
-	 * We want to avoid hitting the (re)distributor as much as
-	 * possible, as this is a potentially expensive MMIO access
-	 * (not to mention locks in the irq layer), and a solution for
-	 * this is to cache the "active" state in memory.
-	 *
-	 * Things to consider: we cannot cache an "active set" state,
-	 * because the HW can change this behind our back (it becomes
-	 * "clear" in the HW). We must then restrict the caching to
-	 * the "clear" state.
-	 *
-	 * The cache is invalidated on:
-	 * - vcpu put, indicating that the HW cannot be trusted to be
-	 *   in a sane state on the next vcpu load,
-	 * - any change in the interrupt state
-	 *
-	 * Usage conditions:
-	 * - cached value is "active clear"
-	 * - value to be programmed is "active clear"
-	 */
-	if (timer->active_cleared_last && !phys_active)
-		return;
+	if (irqchip_in_kernel(vcpu->kvm) && vgic_initialized(vcpu->kvm)) {
+		phys_active = timer->irq.level ||
+				kvm_vgic_map_is_active(vcpu, timer->irq.irq);
+
+		/*
+		 * We want to avoid hitting the (re)distributor as much as
+		 * possible, as this is a potentially expensive MMIO access
+		 * (not to mention locks in the irq layer), and a solution for
+		 * this is to cache the "active" state in memory.
+		 *
+		 * Things to consider: we cannot cache an "active set" state,
+		 * because the HW can change this behind our back (it becomes
+		 * "clear" in the HW). We must then restrict the caching to
+		 * the "clear" state.
+		 *
+		 * The cache is invalidated on:
+		 * - vcpu put, indicating that the HW cannot be trusted to be
+		 *   in a sane state on the next vcpu load,
+		 * - any change in the interrupt state
+		 *
+		 * Usage conditions:
+		 * - cached value is "active clear"
+		 * - value to be programmed is "active clear"
+		 */
+		if (timer->active_cleared_last && !phys_active)
+			return;
+
+		ret = irq_set_irqchip_state(host_vtimer_irq,
+					    IRQCHIP_STATE_ACTIVE,
+					    phys_active);
+	} else {
+		/* User space tells us whether the timer is in active mode */
+		phys_active = vcpu->run->request_interrupt_window &
+			      KVM_IRQWINDOW_VTIMER;
+
+		/* However if the line is high, we exit anyway, so we want
+		 * to keep the IRQ masked */
+		phys_active = phys_active || timer->irq.level;
+
+		/*
+		 * So we can just explicitly mask or unmask the IRQ, gaining
+		 * more compatibility with oddball irq controllers.
+		 */
+		if (phys_active)
+			disable_percpu_irq(host_vtimer_irq);
+		else
+			enable_percpu_irq(host_vtimer_irq, 0);
+
+		ret = 0;
+	}
 
-	ret = irq_set_irqchip_state(host_vtimer_irq,
-				    IRQCHIP_STATE_ACTIVE,
-				    phys_active);
 	WARN_ON(ret);
 
 	timer->active_cleared_last = !phys_active;
@@ -479,6 +532,10 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
 	if (timer->enabled)
 		return 0;
 
+	/* No need to route physical IRQs when we don't use the vgic */
+	if (!irqchip_in_kernel(vcpu->kvm))
+		goto no_vgic;
+
 	/*
 	 * Find the physical IRQ number corresponding to the host_vtimer_irq
 	 */
@@ -502,6 +559,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
 	if (ret)
 		return ret;
 
+no_vgic:
 
 	/*
 	 * There is a potential race here between VCPUs starting for the first
-- 
2.6.6

^ permalink raw reply related

* [PATCH v2] KVM: arm/arm64: Route vtimer events to user space
From: Alexander Graf @ 2016-09-16  5:06 UTC (permalink / raw)
  To: linux-arm-kernel

We have 2 modes for dealing with interrupts in the ARM world. We can either
handle them all using hardware acceleration through the vgic or we can emulate
a gic in user space and only drive CPU IRQ pins from there.

Unfortunately, when driving IRQs from user space, we never tell user space
about timer events that may result in interrupt line state changes, so we
lose out on timer events if we run with user space gic emulation.

This patch set fixes that by routing vtimer expiration events to user space.
With this patch I can successfully run edk2 and Linux with user space gic
emulation.

Signed-off-by: Alexander Graf <agraf@suse.de>

---

A branch with WIP QEMU code can be found here:

  https://github.com/agraf/qemu.git no-kvm-irqchip

v1 -> v2:

  - Add back curly brace that got lost
---
 Documentation/virtual/kvm/api.txt |  28 ++++++++-
 arch/arm/include/asm/kvm_host.h   |   3 +
 arch/arm/kvm/arm.c                |  46 +++++++++++---
 arch/arm64/include/asm/kvm_host.h |   3 +
 include/uapi/linux/kvm.h          |  14 +++++
 virt/kvm/arm/arch_timer.c         | 126 ++++++++++++++++++++++++++++----------
 6 files changed, 177 insertions(+), 43 deletions(-)

diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 739db9a..6a64c53 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -997,7 +997,9 @@ documentation when it pops into existence).
 
 Capability: KVM_CAP_ENABLE_CAP, KVM_CAP_ENABLE_CAP_VM
 Architectures: x86 (only KVM_CAP_ENABLE_CAP_VM),
-	       mips (only KVM_CAP_ENABLE_CAP), ppc, s390
+	       mips (only KVM_CAP_ENABLE_CAP), ppc, s390,
+	       arm (only KVM_CAP_ENABLE_CAP),
+	       arm64 (only only KVM_CAP_ENABLE_CAP)
 Type: vcpu ioctl, vm ioctl (with KVM_CAP_ENABLE_CAP_VM)
 Parameters: struct kvm_enable_cap (in)
 Returns: 0 on success; -1 on error
@@ -3200,8 +3202,10 @@ struct kvm_run {
 	/* in */
 	__u8 request_interrupt_window;
 
-Request that KVM_RUN return when it becomes possible to inject external
+[x86] Request that KVM_RUN return when it becomes possible to inject external
 interrupts into the guest.  Useful in conjunction with KVM_INTERRUPT.
+[arm*] Bits set to 1 in here mask IRQ lines that would otherwise potentially
+trigger forever. Useful with KVM_CAP_ARM_TIMER.
 
 	__u8 padding1[7];
 
@@ -3517,6 +3521,16 @@ Hyper-V SynIC state change. Notification is used to remap SynIC
 event/message pages and to enable/disable SynIC messages/events processing
 in userspace.
 
+		/* KVM_EXIT_ARM_TIMER */
+		struct {
+			__u8 timesource;
+		} arm_timer;
+
+Indicates that a timer triggered that user space needs to handle and
+potentially mask with vcpu->run->request_interrupt_window to allow the
+guest to proceed. This only happens for timers that got enabled through
+KVM_CAP_ARM_TIMER.
+
 		/* Fix the size of the union. */
 		char padding[256];
 	};
@@ -3737,6 +3751,16 @@ Once this is done the KVM_REG_MIPS_VEC_* and KVM_REG_MIPS_MSA_* registers can be
 accessed, and the Config5.MSAEn bit is accessible via the KVM API and also from
 the guest.
 
+6.11 KVM_CAP_ARM_TIMER
+
+Architectures: arm, arm64
+Target: vcpu
+Parameters: args[0] contains a bitmap of timers to enable
+
+This capability allows to route per-core timers into user space. When it's
+enabled, the enabled timers trigger KVM_EXIT_ARM_TIMER guest exits when they
+are pending, unless masked by vcpu->run->request_interrupt_window.
+
 7. Capabilities that can be enabled on VMs
 ------------------------------------------
 
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index de338d9..77d1f73 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -180,6 +180,9 @@ struct kvm_vcpu_arch {
 
 	/* Detect first run of a vcpu */
 	bool has_run_once;
+
+	/* User space wants timer notifications */
+	bool user_space_arm_timers;
 };
 
 struct kvm_vm_stat {
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 75f130e..1b4b9a6 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -187,6 +187,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 	case KVM_CAP_ARM_PSCI_0_2:
 	case KVM_CAP_READONLY_MEM:
 	case KVM_CAP_MP_STATE:
+	case KVM_CAP_ARM_TIMER:
 		r = 1;
 		break;
 	case KVM_CAP_COALESCED_MMIO:
@@ -474,13 +475,7 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
 			return ret;
 	}
 
-	/*
-	 * Enable the arch timers only if we have an in-kernel VGIC
-	 * and it has been properly initialized, since we cannot handle
-	 * interrupts from the virtual timer with a userspace gic.
-	 */
-	if (irqchip_in_kernel(kvm) && vgic_initialized(kvm))
-		ret = kvm_timer_enable(vcpu);
+	ret = kvm_timer_enable(vcpu);
 
 	return ret;
 }
@@ -601,6 +596,13 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
 			run->exit_reason = KVM_EXIT_INTR;
 		}
 
+		if (kvm_check_request(KVM_REQ_PENDING_TIMER, vcpu)) {
+			/* Tell user space about the pending vtimer */
+			ret = 0;
+			run->exit_reason = KVM_EXIT_ARM_TIMER;
+			run->arm_timer.timesource = KVM_ARM_TIMER_VTIMER;
+		}
+
 		if (ret <= 0 || need_new_vmid_gen(vcpu->kvm) ||
 			vcpu->arch.power_off || vcpu->arch.pause) {
 			local_irq_enable();
@@ -878,6 +880,29 @@ static int kvm_arm_vcpu_has_attr(struct kvm_vcpu *vcpu,
 	return ret;
 }
 
+static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
+				     struct kvm_enable_cap *cap)
+{
+	int r;
+
+	if (cap->flags)
+		return -EINVAL;
+
+	switch (cap->cap) {
+	case KVM_CAP_ARM_TIMER:
+		r = 0;
+		if (cap->args[0] != KVM_ARM_TIMER_VTIMER)
+			return -EINVAL;
+		vcpu->arch.user_space_arm_timers = true;
+		break;
+	default:
+		r = -EINVAL;
+		break;
+	}
+
+	return r;
+}
+
 long kvm_arch_vcpu_ioctl(struct file *filp,
 			 unsigned int ioctl, unsigned long arg)
 {
@@ -940,6 +965,13 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
 		if (copy_from_user(&attr, argp, sizeof(attr)))
 			return -EFAULT;
 		return kvm_arm_vcpu_has_attr(vcpu, &attr);
+	case KVM_ENABLE_CAP:
+	{
+		struct kvm_enable_cap cap;
+
+		if (copy_from_user(&cap, argp, sizeof(cap)))
+			return -EFAULT;
+		return kvm_vcpu_ioctl_enable_cap(vcpu, &cap);
 	}
 	default:
 		return -EINVAL;
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 3eda975..3d01481 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -270,6 +270,9 @@ struct kvm_vcpu_arch {
 
 	/* Detect first run of a vcpu */
 	bool has_run_once;
+
+	/* User space wants timer notifications */
+	bool user_space_arm_timers;
 };
 
 #define vcpu_gp_regs(v)		(&(v)->arch.ctxt.gp_regs)
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 300ef25..00f4948 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -205,6 +205,7 @@ struct kvm_hyperv_exit {
 #define KVM_EXIT_S390_STSI        25
 #define KVM_EXIT_IOAPIC_EOI       26
 #define KVM_EXIT_HYPERV           27
+#define KVM_EXIT_ARM_TIMER        28
 
 /* For KVM_EXIT_INTERNAL_ERROR */
 /* Emulate instruction failed. */
@@ -361,6 +362,10 @@ struct kvm_run {
 		} eoi;
 		/* KVM_EXIT_HYPERV */
 		struct kvm_hyperv_exit hyperv;
+		/* KVM_EXIT_ARM_TIMER */
+		struct {
+			__u8 timesource;
+		} arm_timer;
 		/* Fix the size of the union. */
 		char padding[256];
 	};
@@ -870,6 +875,7 @@ struct kvm_ppc_smmu_info {
 #define KVM_CAP_S390_USER_INSTR0 130
 #define KVM_CAP_MSI_DEVID 131
 #define KVM_CAP_PPC_HTM 132
+#define KVM_CAP_ARM_TIMER 133
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1327,4 +1333,12 @@ struct kvm_assigned_msix_entry {
 #define KVM_X2APIC_API_USE_32BIT_IDS            (1ULL << 0)
 #define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK  (1ULL << 1)
 
+/* Available with KVM_CAP_ARM_TIMER */
+
+/* Bits for run->request_interrupt_window */
+#define KVM_IRQWINDOW_VTIMER		(1 << 0)
+
+/* Bits for run->arm_timer.timesource */
+#define KVM_ARM_TIMER_VTIMER		(1 << 0)
+
 #endif /* __LINUX_KVM_H */
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 4309b60..d0e999d 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -24,6 +24,7 @@
 
 #include <clocksource/arm_arch_timer.h>
 #include <asm/arch_timer.h>
+#include <asm/kvm_emulate.h>
 
 #include <kvm/arm_vgic.h>
 #include <kvm/arm_arch_timer.h>
@@ -170,16 +171,45 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level)
 {
 	int ret;
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+	struct kvm_run *run = vcpu->run;
 
-	BUG_ON(!vgic_initialized(vcpu->kvm));
+	BUG_ON(irqchip_in_kernel(vcpu->kvm) && !vgic_initialized(vcpu->kvm));
 
 	timer->active_cleared_last = false;
 	timer->irq.level = new_level;
-	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->irq.irq,
+	trace_kvm_timer_update_irq(vcpu->vcpu_id, host_vtimer_irq,
 				   timer->irq.level);
-	ret = kvm_vgic_inject_mapped_irq(vcpu->kvm, vcpu->vcpu_id,
-					 timer->irq.irq,
-					 timer->irq.level);
+
+	if (irqchip_in_kernel(vcpu->kvm) && vgic_initialized(vcpu->kvm)) {
+		/* Fire the timer in the VGIC */
+
+		ret = kvm_vgic_inject_mapped_irq(vcpu->kvm, vcpu->vcpu_id,
+						 timer->irq.irq,
+						 timer->irq.level);
+	} else if (!vcpu->arch.user_space_arm_timers) {
+		/* User space has not activated timer use */
+		ret = 0;
+	} else {
+		/*
+		 * Set PENDING_TIMER so that user space can handle the event if
+		 *
+		 *   1) Level is high
+		 *   2) The vtimer is not suppressed by user space
+		 *   3) We are not in the timer trigger exit path
+		 */
+		if (new_level &&
+		    !(run->request_interrupt_window & KVM_IRQWINDOW_VTIMER) &&
+		    (run->exit_reason != KVM_EXIT_ARM_TIMER)) {
+			/* KVM_REQ_PENDING_TIMER means vtimer triggered */
+			kvm_make_request(KVM_REQ_PENDING_TIMER, vcpu);
+		}
+
+		/* Force a new level high check on next entry */
+		timer->irq.level = 0;
+
+		ret = 0;
+	}
+
 	WARN_ON(ret);
 }
 
@@ -197,7 +227,8 @@ static int kvm_timer_update_state(struct kvm_vcpu *vcpu)
 	 * because the guest would never see the interrupt.  Instead wait
 	 * until we call this function from kvm_timer_flush_hwstate.
 	 */
-	if (!vgic_initialized(vcpu->kvm) || !timer->enabled)
+	if ((irqchip_in_kernel(vcpu->kvm) && !vgic_initialized(vcpu->kvm)) ||
+	    !timer->enabled)
 		return -ENODEV;
 
 	if (kvm_timer_should_fire(vcpu) != timer->irq.level)
@@ -275,35 +306,57 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
 	* to ensure that hardware interrupts from the timer triggers a guest
 	* exit.
 	*/
-	phys_active = timer->irq.level ||
-			kvm_vgic_map_is_active(vcpu, timer->irq.irq);
-
-	/*
-	 * We want to avoid hitting the (re)distributor as much as
-	 * possible, as this is a potentially expensive MMIO access
-	 * (not to mention locks in the irq layer), and a solution for
-	 * this is to cache the "active" state in memory.
-	 *
-	 * Things to consider: we cannot cache an "active set" state,
-	 * because the HW can change this behind our back (it becomes
-	 * "clear" in the HW). We must then restrict the caching to
-	 * the "clear" state.
-	 *
-	 * The cache is invalidated on:
-	 * - vcpu put, indicating that the HW cannot be trusted to be
-	 *   in a sane state on the next vcpu load,
-	 * - any change in the interrupt state
-	 *
-	 * Usage conditions:
-	 * - cached value is "active clear"
-	 * - value to be programmed is "active clear"
-	 */
-	if (timer->active_cleared_last && !phys_active)
-		return;
+	if (irqchip_in_kernel(vcpu->kvm) && vgic_initialized(vcpu->kvm)) {
+		phys_active = timer->irq.level ||
+				kvm_vgic_map_is_active(vcpu, timer->irq.irq);
+
+		/*
+		 * We want to avoid hitting the (re)distributor as much as
+		 * possible, as this is a potentially expensive MMIO access
+		 * (not to mention locks in the irq layer), and a solution for
+		 * this is to cache the "active" state in memory.
+		 *
+		 * Things to consider: we cannot cache an "active set" state,
+		 * because the HW can change this behind our back (it becomes
+		 * "clear" in the HW). We must then restrict the caching to
+		 * the "clear" state.
+		 *
+		 * The cache is invalidated on:
+		 * - vcpu put, indicating that the HW cannot be trusted to be
+		 *   in a sane state on the next vcpu load,
+		 * - any change in the interrupt state
+		 *
+		 * Usage conditions:
+		 * - cached value is "active clear"
+		 * - value to be programmed is "active clear"
+		 */
+		if (timer->active_cleared_last && !phys_active)
+			return;
+
+		ret = irq_set_irqchip_state(host_vtimer_irq,
+					    IRQCHIP_STATE_ACTIVE,
+					    phys_active);
+	} else {
+		/* User space tells us whether the timer is in active mode */
+		phys_active = vcpu->run->request_interrupt_window &
+			      KVM_IRQWINDOW_VTIMER;
+
+		/* However if the line is high, we exit anyway, so we want
+		 * to keep the IRQ masked */
+		phys_active = phys_active || timer->irq.level;
+
+		/*
+		 * So we can just explicitly mask or unmask the IRQ, gaining
+		 * more compatibility with oddball irq controllers.
+		 */
+		if (phys_active)
+			disable_percpu_irq(host_vtimer_irq);
+		else
+			enable_percpu_irq(host_vtimer_irq, 0);
+
+		ret = 0;
+	}
 
-	ret = irq_set_irqchip_state(host_vtimer_irq,
-				    IRQCHIP_STATE_ACTIVE,
-				    phys_active);
 	WARN_ON(ret);
 
 	timer->active_cleared_last = !phys_active;
@@ -479,6 +532,10 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
 	if (timer->enabled)
 		return 0;
 
+	/* No need to route physical IRQs when we don't use the vgic */
+	if (!irqchip_in_kernel(vcpu->kvm))
+		goto no_vgic;
+
 	/*
 	 * Find the physical IRQ number corresponding to the host_vtimer_irq
 	 */
@@ -502,6 +559,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
 	if (ret)
 		return ret;
 
+no_vgic:
 
 	/*
 	 * There is a potential race here between VCPUs starting for the first
-- 
2.6.6

^ permalink raw reply related

* [RESEND PATCH] arm64: kgdb: fix single stepping
From: AKASHI Takahiro @ 2016-09-16  4:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <0ea7dfad-e25d-2919-2d03-17b850d7ba91@windriver.com>

Hi Jason,

Welcome back to mainline development.
I've been looking forward to your comments.

On Thu, Sep 15, 2016 at 08:04:57AM -0500, Jason Wessel wrote:
> On 04/20/2015 08:13 PM, AKASHI Takahiro wrote:
> >Jason,
> >
> >Could you please review my patch below?
> >See also arm64 maintainer's comment:
> >http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/313712.html
> >
> >Thanks,
> >-Takahiro AKASHI
> >
> >I tried to verify kgdb in vanilla kernel on fast model, but it seems that
> >the single stepping with kgdb doesn't work correctly since its first
> >appearance at v3.15.
> >
> >On v3.15, 'stepi' command after breaking the kernel at some breakpoint
> >steps forward to the next instruction, but the succeeding 'stepi' never
> >goes beyond that.
> >On v3.16, 'stepi' moves forward and stops at the next instruction just
> >after enable_dbg in el1_dbg, and never goes beyond that. This variance of
> >behavior seems to come in with the following patch in v3.16:
> >
> >    commit 2a2830703a23 ("arm64: debug: avoid accessing mdscr_el1 on fault
> >    paths where possible")
> >
> >This patch
> >(1) moves kgdb_disable_single_step() from 'c' command handling to single
> >    step handler.
> >    This makes sure that single stepping gets effective at every 's' command.
> >    Please note that, under the current implementation, single step bit in
> >    spsr, which is cleared by the first single stepping, will not be set
> >    again for the consecutive 's' commands because single step bit in mdscr
> >    is still kept on (that is, kernel_active_single_step() in
> >    kgdb_arch_handle_exception() is true).
> >(2) re-implements kgdb_roundup_cpus() because the current implementation
> >    enabled interrupts naively. See below.
> >(3) removes 'enable_dbg' in el1_dbg.
> >    Single step bit in mdscr is turned on in do_handle_exception()->
> >    kgdb_handle_expection() before returning to debugged context, and if
> >    debug exception is enabled in el1_dbg, we will see unexpected single-
> >    stepping in el1_dbg.
> >    Since v3.18, the following patch does the same:
> >      commit 1059c6bf8534 ("arm64: debug: don't re-enable debug exceptions
> >      on return from el1_dbg)
> >(4) masks interrupts while single-stepping one instruction.
> >    If an interrupt is caught during processing a single-stepping, debug
> >    exception is unintentionally enabled by el1_irq's 'enable_dbg' before
> >    returning to debugged context.
> >    Thus, like in (2), we will see unexpected single-stepping in el1_irq.
> >
> >Basically (1) and (2) are for v3.15, (3) and (4) for v3.1[67].
> >
> >@@ -176,18 +183,14 @@ int kgdb_arch_handle_exception(int exception_vector, int signo,
> > 		 * over and over again.
> > 		 */
> > 		kgdb_arch_update_addr(linux_regs, remcom_in_buffer);
> >-		atomic_set(&kgdb_cpu_doing_single_step, -1);
> >-		kgdb_single_step =  0;
> 
> 
> This is a subtle change, but I assume it is what you intended?  All the CPUs will get released into the run state when exiting the kgdb exception handler.

You are talking about "- kgdb_single_step = 0." Right?
Do you think that there is any (negative) side effect of this change?
Since most of architectures, including x86, don't handle this variable
explicitly, I didn't expect that it was essential.

> 
> >-
> >-		/*
> >-		 * Received continue command, disable single step
> >-		 */
> >-		if (kernel_active_single_step())
> >-			kernel_disable_single_step();
> >
> 
> 
> I see why this is not needed above any more given that you have a function that cleans up the state on entry to the kgdb exception handler.

Yeah, the point here is that, on arm64, we need to set SS (Software step)
bit in SPSR as well as MDSCR before returning from the exception handler
in order to enable a hardware single step according to ARM ARM D2.12
("Software Step exceptions").
So it might be good enough just to call kernel_enable_single_step()
at 's' command unconditionally instead of "if (!kernel_active_single_step)".
(Please note that, as I mentioned in the commit message, SPSR.SS bit will
be cleared while MDSCR.SS bit is kept on after a hardware single step.)

But anyhow, I believe that the hunk above is redundant in my implementation.

> The rest of the patch is fine.

Thank you.

> I added the patch to kgdb-next after fixing up the context since it no longer applied to the mainline ( https://git.kernel.org/cgit/linux/kernel/git/jwessel/kgdb.git/log/?h=kgdb-next).  If there is further discussion on the point above, another patch can be added, but it I am assuming this is the way you desire it to work as there are some other architectures that use the same behaviour.  I do not presently have any ARM64 hardware to validate this particular change.
> 
> I also added to the patch a "Cc: linux-stable <stable@vger.kernel.org>" so we can have this appear on some of the older kernels.

Since Will asked me to split this patch into a few, I need some reworks
to clarify which hunks in the patch are necessary for which version of kernel.

Thanks,
-Takahiro AKASHI

> 
> Thanks,
> Jason.
> 

^ permalink raw reply

* [PATCH v26 2/7] arm64: kdump: implement machine_crash_shutdown()
From: AKASHI Takahiro @ 2016-09-16  3:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <57D9925D.5000508@arm.com>

James,

Thank you for your review.

On Wed, Sep 14, 2016 at 07:09:33PM +0100, James Morse wrote:
> Hi Akashi,
> 
> (CC: Marc who knows how this irqchip wizardry works
>  Cover letter: https://www.spinics.net/lists/arm-kernel/msg529520.html )
> 
> On 07/09/16 05:29, AKASHI Takahiro wrote:
> > Primary kernel calls machine_crash_shutdown() to shut down non-boot cpus
> > and save registers' status in per-cpu ELF notes before starting crash
> > dump kernel. See kernel_kexec().
> > Even if not all secondary cpus have shut down, we do kdump anyway.
> > 
> > As we don't have to make non-boot(crashed) cpus offline (to preserve
> > correct status of cpus at crash dump) before shutting down, this patch
> > also adds a variant of smp_send_stop().
> > 
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > ---
> >  arch/arm64/include/asm/hardirq.h  |  2 +-
> >  arch/arm64/include/asm/kexec.h    | 41 ++++++++++++++++++++++++-
> >  arch/arm64/include/asm/smp.h      |  2 ++
> >  arch/arm64/kernel/machine_kexec.c | 56 ++++++++++++++++++++++++++++++++--
> >  arch/arm64/kernel/smp.c           | 63 +++++++++++++++++++++++++++++++++++++++
> >  5 files changed, 159 insertions(+), 5 deletions(-)
> > 
> > diff --git a/arch/arm64/include/asm/hardirq.h b/arch/arm64/include/asm/hardirq.h
> > index 8740297..1473fc2 100644
> > --- a/arch/arm64/include/asm/hardirq.h
> > +++ b/arch/arm64/include/asm/hardirq.h
> > @@ -20,7 +20,7 @@
> >  #include <linux/threads.h>
> >  #include <asm/irq.h>
> >  
> > -#define NR_IPI	6
> > +#define NR_IPI	7
> >  
> >  typedef struct {
> >  	unsigned int __softirq_pending;
> > diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h
> > index 04744dc..a908958 100644
> > --- a/arch/arm64/include/asm/kexec.h
> > +++ b/arch/arm64/include/asm/kexec.h
> > @@ -40,7 +40,46 @@
> >  static inline void crash_setup_regs(struct pt_regs *newregs,
> >  				    struct pt_regs *oldregs)
> >  {
> > -	/* Empty routine needed to avoid build errors. */
> > +	if (oldregs) {
> > +		memcpy(newregs, oldregs, sizeof(*newregs));
> > +	} else {
> > +		u64 tmp1, tmp2;
> > +
> > +		__asm__ __volatile__ (
> > +			"stp	 x0,   x1, [%2, #16 *  0]\n"
> > +			"stp	 x2,   x3, [%2, #16 *  1]\n"
> > +			"stp	 x4,   x5, [%2, #16 *  2]\n"
> > +			"stp	 x6,   x7, [%2, #16 *  3]\n"
> > +			"stp	 x8,   x9, [%2, #16 *  4]\n"
> > +			"stp	x10,  x11, [%2, #16 *  5]\n"
> > +			"stp	x12,  x13, [%2, #16 *  6]\n"
> > +			"stp	x14,  x15, [%2, #16 *  7]\n"
> > +			"stp	x16,  x17, [%2, #16 *  8]\n"
> > +			"stp	x18,  x19, [%2, #16 *  9]\n"
> > +			"stp	x20,  x21, [%2, #16 * 10]\n"
> > +			"stp	x22,  x23, [%2, #16 * 11]\n"
> > +			"stp	x24,  x25, [%2, #16 * 12]\n"
> > +			"stp	x26,  x27, [%2, #16 * 13]\n"
> > +			"stp	x28,  x29, [%2, #16 * 14]\n"
> > +			"mov	 %0,  sp\n"
> > +			"stp	x30,  %0,  [%2, #16 * 15]\n"
> > +
> > +			"/* faked current PSTATE */\n"
> > +			"mrs	 %0, CurrentEL\n"
> > +			"mrs	 %1, DAIF\n"
> > +			"orr	 %0, %0, %1\n"
> > +			"mrs	 %1, NZCV\n"
> > +			"orr	 %0, %0, %1\n"
> > +
> 
> What about SPSEL? While we don't use it, it is correctly preserved for
> everything except a CPU that calls panic()...

My comment above might be confusing, but what I want to fake
here is "spsr" as pt_regs.pstate is normally set based on spsr_el1.
So there is no corresponding field of SPSEL in spsr.

> 
> > +			/* pc */
> > +			"adr	 %1, 1f\n"
> > +		"1:\n"
> > +			"stp	 %1, %0,   [%2, #16 * 16]\n"
> > +			: "=r" (tmp1), "=r" (tmp2), "+r" (newregs)
> > +			:
> > +			: "memory"
> > +		);
> > +	}
> >  }
> >  
> >  #endif /* __ASSEMBLY__ */
> > diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h
> > index 0226447..6b0f2c7 100644
> > --- a/arch/arm64/include/asm/smp.h
> > +++ b/arch/arm64/include/asm/smp.h
> > @@ -136,6 +136,8 @@ static inline void cpu_panic_kernel(void)
> >   */
> >  bool cpus_are_stuck_in_kernel(void);
> >  
> > +extern void smp_send_crash_stop(void);
> > +
> >  #endif /* ifndef __ASSEMBLY__ */
> >  
> >  #endif /* ifndef __ASM_SMP_H */
> > diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
> > index bc96c8a..8ac9dba8 100644
> > --- a/arch/arm64/kernel/machine_kexec.c
> > +++ b/arch/arm64/kernel/machine_kexec.c
> > @@ -9,6 +9,9 @@
> >   * published by the Free Software Foundation.
> >   */
> >  
> > +#include <linux/interrupt.h>
> > +#include <linux/irq.h>
> > +#include <linux/kernel.h>
> >  #include <linux/kexec.h>
> >  #include <linux/smp.h>
> >  
> > @@ -22,6 +25,7 @@
> >  extern const unsigned char arm64_relocate_new_kernel[];
> >  extern const unsigned long arm64_relocate_new_kernel_size;
> >  
> > +bool in_crash_kexec;
> 
> static?

Yes, it can be.

> >  static unsigned long kimage_start;
> >  
> >  /**
> > @@ -148,7 +152,8 @@ void machine_kexec(struct kimage *kimage)
> >  	/*
> >  	 * New cpus may have become stuck_in_kernel after we loaded the image.
> >  	 */
> > -	BUG_ON(cpus_are_stuck_in_kernel() || (num_online_cpus() > 1));
> > +	BUG_ON((cpus_are_stuck_in_kernel() || (num_online_cpus() > 1)) &&
> > +			!WARN_ON(in_crash_kexec));
> 
> In the kdump case, num_online_cpus() is unchanged as ipi_cpu_crash_stop()
> doesn't update the online cpu masks, so this WARN_ON always fires. This is
> confusing as the 'failed to stop secondary CPUs' message doesn't appear, because
> those CPUs did stop, and waiting_for_crash_ipi has the expected value...

Good catch! I've never noticed that the message was wrong.
The line should be changed to:
	BUG_ON((cpus_are_stuck_in_kernel() || (num_online_cpus() > 1)) &&
			!in_crash_kexec);

> >  
> >  	reboot_code_buffer_phys = page_to_phys(kimage->control_code_page);
> >  	reboot_code_buffer = phys_to_virt(reboot_code_buffer_phys);
> > @@ -200,13 +205,58 @@ void machine_kexec(struct kimage *kimage)
> >  	 * relocation is complete.
> >  	 */
> >  
> > -	cpu_soft_restart(1, reboot_code_buffer_phys, kimage->head,
> > +	cpu_soft_restart(!in_crash_kexec, reboot_code_buffer_phys, kimage->head,
> >  		kimage_start, 0);
> >  
> >  	BUG(); /* Should never get here. */
> >  }
> 
> 
> 
> > +static void machine_kexec_mask_interrupts(void)
> > +{
> > +	unsigned int i;
> > +	struct irq_desc *desc;
> > +
> > +	for_each_irq_desc(i, desc) {
> > +		struct irq_chip *chip;
> > +		int ret;
> > +
> > +		chip = irq_desc_get_chip(desc);
> > +		if (!chip)
> > +			continue;
> > +
> > +		/*
> > +		 * First try to remove the active state. If this
> > +		 * fails, try to EOI the interrupt.
> > +		 */
> > +		ret = irq_set_irqchip_state(i, IRQCHIP_STATE_ACTIVE, false);
> > +
> > +		if (ret && irqd_irq_inprogress(&desc->irq_data) &&
> > +		    chip->irq_eoi)
> > +			chip->irq_eoi(&desc->irq_data);
> > +
> > +		if (chip->irq_mask)
> > +			chip->irq_mask(&desc->irq_data);
> > +
> > +		if (chip->irq_disable && !irqd_irq_disabled(&desc->irq_data))
> > +			chip->irq_disable(&desc->irq_data);
> > +	}
> > +}
> 
> This function is over my head ... I have no idea how this works, I can only
> comment that its different to the version under arch/arm
> 
> /me adds Marc Z to CC.

This function was once borrowed from arch/arm, then dropped temporarily
and revamped based on Marc's comment IIRC.
So I would like to defer to Marc.

> 
> > +/**
> > + * machine_crash_shutdown - shutdown non-crashing cpus and save registers
> > + */
> >  void machine_crash_shutdown(struct pt_regs *regs)
> >  {
> > -	/* Empty routine needed to avoid build errors. */
> > +	local_irq_disable();
> > +
> > +	in_crash_kexec = true;
> > +
> > +	/* shutdown non-crashing cpus */
> > +	smp_send_crash_stop();
> > +
> > +	/* for crashing cpu */
> > +	crash_save_cpu(regs, smp_processor_id());
> > +	machine_kexec_mask_interrupts();
> > +
> > +	pr_info("Starting crashdump kernel...\n");
> >  }
> > diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
> > index d93d433..b401b25 100644
> > --- a/arch/arm64/kernel/smp.c
> > +++ b/arch/arm64/kernel/smp.c
> > @@ -37,6 +37,7 @@
> >  #include <linux/completion.h>
> >  #include <linux/of.h>
> >  #include <linux/irq_work.h>
> > +#include <linux/kexec.h>
> >  
> >  #include <asm/alternative.h>
> >  #include <asm/atomic.h>
> > @@ -71,6 +72,7 @@ enum ipi_msg_type {
> >  	IPI_RESCHEDULE,
> >  	IPI_CALL_FUNC,
> >  	IPI_CPU_STOP,
> > +	IPI_CPU_CRASH_STOP,
> >  	IPI_TIMER,
> >  	IPI_IRQ_WORK,
> >  	IPI_WAKEUP
> > @@ -734,6 +736,7 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = {
> >  	S(IPI_RESCHEDULE, "Rescheduling interrupts"),
> >  	S(IPI_CALL_FUNC, "Function call interrupts"),
> >  	S(IPI_CPU_STOP, "CPU stop interrupts"),
> > +	S(IPI_CPU_CRASH_STOP, "CPU stop (for crash dump) interrupts"),
> >  	S(IPI_TIMER, "Timer broadcast interrupts"),
> >  	S(IPI_IRQ_WORK, "IRQ work interrupts"),
> >  	S(IPI_WAKEUP, "CPU wake-up interrupts"),
> > @@ -808,6 +811,29 @@ static void ipi_cpu_stop(unsigned int cpu)
> >  		cpu_relax();
> >  }
> >  
> > +#ifdef CONFIG_KEXEC_CORE
> > +static atomic_t waiting_for_crash_ipi;
> > +#endif
> > +
> > +static void ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs)
> > +{
> > +#ifdef CONFIG_KEXEC_CORE
> > +	crash_save_cpu(regs, cpu);
> > +
> > +	atomic_dec(&waiting_for_crash_ipi);
> > +
> > +	local_irq_disable();
> > +
> > +#ifdef CONFIG_HOTPLUG_CPU
> > +	if (cpu_ops[cpu]->cpu_die)
> > +		cpu_ops[cpu]->cpu_die(cpu);
> > +#endif
> > +
> > +	/* just in case */
> > +	cpu_park_loop();
> > +#endif
> > +}
> > +
> >  /*
> >   * Main handler for inter-processor interrupts
> >   */
> > @@ -838,6 +864,15 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
> >  		irq_exit();
> >  		break;
> >  
> > +	case IPI_CPU_CRASH_STOP:
> > +		if (IS_ENABLED(CONFIG_KEXEC_CORE)) {
> > +			irq_enter();
> > +			ipi_cpu_crash_stop(cpu, regs);
> > +
> > +			unreachable();
> > +		}
> > +		break;
> > +
> >  #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
> >  	case IPI_TIMER:
> >  		irq_enter();
> > @@ -910,6 +945,34 @@ void smp_send_stop(void)
> >  			   cpumask_pr_args(cpu_online_mask));
> >  }
> >  
> > +#ifdef CONFIG_KEXEC_CORE
> > +void smp_send_crash_stop(void)
> > +{
> > +	cpumask_t mask;
> > +	unsigned long timeout;
> > +
> > +	if (num_online_cpus() == 1)
> > +		return;
> > +
> > +	cpumask_copy(&mask, cpu_online_mask);
> > +	cpumask_clear_cpu(smp_processor_id(), &mask);
> > +
> > +	atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
> > +
> > +	pr_crit("SMP: stopping secondary CPUs\n");
> > +	smp_cross_call(&mask, IPI_CPU_CRASH_STOP);
> > +
> > +	/* Wait up to one second for other CPUs to stop */
> > +	timeout = USEC_PER_SEC;
> > +	while ((atomic_read(&waiting_for_crash_ipi) > 0) && timeout--)
> > +		udelay(1);
> > +
> > +	if (atomic_read(&waiting_for_crash_ipi) > 0)
> > +		pr_warning("SMP: failed to stop secondary CPUs %*pbl\n",
> > +			   cpumask_pr_args(cpu_online_mask));
> > +}
> > +#endif
> 
> This is very similar to smp_send_stop() which also has the timeout. Is it
> possible to merge them? You could use in_crash_kexec to choose the IPI type.

Yeah, we could merge them along with ipi_cpu_(crash_)stop().
But the resulting code would be quite noisy if each line
is switched by "if (in_crash_kexec)."
Otherwise, we may have one big "if" like:
void smp_send_stop(void)
{
    if (in_crash_kexec)
        ...
    else
        ...
}
It seems to me that it is not much different from the current code.
What do you think?

-Takahiro AKASHI


> 
> > +
> >  /*
> >   * not supported here
> >   */
> > 
> 
> 
> Reviewed-by: James Morse <james.morse@arm.com>
> 
> 
> Thanks,
> 
> James
> 
> 
> 

^ permalink raw reply

* [PATCH v5 2/3] arm64: dts: Add ZTE ZX296718 SoC dts and Makefile
From: Shawn Guo @ 2016-09-16  2:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473730926-1034-3-git-send-email-jun.nie@linaro.org>

On Tue, Sep 13, 2016 at 09:42:05AM +0800, Jun Nie wrote:
> diff --git a/arch/arm64/boot/dts/zte/zx296718-evb.dts b/arch/arm64/boot/dts/zte/zx296718-evb.dts
> new file mode 100644
> index 0000000..820fe1c
> --- /dev/null
> +++ b/arch/arm64/boot/dts/zte/zx296718-evb.dts
> @@ -0,0 +1,29 @@
> +/*
> + * ZTE Ltd. zx296718 Plaform
> + *
> + * 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
> + * publishhed by the Free Software Foundation.
> + *
> + */

Just found this is still not what's recommended, i.e. GPL/X11 dual
license.  I updated it and applied all 3 patches.

Shawn

^ permalink raw reply

* [PATCH -next v2] ARM: orion: fix invalid use of sizeof in orion_ge00_switch_init()
From: Wei Yongjun @ 2016-09-16  2:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473990720-20605-1-git-send-email-weiyj.lk@gmail.com>

From: Wei Yongjun <weiyongjun1@huawei.com>

sizeof() when applied to a pointer typed expression gives the
size of the pointer, not that of the pointed data.

Fixes: fe158a17c1e0 ("ARM: orion: simplify orion_ge00_switch_init")
Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
---
v1 -> v2: fix file module name in subject
---
 arch/arm/plat-orion/common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
index 272f49b..23a975a 100644
--- a/arch/arm/plat-orion/common.c
+++ b/arch/arm/plat-orion/common.c
@@ -478,7 +478,7 @@ void __init orion_ge00_switch_init(struct dsa_platform_data *d)
 	for (i = 0; i < d->nr_chips; i++)
 		d->chip[i].host_dev = &orion_ge_mvmdio.dev;
 
-	platform_device_register_data(NULL, "dsa", 0, d, sizeof(d));
+	platform_device_register_data(NULL, "dsa", 0, d, sizeof(*d));
 }
 
 /*****************************************************************************

^ permalink raw reply related

* [PATCH -next] dma: mv_xor: fix invalid use of sizeof in orion_ge00_switch_init()
From: Wei Yongjun @ 2016-09-16  1:52 UTC (permalink / raw)
  To: linux-arm-kernel

From: Wei Yongjun <weiyongjun1@huawei.com>

sizeof() when applied to a pointer typed expression gives the
size of the pointer, not that of the pointed data.

Fixes: fe158a17c1e0 ("ARM: orion: simplify orion_ge00_switch_init")
Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
---
 arch/arm/plat-orion/common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
index 272f49b..23a975a 100644
--- a/arch/arm/plat-orion/common.c
+++ b/arch/arm/plat-orion/common.c
@@ -478,7 +478,7 @@ void __init orion_ge00_switch_init(struct dsa_platform_data *d)
 	for (i = 0; i < d->nr_chips; i++)
 		d->chip[i].host_dev = &orion_ge_mvmdio.dev;
 
-	platform_device_register_data(NULL, "dsa", 0, d, sizeof(d));
+	platform_device_register_data(NULL, "dsa", 0, d, sizeof(*d));
 }
 
 /*****************************************************************************

^ permalink raw reply related

* [GIT PULL 4/5] Freescale arm64 device tree updates for 4.9
From: Shawn Guo @ 2016-09-16  1:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <2241121.MvRjeYAnGC@wuerfel>

On Wed, Sep 14, 2016 at 05:30:49PM +0200, Arnd Bergmann wrote:
> On Monday, September 12, 2016 5:02:27 PM CEST Shawn Guo wrote:
> > i.MX arm64 device tree changes for 4.9:
> >  - Add property dma-coherent for ls2080a PCI device to save software
> >    cache maintenance.
> >  - Update serial aliases and use stdout-path to sepecify console for
> >    ls2080a and ls1043a boards.
> >  - Add DDR memory controller device node for ls2080a and ls1043a SoCs.
> > 
> 
> Pulled into next/dt64, thanks!
> 
> The "dma-coherent" change sounds like a bugfix, should that be backported
> to stable kernels? Usually if you lack that property on a device that
> is actually coherent, you can get silent data corruption by treating it as
> non-coherent.

My impression is that those cache maintenance enforced for non-coherent
device will hurt performance on coherent device.  I don't know it will
cause data corruption.

@Liu Gang,

Did you experience any functional issue with PCI device before adding
"dma-coherent" property?  If not, can you please do more testing to
confirm this is only about performance?  Otherwise, you should follow
Arnd's suggestion to send the change for stable kernel.

Shawn

^ permalink raw reply

* [PATCH v5 3/3] clk: imx6: Fix procedure to switch the parent of LDB_DI_CLK
From: Shawn Guo @ 2016-09-16  1:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAOMZO5DkMaRFwzH7HY872pLUdDrZfMq0xqLG+Xv88ut3Jd5Saw@mail.gmail.com>

On Mon, Sep 12, 2016 at 12:15:40PM -0300, Fabio Estevam wrote:
> Hi Akshay and Charles,
> 
> On Mon, Sep 12, 2016 at 12:09 PM, Akshay Bhat <akshay.bhat@timesys.com> wrote:
> 
> > Hi Fabio, Shawn,
> >
> > Advantech tested the v5 patch series on imx6q-b450v3 board (with 4.7
> > kernel) and confirmed the patch fixes the lvds blank display issue
> > being seen on some imx6q-b450v3 boards.
> >
> > Details below:
> > With the patch applied:
> > Board # 1: 100 times power on/off, no LVDS display failure
> > Board # 2: 100 times power on/off, no LVDS display failure
> >
> > Without the patch:
> > Board # 1: LVDS display failure (blank display output) at 4th time power on/off.
> > Board # 2: LVDS display failure (blank display output) at 3rd time power on/off.
> >
> > Tested-by: Charles Kang <Charles.Kang@advantech.com.tw>
> 
> Thanks for testing it.
> 
> > Since the patch has been reviewed and confirmed to fix display
> > failures on 2 different boards (imx6q-evi and imx6q-b450v3), can it be
> > applied?
> 
> Yes, I think this series is in a good shape now.
> 
> Shawn,
> 
> Are you happy with it?

Acked-by: Shawn Guo <shawnguo@kernel.org>

Please send it to clk maintainers for applying.

Shawn

^ permalink raw reply

* [RFC/PATCH] usb: misc: Add a driver for TC7USB40MU
From: Stephen Boyd @ 2016-09-16  1:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160915090158.GB6919@b29397-desktop>

Quoting Peter Chen (2016-09-15 02:01:58)
> On Wed, Sep 14, 2016 at 01:45:04AM -0700, Stephen Boyd wrote:
> > Quoting Peter Chen (2016-09-14 01:03:21)
> > > On Tue, Sep 13, 2016 at 10:58:26PM -0700, Stephen Boyd wrote:
> > > > Quoting Peter Chen (2016-09-13 20:32:00)
> > > > > On Tue, Sep 13, 2016 at 06:42:46PM -0700, Stephen Boyd wrote:
> > > > > > On the db410c 96boards platform we have a TC7USB40MU[1] on the
> > > > > > board to mux the D+/D- lines from the SoC between a micro usb
> > > > > > "device" port and a USB hub for "host" roles. Upon a role switch,
> > > > > > we need to change this mux to forward the D+/D- lines to either
> > > > > > the port or the hub. Therefore, introduce a driver for this
> > > > > > device that intercepts extcon USB_HOST events and logically
> > > > > > asserts a gpio to mux the "host" D+/D- lines when a host cable is
> > > > > > attached. When the cable goes away, it will logically deassert
> > > > > > the gpio and mux the "device" lines.
> > > > > 
> > > > > Would you please draw the design? It can also help me review your
> > > > > chipidea patch well.
> > > > > 
> > > > > 1. How many ports on the board?
> > > > > 2. How the lines are connected on the board?
> > > > > 
> > > > 
> > > > The schematic for the db410c is publically available here[2][3].
> > > > 
> > > > There's also the 96boards spec[4] which talks about this switch based
> > > > design a little bit. See the section titled "Single USB port Example".
> > > > 
> > > > [2] https://github.com/96boards/documentation/blob/master/ConsumerEdition/DragonBoard-410c/HardwareDocs/Schematics_DragonBoard.pdf
> > > > [3] https://github.com/96boards/documentation/raw/master/ConsumerEdition/DragonBoard-410c/HardwareDocs/Schematics_DragonBoard.pdf
> > > > [4] https://www.96boards.org/wp-content/uploads/2015/02/96BoardsCESpecificationv1.0-EA1.pdf
> > > 
> > > Ok, I see several use cases for this role switch
> > > 
> > > 1. Using the hardware switch (218-4LPST)
> > > In this case, you can set USB_SW_SEL as input gpio, and use
> > > extcon-usb-gpio.c like before, just set this gpio as active
> > > low at dts.
> > 
> > Nice! I didn't think of this case but it's good that we can support
> > that with some work.
> > 
> 
> After looking more, I find the main purpose of this switch is
> what it writes, FORCE DSI SELECTION TO USB HOST MODE
> 
> When the switch is on, the system is host-only.
> When the switch is off, the default role is device mode, and
> switch the role through gpio USB_SW_SEL_PM by software.

Correct.

> 
> > > 
> > > 2. Using USB_HS_ID as vbus-gpio (input), and USB_SW_SEL as id-gpio (output)
> > 
> > This is pretty much what has been implemented. USB_HS_ID is an
> > extcon-usb-gpio.c device.
> 
> At some designs, this gpio is tied to ID pin at MicroB connector, and
> using a Mirco-AB cable to switch the role.
> 
> > 
> > > I can't find hardware relationship between each other, maybe I miss
> > > something.
> > 
> > I believe USB_SW_SEL is the physical switch (218-4LPST) while
> > USB_SW_SEL_PM is the software controllable part using a GPIO. USB_HS_ID
> > is just the vbus line from the uB connector and that line goes straight
> > into the SoC via a GPIO.
> > 
> > > This use case (design) seems strange, usually, we use ID pin controls
> > > vbus, but seldom use vbus pin control ID.
> > > How you would like to implement it? When the USB cable is connected
> > > (between PC), it receives vbus-gpio interrupt, then you set USB_SW_SEL
> > > as low? If disconnected, you set USB_SW_SEL as high?
> > 
> > Right. The documented behavior is to detect the micro-usb cable and
> > drive USB_SW_SEL low. When the cable is unplugged we drive USB_SW_SEL
> > high. Maybe that should be changed though? If we always sampled
> > USB_SW_SEL as a USB_HOST extcon and the vbus line as a USB extcon then
> > we could allow the user to decide either with the physical switch or
> > with some sort of software control to toggle that gpio.
> > 
> > > When the USB controller works at Host mode, what will happen if the user
> > > connects USB cable at device port?
> > 
> > The devices on the two type-A connectors will be disconnected and we'll
> > switch from host mode to device mode.
> > 
> > > 
> > > 3. Using sysfs to switch the role
> > > Set USB_SW_SEL according to "role" at debugfs
> > 
> > sysfs isn't debugfs, but yes I wonder if we need to worry about the
> > debugfs role switching support here and toggle the gpio manually without
> > involving extcon. That would mean we need to have a way for the chipidea
> > controller to toggle this gpio/mux itself.
> > 
> > > 
> > > Which one you would like to implement? Or anything else I miss?
> > > 
> > 
> > Mostly #2, but I'm concerned that the DT binding is going to force that
> > decision on others who may have the same switch and want to do #1 or #3.
> > So how to design it in a way that makes it work in all cases? Also, what
> > to do if the USB_SW_SEL switch is driven high by the physical switch?
> > That will "override" any software control we might be able to use, so
> > hopefully we can detect this somehow and prevent the role switch from
> > happening.
> 
> From my point, the physical switch is only used to force host mode. The
> #1 and #2 can't be supported at the same time.

Sure. I mean to say support all use cases with the same DT binding.

> For #3, it is not the
> use case for this design. #3 is usually used for the single port which
> needs to support switching role on the fly without disconnection.
> So, you may only need to consider #2, you can't use extcon-usb-gpio.c
> directly since you need to set one gpio to mux the dp/dm, Baolu Lu had
> USB MUX patch set before which may satisfy your requirement. [1]

Ok. Did the usb mux patches go anywhere? It seemed to get tangled up in
DRD framework and I haven't been following along. I'll look into these
patches more.

^ permalink raw reply

* [PATCH] KVM: arm/arm64: Route vtimer events to user space
From: Alexander Graf @ 2016-09-15 23:15 UTC (permalink / raw)
  To: linux-arm-kernel

We have 2 modes for dealing with interrupts in the ARM world. We can either
handle them all using hardware acceleration through the vgic or we can emulate
a gic in user space and only drive CPU IRQ pins from there.

Unfortunately, when driving IRQs from user space, we never tell user space
about timer events that may result in interrupt line state changes, so we
lose out on timer events if we run with user space gic emulation.

This patch set fixes that by routing vtimer expiration events to user space.
With this patch I can successfully run edk2 and Linux with user space gic
emulation.

Signed-off-by: Alexander Graf <agraf@suse.de>

---

A branch with WIP QEMU code can be found here:

  https://github.com/agraf/qemu.git no-kvm-irqchip
---
 Documentation/virtual/kvm/api.txt |  28 ++++++++-
 arch/arm/include/asm/kvm_host.h   |   3 +
 arch/arm/kvm/arm.c                |  46 +++++++++++---
 arch/arm64/include/asm/kvm_host.h |   3 +
 include/uapi/linux/kvm.h          |  14 +++++
 virt/kvm/arm/arch_timer.c         | 126 ++++++++++++++++++++++++++++----------
 6 files changed, 177 insertions(+), 43 deletions(-)

diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 739db9a..6a64c53 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -997,7 +997,9 @@ documentation when it pops into existence).
 
 Capability: KVM_CAP_ENABLE_CAP, KVM_CAP_ENABLE_CAP_VM
 Architectures: x86 (only KVM_CAP_ENABLE_CAP_VM),
-	       mips (only KVM_CAP_ENABLE_CAP), ppc, s390
+	       mips (only KVM_CAP_ENABLE_CAP), ppc, s390,
+	       arm (only KVM_CAP_ENABLE_CAP),
+	       arm64 (only only KVM_CAP_ENABLE_CAP)
 Type: vcpu ioctl, vm ioctl (with KVM_CAP_ENABLE_CAP_VM)
 Parameters: struct kvm_enable_cap (in)
 Returns: 0 on success; -1 on error
@@ -3200,8 +3202,10 @@ struct kvm_run {
 	/* in */
 	__u8 request_interrupt_window;
 
-Request that KVM_RUN return when it becomes possible to inject external
+[x86] Request that KVM_RUN return when it becomes possible to inject external
 interrupts into the guest.  Useful in conjunction with KVM_INTERRUPT.
+[arm*] Bits set to 1 in here mask IRQ lines that would otherwise potentially
+trigger forever. Useful with KVM_CAP_ARM_TIMER.
 
 	__u8 padding1[7];
 
@@ -3517,6 +3521,16 @@ Hyper-V SynIC state change. Notification is used to remap SynIC
 event/message pages and to enable/disable SynIC messages/events processing
 in userspace.
 
+		/* KVM_EXIT_ARM_TIMER */
+		struct {
+			__u8 timesource;
+		} arm_timer;
+
+Indicates that a timer triggered that user space needs to handle and
+potentially mask with vcpu->run->request_interrupt_window to allow the
+guest to proceed. This only happens for timers that got enabled through
+KVM_CAP_ARM_TIMER.
+
 		/* Fix the size of the union. */
 		char padding[256];
 	};
@@ -3737,6 +3751,16 @@ Once this is done the KVM_REG_MIPS_VEC_* and KVM_REG_MIPS_MSA_* registers can be
 accessed, and the Config5.MSAEn bit is accessible via the KVM API and also from
 the guest.
 
+6.11 KVM_CAP_ARM_TIMER
+
+Architectures: arm, arm64
+Target: vcpu
+Parameters: args[0] contains a bitmap of timers to enable
+
+This capability allows to route per-core timers into user space. When it's
+enabled, the enabled timers trigger KVM_EXIT_ARM_TIMER guest exits when they
+are pending, unless masked by vcpu->run->request_interrupt_window.
+
 7. Capabilities that can be enabled on VMs
 ------------------------------------------
 
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index de338d9..77d1f73 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -180,6 +180,9 @@ struct kvm_vcpu_arch {
 
 	/* Detect first run of a vcpu */
 	bool has_run_once;
+
+	/* User space wants timer notifications */
+	bool user_space_arm_timers;
 };
 
 struct kvm_vm_stat {
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 75f130e..1b4b9a6 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -187,6 +187,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 	case KVM_CAP_ARM_PSCI_0_2:
 	case KVM_CAP_READONLY_MEM:
 	case KVM_CAP_MP_STATE:
+	case KVM_CAP_ARM_TIMER:
 		r = 1;
 		break;
 	case KVM_CAP_COALESCED_MMIO:
@@ -474,13 +475,7 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
 			return ret;
 	}
 
-	/*
-	 * Enable the arch timers only if we have an in-kernel VGIC
-	 * and it has been properly initialized, since we cannot handle
-	 * interrupts from the virtual timer with a userspace gic.
-	 */
-	if (irqchip_in_kernel(kvm) && vgic_initialized(kvm))
-		ret = kvm_timer_enable(vcpu);
+	ret = kvm_timer_enable(vcpu);
 
 	return ret;
 }
@@ -601,6 +596,13 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
 			run->exit_reason = KVM_EXIT_INTR;
 		}
 
+		if (kvm_check_request(KVM_REQ_PENDING_TIMER, vcpu)) {
+			/* Tell user space about the pending vtimer */
+			ret = 0;
+			run->exit_reason = KVM_EXIT_ARM_TIMER;
+			run->arm_timer.timesource = KVM_ARM_TIMER_VTIMER;
+		}
+
 		if (ret <= 0 || need_new_vmid_gen(vcpu->kvm) ||
 			vcpu->arch.power_off || vcpu->arch.pause) {
 			local_irq_enable();
@@ -878,6 +880,29 @@ static int kvm_arm_vcpu_has_attr(struct kvm_vcpu *vcpu,
 	return ret;
 }
 
+static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
+				     struct kvm_enable_cap *cap)
+{
+	int r;
+
+	if (cap->flags)
+		return -EINVAL;
+
+	switch (cap->cap) {
+	case KVM_CAP_ARM_TIMER:
+		r = 0;
+		if (cap->args[0] != KVM_ARM_TIMER_VTIMER)
+			return -EINVAL;
+		vcpu->arch.user_space_arm_timers = true;
+		break;
+	default:
+		r = -EINVAL;
+		break;
+	}
+
+	return r;
+}
+
 long kvm_arch_vcpu_ioctl(struct file *filp,
 			 unsigned int ioctl, unsigned long arg)
 {
@@ -940,6 +965,13 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
 		if (copy_from_user(&attr, argp, sizeof(attr)))
 			return -EFAULT;
 		return kvm_arm_vcpu_has_attr(vcpu, &attr);
+	case KVM_ENABLE_CAP:
+	{
+		struct kvm_enable_cap cap;
+
+		if (copy_from_user(&cap, argp, sizeof(cap)))
+			return -EFAULT;
+		return kvm_vcpu_ioctl_enable_cap(vcpu, &cap);
 	}
 	default:
 		return -EINVAL;
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 3eda975..3d01481 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -270,6 +270,9 @@ struct kvm_vcpu_arch {
 
 	/* Detect first run of a vcpu */
 	bool has_run_once;
+
+	/* User space wants timer notifications */
+	bool user_space_arm_timers;
 };
 
 #define vcpu_gp_regs(v)		(&(v)->arch.ctxt.gp_regs)
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 300ef25..00f4948 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -205,6 +205,7 @@ struct kvm_hyperv_exit {
 #define KVM_EXIT_S390_STSI        25
 #define KVM_EXIT_IOAPIC_EOI       26
 #define KVM_EXIT_HYPERV           27
+#define KVM_EXIT_ARM_TIMER        28
 
 /* For KVM_EXIT_INTERNAL_ERROR */
 /* Emulate instruction failed. */
@@ -361,6 +362,10 @@ struct kvm_run {
 		} eoi;
 		/* KVM_EXIT_HYPERV */
 		struct kvm_hyperv_exit hyperv;
+		/* KVM_EXIT_ARM_TIMER */
+		struct {
+			__u8 timesource;
+		} arm_timer;
 		/* Fix the size of the union. */
 		char padding[256];
 	};
@@ -870,6 +875,7 @@ struct kvm_ppc_smmu_info {
 #define KVM_CAP_S390_USER_INSTR0 130
 #define KVM_CAP_MSI_DEVID 131
 #define KVM_CAP_PPC_HTM 132
+#define KVM_CAP_ARM_TIMER 133
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1327,4 +1333,12 @@ struct kvm_assigned_msix_entry {
 #define KVM_X2APIC_API_USE_32BIT_IDS            (1ULL << 0)
 #define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK  (1ULL << 1)
 
+/* Available with KVM_CAP_ARM_TIMER */
+
+/* Bits for run->request_interrupt_window */
+#define KVM_IRQWINDOW_VTIMER		(1 << 0)
+
+/* Bits for run->arm_timer.timesource */
+#define KVM_ARM_TIMER_VTIMER		(1 << 0)
+
 #endif /* __LINUX_KVM_H */
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 4309b60..d0e999d 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -24,6 +24,7 @@
 
 #include <clocksource/arm_arch_timer.h>
 #include <asm/arch_timer.h>
+#include <asm/kvm_emulate.h>
 
 #include <kvm/arm_vgic.h>
 #include <kvm/arm_arch_timer.h>
@@ -170,16 +171,45 @@ static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level)
 {
 	int ret;
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+	struct kvm_run *run = vcpu->run;
 
-	BUG_ON(!vgic_initialized(vcpu->kvm));
+	BUG_ON(irqchip_in_kernel(vcpu->kvm) && !vgic_initialized(vcpu->kvm));
 
 	timer->active_cleared_last = false;
 	timer->irq.level = new_level;
-	trace_kvm_timer_update_irq(vcpu->vcpu_id, timer->irq.irq,
+	trace_kvm_timer_update_irq(vcpu->vcpu_id, host_vtimer_irq,
 				   timer->irq.level);
-	ret = kvm_vgic_inject_mapped_irq(vcpu->kvm, vcpu->vcpu_id,
-					 timer->irq.irq,
-					 timer->irq.level);
+
+	if (irqchip_in_kernel(vcpu->kvm) && vgic_initialized(vcpu->kvm)) {
+		/* Fire the timer in the VGIC */
+
+		ret = kvm_vgic_inject_mapped_irq(vcpu->kvm, vcpu->vcpu_id,
+						 timer->irq.irq,
+						 timer->irq.level);
+	} else if (!vcpu->arch.user_space_arm_timers) {
+		/* User space has not activated timer use */
+		ret = 0;
+	} else {
+		/*
+		 * Set PENDING_TIMER so that user space can handle the event if
+		 *
+		 *   1) Level is high
+		 *   2) The vtimer is not suppressed by user space
+		 *   3) We are not in the timer trigger exit path
+		 */
+		if (new_level &&
+		    !(run->request_interrupt_window & KVM_IRQWINDOW_VTIMER) &&
+		    (run->exit_reason != KVM_EXIT_ARM_TIMER)) {
+			/* KVM_REQ_PENDING_TIMER means vtimer triggered */
+			kvm_make_request(KVM_REQ_PENDING_TIMER, vcpu);
+		}
+
+		/* Force a new level high check on next entry */
+		timer->irq.level = 0;
+
+		ret = 0;
+	}
+
 	WARN_ON(ret);
 }
 
@@ -197,7 +227,8 @@ static int kvm_timer_update_state(struct kvm_vcpu *vcpu)
 	 * because the guest would never see the interrupt.  Instead wait
 	 * until we call this function from kvm_timer_flush_hwstate.
 	 */
-	if (!vgic_initialized(vcpu->kvm) || !timer->enabled)
+	if ((irqchip_in_kernel(vcpu->kvm) && !vgic_initialized(vcpu->kvm)) ||
+	    !timer->enabled)
 		return -ENODEV;
 
 	if (kvm_timer_should_fire(vcpu) != timer->irq.level)
@@ -275,35 +306,57 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
 	* to ensure that hardware interrupts from the timer triggers a guest
 	* exit.
 	*/
-	phys_active = timer->irq.level ||
-			kvm_vgic_map_is_active(vcpu, timer->irq.irq);
-
-	/*
-	 * We want to avoid hitting the (re)distributor as much as
-	 * possible, as this is a potentially expensive MMIO access
-	 * (not to mention locks in the irq layer), and a solution for
-	 * this is to cache the "active" state in memory.
-	 *
-	 * Things to consider: we cannot cache an "active set" state,
-	 * because the HW can change this behind our back (it becomes
-	 * "clear" in the HW). We must then restrict the caching to
-	 * the "clear" state.
-	 *
-	 * The cache is invalidated on:
-	 * - vcpu put, indicating that the HW cannot be trusted to be
-	 *   in a sane state on the next vcpu load,
-	 * - any change in the interrupt state
-	 *
-	 * Usage conditions:
-	 * - cached value is "active clear"
-	 * - value to be programmed is "active clear"
-	 */
-	if (timer->active_cleared_last && !phys_active)
-		return;
+	if (irqchip_in_kernel(vcpu->kvm) && vgic_initialized(vcpu->kvm)) {
+		phys_active = timer->irq.level ||
+				kvm_vgic_map_is_active(vcpu, timer->irq.irq);
+
+		/*
+		 * We want to avoid hitting the (re)distributor as much as
+		 * possible, as this is a potentially expensive MMIO access
+		 * (not to mention locks in the irq layer), and a solution for
+		 * this is to cache the "active" state in memory.
+		 *
+		 * Things to consider: we cannot cache an "active set" state,
+		 * because the HW can change this behind our back (it becomes
+		 * "clear" in the HW). We must then restrict the caching to
+		 * the "clear" state.
+		 *
+		 * The cache is invalidated on:
+		 * - vcpu put, indicating that the HW cannot be trusted to be
+		 *   in a sane state on the next vcpu load,
+		 * - any change in the interrupt state
+		 *
+		 * Usage conditions:
+		 * - cached value is "active clear"
+		 * - value to be programmed is "active clear"
+		 */
+		if (timer->active_cleared_last && !phys_active)
+			return;
+
+		ret = irq_set_irqchip_state(host_vtimer_irq,
+					    IRQCHIP_STATE_ACTIVE,
+					    phys_active);
+	} else {
+		/* User space tells us whether the timer is in active mode */
+		phys_active = vcpu->run->request_interrupt_window &
+			      KVM_IRQWINDOW_VTIMER;
+
+		/* However if the line is high, we exit anyway, so we want
+		 * to keep the IRQ masked */
+		phys_active = phys_active || timer->irq.level;
+
+		/*
+		 * So we can just explicitly mask or unmask the IRQ, gaining
+		 * more compatibility with oddball irq controllers.
+		 */
+		if (phys_active)
+			disable_percpu_irq(host_vtimer_irq);
+		else
+			enable_percpu_irq(host_vtimer_irq, 0);
+
+		ret = 0;
+	}
 
-	ret = irq_set_irqchip_state(host_vtimer_irq,
-				    IRQCHIP_STATE_ACTIVE,
-				    phys_active);
 	WARN_ON(ret);
 
 	timer->active_cleared_last = !phys_active;
@@ -479,6 +532,10 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
 	if (timer->enabled)
 		return 0;
 
+	/* No need to route physical IRQs when we don't use the vgic */
+	if (!irqchip_in_kernel(vcpu->kvm))
+		goto no_vgic;
+
 	/*
 	 * Find the physical IRQ number corresponding to the host_vtimer_irq
 	 */
@@ -502,6 +559,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
 	if (ret)
 		return ret;
 
+no_vgic:
 
 	/*
 	 * There is a potential race here between VCPUs starting for the first
-- 
2.6.6

^ permalink raw reply related

* [PATCH 0/3] clk: sunxi-ng: sun6i-a31: Register offset and clk flag fixes
From: Stephen Boyd @ 2016-09-15 23:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160915083436.GC10128@lukather>

On 09/15/2016 01:34 AM, Maxime Ripard wrote:
> Hi,
>
> On Thu, Sep 15, 2016 at 02:57:37PM +0800, Chen-Yu Tsai wrote:
>> Hi,
>>
>> Here are 3 fixes for the new sunxi-ng clk driver for sun6i-a31 recently
>> introduced for 4.9. The issues were noticed while working on the display
>> pipeline for the A31/A31s. The second patch follows what Maxime has done
>> for the A33 CCU driver. The third issue was noticed while doing the first
>> patch.
>>
>> I hope we can get this into 4.9 as well, either right in -rc1, or in a
>> later -rc.
> Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
>
> Stephen, could you apply those patches directly on top of my previous
> PR, or do you want me to send another one?
>

I can apply directly to clk-next.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* [PATCH] ASoC: rockchip: Support headset button function on rk3399
From: Cheng-Yi Chiang @ 2016-09-15 23:10 UTC (permalink / raw)
  To: linux-arm-kernel

Set the mapping between button and media key event.

Signed-off-by: Cheng-Yi Chiang <cychiang@chromium.org>
---
 sound/soc/rockchip/rk3399_gru_sound.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c
index 164b6da..ee06489 100644
--- a/sound/soc/rockchip/rk3399_gru_sound.c
+++ b/sound/soc/rockchip/rk3399_gru_sound.c
@@ -23,6 +23,7 @@
 #include <linux/of_gpio.h>
 #include <linux/delay.h>
 #include <linux/spi/spi.h>
+#include <linux/input.h>
 #include <sound/core.h>
 #include <sound/jack.h>
 #include <sound/pcm.h>
@@ -209,6 +210,14 @@ static int rockchip_sound_da7219_init(struct snd_soc_pcm_runtime *rtd)
 		return ret;
 	}
 
+	snd_jack_set_key(rockchip_sound_jack.jack, SND_JACK_BTN_0, KEY_MEDIA);
+	snd_jack_set_key(
+		rockchip_sound_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
+	snd_jack_set_key(
+		rockchip_sound_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
+	snd_jack_set_key(
+		rockchip_sound_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND);
+
 	da7219_aad_jack_det(codec, &rockchip_sound_jack);
 
 	return 0;
-- 
2.6.6

^ permalink raw reply related

* [GIT PULL] Amlogic 64-bit DT updates for v4.9, round 2 (for next/late)
From: Kevin Hilman @ 2016-09-15 22:59 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Arnd, Olof,

Here is round 2 of the 64-bit DT changes for v4.9.

Based on my drivers pull (round 2), this is targetted at next/late also
since the DT patches here are using clock IDs that come from my 2nd
drivers pull (which itself has merged an immtable branch from the clock
tree.)

Please pull,

Kevin


The following changes since commit dfdd7d4af6ebee027be7bf2636b2314937948da6:

  clk: gxbb: expose i2c clocks (2016-09-14 11:24:04 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-amlogic.git tags/amlogic-dt64-2

for you to fetch changes up to e1e4a1a4fad203f8a02b887149809966e128a3d8:

  Merge branch 'v4.8/dt64' into v4.8/dt64-2 (2016-09-15 15:35:50 -0700)

----------------------------------------------------------------
Amlogic 64-bit DT changes for v4.9, round 2

Primarily adding support for newly added drivers

- USB host
- I2C
- SPI flash controller
- PWM
- mailbox, MHU
- pinctrl: add pins for SPI, I2C, SDIO

and then enabling these drivers on various boards.

----------------------------------------------------------------
Carlo Caione (4):
      documentation: Add secure monitor bindings documentation
      ARM64: dts: amlogic: gxbb: Enable secure monitor
      documentation: Add nvmem bindings documentation
      ARM64: dts: amlogic: gxbb: Enable NVMEM

Jerome Brunet (4):
      ARM64: dts: amlogic: add spi nor pins
      ARM64: dts: meson-gxbb: add pins for I2C
      ARM64: dts: gxbb: add i2c bus
      ARM64: dts: meson-gxbb-p20x: Enable USB Nodes

Kevin Hilman (6):
      ARM64: DTS: meson-gxbb: switch ethernet to real clock
      Merge branch 'clk-meson-gxbb-ao' of git://git.kernel.org/.../clk/linux into v4.8/dt64
      ARM64: dts: amlogic: add the input pin for the IR remote
      ARM64: dts: meson-gxbb: Add PWM pinctrl nodes
      Merge tag 'amlogic-drivers-2' into v4.8/dt64-2
      Merge branch 'v4.8/dt64' into v4.8/dt64-2

Martin Blumenstingl (5):
      ARM64: dts: meson-gxbb: Enable the the IR decoder on supported boards
      ARM64: dts: amlogic: enable ethernet on all Tronsmart Vega S95 devices
      ARM64: dts: meson-gxbb: use the new GXBB DWMAC glue driver
      ARM64: dts: meson-gxbb: add USB Nodes
      ARM64: dts: meson-gxbb-vega-s95: Enable USB Nodes

Neil Armstrong (9):
      ARM64: dts: amlogic: meson-gxbb: Add watchdog node
      ARM64: dts: meson-gxbb: Add GXBB AO Clock and Reset node
      dt-bindings: media: meson-ir: Add Meson8b and GXBB compatible strings
      ARM64: dts: meson-gxbb: Add Infrared Remote Controller decoder
      ARM64: dts: meson-gxbb: Add Meson MHU Node
      ARM64: dts: meson-gxbb: Add Meson GXBB PWM Controller nodes
      ARM64: dts: meson-gxbb: add the SDIO pins
      ARM64: dts: meson-gxbb: Add SPIFC node
      ARM64: dts: meson-gxbb: add I2C nodes

 Documentation/devicetree/bindings/firmware/meson/meson_sm.txt |  15 ++++
 Documentation/devicetree/bindings/media/meson-ir.txt          |   5 +-
 Documentation/devicetree/bindings/nvmem/amlogic-efuse.txt     |  39 +++++++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts           |  11 +++
 arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts               |   6 ++
 arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi              |  35 ++++++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi          |  42 ++++++++++++
 arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi                   | 329 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 8 files changed, 478 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/firmware/meson/meson_sm.txt
 create mode 100644 Documentation/devicetree/bindings/nvmem/amlogic-efuse.txt

^ permalink raw reply

* [PATCH] soc: rockchip: power-domain: Handle errors from of_genpd_add_provider_onecell
From: Heiko Stübner @ 2016-09-15 22:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <14744126.0kYUlUJ0mc@diego>

Am Donnerstag, 15. September 2016, 16:39:34 schrieb Heiko St?bner:
> Am Donnerstag, 15. September 2016, 12:43:41 schrieb Tomeu Vizoso:
> > It was a bit surprising that the device was reported to have probed just
> > fine, but the provider hadn't been registered.
> > 
> > So handle any errors when registering the provider and fail the probe
> > accordingly.
> > 
> > Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> > Cc: Caesar Wang <wxt@rock-chips.com>
> > ---
> > 
> >  drivers/soc/rockchip/pm_domains.c | 6 +++++-
> >  1 file changed, 5 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/soc/rockchip/pm_domains.c
> > b/drivers/soc/rockchip/pm_domains.c index 7acd1517dd37..57e920128cb2
> > 100644
> > --- a/drivers/soc/rockchip/pm_domains.c
> > +++ b/drivers/soc/rockchip/pm_domains.c
> > @@ -627,7 +627,11 @@ static int rockchip_pm_domain_probe(struct
> > platform_device *pdev) goto err_out;
> > 
> >  	}
> > 
> > -	of_genpd_add_provider_onecell(np, &pmu->genpd_data);
> > +	error = of_genpd_add_provider_onecell(np, &pmu->genpd_data);
> > +	if (error) {
> > +		dev_err(dev, "failed to add provider: %d\n", error);
> > +		goto err_out;
> > +	}
> > 
> >  	return 0;
> 
> Looks good in itself, but seems to trigger some issue in the genpd code
> when applied alone on top of linux-next-20160915. Looks like genpd
> is missing counter-initialization somewhere, as I'm seeing now:
> 
> [    1.664744] genpd_poweroff_unused disabling (null)
> [    1.669553] ------------[ cut here ]------------
> [    1.674169] WARNING: CPU: 0 PID: 1 at ../kernel/workqueue.c:1440
> __queue_work+0x2b8/0x3f8 [    1.682337] Modules linked in:
> [    1.685401] CPU: 0 PID: 1 Comm: swapper/0 Not tainted
> 4.8.0-rc6-next-20160915-00001-g7432710-dirty #5 [    1.694608] Hardware
> name: Rockchip (Device Tree)
> [    1.699312] [<c0310388>] (unwind_backtrace) from [<c030ba04>]
> (show_stack+0x10/0x14) [    1.707050] [<c030ba04>] (show_stack) from
> [<c0599c90>] (dump_stack+0x90/0xa4) [    1.714267] [<c0599c90>]
> (dump_stack) from [<c0341bc0>] (__warn+0xe8/0x100) [    1.721221]
> [<c0341bc0>] (__warn) from [<c0341c88>] (warn_slowpath_null+0x20/0x28) [   
> 1.728785] [<c0341c88>] (warn_slowpath_null) from [<c0355b28>]
> (__queue_work+0x2b8/0x3f8) [    1.737041] [<c0355b28>] (__queue_work) from
> [<c0355ca8>] (queue_work_on+0x40/0x4c) [    1.744692] [<c0355ca8>]
> (queue_work_on) from [<c103e8b8>] (genpd_poweroff_unused+0x78/0x9c) [   
> 1.753123] [<c103e8b8>] (genpd_poweroff_unused) from [<c0301e78>]
> (do_one_initcall+0x40/0x170) [    1.761815] [<c0301e78>] (do_one_initcall)
> from [<c1000dc8>] (kernel_init_freeable+0x15c/0x1fc) [    1.770507]
> [<c1000dc8>] (kernel_init_freeable) from [<c0bb7ba0>]
> (kernel_init+0x8/0x114) [    1.778678] [<c0bb7ba0>] (kernel_init) from
> [<c0307df8>] (ret_from_fork+0x14/0x3c) [    1.786240] ---[ end trace
> b38c51ace1463add ]---
> [    1.790875] genpd_poweroff_unused disabling ??????
> [    1.795856] genpd_poweroff_unused disabling ??????
> [    1.800830] ------------[ cut here ]------------
> [    1.805443] WARNING: CPU: 0 PID: 1 at ../kernel/workqueue.c:1440
> __queue_work+0x2b8/0x3f8 [    1.813610] Modules linked in:
> [    1.816673] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W      
> 4.8.0-rc6-next-20160915-00001-g7432710-dirty #5 [    1.827094] Hardware
> name: Rockchip (Device Tree)
> [    1.831795] [<c0310388>] (unwind_backtrace) from [<c030ba04>]
> (show_stack+0x10/0x14) [    1.839532] [<c030ba04>] (show_stack) from
> [<c0599c90>] (dump_stack+0x90/0xa4) [    1.846747] [<c0599c90>]
> (dump_stack) from [<c0341bc0>] (__warn+0xe8/0x100) [    1.853700]
> [<c0341bc0>] (__warn) from [<c0341c88>] (warn_slowpath_null+0x20/0x28) [   
> 1.861264] [<c0341c88>] (warn_slowpath_null) from [<c0355b28>]
> (__queue_work+0x2b8/0x3f8) [    1.869521] [<c0355b28>] (__queue_work) from
> [<c0355ca8>] (queue_work_on+0x40/0x4c) [    1.877170] [<c0355ca8>]
> (queue_work_on) from [<c103e8b8>] (genpd_poweroff_unused+0x78/0x9c) [   
> 1.885600] [<c103e8b8>] (genpd_poweroff_unused) from [<c0301e78>]
> (do_one_initcall+0x40/0x170) [    1.894290] [<c0301e78>] (do_one_initcall)
> from [<c1000dc8>] (kernel_init_freeable+0x15c/0x1fc) [    1.902981]
> [<c1000dc8>] (kernel_init_freeable) from [<c0bb7ba0>]
> (kernel_init+0x8/0x114) [    1.911152] [<c0bb7ba0>] (kernel_init) from
> [<c0307df8>] (ret_from_fork+0x14/0x3c) [    1.918713] ---[ end trace
> b38c51ace1463ade ]---
> [    1.923338] genpd_poweroff_unused disabling ??????
> [    1.928325] genpd_poweroff_unused disabling ??????
> 
> [+ millions more of those]

just for completenes sake, I've included your patch in a series of my
own [0] which adds the necessary  pm_genpd_remove prequisite to prevent
the errors shown above.


Heiko

[0] "[PATCH 0/2] soc: rockchip: fix probe error path in power-domain driver"

^ permalink raw reply

* [PATCH v2 6/6] ARM64: meson-gxbb-vega-s95: Enable USB Nodes
From: Kevin Hilman @ 2016-09-15 22:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160911134111.31141-7-martin.blumenstingl@googlemail.com>

Martin Blumenstingl <martin.blumenstingl@googlemail.com> writes:

> Enable both gxbb USB controller and add a 5V regulator for the OTG port
> VBUS
>
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>

Applied (after adding a "dts: " to the subject.

Kevin

^ permalink raw reply

* [PATCH v2 4/6] ARM64: meson-gxbb: add USB Nodes
From: Kevin Hilman @ 2016-09-15 22:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160911134111.31141-5-martin.blumenstingl@googlemail.com>

Martin Blumenstingl <martin.blumenstingl@googlemail.com> writes:

> Add the nodes for the dwc2 USB controller and the related USB PHYs.
> Currently we force usb0 to host mode because OTG is currently not
> working in our PHY driver.
>
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>

Applied (after adding a "dts: " to the subject.

Kevin

^ permalink raw reply

* [PATCH v2 5/6] ARM64: meson-gxbb-p20x: Enable USB Nodes
From: Kevin Hilman @ 2016-09-15 22:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <7h37l2mk6a.fsf@baylibre.com>

Kevin Hilman <khilman@baylibre.com> writes:

> Martin Blumenstingl <martin.blumenstingl@googlemail.com> writes:
>
>> From: Jerome Brunet <jbrunet@baylibre.com>
>>
>> Enable both gxbb USB controller and add a 5V regulator for the OTG port
>> VBUS
>>
>> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
>
> nit: subject should have "ARM64: dts:" prefix.
>
>> ---
>>  arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi | 29 ++++++++++++++++++++++++
>>  1 file changed, 29 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
>> index ce105fe..4493bce 100644
>> --- a/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
>> +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
>> @@ -93,6 +93,18 @@
>>  		compatible = "mmc-pwrseq-emmc";
>>  		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
>>  	};
>> +
>> +	usb_vbus: regulator-usb0-vbus {
>
> nit: I like to use the signal name from the schematics for the node name
> (and for regulator-name below).  In the schematics, that signal is named
> USB_PWR.
>
>
>> +		compatible = "regulator-fixed";
>> +
>> +		regulator-name = "USB0_VBUS";
>> +		regulator-min-microvolt = <5000000>;
>> +		regulator-max-microvolt = <5000000>;
>> +
>> +		gpio = <&gpio GPIODV_24 GPIO_ACTIVE_HIGH>;
>
> Please add a comment above this line with the schematic signal name: USB_PWR_EN.
>

For the record... after a chat with Martin on IRC, I just fixed these up
myself locally, so...

Applied,

Kevin

^ permalink raw reply

* [PATCH] ARM: dts: msm8974: Add definitions for QCE & cryptobam
From: Andy Gross @ 2016-09-15 21:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160830153740.13275-1-voker57@gmail.com>

On Tue, Aug 30, 2016 at 06:37:40PM +0300, Iaroslav Gridin wrote:
> From: Voker57 <voker57@gmail.com>
> 
> Add device tree definitions for Qualcomm Cryptography engine and its BAM
> Signed-off-by: Iaroslav Gridin <voker57@gmail.com>
> ---
>  arch/arm/boot/dts/qcom-msm8974.dtsi | 42 +++++++++++++++++++++++++++++++++++++
>  1 file changed, 42 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi
> index 561d4d1..c0da739 100644
> --- a/arch/arm/boot/dts/qcom-msm8974.dtsi
> +++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
> @@ -287,6 +287,48 @@
>  			reg = <0xf9011000 0x1000>;
>  		};
>  
> +		cryptobam: dma at fd444000 {
> +			compatible = "qcom,bam-v1.4.0";
> +			reg = <0xfd444000 0x15000>;
> +			interrupts = <0 236 0>;
> +			clocks = <&gcc GCC_CE2_AHB_CLK>,
> +				 <&gcc GCC_CE2_AXI_CLK>,
> +				 <&gcc GCC_CE2_CLK>;
> +			clock-names = "bam_clk", "axi_clk", "core_clk";

Actually, on thinking about this more, the bam block itself only requires the
single clock.  The peripheral it is attached to has to keep its sanity during
the duration of the transfer (crypto).  The crypto requires 3 clocks, one of
which is the same clk the bam requires.

You can access the BAM registers with the bam_clk only, correct?


> +			#dma-cells = <1>;
> +			qcom,ee = <1>;
> +			qcom,controlled-remotely;
> +			};
> +
> +		qcom,qcrypto at fd440000 {
> +			compatible = "qcom,crypto-v5.1";
> +			reg = <0xfd45a000 0x6000>;
> +			reg-names = "crypto-base";
> +			interrupts = <0 236 0>;
> +			qcom,bam-pipe-pair = <2>;
> +			qcom,ce-hw-instance = <1>;
> +			qcom,ce-device = <0>;
> +			clocks = <&gcc GCC_CE2_CLK>,
> +				 <&gcc GCC_CE2_AHB_CLK>,
> +				 <&gcc GCC_CE2_AXI_CLK>,
> +				 <&gcc CE2_CLK_SRC>;

The CLK_SRC is unnecessary.  Or should be at least.  That gets turned on by
getting the CE2_CLK.  I vaguely remember a parent issue that was fixed.

> +
> +			dmas = <&cryptobam 2>, <&cryptobam 3>;
> +			dma-names = "rx", "tx";
> +			clock-names = "core", "iface", "bus", "core_src";
> +			qcom,clk-mgmt-sus-res;
> +			qcom,msm-bus,name = "qcrypto-noc";
> +
> +			qcom,msm-bus,num-cases = <2>;
> +			qcom,msm-bus,num-paths = <1>;
> +			qcom,use-sw-aes-cbc-ecb-ctr-algo;
> +			qcom,use-sw-aes-xts-algo;
> +			qcom,use-sw-ahash-algo;
> +			qcom,msm-bus,vectors-KBps = <56 512 0 0>,
> +						    <56 512 3936000 393600>;
> +			};
> +
> +
>  		timer at f9020000 {
>  			#address-cells = <1>;
>  			#size-cells = <1>;

Regards,

Andy

^ permalink raw reply

* [RFC PATCH v2 5/5] ARM: hisi: add devicetree for hi3520
From: Marty Plummer @ 2016-09-15 21:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160915210505.21878-1-netz.kernel@gmail.com>

Probably needs a lot more work, but as of right now this can get me into
a basic busybox userspace 
Signed-off-by: Marty Plummer <netz.kernel@gmail.com>
---
 arch/arm/boot/dts/Makefile              |   2 +
 arch/arm/boot/dts/hi3520-1176-dm77a.dts |  62 +++++++++++
 arch/arm/boot/dts/hi3520-1176.dtsi      | 178 ++++++++++++++++++++++++++++++++
 3 files changed, 242 insertions(+)
 create mode 100644 arch/arm/boot/dts/hi3520-1176-dm77a.dts
 create mode 100644 arch/arm/boot/dts/hi3520-1176.dtsi

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 7ffd3a3..285f56a 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -154,6 +154,8 @@ dtb-$(CONFIG_ARCH_EXYNOS5) += \
 	exynos5440-sd5v1.dtb \
 	exynos5440-ssdk5440.dtb \
 	exynos5800-peach-pi.dtb
+dtb-$(CONFIG_ARCH_HI3520_1176) += \
+	hi3520-1176-dm77a.dtb
 dtb-$(CONFIG_ARCH_HI3620) += \
 	hi3620-hi4511.dtb
 dtb-$(CONFIG_ARCH_HIGHBANK) += \
diff --git a/arch/arm/boot/dts/hi3520-1176-dm77a.dts b/arch/arm/boot/dts/hi3520-1176-dm77a.dts
new file mode 100644
index 0000000..c87a18e
--- /dev/null
+++ b/arch/arm/boot/dts/hi3520-1176-dm77a.dts
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016  Marty Plummer <netz.kernel@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/dts-v1/;
+#include "hi3520-1176.dtsi"
+
+/ {
+	model = "Nightowl zeus-dvr";
+	compatible = "hisilicon,hi3520-1176";
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+	};
+
+	/* chosen { */
+	/* 	bootargs = "mem=72M console=ttyAMA0,115200 root=/dev/ram"; */
+	/* 	stdout-path = "serial0:115200n8"; */
+	/* }; */
+
+	memory at e2000000 {
+		device_type = "memory";
+		reg = <0xe2000000 0x4800000>;
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&dual_timer0 {
+	status = "okay";
+};
+
+&gmac0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	phy-handle = <&phy1>;
+	phy-mode = "mii";
+	mac-address = [00 00 00 00 00 00];
+	status = "okay";
+
+	phy1: ethernet-phy at 1 {
+		reg = <1>;
+	};
+};
diff --git a/arch/arm/boot/dts/hi3520-1176.dtsi b/arch/arm/boot/dts/hi3520-1176.dtsi
new file mode 100644
index 0000000..a7dbc16
--- /dev/null
+++ b/arch/arm/boot/dts/hi3520-1176.dtsi
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2016  Marty Plummer <netz.kernel@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	/* interrupt-parent = <&vic0>; */
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,arm1176jzf-s";
+			reg = <0>;
+		};
+	};
+
+	uartclk: uartclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <101000000>;
+	};
+
+	clk_3m: clk_3m {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <101000000>;
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+
+		vic0: interrupt-controller at 10070000 {
+			compatible = "arm,pl190-vic";
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			reg = <0x10070000 0x1000>;
+		};
+
+		vic1: interrupt-controller at 10080000 {
+			compatible = "arm,pl190-vic";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			reg = <0x10080000 0x1000>;
+		};
+
+		amba {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			ranges;
+
+			uart0: uart at 20090000 {
+				compatible = "arm,pl011", "arm,primecell";
+				reg = <0x20090000 0x1000>;
+				clocks = <&uartclk &clk_3m>;
+				clock-names = "uartclk", "apb_pclk";
+				interrupts-extended = <&vic0 12 4>;
+				status = "disable";
+			};
+
+			uart1: uart at 200a0000 {
+				compatible = "arm,pl011", "arm,primecell";
+				reg = <0x200a0000 0x1000>;
+				clocks = <&uartclk &clk_3m>;
+				clock-names = "uartclk", "apb_pclk";
+				interrupts-extended = <&vic0 12 4>;
+			};
+
+			uart2: uart at 200b0000 {
+				compatible = "arm,pl011", "arm,primecell";
+				reg = <0x200b0000 0x1000>;
+				clocks = <&uartclk &clk_3m>;
+				clock-names = "uartclk", "apb_pclk";
+				interrupts-extended = <&vic0 13 4>;
+			};
+
+			uart3: uart at 200c0000 {
+				compatible = "arm,pl011", "arm,primecell";
+				reg = <0x200c0000 0x1000>;
+				clocks = <&uartclk &clk_3m>;
+				clock-names = "uartclk", "apb_pclk";
+				interrupts-extended = <&vic0 13 4>;
+			};
+
+			gpio0: gpio at 20150000 {
+				compatible = "arm,pl061", "arm,primecell";
+				reg = <0x20150000 0x1000>;
+				interrupts-extended = <&vic1 6 4>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				clocks = <&uartclk &clk_3m>;
+				clock-names = "apb_pclk";
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				status = "disabled";
+			};
+
+			dual_timer0: dual_timer at 20000000 {
+				compatible = "arm,sp804", "arm,primecell";
+				reg = <0x20000000 0x1000>;
+				interrupts-extended = <&vic0 4 4>, <&vic0 4 4>;
+				clocks = <&clk_3m>;
+				clock-names = "apb_pclk";
+				status = "disable";
+			};
+
+			dual_timer1: dual_timer at 20010000 {
+				compatible = "arm,sp804", "arm,primecell";
+				reg = <0x20010000 0x1000>;
+				interrupts-extended = <&vic0 5 4>, <&vic0 5 4>;
+				clocks = <&clk_3m>;
+				clock-names = "apb_pclk";
+				status = "disable";
+			};
+
+			spi_bus0: spi at 200e0000 {
+				compatible = "arm,pl022", "arm,primecell";
+				reg = <0x200e0000 0x1000>;
+				interrupts-extended = <&vic0 11 4>;
+				num-cs = <1>;
+			};
+		};
+
+		sysctrl: system-controller at 20050000 {
+			compatible = "hisilicon,hi3520-sysctrl", "syscon";
+			reg = <0x20050000 0x1000>;
+		};
+
+		reboot {
+			compatible = "syscon-reboot";
+			regmap = <&sysctrl>;
+			offset = <0x4>;
+			mask = <0xdeadbeef>;
+		};
+
+		/* gmac0: ethernet at 10090000 { */
+		/* 	compatible = "hisilicon,hix5hd2-gmac"; */
+		/* 	reg = <0x10090000 0x1000>,<0x20050000 0x1000>; */
+		/* 	interrupts-extended = <&vic0 14 4>; */
+		/* 	clocks = <&clk_3m>; */
+		/* 	status = "disabled"; */
+		/* }; */
+
+		usb0: ehci at 100b0000 {
+			compatible = "generic-ehci";
+			reg = <0x100b0000 0x1000>;
+			interrupts-extended = <&vic0 23 4>;
+			clocks = <&clk_3m>;
+		};
+
+		usb1: ohci at 100a0000 {
+			compatible = "generic-ohci";
+			reg = <0x100a0000 0x1000>;
+			interrupts-extended = <&vic0 22 4>;
+			clocks = <&clk_3m>;
+		};
+	};
+};
-- 
2.9.3

^ permalink raw reply related

* [RFC PATCH v2 4/5] ARM: hisi: enable devicetree support for hi3520
From: Marty Plummer @ 2016-09-15 21:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160915210505.21878-1-netz.kernel@gmail.com>

GIC removed from the ARCH_HISI namespace and placed in individual SoC as
hi3520 uses a VIC instead and doesn't require a GIC

Signed-off-by: Marty Plummer <netz.kernel@gmail.com>
---
 arch/arm/mach-hisi/Kconfig     | 28 +++++++++++++++++++---------
 arch/arm/mach-hisi/hisilicon.c | 28 ++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+), 9 deletions(-)

diff --git a/arch/arm/mach-hisi/Kconfig b/arch/arm/mach-hisi/Kconfig
index 8a552c3..ea4e5b1 100644
--- a/arch/arm/mach-hisi/Kconfig
+++ b/arch/arm/mach-hisi/Kconfig
@@ -1,8 +1,7 @@
 config ARCH_HISI
 	bool "Hisilicon SoC Support"
-	depends on ARCH_MULTI_V7
+	depends on ARCH_MULTI_V6 || ARCH_MULTI_V7
 	select ARM_AMBA
-	select ARM_GIC
 	select ARM_TIMER_SP804
 	select POWER_RESET
 	select POWER_RESET_HISI
@@ -12,9 +11,17 @@ if ARCH_HISI
 
 menu "Hisilicon platform type"
 
+config ARCH_HI3520_1176
+	bool "Hisilicon	Hi3520 family"
+	depends on ARCH_MULTI_V6
+	select ARM_VIC
+	help
+	  Support for Hisilicon Hi3520 SoC family
+
 config ARCH_HI3620
 	bool "Hisilicon Hi3620 family"
 	depends on ARCH_MULTI_V7
+	select ARM_GIC
 	select CACHE_L2X0
 	select HAVE_ARM_SCU if SMP
 	select HAVE_ARM_TWD if SMP
@@ -24,17 +31,19 @@ config ARCH_HI3620
 	  Support for Hisilicon Hi36xx SoC family
 
 config ARCH_HIP01
-       bool "Hisilicon HIP01 family"
-       depends on ARCH_MULTI_V7
-       select HAVE_ARM_SCU if SMP
-       select HAVE_ARM_TWD if SMP
-       select ARM_GLOBAL_TIMER
-       help
-         Support for Hisilicon HIP01 SoC family
+	bool "Hisilicon HIP01 family"
+	depends on ARCH_MULTI_V7
+	select ARM_GIC
+	select HAVE_ARM_SCU if SMP
+	select HAVE_ARM_TWD if SMP
+	select ARM_GLOBAL_TIMER
+	help
+	  Support for Hisilicon HIP01 SoC family
 
 config ARCH_HIP04
 	bool "Hisilicon HiP04 Cortex A15 family"
 	depends on ARCH_MULTI_V7
+	select ARM_GIC
 	select ARM_ERRATA_798181 if SMP
 	select HAVE_ARM_ARCH_TIMER
 	select MCPM if SMP
@@ -45,6 +54,7 @@ config ARCH_HIP04
 config ARCH_HIX5HD2
 	bool "Hisilicon X5HD2 family"
 	depends on ARCH_MULTI_V7
+	select ARM_GIC
 	select CACHE_L2X0
 	select HAVE_ARM_SCU if SMP
 	select HAVE_ARM_TWD if SMP
diff --git a/arch/arm/mach-hisi/hisilicon.c b/arch/arm/mach-hisi/hisilicon.c
index dfa1ee8..7a15936 100644
--- a/arch/arm/mach-hisi/hisilicon.c
+++ b/arch/arm/mach-hisi/hisilicon.c
@@ -17,6 +17,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
+#define HI3520_1176_SYSCTRL_PHYS_BASE		0x20050000
+#define HI3520_1176_SYSCTRL_VIRT_BASE		0xfe350000
 #define HI3620_SYSCTRL_PHYS_BASE		0xfc802000
 #define HI3620_SYSCTRL_VIRT_BASE		0xfe802000
 
@@ -28,6 +30,16 @@
  * spaces wasted since ioremap() may be called multi times for the same
  * IO space.
  */
+static struct map_desc hi3520_1176_io_desc[] __initdata = {
+	{
+		/* sysctrl */
+		.virtual	= HI3520_1176_SYSCTRL_VIRT_BASE,
+		.pfn		= __phys_to_pfn(HI3520_1176_SYSCTRL_PHYS_BASE),
+		.length		= 0x10000,
+		.type		= MT_DEVICE,
+	},
+};
+
 static struct map_desc hi3620_io_desc[] __initdata = {
 	{
 		/* sysctrl */
@@ -38,17 +50,33 @@ static struct map_desc hi3620_io_desc[] __initdata = {
 	},
 };
 
+static void __init hi3520_1176_map_io(void)
+{
+	debug_ll_io_init();
+	iotable_init(hi3520_1176_io_desc, ARRAY_SIZE(hi3520_1176_io_desc));
+}
+
 static void __init hi3620_map_io(void)
 {
 	debug_ll_io_init();
 	iotable_init(hi3620_io_desc, ARRAY_SIZE(hi3620_io_desc));
 }
 
+static const char *const hi3520_1176_compat[] __initconst = {
+	"hisilicon,hi3520-1176",
+	NULL,
+};
+
 static const char *const hi3620_compat[] __initconst = {
 	"hisilicon,hi3620-hi4511",
 	NULL,
 };
 
+DT_MACHINE_START(HI3520_1176, "Hisilicon Hi3520-1176 (Flattened Device Tree)")
+	.map_io		= hi3520_1176_map_io,
+	.dt_compat	= hi3520_1176_compat,
+MACHINE_END
+
 DT_MACHINE_START(HI3620, "Hisilicon Hi3620 (Flattened Device Tree)")
 	.map_io		= hi3620_map_io,
 	.dt_compat	= hi3620_compat,
-- 
2.9.3

^ permalink raw reply related

* [RFC PATCH v2 3/5] dmaengine: hi3620: Make hi3620 explicit, remove wildcard
From: Marty Plummer @ 2016-09-15 21:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160915210505.21878-1-netz.kernel@gmail.com>

Signed-off-by: Marty Plummer <netz.kernel@gmail.com>
---
 drivers/dma/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 739f797..74bab9d0 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -279,7 +279,7 @@ config INTEL_MIC_X100_DMA
 
 config K3_DMA
 	tristate "Hisilicon K3 DMA support"
-	depends on ARCH_HI3xxx
+	depends on ARCH_HI3620
 	select DMA_ENGINE
 	select DMA_VIRTUAL_CHANNELS
 	help
-- 
2.9.3

^ permalink raw reply related

* [RFC PATCH v2 2/5] clk: hi3620: Make 3620 explicit, remove wildcard
From: Marty Plummer @ 2016-09-15 21:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160915210505.21878-1-netz.kernel@gmail.com>

Signed-off-by: Marty Plummer <netz.kernel@gmail.com>
---
 drivers/clk/hisilicon/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
index e169ec7..2edf3b5 100644
--- a/drivers/clk/hisilicon/Makefile
+++ b/drivers/clk/hisilicon/Makefile
@@ -4,7 +4,7 @@
 
 obj-y	+= clk.o clkgate-separated.o clkdivider-hi6220.o
 
-obj-$(CONFIG_ARCH_HI3xxx)	+= clk-hi3620.o
+obj-$(CONFIG_ARCH_HI3620)	+= clk-hi3620.o
 obj-$(CONFIG_ARCH_HIP04)	+= clk-hip04.o
 obj-$(CONFIG_ARCH_HIX5HD2)	+= clk-hix5hd2.o
 obj-$(CONFIG_COMMON_CLK_HI3519)	+= clk-hi3519.o
-- 
2.9.3

^ permalink raw reply related

* [RFC PATCH v2 1/5] ARM: hisi: Make 3620 explicit, remove wildcards
From: Marty Plummer @ 2016-09-15 21:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160915210505.21878-1-netz.kernel@gmail.com>

Signed-off-by: Marty Plummer <netz.kernel@gmail.com>
---
 arch/arm/Kconfig.debug              |  2 +-
 arch/arm/boot/dts/Makefile          |  2 +-
 arch/arm/configs/hisi_defconfig     |  2 +-
 arch/arm/configs/multi_v7_defconfig |  2 +-
 arch/arm/mach-hisi/Kconfig          |  4 ++--
 arch/arm/mach-hisi/core.h           | 10 +++++-----
 arch/arm/mach-hisi/hisilicon.c      |  6 +++---
 arch/arm/mach-hisi/hotplug.c        | 16 ++++++++--------
 arch/arm/mach-hisi/platsmp.c        | 24 ++++++++++++------------
 9 files changed, 34 insertions(+), 34 deletions(-)

diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index a9693b6..9094ca6 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -280,7 +280,7 @@ choice
 
 	config DEBUG_HI3620_UART
 		bool "Hisilicon HI3620 Debug UART"
-		depends on ARCH_HI3xxx
+		depends on ARCH_HI3620
 		select DEBUG_UART_PL01X
 		help
 		  Say Y here if you want kernel low-level debugging support
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index faacd52..7ffd3a3 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -154,7 +154,7 @@ dtb-$(CONFIG_ARCH_EXYNOS5) += \
 	exynos5440-sd5v1.dtb \
 	exynos5440-ssdk5440.dtb \
 	exynos5800-peach-pi.dtb
-dtb-$(CONFIG_ARCH_HI3xxx) += \
+dtb-$(CONFIG_ARCH_HI3620) += \
 	hi3620-hi4511.dtb
 dtb-$(CONFIG_ARCH_HIGHBANK) += \
 	highbank.dtb \
diff --git a/arch/arm/configs/hisi_defconfig b/arch/arm/configs/hisi_defconfig
index b2e340b..14c8da6 100644
--- a/arch/arm/configs/hisi_defconfig
+++ b/arch/arm/configs/hisi_defconfig
@@ -4,7 +4,7 @@ CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_RD_LZMA=y
 CONFIG_ARCH_HISI=y
-CONFIG_ARCH_HI3xxx=y
+CONFIG_ARCH_HI3620=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_CMDLINE_PARTITION=y
 CONFIG_ARCH_HIX5HD2=y
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 2c8665c..a63865e 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -45,7 +45,7 @@ CONFIG_MACH_BERLIN_BG2Q=y
 CONFIG_ARCH_DIGICOLOR=y
 CONFIG_ARCH_HIGHBANK=y
 CONFIG_ARCH_HISI=y
-CONFIG_ARCH_HI3xxx=y
+CONFIG_ARCH_HI3620=y
 CONFIG_ARCH_HIX5HD2=y
 CONFIG_ARCH_HIP01=y
 CONFIG_ARCH_HIP04=y
diff --git a/arch/arm/mach-hisi/Kconfig b/arch/arm/mach-hisi/Kconfig
index a3b091a..8a552c3 100644
--- a/arch/arm/mach-hisi/Kconfig
+++ b/arch/arm/mach-hisi/Kconfig
@@ -12,8 +12,8 @@ if ARCH_HISI
 
 menu "Hisilicon platform type"
 
-config ARCH_HI3xxx
-	bool "Hisilicon Hi36xx family"
+config ARCH_HI3620
+	bool "Hisilicon Hi3620 family"
 	depends on ARCH_MULTI_V7
 	select CACHE_L2X0
 	select HAVE_ARM_SCU if SMP
diff --git a/arch/arm/mach-hisi/core.h b/arch/arm/mach-hisi/core.h
index e883583..cb7bc84 100644
--- a/arch/arm/mach-hisi/core.h
+++ b/arch/arm/mach-hisi/core.h
@@ -3,13 +3,13 @@
 
 #include <linux/reboot.h>
 
-extern void hi3xxx_set_cpu_jump(int cpu, void *jump_addr);
-extern int hi3xxx_get_cpu_jump(int cpu);
+extern void hi3620_set_cpu_jump(int cpu, void *jump_addr);
+extern int hi3620_get_cpu_jump(int cpu);
 extern void secondary_startup(void);
 
-extern void hi3xxx_cpu_die(unsigned int cpu);
-extern int hi3xxx_cpu_kill(unsigned int cpu);
-extern void hi3xxx_set_cpu(int cpu, bool enable);
+extern void hi3620_cpu_die(unsigned int cpu);
+extern int hi3620_cpu_kill(unsigned int cpu);
+extern void hi3620_set_cpu(int cpu, bool enable);
 
 extern void hix5hd2_set_cpu(int cpu, bool enable);
 extern void hix5hd2_cpu_die(unsigned int cpu);
diff --git a/arch/arm/mach-hisi/hisilicon.c b/arch/arm/mach-hisi/hisilicon.c
index c08c44e..dfa1ee8 100644
--- a/arch/arm/mach-hisi/hisilicon.c
+++ b/arch/arm/mach-hisi/hisilicon.c
@@ -9,7 +9,7 @@
  * 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 <linux/clocksource.h>
 #include <linux/irqchip.h>
@@ -44,12 +44,12 @@ static void __init hi3620_map_io(void)
 	iotable_init(hi3620_io_desc, ARRAY_SIZE(hi3620_io_desc));
 }
 
-static const char *const hi3xxx_compat[] __initconst = {
+static const char *const hi3620_compat[] __initconst = {
 	"hisilicon,hi3620-hi4511",
 	NULL,
 };
 
 DT_MACHINE_START(HI3620, "Hisilicon Hi3620 (Flattened Device Tree)")
 	.map_io		= hi3620_map_io,
-	.dt_compat	= hi3xxx_compat,
+	.dt_compat	= hi3620_compat,
 MACHINE_END
diff --git a/arch/arm/mach-hisi/hotplug.c b/arch/arm/mach-hisi/hotplug.c
index a129aae..f06b428 100644
--- a/arch/arm/mach-hisi/hotplug.c
+++ b/arch/arm/mach-hisi/hotplug.c
@@ -143,7 +143,7 @@ static void set_cpu_hi3620(int cpu, bool enable)
 	}
 }
 
-static int hi3xxx_hotplug_init(void)
+static int hi3620_hotplug_init(void)
 {
 	struct device_node *node;
 
@@ -157,10 +157,10 @@ static int hi3xxx_hotplug_init(void)
 	return -ENOENT;
 }
 
-void hi3xxx_set_cpu(int cpu, bool enable)
+void hi3620_set_cpu(int cpu, bool enable)
 {
 	if (!ctrl_base) {
-		if (hi3xxx_hotplug_init() < 0)
+		if (hi3620_hotplug_init() < 0)
 			return;
 	}
 
@@ -262,24 +262,24 @@ static inline void cpu_enter_lowpower(void)
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-void hi3xxx_cpu_die(unsigned int cpu)
+void hi3620_cpu_die(unsigned int cpu)
 {
 	cpu_enter_lowpower();
-	hi3xxx_set_cpu_jump(cpu, phys_to_virt(0));
+	hi3620_set_cpu_jump(cpu, phys_to_virt(0));
 	cpu_do_idle();
 
 	/* We should have never returned from idle */
 	panic("cpu %d unexpectedly exit from shutdown\n", cpu);
 }
 
-int hi3xxx_cpu_kill(unsigned int cpu)
+int hi3620_cpu_kill(unsigned int cpu)
 {
 	unsigned long timeout = jiffies + msecs_to_jiffies(50);
 
-	while (hi3xxx_get_cpu_jump(cpu))
+	while (hi3620_get_cpu_jump(cpu))
 		if (time_after(jiffies, timeout))
 			return 0;
-	hi3xxx_set_cpu(cpu, false);
+	hi3620_set_cpu(cpu, false);
 	return 1;
 }
 
diff --git a/arch/arm/mach-hisi/platsmp.c b/arch/arm/mach-hisi/platsmp.c
index e1d6764..e36783e 100644
--- a/arch/arm/mach-hisi/platsmp.c
+++ b/arch/arm/mach-hisi/platsmp.c
@@ -23,7 +23,7 @@
 
 static void __iomem *ctrl_base;
 
-void hi3xxx_set_cpu_jump(int cpu, void *jump_addr)
+void hi3620_set_cpu_jump(int cpu, void *jump_addr)
 {
 	cpu = cpu_logical_map(cpu);
 	if (!cpu || !ctrl_base)
@@ -31,7 +31,7 @@ void hi3xxx_set_cpu_jump(int cpu, void *jump_addr)
 	writel_relaxed(virt_to_phys(jump_addr), ctrl_base + ((cpu - 1) << 2));
 }
 
-int hi3xxx_get_cpu_jump(int cpu)
+int hi3620_get_cpu_jump(int cpu)
 {
 	cpu = cpu_logical_map(cpu);
 	if (!cpu || !ctrl_base)
@@ -56,7 +56,7 @@ static void __init hisi_enable_scu_a9(void)
 	}
 }
 
-static void __init hi3xxx_smp_prepare_cpus(unsigned int max_cpus)
+static void __init hi3620_smp_prepare_cpus(unsigned int max_cpus)
 {
 	struct device_node *np = NULL;
 	u32 offset = 0;
@@ -81,20 +81,20 @@ static void __init hi3xxx_smp_prepare_cpus(unsigned int max_cpus)
 	}
 }
 
-static int hi3xxx_boot_secondary(unsigned int cpu, struct task_struct *idle)
+static int hi3620_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
-	hi3xxx_set_cpu(cpu, true);
-	hi3xxx_set_cpu_jump(cpu, secondary_startup);
+	hi3620_set_cpu(cpu, true);
+	hi3620_set_cpu_jump(cpu, secondary_startup);
 	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
 	return 0;
 }
 
-static const struct smp_operations hi3xxx_smp_ops __initconst = {
-	.smp_prepare_cpus	= hi3xxx_smp_prepare_cpus,
-	.smp_boot_secondary	= hi3xxx_boot_secondary,
+static const struct smp_operations hi3620_smp_ops __initconst = {
+	.smp_prepare_cpus	= hi3620_smp_prepare_cpus,
+	.smp_boot_secondary	= hi3620_boot_secondary,
 #ifdef CONFIG_HOTPLUG_CPU
-	.cpu_die		= hi3xxx_cpu_die,
-	.cpu_kill		= hi3xxx_cpu_kill,
+	.cpu_die		= hi3620_cpu_die,
+	.cpu_kill		= hi3620_cpu_kill,
 #endif
 };
 
@@ -181,6 +181,6 @@ static const struct smp_operations hip01_smp_ops __initconst = {
 	.smp_boot_secondary     = hip01_boot_secondary,
 };
 
-CPU_METHOD_OF_DECLARE(hi3xxx_smp, "hisilicon,hi3620-smp", &hi3xxx_smp_ops);
+CPU_METHOD_OF_DECLARE(hi3620_smp, "hisilicon,hi3620-smp", &hi3620_smp_ops);
 CPU_METHOD_OF_DECLARE(hix5hd2_smp, "hisilicon,hix5hd2-smp", &hix5hd2_smp_ops);
 CPU_METHOD_OF_DECLARE(hip01_smp, "hisilicon,hip01-smp", &hip01_smp_ops);
-- 
2.9.3

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox