Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1234004 > unrolled thread
| Started by | Markos Chandras <markos.chandras@imgtec.com> |
|---|---|
| First post | 2015-09-28 12:10 +0200 |
| Last post | 2015-09-28 15:20 +0200 |
| Articles | 9 — 6 participants |
Back to article view | Back to linux.kernel
[PATCH 0/3] MIPS VDSO support Markos Chandras <markos.chandras@imgtec.com> - 2015-09-28 12:10 +0200
[PATCH 3/3] MIPS: VDSO: Add implementations of gettimeofday() and clock_gettime() Markos Chandras <markos.chandras@imgtec.com> - 2015-09-28 12:20 +0200
[PATCH 2/3] irqchip: irq-mips-gic: Provide function to map GIC user section Markos Chandras <markos.chandras@imgtec.com> - 2015-09-28 12:20 +0200
Re: [PATCH 2/3] irqchip: irq-mips-gic: Provide function to map GIC user section Marc Zyngier <marc.zyngier@arm.com> - 2015-09-28 13:00 +0200
Re: [PATCH 2/3] irqchip: irq-mips-gic: Provide function to map GIC user section Qais Yousef <qais.yousef@imgtec.com> - 2015-09-28 16:20 +0200
Re: [PATCH 2/3] irqchip: irq-mips-gic: Provide function to map GIC user section Marc Zyngier <marc.zyngier@arm.com> - 2015-09-28 17:10 +0200
Re: [PATCH 2/3] irqchip: irq-mips-gic: Provide function to map GIC user section Markos Chandras <Markos.Chandras@imgtec.com> - 2015-10-05 10:30 +0200
Re: [PATCH 1/3] MIPS: Initial implementation of a VDSO Alex Smith <alex@alex-smith.me.uk> - 2015-09-28 13:00 +0200
RE: [PATCH 1/3] MIPS: Initial implementation of a VDSO Matthew Fortune <Matthew.Fortune@imgtec.com> - 2015-09-28 15:20 +0200
| From | Markos Chandras <markos.chandras@imgtec.com> |
|---|---|
| Date | 2015-09-28 12:10 +0200 |
| Subject | [PATCH 0/3] MIPS VDSO support |
| Message-ID | <qdDxE-2zm-11@gated-at.bofh.it> |
Hi, This series adds a proper VDSO to the kernel on MIPS. The first commit adds the basic VDSO, replacing the current signal return trampoline page. The following commits add user implementations of gettimeofday() and clock_gettime() which can make use of either the CP0 count or the GIC user-mode visible section. A tree with these changes can be found at [1]. It's based on v4.3-rc3 Use of the time functions relies on glibc modifications. A patch for this can be found in my repository at [2] and I will soon post it to the glibc mailing list. [1]: http://git.linux-mips.org/cgit/mchandras/linux.git/log/?h=4.3-vdso [2]: https://github.com/hwoarang/glibc/tree/2.22-vdso Alex Smith (3): MIPS: Initial implementation of a VDSO irqchip: irq-mips-gic: Provide function to map GIC user section MIPS: VDSO: Add implementations of gettimeofday() and clock_gettime() arch/mips/Kbuild | 1 + arch/mips/Kconfig | 5 + arch/mips/include/asm/abi.h | 5 +- arch/mips/include/asm/clocksource.h | 29 ++++ arch/mips/include/asm/elf.h | 7 + arch/mips/include/asm/processor.h | 8 +- arch/mips/include/asm/vdso.h | 139 +++++++++++++++-- arch/mips/include/uapi/asm/Kbuild | 2 +- arch/mips/include/uapi/asm/auxvec.h | 17 ++ arch/mips/kernel/csrc-r4k.c | 44 ++++++ arch/mips/kernel/signal.c | 12 +- arch/mips/kernel/signal32.c | 7 +- arch/mips/kernel/signal_n32.c | 5 +- arch/mips/kernel/vdso.c | 198 ++++++++++++++--------- arch/mips/vdso/.gitignore | 4 + arch/mips/vdso/Makefile | 142 +++++++++++++++++ arch/mips/vdso/elf.S | 68 ++++++++ arch/mips/vdso/genvdso.c | 294 +++++++++++++++++++++++++++++++++++ arch/mips/vdso/genvdso.h | 188 ++++++++++++++++++++++ arch/mips/vdso/gettimeofday.c | 232 +++++++++++++++++++++++++++ arch/mips/vdso/sigreturn.S | 49 ++++++ arch/mips/vdso/vdso.h | 84 ++++++++++ arch/mips/vdso/vdso.lds.S | 103 ++++++++++++ drivers/clocksource/mips-gic-timer.c | 7 +- drivers/irqchip/irq-mips-gic.c | 27 +++- include/linux/irqchip/mips-gic.h | 24 ++- 26 files changed, 1572 insertions(+), 129 deletions(-) create mode 100644 arch/mips/include/asm/clocksource.h create mode 100644 arch/mips/include/uapi/asm/auxvec.h create mode 100644 arch/mips/vdso/.gitignore create mode 100644 arch/mips/vdso/Makefile create mode 100644 arch/mips/vdso/elf.S create mode 100644 arch/mips/vdso/genvdso.c create mode 100644 arch/mips/vdso/genvdso.h create mode 100644 arch/mips/vdso/gettimeofday.c create mode 100644 arch/mips/vdso/sigreturn.S create mode 100644 arch/mips/vdso/vdso.h create mode 100644 arch/mips/vdso/vdso.lds.S -- 2.5.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Markos Chandras <markos.chandras@imgtec.com> |
|---|---|
| Date | 2015-09-28 12:20 +0200 |
| Subject | [PATCH 3/3] MIPS: VDSO: Add implementations of gettimeofday() and clock_gettime() |
| Message-ID | <qdDHj-2KC-17@gated-at.bofh.it> |
| In reply to | #1234004 |
From: Alex Smith <alex.smith@imgtec.com>
Add user-mode implementations of gettimeofday() and clock_gettime() to
the VDSO. This is currently usable with 2 clocksources: the CP0 count
register, which is accessible to user-mode via RDHWR on R2 and later
cores, or the MIPS Global Interrupt Controller (GIC) timer, which
provides a "user-mode visible" section containing a mirror of its
counter registers. This section must be mapped into user memory, which
is done below the VDSO data page.
When a supported clocksource is not in use, the VDSO functions will
return -ENOSYS, which causes libc to fall back on the standard syscall
path.
When support for neither of these clocksources is compiled into the
kernel at all, the VDSO still provides clock_gettime(), as the coarse
realtime/monotonic clocks can still be implemented. However,
gettimeofday() is not provided in this case as nothing can be done
without a suitable clocksource. This causes the symbol lookup to fail
in libc and it will then always use the standard syscall path.
This patch includes a workaround for a bug in QEMU which results in
RDHWR on the CP0 count register always returning a constant (incorrect)
value. A fix for this has been submitted, and the workaround can be
removed after the fix has been in stable releases for a reasonable
amount of time.
A simple performance test which calls gettimeofday() 1000 times in a
loop and calculates the average execution time gives the following
results on a Malta + I6400 (running at 20MHz):
- Syscall: ~31000 ns
- VDSO (GIC): ~15000 ns
- VDSO (CP0): ~9500 ns
[markos.chandras@imgtec.com:
- Minor code re-arrangements in order for mappings to be made
in the order they appear to the process' address space.
- Move do_{monotonic, realtime} outside of the MIPS_CLOCK_VSYSCALL ifdef]
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Alex Smith <alex.smith@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
arch/mips/Kconfig | 5 +
arch/mips/include/asm/clocksource.h | 29 +++++
arch/mips/include/asm/vdso.h | 68 +++++++++-
arch/mips/kernel/csrc-r4k.c | 44 +++++++
arch/mips/kernel/vdso.c | 62 +++++++++-
arch/mips/vdso/Makefile | 2 +-
arch/mips/vdso/gettimeofday.c | 232 +++++++++++++++++++++++++++++++++++
arch/mips/vdso/vdso.h | 9 ++
arch/mips/vdso/vdso.lds.S | 3 +
drivers/clocksource/mips-gic-timer.c | 7 +-
10 files changed, 450 insertions(+), 11 deletions(-)
create mode 100644 arch/mips/include/asm/clocksource.h
create mode 100644 arch/mips/vdso/gettimeofday.c
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index e3aa5b0b4ef1..68f4f246887c 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -60,6 +60,8 @@ config MIPS
select SYSCTL_EXCEPTION_TRACE
select HAVE_VIRT_CPU_ACCOUNTING_GEN
select HAVE_IRQ_TIME_ACCOUNTING
+ select GENERIC_TIME_VSYSCALL
+ select ARCH_CLOCKSOURCE_DATA
menu "Machine selection"
@@ -1036,6 +1038,9 @@ config CSRC_R4K
config CSRC_SB1250
bool
+config MIPS_CLOCK_VSYSCALL
+ def_bool CSRC_R4K || CLKSRC_MIPS_GIC
+
config GPIO_TXX9
select ARCH_REQUIRE_GPIOLIB
bool
diff --git a/arch/mips/include/asm/clocksource.h b/arch/mips/include/asm/clocksource.h
new file mode 100644
index 000000000000..3deb1d0c1a94
--- /dev/null
+++ b/arch/mips/include/asm/clocksource.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_CLOCKSOURCE_H
+#define __ASM_CLOCKSOURCE_H
+
+#include <linux/types.h>
+
+/* VDSO clocksources. */
+#define VDSO_CLOCK_NONE 0 /* No suitable clocksource. */
+#define VDSO_CLOCK_R4K 1 /* Use the coprocessor 0 count. */
+#define VDSO_CLOCK_GIC 2 /* Use the GIC. */
+
+/**
+ * struct arch_clocksource_data - Architecture-specific clocksource information.
+ * @vdso_clock_mode: Method the VDSO should use to access the clocksource.
+ */
+struct arch_clocksource_data {
+ u8 vdso_clock_mode;
+};
+
+#endif /* __ASM_CLOCKSOURCE_H */
diff --git a/arch/mips/include/asm/vdso.h b/arch/mips/include/asm/vdso.h
index db2d45be8f2e..8f4ca5dd992b 100644
--- a/arch/mips/include/asm/vdso.h
+++ b/arch/mips/include/asm/vdso.h
@@ -13,6 +13,8 @@
#include <linux/mm_types.h>
+#include <asm/barrier.h>
+
/**
* struct mips_vdso_image - Details of a VDSO image.
* @data: Pointer to VDSO image data (page-aligned).
@@ -53,18 +55,82 @@ extern struct mips_vdso_image vdso_image_n32;
/**
* union mips_vdso_data - Data provided by the kernel for the VDSO.
+ * @xtime_sec: Current real time (seconds part).
+ * @xtime_nsec: Current real time (nanoseconds part, shifted).
+ * @wall_to_mono_sec: Wall-to-monotonic offset (seconds part).
+ * @wall_to_mono_nsec: Wall-to-monotonic offset (nanoseconds part).
+ * @seq_count: Counter to synchronise updates (odd = updating).
+ * @cs_shift: Clocksource shift value.
+ * @clock_mode: Clocksource to use for time functions.
+ * @cs_mult: Clocksource multiplier value.
+ * @cs_cycle_last: Clock cycle value at last update.
+ * @cs_mask: Clocksource mask value.
+ * @tz_minuteswest: Minutes west of Greenwich (from timezone).
+ * @tz_dsttime: Type of DST correction (from timezone).
*
* This structure contains data needed by functions within the VDSO. It is
- * populated by the kernel and mapped read-only into user memory.
+ * populated by the kernel and mapped read-only into user memory. The time
+ * fields are mirrors of internal data from the timekeeping infrastructure.
*
* Note: Care should be taken when modifying as the layout must remain the same
* for both 64- and 32-bit (for 32-bit userland on 64-bit kernel).
*/
union mips_vdso_data {
struct {
+ u64 xtime_sec;
+ u64 xtime_nsec;
+ u32 wall_to_mono_sec;
+ u32 wall_to_mono_nsec;
+ u32 seq_count;
+ u32 cs_shift;
+ u8 clock_mode;
+ u32 cs_mult;
+ u64 cs_cycle_last;
+ u64 cs_mask;
+ s32 tz_minuteswest;
+ s32 tz_dsttime;
};
u8 page[PAGE_SIZE];
};
+static inline u32 vdso_data_read_begin(const union mips_vdso_data *data)
+{
+ u32 seq;
+
+ while (true) {
+ seq = ACCESS_ONCE(data->seq_count);
+ if (likely(!(seq & 1))) {
+ /* Paired with smp_wmb() in vdso_data_write_*(). */
+ smp_rmb();
+ return seq;
+ }
+
+ cpu_relax();
+ }
+}
+
+static inline bool vdso_data_read_retry(const union mips_vdso_data *data,
+ u32 start_seq)
+{
+ /* Paired with smp_wmb() in vdso_data_write_*(). */
+ smp_rmb();
+ return unlikely(data->seq_count != start_seq);
+}
+
+static inline void vdso_data_write_begin(union mips_vdso_data *data)
+{
+ ++data->seq_count;
+
+ /* Ensure sequence update is written before other data page values. */
+ smp_wmb();
+}
+
+static inline void vdso_data_write_end(union mips_vdso_data *data)
+{
+ /* Ensure data values are written before updating sequence again. */
+ smp_wmb();
+ ++data->seq_count;
+}
+
#endif /* __ASM_VDSO_H */
diff --git a/arch/mips/kernel/csrc-r4k.c b/arch/mips/kernel/csrc-r4k.c
index e5ed7ada1433..1f910563fdf6 100644
--- a/arch/mips/kernel/csrc-r4k.c
+++ b/arch/mips/kernel/csrc-r4k.c
@@ -28,6 +28,43 @@ static u64 notrace r4k_read_sched_clock(void)
return read_c0_count();
}
+static inline unsigned int rdhwr_count(void)
+{
+ unsigned int count;
+
+ __asm__ __volatile__(
+ " .set push\n"
+ " .set mips32r2\n"
+ " rdhwr %0, $2\n"
+ " .set pop\n"
+ : "=r" (count));
+
+ return count;
+}
+
+static bool rdhwr_count_usable(void)
+{
+ unsigned int prev, curr, i;
+
+ /*
+ * Older QEMUs have a broken implementation of RDHWR for the CP0 count
+ * which always returns a constant value. Try to identify this and don't
+ * use it in the VDSO if it is broken. This workaround can be removed
+ * once the fix has been in QEMU stable for a reasonable amount of time.
+ */
+ for (i = 0, prev = rdhwr_count(); i < 100; i++) {
+ curr = rdhwr_count();
+
+ if (curr != prev)
+ return true;
+
+ prev = curr;
+ }
+
+ pr_warn("Not using R4K clocksource in VDSO due to broken RDHWR\n");
+ return false;
+}
+
int __init init_r4k_clocksource(void)
{
if (!cpu_has_counter || !mips_hpt_frequency)
@@ -36,6 +73,13 @@ int __init init_r4k_clocksource(void)
/* Calculate a somewhat reasonable rating value */
clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000;
+ /*
+ * R2 onwards makes the count accessible to user mode so it can be used
+ * by the VDSO (HWREna is configured by configure_hwrena()).
+ */
+ if (cpu_has_mips_r2_r6 && rdhwr_count_usable())
+ clocksource_mips.archdata.vdso_clock_mode = VDSO_CLOCK_R4K;
+
clocksource_register_hz(&clocksource_mips, mips_hpt_frequency);
sched_clock_register(r4k_read_sched_clock, 32, mips_hpt_frequency);
diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c
index 56cc3c4377fb..7894db0c7922 100644
--- a/arch/mips/kernel/vdso.c
+++ b/arch/mips/kernel/vdso.c
@@ -12,9 +12,11 @@
#include <linux/elf.h>
#include <linux/err.h>
#include <linux/init.h>
+#include <linux/irqchip/mips-gic.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/timekeeper_internal.h>
#include <asm/abi.h>
#include <asm/vdso.h>
@@ -23,7 +25,7 @@
static union mips_vdso_data vdso_data __page_aligned_data;
/*
- * Mapping for the VDSO data pages. The real pages are mapped manually, as
+ * Mapping for the VDSO data/GIC pages. The real pages are mapped manually, as
* what we map and where within the area they are mapped is determined at
* runtime.
*/
@@ -64,25 +66,66 @@ static int __init init_vdso(void)
}
subsys_initcall(init_vdso);
+void update_vsyscall(struct timekeeper *tk)
+{
+ vdso_data_write_begin(&vdso_data);
+
+ vdso_data.xtime_sec = tk->xtime_sec;
+ vdso_data.xtime_nsec = tk->tkr_mono.xtime_nsec;
+ vdso_data.wall_to_mono_sec = tk->wall_to_monotonic.tv_sec;
+ vdso_data.wall_to_mono_nsec = tk->wall_to_monotonic.tv_nsec;
+ vdso_data.cs_shift = tk->tkr_mono.shift;
+
+ vdso_data.clock_mode = tk->tkr_mono.clock->archdata.vdso_clock_mode;
+ if (vdso_data.clock_mode != VDSO_CLOCK_NONE) {
+ vdso_data.cs_mult = tk->tkr_mono.mult;
+ vdso_data.cs_cycle_last = tk->tkr_mono.cycle_last;
+ vdso_data.cs_mask = tk->tkr_mono.mask;
+ }
+
+ vdso_data_write_end(&vdso_data);
+}
+
+void update_vsyscall_tz(void)
+{
+ if (vdso_data.clock_mode != VDSO_CLOCK_NONE) {
+ vdso_data.tz_minuteswest = sys_tz.tz_minuteswest;
+ vdso_data.tz_dsttime = sys_tz.tz_dsttime;
+ }
+}
+
int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
{
struct mips_vdso_image *image = current->thread.abi->vdso;
struct mm_struct *mm = current->mm;
- unsigned long base, vdso_addr;
+ unsigned long gic_size, vvar_size, size, base, data_addr, vdso_addr;
struct vm_area_struct *vma;
int ret;
down_write(&mm->mmap_sem);
- base = get_unmapped_area(NULL, 0, PAGE_SIZE + image->size, 0, 0);
+ /*
+ * Determine total area size. This includes the VDSO data itself, the
+ * data page, and the GIC user page if present. Always create a mapping
+ * for the GIC user area if the GIC is present regardless of whether it
+ * is the current clocksource, in case it comes into use later on. We
+ * only map a page even though the total area is 64K, as we only need
+ * the counter registers at the start.
+ */
+ gic_size = gic_present ? PAGE_SIZE : 0;
+ vvar_size = gic_size + PAGE_SIZE;
+ size = vvar_size + image->size;
+
+ base = get_unmapped_area(NULL, 0, size, 0, 0);
if (IS_ERR_VALUE(base)) {
ret = base;
goto out;
}
- vdso_addr = base + PAGE_SIZE;
+ data_addr = base + gic_size;
+ vdso_addr = data_addr + PAGE_SIZE;
- vma = _install_special_mapping(mm, base, PAGE_SIZE,
+ vma = _install_special_mapping(mm, base, vvar_size,
VM_READ | VM_MAYREAD,
&vdso_vvar_mapping);
if (IS_ERR(vma)) {
@@ -90,8 +133,15 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
goto out;
}
+ /* Map GIC user page. */
+ if (gic_size) {
+ ret = gic_map_user_section(vma, base, gic_size);
+ if (ret)
+ goto out;
+ }
+
/* Map data page. */
- ret = remap_pfn_range(vma, base,
+ ret = remap_pfn_range(vma, data_addr,
virt_to_phys(&vdso_data) >> PAGE_SHIFT,
PAGE_SIZE, PAGE_READONLY);
if (ret)
diff --git a/arch/mips/vdso/Makefile b/arch/mips/vdso/Makefile
index 9a8a6b373eb0..c2820997ea9b 100644
--- a/arch/mips/vdso/Makefile
+++ b/arch/mips/vdso/Makefile
@@ -1,5 +1,5 @@
# Objects to go into the VDSO.
-obj-vdso-y := elf.o sigreturn.o
+obj-vdso-y := elf.o gettimeofday.o sigreturn.o
# Common compiler flags between ABIs.
ccflags-vdso := \
diff --git a/arch/mips/vdso/gettimeofday.c b/arch/mips/vdso/gettimeofday.c
new file mode 100644
index 000000000000..ce89c9e294f9
--- /dev/null
+++ b/arch/mips/vdso/gettimeofday.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2015 Imagination Technologies
+ * Author: Alex Smith <alex.smith@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include "vdso.h"
+
+#include <linux/compiler.h>
+#include <linux/irqchip/mips-gic.h>
+#include <linux/time.h>
+
+#include <asm/clocksource.h>
+#include <asm/io.h>
+#include <asm/mips-cm.h>
+#include <asm/unistd.h>
+#include <asm/vdso.h>
+
+static __always_inline int do_realtime_coarse(struct timespec *ts,
+ const union mips_vdso_data *data)
+{
+ u32 start_seq;
+
+ do {
+ start_seq = vdso_data_read_begin(data);
+
+ ts->tv_sec = data->xtime_sec;
+ ts->tv_nsec = data->xtime_nsec >> data->cs_shift;
+ } while (vdso_data_read_retry(data, start_seq));
+
+ return 0;
+}
+
+static __always_inline int do_monotonic_coarse(struct timespec *ts,
+ const union mips_vdso_data *data)
+{
+ u32 start_seq;
+ u32 to_mono_sec;
+ u32 to_mono_nsec;
+
+ do {
+ start_seq = vdso_data_read_begin(data);
+
+ ts->tv_sec = data->xtime_sec;
+ ts->tv_nsec = data->xtime_nsec >> data->cs_shift;
+
+ to_mono_sec = data->wall_to_mono_sec;
+ to_mono_nsec = data->wall_to_mono_nsec;
+ } while (vdso_data_read_retry(data, start_seq));
+
+ ts->tv_sec += to_mono_sec;
+ timespec_add_ns(ts, to_mono_nsec);
+
+ return 0;
+}
+
+#ifdef CONFIG_CSRC_R4K
+
+static __always_inline u64 read_r4k_count(void)
+{
+ unsigned int count;
+
+ __asm__ __volatile__(
+ " .set push\n"
+ " .set mips32r2\n"
+ " rdhwr %0, $2\n"
+ " .set pop\n"
+ : "=r" (count));
+
+ return count;
+}
+
+#endif
+
+#ifdef CONFIG_CLKSRC_MIPS_GIC
+
+static __always_inline u64 read_gic_count(const union mips_vdso_data *data)
+{
+ void __iomem *gic = get_gic(data);
+ u32 hi, hi2, lo;
+
+ do {
+ hi = __raw_readl(gic + GIC_UMV_SH_COUNTER_63_32_OFS);
+ lo = __raw_readl(gic + GIC_UMV_SH_COUNTER_31_00_OFS);
+ hi2 = __raw_readl(gic + GIC_UMV_SH_COUNTER_63_32_OFS);
+ } while (hi2 != hi);
+
+ return (((u64)hi) << 32) + lo;
+}
+
+#endif
+
+static __always_inline u64 get_ns(const union mips_vdso_data *data)
+{
+ u64 cycle_now, delta, nsec;
+
+ switch (data->clock_mode) {
+#ifdef CONFIG_CSRC_R4K
+ case VDSO_CLOCK_R4K:
+ cycle_now = read_r4k_count();
+ break;
+#endif
+#ifdef CONFIG_CLKSRC_MIPS_GIC
+ case VDSO_CLOCK_GIC:
+ cycle_now = read_gic_count(data);
+ break;
+#endif
+ default:
+ return 0;
+ }
+
+ delta = (cycle_now - data->cs_cycle_last) & data->cs_mask;
+
+ nsec = (delta * data->cs_mult) + data->xtime_nsec;
+ nsec >>= data->cs_shift;
+
+ return nsec;
+}
+
+static __always_inline int do_realtime(struct timespec *ts,
+ const union mips_vdso_data *data)
+{
+ u32 start_seq;
+ u64 ns;
+
+ do {
+ start_seq = vdso_data_read_begin(data);
+
+ if (data->clock_mode == VDSO_CLOCK_NONE)
+ return -ENOSYS;
+
+ ts->tv_sec = data->xtime_sec;
+ ns = get_ns(data);
+ } while (vdso_data_read_retry(data, start_seq));
+
+ ts->tv_nsec = 0;
+ timespec_add_ns(ts, ns);
+
+ return 0;
+}
+
+static __always_inline int do_monotonic(struct timespec *ts,
+ const union mips_vdso_data *data)
+{
+ u32 start_seq;
+ u64 ns;
+ u32 to_mono_sec;
+ u32 to_mono_nsec;
+
+ do {
+ start_seq = vdso_data_read_begin(data);
+
+ if (data->clock_mode == VDSO_CLOCK_NONE)
+ return -ENOSYS;
+
+ ts->tv_sec = data->xtime_sec;
+ ns = get_ns(data);
+
+ to_mono_sec = data->wall_to_mono_sec;
+ to_mono_nsec = data->wall_to_mono_nsec;
+ } while (vdso_data_read_retry(data, start_seq));
+
+ ts->tv_sec += to_mono_sec;
+ ts->tv_nsec = 0;
+ timespec_add_ns(ts, ns + to_mono_nsec);
+
+ return 0;
+}
+
+#ifdef CONFIG_MIPS_CLOCK_VSYSCALL
+
+/*
+ * This is behind the ifdef so that we don't provide the symbol when there's no
+ * possibility of there being a usable clocksource, because there's nothing we
+ * can do without it. When libc fails the symbol lookup it should fall back on
+ * the standard syscall path.
+ */
+int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+ const union mips_vdso_data *data = get_vdso_data();
+ struct timespec ts;
+ int ret;
+
+ ret = do_realtime(&ts, data);
+ if (ret)
+ return ret;
+
+ if (tv) {
+ tv->tv_sec = ts.tv_sec;
+ tv->tv_usec = ts.tv_nsec / 1000;
+ }
+
+ if (tz) {
+ tz->tz_minuteswest = data->tz_minuteswest;
+ tz->tz_dsttime = data->tz_dsttime;
+ }
+
+ return 0;
+}
+
+#endif /* CONFIG_CLKSRC_MIPS_GIC */
+
+int __vdso_clock_gettime(clockid_t clkid, struct timespec *ts)
+{
+ const union mips_vdso_data *data = get_vdso_data();
+ int ret;
+
+ switch (clkid) {
+ case CLOCK_REALTIME_COARSE:
+ ret = do_realtime_coarse(ts, data);
+ break;
+ case CLOCK_MONOTONIC_COARSE:
+ ret = do_monotonic_coarse(ts, data);
+ break;
+ case CLOCK_REALTIME:
+ ret = do_realtime(ts, data);
+ break;
+ case CLOCK_MONOTONIC:
+ ret = do_monotonic(ts, data);
+ break;
+ default:
+ ret = -ENOSYS;
+ break;
+ }
+
+ /* If we return -ENOSYS libc should fall back to a syscall. */
+ return ret;
+}
diff --git a/arch/mips/vdso/vdso.h b/arch/mips/vdso/vdso.h
index 64b98967e245..1072f8634417 100644
--- a/arch/mips/vdso/vdso.h
+++ b/arch/mips/vdso/vdso.h
@@ -76,4 +76,13 @@ static inline const union mips_vdso_data *get_vdso_data(void)
return (const union mips_vdso_data *)(get_vdso_base() - PAGE_SIZE);
}
+#ifdef CONFIG_CLKSRC_MIPS_GIC
+
+static inline void __iomem *get_gic(const union mips_vdso_data *data)
+{
+ return (void __iomem *)data - PAGE_SIZE;
+}
+
+#endif /* CONFIG_CLKSRC_MIPS_GIC */
+
#endif /* __ASSEMBLY__ */
diff --git a/arch/mips/vdso/vdso.lds.S b/arch/mips/vdso/vdso.lds.S
index 21655b6fefc5..0bda37c5a1e6 100644
--- a/arch/mips/vdso/vdso.lds.S
+++ b/arch/mips/vdso/vdso.lds.S
@@ -95,6 +95,9 @@ PHDRS
VERSION
{
LINUX_2.6 {
+ global:
+ __vdso_clock_gettime;
+ __vdso_gettimeofday;
local: *;
};
}
diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-gic-timer.c
index 02a1945e5093..89d3e4d7900c 100644
--- a/drivers/clocksource/mips-gic-timer.c
+++ b/drivers/clocksource/mips-gic-timer.c
@@ -140,9 +140,10 @@ static cycle_t gic_hpt_read(struct clocksource *cs)
}
static struct clocksource gic_clocksource = {
- .name = "GIC",
- .read = gic_hpt_read,
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ .name = "GIC",
+ .read = gic_hpt_read,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ .archdata = { .vdso_clock_mode = VDSO_CLOCK_GIC },
};
static void __init __gic_clocksource_init(void)
--
2.5.3
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Markos Chandras <markos.chandras@imgtec.com> |
|---|---|
| Date | 2015-09-28 12:20 +0200 |
| Subject | [PATCH 2/3] irqchip: irq-mips-gic: Provide function to map GIC user section |
| Message-ID | <qdDHj-2KC-11@gated-at.bofh.it> |
| In reply to | #1234004 |
From: Alex Smith <alex.smith@imgtec.com>
The GIC provides a "user-mode visible" section containing a mirror of
the counter registers which can be mapped into user memory. This will
be used by the VDSO time function implementations, so provide a
function to map it in.
When the GIC is not enabled in Kconfig a dummy inline version of this
function is provided, along with "#define gic_present 0", so that we
don't have to litter the VDSO code with ifdefs.
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Alex Smith <alex.smith@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
---
drivers/irqchip/irq-mips-gic.c | 27 +++++++++++++++++++++------
include/linux/irqchip/mips-gic.h | 24 ++++++++++++++++++++++--
2 files changed, 43 insertions(+), 8 deletions(-)
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index af2f16bb8a94..c995b199ca32 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -13,6 +13,7 @@
#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/irqchip/mips-gic.h>
+#include <linux/mm.h>
#include <linux/of_address.h>
#include <linux/sched.h>
#include <linux/smp.h>
@@ -29,6 +30,7 @@ struct gic_pcpu_mask {
DECLARE_BITMAP(pcpu_mask, GIC_MAX_INTRS);
};
+static unsigned long gic_base_addr;
static void __iomem *gic_base;
static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
static DEFINE_SPINLOCK(gic_lock);
@@ -301,6 +303,19 @@ int gic_get_c0_fdc_int(void)
GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_FDC));
}
+int gic_map_user_section(struct vm_area_struct *vma, unsigned long base,
+ unsigned long size)
+{
+ unsigned long pfn;
+
+ BUG_ON(!gic_present);
+ BUG_ON(size > USM_VISIBLE_SECTION_SIZE);
+
+ pfn = (gic_base_addr + USM_VISIBLE_SECTION_OFS) >> PAGE_SHIFT;
+ return io_remap_pfn_range(vma, base, pfn, size,
+ pgprot_noncached(PAGE_READONLY));
+}
+
static void gic_handle_shared_int(bool chained)
{
unsigned int i, intr, virq, gic_reg_step = mips_cm_is64 ? 8 : 4;
@@ -783,14 +798,15 @@ static const struct irq_domain_ops gic_irq_domain_ops = {
.xlate = gic_irq_domain_xlate,
};
-static void __init __gic_init(unsigned long gic_base_addr,
- unsigned long gic_addrspace_size,
+static void __init __gic_init(unsigned long base_addr,
+ unsigned long addrspace_size,
unsigned int cpu_vec, unsigned int irqbase,
struct device_node *node)
{
unsigned int gicconfig;
- gic_base = ioremap_nocache(gic_base_addr, gic_addrspace_size);
+ gic_base_addr = base_addr;
+ gic_base = ioremap_nocache(base_addr, addrspace_size);
gicconfig = gic_read(GIC_REG(SHARED, GIC_SH_CONFIG));
gic_shared_intrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >>
@@ -847,11 +863,10 @@ static void __init __gic_init(unsigned long gic_base_addr,
gic_ipi_init();
}
-void __init gic_init(unsigned long gic_base_addr,
- unsigned long gic_addrspace_size,
+void __init gic_init(unsigned long base_addr, unsigned long addrspace_size,
unsigned int cpu_vec, unsigned int irqbase)
{
- __gic_init(gic_base_addr, gic_addrspace_size, cpu_vec, irqbase, NULL);
+ __gic_init(base_addr, addrspace_size, cpu_vec, irqbase, NULL);
}
static int __init gic_of_init(struct device_node *node,
diff --git a/include/linux/irqchip/mips-gic.h b/include/linux/irqchip/mips-gic.h
index 4e6861605050..68f2e9539204 100644
--- a/include/linux/irqchip/mips-gic.h
+++ b/include/linux/irqchip/mips-gic.h
@@ -245,10 +245,14 @@
#define GIC_SHARED_TO_HWIRQ(x) (GIC_SHARED_HWIRQ_BASE + (x))
#define GIC_HWIRQ_TO_SHARED(x) ((x) - GIC_SHARED_HWIRQ_BASE)
+struct vm_area_struct;
+
+#ifdef CONFIG_MIPS_GIC
+
extern unsigned int gic_present;
-extern void gic_init(unsigned long gic_base_addr,
- unsigned long gic_addrspace_size, unsigned int cpu_vec,
+extern void gic_init(unsigned long base_addr,
+ unsigned long addrspace_size, unsigned int cpu_vec,
unsigned int irqbase);
extern void gic_clocksource_init(unsigned int);
extern cycle_t gic_read_count(void);
@@ -264,4 +268,20 @@ extern unsigned int plat_ipi_resched_int_xlate(unsigned int);
extern int gic_get_c0_compare_int(void);
extern int gic_get_c0_perfcount_int(void);
extern int gic_get_c0_fdc_int(void);
+extern int gic_map_user_section(struct vm_area_struct *vma, unsigned long base,
+ unsigned long size);
+
+#else /* CONFIG_MIPS_GIC */
+
+#define gic_present 0
+
+static inline int gic_map_user_section(struct vm_area_struct *vma,
+ unsigned long base, unsigned long size)
+{
+ /* Shouldn't be called. */
+ return -1;
+}
+
+#endif /* CONFIG_MIPS_GIC */
+
#endif /* __LINUX_IRQCHIP_MIPS_GIC_H */
--
2.5.3
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Marc Zyngier <marc.zyngier@arm.com> |
|---|---|
| Date | 2015-09-28 13:00 +0200 |
| Subject | Re: [PATCH 2/3] irqchip: irq-mips-gic: Provide function to map GIC user section |
| Message-ID | <qdEk3-3tU-25@gated-at.bofh.it> |
| In reply to | #1234011 |
On 28/09/15 11:11, Markos Chandras wrote:
> From: Alex Smith <alex.smith@imgtec.com>
>
> The GIC provides a "user-mode visible" section containing a mirror of
> the counter registers which can be mapped into user memory. This will
> be used by the VDSO time function implementations, so provide a
> function to map it in.
>
> When the GIC is not enabled in Kconfig a dummy inline version of this
> function is provided, along with "#define gic_present 0", so that we
> don't have to litter the VDSO code with ifdefs.
>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Jason Cooper <jason@lakedaemon.net>
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Alex Smith <alex.smith@imgtec.com>
> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
> ---
> drivers/irqchip/irq-mips-gic.c | 27 +++++++++++++++++++++------
> include/linux/irqchip/mips-gic.h | 24 ++++++++++++++++++++++--
> 2 files changed, 43 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
> index af2f16bb8a94..c995b199ca32 100644
> --- a/drivers/irqchip/irq-mips-gic.c
> +++ b/drivers/irqchip/irq-mips-gic.c
> @@ -13,6 +13,7 @@
> #include <linux/irq.h>
> #include <linux/irqchip.h>
> #include <linux/irqchip/mips-gic.h>
> +#include <linux/mm.h>
> #include <linux/of_address.h>
> #include <linux/sched.h>
> #include <linux/smp.h>
> @@ -29,6 +30,7 @@ struct gic_pcpu_mask {
> DECLARE_BITMAP(pcpu_mask, GIC_MAX_INTRS);
> };
>
> +static unsigned long gic_base_addr;
> static void __iomem *gic_base;
> static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
> static DEFINE_SPINLOCK(gic_lock);
> @@ -301,6 +303,19 @@ int gic_get_c0_fdc_int(void)
> GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_FDC));
> }
>
> +int gic_map_user_section(struct vm_area_struct *vma, unsigned long base,
> + unsigned long size)
> +{
> + unsigned long pfn;
> +
> + BUG_ON(!gic_present);
Why do you have a BUG() here, while you're just returning -1 in the case
where CONFIG_MIPS_GIC is not refined? This feels overly harsh to me.
> + BUG_ON(size > USM_VISIBLE_SECTION_SIZE);
Same here.
> +
> + pfn = (gic_base_addr + USM_VISIBLE_SECTION_OFS) >> PAGE_SHIFT;
> + return io_remap_pfn_range(vma, base, pfn, size,
> + pgprot_noncached(PAGE_READONLY));
Two things:
- I suppose you are comfortable with making this region accessible to
userspace (obviously). Not knowing anything about it, is it guaranteed
not to trigger any unpleasant event even if the luser tries to play
dirty tricks on it (like doing unaligned or exclusive access)?
- Does this code have to be in the irqchip driver? It really feels out
of place, and I'd rather see a function that returns the mappable range
to the VDSO code, where the mapping would occur.
Thanks,
M.
--
Jazz is not dead. It just smells funny...
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Qais Yousef <qais.yousef@imgtec.com> |
|---|---|
| Date | 2015-09-28 16:20 +0200 |
| Subject | Re: [PATCH 2/3] irqchip: irq-mips-gic: Provide function to map GIC user section |
| Message-ID | <qdHrB-1Q9-33@gated-at.bofh.it> |
| In reply to | #1234050 |
On 09/28/2015 11:55 AM, Marc Zyngier wrote: > On 28/09/15 11:11, Markos Chandras wrote: > >> + >> + pfn = (gic_base_addr + USM_VISIBLE_SECTION_OFS) >> PAGE_SHIFT; >> + return io_remap_pfn_range(vma, base, pfn, size, >> + pgprot_noncached(PAGE_READONLY)); > > - Does this code have to be in the irqchip driver? It really feels out > of place, and I'd rather see a function that returns the mappable range > to the VDSO code, where the mapping would occur. > I don't think it's a good idea either for the VDSO code to know about gic_base_addr. Maybe this function could be split to return the pfn and let the caller do io_remap_pfn_range(). Though I think it's nice to have it all there. USM stands for USer Mode - GIC wants to make some stuff visible to user mode and it puts them in that special section. So it makes sense to do it all there IMO. Qais -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Marc Zyngier <marc.zyngier@arm.com> |
|---|---|
| Date | 2015-09-28 17:10 +0200 |
| Subject | Re: [PATCH 2/3] irqchip: irq-mips-gic: Provide function to map GIC user section |
| Message-ID | <qdIdY-301-25@gated-at.bofh.it> |
| In reply to | #1234197 |
On 28/09/15 15:16, Qais Yousef wrote:
> On 09/28/2015 11:55 AM, Marc Zyngier wrote:
>> On 28/09/15 11:11, Markos Chandras wrote:
>>
>>> +
>>> + pfn = (gic_base_addr + USM_VISIBLE_SECTION_OFS) >> PAGE_SHIFT;
>>> + return io_remap_pfn_range(vma, base, pfn, size,
>>> + pgprot_noncached(PAGE_READONLY));
>>
>> - Does this code have to be in the irqchip driver? It really feels out
>> of place, and I'd rather see a function that returns the mappable range
>> to the VDSO code, where the mapping would occur.
>>
>
>
> I don't think it's a good idea either for the VDSO code to know about
> gic_base_addr. Maybe this function could be split to return the pfn and
> let the caller do io_remap_pfn_range(). Though I think it's nice to have
> it all there. USM stands for USer Mode - GIC wants to make some stuff
> visible to user mode and it puts them in that special section. So it
> makes sense to do it all there IMO.
Maybe I wasn't clear enough. My suggestion was to expose this in
the VDSO setup code:
@@ -90,8 +133,15 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
goto out;
}
+ /* Map GIC user page. */
+ if (gic_size) {
+ ret = gic_map_user_section(vma, base, gic_size);
+ if (ret)
+ goto out;
+ }
+
This could easily be written as:
if (gic_size) {
struct resource gic_res;
ret = gic_get_usm_range(&gic_res);
if (ret)
goto out;
... and perform the mapping here...
}
You can also rewrite the hunks above to actually get the present/size
information from the GIC. And if you have DT, you should be able to
directly find the memory region there, without involving the GIC
driver at all.
I don't really fancy having some userspace visible stuff in an
interrupt controller driver, and I tend to find it nicer to split
the responsabilities: the VDSO code deals with the userspace mapping,
and the interrupt controller deals with interrupts.
Thanks,
M.
--
Jazz is not dead. It just smells funny...
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Markos Chandras <Markos.Chandras@imgtec.com> |
|---|---|
| Date | 2015-10-05 10:30 +0200 |
| Subject | Re: [PATCH 2/3] irqchip: irq-mips-gic: Provide function to map GIC user section |
| Message-ID | <qg9jJ-1RW-25@gated-at.bofh.it> |
| In reply to | #1234050 |
Hi,
On 09/28/2015 11:55 AM, Marc Zyngier wrote:
> On 28/09/15 11:11, Markos Chandras wrote:
>> From: Alex Smith <alex.smith@imgtec.com>
>>
>> The GIC provides a "user-mode visible" section containing a mirror of
>> the counter registers which can be mapped into user memory. This will
>> be used by the VDSO time function implementations, so provide a
>> function to map it in.
>>
>> When the GIC is not enabled in Kconfig a dummy inline version of this
>> function is provided, along with "#define gic_present 0", so that we
>> don't have to litter the VDSO code with ifdefs.
>>
>> Cc: Thomas Gleixner <tglx@linutronix.de>
>> Cc: Jason Cooper <jason@lakedaemon.net>
>> Cc: Marc Zyngier <marc.zyngier@arm.com>
>> Cc: linux-kernel@vger.kernel.org
>> Signed-off-by: Alex Smith <alex.smith@imgtec.com>
>> Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
>> ---
>> drivers/irqchip/irq-mips-gic.c | 27 +++++++++++++++++++++------
>> include/linux/irqchip/mips-gic.h | 24 ++++++++++++++++++++++--
>> 2 files changed, 43 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
>> index af2f16bb8a94..c995b199ca32 100644
>> --- a/drivers/irqchip/irq-mips-gic.c
>> +++ b/drivers/irqchip/irq-mips-gic.c
>> @@ -13,6 +13,7 @@
>> #include <linux/irq.h>
>> #include <linux/irqchip.h>
>> #include <linux/irqchip/mips-gic.h>
>> +#include <linux/mm.h>
>> #include <linux/of_address.h>
>> #include <linux/sched.h>
>> #include <linux/smp.h>
>> @@ -29,6 +30,7 @@ struct gic_pcpu_mask {
>> DECLARE_BITMAP(pcpu_mask, GIC_MAX_INTRS);
>> };
>>
>> +static unsigned long gic_base_addr;
>> static void __iomem *gic_base;
>> static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
>> static DEFINE_SPINLOCK(gic_lock);
>> @@ -301,6 +303,19 @@ int gic_get_c0_fdc_int(void)
>> GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_FDC));
>> }
>>
>> +int gic_map_user_section(struct vm_area_struct *vma, unsigned long base,
>> + unsigned long size)
>> +{
>> + unsigned long pfn;
>> +
>> + BUG_ON(!gic_present);
>
> Why do you have a BUG() here, while you're just returning -1 in the case
> where CONFIG_MIPS_GIC is not refined? This feels overly harsh to me.
I suppose i could change that to return -1 if git_present is not true.
>
>> + BUG_ON(size > USM_VISIBLE_SECTION_SIZE);
>
> Same here.
But I think this is different. The size of mapping has to be less than
USM_VISIBLE_SECTION_SIZE because that's the maximum data size exposed by
the GIC chip for userspace use. So if that's not true, then BUG_ON seems
like a sensible thing to do.
>
> - Does this code have to be in the irqchip driver? It really feels out
> of place, and I'd rather see a function that returns the mappable range
> to the VDSO code, where the mapping would occur.
>
> Thanks,
>
That does seem like a good idea. I will have a look
--
markos
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Alex Smith <alex@alex-smith.me.uk> |
|---|---|
| Date | 2015-09-28 13:00 +0200 |
| Subject | Re: [PATCH 1/3] MIPS: Initial implementation of a VDSO |
| Message-ID | <qdEk2-3tU-1@gated-at.bofh.it> |
| In reply to | #1234004 |
Hi Markos,
Thanks for finishing this off. Just got a few of minor comments.
On 28 September 2015 at 11:10, Markos Chandras
<markos.chandras@imgtec.com> wrote:
> diff --git a/arch/mips/vdso/elf.S b/arch/mips/vdso/elf.S
> new file mode 100644
> index 000000000000..60c23d0d452c
> --- /dev/null
> +++ b/arch/mips/vdso/elf.S
> @@ -0,0 +1,68 @@
> +/*
> + * Copyright (C) 2015 Imagination Technologies
> + * Author: Alex Smith <alex.smith@imgtec.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + */
> +
> +#include "vdso.h"
> +
> +#include <linux/elfnote.h>
> +#include <linux/version.h>
> +
> +ELFNOTE_START(Linux, 0, "a")
> + .long LINUX_VERSION_CODE
> +ELFNOTE_END
> +
> +/*
> + * The .MIPS.abiflags section must be defined with the FP ABI flags set
> + * to 'any' to be able to link with both old and new libraries.
> + * Newer toolchains are capable of automatically generating this, but we want
> + * to work with older toolchains as well. Therefore, we define the contents of
> + * this section here (under different names), and then genvdso will patch
> + * it to have the correct name and type.
> + *
> + * We base the .MIPS.abiflags section on preprocessor definitions rather than
> + * CONFIG_* because we need to match the particular ABI we are building the
> + * VDSO for.
> + *
> + * See https://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking
> + * for the .MIPS.abitflags and .gnu.attributes section description.
> + */
s/abitflags/abiflags/
> diff --git a/arch/mips/vdso/vdso.h b/arch/mips/vdso/vdso.h
> new file mode 100644
> index 000000000000..64b98967e245
> --- /dev/null
> +++ b/arch/mips/vdso/vdso.h
> @@ -0,0 +1,79 @@
> +/*
> + * Copyright (C) 2015 Imagination Technologies
> + * Author: Alex Smith <alex.smith@imgtec.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + */
> +
> +#include <asm/sgidefs.h>
> +
> +#if _MIPS_SIM != _MIPS_SIM_ABI64 && defined(CONFIG_64BIT)
> +
> +/* Building 32-bit VDSO for the 64-bit kernel. Fake a 32-bit Kconfig. */
> +#undef CONFIG_64BIT
> +#define CONFIG_32BIT 1
> +
> +#endif
> +
> +#ifndef __ASSEMBLY__
> +
> +#include <asm/asm.h>
> +#include <asm/page.h>
> +#include <asm/vdso.h>
> +
> +static inline unsigned long get_vdso_base(void)
> +{
> + unsigned long addr;
> +
> + /*
> + * Get the base load address of the VDSO. We have to avoid generating
> + * relocations and references to the GOT because ld.so does not peform
> + * relocations on the VDSO. We use the current offset from the VDSO base
> + * and perform a PC-relative branch which gives the absolute address in
> + * ra, and take the difference. The assembler chokes on
> + * "li %0, _start - .", so embed the offset as a word and branch over
> + * it.
> + *
> + * TODO: Is there a better way to do this?
Unless somebody else can come up with a better way to do this I'd say
this TODO can go :)
Also perhaps move the description of what the code is doing (from "We
use the current offset from the VDSO base" onwards) down to after the
#else since it applies to that code rather than the R6 code which
comes first.
> + */
> +
> +#ifdef CONFIG_CPU_MIPSR6
> + /*
> + * We can't use cpu_has_mips_r6 since it will create a relocation
> + * in the VDSO because of the global cpu_data[] variable.
> + */
I think it would be more correct to say here that cpu_data doesn't
even exist to the VDSO because it's a kernel symbol.
> +
> + /* lapc <symbol> is an alias to addiupc reg, <symbol> - .
> + *
> + * We can't use addiupc because there is no label-label
> + * support for the addiupc reloc
> + */
> + __asm__("lapc %0, _start \n"
> + : "=r" (addr) : :);
Just curious - if lapc is just an alias to addiupc, why does that work
but not addiupc? IIRC I did try addiupc previously but removed it
because it wasn't working, didn't know about lapc!
Thanks,
Alex
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Matthew Fortune <Matthew.Fortune@imgtec.com> |
|---|---|
| Date | 2015-09-28 15:20 +0200 |
| Subject | RE: [PATCH 1/3] MIPS: Initial implementation of a VDSO |
| Message-ID | <qdGvw-6My-23@gated-at.bofh.it> |
| In reply to | #1234045 |
QWxleCBTbWl0aCA8YWxleEBhbGV4LXNtaXRoLm1lLnVrPiB3cml0ZXM6DQo+ID4gKw0KPiA+ICsg ICAgICAgLyogbGFwYyA8c3ltYm9sPiBpcyBhbiBhbGlhcyB0byBhZGRpdXBjIHJlZywgPHN5bWJv bD4gLSAuDQo+ID4gKyAgICAgICAgKg0KPiA+ICsgICAgICAgICogV2UgY2FuJ3QgdXNlIGFkZGl1 cGMgYmVjYXVzZSB0aGVyZSBpcyBubyBsYWJlbC1sYWJlbA0KPiA+ICsgICAgICAgICogc3VwcG9y dCBmb3IgdGhlIGFkZGl1cGMgcmVsb2MNCj4gPiArICAgICAgICAqLw0KPiA+ICsgICAgICAgX19h c21fXygibGFwYyAgICUwLCBfc3RhcnQgICAgICAgICAgICAgICAgICAgICAgXG4iDQo+ID4gKyAg ICAgICAgICAgICAgIDogIj1yIiAoYWRkcikgOiA6KTsNCj4gDQo+IEp1c3QgY3VyaW91cyAtIGlm IGxhcGMgaXMganVzdCBhbiBhbGlhcyB0byBhZGRpdXBjLCB3aHkgZG9lcyB0aGF0IHdvcmsNCj4g YnV0IG5vdCBhZGRpdXBjPyBJSVJDIEkgZGlkIHRyeSBhZGRpdXBjIHByZXZpb3VzbHkgYnV0IHJl bW92ZWQgaXQNCj4gYmVjYXVzZSBpdCB3YXNuJ3Qgd29ya2luZywgZGlkbid0IGtub3cgYWJvdXQg bGFwYyENCg0KVGhpcyBpcyBqdXN0IGFuIHVuZm9ydHVuYXRlIHF1aXJrIG9mIGhvdyB0aGUgaW1w bGVtZW50YXRpb24gaXMgZG9uZSBpbg0KYmludXRpbHMuIFdlIGRvbid0IHJlY29nbmlzZSB0aGUg c3BlY2lhbCBjYXNlIHRoYXQ6DQoNCmFkZGl1cGMgPHJlZz4sIDxzeW0+IC0gLg0KDQppcyB0aGUg c2FtZSBhcw0KDQpsYXBjIDxyZWc+LCA8c3ltPg0KDQpBbmQgdGhlcmVmb3JlIGRvbid0IGtub3cg dGhhdCB3ZSBjYW4ganVzdCB1c2UgdGhlIE1JUFNfUEMxOV9TMiByZWxvYw0KKG5hbWUgb2YgdGhh dCByZWxvYyBtYXkgbm90IGJlIHBlcmZlY3RseSBjb3JyZWN0KS4gSXQgaXMgYSBzcGVjaWFsDQpj YXNlIGFzIHRoZSBSSFMgb2YgdGhlIGV4cHJlc3Npb24gaW4gQURESVVQQyBhYm92ZSBjYW4gYmUg dGhlb3JldGljYWxseQ0KYW55dGhpbmcgc28gd2Ugb25seSBzdXBwb3J0IGFzc2VtYmx5IHRpbWUg Y29uc3RhbnRzIHdpdGggYWRkaXVwYy4NCg0KQXBhcnQgZnJvbSB0aGUgbmVlZCB0byBkb2N1bWVu dCB0aGUgTEFQQyBhbGlhcyBzb21ld2hlcmUgSSdtIG5vdCBzdXJlDQp3ZSBuZWVkIGRvIGFueXRo aW5nIHRvIGltcHJvdmUgYWRkaXVwYyBpdHNlbGYgcGFydGljdWxhcmx5Lg0KDQpUaGFua3MsDQpN YXR0aGV3DQo= -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web