Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1731250 > unrolled thread
| Started by | Palmer Dabbelt <palmer@dabbelt.com> |
|---|---|
| First post | 2017-09-13 00:00 +0200 |
| Last post | 2017-09-16 23:40 +0200 |
| Articles | 18 — 6 participants |
Back to article view | Back to linux.kernel
RISC-V Linux Port v8 Palmer Dabbelt <palmer@dabbelt.com> - 2017-09-13 00:00 +0200
[PATCH v8 07/18] irqchip: RISC-V Local Interrupt Controller Driver Palmer Dabbelt <palmer@dabbelt.com> - 2017-09-13 00:00 +0200
[PATCH v8 01/18] MAINTAINERS: Add RISC-V Palmer Dabbelt <palmer@dabbelt.com> - 2017-09-13 00:00 +0200
Re: [PATCH v8 01/18] MAINTAINERS: Add RISC-V Joe Perches <joe@perches.com> - 2017-09-13 16:40 +0200
Re: [PATCH v8 01/18] MAINTAINERS: Add RISC-V Palmer Dabbelt <palmer@dabbelt.com> - 2017-09-13 18:00 +0200
[PATCH v8 02/18] lib: Add shared copies of some GCC library routines Palmer Dabbelt <palmer@dabbelt.com> - 2017-09-13 00:10 +0200
[PATCH v8 04/18] dt-bindings: interrupt-controller: RISC-V PLIC documentation Palmer Dabbelt <palmer@dabbelt.com> - 2017-09-13 00:10 +0200
Re: [PATCH v8 04/18] dt-bindings: interrupt-controller: RISC-V PLIC documentation Rob Herring <robh@kernel.org> - 2017-09-15 16:40 +0200
Re: [PATCH v8 04/18] dt-bindings: interrupt-controller: RISC-V PLIC documentation Palmer Dabbelt <palmer@dabbelt.com> - 2017-09-15 18:30 +0200
[PATCH v8 03/18] dt-bindings: interrupt-controller: RISC-V local interrupt controller docs Palmer Dabbelt <palmer@dabbelt.com> - 2017-09-13 00:10 +0200
[PATCH v8 08/18] irqchip: New RISC-V PLIC Driver Palmer Dabbelt <palmer@dabbelt.com> - 2017-09-13 00:10 +0200
Re: [patches] [PATCH v8 08/18] irqchip: New RISC-V PLIC Driver Jonathan Neuschäfer <j.neuschaefer@gmx.net> - 2017-09-14 13:10 +0200
[PATCH v8 09/18] tty: New RISC-V SBI console driver Palmer Dabbelt <palmer@dabbelt.com> - 2017-09-13 00:10 +0200
[PATCH v8 13/18] RISC-V: ELF and module implementation Palmer Dabbelt <palmer@dabbelt.com> - 2017-09-13 00:10 +0200
Re: [PATCH v8 10/18] RISC-V: Init and Halt Code Daniel Lezcano <daniel.lezcano@linaro.org> - 2017-09-13 20:20 +0200
Re: [PATCH v8 10/18] RISC-V: Init and Halt Code Dmitriy Cherkasov <dmitriy@oss-tech.org> - 2017-09-16 08:30 +0200
Re: [PATCH v8 10/18] RISC-V: Init and Halt Code Daniel Lezcano <daniel.lezcano@linaro.org> - 2017-09-16 15:30 +0200
Re: [PATCH v8 10/18] RISC-V: Init and Halt Code Dmitriy Cherkasov <dmitriy@oss-tech.org> - 2017-09-16 23:40 +0200
| From | Palmer Dabbelt <palmer@dabbelt.com> |
|---|---|
| Date | 2017-09-13 00:00 +0200 |
| Subject | RISC-V Linux Port v8 |
| Message-ID | <up1nP-6OS-3@gated-at.bofh.it> |
I know it may not be the ideal time to submit a patch set right now, as it's
the middle of the merge window, but things have calmed down quite a bit in the
last month so I thought it would be good to get everyone on the same page.
There's been a handful of changes since the last patch set, but most of them
are fairly minor:
* We changed PAGE_OFFSET to allowing mapping more physical memory on 64-bit
systems. This is user configurable, as it triggers a different code model
that generates slightly less efficient code.
* The device tree binding documentation is back, I'd managed to lose it at some
point.
* We now pass the atomic64 test suite.
* The SBI timer driver has been refactored.
To the best of by knowledge, all the feedback we've gotten so far has been
taken into account for this patch set. If I've missed anyone's feedback I'm
sorry, just point it out and I'll try to dig it up.
Just to be clear on timelines: we're not pushing to get into 4.14, but we are
hoping we can make it in for 4.15. If I understand the process correctly, we
should aim to get into linux-next some time in the next month so we can be
merged during the next merge window.
As usual, we've make this patch set availiable Online in addition to via this
submission. There are a handful of additional patches there, but those should
all be going upstream either in other trees (though frequently in a heavily
modified form, as there was already a fix floating around).
https://github.com/riscv/riscv-linux/tree/riscv-for-submission-v8
Here's a summary, in case something gets lost
[PATCH v8 01/18] MAINTAINERS: Add RISC-V
[PATCH v8 02/18] lib: Add shared copies of some GCC library routines
[PATCH v8 03/18] dt-bindings: interrupt-controller: RISC-V local
[PATCH v8 04/18] dt-bindings: interrupt-controller: RISC-V PLIC
[PATCH v8 05/18] dt-bindings: RISC-V CPU Bindings
[PATCH v8 06/18] clocksource: New RISC-V SBI timer driver
[PATCH v8 07/18] irqchip: RISC-V Local Interrupt Controller Driver
[PATCH v8 08/18] irqchip: New RISC-V PLIC Driver
[PATCH v8 09/18] tty: New RISC-V SBI console driver
[PATCH v8 10/18] RISC-V: Init and Halt Code
[PATCH v8 11/18] RISC-V: Atomic and Locking Code
[PATCH v8 12/18] RISC-V: Generic library routines and assembly
[PATCH v8 13/18] RISC-V: ELF and module implementation
[PATCH v8 14/18] RISC-V: Task implementation
[PATCH v8 15/18] RISC-V: Device, timer, IRQs, and the SBI
[PATCH v8 16/18] RISC-V: Paging and MMU
[PATCH v8 17/18] RISC-V: User-facing API
[PATCH v8 18/18] RISC-V: Build Infastructure
Here's the change highlights from the whole patch set
(v7) It's been a while since my last patch set, but the changes han been fairly
minimal:
* The PCI cleanup patches have been dropped, we'll do them as a separate patch
set later.
* We've the Kconfig entries from CONFIG_ISA_* to CONFIG_RISCV_ISA_*, to make
grep easier.
* There have been a handful of memory model related tweaks in I/O land,
particularly relating the PCI and the upcoming platform specification.
There are significant comments in the relevant files. This is still a WIP,
but I think we're close to getting as good as we're going to get until we
end up with some more specifications.
(v6) As it's been only a day since the v5 patch set, the changes are pretty
minimal:
* The patch set is now based on linux-next/master, which I believe is a better
base now that we're getting closer to upstream.
* EARLY_PRINTK is no longer an option. Since the SBI console is reasonable,
there's no penalty to enabling it (and thus no benefit to disabling it).
* The mmap syscalls were refactored a bit.
(v5) Things have really started to calm down, so this is fairly similar to the
v4 patch set. The most interesting changes include:
* We've moved back to a single patch set.
* SMP support has been fixed, I was accidentally running on a non-SMP
configuration. There were various mistakes all over the tree as a result of
this.
* The cmpxchg syscalls have been removed, as they were deemed a bad idea. As
a result, RISC-V Linux systems mandate the A extension. The corresponding
Kconfig entry to enable builds on non-A systems has been removed.
* A few more atomic fixes: mostly fence changes, but those resulted in a
handful of additional macros that were no longer necessary.
* riscv_early_sie has been removed.
(v4) There have only been a few changes since the v3 patch set:
* The cmpxchg64 syscall is no longer enabled on 32-bit systems. It's not
possible to provide this on SMP systems, and it's not necessary as glibc
knows not to call it.
* We provide a ELF_HWCAP so users can determine the ISA of the machine the
kernel is running on.
* The multi-line comments are in a better form.
* There were a handful of headers that could be replaced with the asm-generic
versions, and a few unnecessary definitions.
* We no longer use printk, but instead use pr_*.
* A few Kconfig and defconfig entries have been cleaned up.
(v3) A highlight of the changes since the v2 patch set includes:
* We've split out all our drivers into separate patch sets, which I've already
sent out to the relevant maintainers. I haven't included those patches in
this patch set, but some of them are necessary to build our port. A git
tree that contains all our patch sets merged together lives at
<https://github.com/riscv/riscv-linux/tree/riscv-for-submission-v3>.
* The patch set is now split up differently: rather than being split per
directory it is split per topic. Hopefully this will make it easier to
review the port on the mailing list. The split is a bit rough, so you
probably still want to look at the patch set as a whole.
* atomic.h has been completely rewritten and is hopefully now correct. I've
attempted to sanitize the various other memory model related code as well,
and I think it should all be sane now aside from a handful of FIXMEs
commented in the code.
* We've changed the cmpexchg syscall to always exist and to not be
multiplexed. There is also a VDSO entry for compare and exchange, which
allows kernels with the A extension to execute user code without the A
extension reasonably fast.
* Our user-visible register state now contains enough space for the Q
extension for 128-bit floating point, as well as a few words to allow
extensibility to future ISA extensions like the eventual V extension for
vectors.
* A handful of driver cleanups, but these have been split into separate patch
sets now so I won't duplicate them here.
(v2) A highlight of the changes since the v1 patch set includes:
* We've split out our drivers into the right places, which means now there's
a lot more patches. I'll be submitting these patches to various subsystem
maintainers and including them in any future RISC-V patch sets until
they've been merged.
* The SBI console driver has been completely rewritten to use the HVC helpers
and is now significantly smaller.
* We've begun to use weaker barriers as opposed to just the big "fence".
There's still some work to do here, specifically:
- We need fences in the relaxed MMIO functions.
- The non-relaxed MMIO functions are missing R/W bits on their fences.
- Many AMOs need the aq and rl bits set.
* We now have thread_info in task_struct. As a result, sscratch now contains
TP instead of SP. This was necessary because thread_info is no longer on
the stack.
* A few shared routines have been added that we use instead of creating
another arch copy.
[toc] | [next] | [standalone]
| From | Palmer Dabbelt <palmer@dabbelt.com> |
|---|---|
| Date | 2017-09-13 00:00 +0200 |
| Subject | [PATCH v8 07/18] irqchip: RISC-V Local Interrupt Controller Driver |
| Message-ID | <up1nR-6OS-27@gated-at.bofh.it> |
| In reply to | #1731250 |
This patch adds a driver that manages the local interrupts on each
RISC-V hart, as specifiec by the RISC-V supervisor level ISA manual.
The local interrupt controller manages software interrupts, timer
interrupts, and hardware interrupts (which are routed via the
platform level interrupt controller). Per-hart local interrupt
controllers are found on all RISC-V systems.
Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com>
---
drivers/irqchip/Kconfig | 14 +++
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-riscv-intc.c | 210 +++++++++++++++++++++++++++++++++++++++
3 files changed, 225 insertions(+)
create mode 100644 drivers/irqchip/irq-riscv-intc.c
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index f1fd5f44d1d4..7923d3fa8fae 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -306,3 +306,17 @@ config QCOM_IRQ_COMBINER
help
Say yes here to add support for the IRQ combiner devices embedded
in Qualcomm Technologies chips.
+
+config RISCV_INTC
+ def_bool y if RISCV
+ #bool "RISC-V Interrupt Controller"
+ depends on RISCV
+ default y
+ help
+ This enables support for the local interrupt controller found in
+ standard RISC-V systems. The local interrupt controller handles
+ timer interrupts, software interrupts, and hardware interrupts.
+ Without a local interrupt controller the system will be unable to
+ handle any interrupts, including those passed via the PLIC.
+
+ If you don't know what to do here, say Y.
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index e88d856cc09c..b1aa9114afc4 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -78,3 +78,4 @@ obj-$(CONFIG_EZNPS_GIC) += irq-eznps.o
obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o irq-aspeed-i2c-ic.o
obj-$(CONFIG_STM32_EXTI) += irq-stm32-exti.o
obj-$(CONFIG_QCOM_IRQ_COMBINER) += qcom-irq-combiner.o
+obj-$(CONFIG_RISCV_INTC) += irq-riscv-intc.o
diff --git a/drivers/irqchip/irq-riscv-intc.c b/drivers/irqchip/irq-riscv-intc.c
new file mode 100644
index 000000000000..d019bd3a4ae3
--- /dev/null
+++ b/drivers/irqchip/irq-riscv-intc.c
@@ -0,0 +1,210 @@
+/*
+ * 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/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqdomain.h>
+#include <linux/interrupt.h>
+#include <linux/ftrace.h>
+#include <linux/of.h>
+#include <linux/seq_file.h>
+
+#include <asm/ptrace.h>
+#include <asm/sbi.h>
+#include <asm/smp.h>
+
+#define PTR_BITS (8 * sizeof(uintptr_t))
+
+struct riscv_irq_data {
+ struct irq_chip chip;
+ struct irq_domain *domain;
+ int hart;
+ char name[20];
+};
+DEFINE_PER_CPU(struct riscv_irq_data, riscv_irq_data);
+
+static void riscv_software_interrupt(void)
+{
+#ifdef CONFIG_SMP
+ irqreturn_t ret;
+
+ ret = handle_ipi();
+
+ WARN_ON(ret == IRQ_NONE);
+#else
+ /*
+ * We currently only use software interrupts to pass inter-processor
+ * interrupts, so if a non-SMP system gets a software interrupt then we
+ * don't know what to do.
+ */
+ pr_warning("Software Interrupt without CONFIG_SMP\n");
+#endif
+}
+
+asmlinkage void __irq_entry do_IRQ(unsigned int cause, struct pt_regs *regs)
+{
+ struct pt_regs *old_regs = set_irq_regs(regs);
+ struct irq_domain *domain;
+
+ irq_enter();
+
+ /*
+ * There are three classes of interrupt: timer, software, and
+ * external devices. We dispatch between them here. External
+ * device interrupts use the generic IRQ mechanisms.
+ */
+ switch (cause) {
+ case INTERRUPT_CAUSE_TIMER:
+ riscv_timer_interrupt();
+ break;
+ case INTERRUPT_CAUSE_SOFTWARE:
+ riscv_software_interrupt();
+ break;
+ default:
+ domain = per_cpu(riscv_irq_data, smp_processor_id()).domain;
+ generic_handle_irq(irq_find_mapping(domain, cause));
+ break;
+ }
+
+ irq_exit();
+ set_irq_regs(old_regs);
+}
+
+static int riscv_irqdomain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ struct riscv_irq_data *data = d->host_data;
+
+ irq_set_chip_and_handler(irq, &data->chip, handle_simple_irq);
+ irq_set_chip_data(irq, data);
+ irq_set_noprobe(irq);
+ irq_set_affinity(irq, cpumask_of(data->hart));
+
+ return 0;
+}
+
+static const struct irq_domain_ops riscv_irqdomain_ops = {
+ .map = riscv_irqdomain_map,
+ .xlate = irq_domain_xlate_onecell,
+};
+
+/*
+ * On RISC-V systems local interrupts are masked or unmasked by writing the SIE
+ * (Supervisor Interrupt Enable) CSR. As CSRs can only be written on the local
+ * hart, these functions can only be called on the hart that corresponds to the
+ * IRQ chip. They are only called internally to this module, so they BUG_ON if
+ * this condition is violated rather than attempting to handle the error by
+ * forwarding to the target hart, as that's already expected to have been done.
+ */
+static void riscv_irq_mask(struct irq_data *d)
+{
+ struct riscv_irq_data *data = irq_data_get_irq_chip_data(d);
+
+ BUG_ON(smp_processor_id() != data->hart);
+ csr_clear(sie, 1 << (long)d->hwirq);
+}
+
+static void riscv_irq_unmask(struct irq_data *d)
+{
+ struct riscv_irq_data *data = irq_data_get_irq_chip_data(d);
+
+ BUG_ON(smp_processor_id() != data->hart);
+ csr_set(sie, 1 << (long)d->hwirq);
+}
+
+/* Callbacks for twiddling SIE on another hart. */
+static void riscv_irq_enable_helper(void *d)
+{
+ riscv_irq_unmask(d);
+}
+
+static void riscv_irq_disable_helper(void *d)
+{
+ riscv_irq_mask(d);
+}
+
+static void riscv_remote_ctrl(unsigned int cpu, void (*fn)(void *d),
+ struct irq_data *data)
+{
+ smp_call_function_single(cpu, fn, data, true);
+}
+
+static void riscv_irq_enable(struct irq_data *d)
+{
+ struct riscv_irq_data *data = irq_data_get_irq_chip_data(d);
+
+ /*
+ * It's only possible to write SIE on the current hart. This jumps
+ * over to the target hart if it's not the current one. It's invalid
+ * to write SIE on a hart that's not currently running.
+ */
+ if (data->hart == smp_processor_id())
+ riscv_irq_unmask(d);
+ else if (cpu_online(data->hart))
+ riscv_remote_ctrl(data->hart, riscv_irq_enable_helper, d);
+ else
+ WARN_ON_ONCE(1);
+}
+
+static void riscv_irq_disable(struct irq_data *d)
+{
+ struct riscv_irq_data *data = irq_data_get_irq_chip_data(d);
+
+ /*
+ * It's only possible to write SIE on the current hart. This jumps
+ * over to the target hart if it's not the current one. It's invalid
+ * to write SIE on a hart that's not currently running.
+ */
+ if (data->hart == smp_processor_id())
+ riscv_irq_mask(d);
+ else if (cpu_online(data->hart))
+ riscv_remote_ctrl(data->hart, riscv_irq_disable_helper, d);
+ else
+ WARN_ON_ONCE(1);
+}
+
+static int riscv_intc_init(struct device_node *node, struct device_node *parent)
+{
+ int hart;
+ struct riscv_irq_data *data;
+
+ if (parent)
+ return 0;
+
+ hart = riscv_of_processor_hart(node->parent);
+ if (hart < 0)
+ return -EIO;
+
+ data = &per_cpu(riscv_irq_data, hart);
+ snprintf(data->name, sizeof(data->name), "riscv,cpu_intc,%d", hart);
+ data->hart = hart;
+ data->chip.name = data->name;
+ data->chip.irq_mask = riscv_irq_mask;
+ data->chip.irq_unmask = riscv_irq_unmask;
+ data->chip.irq_enable = riscv_irq_enable;
+ data->chip.irq_disable = riscv_irq_disable;
+ data->domain = irq_domain_add_linear(node, PTR_BITS,
+ &riscv_irqdomain_ops, data);
+ if (!data->domain)
+ goto error_add_linear;
+ pr_info("%s: %d local interrupts mapped\n", data->name, PTR_BITS);
+ return 0;
+
+error_add_linear:
+ pr_warning("%s: unable to add IRQ domain\n",
+ data->name);
+ return -ENXIO;
+}
+
+IRQCHIP_DECLARE(riscv, "riscv,cpu-intc", riscv_intc_init);
--
2.13.5
[toc] | [prev] | [next] | [standalone]
| From | Palmer Dabbelt <palmer@dabbelt.com> |
|---|---|
| Date | 2017-09-13 00:00 +0200 |
| Subject | [PATCH v8 01/18] MAINTAINERS: Add RISC-V |
| Message-ID | <up1nR-6OS-29@gated-at.bofh.it> |
| In reply to | #1731250 |
From: Jonathan Neuschäfer <j.neuschaefer@gmx.net> RISC-V needs a MAINTAINERS entry. Let's add one. Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net> Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com> --- MAINTAINERS | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 1c3feffb1c1c..d5d70a1318d5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11253,6 +11253,15 @@ S: Maintained F: drivers/mtd/nand/r852.c F: drivers/mtd/nand/r852.h +RISC-V ARCHITECTURE +M: Palmer Dabbelt <palmer@sifive.com> +M: Albert Ou <albert@sifive.com> +L: patches@groups.riscv.org +T: git https://github.com/riscv/riscv-linux +S: Supported +F: arch/riscv/ +K: riscv + ROCCAT DRIVERS M: Stefan Achatz <erazor_de@users.sourceforge.net> W: http://sourceforge.net/projects/roccat/ -- 2.13.5
[toc] | [prev] | [next] | [standalone]
| From | Joe Perches <joe@perches.com> |
|---|---|
| Date | 2017-09-13 16:40 +0200 |
| Subject | Re: [PATCH v8 01/18] MAINTAINERS: Add RISC-V |
| Message-ID | <upgZA-7n-3@gated-at.bofh.it> |
| In reply to | #1731252 |
On Tue, 2017-09-12 at 14:56 -0700, Palmer Dabbelt wrote: > RISC-V needs a MAINTAINERS entry. Let's add one. [] > diff --git a/MAINTAINERS b/MAINTAINERS [] > @@ -11253,6 +11253,15 @@ S: Maintained > F: drivers/mtd/nand/r852.c > F: drivers/mtd/nand/r852.h > > +RISC-V ARCHITECTURE > +M: Palmer Dabbelt <palmer@sifive.com> > +M: Albert Ou <albert@sifive.com> > +L: patches@groups.riscv.org > +T: git https://github.com/riscv/riscv-linux > +S: Supported > +F: arch/riscv/ > +K: riscv perhaps add N: riscv
[toc] | [prev] | [next] | [standalone]
| From | Palmer Dabbelt <palmer@dabbelt.com> |
|---|---|
| Date | 2017-09-13 18:00 +0200 |
| Subject | Re: [PATCH v8 01/18] MAINTAINERS: Add RISC-V |
| Message-ID | <upieZ-Ri-9@gated-at.bofh.it> |
| In reply to | #1731636 |
On Wed, 13 Sep 2017 07:39:05 PDT (-0700), joe@perches.com wrote: > On Tue, 2017-09-12 at 14:56 -0700, Palmer Dabbelt wrote: >> RISC-V needs a MAINTAINERS entry. Let's add one. > [] >> diff --git a/MAINTAINERS b/MAINTAINERS > [] >> @@ -11253,6 +11253,15 @@ S: Maintained >> F: drivers/mtd/nand/r852.c >> F: drivers/mtd/nand/r852.h >> >> +RISC-V ARCHITECTURE >> +M: Palmer Dabbelt <palmer@sifive.com> >> +M: Albert Ou <albert@sifive.com> >> +L: patches@groups.riscv.org >> +T: git https://github.com/riscv/riscv-linux >> +S: Supported >> +F: arch/riscv/ >> +K: riscv > > perhaps add > > N: riscv OK. I'm assuming we'll submit a v9 that's based on linux-next, so I'll just squash this in. diff --git a/MAINTAINERS b/MAINTAINERS index d5d70a1318d5..a84ebf12356f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11261,6 +11261,7 @@ T: git https://github.com/riscv/riscv-linux S: Supported F: arch/riscv/ K: riscv +N: riscv ROCCAT DRIVERS M: Stefan Achatz <erazor_de@users.sourceforge.net>
[toc] | [prev] | [next] | [standalone]
| From | Palmer Dabbelt <palmer@dabbelt.com> |
|---|---|
| Date | 2017-09-13 00:10 +0200 |
| Subject | [PATCH v8 02/18] lib: Add shared copies of some GCC library routines |
| Message-ID | <up1xv-77C-3@gated-at.bofh.it> |
| In reply to | #1731250 |
Many ports (m32r, microblaze, mips, parisc, score, and sparc) use
functionally identical copies of various GCC library routine files,
which came up as we were submitting the RISC-V port (which also uses
some of these).
This patch adds a new copy of these library routine files, which are
functionally identical to the various other copies. These are
availiable via Kconfig as CONFIG_GENERIC_$ROUTINE, which currently isn't
used anywhere.
Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com>
---
include/lib/libgcc.h | 43 +++++++++++++++++++++++++++++++
lib/Kconfig | 18 +++++++++++++
lib/Makefile | 8 ++++++
lib/ashldi3.c | 44 ++++++++++++++++++++++++++++++++
lib/ashrdi3.c | 46 +++++++++++++++++++++++++++++++++
lib/cmpdi2.c | 42 ++++++++++++++++++++++++++++++
lib/lshrdi3.c | 45 ++++++++++++++++++++++++++++++++
lib/muldi3.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/ucmpdi2.c | 35 +++++++++++++++++++++++++
9 files changed, 353 insertions(+)
create mode 100644 include/lib/libgcc.h
create mode 100644 lib/ashldi3.c
create mode 100644 lib/ashrdi3.c
create mode 100644 lib/cmpdi2.c
create mode 100644 lib/lshrdi3.c
create mode 100644 lib/muldi3.c
create mode 100644 lib/ucmpdi2.c
diff --git a/include/lib/libgcc.h b/include/lib/libgcc.h
new file mode 100644
index 000000000000..32e1e0f4b2d0
--- /dev/null
+++ b/include/lib/libgcc.h
@@ -0,0 +1,43 @@
+/*
+ * include/lib/libgcc.h
+ *
+ * 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.
+ */
+
+#ifndef __LIB_LIBGCC_H
+#define __LIB_LIBGCC_H
+
+#include <asm/byteorder.h>
+
+typedef int word_type __attribute__ ((mode (__word__)));
+
+#ifdef __BIG_ENDIAN
+struct DWstruct {
+ int high, low;
+};
+#elif defined(__LITTLE_ENDIAN)
+struct DWstruct {
+ int low, high;
+};
+#else
+#error I feel sick.
+#endif
+
+typedef union {
+ struct DWstruct s;
+ long long ll;
+} DWunion;
+
+#endif /* __ASM_LIBGCC_H */
diff --git a/lib/Kconfig b/lib/Kconfig
index 6762529ad9e4..ee7d8bf0b7e1 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -576,3 +576,21 @@ config PRIME_NUMBERS
tristate
endmenu
+
+config GENERIC_ASHLDI3
+ bool
+
+config GENERIC_ASHRDI3
+ bool
+
+config GENERIC_LSHRDI3
+ bool
+
+config GENERIC_MULDI3
+ bool
+
+config GENERIC_CMPDI2
+ bool
+
+config GENERIC_UCMPDI2
+ bool
diff --git a/lib/Makefile b/lib/Makefile
index 40c18372b301..a9ee19497331 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -243,3 +243,11 @@ UBSAN_SANITIZE_ubsan.o := n
obj-$(CONFIG_SBITMAP) += sbitmap.o
obj-$(CONFIG_PARMAN) += parman.o
+
+# GCC library routines
+obj-$(CONFIG_GENERIC_ASHLDI3) += ashldi3.o
+obj-$(CONFIG_GENERIC_ASHRDI3) += ashrdi3.o
+obj-$(CONFIG_GENERIC_LSHRDI3) += lshrdi3.o
+obj-$(CONFIG_GENERIC_MULDI3) += muldi3.o
+obj-$(CONFIG_GENERIC_CMPDI2) += cmpdi2.o
+obj-$(CONFIG_GENERIC_UCMPDI2) += ucmpdi2.o
diff --git a/lib/ashldi3.c b/lib/ashldi3.c
new file mode 100644
index 000000000000..1b6087db95a5
--- /dev/null
+++ b/lib/ashldi3.c
@@ -0,0 +1,44 @@
+/*
+ * 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/export.h>
+
+#include <lib/libgcc.h>
+
+long long notrace __ashldi3(long long u, word_type b)
+{
+ DWunion uu, w;
+ word_type bm;
+
+ if (b == 0)
+ return u;
+
+ uu.ll = u;
+ bm = 32 - b;
+
+ if (bm <= 0) {
+ w.s.low = 0;
+ w.s.high = (unsigned int) uu.s.low << -bm;
+ } else {
+ const unsigned int carries = (unsigned int) uu.s.low >> bm;
+
+ w.s.low = (unsigned int) uu.s.low << b;
+ w.s.high = ((unsigned int) uu.s.high << b) | carries;
+ }
+
+ return w.ll;
+}
+EXPORT_SYMBOL(__ashldi3);
diff --git a/lib/ashrdi3.c b/lib/ashrdi3.c
new file mode 100644
index 000000000000..2e67c97ac65a
--- /dev/null
+++ b/lib/ashrdi3.c
@@ -0,0 +1,46 @@
+/*
+ * 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/export.h>
+
+#include <lib/libgcc.h>
+
+long long notrace __ashrdi3(long long u, word_type b)
+{
+ DWunion uu, w;
+ word_type bm;
+
+ if (b == 0)
+ return u;
+
+ uu.ll = u;
+ bm = 32 - b;
+
+ if (bm <= 0) {
+ /* w.s.high = 1..1 or 0..0 */
+ w.s.high =
+ uu.s.high >> 31;
+ w.s.low = uu.s.high >> -bm;
+ } else {
+ const unsigned int carries = (unsigned int) uu.s.high << bm;
+
+ w.s.high = uu.s.high >> b;
+ w.s.low = ((unsigned int) uu.s.low >> b) | carries;
+ }
+
+ return w.ll;
+}
+EXPORT_SYMBOL(__ashrdi3);
diff --git a/lib/cmpdi2.c b/lib/cmpdi2.c
new file mode 100644
index 000000000000..6d7ebf6c2b86
--- /dev/null
+++ b/lib/cmpdi2.c
@@ -0,0 +1,42 @@
+/*
+ * 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/export.h>
+
+#include <lib/libgcc.h>
+
+word_type notrace __cmpdi2(long long a, long long b)
+{
+ const DWunion au = {
+ .ll = a
+ };
+ const DWunion bu = {
+ .ll = b
+ };
+
+ if (au.s.high < bu.s.high)
+ return 0;
+ else if (au.s.high > bu.s.high)
+ return 2;
+
+ if ((unsigned int) au.s.low < (unsigned int) bu.s.low)
+ return 0;
+ else if ((unsigned int) au.s.low > (unsigned int) bu.s.low)
+ return 2;
+
+ return 1;
+}
+EXPORT_SYMBOL(__cmpdi2);
diff --git a/lib/lshrdi3.c b/lib/lshrdi3.c
new file mode 100644
index 000000000000..8e845f4bb65f
--- /dev/null
+++ b/lib/lshrdi3.c
@@ -0,0 +1,45 @@
+/*
+ * lib/lshrdi3.c
+ *
+ * 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/module.h>
+#include <lib/libgcc.h>
+
+long long notrace __lshrdi3(long long u, word_type b)
+{
+ DWunion uu, w;
+ word_type bm;
+
+ if (b == 0)
+ return u;
+
+ uu.ll = u;
+ bm = 32 - b;
+
+ if (bm <= 0) {
+ w.s.high = 0;
+ w.s.low = (unsigned int) uu.s.high >> -bm;
+ } else {
+ const unsigned int carries = (unsigned int) uu.s.high << bm;
+
+ w.s.high = (unsigned int) uu.s.high >> b;
+ w.s.low = ((unsigned int) uu.s.low >> b) | carries;
+ }
+
+ return w.ll;
+}
+EXPORT_SYMBOL(__lshrdi3);
diff --git a/lib/muldi3.c b/lib/muldi3.c
new file mode 100644
index 000000000000..88938543e10a
--- /dev/null
+++ b/lib/muldi3.c
@@ -0,0 +1,72 @@
+/*
+ * 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/export.h>
+#include <lib/libgcc.h>
+
+#define W_TYPE_SIZE 32
+
+#define __ll_B ((unsigned long) 1 << (W_TYPE_SIZE / 2))
+#define __ll_lowpart(t) ((unsigned long) (t) & (__ll_B - 1))
+#define __ll_highpart(t) ((unsigned long) (t) >> (W_TYPE_SIZE / 2))
+
+/* If we still don't have umul_ppmm, define it using plain C. */
+#if !defined(umul_ppmm)
+#define umul_ppmm(w1, w0, u, v) \
+ do { \
+ unsigned long __x0, __x1, __x2, __x3; \
+ unsigned short __ul, __vl, __uh, __vh; \
+ \
+ __ul = __ll_lowpart(u); \
+ __uh = __ll_highpart(u); \
+ __vl = __ll_lowpart(v); \
+ __vh = __ll_highpart(v); \
+ \
+ __x0 = (unsigned long) __ul * __vl; \
+ __x1 = (unsigned long) __ul * __vh; \
+ __x2 = (unsigned long) __uh * __vl; \
+ __x3 = (unsigned long) __uh * __vh; \
+ \
+ __x1 += __ll_highpart(__x0); /* this can't give carry */\
+ __x1 += __x2; /* but this indeed can */ \
+ if (__x1 < __x2) /* did we get it? */ \
+ __x3 += __ll_B; /* yes, add it in the proper pos */ \
+ \
+ (w1) = __x3 + __ll_highpart(__x1); \
+ (w0) = __ll_lowpart(__x1) * __ll_B + __ll_lowpart(__x0);\
+ } while (0)
+#endif
+
+#if !defined(__umulsidi3)
+#define __umulsidi3(u, v) ({ \
+ DWunion __w; \
+ umul_ppmm(__w.s.high, __w.s.low, u, v); \
+ __w.ll; \
+ })
+#endif
+
+long long notrace __muldi3(long long u, long long v)
+{
+ const DWunion uu = {.ll = u};
+ const DWunion vv = {.ll = v};
+ DWunion w = {.ll = __umulsidi3(uu.s.low, vv.s.low)};
+
+ w.s.high += ((unsigned long) uu.s.low * (unsigned long) vv.s.high
+ + (unsigned long) uu.s.high * (unsigned long) vv.s.low);
+
+ return w.ll;
+}
+EXPORT_SYMBOL(__muldi3);
diff --git a/lib/ucmpdi2.c b/lib/ucmpdi2.c
new file mode 100644
index 000000000000..49a53505c8e3
--- /dev/null
+++ b/lib/ucmpdi2.c
@@ -0,0 +1,35 @@
+/*
+ * 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/module.h>
+#include <lib/libgcc.h>
+
+word_type __ucmpdi2(unsigned long long a, unsigned long long b)
+{
+ const DWunion au = {.ll = a};
+ const DWunion bu = {.ll = b};
+
+ if ((unsigned int) au.s.high < (unsigned int) bu.s.high)
+ return 0;
+ else if ((unsigned int) au.s.high > (unsigned int) bu.s.high)
+ return 2;
+ if ((unsigned int) au.s.low < (unsigned int) bu.s.low)
+ return 0;
+ else if ((unsigned int) au.s.low > (unsigned int) bu.s.low)
+ return 2;
+ return 1;
+}
+EXPORT_SYMBOL(__ucmpdi2);
--
2.13.5
[toc] | [prev] | [next] | [standalone]
| From | Palmer Dabbelt <palmer@dabbelt.com> |
|---|---|
| Date | 2017-09-13 00:10 +0200 |
| Subject | [PATCH v8 04/18] dt-bindings: interrupt-controller: RISC-V PLIC documentation |
| Message-ID | <up1xw-77C-11@gated-at.bofh.it> |
| In reply to | #1731250 |
This patch adds documentation for the platform-level interrupt
controller (PLIC) found in all RISC-V systems. This interrupt
controller routes interrupts from all the devices in the system to each
hart-local interrupt controller.
Note: the DTS bindings for the PLIC aren't set in stone yet, as we might
want to change how we're specifying holes in the hart list.
Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com>
---
.../bindings/interrupt-controller/riscv,plic0.txt | 55 ++++++++++++++++++++++
1 file changed, 55 insertions(+)
create mode 100644 Documentation/devicetree/bindings/interrupt-controller/riscv,plic0.txt
diff --git a/Documentation/devicetree/bindings/interrupt-controller/riscv,plic0.txt b/Documentation/devicetree/bindings/interrupt-controller/riscv,plic0.txt
new file mode 100644
index 000000000000..99cd359dbd43
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/riscv,plic0.txt
@@ -0,0 +1,55 @@
+RISC-V Platform-Level Interrupt Controller (PLIC)
+-------------------------------------------------
+
+The RISC-V supervisor ISA specification allows for the presence of a
+platform-level interrupt controller (PLIC). The PLIC connects all external
+interrupts in the system to all hart contexts in the system, via the external
+interrupt source in each hart's hart-local interrupt controller (HLIC). A hart
+context is a privilege mode in a hardware execution thread. For example, in
+an 4 core system with 2-way SMT, you have 8 harts and probably at least two
+privilege modes per hart; machine mode and supervisor mode.
+
+Each interrupt can be enabled on per-context basis. Any context can claim
+a pending enabled interrupt and then release it once it has been handled.
+
+Each interrupt has a configurable priority. Higher priority interrupts are
+serviced firs. Each context can specify a priority threshold. Interrupts
+with priority below this threshold will not cause the PLIC to raise its
+interrupt line leading to the context.
+
+While the PLIC supports both edge-triggered and level-triggered interrupts,
+interrupt handlers are oblivious to this distinction and therefor it is not
+specific in the PLIC device-tree binding.
+
+While the RISC-V ISA doesn't specify a memory layout for the PLIC, the
+"riscv,plic0" device is a concrete implementation of the PLIC that contains a
+specific memory layout. More details about the memory layout of the
+"riscv,plic0" device can be found as a comment in the device driver, or as part
+of the SiFive U5 Coreplex Series Manual (page 22 of the PDF of version 1.0)
+<https://www.sifive.com/documentation/coreplex/u5-coreplex-series-manual/>
+
+Required properties:
+- compatible : "riscv,plic0"
+- #address-cells : should be <0>
+- #interrupt-cells : should be <1>
+- interrupt-controller : Identifies the node as an interrupt controller
+- reg : Should contain 1 register range (address and length)
+- interrupts-extended : Specifies which contexts are connected to the PLIC,
+ with "-1" specifying that a context is not present.
+
+Example:
+
+ plic: interrupt-controller@c000000 {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ compatible = "riscv,plic0";
+ interrupt-controller;
+ interrupts-extended = <
+ &cpu0-intc 11
+ &cpu1-intc 11 &cpu1-intc 9
+ &cpu2-intc 11 &cpu2-intc 9
+ &cpu3-intc 11 &cpu3-intc 9
+ &cpu4-intc 11 &cpu4-intc 9>;
+ reg = <0xc000000 0x4000000>;
+ riscv,ndev = <10>;
+ };
--
2.13.5
[toc] | [prev] | [next] | [standalone]
| From | Rob Herring <robh@kernel.org> |
|---|---|
| Date | 2017-09-15 16:40 +0200 |
| Subject | Re: [PATCH v8 04/18] dt-bindings: interrupt-controller: RISC-V PLIC documentation |
| Message-ID | <upZWF-4c0-3@gated-at.bofh.it> |
| In reply to | #1731255 |
On Tue, Sep 12, 2017 at 4:57 PM, Palmer Dabbelt <palmer@dabbelt.com> wrote: > This patch adds documentation for the platform-level interrupt > controller (PLIC) found in all RISC-V systems. This interrupt > controller routes interrupts from all the devices in the system to each > hart-local interrupt controller. It has been mentioned before, but please copy the right people and lists. IOW, use scripts/get_maintainers.pl. You've got a whole bunch of people CCed and probably most don't care about DT bindings at all. Rob
[toc] | [prev] | [next] | [standalone]
| From | Palmer Dabbelt <palmer@dabbelt.com> |
|---|---|
| Date | 2017-09-15 18:30 +0200 |
| Subject | Re: [PATCH v8 04/18] dt-bindings: interrupt-controller: RISC-V PLIC documentation |
| Message-ID | <uq1F7-5pk-1@gated-at.bofh.it> |
| In reply to | #1732912 |
On Fri, 15 Sep 2017 07:34:33 PDT (-0700), robh@kernel.org wrote: > On Tue, Sep 12, 2017 at 4:57 PM, Palmer Dabbelt <palmer@dabbelt.com> wrote: >> This patch adds documentation for the platform-level interrupt >> controller (PLIC) found in all RISC-V systems. This interrupt >> controller routes interrupts from all the devices in the system to each >> hart-local interrupt controller. > > It has been mentioned before, but please copy the right people and > lists. IOW, use scripts/get_maintainers.pl. You've got a whole bunch > of people CCed and probably most don't care about DT bindings at all. Sorry about that -- I'd just been CCing everyone on the entire patch set so everyone's on the same page. It was suggested we start splitting up the patches again, so if you think it's better I can submit just the binding patches as another patch set right now? Then they'll only go to the people from get_maintainers.
[toc] | [prev] | [next] | [standalone]
| From | Palmer Dabbelt <palmer@dabbelt.com> |
|---|---|
| Date | 2017-09-13 00:10 +0200 |
| Subject | [PATCH v8 03/18] dt-bindings: interrupt-controller: RISC-V local interrupt controller docs |
| Message-ID | <up1xw-77C-17@gated-at.bofh.it> |
| In reply to | #1731250 |
This patch adds documentation on the RISC-V local interrupt controller,
which is a per-hart interrupt controller that manages all interrupts
entering a RISC-V hart. This interrupt controller is present on all
RISC-V systems.
Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com>
---
.../interrupt-controller/riscv,cpu-intc.txt | 41 ++++++++++++++++++++++
1 file changed, 41 insertions(+)
create mode 100644 Documentation/devicetree/bindings/interrupt-controller/riscv,cpu-intc.txt
diff --git a/Documentation/devicetree/bindings/interrupt-controller/riscv,cpu-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/riscv,cpu-intc.txt
new file mode 100644
index 000000000000..61900e2e3868
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/riscv,cpu-intc.txt
@@ -0,0 +1,41 @@
+RISC-V Hart-Level Interrupt Controller (HLIC)
+---------------------------------------------
+
+RISC-V cores include Control Status Registers (CSRs) which are local to each
+hart and can be read or written by software. Some of these CSRs are used to
+control local interrupts connected to the core. Every interrupt is ultimately
+routed through a hart's HLIC before it interrupts that hart.
+
+The RISC-V supervisor ISA manual specifies three interrupt sources that are
+attached to every HLIC: software interrupts, the timer interrupt, and external
+interrupts. Software interrupts are used to send IPIs between cores. The
+timer interrupt comes from an architecturally mandated real-time timer that is
+controller via SBI calls and CSR reads. External interrupts connect all other
+device interrupts to the HLIC, which are routed via the platform-level
+interrupt controller (PLIC).
+
+All RISC-V systems that conform to the supervisor ISA specification are
+required to have a HLIC with these three interrupt sources present. Since the
+interrupt map is defined by the ISA it's not listed in the HLIC's device tree
+entry, though external interrupt controllers (like the PLIC, for example) will
+need to define how their interrupts map to the relevant HLICs.
+
+Required properties:
+- compatible : "riscv,cpu-intc"
+- #interrupt-cells : should be <1>
+- interrupt-controller : Identifies the node as an interrupt controller
+
+Furthermore, this interrupt-controller MUST be embedded inside the cpu
+definition of the hart whose CSRs control these local interrupts.
+
+An example device tree entry for a HLIC is show below.
+
+ cpu1: cpu@1 {
+ compatible = "riscv";
+ ...
+ cpu1-intc: interrupt-controller {
+ #interrupt-cells = <1>;
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ };
+ };
--
2.13.5
[toc] | [prev] | [next] | [standalone]
| From | Palmer Dabbelt <palmer@dabbelt.com> |
|---|---|
| Date | 2017-09-13 00:10 +0200 |
| Subject | [PATCH v8 08/18] irqchip: New RISC-V PLIC Driver |
| Message-ID | <up1xw-77C-21@gated-at.bofh.it> |
| In reply to | #1731250 |
This patch adds a driver for the Platform Level Interrupt Controller
(PLIC) specified as part of the RISC-V supervisor level ISA manual.
The PLIC connocts global interrupt sources to the local interrupt
controller on each hart. A PLIC is present on all RISC-V systems.
Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com>
---
drivers/irqchip/Kconfig | 13 ++
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-riscv-plic.c | 379 +++++++++++++++++++++++++++++++++++++++
3 files changed, 393 insertions(+)
create mode 100644 drivers/irqchip/irq-riscv-plic.c
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 7923d3fa8fae..c23539923c10 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -307,6 +307,19 @@ config QCOM_IRQ_COMBINER
Say yes here to add support for the IRQ combiner devices embedded
in Qualcomm Technologies chips.
+config RISCV_PLIC
+ bool "Platform-Level Interrupt Controller"
+ depends on RISCV
+ default y
+ help
+ This enables support for the PLIC chip found in standard RISC-V
+ systems. The PLIC controls devices interrupts and connects them to
+ each core's local interrupt controller. Aside from timer and
+ software interrupts, all other interrupt sources (MSI, GPIO, etc)
+ are subordinate to the PLIC.
+
+ If you don't know what to do here, say Y.
+
config RISCV_INTC
def_bool y if RISCV
#bool "RISC-V Interrupt Controller"
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index b1aa9114afc4..7880c9cec40e 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -78,4 +78,5 @@ obj-$(CONFIG_EZNPS_GIC) += irq-eznps.o
obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o irq-aspeed-i2c-ic.o
obj-$(CONFIG_STM32_EXTI) += irq-stm32-exti.o
obj-$(CONFIG_QCOM_IRQ_COMBINER) += qcom-irq-combiner.o
+obj-$(CONFIG_RISCV_PLIC) += irq-riscv-plic.o
obj-$(CONFIG_RISCV_INTC) += irq-riscv-intc.o
diff --git a/drivers/irqchip/irq-riscv-plic.c b/drivers/irqchip/irq-riscv-plic.c
new file mode 100644
index 000000000000..b5182b43b377
--- /dev/null
+++ b/drivers/irqchip/irq-riscv-plic.c
@@ -0,0 +1,379 @@
+/*
+ * 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/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+/*
+ * From the RISC-V Privlidged Spec v1.10:
+ *
+ * Global interrupt sources are assigned small unsigned integer identifiers,
+ * beginning at the value 1. An interrupt ID of 0 is reserved to mean “no
+ * interrupt”. Interrupt identifiers are also used to break ties when two or
+ * more interrupt sources have the same assigned priority. Smaller values of
+ * interrupt ID take precedence over larger values of interrupt ID.
+ *
+ * While the RISC-V supervisor spec doesn't define the maximum number of
+ * devices supported by the PLIC, the largest number supported by devices
+ * marked as 'riscv,plic0' (which is the only device type this driver supports,
+ * and is the only extant PLIC as of now) is 1024. As mentioned above, device
+ * 0 is defined to be non-existant so this device really only supports 1023
+ * devices.
+ */
+#define MAX_DEVICES 1024
+#define MAX_CONTEXTS 15872
+
+/*
+ * The PLIC consists of memory-mapped control registers, with a memory map as
+ * follows:
+ *
+ * base + 0x000000: Reserved (interrupt source 0 does not exist)
+ * base + 0x000004: Interrupt source 1 priority
+ * base + 0x000008: Interrupt source 2 priority
+ * ...
+ * base + 0x000FFC: Interrupt source 1023 priority
+ * base + 0x001000: Pending 0
+ * base + 0x001FFF: Pending
+ * base + 0x002000: Enable bits for sources 0-31 on context 0
+ * base + 0x002004: Enable bits for sources 32-63 on context 0
+ * ...
+ * base + 0x0020FC: Enable bits for sources 992-1023 on context 0
+ * base + 0x002080: Enable bits for sources 0-31 on context 1
+ * ...
+ * base + 0x002100: Enable bits for sources 0-31 on context 2
+ * ...
+ * base + 0x1F1F80: Enable bits for sources 992-1023 on context 15871
+ * base + 0x1F1F84: Reserved
+ * ... (higher context IDs would fit here, but wouldn't fit
+ * inside the per-context priority vector)
+ * base + 0x1FFFFC: Reserved
+ * base + 0x200000: Priority threshold for context 0
+ * base + 0x200004: Claim/complete for context 0
+ * base + 0x200008: Reserved
+ * ...
+ * base + 0x200FFC: Reserved
+ * base + 0x201000: Priority threshold for context 1
+ * base + 0x201004: Claim/complete for context 1
+ * ...
+ * base + 0xFFE000: Priority threshold for context 15871
+ * base + 0xFFE004: Claim/complete for context 15871
+ * base + 0xFFE008: Reserved
+ * ...
+ * base + 0xFFFFFC: Reserved
+ */
+
+/* Each interrupt source has a priority register associated with it. */
+#define PRIORITY_BASE 0
+#define PRIORITY_PER_ID 4
+
+/*
+ * Each hart context has a vector of interupt enable bits associated with it.
+ * There's one bit for each interrupt source.
+ */
+#define ENABLE_BASE 0x2000
+#define ENABLE_PER_HART 0x80
+
+/*
+ * Each hart context has a set of control registers associated with it. Right
+ * now there's only two: a source priority threshold over which the hart will
+ * take an interrupt, and a register to claim interrupts.
+ */
+#define CONTEXT_BASE 0x200000
+#define CONTEXT_PER_HART 0x1000
+#define CONTEXT_THRESHOLD 0
+#define CONTEXT_CLAIM 4
+
+/*
+ * PLIC devices are named like 'riscv,plic0,%llx', this is enough space to
+ * store that name.
+ */
+#define PLIC_DATA_NAME_SIZE 30
+
+struct plic_handler {
+ bool present;
+ int contextid;
+ struct plic_data *data;
+};
+
+struct plic_data {
+ struct irq_chip chip;
+ struct irq_domain *domain;
+ u32 ndev;
+ void __iomem *reg;
+ int handlers;
+ struct plic_handler *handler;
+ char name[PLIC_DATA_NAME_SIZE];
+ spinlock_t lock;
+};
+
+/* Addressing helper functions. */
+static inline
+void __iomem *plic_enable_vector(struct plic_data *data, int contextid)
+{
+ return data->reg + ENABLE_BASE + contextid * ENABLE_PER_HART;
+}
+
+static inline
+void __iomem *plic_priority(struct plic_data *data, int hwirq)
+{
+ return data->reg + PRIORITY_BASE + hwirq * PRIORITY_PER_ID;
+}
+
+static inline
+void __iomem *plic_hart_threshold(struct plic_data *data, int contextid)
+{
+ return data->reg + CONTEXT_BASE + CONTEXT_PER_HART * contextid + CONTEXT_THRESHOLD;
+}
+
+static inline
+void __iomem *plic_hart_claim(struct plic_data *data, int contextid)
+{
+ return data->reg + CONTEXT_BASE + CONTEXT_PER_HART * contextid + CONTEXT_CLAIM;
+}
+
+/*
+ * Handling an interrupt is a two-step process: first you claim the interrupt
+ * by reading the claim register, then you complete the interrupt by writing
+ * that source ID back to the same claim register. This automatically enables
+ * and disables the interrupt, so there's nothing else to do.
+ */
+static inline
+u32 plic_claim(struct plic_data *data, int contextid)
+{
+ return readl(plic_hart_claim(data, contextid));
+}
+
+static inline
+void plic_complete(struct plic_data *data, int contextid, u32 claim)
+{
+ writel(claim, plic_hart_claim(data, contextid));
+}
+
+/* Explicit interrupt masking. */
+static void plic_disable(struct plic_data *data, int contextid, int hwirq)
+{
+ void __iomem *reg = plic_enable_vector(data, contextid) + (hwirq / 32);
+ u32 mask = ~(1 << (hwirq % 32));
+
+ spin_lock(&data->lock);
+ writel(readl(reg) & mask, reg);
+ spin_unlock(&data->lock);
+}
+
+static void plic_enable(struct plic_data *data, int contextid, int hwirq)
+{
+ void __iomem *reg = plic_enable_vector(data, contextid) + (hwirq / 32);
+ u32 bit = 1 << (hwirq % 32);
+
+ spin_lock(&data->lock);
+ writel(readl(reg) | bit, reg);
+ spin_unlock(&data->lock);
+}
+
+/*
+ * There is no need to mask/unmask PLIC interrupts
+ * They are "masked" by reading claim and "unmasked" when writing it back.
+ */
+static void plic_irq_mask(struct irq_data *d) { }
+static void plic_irq_unmask(struct irq_data *d) { }
+
+static void plic_irq_enable(struct irq_data *d)
+{
+ struct plic_data *data = irq_data_get_irq_chip_data(d);
+ void __iomem *priority = plic_priority(data, d->hwirq);
+ int i;
+
+ writel(1, priority);
+ for (i = 0; i < data->handlers; ++i)
+ if (data->handler[i].present)
+ plic_enable(data, i, d->hwirq);
+}
+
+static void plic_irq_disable(struct irq_data *d)
+{
+ struct plic_data *data = irq_data_get_irq_chip_data(d);
+ void __iomem *priority = plic_priority(data, d->hwirq);
+ int i;
+
+ writel(0, priority);
+ for (i = 0; i < data->handlers; ++i)
+ if (data->handler[i].present)
+ plic_disable(data, i, d->hwirq);
+}
+
+static void plic_irq_eoi(struct irq_data *d)
+{
+ /* FIXME: I can't figure out what's going on here: when I set the PLIC
+ * driver to use hadle_fasteoi_irq I end up with !handler here. The
+ * difference is that here we get an irq_data and use
+ * common.handler_data, while in the working version we get an
+ * irq_desc and use irq_common_data.handler_data. */
+ struct plic_handler *handler = d->common->handler_data;
+ BUG_ON(!handler);
+ plic_complete(handler->data, handler->contextid, d->hwirq);
+}
+
+static int plic_irqdomain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ struct plic_data *data = d->host_data;
+
+ /* FIXME: ... I want to set handle_fasteoi_irq here. */
+ irq_set_chip_and_handler(irq, &data->chip, handle_simple_irq);
+ irq_set_chip_data(irq, data);
+ irq_set_noprobe(irq);
+
+ return 0;
+}
+
+static const struct irq_domain_ops plic_irqdomain_ops = {
+ .map = plic_irqdomain_map,
+ .xlate = irq_domain_xlate_onecell,
+};
+
+static void plic_chained_handle_irq(struct irq_desc *desc)
+{
+ struct plic_handler *handler = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct irq_domain *domain = handler->data->domain;
+ u32 what;
+
+ chained_irq_enter(chip, desc);
+
+ while ((what = plic_claim(handler->data, handler->contextid))) {
+ int irq = irq_find_mapping(domain, what);
+
+ if (irq > 0)
+ generic_handle_irq(irq);
+ else
+ handle_bad_irq(desc);
+ plic_complete(handler->data, handler->contextid, what);
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static int plic_init(struct device_node *node, struct device_node *parent)
+{
+ struct plic_data *data;
+ struct resource resource;
+ int i, ok = 0;
+ int out = -1;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (WARN_ON(!data))
+ return -ENOMEM;
+
+ spin_lock_init(&data->lock);
+
+ data->reg = of_iomap(node, 0);
+ if (WARN_ON(!data->reg)) {
+ out = -EIO;
+ goto free_data;
+ }
+
+ of_property_read_u32(node, "riscv,ndev", &data->ndev);
+ if (WARN_ON(!data->ndev)) {
+ out = -EINVAL;
+ goto free_reg;
+ }
+
+ data->handlers = of_irq_count(node);
+ if (WARN_ON(!data->handlers)) {
+ out = -EINVAL;
+ goto free_reg;
+ }
+
+ data->handler =
+ kcalloc(data->handlers, sizeof(*data->handler), GFP_KERNEL);
+ if (WARN_ON(!data->handler)) {
+ out = -ENOMEM;
+ goto free_reg;
+ }
+
+ data->domain = irq_domain_add_linear(node, data->ndev+1, &plic_irqdomain_ops, data);
+ if (WARN_ON(!data->domain)) {
+ out = -ENOMEM;
+ goto free_handler;
+ }
+
+ of_address_to_resource(node, 0, &resource);
+ snprintf(data->name, sizeof(data->name),
+ "riscv,plic0,%llx", resource.start);
+ data->chip.name = data->name;
+ data->chip.irq_mask = plic_irq_mask;
+ data->chip.irq_unmask = plic_irq_unmask;
+ data->chip.irq_enable = plic_irq_enable;
+ data->chip.irq_disable = plic_irq_disable;
+ data->chip.irq_eoi = plic_irq_eoi;
+
+ for (i = 0; i < data->handlers; ++i) {
+ struct plic_handler *handler = &data->handler[i];
+ struct of_phandle_args parent;
+ int parent_irq, hwirq;
+
+ handler->present = false;
+
+ if (of_irq_parse_one(node, i, &parent))
+ continue;
+ /* skip context holes */
+ if (parent.args[0] == -1)
+ continue;
+
+ /* skip any contexts that lead to inactive harts */
+ if (of_device_is_compatible(parent.np, "riscv,cpu-intc") &&
+ parent.np->parent &&
+ riscv_of_processor_hart(parent.np->parent) < 0)
+ continue;
+
+ parent_irq = irq_create_of_mapping(&parent);
+ if (!parent_irq)
+ continue;
+
+ handler->present = true;
+ handler->contextid = i;
+ handler->data = data;
+ /* hwirq prio must be > this to trigger an interrupt */
+ writel(0, plic_hart_threshold(data, i));
+
+ for (hwirq = 1; hwirq <= data->ndev; ++hwirq)
+ plic_disable(data, i, hwirq);
+ irq_set_chained_handler_and_data(parent_irq, plic_chained_handle_irq, handler);
+ ++ok;
+ }
+
+ pr_info("%s: mapped %d interrupts to %d/%d handlers\n",
+ data->name, data->ndev, ok, data->handlers);
+ WARN_ON(!ok);
+ return 0;
+
+free_handler:
+ kfree(data->handler);
+free_reg:
+ iounmap(data->reg);
+free_data:
+ kfree(data);
+ return out;
+}
+
+IRQCHIP_DECLARE(plic0, "riscv,plic0", plic_init);
--
2.13.5
[toc] | [prev] | [next] | [standalone]
| From | Jonathan Neuschäfer <j.neuschaefer@gmx.net> |
|---|---|
| Date | 2017-09-14 13:10 +0200 |
| Subject | Re: [patches] [PATCH v8 08/18] irqchip: New RISC-V PLIC Driver |
| Message-ID | <upAbU-4fq-33@gated-at.bofh.it> |
| In reply to | #1731258 |
[Multipart message — attachments visible in raw view] — view raw
Hi, On Tue, Sep 12, 2017 at 02:57:05PM -0700, Palmer Dabbelt wrote: > This patch adds a driver for the Platform Level Interrupt Controller > (PLIC) specified as part of the RISC-V supervisor level ISA manual. > The PLIC connocts global interrupt sources to the local interrupt s/connocts/connects/? > controller on each hart. A PLIC is present on all RISC-V systems. > > Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com> > --- [...] > +/* > + * The PLIC consists of memory-mapped control registers, with a memory map as > + * follows: This memory map is mostly still as confusing as before (see my email in the v7 thread). > + * > + * base + 0x000000: Reserved (interrupt source 0 does not exist) > + * base + 0x000004: Interrupt source 1 priority > + * base + 0x000008: Interrupt source 2 priority > + * ... > + * base + 0x000FFC: Interrupt source 1023 priority > + * base + 0x001000: Pending 0 > + * base + 0x001FFF: Pending > + * base + 0x002000: Enable bits for sources 0-31 on context 0 > + * base + 0x002004: Enable bits for sources 32-63 on context 0 > + * ... > + * base + 0x0020FC: Enable bits for sources 992-1023 on context 0 > + * base + 0x002080: Enable bits for sources 0-31 on context 1 > + * ... > + * base + 0x002100: Enable bits for sources 0-31 on context 2 > + * ... > + * base + 0x1F1F80: Enable bits for sources 992-1023 on context 15871 > + * base + 0x1F1F84: Reserved > + * ... (higher context IDs would fit here, but wouldn't fit > + * inside the per-context priority vector) > + * base + 0x1FFFFC: Reserved > + * base + 0x200000: Priority threshold for context 0 > + * base + 0x200004: Claim/complete for context 0 > + * base + 0x200008: Reserved > + * ... > + * base + 0x200FFC: Reserved > + * base + 0x201000: Priority threshold for context 1 > + * base + 0x201004: Claim/complete for context 1 > + * ... > + * base + 0xFFE000: Priority threshold for context 15871 > + * base + 0xFFE004: Claim/complete for context 15871 > + * base + 0xFFE008: Reserved > + * ... > + * base + 0xFFFFFC: Reserved > + */ Jonathan Neuschäfer
[toc] | [prev] | [next] | [standalone]
| From | Palmer Dabbelt <palmer@dabbelt.com> |
|---|---|
| Date | 2017-09-13 00:10 +0200 |
| Subject | [PATCH v8 09/18] tty: New RISC-V SBI console driver |
| Message-ID | <up1xw-77C-27@gated-at.bofh.it> |
| In reply to | #1731250 |
The RISC-V ISA defines a simple console that is availiable via SBI calls
on all systems. This patch adds a driver for this console interface
that can act as both a target for early printk and as the system
console.
Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com>
---
arch/riscv/include/asm/hvc_riscv_sbi.h | 25 ++++++++++
drivers/tty/hvc/Kconfig | 11 +++++
drivers/tty/hvc/Makefile | 1 +
drivers/tty/hvc/hvc_riscv_sbi.c | 90 ++++++++++++++++++++++++++++++++++
4 files changed, 127 insertions(+)
create mode 100644 arch/riscv/include/asm/hvc_riscv_sbi.h
create mode 100644 drivers/tty/hvc/hvc_riscv_sbi.c
diff --git a/arch/riscv/include/asm/hvc_riscv_sbi.h b/arch/riscv/include/asm/hvc_riscv_sbi.h
new file mode 100644
index 000000000000..d4f3cf0c17e9
--- /dev/null
+++ b/arch/riscv/include/asm/hvc_riscv_sbi.h
@@ -0,0 +1,25 @@
+/*
+ * RISC-V SBI console interface
+ *
+ * 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.
+ */
+
+#ifndef _ASM_RISCV_HVC_RISCV_SBI_H
+#define _ASM_RISCV_HVC_RISCV_SBI_H
+
+/*
+ * We always support CONFIG_EARLY_PRINTK via the SBI console driver because it
+ * works well enough that there's no penalty to doing so.
+ */
+extern struct console riscv_sbi_early_console_dev __initdata;
+
+#endif
diff --git a/drivers/tty/hvc/Kconfig b/drivers/tty/hvc/Kconfig
index b8d5ea0ae26b..abe331761bdb 100644
--- a/drivers/tty/hvc/Kconfig
+++ b/drivers/tty/hvc/Kconfig
@@ -97,6 +97,17 @@ config HVC_BFIN_JTAG
the HVC driver. If you don't have JTAG, then you probably don't
want this option.
+config HVC_RISCV_SBI
+ bool "RISC-V SBI console support"
+ depends on RISCV
+ select HVC_DRIVER
+ default y
+ help
+ This enables support for console output via RISC-V SBI calls, which
+ is normally used only during boot to output printk.
+
+ If you don't know what do to here, say Y.
+
config HVCS
tristate "IBM Hypervisor Virtual Console Server support"
depends on PPC_PSERIES && HVC_CONSOLE
diff --git a/drivers/tty/hvc/Makefile b/drivers/tty/hvc/Makefile
index 6a2702be76d1..be497f9312d1 100644
--- a/drivers/tty/hvc/Makefile
+++ b/drivers/tty/hvc/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_HVC_IUCV) += hvc_iucv.o
obj-$(CONFIG_HVC_UDBG) += hvc_udbg.o
obj-$(CONFIG_HVC_BFIN_JTAG) += hvc_bfin_jtag.o
obj-$(CONFIG_HVCS) += hvcs.o
+obj-$(CONFIG_HVC_RISCV_SBI) += hvc_riscv_sbi.o
diff --git a/drivers/tty/hvc/hvc_riscv_sbi.c b/drivers/tty/hvc/hvc_riscv_sbi.c
new file mode 100644
index 000000000000..2548d658e110
--- /dev/null
+++ b/drivers/tty/hvc/hvc_riscv_sbi.c
@@ -0,0 +1,90 @@
+/*
+ * RISC-V SBI interface to hvc_console.c
+ * based on drivers-tty/hvc/hvc_udbg.c
+ *
+ * Copyright (C) 2008 David Gibson, IBM Corporation
+ * 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/console.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+
+#include <asm/sbi.h>
+#include <asm/hvc_riscv_sbi.h>
+
+#include "hvc_console.h"
+
+static int hvc_sbi_tty_put(uint32_t vtermno, const char *buf, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ sbi_console_putchar(buf[i]);
+
+ return i;
+}
+
+static int hvc_sbi_tty_get(uint32_t vtermno, char *buf, int count)
+{
+ int i, c;
+
+ for (i = 0; i < count; i++) {
+ if ((c = sbi_console_getchar()) < 0)
+ break;
+ buf[i] = c;
+ }
+
+ return i;
+}
+
+static const struct hv_ops hvc_sbi_ops = {
+ .get_chars = hvc_sbi_tty_get,
+ .put_chars = hvc_sbi_tty_put,
+};
+
+static int __init hvc_sbi_init(void)
+{
+ return PTR_ERR_OR_ZERO(hvc_alloc(0, 0, &hvc_sbi_ops, 16));
+}
+device_initcall(hvc_sbi_init);
+
+static int __init hvc_sbi_console_init(void)
+{
+ hvc_instantiate(0, 0, &hvc_sbi_ops);
+ add_preferred_console("hvc", 0, NULL);
+
+ return 0;
+}
+console_initcall(hvc_sbi_console_init);
+
+static void sbi_console_write(struct console *co, const char *buf,
+ unsigned int n)
+{
+ int i;
+
+ for (i = 0; i < n; ++i) {
+ if (buf[i] == '\n')
+ sbi_console_putchar('\r');
+ sbi_console_putchar(buf[i]);
+ }
+}
+
+struct console riscv_sbi_early_console_dev __initdata = {
+ .name = "early",
+ .write = sbi_console_write,
+ .flags = CON_PRINTBUFFER | CON_BOOT | CON_ANYTIME,
+ .index = -1
+};
--
2.13.5
[toc] | [prev] | [next] | [standalone]
| From | Palmer Dabbelt <palmer@dabbelt.com> |
|---|---|
| Date | 2017-09-13 00:10 +0200 |
| Subject | [PATCH v8 13/18] RISC-V: ELF and module implementation |
| Message-ID | <up1xx-77C-31@gated-at.bofh.it> |
| In reply to | #1731250 |
This patch contains the code that interfaces with ELF objects on RISC-V
systems, the vast majority of which is present to load kernel modules.
Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com>
---
arch/riscv/include/asm/compat.h | 29 ++++++++++++++
arch/riscv/include/asm/elf.h | 84 +++++++++++++++++++++++++++++++++++++++++
arch/riscv/include/asm/hwcap.h | 37 ++++++++++++++++++
arch/riscv/mm/extable.c | 37 ++++++++++++++++++
4 files changed, 187 insertions(+)
create mode 100644 arch/riscv/include/asm/compat.h
create mode 100644 arch/riscv/include/asm/elf.h
create mode 100644 arch/riscv/include/asm/hwcap.h
create mode 100644 arch/riscv/mm/extable.c
diff --git a/arch/riscv/include/asm/compat.h b/arch/riscv/include/asm/compat.h
new file mode 100644
index 000000000000..044aecff8854
--- /dev/null
+++ b/arch/riscv/include/asm/compat.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2012 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_COMPAT_H
+#define __ASM_COMPAT_H
+#ifdef CONFIG_COMPAT
+
+#if defined(CONFIG_64BIT)
+#define COMPAT_UTS_MACHINE "riscv64\0\0"
+#elif defined(CONFIG_32BIT)
+#define COMPAT_UTS_MACHINE "riscv32\0\0"
+#else
+#error "Unknown RISC-V base ISA"
+#endif
+
+#endif /*CONFIG_COMPAT*/
+#endif /*__ASM_COMPAT_H*/
diff --git a/arch/riscv/include/asm/elf.h b/arch/riscv/include/asm/elf.h
new file mode 100644
index 000000000000..a1ef503d616e
--- /dev/null
+++ b/arch/riscv/include/asm/elf.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * 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.
+ */
+
+#ifndef _ASM_RISCV_ELF_H
+#define _ASM_RISCV_ELF_H
+
+#include <uapi/asm/elf.h>
+#include <asm/auxvec.h>
+#include <asm/byteorder.h>
+
+/* TODO: Move definition into include/uapi/linux/elf-em.h */
+#define EM_RISCV 0xF3
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_ARCH EM_RISCV
+
+#ifdef CONFIG_64BIT
+#define ELF_CLASS ELFCLASS64
+#else
+#define ELF_CLASS ELFCLASS32
+#endif
+
+#if defined(__LITTLE_ENDIAN)
+#define ELF_DATA ELFDATA2LSB
+#elif defined(__BIG_ENDIAN)
+#define ELF_DATA ELFDATA2MSB
+#else
+#error "Unknown endianness"
+#endif
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) ((x)->e_machine == EM_RISCV)
+
+#define CORE_DUMP_USE_REGSET
+#define ELF_EXEC_PAGESIZE (PAGE_SIZE)
+
+/*
+ * This is the location that an ET_DYN program is loaded if exec'ed. Typical
+ * use of this is to invoke "./ld.so someprog" to test out a new version of
+ * the loader. We need to make sure that it is out of the way of the program
+ * that it will "exec", and that there is sufficient room for the brk.
+ */
+#define ELF_ET_DYN_BASE ((TASK_SIZE / 3) * 2)
+
+/*
+ * This yields a mask that user programs can use to figure out what
+ * instruction set this CPU supports. This could be done in user space,
+ * but it's not easy, and we've already done it here.
+ */
+#define ELF_HWCAP (elf_hwcap)
+extern unsigned long elf_hwcap;
+
+/*
+ * This yields a string that ld.so will use to load implementation
+ * specific libraries for optimization. This is more specific in
+ * intent than poking at uname or /proc/cpuinfo.
+ */
+#define ELF_PLATFORM (NULL)
+
+#define ARCH_DLINFO \
+do { \
+ NEW_AUX_ENT(AT_SYSINFO_EHDR, \
+ (elf_addr_t)current->mm->context.vdso); \
+} while (0)
+
+
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
+struct linux_binprm;
+extern int arch_setup_additional_pages(struct linux_binprm *bprm,
+ int uses_interp);
+
+#endif /* _ASM_RISCV_ELF_H */
diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h
new file mode 100644
index 000000000000..8a4ed7bbcbea
--- /dev/null
+++ b/arch/riscv/include/asm/hwcap.h
@@ -0,0 +1,37 @@
+/*
+ * Copied from arch/arm64/include/asm/hwcap.h
+ *
+ * Copyright (C) 2012 ARM Ltd.
+ * 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 version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_HWCAP_H
+#define __ASM_HWCAP_H
+
+#include <uapi/asm/hwcap.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * This yields a mask that user programs can use to figure out what
+ * instruction set this cpu supports.
+ */
+#define ELF_HWCAP (elf_hwcap)
+
+enum {
+ CAP_HWCAP = 1,
+};
+
+extern unsigned long elf_hwcap;
+#endif
+#endif
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;
+}
--
2.13.5
[toc] | [prev] | [next] | [standalone]
| From | Daniel Lezcano <daniel.lezcano@linaro.org> |
|---|---|
| Date | 2017-09-13 20:20 +0200 |
| Subject | Re: [PATCH v8 10/18] RISC-V: Init and Halt Code |
| Message-ID | <upkqt-2qd-3@gated-at.bofh.it> |
| In reply to | #1731250 |
On 12/09/2017 23:57, Palmer Dabbelt wrote:
> This contains the various __init C functions, the initial assembly
> kernel entry point, and the code to reset the system. When a file was
> init-related this patch contains the entire file.
>
> Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com>
> ---
[ ... ]
> diff --git a/arch/riscv/kernel/time.c b/arch/riscv/kernel/time.c
> new file mode 100644
> index 000000000000..8362a0e17a1a
> --- /dev/null
> +++ b/arch/riscv/kernel/time.c
> @@ -0,0 +1,78 @@
> +/*
> + * 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/delay.h>
> +#include <linux/timer_riscv.h>
> +
> +#include <asm/sbi.h>
> +
> +unsigned long riscv_timebase;
> +
> +DECLARE_PER_CPU(struct clock_event_device, riscv_clock_event);
> +
> +static int next_event(unsigned long delta, struct clock_event_device *ce)
> +{
> + /*
> + * time_init() allocates a timer for each CPU. Since we're writing the
> + * timer comparison register here we can't allow the timers to cross
> + * harts.
> + */
> + BUG_ON(ce != this_cpu_ptr(&riscv_clock_event));
> + sbi_set_timer(get_cycles64() + delta);
> + return 0;
> +}
> +
> +static unsigned long long rdtime(struct clocksource *cs)
> +{
> + /*
> + * It's guarnteed that all the timers across all the harts are
> + * synchronized within one tick of each other, so while this could
> + * technically go backwards when hopping between CPUs, practically it
> + * won't happen.
> + */
> + return get_cycles64();
> +}
> +
> +void riscv_timer_interrupt(void)
> +{
> + struct clock_event_device *evdev = this_cpu_ptr(&riscv_clock_event);
> +
> + evdev->event_handler(evdev);
> +}
> +
> +void __init init_clockevent(void)
> +{
> + int cpu_id = smp_processor_id();
> +
> + timer_riscv_init(cpu_id, riscv_timebase, &next_event);
> + csr_set(sie, SIE_STIE);
> +}
> +
> +void __init time_init(void)
> +{
> + struct device_node *cpu;
> + u32 prop;
> +
> + cpu = of_find_node_by_path("/cpus");
> + if (!cpu || of_property_read_u32(cpu, "timebase-frequency", &prop))
> + panic(KERN_WARNING "RISC-V system with no 'timebase-frequency' in DTS\n");
> + riscv_timebase = prop;
> +
> + lpj_fine = riscv_timebase / HZ;
> +
> + clocksource_riscv_init(&rdtime);
> + init_clockevent();
> +}
All this code must go in the timer side and use the TIMER_OF_DECLARE
macro with the proper wrappers.
Where is the request_per_cpu_interrupt()?
What is this riscv_timer_interrupt() signature?
Where is get_cycles64() ?
The timer driver should be self-contained and not spread across
different places, it is very difficult to review it.
[ ... ]
--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
[toc] | [prev] | [next] | [standalone]
| From | Dmitriy Cherkasov <dmitriy@oss-tech.org> |
|---|---|
| Date | 2017-09-16 08:30 +0200 |
| Subject | Re: [PATCH v8 10/18] RISC-V: Init and Halt Code |
| Message-ID | <uqeM2-655-11@gated-at.bofh.it> |
| In reply to | #1731766 |
On 09/13/2017 11:15 AM, Daniel Lezcano wrote: > > All this code must go in the timer side and use the TIMER_OF_DECLARE > macro with the proper wrappers. Hi, thanks for the feedback. Agreed. I'll clean this up. > > Where is the request_per_cpu_interrupt()? > > What is this riscv_timer_interrupt() signature? This arch defines a separate exception type for local timer interrupts. Currently the interrupt controller driver checks the trap cause register, determines that it's a timer, and calls the handler directly. To make this go through the interrupt subsystem, this driver would need to be reworked. > > Where is get_cycles64() ? This is in asm/timex.h. Should this be split into a separate asm header ala arm64? > > The timer driver should be self-contained and not spread across > different places, it is very difficult to review it. > > [ ... ] > Agreed, thanks again for reviewing it anyway :)
[toc] | [prev] | [next] | [standalone]
| From | Daniel Lezcano <daniel.lezcano@linaro.org> |
|---|---|
| Date | 2017-09-16 15:30 +0200 |
| Subject | Re: [PATCH v8 10/18] RISC-V: Init and Halt Code |
| Message-ID | <uqlku-26H-9@gated-at.bofh.it> |
| In reply to | #1733216 |
On 16/09/2017 08:23, Dmitriy Cherkasov wrote: > On 09/13/2017 11:15 AM, Daniel Lezcano wrote: >> >> All this code must go in the timer side and use the TIMER_OF_DECLARE >> macro with the proper wrappers. > > Hi, thanks for the feedback. > > Agreed. I'll clean this up. > >> >> Where is the request_per_cpu_interrupt()? >> >> What is this riscv_timer_interrupt() signature? > > This arch defines a separate exception type for local timer interrupts. > Currently the interrupt controller driver checks the trap cause > register, determines that it's a timer, and calls the handler directly. > To make this go through the interrupt subsystem, this driver would need > to be reworked. > >> >> Where is get_cycles64() ? > > This is in asm/timex.h. Should this be split into a separate asm header > ala arm64? No, it is fine but may be it is get_cycles(), no get_cycles64(), right? >> The timer driver should be self-contained and not spread across >> different places, it is very difficult to review it. >> >> [ ... ] >> > > Agreed, thanks again for reviewing it anyway :) Ok, thanks. -- Daniel -- <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook | <http://twitter.com/#!/linaroorg> Twitter | <http://www.linaro.org/linaro-blog/> Blog
[toc] | [prev] | [next] | [standalone]
| From | Dmitriy Cherkasov <dmitriy@oss-tech.org> |
|---|---|
| Date | 2017-09-16 23:40 +0200 |
| Subject | Re: [PATCH v8 10/18] RISC-V: Init and Halt Code |
| Message-ID | <uqsYF-7fL-3@gated-at.bofh.it> |
| In reply to | #1733283 |
On 09/16/2017 06:28 AM, Daniel Lezcano wrote: > On 16/09/2017 08:23, Dmitriy Cherkasov wrote: >> On 09/13/2017 11:15 AM, Daniel Lezcano wrote: >>> >>> Where is get_cycles64() ? >> >> This is in asm/timex.h. Should this be split into a separate asm header >> ala arm64? > > No, it is fine but may be it is get_cycles(), no get_cycles64(), right? > get_cycles() returns a 32 or 64-bit value depending on machine register width, using one assembly instruction to retrieve it. get_cycles64() always returns a 64-bit value at the expense of a few more instructions on 32-bit systems.
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web