Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1659280 > unrolled thread
| Started by | Palmer Dabbelt <palmer@dabbelt.com> |
|---|---|
| First post | 2017-06-07 01:10 +0200 |
| Last post | 2017-06-09 10:20 +0200 |
| Articles | 20 on this page of 46 — 13 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
RISC-V Linux Port v2 Palmer Dabbelt <palmer@dabbelt.com> - 2017-06-07 01:10 +0200
[PATCH 06/17] pci: Add generic pcibios_{fixup_bus,align_resource} Palmer Dabbelt <palmer@dabbelt.com> - 2017-06-07 01:10 +0200
Re: [PATCH 06/17] pci: Add generic pcibios_{fixup_bus,align_resource} Geert Uytterhoeven <geert@linux-m68k.org> - 2017-06-07 09:30 +0200
Re: [PATCH 06/17] pci: Add generic pcibios_{fixup_bus,align_resource} Arnd Bergmann <arnd@arndb.de> - 2017-06-07 10:10 +0200
Re: [PATCH 06/17] pci: Add generic pcibios_{fixup_bus,align_resource} Christoph Hellwig <hch@infradead.org> - 2017-06-08 10:20 +0200
Re: [PATCH 06/17] pci: Add generic pcibios_{fixup_bus,align_resource} Arnd Bergmann <arnd@arndb.de> - 2017-06-08 10:40 +0200
[PATCH 08/17] dts: include documentation for the RISC-V interrupt controllers Palmer Dabbelt <palmer@dabbelt.com> - 2017-06-07 01:10 +0200
Re: [PATCH 08/17] dts: include documentation for the RISC-V interrupt controllers Geert Uytterhoeven <geert@linux-m68k.org> - 2017-06-07 09:20 +0200
Re: [PATCH 08/17] dts: include documentation for the RISC-V interrupt controllers Mark Rutland <mark.rutland@arm.com> - 2017-06-07 12:20 +0200
Re: [PATCH 08/17] dts: include documentation for the RISC-V interrupt controllers Wesley Terpstra <wesley@sifive.com> - 2017-06-07 21:00 +0200
Re: [PATCH 08/17] dts: include documentation for the RISC-V interrupt controllers Rob Herring <robh+dt@kernel.org> - 2017-06-07 22:00 +0200
Re: [PATCH 08/17] dts: include documentation for the RISC-V interrupt controllers Wesley Terpstra <wesley@sifive.com> - 2017-06-07 22:40 +0200
Re: [PATCH 08/17] dts: include documentation for the RISC-V interrupt controllers Mark Rutland <mark.rutland@arm.com> - 2017-06-08 13:00 +0200
Re: [PATCH 08/17] dts: include documentation for the RISC-V interrupt controllers Wesley Terpstra <wesley@sifive.com> - 2017-06-09 23:50 +0200
Re: [PATCH 08/17] dts: include documentation for the RISC-V interrupt controllers Wesley Terpstra <wesley@sifive.com> - 2017-06-10 00:00 +0200
Re: [PATCH 08/17] dts: include documentation for the RISC-V interrupt controllers Mark Rutland <mark.rutland@arm.com> - 2017-06-19 16:40 +0200
Re: [PATCH 08/17] dts: include documentation for the RISC-V interrupt controllers "Luis R. Rodriguez" <mcgrof@kernel.org> - 2017-06-08 00:30 +0200
[PATCH 11/17] irqchip: RISC-V Local Interrupt Controller Driver Palmer Dabbelt <palmer@dabbelt.com> - 2017-06-07 01:10 +0200
Re: [PATCH 11/17] irqchip: RISC-V Local Interrupt Controller Driver Geert Uytterhoeven <geert@linux-m68k.org> - 2017-06-07 09:20 +0200
[PATCH 01/17] drivers: support PCIe in RISCV Palmer Dabbelt <palmer@dabbelt.com> - 2017-06-07 01:10 +0200
Re: [PATCH 01/17] drivers: support PCIe in RISCV Geert Uytterhoeven <geert@linux-m68k.org> - 2017-06-07 09:20 +0200
Re: [PATCH 01/17] drivers: support PCIe in RISCV Christoph Hellwig <hch@infradead.org> - 2017-06-07 16:30 +0200
Re: [PATCH 01/17] drivers: support PCIe in RISCV Olof Johansson <olof@lixom.net> - 2017-06-07 19:50 +0200
[PATCH 15/17] RISC-V: Add mm subdirectory Palmer Dabbelt <palmer@dabbelt.com> - 2017-06-07 01:10 +0200
[PATCH 09/17] clocksource/timer-riscv: New RISC-V Clocksource Palmer Dabbelt <palmer@dabbelt.com> - 2017-06-07 01:10 +0200
Re: [PATCH 09/17] clocksource/timer-riscv: New RISC-V Clocksource Geert Uytterhoeven <geert@linux-m68k.org> - 2017-06-07 09:20 +0200
Re: [PATCH 09/17] clocksource/timer-riscv: New RISC-V Clocksource Arnd Bergmann <arnd@arndb.de> - 2017-06-07 09:30 +0200
Re: [PATCH 09/17] clocksource/timer-riscv: New RISC-V Clocksource Marc Zyngier <marc.zyngier@arm.com> - 2017-06-07 11:50 +0200
Re: RISC-V Linux Port v2 David Howells <dhowells@redhat.com> - 2017-06-07 09:30 +0200
Re: RISC-V Linux Port v2 Palmer Dabbelt <palmer@dabbelt.com> - 2017-06-08 00:00 +0200
Re: [PATCH 13/17] RISC-V: Add include subdirectory Arnd Bergmann <arnd@arndb.de> - 2017-06-07 10:20 +0200
Re: RISC-V Linux Port v2 Will Deacon <will.deacon@arm.com> - 2017-06-07 11:30 +0200
Re: RISC-V Linux Port v2 Palmer Dabbelt <palmer@dabbelt.com> - 2017-06-08 00:00 +0200
Re: RISC-V Linux Port v2 Will Deacon <will.deacon@arm.com> - 2017-06-08 12:30 +0200
Re: RISC-V Linux Port v2 Palmer Dabbelt <palmer@dabbelt.com> - 2017-06-08 20:20 +0200
Re: [PATCH 13/17] RISC-V: Add include subdirectory Peter Zijlstra <peterz@infradead.org> - 2017-06-07 14:00 +0200
Re: [PATCH 13/17] RISC-V: Add include subdirectory Peter Zijlstra <peterz@infradead.org> - 2017-06-07 14:30 +0200
Re: [PATCH 13/17] RISC-V: Add include subdirectory Peter Zijlstra <peterz@infradead.org> - 2017-06-07 14:10 +0200
Re: [PATCH 13/17] RISC-V: Add include subdirectory Peter Zijlstra <peterz@infradead.org> - 2017-06-07 14:30 +0200
Re: [PATCH 13/17] RISC-V: Add include subdirectory Peter Zijlstra <peterz@infradead.org> - 2017-06-07 14:40 +0200
Re: [PATCH 13/17] RISC-V: Add include subdirectory Peter Zijlstra <peterz@infradead.org> - 2017-06-07 15:00 +0200
Re: [PATCH 13/17] RISC-V: Add include subdirectory Will Deacon <will.deacon@arm.com> - 2017-06-07 15:20 +0200
Re: [PATCH 13/17] RISC-V: Add include subdirectory Peter Zijlstra <peterz@infradead.org> - 2017-06-07 18:40 +0200
Re: [PATCH 13/17] RISC-V: Add include subdirectory Peter Zijlstra <peterz@infradead.org> - 2017-06-07 14:50 +0200
Re: [PATCH 13/17] RISC-V: Add include subdirectory Peter Zijlstra <peterz@infradead.org> - 2017-06-07 15:20 +0200
Re: [PATCH 13/17] RISC-V: Add include subdirectory Peter Zijlstra <peterz@infradead.org> - 2017-06-09 10:20 +0200
Page 2 of 3 — ← Prev page 1 [2] 3 Next page →
| From | Geert Uytterhoeven <geert@linux-m68k.org> |
|---|---|
| Date | 2017-06-07 09:20 +0200 |
| Subject | Re: [PATCH 01/17] drivers: support PCIe in RISCV |
| Message-ID | <tPDq2-3rU-25@gated-at.bofh.it> |
| In reply to | #1659285 |
CC pci folks On Wed, Jun 7, 2017 at 12:59 AM, Palmer Dabbelt <palmer@dabbelt.com> wrote: > From: "Wesley W. Terpstra" <wesley@sifive.com> > > There are RISC-V systems that have been mapped to Xilinx FPGAs that have > their PCIe controllers on chip. These build system changes allow RISC-V > systems to enable the Xilinx PCIe controller, and to setup PCIe IRQs. > > Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com> > --- > drivers/pci/Makefile | 1 + > drivers/pci/host/Kconfig | 2 +- > 2 files changed, 2 insertions(+), 1 deletion(-) > > diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile > index 462c1f5f5546..a29d9ec05d13 100644 > --- a/drivers/pci/Makefile > +++ b/drivers/pci/Makefile > @@ -41,6 +41,7 @@ obj-$(CONFIG_MIPS) += setup-irq.o > obj-$(CONFIG_TILE) += setup-irq.o > obj-$(CONFIG_SPARC_LEON) += setup-irq.o > obj-$(CONFIG_M68K) += setup-irq.o > +obj-$(CONFIG_RISCV) += setup-irq.o > > # > # ACPI Related PCI FW Functions > diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig > index 7f47cd5e10a5..5148f3d3cab7 100644 > --- a/drivers/pci/host/Kconfig > +++ b/drivers/pci/host/Kconfig > @@ -71,7 +71,7 @@ config PCI_HOST_GENERIC > > config PCIE_XILINX > bool "Xilinx AXI PCIe host bridge support" > - depends on ARCH_ZYNQ || MICROBLAZE > + depends on ARCH_ZYNQ || MICROBLAZE || RISCV > help > Say 'Y' here if you want kernel to support the Xilinx AXI PCIe > Host Bridge driver. > -- > 2.13.0
[toc] | [prev] | [next] | [standalone]
| From | Christoph Hellwig <hch@infradead.org> |
|---|---|
| Date | 2017-06-07 16:30 +0200 |
| Subject | Re: [PATCH 01/17] drivers: support PCIe in RISCV |
| Message-ID | <tPK89-7Mn-11@gated-at.bofh.it> |
| In reply to | #1659285 |
On Tue, Jun 06, 2017 at 03:59:51PM -0700, Palmer Dabbelt wrote: > From: "Wesley W. Terpstra" <wesley@sifive.com> > > There are RISC-V systems that have been mapped to Xilinx FPGAs that have > their PCIe controllers on chip. These build system changes allow RISC-V > systems to enable the Xilinx PCIe controller, and to setup PCIe IRQs. > > Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com> > --- > drivers/pci/Makefile | 1 + > drivers/pci/host/Kconfig | 2 +- > 2 files changed, 2 insertions(+), 1 deletion(-) > > diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile > index 462c1f5f5546..a29d9ec05d13 100644 > --- a/drivers/pci/Makefile > +++ b/drivers/pci/Makefile > @@ -41,6 +41,7 @@ obj-$(CONFIG_MIPS) += setup-irq.o > obj-$(CONFIG_TILE) += setup-irq.o > obj-$(CONFIG_SPARC_LEON) += setup-irq.o > obj-$(CONFIG_M68K) += setup-irq.o > +obj-$(CONFIG_RISCV) += setup-irq.o Can we do a cleanup here and add a ARCH_USE_GENERIC_PCI_SETUP Kconfig symbol that all these architectures can select? > > # > # ACPI Related PCI FW Functions > diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig > index 7f47cd5e10a5..5148f3d3cab7 100644 > --- a/drivers/pci/host/Kconfig > +++ b/drivers/pci/host/Kconfig > @@ -71,7 +71,7 @@ config PCI_HOST_GENERIC > > config PCIE_XILINX > bool "Xilinx AXI PCIe host bridge support" > - depends on ARCH_ZYNQ || MICROBLAZE > + depends on ARCH_ZYNQ || MICROBLAZE || RISCV What about of arch support does this driver need? It seems to compile just fine on x86 for me, so maybe we should just drop the arch dependency entirely.
[toc] | [prev] | [next] | [standalone]
| From | Olof Johansson <olof@lixom.net> |
|---|---|
| Date | 2017-06-07 19:50 +0200 |
| Subject | Re: [PATCH 01/17] drivers: support PCIe in RISCV |
| Message-ID | <tPNfH-1eJ-9@gated-at.bofh.it> |
| In reply to | #1659847 |
On Wed, Jun 7, 2017 at 10:09 AM, Wesley Terpstra <wesley@sifive.com> wrote: > > > On Jun 7, 2017 7:26 AM, "Christoph Hellwig" <hch@infradead.org> wrote: > > On Tue, Jun 06, 2017 at 03:59:51PM -0700, Palmer Dabbelt wrote: >> From: "Wesley W. Terpstra" <wesley@sifive.com> >> >> There are RISC-V systems that have been mapped to Xilinx FPGAs that have >> their PCIe controllers on chip. These build system changes allow RISC-V >> systems to enable the Xilinx PCIe controller, and to setup PCIe IRQs. >> >> Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com> >> --- >> drivers/pci/Makefile | 1 + >> drivers/pci/host/Kconfig | 2 +- >> 2 files changed, 2 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile >> index 462c1f5f5546..a29d9ec05d13 100644 >> --- a/drivers/pci/Makefile >> +++ b/drivers/pci/Makefile >> @@ -41,6 +41,7 @@ obj-$(CONFIG_MIPS) += setup-irq.o >> obj-$(CONFIG_TILE) += setup-irq.o >> obj-$(CONFIG_SPARC_LEON) += setup-irq.o >> obj-$(CONFIG_M68K) += setup-irq.o >> +obj-$(CONFIG_RISCV) += setup-irq.o > > Can we do a cleanup here and add a ARCH_USE_GENERIC_PCI_SETUP Kconfig > symbol that all these architectures can select? > > > That would probably be better. I did not want to touch other arch/ folders > in our changes. I understand that approach when you're doing things in your tree early, but in this case (and at this phase in submission/merging), don't be afraid to touch other architectures and refactor/clean up. Please do the refactor in a separate preceding patch and submit it separate/soon instead of keeping it just in the series and bundled with your addition. That way it can go in when ready even if the rest of the series is spinning. -Olof
[toc] | [prev] | [next] | [standalone]
| From | Palmer Dabbelt <palmer@dabbelt.com> |
|---|---|
| Date | 2017-06-07 01:10 +0200 |
| Subject | [PATCH 15/17] RISC-V: Add mm subdirectory |
| Message-ID | <tPvLR-6UA-47@gated-at.bofh.it> |
| In reply to | #1659280 |
These files are mostly based on the score port, but as all the non-stub
functions are very ISA specific they've been heavily modified.
Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com>
---
arch/riscv/mm/Makefile | 1 +
arch/riscv/mm/extable.c | 37 +++++++
arch/riscv/mm/fault.c | 280 ++++++++++++++++++++++++++++++++++++++++++++++++
arch/riscv/mm/init.c | 72 +++++++++++++
arch/riscv/mm/ioremap.c | 93 ++++++++++++++++
5 files changed, 483 insertions(+)
create mode 100644 arch/riscv/mm/Makefile
create mode 100644 arch/riscv/mm/extable.c
create mode 100644 arch/riscv/mm/fault.c
create mode 100644 arch/riscv/mm/init.c
create mode 100644 arch/riscv/mm/ioremap.c
diff --git a/arch/riscv/mm/Makefile b/arch/riscv/mm/Makefile
new file mode 100644
index 000000000000..36ebe6feb5d6
--- /dev/null
+++ b/arch/riscv/mm/Makefile
@@ -0,0 +1 @@
+obj-y := init.o fault.o extable.o ioremap.o
diff --git a/arch/riscv/mm/extable.c b/arch/riscv/mm/extable.c
new file mode 100644
index 000000000000..11bb9417123b
--- /dev/null
+++ b/arch/riscv/mm/extable.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2009 Sunplus Core Technology Co., Ltd.
+ * Lennox Wu <lennox.wu@sunplusct.com>
+ * Chen Liqin <liqin.chen@sunplusct.com>
+ * Copyright (C) 2013 Regents of the University of California
+ *
+ * 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.
+ *
+ * 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 the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ */
+
+
+#include <linux/extable.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+
+int fixup_exception(struct pt_regs *regs)
+{
+ const struct exception_table_entry *fixup;
+
+ fixup = search_exception_tables(regs->sepc);
+ if (fixup) {
+ regs->sepc = fixup->fixup;
+ return 1;
+ }
+ return 0;
+}
diff --git a/arch/riscv/mm/fault.c b/arch/riscv/mm/fault.c
new file mode 100644
index 000000000000..b2a431c7f233
--- /dev/null
+++ b/arch/riscv/mm/fault.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2009 Sunplus Core Technology Co., Ltd.
+ * Lennox Wu <lennox.wu@sunplusct.com>
+ * Chen Liqin <liqin.chen@sunplusct.com>
+ * Copyright (C) 2012 Regents of the University of California
+ *
+ * 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.
+ *
+ * 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 the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ */
+
+
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/perf_event.h>
+#include <linux/signal.h>
+#include <linux/uaccess.h>
+
+#include <asm/pgalloc.h>
+#include <asm/ptrace.h>
+#include <asm/uaccess.h>
+
+/*
+ * This routine handles page faults. It determines the address and the
+ * problem, and then passes it off to one of the appropriate routines.
+ */
+asmlinkage void do_page_fault(struct pt_regs *regs)
+{
+ struct task_struct *tsk;
+ struct vm_area_struct *vma;
+ struct mm_struct *mm;
+ unsigned long addr, cause;
+ unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
+ int fault, code = SEGV_MAPERR;
+
+ cause = regs->scause;
+ addr = regs->sbadaddr;
+
+ tsk = current;
+ mm = tsk->mm;
+
+ /*
+ * Fault-in kernel-space virtual memory on-demand.
+ * The 'reference' page table is init_mm.pgd.
+ *
+ * NOTE! We MUST NOT take any locks for this case. We may
+ * be in an interrupt or a critical region, and should
+ * only copy the information from the master page table,
+ * nothing more.
+ */
+ if (unlikely((addr >= VMALLOC_START) && (addr <= VMALLOC_END)))
+ goto vmalloc_fault;
+
+ /* Enable interrupts if they were enabled in the parent context. */
+ if (likely(regs->sstatus & SR_PIE))
+ local_irq_enable();
+
+ /*
+ * If we're in an interrupt, have no user context, or are running
+ * in an atomic region, then we must not take the fault.
+ */
+ if (unlikely(faulthandler_disabled() || !mm))
+ goto no_context;
+
+ if (user_mode(regs))
+ flags |= FAULT_FLAG_USER;
+
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, addr);
+
+retry:
+ down_read(&mm->mmap_sem);
+ vma = find_vma(mm, addr);
+ if (unlikely(!vma))
+ goto bad_area;
+ if (likely(vma->vm_start <= addr))
+ goto good_area;
+ if (unlikely(!(vma->vm_flags & VM_GROWSDOWN)))
+ goto bad_area;
+ if (unlikely(expand_stack(vma, addr)))
+ goto bad_area;
+
+ /*
+ * Ok, we have a good vm_area for this memory access, so
+ * we can handle it.
+ */
+good_area:
+ code = SEGV_ACCERR;
+
+ switch (cause) {
+ case EXC_INST_PAGE_FAULT:
+ if (!(vma->vm_flags & VM_EXEC))
+ goto bad_area;
+ break;
+ case EXC_LOAD_PAGE_FAULT:
+ if (!(vma->vm_flags & VM_READ))
+ goto bad_area;
+ break;
+ case EXC_STORE_PAGE_FAULT:
+ if (!(vma->vm_flags & VM_WRITE))
+ goto bad_area;
+ flags |= FAULT_FLAG_WRITE;
+ break;
+ default:
+ panic("%s: unhandled cause %lu", __func__, cause);
+ }
+
+ /*
+ * If for any reason at all we could not handle the fault,
+ * make sure we exit gracefully rather than endlessly redo
+ * the fault.
+ */
+ fault = handle_mm_fault(vma, addr, flags);
+
+ /*
+ * If we need to retry but a fatal signal is pending, handle the
+ * signal first. We do not need to release the mmap_sem because it
+ * would already be released in __lock_page_or_retry in mm/filemap.c.
+ */
+ if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(tsk))
+ return;
+
+ if (unlikely(fault & VM_FAULT_ERROR)) {
+ if (fault & VM_FAULT_OOM)
+ goto out_of_memory;
+ else if (fault & VM_FAULT_SIGBUS)
+ goto do_sigbus;
+ BUG();
+ }
+
+ /*
+ * Major/minor page fault accounting is only done on the
+ * initial attempt. If we go through a retry, it is extremely
+ * likely that the page will be found in page cache at that point.
+ */
+ if (flags & FAULT_FLAG_ALLOW_RETRY) {
+ if (fault & VM_FAULT_MAJOR) {
+ tsk->maj_flt++;
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ,
+ 1, regs, addr);
+ } else {
+ tsk->min_flt++;
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN,
+ 1, regs, addr);
+ }
+ if (fault & VM_FAULT_RETRY) {
+ /*
+ * Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
+ * of starvation.
+ */
+ flags &= ~(FAULT_FLAG_ALLOW_RETRY);
+ flags |= FAULT_FLAG_TRIED;
+
+ /*
+ * No need to up_read(&mm->mmap_sem) as we would
+ * have already released it in __lock_page_or_retry
+ * in mm/filemap.c.
+ */
+ goto retry;
+ }
+ }
+
+ up_read(&mm->mmap_sem);
+ return;
+
+ /*
+ * Something tried to access memory that isn't in our memory map.
+ * Fix it, but check if it's kernel or user first.
+ */
+bad_area:
+ up_read(&mm->mmap_sem);
+ /* User mode accesses just cause a SIGSEGV */
+ if (user_mode(regs)) {
+ do_trap(regs, SIGSEGV, code, addr, tsk);
+ return;
+ }
+
+no_context:
+ /* Are we prepared to handle this kernel fault? */
+ if (fixup_exception(regs))
+ return;
+
+ /*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+ */
+ bust_spinlocks(1);
+ pr_alert("Unable to handle kernel %s at virtual address " REG_FMT "\n",
+ (addr < PAGE_SIZE) ? "NULL pointer dereference" :
+ "paging request", addr);
+ die(regs, "Oops");
+ do_exit(SIGKILL);
+
+ /*
+ * We ran out of memory, call the OOM killer, and return the userspace
+ * (which will retry the fault, or kill us if we got oom-killed).
+ */
+out_of_memory:
+ up_read(&mm->mmap_sem);
+ if (!user_mode(regs))
+ goto no_context;
+ pagefault_out_of_memory();
+ return;
+
+do_sigbus:
+ up_read(&mm->mmap_sem);
+ /* Kernel mode? Handle exceptions or die */
+ if (!user_mode(regs))
+ goto no_context;
+ do_trap(regs, SIGBUS, BUS_ADRERR, addr, tsk);
+ return;
+
+vmalloc_fault:
+ {
+ pgd_t *pgd, *pgd_k;
+ pud_t *pud, *pud_k;
+ p4d_t *p4d, *p4d_k;
+ pmd_t *pmd, *pmd_k;
+ pte_t *pte_k;
+ int index;
+
+ if (user_mode(regs))
+ goto bad_area;
+
+ /*
+ * Synchronize this task's top level page-table
+ * with the 'reference' page table.
+ *
+ * Do _not_ use "tsk->active_mm->pgd" here.
+ * We might be inside an interrupt in the middle
+ * of a task switch.
+ */
+ index = pgd_index(addr);
+ pgd = (pgd_t *)pfn_to_virt(csr_read(sptbr)) + index;
+ pgd_k = init_mm.pgd + index;
+
+ if (!pgd_present(*pgd_k))
+ goto no_context;
+ set_pgd(pgd, *pgd_k);
+
+ p4d = p4d_offset(pgd, addr);
+ p4d_k = p4d_offset(pgd_k, addr);
+ if (!p4d_present(*p4d_k))
+ goto no_context;
+
+ pud = pud_offset(p4d, addr);
+ pud_k = pud_offset(p4d_k, addr);
+ if (!pud_present(*pud_k))
+ goto no_context;
+
+ /* Since the vmalloc area is global, it is unnecessary
+ * to copy individual PTEs
+ */
+ pmd = pmd_offset(pud, addr);
+ pmd_k = pmd_offset(pud_k, addr);
+ if (!pmd_present(*pmd_k))
+ goto no_context;
+ set_pmd(pmd, *pmd_k);
+
+ /* Make sure the actual PTE exists as well to
+ * catch kernel vmalloc-area accesses to non-mapped
+ * addresses. If we don't do this, this will just
+ * silently loop forever.
+ */
+ pte_k = pte_offset_kernel(pmd_k, addr);
+ if (!pte_present(*pte_k))
+ goto no_context;
+ return;
+ }
+}
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
new file mode 100644
index 000000000000..8ad464ce4a4c
--- /dev/null
+++ b/arch/riscv/mm/init.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2012 Regents of the University of California
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/initrd.h>
+#include <linux/memblock.h>
+#include <linux/swap.h>
+
+#include <asm/tlbflush.h>
+#include <asm/sections.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+
+static void __init zone_sizes_init(void)
+{
+ unsigned long zones_size[MAX_NR_ZONES];
+
+ memset(zones_size, 0, sizeof(zones_size));
+ zones_size[ZONE_NORMAL] = pfn_base + max_mapnr;
+ free_area_init_node(0, zones_size, pfn_base, NULL);
+}
+
+void setup_zero_page(void)
+{
+ memset((void *)empty_zero_page, 0, PAGE_SIZE);
+}
+
+void __init paging_init(void)
+{
+ init_mm.pgd = (pgd_t *)pfn_to_virt(csr_read(sptbr));
+
+ setup_zero_page();
+ local_flush_tlb_all();
+ zone_sizes_init();
+}
+
+void __init mem_init(void)
+{
+#ifdef CONFIG_FLATMEM
+ BUG_ON(!mem_map);
+#endif /* CONFIG_FLATMEM */
+
+ high_memory = (void *)(__va(PFN_PHYS(max_low_pfn)));
+ free_all_bootmem();
+
+ mem_init_print_info(NULL);
+}
+
+void free_initmem(void)
+{
+ free_initmem_default(0);
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+// free_reserved_area(start, end, 0, "initrd");
+}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
diff --git a/arch/riscv/mm/ioremap.c b/arch/riscv/mm/ioremap.c
new file mode 100644
index 000000000000..c5cc0935096d
--- /dev/null
+++ b/arch/riscv/mm/ioremap.c
@@ -0,0 +1,93 @@
+/*
+ * (C) Copyright 1995 1996 Linus Torvalds
+ * (C) Copyright 2012 Regents of the University of California
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+#include <linux/export.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/io.h>
+
+#include <asm/pgtable.h>
+
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space. Needed when the kernel wants to access high addresses
+ * directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
+ */
+static void __iomem *__ioremap_caller(phys_addr_t addr, size_t size,
+ pgprot_t prot, void *caller)
+{
+ phys_addr_t last_addr;
+ unsigned long offset, vaddr;
+ struct vm_struct *area;
+
+ /* Disallow wrap-around or zero size */
+ last_addr = addr + size - 1;
+ if (!size || last_addr < addr)
+ return NULL;
+
+ /* Page-align mappings */
+ offset = addr & (~PAGE_MASK);
+ addr &= PAGE_MASK;
+ size = PAGE_ALIGN(size + offset);
+
+ area = get_vm_area_caller(size, VM_IOREMAP, caller);
+ if (!area)
+ return NULL;
+ vaddr = (unsigned long)area->addr;
+
+ if (ioremap_page_range(vaddr, vaddr + size, addr, prot)) {
+ free_vm_area(area);
+ return NULL;
+ }
+
+ return (void __iomem *)(vaddr + offset);
+}
+
+/*
+ * ioremap - map bus memory into CPU space
+ * @offset: bus address of the memory
+ * @size: size of the resource to map
+ *
+ * ioremap performs a platform specific sequence of operations to
+ * make bus memory CPU accessible via the readb/readw/readl/writeb/
+ * writew/writel functions and the other mmio helpers. The returned
+ * address is not guaranteed to be usable directly as a virtual
+ * address.
+ *
+ * Must be freed with iounmap.
+ */
+void __iomem *ioremap(phys_addr_t offset, unsigned long size)
+{
+ return __ioremap_caller(offset, size, PAGE_KERNEL,
+ __builtin_return_address(0));
+}
+EXPORT_SYMBOL(ioremap);
+
+
+/**
+ * iounmap - Free a IO remapping
+ * @addr: virtual address from ioremap_*
+ *
+ * Caller must ensure there is only one unmapping for the same pointer.
+ */
+void iounmap(void __iomem *addr)
+{
+ vunmap((void *)((unsigned long)addr & PAGE_MASK));
+}
+EXPORT_SYMBOL(iounmap);
+
--
2.13.0
[toc] | [prev] | [next] | [standalone]
| From | Palmer Dabbelt <palmer@dabbelt.com> |
|---|---|
| Date | 2017-06-07 01:10 +0200 |
| Subject | [PATCH 09/17] clocksource/timer-riscv: New RISC-V Clocksource |
| Message-ID | <tPvLR-6UA-45@gated-at.bofh.it> |
| In reply to | #1659280 |
The RISC-V ISA defines a single RTC as well as an SBI oneshot timer.
This timer is present on all RISC-V systems.
Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com>
---
drivers/clocksource/Kconfig | 8 +++
drivers/clocksource/Makefile | 1 +
drivers/clocksource/timer-riscv.c | 118 ++++++++++++++++++++++++++++++++++++++
3 files changed, 127 insertions(+)
create mode 100644 drivers/clocksource/timer-riscv.c
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 545d541ae20e..1c2c6e7c7fab 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -612,4 +612,12 @@ config CLKSRC_ST_LPC
Enable this option to use the Low Power controller timer
as clocksource.
+config CLKSRC_RISCV
+ #bool "Clocksource for the RISC-V platform"
+ def_bool y if RISCV
+ depends on RISCV
+ help
+ This enables a clocksource based on the RISC-V SBI timer, which is
+ built in to all RISC-V systems.
+
endmenu
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 2b5b56a6f00f..408ed9d314dc 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -73,3 +73,4 @@ obj-$(CONFIG_H8300_TMR16) += h8300_timer16.o
obj-$(CONFIG_H8300_TPU) += h8300_tpu.o
obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o
obj-$(CONFIG_X86_NUMACHIP) += numachip.o
+obj-$(CONFIG_CLKSRC_RISCV) += timer-riscv.o
diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c
new file mode 100644
index 000000000000..04ef7b9130b3
--- /dev/null
+++ b/drivers/clocksource/timer-riscv.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2012 Regents of the University of California
+ * Copyright (C) 2017 SiFive
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+
+#include <asm/irq.h>
+#include <asm/csr.h>
+#include <asm/sbi.h>
+#include <asm/delay.h>
+
+unsigned long riscv_timebase;
+
+static DEFINE_PER_CPU(struct clock_event_device, clock_event);
+
+static int riscv_timer_set_next_event(unsigned long delta,
+ struct clock_event_device *evdev)
+{
+ sbi_set_timer(get_cycles() + delta);
+ return 0;
+}
+
+static int riscv_timer_set_oneshot(struct clock_event_device *evt)
+{
+ /* no-op; only one mode */
+ return 0;
+}
+
+static int riscv_timer_set_shutdown(struct clock_event_device *evt)
+{
+ /* can't stop the clock! */
+ return 0;
+}
+
+static u64 riscv_rdtime(struct clocksource *cs)
+{
+ return get_cycles();
+}
+
+static struct clocksource riscv_clocksource = {
+ .name = "riscv_clocksource",
+ .rating = 300,
+ .read = riscv_rdtime,
+#ifdef CONFIG_64BITS
+ .mask = CLOCKSOURCE_MASK(64),
+#else
+ .mask = CLOCKSOURCE_MASK(32),
+#endif /* CONFIG_64BITS */
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+void riscv_timer_interrupt(void)
+{
+ int cpu = smp_processor_id();
+ struct clock_event_device *evdev = &per_cpu(clock_event, cpu);
+
+ evdev->event_handler(evdev);
+}
+
+void __init init_clockevent(void)
+{
+ int cpu = smp_processor_id();
+ struct clock_event_device *ce = &per_cpu(clock_event, cpu);
+
+ *ce = (struct clock_event_device){
+ .name = "riscv_timer_clockevent",
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .rating = 300,
+ .cpumask = cpumask_of(cpu),
+ .set_next_event = riscv_timer_set_next_event,
+ .set_state_oneshot = riscv_timer_set_oneshot,
+ .set_state_shutdown = riscv_timer_set_shutdown,
+ };
+
+ /* Enable timer interrupts */
+ csr_set(sie, SIE_STIE);
+
+ clockevents_config_and_register(ce, riscv_timebase, 100, 0x7fffffff);
+}
+
+static unsigned long __init of_timebase(void)
+{
+ struct device_node *cpu;
+ const __be32 *prop;
+
+ cpu = of_find_node_by_path("/cpus");
+ if (cpu) {
+ prop = of_get_property(cpu, "timebase-frequency", NULL);
+ if (prop)
+ return be32_to_cpu(*prop);
+ }
+
+ return 10000000;
+}
+
+void __init time_init(void)
+{
+ riscv_timebase = of_timebase();
+ lpj_fine = riscv_timebase / HZ;
+
+ clocksource_register_hz(&riscv_clocksource, riscv_timebase);
+ init_clockevent();
+}
--
2.13.0
[toc] | [prev] | [next] | [standalone]
| From | Geert Uytterhoeven <geert@linux-m68k.org> |
|---|---|
| Date | 2017-06-07 09:20 +0200 |
| Subject | Re: [PATCH 09/17] clocksource/timer-riscv: New RISC-V Clocksource |
| Message-ID | <tPDq2-3rU-23@gated-at.bofh.it> |
| In reply to | #1659287 |
CC clocksource folks
On Wed, Jun 7, 2017 at 12:59 AM, Palmer Dabbelt <palmer@dabbelt.com> wrote:
> The RISC-V ISA defines a single RTC as well as an SBI oneshot timer.
> This timer is present on all RISC-V systems.
>
> Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com>
> ---
> drivers/clocksource/Kconfig | 8 +++
> drivers/clocksource/Makefile | 1 +
> drivers/clocksource/timer-riscv.c | 118 ++++++++++++++++++++++++++++++++++++++
> 3 files changed, 127 insertions(+)
> create mode 100644 drivers/clocksource/timer-riscv.c
>
> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
> index 545d541ae20e..1c2c6e7c7fab 100644
> --- a/drivers/clocksource/Kconfig
> +++ b/drivers/clocksource/Kconfig
> @@ -612,4 +612,12 @@ config CLKSRC_ST_LPC
> Enable this option to use the Low Power controller timer
> as clocksource.
>
> +config CLKSRC_RISCV
> + #bool "Clocksource for the RISC-V platform"
> + def_bool y if RISCV
> + depends on RISCV
> + help
> + This enables a clocksource based on the RISC-V SBI timer, which is
> + built in to all RISC-V systems.
> +
> endmenu
> diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
> index 2b5b56a6f00f..408ed9d314dc 100644
> --- a/drivers/clocksource/Makefile
> +++ b/drivers/clocksource/Makefile
> @@ -73,3 +73,4 @@ obj-$(CONFIG_H8300_TMR16) += h8300_timer16.o
> obj-$(CONFIG_H8300_TPU) += h8300_tpu.o
> obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o
> obj-$(CONFIG_X86_NUMACHIP) += numachip.o
> +obj-$(CONFIG_CLKSRC_RISCV) += timer-riscv.o
> diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c
> new file mode 100644
> index 000000000000..04ef7b9130b3
> --- /dev/null
> +++ b/drivers/clocksource/timer-riscv.c
> @@ -0,0 +1,118 @@
> +/*
> + * Copyright (C) 2012 Regents of the University of California
> + * Copyright (C) 2017 SiFive
> + *
> + * 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.
> + *
> + * 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.
> + */
> +
> +#include <linux/clocksource.h>
> +#include <linux/clockchips.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/delay.h>
> +#include <linux/of.h>
> +
> +#include <asm/irq.h>
> +#include <asm/csr.h>
> +#include <asm/sbi.h>
> +#include <asm/delay.h>
> +
> +unsigned long riscv_timebase;
> +
> +static DEFINE_PER_CPU(struct clock_event_device, clock_event);
> +
> +static int riscv_timer_set_next_event(unsigned long delta,
> + struct clock_event_device *evdev)
> +{
> + sbi_set_timer(get_cycles() + delta);
> + return 0;
> +}
> +
> +static int riscv_timer_set_oneshot(struct clock_event_device *evt)
> +{
> + /* no-op; only one mode */
> + return 0;
> +}
> +
> +static int riscv_timer_set_shutdown(struct clock_event_device *evt)
> +{
> + /* can't stop the clock! */
> + return 0;
> +}
> +
> +static u64 riscv_rdtime(struct clocksource *cs)
> +{
> + return get_cycles();
> +}
> +
> +static struct clocksource riscv_clocksource = {
> + .name = "riscv_clocksource",
> + .rating = 300,
> + .read = riscv_rdtime,
> +#ifdef CONFIG_64BITS
> + .mask = CLOCKSOURCE_MASK(64),
> +#else
> + .mask = CLOCKSOURCE_MASK(32),
> +#endif /* CONFIG_64BITS */
> + .flags = CLOCK_SOURCE_IS_CONTINUOUS,
> +};
> +
> +void riscv_timer_interrupt(void)
> +{
> + int cpu = smp_processor_id();
> + struct clock_event_device *evdev = &per_cpu(clock_event, cpu);
> +
> + evdev->event_handler(evdev);
> +}
> +
> +void __init init_clockevent(void)
> +{
> + int cpu = smp_processor_id();
> + struct clock_event_device *ce = &per_cpu(clock_event, cpu);
> +
> + *ce = (struct clock_event_device){
> + .name = "riscv_timer_clockevent",
> + .features = CLOCK_EVT_FEAT_ONESHOT,
> + .rating = 300,
> + .cpumask = cpumask_of(cpu),
> + .set_next_event = riscv_timer_set_next_event,
> + .set_state_oneshot = riscv_timer_set_oneshot,
> + .set_state_shutdown = riscv_timer_set_shutdown,
> + };
> +
> + /* Enable timer interrupts */
> + csr_set(sie, SIE_STIE);
> +
> + clockevents_config_and_register(ce, riscv_timebase, 100, 0x7fffffff);
> +}
> +
> +static unsigned long __init of_timebase(void)
> +{
> + struct device_node *cpu;
> + const __be32 *prop;
> +
> + cpu = of_find_node_by_path("/cpus");
> + if (cpu) {
> + prop = of_get_property(cpu, "timebase-frequency", NULL);
> + if (prop)
> + return be32_to_cpu(*prop);
> + }
> +
> + return 10000000;
> +}
> +
> +void __init time_init(void)
> +{
> + riscv_timebase = of_timebase();
> + lpj_fine = riscv_timebase / HZ;
> +
> + clocksource_register_hz(&riscv_clocksource, riscv_timebase);
> + init_clockevent();
> +}
> --
> 2.13.0
[toc] | [prev] | [next] | [standalone]
| From | Arnd Bergmann <arnd@arndb.de> |
|---|---|
| Date | 2017-06-07 09:30 +0200 |
| Subject | Re: [PATCH 09/17] clocksource/timer-riscv: New RISC-V Clocksource |
| Message-ID | <tPDzH-3vN-15@gated-at.bofh.it> |
| In reply to | #1659456 |
On Wed, Jun 7, 2017 at 9:12 AM, Geert Uytterhoeven <geert@linux-m68k.org> wrote:
> CC clocksource folks
>
> On Wed, Jun 7, 2017 at 12:59 AM, Palmer Dabbelt <palmer@dabbelt.com> wrote:
>> The RISC-V ISA defines a single RTC as well as an SBI oneshot timer.
>> This timer is present on all RISC-V systems.
>>
>> Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com>
>> ---
>> drivers/clocksource/Kconfig | 8 +++
>> drivers/clocksource/Makefile | 1 +
>> drivers/clocksource/timer-riscv.c | 118 ++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 127 insertions(+)
>> create mode 100644 drivers/clocksource/timer-riscv.c
>>
>> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
>> index 545d541ae20e..1c2c6e7c7fab 100644
>> --- a/drivers/clocksource/Kconfig
>> +++ b/drivers/clocksource/Kconfig
>> @@ -612,4 +612,12 @@ config CLKSRC_ST_LPC
>> Enable this option to use the Low Power controller timer
>> as clocksource.
>>
>> +config CLKSRC_RISCV
>> + #bool "Clocksource for the RISC-V platform"
>> + def_bool y if RISCV
>> + depends on RISCV
I don't like the commenting out parts of the entry. If there are no
build-time dependencies, you can just make it 'default y' and still allow
users to disabled the driver if they really want to (e.g. on a machine
specific kernel that has a driver for another clocksource), or you
just leave it 'def_bool RISCV'.
>> +
>> +static int riscv_timer_set_oneshot(struct clock_event_device *evt)
>> +{
>> + /* no-op; only one mode */
>> + return 0;
>> +}
>> +
>> +static int riscv_timer_set_shutdown(struct clock_event_device *evt)
>> +{
>> + /* can't stop the clock! */
>> + return 0;
>> +}
I'd just leave out the empty callbacks, the callers all protect NULL
pointers.
>> +static u64 riscv_rdtime(struct clocksource *cs)
>> +{
>> + return get_cycles();
>> +}
>> +
>> +static struct clocksource riscv_clocksource = {
>> + .name = "riscv_clocksource",
>> + .rating = 300,
>> + .read = riscv_rdtime,
>> +#ifdef CONFIG_64BITS
>> + .mask = CLOCKSOURCE_MASK(64),
>> +#else
>> + .mask = CLOCKSOURCE_MASK(32),
>> +#endif /* CONFIG_64BITS */
>> + .flags = CLOCK_SOURCE_IS_CONTINUOUS,
>> +};
".mask = BITS_PER_LONG" maybe?
>> +void riscv_timer_interrupt(void)
>> +{
>> + int cpu = smp_processor_id();
>> + struct clock_event_device *evdev = &per_cpu(clock_event, cpu);
>> +
>> + evdev->event_handler(evdev);
>> +}
>> +
>> +void __init init_clockevent(void)
>> +{
>> + int cpu = smp_processor_id();
>> + struct clock_event_device *ce = &per_cpu(clock_event, cpu);
>> +
>> + *ce = (struct clock_event_device){
>> + .name = "riscv_timer_clockevent",
>> + .features = CLOCK_EVT_FEAT_ONESHOT,
>> + .rating = 300,
>> + .cpumask = cpumask_of(cpu),
>> + .set_next_event = riscv_timer_set_next_event,
>> + .set_state_oneshot = riscv_timer_set_oneshot,
>> + .set_state_shutdown = riscv_timer_set_shutdown,
>> + };
>> +
>> + /* Enable timer interrupts */
>> + csr_set(sie, SIE_STIE);
>> +
>> + clockevents_config_and_register(ce, riscv_timebase, 100, 0x7fffffff);
>> +}
>> +
>> +static unsigned long __init of_timebase(void)
>> +{
>> + struct device_node *cpu;
>> + const __be32 *prop;
>> +
>> + cpu = of_find_node_by_path("/cpus");
>> + if (cpu) {
>> + prop = of_get_property(cpu, "timebase-frequency", NULL);
>> + if (prop)
>> + return be32_to_cpu(*prop);
of_property_read_u32()
>> + }
>> +
>> + return 10000000;
The default seems rather arbitrary. Any reason for this particular
number? Maybe it's better to fail if the property is missing.
Arnd
[toc] | [prev] | [next] | [standalone]
| From | Marc Zyngier <marc.zyngier@arm.com> |
|---|---|
| Date | 2017-06-07 11:50 +0200 |
| Subject | Re: [PATCH 09/17] clocksource/timer-riscv: New RISC-V Clocksource |
| Message-ID | <tPFLc-4SX-35@gated-at.bofh.it> |
| In reply to | #1659287 |
On 06/06/17 23:59, Palmer Dabbelt wrote:
> The RISC-V ISA defines a single RTC as well as an SBI oneshot timer.
> This timer is present on all RISC-V systems.
>
> Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com>
> ---
> drivers/clocksource/Kconfig | 8 +++
> drivers/clocksource/Makefile | 1 +
> drivers/clocksource/timer-riscv.c | 118 ++++++++++++++++++++++++++++++++++++++
> 3 files changed, 127 insertions(+)
> create mode 100644 drivers/clocksource/timer-riscv.c
>
> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
> index 545d541ae20e..1c2c6e7c7fab 100644
> --- a/drivers/clocksource/Kconfig
> +++ b/drivers/clocksource/Kconfig
> @@ -612,4 +612,12 @@ config CLKSRC_ST_LPC
> Enable this option to use the Low Power controller timer
> as clocksource.
>
> +config CLKSRC_RISCV
> + #bool "Clocksource for the RISC-V platform"
> + def_bool y if RISCV
> + depends on RISCV
> + help
> + This enables a clocksource based on the RISC-V SBI timer, which is
> + built in to all RISC-V systems.
> +
> endmenu
> diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
> index 2b5b56a6f00f..408ed9d314dc 100644
> --- a/drivers/clocksource/Makefile
> +++ b/drivers/clocksource/Makefile
> @@ -73,3 +73,4 @@ obj-$(CONFIG_H8300_TMR16) += h8300_timer16.o
> obj-$(CONFIG_H8300_TPU) += h8300_tpu.o
> obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o
> obj-$(CONFIG_X86_NUMACHIP) += numachip.o
> +obj-$(CONFIG_CLKSRC_RISCV) += timer-riscv.o
> diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c
> new file mode 100644
> index 000000000000..04ef7b9130b3
> --- /dev/null
> +++ b/drivers/clocksource/timer-riscv.c
> @@ -0,0 +1,118 @@
> +/*
> + * Copyright (C) 2012 Regents of the University of California
> + * Copyright (C) 2017 SiFive
> + *
> + * 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.
> + *
> + * 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.
> + */
> +
> +#include <linux/clocksource.h>
> +#include <linux/clockchips.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/delay.h>
> +#include <linux/of.h>
> +
> +#include <asm/irq.h>
> +#include <asm/csr.h>
> +#include <asm/sbi.h>
> +#include <asm/delay.h>
> +
> +unsigned long riscv_timebase;
> +
> +static DEFINE_PER_CPU(struct clock_event_device, clock_event);
> +
> +static int riscv_timer_set_next_event(unsigned long delta,
> + struct clock_event_device *evdev)
> +{
> + sbi_set_timer(get_cycles() + delta);
> + return 0;
> +}
> +
> +static int riscv_timer_set_oneshot(struct clock_event_device *evt)
> +{
> + /* no-op; only one mode */
> + return 0;
> +}
> +
> +static int riscv_timer_set_shutdown(struct clock_event_device *evt)
> +{
> + /* can't stop the clock! */
> + return 0;
> +}
> +
> +static u64 riscv_rdtime(struct clocksource *cs)
> +{
> + return get_cycles();
> +}
> +
> +static struct clocksource riscv_clocksource = {
> + .name = "riscv_clocksource",
> + .rating = 300,
> + .read = riscv_rdtime,
> +#ifdef CONFIG_64BITS
> + .mask = CLOCKSOURCE_MASK(64),
> +#else
> + .mask = CLOCKSOURCE_MASK(32),
> +#endif /* CONFIG_64BITS */
> + .flags = CLOCK_SOURCE_IS_CONTINUOUS,
> +};
> +
> +void riscv_timer_interrupt(void)
> +{
> + int cpu = smp_processor_id();
> + struct clock_event_device *evdev = &per_cpu(clock_event, cpu);
> +
> + evdev->event_handler(evdev);
> +}
> +
> +void __init init_clockevent(void)
> +{
> + int cpu = smp_processor_id();
> + struct clock_event_device *ce = &per_cpu(clock_event, cpu);
> +
> + *ce = (struct clock_event_device){
> + .name = "riscv_timer_clockevent",
> + .features = CLOCK_EVT_FEAT_ONESHOT,
> + .rating = 300,
> + .cpumask = cpumask_of(cpu),
> + .set_next_event = riscv_timer_set_next_event,
> + .set_state_oneshot = riscv_timer_set_oneshot,
> + .set_state_shutdown = riscv_timer_set_shutdown,
> + };
> +
> + /* Enable timer interrupts */
> + csr_set(sie, SIE_STIE);
> +
> + clockevents_config_and_register(ce, riscv_timebase, 100, 0x7fffffff);
> +}
> +
> +static unsigned long __init of_timebase(void)
> +{
> + struct device_node *cpu;
> + const __be32 *prop;
> +
> + cpu = of_find_node_by_path("/cpus");
> + if (cpu) {
> + prop = of_get_property(cpu, "timebase-frequency", NULL);
> + if (prop)
> + return be32_to_cpu(*prop);
Consider using of_property_read_u32() instead.
> + }
> +
> + return 10000000;
Is this an architectural guarantee? Or something that is implementation
specific?
> +}
> +
> +void __init time_init(void)
> +{
> + riscv_timebase = of_timebase();
> + lpj_fine = riscv_timebase / HZ;
> +
> + clocksource_register_hz(&riscv_clocksource, riscv_timebase);
> + init_clockevent();
> +}
>
Thanks,
M.
--
Jazz is not dead. It just smells funny...
[toc] | [prev] | [next] | [standalone]
| From | David Howells <dhowells@redhat.com> |
|---|---|
| Date | 2017-06-07 09:30 +0200 |
| Message-ID | <tPDzH-3vN-1@gated-at.bofh.it> |
| In reply to | #1659280 |
What's the target type for building cross-binutils and cross-gcc for it? David
[toc] | [prev] | [next] | [standalone]
| From | Palmer Dabbelt <palmer@dabbelt.com> |
|---|---|
| Date | 2017-06-08 00:00 +0200 |
| Message-ID | <tPR9E-3Ll-21@gated-at.bofh.it> |
| In reply to | #1659468 |
On Wed, 07 Jun 2017 00:29:44 PDT (-0700), dhowells@redhat.com wrote: > What's the target type for building cross-binutils and cross-gcc for it? riscv64-unknown-linux-gnu We have a super-repo that scripts the build, and includes a handful of patches that fix GCC and binutils bugs that are in our first releases. https://github.com/riscv/riscv-gnu-toolchain
[toc] | [prev] | [next] | [standalone]
| From | Arnd Bergmann <arnd@arndb.de> |
|---|---|
| Date | 2017-06-07 10:20 +0200 |
| Subject | Re: [PATCH 13/17] RISC-V: Add include subdirectory |
| Message-ID | <tPEm5-44h-7@gated-at.bofh.it> |
| In reply to | #1659280 |
On Wed, Jun 7, 2017 at 1:00 AM, Palmer Dabbelt <palmer@dabbelt.com> wrote:
> This patch adds the include files for the RISC-V port. These are mostly
> based on the score port, but there are a lot of arm64-based files as
> well.
>
> Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com>
It might be better to split this up into several parts, as the patch
is longer than
most people are willing to review at once.
The uapi should definitely be a separate patch, as it includes the parts that
cannot be changed any more later. memory management (pgtable, mmu,
uaccess) would be another part to split out, and possibly all the atomics
in one separate patch (along with spinlocks and bitops).
> +
> +/* IO barriers. These only fence on the IO bits because they're only required
> + * to order device access. We're defining mmiowb because our AMO instructions
> + * (which are used to implement locks) don't specify ordering. From Chapter 7
> + * of v2.2 of the user ISA:
> + * "The bits order accesses to one of the two address domains, memory or I/O,
> + * depending on which address domain the atomic instruction is accessing. No
> + * ordering constraint is implied to accesses to the other domain, and a FENCE
> + * instruction should be used to order across both domains."
> + */
> +
> +#define __iormb() __asm__ __volatile__ ("fence i,io" : : : "memory");
> +#define __iowmb() __asm__ __volatile__ ("fence io,o" : : : "memory");
> +
> +#define mmiowb() __asm__ __volatile__ ("fence io,io" : : : "memory");
> +
> +/*
> + * Relaxed I/O memory access primitives. These follow the Device memory
> + * ordering rules but do not guarantee any ordering relative to Normal memory
> + * accesses.
> + */
> +#define readb_relaxed(c) ({ u8 __r = __raw_readb(c); __r; })
> +#define readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16)__raw_readw(c)); __r; })
> +#define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32)__raw_readl(c)); __r; })
> +#define readq_relaxed(c) ({ u64 __r = le64_to_cpu((__force __le64)__raw_readq(c)); __r; })
> +
> +#define writeb_relaxed(v,c) ((void)__raw_writeb((v),(c)))
> +#define writew_relaxed(v,c) ((void)__raw_writew((__force u16)cpu_to_le16(v),(c)))
> +#define writel_relaxed(v,c) ((void)__raw_writel((__force u32)cpu_to_le32(v),(c)))
> +#define writeq_relaxed(v,c) ((void)__raw_writeq((__force u64)cpu_to_le64(v),(c)))
> +
> +/*
> + * I/O memory access primitives. Reads are ordered relative to any
> + * following Normal memory access. Writes are ordered relative to any prior
> + * Normal memory access.
> + */
> +#define readb(c) ({ u8 __v = readb_relaxed(c); __iormb(); __v; })
> +#define readw(c) ({ u16 __v = readw_relaxed(c); __iormb(); __v; })
> +#define readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; })
> +#define readq(c) ({ u64 __v = readq_relaxed(c); __iormb(); __v; })
> +
> +#define writeb(v,c) ({ __iowmb(); writeb_relaxed((v),(c)); })
> +#define writew(v,c) ({ __iowmb(); writew_relaxed((v),(c)); })
> +#define writel(v,c) ({ __iowmb(); writel_relaxed((v),(c)); })
> +#define writeq(v,c) ({ __iowmb(); writeq_relaxed((v),(c)); })
> +
> +#include <asm-generic/io.h>
These do not yet contain all the changes we discussed: the relaxed operations
don't seem to be ordered against one another and the regular accessors
are not ordered against DMA.
Arnd
[toc] | [prev] | [next] | [standalone]
| From | Will Deacon <will.deacon@arm.com> |
|---|---|
| Date | 2017-06-07 11:30 +0200 |
| Message-ID | <tPFrQ-4M0-31@gated-at.bofh.it> |
| In reply to | #1659280 |
Hi Palmer, On Tue, Jun 06, 2017 at 03:59:50PM -0700, Palmer Dabbelt wrote: > Thanks to everyone who has participated in the review process so far. We've > made a lot of changes since the v1 and while this isn't ready to go yet, I > finally managed to get through everything in my inbox so I thought it would be > a good time to submit a v2 so everyone is on the same page. [...] > [PATCH 13/17] RISC-V: Add include subdirectory This guy is too big, and got silently dropped by the mailing list. Any chance you could split it up please, so that it can be reviewed? Thanks, Will
[toc] | [prev] | [next] | [standalone]
| From | Palmer Dabbelt <palmer@dabbelt.com> |
|---|---|
| Date | 2017-06-08 00:00 +0200 |
| Message-ID | <tPR9E-3Ll-11@gated-at.bofh.it> |
| In reply to | #1659590 |
On Wed, 07 Jun 2017 02:23:42 PDT (-0700), will.deacon@arm.com wrote: > Hi Palmer, > > On Tue, Jun 06, 2017 at 03:59:50PM -0700, Palmer Dabbelt wrote: >> Thanks to everyone who has participated in the review process so far. We've >> made a lot of changes since the v1 and while this isn't ready to go yet, I >> finally managed to get through everything in my inbox so I thought it would be >> a good time to submit a v2 so everyone is on the same page. > > [...] > >> [PATCH 13/17] RISC-V: Add include subdirectory > > This guy is too big, and got silently dropped by the mailing list. Any > chance you could split it up please, so that it can be reviewed? Sorry about that. It's online https://github.com/riscv/riscv-linux/commit/daaea1609cb5e8c93745c1ce112a06e90f5b663c I'll be sure to split it up next time. I can submit a v3 if you want?
[toc] | [prev] | [next] | [standalone]
| From | Will Deacon <will.deacon@arm.com> |
|---|---|
| Date | 2017-06-08 12:30 +0200 |
| Message-ID | <tQ2Rr-33b-1@gated-at.bofh.it> |
| In reply to | #1660271 |
On Wed, Jun 07, 2017 at 02:54:16PM -0700, Palmer Dabbelt wrote: > On Wed, 07 Jun 2017 02:23:42 PDT (-0700), will.deacon@arm.com wrote: > > Hi Palmer, > > > > On Tue, Jun 06, 2017 at 03:59:50PM -0700, Palmer Dabbelt wrote: > >> Thanks to everyone who has participated in the review process so far. We've > >> made a lot of changes since the v1 and while this isn't ready to go yet, I > >> finally managed to get through everything in my inbox so I thought it would be > >> a good time to submit a v2 so everyone is on the same page. > > > > [...] > > > >> [PATCH 13/17] RISC-V: Add include subdirectory > > > > This guy is too big, and got silently dropped by the mailing list. Any > > chance you could split it up please, so that it can be reviewed? > > Sorry about that. It's online > > https://github.com/riscv/riscv-linux/commit/daaea1609cb5e8c93745c1ce112a06e90f5b663c > > I'll be sure to split it up next time. I can submit a v3 if you want? It looks like you'll be submitting a v3 anyway, so if you could split it up for that then it would be much appreciated. Thanks, Will
[toc] | [prev] | [next] | [standalone]
| From | Palmer Dabbelt <palmer@dabbelt.com> |
|---|---|
| Date | 2017-06-08 20:20 +0200 |
| Message-ID | <tQach-7H1-9@gated-at.bofh.it> |
| In reply to | #1661035 |
On Thu, 08 Jun 2017 03:26:32 PDT (-0700), will.deacon@arm.com wrote: > On Wed, Jun 07, 2017 at 02:54:16PM -0700, Palmer Dabbelt wrote: >> On Wed, 07 Jun 2017 02:23:42 PDT (-0700), will.deacon@arm.com wrote: >> > Hi Palmer, >> > >> > On Tue, Jun 06, 2017 at 03:59:50PM -0700, Palmer Dabbelt wrote: >> >> Thanks to everyone who has participated in the review process so far. We've >> >> made a lot of changes since the v1 and while this isn't ready to go yet, I >> >> finally managed to get through everything in my inbox so I thought it would be >> >> a good time to submit a v2 so everyone is on the same page. >> > >> > [...] >> > >> >> [PATCH 13/17] RISC-V: Add include subdirectory >> > >> > This guy is too big, and got silently dropped by the mailing list. Any >> > chance you could split it up please, so that it can be reviewed? >> >> Sorry about that. It's online >> >> https://github.com/riscv/riscv-linux/commit/daaea1609cb5e8c93745c1ce112a06e90f5b663c >> >> I'll be sure to split it up next time. I can submit a v3 if you want? > > It looks like you'll be submitting a v3 anyway, so if you could split it up > for that then it would be much appreciated. Sounds good. I won't spin a v3 just for this problem, as there's a lot of other comments I need to go through.
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2017-06-07 14:00 +0200 |
| Subject | Re: [PATCH 13/17] RISC-V: Add include subdirectory |
| Message-ID | <tPHMZ-68d-9@gated-at.bofh.it> |
| In reply to | #1659280 |
On Tue, Jun 06, 2017 at 04:00:03PM -0700, Palmer Dabbelt wrote: > +/* Assume that atomic operations are already serializing */ > +#define smp_mb__before_atomic_dec() barrier() > +#define smp_mb__after_atomic_dec() barrier() > +#define smp_mb__before_atomic_inc() barrier() > +#define smp_mb__after_atomic_inc() barrier() > +#define smp_mb__before_clear_bit() smp_mb() > +#define smp_mb__after_clear_bit() smp_mb() These no longer exist.. Also how can they be different? bitops would use the same atomic primitives as regular atomic ops would and would thus have the very same implicit ordering.
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2017-06-07 14:30 +0200 |
| Subject | Re: [PATCH 13/17] RISC-V: Add include subdirectory |
| Message-ID | <tPIg1-6zL-1@gated-at.bofh.it> |
| In reply to | #1659708 |
On Wed, Jun 07, 2017 at 01:54:23PM +0200, Peter Zijlstra wrote: > On Tue, Jun 06, 2017 at 04:00:03PM -0700, Palmer Dabbelt wrote: > > +/* Assume that atomic operations are already serializing */ > > +#define smp_mb__before_atomic_dec() barrier() > > +#define smp_mb__after_atomic_dec() barrier() > > +#define smp_mb__before_atomic_inc() barrier() > > +#define smp_mb__after_atomic_inc() barrier() > > > +#define smp_mb__before_clear_bit() smp_mb() > > +#define smp_mb__after_clear_bit() smp_mb() > > These no longer exist.. Also how can they be different? bitops would use > the same atomic primitives as regular atomic ops would and would thus > have the very same implicit ordering. Your manual states that each atomic instruction (be it AMO or LR/SC) have two ordering bits: AQ and RL. If neither are set the instruction is unordered, if either one is set, its either an ACQUIRE or a RELEASE and if both are set its SC. So you can in fact make the above happen, however your atomic implementation does not appear to use ".aq.rl" mnemonics so would be entirely unordered, just like your bitops. Therefore the above is just plain wrong and broken.
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2017-06-07 14:10 +0200 |
| Subject | Re: [PATCH 13/17] RISC-V: Add include subdirectory |
| Message-ID | <tPHWG-6rv-19@gated-at.bofh.it> |
| In reply to | #1659280 |
On Tue, Jun 06, 2017 at 04:00:03PM -0700, Palmer Dabbelt wrote:
> + * atomic_add - add integer to atomic variable
> + * @i: integer value to add
> + * @v: pointer of type atomic_t
> + *
> + * Atomically adds @i to @v.
> + */
> +static inline void atomic_add(int i, atomic_t *v)
> +{
> + __asm__ __volatile__ (
> + "amoadd.w zero, %1, %0"
> + : "+A" (v->counter)
> + : "r" (i));
> +}
> +
> +#define atomic_fetch_add atomic_fetch_add
> +static inline int atomic_fetch_add(unsigned int mask, atomic_t *v)
> +{
> + int out;
> +
> + __asm__ __volatile__ (
> + "amoadd.w %2, %1, %0"
> + : "+A" (v->counter), "=r" (out)
> + : "r" (mask));
> + return out;
> +}
> +
> +/**
> + * atomic_sub - subtract integer from atomic variable
> + * @i: integer value to subtract
> + * @v: pointer of type atomic_t
> + *
> + * Atomically subtracts @i from @v.
> + */
> +static inline void atomic_sub(int i, atomic_t *v)
> +{
> + atomic_add(-i, v);
> +}
> +
> +#define atomic_fetch_sub atomic_fetch_sub
> +static inline int atomic_fetch_sub(unsigned int mask, atomic_t *v)
> +{
> + int out;
> +
> + __asm__ __volatile__ (
> + "amosub.w %2, %1, %0"
> + : "+A" (v->counter), "=r" (out)
> + : "r" (mask));
> + return out;
> +}
> +
> +/**
> + * atomic_add_return - add integer to atomic variable
> + * @i: integer value to add
> + * @v: pointer of type atomic_t
> + *
> + * Atomically adds @i to @v and returns the result
> + */
> +static inline int atomic_add_return(int i, atomic_t *v)
> +{
> + register int c;
> +
> + __asm__ __volatile__ (
> + "amoadd.w %0, %2, %1"
> + : "=r" (c), "+A" (v->counter)
> + : "r" (i));
> + return (c + i);
> +}
> +
> +/**
> + * atomic_sub_return - subtract integer from atomic variable
> + * @i: integer value to subtract
> + * @v: pointer of type atomic_t
> + *
> + * Atomically subtracts @i from @v and returns the result
> + */
> +static inline int atomic_sub_return(int i, atomic_t *v)
> +{
> + return atomic_add_return(-i, v);
> +}
> +
> +/**
> + * atomic_and - Atomically clear bits in atomic variable
> + * @mask: Mask of the bits to be retained
> + * @v: pointer of type atomic_t
> + *
> + * Atomically retains the bits set in @mask from @v
> + */
> +static inline void atomic_and(unsigned int mask, atomic_t *v)
> +{
> + __asm__ __volatile__ (
> + "amoand.w zero, %1, %0"
> + : "+A" (v->counter)
> + : "r" (mask));
> +}
> +
> +#define atomic_fetch_and atomic_fetch_and
> +static inline int atomic_fetch_and(unsigned int mask, atomic_t *v)
> +{
> + int out;
> +
> + __asm__ __volatile__ (
> + "amoand.w %2, %1, %0"
> + : "+A" (v->counter), "=r" (out)
> + : "r" (mask));
> + return out;
> +}
> +
> +/**
> + * atomic_or - Atomically set bits in atomic variable
> + * @mask: Mask of the bits to be set
> + * @v: pointer of type atomic_t
> + *
> + * Atomically sets the bits set in @mask in @v
> + */
> +static inline void atomic_or(unsigned int mask, atomic_t *v)
> +{
> + __asm__ __volatile__ (
> + "amoor.w zero, %1, %0"
> + : "+A" (v->counter)
> + : "r" (mask));
> +}
> +
> +#define atomic_fetch_or atomic_fetch_or
> +static inline int atomic_fetch_or(unsigned int mask, atomic_t *v)
> +{
> + int out;
> +
> + __asm__ __volatile__ (
> + "amoor.w %2, %1, %0"
> + : "+A" (v->counter), "=r" (out)
> + : "r" (mask));
> + return out;
> +}
> +
> +/**
> + * atomic_xor - Atomically flips bits in atomic variable
> + * @mask: Mask of the bits to be flipped
> + * @v: pointer of type atomic_t
> + *
> + * Atomically flips the bits set in @mask in @v
> + */
> +static inline void atomic_xor(unsigned int mask, atomic_t *v)
> +{
> + __asm__ __volatile__ (
> + "amoxor.w zero, %1, %0"
> + : "+A" (v->counter)
> + : "r" (mask));
> +}
> +
> +#define atomic_fetch_xor atomic_fetch_xor
> +static inline int atomic_fetch_xor(unsigned int mask, atomic_t *v)
> +{
> + int out;
> +
> + __asm__ __volatile__ (
> + "amoxor.w %2, %1, %0"
> + : "+A" (v->counter), "=r" (out)
> + : "r" (mask));
> + return out;
> +}
What pretty much all the other architectures do is something like:
#define ATOMIC_OP(op, asm_op, c_op) \
static __always_inline void atomic_##op(int i, atomic_t *v) \
{ \
__asm__ __volatile__ ( \
"amo" #asm_op ".w zero, %1, %0" \
: "+A" (v->counter) \
: "r" (i)); \
}
#define ATOMIC_FETCH_OP(op, asm_op, c_op) \
static __always_inline int atomic_fetch_##op(int i, atomic_t *v)\
{ \
register int ret; \
__asm__ __volatile__ ( \
"amo" #asm_op ".w %2, %1, %0" \
: "+A" (v->counter), "=r" (ret) \
: "r" (mask)); \
return ret; \
}
#define ATOMIC_OP_RETURN(op, asm_op, c_op) \
static __always_inline int atomic_##op##_return(int i, atomic_t *v) \
{ \
return atomic_fetch_##op(i, v) c_op i; \
}
#define ATOMIC_OPS(op, asm_op, c_op) \
ATOMIC_OP(op, asm_op, c_op) \
ATOMIC_OP_RETURN(op, asm_op, c_op) \
ATOMIC_FETCH_OP(op, asm_op, c_op)
ATOMIC_OPS(add, add, +)
ATOMIC_OPS(sub, sub, -)
#undef ATOMIC_OPS
#define ATOMIC_OPS(op, asm_op, c_op) \
ATOMIC_OP(op, asm_op, c_op) \
ATOMIC_FETCH_OP(op, asm_op, c_op)
ATOMIC_OPS(and, and, &)
ATOMIC_OPS(or, or, |)
ATOMIC_OPS(xor, xor, ^)
#undef ATOMIC_OPS
Which is much simpler no?
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2017-06-07 14:30 +0200 |
| Subject | Re: [PATCH 13/17] RISC-V: Add include subdirectory |
| Message-ID | <tPIg1-6zL-9@gated-at.bofh.it> |
| In reply to | #1659734 |
On Wed, Jun 07, 2017 at 02:06:13PM +0200, Peter Zijlstra wrote:
> On Tue, Jun 06, 2017 at 04:00:03PM -0700, Palmer Dabbelt wrote:
> > +static inline int atomic_fetch_sub(unsigned int mask, atomic_t *v)
> > +{
> > + int out;
> > +
> > + __asm__ __volatile__ (
> > + "amosub.w %2, %1, %0"
> > + : "+A" (v->counter), "=r" (out)
> > + : "r" (mask));
> > + return out;
> > +}
Your instruction manual does not list AMOSUB as a valid instruction. So
either it is wrong or this code never compiled. Please clarify.
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2017-06-07 14:40 +0200 |
| Subject | Re: [PATCH 13/17] RISC-V: Add include subdirectory |
| Message-ID | <tPIpI-6D4-13@gated-at.bofh.it> |
| In reply to | #1659734 |
On Wed, Jun 07, 2017 at 02:06:13PM +0200, Peter Zijlstra wrote:
> On Tue, Jun 06, 2017 at 04:00:03PM -0700, Palmer Dabbelt wrote:
> What pretty much all the other architectures do is something like:
>
> #define ATOMIC_OP(op, asm_op, c_op) \
> static __always_inline void atomic_##op(int i, atomic_t *v) \
> { \
> __asm__ __volatile__ ( \
> "amo" #asm_op ".w zero, %1, %0" \
> : "+A" (v->counter) \
> : "r" (i)); \
> }
>
> #define ATOMIC_FETCH_OP(op, asm_op, c_op) \
> static __always_inline int atomic_fetch_##op(int i, atomic_t *v)\
> { \
> register int ret; \
> __asm__ __volatile__ ( \
> "amo" #asm_op ".w %2, %1, %0" \
> : "+A" (v->counter), "=r" (ret) \
> : "r" (mask)); \
> return ret; \
> }
>
> #define ATOMIC_OP_RETURN(op, asm_op, c_op) \
> static __always_inline int atomic_##op##_return(int i, atomic_t *v) \
> { \
> return atomic_fetch_##op(i, v) c_op i; \
> }
>
> #define ATOMIC_OPS(op, asm_op, c_op) \
> ATOMIC_OP(op, asm_op, c_op) \
> ATOMIC_OP_RETURN(op, asm_op, c_op) \
> ATOMIC_FETCH_OP(op, asm_op, c_op)
>
> ATOMIC_OPS(add, add, +)
> ATOMIC_OPS(sub, sub, -)
>
> #undef ATOMIC_OPS
>
> #define ATOMIC_OPS(op, asm_op, c_op) \
> ATOMIC_OP(op, asm_op, c_op) \
> ATOMIC_FETCH_OP(op, asm_op, c_op)
>
> ATOMIC_OPS(and, and, &)
> ATOMIC_OPS(or, or, |)
> ATOMIC_OPS(xor, xor, ^)
>
> #undef ATOMIC_OPS
>
> Which is much simpler no?
In fact, after having read your manual you'd want something like:
#define ATOMIC_OP(op, asm_op, c_op) \
static __always_inline void atomic_##op(int i, atomic_t *v) \
{ \
__asm__ __volatile__ ( \
"amo" #asm_op ".w zero, %1, %0" \
: "+A" (v->counter) \
: "r" (i)); \
}
#define ATOMIC_FETCH_OP(op, asm_op, c_op, asm_or, order) \
static __always_inline int atomic_fetch_##op##order(int i, atomic_t *v)\
{ \
register int ret; \
__asm__ __volatile__ ( \
"amo" #asm_op ".w" #asm_or " %2, %1, %0" \
: "+A" (v->counter), "=r" (ret) \
: "r" (mask)); \
return ret; \
}
#define ATOMIC_OP_RETURN(op, asm_op, c_op, asm_or, order) \
static __always_inline int atomic_##op##_return##order(int i, atomic_t *v) \
{ \
return atomic_fetch_##op##order(i, v) c_op i; \
}
#define ATOMIC_OPS(op, asm_op, c_op) \
ATOMIC_OP(op, asm_op, c_op, , _relaxed) \
ATOMIC_OP_RETURN(op, asm_op, c_op, , _relaxed) \
ATOMIC_FETCH_OP(op, asm_op, c_op, , _relaxed)
ATOMIC_OPS(add, add, +)
ATOMIC_OPS(sub, sub, -)
#undef ATOMIC_OPS
#define ATOMIC_OPS(op, asm_op, c_op, asm_or, order) \
ATOMIC_OP_RETURN(op, asm_op, c_op, , _relaxed) \
ATOMIC_FETCH_OP(op, asm_op, c_op, , _relaxed)
ATOMIC_OPS(add, add, +, ".aq", _acquire)
ATOMIC_OPS(add, add, +, ".rl", _release)
ATOMIC_OPS(add, add, +, ".aq.rl", )
ATOMIC_OPS(sub, sub, -, ".aq", _acquire)
ATOMIC_OPS(sub, sub, -, ".rl", _release)
ATOMIC_OPS(sub, sub, -, ".aq.rl", )
#undef ATOMIC_OPS
#define ATOMIC_OPS(op, asm_op, c_op) \
ATOMIC_OP(op, asm_op, c_op) \
ATOMIC_FETCH_OP(op, asm_op, c_op, , _relaxed)
ATOMIC_OPS(and, and, &)
ATOMIC_OPS(or, or, |)
ATOMIC_OPS(xor, xor, ^)
#undef ATOMIC_OPS
ATOMIC_FETCH_OP(and, and, &, ".aq", _acquire)
ATOMIC_FETCH_OP(and, and, &, ".rl", _release)
ATOMIC_FETCH_OP(and, and, &, ".aq.rl", )
ATOMIC_FETCH_OP(or, or, |, ".aq", _acquire)
ATOMIC_FETCH_OP(or, or, |, ".rl", _release)
ATOMIC_FETCH_OP(or, or, |, ".aq.rl", )
ATOMIC_FETCH_OP(xor, xor, ^, ".aq", _acquire)
ATOMIC_FETCH_OP(xor, xor, ^, ".rl", _release)
ATOMIC_FETCH_OP(xor, xor, ^, ".aq.rl", )
#define smp_mb__before_atomic() smp_mb()
#define smp_mb__after_atomic() smp_mb()
Which (pending the sub confusion) will generate the entire set of:
atomic_add, atomic_add_return{_relaxed,_acquire,_release,} atomic_fetch_add{_relaxed,_acquire,_release,}
atomic_sub, atomic_sub_return{_relaxed,_acquire,_release,} atomic_fetch_sub{_relaxed,_acquire,_release,}
atomic_and, atomic_fetch_and{_relaxed,_acquire,_release,}
atomic_or, atomic_fetch_or{_relaxed,_acquire,_release,}
atomic_xor, atomic_fetch_xor{_relaxed,_acquire,_release,}
[toc] | [prev] | [next] | [standalone]
Page 2 of 3 — ← Prev page 1 [2] 3 Next page →
Back to top | Article view | linux.kernel
csiph-web