* Re: [PATCH v3 17/33] nds32: VDSO support
From: Mark Rutland @ 2017-12-08 10:21 UTC (permalink / raw)
To: Greentime Hu
Cc: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
marc.zyngier, robh+dt, netdev, deanbo422, devicetree, viro,
dhowells, will.deacon, daniel.lezcano, linux-serial,
geert.uytterhoeven, linus.walleij, greg, Vincent Chen
In-Reply-To: <921ccfa97c4c13f12c7b22b9554f52dcce51f87e.1512723245.git.green.hu@gmail.com>
On Fri, Dec 08, 2017 at 05:12:00PM +0800, Greentime Hu wrote:
> From: Greentime Hu <greentime@andestech.com>
>
> This patch adds VDSO support. The VDSO code is currently used for
> sys_rt_sigreturn() and optimised gettimeofday() (using the SoC timer counter).
[...]
> +static int grab_timer_node_info(void)
> +{
> + struct device_node *timer_node;
> +
> + timer_node = of_find_node_by_name(NULL, "timer");
Please use a compatible string, rather than matching the timer by name.
It's plausible that you have multiple nodes called "timer" in the DT,
under different parent nodes, and this might not be the device you
think it is. I see your dt in patch 24 has two timer nodes.
It would be best if your clocksource driver exposed some stuct that you
looked at here, so that you're guaranteed to user the same device.
> + of_property_read_u32(timer_node, "cycle-count-offset",
> + &vdso_data->cycle_count_offset);
> + vdso_data->cycle_count_down =
> + of_property_read_bool(timer_node, "cycle-count-down");
... and then you'd only need to parse these in one place, too.
IIUC these are proeprties for the atcpit device, which has no
documentation or driver in this series.
So I'm rather confused as to what's going on here.
> + return of_address_to_resource(timer_node, 0, &timer_res);
> +}
> +int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
> +{
> + /*Map timer to user space */
> + vdso_base += PAGE_SIZE;
> + prot = __pgprot(_PAGE_V | _PAGE_M_UR_KR | _PAGE_D |
> + _PAGE_G | _PAGE_C_DEV);
> + ret = io_remap_pfn_range(vma, vdso_base, timer_res.start >> PAGE_SHIFT,
> + PAGE_SIZE, prot);
> + if (ret)
> + goto up_fail;
Maybe this is fine, but it looks a bit suspicious.
Is it safe to map IO memory to a userspace process like this?
In general that isn't safe, since userspace could access other registers
(if those exist), perform accesses that change the state of hardware, or
make unsupported access types (e.g. unaligned, atomic) that result in
errors the kernel can't handle.
Does none of that apply here?
Thanks,
Mark.
^ permalink raw reply
* Re: [PATCH 2/2] serial: tegra: Fix a typo in a comment line
From: Laxman Dewangan @ 2017-12-08 9:37 UTC (permalink / raw)
To: SF Markus Elfring, linux-serial-u79uwXL29TY76Z2rM5mHXA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA, Greg Kroah-Hartman,
Jiri Slaby, Jonathan Hunter, Thierry Reding
Cc: LKML, kernel-janitors-u79uwXL29TY76Z2rM5mHXA,
trivial-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <2b7ff65b-dcb8-996b-1f34-f1bff28bb515-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
On Friday 08 December 2017 01:51 AM, SF Markus Elfring wrote:
> From: Markus Elfring <elfring-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
> Date: Thu, 7 Dec 2017 21:06:25 +0100
>
> Delete a duplicate character in a word of this description.
>
Acked-by: Laxman Dewangan <ldewangan-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
^ permalink raw reply
* Re: [PATCH 1/2] serial: tegra: Delete an error message for a failed memory allocation in tegra_uart_probe()
From: Laxman Dewangan @ 2017-12-08 9:37 UTC (permalink / raw)
To: SF Markus Elfring, linux-serial-u79uwXL29TY76Z2rM5mHXA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA, Greg Kroah-Hartman,
Jiri Slaby, Jonathan Hunter, Thierry Reding
Cc: LKML, kernel-janitors-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <aee3d79d-a59e-a3fd-6c6b-45ee46132cc6-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
On Friday 08 December 2017 01:49 AM, SF Markus Elfring wrote:
> From: Markus Elfring <elfring-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
> Date: Thu, 7 Dec 2017 21:00:05 +0100
>
> Omit an extra message for a memory allocation failure in this function.
>
> This issue was detected by using the Coccinelle software.
>
Acked-by: Laxman Dewangan <ldewangan-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
^ permalink raw reply
* [PATCH v3 33/33] net: faraday add nds32 support.
From: Greentime Hu @ 2017-12-08 9:12 UTC (permalink / raw)
To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
marc.zyngier, robh+dt, netdev, deanbo422, devicetree, viro,
dhowells, will.deacon, daniel.lezcano, linux-serial,
geert.uytterhoeven, linus.walleij, mark.rutland, greg
Cc: green.hu
In-Reply-To: <cover.1512723245.git.green.hu@gmail.com>
From: Greentime Hu <greentime@andestech.com>
This patch is used to support nds32 architecture to use these faraday
mac IP.
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
drivers/net/ethernet/faraday/Kconfig | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/faraday/Kconfig b/drivers/net/ethernet/faraday/Kconfig
index 040c7f1..1bdaffc 100644
--- a/drivers/net/ethernet/faraday/Kconfig
+++ b/drivers/net/ethernet/faraday/Kconfig
@@ -5,7 +5,7 @@
config NET_VENDOR_FARADAY
bool "Faraday devices"
default y
- depends on ARM
+ depends on ARM || NDS32 || COMPILE_TEST
---help---
If you have a network (Ethernet) card belonging to this class, say Y.
@@ -18,7 +18,7 @@ if NET_VENDOR_FARADAY
config FTMAC100
tristate "Faraday FTMAC100 10/100 Ethernet support"
- depends on ARM
+ depends on ARM || NDS32 || COMPILE_TEST
select MII
---help---
This driver supports the FTMAC100 10/100 Ethernet controller
@@ -27,7 +27,7 @@ config FTMAC100
config FTGMAC100
tristate "Faraday FTGMAC100 Gigabit Ethernet support"
- depends on ARM
+ depends on ARM || NDS32 || COMPILE_TEST
select PHYLIB
---help---
This driver supports the FTGMAC100 Gigabit Ethernet controller
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 32/33] irqchip: Andestech Internal Vector Interrupt Controller driver
From: Greentime Hu @ 2017-12-08 9:12 UTC (permalink / raw)
To: greentime-MUIXKm3Oiri1Z/+hSey0Gg,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, arnd-r2nGTMty4D4,
linux-arch-u79uwXL29TY76Z2rM5mHXA, tglx-hfZtesqFncYOwBW4kG4KsQ,
jason-NLaQJdtUoK4Be96aLqz0jA, marc.zyngier-5wv7dgnIgG8,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, netdev-u79uwXL29TY76Z2rM5mHXA,
deanbo422-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA,
viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
dhowells-H+wXaHxf7aLQT0dZR+AlfA, will.deacon-5wv7dgnIgG8,
daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A,
linux-serial-u79uwXL29TY76Z2rM5mHXA,
geert.uytterhoeven-Re5JQEeQqe8AvxtiuMwx3w,
linus.walleij-QSEj5FYQhm4dnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
greg-U8xfFu+wG4EAvxtiuMwx3w
Cc: green.hu-Re5JQEeQqe8AvxtiuMwx3w, Rick Chen
In-Reply-To: <cover.1512723245.git.green.hu-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
From: Greentime Hu <greentime-MUIXKm3Oiri1Z/+hSey0Gg@public.gmane.org>
This patch adds the Andestech Internal Vector Interrupt Controller
driver. You can find the spec here. Ch4.9 of AndeStar SPA V3 Manual.
http://www.andestech.com/product.php?cls=9
Signed-off-by: Rick Chen <rick-MUIXKm3Oiri1Z/+hSey0Gg@public.gmane.org>
Signed-off-by: Greentime Hu <greentime-MUIXKm3Oiri1Z/+hSey0Gg@public.gmane.org>
---
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-ativic32.c | 120 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 121 insertions(+)
create mode 100644 drivers/irqchip/irq-ativic32.c
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index b842dfd..201ca9f 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -80,3 +80,4 @@ 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_IRQ_UNIPHIER_AIDET) += irq-uniphier-aidet.o
+obj-$(CONFIG_NDS32) += irq-ativic32.o
diff --git a/drivers/irqchip/irq-ativic32.c b/drivers/irqchip/irq-ativic32.c
new file mode 100644
index 0000000..709b65c
--- /dev/null
+++ b/drivers/irqchip/irq-ativic32.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip.h>
+#include <nds32_intrinsic.h>
+
+static void ativic32_ack_irq(struct irq_data *data)
+{
+ __nds32__mtsr_dsb(BIT(data->hwirq), NDS32_SR_INT_PEND2);
+}
+
+static void ativic32_mask_irq(struct irq_data *data)
+{
+ unsigned long int_mask2 = __nds32__mfsr(NDS32_SR_INT_MASK2);
+ __nds32__mtsr_dsb(int_mask2 & (~(BIT(data->hwirq))), NDS32_SR_INT_MASK2);
+}
+
+static void ativic32_unmask_irq(struct irq_data *data)
+{
+ unsigned long int_mask2 = __nds32__mfsr(NDS32_SR_INT_MASK2);
+ __nds32__mtsr_dsb(int_mask2 | (BIT(data->hwirq)), NDS32_SR_INT_MASK2);
+}
+
+static struct irq_chip ativic32_chip = {
+ .name = "ativic32",
+ .irq_ack = ativic32_ack_irq,
+ .irq_mask = ativic32_mask_irq,
+ .irq_unmask = ativic32_unmask_irq,
+};
+
+static unsigned int __initdata nivic_map[6] = { 6, 2, 10, 16, 24, 32 };
+
+static struct irq_domain *root_domain;
+static int ativic32_irq_domain_map(struct irq_domain *id, unsigned int virq,
+ irq_hw_number_t hw)
+{
+
+ unsigned long int_trigger_type;
+ u32 type;
+ struct irq_data *irq_data;
+ int_trigger_type = __nds32__mfsr(NDS32_SR_INT_TRIGGER);
+ irq_data = irq_get_irq_data(virq);
+ if (!irq_data)
+ return -EINVAL;
+
+ if (int_trigger_type & (BIT(hw))) {
+ irq_set_chip_and_handler(virq, &ativic32_chip, handle_edge_irq);
+ type = IRQ_TYPE_EDGE_RISING;
+ } else {
+ irq_set_chip_and_handler(virq, &ativic32_chip, handle_level_irq);
+ type = IRQ_TYPE_LEVEL_HIGH;
+ }
+
+ irqd_set_trigger_type(irq_data, type);
+ return 0;
+}
+
+static struct irq_domain_ops ativic32_ops = {
+ .map = ativic32_irq_domain_map,
+ .xlate = irq_domain_xlate_onecell
+};
+
+static irq_hw_number_t get_intr_src(void)
+{
+ return ((__nds32__mfsr(NDS32_SR_ITYPE) & ITYPE_mskVECTOR) >> ITYPE_offVECTOR)
+ - NDS32_VECTOR_offINTERRUPT;
+}
+
+asmlinkage void asm_do_IRQ(struct pt_regs *regs)
+{
+ irq_hw_number_t hwirq = get_intr_src();
+ handle_domain_irq(root_domain, hwirq, regs);
+}
+
+int __init ativic32_init_irq(struct device_node *node, struct device_node *parent)
+{
+ unsigned long int_vec_base, nivic, nr_ints;
+
+ if (WARN(parent, "non-root ativic32 are not supported"))
+ return -EINVAL;
+
+ int_vec_base = __nds32__mfsr(NDS32_SR_IVB);
+
+ if (((int_vec_base & IVB_mskIVIC_VER) >> IVB_offIVIC_VER) == 0)
+ panic("Unable to use atcivic32 for this cpu.\n");
+
+ nivic = (int_vec_base & IVB_mskNIVIC) >> IVB_offNIVIC;
+ if (nivic >= ARRAY_SIZE(nivic_map))
+ panic("The number of input for ativic32 is not supported.\n");
+
+ nr_ints = nivic_map[nivic];
+
+ root_domain = irq_domain_add_linear(node, nr_ints,
+ &ativic32_ops, NULL);
+
+ if (!root_domain)
+ panic("%s: unable to create IRQ domain\n", node->full_name);
+
+ return 0;
+}
+IRQCHIP_DECLARE(ativic32, "andestech,ativic32", ativic32_init_irq);
--
1.7.9.5
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v3 31/33] dt-bindings: interrupt-controller: Andestech Internal Vector Interrupt Controller
From: Greentime Hu @ 2017-12-08 9:12 UTC (permalink / raw)
To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
marc.zyngier, robh+dt, netdev, deanbo422, devicetree, viro,
dhowells, will.deacon, daniel.lezcano, linux-serial,
geert.uytterhoeven, linus.walleij, mark.rutland, greg
Cc: green.hu, Rick Chen
In-Reply-To: <cover.1512723245.git.green.hu@gmail.com>
From: Greentime Hu <greentime@andestech.com>
This patch adds an irqchip driver document for the Andestech Internal Vector
Interrupt Controller.
Signed-off-by: Rick Chen <rick@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
.../interrupt-controller/andestech,ativic32.txt | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
create mode 100644 Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt
diff --git a/Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt b/Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt
new file mode 100644
index 0000000..f4b4193
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt
@@ -0,0 +1,19 @@
+* Andestech Internal Vector Interrupt Controller
+
+The Internal Vector Interrupt Controller (IVIC) is a basic interrupt controller
+suitable for a simpler SoC platform not requiring a more sophisticated and
+bigger External Vector Interrupt Controller.
+
+
+Main node required properties:
+
+- compatible : should at least contain "andestech,ativic32".
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells: 1 cells and refer to interrupt-controller/interrupts
+
+Examples:
+ intc: interrupt-controller {
+ compatible = "andestech,ativic32";
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 30/33] dt-bindings: nds32 SoC Bindings
From: Greentime Hu @ 2017-12-08 9:12 UTC (permalink / raw)
To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
marc.zyngier, robh+dt, netdev, deanbo422, devicetree, viro,
dhowells, will.deacon, daniel.lezcano, linux-serial,
geert.uytterhoeven, linus.walleij, mark.rutland, greg
Cc: green.hu
In-Reply-To: <cover.1512723245.git.green.hu@gmail.com>
From: Greentime Hu <greentime@andestech.com>
This patch adds nds32 SoC(AE3XX and AG101P) binding documents.
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
.../devicetree/bindings/nds32/andestech-boards | 40 ++++++++++++++++++++
1 file changed, 40 insertions(+)
create mode 100644 Documentation/devicetree/bindings/nds32/andestech-boards
diff --git a/Documentation/devicetree/bindings/nds32/andestech-boards b/Documentation/devicetree/bindings/nds32/andestech-boards
new file mode 100644
index 0000000..f5d7569
--- /dev/null
+++ b/Documentation/devicetree/bindings/nds32/andestech-boards
@@ -0,0 +1,40 @@
+Andestech(nds32) AE3XX Platform
+-----------------------------------------------------------------------------
+The AE3XX prototype demonstrates the AE3XX example platform on the FPGA. It
+is composed of one Andestech(nds32) processor and AE3XX.
+
+Required properties (in root node):
+- compatible = "andestech,ae3xx";
+
+Example:
+/dts-v1/;
+/ {
+ compatible = "andestech,ae3xx";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&intc>;
+};
+
+Andestech(nds32) AG101P Platform
+-----------------------------------------------------------------------------
+AG101P is a generic SoC Platform IP that works with any of Andestech(nds32)
+processors to provide a cost-effective and high performance solution for
+majority of embedded systems in variety of application domains. Users may
+simply attach their IP on one of the system buses together with certain glue
+logics to complete a SoC solution for a specific application. With
+comprehensive simulation and design environments, users may evaluate the
+system performance of their applications and track bugs of their designs
+efficiently. The optional hardware development platform further provides real
+system environment for early prototyping and software/hardware co-development.
+
+Required properties (in root node):
+ compatible = "andestech,ag101p";
+
+Example:
+/dts-v1/;
+/ {
+ compatible = "andestech,ag101p";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&intc>;
+};
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 29/33] dt-bindings: nds32 CPU Bindings
From: Greentime Hu @ 2017-12-08 9:12 UTC (permalink / raw)
To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
marc.zyngier, robh+dt, netdev, deanbo422, devicetree, viro,
dhowells, will.deacon, daniel.lezcano, linux-serial,
geert.uytterhoeven, linus.walleij, mark.rutland, greg
Cc: green.hu, Vincent Chen, Rick Chen, Zong Li
In-Reply-To: <cover.1512723245.git.green.hu@gmail.com>
From: Greentime Hu <greentime@andestech.com>
This patch adds nds32 CPU binding documents.
Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Rick Chen <rick@andestech.com>
Signed-off-by: Zong Li <zong@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
Documentation/devicetree/bindings/nds32/cpus.txt | 37 ++++++++++++++++++++++
1 file changed, 37 insertions(+)
create mode 100644 Documentation/devicetree/bindings/nds32/cpus.txt
diff --git a/Documentation/devicetree/bindings/nds32/cpus.txt b/Documentation/devicetree/bindings/nds32/cpus.txt
new file mode 100644
index 0000000..9a52937
--- /dev/null
+++ b/Documentation/devicetree/bindings/nds32/cpus.txt
@@ -0,0 +1,37 @@
+* Andestech Processor Binding
+
+This binding specifies what properties must be available in the device tree
+representation of a Andestech Processor Core, which is the root node in the
+tree.
+
+Required properties:
+
+ - compatible:
+ Usage: required
+ Value type: <string>
+ Definition: should be one of:
+ "andestech,n13"
+ "andestech,n15"
+ "andestech,d15"
+ "andestech,n10"
+ "andestech,d10"
+ "andestech,nds32v3"
+ - device_type
+ Usage: required
+ Value type: <string>
+ Definition: must be "cpu"
+ - reg: Contains CPU index.
+ - clock-frequency: Contains the clock frequency for CPU, in Hz.
+
+* Examples
+
+/ {
+ cpus {
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "andestech,n13", "andestech,nds32v3";
+ reg = <0x0>;
+ clock-frequency = <60000000>
+ };
+ };
+};
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 28/33] MAINTAINERS: Add nds32
From: Greentime Hu @ 2017-12-08 9:12 UTC (permalink / raw)
To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
marc.zyngier, robh+dt, netdev, deanbo422, devicetree, viro,
dhowells, will.deacon, daniel.lezcano, linux-serial,
geert.uytterhoeven, linus.walleij, mark.rutland, greg
Cc: green.hu
In-Reply-To: <cover.1512723245.git.green.hu@gmail.com>
From: Greentime Hu <greentime@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
MAINTAINERS | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 2f4e462..20284c8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -857,6 +857,17 @@ X: drivers/iio/*/adjd*
F: drivers/staging/iio/*/ad*
F: drivers/staging/iio/trigger/iio-trig-bfin-timer.c
+ANDES ARCHITECTURE
+M: Greentime Hu <green.hu@gmail.com>
+M: Vincent Chen <deanbo422@gmail.com>
+T: git https://github.com/andestech/linux.git
+S: Supported
+F: arch/nds32
+F: Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt
+F: Documentation/devicetree/bindings/nds32
+K: nds32
+N: nds32
+
ANDROID CONFIG FRAGMENTS
M: Rob Herring <robh@kernel.org>
S: Supported
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 27/33] nds32: Build infrastructure
From: Greentime Hu @ 2017-12-08 9:12 UTC (permalink / raw)
To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
marc.zyngier, robh+dt, netdev, deanbo422, devicetree, viro,
dhowells, will.deacon, daniel.lezcano, linux-serial,
geert.uytterhoeven, linus.walleij, mark.rutland, greg
Cc: green.hu, Vincent Chen
In-Reply-To: <cover.1512723245.git.green.hu@gmail.com>
From: Greentime Hu <greentime@andestech.com>
This patch adds Makefile, Kconfig and vmlinux.lds.S files required for building
an nds32 kernel.
Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
arch/nds32/Kconfig | 108 ++++++++++++++++++++++++
arch/nds32/Kconfig.cpu | 161 ++++++++++++++++++++++++++++++++++++
arch/nds32/Makefile | 66 +++++++++++++++
arch/nds32/boot/Makefile | 15 ++++
arch/nds32/include/asm/Kbuild | 53 ++++++++++++
arch/nds32/include/uapi/asm/Kbuild | 28 +++++++
arch/nds32/kernel/Makefile | 23 ++++++
arch/nds32/kernel/vmlinux.lds.S | 70 ++++++++++++++++
arch/nds32/mm/Makefile | 7 ++
9 files changed, 531 insertions(+)
create mode 100644 arch/nds32/Kconfig
create mode 100644 arch/nds32/Kconfig.cpu
create mode 100644 arch/nds32/Makefile
create mode 100644 arch/nds32/boot/Makefile
create mode 100644 arch/nds32/include/asm/Kbuild
create mode 100644 arch/nds32/include/uapi/asm/Kbuild
create mode 100644 arch/nds32/kernel/Makefile
create mode 100644 arch/nds32/kernel/vmlinux.lds.S
create mode 100644 arch/nds32/mm/Makefile
diff --git a/arch/nds32/Kconfig b/arch/nds32/Kconfig
new file mode 100644
index 0000000..c83506e
--- /dev/null
+++ b/arch/nds32/Kconfig
@@ -0,0 +1,108 @@
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.txt.
+#
+
+config NDS32
+ def_bool y
+ select ARCH_HAS_RAW_COPY_USER
+ select ARCH_WANT_FRAME_POINTERS if FTRACE
+ select ARCH_WANT_IPC_PARSE_VERSION
+ select CLKSRC_MMIO
+ select CLONE_BACKWARDS
+ select COMMON_CLK
+ select TIMER_OF
+ select FRAME_POINTER
+ select GENERIC_ATOMIC64
+ select GENERIC_CPU_DEVICES
+ select GENERIC_CLOCKEVENTS
+ select GENERIC_IRQ_CHIP
+ select GENERIC_IRQ_PROBE
+ select GENERIC_IRQ_SHOW
+ select GENERIC_STRNCPY_FROM_USER
+ select GENERIC_STRNLEN_USER
+ select GENERIC_TIME_VSYSCALL
+ select HANDLE_DOMAIN_IRQ
+ select HAVE_ARCH_TRACEHOOK
+ select HAVE_DEBUG_KMEMLEAK
+ select HAVE_MEMBLOCK
+ select HAVE_REGS_AND_STACK_ACCESS_API
+ select IRQ_DOMAIN
+ select LOCKDEP_SUPPORT
+ select MODULES_USE_ELF_RELA
+ select OF
+ select OF_EARLY_FLATTREE
+ select NO_BOOTMEM
+ select NO_IOPORT_MAP
+ select RTC_LIB
+ select THREAD_INFO_IN_TASK
+ help
+ Andes(nds32) Linux support.
+
+config GENERIC_CALIBRATE_DELAY
+ def_bool n
+
+config GENERIC_CSUM
+ def_bool y
+
+config GENERIC_HWEIGHT
+ def_bool y
+
+config GENERIC_LOCKBREAK
+ def_bool y
+ depends on PREEMPT
+
+config RWSEM_GENERIC_SPINLOCK
+ def_bool y
+
+config TRACE_IRQFLAGS_SUPPORT
+ def_bool y
+
+config STACKTRACE_SUPPORT
+ def_bool y
+
+config FIX_EARLYCON_MEM
+ def_bool y
+
+config PGTABLE_LEVELS
+ default 2
+
+source "init/Kconfig"
+
+menu "System Type"
+source "arch/nds32/Kconfig.cpu"
+config NR_CPUS
+ int
+ default 1
+
+config MMU
+ def_bool y
+
+config NDS32_BUILTIN_DTB
+ string "Builtin DTB"
+ default ""
+ help
+ User can use it to specify the dts of the SoC
+endmenu
+
+menu "Kernel Features"
+source "kernel/Kconfig.preempt"
+source "mm/Kconfig"
+source "kernel/Kconfig.hz"
+endmenu
+
+menu "Executable file formats"
+source "fs/Kconfig.binfmt"
+endmenu
+
+source "net/Kconfig"
+source "drivers/Kconfig"
+source "fs/Kconfig"
+
+menu "Kernel hacking"
+source "lib/Kconfig.debug"
+endmenu
+
+source "security/Kconfig"
+source "crypto/Kconfig"
+source "lib/Kconfig"
diff --git a/arch/nds32/Kconfig.cpu b/arch/nds32/Kconfig.cpu
new file mode 100644
index 0000000..6c9fbdc
--- /dev/null
+++ b/arch/nds32/Kconfig.cpu
@@ -0,0 +1,161 @@
+comment "Processor Features"
+
+config CPU_BIG_ENDIAN
+ bool "Big endian"
+
+config CPU_LITTLE_ENDIAN
+ def_bool !CPU_BIG_ENDIAN
+
+config HWZOL
+ bool "hardware zero overhead loop support"
+ depends on CPU_D10 || CPU_D15
+ default n
+ help
+ A set of Zero-Overhead Loop mechanism is provided to reduce the
+ instruction fetch and execution overhead of loop-control instructions.
+ It will save 3 registers($LB, $LC, $LE) for context saving if say Y.
+ You don't need to save these registers if you can make sure your user
+ program doesn't use these registers.
+
+ If unsure, say N.
+
+config CPU_CACHE_ALIASING
+ bool "Aliasing cache"
+ depends on CPU_N10 || CPU_D10 || CPU_N13 || CPU_V3
+ default y
+ help
+ If this CPU is using VIPT data cache and its cache way size is larger
+ than page size, say Y. If it is using PIPT data cache, say N.
+
+ If unsure, say Y.
+
+choice
+ prompt "CPU type"
+ default CPU_V3
+config CPU_N15
+ bool "AndesCore N15"
+config CPU_N13
+ bool "AndesCore N13"
+ select CPU_CACHE_ALIASING if ANDES_PAGE_SIZE_4KB
+config CPU_N10
+ bool "AndesCore N10"
+ select CPU_CACHE_ALIASING
+config CPU_D15
+ bool "AndesCore D15"
+config CPU_D10
+ bool "AndesCore D10"
+ select CPU_CACHE_ALIASING
+config CPU_V3
+ bool "AndesCore v3 compatible"
+ select ANDES_PAGE_SIZE_8KB
+endchoice
+choice
+ prompt "Paging -- page size "
+ default ANDES_PAGE_SIZE_4KB
+config ANDES_PAGE_SIZE_4KB
+ bool "use 4KB page size"
+config ANDES_PAGE_SIZE_8KB
+ bool "use 8KB page size"
+endchoice
+
+config CPU_ICACHE_DISABLE
+ bool "Disable I-Cache"
+ help
+ Say Y here to disable the processor instruction cache. Unless
+ you have a reason not to or are unsure, say N.
+
+config CPU_DCACHE_DISABLE
+ bool "Disable D-Cache"
+ help
+ Say Y here to disable the processor data cache. Unless
+ you have a reason not to or are unsure, say N.
+
+config CPU_DCACHE_WRITETHROUGH
+ bool "Force write through D-cache"
+ depends on !CPU_DCACHE_DISABLE
+ help
+ Say Y here to use the data cache in writethrough mode. Unless you
+ specifically require this or are unsure, say N.
+
+config WBNA
+ bool "WBNA"
+ default n
+ help
+ Say Y here to enable write-back memory with no-write-allocation policy.
+
+config ALIGNMENT_TRAP
+ bool "Kernel support unaligned access handling by sw"
+ depends on PROC_FS
+ default n
+ help
+ Andes processors cannot fetch/store information which is not
+ naturally aligned on the bus, i.e., a 4 byte fetch must start at an
+ address divisible by 4. On 32-bit Andes processors, these non-aligned
+ fetch/store instructions will be emulated in software if you say
+ here, which has a severe performance impact. With an IP-only
+ configuration it is safe to say N, otherwise say Y.
+
+config HW_SUPPORT_UNALIGNMENT_ACCESS
+ bool "Kernel support unaligned access handling by hw"
+ depends on !ALIGNMENT_TRAP
+ default n
+ help
+ Andes processors load/store world/half-word instructions can access
+ unaligned memory locations without generating the Data Alignment
+ Check exceptions. With an IP-only configuration it is safe to say N,
+ otherwise say Y.
+
+config HIGHMEM
+ bool "High Memory Support"
+ depends on MMU && CPU_CACHE_NONALIASING
+ help
+ The address space of Andes processors is only 4 Gigabytes large
+ and it has to accommodate user address space, kernel address
+ space as well as some memory mapped IO. That means that, if you
+ have a large amount of physical memory and/or IO, not all of the
+ memory can be "permanently mapped" by the kernel. The physical
+ memory that is not permanently mapped is called "high memory".
+
+ Depending on the selected kernel/user memory split, minimum
+ vmalloc space and actual amount of RAM, you may not need this
+ option which should result in a slightly faster kernel.
+
+ If unsure, say N.
+
+config CACHE_L2
+ bool "Support L2 cache"
+ default y
+ help
+ Say Y here to enable L2 cache if your SoC are integrated with L2CC.
+ If unsure, say N.
+
+menu "Memory configuration"
+
+choice
+ prompt "Memory split"
+ depends on MMU
+ default VMSPLIT_3G
+ help
+ Select the desired split between kernel and user memory.
+
+ If you are not absolutely sure what you are doing, leave this
+ option alone!
+
+ config VMSPLIT_3G
+ bool "3G/1G user/kernel split"
+ config VMSPLIT_3G_OPT
+ bool "3G/1G user/kernel split (for full 1G low memory)"
+ config VMSPLIT_2G
+ bool "2G/2G user/kernel split"
+ config VMSPLIT_1G
+ bool "1G/3G user/kernel split"
+endchoice
+
+config PAGE_OFFSET
+ hex
+ default 0x40000000 if VMSPLIT_1G
+ default 0x80000000 if VMSPLIT_2G
+ default 0xB0000000 if VMSPLIT_3G_OPT
+ default 0xC0000000
+
+endmenu
diff --git a/arch/nds32/Makefile b/arch/nds32/Makefile
new file mode 100644
index 0000000..54b4de9
--- /dev/null
+++ b/arch/nds32/Makefile
@@ -0,0 +1,66 @@
+LDFLAGS_vmlinux := --no-undefined -X
+OBJCOPYFLAGS := -O binary -R .note -R .note.gnu.build-id -R .comment -S
+
+KBUILD_DEFCONFIG := defconfig
+
+comma = ,
+
+KBUILD_CFLAGS +=-mno-sched-prolog-epilog -mcmodel=large
+
+KBUILD_CFLAGS +=$(arch-y) $(tune-y)
+KBUILD_AFLAGS +=$(arch-y) $(tune-y)
+
+#Default value
+head-y := arch/nds32/kernel/head.o
+textaddr-y := $(CONFIG_PAGE_OFFSET)+0xc000
+
+TEXTADDR := $(textaddr-y)
+
+export TEXTADDR
+
+
+# If we have a machine-specific directory, then include it in the build.
+core-y += arch/nds32/kernel/ arch/nds32/mm/
+libs-y += arch/nds32/lib/
+LIBGCC_PATH := \
+ $(shell $(CC) $(KBUILD_CFLAGS) $(KCFLAGS) -print-libgcc-file-name)
+libs-y += $(LIBGCC_PATH)
+
+ifneq '$(CONFIG_NDS32_BUILTIN_DTB)' '""'
+BUILTIN_DTB := y
+else
+BUILTIN_DTB := n
+endif
+
+ifdef CONFIG_CPU_LITTLE_ENDIAN
+KBUILD_CFLAGS += -EL
+else
+KBUILD_CFLAGS += -EB
+endif
+
+boot := arch/nds32/boot
+core-$(BUILTIN_DTB) += $(boot)/dts/
+
+.PHONY: FORCE
+
+Image: vmlinux
+ $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+
+
+PHONY += vdso_install
+vdso_install:
+ $(Q)$(MAKE) $(build)=arch/nds32/kernel/vdso $@
+
+prepare: vdso_prepare
+vdso_prepare: prepare0
+ $(Q)$(MAKE) $(build)=arch/nds32/kernel/vdso include/generated/vdso-offsets.h
+
+CLEAN_FILES += include/asm-nds32/constants.h*
+
+# We use MRPROPER_FILES and CLEAN_FILES now
+archclean:
+ $(Q)$(MAKE) $(clean)=$(boot)
+
+define archhelp
+ echo ' Image - kernel image (arch/$(ARCH)/boot/Image)'
+endef
diff --git a/arch/nds32/boot/Makefile b/arch/nds32/boot/Makefile
new file mode 100644
index 0000000..3f9b86f
--- /dev/null
+++ b/arch/nds32/boot/Makefile
@@ -0,0 +1,15 @@
+targets := Image Image.gz
+
+$(obj)/Image: vmlinux FORCE
+ $(call if_changed,objcopy)
+
+$(obj)/Image.gz: $(obj)/Image FORCE
+ $(call if_changed,gzip)
+
+install: $(obj)/Image
+ $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
+ $(obj)/Image System.map "$(INSTALL_PATH)"
+
+zinstall: $(obj)/Image.gz
+ $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
+ $(obj)/Image.gz System.map "$(INSTALL_PATH)"
diff --git a/arch/nds32/include/asm/Kbuild b/arch/nds32/include/asm/Kbuild
new file mode 100644
index 0000000..8046ca5
--- /dev/null
+++ b/arch/nds32/include/asm/Kbuild
@@ -0,0 +1,53 @@
+generic-y += asm-offsets.h
+generic-y += atomic.h
+generic-y += bitops.h
+generic-y += bitsperlong.h
+generic-y += bug.h
+generic-y += bugs.h
+generic-y += checksum.h
+generic-y += clkdev.h
+generic-y += cmpxchg.h
+generic-y += cmpxchg-local.h
+generic-y += cputime.h
+generic-y += device.h
+generic-y += div64.h
+generic-y += dma.h
+generic-y += emergency-restart.h
+generic-y += errno.h
+generic-y += exec.h
+generic-y += fb.h
+generic-y += fcntl.h
+generic-y += ftrace.h
+generic-y += gpio.h
+generic-y += hardirq.h
+generic-y += hw_irq.h
+generic-y += ioctl.h
+generic-y += ioctls.h
+generic-y += irq.h
+generic-y += irq_regs.h
+generic-y += irq_work.h
+generic-y += kdebug.h
+generic-y += kmap_types.h
+generic-y += kprobes.h
+generic-y += kvm_para.h
+generic-y += limits.h
+generic-y += local.h
+generic-y += mm-arch-hooks.h
+generic-y += mman.h
+generic-y += parport.h
+generic-y += pci.h
+generic-y += percpu.h
+generic-y += preempt.h
+generic-y += sections.h
+generic-y += segment.h
+generic-y += serial.h
+generic-y += shmbuf.h
+generic-y += sizes.h
+generic-y += stat.h
+generic-y += switch_to.h
+generic-y += timex.h
+generic-y += topology.h
+generic-y += trace_clock.h
+generic-y += unaligned.h
+generic-y += user.h
+generic-y += word-at-a-time.h
diff --git a/arch/nds32/include/uapi/asm/Kbuild b/arch/nds32/include/uapi/asm/Kbuild
new file mode 100644
index 0000000..c4dc909
--- /dev/null
+++ b/arch/nds32/include/uapi/asm/Kbuild
@@ -0,0 +1,28 @@
+# UAPI Header export list
+include include/uapi/asm-generic/Kbuild.asm
+
+generic-y += errno.h
+generic-y += ioctl.h
+generic-y += ioctls.h
+generic-y += ipcbuf.h
+generic-y += shmbuf.h
+generic-y += bitsperlong.h
+generic-y += fcntl.h
+generic-y += stat.h
+generic-y += mman.h
+generic-y += msgbuf.h
+generic-y += poll.h
+generic-y += posix_types.h
+generic-y += resource.h
+generic-y += sembuf.h
+generic-y += setup.h
+generic-y += siginfo.h
+generic-y += signal.h
+generic-y += socket.h
+generic-y += sockios.h
+generic-y += swab.h
+generic-y += statfs.h
+generic-y += termbits.h
+generic-y += termios.h
+generic-y += types.h
+generic-y += ucontext.h
diff --git a/arch/nds32/kernel/Makefile b/arch/nds32/kernel/Makefile
new file mode 100644
index 0000000..4279274
--- /dev/null
+++ b/arch/nds32/kernel/Makefile
@@ -0,0 +1,23 @@
+#
+# Makefile for the linux kernel.
+#
+
+CPPFLAGS_vmlinux.lds := -DTEXTADDR=$(TEXTADDR)
+AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR)
+
+# Object file lists.
+
+obj-y := ex-entry.o ex-exit.o ex-scall.o irq.o \
+ process.o ptrace.o setup.o signal.o \
+ sys_nds32.o time.o traps.o cacheinfo.o \
+ dma.o syscall_table.o vdso.o
+
+obj-$(CONFIG_MODULES) += nds32_ksyms.o module.o
+obj-$(CONFIG_STACKTRACE) += stacktrace.o
+obj-$(CONFIG_OF) += devtree.o
+obj-$(CONFIG_CACHE_L2) += atl2c.o
+
+extra-y := head.o vmlinux.lds
+
+
+obj-y += vdso/
diff --git a/arch/nds32/kernel/vmlinux.lds.S b/arch/nds32/kernel/vmlinux.lds.S
new file mode 100644
index 0000000..2b1e55d
--- /dev/null
+++ b/arch/nds32/kernel/vmlinux.lds.S
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <asm/page.h>
+#include <asm/thread_info.h>
+#include <asm/cache.h>
+#include <asm/memory.h>
+
+#define LOAD_OFFSET (PAGE_OFFSET - PHYS_OFFSET)
+#include <asm-generic/vmlinux.lds.h>
+
+OUTPUT_ARCH(nds32)
+ENTRY(_stext_lma)
+jiffies = jiffies_64;
+
+SECTIONS
+{
+ _stext_lma = TEXTADDR - LOAD_OFFSET;
+ . = TEXTADDR;
+ __init_begin = .;
+ HEAD_TEXT_SECTION
+ INIT_TEXT_SECTION(PAGE_SIZE)
+ INIT_DATA_SECTION(16)
+ PERCPU_SECTION(L1_CACHE_BYTES)
+ __init_end = .;
+
+ . = ALIGN(PAGE_SIZE);
+ _stext = .;
+ /* Real text segment */
+ .text : AT(ADDR(.text) - LOAD_OFFSET) {
+ _text = .; /* Text and read-only data */
+ TEXT_TEXT
+ SCHED_TEXT
+ CPUIDLE_TEXT
+ LOCK_TEXT
+ KPROBES_TEXT
+ IRQENTRY_TEXT
+ *(.fixup)
+ }
+
+ _etext = .; /* End of text and rodata section */
+
+ _sdata = .;
+ RO_DATA_SECTION(PAGE_SIZE)
+ RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
+ _edata = .;
+
+ EXCEPTION_TABLE(16)
+ NOTES
+ BSS_SECTION(4, 4, 4)
+ _end = .;
+
+ STABS_DEBUG
+ DWARF_DEBUG
+
+ DISCARDS
+}
diff --git a/arch/nds32/mm/Makefile b/arch/nds32/mm/Makefile
new file mode 100644
index 0000000..6b68558
--- /dev/null
+++ b/arch/nds32/mm/Makefile
@@ -0,0 +1,7 @@
+obj-y := extable.o tlb.o \
+ fault.o init.o ioremap.o mmap.o \
+ mm-nds32.o cacheflush.o proc.o
+
+obj-$(CONFIG_ALIGNMENT_TRAP) += alignment.o
+obj-$(CONFIG_HIGHMEM) += highmem.o
+CFLAGS_proc-n13.o += -fomit-frame-pointer
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 26/33] nds32: defconfig
From: Greentime Hu @ 2017-12-08 9:12 UTC (permalink / raw)
To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
marc.zyngier, robh+dt, netdev, deanbo422, devicetree, viro,
dhowells, will.deacon, daniel.lezcano, linux-serial,
geert.uytterhoeven, linus.walleij, mark.rutland, greg
Cc: green.hu, Vincent Chen
In-Reply-To: <cover.1512723245.git.green.hu@gmail.com>
From: Greentime Hu <greentime@andestech.com>
This patch adds nds32 defconfig.
Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
arch/nds32/configs/defconfig | 108 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 108 insertions(+)
create mode 100644 arch/nds32/configs/defconfig
diff --git a/arch/nds32/configs/defconfig b/arch/nds32/configs/defconfig
new file mode 100644
index 0000000..069ebe6
--- /dev/null
+++ b/arch/nds32/configs/defconfig
@@ -0,0 +1,108 @@
+CONFIG_CROSS_COMPILE="nds32le-linux-"
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_USER_NS=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_PROFILING=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_CACHE_L2 is not set
+CONFIG_VMSPLIT_3G_OPT=y
+CONFIG_PREEMPT=y
+# CONFIG_COMPACTION is not set
+CONFIG_HZ_100=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_BLK_DEV is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+CONFIG_FTMAC100=y
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_SERIO is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=3
+CONFIG_SERIAL_8250_RUNTIME_UARTS=3
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_RC_CORE is not set
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_ITE is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_CLKSRC_ATCPIT100=y
+CONFIG_GENERIC_PHY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
+CONFIG_FUSE_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_NFS_USE_LEGACY_DNS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_INFO_DWARF4=y
+CONFIG_GDB_SCRIPTS=y
+CONFIG_READABLE_ASM=y
+CONFIG_HEADERS_CHECK=y
+CONFIG_DEBUG_SECTION_MISMATCH=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_PANIC_ON_OOPS=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_STACKTRACE=y
+CONFIG_RCU_CPU_STALL_TIMEOUT=300
+# CONFIG_CRYPTO_HW is not set
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 25/33] nds32: Miscellaneous header files
From: Greentime Hu @ 2017-12-08 9:12 UTC (permalink / raw)
To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
marc.zyngier, robh+dt, netdev, deanbo422, devicetree, viro,
dhowells, will.deacon, daniel.lezcano, linux-serial,
geert.uytterhoeven, linus.walleij, mark.rutland, greg
Cc: green.hu, Vincent Chen
In-Reply-To: <cover.1512723245.git.green.hu@gmail.com>
From: Greentime Hu <greentime@andestech.com>
This patch introduces some miscellaneous header files.
Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
arch/nds32/include/asm/delay.h | 51 +++++++++++++++++++++++++++++++
arch/nds32/include/asm/linkage.h | 24 +++++++++++++++
arch/nds32/include/uapi/asm/byteorder.h | 26 ++++++++++++++++
3 files changed, 101 insertions(+)
create mode 100644 arch/nds32/include/asm/delay.h
create mode 100644 arch/nds32/include/asm/linkage.h
create mode 100644 arch/nds32/include/uapi/asm/byteorder.h
diff --git a/arch/nds32/include/asm/delay.h b/arch/nds32/include/asm/delay.h
new file mode 100644
index 0000000..bdeeb76
--- /dev/null
+++ b/arch/nds32/include/asm/delay.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * 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 __NDS32_DELAY_H__
+#define __NDS32_DELAY_H__
+
+#include <asm/param.h>
+
+static inline void __delay(unsigned long loops)
+{
+ __asm__ __volatile__(".align 2\n"
+ "1:\n"
+ "\taddi\t%0, %0, -1\n"
+ "\tbgtz\t%0, 1b\n"
+ :"=r"(loops)
+ :"0"(loops));
+}
+
+static inline void __udelay(unsigned long usecs, unsigned long lpj)
+{
+ usecs *= (unsigned long)(((0x8000000000000000ULL / (500000 / HZ)) +
+ 0x80000000ULL) >> 32);
+ usecs = (unsigned long)(((unsigned long long)usecs * lpj) >> 32);
+ __delay(usecs);
+}
+
+#define udelay(usecs) __udelay((usecs), loops_per_jiffy)
+
+/* make sure "usecs *= ..." in udelay do not overflow. */
+#if HZ >= 1000
+#define MAX_UDELAY_MS 1
+#elif HZ <= 200
+#define MAX_UDELAY_MS 5
+#else
+#define MAX_UDELAY_MS (1000 / HZ)
+#endif
+
+#endif
diff --git a/arch/nds32/include/asm/linkage.h b/arch/nds32/include/asm/linkage.h
new file mode 100644
index 0000000..d17abd8
--- /dev/null
+++ b/arch/nds32/include/asm/linkage.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * 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_LINKAGE_H
+#define __ASM_LINKAGE_H
+
+/* This file is required by include/linux/linkage.h */
+#define __ALIGN .align 2
+#define __ALIGN_STR ".align 2"
+
+#endif
diff --git a/arch/nds32/include/uapi/asm/byteorder.h b/arch/nds32/include/uapi/asm/byteorder.h
new file mode 100644
index 0000000..198e8dd
--- /dev/null
+++ b/arch/nds32/include/uapi/asm/byteorder.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * 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 __NDS32_BYTEORDER_H__
+#define __NDS32_BYTEORDER_H__
+
+#ifdef __NDS32_EB__
+#include <linux/byteorder/big_endian.h>
+#else
+#include <linux/byteorder/little_endian.h>
+#endif
+
+#endif /* __NDS32_BYTEORDER_H__ */
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 24/33] nds32: Device tree support
From: Greentime Hu @ 2017-12-08 9:12 UTC (permalink / raw)
To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
marc.zyngier, robh+dt, netdev, deanbo422, devicetree, viro,
dhowells, will.deacon, daniel.lezcano, linux-serial,
geert.uytterhoeven, linus.walleij, mark.rutland, greg
Cc: green.hu, Vincent Chen
In-Reply-To: <cover.1512723245.git.green.hu@gmail.com>
From: Greentime Hu <greentime@andestech.com>
This patch adds support for device tree.
Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
arch/nds32/boot/dts/Makefile | 8 +++++
arch/nds32/boot/dts/ae3xx.dts | 67 ++++++++++++++++++++++++++++++++++++++
arch/nds32/boot/dts/ag101p.dts | 70 ++++++++++++++++++++++++++++++++++++++++
arch/nds32/kernel/devtree.c | 32 ++++++++++++++++++
4 files changed, 177 insertions(+)
create mode 100644 arch/nds32/boot/dts/Makefile
create mode 100644 arch/nds32/boot/dts/ae3xx.dts
create mode 100644 arch/nds32/boot/dts/ag101p.dts
create mode 100644 arch/nds32/kernel/devtree.c
diff --git a/arch/nds32/boot/dts/Makefile b/arch/nds32/boot/dts/Makefile
new file mode 100644
index 0000000..d31faa8
--- /dev/null
+++ b/arch/nds32/boot/dts/Makefile
@@ -0,0 +1,8 @@
+ifneq '$(CONFIG_NDS32_BUILTIN_DTB)' '""'
+BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_NDS32_BUILTIN_DTB)).dtb.o
+else
+BUILTIN_DTB :=
+endif
+obj-$(CONFIG_OF) += $(BUILTIN_DTB)
+
+clean-files := *.dtb *.dtb.S
diff --git a/arch/nds32/boot/dts/ae3xx.dts b/arch/nds32/boot/dts/ae3xx.dts
new file mode 100644
index 0000000..ccdb2fc
--- /dev/null
+++ b/arch/nds32/boot/dts/ae3xx.dts
@@ -0,0 +1,67 @@
+/dts-v1/;
+/ {
+ compatible = "andestech,ae3xx";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&intc>;
+
+ chosen {
+ stdout-path = &serial0;
+ };
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x00000000 0x40000000>;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "andestech,n13", "andestech,nds32v3";
+ reg = <0>;
+ clock-frequency = <60000000>;
+ };
+ };
+
+ clk_pll: ref_30mhz {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <30000000>;
+ };
+
+
+ intc: interrupt-controller {
+ compatible = "andestech,ativic32";
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+
+ serial0: serial@f0300000 {
+ compatible = "andestech,uart16550", "ns16550a";
+ reg = <0xf0300000 0x1000>;
+ interrupts = <8>;
+ clock-frequency = <14745600>;
+ reg-shift = <2>;
+ reg-offset = <32>;
+ no-loopback-test = <1>;
+ };
+
+ timer0: timer@f0400000 {
+ compatible = "andestech,atcpit100";
+ reg = <0xf0400000 0x1000>;
+ interrupts = <2>;
+ clocks = <&clk_pll>;
+ clock-names = "apb_pclk";
+ cycle-count-offset = <0x38>;
+ cycle-count-down;
+ };
+
+ mac0: mac@e0100000 {
+ compatible = "andestech,atmac100";
+ reg = <0xe0100000 0x1000>;
+ interrupts = <18>;
+ };
+
+};
diff --git a/arch/nds32/boot/dts/ag101p.dts b/arch/nds32/boot/dts/ag101p.dts
new file mode 100644
index 0000000..fb9d509
--- /dev/null
+++ b/arch/nds32/boot/dts/ag101p.dts
@@ -0,0 +1,70 @@
+/dts-v1/;
+/ {
+ compatible = "andestech,ag101p";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&intc>;
+
+ chosen {
+ stdout-path = &serial0;
+ };
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x00000000 0x40000000>;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "andestech,n13", "andestech,nds32v3";
+ reg = <0x0>;
+ clock-frequency = <60000000>;
+ };
+ };
+
+ clk_pll: ref_30mhz {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <30000000>;
+ };
+
+ intc: interrupt-controller {
+ compatible = "andestech,ativic32";
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+
+ serial0: serial@99600000 {
+ compatible = "andestech,uart16550", "ns16550a";
+ reg = <0x99600000 0x1000>;
+ interrupts = <7>;
+ clock-frequency = <14745600>;
+ reg-shift = <2>;
+ no-loopback-test = <1>;
+ };
+
+ timer0: timer@98400000 {
+ compatible = "andestech,atftmr010";
+ reg = <0x98400000 0x1000>;
+ interrupts = <19>;
+ clocks = <&clk_pll>;
+ clock-names = "apb_pclk";
+ cycle-count-offset = <0x20>;
+ };
+
+ mac0: mac@90900000 {
+ compatible = "andestech,atmac100";
+ reg = <0x90900000 0x1000>;
+ interrupts = <25>;
+ };
+
+ L2: l2-cache {
+ compatible = "andestech,atl2c";
+ reg = <0x90f00000 0x1000>;
+ cache-unified;
+ cache-level = <2>;
+ };
+};
diff --git a/arch/nds32/kernel/devtree.c b/arch/nds32/kernel/devtree.c
new file mode 100644
index 0000000..858fe3a
--- /dev/null
+++ b/arch/nds32/kernel/devtree.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/bug.h>
+#include <linux/printk.h>
+#include <linux/of_fdt.h>
+
+void __init early_init_devtree(void *params)
+{
+ if (!params || !early_init_dt_scan(params)) {
+ pr_crit("\n"
+ "Error: invalid device tree blob at (virtual address 0x%p)\n"
+ "\nPlease check your bootloader.", params);
+
+ BUG_ON(1);
+ }
+
+ dump_stack_set_arch_desc("%s (DT)", of_flat_dt_get_machine_name());
+}
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 23/33] nds32: Generic timers support
From: Greentime Hu @ 2017-12-08 9:12 UTC (permalink / raw)
To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
marc.zyngier, robh+dt, netdev, deanbo422, devicetree, viro,
dhowells, will.deacon, daniel.lezcano, linux-serial,
geert.uytterhoeven, linus.walleij, mark.rutland, greg
Cc: green.hu, Vincent Chen
In-Reply-To: <cover.1512723245.git.green.hu@gmail.com>
From: Greentime Hu <greentime@andestech.com>
This patch adds support for timer.
Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
arch/nds32/kernel/time.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
create mode 100644 arch/nds32/kernel/time.c
diff --git a/arch/nds32/kernel/time.c b/arch/nds32/kernel/time.c
new file mode 100644
index 0000000..aef06f6
--- /dev/null
+++ b/arch/nds32/kernel/time.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clocksource.h>
+#include <linux/clk-provider.h>
+
+void __init time_init(void)
+{
+ of_clk_init(NULL);
+ timer_probe();
+}
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 22/33] nds32: Loadable modules
From: Greentime Hu @ 2017-12-08 9:12 UTC (permalink / raw)
To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
marc.zyngier, robh+dt, netdev, deanbo422, devicetree, viro,
dhowells, will.deacon, daniel.lezcano, linux-serial,
geert.uytterhoeven, linus.walleij, mark.rutland, greg
Cc: green.hu, Vincent Chen
In-Reply-To: <cover.1512723245.git.green.hu@gmail.com>
From: Greentime Hu <greentime@andestech.com>
This patch adds support for loadable modules.
Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
arch/nds32/include/asm/module.h | 24 ++++
arch/nds32/kernel/module.c | 299 +++++++++++++++++++++++++++++++++++++++
2 files changed, 323 insertions(+)
create mode 100644 arch/nds32/include/asm/module.h
create mode 100644 arch/nds32/kernel/module.c
diff --git a/arch/nds32/include/asm/module.h b/arch/nds32/include/asm/module.h
new file mode 100644
index 0000000..5ed2b75
--- /dev/null
+++ b/arch/nds32/include/asm/module.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * 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_NDS32_MODULE_H
+#define _ASM_NDS32_MODULE_H
+
+#include <asm-generic/module.h>
+
+#define MODULE_ARCH_VERMAGIC "NDS32v3"
+
+#endif /* _ASM_NDS32_MODULE_H */
diff --git a/arch/nds32/kernel/module.c b/arch/nds32/kernel/module.c
new file mode 100644
index 0000000..bb34e23
--- /dev/null
+++ b/arch/nds32/kernel/module.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+
+#include <asm/pgtable.h>
+
+void *module_alloc(unsigned long size)
+{
+ return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
+ GFP_KERNEL, PAGE_KERNEL, 0, NUMA_NO_NODE,
+ __builtin_return_address(0));
+}
+
+void module_free(struct module *module, void *region)
+{
+ vfree(region);
+}
+
+int module_frob_arch_sections(Elf_Ehdr * hdr,
+ Elf_Shdr * sechdrs,
+ char *secstrings, struct module *mod)
+{
+ return 0;
+}
+
+void do_reloc16(unsigned int val, unsigned int *loc, unsigned int val_mask,
+ unsigned int val_shift, unsigned int loc_mask,
+ unsigned int partial_in_place, unsigned int swap)
+{
+ unsigned int tmp = 0, tmp2 = 0;
+
+ __asm__ __volatile__("\tlhi.bi\t%0, [%2], 0\n"
+ "\tbeqz\t%3, 1f\n"
+ "\twsbh\t%0, %1\n"
+ "1:\n":"=r"(tmp):"0"(tmp), "r"(loc), "r"(swap)
+ );
+
+ tmp2 = tmp & loc_mask;
+ if (partial_in_place) {
+ tmp &= (!loc_mask);
+ tmp =
+ tmp2 | ((tmp + ((val & val_mask) >> val_shift)) & val_mask);
+ } else {
+ tmp = tmp2 | ((val & val_mask) >> val_shift);
+ }
+
+ __asm__ __volatile__("\tbeqz\t%3, 2f\n"
+ "\twsbh\t%0, %1\n"
+ "2:\n"
+ "\tshi.bi\t%0, [%2], 0\n":"=r"(tmp):"0"(tmp),
+ "r"(loc), "r"(swap)
+ );
+}
+
+void do_reloc32(unsigned int val, unsigned int *loc, unsigned int val_mask,
+ unsigned int val_shift, unsigned int loc_mask,
+ unsigned int partial_in_place, unsigned int swap)
+{
+ unsigned int tmp = 0, tmp2 = 0;
+
+ __asm__ __volatile__("\tlmw.bi\t%0, [%2], %0, 0\n"
+ "\tbeqz\t%3, 1f\n"
+ "\twsbh\t%0, %1\n"
+ "\trotri\t%0, %1, 16\n"
+ "1:\n":"=r"(tmp):"0"(tmp), "r"(loc), "r"(swap)
+ );
+
+ tmp2 = tmp & loc_mask;
+ if (partial_in_place) {
+ tmp &= (!loc_mask);
+ tmp =
+ tmp2 | ((tmp + ((val & val_mask) >> val_shift)) & val_mask);
+ } else {
+ tmp = tmp2 | ((val & val_mask) >> val_shift);
+ }
+
+ __asm__ __volatile__("\tbeqz\t%3, 2f\n"
+ "\twsbh\t%0, %1\n"
+ "\trotri\t%0, %1, 16\n"
+ "2:\n"
+ "\tsmw.bi\t%0, [%2], %0, 0\n":"=r"(tmp):"0"(tmp),
+ "r"(loc), "r"(swap)
+ );
+}
+
+static inline int exceed_limit(int offset, unsigned int val_mask,
+ struct module *module, Elf32_Rela * rel,
+ unsigned int relindex, unsigned int reloc_order)
+{
+ int abs_off = offset < 0 ? ~offset : offset;
+
+ if (abs_off & (~val_mask)) {
+ pr_err("\n%s: relocation type %d out of range.\n"
+ "please rebuild the kernel module with gcc option \"-Wa,-mno-small-text\".\n",
+ module->name, ELF32_R_TYPE(rel->r_info));
+ pr_err("section %d reloc %d offset 0x%x relative 0x%x.\n",
+ relindex, reloc_order, rel->r_offset, offset);
+ return true;
+ }
+ return false;
+}
+
+#ifdef __NDS32_EL__
+#define NEED_SWAP 1
+#else
+#define NEED_SWAP 0
+#endif
+
+int
+apply_relocate_add(Elf32_Shdr * sechdrs, const char *strtab,
+ unsigned int symindex, unsigned int relindex,
+ struct module *module)
+{
+ Elf32_Shdr *symsec = sechdrs + symindex;
+ Elf32_Shdr *relsec = sechdrs + relindex;
+ Elf32_Shdr *dstsec = sechdrs + relsec->sh_info;
+ Elf32_Rela *rel = (void *)relsec->sh_addr;
+ unsigned int i;
+
+ for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rela); i++, rel++) {
+ Elf32_Addr *loc;
+ Elf32_Sym *sym;
+ Elf32_Addr v;
+ s32 offset;
+
+ offset = ELF32_R_SYM(rel->r_info);
+ if (offset < 0
+ || offset > (symsec->sh_size / sizeof(Elf32_Sym))) {
+ pr_err("%s: bad relocation\n", module->name);
+ pr_err("section %d reloc %d\n", relindex, i);
+ return -ENOEXEC;
+ }
+
+ sym = ((Elf32_Sym *) symsec->sh_addr) + offset;
+
+ if (rel->r_offset < 0
+ || rel->r_offset > dstsec->sh_size - sizeof(u16)) {
+ pr_err("%s: out of bounds relocation\n", module->name);
+ pr_err("section %d reloc %d offset 0x%0x size %d\n",
+ relindex, i, rel->r_offset, dstsec->sh_size);
+ return -ENOEXEC;
+ }
+
+ loc = (Elf32_Addr *) (dstsec->sh_addr + rel->r_offset);
+ v = sym->st_value + rel->r_addend;
+
+ switch (ELF32_R_TYPE(rel->r_info)) {
+ case R_NDS32_NONE:
+ case R_NDS32_INSN16:
+ case R_NDS32_LABEL:
+ case R_NDS32_LONGCALL1:
+ case R_NDS32_LONGCALL2:
+ case R_NDS32_LONGCALL3:
+ case R_NDS32_LONGCALL4:
+ case R_NDS32_LONGJUMP1:
+ case R_NDS32_LONGJUMP2:
+ case R_NDS32_LONGJUMP3:
+ case R_NDS32_9_FIXED_RELA:
+ case R_NDS32_15_FIXED_RELA:
+ case R_NDS32_17_FIXED_RELA:
+ case R_NDS32_25_FIXED_RELA:
+ case R_NDS32_LOADSTORE:
+ case R_NDS32_DWARF2_OP1_RELA:
+ case R_NDS32_DWARF2_OP2_RELA:
+ case R_NDS32_DWARF2_LEB_RELA:
+ case R_NDS32_RELA_NOP_MIX ... R_NDS32_RELA_NOP_MAX:
+ break;
+
+ case R_NDS32_32_RELA:
+ do_reloc32(v, loc, 0xffffffff, 0, 0, 0, 0);
+ break;
+
+ case R_NDS32_HI20_RELA:
+ do_reloc32(v, loc, 0xfffff000, 12, 0xfff00000, 0,
+ NEED_SWAP);
+ break;
+
+ case R_NDS32_LO12S3_RELA:
+ do_reloc32(v, loc, 0x00000fff, 3, 0xfffff000, 0,
+ NEED_SWAP);
+ break;
+
+ case R_NDS32_LO12S2_RELA:
+ do_reloc32(v, loc, 0x00000fff, 2, 0xfffff000, 0,
+ NEED_SWAP);
+ break;
+
+ case R_NDS32_LO12S1_RELA:
+ do_reloc32(v, loc, 0x00000fff, 1, 0xfffff000, 0,
+ NEED_SWAP);
+ break;
+
+ case R_NDS32_LO12S0_RELA:
+ case R_NDS32_LO12S0_ORI_RELA:
+ do_reloc32(v, loc, 0x00000fff, 0, 0xfffff000, 0,
+ NEED_SWAP);
+ break;
+
+ case R_NDS32_9_PCREL_RELA:
+ if (exceed_limit
+ ((v - (Elf32_Addr) loc), 0x000000ff, module, rel,
+ relindex, i))
+ return -ENOEXEC;
+ do_reloc16(v - (Elf32_Addr) loc, loc, 0x000001ff, 1,
+ 0xffffff00, 0, NEED_SWAP);
+ break;
+
+ case R_NDS32_15_PCREL_RELA:
+ if (exceed_limit
+ ((v - (Elf32_Addr) loc), 0x00003fff, module, rel,
+ relindex, i))
+ return -ENOEXEC;
+ do_reloc32(v - (Elf32_Addr) loc, loc, 0x00007fff, 1,
+ 0xffffc000, 0, NEED_SWAP);
+ break;
+
+ case R_NDS32_17_PCREL_RELA:
+ if (exceed_limit
+ ((v - (Elf32_Addr) loc), 0x0000ffff, module, rel,
+ relindex, i))
+ return -ENOEXEC;
+ do_reloc32(v - (Elf32_Addr) loc, loc, 0x0001ffff, 1,
+ 0xffff0000, 0, NEED_SWAP);
+ break;
+
+ case R_NDS32_25_PCREL_RELA:
+ if (exceed_limit
+ ((v - (Elf32_Addr) loc), 0x00ffffff, module, rel,
+ relindex, i))
+ return -ENOEXEC;
+ do_reloc32(v - (Elf32_Addr) loc, loc, 0x01ffffff, 1,
+ 0xff000000, 0, NEED_SWAP);
+ break;
+ case R_NDS32_WORD_9_PCREL_RELA:
+ if (exceed_limit
+ ((v - (Elf32_Addr) loc), 0x000000ff, module, rel,
+ relindex, i))
+ return -ENOEXEC;
+ do_reloc32(v - (Elf32_Addr) loc, loc, 0x000001ff, 1,
+ 0xffffff00, 0, NEED_SWAP);
+ break;
+
+ case R_NDS32_SDA15S3_RELA:
+ case R_NDS32_SDA15S2_RELA:
+ case R_NDS32_SDA15S1_RELA:
+ case R_NDS32_SDA15S0_RELA:
+ pr_err("%s: unsupported relocation type %d.\n",
+ module->name, ELF32_R_TYPE(rel->r_info));
+ pr_err
+ ("Small data section access doesn't work in the kernel space; "
+ "please rebuild the kernel module with gcc option -mcmodel=large.\n");
+ pr_err("section %d reloc %d offset 0x%x size %d\n",
+ relindex, i, rel->r_offset, dstsec->sh_size);
+ break;
+
+ default:
+ pr_err("%s: unsupported relocation type %d.\n",
+ module->name, ELF32_R_TYPE(rel->r_info));
+ pr_err("section %d reloc %d offset 0x%x size %d\n",
+ relindex, i, rel->r_offset, dstsec->sh_size);
+ }
+ }
+ return 0;
+}
+
+int
+apply_relocate(Elf32_Shdr * sechdrs, const char *strtab,
+ unsigned int symindex, unsigned int relsec,
+ struct module *module)
+{
+ return 0;
+}
+
+int
+module_finalize(const Elf32_Ehdr * hdr, const Elf_Shdr * sechdrs,
+ struct module *module)
+{
+ return 0;
+}
+
+void module_arch_cleanup(struct module *mod)
+{
+}
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 21/33] nds32: L2 cache support
From: Greentime Hu @ 2017-12-08 9:12 UTC (permalink / raw)
To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
marc.zyngier, robh+dt, netdev, deanbo422, devicetree, viro,
dhowells, will.deacon, daniel.lezcano, linux-serial,
geert.uytterhoeven, linus.walleij, mark.rutland, greg
Cc: green.hu, Vincent Chen
In-Reply-To: <cover.1512723245.git.green.hu@gmail.com>
From: Greentime Hu <greentime@andestech.com>
This patch adds L2 cache support.
Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
arch/nds32/include/asm/l2_cache.h | 155 +++++++++++++++++++++++++++++++++++++
arch/nds32/kernel/atl2c.c | 77 ++++++++++++++++++
2 files changed, 232 insertions(+)
create mode 100644 arch/nds32/include/asm/l2_cache.h
create mode 100644 arch/nds32/kernel/atl2c.c
diff --git a/arch/nds32/include/asm/l2_cache.h b/arch/nds32/include/asm/l2_cache.h
new file mode 100644
index 0000000..a12a3fe
--- /dev/null
+++ b/arch/nds32/include/asm/l2_cache.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * 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 L2_CACHE_H
+#define L2_CACHE_H
+
+/* CCTL_CMD_OP */
+#define L2_CA_CONF_OFF 0x0
+#define L2_IF_CONF_OFF 0x4
+#define L2CC_SETUP_OFF 0x8
+#define L2CC_PROT_OFF 0xC
+#define L2CC_CTRL_OFF 0x10
+#define L2_INT_EN_OFF 0x20
+#define L2_STA_OFF 0x24
+#define RDERR_ADDR_OFF 0x28
+#define WRERR_ADDR_OFF 0x2c
+#define EVDPTERR_ADDR_OFF 0x30
+#define IMPL3ERR_ADDR_OFF 0x34
+#define L2_CNT0_CTRL_OFF 0x40
+#define L2_EVNT_CNT0_OFF 0x44
+#define L2_CNT1_CTRL_OFF 0x48
+#define L2_EVNT_CNT1_OFF 0x4c
+#define L2_CCTL_CMD_OFF 0x60
+#define L2_CCTL_STATUS_OFF 0x64
+#define L2_LINE_TAG_OFF 0x68
+#define L2_LINE_DPT_OFF 0x70
+
+#define CCTL_CMD_L2_IX_INVAL 0x0
+#define CCTL_CMD_L2_PA_INVAL 0x1
+#define CCTL_CMD_L2_IX_WB 0x2
+#define CCTL_CMD_L2_PA_WB 0x3
+#define CCTL_CMD_L2_PA_WBINVAL 0x5
+#define CCTL_CMD_L2_SYNC 0xa
+
+/* CCTL_CMD_TYPE */
+#define CCTL_SINGLE_CMD 0
+#define CCTL_BLOCK_CMD 0x10
+#define CCTL_ALL_CMD 0x10
+
+/******************************************************************************
+ * L2_CA_CONF (Cache architecture configuration)
+ *****************************************************************************/
+#define L2_CA_CONF_offL2SET 0
+#define L2_CA_CONF_offL2WAY 4
+#define L2_CA_CONF_offL2CLSZ 8
+#define L2_CA_CONF_offL2DW 11
+#define L2_CA_CONF_offL2PT 14
+#define L2_CA_CONF_offL2VER 16
+
+#define L2_CA_CONF_mskL2SET (0xFUL << L2_CA_CONF_offL2SET)
+#define L2_CA_CONF_mskL2WAY (0xFUL << L2_CA_CONF_offL2WAY)
+#define L2_CA_CONF_mskL2CLSZ (0x7UL << L2_CA_CONF_offL2CLSZ)
+#define L2_CA_CONF_mskL2DW (0x7UL << L2_CA_CONF_offL2DW)
+#define L2_CA_CONF_mskL2PT (0x3UL << L2_CA_CONF_offL2PT)
+#define L2_CA_CONF_mskL2VER (0xFFFFUL << L2_CA_CONF_offL2VER)
+
+/******************************************************************************
+ * L2CC_SETUP (L2CC Setup register)
+ *****************************************************************************/
+#define L2CC_SETUP_offPART 0
+#define L2CC_SETUP_mskPART (0x3UL << L2CC_SETUP_offPART)
+#define L2CC_SETUP_offDDLATC 4
+#define L2CC_SETUP_mskDDLATC (0x3UL << L2CC_SETUP_offDDLATC)
+#define L2CC_SETUP_offTDLATC 8
+#define L2CC_SETUP_mskTDLATC (0x3UL << L2CC_SETUP_offTDLATC)
+
+/******************************************************************************
+ * L2CC_PROT (L2CC Protect register)
+ *****************************************************************************/
+#define L2CC_PROT_offMRWEN 31
+#define L2CC_PROT_mskMRWEN (0x1UL << L2CC_PROT_offMRWEN)
+
+/******************************************************************************
+ * L2_CCTL_STATUS_Mn (The L2CCTL command working status for Master n)
+ *****************************************************************************/
+#define L2CC_CTRL_offEN 31
+#define L2CC_CTRL_mskEN (0x1UL << L2CC_CTRL_offEN)
+
+/******************************************************************************
+ * L2_CCTL_STATUS_Mn (The L2CCTL command working status for Master n)
+ *****************************************************************************/
+#define L2_CCTL_STATUS_offCMD_COMP 31
+#define L2_CCTL_STATUS_mskCMD_COMP (0x1 << L2_CCTL_STATUS_offCMD_COMP)
+
+#ifndef __ASSEMBLY__
+extern void __iomem *atl2c_base;
+
+#include <linux/smp.h>
+#include <asm/io.h>
+#include <asm/bitfield.h>
+
+#define L2C_R_REG(offset) readl(atl2c_base + offset)
+#define L2C_W_REG(offset, value) writel(value, atl2c_base + offset)
+
+#define L2_CMD_RDY() \
+ do{;}while((L2C_R_REG(L2_CCTL_STATUS_OFF) & L2_CCTL_STATUS_mskCMD_COMP) == 0)
+
+static inline unsigned long L2_CACHE_SET(void)
+{
+ return 64 << ((L2C_R_REG(L2_CA_CONF_OFF) & L2_CA_CONF_mskL2SET) >>
+ L2_CA_CONF_offL2SET);
+}
+
+static inline unsigned long L2_CACHE_WAY(void)
+{
+ return 1 +
+ ((L2C_R_REG(L2_CA_CONF_OFF) & L2_CA_CONF_mskL2WAY) >>
+ L2_CA_CONF_offL2WAY);
+}
+
+static inline unsigned long L2_CACHE_LINE_SIZE(void)
+{
+
+ return 4 << ((L2C_R_REG(L2_CA_CONF_OFF) & L2_CA_CONF_mskL2CLSZ) >>
+ L2_CA_CONF_offL2CLSZ);
+}
+
+static inline unsigned long GET_L2CC_CTRL_CPU(unsigned long cpu)
+{
+ if (cpu == smp_processor_id())
+ return L2C_R_REG(L2CC_CTRL_OFF);
+ return L2C_R_REG(L2CC_CTRL_OFF + (cpu << 8));
+}
+
+static inline void SET_L2CC_CTRL_CPU(unsigned long cpu, unsigned long val)
+{
+ if (cpu == smp_processor_id())
+ L2C_W_REG(L2CC_CTRL_OFF, val);
+ else
+ L2C_W_REG(L2CC_CTRL_OFF + (cpu << 8), val);
+}
+
+static inline unsigned long GET_L2CC_STATUS_CPU(unsigned long cpu)
+{
+ if (cpu == smp_processor_id())
+ return L2C_R_REG(L2_CCTL_STATUS_OFF);
+ return L2C_R_REG(L2_CCTL_STATUS_OFF + (cpu << 8));
+}
+
+#endif
+
+#endif
diff --git a/arch/nds32/kernel/atl2c.c b/arch/nds32/kernel/atl2c.c
new file mode 100644
index 0000000..dd87fc9
--- /dev/null
+++ b/arch/nds32/kernel/atl2c.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/compiler.h>
+#include <linux/of_address.h>
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
+#include <asm/l2_cache.h>
+
+void __iomem *atl2c_base;
+static const struct of_device_id atl2c_ids[] __initconst = {
+ {.compatible = "andestech,atl2c",}
+};
+
+static int __init atl2c_of_init(void)
+{
+ struct device_node *np;
+ struct resource res;
+ unsigned long tmp = 0;
+ unsigned long l2set, l2way, l2clsz;
+
+ if (!(__nds32__mfsr(NDS32_SR_MSC_CFG) & MSC_CFG_mskL2C))
+ return -ENODEV;
+
+ np = of_find_matching_node(NULL, atl2c_ids);
+ if (!np)
+ return -ENODEV;
+
+ if (of_address_to_resource(np, 0, &res))
+ return -ENODEV;
+
+ atl2c_base = ioremap(res.start, resource_size(&res));
+ if (!atl2c_base)
+ return -ENOMEM;
+
+ l2set =
+ 64 << ((L2C_R_REG(L2_CA_CONF_OFF) & L2_CA_CONF_mskL2SET) >>
+ L2_CA_CONF_offL2SET);
+ l2way =
+ 1 +
+ ((L2C_R_REG(L2_CA_CONF_OFF) & L2_CA_CONF_mskL2WAY) >>
+ L2_CA_CONF_offL2WAY);
+ l2clsz =
+ 4 << ((L2C_R_REG(L2_CA_CONF_OFF) & L2_CA_CONF_mskL2CLSZ) >>
+ L2_CA_CONF_offL2CLSZ);
+ pr_info("L2:%luKB/%luS/%luW/%luB\n",
+ l2set * l2way * l2clsz / 1024, l2set, l2way, l2clsz);
+
+ tmp = L2C_R_REG(L2CC_PROT_OFF);
+ tmp &= ~L2CC_PROT_mskMRWEN;
+ L2C_W_REG(L2CC_PROT_OFF, tmp);
+
+ tmp = L2C_R_REG(L2CC_SETUP_OFF);
+ tmp &= ~L2CC_SETUP_mskPART;
+ L2C_W_REG(L2CC_SETUP_OFF, tmp);
+
+ tmp = L2C_R_REG(L2CC_CTRL_OFF);
+ tmp |= L2CC_CTRL_mskEN;
+ L2C_W_REG(L2CC_CTRL_OFF, tmp);
+
+ return 0;
+}
+
+subsys_initcall(atl2c_of_init);
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 20/33] nds32: Debugging support
From: Greentime Hu @ 2017-12-08 9:12 UTC (permalink / raw)
To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
marc.zyngier, robh+dt, netdev, deanbo422, devicetree, viro,
dhowells, will.deacon, daniel.lezcano, linux-serial,
geert.uytterhoeven, linus.walleij, mark.rutland, greg
Cc: green.hu, Vincent Chen
In-Reply-To: <cover.1512723245.git.green.hu@gmail.com>
From: Greentime Hu <greentime@andestech.com>
This patch adds ptrace support.
Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
arch/nds32/include/uapi/asm/ptrace.h | 38 ++++
arch/nds32/kernel/ptrace.c | 325 ++++++++++++++++++++++++++++++++++
2 files changed, 363 insertions(+)
create mode 100644 arch/nds32/include/uapi/asm/ptrace.h
create mode 100644 arch/nds32/kernel/ptrace.c
diff --git a/arch/nds32/include/uapi/asm/ptrace.h b/arch/nds32/include/uapi/asm/ptrace.h
new file mode 100644
index 0000000..76fe2ae
--- /dev/null
+++ b/arch/nds32/include/uapi/asm/ptrace.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * 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 __UAPI_ASM_NDS32_PTRACE_H
+#define __UAPI_ASM_NDS32_PTRACE_H
+
+#ifndef __ASSEMBLY__
+
+/*
+ * User structures for general purpose register.
+ */
+struct user_pt_regs {
+ long uregs[26];
+ long fp;
+ long gp;
+ long lp;
+ long sp;
+ long ipc;
+ long lb;
+ long le;
+ long lc;
+ long syscallno;
+};
+#endif
+#endif
diff --git a/arch/nds32/kernel/ptrace.c b/arch/nds32/kernel/ptrace.c
new file mode 100644
index 0000000..d91b3b8
--- /dev/null
+++ b/arch/nds32/kernel/ptrace.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+#include <linux/security.h>
+#include <linux/init.h>
+#include <linux/uaccess.h>
+#include <linux/regset.h>
+#include <linux/tracehook.h>
+#include <linux/elf.h>
+#include <linux/sched/task_stack.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+enum nds32_regset {
+ REGSET_GPR,
+};
+
+static int gpr_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user * ubuf)
+{
+ struct user_pt_regs *uregs = &task_pt_regs(target)->user_regs;
+ return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1);
+}
+
+static int gpr_set(struct task_struct *target, const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user * ubuf)
+{
+ int err;
+ struct user_pt_regs newregs = task_pt_regs(target)->user_regs;
+
+ err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1);
+ if (err)
+ return err;
+
+ task_pt_regs(target)->user_regs = newregs;
+ return 0;
+}
+
+static const struct user_regset nds32_regsets[] = {
+ [REGSET_GPR] = {
+ .core_note_type = NT_PRSTATUS,
+ .n = sizeof(struct user_pt_regs) / sizeof(u32),
+ .size = sizeof(u32),
+ .align = sizeof(u32),
+ .get = gpr_get,
+ .set = gpr_set}
+};
+
+static const struct user_regset_view nds32_user_view = {
+ .name = "nds32",.e_machine = EM_NDS32,
+ .regsets = nds32_regsets,.n = ARRAY_SIZE(nds32_regsets)
+};
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+ return &nds32_user_view;
+}
+
+/* get_user_reg()
+ *
+ * This routine will get a word off of the processes privileged stack.
+ * the offset is how far from the base addr as stored in the THREAD.
+ * this routine assumes that all the privileged stacks are in our
+ * data space.
+ */
+static inline unsigned int get_user_reg(struct task_struct *task, int offset)
+{
+ return task_pt_regs(task)->uregs[offset];
+}
+
+/* put_user_reg()
+ *
+ * this routine will put a word on the processes privileged stack.
+ * the offset is how far from the base addr as stored in the THREAD.
+ * this routine assumes that all the privileged stacks are in our
+ * data space.
+ */
+static inline int put_user_reg(struct task_struct *task, int offset, long data)
+{
+ struct pt_regs newregs, *regs = task_pt_regs(task);
+ int ret = -EINVAL;
+
+ newregs = *regs;
+ newregs.uregs[offset] = data;
+
+ if (valid_user_regs(&newregs)) {
+ regs->uregs[offset] = data;
+ ret = 0;
+ }
+
+ return ret;
+}
+
+/*
+ * Called by kernel/ptrace.c when detaching..
+ *
+ * Make sure the single step bit is not set.
+ */
+void ptrace_disable(struct task_struct *child)
+{
+ user_disable_single_step(child);
+}
+
+static void fill_sigtrap_info(struct task_struct *tsk,
+ struct pt_regs *regs,
+ int error_code, int si_code, struct siginfo *info)
+{
+ tsk->thread.trap_no = ENTRY_DEBUG_RELATED;
+ tsk->thread.error_code = error_code;
+
+ memset(info, 0, sizeof(*info));
+ info->si_signo = SIGTRAP;
+ info->si_code = si_code;
+ info->si_addr = (void __user *)instruction_pointer(regs);
+}
+
+void user_single_step_siginfo(struct task_struct *tsk,
+ struct pt_regs *regs, struct siginfo *info)
+{
+ fill_sigtrap_info(tsk, regs, 0, TRAP_BRKPT, info);
+}
+
+/*
+ * Handle hitting a breakpoint.
+ */
+void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
+ int error_code, int si_code)
+{
+ struct siginfo info;
+
+ fill_sigtrap_info(tsk, regs, error_code, TRAP_BRKPT, &info);
+ /* Send us the fake SIGTRAP */
+ force_sig_info(SIGTRAP, &info, tsk);
+}
+
+/* ptrace_read_user()
+ *
+ * Read the word at offset "off" into the "struct user". We
+ * actually access the pt_regs stored on the kernel stack.
+ */
+static int
+ptrace_read_user(struct task_struct *tsk, unsigned long off,
+ unsigned long __user * ret)
+{
+ unsigned long tmp = 0;
+
+ if (off < sizeof(struct pt_regs)) {
+ if (off & 3)
+ return -EIO;
+ tmp = get_user_reg(tsk, off >> 2);
+ return put_user(tmp, ret);
+ } else
+ return -EIO;
+}
+
+/* ptrace_write_user()
+ *
+ * Write the word at offset "off" into "struct user". We
+ * actually access the pt_regs stored on the kernel stack.
+ */
+static int
+ptrace_write_user(struct task_struct *tsk, unsigned long off, unsigned long val)
+{
+ if (off < sizeof(struct pt_regs)) {
+ if (off & 3)
+ return -EIO;
+ return put_user_reg(tsk, off >> 2, val);
+ } else
+ return -EIO;
+}
+
+/* ptrace_getregs()
+ *
+ * Get all user integer registers.
+ */
+static int ptrace_getregs(struct task_struct *tsk, void __user * uregs)
+{
+ struct pt_regs *regs = task_pt_regs(tsk);
+
+ return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0;
+}
+
+/* ptrace_setregs()
+ *
+ * Set all user integer registers.
+ */
+static int ptrace_setregs(struct task_struct *tsk, void __user * uregs)
+{
+ struct pt_regs newregs;
+ int ret;
+
+ ret = -EFAULT;
+ if (copy_from_user(&newregs, uregs, sizeof(struct pt_regs)) == 0) {
+ struct pt_regs *regs = task_pt_regs(tsk);
+
+ ret = -EINVAL;
+ if (valid_user_regs(&newregs)) {
+ *regs = newregs;
+ ret = 0;
+ }
+ }
+
+ return ret;
+}
+
+/* ptrace_getfpregs()
+ *
+ * Get the child FPU state.
+ */
+static int ptrace_getfpregs(struct task_struct *tsk, void __user * ufpregs)
+{
+ return -EFAULT;
+}
+
+/*
+ * Set the child FPU state.
+ */
+static int ptrace_setfpregs(struct task_struct *tsk, void __user * ufpregs)
+{
+ return -EFAULT;
+}
+
+/* do_ptrace()
+ *
+ * Provide ptrace defined service.
+ */
+long arch_ptrace(struct task_struct *child, long request, unsigned long addr,
+ unsigned long data)
+{
+ int ret;
+
+ switch (request) {
+ case PTRACE_PEEKUSR:
+ ret =
+ ptrace_read_user(child, addr, (unsigned long __user *)data);
+ break;
+
+ case PTRACE_POKEUSR:
+ ret = ptrace_write_user(child, addr, data);
+ break;
+
+ case PTRACE_GETREGS:
+ ret = ptrace_getregs(child, (void __user *)data);
+ break;
+
+ case PTRACE_SETREGS:
+ ret = ptrace_setregs(child, (void __user *)data);
+ break;
+
+ case PTRACE_GETFPREGS:
+ ret = ptrace_getfpregs(child, (void __user *)data);
+ break;
+
+ case PTRACE_SETFPREGS:
+ ret = ptrace_setfpregs(child, (void __user *)data);
+ break;
+
+ default:
+ ret = ptrace_request(child, request, addr, data);
+ break;
+ }
+
+ return ret;
+}
+
+void user_enable_single_step(struct task_struct *child)
+{
+ struct pt_regs *regs;
+ regs = task_pt_regs(child);
+ regs->ipsw |= PSW_mskHSS;
+ set_tsk_thread_flag(child, TIF_SINGLESTEP);
+}
+
+void user_disable_single_step(struct task_struct *child)
+{
+ struct pt_regs *regs;
+ regs = task_pt_regs(child);
+ regs->ipsw &= ~PSW_mskHSS;
+ clear_tsk_thread_flag(child, TIF_SINGLESTEP);
+}
+
+/* sys_trace()
+ *
+ * syscall trace handler.
+ */
+
+asmlinkage int syscall_trace_enter(int syscall, struct pt_regs *regs)
+{
+ if (test_thread_flag(TIF_SYSCALL_TRACE)) {
+ if (tracehook_report_syscall_entry(regs))
+ return -1;
+ }
+ return syscall;
+}
+
+asmlinkage void syscall_trace_leave(struct pt_regs *regs)
+{
+ int step = test_thread_flag(TIF_SINGLESTEP);
+ if (step || test_thread_flag(TIF_SYSCALL_TRACE))
+ tracehook_report_syscall_exit(regs, step);
+
+}
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 19/33] nds32: Library functions
From: Greentime Hu @ 2017-12-08 9:12 UTC (permalink / raw)
To: greentime-MUIXKm3Oiri1Z/+hSey0Gg,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, arnd-r2nGTMty4D4,
linux-arch-u79uwXL29TY76Z2rM5mHXA, tglx-hfZtesqFncYOwBW4kG4KsQ,
jason-NLaQJdtUoK4Be96aLqz0jA, marc.zyngier-5wv7dgnIgG8,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, netdev-u79uwXL29TY76Z2rM5mHXA,
deanbo422-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA,
viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
dhowells-H+wXaHxf7aLQT0dZR+AlfA, will.deacon-5wv7dgnIgG8,
daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A,
linux-serial-u79uwXL29TY76Z2rM5mHXA,
geert.uytterhoeven-Re5JQEeQqe8AvxtiuMwx3w,
linus.walleij-QSEj5FYQhm4dnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
greg-U8xfFu+wG4EAvxtiuMwx3w
Cc: green.hu-Re5JQEeQqe8AvxtiuMwx3w, Vincent Chen
In-Reply-To: <cover.1512723245.git.green.hu-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
From: Greentime Hu <greentime-MUIXKm3Oiri1Z/+hSey0Gg@public.gmane.org>
This patch add support for various library functions.
Signed-off-by: Vincent Chen <vincentc-MUIXKm3Oiri1Z/+hSey0Gg@public.gmane.org>
Signed-off-by: Greentime Hu <greentime-MUIXKm3Oiri1Z/+hSey0Gg@public.gmane.org>
---
arch/nds32/include/asm/string.h | 30 ++++
arch/nds32/include/asm/swab.h | 48 +++++++
arch/nds32/include/asm/uaccess.h | 296 ++++++++++++++++++++++++++++++++++++++
arch/nds32/kernel/nds32_ksyms.c | 44 ++++++
arch/nds32/lib/Makefile | 3 +
arch/nds32/lib/clear_user.S | 55 +++++++
arch/nds32/lib/copy_from_user.S | 58 ++++++++
arch/nds32/lib/copy_template.S | 83 +++++++++++
arch/nds32/lib/copy_to_user.S | 58 ++++++++
arch/nds32/lib/memcpy.S | 43 ++++++
arch/nds32/lib/memmove.S | 83 +++++++++++
arch/nds32/lib/memset.S | 46 ++++++
arch/nds32/lib/memzero.S | 31 ++++
13 files changed, 878 insertions(+)
create mode 100644 arch/nds32/include/asm/string.h
create mode 100644 arch/nds32/include/asm/swab.h
create mode 100644 arch/nds32/include/asm/uaccess.h
create mode 100644 arch/nds32/kernel/nds32_ksyms.c
create mode 100644 arch/nds32/lib/Makefile
create mode 100644 arch/nds32/lib/clear_user.S
create mode 100644 arch/nds32/lib/copy_from_user.S
create mode 100644 arch/nds32/lib/copy_template.S
create mode 100644 arch/nds32/lib/copy_to_user.S
create mode 100644 arch/nds32/lib/memcpy.S
create mode 100644 arch/nds32/lib/memmove.S
create mode 100644 arch/nds32/lib/memset.S
create mode 100644 arch/nds32/lib/memzero.S
diff --git a/arch/nds32/include/asm/string.h b/arch/nds32/include/asm/string.h
new file mode 100644
index 0000000..cf4d4b8
--- /dev/null
+++ b/arch/nds32/include/asm/string.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * 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_NDS32_STRING_H
+#define __ASM_NDS32_STRING_H
+
+#define __HAVE_ARCH_MEMCPY
+extern void *memcpy(void *, const void *, __kernel_size_t);
+
+#define __HAVE_ARCH_MEMMOVE
+extern void *memmove(void *, const void *, __kernel_size_t);
+
+#define __HAVE_ARCH_MEMSET
+extern void *memset(void *, int, __kernel_size_t);
+
+extern void *memzero(void *ptr, __kernel_size_t n);
+#endif
diff --git a/arch/nds32/include/asm/swab.h b/arch/nds32/include/asm/swab.h
new file mode 100644
index 0000000..4815d6a
--- /dev/null
+++ b/arch/nds32/include/asm/swab.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * 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 __NDS32_SWAB_H__
+#define __NDS32_SWAB_H__
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+
+static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
+{
+ __asm__("wsbh %0, %0\n\t" /* word swap byte within halfword */
+ "rotri %0, %0, #16\n"
+ :"=r"(x)
+ :"0"(x));
+ return x;
+}
+
+static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x)
+{
+ __asm__("wsbh %0, %0\n" /* word swap byte within halfword */
+ :"=r"(x)
+ :"0"(x));
+ return x;
+}
+
+#define __arch_swab32(x) ___arch__swab32(x)
+#define __arch_swab16(x) ___arch__swab16(x)
+
+#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+#define __BYTEORDER_HAS_U64__
+#define __SWAB_64_THRU_32__
+#endif
+
+#endif /* __NDS32_SWAB_H__ */
diff --git a/arch/nds32/include/asm/uaccess.h b/arch/nds32/include/asm/uaccess.h
new file mode 100644
index 0000000..3087523
--- /dev/null
+++ b/arch/nds32/include/asm/uaccess.h
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * 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 _ASMANDES_UACCESS_H
+#define _ASMANDES_UACCESS_H
+
+/*
+ * User space memory access functions
+ */
+#include <linux/sched.h>
+#include <asm/errno.h>
+#include <asm/memory.h>
+#include <asm/types.h>
+#include <linux/mm.h>
+
+#define VERIFY_READ 0
+#define VERIFY_WRITE 1
+
+#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t"
+
+/*
+ * The exception table consists of pairs of addresses: the first is the
+ * address of an instruction that is allowed to fault, and the second is
+ * the address at which the program should continue. No registers are
+ * modified, so it is entirely up to the continuation code to figure out
+ * what to do.
+ *
+ * All the routines below use bits of fixup code that are out of line
+ * with the main instruction path. This means when everything is well,
+ * we don't even have to jump over them. Further, they do not intrude
+ * on our cache or tlb entries.
+ */
+
+struct exception_table_entry {
+ unsigned long insn, fixup;
+};
+
+extern int fixup_exception(struct pt_regs *regs);
+
+#define KERNEL_DS ((mm_segment_t) { ~0UL })
+#define USER_DS ((mm_segment_t) {TASK_SIZE - 1})
+
+#define get_ds() (KERNEL_DS)
+#define get_fs() (current_thread_info()->addr_limit)
+#define user_addr_max get_fs
+
+static inline void set_fs(mm_segment_t fs)
+{
+ current_thread_info()->addr_limit = fs;
+}
+
+#define segment_eq(a, b) ((a) == (b))
+
+#define __range_ok(addr, size) (size <= get_fs() && addr <= (get_fs() -size))
+
+#define access_ok(type, addr, size) \
+ __range_ok((unsigned long)addr, (unsigned long)size)
+/*
+ * Single-value transfer routines. They automatically use the right
+ * size if we just have the right pointer type. Note that the functions
+ * which read from user space (*get_*) need to take care not to leak
+ * kernel data even if the calling code is buggy and fails to check
+ * the return value. This means zeroing out the destination variable
+ * or buffer on error. Normally this is done out of line by the
+ * fixup code, but there are a few places where it intrudes on the
+ * main code path. When we only write to user space, there is no
+ * problem.
+ *
+ * The "__xxx" versions of the user access functions do not verify the
+ * address space - it must have been done previously with a separate
+ * "access_ok()" call.
+ *
+ * The "xxx_error" versions set the third argument to EFAULT if an
+ * error occurs, and leave it unchanged on success. Note that these
+ * versions are void (ie, don't return a value as such).
+ */
+
+#define get_user(x,p) \
+({ \
+ long __e = -EFAULT; \
+ if(likely(access_ok(VERIFY_READ, p, sizeof(*p)))) { \
+ __e = __get_user(x,p); \
+ } else \
+ x = 0; \
+ __e; \
+})
+#define __get_user(x,ptr) \
+({ \
+ long __gu_err = 0; \
+ __get_user_err((x),(ptr),__gu_err); \
+ __gu_err; \
+})
+
+#define __get_user_error(x,ptr,err) \
+({ \
+ __get_user_err((x),(ptr),err); \
+ (void) 0; \
+})
+
+#define __get_user_err(x,ptr,err) \
+do { \
+ unsigned long __gu_addr = (unsigned long)(ptr); \
+ unsigned long __gu_val; \
+ __chk_user_ptr(ptr); \
+ switch (sizeof(*(ptr))) { \
+ case 1: \
+ __get_user_asm("lbi",__gu_val,__gu_addr,err); \
+ break; \
+ case 2: \
+ __get_user_asm("lhi",__gu_val,__gu_addr,err); \
+ break; \
+ case 4: \
+ __get_user_asm("lwi",__gu_val,__gu_addr,err); \
+ break; \
+ case 8: \
+ __get_user_asm_dword(__gu_val,__gu_addr,err); \
+ break; \
+ default: \
+ BUILD_BUG(); \
+ break; \
+ } \
+ (x) = (__typeof__(*(ptr)))__gu_val; \
+} while (0)
+
+#define __get_user_asm(inst,x,addr,err) \
+ asm volatile( \
+ "1: "inst" %1,[%2]\n" \
+ "2:\n" \
+ " .section .fixup,\"ax\"\n" \
+ " .align 2\n" \
+ "3: move %0, %3\n" \
+ " move %1, #0\n" \
+ " b 2b\n" \
+ " .previous\n" \
+ " .section __ex_table,\"a\"\n" \
+ " .align 3\n" \
+ " .long 1b, 3b\n" \
+ " .previous" \
+ : "+r" (err), "=&r" (x) \
+ : "r" (addr), "i" (-EFAULT) \
+ : "cc")
+
+#ifdef __NDS32_EB__
+#define __gu_reg_oper0 "%H1"
+#define __gu_reg_oper1 "%L1"
+#else
+#define __gu_reg_oper0 "%L1"
+#define __gu_reg_oper1 "%H1"
+#endif
+
+#define __get_user_asm_dword(x, addr, err) \
+ asm volatile( \
+ "\n1:\tlwi " __gu_reg_oper0 ",[%2]\n" \
+ "\n2:\tlwi " __gu_reg_oper1 ",[%2+4]\n" \
+ "3:\n" \
+ " .section .fixup,\"ax\"\n" \
+ " .align 2\n" \
+ "4: move %0, %3\n" \
+ " b 3b\n" \
+ " .previous\n" \
+ " .section __ex_table,\"a\"\n" \
+ " .align 3\n" \
+ " .long 1b, 4b\n" \
+ " .long 2b, 4b\n" \
+ " .previous" \
+ : "+r"(err), "=&r"(x) \
+ : "r"(addr), "i"(-EFAULT) \
+ : "cc")
+#define put_user(x,p) \
+({ \
+ long __e = -EFAULT; \
+ if(likely(access_ok(VERIFY_WRITE, p, sizeof(*p)))) { \
+ __e = __put_user(x,p); \
+ } \
+ __e; \
+})
+#define __put_user(x,ptr) \
+({ \
+ long __pu_err = 0; \
+ __put_user_err((x),(ptr),__pu_err); \
+ __pu_err; \
+})
+
+#define __put_user_error(x,ptr,err) \
+({ \
+ __put_user_err((x),(ptr),err); \
+ (void) 0; \
+})
+
+#define __put_user_err(x,ptr,err) \
+do { \
+ unsigned long __pu_addr = (unsigned long)(ptr); \
+ __typeof__(*(ptr)) __pu_val = (x); \
+ __chk_user_ptr(ptr); \
+ switch (sizeof(*(ptr))) { \
+ case 1: \
+ __put_user_asm("sbi",__pu_val,__pu_addr,err); \
+ break; \
+ case 2: \
+ __put_user_asm("shi",__pu_val,__pu_addr,err); \
+ break; \
+ case 4: \
+ __put_user_asm("swi",__pu_val,__pu_addr,err); \
+ break; \
+ case 8: \
+ __put_user_asm_dword(__pu_val,__pu_addr,err); \
+ break; \
+ default: \
+ BUILD_BUG(); \
+ break; \
+ } \
+} while (0)
+
+#define __put_user_asm(inst,x,addr,err) \
+ asm volatile( \
+ "1: "inst" %1,[%2]\n" \
+ "2:\n" \
+ " .section .fixup,\"ax\"\n" \
+ " .align 2\n" \
+ "3: move %0, %3\n" \
+ " b 2b\n" \
+ " .previous\n" \
+ " .section __ex_table,\"a\"\n" \
+ " .align 3\n" \
+ " .long 1b, 3b\n" \
+ " .previous" \
+ : "+r" (err) \
+ : "r" (x), "r" (addr), "i" (-EFAULT) \
+ : "cc")
+
+#ifdef __NDS32_EB__
+#define __pu_reg_oper0 "%H2"
+#define __pu_reg_oper1 "%L2"
+#else
+#define __pu_reg_oper0 "%L2"
+#define __pu_reg_oper1 "%H2"
+#endif
+
+#define __put_user_asm_dword(x, addr, err) \
+ asm volatile( \
+ "\n1:\tswi " __pu_reg_oper0 ",[%1]\n" \
+ "\n2:\tswi " __pu_reg_oper1 ",[%1+4]\n" \
+ "3:\n" \
+ " .section .fixup,\"ax\"\n" \
+ " .align 2\n" \
+ "4: move %0, %3\n" \
+ " b 3b\n" \
+ " .previous\n" \
+ " .section __ex_table,\"a\"\n" \
+ " .align 3\n" \
+ " .long 1b, 4b\n" \
+ " .long 2b, 4b\n" \
+ " .previous" \
+ : "+r"(err) \
+ : "r"(addr), "r"(x), "i"(-EFAULT) \
+ : "cc")
+extern unsigned long __arch_clear_user(void __user * addr, unsigned long n);
+extern long strncpy_from_user(char *dest, const char __user * src, long count);
+extern __must_check long strlen_user(const char __user * str);
+extern __must_check long strnlen_user(const char __user * str, long n);
+extern unsigned long __arch_copy_from_user(void *to, const void __user * from,
+ unsigned long n);
+extern unsigned long __arch_copy_to_user(void __user * to, const void *from,
+ unsigned long n);
+
+#define raw_copy_from_user __arch_copy_from_user
+#define raw_copy_to_user __arch_copy_to_user
+
+#define INLINE_COPY_FROM_USER
+#define INLINE_COPY_TO_USER
+static inline unsigned long clear_user(void __user * to, unsigned long n)
+{
+ if (access_ok(VERIFY_WRITE, to, n))
+ n = __arch_clear_user(to, n);
+ return n;
+}
+
+static inline unsigned long __clear_user(void __user * to, unsigned long n)
+{
+ return __arch_clear_user(to, n);
+}
+
+#endif /* _ASMNDS32_UACCESS_H */
diff --git a/arch/nds32/kernel/nds32_ksyms.c b/arch/nds32/kernel/nds32_ksyms.c
new file mode 100644
index 0000000..f8bbb18
--- /dev/null
+++ b/arch/nds32/kernel/nds32_ksyms.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/in6.h>
+#include <linux/syscalls.h>
+
+#include <asm/checksum.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/ftrace.h>
+#include <asm/proc-fns.h>
+
+/* mem functions */
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memzero);
+
+/* user mem (segment) */
+EXPORT_SYMBOL(__arch_copy_from_user);
+EXPORT_SYMBOL(__arch_copy_to_user);
+EXPORT_SYMBOL(__arch_clear_user);
+
+/* cache handling */
+EXPORT_SYMBOL(cpu_icache_inval_all);
+EXPORT_SYMBOL(cpu_dcache_wbinval_all);
+EXPORT_SYMBOL(cpu_dma_inval_range);
+EXPORT_SYMBOL(cpu_dma_wb_range);
diff --git a/arch/nds32/lib/Makefile b/arch/nds32/lib/Makefile
new file mode 100644
index 0000000..0f98401
--- /dev/null
+++ b/arch/nds32/lib/Makefile
@@ -0,0 +1,3 @@
+lib-y := copy_page.o memcpy.o memmove.o \
+ memset.o memzero.o \
+ copy_from_user.o copy_to_user.o clear_user.o
diff --git a/arch/nds32/lib/clear_user.S b/arch/nds32/lib/clear_user.S
new file mode 100644
index 0000000..279076a
--- /dev/null
+++ b/arch/nds32/lib/clear_user.S
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/errno.h>
+
+/* Prototype: int __arch_clear_user(void *addr, size_t sz)
+ * Purpose : clear some user memory
+ * Params : addr - user memory address to clear
+ * : sz - number of bytes to clear
+ * Returns : number of bytes NOT cleared
+ */
+ .text
+ .align 5
+ENTRY(__arch_clear_user)
+ add $r5, $r0, $r1
+ beqz $r1, clear_exit
+ xor $p1, $p1, $p1 ! Use $p1=0 to clear mem
+ srli $p0, $r1, #2 ! $p0 = number of word to clear
+ andi $r1, $r1, #3 ! Bytes less than a word to copy
+ beqz $p0, byte_clear ! Only less than a word to clear
+word_clear:
+USER( smw.bim,$p1, [$r0], $p1) ! Clear the word
+ addi $p0, $p0, #-1 ! Decrease word count
+ bnez $p0, word_clear ! Continue looping to clear all words
+ beqz $r1, clear_exit ! No left bytes to copy
+byte_clear:
+USER( sbi.bi, $p1, [$r0], #1) ! Clear the byte
+ addi $r1, $r1, #-1 ! Decrease byte count
+ bnez $r1, byte_clear ! Continue looping to clear all left bytes
+clear_exit:
+ move $r0, $r1 ! Set return value
+ ret
+
+ .section .fixup,"ax"
+ .align 0
+9001:
+ sub $r0, $r5, $r0 ! Bytes left to copy
+ ret
+ .previous
+ENDPROC(__arch_clear_user)
diff --git a/arch/nds32/lib/copy_from_user.S b/arch/nds32/lib/copy_from_user.S
new file mode 100644
index 0000000..8130ad5
--- /dev/null
+++ b/arch/nds32/lib/copy_from_user.S
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/errno.h>
+
+.macro lbi1 dst, addr, adj
+USER( lbi.bi, \dst, [\addr], \adj)
+.endm
+
+.macro sbi1 src, addr, adj
+sbi.bi \src, [\addr], \adj
+.endm
+
+.macro lmw1 start_reg, addr, end_reg
+USER( lmw.bim, \start_reg, [\addr], \end_reg)
+.endm
+
+.macro smw1 start_reg, addr, end_reg
+smw.bim \start_reg, [\addr], \end_reg
+.endm
+
+
+/* Prototype: int __arch_copy_from_user(void *to, const char *from, size_t n)
+ * Purpose : copy a block from user memory to kernel memory
+ * Params : to - kernel memory
+ * : from - user memory
+ * : n - number of bytes to copy
+ * Returns : Number of bytes NOT copied.
+ */
+
+.text
+ENTRY(__arch_copy_from_user)
+ add $r5, $r0, $r2
+#include "copy_template.S"
+ move $r0, $r2
+ ret
+.section .fixup,"ax"
+.align 2
+9001:
+ sub $r0, $r5, $r0
+ ret
+.previous
+ENDPROC(__arch_copy_from_user)
diff --git a/arch/nds32/lib/copy_template.S b/arch/nds32/lib/copy_template.S
new file mode 100644
index 0000000..3961ac2
--- /dev/null
+++ b/arch/nds32/lib/copy_template.S
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * 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/>.
+ */
+
+
+ beq $r1, $r0, quit_memcpy
+ beqz $r2, quit_memcpy
+ srli $r3, $r2, #5 ! check if len < cache-line size 32
+ beqz $r3, word_copy_entry
+ andi $r4, $r0, #0x3 ! check byte-align
+ beqz $r4, unalign_word_copy_entry
+
+ addi $r4, $r4,#-4
+ abs $r4, $r4 ! check how many un-align byte to copy
+ sub $r2, $r2, $r4 ! update $R2
+
+unalign_byte_copy:
+ lbi1 $r3, $r1, #1
+ addi $r4, $r4, #-1
+ sbi1 $r3, $r0, #1
+ bnez $r4, unalign_byte_copy
+ beqz $r2, quit_memcpy
+
+unalign_word_copy_entry:
+ andi $r3, $r0, 0x1f ! check cache-line unaligncount
+ beqz $r3, cache_copy
+
+ addi $r3, $r3, #-32
+ abs $r3, $r3
+ sub $r2, $r2, $r3 ! update $R2
+
+unalign_word_copy:
+ lmw1 $r4, $r1, $r4
+ addi $r3, $r3, #-4
+ smw1 $r4, $r0, $r4
+ bnez $r3, unalign_word_copy
+ beqz $r2, quit_memcpy
+
+ addi $r3, $r2, #-32 ! to check $r2< cache_line , than go to word_copy
+ bltz $r3, word_copy_entry
+cache_copy:
+ srli $r3, $r2, #5
+ beqz $r3, word_copy_entry
+3:
+ lmw1 $r17, $r1, $r24
+ addi $r3, $r3, #-1
+ smw1 $r17, $r0, $r24
+ bnez $r3, 3b
+
+word_copy_entry:
+ andi $r2, $r2, #31
+
+ beqz $r2, quit_memcpy
+5:
+ srli $r3, $r2, #2
+ beqz $r3, byte_copy
+word_copy:
+ lmw1 $r4, $r1, $r4
+ addi $r3, $r3, #-1
+ smw1 $r4, $r0, $r4
+ bnez $r3, word_copy
+ andi $r2, $r2, #3
+ beqz $r2, quit_memcpy
+byte_copy:
+ lbi1 $r3, $r1, #1
+ addi $r2, $r2, #-1
+
+ sbi1 $r3, $r0, #1
+ bnez $r2, byte_copy
+quit_memcpy:
+
diff --git a/arch/nds32/lib/copy_to_user.S b/arch/nds32/lib/copy_to_user.S
new file mode 100644
index 0000000..a030a8e
--- /dev/null
+++ b/arch/nds32/lib/copy_to_user.S
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/errno.h>
+
+.macro lbi1 dst, addr, adj
+lbi.bi \dst, [\addr], \adj
+.endm
+
+.macro sbi1 src, addr, adj
+USER( sbi.bi, \src, [\addr], \adj)
+.endm
+
+.macro lmw1 start_reg, addr, end_reg
+lmw.bim \start_reg, [\addr], \end_reg
+.endm
+
+.macro smw1 start_reg, addr, end_reg
+USER( smw.bim, \start_reg, [\addr], \end_reg)
+.endm
+
+
+/* Prototype: int __arch_copy_to_user(void *to, const char *from, size_t n)
+ * Purpose : copy a block to user memory from kernel memory
+ * Params : to - user memory
+ * : from - kernel memory
+ * : n - number of bytes to copy
+ * Returns : Number of bytes NOT copied.
+ */
+
+.text
+ENTRY(__arch_copy_to_user)
+ add $r5, $r0, $r2
+#include "copy_template.S"
+ move $r0, $r2
+ ret
+.section .fixup,"ax"
+.align 2
+9001:
+ sub $r0, $r5, $r0
+ ret
+.previous
+ENDPROC(__arch_copy_to_user)
diff --git a/arch/nds32/lib/memcpy.S b/arch/nds32/lib/memcpy.S
new file mode 100644
index 0000000..524878f
--- /dev/null
+++ b/arch/nds32/lib/memcpy.S
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+
+
+.macro lbi1 dst, addr, adj
+lbi.bi \dst, [\addr], \adj
+.endm
+
+.macro sbi1 src, addr, adj
+sbi.bi \src, [\addr], \adj
+.endm
+
+.macro lmw1 start_reg, addr, end_reg
+lmw.bim \start_reg, [\addr], \end_reg
+.endm
+
+.macro smw1 start_reg, addr, end_reg
+smw.bim \start_reg, [\addr], \end_reg
+.endm
+
+.text
+ENTRY(memcpy)
+ move $r5, $r0
+#include "copy_template.S"
+ move $r0, $r5
+ ret
+
+ENDPROC(memcpy)
diff --git a/arch/nds32/lib/memmove.S b/arch/nds32/lib/memmove.S
new file mode 100644
index 0000000..0c54350
--- /dev/null
+++ b/arch/nds32/lib/memmove.S
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+
+/*
+ void *memmove(void *dst, const void *src, int n);
+
+ dst: $r0
+ src: $r1
+ n : $r2
+ ret: $r0 - pointer to the memory area dst.
+*/
+ .text
+
+ENTRY(memmove)
+ move $r5, $r0 ! Set return value = det
+ beq $r0, $r1, exit_memcpy ! Exit when det = src
+ beqz $r2, exit_memcpy ! Exit when n = 0
+ pushm $t0, $t1 ! Save reg
+ srli $p1, $r2, #2 ! $p1 is how many words to copy
+
+ ! Avoid data lost when memory overlap
+ ! Copy data reversely when src < dst
+ slt $p0, $r0, $r1 ! check if $r0 < $r1
+ beqz $p0, do_reverse ! branch if dst > src
+
+ ! No reverse, dst < src
+ andi $r2, $r2, #3 ! How many bytes are less than a word
+ li $t0, #1 ! Determining copy direction in byte_cpy
+ beqz $p1, byte_cpy ! When n is less than a word
+
+word_cpy:
+ lmw.bim $p0, [$r1], $p0 ! Read a word from src
+ addi $p1, $p1, #-1 ! How many words left to copy
+ smw.bim $p0, [$r0], $p0 ! Copy the word to det
+ bnez $p1, word_cpy ! If remained words > 0
+ beqz $r2, end_memcpy ! No left bytes to copy
+ b byte_cpy
+
+do_reverse:
+ add $r0, $r0, $r2 ! Start with the end of $r0
+ add $r1, $r1, $r2 ! Start with the end of $r1
+ andi $r2, $r2, #3 ! How many bytes are less than a word
+ li $t0, #-1 ! Determining copy direction in byte_cpy
+ beqz $p1, reverse_byte_cpy ! When n is less than a word
+
+reverse_word_cpy:
+ lmw.adm $p0, [$r1], $p0 ! Read a word from src
+ addi $p1, $p1, #-1 ! How many words left to copy
+ smw.adm $p0, [$r0], $p0 ! Copy the word to det
+ bnez $p1, reverse_word_cpy ! If remained words > 0
+ beqz $r2, end_memcpy ! No left bytes to copy
+
+reverse_byte_cpy:
+ addi $r0, $r0, #-1
+ addi $r1, $r1, #-1
+byte_cpy: ! Less than 4 bytes to copy now
+ lb.bi $p0, [$r1], $t0 ! Read a byte from src
+ addi $r2, $r2, #-1 ! How many bytes left to copy
+ sb.bi $p0, [$r0], $t0 ! copy the byte to det
+ bnez $r2, byte_cpy ! If remained bytes > 0
+
+end_memcpy:
+ popm $t0, $t1
+exit_memcpy:
+ move $r0, $r5
+ ret
+
+ENDPROC(memmove)
diff --git a/arch/nds32/lib/memset.S b/arch/nds32/lib/memset.S
new file mode 100644
index 0000000..05ec352
--- /dev/null
+++ b/arch/nds32/lib/memset.S
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+
+ .text
+ENTRY(memset)
+ move $r5, $r0 ! Return value
+ beqz $r2, end_memset ! Exit when len = 0
+ srli $p1, $r2, 2 ! $p1 is how many words to copy
+ andi $r2, $r2, 3 ! How many bytes are less than a word
+ beqz $p1, byte_set ! When n is less than a word
+
+ ! set $r1 from ??????ab to abababab
+ andi $r1, $r1, #0x00ff ! $r1 = 000000ab
+ slli $p0, $r1, #8 ! $p0 = 0000ab00
+ or $r1, $r1, $p0 ! $r1 = 0000abab
+ slli $p0, $r1, #16 ! $p0 = abab0000
+ or $r1, $r1, $p0 ! $r1 = abababab
+word_set:
+ addi $p1, $p1, #-1 ! How many words left to copy
+ smw.bim $r1, [$r0], $r1 ! Copy the word to det
+ bnez $p1, word_set ! Still words to set, continue looping
+ beqz $r2, end_memset ! No left byte to set
+byte_set: ! Less than 4 bytes left to set
+ addi $r2, $r2, #-1 ! Decrease len by 1
+ sbi.bi $r1, [$r0], #1 ! Set data of the next byte to $r1
+ bnez $r2, byte_set ! Still bytes left to set
+end_memset:
+ move $r0, $r5
+ ret
+
+ENDPROC(memset)
diff --git a/arch/nds32/lib/memzero.S b/arch/nds32/lib/memzero.S
new file mode 100644
index 0000000..00c9996
--- /dev/null
+++ b/arch/nds32/lib/memzero.S
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+
+ .text
+ENTRY(memzero)
+ beqz $r1, 1f
+ push $lp
+ move $r2, $r1
+ move $r1, #0
+ push $r0
+ bal memset
+ pop $r0
+ pop $lp
+1:
+ ret
+ENDPROC(memzero)
--
1.7.9.5
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v3 18/33] nds32: Signal handling support
From: Greentime Hu @ 2017-12-08 9:12 UTC (permalink / raw)
To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
marc.zyngier, robh+dt, netdev, deanbo422, devicetree, viro,
dhowells, will.deacon, daniel.lezcano, linux-serial,
geert.uytterhoeven, linus.walleij, mark.rutland, greg
Cc: green.hu, Vincent Chen
In-Reply-To: <cover.1512723245.git.green.hu@gmail.com>
From: Greentime Hu <greentime@andestech.com>
This patch adds support for signal handling.
Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
arch/nds32/include/uapi/asm/sigcontext.h | 73 +++++++
arch/nds32/kernel/signal.c | 350 ++++++++++++++++++++++++++++++
2 files changed, 423 insertions(+)
create mode 100644 arch/nds32/include/uapi/asm/sigcontext.h
create mode 100644 arch/nds32/kernel/signal.c
diff --git a/arch/nds32/include/uapi/asm/sigcontext.h b/arch/nds32/include/uapi/asm/sigcontext.h
new file mode 100644
index 0000000..1c0dfcb
--- /dev/null
+++ b/arch/nds32/include/uapi/asm/sigcontext.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * 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 _ASMNDS32_SIGCONTEXT_H
+#define _ASMNDS32_SIGCONTEXT_H
+
+/*
+ * Signal context structure - contains all info to do with the state
+ * before the signal handler was invoked. Note: only add new entries
+ * to the end of the structure.
+ */
+
+struct zol_struct {
+ unsigned long nds32_lc; /* $LC */
+ unsigned long nds32_le; /* $LE */
+ unsigned long nds32_lb; /* $LB */
+};
+
+struct sigcontext {
+ unsigned long trap_no;
+ unsigned long error_code;
+ unsigned long oldmask;
+ unsigned long nds32_r0;
+ unsigned long nds32_r1;
+ unsigned long nds32_r2;
+ unsigned long nds32_r3;
+ unsigned long nds32_r4;
+ unsigned long nds32_r5;
+ unsigned long nds32_r6;
+ unsigned long nds32_r7;
+ unsigned long nds32_r8;
+ unsigned long nds32_r9;
+ unsigned long nds32_r10;
+ unsigned long nds32_r11;
+ unsigned long nds32_r12;
+ unsigned long nds32_r13;
+ unsigned long nds32_r14;
+ unsigned long nds32_r15;
+ unsigned long nds32_r16;
+ unsigned long nds32_r17;
+ unsigned long nds32_r18;
+ unsigned long nds32_r19;
+ unsigned long nds32_r20;
+ unsigned long nds32_r21;
+ unsigned long nds32_r22;
+ unsigned long nds32_r23;
+ unsigned long nds32_r24;
+ unsigned long nds32_r25;
+ unsigned long nds32_fp; /* $r28 */
+ unsigned long nds32_gp; /* $r29 */
+ unsigned long nds32_lp; /* $r30 */
+ unsigned long nds32_sp; /* $r31 */
+ unsigned long nds32_ipc;
+ unsigned long fault_address;
+ unsigned long used_math_flag;
+ /* FPU Registers */
+ struct zol_struct zol;
+};
+
+#endif
diff --git a/arch/nds32/kernel/signal.c b/arch/nds32/kernel/signal.c
new file mode 100644
index 0000000..f43248a
--- /dev/null
+++ b/arch/nds32/kernel/signal.c
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/ptrace.h>
+#include <linux/personality.h>
+#include <linux/freezer.h>
+#include <linux/tracehook.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <asm/ucontext.h>
+#include <asm/unistd.h>
+
+#include <asm/ptrace.h>
+#include <asm/vdso.h>
+
+struct rt_sigframe {
+ struct siginfo info;
+ struct ucontext uc;
+};
+
+static int restore_sigframe(struct pt_regs *regs,
+ struct rt_sigframe __user * sf)
+{
+ sigset_t set;
+ int err;
+
+ err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
+ if (err == 0) {
+ set_current_blocked(&set);
+ }
+
+ __get_user_error(regs->uregs[0], &sf->uc.uc_mcontext.nds32_r0, err);
+ __get_user_error(regs->uregs[1], &sf->uc.uc_mcontext.nds32_r1, err);
+ __get_user_error(regs->uregs[2], &sf->uc.uc_mcontext.nds32_r2, err);
+ __get_user_error(regs->uregs[3], &sf->uc.uc_mcontext.nds32_r3, err);
+ __get_user_error(regs->uregs[4], &sf->uc.uc_mcontext.nds32_r4, err);
+ __get_user_error(regs->uregs[5], &sf->uc.uc_mcontext.nds32_r5, err);
+ __get_user_error(regs->uregs[6], &sf->uc.uc_mcontext.nds32_r6, err);
+ __get_user_error(regs->uregs[7], &sf->uc.uc_mcontext.nds32_r7, err);
+ __get_user_error(regs->uregs[8], &sf->uc.uc_mcontext.nds32_r8, err);
+ __get_user_error(regs->uregs[9], &sf->uc.uc_mcontext.nds32_r9, err);
+ __get_user_error(regs->uregs[10], &sf->uc.uc_mcontext.nds32_r10, err);
+ __get_user_error(regs->uregs[11], &sf->uc.uc_mcontext.nds32_r11, err);
+ __get_user_error(regs->uregs[12], &sf->uc.uc_mcontext.nds32_r12, err);
+ __get_user_error(regs->uregs[13], &sf->uc.uc_mcontext.nds32_r13, err);
+ __get_user_error(regs->uregs[14], &sf->uc.uc_mcontext.nds32_r14, err);
+ __get_user_error(regs->uregs[15], &sf->uc.uc_mcontext.nds32_r15, err);
+ __get_user_error(regs->uregs[16], &sf->uc.uc_mcontext.nds32_r16, err);
+ __get_user_error(regs->uregs[17], &sf->uc.uc_mcontext.nds32_r17, err);
+ __get_user_error(regs->uregs[18], &sf->uc.uc_mcontext.nds32_r18, err);
+ __get_user_error(regs->uregs[19], &sf->uc.uc_mcontext.nds32_r19, err);
+ __get_user_error(regs->uregs[20], &sf->uc.uc_mcontext.nds32_r20, err);
+ __get_user_error(regs->uregs[21], &sf->uc.uc_mcontext.nds32_r21, err);
+ __get_user_error(regs->uregs[22], &sf->uc.uc_mcontext.nds32_r22, err);
+ __get_user_error(regs->uregs[23], &sf->uc.uc_mcontext.nds32_r23, err);
+ __get_user_error(regs->uregs[24], &sf->uc.uc_mcontext.nds32_r24, err);
+ __get_user_error(regs->uregs[25], &sf->uc.uc_mcontext.nds32_r25, err);
+
+ __get_user_error(regs->fp, &sf->uc.uc_mcontext.nds32_fp, err);
+ __get_user_error(regs->gp, &sf->uc.uc_mcontext.nds32_gp, err);
+ __get_user_error(regs->lp, &sf->uc.uc_mcontext.nds32_lp, err);
+ __get_user_error(regs->sp, &sf->uc.uc_mcontext.nds32_sp, err);
+ __get_user_error(regs->ipc, &sf->uc.uc_mcontext.nds32_ipc, err);
+#if defined(CONFIG_HWZOL)
+ __get_user_error(regs->lc, &sf->uc.uc_mcontext.zol.nds32_lc, err);
+ __get_user_error(regs->le, &sf->uc.uc_mcontext.zol.nds32_le, err);
+ __get_user_error(regs->lb, &sf->uc.uc_mcontext.zol.nds32_lb, err);
+#endif
+
+ return err;
+}
+
+asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
+{
+ struct rt_sigframe __user *frame;
+
+ /* Always make any pending restarted system calls return -EINTR */
+ current->restart_block.fn = do_no_restart_syscall;
+
+ /*
+ * Since we stacked the signal on a 64-bit boundary,
+ * then 'sp' should be two-word aligned here. If it's
+ * not, then the user is trying to mess with us.
+ */
+ if (regs->sp & 7)
+ goto badframe;
+
+ frame = (struct rt_sigframe __user *)regs->sp;
+
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+
+ if (restore_sigframe(regs, frame))
+ goto badframe;
+
+ if (restore_altstack(&frame->uc.uc_stack))
+ goto badframe;
+
+ return regs->uregs[0];
+
+badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+}
+
+static int
+setup_sigframe(struct rt_sigframe __user * sf, struct pt_regs *regs,
+ sigset_t * set)
+{
+ int err = 0;
+
+
+ __put_user_error(regs->uregs[0], &sf->uc.uc_mcontext.nds32_r0, err);
+ __put_user_error(regs->uregs[1], &sf->uc.uc_mcontext.nds32_r1, err);
+ __put_user_error(regs->uregs[2], &sf->uc.uc_mcontext.nds32_r2, err);
+ __put_user_error(regs->uregs[3], &sf->uc.uc_mcontext.nds32_r3, err);
+ __put_user_error(regs->uregs[4], &sf->uc.uc_mcontext.nds32_r4, err);
+ __put_user_error(regs->uregs[5], &sf->uc.uc_mcontext.nds32_r5, err);
+ __put_user_error(regs->uregs[6], &sf->uc.uc_mcontext.nds32_r6, err);
+ __put_user_error(regs->uregs[7], &sf->uc.uc_mcontext.nds32_r7, err);
+ __put_user_error(regs->uregs[8], &sf->uc.uc_mcontext.nds32_r8, err);
+ __put_user_error(regs->uregs[9], &sf->uc.uc_mcontext.nds32_r9, err);
+ __put_user_error(regs->uregs[10], &sf->uc.uc_mcontext.nds32_r10, err);
+ __put_user_error(regs->uregs[11], &sf->uc.uc_mcontext.nds32_r11, err);
+ __put_user_error(regs->uregs[12], &sf->uc.uc_mcontext.nds32_r12, err);
+ __put_user_error(regs->uregs[13], &sf->uc.uc_mcontext.nds32_r13, err);
+ __put_user_error(regs->uregs[14], &sf->uc.uc_mcontext.nds32_r14, err);
+ __put_user_error(regs->uregs[15], &sf->uc.uc_mcontext.nds32_r15, err);
+ __put_user_error(regs->uregs[16], &sf->uc.uc_mcontext.nds32_r16, err);
+ __put_user_error(regs->uregs[17], &sf->uc.uc_mcontext.nds32_r17, err);
+ __put_user_error(regs->uregs[18], &sf->uc.uc_mcontext.nds32_r18, err);
+ __put_user_error(regs->uregs[19], &sf->uc.uc_mcontext.nds32_r19, err);
+ __put_user_error(regs->uregs[20], &sf->uc.uc_mcontext.nds32_r20, err);
+
+ __put_user_error(regs->uregs[21], &sf->uc.uc_mcontext.nds32_r21, err);
+ __put_user_error(regs->uregs[22], &sf->uc.uc_mcontext.nds32_r22, err);
+ __put_user_error(regs->uregs[23], &sf->uc.uc_mcontext.nds32_r23, err);
+ __put_user_error(regs->uregs[24], &sf->uc.uc_mcontext.nds32_r24, err);
+ __put_user_error(regs->uregs[25], &sf->uc.uc_mcontext.nds32_r25, err);
+ __put_user_error(regs->fp, &sf->uc.uc_mcontext.nds32_fp, err);
+ __put_user_error(regs->gp, &sf->uc.uc_mcontext.nds32_gp, err);
+ __put_user_error(regs->lp, &sf->uc.uc_mcontext.nds32_lp, err);
+ __put_user_error(regs->sp, &sf->uc.uc_mcontext.nds32_sp, err);
+ __put_user_error(regs->ipc, &sf->uc.uc_mcontext.nds32_ipc, err);
+#if defined(CONFIG_HWZOL)
+ __put_user_error(regs->lc, &sf->uc.uc_mcontext.zol.nds32_lc, err);
+ __put_user_error(regs->le, &sf->uc.uc_mcontext.zol.nds32_le, err);
+ __put_user_error(regs->lb, &sf->uc.uc_mcontext.zol.nds32_lb, err);
+#endif
+
+ __put_user_error(current->thread.trap_no, &sf->uc.uc_mcontext.trap_no,
+ err);
+ __put_user_error(current->thread.error_code,
+ &sf->uc.uc_mcontext.error_code, err);
+ __put_user_error(current->thread.address,
+ &sf->uc.uc_mcontext.fault_address, err);
+ __put_user_error(set->sig[0], &sf->uc.uc_mcontext.oldmask, err);
+
+ err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));
+
+ return err;
+}
+
+static inline void __user *get_sigframe(struct ksignal *ksig,
+ struct pt_regs *regs, int framesize)
+{
+ unsigned long sp = sigsp(regs->sp, ksig);
+ void __user *frame;
+
+ /*
+ * nds32 mandates 8-byte alignment
+ */
+ frame = (void __user *)((sp - framesize) & ~7);
+
+ /*
+ * Check that we can actually write to the signal frame.
+ */
+ if (!access_ok(VERIFY_WRITE, frame, framesize))
+ frame = NULL;
+
+ return frame;
+}
+
+static int
+setup_return(struct pt_regs *regs, struct ksignal *ksig, void __user * frame)
+{
+ unsigned long handler = (unsigned long)ksig->ka.sa.sa_handler;
+ unsigned long retcode;
+
+ retcode = VDSO_SYMBOL(current->mm->context.vdso, rt_sigtramp);
+ regs->uregs[0] = ksig->sig;
+ regs->sp = (unsigned long)frame;
+ regs->lp = retcode;
+ regs->ipc = handler;
+
+ return 0;
+}
+
+static int
+setup_rt_frame(struct ksignal *ksig, sigset_t * set, struct pt_regs *regs)
+{
+ struct rt_sigframe __user *frame =
+ get_sigframe(ksig, regs, sizeof(*frame));
+ int err = 0;
+
+ if (!frame)
+ return 1;
+
+ err |= copy_siginfo_to_user(&frame->info, &ksig->info);
+
+ __put_user_error(0, &frame->uc.uc_flags, err);
+ __put_user_error(NULL, &frame->uc.uc_link, err);
+
+ err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
+ err |= setup_sigframe(frame, regs, set);
+ if (err == 0) {
+ setup_return(regs, ksig, frame);
+
+ if (err == 0) {
+ /*
+ * For realtime signals we must also set the second and third
+ * arguments for the signal handler.
+ * -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06
+ */
+ regs->uregs[1] = (unsigned long)&frame->info;
+ regs->uregs[2] = (unsigned long)&frame->uc;
+ }
+ }
+ return err;
+}
+
+/*
+ * OK, we're invoking a handler
+ */
+static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
+{
+ int ret;
+ sigset_t *oldset = sigmask_to_save();
+
+ /*
+ * Set up the stack frame
+ */
+ ret = setup_rt_frame(ksig, oldset, regs);
+
+ /*
+ * Check that the resulting registers are actually sane.
+ */
+ ret |= !valid_user_regs(regs);
+
+ signal_setup_done(ret, ksig, 0);
+}
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ *
+ * Note that we go through the signals twice: once to check the signals that
+ * the kernel can handle, and then we build all the user-level signal handling
+ * stack-frames in one go after that.
+ */
+static int do_signal(struct pt_regs *regs, int syscall)
+{
+ unsigned int retval = 0, continue_addr = 0, restart_addr = 0;
+ struct ksignal ksig;
+ int restart = 0;
+
+ /*
+ * If we were from a system call, check for system call restarting...
+ */
+ if (syscall) {
+ continue_addr = regs->ipc;
+ restart_addr = continue_addr - 4;
+ retval = regs->uregs[0];
+
+ /*
+ * Prepare for system call restart. We do this here so that a
+ * debugger will see the already changed PSW.
+ */
+ switch (retval) {
+ case -ERESTART_RESTARTBLOCK:
+ restart -= 2;
+ case -ERESTARTNOHAND:
+ case -ERESTARTSYS:
+ case -ERESTARTNOINTR:
+ restart++;
+ regs->uregs[0] = regs->orig_r0;
+ regs->ipc = restart_addr;
+ break;
+ }
+ }
+
+ /*
+ * Get the signal to deliver. When running under ptrace, at this
+ * point the debugger may change all our registers ...
+ */
+ /*
+ * Depending on the signal settings we may need to revert the
+ * decision to restart the system call. But skip this if a
+ * debugger has chosen to restart at a different PC.
+ */
+ if (get_signal(&ksig)) {
+ if (unlikely(restart) && regs->ipc == restart_addr) {
+ if (retval == -ERESTARTNOHAND ||
+ retval == -ERESTART_RESTARTBLOCK
+ || (retval == -ERESTARTSYS
+ && !(ksig.ka.sa.sa_flags & SA_RESTART))) {
+ regs->uregs[0] = -EINTR;
+ regs->ipc = continue_addr;
+ }
+ }
+ handle_signal(&ksig, regs);
+ } else {
+ restore_saved_sigmask();
+ if (unlikely(restart) && regs->ipc == restart_addr) {
+ regs->ipc = continue_addr;
+ return restart;
+ }
+ }
+ return 0;
+}
+
+asmlinkage int
+do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall)
+{
+ if (thread_flags & _TIF_SIGPENDING)
+ return do_signal(regs, syscall);
+
+ if (thread_flags & _TIF_NOTIFY_RESUME) {
+ clear_thread_flag(TIF_NOTIFY_RESUME);
+ tracehook_notify_resume(regs);
+ }
+ return 0;
+}
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 17/33] nds32: VDSO support
From: Greentime Hu @ 2017-12-08 9:12 UTC (permalink / raw)
To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
marc.zyngier, robh+dt, netdev, deanbo422, devicetree, viro,
dhowells, will.deacon, daniel.lezcano, linux-serial,
geert.uytterhoeven, linus.walleij, mark.rutland, greg
Cc: green.hu, Vincent Chen
In-Reply-To: <cover.1512723245.git.green.hu@gmail.com>
From: Greentime Hu <greentime@andestech.com>
This patch adds VDSO support. The VDSO code is currently used for
sys_rt_sigreturn() and optimised gettimeofday() (using the SoC timer counter).
Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
arch/nds32/include/asm/vdso.h | 35 ++++
arch/nds32/include/asm/vdso_datapage.h | 51 ++++++
arch/nds32/kernel/vdso.c | 245 +++++++++++++++++++++++++
arch/nds32/kernel/vdso/Makefile | 82 +++++++++
arch/nds32/kernel/vdso/datapage.S | 34 ++++
arch/nds32/kernel/vdso/gen_vdso_offsets.sh | 15 ++
arch/nds32/kernel/vdso/gettimeofday.c | 266 ++++++++++++++++++++++++++++
arch/nds32/kernel/vdso/note.S | 29 +++
arch/nds32/kernel/vdso/sigreturn.S | 36 ++++
arch/nds32/kernel/vdso/vdso.S | 33 ++++
arch/nds32/kernel/vdso/vdso.lds.S | 87 +++++++++
11 files changed, 913 insertions(+)
create mode 100644 arch/nds32/include/asm/vdso.h
create mode 100644 arch/nds32/include/asm/vdso_datapage.h
create mode 100644 arch/nds32/kernel/vdso.c
create mode 100644 arch/nds32/kernel/vdso/Makefile
create mode 100644 arch/nds32/kernel/vdso/datapage.S
create mode 100755 arch/nds32/kernel/vdso/gen_vdso_offsets.sh
create mode 100644 arch/nds32/kernel/vdso/gettimeofday.c
create mode 100644 arch/nds32/kernel/vdso/note.S
create mode 100644 arch/nds32/kernel/vdso/sigreturn.S
create mode 100644 arch/nds32/kernel/vdso/vdso.S
create mode 100644 arch/nds32/kernel/vdso/vdso.lds.S
diff --git a/arch/nds32/include/asm/vdso.h b/arch/nds32/include/asm/vdso.h
new file mode 100644
index 0000000..7298c49
--- /dev/null
+++ b/arch/nds32/include/asm/vdso.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_VDSO_H
+#define __ASM_VDSO_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+
+#include <generated/vdso-offsets.h>
+
+#define VDSO_SYMBOL(base, name) \
+({ \
+ (unsigned long)(vdso_offset_##name + (unsigned long)(base)); \
+})
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_VDSO_H */
diff --git a/arch/nds32/include/asm/vdso_datapage.h b/arch/nds32/include/asm/vdso_datapage.h
new file mode 100644
index 0000000..ffae33c
--- /dev/null
+++ b/arch/nds32/include/asm/vdso_datapage.h
@@ -0,0 +1,51 @@
+/*
+ * Adapted from arm64 version.
+ *
+ * Copyright (C) 2012 ARM Limited
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_VDSO_DATAPAGE_H
+#define __ASM_VDSO_DATAPAGE_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+
+struct vdso_data {
+ bool cycle_count_down; /* timer cyclye counter is decrease with time */
+ u32 cycle_count_offset; /* offset of timer cycle counter register */
+ u32 seq_count; /* sequence count - odd during updates */
+ u32 xtime_coarse_sec; /* coarse time */
+ u32 xtime_coarse_nsec;
+
+ u32 wtm_clock_sec; /* wall to monotonic offset */
+ u32 wtm_clock_nsec;
+ u32 xtime_clock_sec; /* CLOCK_REALTIME - seconds */
+ u32 cs_mult; /* clocksource multiplier */
+ u32 cs_shift; /* Cycle to nanosecond divisor (power of two) */
+
+ u64 cs_cycle_last; /* last cycle value */
+ u64 cs_mask; /* clocksource mask */
+
+ u64 xtime_clock_nsec; /* CLOCK_REALTIME sub-ns base */
+ u32 tz_minuteswest; /* timezone info for gettimeofday(2) */
+ u32 tz_dsttime;
+};
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_VDSO_DATAPAGE_H */
diff --git a/arch/nds32/kernel/vdso.c b/arch/nds32/kernel/vdso.c
new file mode 100644
index 0000000..258c8a7
--- /dev/null
+++ b/arch/nds32/kernel/vdso.c
@@ -0,0 +1,245 @@
+/*
+ * VDSO implementation for AArch64 and vector page setup for AArch32.
+ *
+ * Copyright (C) 2012 ARM Limited
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
+#include <linux/cache.h>
+#include <linux/clocksource.h>
+#include <linux/elf.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/gfp.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/slab.h>
+#include <linux/timekeeper_internal.h>
+#include <linux/vmalloc.h>
+
+#include <linux/platform_device.h>
+#include <linux/of_address.h>
+#include <asm/cacheflush.h>
+#include <asm/vdso.h>
+#include <asm/vdso_datapage.h>
+#include <linux/random.h>
+#include <asm/cache_info.h>
+extern struct cache_info L1_cache_info[2];
+extern char vdso_start, vdso_end;
+static unsigned long vdso_pages __ro_after_init;
+struct resource timer_res;
+
+/*
+ * The vDSO data page.
+ */
+static struct page *no_pages[] = { NULL };
+
+static union {
+ struct vdso_data data;
+ u8 page[PAGE_SIZE];
+} vdso_data_store __page_aligned_data;
+struct vdso_data *vdso_data = &vdso_data_store.data;
+static struct vm_special_mapping vdso_spec[2] __ro_after_init = {
+ {
+ .name = "[vvar]",
+ .pages = no_pages,
+ },
+ {
+ .name = "[vdso]",
+ },
+};
+
+static int grab_timer_node_info(void)
+{
+ struct device_node *timer_node;
+
+ timer_node = of_find_node_by_name(NULL, "timer");
+ of_property_read_u32(timer_node, "cycle-count-offset",
+ &vdso_data->cycle_count_offset);
+ vdso_data->cycle_count_down =
+ of_property_read_bool(timer_node, "cycle-count-down");
+ return of_address_to_resource(timer_node, 0, &timer_res);
+}
+
+static int __init vdso_init(void)
+{
+ int i;
+ struct page **vdso_pagelist;
+
+ if (memcmp(&vdso_start, "\177ELF", 4)) {
+ pr_err("vDSO is not a valid ELF object!\n");
+ return -EINVAL;
+ }
+ /* Creat a timer io mapping to get clock cycles counter */
+ if (grab_timer_node_info())
+ return -ENODEV;
+
+ vdso_pages = (&vdso_end - &vdso_start) >> PAGE_SHIFT;
+ pr_info("vdso: %ld pages (%ld code @ %p, %ld data @ %p)\n",
+ vdso_pages + 1, vdso_pages, &vdso_start, 1L, vdso_data);
+
+ /* Allocate the vDSO pagelist */
+ vdso_pagelist = kcalloc(vdso_pages, sizeof(struct page *), GFP_KERNEL);
+ if (vdso_pagelist == NULL)
+ return -ENOMEM;
+
+ for (i = 0; i < vdso_pages; i++)
+ vdso_pagelist[i] = virt_to_page(&vdso_start + i * PAGE_SIZE);
+ vdso_spec[1].pages = &vdso_pagelist[0];
+
+ return 0;
+}
+
+arch_initcall(vdso_init);
+
+unsigned long inline vdso_random_addr(unsigned long vdso_mapping_len)
+{
+ unsigned long start = current->mm->mmap_base, end, offset, addr;
+ start = PAGE_ALIGN(start);
+
+ /* Round the lowest possible end address up to a PMD boundary. */
+ end = (start + vdso_mapping_len + PMD_SIZE - 1) & PMD_MASK;
+ if (end >= TASK_SIZE)
+ end = TASK_SIZE;
+ end -= vdso_mapping_len;
+
+ if (end > start) {
+ offset = get_random_int() % (((end - start) >> PAGE_SHIFT) + 1);
+ addr = start + (offset << PAGE_SHIFT);
+ } else {
+ addr = start;
+ }
+ return addr;
+}
+
+int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+{
+ struct mm_struct *mm = current->mm;
+ unsigned long vdso_base, vdso_text_len, vdso_mapping_len;
+ struct vm_area_struct *vma;
+ unsigned long addr = 0;
+ pgprot_t prot;
+ int ret;
+
+ vdso_text_len = vdso_pages << PAGE_SHIFT;
+ /* Be sure to map the data page */
+ vdso_mapping_len = vdso_text_len + 2 * PAGE_SIZE;
+#ifdef CONFIG_CPU_CACHE_ALIASING
+ vdso_mapping_len += L1_cache_info[DCACHE].aliasing_num - 1;
+#endif
+
+ if (down_write_killable(&mm->mmap_sem))
+ return -EINTR;
+
+ addr = vdso_random_addr(vdso_mapping_len);
+ vdso_base = get_unmapped_area(NULL, addr, vdso_mapping_len, 0, 0);
+ if (IS_ERR_VALUE(vdso_base)) {
+ ret = vdso_base;
+ goto up_fail;
+ }
+
+#ifdef CONFIG_CPU_CACHE_ALIASING
+ {
+ unsigned int aliasing_mask =
+ L1_cache_info[DCACHE].aliasing_mask;
+ unsigned int page_colour_ofs;
+ page_colour_ofs = ((unsigned int)vdso_data & aliasing_mask) -
+ (vdso_base & aliasing_mask);
+ vdso_base += page_colour_ofs & aliasing_mask;
+ }
+#endif
+
+ vma = _install_special_mapping(mm, vdso_base, 2 * PAGE_SIZE,
+ VM_READ | VM_MAYREAD, &vdso_spec[0]);
+ if (IS_ERR(vma)) {
+ ret = PTR_ERR(vma);
+ goto up_fail;
+ }
+
+ /*Map vdata to user space */
+ ret = io_remap_pfn_range(vma, vdso_base,
+ virt_to_phys(vdso_data) >> PAGE_SHIFT,
+ PAGE_SIZE, vma->vm_page_prot);
+ if (ret)
+ goto up_fail;
+
+ /*Map timer to user space */
+ vdso_base += PAGE_SIZE;
+ prot = __pgprot(_PAGE_V | _PAGE_M_UR_KR | _PAGE_D |
+ _PAGE_G | _PAGE_C_DEV);
+ ret = io_remap_pfn_range(vma, vdso_base, timer_res.start >> PAGE_SHIFT,
+ PAGE_SIZE, prot);
+ if (ret)
+ goto up_fail;
+
+ /*Map vdso to user space */
+ vdso_base += PAGE_SIZE;
+ mm->context.vdso = (void *)vdso_base;
+ vma = _install_special_mapping(mm, vdso_base, vdso_text_len,
+ VM_READ | VM_EXEC |
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
+ &vdso_spec[1]);
+ if (IS_ERR(vma)) {
+ ret = PTR_ERR(vma);
+ goto up_fail;
+ }
+
+ up_write(&mm->mmap_sem);
+ return 0;
+
+up_fail:
+ mm->context.vdso = NULL;
+ up_write(&mm->mmap_sem);
+ return ret;
+}
+
+static void vdso_write_begin(struct vdso_data *vdata)
+{
+ ++vdso_data->seq_count;
+ smp_wmb(); /* Pairs with smp_rmb in vdso_read_retry */
+}
+
+static void vdso_write_end(struct vdso_data *vdata)
+{
+ smp_wmb(); /* Pairs with smp_rmb in vdso_read_begin */
+ ++vdso_data->seq_count;
+}
+
+void update_vsyscall(struct timekeeper *tk)
+{
+ vdso_write_begin(vdso_data);
+ vdso_data->cs_mask = tk->tkr_mono.mask;
+ vdso_data->cs_mult = tk->tkr_mono.mult;
+ vdso_data->cs_shift = tk->tkr_mono.shift;
+ vdso_data->cs_cycle_last = tk->tkr_mono.cycle_last;
+ vdso_data->wtm_clock_sec = tk->wall_to_monotonic.tv_sec;
+ vdso_data->wtm_clock_nsec = tk->wall_to_monotonic.tv_nsec;
+ vdso_data->xtime_clock_sec = tk->xtime_sec;
+ vdso_data->xtime_clock_nsec = tk->tkr_mono.xtime_nsec;
+ vdso_data->xtime_coarse_sec = tk->xtime_sec;
+ vdso_data->xtime_coarse_nsec = tk->tkr_mono.xtime_nsec >>
+ tk->tkr_mono.shift;
+ vdso_write_end(vdso_data);
+}
+
+void update_vsyscall_tz(void)
+{
+ vdso_data->tz_minuteswest = sys_tz.tz_minuteswest;
+ vdso_data->tz_dsttime = sys_tz.tz_dsttime;
+}
diff --git a/arch/nds32/kernel/vdso/Makefile b/arch/nds32/kernel/vdso/Makefile
new file mode 100644
index 0000000..e6c50a7
--- /dev/null
+++ b/arch/nds32/kernel/vdso/Makefile
@@ -0,0 +1,82 @@
+#
+# Building a vDSO image for AArch64.
+#
+# Author: Will Deacon <will.deacon@arm.com>
+# Heavily based on the vDSO Makefiles for other archs.
+#
+
+obj-vdso := note.o datapage.o sigreturn.o gettimeofday.o
+
+# Build rules
+targets := $(obj-vdso) vdso.so vdso.so.dbg
+obj-vdso := $(addprefix $(obj)/, $(obj-vdso))
+
+ccflags-y := -shared -fno-common -fno-builtin
+ccflags-y += -nostdlib -Wl,-soname=linux-vdso.so.1 \
+ $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
+ccflags-y += -fPIC -Wl,-shared -g
+
+# Disable gcov profiling for VDSO code
+GCOV_PROFILE := n
+
+
+obj-y += vdso.o
+extra-y += vdso.lds
+CPPFLAGS_vdso.lds += -P -C -U$(ARCH)
+
+# Force dependency
+$(obj)/vdso.o : $(obj)/vdso.so
+
+# Link rule for the .so file, .lds has to be first
+$(obj)/vdso.so.dbg: $(src)/vdso.lds $(obj-vdso)
+ $(call if_changed,vdsold)
+
+
+# Strip rule for the .so file
+$(obj)/%.so: OBJCOPYFLAGS := -S
+$(obj)/%.so: $(obj)/%.so.dbg FORCE
+ $(call if_changed,objcopy)
+
+# Generate VDSO offsets using helper script
+gen-vdsosym := $(srctree)/$(src)/gen_vdso_offsets.sh
+quiet_cmd_vdsosym = VDSOSYM $@
+define cmd_vdsosym
+ $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@
+endef
+
+include/generated/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE
+ $(call if_changed,vdsosym)
+
+
+
+# Assembly rules for the .S files
+
+sigreturn.o : sigreturn.S
+ $(call if_changed_dep,vdsoas)
+
+note.o : note.S
+ $(call if_changed_dep,vdsoas)
+
+datapage.o : datapage.S
+ $(call if_changed_dep,vdsoas)
+
+gettimeofday.o : gettimeofday.c FORCE
+ $(call if_changed_dep,vdsocc)
+
+# Actual build commands
+quiet_cmd_vdsold = VDSOL $@
+ cmd_vdsold = $(CC) $(c_flags) -Wl,-n -Wl,-T $^ -o $@
+quiet_cmd_vdsoas = VDSOA $@
+ cmd_vdsoas = $(CC) $(a_flags) -c -o $@ $<
+quiet_cmd_vdsocc = VDSOA $@
+ cmd_vdsocc = $(CC) $(c_flags) -c -o $@ $<
+
+# Install commands for the unstripped file
+quiet_cmd_vdso_install = INSTALL $@
+ cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
+
+vdso.so: $(obj)/vdso.so.dbg
+ @mkdir -p $(MODLIB)/vdso
+ $(call cmd,vdso_install)
+
+vdso_install: vdso.so
diff --git a/arch/nds32/kernel/vdso/datapage.S b/arch/nds32/kernel/vdso/datapage.S
new file mode 100644
index 0000000..d86af66
--- /dev/null
+++ b/arch/nds32/kernel/vdso/datapage.S
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <asm/page.h>
+
+ENTRY(__get_timerpage)
+ sethi $r0, hi20(. + PAGE_SIZE + 8)
+ ori $r0, $r0, lo12(. + PAGE_SIZE + 4)
+ mfusr $r1, $pc
+ sub $r0, $r1, $r0
+ ret
+ENDPROC(__get_timerpage)
+
+ENTRY(__get_datapage)
+ sethi $r0, hi20(. + 2*PAGE_SIZE + 8)
+ ori $r0, $r0, lo12(. + 2*PAGE_SIZE + 4)
+ mfusr $r1, $pc
+ sub $r0, $r1, $r0
+ ret
+ENDPROC(__get_datapage)
diff --git a/arch/nds32/kernel/vdso/gen_vdso_offsets.sh b/arch/nds32/kernel/vdso/gen_vdso_offsets.sh
new file mode 100755
index 0000000..01924ff
--- /dev/null
+++ b/arch/nds32/kernel/vdso/gen_vdso_offsets.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+#
+# Match symbols in the DSO that look like VDSO_*; produce a header file
+# of constant offsets into the shared object.
+#
+# Doing this inside the Makefile will break the $(filter-out) function,
+# causing Kbuild to rebuild the vdso-offsets header file every time.
+#
+# Author: Will Deacon <will.deacon@arm.com
+#
+
+LC_ALL=C
+sed -n -e 's/^00*/0/' -e \
+'s/^\([0-9a-fA-F]*\) . VDSO_\([a-zA-Z0-9_]*\)$/\#define vdso_offset_\2\t0x\1/p'
diff --git a/arch/nds32/kernel/vdso/gettimeofday.c b/arch/nds32/kernel/vdso/gettimeofday.c
new file mode 100644
index 0000000..8591b55
--- /dev/null
+++ b/arch/nds32/kernel/vdso/gettimeofday.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2015 Mentor Graphics Corporation.
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/compiler.h>
+#include <linux/hrtimer.h>
+#include <linux/time.h>
+#include <asm/io.h>
+#include <asm/barrier.h>
+#include <asm/bug.h>
+#include <asm/page.h>
+#include <asm/unistd.h>
+#include <asm/vdso_datapage.h>
+#include <asm/asm-offsets.h>
+
+#define X(x) #x
+#define Y(x) X(x)
+
+extern struct vdso_data *__get_datapage(void);
+extern struct vdso_data *__get_timerpage(void);
+
+static notrace unsigned int __vdso_read_begin(const struct vdso_data *vdata)
+{
+ u32 seq;
+repeat:
+ seq = ACCESS_ONCE(vdata->seq_count);
+ if (seq & 1) {
+ cpu_relax();
+ goto repeat;
+ }
+ return seq;
+}
+
+static notrace unsigned int vdso_read_begin(const struct vdso_data *vdata)
+{
+ unsigned int seq;
+
+ seq = __vdso_read_begin(vdata);
+
+ smp_rmb(); /* Pairs with smp_wmb in vdso_write_end */
+ return seq;
+}
+
+static notrace int vdso_read_retry(const struct vdso_data *vdata, u32 start)
+{
+ smp_rmb(); /* Pairs with smp_wmb in vdso_write_begin */
+ return vdata->seq_count != start;
+}
+
+static notrace long clock_gettime_fallback(clockid_t _clkid,
+ struct timespec *_ts)
+{
+ register struct timespec *ts asm("$r1") = _ts;
+ register clockid_t clkid asm("$r0") = _clkid;
+ register long ret asm("$r0");
+
+ asm volatile (
+ "movi $r15, %3\n"
+ "syscall 0x0\n"
+ :"=r"(ret)
+ :"r"(clkid), "r"(ts), "i"(__NR_clock_gettime)
+ :"$r15","memory");
+
+ return ret;
+}
+
+static notrace int do_realtime_coarse(struct timespec *ts,
+ struct vdso_data *vdata)
+{
+ u32 seq;
+
+ do {
+ seq = vdso_read_begin(vdata);
+
+ ts->tv_sec = vdata->xtime_coarse_sec;
+ ts->tv_nsec = vdata->xtime_coarse_nsec;
+
+ } while (vdso_read_retry(vdata, seq));
+ return 0;
+}
+
+static notrace int do_monotonic_coarse(struct timespec *ts,
+ struct vdso_data *vdata)
+{
+ struct timespec tomono;
+ u32 seq;
+
+ do {
+ seq = vdso_read_begin(vdata);
+
+ ts->tv_sec = vdata->xtime_coarse_sec;
+ ts->tv_nsec = vdata->xtime_coarse_nsec;
+
+ tomono.tv_sec = vdata->wtm_clock_sec;
+ tomono.tv_nsec = vdata->wtm_clock_nsec;
+
+ } while (vdso_read_retry(vdata, seq));
+
+ ts->tv_sec += tomono.tv_sec;
+ timespec_add_ns(ts, tomono.tv_nsec);
+ return 0;
+}
+
+static inline u64 vgetsns(struct vdso_data *vdso)
+{
+ u32 cycle_now;
+ u32 cycle_delta;
+ u32 *timer_cycle_base;
+
+ timer_cycle_base =
+ (u32 *) ((char *)__get_timerpage() + vdso->cycle_count_offset);
+ cycle_now = readl_relaxed(timer_cycle_base);
+ if (true == vdso->cycle_count_down)
+ cycle_now = ~(*timer_cycle_base);
+ cycle_delta = cycle_now - (u32) vdso->cs_cycle_last;
+ return ((u64) cycle_delta & vdso->cs_mask) * vdso->cs_mult;
+}
+
+static notrace int do_realtime(struct timespec *ts, struct vdso_data *vdata)
+{
+ unsigned count;
+ u64 ns;
+ do {
+ count = vdso_read_begin(vdata);
+ ts->tv_sec = vdata->xtime_clock_sec;
+ ns = vdata->xtime_clock_nsec;
+ ns += vgetsns(vdata);
+ ns >>= vdata->cs_shift;
+ } while (vdso_read_retry(vdata, count));
+
+ ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
+ ts->tv_nsec = ns;
+
+ return 0;
+}
+
+static notrace int do_monotonic(struct timespec *ts, struct vdso_data *vdata)
+{
+ struct timespec tomono;
+ u64 nsecs;
+ u32 seq;
+
+ do {
+ seq = vdso_read_begin(vdata);
+
+ ts->tv_sec = vdata->xtime_clock_sec;
+ nsecs = vdata->xtime_clock_nsec;
+ nsecs += vgetsns(vdata);
+ nsecs >>= vdata->cs_shift;
+
+ tomono.tv_sec = vdata->wtm_clock_sec;
+ tomono.tv_nsec = vdata->wtm_clock_nsec;
+
+ } while (vdso_read_retry(vdata, seq));
+
+ ts->tv_sec += tomono.tv_sec;
+ ts->tv_nsec = 0;
+ timespec_add_ns(ts, nsecs + tomono.tv_nsec);
+ return 0;
+}
+
+notrace int __vdso_clock_gettime(clockid_t clkid, struct timespec *ts)
+{
+ struct vdso_data *vdata;
+ int ret = -1;
+
+ vdata = __get_datapage();
+
+ switch (clkid) {
+ case CLOCK_REALTIME_COARSE:
+ ret = do_realtime_coarse(ts, vdata);
+ break;
+ case CLOCK_MONOTONIC_COARSE:
+ ret = do_monotonic_coarse(ts, vdata);
+ break;
+ case CLOCK_REALTIME:
+ ret = do_realtime(ts, vdata);
+ break;
+ case CLOCK_MONOTONIC:
+ ret = do_monotonic(ts, vdata);
+ break;
+ default:
+ break;
+ }
+
+ if (ret)
+ ret = clock_gettime_fallback(clkid, ts);
+
+ return ret;
+}
+
+static notrace long clock_getres_fallback(clockid_t _clk_id,
+ struct timespec *_res)
+{
+ register clockid_t clk_id asm("$r0") = _clk_id;
+ register struct timespec *res asm("$r1") = _res;
+ register long ret asm("$r0");
+
+ asm volatile (
+ "movi $r15, %3\n"
+ "syscall 0x0\n"
+ :"=r"(ret)
+ :"r"(clk_id), "r"(res), "i"(__NR_clock_getres)
+ :"$r15","memory");
+
+ return ret;
+}
+
+notrace int __vdso_clock_getres(clockid_t clk_id, struct timespec *res)
+{
+ if (res == NULL)
+ return -EFAULT;
+ switch (clk_id) {
+ case CLOCK_REALTIME:
+ case CLOCK_MONOTONIC:
+ case CLOCK_MONOTONIC_RAW:
+ res->tv_sec = 0;
+ res->tv_nsec = CLOCK_REALTIME_RES;
+ break;
+ case CLOCK_REALTIME_COARSE:
+ case CLOCK_MONOTONIC_COARSE:
+ res->tv_sec = 0;
+ res->tv_nsec = CLOCK_COARSE_RES;
+ break;
+ default:
+ clock_getres_fallback(clk_id, res);
+ break;
+ }
+ return 0;
+}
+
+notrace int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+ struct timespec ts;
+ struct vdso_data *vdata;
+ int ret;
+
+ vdata = __get_datapage();
+
+ ret = do_realtime(&ts, vdata);
+
+ if (tv) {
+ tv->tv_sec = ts.tv_sec;
+ tv->tv_usec = ts.tv_nsec / 1000;
+ }
+ if (tz) {
+ tz->tz_minuteswest = vdata->tz_minuteswest;
+ tz->tz_dsttime = vdata->tz_dsttime;
+ }
+
+ return ret;
+}
diff --git a/arch/nds32/kernel/vdso/note.S b/arch/nds32/kernel/vdso/note.S
new file mode 100644
index 0000000..59c6397
--- /dev/null
+++ b/arch/nds32/kernel/vdso/note.S
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2012 ARM Limited
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ *
+ * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
+ * Here we can supply some information useful to userland.
+ */
+
+#include <linux/uts.h>
+#include <linux/version.h>
+#include <linux/elfnote.h>
+
+ELFNOTE_START(Linux, 0, "a")
+ .long LINUX_VERSION_CODE
+ELFNOTE_END
diff --git a/arch/nds32/kernel/vdso/sigreturn.S b/arch/nds32/kernel/vdso/sigreturn.S
new file mode 100644
index 0000000..8b4bd4e
--- /dev/null
+++ b/arch/nds32/kernel/vdso/sigreturn.S
@@ -0,0 +1,36 @@
+/*
+ * Sigreturn trampoline for returning from a signal
+ *
+ * Copyright (C) 2012 ARM Limited
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
+#include <linux/linkage.h>
+#include <asm/unistd.h>
+
+ .text
+
+ENTRY(__kernel_rt_sigreturn)
+ .cfi_startproc
+ movi $r15, __NR_rt_sigreturn
+ /*
+ * The SWID of syscall should be __NR_rt_sigreturn to synchronize
+ * the unwinding scheme in gcc
+ */
+ syscall __NR_rt_sigreturn
+ .cfi_endproc
+ENDPROC(__kernel_rt_sigreturn)
diff --git a/arch/nds32/kernel/vdso/vdso.S b/arch/nds32/kernel/vdso/vdso.S
new file mode 100644
index 0000000..4444082
--- /dev/null
+++ b/arch/nds32/kernel/vdso/vdso.S
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2012 ARM Limited
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/const.h>
+#include <asm/page.h>
+
+ .globl vdso_start, vdso_end
+ .section .rodata
+ .balign PAGE_SIZE
+vdso_start:
+ .incbin "arch/nds32/kernel/vdso/vdso.so"
+ .balign PAGE_SIZE
+vdso_end:
+
+ .previous
diff --git a/arch/nds32/kernel/vdso/vdso.lds.S b/arch/nds32/kernel/vdso/vdso.lds.S
new file mode 100644
index 0000000..9599db4
--- /dev/null
+++ b/arch/nds32/kernel/vdso/vdso.lds.S
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <linux/const.h>
+#include <asm/page.h>
+#include <asm/vdso.h>
+
+OUTPUT_FORMAT("elf32-nds32le-linux", "elf32-nds32be-linux", "elf32-nds32le-linux")
+OUTPUT_ARCH(nds32)
+
+SECTIONS
+{
+ . = SIZEOF_HEADERS;
+
+ .hash : { *(.hash) } :text
+ .gnu.hash : { *(.gnu.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+
+ .note : { *(.note.*) } :text :note
+
+
+ .text : { *(.text*) } :text
+
+ .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
+ .eh_frame : { KEEP (*(.eh_frame)) } :text
+
+ .dynamic : { *(.dynamic) } :text :dynamic
+
+ .rodata : { *(.rodata*) } :text
+
+
+ /DISCARD/ : {
+ *(.note.GNU-stack)
+ *(.data .data.* .gnu.linkonce.d.* .sdata*)
+ *(.bss .sbss .dynbss .dynsbss)
+ }
+}
+
+/*
+ * We must supply the ELF program headers explicitly to get just one
+ * PT_LOAD segment, and set the flags explicitly to make segments read-only.
+ */
+PHDRS
+{
+ text PT_LOAD FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */
+ dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
+ note PT_NOTE FLAGS(4); /* PF_R */
+ eh_frame_hdr PT_GNU_EH_FRAME;
+}
+
+/*
+ * This controls what symbols we export from the DSO.
+ */
+VERSION
+{
+ LINUX_4 {
+ global:
+ __kernel_rt_sigreturn;
+ __vdso_gettimeofday;
+ __vdso_clock_getres;
+ __vdso_clock_gettime;
+ local: *;
+ };
+}
+
+/*
+ * Make the rt_sigreturn code visible to the kernel.
+ */
+VDSO_rt_sigtramp = __kernel_rt_sigreturn;
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 16/33] nds32: System calls handling
From: Greentime Hu @ 2017-12-08 9:11 UTC (permalink / raw)
To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
marc.zyngier, robh+dt, netdev, deanbo422, devicetree, viro,
dhowells, will.deacon, daniel.lezcano, linux-serial,
geert.uytterhoeven, linus.walleij, mark.rutland, greg
Cc: green.hu, Vincent Chen
In-Reply-To: <cover.1512723245.git.green.hu@gmail.com>
From: Greentime Hu <greentime@andestech.com>
This patch adds support for system calls.
Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
arch/nds32/include/asm/syscall.h | 203 ++++++++++++++++++++++++++++++++++
arch/nds32/include/asm/syscalls.h | 26 +++++
arch/nds32/include/asm/unistd.h | 19 ++++
arch/nds32/include/uapi/asm/unistd.h | 25 +++++
arch/nds32/kernel/ex-scall.S | 119 ++++++++++++++++++++
arch/nds32/kernel/sys_nds32.c | 74 +++++++++++++
arch/nds32/kernel/syscall_table.c | 30 +++++
7 files changed, 496 insertions(+)
create mode 100644 arch/nds32/include/asm/syscall.h
create mode 100644 arch/nds32/include/asm/syscalls.h
create mode 100644 arch/nds32/include/asm/unistd.h
create mode 100644 arch/nds32/include/uapi/asm/unistd.h
create mode 100644 arch/nds32/kernel/ex-scall.S
create mode 100644 arch/nds32/kernel/sys_nds32.c
create mode 100644 arch/nds32/kernel/syscall_table.c
diff --git a/arch/nds32/include/asm/syscall.h b/arch/nds32/include/asm/syscall.h
new file mode 100644
index 0000000..3066bae
--- /dev/null
+++ b/arch/nds32/include/asm/syscall.h
@@ -0,0 +1,203 @@
+/*
+ * Access to user system call parameters and results
+ *
+ * Copyright (C) 2008-2009 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * This file is a stub providing documentation for what functions
+ * asm-ARCH/syscall.h files need to define. Most arch definitions
+ * will be simple inlines.
+ *
+ * All of these functions expect to be called with no locks,
+ * and only when the caller is sure that the task of interest
+ * cannot return to user mode while we are looking at it.
+ */
+
+#ifndef _ASM_NDS32_SYSCALL_H
+#define _ASM_NDS32_SYSCALL_H 1
+
+#include <linux/err.h>
+struct task_struct;
+struct pt_regs;
+
+/**
+ * syscall_get_nr - find what system call a task is executing
+ * @task: task of interest, must be blocked
+ * @regs: task_pt_regs() of @task
+ *
+ * If @task is executing a system call or is at system call
+ * tracing about to attempt one, returns the system call number.
+ * If @task is not executing a system call, i.e. it's blocked
+ * inside the kernel for a fault or signal, returns -1.
+ *
+ * Note this returns int even on 64-bit machines. Only 32 bits of
+ * system call number can be meaningful. If the actual arch value
+ * is 64 bits, this truncates to 32 bits so 0xffffffff means -1.
+ *
+ * It's only valid to call this when @task is known to be blocked.
+ */
+int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
+{
+ return regs->syscallno;
+}
+
+/**
+ * syscall_rollback - roll back registers after an aborted system call
+ * @task: task of interest, must be in system call exit tracing
+ * @regs: task_pt_regs() of @task
+ *
+ * It's only valid to call this when @task is stopped for system
+ * call exit tracing (due to TIF_SYSCALL_TRACE or TIF_SYSCALL_AUDIT),
+ * after tracehook_report_syscall_entry() returned nonzero to prevent
+ * the system call from taking place.
+ *
+ * This rolls back the register state in @regs so it's as if the
+ * system call instruction was a no-op. The registers containing
+ * the system call number and arguments are as they were before the
+ * system call instruction. This may not be the same as what the
+ * register state looked like at system call entry tracing.
+ */
+void syscall_rollback(struct task_struct *task, struct pt_regs *regs)
+{
+ regs->uregs[0] = regs->orig_r0;
+}
+
+/**
+ * syscall_get_error - check result of traced system call
+ * @task: task of interest, must be blocked
+ * @regs: task_pt_regs() of @task
+ *
+ * Returns 0 if the system call succeeded, or -ERRORCODE if it failed.
+ *
+ * It's only valid to call this when @task is stopped for tracing on exit
+ * from a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT.
+ */
+long syscall_get_error(struct task_struct *task, struct pt_regs *regs)
+{
+ unsigned long error = regs->uregs[0];
+ return IS_ERR_VALUE(error) ? error : 0;
+}
+
+/**
+ * syscall_get_return_value - get the return value of a traced system call
+ * @task: task of interest, must be blocked
+ * @regs: task_pt_regs() of @task
+ *
+ * Returns the return value of the successful system call.
+ * This value is meaningless if syscall_get_error() returned nonzero.
+ *
+ * It's only valid to call this when @task is stopped for tracing on exit
+ * from a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT.
+ */
+long syscall_get_return_value(struct task_struct *task, struct pt_regs *regs)
+{
+ return regs->uregs[0];
+}
+
+/**
+ * syscall_set_return_value - change the return value of a traced system call
+ * @task: task of interest, must be blocked
+ * @regs: task_pt_regs() of @task
+ * @error: negative error code, or zero to indicate success
+ * @val: user return value if @error is zero
+ *
+ * This changes the results of the system call that user mode will see.
+ * If @error is zero, the user sees a successful system call with a
+ * return value of @val. If @error is nonzero, it's a negated errno
+ * code; the user sees a failed system call with this errno code.
+ *
+ * It's only valid to call this when @task is stopped for tracing on exit
+ * from a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT.
+ */
+void syscall_set_return_value(struct task_struct *task, struct pt_regs *regs,
+ int error, long val)
+{
+ regs->uregs[0] = (long)error ? error : val;
+}
+
+/**
+ * syscall_get_arguments - extract system call parameter values
+ * @task: task of interest, must be blocked
+ * @regs: task_pt_regs() of @task
+ * @i: argument index [0,5]
+ * @n: number of arguments; n+i must be [1,6].
+ * @args: array filled with argument values
+ *
+ * Fetches @n arguments to the system call starting with the @i'th argument
+ * (from 0 through 5). Argument @i is stored in @args[0], and so on.
+ * An arch inline version is probably optimal when @i and @n are constants.
+ *
+ * It's only valid to call this when @task is stopped for tracing on
+ * entry to a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT.
+ * It's invalid to call this with @i + @n > 6; we only support system calls
+ * taking up to 6 arguments.
+ */
+#define SYSCALL_MAX_ARGS 6
+void syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
+ unsigned int i, unsigned int n, unsigned long *args)
+{
+ if (n == 0)
+ return;
+ if (i + n > SYSCALL_MAX_ARGS) {
+ unsigned long *args_bad = args + SYSCALL_MAX_ARGS - i;
+ unsigned int n_bad = n + i - SYSCALL_MAX_ARGS;
+ pr_warning("%s called with max args %d, handling only %d\n",
+ __func__, i + n, SYSCALL_MAX_ARGS);
+ memset(args_bad, 0, n_bad * sizeof(args[0]));
+ memset(args_bad, 0, n_bad * sizeof(args[0]));
+ }
+
+ if (i == 0) {
+ args[0] = regs->orig_r0;
+ args++;
+ i++;
+ n--;
+ }
+
+ memcpy(args, ®s->uregs[0] + i, n * sizeof(args[0]));
+}
+
+/**
+ * syscall_set_arguments - change system call parameter value
+ * @task: task of interest, must be in system call entry tracing
+ * @regs: task_pt_regs() of @task
+ * @i: argument index [0,5]
+ * @n: number of arguments; n+i must be [1,6].
+ * @args: array of argument values to store
+ *
+ * Changes @n arguments to the system call starting with the @i'th argument.
+ * Argument @i gets value @args[0], and so on.
+ * An arch inline version is probably optimal when @i and @n are constants.
+ *
+ * It's only valid to call this when @task is stopped for tracing on
+ * entry to a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT.
+ * It's invalid to call this with @i + @n > 6; we only support system calls
+ * taking up to 6 arguments.
+ */
+void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs,
+ unsigned int i, unsigned int n,
+ const unsigned long *args)
+{
+ if (n == 0)
+ return;
+
+ if (i + n > SYSCALL_MAX_ARGS) {
+ pr_warn("%s called with max args %d, handling only %d\n",
+ __func__, i + n, SYSCALL_MAX_ARGS);
+ n = SYSCALL_MAX_ARGS - i;
+ }
+
+ if (i == 0) {
+ regs->orig_r0 = args[0];
+ args++;
+ i++;
+ n--;
+ }
+
+ memcpy(®s->uregs[0] + i, args, n * sizeof(args[0]));
+}
+#endif /* _ASM_NDS32_SYSCALL_H */
diff --git a/arch/nds32/include/asm/syscalls.h b/arch/nds32/include/asm/syscalls.h
new file mode 100644
index 0000000..bb0578a
--- /dev/null
+++ b/arch/nds32/include/asm/syscalls.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * 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_NDS32_SYSCALLS_H
+#define __ASM_NDS32_SYSCALLS_H
+
+asmlinkage long sys_cacheflush(unsigned long addr, unsigned long len, unsigned int op);
+asmlinkage long sys_fadvise64_64_wrapper(int fd, int advice, loff_t offset, loff_t len);
+asmlinkage long sys_rt_sigreturn_wrapper(void);
+
+#include <asm-generic/syscalls.h>
+
+#endif /* __ASM_NDS32_SYSCALLS_H */
diff --git a/arch/nds32/include/asm/unistd.h b/arch/nds32/include/asm/unistd.h
new file mode 100644
index 0000000..a66b8bb
--- /dev/null
+++ b/arch/nds32/include/asm/unistd.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * 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/>.
+ */
+
+#define __ARCH_WANT_SYS_CLONE
+
+#include <uapi/asm/unistd.h>
diff --git a/arch/nds32/include/uapi/asm/unistd.h b/arch/nds32/include/uapi/asm/unistd.h
new file mode 100644
index 0000000..325ca3b
--- /dev/null
+++ b/arch/nds32/include/uapi/asm/unistd.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * 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/>.
+ */
+
+#define __ARCH_WANT_SYNC_FILE_RANGE2
+
+/* Use the standard ABI for syscalls */
+#include <asm-generic/unistd.h>
+
+/* Additional NDS32 specific syscalls. */
+#define __NR_cacheflush (__NR_arch_specific_syscall)
+#define __NR__llseek __NR_llseek
+__SYSCALL(__NR_cacheflush, sys_cacheflush)
diff --git a/arch/nds32/kernel/ex-scall.S b/arch/nds32/kernel/ex-scall.S
new file mode 100644
index 0000000..0ad7833
--- /dev/null
+++ b/arch/nds32/kernel/ex-scall.S
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <asm/unistd.h>
+#include <asm/assembler.h>
+#include <asm/nds32.h>
+#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
+#include <asm/current.h>
+
+/*
+ * $r0 = previous task_struct,
+ * $r1 = next task_struct,
+ * previous and next are guaranteed not to be the same.
+ */
+
+ENTRY(__switch_to)
+
+ la $p0, __entry_task
+ sw $r1, [$p0]
+ move $p1, $r0
+ addi $p1, $p1, #THREAD_CPU_CONTEXT
+ smw.bi $r6, [$p1], $r14, #0xb ! push r6~r14, fp, lp, sp
+ move $r25, $r1
+ addi $r1, $r1, #THREAD_CPU_CONTEXT
+ lmw.bi $r6, [$r1], $r14, #0xb ! pop r6~r14, fp, lp, sp
+ ret
+
+/*
+ * These are the registers used in the syscall handler, and allow us
+ * to have in theory up to 6 arguments to a function - $r0 to $r5.
+ *
+ * We must set at least "tsk" and "tbl" when calling ret_with_reschedule.
+ */
+
+/*
+ * $r7 will be writen as syscall nr
+ * by retrieving from $ITYPE 'SWID' bitfiled
+ */
+ .macro get_scno
+ lwi $r7, [$sp + R15_OFFSET]
+ swi $r7, [$sp + SYSCALLNO_OFFSET]
+ .endm
+
+ .macro updateipc
+ addi $r17, $r13, #4 ! $r13 is $IPC
+ swi $r17, [$sp + IPC_OFFSET]
+ .endm
+
+ENTRY(eh_syscall)
+ updateipc
+
+ get_scno
+ gie_enable
+
+ENTRY(eh_syscall_phase_2)
+ lwi $p0, [tsk+#TSK_TI_FLAGS] ! check for syscall tracing
+
+ andi $p1, $p0, #_TIF_WORK_SYSCALL_ENTRY ! are we tracing syscalls?
+ bnez $p1, __sys_trace
+
+ la $lp, ret_fast_syscall ! return address
+jmp_systbl:
+ addi $p1, $r7, #-__NR_syscalls ! syscall number of syscall instruction is guarded by addembler
+ bgez $p1, _SCNO_EXCEED ! call sys_* routine
+ la tbl, sys_call_table ! load syscall table pointer
+ slli $p1, $r7, #2
+ add $p1, tbl, $p1
+ lwi $p1, [$p1]
+ jr $p1 ! no return
+
+_SCNO_EXCEED:
+ movi why, 0
+ ori $r0, $r7, #0
+ ori $r1, $sp, #0
+ b bad_syscall
+
+/*
+ * This is the really slow path. We're going to be doing
+ * context switches, and waiting for our parent to respond.
+ */
+__sys_trace:
+ move $r1, $sp
+ move $r0, $r7 ! trace entry [IP = 0]
+ bal syscall_trace_enter
+ move $r7, $r0
+ la $lp, __sys_trace_return ! return address
+
+ addi $p1, $r7, #1
+ beqz $p1, ret_slow_syscall ! fatal signal is pending
+
+ addi $p1, $sp, #R0_OFFSET ! pointer to regs
+ lmw.bi $r0, [$p1], $r5 ! have to reload $r0 - $r5
+ b jmp_systbl
+
+__sys_trace_return:
+ swi $r0, [$sp+#R0_OFFSET] ! T: save returned $r0
+ move $r0, $sp ! set pt_regs for syscall_trace_leave
+ bal syscall_trace_leave
+ b ret_slow_syscall
+
+ENTRY(sys_rt_sigreturn_wrapper)
+ addi $r0, $sp, #0
+ b sys_rt_sigreturn
+ENDPROC(sys_rt_sigreturn_wrapper)
diff --git a/arch/nds32/kernel/sys_nds32.c b/arch/nds32/kernel/sys_nds32.c
new file mode 100644
index 0000000..1900bbc
--- /dev/null
+++ b/arch/nds32/kernel/sys_nds32.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/syscalls.h>
+
+#include <asm/uaccess.h>
+#include <asm/cachectl.h>
+#include <asm/proc-fns.h>
+
+SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
+ unsigned long, prot, unsigned long, flags,
+ unsigned long, fd, unsigned long, pgoff)
+{
+ if (pgoff & (~PAGE_MASK >> 12))
+ return -EINVAL;
+
+ return sys_mmap_pgoff(addr, len, prot, flags, fd,
+ pgoff >> (PAGE_SHIFT - 12));
+}
+
+SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
+ unsigned long, prot, unsigned long, flags,
+ unsigned long, fd, unsigned long, pgoff)
+{
+ if (unlikely(pgoff & ~PAGE_MASK))
+ return -EINVAL;
+
+ return sys_mmap_pgoff(addr, len, prot, flags, fd,
+ pgoff >> PAGE_SHIFT);
+}
+
+SYSCALL_DEFINE4(fadvise64_64_wrapper,int, fd, int, advice, loff_t, offset,
+ loff_t, len)
+{
+ return sys_fadvise64_64(fd, offset, len, advice);
+}
+
+SYSCALL_DEFINE3(cacheflush, unsigned int, start, unsigned int, end, int, cache)
+{
+ struct vm_area_struct *vma;
+ bool flushi = true, wbd = true;
+
+ vma = find_vma(current->mm, start);
+ if (!vma)
+ return -EFAULT;
+ switch (cache) {
+ case ICACHE:
+ wbd = false;
+ break;
+ case DCACHE:
+ flushi = false;
+ break;
+ case BCACHE:
+ break;
+ default:
+ return -EINVAL;
+ }
+ cpu_cache_wbinval_range_check(vma, start, end, flushi, wbd);
+
+ return 0;
+}
diff --git a/arch/nds32/kernel/syscall_table.c b/arch/nds32/kernel/syscall_table.c
new file mode 100644
index 0000000..c1edc85
--- /dev/null
+++ b/arch/nds32/kernel/syscall_table.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/syscalls.h>
+#include <linux/signal.h>
+#include <linux/unistd.h>
+#include <asm/syscalls.h>
+
+#undef __SYSCALL
+#define __SYSCALL(nr, call) [nr] = (call),
+
+#define sys_rt_sigreturn sys_rt_sigreturn_wrapper
+#define sys_fadvise64_64 sys_fadvise64_64_wrapper
+void *sys_call_table[__NR_syscalls] __aligned(8192) = {
+ [0 ... __NR_syscalls - 1] = sys_ni_syscall,
+#include <asm/unistd.h>
+};
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 15/33] nds32: ELF definitions
From: Greentime Hu @ 2017-12-08 9:11 UTC (permalink / raw)
To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
marc.zyngier, robh+dt, netdev, deanbo422, devicetree, viro,
dhowells, will.deacon, daniel.lezcano, linux-serial,
geert.uytterhoeven, linus.walleij, mark.rutland, greg
Cc: green.hu, Vincent Chen
In-Reply-To: <cover.1512723245.git.green.hu@gmail.com>
From: Greentime Hu <greentime@andestech.com>
This patch adds definitions for the ELF format, relocation types, vdso
locations and EXEC_PAGESIZE.
Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
arch/nds32/include/asm/elf.h | 192 ++++++++++++++++++++++++++++++++++
arch/nds32/include/uapi/asm/auxvec.h | 25 +++++
arch/nds32/include/uapi/asm/param.h | 24 +++++
3 files changed, 241 insertions(+)
create mode 100644 arch/nds32/include/asm/elf.h
create mode 100644 arch/nds32/include/uapi/asm/auxvec.h
create mode 100644 arch/nds32/include/uapi/asm/param.h
diff --git a/arch/nds32/include/asm/elf.h b/arch/nds32/include/asm/elf.h
new file mode 100644
index 0000000..a6e4c56
--- /dev/null
+++ b/arch/nds32/include/asm/elf.h
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * 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 __ASMNDS32_ELF_H
+#define __ASMNDS32_ELF_H
+
+/*
+ * ELF register definitions..
+ */
+
+#include <asm/ptrace.h>
+
+typedef unsigned long elf_greg_t;
+typedef unsigned long elf_freg_t[3];
+
+extern unsigned int elf_hwcap;
+
+#define EM_NDS32 167
+
+#define R_NDS32_NONE 0
+#define R_NDS32_16_RELA 19
+#define R_NDS32_32_RELA 20
+#define R_NDS32_9_PCREL_RELA 22
+#define R_NDS32_15_PCREL_RELA 23
+#define R_NDS32_17_PCREL_RELA 24
+#define R_NDS32_25_PCREL_RELA 25
+#define R_NDS32_HI20_RELA 26
+#define R_NDS32_LO12S3_RELA 27
+#define R_NDS32_LO12S2_RELA 28
+#define R_NDS32_LO12S1_RELA 29
+#define R_NDS32_LO12S0_RELA 30
+#define R_NDS32_SDA15S3_RELA 31
+#define R_NDS32_SDA15S2_RELA 32
+#define R_NDS32_SDA15S1_RELA 33
+#define R_NDS32_SDA15S0_RELA 34
+#define R_NDS32_GOT20 37
+#define R_NDS32_25_PLTREL 38
+#define R_NDS32_COPY 39
+#define R_NDS32_GLOB_DAT 40
+#define R_NDS32_JMP_SLOT 41
+#define R_NDS32_RELATIVE 42
+#define R_NDS32_GOTOFF 43
+#define R_NDS32_GOTPC20 44
+#define R_NDS32_GOT_HI20 45
+#define R_NDS32_GOT_LO12 46
+#define R_NDS32_GOTPC_HI20 47
+#define R_NDS32_GOTPC_LO12 48
+#define R_NDS32_GOTOFF_HI20 49
+#define R_NDS32_GOTOFF_LO12 50
+#define R_NDS32_INSN16 51
+#define R_NDS32_LABEL 52
+#define R_NDS32_LONGCALL1 53
+#define R_NDS32_LONGCALL2 54
+#define R_NDS32_LONGCALL3 55
+#define R_NDS32_LONGJUMP1 56
+#define R_NDS32_LONGJUMP2 57
+#define R_NDS32_LONGJUMP3 58
+#define R_NDS32_LOADSTORE 59
+#define R_NDS32_9_FIXED_RELA 60
+#define R_NDS32_15_FIXED_RELA 61
+#define R_NDS32_17_FIXED_RELA 62
+#define R_NDS32_25_FIXED_RELA 63
+#define R_NDS32_PLTREL_HI20 64
+#define R_NDS32_PLTREL_LO12 65
+#define R_NDS32_PLT_GOTREL_HI20 66
+#define R_NDS32_PLT_GOTREL_LO12 67
+#define R_NDS32_LO12S0_ORI_RELA 72
+#define R_NDS32_DWARF2_OP1_RELA 77
+#define R_NDS32_DWARF2_OP2_RELA 78
+#define R_NDS32_DWARF2_LEB_RELA 79
+#define R_NDS32_WORD_9_PCREL_RELA 94
+#define R_NDS32_LONGCALL4 107
+#define R_NDS32_RELA_NOP_MIX 192
+#define R_NDS32_RELA_NOP_MAX 255
+
+#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+/* Core file format: The core file is written in such a way that gdb
+ can understand it and provide useful information to the user (under
+ linux we use the 'trad-core' bfd). There are quite a number of
+ obstacles to being able to view the contents of the floating point
+ registers, and until these are solved you will not be able to view the
+ contents of them. Actually, you can read in the core file and look at
+ the contents of the user struct to find out what the floating point
+ registers contain.
+ The actual file contents are as follows:
+ UPAGE: 1 page consisting of a user struct that tells gdb what is present
+ in the file. Directly after this is a copy of the task_struct, which
+ is currently not used by gdb, but it may come in useful at some point.
+ All of the registers are stored as part of the upage. The upage should
+ always be only one page.
+ DATA: The data area is stored. We use current->end_text to
+ current->brk to pick up all of the user variables, plus any memory
+ that may have been malloced. No attempt is made to determine if a page
+ is demand-zero or if a page is totally unused, we just cover the entire
+ range. All of the addresses are rounded in such a way that an integral
+ number of pages is written.
+ STACK: We need the stack information in order to get a meaningful
+ backtrace. We need to write the data from (esp) to
+ current->start_stack, so we round each of these off in order to be able
+ to write an integer number of pages.
+ The minimum core file size is 3 pages, or 12288 bytes.
+*/
+
+struct user_fp {
+ struct fp_reg {
+ unsigned int sign1:1;
+ unsigned int unused:15;
+ unsigned int sign2:1;
+ unsigned int exponent:14;
+ unsigned int j:1;
+ unsigned int mantissa1:31;
+ unsigned int mantissa0:32;
+ } fpregs[8];
+ unsigned int fpsr:32;
+ unsigned int fpcr:32;
+ unsigned char ftype[8];
+ unsigned int init_flag;
+};
+
+typedef struct user_fp elf_fpregset_t;
+
+struct elf32_hdr;
+#define elf_check_arch(x) ((x)->e_machine == EM_NDS32)
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS ELFCLASS32
+#ifdef __NDS32_EB__
+#define ELF_DATA ELFDATA2MSB;
+#else
+#define ELF_DATA ELFDATA2LSB;
+#endif
+#define ELF_ARCH EM_NDS32
+#define USE_ELF_CORE_DUMP
+#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 (2 * TASK_SIZE / 3)
+
+/* When the program starts, a1 contains a pointer to a function to be
+ registered with atexit, as per the SVR4 ABI. A value of 0 means we
+ have no such handler. */
+#define ELF_PLAT_INIT(_r, load_addr) (_r)->uregs[0] = 0
+
+/* This yields a mask that user programs can use to figure out what
+ instruction set this cpu supports. */
+
+#define ELF_HWCAP (elf_hwcap)
+
+#ifdef __KERNEL__
+
+#define ELF_PLATFORM (NULL)
+
+/* Old NetWinder binaries were compiled in such a way that the iBCS
+ heuristic always trips on them. Until these binaries become uncommon
+ enough not to care, don't trust the `ibcs' flag here. In any case
+ there is no other ELF system currently supported by iBCS.
+ @@ Could print a warning message to encourage users to upgrade. */
+#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+
+#endif
+
+#define ARCH_DLINFO \
+do { \
+ NEW_AUX_ENT(AT_SYSINFO_EHDR, \
+ (elf_addr_t)current->mm->context.vdso); \
+} while (0)
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
+struct linux_binprm;
+int arch_setup_additional_pages(struct linux_binprm *, int);
+
+#endif
diff --git a/arch/nds32/include/uapi/asm/auxvec.h b/arch/nds32/include/uapi/asm/auxvec.h
new file mode 100644
index 0000000..02e9757
--- /dev/null
+++ b/arch/nds32/include/uapi/asm/auxvec.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * 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_AUXVEC_H
+#define __ASM_AUXVEC_H
+
+/* VDSO location */
+#define AT_SYSINFO_EHDR 33
+
+#define AT_VECTOR_SIZE_ARCH 1
+
+#endif
diff --git a/arch/nds32/include/uapi/asm/param.h b/arch/nds32/include/uapi/asm/param.h
new file mode 100644
index 0000000..2e4527f3
--- /dev/null
+++ b/arch/nds32/include/uapi/asm/param.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * 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_NDS32_PARAM_H
+#define __ASM_NDS32_PARAM_H
+
+#define EXEC_PAGESIZE 8192
+
+#include <asm-generic/param.h>
+
+#endif /* __ASM_NDS32_PARAM_H */
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 14/33] nds32: DMA mapping API
From: Greentime Hu @ 2017-12-08 9:11 UTC (permalink / raw)
To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
marc.zyngier, robh+dt, netdev, deanbo422, devicetree, viro,
dhowells, will.deacon, daniel.lezcano, linux-serial,
geert.uytterhoeven, linus.walleij, mark.rutland, greg
Cc: green.hu, Vincent Chen
In-Reply-To: <cover.1512723245.git.green.hu@gmail.com>
From: Greentime Hu <greentime@andestech.com>
This patch adds support for the DMA mapping API. It uses dma_map_ops for
flexibility.
Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
arch/nds32/include/asm/dma-mapping.h | 27 ++
arch/nds32/kernel/dma.c | 472 ++++++++++++++++++++++++++++++++++
2 files changed, 499 insertions(+)
create mode 100644 arch/nds32/include/asm/dma-mapping.h
create mode 100644 arch/nds32/kernel/dma.c
diff --git a/arch/nds32/include/asm/dma-mapping.h b/arch/nds32/include/asm/dma-mapping.h
new file mode 100644
index 0000000..63dbeb7
--- /dev/null
+++ b/arch/nds32/include/asm/dma-mapping.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * 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 ASMNDS32_DMA_MAPPING_H
+#define ASMNDS32_DMA_MAPPING_H
+
+extern struct dma_map_ops nds32_dma_ops;
+
+static inline struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
+{
+ return &nds32_dma_ops;
+}
+
+#endif
diff --git a/arch/nds32/kernel/dma.c b/arch/nds32/kernel/dma.c
new file mode 100644
index 0000000..9554aee
--- /dev/null
+++ b/arch/nds32/kernel/dma.c
@@ -0,0 +1,472 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/export.h>
+#include <linux/string.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/cache.h>
+#include <linux/highmem.h>
+#include <linux/slab.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/dma-mapping.h>
+#include <asm/proc-fns.h>
+
+/*
+ * This is the page table (2MB) covering uncached, DMA consistent allocations
+ */
+static pte_t *consistent_pte;
+static DEFINE_RAW_SPINLOCK(consistent_lock);
+
+/*
+ * VM region handling support.
+ *
+ * This should become something generic, handling VM region allocations for
+ * vmalloc and similar (ioremap, module space, etc).
+ *
+ * I envisage vmalloc()'s supporting vm_struct becoming:
+ *
+ * struct vm_struct {
+ * struct vm_region region;
+ * unsigned long flags;
+ * struct page **pages;
+ * unsigned int nr_pages;
+ * unsigned long phys_addr;
+ * };
+ *
+ * get_vm_area() would then call vm_region_alloc with an appropriate
+ * struct vm_region head (eg):
+ *
+ * struct vm_region vmalloc_head = {
+ * .vm_list = LIST_HEAD_INIT(vmalloc_head.vm_list),
+ * .vm_start = VMALLOC_START,
+ * .vm_end = VMALLOC_END,
+ * };
+ *
+ * However, vmalloc_head.vm_start is variable (typically, it is dependent on
+ * the amount of RAM found at boot time.) I would imagine that get_vm_area()
+ * would have to initialise this each time prior to calling vm_region_alloc().
+ */
+struct arch_vm_region {
+ struct list_head vm_list;
+ unsigned long vm_start;
+ unsigned long vm_end;
+ struct page *vm_pages;
+};
+
+static struct arch_vm_region consistent_head = {
+ .vm_list = LIST_HEAD_INIT(consistent_head.vm_list),
+ .vm_start = CONSISTENT_BASE,
+ .vm_end = CONSISTENT_END,
+};
+
+static struct arch_vm_region *vm_region_alloc(struct arch_vm_region *head,
+ size_t size, int gfp)
+{
+ unsigned long addr = head->vm_start, end = head->vm_end - size;
+ unsigned long flags;
+ struct arch_vm_region *c, *new;
+
+ new = kmalloc(sizeof(struct arch_vm_region), gfp);
+ if (!new)
+ goto out;
+
+ raw_spin_lock_irqsave(&consistent_lock, flags);
+
+ list_for_each_entry(c, &head->vm_list, vm_list) {
+ if ((addr + size) < addr)
+ goto nospc;
+ if ((addr + size) <= c->vm_start)
+ goto found;
+ addr = c->vm_end;
+ if (addr > end)
+ goto nospc;
+ }
+
+found:
+ /*
+ * Insert this entry _before_ the one we found.
+ */
+ list_add_tail(&new->vm_list, &c->vm_list);
+ new->vm_start = addr;
+ new->vm_end = addr + size;
+
+ raw_spin_unlock_irqrestore(&consistent_lock, flags);
+ return new;
+
+nospc:
+ raw_spin_unlock_irqrestore(&consistent_lock, flags);
+ kfree(new);
+out:
+ return NULL;
+}
+
+static struct arch_vm_region *vm_region_find(struct arch_vm_region *head,
+ unsigned long addr)
+{
+ struct arch_vm_region *c;
+
+ list_for_each_entry(c, &head->vm_list, vm_list) {
+ if (c->vm_start == addr)
+ goto out;
+ }
+ c = NULL;
+out:
+ return c;
+}
+
+/* FIXME: attrs is not used. */
+static void *nds32_dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t * handle, gfp_t gfp,
+ unsigned long attrs)
+{
+ struct page *page;
+ struct arch_vm_region *c;
+ unsigned long order;
+ u64 mask = ~0ULL, limit;
+ pgprot_t prot = pgprot_noncached(PAGE_KERNEL);
+
+ if (!consistent_pte) {
+ pr_err("%s: not initialized\n", __func__);
+ dump_stack();
+ return NULL;
+ }
+
+ if (dev) {
+ mask = dev->coherent_dma_mask;
+
+ /*
+ * Sanity check the DMA mask - it must be non-zero, and
+ * must be able to be satisfied by a DMA allocation.
+ */
+ if (mask == 0) {
+ dev_warn(dev, "coherent DMA mask is unset\n");
+ goto no_page;
+ }
+
+ }
+
+ /*
+ * Sanity check the allocation size.
+ */
+ size = PAGE_ALIGN(size);
+ limit = (mask + 1) & ~mask;
+ if ((limit && size >= limit) ||
+ size >= (CONSISTENT_END - CONSISTENT_BASE)) {
+ pr_warn("coherent allocation too big "
+ "(requested %#x mask %#llx)\n", size, mask);
+ goto no_page;
+ }
+
+ order = get_order(size);
+
+ if (mask != 0xffffffff)
+ gfp |= GFP_DMA;
+
+ page = alloc_pages(gfp, order);
+ if (!page)
+ goto no_page;
+
+ /*
+ * Invalidate any data that might be lurking in the
+ * kernel direct-mapped region for device DMA.
+ */
+ {
+ unsigned long kaddr = (unsigned long)page_address(page);
+ memset(page_address(page), 0, size);
+ cpu_dma_wbinval_range(kaddr, kaddr + size);
+ }
+
+ /*
+ * Allocate a virtual address in the consistent mapping region.
+ */
+ c = vm_region_alloc(&consistent_head, size,
+ gfp & ~(__GFP_DMA | __GFP_HIGHMEM));
+ if (c) {
+ pte_t *pte = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
+ struct page *end = page + (1 << order);
+
+ c->vm_pages = page;
+
+ /*
+ * Set the "dma handle"
+ */
+ *handle = page_to_phys(page);
+
+ do {
+ BUG_ON(!pte_none(*pte));
+
+ /*
+ * x86 does not mark the pages reserved...
+ */
+ SetPageReserved(page);
+ set_pte(pte, mk_pte(page, prot));
+ page++;
+ pte++;
+ } while (size -= PAGE_SIZE);
+
+ /*
+ * Free the otherwise unused pages.
+ */
+ while (page < end) {
+ __free_page(page);
+ page++;
+ }
+
+ return (void *)c->vm_start;
+ }
+
+ if (page)
+ __free_pages(page, order);
+no_page:
+ *handle = ~0;
+ return NULL;
+}
+
+static void nds32_dma_free(struct device *dev, size_t size, void *cpu_addr,
+ dma_addr_t handle, unsigned long attrs)
+{
+ struct arch_vm_region *c;
+ unsigned long flags, addr;
+ pte_t *ptep;
+
+ size = PAGE_ALIGN(size);
+
+ raw_spin_lock_irqsave(&consistent_lock, flags);
+
+ c = vm_region_find(&consistent_head, (unsigned long)cpu_addr);
+ if (!c)
+ goto no_area;
+
+ if ((c->vm_end - c->vm_start) != size) {
+ pr_err("%s: freeing wrong coherent size (%ld != %d)\n",
+ __func__, c->vm_end - c->vm_start, size);
+ dump_stack();
+ size = c->vm_end - c->vm_start;
+ }
+
+ ptep = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
+ addr = c->vm_start;
+ do {
+ pte_t pte = ptep_get_and_clear(&init_mm, addr, ptep);
+ unsigned long pfn;
+
+ ptep++;
+ addr += PAGE_SIZE;
+
+ if (!pte_none(pte) && pte_present(pte)) {
+ pfn = pte_pfn(pte);
+
+ if (pfn_valid(pfn)) {
+ struct page *page = pfn_to_page(pfn);
+
+ /*
+ * x86 does not mark the pages reserved...
+ */
+ ClearPageReserved(page);
+
+ __free_page(page);
+ continue;
+ }
+ }
+
+ pr_crit("%s: bad page in kernel page table\n", __func__);
+ } while (size -= PAGE_SIZE);
+
+ flush_tlb_kernel_range(c->vm_start, c->vm_end);
+
+ list_del(&c->vm_list);
+
+ raw_spin_unlock_irqrestore(&consistent_lock, flags);
+
+ kfree(c);
+ return;
+
+no_area:
+ raw_spin_unlock_irqrestore(&consistent_lock, flags);
+ pr_err("%s: trying to free invalid coherent area: %p\n",
+ __func__, cpu_addr);
+ dump_stack();
+}
+
+/*
+ * Initialise the consistent memory allocation.
+ */
+static int __init consistent_init(void)
+{
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+ int ret = 0;
+
+ do {
+ pgd = pgd_offset(&init_mm, CONSISTENT_BASE);
+ pmd = pmd_alloc(&init_mm, pgd, CONSISTENT_BASE);
+ if (!pmd) {
+ pr_err("%s: no pmd tables\n", __func__);
+ ret = -ENOMEM;
+ break;
+ }
+ /* The first level mapping may be created in somewhere.
+ * It's not necessary to warn here. */
+ /* WARN_ON(!pmd_none(*pmd)); */
+
+ pte = pte_alloc_kernel(pmd, CONSISTENT_BASE);
+ if (!pte) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ consistent_pte = pte;
+ } while (0);
+
+ return ret;
+}
+
+core_initcall(consistent_init);
+static void consistent_sync(void *vaddr, size_t size, int direction);
+static dma_addr_t nds32_dma_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size,
+ enum dma_data_direction dir,
+ unsigned long attrs)
+{
+ consistent_sync((void *)(page_address(page) + offset), size, dir);
+ return page_to_phys(page) + offset;
+}
+
+static void nds32_dma_unmap_page(struct device *dev, dma_addr_t handle,
+ size_t size, enum dma_data_direction dir,
+ unsigned long attrs)
+{
+ consistent_sync(phys_to_virt(handle), size, dir);
+}
+
+/*
+ * Make an area consistent for devices.
+ */
+static void consistent_sync(void *vaddr, size_t size, int direction)
+{
+ unsigned long start = (unsigned long)vaddr;
+ unsigned long end = start + size;
+
+ switch (direction) {
+ case DMA_FROM_DEVICE: /* invalidate only */
+ cpu_dma_inval_range(start, end);
+ break;
+ case DMA_TO_DEVICE: /* writeback only */
+ cpu_dma_wb_range(start, end);
+ break;
+ case DMA_BIDIRECTIONAL: /* writeback and invalidate */
+ cpu_dma_wbinval_range(start, end);
+ break;
+ default:
+ BUG();
+ }
+}
+
+static int nds32_dma_map_sg(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir,
+ unsigned long attrs)
+{
+ int i;
+
+ for (i = 0; i < nents; i++, sg++) {
+ void *virt;
+ unsigned long pfn;
+ struct page *page = sg_page(sg);
+
+ sg->dma_address = sg_phys(sg);
+ pfn = page_to_pfn(page) + sg->offset / PAGE_SIZE;
+ page = pfn_to_page(pfn);
+ if (PageHighMem(page)) {
+ virt = kmap_atomic(page);
+ consistent_sync(virt, sg->length, dir);
+ kunmap_atomic(virt);
+ } else {
+ if (sg->offset > PAGE_SIZE)
+ panic("sg->offset:%08x > PAGE_SIZE\n",
+ sg->offset);
+ virt = page_address(page) + sg->offset;
+ consistent_sync(virt, sg->length, dir);
+ }
+ }
+ return nents;
+}
+
+static void nds32_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+ int nhwentries, enum dma_data_direction dir,
+ unsigned long attrs)
+{
+}
+
+static void
+nds32_dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle,
+ size_t size, enum dma_data_direction dir)
+{
+ consistent_sync((void *)phys_to_virt(handle), size, dir);
+}
+
+static void
+nds32_dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
+ size_t size, enum dma_data_direction dir)
+{
+ consistent_sync((void *)phys_to_virt(handle), size, dir);
+}
+
+static void
+nds32_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction dir)
+{
+ int i;
+
+ for (i = 0; i < nents; i++, sg++) {
+ char *virt =
+ page_address((struct page *)sg->page_link) + sg->offset;
+ consistent_sync(virt, sg->length, dir);
+ }
+}
+
+static void
+nds32_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir)
+{
+ int i;
+
+ for (i = 0; i < nents; i++, sg++) {
+ char *virt =
+ page_address((struct page *)sg->page_link) + sg->offset;
+ consistent_sync(virt, sg->length, dir);
+ }
+}
+
+struct dma_map_ops nds32_dma_ops = {
+ .alloc = nds32_dma_alloc_coherent,
+ .free = nds32_dma_free,
+ .map_page = nds32_dma_map_page,
+ .unmap_page = nds32_dma_unmap_page,
+ .map_sg = nds32_dma_map_sg,
+ .unmap_sg = nds32_dma_unmap_sg,
+ .sync_single_for_device = nds32_dma_sync_single_for_device,
+ .sync_single_for_cpu = nds32_dma_sync_single_for_cpu,
+ .sync_sg_for_cpu = nds32_dma_sync_sg_for_cpu,
+ .sync_sg_for_device = nds32_dma_sync_sg_for_device,
+};
+
+EXPORT_SYMBOL(nds32_dma_ops);
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 13/33] nds32: Device specific operations
From: Greentime Hu @ 2017-12-08 9:11 UTC (permalink / raw)
To: greentime-MUIXKm3Oiri1Z/+hSey0Gg,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, arnd-r2nGTMty4D4,
linux-arch-u79uwXL29TY76Z2rM5mHXA, tglx-hfZtesqFncYOwBW4kG4KsQ,
jason-NLaQJdtUoK4Be96aLqz0jA, marc.zyngier-5wv7dgnIgG8,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, netdev-u79uwXL29TY76Z2rM5mHXA,
deanbo422-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA,
viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
dhowells-H+wXaHxf7aLQT0dZR+AlfA, will.deacon-5wv7dgnIgG8,
daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A,
linux-serial-u79uwXL29TY76Z2rM5mHXA,
geert.uytterhoeven-Re5JQEeQqe8AvxtiuMwx3w,
linus.walleij-QSEj5FYQhm4dnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
greg-U8xfFu+wG4EAvxtiuMwx3w
Cc: green.hu-Re5JQEeQqe8AvxtiuMwx3w, Vincent Chen
In-Reply-To: <cover.1512723245.git.green.hu-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
From: Greentime Hu <greentime-MUIXKm3Oiri1Z/+hSey0Gg@public.gmane.org>
This patch introduces ioremap implementations.
Signed-off-by: Vincent Chen <vincentc-MUIXKm3Oiri1Z/+hSey0Gg@public.gmane.org>
Signed-off-by: Greentime Hu <greentime-MUIXKm3Oiri1Z/+hSey0Gg@public.gmane.org>
---
arch/nds32/include/asm/io.h | 96 +++++++++++++++++++++++++++++++++++++++++++
arch/nds32/mm/ioremap.c | 75 +++++++++++++++++++++++++++++++++
2 files changed, 171 insertions(+)
create mode 100644 arch/nds32/include/asm/io.h
create mode 100644 arch/nds32/mm/ioremap.c
diff --git a/arch/nds32/include/asm/io.h b/arch/nds32/include/asm/io.h
new file mode 100644
index 0000000..16ff6a5
--- /dev/null
+++ b/arch/nds32/include/asm/io.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * 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_NDS32_IO_H
+#define __ASM_NDS32_IO_H
+
+extern void iounmap(void __iomem *addr);
+#define __raw_writeb __raw_writeb
+static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
+{
+ asm volatile("sbi %0, [%1]" : : "r" (val), "r" (addr));
+}
+
+#define __raw_writew __raw_writew
+static inline void __raw_writew(u16 val, volatile void __iomem *addr)
+{
+ asm volatile("shi %0, [%1]" : : "r" (val), "r" (addr));
+}
+
+#define __raw_writel __raw_writel
+static inline void __raw_writel(u32 val, volatile void __iomem *addr)
+{
+ asm volatile("swi %0, [%1]" : : "r" (val), "r" (addr));
+}
+
+#define __raw_readb __raw_readb
+static inline u8 __raw_readb(const volatile void __iomem *addr)
+{
+ u8 val;
+
+ asm volatile("lbi %0, [%1]" : "=r" (val) : "r" (addr));
+ return val;
+}
+
+#define __raw_readw __raw_readw
+static inline u16 __raw_readw(const volatile void __iomem *addr)
+{
+ u16 val;
+
+ asm volatile("lhi %0, [%1]" : "=r" (val) : "r" (addr));
+ return val;
+}
+
+#define __raw_readl __raw_readl
+static inline u32 __raw_readl(const volatile void __iomem *addr)
+{
+ u32 val;
+
+ asm volatile("lwi %0, [%1]" : "=r" (val) : "r" (addr));
+ return val;
+}
+
+#define __iormb() rmb()
+#define __iowmb() wmb()
+
+#define mmiowb() __asm__ __volatile__ ("msync all" : : : "memory");
+
+/*
+ * {read,write}{b,w,l,q}_relaxed() are like the regular version, but
+ * are not guaranteed to provide ordering against spinlocks or memory
+ * accesses.
+ */
+
+#define readb_relaxed(c) ({ u8 __v = __raw_readb(c); __v; })
+#define readw_relaxed(c) ({ u16 __v = le16_to_cpu((__force __le16)__raw_readw(c)); __v; })
+#define readl_relaxed(c) ({ u32 __v = le32_to_cpu((__force __le32)__raw_readl(c)); __v; })
+#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)))
+
+/*
+ * {read,write}{b,w,l,q}() access little endian memory and return result in
+ * native endianness.
+ */
+#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 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)); })
+#include <asm-generic/io.h>
+#endif /* __ASM_NDS32_IO_H */
diff --git a/arch/nds32/mm/ioremap.c b/arch/nds32/mm/ioremap.c
new file mode 100644
index 0000000..9b404eb
--- /dev/null
+++ b/arch/nds32/mm/ioremap.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/vmalloc.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <asm/pgtable.h>
+
+void __iomem *ioremap(phys_addr_t phys_addr, size_t size);
+
+static void __iomem *__ioremap_caller(phys_addr_t phys_addr, size_t size,
+ void *caller)
+{
+ struct vm_struct *area;
+ unsigned long addr, offset, last_addr;
+ pgprot_t prot;
+
+ /* Don't allow wraparound or zero size */
+ last_addr = phys_addr + size - 1;
+ if (!size || last_addr < phys_addr)
+ return NULL;
+
+ /*
+ * Mappings have to be page-aligned
+ */
+ offset = phys_addr & ~PAGE_MASK;
+ phys_addr &= PAGE_MASK;
+ size = PAGE_ALIGN(last_addr + 1) - phys_addr;
+
+ /*
+ * Ok, go for it..
+ */
+ area = get_vm_area_caller(size, VM_IOREMAP, caller);
+ if (!area)
+ return NULL;
+
+ area->phys_addr = phys_addr;
+ addr = (unsigned long)area->addr;
+ prot = __pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_D |
+ _PAGE_G | _PAGE_C_DEV);
+ if (ioremap_page_range(addr, addr + size, phys_addr, prot)) {
+ vunmap((void *)addr);
+ return NULL;
+ }
+ return (__force void __iomem *)(offset + (char *)addr);
+
+}
+
+void __iomem *ioremap(phys_addr_t phys_addr, size_t size)
+{
+ return __ioremap_caller(phys_addr, size,
+ __builtin_return_address(0));
+}
+
+EXPORT_SYMBOL(ioremap);
+
+void iounmap(void __iomem * addr)
+{
+ vunmap((void *)(PAGE_MASK & (unsigned long)addr));
+}
+
+EXPORT_SYMBOL(iounmap);
--
1.7.9.5
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH v3 12/33] nds32: Atomic operations
From: Greentime Hu @ 2017-12-08 9:11 UTC (permalink / raw)
To: greentime-MUIXKm3Oiri1Z/+hSey0Gg,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, arnd-r2nGTMty4D4,
linux-arch-u79uwXL29TY76Z2rM5mHXA, tglx-hfZtesqFncYOwBW4kG4KsQ,
jason-NLaQJdtUoK4Be96aLqz0jA, marc.zyngier-5wv7dgnIgG8,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, netdev-u79uwXL29TY76Z2rM5mHXA,
deanbo422-Re5JQEeQqe8AvxtiuMwx3w,
devicetree-u79uwXL29TY76Z2rM5mHXA,
viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
dhowells-H+wXaHxf7aLQT0dZR+AlfA, will.deacon-5wv7dgnIgG8,
daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A,
linux-serial-u79uwXL29TY76Z2rM5mHXA,
geert.uytterhoeven-Re5JQEeQqe8AvxtiuMwx3w,
linus.walleij-QSEj5FYQhm4dnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
greg-U8xfFu+wG4EAvxtiuMwx3w
Cc: green.hu-Re5JQEeQqe8AvxtiuMwx3w, Vincent Chen
In-Reply-To: <cover.1512723245.git.green.hu-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
From: Greentime Hu <greentime-MUIXKm3Oiri1Z/+hSey0Gg@public.gmane.org>
This patch includes the atomic and futex operations. Many atomic operations use
the load-lock word(llw) and store-condition word(scw) operations.
Signed-off-by: Vincent Chen <vincentc-MUIXKm3Oiri1Z/+hSey0Gg@public.gmane.org>
Signed-off-by: Greentime Hu <greentime-MUIXKm3Oiri1Z/+hSey0Gg@public.gmane.org>
---
arch/nds32/include/asm/barrier.h | 28 +++++++++
arch/nds32/include/asm/futex.h | 116 ++++++++++++++++++++++++++++++++++++++
2 files changed, 144 insertions(+)
create mode 100644 arch/nds32/include/asm/barrier.h
create mode 100644 arch/nds32/include/asm/futex.h
diff --git a/arch/nds32/include/asm/barrier.h b/arch/nds32/include/asm/barrier.h
new file mode 100644
index 0000000..d325a78
--- /dev/null
+++ b/arch/nds32/include/asm/barrier.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * 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 __NDS32_ASM_BARRIER_H
+#define __NDS32_ASM_BARRIER_H
+
+#ifndef __ASSEMBLY__
+#define mb() asm volatile("msync all":::"memory")
+#define rmb() asm volatile("msync all":::"memory")
+#define wmb() asm volatile("msync store":::"memory")
+#include <asm-generic/barrier.h>
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __NDS32_ASM_BARRIER_H */
diff --git a/arch/nds32/include/asm/futex.h b/arch/nds32/include/asm/futex.h
new file mode 100644
index 0000000..5aa107c
--- /dev/null
+++ b/arch/nds32/include/asm/futex.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * 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 __NDS32_FUTEX_H__
+#define __NDS32_FUTEX_H__
+
+#include <linux/futex.h>
+#include <linux/uaccess.h>
+#include <asm/errno.h>
+
+#define __futex_atomic_ex_table(err_reg) \
+ " .pushsection __ex_table,\"a\"\n" \
+ " .align 3\n" \
+ " .long 1b, 4f\n" \
+ " .long 2b, 4f\n" \
+ " .popsection\n" \
+ " .pushsection .fixup,\"ax\"\n" \
+ "4: move %0, " err_reg "\n" \
+ " j 3b\n" \
+ " .popsection"
+
+#define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg) \
+ smp_mb(); \
+ asm volatile( \
+ " movi $ta, #0\n" \
+ "1: llw %1, [%2+$ta]\n" \
+ " " insn "\n" \
+ "2: scw %0, [%2+$ta]\n" \
+ " beqz %0, 1b\n" \
+ " movi %0, #0\n" \
+ "3:\n" \
+ __futex_atomic_ex_table("%4") \
+ : "=&r" (ret), "=&r" (oldval) \
+ : "r" (uaddr), "r" (oparg), "i" (-EFAULT) \
+ : "cc", "memory")
+static inline int
+futex_atomic_cmpxchg_inatomic(u32 * uval, u32 __user * uaddr,
+ u32 oldval, u32 newval)
+{
+ int ret = 0;
+ u32 val, tmp, flags;
+
+ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
+ return -EFAULT;
+
+ smp_mb();
+ asm volatile (" movi $ta, #0\n"
+ "1: llw %1, [%6 + $ta]\n"
+ " sub %3, %1, %4\n"
+ " cmovz %2, %5, %3\n"
+ " cmovn %2, %1, %3\n"
+ "2: scw %2, [%6 + $ta]\n"
+ " beqz %2, 1b\n"
+ "3:\n " __futex_atomic_ex_table("%7")
+ :"+&r"(ret), "=&r"(val), "=&r"(tmp), "=&r"(flags)
+ :"r"(oldval), "r"(newval), "r"(uaddr), "i"(-EFAULT)
+ :"$ta", "memory");
+ smp_mb();
+
+ *uval = val;
+ return ret;
+}
+
+static inline int
+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
+{
+ int oldval = 0, ret;
+
+
+ pagefault_disable();
+ switch (op) {
+ case FUTEX_OP_SET:
+ __futex_atomic_op("move %0, %3", ret, oldval, tmp, uaddr,
+ oparg);
+ break;
+ case FUTEX_OP_ADD:
+ __futex_atomic_op("add %0, %1, %3", ret, oldval, tmp, uaddr,
+ oparg);
+ break;
+ case FUTEX_OP_OR:
+ __futex_atomic_op("or %0, %1, %3", ret, oldval, tmp, uaddr,
+ oparg);
+ break;
+ case FUTEX_OP_ANDN:
+ __futex_atomic_op("and %0, %1, %3", ret, oldval, tmp, uaddr,
+ ~oparg);
+ break;
+ case FUTEX_OP_XOR:
+ __futex_atomic_op("xor %0, %1, %3", ret, oldval, tmp, uaddr,
+ oparg);
+ break;
+ default:
+ ret = -ENOSYS;
+ }
+
+ pagefault_enable();
+
+ if (!ret)
+ *oval = oldval;
+
+ return ret;
+}
+#endif /* __NDS32_FUTEX_H__ */
--
1.7.9.5
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox