Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [RFC/PATCH] ARM: vDSO gettimeofday using generic timer architecture
From: Nathan Lynch @ 2014-01-28 21:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390926308-15581-1-git-send-email-steve.capper@linaro.org>

Provide fast userspace implementations of gettimeofday and
clock_gettime on systems that implement the generic timers extension
defined in ARMv7.  This follows the example of arm64 in conception but
significantly differs in some aspects of the implementation (C vs
assembly, mainly).

Clocks supported:
- CLOCK_REALTIME
- CLOCK_MONOTONIC
- CLOCK_REALTIME_COARSE
- CLOCK_MONOTONIC_COARSE

This also provides clock_getres (as arm64 does).

Tested on OMAP5 UEVM (Cortex A15) using a LD_PRELOAD shim to redirect
system calls to the vDSO.  I plan to undertake adding proper support
to glibc if the overall approach is acceptable.

Note that while the high-precision realtime and monotonic clock
support depends on the generic timers extension, support for
clock_getres and (I think) the coarse clocks is pretty much
independent of the timer implementation in use and could be provided
unconditionally.

I also hope to add getcpu to the vDSO, using something like
TPIDRURO/TPIDRURW (although I believe these registers are claimed for
other uses already -- suggestions welcome).

This is RFC-quality code at the moment -- I haven't tested this on a
system lacking generic timers, nor have I done much build testing.
I'm sure there is plenty of room for improvement.

Based on linux-next 20140124.
---
 arch/arm/Kconfig                     |   1 +
 arch/arm/include/asm/arch_timer.h    |   7 +-
 arch/arm/include/asm/auxvec.h        |   7 +
 arch/arm/include/asm/elf.h           |   6 +
 arch/arm/include/asm/mmu.h           |   1 +
 arch/arm/include/asm/vdso.h          |  26 +++
 arch/arm/include/asm/vdso_datapage.h |  45 ++++++
 arch/arm/kernel/Makefile             |   3 +-
 arch/arm/kernel/process.c            |  16 +-
 arch/arm/kernel/vdso.c               | 157 ++++++++++++++++++
 arch/arm/kernel/vdso/.gitignore      |   2 +
 arch/arm/kernel/vdso/Makefile        |  46 ++++++
 arch/arm/kernel/vdso/vdso.S          |  35 ++++
 arch/arm/kernel/vdso/vdso.lds.S      |  93 +++++++++++
 arch/arm/kernel/vdso/vgettimeofday.c | 303 +++++++++++++++++++++++++++++++++++
 15 files changed, 742 insertions(+), 6 deletions(-)
 create mode 100644 arch/arm/include/asm/auxvec.h
 create mode 100644 arch/arm/include/asm/vdso.h
 create mode 100644 arch/arm/include/asm/vdso_datapage.h
 create mode 100644 arch/arm/kernel/vdso.c
 create mode 100644 arch/arm/kernel/vdso/.gitignore
 create mode 100644 arch/arm/kernel/vdso/Makefile
 create mode 100644 arch/arm/kernel/vdso/vdso.S
 create mode 100644 arch/arm/kernel/vdso/vdso.lds.S
 create mode 100644 arch/arm/kernel/vdso/vgettimeofday.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index dc6ef9a2c649..c9f69d059c76 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -23,6 +23,7 @@ config ARM
 	select GENERIC_SMP_IDLE_THREAD
 	select GENERIC_STRNCPY_FROM_USER
 	select GENERIC_STRNLEN_USER
+	select GENERIC_TIME_VSYSCALL
 	select HARDIRQS_SW_RESEND
 	select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL
 	select HAVE_ARCH_KGDB
diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h
index 30cc2fb09416..80f24827af94 100644
--- a/arch/arm/include/asm/arch_timer.h
+++ b/arch/arm/include/asm/arch_timer.h
@@ -102,13 +102,16 @@ static inline void arch_counter_set_user_access(void)
 {
 	u32 cntkctl = arch_timer_get_cntkctl();
 
-	/* Disable user access to both physical/virtual counters/timers */
+	/* Disable user access to the timers and the physical counter */
 	/* Also disable virtual event stream */
 	cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN
 			| ARCH_TIMER_USR_VT_ACCESS_EN
 			| ARCH_TIMER_VIRT_EVT_EN
-			| ARCH_TIMER_USR_VCT_ACCESS_EN
 			| ARCH_TIMER_USR_PCT_ACCESS_EN);
+
+	/* Enable user access to the virtual counter */
+	cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN;
+
 	arch_timer_set_cntkctl(cntkctl);
 }
 
diff --git a/arch/arm/include/asm/auxvec.h b/arch/arm/include/asm/auxvec.h
new file mode 100644
index 000000000000..f56936b97ec2
--- /dev/null
+++ b/arch/arm/include/asm/auxvec.h
@@ -0,0 +1,7 @@
+#ifndef __ASM_AUXVEC_H
+#define __ASM_AUXVEC_H
+
+/* vDSO location */
+#define AT_SYSINFO_EHDR	33
+
+#endif
diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
index f4b46d39b9cf..b8d099264000 100644
--- a/arch/arm/include/asm/elf.h
+++ b/arch/arm/include/asm/elf.h
@@ -1,6 +1,7 @@
 #ifndef __ASMARM_ELF_H
 #define __ASMARM_ELF_H
 
+#include <asm/auxvec.h>
 #include <asm/hwcap.h>
 
 /*
@@ -129,6 +130,11 @@ extern unsigned long arch_randomize_brk(struct mm_struct *mm);
 #define arch_randomize_brk arch_randomize_brk
 
 #ifdef CONFIG_MMU
+#define ARCH_DLINFO							\
+do {									\
+	NEW_AUX_ENT(AT_SYSINFO_EHDR,					\
+		    (elf_addr_t)current->mm->context.vdso);		\
+} while (0)
 #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
 struct linux_binprm;
 int arch_setup_additional_pages(struct linux_binprm *, int);
diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h
index 64fd15159b7d..1ee0f42a3b26 100644
--- a/arch/arm/include/asm/mmu.h
+++ b/arch/arm/include/asm/mmu.h
@@ -11,6 +11,7 @@ typedef struct {
 #endif
 	unsigned int	vmalloc_seq;
 	unsigned long	sigpage;
+	unsigned long	vdso;
 } mm_context_t;
 
 #ifdef CONFIG_CPU_HAS_ASID
diff --git a/arch/arm/include/asm/vdso.h b/arch/arm/include/asm/vdso.h
new file mode 100644
index 000000000000..ab080bbc4acf
--- /dev/null
+++ b/arch/arm/include/asm/vdso.h
@@ -0,0 +1,26 @@
+#ifndef __ASM_VDSO_H
+#define __ASM_VDSO_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+
+#include <linux/mm_types.h>
+#include <asm/mmu.h>
+
+static inline bool vma_is_vdso(struct vm_area_struct *vma)
+{
+	if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.vdso)
+		return true;
+	return false;
+}
+
+void arm_install_vdso(void);
+
+#endif /* __ASSEMBLY__ */
+
+#define VDSO_LBASE	0x0
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_VDSO_H */
diff --git a/arch/arm/include/asm/vdso_datapage.h b/arch/arm/include/asm/vdso_datapage.h
new file mode 100644
index 000000000000..e55358c1d565
--- /dev/null
+++ b/arch/arm/include/asm/vdso_datapage.h
@@ -0,0 +1,45 @@
+/*
+ * Adapted from arm64 version.
+ *
+ * Copyright (C) 2012 ARM Limited
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_VDSO_DATAPAGE_H
+#define __ASM_VDSO_DATAPAGE_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+
+struct vdso_data {
+	__u64 cs_cycle_last;	/* Timebase at clocksource init */
+	__u32 xtime_clock_sec;	/* Kernel time */
+	__u32 xtime_clock_nsec;
+	__u32 xtime_coarse_sec;	/* Coarse time */
+	__u32 xtime_coarse_nsec;
+	__u32 wtm_clock_sec;	/* Wall to monotonic time */
+	__u32 wtm_clock_nsec;
+	__u32 tb_seq_count;	/* Timebase sequence counter */
+	__u32 cs_mult;		/* Clocksource multiplier */
+	__u32 cs_shift;		/* Clocksource shift */
+	__u32 tz_minuteswest;	/* Whacky timezone stuff */
+	__u32 tz_dsttime;
+	__u32 use_syscall;
+};
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_VDSO_DATAPAGE_H */
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index a30fc9be9e9e..9e785550b307 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -18,7 +18,8 @@ CFLAGS_REMOVE_return_address.o = -pg
 obj-y		:= elf.o entry-common.o irq.o opcodes.o \
 		   process.o ptrace.o return_address.o \
 		   setup.o signal.o sigreturn_codes.o \
-		   stacktrace.o sys_arm.o time.o traps.o
+		   stacktrace.o sys_arm.o time.o traps.o \
+		   vdso.o vdso/
 
 obj-$(CONFIG_ATAGS)		+= atags_parse.o
 obj-$(CONFIG_ATAGS_PROC)	+= atags_proc.o
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 92f7b15dd221..9907227adf92 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -41,6 +41,7 @@
 #include <asm/stacktrace.h>
 #include <asm/mach/time.h>
 #include <asm/tls.h>
+#include <asm/vdso.h>
 
 #ifdef CONFIG_CC_STACKPROTECTOR
 #include <linux/stackprotector.h>
@@ -472,9 +473,16 @@ int in_gate_area_no_mm(unsigned long addr)
 
 const char *arch_vma_name(struct vm_area_struct *vma)
 {
-	return is_gate_vma(vma) ? "[vectors]" :
-		(vma->vm_mm && vma->vm_start == vma->vm_mm->context.sigpage) ?
-		 "[sigpage]" : NULL;
+	if (is_gate_vma(vma))
+		return "[vectors]";
+
+	if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.sigpage)
+		return "[sigpage]";
+
+	if (vma_is_vdso(vma))
+		return "[vdso]";
+
+	return NULL;
 }
 
 static struct page *signal_page;
@@ -505,6 +513,8 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 	if (ret == 0)
 		mm->context.sigpage = addr;
 
+	arm_install_vdso();
+
  up_fail:
 	up_write(&mm->mmap_sem);
 	return ret;
diff --git a/arch/arm/kernel/vdso.c b/arch/arm/kernel/vdso.c
new file mode 100644
index 000000000000..82ffb77df861
--- /dev/null
+++ b/arch/arm/kernel/vdso.c
@@ -0,0 +1,157 @@
+/*
+ * Adapted from arm64 version.
+ *
+ * Copyright (C) 2012 ARM Limited
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/timekeeper_internal.h>
+#include <linux/vmalloc.h>
+
+#include <asm/page.h>
+#include <asm/vdso.h>
+#include <asm/vdso_datapage.h>
+
+extern char vdso_start, vdso_end;
+
+static unsigned long vdso_pages;
+static struct page **vdso_pagelist;
+
+static union {
+	struct vdso_data	data;
+	u8			page[PAGE_SIZE];
+} vdso_data_store __page_aligned_data;
+struct vdso_data *vdso_data = &vdso_data_store.data;
+
+/*
+ * The vDSO data page.
+ */
+
+static int __init vdso_init(void)
+{
+	struct page *pg;
+	char *vbase;
+	int i, ret = 0;
+
+	vdso_pages = (&vdso_end - &vdso_start) >> PAGE_SHIFT;
+	pr_info("vdso: %ld pages (%ld code, %ld data) at base %p\n",
+		vdso_pages + 1, vdso_pages, 1L, &vdso_start);
+
+	/* Allocate the vDSO pagelist, plus a page for the data. */
+	vdso_pagelist = kzalloc(sizeof(struct page *) * (vdso_pages + 1),
+				GFP_KERNEL);
+	if (vdso_pagelist == NULL) {
+		pr_err("Failed to allocate vDSO pagelist!\n");
+		return -ENOMEM;
+	}
+
+	/* Grab the vDSO code pages. */
+	for (i = 0; i < vdso_pages; i++) {
+		pg = virt_to_page(&vdso_start + i*PAGE_SIZE);
+		ClearPageReserved(pg);
+		get_page(pg);
+		vdso_pagelist[i] = pg;
+	}
+
+	/* Sanity check the shared object header. */
+	vbase = vmap(vdso_pagelist, 1, 0, PAGE_KERNEL);
+	if (vbase == NULL) {
+		pr_err("Failed to map vDSO pagelist!\n");
+		return -ENOMEM;
+	} else if (memcmp(vbase, "\177ELF", 4)) {
+		pr_err("vDSO is not a valid ELF object!\n");
+		ret = -EINVAL;
+		goto unmap;
+	}
+
+	/* Grab the vDSO data page. */
+	pg = virt_to_page(vdso_data);
+	get_page(pg);
+	vdso_pagelist[i] = pg;
+
+unmap:
+	vunmap(vbase);
+	return ret;
+}
+arch_initcall(vdso_init);
+
+/* assumes mmap_sem is write-locked */
+void arm_install_vdso(void)
+{
+	struct mm_struct *mm = current->mm;
+	unsigned long vdso_base, vdso_mapping_len;
+	int ret;
+
+	/* Be sure to map the data page */
+	vdso_mapping_len = (vdso_pages + 1) << PAGE_SHIFT;
+
+	vdso_base = get_unmapped_area(NULL, 0, vdso_mapping_len, 0, 0);
+	if (IS_ERR_VALUE(vdso_base)) {
+		pr_notice_once("%s: get_unapped_area failed (%ld)\n",
+			       __func__, (long)vdso_base);
+		ret = vdso_base;
+		return;
+	}
+	mm->context.vdso = vdso_base;
+
+	ret = install_special_mapping(mm, vdso_base, vdso_mapping_len,
+				      VM_READ|VM_EXEC|
+				      VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
+				      vdso_pagelist);
+	if (ret) {
+		pr_notice_once("%s: install_special_mapping failed (%d)\n",
+			       __func__, ret);
+		mm->context.vdso = 0;
+		return;
+	}
+}
+
+void update_vsyscall(struct timekeeper *tk)
+{
+	struct timespec xtime_coarse;
+	struct timespec wall_time = tk_xtime(tk);
+	struct timespec *wtm = &tk->wall_to_monotonic;
+	u32 use_syscall = strcmp(tk->clock->name, "arch_sys_counter");
+
+	++vdso_data->tb_seq_count;
+	smp_wmb();
+
+	xtime_coarse = __current_kernel_time();
+	vdso_data->use_syscall			= use_syscall;
+	vdso_data->xtime_coarse_sec		= xtime_coarse.tv_sec;
+	vdso_data->xtime_coarse_nsec		= xtime_coarse.tv_nsec;
+
+	if (!use_syscall) {
+		vdso_data->cs_cycle_last	= tk->clock->cycle_last;
+		vdso_data->xtime_clock_sec	= wall_time.tv_sec;
+		vdso_data->xtime_clock_nsec	= wall_time.tv_nsec;
+		vdso_data->cs_mult		= tk->mult;
+		vdso_data->cs_shift		= tk->shift;
+		vdso_data->wtm_clock_sec	= wtm->tv_sec;
+		vdso_data->wtm_clock_nsec	= wtm->tv_nsec;
+	}
+
+	smp_wmb();
+	++vdso_data->tb_seq_count;
+}
+
+void update_vsyscall_tz(void)
+{
+	vdso_data->tz_minuteswest	= sys_tz.tz_minuteswest;
+	vdso_data->tz_dsttime		= sys_tz.tz_dsttime;
+}
diff --git a/arch/arm/kernel/vdso/.gitignore b/arch/arm/kernel/vdso/.gitignore
new file mode 100644
index 000000000000..a4093e0671be
--- /dev/null
+++ b/arch/arm/kernel/vdso/.gitignore
@@ -0,0 +1,2 @@
+vdso.lds
+
diff --git a/arch/arm/kernel/vdso/Makefile b/arch/arm/kernel/vdso/Makefile
new file mode 100644
index 000000000000..cc2b42db840e
--- /dev/null
+++ b/arch/arm/kernel/vdso/Makefile
@@ -0,0 +1,46 @@
+obj-vdso := vgettimeofday.o
+
+# Build rules
+targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.lds
+obj-vdso := $(addprefix $(obj)/, $(obj-vdso))
+
+ccflags-y := -shared -fPIC -fno-common -fno-builtin
+ccflags-y += -nostdlib -Wl,-soname=linux-vdso.so.1 \
+		$(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
+
+obj-y += vdso.o
+extra-y += vdso.lds
+CPPFLAGS_vdso.lds += -P -C -U$(ARCH)
+
+CFLAGS_REMOVE_vdso.o = -pg
+CFLAGS_REMOVE_vgettimeofday.o = -pg
+
+# Disable gcov profiling for VDSO code
+GCOV_PROFILE := n
+
+# Force dependency
+$(obj)/vdso.o : $(obj)/vdso.so
+
+# Link rule for the .so file, .lds has to be first
+SYSCFLAGS_vdso.so.dbg = $(c_flags)
+$(obj)/vdso.so.dbg: $(src)/vdso.lds $(obj-vdso)
+	$(call if_changed,vdsold)
+
+# Strip rule for the .so file
+$(obj)/%.so: OBJCOPYFLAGS := -S
+$(obj)/%.so: $(obj)/%.so.dbg FORCE
+	$(call if_changed,objcopy)
+
+# Actual build commands
+quiet_cmd_vdsold = VDSOL $@
+      cmd_vdsold = $(CC) $(c_flags) -Wl,-T $^ -o $@
+
+# Install commands for the unstripped file
+quiet_cmd_vdso_install = INSTALL $@
+      cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
+
+vdso.so: $(obj)/vdso.so.dbg
+	@mkdir -p $(MODLIB)/vdso
+	$(call cmd,vdso_install)
+
+vdso_install: vdso.so
diff --git a/arch/arm/kernel/vdso/vdso.S b/arch/arm/kernel/vdso/vdso.S
new file mode 100644
index 000000000000..aed16ff84c5f
--- /dev/null
+++ b/arch/arm/kernel/vdso/vdso.S
@@ -0,0 +1,35 @@
+/*
+ * Adapted from arm64 version.
+ *
+ * Copyright (C) 2012 ARM Limited
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/const.h>
+#include <asm/page.h>
+
+	__PAGE_ALIGNED_DATA
+
+	.globl vdso_start, vdso_end
+	.balign PAGE_SIZE
+vdso_start:
+	.incbin "arch/arm/kernel/vdso/vdso.so"
+	.balign PAGE_SIZE
+vdso_end:
+
+	.previous
diff --git a/arch/arm/kernel/vdso/vdso.lds.S b/arch/arm/kernel/vdso/vdso.lds.S
new file mode 100644
index 000000000000..e16f8f6f08e1
--- /dev/null
+++ b/arch/arm/kernel/vdso/vdso.lds.S
@@ -0,0 +1,93 @@
+/*
+ * Adapted from arm64 version.
+ *
+ * GNU linker script for the VDSO library.
+ *
+ * Copyright (C) 2012 ARM Limited
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ * Heavily based on the vDSO linker scripts for other archs.
+ */
+
+#include <linux/const.h>
+#include <asm/page.h>
+#include <asm/vdso.h>
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+
+SECTIONS
+{
+	. = VDSO_LBASE + SIZEOF_HEADERS;
+
+	.hash		: { *(.hash) }			:text
+	.gnu.hash	: { *(.gnu.hash) }
+	.dynsym		: { *(.dynsym) }
+	.dynstr		: { *(.dynstr) }
+	.gnu.version	: { *(.gnu.version) }
+	.gnu.version_d	: { *(.gnu.version_d) }
+	.gnu.version_r	: { *(.gnu.version_r) }
+
+	.note		: { *(.note.*) }		:text	:note
+
+	. = ALIGN(16);
+
+	.text		: { *(.text*) }			:text	=0xd503201f
+	PROVIDE (__etext = .);
+	PROVIDE (_etext = .);
+	PROVIDE (etext = .);
+
+	.eh_frame_hdr	: { *(.eh_frame_hdr) }		:text	:eh_frame_hdr
+	.eh_frame	: { KEEP (*(.eh_frame)) }	:text
+
+	.dynamic	: { *(.dynamic) }		:text	:dynamic
+
+	.rodata		: { *(.rodata*) }		:text
+
+	_end = .;
+	PROVIDE(end = .);
+
+	. = ALIGN(PAGE_SIZE);
+	PROVIDE(_vdso_data = .);
+
+	/DISCARD/	: {
+		*(.note.GNU-stack)
+		*(.data .data.* .gnu.linkonce.d.* .sdata*)
+		*(.bss .sbss .dynbss .dynsbss)
+	}
+}
+
+/*
+ * We must supply the ELF program headers explicitly to get just one
+ * PT_LOAD segment, and set the flags explicitly to make segments read-only.
+ */
+PHDRS
+{
+	text		PT_LOAD		FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */
+	dynamic		PT_DYNAMIC	FLAGS(4);		/* PF_R */
+	note		PT_NOTE		FLAGS(4);		/* PF_R */
+	eh_frame_hdr	PT_GNU_EH_FRAME;
+}
+
+VERSION
+{
+	LINUX_3.15 {
+	global:
+		__kernel_clock_getres;
+		__kernel_clock_gettime;
+		__kernel_gettimeofday;
+	local: *;
+	};
+}
diff --git a/arch/arm/kernel/vdso/vgettimeofday.c b/arch/arm/kernel/vdso/vgettimeofday.c
new file mode 100644
index 000000000000..1519283dc2e5
--- /dev/null
+++ b/arch/arm/kernel/vdso/vgettimeofday.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2014 Mentor Graphics Corporation.
+ *
+ * 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; version 2 of the
+ * License.
+ *
+ */
+
+#include <linux/compiler.h>
+#include <linux/hrtimer.h>
+#include <linux/time.h>
+#include <asm/arch_timer.h>
+#include <asm/barrier.h>
+#include <asm/unistd.h>
+#include <asm/vdso_datapage.h>
+
+extern struct vdso_data _vdso_data;
+
+static struct vdso_data *get_datapage(void)
+{
+	struct vdso_data *ret;
+
+	/* Hack to perform pc-relative load of data page */
+	asm("b 1f\n"
+	    ".align 2\n"
+	    "2:\n"
+	    ".long _vdso_data - .\n"
+	    "1:\n"
+	    "adr r2, 2b\n"
+	    "ldr r3, [r2]\n"
+	    "add %0, r2, r3\n" :
+	    "=r" (ret) : : "r2", "r3");
+
+	return ret;
+}
+
+static u32 seqcnt_acquire(struct vdso_data *vdata)
+{
+	u32 seq;
+
+	do {
+		seq = ACCESS_ONCE(vdata->tb_seq_count);
+	} while (seq & 1);
+
+	dmb(ish);
+
+	return seq;
+}
+
+static u32 seqcnt_read(struct vdso_data *vdata)
+{
+	dmb(ish);
+
+	return ACCESS_ONCE(vdata->tb_seq_count);
+}
+
+static long clock_gettime_fallback(clockid_t _clkid, struct timespec *_ts)
+{
+	register struct timespec *ts asm("r1") = _ts;
+	register clockid_t clkid asm("r0") = _clkid;
+	register long ret asm ("r0");
+	register long nr asm("r7") = __NR_clock_gettime;
+
+	asm("swi #0" : "=r" (ret) : "r" (clkid), "r" (ts), "r" (nr) : "memory");
+
+	return ret;
+}
+
+static int do_realtime_coarse(struct timespec *ts, struct vdso_data *vdata)
+{
+	struct timespec copy;
+	u32 seq;
+
+	do {
+		seq = seqcnt_acquire(vdata);
+
+		if (vdata->use_syscall)
+			return -1;
+
+		copy.tv_sec = vdata->xtime_coarse_sec;
+		copy.tv_nsec = vdata->xtime_coarse_nsec;
+	} while (seq != seqcnt_read(vdata));
+
+	*ts = copy;
+
+	return 0;
+}
+
+static int do_monotonic_coarse(struct timespec *ts, struct vdso_data *vdata)
+{
+	struct timespec copy;
+	struct timespec wtm;
+	u32 seq;
+
+	do {
+		seq = seqcnt_acquire(vdata);
+
+		if (vdata->use_syscall)
+			return -1;
+
+		copy.tv_sec = vdata->xtime_coarse_sec;
+		copy.tv_nsec = vdata->xtime_coarse_nsec;
+		wtm.tv_sec = vdata->wtm_clock_sec;
+		wtm.tv_nsec = vdata->wtm_clock_nsec;
+	} while (seq != seqcnt_read(vdata));
+
+	copy.tv_sec += wtm.tv_sec;
+	copy.tv_nsec += wtm.tv_nsec;
+	if (copy.tv_nsec >= NSEC_PER_SEC) {
+		copy.tv_nsec -= NSEC_PER_SEC;
+		copy.tv_sec += 1;
+	}
+
+	*ts = copy;
+
+	return 0;
+}
+
+static int do_realtime(struct timespec *ts, struct vdso_data *vdata)
+{
+	unsigned long sec;
+	u32 seq;
+	u64 ns;
+
+	do {
+		u64 cycles;
+
+		seq = seqcnt_acquire(vdata);
+
+		if (vdata->use_syscall)
+			return -1;
+
+		cycles = arch_counter_get_cntvct() - vdata->cs_cycle_last;
+
+		/* The generic timer architecture guarantees only 56 bits */
+		cycles &= ~(0xff00ULL << 48);
+		ns = (cycles * vdata->cs_mult) >> vdata->cs_shift;
+
+		sec = vdata->xtime_clock_sec;
+		ns += vdata->xtime_clock_nsec;
+
+		while (ns >= NSEC_PER_SEC) {
+			ns -= NSEC_PER_SEC;
+			sec += 1;
+		}
+	} while (seq != seqcnt_read(vdata));
+
+	ts->tv_sec = sec;
+	ts->tv_nsec = ns;
+
+	return 0;
+}
+
+static int do_monotonic(struct timespec *ts, struct vdso_data *vdata)
+{
+	unsigned long sec;
+	u32 seq;
+	u64 ns;
+
+	do {
+		u64 cycles;
+
+		seq = seqcnt_acquire(vdata);
+
+		if (vdata->use_syscall)
+			return -1;
+
+		cycles = arch_counter_get_cntvct() - vdata->cs_cycle_last;
+
+		/* The generic timer architecture guarantees only 56 bits */
+		cycles &= ~(0xff00ULL << 48);
+		ns = (cycles * vdata->cs_mult) >> vdata->cs_shift;
+
+		sec = vdata->xtime_clock_sec;
+		ns += vdata->xtime_clock_nsec;
+
+		sec += vdata->wtm_clock_sec;
+		ns += vdata->wtm_clock_nsec;
+
+		while (ns >= NSEC_PER_SEC) {
+			ns -= NSEC_PER_SEC;
+			sec += 1;
+		}
+	} while (seq != seqcnt_read(vdata));
+
+	ts->tv_sec = sec;
+	ts->tv_nsec = ns;
+
+	return 0;
+}
+
+int __kernel_clock_gettime(clockid_t clkid, struct timespec *ts)
+{
+	struct vdso_data *vdata;
+	int ret = -1;
+
+	vdata = get_datapage();
+
+	switch (clkid) {
+	case CLOCK_REALTIME_COARSE:
+		ret = do_realtime_coarse(ts, vdata);
+		break;
+	case CLOCK_MONOTONIC_COARSE:
+		ret = do_monotonic_coarse(ts, vdata);
+		break;
+	case CLOCK_REALTIME:
+		ret = do_realtime(ts, vdata);
+		break;
+	case CLOCK_MONOTONIC:
+		ret = do_monotonic(ts, vdata);
+		break;
+	default:
+		break;
+	}
+
+	if (ret)
+		ret = clock_gettime_fallback(clkid, ts);
+
+	return ret;
+}
+
+static long clock_getres_fallback(clockid_t _clkid, struct timespec *_ts)
+{
+	register struct timespec *ts asm("r1") = _ts;
+	register clockid_t clkid asm("r0") = _clkid;
+	register long ret asm ("r0");
+	register long nr asm("r7") = __NR_clock_getres;
+
+	asm volatile(
+		"swi #0" :
+		"=r" (ret) :
+		"r" (clkid), "r" (ts), "r" (nr) :
+		"memory");
+
+	return ret;
+}
+
+int __kernel_clock_getres(clockid_t clkid, struct timespec *ts)
+{
+	int ret;
+
+	switch (clkid) {
+	case CLOCK_REALTIME:
+	case CLOCK_MONOTONIC:
+		if (ts) {
+			ts->tv_sec = 0;
+			ts->tv_nsec = MONOTONIC_RES_NSEC;
+		}
+		ret = 0;
+		break;
+	case CLOCK_REALTIME_COARSE:
+	case CLOCK_MONOTONIC_COARSE:
+		if (ts) {
+			ts->tv_sec = 0;
+			ts->tv_nsec = LOW_RES_NSEC;
+		}
+		ret = 0;
+		break;
+	default:
+		ret = clock_getres_fallback(clkid, ts);
+		break;
+	}
+
+	return ret;
+}
+
+static long gettimeofday_fallback(struct timeval *_tv, struct timezone *_tz)
+{
+	register struct timezone *tz asm("r1") = _tz;
+	register struct timeval *tv asm("r0") = _tv;
+	register long ret asm ("r0");
+	register long nr asm("r7") = __NR_gettimeofday;
+
+	asm("swi #0" : "=r" (ret) : "r" (tv), "r" (tz), "r" (nr) : "memory");
+
+	return ret;
+}
+
+int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+	struct timespec ts;
+	struct vdso_data *vdata;
+	int ret;
+
+	vdata = get_datapage();
+
+	ret = do_realtime(&ts, vdata);
+	if (ret)
+		return gettimeofday_fallback(tv, tz);
+
+	if (tv) {
+		tv->tv_sec = ts.tv_sec;
+		tv->tv_usec = ts.tv_nsec / 1000;
+	}
+	if (tz) {
+		tz->tz_minuteswest = vdata->tz_minuteswest;
+		tz->tz_dsttime = vdata->tz_dsttime;
+	}
+
+	return ret;
+}
-- 
1.8.3.1

^ permalink raw reply related

* [RFC] arm: vdso: Convert sigpage to vdso implementation
From: Nathan Lynch @ 2014-01-28 21:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390926308-15581-1-git-send-email-steve.capper@linaro.org>

Hi Steve,

On 01/28/2014 10:25 AM, Steve Capper wrote:
> ARM has a special sigpage that is used for signal return trampolines.
> Its implementation is very similar to a VDSO conceptually in that it
> occupies a special mapping in user address space.
> 
> One could actually host the trampoline code in a VDSO instead with the
> added advantage that one could also host specialised routines there.
> One such routine could be gettimeofday where on ARM we have architected
> (and some vendor supplied) timers that can be queried entirely in
> userspace, obviating the need for an expensive syscall.
> 
> This patch converts the sigpage implementation to a VDSO. It is mostly
> a direct port from Will Deacon's arm64 implementation with the ARM
> signal trampoline plumbed in.
> 
> Signed-off-by: Steve Capper <steve.capper@linaro.org>
> ---
> As can be inferred from this RFC, I am interested ultimately in
> implementing a syscall-less gettimeofday for ARM. Whilst researching
> possible vectors page or VDSO implementations, I came across the
> sigpage mechanism which is very similar to a VDSO.
> 
> The very simple function, __kernel_vdso_doubler, resolved in a test
> program automatically on my Arndale board (running Fedora 20) without
> any additional prodding.
> 
> IPC stress tests from LTP were executed to test the signal trampoline.
> 
> I would appreciate any comments on this approach of converting the
> sigpage to a VDSO. If this looks sane to people, I will work on the
> gettimeofday logic in a later patch.

As it happens, I've been working on a vDSO implementation of
gettimeofday/clock_gettime which does not mess with the signal page.
I'll reply with the patch separately in a moment.

^ permalink raw reply

* iop32x: gpio breakage after "instantiate GPIO from platform device"
From: Arnd Bergmann @ 2014-01-28 21:05 UTC (permalink / raw)
  To: linux-arm-kernel

Commit 7b85b867b9904 "ARM: plat-iop: instantiate GPIO from platform
device" nicely cleaned up the gpio register access for iop, but
forgot one board that directly pokes into the gpio registers
to do a system reset.

That board no longer compiles, and this patch just disables
the code in question to work around it so I can locally build
randconfig again, but it needs to be fixed properly.

diff --git a/arch/arm/mach-iop32x/em7210.c b/arch/arm/mach-iop32x/em7210.c
index 177cd07..f3cb8e1 100644
--- a/arch/arm/mach-iop32x/em7210.c
+++ b/arch/arm/mach-iop32x/em7210.c
@@ -178,8 +178,10 @@ static struct platform_device em7210_serial_device = {
 
 void em7210_power_off(void)
 {
+#if 0
 	*IOP3XX_GPOE &= 0xfe;
 	*IOP3XX_GPOD |= 0x01;
+#endif
 }
 
 static void __init em7210_init_machine(void)

^ permalink raw reply related

* [RFC PATCH 3/3] KVM: Documentation: Add info regarding KVM_ARM_VCPU_PSCI_0_2 feature
From: Christoffer Dall @ 2014-01-28 21:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390309301-28424-4-git-send-email-anup.patel@linaro.org>

On Tue, Jan 21, 2014 at 06:31:41PM +0530, Anup Patel wrote:
> We have in-kernel emulation of PSCI v0.2 in KVM ARM/ARM64. To provide
> PSCI v0.2 interface to VCPUs, we have to enable KVM_ARM_VCPU_PSCI_0_2
> feature when doing KVM_ARM_VCPU_INIT ioctl.
> 
> The patch updates documentation of KVM_ARM_VCPU_INIT ioctl to provide
> info regarding KVM_ARM_VCPU_PSCI_0_2 feature.
> 
> Signed-off-by: Anup Patel <anup.patel@linaro.org>
> Signed-off-by: Pranavkumar Sawargaonkar <pranavkumar@linaro.org>
> ---
>  Documentation/virtual/kvm/api.txt |    2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> index aad3244..a15fcdd 100644
> --- a/Documentation/virtual/kvm/api.txt
> +++ b/Documentation/virtual/kvm/api.txt
> @@ -2346,6 +2346,8 @@ Possible features:
>  	  Depends on KVM_CAP_ARM_PSCI.
>  	- KVM_ARM_VCPU_EL1_32BIT: Starts the CPU in a 32bit mode.
>  	  Depends on KVM_CAP_ARM_EL1_32BIT (arm64 only).
> +	- KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 for CPU.

nit: s/for CPU/for the CPU/

> +	  Depends on KVM_CAP_ARM_PSCI_0_2.
>  
>  
>  4.83 KVM_ARM_PREFERRED_TARGET
> -- 
> 1.7.9.5
> 

^ permalink raw reply

* [RFC PATCH 2/3] ARM/ARM64: KVM: Add support for PSCI v0.2 emulation
From: Christoffer Dall @ 2014-01-28 21:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390309301-28424-3-git-send-email-anup.patel@linaro.org>

On Tue, Jan 21, 2014 at 06:31:40PM +0530, Anup Patel wrote:
> Currently, the in-kernel PSCI emulation provides PSCI v0.1 interface to
> VCPUs. This patch extends current in-kernel PSCI emulation to provide
> PSCI v0.2 interface to VCPUs.
> 
> By default, ARM/ARM64 KVM will always provide PSCI v0.1 interface for
> keeping the ABI backward-compatible.
> 
> To select PSCI v0.2 interface for VCPUs, the user space (i.e. QEMU or
> KVMTOOL) will have to set KVM_ARM_VCPU_PSCI_0_2 feature when doing VCPU
> init using KVM_ARM_VCPU_INIT ioctl.
> 
> Signed-off-by: Anup Patel <anup.patel@linaro.org>
> Signed-off-by: Pranavkumar Sawargaonkar <pranavkumar@linaro.org>
> ---
>  arch/arm/include/asm/kvm_host.h   |    2 +-
>  arch/arm/include/uapi/asm/kvm.h   |   39 ++++++++++++++++--
>  arch/arm/kvm/arm.c                |    6 ++-
>  arch/arm/kvm/psci.c               |   79 ++++++++++++++++++++++++++++++-------
>  arch/arm64/include/asm/kvm_host.h |    2 +-
>  arch/arm64/include/uapi/asm/kvm.h |   39 ++++++++++++++++--
>  6 files changed, 143 insertions(+), 24 deletions(-)
> 
> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
> index 8a6f6db..0239ac5 100644
> --- a/arch/arm/include/asm/kvm_host.h
> +++ b/arch/arm/include/asm/kvm_host.h
> @@ -36,7 +36,7 @@
>  #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
>  #define KVM_HAVE_ONE_REG
>  
> -#define KVM_VCPU_MAX_FEATURES 1
> +#define KVM_VCPU_MAX_FEATURES 2
>  
>  #include <kvm/arm_vgic.h>
>  
> diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
> index c498b60..d9eb74c 100644
> --- a/arch/arm/include/uapi/asm/kvm.h
> +++ b/arch/arm/include/uapi/asm/kvm.h
> @@ -83,6 +83,7 @@ struct kvm_regs {
>  #define KVM_VGIC_V2_CPU_SIZE		0x2000
>  
>  #define KVM_ARM_VCPU_POWER_OFF		0 /* CPU is started in OFF state */
> +#define KVM_ARM_VCPU_PSCI_0_2		1 /* CPU uses PSCI v0.2 */
>  
>  struct kvm_vcpu_init {
>  	__u32 target;
> @@ -164,7 +165,7 @@ struct kvm_arch_memory_slot {
>  /* Highest supported SPI, from VGIC_NR_IRQS */
>  #define KVM_ARM_IRQ_GIC_MAX		127
>  
> -/* PSCI interface */
> +/* PSCI v0.1 interface */
>  #define KVM_PSCI_FN_BASE		0x95c1ba5e
>  #define KVM_PSCI_FN(n)			(KVM_PSCI_FN_BASE + (n))
>  
> @@ -173,9 +174,41 @@ struct kvm_arch_memory_slot {
>  #define KVM_PSCI_FN_CPU_ON		KVM_PSCI_FN(2)
>  #define KVM_PSCI_FN_MIGRATE		KVM_PSCI_FN(3)
>  
> +/* PSCI v0.2 interface */
> +#define KVM_PSCI_0_2_FN_BASE		0x84000000
> +#define KVM_PSCI_0_2_FN(n)		(KVM_PSCI_0_2_FN_BASE + (n))
> +#define KVM_PSCI_0_2_FN64_BASE		0xC4000000
> +#define KVM_PSCI_0_2_FN64(n)		(KVM_PSCI_0_2_FN64_BASE + (n))
> +
> +#define KVM_PSCI_0_2_FN_PSCI_VERSION	KVM_PSCI_0_2_FN(0)
> +#define KVM_PSCI_0_2_FN_CPU_SUSPEND	KVM_PSCI_0_2_FN(1)
> +#define KVM_PSCI_0_2_FN_CPU_OFF		KVM_PSCI_0_2_FN(2)
> +#define KVM_PSCI_0_2_FN_CPU_ON		KVM_PSCI_0_2_FN(3)
> +#define KVM_PSCI_0_2_FN_AFFINITY_INFO	KVM_PSCI_0_2_FN(4)
> +#define KVM_PSCI_0_2_FN_MIGRATE		KVM_PSCI_0_2_FN(5)
> +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE \
> +					KVM_PSCI_0_2_FN(6)
> +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU \
> +					KVM_PSCI_0_2_FN(7)
> +#define KVM_PSCI_0_2_FN_SYSTEM_OFF	KVM_PSCI_0_2_FN(8)
> +#define KVM_PSCI_0_2_FN_SYSTEM_RESET	KVM_PSCI_0_2_FN(9)
> +
> +#define KVM_PSCI_0_2_FN64_CPU_SUSPEND	KVM_PSCI_0_2_FN64(1)
> +#define KVM_PSCI_0_2_FN64_CPU_ON	KVM_PSCI_0_2_FN64(3)
> +#define KVM_PSCI_0_2_FN64_AFFINITY_INFO	KVM_PSCI_0_2_FN64(4)
> +#define KVM_PSCI_0_2_FN64_MIGRATE	KVM_PSCI_0_2_FN64(5)
> +#define KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU \
> +					KVM_PSCI_0_2_FN64(7)
> +
> +/* PSCI return values */
>  #define KVM_PSCI_RET_SUCCESS		0
> -#define KVM_PSCI_RET_NI			((unsigned long)-1)
> -#define KVM_PSCI_RET_INVAL		((unsigned long)-2)
> +#define KVM_PSCI_RET_NOT_SUPPORTED	((unsigned long)-1)
> +#define KVM_PSCI_RET_INVALID_PARAMS	((unsigned long)-2)
>  #define KVM_PSCI_RET_DENIED		((unsigned long)-3)
> +#define KVM_PSCI_RET_ALREADY_ON		((unsigned long)-4)
> +#define KVM_PSCI_RET_ON_PENDING		((unsigned long)-5)
> +#define KVM_PSCI_RET_INTERNAL_FAILURE	((unsigned long)-6)
> +#define KVM_PSCI_RET_NOT_PRESENT	((unsigned long)-7)
> +#define KVM_PSCI_RET_DISABLED		((unsigned long)-8)
>  
>  #endif /* __ARM_KVM_H__ */
> diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
> index 2a700e0..0b7817a 100644
> --- a/arch/arm/kvm/arm.c
> +++ b/arch/arm/kvm/arm.c
> @@ -193,6 +193,7 @@ int kvm_dev_ioctl_check_extension(long ext)
>  	case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
>  	case KVM_CAP_ONE_REG:
>  	case KVM_CAP_ARM_PSCI:
> +	case KVM_CAP_ARM_PSCI_0_2:
>  		r = 1;
>  		break;
>  	case KVM_CAP_COALESCED_MMIO:
> @@ -483,7 +484,10 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
>  	 * PSCI code.
>  	 */
>  	if (test_and_clear_bit(KVM_ARM_VCPU_POWER_OFF, vcpu->arch.features)) {
> -		*vcpu_reg(vcpu, 0) = KVM_PSCI_FN_CPU_OFF;
> +		if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features))
> +			*vcpu_reg(vcpu, 0) = KVM_PSCI_0_2_FN_CPU_OFF;
> +		else
> +			*vcpu_reg(vcpu, 0) = KVM_PSCI_FN_CPU_OFF;
>  		kvm_psci_call(vcpu);

Which tree does this patch apply to?  It looks like you'll get a
conflict with:
478a823 arm: KVM: Don't return PSCI_INVAL if waitqueue is inactive

>  	}
>  
> diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c
> index 0881bf1..ee044a3 100644
> --- a/arch/arm/kvm/psci.c
> +++ b/arch/arm/kvm/psci.c
> @@ -55,13 +55,13 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
>  	}
>  
>  	if (!vcpu)
> -		return KVM_PSCI_RET_INVAL;
> +		return KVM_PSCI_RET_INVALID_PARAMS;
>  
>  	target_pc = *vcpu_reg(source_vcpu, 2);
>  
>  	wq = kvm_arch_vcpu_wq(vcpu);
>  	if (!waitqueue_active(wq))
> -		return KVM_PSCI_RET_INVAL;
> +		return KVM_PSCI_RET_INVALID_PARAMS;
>  
>  	kvm_reset_vcpu(vcpu);
>  
> @@ -84,17 +84,49 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
>  	return KVM_PSCI_RET_SUCCESS;
>  }
>  
> -/**
> - * kvm_psci_call - handle PSCI call if r0 value is in range
> - * @vcpu: Pointer to the VCPU struct
> - *
> - * Handle PSCI calls from guests through traps from HVC instructions.
> - * The calling convention is similar to SMC calls to the secure world where
> - * the function number is placed in r0 and this function returns true if the
> - * function number specified in r0 is withing the PSCI range, and false
> - * otherwise.
> - */
> -bool kvm_psci_call(struct kvm_vcpu *vcpu)
> +static bool kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
> +{
> +	unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
> +	unsigned long val;
> +
> +	switch (psci_fn) {
> +	case KVM_PSCI_0_2_FN_PSCI_VERSION:
> +		/*
> +		 * Bits[31:16] = Major Version = 0
> +		 * Bits[15:0] = Minor Version = 2
> +		 */
> +		val = 2;
> +		break;
> +	case KVM_PSCI_0_2_FN_CPU_OFF:
> +		kvm_psci_vcpu_off(vcpu);
> +		val = KVM_PSCI_RET_SUCCESS;
> +		break;
> +	case KVM_PSCI_0_2_FN_CPU_ON:
> +	case KVM_PSCI_0_2_FN64_CPU_ON:
> +		val = kvm_psci_vcpu_on(vcpu);
> +		break;
> +	case KVM_PSCI_0_2_FN_CPU_SUSPEND:
> +	case KVM_PSCI_0_2_FN_AFFINITY_INFO:
> +	case KVM_PSCI_0_2_FN_MIGRATE:
> +	case KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
> +	case KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU:
> +	case KVM_PSCI_0_2_FN_SYSTEM_OFF:
> +	case KVM_PSCI_0_2_FN_SYSTEM_RESET:
> +	case KVM_PSCI_0_2_FN64_CPU_SUSPEND:
> +	case KVM_PSCI_0_2_FN64_AFFINITY_INFO:
> +	case KVM_PSCI_0_2_FN64_MIGRATE:
> +	case KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU:
> +		val = KVM_PSCI_RET_NOT_SUPPORTED;
> +		break;
> +	default:
> +		return false;
> +	}
> +
> +	*vcpu_reg(vcpu, 0) = val;
> +	return true;
> +}
> +
> +static bool kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
>  {
>  	unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0);
>  	unsigned long val;
> @@ -109,9 +141,8 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu)
>  		break;
>  	case KVM_PSCI_FN_CPU_SUSPEND:
>  	case KVM_PSCI_FN_MIGRATE:
> -		val = KVM_PSCI_RET_NI;
> +		val = KVM_PSCI_RET_NOT_SUPPORTED;
>  		break;
> -
>  	default:
>  		return false;
>  	}
> @@ -119,3 +150,21 @@ bool kvm_psci_call(struct kvm_vcpu *vcpu)
>  	*vcpu_reg(vcpu, 0) = val;
>  	return true;
>  }
> +
> +/**
> + * kvm_psci_call - handle PSCI call if r0 value is in range
> + * @vcpu: Pointer to the VCPU struct
> + *
> + * Handle PSCI calls from guests through traps from HVC instructions.
> + * The calling convention is similar to SMC calls to the secure world where
> + * the function number is placed in r0 and this function returns true if the
> + * function number specified in r0 is withing the PSCI range, and false
> + * otherwise.
> + */
> +bool kvm_psci_call(struct kvm_vcpu *vcpu)
> +{
> +	if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features))
> +		return kvm_psci_0_2_call(vcpu);
> +
> +	return kvm_psci_0_1_call(vcpu);
> +}

Why don't we just try one after the other?  Do they conflict in some
way?

I assume PSCI calls are never going to be in the critical path and calls
into PSCI are pretty much expected to be slow as a dog anyhow, so if we
could avoid the extra churn in user space code and potential user
confusion (providing PSCI 0.2 kernel but too old user space tool for
example), I think that would be preferred.

> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index 0a1d697..92242ce 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -39,7 +39,7 @@
>  #include <kvm/arm_vgic.h>
>  #include <kvm/arm_arch_timer.h>
>  
> -#define KVM_VCPU_MAX_FEATURES 2
> +#define KVM_VCPU_MAX_FEATURES 3
>  
>  struct kvm_vcpu;
>  int kvm_target_cpu(void);
> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
> index d9f026b..0eb254d 100644
> --- a/arch/arm64/include/uapi/asm/kvm.h
> +++ b/arch/arm64/include/uapi/asm/kvm.h
> @@ -77,6 +77,7 @@ struct kvm_regs {
>  
>  #define KVM_ARM_VCPU_POWER_OFF		0 /* CPU is started in OFF state */
>  #define KVM_ARM_VCPU_EL1_32BIT		1 /* CPU running a 32bit VM */
> +#define KVM_ARM_VCPU_PSCI_0_2		2 /* CPU uses PSCI v0.2 */
>  
>  struct kvm_vcpu_init {
>  	__u32 target;
> @@ -150,7 +151,7 @@ struct kvm_arch_memory_slot {
>  /* Highest supported SPI, from VGIC_NR_IRQS */
>  #define KVM_ARM_IRQ_GIC_MAX		127
>  
> -/* PSCI interface */
> +/* PSCI v0.1 interface */
>  #define KVM_PSCI_FN_BASE		0x95c1ba5e
>  #define KVM_PSCI_FN(n)			(KVM_PSCI_FN_BASE + (n))
>  
> @@ -159,10 +160,42 @@ struct kvm_arch_memory_slot {
>  #define KVM_PSCI_FN_CPU_ON		KVM_PSCI_FN(2)
>  #define KVM_PSCI_FN_MIGRATE		KVM_PSCI_FN(3)
>  
> +/* PSCI v0.2 interface */
> +#define KVM_PSCI_0_2_FN_BASE		0x84000000
> +#define KVM_PSCI_0_2_FN(n)		(KVM_PSCI_0_2_FN_BASE + (n))
> +#define KVM_PSCI_0_2_FN64_BASE		0xC4000000
> +#define KVM_PSCI_0_2_FN64(n)		(KVM_PSCI_0_2_FN64_BASE + (n))
> +
> +#define KVM_PSCI_0_2_FN_PSCI_VERSION	KVM_PSCI_0_2_FN(0)
> +#define KVM_PSCI_0_2_FN_CPU_SUSPEND	KVM_PSCI_0_2_FN(1)
> +#define KVM_PSCI_0_2_FN_CPU_OFF		KVM_PSCI_0_2_FN(2)
> +#define KVM_PSCI_0_2_FN_CPU_ON		KVM_PSCI_0_2_FN(3)
> +#define KVM_PSCI_0_2_FN_AFFINITY_INFO	KVM_PSCI_0_2_FN(4)
> +#define KVM_PSCI_0_2_FN_MIGRATE		KVM_PSCI_0_2_FN(5)
> +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_TYPE \
> +					KVM_PSCI_0_2_FN(6)
> +#define KVM_PSCI_0_2_FN_MIGRATE_INFO_UP_CPU \
> +					KVM_PSCI_0_2_FN(7)
> +#define KVM_PSCI_0_2_FN_SYSTEM_OFF	KVM_PSCI_0_2_FN(8)
> +#define KVM_PSCI_0_2_FN_SYSTEM_RESET	KVM_PSCI_0_2_FN(9)
> +
> +#define KVM_PSCI_0_2_FN64_CPU_SUSPEND	KVM_PSCI_0_2_FN64(1)
> +#define KVM_PSCI_0_2_FN64_CPU_ON	KVM_PSCI_0_2_FN64(3)
> +#define KVM_PSCI_0_2_FN64_AFFINITY_INFO	KVM_PSCI_0_2_FN64(4)
> +#define KVM_PSCI_0_2_FN64_MIGRATE	KVM_PSCI_0_2_FN64(5)
> +#define KVM_PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU \
> +					KVM_PSCI_0_2_FN64(7)
> +
> +/* PSCI return values */
>  #define KVM_PSCI_RET_SUCCESS		0
> -#define KVM_PSCI_RET_NI			((unsigned long)-1)
> -#define KVM_PSCI_RET_INVAL		((unsigned long)-2)
> +#define KVM_PSCI_RET_NOT_SUPPORTED	((unsigned long)-1)
> +#define KVM_PSCI_RET_INVALID_PARAMS	((unsigned long)-2)
>  #define KVM_PSCI_RET_DENIED		((unsigned long)-3)
> +#define KVM_PSCI_RET_ALREADY_ON		((unsigned long)-4)
> +#define KVM_PSCI_RET_ON_PENDING		((unsigned long)-5)
> +#define KVM_PSCI_RET_INTERNAL_FAILURE	((unsigned long)-6)
> +#define KVM_PSCI_RET_NOT_PRESENT	((unsigned long)-7)
> +#define KVM_PSCI_RET_DISABLED		((unsigned long)-8)
>  
>  #endif
>  
> -- 
> 1.7.9.5
> 

Thanks,
-- 
Christoffer

^ permalink raw reply

* [PATCH v3 1/3] ARM: sun7i/sun6i: irqchip: Add irqchip driver for NMI controller
From: Carlo Caione @ 2014-01-28 21:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140128164142.GL3867@lukather>

Hi,

On Tue, Jan 28, 2014 at 5:41 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Hi,
>
> On Tue, Jan 28, 2014 at 12:02:23PM +0100, Hans de Goede wrote:
>> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA1
>>
>> Hi,
>>
>> On 01/28/2014 11:40 AM, Maxime Ripard wrote:
>>
>> Jumping in here to try and clarify things, or so I hope at least :)
>
> Sure :)
>
>> No, the IRQ from the PMIC is a level sensitive IRQ, so it would look
>> like this:
>
> Hmm, your mailer seems to have mangled your drawing :(
>
>> The PMIC irq line won't go low until an i2c write to its irq status
>> registers write-clears all status bits for which the corresponding
>> bit in the irq-mask register is set.
>
> Which makes sense too
>
>> And the only reason the NMI -> GIC also goes low is because the unmask
>> operation writes a second ack to the NMI controller in the unmask
>> callback of the NMI controller driver.
>
> Yes, and this is exactly what I don't understand. You shouldn't need
> that ack in first place, since it's been done already right after the
> unmask.

But the first ack is ignored since the IRQ line is still maintained
asserted by PMIC.

>> Note that we cannot use edge triggered interrupts here because the PMIC
>> has the typical setup with multiple irq status bits driving a single
>> irq line, so the irq handler does read irq-status, handle stuff,
>> write-clear irq-status. And if any other irq-status bits get set
>> between the read and write-clear the PMIC -> NMI line will stay
>> high, as it should since there are more interrupts to handle.
>
> Yep, the edge-thing was just the only case I could think of where it
> could lead to troubles.
>
> In what you're saying, which makes total sense, if we don't do the
> ack, as soon as the irq will be unmasked, since the level is high, the
> handler will be called again, treat the new interrupts, and so on. I
> don't see how this is an issue actually.

This is exactly why in unmask callback we first ACK and then unmask.
So, if the line is still maintained up by PMIC then a new interrupt is
raised otherwise nothing happens.

>> > But in this case, you would have two events coming from your
>> > device (the two rising edges), so you'd expect two interrupts. And
>> > in the case of a level triggered interrupt, the device would keep
>> > the interrupt line active until it's unmasked, so we wouldn't end
>> > up with this either.
>> >
>> >> sunxi_sc_nmi_ack_and_unmask is therefore called (by
>> >> irq_finalize_oneshot) after the IRQ thread has been
>> >> executed. After the IRQ thread has ACKed the IRQs on the
>> >> originating device we can finally ACK and unmask again the NMI.
>> >
>> > And what happens if you get a new interrupt right between the end
>> > of the handler and the unmask?
>>
>> The implicit ack done by the unmask will be ignored if the NMI line
>> is still high, just like the initial ack is ignored (which is why we
>> need the mask), and when the unmask completes the irq will
>> immediately retrigger, as it should.
>
> Yeah, but why do we need the ack in the first place? I can't think of
> a case where the ACK would be doing something useful. Either:
>   - there is no new interrupts between the mask/ack and the unmask, so
>     there's no interrupt to ack.
>   - There's a new interrupt between the mask/ack and the
>     unmask. There's two more cases here:
>     * The interrupt came before the device handler kicked in, and the
>       handler will treat it/ack it: No issue
>     * The interrupt comes right after the handler has been acking its
>       interrupt, the level stays high, your handler is called once
>       again, you can treat it: No issue

AFAIU the problem here is that the only ACK that is able to assert the
line NMI -> GIC is the ACK by the unmask callback. All the others ACKs
before that one are ignored by the NMI controller since the line PMIC
-> NMI is still asserted.

>> >>> I really wonder whether it makes sense to have a generic chip
>> >>> here. It seems to be much more complicated than it should. It's
>> >>> only about a single interrupt interrupt chip here.
>> >>
>> >> I agree but is there any other way to manage the NMI without the
>> >> driver of the device connected to NMI having to worry about
>> >> acking/masking/unmasking/ etc..?
>> >
>> > Yes, just declare a "raw" irqchip. Pretty much like we do on
>> > irq-sun4i for example.
>>
>> Hmm, I'm not going to say that using a raw irqchip here is a bad
>> idea, it sounds like it would be better.
>
> There's none. It was a separate comment :)
>
>> But I don't think this will solve the need the mask / umask. The
>> problem is we need to do an i2c write to clear the interrupt source,
>> which needs to be done from a thread / workqueue. So when the
>> interrupt handler finishes the source won't be cleared yet, and
>> AFAIK then only way to deal with this is to mask the interrupt until
>> we've cleared the interrupt source.
>
> Yes, but the interrupt is still masked during the time between the
> "hard" handler and the thread, so there's no way you can get an
> interrupt flood during that time.

agree.

BTW fortunately we can talk about this also during FOSDEM ;)

Thank you,

-- 
Carlo Caione

^ permalink raw reply

* [PATCH v3 1/2] init/do_mounts.c: ignore final \n in name_to_dev_t
From: Sebastian Capella @ 2014-01-28 20:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140128125442.4bac748945b404179deb58ba@linux-foundation.org>

Quoting Andrew Morton (2014-01-28 12:54:42)
> The problem is that kernel/power/hibernate.c:resume_store() is handed a
> newline-terminated string, yes?  And if it blindly hands that string
> over to name_to_dev_t(), name_to_dev_t() fails because the string is
> wrong.
> 
> This is an oddity of the sysfs->kernel interface and altering
> name_to_dev_t doesn't really seem appropriate for this problem - it
> would be better to fix the caller to pass in the correct string.
> 
> Something like...
> 
> /*
>  * Clean up a string which may have leading and/or trailing whitespace (as
>  * defined by isspace()) by trimming off that whitespace.  Returns an address
>  * which the caller must kfree(), or NULL on error.
>  */
> char *strim_copy(const char *s, gfp_t gfp)
> {
>         char *ret = kstrdup(skip_spaces(s), gfp);
> 
>         if (ret)
>                 strim(ret);
>         return ret;
> }
> EXPORT_SYMBOL(strim_copy);

Hi Andrew,

Thanks, this is similar, but tidier than my original patch.  I'll
fix up and repost the patch with a fix like what you're proposing.

Thanks!

Sebastian

^ permalink raw reply

* [PATCH v3 1/2] init/do_mounts.c: ignore final \n in name_to_dev_t
From: Andrew Morton @ 2014-01-28 20:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140128185926.5312.36635@capellas-linux>

On Tue, 28 Jan 2014 10:59:26 -0800 Sebastian Capella <sebastian.capella@linaro.org> wrote:

> > Do you have any feedback for me on this?
> > 
> > I'm happy do make any changes you think are correct, but I'm unsure if
> > you're asking me for option #3 above.  It's quite an intrusive change,
> > and changes old, established code and I'd like confirmation that's what
> > you'd like before proceeding down that path.
> > 
> > I've submitted patches with both options #1 and #2 above.
> > 
> > Thanks,
> > 
> > Sebastian
> 
> Ping.
> 
> Sorry for the lapse in attention to this.
> 
> Could you please clarify what is needed for this to be acceptable?
> I'm a little confused about what is being asked of me.

The problem is that kernel/power/hibernate.c:resume_store() is handed a
newline-terminated string, yes?  And if it blindly hands that string
over to name_to_dev_t(), name_to_dev_t() fails because the string is
wrong.

This is an oddity of the sysfs->kernel interface and altering
name_to_dev_t doesn't really seem appropriate for this problem - it
would be better to fix the caller to pass in the correct string.

Something like...

/*
 * Clean up a string which may have leading and/or trailing whitespace (as
 * defined by isspace()) by trimming off that whitespace.  Returns an address
 * which the caller must kfree(), or NULL on error.
 */
char *strim_copy(const char *s, gfp_t gfp)
{
	char *ret = kstrdup(skip_spaces(s), gfp);

	if (ret)
		strim(ret);
	return ret;
}
EXPORT_SYMBOL(strim_copy);

^ permalink raw reply

* [PATCH v2] arm/xen: Initialize event channels earlier
From: Stefano Stabellini @ 2014-01-28 19:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390935264-23155-1-git-send-email-julien.grall@linaro.org>

On Tue, 28 Jan 2014, Julien Grall wrote:
> Event channels driver needs to be initialized very early. Until now, Xen
> initialization was done after all CPUs was bring up.
> 
> We can safely move the initialization to an early initcall.
> 
> Also use a cpu notifier to:
>     - Register the VCPU when the CPU is prepared
>     - Enable event channel IRQ when the CPU is running
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>

Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>


> ---
>     Changes in v2:
>         - Check earlier if the event IRQ is valid
>         - We can safely register the VCPU when the cpu is booting
> ---
>  arch/arm/xen/enlighten.c |   71 ++++++++++++++++++++++++++++------------------
>  1 file changed, 44 insertions(+), 27 deletions(-)
> 
> diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
> index 293eeea..b96723e 100644
> --- a/arch/arm/xen/enlighten.c
> +++ b/arch/arm/xen/enlighten.c
> @@ -23,6 +23,7 @@
>  #include <linux/of_address.h>
>  #include <linux/cpuidle.h>
>  #include <linux/cpufreq.h>
> +#include <linux/cpu.h>
>  
>  #include <linux/mm.h>
>  
> @@ -154,7 +155,7 @@ int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
>  }
>  EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range);
>  
> -static void __init xen_percpu_init(void *unused)
> +static void xen_percpu_init(void)
>  {
>  	struct vcpu_register_vcpu_info info;
>  	struct vcpu_info *vcpup;
> @@ -193,6 +194,31 @@ static void xen_power_off(void)
>  		BUG();
>  }
>  
> +static int xen_cpu_notification(struct notifier_block *self,
> +				unsigned long action,
> +				void *hcpu)
> +{
> +	switch (action) {
> +	case CPU_STARTING:
> +		xen_percpu_init();
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	return NOTIFY_OK;
> +}
> +
> +static struct notifier_block xen_cpu_notifier = {
> +	.notifier_call = xen_cpu_notification,
> +};
> +
> +static irqreturn_t xen_arm_callback(int irq, void *arg)
> +{
> +	xen_hvm_evtchn_do_upcall();
> +	return IRQ_HANDLED;
> +}
> +
>  /*
>   * see Documentation/devicetree/bindings/arm/xen.txt for the
>   * documentation of the Xen Device Tree format.
> @@ -229,6 +255,10 @@ static int __init xen_guest_init(void)
>  	xen_events_irq = irq_of_parse_and_map(node, 0);
>  	pr_info("Xen %s support found, events_irq=%d gnttab_frame=%pa\n",
>  			version, xen_events_irq, &grant_frames);
> +
> +	if (xen_events_irq < 0)
> +		return -ENODEV;
> +
>  	xen_domain_type = XEN_HVM_DOMAIN;
>  
>  	xen_setup_features();
> @@ -281,9 +311,21 @@ static int __init xen_guest_init(void)
>  	disable_cpuidle();
>  	disable_cpufreq();
>  
> +	xen_init_IRQ();
> +
> +	if (request_percpu_irq(xen_events_irq, xen_arm_callback,
> +			       "events", &xen_vcpu)) {
> +		pr_err("Error request IRQ %d\n", xen_events_irq);
> +		return -EINVAL;
> +	}
> +
> +	xen_percpu_init();
> +
> +	register_cpu_notifier(&xen_cpu_notifier);
> +
>  	return 0;
>  }
> -core_initcall(xen_guest_init);
> +early_initcall(xen_guest_init);
>  
>  static int __init xen_pm_init(void)
>  {
> @@ -297,31 +339,6 @@ static int __init xen_pm_init(void)
>  }
>  late_initcall(xen_pm_init);
>  
> -static irqreturn_t xen_arm_callback(int irq, void *arg)
> -{
> -	xen_hvm_evtchn_do_upcall();
> -	return IRQ_HANDLED;
> -}
> -
> -static int __init xen_init_events(void)
> -{
> -	if (!xen_domain() || xen_events_irq < 0)
> -		return -ENODEV;
> -
> -	xen_init_IRQ();
> -
> -	if (request_percpu_irq(xen_events_irq, xen_arm_callback,
> -			"events", &xen_vcpu)) {
> -		pr_err("Error requesting IRQ %d\n", xen_events_irq);
> -		return -EINVAL;
> -	}
> -
> -	on_each_cpu(xen_percpu_init, NULL, 0);
> -
> -	return 0;
> -}
> -postcore_initcall(xen_init_events);
> -
>  /* In the hypervisor.S file. */
>  EXPORT_SYMBOL_GPL(HYPERVISOR_event_channel_op);
>  EXPORT_SYMBOL_GPL(HYPERVISOR_grant_table_op);
> -- 
> 1.7.10.4
> 

^ permalink raw reply

* [Patch v3 2/2] dmaengine: qcom_bam_dma: Add device tree binding
From: Andy Gross @ 2014-01-28 19:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4697306.PPWWh8UGTE@wuerfel>

On Tue, Jan 28, 2014 at 10:16:53AM +0100, Arnd Bergmann wrote:
> On Tuesday 28 January 2014 10:05:35 Lars-Peter Clausen wrote:
> > > +
> > > +Clients must use the format described in the dma.txt file, using a three cell
> > > +specifier for each channel.
> > > +
> > > +The three cells in order are:
> > > +  1. A phandle pointing to the DMA controller
> > > +  2. The channel number
> > > +  3. Direction of the fixed unidirectional channel
> > > +     0 - Memory to Device
> > > +     1 - Device to Memory
> > > +     2 - Device to Device
> > > +
> > 
> > Why does the direction needs to be specified in specifier? I see two
> > options, either the direction per is fixed in hardware. In that case the DMA
> > controller node should describe which channel is which direction. Or the
> > direction is not fixed in hardware and can be changed at runtime in which
> > case it should be set on a per descriptor basis.
> 
> Normally the direction is implied by dmaengine_slave_config().
> Note that neither the dma slave API nor the generic DT binding
> can actually support device-to-device transfers, since this
> normally implies using two dma-request lines rather than one.
> 
> There might be a case where the direction is required in order
> to allocate a channel, because the engine has specialized channels
> per direction, and might connect any of them to any dma request
> line. This does not seem to be the case for "bam", because
> the DMA specifier already contains a specific channel number, not
> a request line or slave ID number.
> 

In the case of BAM, the channels are hardcoded based on the attached peripheral.
For instance, if the BAM is attached to the BLSP UART, channel 0 is uart0-RX,
channel 1 is uart0-TX, channel 2 is uart1-RX... etc, etc.  So not only is the
direction hardcoded, but also the function.

-- 
sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply

* [Patch v3 2/2] dmaengine: qcom_bam_dma: Add device tree binding
From: Andy Gross @ 2014-01-28 19:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <52E772DF.6000604@metafoo.de>

On Tue, Jan 28, 2014 at 10:05:35AM +0100, Lars-Peter Clausen wrote:
> On 01/28/2014 07:27 AM, Andy Gross wrote:
> > Add device tree binding support for the QCOM BAM DMA driver.
> > 
> > Signed-off-by: Andy Gross <agross@codeaurora.org>
> > ---
> >  .../devicetree/bindings/dma/qcom_bam_dma.txt       |   52 ++++++++++++++++++++
> >  1 file changed, 52 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/dma/qcom_bam_dma.txt
> > 
> > diff --git a/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt b/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt
> > new file mode 100644
> > index 0000000..53fd10a
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt
> > @@ -0,0 +1,52 @@
> > +QCOM BAM DMA controller
> > +
> > +Required properties:
> > +- compatible:	Must be "qcom,bam-v1.4.0" for MSM8974 V1
> > +		Must be "qcom,bam-v1.4.1" for MSM8974 V2
> > +- reg: Address range for DMA registers
> > +- interrupts: single interrupt for this controller
> > +- #dma-cells: must be <2>
> > +- clocks: required clock
> > +- clock-names: name of clock
> > +- qcom,ee : indicates the active Execution Environment identifier (0-7)
> > +
> > +Example:
> > +
> > +	uart-bam: dma at f9984000 = {
> > +		compatible = "qcom,bam-v1.4.1";
> > +		reg = <0xf9984000 0x15000>;
> > +		interrupts = <0 94 0>;
> > +		clocks = <&gcc GCC_BAM_DMA_AHB_CLK>;
> > +		clock-names = "bam_clk";
> > +		#dma-cells = <2>;
> > +		qcom,ee = <0>;
> > +	};
> > +
> > +Client:
> > +Required properties:
> > +- dmas: List of dma channel requests
> > +- dma-names: Names of aforementioned requested channels
> > +
> > +Clients must use the format described in the dma.txt file, using a three cell
> > +specifier for each channel.
> > +
> > +The three cells in order are:
> > +  1. A phandle pointing to the DMA controller
> > +  2. The channel number
> > +  3. Direction of the fixed unidirectional channel
> > +     0 - Memory to Device
> > +     1 - Device to Memory
> > +     2 - Device to Device
> > +
> 
> Why does the direction needs to be specified in specifier? I see two
> options, either the direction per is fixed in hardware. In that case the DMA
> controller node should describe which channel is which direction. Or the
> direction is not fixed in hardware and can be changed at runtime in which
> case it should be set on a per descriptor basis.
> 

It is specified because the direction is physically set by the hardware.  And
this can change depending on the attached peripheral.  It probably does make
more sense to set the direction in the controller.

-- 
sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply

* [PATCH v3 1/3] ARM: sun7i/sun6i: irqchip: Add irqchip driver for NMI controller
From: Carlo Caione @ 2014-01-28 19:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <52E78E3F.6080902@redhat.com>

On Tue, Jan 28, 2014 at 12:02 PM, Hans de Goede <hdegoede@redhat.com> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Hi,
>
> On 01/28/2014 11:40 AM, Maxime Ripard wrote:
>
> Jumping in here to try and clarify things, or so I hope at least :)

Thank you :) I'm sure you will explain this better than me.

> The PMIC irq line won't go low until an i2c write to its irq status
> registers write-clears all status bits for which the corresponding
> bit in the irq-mask register is set.
>
> And the only reason the NMI -> GIC also goes low is because the unmask
> operation writes a second ack to the NMI controller in the unmask
> callback of the NMI controller driver.

Exactly. PMIC -> NMI is cleared when the irq handler write-clears all
the IRQs on PMIC while NMI -> GIC is cleared by the ACK in the unmask
callback.

<snip>

> Hmm, I'm not going to say that using a raw irqchip here is a bad idea, it
> sounds like it would be better.
>
> But I don't think this will solve the need the mask / umask. The problem is
> we need to do an i2c write to clear the interrupt source, which needs to
> be done from a thread / workqueue. So when the interrupt handler finishes
> the source won't be cleared yet, and AFAIK then only way to deal with this
> is to mask the interrupt until we've cleared the interrupt source.

That's why the driver using the NMI controller has to use IRQF_ONESHOT
so that the interrupt is not unmasked after the hard interrupt context
handler but it is unmasked after the thread handler function has been
executed (calling the unmask callback)

Thank you for explaining this mess you couldn't be clearer than that.

-- 
Carlo Caione

^ permalink raw reply

* [linux-sunxi] [PATCH v2 1/5] clk: sunxi: Add support for USB clock-register reset bits
From: Emilio López @ 2014-01-28 19:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390426587-16287-2-git-send-email-hdegoede@redhat.com>

Hi Hans,

El 22/01/14 18:36, Hans de Goede escribi?:
> The usb-clk register is special in that it not only contains clk gate bits,
> but also has a few reset bits. This commit adds support for this by allowing
> gates type sunxi clks to also register a reset controller.
>
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
(snip)
>   static const struct gates_data sun4i_axi_gates_data __initconst = {
> @@ -818,6 +873,7 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
>   					 struct gates_data *data)
>   {
>   	struct clk_onecell_data *clk_data;
> +	struct gates_reset_data *reset_data;
>   	const char *clk_parent;
>   	const char *clk_name;
>   	void *reg;
> @@ -861,6 +917,21 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
>   	clk_data->clk_num = i;
>
>   	of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> +
> +	/* Register a reset controler for gates with reset bits */
> +	if (data->reset_mask == 0)
> +		return;
> +
> +	reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL);
> +	if (!reset_data)
> +		return;
> +
> +	reset_data->reg = reg;
> +	reset_data->lock = &clk_lock;
> +	reset_data->rcdev.nr_resets = hweight32(data->reset_mask);

I know I made you change this, but after having a second look into 
nr_resets, I think your original implementation makes more sense. This 
will break if you use a mask with holes on it. Sorry :(

> +	reset_data->rcdev.ops = &sunxi_gates_reset_ops;
> +	reset_data->rcdev.of_node = node;
> +	reset_controller_register(&reset_data->rcdev);
>   }

Emilio

^ permalink raw reply

* [PATCH V3 2/2] ARM: multi_v7_defconfig: add mvebu drivers
From: Jason Cooper @ 2014-01-28 19:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <9609875ac4d1bd7d628bd994e0646340d78e423d.1390936638.git.jason@lakedaemon.net>

Recent boot farm testing has highlighted some issues with mvebu and
multiplatform kernels.  Increase the test coverage so we can discover
these issues earlier.

Signed-off-by: Jason Cooper <jason@lakedaemon.net>
---
v2 -> v3:
 - rebase onto arm-soc/for-next so arm-soc can apply directly for v3.14-rcX

v1 -> v2:
 - split into two patches, update and +mvebu

 arch/arm/configs/multi_v7_defconfig | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 1f3649d94bbb..ef877c44cd21 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -57,6 +57,7 @@ CONFIG_ARCH_ZYNQ=y
 CONFIG_TRUSTED_FOUNDATIONS=y
 CONFIG_PCI=y
 CONFIG_PCI_MSI=y
+CONFIG_PCI_MVEBU=y
 CONFIG_PCI_TEGRA=y
 CONFIG_HIGHPTE=y
 CONFIG_CMA=y
@@ -108,11 +109,13 @@ CONFIG_SATA_MV=y
 CONFIG_NETDEVICES=y
 CONFIG_SUN4I_EMAC=y
 CONFIG_NET_CALXEDA_XGMAC=y
+CONFIG_MVNETA=y
 CONFIG_KS8851=y
 CONFIG_R8169=y
 CONFIG_SMSC911X=y
 CONFIG_STMMAC_ETH=y
 CONFIG_TI_CPSW=y
+CONFIG_MARVELL_PHY=y
 CONFIG_ICPLUS_PHY=y
 CONFIG_USB_PEGASUS=y
 CONFIG_USB_USBNET=y
@@ -155,10 +158,12 @@ CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MUX=y
 CONFIG_I2C_MUX_PINCTRL=y
 CONFIG_I2C_DESIGNWARE_PLATFORM=y
+CONFIG_I2C_MV64XXX=y
 CONFIG_I2C_SIRF=y
 CONFIG_I2C_TEGRA=y
 CONFIG_SPI=y
 CONFIG_SPI_OMAP24XX=y
+CONFIG_SPI_ORION=y
 CONFIG_SPI_PL022=y
 CONFIG_SPI_SIRF=y
 CONFIG_SPI_TEGRA114=y
@@ -177,6 +182,8 @@ CONFIG_BATTERY_SBS=y
 CONFIG_CHARGER_TPS65090=y
 CONFIG_POWER_RESET_GPIO=y
 CONFIG_SENSORS_LM90=y
+CONFIG_THERMAL=y
+CONFIG_ARMADA_THERMAL=y
 CONFIG_MFD_AS3722=y
 CONFIG_MFD_CROS_EC=y
 CONFIG_MFD_CROS_EC_SPI=y
@@ -245,6 +252,7 @@ CONFIG_MMC_SDHCI_SPEAR=y
 CONFIG_MMC_SDHCI_BCM_KONA=y
 CONFIG_MMC_OMAP=y
 CONFIG_MMC_OMAP_HS=y
+CONFIG_MMC_MVSDIO=y
 CONFIG_EDAC=y
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_EDAC_HIGHBANK_MC=y
@@ -259,9 +267,11 @@ CONFIG_RTC_DRV_TPS65910=y
 CONFIG_RTC_DRV_EM3027=y
 CONFIG_RTC_DRV_PL031=y
 CONFIG_RTC_DRV_VT8500=y
+CONFIG_RTC_DRV_MV=y
 CONFIG_RTC_DRV_TEGRA=y
 CONFIG_DMADEVICES=y
 CONFIG_DW_DMAC=y
+CONFIG_MV_XOR=y
 CONFIG_TEGRA20_APB_DMA=y
 CONFIG_STE_DMA40=y
 CONFIG_SIRF_DMA=y
-- 
1.8.5.3

^ permalink raw reply related

* [PATCH V3 1/2] ARM: multi_v7_defconfig: update for v3.14-rc1
From: Jason Cooper @ 2014-01-28 19:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390871129-4838-1-git-send-email-jason@lakedaemon.net>

Just the output of:

  make ARCH=arm multi_v7_defconfig
  make savedefconfig
  mv defconfig arch/arm/configs/multi_v7_defconfig

Signed-off-by: Jason Cooper <jason@lakedaemon.net>
---
v2 -> v3:
 - rebase onto arm-soc/for-next so arm-soc can apply directly for v3.14-rcX

v1 -> v2:
 - split into two patches, update and +mvebu

 arch/arm/configs/multi_v7_defconfig | 13 -------------
 1 file changed, 13 deletions(-)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index e2c0734f22da..1f3649d94bbb 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -58,7 +58,6 @@ CONFIG_TRUSTED_FOUNDATIONS=y
 CONFIG_PCI=y
 CONFIG_PCI_MSI=y
 CONFIG_PCI_TEGRA=y
-CONFIG_SMP=y
 CONFIG_HIGHPTE=y
 CONFIG_CMA=y
 CONFIG_ARM_APPENDED_DTB=y
@@ -176,7 +175,6 @@ CONFIG_GPIO_TPS6586X=y
 CONFIG_GPIO_TPS65910=y
 CONFIG_BATTERY_SBS=y
 CONFIG_CHARGER_TPS65090=y
-CONFIG_POWER_RESET_AS3722=y
 CONFIG_POWER_RESET_GPIO=y
 CONFIG_SENSORS_LM90=y
 CONFIG_MFD_AS3722=y
@@ -205,7 +203,6 @@ CONFIG_MEDIA_CAMERA_SUPPORT=y
 CONFIG_MEDIA_USB_SUPPORT=y
 CONFIG_DRM=y
 CONFIG_DRM_TEGRA=y
-CONFIG_DRM_PANEL_SIMPLE=y
 CONFIG_FB_ARMCLCD=y
 CONFIG_FB_WM8505=y
 CONFIG_FB_SIMPLE=y
@@ -222,7 +219,6 @@ CONFIG_SND_SOC_TEGRA_WM8753=y
 CONFIG_SND_SOC_TEGRA_WM8903=y
 CONFIG_SND_SOC_TEGRA_TRIMSLICE=y
 CONFIG_SND_SOC_TEGRA_ALC5632=y
-CONFIG_SND_SOC_TEGRA_MAX98090=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
@@ -249,14 +245,6 @@ CONFIG_MMC_SDHCI_SPEAR=y
 CONFIG_MMC_SDHCI_BCM_KONA=y
 CONFIG_MMC_OMAP=y
 CONFIG_MMC_OMAP_HS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_ONESHOT=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_LEDS_TRIGGER_GPIO=y
-CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
-CONFIG_LEDS_TRIGGER_TRANSIENT=y
-CONFIG_LEDS_TRIGGER_CAMERA=y
 CONFIG_EDAC=y
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_EDAC_HIGHBANK_MC=y
@@ -289,7 +277,6 @@ CONFIG_MFD_NVEC=y
 CONFIG_KEYBOARD_NVEC=y
 CONFIG_SERIO_NVEC_PS2=y
 CONFIG_NVEC_POWER=y
-CONFIG_NVEC_PAZ00=y
 CONFIG_TEGRA_IOMMU_GART=y
 CONFIG_TEGRA_IOMMU_SMMU=y
 CONFIG_MEMORY=y
-- 
1.8.5.3

^ permalink raw reply related

* [PATCH v3 07/24] drm/i2c: tda998x: set the video mode from the adjusted value
From: Darren Etheridge @ 2014-01-28 19:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140128181218.39d1d15e@armhf>

Jean-Francois Moine <moinejf@free.fr> wrote on Tue [2014-Jan-28 18:12:18 +0100]:
> On Thu, 23 Jan 2014 17:29:07 -0600
> Darren Etheridge <detheridge@ti.com> wrote:
> 
> > > @@ -896,9 +897,9 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder,
> > >  	 * TDA19988 requires high-active sync at input stage,
> > >  	 * so invert low-active sync provided by master encoder here
> > >  	 */
> > > -	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
> > > +	if (adj_mode->flags & DRM_MODE_FLAG_NHSYNC)
> > >  		reg_set(priv, REG_VIP_CNTRL_3, VIP_CNTRL_3_H_TGL);
> > > -	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
> > > +	if (adj_mode->flags & DRM_MODE_FLAG_NVSYNC)
> > >  		reg_set(priv, REG_VIP_CNTRL_3, VIP_CNTRL_3_V_TGL);
> > >    
> > 
> > Using the adj_mode->flags breaks a workaround I had done on BeagleBone Black
> > (tilcdc + tda998x) to resolve an issue with out of spec syncs from the
> > tlcdc.  I invert the HSYNC in adj_mode->flags but don't want the tda998x to
> > really know that I am doing that so I use adj_mode in the tilcdc driver, and
> > mode here in the tda998x driver.  The theory being adj_mode contains whatever
> > workarounds I need to do for the driving device and mode has the pristine
> > values that I want to send to the monitor.  I would need to look if there is a
> > different way to solve this as I am guessing you are actually using adj_mode in
> > the manner it was intended.
> 
> No. In fact, I just wanted the function to use only one mode.
> 
> Looking at the other drivers, it seems that they don't touch the
> adjusted_mode, so, for the Cubox, mode and adjusted_mode have same
> values.
> 
> I will do an other patch so that you will not have to touch the tilcdc
> driver.
> 
Thanks, that would certainly be the easiest path to avoid the regression given
the other drivers that use tda998x don't currently use adj_mode.  However I
don't disagree with your reasoning, it would make sense to only use values
from one of the strctures and not a mix and match.  Anybody looking at only
the tda998x driver would be confused :) I'll work on finding a different
solution for this.

> -- 
> Ken ar c'henta?	|	      ** Breizh ha Linux atav! **
> Jef		|		http://moinejf.free.fr/

^ permalink raw reply

* [PATCH v3 1/2] init/do_mounts.c: ignore final \n in name_to_dev_t
From: Sebastian Capella @ 2014-01-28 18:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20131022175414.14753.58063@capellas-linux>

Quoting Sebastian Capella (2013-10-22 10:54:14)
> Quoting Sebastian Capella (2013-10-10 10:50:10)
> > Quoting Sebastian Capella (2013-10-03 16:47:35)
> > > Quoting Sebastian Capella (2013-10-03 14:42:46)
> > > I looked into removing the const from the store function, but I'm not sure
> > > this is the right idea, so I'm going to shelf that for now.
> > > 
> > Below are the three options considered thus far.  Do
> > you have any additional suggestions or preferences?
> > 
> > 1) copy buffer, remove \n.
> >   - v1 patch did this
> >   - alternatively could use an array on the stack or a preallocated global
> >     Pros:
> >      . cleanest change
> >      . could use strim() proposed by Andrew
> >     Cons:
> >      . adds memcpy
> > 2) make name_to_dev_t work with readonly buffer to ignore \n
> >   - v2 and v3 patches do this
> >     Pros:
> >      . no memcpy, no big modifications to unrelated code
> >     Cons:
> >      . seems more appropriate to harden store functions to user input
> >        than name_to_dev_t.
> >      . a little complicated
> > 3) remove const from buffer and modify contents in place to remove \n
> >   - remove const from sysfs_ops.store, modify dependent definitions
> >   - remove const from kobj_attribute.store, modify dependent definitions
> >     Pros:
> >      . no memcpy
> >     Cons:
> >      . a lot of modifications
> >      . const contract to not modify the input buffer seems the right way.
> 
> Hi Andrew,
> 
> Do you have any feedback for me on this?
> 
> I'm happy do make any changes you think are correct, but I'm unsure if
> you're asking me for option #3 above.  It's quite an intrusive change,
> and changes old, established code and I'd like confirmation that's what
> you'd like before proceeding down that path.
> 
> I've submitted patches with both options #1 and #2 above.
> 
> Thanks,
> 
> Sebastian

Ping.

Sorry for the lapse in attention to this.

Could you please clarify what is needed for this to be acceptable?
I'm a little confused about what is being asked of me.

Thanks!

Sebastian

^ permalink raw reply

* [PATCH v2] arm/xen: Initialize event channels earlier
From: Julien Grall @ 2014-01-28 18:54 UTC (permalink / raw)
  To: linux-arm-kernel

Event channels driver needs to be initialized very early. Until now, Xen
initialization was done after all CPUs was bring up.

We can safely move the initialization to an early initcall.

Also use a cpu notifier to:
    - Register the VCPU when the CPU is prepared
    - Enable event channel IRQ when the CPU is running

Signed-off-by: Julien Grall <julien.grall@linaro.org>

---
    Changes in v2:
        - Check earlier if the event IRQ is valid
        - We can safely register the VCPU when the cpu is booting
---
 arch/arm/xen/enlighten.c |   71 ++++++++++++++++++++++++++++------------------
 1 file changed, 44 insertions(+), 27 deletions(-)

diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
index 293eeea..b96723e 100644
--- a/arch/arm/xen/enlighten.c
+++ b/arch/arm/xen/enlighten.c
@@ -23,6 +23,7 @@
 #include <linux/of_address.h>
 #include <linux/cpuidle.h>
 #include <linux/cpufreq.h>
+#include <linux/cpu.h>
 
 #include <linux/mm.h>
 
@@ -154,7 +155,7 @@ int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
 }
 EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range);
 
-static void __init xen_percpu_init(void *unused)
+static void xen_percpu_init(void)
 {
 	struct vcpu_register_vcpu_info info;
 	struct vcpu_info *vcpup;
@@ -193,6 +194,31 @@ static void xen_power_off(void)
 		BUG();
 }
 
+static int xen_cpu_notification(struct notifier_block *self,
+				unsigned long action,
+				void *hcpu)
+{
+	switch (action) {
+	case CPU_STARTING:
+		xen_percpu_init();
+		break;
+	default:
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block xen_cpu_notifier = {
+	.notifier_call = xen_cpu_notification,
+};
+
+static irqreturn_t xen_arm_callback(int irq, void *arg)
+{
+	xen_hvm_evtchn_do_upcall();
+	return IRQ_HANDLED;
+}
+
 /*
  * see Documentation/devicetree/bindings/arm/xen.txt for the
  * documentation of the Xen Device Tree format.
@@ -229,6 +255,10 @@ static int __init xen_guest_init(void)
 	xen_events_irq = irq_of_parse_and_map(node, 0);
 	pr_info("Xen %s support found, events_irq=%d gnttab_frame=%pa\n",
 			version, xen_events_irq, &grant_frames);
+
+	if (xen_events_irq < 0)
+		return -ENODEV;
+
 	xen_domain_type = XEN_HVM_DOMAIN;
 
 	xen_setup_features();
@@ -281,9 +311,21 @@ static int __init xen_guest_init(void)
 	disable_cpuidle();
 	disable_cpufreq();
 
+	xen_init_IRQ();
+
+	if (request_percpu_irq(xen_events_irq, xen_arm_callback,
+			       "events", &xen_vcpu)) {
+		pr_err("Error request IRQ %d\n", xen_events_irq);
+		return -EINVAL;
+	}
+
+	xen_percpu_init();
+
+	register_cpu_notifier(&xen_cpu_notifier);
+
 	return 0;
 }
-core_initcall(xen_guest_init);
+early_initcall(xen_guest_init);
 
 static int __init xen_pm_init(void)
 {
@@ -297,31 +339,6 @@ static int __init xen_pm_init(void)
 }
 late_initcall(xen_pm_init);
 
-static irqreturn_t xen_arm_callback(int irq, void *arg)
-{
-	xen_hvm_evtchn_do_upcall();
-	return IRQ_HANDLED;
-}
-
-static int __init xen_init_events(void)
-{
-	if (!xen_domain() || xen_events_irq < 0)
-		return -ENODEV;
-
-	xen_init_IRQ();
-
-	if (request_percpu_irq(xen_events_irq, xen_arm_callback,
-			"events", &xen_vcpu)) {
-		pr_err("Error requesting IRQ %d\n", xen_events_irq);
-		return -EINVAL;
-	}
-
-	on_each_cpu(xen_percpu_init, NULL, 0);
-
-	return 0;
-}
-postcore_initcall(xen_init_events);
-
 /* In the hypervisor.S file. */
 EXPORT_SYMBOL_GPL(HYPERVISOR_event_channel_op);
 EXPORT_SYMBOL_GPL(HYPERVISOR_grant_table_op);
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH v3] ARM: hw_breakpoint: Add ARMv8 support
From: Christopher Covington @ 2014-01-28 18:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140128183851.GK2885@mudshark.cambridge.arm.com>

Add the trivial support necessary to get hardware breakpoints
working for GDB on ARMv8 simulators running in AArch32 mode.

Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Christopher Covington <cov@codeaurora.org>
---

 v3: assume for now that ARMv9 and later will update FSR

 v2: modify debug_exception_updates_fsr

 arch/arm/include/asm/hw_breakpoint.h | 1 +
 arch/arm/kernel/hw_breakpoint.c      | 3 ++-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/hw_breakpoint.h b/arch/arm/include/asm/hw_breakpoint.h
index eef55ea..8e427c7 100644
--- a/arch/arm/include/asm/hw_breakpoint.h
+++ b/arch/arm/include/asm/hw_breakpoint.h
@@ -51,6 +51,7 @@ static inline void decode_ctrl_reg(u32 reg,
 #define ARM_DEBUG_ARCH_V7_ECP14	3
 #define ARM_DEBUG_ARCH_V7_MM	4
 #define ARM_DEBUG_ARCH_V7_1	5
+#define ARM_DEBUG_ARCH_V8	6
 
 /* Breakpoint */
 #define ARM_BREAKPOINT_EXECUTE	0
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index 3d44660..9da35c6 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -167,7 +167,7 @@ static int debug_arch_supported(void)
 /* Can we determine the watchpoint access type from the fsr? */
 static int debug_exception_updates_fsr(void)
 {
-	return 0;
+	return get_debug_arch() >= ARM_DEBUG_ARCH_V8;
 }
 
 /* Determine number of WRP registers available. */
@@ -257,6 +257,7 @@ static int enable_monitor_mode(void)
 		break;
 	case ARM_DEBUG_ARCH_V7_ECP14:
 	case ARM_DEBUG_ARCH_V7_1:
+	case ARM_DEBUG_ARCH_V8:
 		ARM_DBG_WRITE(c0, c2, 2, (dscr | ARM_DSCR_MDBGEN));
 		isb();
 		break;
-- 
Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by the Linux Foundation.

^ permalink raw reply related

* [PATCH v2 1/7] cpufreq: cpufreq-cpu0: allow optional safe voltage during frequency transitions
From: Mike Turquette @ 2014-01-28 18:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAJuA9ah1vsgpD04QhM5RApkCe9xcvpPkLvdwzgadKGWvngAt+g@mail.gmail.com>

On Mon, Jan 27, 2014 at 9:30 PM, Thomas Abraham <ta.omasab@gmail.com> wrote:
> Hi Mike,
>
> On Tue, Jan 28, 2014 at 1:55 AM, Mike Turquette <mturquette@linaro.org> wrote:
>> Quoting Thomas Abraham (2014-01-18 04:10:51)
>>> From: Thomas Abraham <thomas.ab@samsung.com>
>>>
>>> On some platforms such as the Samsung Exynos, changing the frequency
>>> of the CPU clock requires changing the frequency of the PLL that is
>>> supplying the CPU clock. To change the frequency of the PLL, the CPU
>>> clock is temporarily reparented to another parent clock.
>>>
>>> The clock frequency of this temporary parent clock could be much higher
>>> than the clock frequency of the PLL at the time of reparenting. Due
>>> to the temporary increase in the CPU clock speed, the CPU (and any other
>>> components in the CPU clock domain such as dividers, mux, etc.) have to
>>> to be operated at a higher voltage level, called the safe voltage level.
>>> This patch adds optional support to temporarily switch to a safe voltage
>>> level during CPU frequency transitions.
>>>
>>> Cc: Shawn Guo <shawn.guo@linaro.org>
>>> Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
>>
>> I'm not a fan of this change. This corner case should be abstracted away
>> somehow. I had talked to Chander Kayshap previously about handling
>> voltage changes in clock notifier callbacks, which then renders any
>> voltage change as a trivial part of the clock rate transition. That
>> means that this "safe voltage" thing could be handled automagically
>> without any additional code in the CPUfreq driver.
>>
>> There are two nice ways to do this with the clock framework. First is
>> explicit re-parenting with voltage scaling done in the clock rate-change
>> notifiers:
>>
>> clk_set_parent(cpu_clk, temp_parent);
>> /* implicit voltage scaling to "safe voltage" happens above */
>> clk_set_rate(pll, some_rate);
>> clk_set_parent(cpu_clk, pll);
>> /* implicit voltage scaling to nominal OPP voltage happens above */
>>
>> The above sequence would require a separate exnyos CPUfreq driver, due
>> to the added clk_set_parent logic.
>>
>> The second way to do this is to abstract the clk re-muxing logic out
>> into the clk driver, which would allow cpufreq-cpu0 to be used for the
>> exynos chips.
>
> This is the approach this patch series takes (patch 2/7). The clock
> re-muxing logic is handled by a clock driver code. The difference from
> what you suggested is that the safe voltage (that may be optionally)
> required before doing the re-muxing is handled here in cpufreq-cpu0
> driver.

Right, I understand the approach taken in this series and I'm not sure
it is the right one. Why does the clock driver handle the remuxing if
it is a functional dependency of the ARM core? As far as I can tell
the remux does not happen because it is necessary to generate the
required clock rate, but because we don't want to run the ARM core out
of spec for a short time while the PLL relocks. Assuming I have that
part of it right, I prefer for the parent mux operation to be a part
of the CPUfreq driver's .target callback instead of hidden away in the
clock driver.

A common pattern I'm seeing for the last 18 months is code
consolidation for the sake of code consolidation and it is not always
a good thing. Having hardware-specific machine drivers under
drivers/cpufreq/ is the right way to go, and we should only
consolidate a driver to cpufreq-cpu0 if it makes sense.

>
> The safe voltage setup can be done in the notifier as you suggested.
> But, doing that in cpufreq-cpu0 driver will help other platforms reuse
> this feature if required. Also, if done here, the regulator handling
> is localized in this driver which otherwise would need to be handled
> in two places, cpufreq-cpu0 driver and the clock notifier.

The notifiers are reusable across other platforms. And the notifier
can be entirely set up within the cpufreq driver. Code location is not
a problem. See this RFC series:
https://lkml.org/lkml/2013/7/7/110

>
> So I tend to prefer the approach in this patch but I am willing to
> consider any suggestions. Shawn, it would be helpful if you could let
> us know your thoughts on this. I am almost done with testing the v3 of
> this series and want to post it so if there are any objections to the
> changes in this patch, please let me know.

Well I wonder if the whole approach could be more generalized. The DT
bindings for CPU frequencies could be used by any platform instead of
being Exynos-specific. We could construct a binding which captures an
arbitrary clock sub-tree snapshot. By that I mean a DT binding in
which any number of clocks and their parents and rates could be
specified in a table. Separately we could have a binding that links a
given clock at a given rate to some specified regulator and voltage.
So in this way the bindings are re-usable.

These DT ideas should be considered separately from the CPUfreq notes
outlined above, and I will respond to patch #3 in this series once I
have a chance.

Thanks,
Mike

>
> Thanks,
> Thomas.
>
>>
>> I'm more a fan of explicitly listing the Exact Steps for the cpu opp
>> transition in a separate exynos-specific CPUfreq driver, but that's
>> probably an unpopular view.
>>
>> Regards,
>> Mike
>>
>>> ---
>>>  .../devicetree/bindings/cpufreq/cpufreq-cpu0.txt   |    7 ++++
>>>  drivers/cpufreq/cpufreq-cpu0.c                     |   37 +++++++++++++++++--
>>>  2 files changed, 40 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
>>> index f055515..37453ab 100644
>>> --- a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
>>> +++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
>>> @@ -19,6 +19,12 @@ Optional properties:
>>>  - cooling-min-level:
>>>  - cooling-max-level:
>>>       Please refer to Documentation/devicetree/bindings/thermal/thermal.txt.
>>> +- safe-opp: Certain platforms require that during a opp transition,
>>> +  a system should not go below a particular opp level. For such systems,
>>> +  this property specifies the minimum opp to be maintained during the
>>> +  opp transitions. The safe-opp value is a tuple with first element
>>> +  representing the safe frequency and the second element representing the
>>> +  safe voltage.
>>>
>>>  Examples:
>>>
>>> @@ -36,6 +42,7 @@ cpus {
>>>                         396000  950000
>>>                         198000  850000
>>>                 >;
>>> +               safe-opp = <396000 950000>
>>>                 clock-latency = <61036>; /* two CLK32 periods */
>>>                 #cooling-cells = <2>;
>>>                 cooling-min-level = <0>;
>>> diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
>>> index 0c12ffc..075d3d1 100644
>>> --- a/drivers/cpufreq/cpufreq-cpu0.c
>>> +++ b/drivers/cpufreq/cpufreq-cpu0.c
>>> @@ -27,6 +27,8 @@
>>>
>>>  static unsigned int transition_latency;
>>>  static unsigned int voltage_tolerance; /* in percentage */
>>> +static unsigned long safe_frequency;
>>> +static unsigned long safe_voltage;
>>>
>>>  static struct device *cpu_dev;
>>>  static struct clk *cpu_clk;
>>> @@ -64,17 +66,30 @@ static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index)
>>>                 volt_old = regulator_get_voltage(cpu_reg);
>>>         }
>>>
>>> -       pr_debug("%u MHz, %ld mV --> %u MHz, %ld mV\n",
>>> +       pr_debug("\n\n%u MHz, %ld mV --> %u MHz, %ld mV\n",
>>>                  old_freq / 1000, volt_old ? volt_old / 1000 : -1,
>>>                  new_freq / 1000, volt ? volt / 1000 : -1);
>>>
>>>         /* scaling up?  scale voltage before frequency */
>>> -       if (!IS_ERR(cpu_reg) && new_freq > old_freq) {
>>> +       if (!IS_ERR(cpu_reg) && new_freq > old_freq &&
>>> +                               new_freq >= safe_frequency) {
>>>                 ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
>>>                 if (ret) {
>>>                         pr_err("failed to scale voltage up: %d\n", ret);
>>>                         return ret;
>>>                 }
>>> +       } else if (!IS_ERR(cpu_reg) && old_freq < safe_frequency) {
>>> +               /*
>>> +                * the scaled up voltage level for the new_freq is lower
>>> +                * than the safe voltage level. so set safe_voltage
>>> +                * as the intermediate voltage level and revert it
>>> +                * back after the frequency has been changed.
>>> +                */
>>> +               ret = regulator_set_voltage_tol(cpu_reg, safe_voltage, tol);
>>> +               if (ret) {
>>> +                       pr_err("failed to set safe voltage: %d\n", ret);
>>> +                       return ret;
>>> +               }
>>>         }
>>>
>>>         ret = clk_set_rate(cpu_clk, freq_exact);
>>> @@ -86,7 +101,8 @@ static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index)
>>>         }
>>>
>>>         /* scaling down?  scale voltage after frequency */
>>> -       if (!IS_ERR(cpu_reg) && new_freq < old_freq) {
>>> +       if (!IS_ERR(cpu_reg) &&
>>> +                       (new_freq < old_freq || new_freq < safe_frequency)) {
>>>                 ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
>>>                 if (ret) {
>>>                         pr_err("failed to scale voltage down: %d\n", ret);
>>> @@ -116,6 +132,8 @@ static struct cpufreq_driver cpu0_cpufreq_driver = {
>>>
>>>  static int cpu0_cpufreq_probe(struct platform_device *pdev)
>>>  {
>>> +       const struct property *prop;
>>> +       struct dev_pm_opp *opp;
>>>         struct device_node *np;
>>>         int ret;
>>>
>>> @@ -165,13 +183,24 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
>>>                 goto out_put_node;
>>>         }
>>>
>>> +       prop = of_find_property(np, "safe-opp", NULL);
>>> +       if (prop) {
>>> +               if (prop->value && (prop->length / sizeof(u32)) == 2) {
>>> +                       const __be32 *val;
>>> +                       val = prop->value;
>>> +                       safe_frequency = be32_to_cpup(val++);
>>> +                       safe_voltage = be32_to_cpup(val);
>>> +               } else {
>>> +                       pr_err("invalid safe-opp level specified\n");
>>> +               }
>>> +       }
>>> +
>>>         of_property_read_u32(np, "voltage-tolerance", &voltage_tolerance);
>>>
>>>         if (of_property_read_u32(np, "clock-latency", &transition_latency))
>>>                 transition_latency = CPUFREQ_ETERNAL;
>>>
>>>         if (!IS_ERR(cpu_reg)) {
>>> -               struct dev_pm_opp *opp;
>>>                 unsigned long min_uV, max_uV;
>>>                 int i;
>>>
>>> --
>>> 1.6.6.rc2
>>>

^ permalink raw reply

* [GIT PULL] ARM: mvebu: DT boards for v3.14 (incr #6)
From: Jason Cooper @ 2014-01-28 18:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAOesGMiTSa=ECDiVtgO44At9tqYCb2Ap8KWwG=FBStVEycqKcQ@mail.gmail.com>

On Tue, Jan 28, 2014 at 10:36:51AM -0800, Olof Johansson wrote:
> On Mon, Jan 20, 2014 at 12:01 PM, Jason Cooper <jason@lakedaemon.net> wrote:
> > All,
> >
> > I had a few boards that came in late in the cycle.  I was holding on to
> > them for the next round, but after Olof's comment this morning:
> >
> >   Re: [PATCH 0/2] DT updates for Hummingboard and new Cubox-i
> >   http://www.spinics.net/lists/arm-kernel/msg301777.html
> >
> > I figured I'd send them off.  As usual, they've been in -next for a
> > while.  Also, this is an incremental request from tags/mvebu-dt-3.14-5
> > to tags/mvebu-dt-3.14-6 on the mvebu/dt branch.
> >
> > If this is going to be ok for the forseeable future, I'll do a separate
> > branch for new boards next time around.
> 
> I should probably clarify my previous statement. I don't think we want
> a free-for-all on new DT contents all the way up until -rc<lownumber>,
> but what we can allow sometimes is new DT files when there's good
> reason to do so -- for example for platforms where a lot of new code
> has landed and it's been hard to sequence DT updates with the rest,
> etc.

ok, no problem.

> So, if you send these late requests please be prepared to motivate
> them. :) These don't look urgent to me so I think we'll queue them for
> 3.15 once -rc1 is out, if that's OK with you.

Yep, I just didn't want to miss the boat. :)  Please drop this request
and I'll queue these up for post-rc1.

thx,

Jason.

^ permalink raw reply

* [PATCH v2] ARM: hw_breakpoint: Add ARMv8 support
From: Will Deacon @ 2014-01-28 18:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390933583-1278-1-git-send-email-cov@codeaurora.org>

On Tue, Jan 28, 2014 at 06:26:23PM +0000, Christopher Covington wrote:
> Add the trivial support necessary to get hardware breakpoints
> working for GDB on ARMv8 simulators running in AArch32 mode.
> 
> Signed-off-by: Christopher Covington <cov@codeaurora.org>
> ---
> 
>  v2: modify debug_exception_updates_fsr
> 
>  arch/arm/include/asm/hw_breakpoint.h | 1 +
>  arch/arm/kernel/hw_breakpoint.c      | 3 ++-
>  2 files changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/include/asm/hw_breakpoint.h b/arch/arm/include/asm/hw_breakpoint.h
> index eef55ea..8e427c7 100644
> --- a/arch/arm/include/asm/hw_breakpoint.h
> +++ b/arch/arm/include/asm/hw_breakpoint.h
> @@ -51,6 +51,7 @@ static inline void decode_ctrl_reg(u32 reg,
>  #define ARM_DEBUG_ARCH_V7_ECP14	3
>  #define ARM_DEBUG_ARCH_V7_MM	4
>  #define ARM_DEBUG_ARCH_V7_1	5
> +#define ARM_DEBUG_ARCH_V8	6
>  
>  /* Breakpoint */
>  #define ARM_BREAKPOINT_EXECUTE	0
> diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
> index 3d44660..a711b27 100644
> --- a/arch/arm/kernel/hw_breakpoint.c
> +++ b/arch/arm/kernel/hw_breakpoint.c
> @@ -167,7 +167,7 @@ static int debug_arch_supported(void)
>  /* Can we determine the watchpoint access type from the fsr? */
>  static int debug_exception_updates_fsr(void)
>  {
> -	return 0;
> +	return get_debug_arch() == ARM_DEBUG_ARCH_V8;

I'd probably make that >= to save on future changes.

With that change:

  Acked-by: Will Deacon <will.deacon@arm.com>

Will

^ permalink raw reply

* [GIT PULL] ARM: mvebu: DT boards for v3.14 (incr #6)
From: Olof Johansson @ 2014-01-28 18:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140120200110.GW29184@titan.lakedaemon.net>

On Mon, Jan 20, 2014 at 12:01 PM, Jason Cooper <jason@lakedaemon.net> wrote:
> All,
>
> I had a few boards that came in late in the cycle.  I was holding on to
> them for the next round, but after Olof's comment this morning:
>
>   Re: [PATCH 0/2] DT updates for Hummingboard and new Cubox-i
>   http://www.spinics.net/lists/arm-kernel/msg301777.html
>
> I figured I'd send them off.  As usual, they've been in -next for a
> while.  Also, this is an incremental request from tags/mvebu-dt-3.14-5
> to tags/mvebu-dt-3.14-6 on the mvebu/dt branch.
>
> If this is going to be ok for the forseeable future, I'll do a separate
> branch for new boards next time around.

I should probably clarify my previous statement. I don't think we want
a free-for-all on new DT contents all the way up until -rc<lownumber>,
but what we can allow sometimes is new DT files when there's good
reason to do so -- for example for platforms where a lot of new code
has landed and it's been hard to sequence DT updates with the rest,
etc.

So, if you send these late requests please be prepared to motivate
them. :) These don't look urgent to me so I think we'll queue them for
3.15 once -rc1 is out, if that's OK with you.


-Olof

^ permalink raw reply

* [Q] block / zynq: DMA bouncing
From: Jason Gunthorpe @ 2014-01-28 18:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140128134827.GK15937@n2100.arm.linux.org.uk>

On Tue, Jan 28, 2014 at 01:48:27PM +0000, Russell King - ARM Linux wrote:
> On Tue, Jan 28, 2014 at 02:28:28PM +0100, Guennadi Liakhovetski wrote:
> > +static void __init zynq_memory_init(void)
> > +{
> > +	/*
> > +	 * Reserve the 0-0x4000 addresses (before page tables and kernel)
> > +	 * which can't be used for DMA
> > +	 */
> > +	if (!__pa(PAGE_OFFSET))
> > +		memblock_reserve(0, 0x4000);
> 
> Or maybe this:
> 
> 	memblock_reserve(__pa(PAGE_OFFSET), __pa(swapper_pg_dir));
> 
> since that's actually what you mean here.

Can you have a non-zero PAGE_OFFSET and swapper_pg_dir != 0x4000?
Crash dump kernel maybe?

Perhaps:
	if (__pa(PAGE_OFFSET) < 0x8000)
 	   memblock_reserve(__pa(PAGE_OFFSET),
	                    min(__pa(swapper_pg_dir), 0x8000));
?

The Zynq TRM, UG585 pg 115, describes this issue. Physical addresses
below 0x8000 are not accessible to DMA from the AXI interconnect.

Though, how does a crash dump kernel know it needs to bounce buffer
the swapper if it dumps it via DMA?

Regards,
Jason

^ permalink raw reply

* [linux-pm] ARM hibernation / suspend-to-disk
From: Sebastian Capella @ 2014-01-28 18:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140128182245.18840.51279@capellas-linux>

Quoting Sebastian Capella (2014-01-28 10:22:45)
> Otherwise, I am still looking at how to get this upstream by verifying
> on omap 5.  In my case, I still have the chicken egg problem, where I'm 
> trying to verify on omap 5 with out of tree patches.

Sorry, incorrect, I'm verifying on Beaglebone black not OMAP 5.

^ permalink raw reply


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