* [PATCH v4 13/13] ARM: KVM: Add VGIC configuration option
From: Christoffer Dall @ 2012-11-10 15:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121110154358.3061.16338.stgit@chazy-air>
From: Marc Zyngier <marc.zyngier@arm.com>
It is now possible to select the VGIC configuration option.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <c.dall@virtualopensystems.com>
---
arch/arm/kvm/Kconfig | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
index bfa3174..3c979ce 100644
--- a/arch/arm/kvm/Kconfig
+++ b/arch/arm/kvm/Kconfig
@@ -51,6 +51,13 @@ config KVM_ARM_MAX_VCPUS
large, so only choose a reasonable number that you expect to
actually use.
+config KVM_ARM_VGIC
+ bool "KVM support for Virtual GIC"
+ depends on KVM_ARM_HOST && OF
+ select HAVE_KVM_IRQCHIP
+ ---help---
+ Adds support for a hardware assisted, in-kernel GIC emulation.
+
source drivers/virtio/Kconfig
endif # VIRTUALIZATION
^ permalink raw reply related
* [PATCH v4 0/5] KVM/ARM Architected Timers support
From: Christoffer Dall @ 2012-11-10 15:45 UTC (permalink / raw)
To: linux-arm-kernel
The following series implements support for the architected generic
timers for KVM/ARM.
This is an unmodified repost of the previously submitted series.
This patch series can also be pulled from:
git://github.com/virtualopensystems/linux-kvm-arm.git
branch: kvm-arm-v13-vgic-timers
---
Marc Zyngier (5):
ARM: arch_timers: switch to physical timers if HYP mode is available
ARM: KVM: arch_timers: Add minimal infrastructure
ARM: KVM: arch_timers: Add guest timer core support
ARM: KVM: arch_timers: Add timer world switch
ARM: KVM: arch_timers: Wire the init code and config option
arch/arm/include/asm/kvm_arch_timer.h | 100 ++++++++++++++++
arch/arm/include/asm/kvm_host.h | 5 +
arch/arm/kernel/arch_timer.c | 7 +
arch/arm/kernel/asm-offsets.c | 8 +
arch/arm/kvm/Kconfig | 7 +
arch/arm/kvm/Makefile | 1
arch/arm/kvm/arm.c | 14 ++
arch/arm/kvm/interrupts.S | 2
arch/arm/kvm/interrupts_head.S | 60 ++++++++++
arch/arm/kvm/reset.c | 9 +
arch/arm/kvm/timer.c | 204 +++++++++++++++++++++++++++++++++
arch/arm/kvm/vgic.c | 1
12 files changed, 417 insertions(+), 1 deletion(-)
create mode 100644 arch/arm/include/asm/kvm_arch_timer.h
create mode 100644 arch/arm/kvm/timer.c
--
^ permalink raw reply
* [PATCH v4 1/5] ARM: arch_timers: switch to physical timers if HYP mode is available
From: Christoffer Dall @ 2012-11-10 15:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121110154554.3274.77777.stgit@chazy-air>
From: Marc Zyngier <marc.zyngier@arm.com>
If we're booted in HYP mode, it is possible that we'll run some
kind of virtualized environment. In this case, it is a better to
switch to the physical timers, and leave the virtual timers to
guests.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/kernel/arch_timer.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c
index c8ef207..8adcd04 100644
--- a/arch/arm/kernel/arch_timer.c
+++ b/arch/arm/kernel/arch_timer.c
@@ -26,6 +26,7 @@
#include <asm/arch_timer.h>
#include <asm/system_info.h>
#include <asm/sched_clock.h>
+#include <asm/virt.h>
static unsigned long arch_timer_rate;
@@ -489,10 +490,14 @@ int __init arch_timer_of_register(void)
arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
/*
+ * If HYP mode is available, we know that the physical timer
+ * has been configured to be accessible from PL1. Use it, so
+ * that a guest can use the virtual timer instead.
+ *
* If no interrupt provided for virtual timer, we'll have to
* stick to the physical timer. It'd better be accessible...
*/
- if (!arch_timer_ppi[VIRT_PPI]) {
+ if (is_hyp_mode_available() || !arch_timer_ppi[VIRT_PPI]) {
arch_timer_use_virtual = false;
if (!arch_timer_ppi[PHYS_SECURE_PPI] ||
^ permalink raw reply related
* [PATCH v4 2/5] ARM: KVM: arch_timers: Add minimal infrastructure
From: Christoffer Dall @ 2012-11-10 15:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121110154554.3274.77777.stgit@chazy-air>
From: Marc Zyngier <marc.zyngier@arm.com>
Add some very minimal architected timer related infrastructure.
For the moment, we just provide empty structures, and enable/disable
access to the physical timer across world switch.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <c.dall@virtualopensystems.com>
---
arch/arm/include/asm/kvm_arch_timer.h | 45 +++++++++++++++++++++++++++++++++
arch/arm/include/asm/kvm_host.h | 5 ++++
arch/arm/kvm/interrupts.S | 2 +
arch/arm/kvm/interrupts_head.S | 19 ++++++++++++++
4 files changed, 71 insertions(+)
create mode 100644 arch/arm/include/asm/kvm_arch_timer.h
diff --git a/arch/arm/include/asm/kvm_arch_timer.h b/arch/arm/include/asm/kvm_arch_timer.h
new file mode 100644
index 0000000..513b852
--- /dev/null
+++ b/arch/arm/include/asm/kvm_arch_timer.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2012 ARM Ltd.
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * 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.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __ASM_ARM_KVM_ARCH_TIMER_H
+#define __ASM_ARM_KVM_ARCH_TIMER_H
+
+struct arch_timer_kvm {
+};
+
+struct arch_timer_cpu {
+};
+
+#ifndef CONFIG_KVM_ARM_TIMER
+static inline int kvm_timer_hyp_init(void)
+{
+ return 0;
+};
+
+static inline int kvm_timer_init(struct kvm *kvm)
+{
+ return 0;
+}
+
+static inline void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) {}
+static inline void kvm_timer_sync_to_cpu(struct kvm_vcpu *vcpu) {}
+static inline void kvm_timer_sync_from_cpu(struct kvm_vcpu *vcpu) {}
+static inline void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu) {}
+#endif
+
+#endif
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 49ba25a..41012ef 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -24,6 +24,7 @@
#include <asm/fpstate.h>
#include <asm/kvm_decode.h>
#include <asm/kvm_vgic.h>
+#include <asm/kvm_arch_timer.h>
#define KVM_MAX_VCPUS CONFIG_KVM_ARM_MAX_VCPUS
#define KVM_MEMORY_SLOTS 32
@@ -48,6 +49,9 @@ struct kvm_arch {
/* VTTBR value associated with below pgd and vmid */
u64 vttbr;
+ /* Timer */
+ struct arch_timer_kvm timer;
+
/*
* Anything that is not used directly from assembly code goes
* here.
@@ -98,6 +102,7 @@ struct kvm_vcpu_arch {
/* VGIC state */
struct vgic_cpu vgic_cpu;
+ struct arch_timer_cpu timer_cpu;
/*
* Anything that is not used directly from assembly code goes
diff --git a/arch/arm/kvm/interrupts.S b/arch/arm/kvm/interrupts.S
index e418c9b..5a09e89 100644
--- a/arch/arm/kvm/interrupts.S
+++ b/arch/arm/kvm/interrupts.S
@@ -92,6 +92,7 @@ ENTRY(__kvm_vcpu_run)
save_host_regs
restore_vgic_state r0
+ restore_timer_state r0
@ Store hardware CP15 state and load guest state
read_cp15_state
@@ -186,6 +187,7 @@ after_vfp_restore:
read_cp15_state 1, r1
write_cp15_state
+ save_timer_state r1
save_vgic_state r1
restore_host_regs
diff --git a/arch/arm/kvm/interrupts_head.S b/arch/arm/kvm/interrupts_head.S
index c2423d8..0003aab 100644
--- a/arch/arm/kvm/interrupts_head.S
+++ b/arch/arm/kvm/interrupts_head.S
@@ -418,6 +418,25 @@
#endif
.endm
+#define CNTHCTL_PL1PCTEN (1 << 0)
+#define CNTHCTL_PL1PCEN (1 << 1)
+
+.macro save_timer_state vcpup
+ @ Allow physical timer/counter access for the host
+ mrc p15, 4, r2, c14, c1, 0 @ CNTHCTL
+ orr r2, r2, #(CNTHCTL_PL1PCEN | CNTHCTL_PL1PCTEN)
+ mcr p15, 4, r2, c14, c1, 0 @ CNTHCTL
+.endm
+
+.macro restore_timer_state vcpup
+ @ Disallow physical timer access for the guest
+ @ Physical counter access is allowed
+ mrc p15, 4, r2, c14, c1, 0 @ CNTHCTL
+ orr r2, r2, #CNTHCTL_PL1PCTEN
+ bic r2, r2, #CNTHCTL_PL1PCEN
+ mcr p15, 4, r2, c14, c1, 0 @ CNTHCTL
+.endm
+
/* Configures the HSTR (Hyp System Trap Register) on entry/return
* (hardware reset value is 0) */
.macro set_hstr entry
^ permalink raw reply related
* [PATCH v4 3/5] ARM: KVM: arch_timers: Add guest timer core support
From: Christoffer Dall @ 2012-11-10 15:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121110154554.3274.77777.stgit@chazy-air>
From: Marc Zyngier <marc.zyngier@arm.com>
We can inject a timer interrupt into the guest as a result of
three possible events:
- The virtual timer interrupt has fired while we were still
executing the guest
- The timer interrupt hasn't fired, but it expired while we
were doing the world switch
- A hrtimer we programmed earlier has fired
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <c.dall@virtualopensystems.com>
---
arch/arm/include/asm/kvm_arch_timer.h | 57 +++++++++
arch/arm/kvm/reset.c | 9 +
arch/arm/kvm/timer.c | 204 +++++++++++++++++++++++++++++++++
3 files changed, 269 insertions(+), 1 deletion(-)
create mode 100644 arch/arm/kvm/timer.c
diff --git a/arch/arm/include/asm/kvm_arch_timer.h b/arch/arm/include/asm/kvm_arch_timer.h
index 513b852..bd5e501 100644
--- a/arch/arm/include/asm/kvm_arch_timer.h
+++ b/arch/arm/include/asm/kvm_arch_timer.h
@@ -19,13 +19,68 @@
#ifndef __ASM_ARM_KVM_ARCH_TIMER_H
#define __ASM_ARM_KVM_ARCH_TIMER_H
+#include <linux/clocksource.h>
+#include <linux/hrtimer.h>
+#include <linux/workqueue.h>
+
struct arch_timer_kvm {
+#ifdef CONFIG_KVM_ARM_TIMER
+ /* Is the timer enabled */
+ bool enabled;
+
+ /*
+ * Virtual offset (kernel access it through cntvoff, HYP code
+ * access it as two 32bit values).
+ */
+ union {
+ cycle_t cntvoff;
+ struct {
+ u32 low; /* Restored only */
+ u32 high; /* Restored only */
+ } cntvoff32;
+ };
+#endif
};
struct arch_timer_cpu {
+#ifdef CONFIG_KVM_ARM_TIMER
+ /* Registers: control register, timer value */
+ u32 cntv_ctl; /* Saved/restored */
+ union {
+ cycle_t cntv_cval;
+ struct {
+ u32 low; /* Saved/restored */
+ u32 high; /* Saved/restored */
+ } cntv_cval32;
+ };
+
+ /*
+ * Anything that is not used directly from assembly code goes
+ * here.
+ */
+
+ /* Background timer used when the guest is not running */
+ struct hrtimer timer;
+
+ /* Work queued with the above timer expires */
+ struct work_struct expired;
+
+ /* Background timer active */
+ bool armed;
+
+ /* Timer IRQ */
+ const struct kvm_irq_level *irq;
+#endif
};
-#ifndef CONFIG_KVM_ARM_TIMER
+#ifdef CONFIG_KVM_ARM_TIMER
+int kvm_timer_hyp_init(void);
+int kvm_timer_init(struct kvm *kvm);
+void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu);
+void kvm_timer_sync_to_cpu(struct kvm_vcpu *vcpu);
+void kvm_timer_sync_from_cpu(struct kvm_vcpu *vcpu);
+void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu);
+#else
static inline int kvm_timer_hyp_init(void)
{
return 0;
diff --git a/arch/arm/kvm/reset.c b/arch/arm/kvm/reset.c
index b80256b..7463f5b 100644
--- a/arch/arm/kvm/reset.c
+++ b/arch/arm/kvm/reset.c
@@ -37,6 +37,12 @@ static struct kvm_regs a15_regs_reset = {
.usr_regs.ARM_cpsr = SVC_MODE | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT,
};
+#ifdef CONFIG_KVM_ARM_TIMER
+static const struct kvm_irq_level a15_virt_timer_ppi = {
+ { .irq = 27 }, /* irq: A7/A15 specific */
+ .level = 1 /* level */
+};
+#endif
/*******************************************************************************
* Exported reset function
@@ -59,6 +65,9 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
return -EINVAL;
cpu_reset = &a15_regs_reset;
vcpu->arch.midr = read_cpuid_id();
+#ifdef CONFIG_KVM_ARM_TIMER
+ vcpu->arch.timer_cpu.irq = &a15_virt_timer_ppi;
+#endif
break;
default:
return -ENODEV;
diff --git a/arch/arm/kvm/timer.c b/arch/arm/kvm/timer.c
new file mode 100644
index 0000000..a241298
--- /dev/null
+++ b/arch/arm/kvm/timer.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2012 ARM Ltd.
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * 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.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/of_irq.h>
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <linux/interrupt.h>
+
+#include <asm/arch_timer.h>
+
+#include <asm/kvm_vgic.h>
+#include <asm/kvm_arch_timer.h>
+
+static struct timecounter *timecounter;
+static struct workqueue_struct *wqueue;
+
+static cycle_t kvm_phys_timer_read(void)
+{
+ return timecounter->cc->read(timecounter->cc);
+}
+
+static void kvm_timer_inject_irq(struct kvm_vcpu *vcpu)
+{
+ struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+
+ timer->cntv_ctl |= 1 << 1; /* Mask the interrupt in the guest */
+ kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id,
+ vcpu->arch.timer_cpu.irq->irq,
+ vcpu->arch.timer_cpu.irq->level);
+}
+
+static irqreturn_t kvm_arch_timer_handler(int irq, void *dev_id)
+{
+ struct kvm_vcpu *vcpu = *(struct kvm_vcpu **)dev_id;
+
+ /*
+ * We disable the timer in the world switch and let it be
+ * handled by kvm_timer_sync_from_cpu(). Getting a timer
+ * interrupt at this point is a sure sign of some major
+ * breakage.
+ */
+ pr_warn("Unexpected interrupt %d on vcpu %p\n", irq, vcpu);
+ return IRQ_HANDLED;
+}
+
+static void kvm_timer_inject_irq_work(struct work_struct *work)
+{
+ struct kvm_vcpu *vcpu;
+
+ vcpu = container_of(work, struct kvm_vcpu, arch.timer_cpu.expired);
+ vcpu->arch.timer_cpu.armed = false;
+ kvm_timer_inject_irq(vcpu);
+}
+
+static enum hrtimer_restart kvm_timer_expire(struct hrtimer *hrt)
+{
+ struct arch_timer_cpu *timer;
+ timer = container_of(hrt, struct arch_timer_cpu, timer);
+ queue_work(wqueue, &timer->expired);
+ return HRTIMER_NORESTART;
+}
+
+void kvm_timer_sync_to_cpu(struct kvm_vcpu *vcpu)
+{
+ struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+
+ /*
+ * We're about to run this vcpu again, so there is no need to
+ * keep the background timer running, as we're about to
+ * populate the CPU timer again.
+ */
+ if (timer->armed) {
+ hrtimer_cancel(&timer->timer);
+ cancel_work_sync(&timer->expired);
+ timer->armed = false;
+ }
+}
+
+void kvm_timer_sync_from_cpu(struct kvm_vcpu *vcpu)
+{
+ struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+ cycle_t cval, now;
+ u64 ns;
+
+ /* Check if the timer is enabled and unmasked first */
+ if ((timer->cntv_ctl & 3) != 1)
+ return;
+
+ cval = timer->cntv_cval;
+ now = kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff;
+
+ BUG_ON(timer->armed);
+
+ if (cval <= now) {
+ /*
+ * Timer has already expired while we were not
+ * looking. Inject the interrupt and carry on.
+ */
+ kvm_timer_inject_irq(vcpu);
+ return;
+ }
+
+ timer->armed = true;
+ ns = cyclecounter_cyc2ns(timecounter->cc, cval - now);
+ hrtimer_start(&timer->timer, ktime_add_ns(ktime_get(), ns),
+ HRTIMER_MODE_ABS);
+}
+
+void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
+{
+ struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+
+ INIT_WORK(&timer->expired, kvm_timer_inject_irq_work);
+ hrtimer_init(&timer->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+ timer->timer.function = kvm_timer_expire;
+}
+
+static void kvm_timer_init_interrupt(void *info)
+{
+ unsigned int *irqp = info;
+
+ enable_percpu_irq(*irqp, 0);
+}
+
+
+static const struct of_device_id arch_timer_of_match[] = {
+ { .compatible = "arm,armv7-timer", },
+ {},
+};
+
+int kvm_timer_hyp_init(void)
+{
+ struct device_node *np;
+ unsigned int ppi;
+ int err;
+
+ timecounter = arch_timer_get_timecounter();
+ if (!timecounter)
+ return -ENODEV;
+
+ np = of_find_matching_node(NULL, arch_timer_of_match);
+ if (!np) {
+ kvm_err("kvm_arch_timer: can't find DT node\n");
+ return -ENODEV;
+ }
+
+ ppi = irq_of_parse_and_map(np, 2);
+ if (!ppi) {
+ kvm_err("kvm_arch_timer: no virtual timer interrupt\n");
+ return -EINVAL;
+ }
+
+ err = request_percpu_irq(ppi, kvm_arch_timer_handler,
+ "kvm guest timer", kvm_get_running_vcpus());
+ if (err) {
+ kvm_err("kvm_arch_timer: can't request interrupt %d (%d)\n",
+ ppi, err);
+ return err;
+ }
+
+ wqueue = create_singlethread_workqueue("kvm_arch_timer");
+ if (!wqueue) {
+ free_percpu_irq(ppi, kvm_get_running_vcpus());
+ return -ENOMEM;
+ }
+
+ kvm_info("%s IRQ%d\n", np->name, ppi);
+ on_each_cpu(kvm_timer_init_interrupt, &ppi, 1);
+
+ return 0;
+}
+
+void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
+{
+ struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+
+ hrtimer_cancel(&timer->timer);
+ cancel_work_sync(&timer->expired);
+}
+
+int kvm_timer_init(struct kvm *kvm)
+{
+ if (timecounter && wqueue) {
+ kvm->arch.timer.cntvoff = kvm_phys_timer_read();
+ kvm->arch.timer.enabled = 1;
+ }
+
+ return 0;
+}
^ permalink raw reply related
* [PATCH v4 4/5] ARM: KVM: arch_timers: Add timer world switch
From: Christoffer Dall @ 2012-11-10 15:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121110154554.3274.77777.stgit@chazy-air>
From: Marc Zyngier <marc.zyngier@arm.com>
Do the necessary save/restore dance for the timers in the world
switch code. In the process, allow the guest to read the physical
counter, which is useful for its own clock_event_device.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <c.dall@virtualopensystems.com>
---
arch/arm/kernel/asm-offsets.c | 8 ++++++++
arch/arm/kvm/arm.c | 3 +++
arch/arm/kvm/interrupts_head.S | 41 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 52 insertions(+)
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 39b6221..50df318 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -177,6 +177,14 @@ int main(void)
DEFINE(VGIC_CPU_APR, offsetof(struct vgic_cpu, vgic_apr));
DEFINE(VGIC_CPU_LR, offsetof(struct vgic_cpu, vgic_lr));
DEFINE(VGIC_CPU_NR_LR, offsetof(struct vgic_cpu, nr_lr));
+#ifdef CONFIG_KVM_ARM_TIMER
+ DEFINE(VCPU_TIMER_CNTV_CTL, offsetof(struct kvm_vcpu, arch.timer_cpu.cntv_ctl));
+ DEFINE(VCPU_TIMER_CNTV_CVALH, offsetof(struct kvm_vcpu, arch.timer_cpu.cntv_cval32.high));
+ DEFINE(VCPU_TIMER_CNTV_CVALL, offsetof(struct kvm_vcpu, arch.timer_cpu.cntv_cval32.low));
+ DEFINE(KVM_TIMER_CNTVOFF_H, offsetof(struct kvm, arch.timer.cntvoff32.high));
+ DEFINE(KVM_TIMER_CNTVOFF_L, offsetof(struct kvm, arch.timer.cntvoff32.low));
+ DEFINE(KVM_TIMER_ENABLED, offsetof(struct kvm, arch.timer.enabled));
+#endif
DEFINE(KVM_VGIC_VCTRL, offsetof(struct kvm, arch.vgic.vctrl_base));
#endif
DEFINE(KVM_VTTBR, offsetof(struct kvm, arch.vttbr));
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 1716f12..8cdef69 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -661,6 +661,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
update_vttbr(vcpu->kvm);
kvm_vgic_sync_to_cpu(vcpu);
+ kvm_timer_sync_to_cpu(vcpu);
local_irq_disable();
@@ -674,6 +675,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
if (ret <= 0 || need_new_vmid_gen(vcpu->kvm)) {
local_irq_enable();
+ kvm_timer_sync_from_cpu(vcpu);
kvm_vgic_sync_from_cpu(vcpu);
continue;
}
@@ -713,6 +715,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
* Back from guest
*************************************************************/
+ kvm_timer_sync_from_cpu(vcpu);
kvm_vgic_sync_from_cpu(vcpu);
ret = handle_exit(vcpu, run, ret);
diff --git a/arch/arm/kvm/interrupts_head.S b/arch/arm/kvm/interrupts_head.S
index 0003aab..ece84d1 100644
--- a/arch/arm/kvm/interrupts_head.S
+++ b/arch/arm/kvm/interrupts_head.S
@@ -422,6 +422,25 @@
#define CNTHCTL_PL1PCEN (1 << 1)
.macro save_timer_state vcpup
+#ifdef CONFIG_KVM_ARM_TIMER
+ ldr r4, [\vcpup, #VCPU_KVM]
+ ldr r2, [r4, #KVM_TIMER_ENABLED]
+ cmp r2, #0
+ beq 1f
+
+ mrc p15, 0, r2, c14, c3, 1 @ CNTV_CTL
+ and r2, #3
+ str r2, [\vcpup, #VCPU_TIMER_CNTV_CTL]
+ bic r2, #1 @ Clear ENABLE
+ mcr p15, 0, r2, c14, c3, 1 @ CNTV_CTL
+ isb
+
+ mrrc p15, 3, r2, r3, c14 @ CNTV_CVAL
+ str r3, [\vcpup, #VCPU_TIMER_CNTV_CVALH]
+ str r2, [\vcpup, #VCPU_TIMER_CNTV_CVALL]
+
+1:
+#endif
@ Allow physical timer/counter access for the host
mrc p15, 4, r2, c14, c1, 0 @ CNTHCTL
orr r2, r2, #(CNTHCTL_PL1PCEN | CNTHCTL_PL1PCTEN)
@@ -435,6 +454,28 @@
orr r2, r2, #CNTHCTL_PL1PCTEN
bic r2, r2, #CNTHCTL_PL1PCEN
mcr p15, 4, r2, c14, c1, 0 @ CNTHCTL
+
+#ifdef CONFIG_KVM_ARM_TIMER
+ ldr r4, [\vcpup, #VCPU_KVM]
+ ldr r2, [r4, #KVM_TIMER_ENABLED]
+ cmp r2, #0
+ beq 1f
+
+ ldr r3, [r4, #KVM_TIMER_CNTVOFF_H]
+ ldr r2, [r4, #KVM_TIMER_CNTVOFF_L]
+ mcrr p15, 4, r2, r3, c14 @ CNTVOFF
+ isb
+
+ ldr r3, [\vcpup, #VCPU_TIMER_CNTV_CVALH]
+ ldr r2, [\vcpup, #VCPU_TIMER_CNTV_CVALL]
+ mcrr p15, 3, r2, r3, c14 @ CNTV_CVAL
+
+ ldr r2, [\vcpup, #VCPU_TIMER_CNTV_CTL]
+ and r2, #3
+ mcr p15, 0, r2, c14, c3, 1 @ CNTV_CTL
+ isb
+1:
+#endif
.endm
/* Configures the HSTR (Hyp System Trap Register) on entry/return
^ permalink raw reply related
* [PATCH v4 5/5] ARM: KVM: arch_timers: Wire the init code and config option
From: Christoffer Dall @ 2012-11-10 15:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121110154554.3274.77777.stgit@chazy-air>
From: Marc Zyngier <marc.zyngier@arm.com>
It is now possible to select CONFIG_KVM_ARM_TIMER to enable the
KVM architected timer support.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <c.dall@virtualopensystems.com>
---
arch/arm/kvm/Kconfig | 7 +++++++
arch/arm/kvm/Makefile | 1 +
arch/arm/kvm/arm.c | 11 +++++++++++
arch/arm/kvm/vgic.c | 1 +
4 files changed, 20 insertions(+)
diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
index 3c979ce..eaecb9f 100644
--- a/arch/arm/kvm/Kconfig
+++ b/arch/arm/kvm/Kconfig
@@ -58,6 +58,13 @@ config KVM_ARM_VGIC
---help---
Adds support for a hardware assisted, in-kernel GIC emulation.
+config KVM_ARM_TIMER
+ bool "KVM support for Architected Timers"
+ depends on KVM_ARM_VGIC && ARM_ARCH_TIMER
+ select HAVE_KVM_IRQCHIP
+ ---help---
+ Adds support for the Architected Timers in virtual machines
+
source drivers/virtio/Kconfig
endif # VIRTUALIZATION
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
index c019f02..7c5a635 100644
--- a/arch/arm/kvm/Makefile
+++ b/arch/arm/kvm/Makefile
@@ -21,3 +21,4 @@ obj-$(CONFIG_KVM_ARM_HOST) += $(addprefix ../../../virt/kvm/, kvm_main.o coalesc
obj-$(CONFIG_KVM_ARM_HOST) += arm.o guest.o mmu.o emulate.o reset.o
obj-$(CONFIG_KVM_ARM_HOST) += coproc.o coproc_a15.o mmio.o decode.o
obj-$(CONFIG_KVM_ARM_VGIC) += vgic.o
+obj-$(CONFIG_KVM_ARM_TIMER) += timer.o
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 8cdef69..e62ba49 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -286,6 +286,7 @@ out:
void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
{
kvm_mmu_free_memory_caches(vcpu);
+ kvm_timer_vcpu_terminate(vcpu);
kmem_cache_free(kvm_vcpu_cache, vcpu);
}
@@ -323,6 +324,9 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
/* Set up VGIC */
kvm_vgic_vcpu_init(vcpu);
+ /* Set up the timer */
+ kvm_timer_vcpu_init(vcpu);
+
return 0;
}
@@ -1048,6 +1052,13 @@ static int init_hyp_mode(void)
if (!err)
vgic_present = true;
+ /*
+ * Init HYP architected timer support
+ */
+ err = kvm_timer_hyp_init();
+ if (err)
+ goto out_free_mappings;
+
return 0;
out_free_vfp:
free_percpu(kvm_host_vfp_state);
diff --git a/arch/arm/kvm/vgic.c b/arch/arm/kvm/vgic.c
index 146de1d..090ea79 100644
--- a/arch/arm/kvm/vgic.c
+++ b/arch/arm/kvm/vgic.c
@@ -1168,6 +1168,7 @@ int kvm_vgic_init(struct kvm *kvm)
for (i = 32; i < VGIC_NR_IRQS; i += 4)
vgic_set_target_reg(kvm, 0, i);
+ kvm_timer_init(kvm);
kvm->arch.vgic.ready = true;
out:
mutex_unlock(&kvm->lock);
^ permalink raw reply related
* [PATCH 1/4] mfd: ab8500: add devicetree support for fuelgauge
From: Francesco Lavra @ 2012-11-10 16:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.02.1211072354150.5888@ubuntu12>
On 11/07/2012 07:45 PM, Rajanikanth H V wrote:
> On Thu, 1 Nov 2012, Francesco Lavra wrote:
> [...]
>>> + btech = of_get_property(np_bat_supply,
>>> + "stericsson,battery-type", NULL);
>>> + if (!btech) {
>>> + dev_warn(dev, "missing property battery-name/type\n");
>>> + strcpy(bat_tech, "UNKNOWN");
>>> + } else {
>>> + strcpy(bat_tech, btech);
>>> + }
>>
>> I don't get the point of declaring the char array and copying the string
>> in it, when you could simply use just the pointer returned by
>> of_get_property().
>
> I am considering a corner case where in 'battery-type' property is not
> present and battery is connected.In this case i promote battery to
> UNKNOWN from null.
You could achieve the same result without using the char array, with
this assignment:
btech = "UNKNOWN";
> FYI: Further, btemp driver will identify the connected battery based on
> resistance value and decide to use.
> Ref: ab8500_btemp_id(...) ab8500_btemp.c
>
>> Anyway, if the string property is longer than 8 characters, you are
>> writing past the size of the destination array.
>
> i believe it is safe as power_supply.h comprises defines having battery
> technology type in 4 characters length which is normally the case and
> 7 chars length being "UNKNOWN" seldom referred
You should be able to handle whatever the device tree contains, and if
it contains unexpected data this is not a good excuse for locking up the
system.
--
Francesco
^ permalink raw reply
* [PATCH v3 4/4] ARM: OMAP: gpmc: add DT bindings for GPMC timings and NAND
From: Daniel Mack @ 2012-11-10 18:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <518397C60809E147AF5323E0420B992E3E9DE420@DBDE01.ent.ti.com>
On 07.11.2012 16:37, Philip, Avinash wrote:
> On Wed, Nov 07, 2012 at 15:18:37, Daniel Mack wrote:
>> On 05.11.2012 14:29, Philip, Avinash wrote:
>>> On Mon, Nov 05, 2012 at 18:28:22, Daniel Mack wrote:
>>>> On 05.11.2012 12:03, Philip, Avinash wrote:
>>>>> On Fri, Nov 02, 2012 at 20:55:56, Daniel Mack wrote:
>>>>>> This patch adds basic DT bindings for OMAP GPMC.
>>>>>>
>>>>>> The actual peripherals are instanciated from child nodes within the GPMC
>>>>>> node, and the only type of device that is currently supported is NAND.
>>>>>>
>>>>>> Code was added to parse the generic GPMC timing parameters and some
>>>>>> documentation with examples on how to use them.
>>>>>>
>>>>>> Successfully tested on an AM33xx board.
>>>>>>
>>>>>> Signed-off-by: Daniel Mack <zonque@gmail.com>
>>>>> [...]
>>>>>> +
>>>>>> + nand at 0,0 {
>>>>>> + reg = <0 0 0>; /* CS0, offset 0 */
>>>>>> + nand-bus-width = <16>;
>>>>>> + nand-ecc-mode = "none";
>>>>>> +
>>>>>> + gpmc,sync-clk = <0>;
>>>>>> + gpmc,cs-on = <0>;
>>>>>> + gpmc,cs-rd-off = <36>;
>>>>>> + gpmc,cs-wr-off = <36>;
>>>>>> + gpmc,adv-on = <6>;
>>>>>> + gpmc,adv-rd-off = <24>;
>>>>>> + gpmc,adv-wr-off = <36>;
>>>>>> + gpmc,we-off = <30>;
>>>>>> + gpmc,oe-off = <48>;
>>>>>> + gpmc,access = <54>;
>>>>>> + gpmc,rd-cycle = <72>;
>>>>>> + gpmc,wr-cycle = <72>;
>>>>>> + gpmc,wr-access = <30>;
>>>>>> + gpmc,wr-data-mux-bus = <0>;
>>>>>> +
>>>>>> + #address-cells = <1>;
>>>>>> + #size-cells = <1>;
>>>>>> +
>>>>>
>>>>> Can you take the timings (for example) from arago tree. The timings is tested in am335x-evm
>>>>> So the timings can be directly used to populate GPMC timings. Timings can found at
>>>>>
>>>>> http://arago-project.org/git/projects/?p=linux-am33x.git;a=commitdiff;
>>>>> h=66bfbd2c5b35dc81edce0c24843c476161ab5978;hp=370630359cb8db711cf0941cd2a242e28ccfb61e
>>>>>
>>>>> [...]
>>>>>> +static int gpmc_probe_dt(struct platform_device *pdev)
>>>>>
>>>>> Can you take care of the following section mismatch.
>>>>> WARNING: vmlinux.o(.text+0x1e2d0): Section mismatch in reference
>>>>> from the function gpmc_probe_dt() to the function .init.text:gpmc_nand_init().
>>>>
>>>> Sore, both fixed for v4.
>>>>
>>>>> [...]
>>>>>> +
>>>>>> + val = of_get_nand_ecc_mode(child);
>>>>>> + if (val >= 0)
>>>>>> + gpmc_nand_data->ecc_opt = val;
>>>>>
>>>>> This will fail for BCH. Index of "soft_bch" is 5 & also don't have selection
>>>>> option between for BCH4 & BCH8 also.
>>>>> Can you use the of_property_read_u32 (as done early) to pass the ecc selection
>>>>> from dt file. This will help selection of BCH4 & BCH8 ecc options.
>>>>
>>>> Hmm. Shouldn't we rather teach of_get_nand_ecc_mode() that two modes and
>>>> bring the enum in sync?
>>>
>>> ecc_opt is for selecting different ecc layout and not for selecting ecc mode.
>>>
>>> In omap2 driver NAND_ECC_HW ecc mode supports 3 ecc layout
>>> OMAP_ECC_HAMMING_CODE_HW_ROMCODE
>>> OMAP_ECC_BCH4_CODE_HW
>>> OMAP_ECC_BCH8_CODE_HW
>>>
>>> So selection of ecc layout data should come from DT not ecc mode.
>>
>> Ok, I see. I would still like to set them by string rather than magic
>> numbers that map to enum entries. Valid values would be "none", "hw",
>> "hw-romcode", "bch4" and "bch8". Are you ok with that?
>
> Ok, that's nice. Better use ecc_opt instead of ecc_mode.
I did some more extensive tests that include reading the same nand pages
from both U-Boot and the kernel with BCH8 ECC, and it turns out that
->is_elm_used needs to be set in the pdata in order to make this work.
So the question is whether we actually want to have a DT property for
that or just always enable that bit in case a hardware supported ecc
mode is selected. Any opinion on this?
That's the last topic before I'm clear to send off v4.
Thanks,
Daniel
^ permalink raw reply
* [PATCH v4 13/13] ARM: KVM: Add VGIC configuration option
From: Sergei Shtylyov @ 2012-11-10 19:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121110154546.3061.12922.stgit@chazy-air>
Hello.
On 10-11-2012 19:45, Christoffer Dall wrote:
> From: Marc Zyngier <marc.zyngier@arm.com>
> It is now possible to select the VGIC configuration option.
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> Signed-off-by: Christoffer Dall <c.dall@virtualopensystems.com>
> ---
> arch/arm/kvm/Kconfig | 7 +++++++
> 1 file changed, 7 insertions(+)
> diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
> index bfa3174..3c979ce 100644
> --- a/arch/arm/kvm/Kconfig
> +++ b/arch/arm/kvm/Kconfig
> @@ -51,6 +51,13 @@ config KVM_ARM_MAX_VCPUS
> large, so only choose a reasonable number that you expect to
> actually use.
>
> +config KVM_ARM_VGIC
> + bool "KVM support for Virtual GIC"
Indent with tabs uniformaly, please.
> + depends on KVM_ARM_HOST && OF
> + select HAVE_KVM_IRQCHIP
> + ---help---
> + Adds support for a hardware assisted, in-kernel GIC emulation.
> +
WBR, Sergei
^ permalink raw reply
* [PATCH v4 4/9] ARM: dts: support pinctrl single in pxa910
From: Tony Lindgren @ 2012-11-10 20:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAN1soZwDn3VXLCk=-LEVZcZYmRgXEN3WHp74Dr0qRAd83F+tuw@mail.gmail.com>
* Haojian Zhuang <haojian.zhuang@gmail.com> [121109 21:38]:
> On Sat, Nov 10, 2012 at 6:48 AM, Tony Lindgren <tony@atomide.com> wrote:
> > Hi,
> >
> > To clarify my binding change comment for the generic pinconf
> > support, here's an example.
> >
> > We need to move pinctrl-single pinconf properties here for
> > each pin group:
> >
> > * Haojian Zhuang <haojian.zhuang@gmail.com> [121107 07:21]:
> >> + uart1_pins: pinmux_uart1_pins {
> >> + pinctrl-single,pins = <
> >> + 0x198 0x6 /* GPIO47_UART1_RXD */
> >> + 0x19c 0x6 /* GPIO48_UART1_TXD */
> >> + >;
> >> + pinctrl-single,power-source = <0x2>;
> >> + pinctrl-single,bias = <0x6>;
> > pinctrl-single,power-source-mask = <0x1800>;
> > pinctrl-single,bias-mask = <0xe000>;
> > pinctrl-single,bias-disable = <0>;
> > pinctrl-single,bias-pull-down = <0xa000>;
> > pinctrl-single,bias-pull-up = <0xc000>;
> It's OK.
>
> >> + };
> >
> >
> >
> >> --- a/arch/arm/boot/dts/pxa910.dtsi
> >> +++ b/arch/arm/boot/dts/pxa910.dtsi
> >> @@ -54,6 +54,80 @@
> >> reg = <0xd4000000 0x00200000>;
> >> ranges;
> >>
> >> + pmx: pinmux at d401e000 {
> >> + compatible = "pinconf-single";
> >> + reg = <0xd401e000 0x0330>;
> >> + #address-cells = <1>;
> >> + #size-cells = <1>;
> >> + ranges;
> >> +
> >> + pinctrl-single,register-width = <32>;
> >> + pinctrl-single,function-mask = <7>;
> >
> > And then..
> >
> >> + pinctrl-single,power-source-mask = <0x1800>;
> >> + pinctrl-single,bias-mask = <0xe000>;
> >> + pinctrl-single,bias-disable = <0>;
> >> + pinctrl-single,bias-pull-down = <0xa000>;
> >> + pinctrl-single,bias-pull-up = <0xc000>;
> >> + pinctrl-single,input-schmitt-mask = <0x70>;
> >
> > ..remove these from here. Otherwise pinctrl-single,bits type controllers
> > won't be able to use the pinconf functions as we can have multiple pins
> > supported in a single register.
> >
> Will do
OK thanks!
Tony
^ permalink raw reply
* [PATCH 2/2] ARM: S3C64XX: Staticly define parent clock of "camera" clock
From: Sylwester Nawrocki @ 2012-11-10 21:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <509e6047.a766980a.0f91.14f6@mx.google.com>
On 11/10/2012 03:07 PM, dron0gus at gmail.com wrote:
> From: Andrey Gusakov<dron_gus@mail.ru>
>
> The "camera" clock have only one parent. Define it staticly and
> remove unused source clock list.
>
> Signed-off-by: Andrey Gusakov<dron0gus@gmail.com>
Reviewed-by: Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
^ permalink raw reply
* [PATCH 1/2] ARM: S3C64XX: Remove duplicated camera clock
From: Sylwester Nawrocki @ 2012-11-10 21:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <509e602f.a766980a.0f91.14f4@mx.google.com>
On 11/10/2012 03:07 PM, dron0gus at gmail.com wrote:
> From: Andrey Gusakov<dron_gus@mail.ru>
>
> Camera clock defined two times. One in init_clocks_off array with
> "cam" name, second in clksrcs array with "camera" name. Leave
> second definition because clock have divider.
>
> Signed-off-by: Andrey Gusakov<dron0gus@gmail.com>
Reviewed-by: Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
^ permalink raw reply
* [PATCH 2/2] ARM: S3C64XX: Staticly define parent clock of "camera" clock
From: Sylwester Nawrocki @ 2012-11-10 21:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <509EC391.9090506@gmail.com>
On 11/10/2012 10:13 PM, Sylwester Nawrocki wrote:
> On 11/10/2012 03:07 PM, dron0gus at gmail.com wrote:
>> From: Andrey Gusakov<dron_gus@mail.ru>
>>
>> The "camera" clock have only one parent. Define it staticly and
Forgot to point out a small typo here: staticly -> statically.
>> remove unused source clock list.
>>
>> Signed-off-by: Andrey Gusakov<dron0gus@gmail.com>
>
> Reviewed-by: Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
^ permalink raw reply
* [PATCH v5 0/4] arch/arm: support seccomp
From: Kees Cook @ 2012-11-10 22:44 UTC (permalink / raw)
To: linux-arm-kernel
This adds support for seccomp BPF to ARM. When built with the seccomp
improvement patch waiting in linux-next ("seccomp: Make syscall skipping
and nr changes more consistent"), this passes the seccomp regression
test suite: https://github.com/redpig/seccomp
Thanks,
-Kees
---
v5:
- clean up seccomp failure path, as requested by Will Deacon.
v4:
- fixed syscall_get_arch, thanks to Will Deacon.
v3:
- updates suggested by Russell King:
- reduced scope of expansion
- leveraged TIF_SYSCALL_WORK bit mask
- fixed syscall==-1 short-circuit logic
v2:
- expanded ptrace_syscall_trace() into both callers and do
secure_computing() hookup there, as requested by Al Viro.
^ permalink raw reply
* [PATCH 1/4] arch/arm: add syscall_get_arch
From: Kees Cook @ 2012-11-10 22:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1352587485-18348-1-git-send-email-keescook@chromium.org>
From: Will Drewry <wad@chromium.org>
Provide an ARM implementation of syscall_get_arch. This is a pre-requisite
for CONFIG_HAVE_ARCH_SECCOMP_FILTER.
Signed-off-by: Will Drewry <wad@chromium.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
arch/arm/include/asm/syscall.h | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/arm/include/asm/syscall.h b/arch/arm/include/asm/syscall.h
index 9fdded6..f1d96d4 100644
--- a/arch/arm/include/asm/syscall.h
+++ b/arch/arm/include/asm/syscall.h
@@ -7,6 +7,8 @@
#ifndef _ASM_ARM_SYSCALL_H
#define _ASM_ARM_SYSCALL_H
+#include <linux/audit.h> /* for AUDIT_ARCH_* */
+#include <linux/elf.h> /* for ELF_EM */
#include <linux/err.h>
#include <linux/sched.h>
@@ -95,4 +97,11 @@ static inline void syscall_set_arguments(struct task_struct *task,
memcpy(®s->ARM_r0 + i, args, n * sizeof(args[0]));
}
+static inline int syscall_get_arch(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ /* ARM tasks don't change audit architectures on the fly. */
+ return AUDIT_ARCH_ARM;
+}
+
#endif /* _ASM_ARM_SYSCALL_H */
--
1.7.9.5
^ permalink raw reply related
* [PATCH 2/4] arch/arm: move secure_computing into trace
From: Kees Cook @ 2012-11-10 22:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1352587485-18348-1-git-send-email-keescook@chromium.org>
There is very little difference in the TIF_SECCOMP and TIF_SYSCALL_WORK
path in entry-common.S, so merge TIF_SECCOMP into TIF_SYSCALL_WORK and
move seccomp into the syscall_trace_enter() handler.
Expanded some of the tracehook logic into the callers to make this code
more readable. Since tracehook needs to do register changing, this portion
is best left in its own function instead of copy/pasting into the callers.
Additionally, the return value for secure_computing() is now checked
and a -1 value will result in the system call being skipped.
Signed-off-by: Kees Cook <keescook@chromium.org>
---
arch/arm/include/asm/thread_info.h | 7 ++++---
arch/arm/kernel/entry-common.S | 10 ----------
arch/arm/kernel/ptrace.c | 29 ++++++++++++++++++++---------
3 files changed, 24 insertions(+), 22 deletions(-)
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index 8477b4c..cddda1f 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -151,10 +151,10 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
#define TIF_SYSCALL_TRACE 8
#define TIF_SYSCALL_AUDIT 9
#define TIF_SYSCALL_TRACEPOINT 10
+#define TIF_SECCOMP 11 /* seccomp syscall filtering active */
#define TIF_USING_IWMMXT 17
#define TIF_MEMDIE 18 /* is terminating due to OOM killer */
#define TIF_RESTORE_SIGMASK 20
-#define TIF_SECCOMP 21
#define TIF_SWITCH_MM 22 /* deferred switch_mm */
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
@@ -163,11 +163,12 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
-#define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT)
#define _TIF_SECCOMP (1 << TIF_SECCOMP)
+#define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT)
/* Checks for any syscall work in entry-common.S */
-#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SYSCALL_TRACEPOINT)
+#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
+ _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP)
/*
* Change these and you break ASM code in entry-common.S
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 3471175..8355d4b 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -417,16 +417,6 @@ local_restart:
ldr r10, [tsk, #TI_FLAGS] @ check for syscall tracing
stmdb sp!, {r4, r5} @ push fifth and sixth args
-#ifdef CONFIG_SECCOMP
- tst r10, #_TIF_SECCOMP
- beq 1f
- mov r0, scno
- bl __secure_computing
- add r0, sp, #S_R0 + S_OFF @ pointer to regs
- ldmia r0, {r0 - r3} @ have to reload r0 - r3
-1:
-#endif
-
tst r10, #_TIF_SYSCALL_WORK @ are we tracing syscalls?
bne __sys_trace
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 739db3a..518536d 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -916,16 +916,11 @@ enum ptrace_syscall_dir {
PTRACE_SYSCALL_EXIT,
};
-static int ptrace_syscall_trace(struct pt_regs *regs, int scno,
- enum ptrace_syscall_dir dir)
+static int tracehook_report_syscall(struct pt_regs *regs,
+ enum ptrace_syscall_dir dir)
{
unsigned long ip;
- current_thread_info()->syscall = scno;
-
- if (!test_thread_flag(TIF_SYSCALL_TRACE))
- return scno;
-
/*
* IP is used to denote syscall entry/exit:
* IP = 0 -> entry, =1 -> exit
@@ -944,19 +939,35 @@ static int ptrace_syscall_trace(struct pt_regs *regs, int scno,
asmlinkage int syscall_trace_enter(struct pt_regs *regs, int scno)
{
- scno = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_ENTER);
+ current_thread_info()->syscall = scno;
+
+ /* Do the secure computing check first; failures should be fast. */
+ if (secure_computing(scno) == -1)
+ return -1;
+
+ if (test_thread_flag(TIF_SYSCALL_TRACE))
+ scno = tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER);
+
if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
trace_sys_enter(regs, scno);
+
audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0, regs->ARM_r1,
regs->ARM_r2, regs->ARM_r3);
+
return scno;
}
asmlinkage int syscall_trace_exit(struct pt_regs *regs, int scno)
{
- scno = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_EXIT);
+ current_thread_info()->syscall = scno;
+
+ if (test_thread_flag(TIF_SYSCALL_TRACE))
+ scno = tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT);
+
if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
trace_sys_exit(regs, scno);
+
audit_syscall_exit(regs);
+
return scno;
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH 3/4] arch/arm: allow a scno of -1 to not cause a SIGILL
From: Kees Cook @ 2012-11-10 22:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1352587485-18348-1-git-send-email-keescook@chromium.org>
On tracehook-friendly platforms, a system call number of -1 falls
through without running much code or taking much action.
ARM is different. This adds a short-circuit check in the trace path to
avoid any additional work, as suggested by Russell King, to make sure
that ARM behaves the same way as other platforms.
Signed-off-by: Kees Cook <keescook@chromium.org>
---
arch/arm/kernel/entry-common.S | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 8355d4b..0bef977 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -448,7 +448,10 @@ __sys_trace:
ldmccia r1, {r0 - r6} @ have to reload r0 - r6
stmccia sp, {r4, r5} @ and update the stack args
ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
- b 2b
+ cmp scno, #-1 @ skip the syscall?
+ bne 2b
+ add sp, sp, #S_OFF @ restore stack
+ b ret_slow_syscall
__sys_trace_return:
str r0, [sp, #S_R0 + S_OFF]! @ save returned r0
--
1.7.9.5
^ permalink raw reply related
* [PATCH 4/4] arch/arm: select HAVE_ARCH_SECCOMP_FILTER
From: Kees Cook @ 2012-11-10 22:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1352587485-18348-1-git-send-email-keescook@chromium.org>
From: Will Drewry <wad@chromium.org>
Reflect architectural support for seccomp filter.
Signed-off-by: Will Drewry <wad@chromium.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
arch/arm/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index ade7e92..0e8d490 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -21,6 +21,7 @@ config ARM
select HAVE_AOUT
select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL
select HAVE_ARCH_KGDB
+ select HAVE_ARCH_SECCOMP_FILTER
select HAVE_ARCH_TRACEHOOK
select HAVE_BPF_JIT
select HAVE_C_RECORDMCOUNT
--
1.7.9.5
^ permalink raw reply related
* [RFC] dt/platform: Use cell-index for device naming if available
From: Rob Herring @ 2012-11-11 2:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1352508532-19241-1-git-send-email-stepanm@codeaurora.org>
On 11/09/2012 06:48 PM, Stepan Moskovchenko wrote:
> Use the cell-index property to construct names for platform
> devices, falling back on the existing scheme of using the
> device register address if cell-index is not specified.
>
> The cell-index property is a more useful device identifier,
> especially in systems containing several numbered instances
> of a particular hardware block, since it more easily
> illustrates how devices relate to each other.
>
> Additionally, userspace software may rely on the classic
> <name>.<id> naming scheme to access device attributes in
> sysfs, without having to know the physical addresses of
> that device on every platform the userspace software may
> support. Using cell-index for device naming allows the
> device addresses to be hidden from userspace and to be
> exposed by logical device number without having to rely on
> auxdata to perform name overrides. This allows userspace to
> make assumptions about which sysfs nodes map to which
> logical instance of a specific hardware block.
>
> Signed-off-by: Stepan Moskovchenko <stepanm@codeaurora.org>
> ---
> I had also considered using something like the linux,label property to allow
> custom names for platform devices without resorting to auxdata, but the
> cell-index approach seems more in line with what cell-index was intended for
> and with what the pre-DT platform device naming scheme used to be. Please let
> me know if you think there is a better way to accomplish this.
>
> This is just being sent out as an RFC for now. If there are no objections, I
> will send this out as an official patch, along with (or combined with) a patch
> to fix up the device names in things like clock tables of any affected
> platforms.
cell-index is basically deprecated. This has been discussed multiple
times in the past. You can use auxdata if you really need to have the
old name.
Rob
>
> drivers/of/platform.c | 13 ++++++++++++-
> 1 files changed, 12 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> index 343ad29..472e374 100644
> --- a/drivers/of/platform.c
> +++ b/drivers/of/platform.c
> @@ -77,8 +77,9 @@ void of_device_make_bus_id(struct device *dev)
> static atomic_t bus_no_reg_magic;
> struct device_node *node = dev->of_node;
> const u32 *reg;
> + u32 cell_index;
> u64 addr;
> - int magic;
> + int magic, ret;
>
> #ifdef CONFIG_PPC_DCR
> /*
> @@ -101,6 +102,16 @@ void of_device_make_bus_id(struct device *dev)
> #endif /* CONFIG_PPC_DCR */
>
> /*
> + * For devices with a specified cell-index, use the traditional
> + * naming scheme of <name>.<id>
> + */
> + ret = of_property_read_u32(node, "cell-index", &cell_index);
> + if (ret == 0) {
> + dev_set_name(dev, "%s.%d", node->name, cell_index);
> + return;
> + }
> +
> + /*
> * For MMIO, get the physical address
> */
> reg = of_get_property(node, "reg", NULL);
> --
> The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> hosted by The Linux Foundation
>
^ permalink raw reply
* [PATCH] ARM: implement optimized percpu variable access
From: Rob Herring @ 2012-11-11 3:20 UTC (permalink / raw)
To: linux-arm-kernel
From: Rob Herring <rob.herring@calxeda.com>
Use the previously unused TPIDRPRW register to store percpu offsets.
TPIDRPRW is only accessible in PL1, so it can only be used in the kernel.
This saves 2 loads for each percpu variable access which should yield
improved performance, but the improvement has not been quantified.
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
arch/arm/include/asm/Kbuild | 1 -
arch/arm/include/asm/percpu.h | 44 +++++++++++++++++++++++++++++++++++++++++
arch/arm/kernel/smp.c | 3 +++
3 files changed, 47 insertions(+), 1 deletion(-)
create mode 100644 arch/arm/include/asm/percpu.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index f70ae17..2ffdaac 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -16,7 +16,6 @@ generic-y += local64.h
generic-y += msgbuf.h
generic-y += param.h
generic-y += parport.h
-generic-y += percpu.h
generic-y += poll.h
generic-y += resource.h
generic-y += sections.h
diff --git a/arch/arm/include/asm/percpu.h b/arch/arm/include/asm/percpu.h
new file mode 100644
index 0000000..9eb7372
--- /dev/null
+++ b/arch/arm/include/asm/percpu.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2012 Calxeda, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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/>.
+ */
+#ifndef _ASM_ARM_PERCPU_H_
+#define _ASM_ARM_PERCPU_H_
+
+/*
+ * Same as asm-generic/percpu.h, except that we store the per cpu offset
+ * in the TPIDRPRW.
+ */
+#if defined(CONFIG_SMP) && (__LINUX_ARM_ARCH__ >= 6)
+
+static inline void set_my_cpu_offset(unsigned long off)
+{
+ asm volatile("mcr p15, 0, %0, c13, c0, 4 @ set TPIDRPRW" : : "r" (off) : "cc" );
+}
+
+static inline unsigned long __my_cpu_offset(void)
+{
+ unsigned long off;
+ asm("mrc p15, 0, %0, c13, c0, 4 @ get TPIDRPRW" : "=r" (off) : );
+ return off;
+}
+#define __my_cpu_offset __my_cpu_offset()
+#else
+#define set_my_cpu_offset(x) do {} while(0)
+
+#endif /* CONFIG_SMP */
+
+#include <asm-generic/percpu.h>
+
+#endif /* _ASM_ARM_PERCPU_H_ */
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index fbc8b26..897ef60 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -313,6 +313,8 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
current->active_mm = mm;
cpumask_set_cpu(cpu, mm_cpumask(mm));
+ set_my_cpu_offset(per_cpu_offset(cpu));
+
printk("CPU%u: Booted secondary processor\n", cpu);
cpu_init();
@@ -371,6 +373,7 @@ void __init smp_cpus_done(unsigned int max_cpus)
void __init smp_prepare_boot_cpu(void)
{
+ set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
}
void __init smp_prepare_cpus(unsigned int max_cpus)
--
1.7.10.4
^ permalink raw reply related
* [PATCH 00/14] ARM: SPEAr: DT updates
From: Viresh Kumar @ 2012-11-11 4:39 UTC (permalink / raw)
To: linux-arm-kernel
Hi Arnd/Olof,
These are DT updates for SPEAr SoCs. There aren't any fixes that we want to get
into 3.7-rc* and we are happy with 3.8.
Please apply them from mail, as i wouldn't be hosting them in my repo.
Some of the dtbs which use gpiopinctrl have dependency on Linus's pinctrl tree,
where an earlier update for adding gpiopinctrl node is present.
Deepak Sikri (1):
ARM: SPEAr: DT: Modify DT bindings for STMMAC
Shiraz Hashim (7):
pinctrl: SPEAr: add spi chipselect control driver
ARM: SPEAr13xx: DT: Add spics gpio controller nodes
ARM: SPEAr: DT: Update device nodes
ARM: SPEAr13xx: Remove fields not required for ssp controller
ARM: SPEAr3xx: shirq: simplify and move the shared irq multiplexor to
DT
ARM: SPEAr3xx: DT: add shirq node for interrupt multiplexor
ARM: SPEAr320: DT: Add SPEAr 320 HMI board support
Vipin Kumar (1):
ARM: SPEAr: DT: Update partition info for MTD devices
Vipul Kumar Samar (5):
ARM: SPEAr: DT: Update pinctrl list
ARM: SPEAr: DT: Fix existing DT support
ARM: SPEAr: DT: add uart state to fix warning
ARM: SPEAr1310: Move 1310 specific misc register into machine
specific files
ARM: SPEAr1310: Fix AUXDATA for compact flash controller
.../devicetree/bindings/arm/spear/shirq.txt | 48 ++++
.../bindings/pinctrl/pinctrl_spear_spics.txt | 50 ++++
arch/arm/boot/dts/Makefile | 3 +-
arch/arm/boot/dts/spear1310-evb.dts | 171 ++++++++++--
arch/arm/boot/dts/spear1310.dtsi | 32 ++-
arch/arm/boot/dts/spear1340-evb.dts | 262 ++++++++++++++++--
arch/arm/boot/dts/spear1340.dtsi | 61 +++++
arch/arm/boot/dts/spear13xx.dtsi | 72 ++++-
arch/arm/boot/dts/spear300-evb.dts | 20 +-
arch/arm/boot/dts/spear300.dtsi | 14 +-
arch/arm/boot/dts/spear310-evb.dts | 30 +-
arch/arm/boot/dts/spear310.dtsi | 18 ++
arch/arm/boot/dts/spear320-evb.dts | 35 ++-
arch/arm/boot/dts/spear320-hmi.dts | 305 +++++++++++++++++++++
arch/arm/boot/dts/spear320.dtsi | 39 ++-
arch/arm/boot/dts/spear3xx.dtsi | 5 +-
arch/arm/boot/dts/spear600-evb.dts | 46 +++-
arch/arm/boot/dts/spear600.dtsi | 16 ++
arch/arm/mach-spear13xx/include/mach/spear.h | 8 -
arch/arm/mach-spear13xx/spear1310.c | 16 +-
arch/arm/mach-spear13xx/spear13xx.c | 2 -
arch/arm/mach-spear3xx/include/mach/irqs.h | 10 +-
arch/arm/mach-spear3xx/spear300.c | 103 -------
arch/arm/mach-spear3xx/spear310.c | 202 --------------
arch/arm/mach-spear3xx/spear320.c | 205 +-------------
arch/arm/mach-spear3xx/spear3xx.c | 4 +
arch/arm/plat-spear/include/plat/shirq.h | 35 +--
arch/arm/plat-spear/shirq.c | 305 +++++++++++++++++----
drivers/clk/spear/spear1310_clock.c | 1 +
drivers/pinctrl/spear/Makefile | 4 +-
drivers/pinctrl/spear/pinctrl-spics.c | 217 +++++++++++++++
31 files changed, 1638 insertions(+), 701 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/spear/shirq.txt
create mode 100644 Documentation/devicetree/bindings/pinctrl/pinctrl_spear_spics.txt
create mode 100644 arch/arm/boot/dts/spear320-hmi.dts
create mode 100644 drivers/pinctrl/spear/pinctrl-spics.c
--
1.7.12.rc2.18.g61b472e
^ permalink raw reply
* [PATCH 01/14] pinctrl: SPEAr: add spi chipselect control driver
From: Viresh Kumar @ 2012-11-11 4:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1352608333.git.viresh.kumar@linaro.org>
From: Shiraz Hashim <shiraz.hashim@st.com>
SPEAr platform provides a provision to control chipselects of ARM PL022
Prime Cell spi controller through its system registers, which otherwise
remains under PL022 control which some protocols do not want.
This commit intends to provide the spi chipselect control in software
over gpiolib interface. Since it is tied to pinctrl, we place it under
'drivers/pinctrl/spear/' directory.
spi chip drivers can use the exported gpiolib interface to define their
chipselect through DT or platform data.
Cc: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Shiraz Hashim <shiraz.hashim@st.com>
Reviewed-by: Vipin Kumar <vipin.kumar@st.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
.../bindings/pinctrl/pinctrl_spear_spics.txt | 50 +++++
drivers/pinctrl/spear/Makefile | 4 +-
drivers/pinctrl/spear/pinctrl-spics.c | 217 +++++++++++++++++++++
3 files changed, 269 insertions(+), 2 deletions(-)
create mode 100644 Documentation/devicetree/bindings/pinctrl/pinctrl_spear_spics.txt
create mode 100644 drivers/pinctrl/spear/pinctrl-spics.c
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl_spear_spics.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl_spear_spics.txt
new file mode 100644
index 0000000..1c81280
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl_spear_spics.txt
@@ -0,0 +1,50 @@
+=== ST Microelectronics SPEAr SPI CS Driver ===
+
+SPEAr platform provides a provision to control chipselects of ARM PL022 Prime
+Cell spi controller through its system registers, which otherwise remains under
+PL022 control. If chipselect remain under PL022 control then they would be
+released as soon as transfer is over and TxFIFO becomes empty. This is not
+desired by some of the device protocols above spi which expect (multiple)
+transfers without releasing their chipselects.
+
+Chipselects can be controlled by software by turning them as GPIOs. SPEAr
+provides another interface through system registers through which software can
+directly control each PL022 chipselect. Hence, it is natural for SPEAr to export
+the control of this interface as gpio.
+
+Required properties:
+
+ * compatible: should be defined as "st,spear-pinctrl-spics"
+ * reg: mentioning address range of spics controller
+ * st-spics,peripcfg-reg: peripheral configuration register offset
+ * st-spics,sw-enable-bit: bit offset to enable sw control
+ * st-spics,cs-value-bit: bit offset to drive chipselect low or high
+ * st-spics,cs-enable-mask: chip select number bit mask
+ * st-spics,cs-enable-shift: chip select number program offset
+ * gpio-controller: Marks the device node as gpio controller
+ * #gpio-cells: should be 1 and will mention chip select number
+
+All the above bit offsets are within peripcfg register.
+
+Example:
+-------
+spics: spics at e0700000{
+ compatible = "st,spear-spics-gpio";
+ reg = <0xe0700000 0x1000>;
+ st-spics,peripcfg-reg = <0x3b0>;
+ st-spics,sw-enable-bit = <12>;
+ st-spics,cs-value-bit = <11>;
+ st-spics,cs-enable-mask = <3>;
+ st-spics,cs-enable-shift = <8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+};
+
+
+spi0: spi at e0100000 {
+ status = "okay";
+ num-cs = <3>;
+ cs-gpios = <&gpio1 7 0>, <&spics 0>,
+ <&spics 1>;
+ ...
+}
diff --git a/drivers/pinctrl/spear/Makefile b/drivers/pinctrl/spear/Makefile
index b28a7ba..6caec55 100644
--- a/drivers/pinctrl/spear/Makefile
+++ b/drivers/pinctrl/spear/Makefile
@@ -5,5 +5,5 @@ obj-$(CONFIG_PINCTRL_SPEAR3XX) += pinctrl-spear3xx.o
obj-$(CONFIG_PINCTRL_SPEAR300) += pinctrl-spear300.o
obj-$(CONFIG_PINCTRL_SPEAR310) += pinctrl-spear310.o
obj-$(CONFIG_PINCTRL_SPEAR320) += pinctrl-spear320.o
-obj-$(CONFIG_PINCTRL_SPEAR1310) += pinctrl-spear1310.o
-obj-$(CONFIG_PINCTRL_SPEAR1340) += pinctrl-spear1340.o
+obj-$(CONFIG_PINCTRL_SPEAR1310) += pinctrl-spear1310.o pinctrl-spics.o
+obj-$(CONFIG_PINCTRL_SPEAR1340) += pinctrl-spear1340.o pinctrl-spics.o
diff --git a/drivers/pinctrl/spear/pinctrl-spics.c b/drivers/pinctrl/spear/pinctrl-spics.c
new file mode 100644
index 0000000..5f45fc4
--- /dev/null
+++ b/drivers/pinctrl/spear/pinctrl-spics.c
@@ -0,0 +1,217 @@
+/*
+ * SPEAr platform SPI chipselect abstraction over gpiolib
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Shiraz Hashim <shiraz.hashim@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+/* maximum chipselects */
+#define NUM_OF_GPIO 4
+
+/*
+ * Provision is available on some SPEAr SoCs to control ARM PL022 spi cs
+ * through system registers. This register lies outside spi (pl022)
+ * address space into system registers.
+ *
+ * It provides control for spi chip select lines so that any chipselect
+ * (out of 4 possible chipselects in pl022) can be made low to select
+ * the particular slave.
+ */
+
+/**
+ * struct spear_spics - represents spi chip select control
+ * @base: base address
+ * @perip_cfg: configuration register
+ * @sw_enable_bit: bit to enable s/w control over chipselects
+ * @cs_value_bit: bit to program high or low chipselect
+ * @cs_enable_mask: mask to select bits required to select chipselect
+ * @cs_enable_shift: bit pos of cs_enable_mask
+ * @use_count: use count of a spi controller cs lines
+ * @last_off: stores last offset caller of set_value()
+ * @chip: gpio_chip abstraction
+ */
+struct spear_spics {
+ void __iomem *base;
+ u32 perip_cfg;
+ u32 sw_enable_bit;
+ u32 cs_value_bit;
+ u32 cs_enable_mask;
+ u32 cs_enable_shift;
+ unsigned long use_count;
+ int last_off;
+ struct gpio_chip chip;
+};
+
+/* gpio framework specific routines */
+static int spics_get_value(struct gpio_chip *chip, unsigned offset)
+{
+ return -ENXIO;
+}
+
+static void spics_set_value(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct spear_spics *spics = container_of(chip, struct spear_spics,
+ chip);
+ u32 tmp;
+
+ /* select chip select from register */
+ tmp = readl_relaxed(spics->base + spics->perip_cfg);
+ if (spics->last_off != offset) {
+ spics->last_off = offset;
+ tmp &= ~(spics->cs_enable_mask << spics->cs_enable_shift);
+ tmp |= offset << spics->cs_enable_shift;
+ }
+
+ /* toggle chip select line */
+ tmp &= ~(0x1 << spics->cs_value_bit);
+ tmp |= value << spics->cs_value_bit;
+ writel_relaxed(tmp, spics->base + spics->perip_cfg);
+}
+
+static int spics_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ return -ENXIO;
+}
+
+static int spics_direction_output(struct gpio_chip *chip, unsigned offset,
+ int value)
+{
+ spics_set_value(chip, offset, value);
+ return 0;
+}
+
+static int spics_request(struct gpio_chip *chip, unsigned offset)
+{
+ struct spear_spics *spics = container_of(chip, struct spear_spics,
+ chip);
+ u32 tmp;
+
+ if (!spics->use_count++) {
+ tmp = readl_relaxed(spics->base + spics->perip_cfg);
+ tmp |= 0x1 << spics->sw_enable_bit;
+ tmp |= 0x1 << spics->cs_value_bit;
+ writel_relaxed(tmp, spics->base + spics->perip_cfg);
+ }
+
+ return 0;
+}
+
+static void spics_free(struct gpio_chip *chip, unsigned offset)
+{
+ struct spear_spics *spics = container_of(chip, struct spear_spics,
+ chip);
+ u32 tmp;
+
+ if (!--spics->use_count) {
+ tmp = readl_relaxed(spics->base + spics->perip_cfg);
+ tmp &= ~(0x1 << spics->sw_enable_bit);
+ writel_relaxed(tmp, spics->base + spics->perip_cfg);
+ }
+}
+
+static int spics_gpio_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct spear_spics *spics;
+ struct resource *res;
+ int ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "invalid IORESOURCE_MEM\n");
+ return -EBUSY;
+ }
+
+ spics = devm_kzalloc(&pdev->dev, sizeof(*spics), GFP_KERNEL);
+ if (!spics) {
+ dev_err(&pdev->dev, "memory allocation fail\n");
+ return -ENOMEM;
+ }
+
+ spics->base = devm_request_and_ioremap(&pdev->dev, res);
+ if (!spics->base) {
+ dev_err(&pdev->dev, "request and ioremap fail\n");
+ return -ENOMEM;
+ }
+
+ if (of_property_read_u32(np, "st-spics,peripcfg-reg",
+ &spics->perip_cfg))
+ goto err_dt_data;
+ if (of_property_read_u32(np, "st-spics,sw-enable-bit",
+ &spics->sw_enable_bit))
+ goto err_dt_data;
+ if (of_property_read_u32(np, "st-spics,cs-value-bit",
+ &spics->cs_value_bit))
+ goto err_dt_data;
+ if (of_property_read_u32(np, "st-spics,cs-enable-mask",
+ &spics->cs_enable_mask))
+ goto err_dt_data;
+ if (of_property_read_u32(np, "st-spics,cs-enable-shift",
+ &spics->cs_enable_shift))
+ goto err_dt_data;
+
+ platform_set_drvdata(pdev, spics);
+
+ spics->chip.ngpio = NUM_OF_GPIO;
+ spics->chip.base = -1;
+ spics->chip.request = spics_request;
+ spics->chip.free = spics_free;
+ spics->chip.direction_input = spics_direction_input;
+ spics->chip.direction_output = spics_direction_output;
+ spics->chip.get = spics_get_value;
+ spics->chip.set = spics_set_value;
+ spics->chip.label = dev_name(&pdev->dev);
+ spics->chip.dev = &pdev->dev;
+ spics->chip.owner = THIS_MODULE;
+ spics->last_off = -1;
+
+ ret = gpiochip_add(&spics->chip);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to add gpio chip\n");
+ return ret;
+ }
+
+ dev_info(&pdev->dev, "spear spics registered\n");
+ return 0;
+
+err_dt_data:
+ dev_err(&pdev->dev, "DT probe failed\n");
+ return -EINVAL;
+}
+
+static const struct of_device_id spics_gpio_of_match[] = {
+ { .compatible = "st,spear-spics-gpio" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, spics_gpio_of_match);
+
+static struct platform_driver spics_gpio_driver = {
+ .probe = spics_gpio_probe,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "spear-spics-gpio",
+ .of_match_table = spics_gpio_of_match,
+ },
+};
+
+static int __init spics_gpio_init(void)
+{
+ return platform_driver_register(&spics_gpio_driver);
+}
+subsys_initcall(spics_gpio_init);
+
+MODULE_AUTHOR("Shiraz Hashim <shiraz.hashim@st.com>");
+MODULE_DESCRIPTION("ST Microlectronics SPEAr SPI Chip Select Abstraction");
+MODULE_LICENSE("GPL");
--
1.7.12.rc2.18.g61b472e
^ permalink raw reply related
* [PATCH 02/14] ARM: SPEAr13xx: DT: Add spics gpio controller nodes
From: Viresh Kumar @ 2012-11-11 4:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1352608333.git.viresh.kumar@linaro.org>
From: Shiraz Hashim <shiraz.hashim@st.com>
SPEAr platform provides a provision to control chipselects of ARM PL022 Prime
Cell spi controller through its system registers, which otherwise remains under
PL022 control which some protocols do not want.
This patch adds spics controller nodes in device tree for various SPEAr13xx
SoCs.
Cc: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Shiraz Hashim <shiraz.hashim@st.com>
Reviewed-by: Vipin Kumar <vipin.kumar@st.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
arch/arm/boot/dts/spear1310.dtsi | 12 ++++++++++++
arch/arm/boot/dts/spear1340.dtsi | 14 ++++++++++++++
2 files changed, 26 insertions(+)
diff --git a/arch/arm/boot/dts/spear1310.dtsi b/arch/arm/boot/dts/spear1310.dtsi
index 419ea74..d5661ee 100644
--- a/arch/arm/boot/dts/spear1310.dtsi
+++ b/arch/arm/boot/dts/spear1310.dtsi
@@ -17,6 +17,18 @@
compatible = "st,spear1310";
ahb {
+ spics: spics at e0700000{
+ compatible = "st,spear-spics-gpio";
+ reg = <0xe0700000 0x1000>;
+ st-spics,peripcfg-reg = <0x3b0>;
+ st-spics,sw-enable-bit = <12>;
+ st-spics,cs-value-bit = <11>;
+ st-spics,cs-enable-mask = <3>;
+ st-spics,cs-enable-shift = <8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
ahci at b1000000 {
compatible = "snps,spear-ahci";
reg = <0xb1000000 0x10000>;
diff --git a/arch/arm/boot/dts/spear1340.dtsi b/arch/arm/boot/dts/spear1340.dtsi
index d71fe2a..1604425 100644
--- a/arch/arm/boot/dts/spear1340.dtsi
+++ b/arch/arm/boot/dts/spear1340.dtsi
@@ -17,6 +17,20 @@
compatible = "st,spear1340";
ahb {
+
+ spics: spics at e0700000{
+ compatible = "st,spear-spics-gpio";
+ reg = <0xe0700000 0x1000>;
+ st-spics,peripcfg-reg = <0x42c>;
+ st-spics,sw-enable-bit = <21>;
+ st-spics,cs-value-bit = <20>;
+ st-spics,cs-enable-mask = <3>;
+ st-spics,cs-enable-shift = <18>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
ahci at b1000000 {
compatible = "snps,spear-ahci";
reg = <0xb1000000 0x10000>;
--
1.7.12.rc2.18.g61b472e
^ permalink raw reply related
* [PATCH 03/14] ARM: SPEAr: DT: Update pinctrl list
From: Viresh Kumar @ 2012-11-11 4:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1352608333.git.viresh.kumar@linaro.org>
From: Vipul Kumar Samar <vipulkumar.samar@st.com>
This patch updates pinctrl configuration for SPEAr SoC's.
Signed-off-by: Shiraz Hashim <shiraz.hashim@st.com>
Signed-off-by: Vipul Kumar Samar <vipulkumar.samar@st.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
arch/arm/boot/dts/spear1310-evb.dts | 23 +++++++++++++++++------
arch/arm/boot/dts/spear1340-evb.dts | 35 +++++++++++++++++++++--------------
arch/arm/boot/dts/spear320-evb.dts | 6 +-----
3 files changed, 39 insertions(+), 25 deletions(-)
diff --git a/arch/arm/boot/dts/spear1310-evb.dts b/arch/arm/boot/dts/spear1310-evb.dts
index dd4358b..08697ac 100644
--- a/arch/arm/boot/dts/spear1310-evb.dts
+++ b/arch/arm/boot/dts/spear1310-evb.dts
@@ -30,10 +30,14 @@
pinctrl-0 = <&state_default>;
state_default: pinmux {
- i2c0-pmx {
+ i2c0 {
st,pins = "i2c0_grp";
st,function = "i2c0";
};
+ i2s0 {
+ st,pins = "i2s0_grp";
+ st,function = "i2s0";
+ };
i2s1 {
st,pins = "i2s1_grp";
st,function = "i2s1";
@@ -42,6 +46,10 @@
st,pins = "arm_gpio_grp";
st,function = "arm_gpio";
};
+ clcd {
+ st,pins = "clcd_grp" , "clcd_high_res";
+ st,function = "clcd";
+ };
eth {
st,pins = "gmii_grp";
st,function = "gmii";
@@ -74,11 +82,6 @@
st,pins = "i2c_1_2_grp";
st,function = "i2c_1_2";
};
- pci {
- st,pins = "pcie0_grp","pcie1_grp",
- "pcie2_grp";
- st,function = "pci";
- };
smii {
st,pins = "smii_0_1_2_grp";
st,function = "smii_0_1_2";
@@ -88,6 +91,14 @@
"nand_16bit_grp";
st,function = "nand";
};
+ sata {
+ st,pins = "sata0_grp";
+ st,function = "sata";
+ };
+ pcie {
+ st,pins = "pcie1_grp", "pcie2_grp";
+ st,function = "pci_express";
+ };
};
};
diff --git a/arch/arm/boot/dts/spear1340-evb.dts b/arch/arm/boot/dts/spear1340-evb.dts
index c9a54e0..8e35c14 100644
--- a/arch/arm/boot/dts/spear1340-evb.dts
+++ b/arch/arm/boot/dts/spear1340-evb.dts
@@ -38,20 +38,15 @@
st,pins = "fsmc_8bit_grp";
st,function = "fsmc";
};
- kbd {
- st,pins = "keyboard_row_col_grp",
- "keyboard_col5_grp";
- st,function = "keyboard";
- };
uart0 {
- st,pins = "uart0_grp", "uart0_enh_grp";
+ st,pins = "uart0_grp";
st,function = "uart0";
};
- i2c0-pmx {
+ i2c0 {
st,pins = "i2c0_grp";
st,function = "i2c0";
};
- i2c1-pmx {
+ i2c1 {
st,pins = "i2c1_grp";
st,function = "i2c1";
};
@@ -64,14 +59,9 @@
st,function = "spdif_out";
};
ssp0 {
- st,pins = "ssp0_grp", "ssp0_cs1_grp",
- "ssp0_cs3_grp";
+ st,pins = "ssp0_grp", "ssp0_cs1_grp", "ssp0_cs2_grp", "ssp0_cs3_grp";
st,function = "ssp0";
};
- pwm {
- st,pins = "pwm2_grp", "pwm3_grp";
- st,function = "pwm";
- };
smi-pmx {
st,pins = "smi_grp";
st,function = "smi";
@@ -84,6 +74,18 @@
st,pins = "gmii_grp", "rgmii_grp";
st,function = "gmac";
};
+ cam0 {
+ st,pins = "cam0_grp";
+ st,function = "cam0";
+ };
+ cam1 {
+ st,pins = "cam1_grp";
+ st,function = "cam1";
+ };
+ cam2 {
+ st,pins = "cam2_grp";
+ st,function = "cam2";
+ };
cam3 {
st,pins = "cam3_grp";
st,function = "cam3";
@@ -108,6 +110,11 @@
st,pins = "sata_grp";
st,function = "sata";
};
+ pcie {
+ st,pins = "pcie_grp";
+ st,function = "pcie";
+ };
+
};
};
diff --git a/arch/arm/boot/dts/spear320-evb.dts b/arch/arm/boot/dts/spear320-evb.dts
index 082328b..3f87cd0 100644
--- a/arch/arm/boot/dts/spear320-evb.dts
+++ b/arch/arm/boot/dts/spear320-evb.dts
@@ -76,13 +76,9 @@
st,function = "mii2";
};
pwm0_1 {
- st,pins = "pwm0_1_pin_14_15_grp";
+ st,pins = "pwm0_1_pin_37_38_grp";
st,function = "pwm0_1";
};
- pwm2 {
- st,pins = "pwm2_pin_13_grp";
- st,function = "pwm2";
- };
};
};
--
1.7.12.rc2.18.g61b472e
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox