Hi all,
I think that is the right time to send you next pack with
Microblaze support. It is seventh pack - some previous packs
was review by community and I hope there are not any big faults.
We tested this kernel on some boards.
We have GIT server up and gitweb is available at http://developer.petalogix.com/git/gitweb.cgi
All information about git clone you can find on gitweb.
This pack is available in for-linus branch. Information about other branches are on gitweb too.
More information about microblaze fdt kernel you can find at http://www.monstr.eu/fdt/
If you want to test kernel with microblaze toolchain let me know.
I added only uart16550 and uartlite support - that's enought for first merge.
Thanks for you comments and especially for your ACK,
Michal
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/platform/platform.c | 31 +++++++++++++++++++++++++++++++
1 files changed, 31 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/platform/platform.c
diff --git a/arch/microblaze/platform/platform.c b/arch/microblaze/platform/platform.c
new file mode 100644
index 0000000..56e0234
--- /dev/null
+++ b/arch/microblaze/platform/platform.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 Michal Simek <[email protected]>
+ *
+ * based on virtex.c file
+ *
+ * Copyright 2007 Secret Lab Technologies Ltd.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/init.h>
+#include <linux/of_platform.h>
+#include <asm/prom.h>
+
+static struct of_device_id xilinx_of_bus_ids[] __initdata = {
+ { .compatible = "simple-bus", },
+ { .compatible = "xlnx,plb-v46-1.00.a", },
+ { .compatible = "xlnx,opb-v20-1.10.c", },
+ { .compatible = "xlnx,opb-v20-1.10.b", },
+ { .compatible = "xlnx,compound", },
+ {}
+};
+
+static int __init microblaze_device_probe(void)
+{
+ of_platform_bus_probe(NULL, xilinx_of_bus_ids, NULL);
+ return 0;
+}
+device_initcall(microblaze_device_probe);
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/Kconfig | 136 +++++++++++++++++++++++++
arch/microblaze/Kconfig.debug | 26 +++++
arch/microblaze/platform/Kconfig.platform | 85 +++++++++++++++
arch/microblaze/platform/generic/Kconfig.auto | 62 +++++++++++
4 files changed, 309 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/Kconfig
create mode 100644 arch/microblaze/Kconfig.debug
create mode 100644 arch/microblaze/platform/Kconfig.platform
create mode 100644 arch/microblaze/platform/generic/Kconfig.auto
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
new file mode 100644
index 0000000..a2df3f8
--- /dev/null
+++ b/arch/microblaze/Kconfig
@@ -0,0 +1,136 @@
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.txt.
+
+mainmenu "Linux/Microblaze Kernel Configuration"
+
+config MICROBLAZE
+ def_bool y
+ select HAVE_LMB
+
+config SWAP
+ def_bool n
+
+config RWSEM_GENERIC_SPINLOCK
+ def_bool y
+
+config RWSEM_XCHGADD_ALGORITHM
+ bool
+
+config ARCH_HAS_ILOG2_U32
+ def_bool n
+
+config ARCH_HAS_ILOG2_U64
+ def_bool n
+
+config GENERIC_FIND_NEXT_BIT
+ def_bool y
+
+config GENERIC_HWEIGHT
+ def_bool y
+
+config GENERIC_HARDIRQS
+ def_bool y
+
+config GENERIC_IRQ_PROBE
+ def_bool y
+
+config GENERIC_CALIBRATE_DELAY
+ def_bool y
+
+config GENERIC_TIME
+ def_bool y
+
+config GENERIC_TIME_VSYSCALL
+ def_bool n
+
+config GENERIC_CLOCKEVENTS
+ def_bool y
+
+config PCI
+ depends on !MMU
+ def_bool n
+
+config NO_DMA
+ depends on !MMU
+ def_bool n
+
+source "init/Kconfig"
+
+source "arch/microblaze/platform/Kconfig.platform"
+
+menu "Processor type and features"
+
+source kernel/time/Kconfig
+
+source "kernel/Kconfig.preempt"
+
+source "kernel/Kconfig.hz"
+
+config MMU
+ def_bool n
+
+config NO_MMU
+ bool
+ depends on !MMU
+ default y
+
+comment "Boot options"
+
+config CMDLINE_BOOL
+ bool "Default bootloader kernel arguments"
+
+config CMDLINE
+ string "Default kernel command string"
+ depends on CMDLINE_BOOL
+ default "console=ttyUL0,115200"
+ help
+ On some architectures there is currently no way for the boot loader
+ to pass arguments to the kernel. For these architectures, you should
+ supply some command-line options at build time by entering them
+ here.
+
+config CMDLINE_FORCE
+ bool "Force default kernel command string"
+ depends on CMDLINE_BOOL
+ default n
+ help
+ Set this to have arguments from the default kernel command string
+ override those passed by the boot loader.
+
+config OF
+ def_bool y
+
+config OF_DEVICE
+ def_bool y
+
+config PROC_DEVICETREE
+ bool "Support for device tree in /proc"
+ depends on PROC_FS
+ help
+ This option adds a device-tree directory under /proc which contains
+ an image of the device tree that the kernel copies from Open
+ Firmware or other boot firmware. If unsure, say Y here.
+
+endmenu
+
+source "mm/Kconfig"
+
+menu "Exectuable file formats"
+
+source "fs/Kconfig.binfmt"
+
+endmenu
+
+source "net/Kconfig"
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+source "arch/microblaze/Kconfig.debug"
+
+source "security/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
diff --git a/arch/microblaze/Kconfig.debug b/arch/microblaze/Kconfig.debug
new file mode 100644
index 0000000..242cd35
--- /dev/null
+++ b/arch/microblaze/Kconfig.debug
@@ -0,0 +1,26 @@
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.txt.
+
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config EARLY_PRINTK
+ bool "Early printk function for kernel"
+ default n
+ help
+ This option turns on/off early printk messages to console.
+ First Uartlite node is taken.
+
+config HEART_BEAT
+ bool "Heart beat function for kernel"
+ default n
+ help
+ This option turns on/off heart beat kernel functionality.
+ First GPIO node is taken.
+
+config DEBUG_BOOTMEM
+ depends on DEBUG_KERNEL
+ bool "Debug BOOTMEM initialization"
+
+endmenu
diff --git a/arch/microblaze/platform/Kconfig.platform b/arch/microblaze/platform/Kconfig.platform
new file mode 100644
index 0000000..8e9b475
--- /dev/null
+++ b/arch/microblaze/platform/Kconfig.platform
@@ -0,0 +1,85 @@
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.txt.
+#
+# Platform selection Kconfig menu for MicroBlaze targets
+#
+
+menu "Platform options"
+choice
+ prompt "Platform"
+ default PLATFORM_MICROBLAZE_AUTO
+ help
+ Choose which hardware board/platform you are targeting.
+
+config PLATFORM_GENERIC
+ bool "Generic"
+ help
+ Choose this option for the Generic platform.
+
+endchoice
+
+config SELFMOD
+ bool "Use self modified code for intc/timer"
+ depends on EXPERIMENTAL && NO_MMU
+ default n
+ help
+ This choice enables self-modified code for interrupt controller
+ and timer.
+
+config SELFMOD_INTC
+ bool "Use self modified code for intc"
+ depends on SELFMOD
+ default y
+ help
+ This choice enables self-modified code for interrupt controller.
+
+config SELFMOD_TIMER
+ bool "Use self modified code for timer"
+ depends on SELFMOD
+ default y
+ help
+ This choice enables self-modified code for timer.
+
+config OPT_LIB_FUNCTION
+ bool "Optimalized lib function"
+ default y
+ help
+ Allows turn on optimalized library function (memcpy and memmove).
+ They are optimized by using word alignment. This will work
+ fine if both source and destination are aligned on the same
+ boundary. However, if they are aligned on different boundaries
+ shifts will be necessary. This might result in bad performance
+ on MicroBlaze systems without a barrel shifter.
+
+config OPT_LIB_ASM
+ bool "Optimalized lib function ASM"
+ depends on OPT_LIB_FUNCTION
+ default n
+ help
+ Allows turn on optimalized library function (memcpy and memmove).
+ Function are written in asm code.
+
+# This is still a bit broken - disabling for now JW 20070504
+config ALLOW_EDIT_AUTO
+ bool "Permit Display/edit of Kconfig.auto platform settings"
+ default n
+ help
+ Allows the editing of auto-generated platform settings from
+ the Kconfig.auto file. Obviously this does not change the
+ underlying hardware, so be very careful if you go editing
+ these settings.
+
+ Also, if you enable this, and edit various Kconfig.auto
+ settings, YOUR CHANGES WILL BE LOST if you then disable it
+ again. You have been warned!
+
+ If unsure, say no.
+
+comment "Automatic platform settings from Kconfig.auto"
+ depends on ALLOW_EDIT_AUTO
+
+if PLATFORM_GENERIC=y
+ source "arch/microblaze/platform/generic/Kconfig.auto"
+endif
+
+endmenu
diff --git a/arch/microblaze/platform/generic/Kconfig.auto b/arch/microblaze/platform/generic/Kconfig.auto
new file mode 100644
index 0000000..fbca22d
--- /dev/null
+++ b/arch/microblaze/platform/generic/Kconfig.auto
@@ -0,0 +1,62 @@
+#
+# (C) Copyright 2007 Michal Simek
+#
+# Michal SIMEK <[email protected]>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+# Definitions for MICROBLAZE0
+comment "Definitions for MICROBLAZE0"
+ depends on ALLOW_EDIT_AUTO
+
+config KERNEL_BASE_ADDR
+ hex "Physical address where Linux Kernel is"
+ default "0x90000000"
+ help
+ BASE Address for kernel
+
+config XILINX_MICROBLAZE0_FAMILY
+ string "Targetted FPGA family" if ALLOW_EDIT_AUTO
+ default "virtex5"
+
+config XILINX_MICROBLAZE0_USE_MSR_INSTR
+ int "USE_MSR_INSTR range (0:1)" if ALLOW_EDIT_AUTO
+ default 1
+
+config XILINX_MICROBLAZE0_USE_PCMP_INSTR
+ int "USE_PCMP_INSTR range (0:1)" if ALLOW_EDIT_AUTO
+ default 1
+
+config XILINX_MICROBLAZE0_USE_BARREL
+ int "USE_BARREL range (0:1)" if ALLOW_EDIT_AUTO
+ default 1
+
+config XILINX_MICROBLAZE0_USE_DIV
+ int "USE_DIV range (0:1)" if ALLOW_EDIT_AUTO
+ default 1
+
+config XILINX_MICROBLAZE0_USE_HW_MUL
+ int "USE_HW_MUL values (0=NONE, 1=MUL32, 2=MUL64)" if ALLOW_EDIT_AUTO
+ default 2
+
+config XILINX_MICROBLAZE0_USE_FPU
+ int "USE_FPU values (0=NONE, 1=BASIC, 2=EXTENDED)" if ALLOW_EDIT_AUTO
+ default 2
+
+config XILINX_MICROBLAZE0_HW_VER
+ string "Core version number" if ALLOW_EDIT_AUTO
+ default 7.10.d
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/Makefile | 69 +++++++++++++++++++++++++++++
arch/microblaze/boot/Makefile | 17 +++++++
arch/microblaze/kernel/Makefile | 19 ++++++++
arch/microblaze/kernel/cpu/Makefile | 8 +++
arch/microblaze/lib/Makefile | 13 +++++
arch/microblaze/mm/Makefile | 5 ++
arch/microblaze/platform/Makefile | 6 +++
arch/microblaze/platform/generic/Makefile | 3 +
8 files changed, 140 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/Makefile
create mode 100644 arch/microblaze/boot/Makefile
create mode 100644 arch/microblaze/kernel/Makefile
create mode 100644 arch/microblaze/kernel/cpu/Makefile
create mode 100644 arch/microblaze/lib/Makefile
create mode 100644 arch/microblaze/mm/Makefile
create mode 100644 arch/microblaze/platform/Makefile
create mode 100644 arch/microblaze/platform/generic/Makefile
diff --git a/arch/microblaze/Makefile b/arch/microblaze/Makefile
new file mode 100644
index 0000000..0dcbb98
--- /dev/null
+++ b/arch/microblaze/Makefile
@@ -0,0 +1,69 @@
+UTS_SYSNAME = -DUTS_SYSNAME=\"uClinux\"
+
+# What CPU vesion are we building for, and crack it open
+# as major.minor.rev
+CPU_VER=$(subst ",,$(CONFIG_XILINX_MICROBLAZE0_HW_VER) )
+CPU_MAJOR=$(shell echo $(CPU_VER) | cut -d '.' -f 1)
+CPU_MINOR=$(shell echo $(CPU_VER) | cut -d '.' -f 2)
+CPU_REV=$(shell echo $(CPU_VER) | cut -d '.' -f 3)
+
+export CPU_VER CPU_MAJOR CPU_MINOR CPU_REV
+
+# Use cpu-related CONFIG_ vars to set compile options.
+
+# Work out HW multipler support. This is icky.
+# 1. Spartan2 has no HW multiplers.
+# 2. MicroBlaze v3.x always uses them, except in Spartan 2
+# 3. All other FPGa/CPU ver combos, we can trust the CONFIG_ settings
+ifeq (,$(findstring spartan2,$(CONFIG_XILINX_MICROBLAZE0_FAMILY)))
+ ifeq ($(CPU_MAJOR),3)
+ CPUFLAGS-1 += -mno-xl-soft-mul
+ else
+ # USE_HW_MUL can be 0, 1, or 2, defining a heirarchy of HW Mul support.
+ CPUFLAGS-$(subst 1,,$(CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL)) += -mxl-multiply-high
+ CPUFLAGS-$(CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL) += -mno-xl-soft-mul
+ endif
+endif
+CPUFLAGS-$(CONFIG_XILINX_MICROBLAZE0_USE_DIV) += -mno-xl-soft-div
+CPUFLAGS-$(CONFIG_XILINX_MICROBLAZE0_USE_BARREL) += -mxl-barrel-shift
+CPUFLAGS-$(CONFIG_XILINX_MICROBLAZE0_USE_PCMP) += -mxl-pattern-compare
+
+CPUFLAGS-1 += $(call cc-option,-mcpu=v$(CPU_VER))
+
+# The various CONFIG_XILINX cpu features options are integers 0/1/2...
+# rather than bools y/n
+CFLAGS += $(CPUFLAGS-1)
+CFLAGS += $(CPUFLAGS-2)
+
+# r31 holds current when in kernel mode
+CFLAGS += -ffixed-r31
+
+LDFLAGS_BLOB := --format binary --oformat elf32-microblaze
+
+LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
+
+head-y := arch/microblaze/kernel/head.o
+libs-y += arch/microblaze/lib/ $(LIBGCC)
+core-y += arch/microblaze/kernel/ arch/microblaze/mm/ \
+ arch/microblaze/platform/
+
+boot := arch/$(ARCH)/boot
+
+# defines filename extension depending memory management type
+ifeq ($(CONFIG_MMU),)
+MMUEXT := -nommu
+endif
+export MMUEXT
+
+all: linux.bin
+
+archclean:
+ $(Q)$(MAKE) $(clean)=$(boot)
+
+linux.bin linux.bin.gz: vmlinux
+ $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+
+define archhelp
+ echo '* linux.bin - Create raw binary'
+ echo ' linux.bin.gz - Create compressed raw binary'
+endef
diff --git a/arch/microblaze/boot/Makefile b/arch/microblaze/boot/Makefile
new file mode 100644
index 0000000..844edf4
--- /dev/null
+++ b/arch/microblaze/boot/Makefile
@@ -0,0 +1,17 @@
+#
+# arch/microblaze/boot/Makefile
+#
+
+targets := linux.bin linux.bin.gz
+
+OBJCOPYFLAGS_linux.bin := -O binary
+
+$(obj)/linux.bin: vmlinux FORCE
+ $(call if_changed,objcopy)
+ @echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
+
+$(obj)/linux.bin.gz: $(obj)/linux.bin FORCE
+ $(call if_changed,gzip)
+ @echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
+
+clean-kernel += linux.bin linux.bin.gz
diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile
new file mode 100644
index 0000000..da94bec
--- /dev/null
+++ b/arch/microblaze/kernel/Makefile
@@ -0,0 +1,19 @@
+#
+# Makefile
+#
+
+extra-y := head.o vmlinux.lds
+
+obj-y += exceptions.o \
+ hw_exception_handler.o init_task.o intc.o irq.o of_device.o \
+ of_platform.o process.o prom.o prom_parse.o ptrace.o \
+ setup.o signal.o sys_microblaze.o timer.o traps.o
+
+obj-y += cpu/
+
+obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+obj-$(CONFIG_SELFMOD) += selfmod.o
+obj-$(CONFIG_HEART_BEAT) += heartbeat.o
+obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o
+
+obj-y += entry$(MMUEXT).o
diff --git a/arch/microblaze/kernel/cpu/Makefile b/arch/microblaze/kernel/cpu/Makefile
new file mode 100644
index 0000000..20646e5
--- /dev/null
+++ b/arch/microblaze/kernel/cpu/Makefile
@@ -0,0 +1,8 @@
+#
+# Build the appropriate CPU version support
+#
+
+EXTRA_CFLAGS += -DCPU_MAJOR=$(CPU_MAJOR) -DCPU_MINOR=$(CPU_MINOR) \
+ -DCPU_REV=$(CPU_REV)
+
+obj-y += cache.o cpuinfo.o cpuinfo-pvr-full.o cpuinfo-static.o mb.o pvr.o
diff --git a/arch/microblaze/lib/Makefile b/arch/microblaze/lib/Makefile
new file mode 100644
index 0000000..86d63fd
--- /dev/null
+++ b/arch/microblaze/lib/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile
+#
+
+lib-y := memset.o checksum.o
+
+ifeq ($(CONFIG_OPT_LIB_ASM),y)
+lib-y += fastcopy.o
+else
+lib-y += memcpy.o memmove.o
+endif
+
+lib-y += uaccess.o
diff --git a/arch/microblaze/mm/Makefile b/arch/microblaze/mm/Makefile
new file mode 100644
index 0000000..bf9e447
--- /dev/null
+++ b/arch/microblaze/mm/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile
+#
+
+obj-y := init.o
diff --git a/arch/microblaze/platform/Makefile b/arch/microblaze/platform/Makefile
new file mode 100644
index 0000000..ea1b75c
--- /dev/null
+++ b/arch/microblaze/platform/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for arch/microblaze/platform directory
+#
+#obj-$(CONFIG_PLATFORM_GENERIC) += generic/
+
+obj-y += platform.o
diff --git a/arch/microblaze/platform/generic/Makefile b/arch/microblaze/platform/generic/Makefile
new file mode 100644
index 0000000..9a8b1bd
--- /dev/null
+++ b/arch/microblaze/platform/generic/Makefile
@@ -0,0 +1,3 @@
+#
+# Empty Makefile to keep make clean happy
+#
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/cpuinfo.h | 102 +++++++++++++++++
arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c | 101 +++++++++++++++++
arch/microblaze/kernel/cpu/cpuinfo-static.c | 145 +++++++++++++++++++++++++
arch/microblaze/kernel/cpu/cpuinfo.c | 87 +++++++++++++++
4 files changed, 435 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/cpuinfo.h
create mode 100644 arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
create mode 100644 arch/microblaze/kernel/cpu/cpuinfo-static.c
create mode 100644 arch/microblaze/kernel/cpu/cpuinfo.c
diff --git a/arch/microblaze/include/asm/cpuinfo.h b/arch/microblaze/include/asm/cpuinfo.h
new file mode 100644
index 0000000..0f40f7a
--- /dev/null
+++ b/arch/microblaze/include/asm/cpuinfo.h
@@ -0,0 +1,102 @@
+/*
+ * Generic support for queying CPU info
+ *
+ * Copyright (C) 2007-2008 Michal Simek <[email protected]>
+ * Copyright (C) 2007 John Williams <[email protected]>
+ * Copyright (C) 2007 PetaLogix
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_CPUINFO_H
+#define _ASM_MICROBLAZE_CPUINFO_H
+
+#include <asm/prom.h>
+
+/* CPU Version and FPGA Family code conversion table type */
+struct cpu_ver_key {
+ const char *s;
+ const unsigned k;
+};
+
+extern const struct cpu_ver_key cpu_ver_lookup[];
+
+struct family_string_key {
+ const char *s;
+ const unsigned k;
+};
+
+extern const struct family_string_key family_string_lookup[];
+
+struct cpuinfo {
+ /* Core CPU configuration */
+ int use_instr;
+ int use_mult;
+ int use_fpu;
+ int use_exc;
+ int ver_code;
+ int mmu;
+
+ /* CPU caches */
+ int use_icache;
+ int icache_tagbits;
+ int icache_write;
+ int icache_line;
+ int icache_size;
+ unsigned long icache_base;
+ unsigned long icache_high;
+
+ int use_dcache;
+ int dcache_tagbits;
+ int dcache_write;
+ int dcache_line;
+ int dcache_size;
+ unsigned long dcache_base;
+ unsigned long dcache_high;
+
+ /* Bus connections */
+ int use_dopb;
+ int use_iopb;
+ int use_dlmb;
+ int use_ilmb;
+ int num_fsl;
+
+ /* CPU interrupt line info */
+ int irq_edge;
+ int irq_positive;
+
+ int area_optimised;
+
+ /* HW debug support */
+ int hw_debug;
+ int num_pc_brk;
+ int num_rd_brk;
+ int num_wr_brk;
+ int cpu_clock_freq; /* store real freq of cpu */
+ int freq_div_hz; /* store freq/HZ */
+
+ /* FPGA family */
+ int fpga_family_code;
+
+ /* User define */
+ int pvr_user1;
+ int pvr_user2;
+};
+
+extern struct cpuinfo cpuinfo;
+
+/* fwd declarations of the various CPUinfo populators */
+void setup_cpuinfo(void);
+
+void set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu);
+void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu);
+
+static inline unsigned int fcpu(struct device_node *cpu, char *n)
+{
+ int *val;
+ return (val = (int *) of_get_property(cpu, n, NULL)) ? *val : 0;
+}
+
+#endif /* _ASM_MICROBLAZE_CPUINFO_H */
diff --git a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
new file mode 100644
index 0000000..576b456
--- /dev/null
+++ b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
@@ -0,0 +1,101 @@
+/*
+ * Support for MicroBlaze PVR (processor version register)
+ *
+ * Copyright (C) 2007 John Williams <[email protected]>
+ * Copyright (C) 2007 PetaLogix
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/string.h>
+#include <asm/pvr.h>
+#include <asm/cpuinfo.h>
+
+/*
+ * Helper macro to map between fields in our struct cpuinfo, and
+ * the PVR macros in pvr.h.
+ */
+
+#define CI(c, p) { ci->c = PVR_##p(pvr); }
+#define err_printk(x) \
+ early_printk("ERROR: Microblaze " x " - different for PVR and DTS\n");
+
+void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
+{
+ struct pvr_s pvr;
+ int temp; /* for saving temp value */
+ get_pvr(&pvr);
+
+ temp = PVR_USE_BARREL(pvr) | PVR_USE_MSR_INSTR(pvr) |\
+ PVR_USE_PCMP_INSTR(pvr) | PVR_USE_DIV(pvr);
+ if (ci->use_instr != temp)
+ err_printk("BARREL, MSR, PCMP or DIV");
+ ci->use_instr = temp;
+
+ temp = PVR_USE_HW_MUL(pvr) | PVR_USE_MUL64(pvr);
+ if (ci->use_mult != temp)
+ err_printk("HW_MUL");
+ ci->use_mult = temp;
+
+ temp = PVR_USE_FPU(pvr) | PVR_USE_FPU2(pvr);
+ if (ci->use_fpu != temp)
+ err_printk("HW_FPU");
+ ci->use_fpu = temp;
+
+ ci->use_exc = PVR_OPCODE_0x0_ILLEGAL(pvr) |\
+ PVR_UNALIGNED_EXCEPTION(pvr) |\
+ PVR_ILL_OPCODE_EXCEPTION(pvr) |\
+ PVR_IOPB_BUS_EXCEPTION(pvr) |\
+ PVR_DOPB_BUS_EXCEPTION(pvr) |\
+ PVR_DIV_ZERO_EXCEPTION(pvr) |\
+ PVR_FPU_EXCEPTION(pvr) |\
+ PVR_FSL_EXCEPTION(pvr);
+
+ CI(pvr_user1, USER1);
+ CI(pvr_user2, USER2);
+
+ CI(mmu, USE_MMU);
+
+ CI(ver_code, VERSION);
+
+ CI(use_icache, USE_ICACHE);
+ CI(icache_tagbits, ICACHE_ADDR_TAG_BITS);
+ CI(icache_write, ICACHE_ALLOW_WR);
+ CI(icache_line, ICACHE_LINE_LEN);
+ CI(icache_size, ICACHE_BYTE_SIZE);
+ CI(icache_base, ICACHE_BASEADDR);
+ CI(icache_high, ICACHE_HIGHADDR);
+
+ CI(use_dcache, USE_DCACHE);
+ CI(dcache_tagbits, DCACHE_ADDR_TAG_BITS);
+ CI(dcache_write, DCACHE_ALLOW_WR);
+ CI(dcache_line, DCACHE_LINE_LEN);
+ CI(dcache_size, DCACHE_BYTE_SIZE);
+ CI(dcache_base, DCACHE_BASEADDR);
+ CI(dcache_high, DCACHE_HIGHADDR);
+
+ CI(use_dopb, D_OPB);
+ CI(use_iopb, I_OPB);
+ CI(use_dlmb, D_LMB);
+ CI(use_ilmb, I_LMB);
+ CI(num_fsl, FSL_LINKS);
+
+ CI(irq_edge, INTERRUPT_IS_EDGE);
+ CI(irq_positive, EDGE_IS_POSITIVE);
+
+ CI(area_optimised, AREA_OPTIMISED);
+
+ CI(hw_debug, DEBUG_ENABLED);
+ CI(num_pc_brk, NUMBER_OF_PC_BRK);
+ CI(num_rd_brk, NUMBER_OF_RD_ADDR_BRK);
+ CI(num_wr_brk, NUMBER_OF_WR_ADDR_BRK);
+
+ CI(fpga_family_code, TARGET_FAMILY);
+
+ /* take timebase-frequency from DTS */
+ ci->cpu_clock_freq = fcpu(cpu, "timebase-frequency");
+}
diff --git a/arch/microblaze/kernel/cpu/cpuinfo-static.c b/arch/microblaze/kernel/cpu/cpuinfo-static.c
new file mode 100644
index 0000000..2bba402
--- /dev/null
+++ b/arch/microblaze/kernel/cpu/cpuinfo-static.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2007-2008 Michal Simek <[email protected]>
+ * Copyright (C) 2007 John Williams <[email protected]>
+ * Copyright (C) 2007 PetaLogix
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <asm/cpuinfo.h>
+#include <asm/pvr.h>
+
+const static char family_string[] = CONFIG_XILINX_MICROBLAZE0_FAMILY;
+const static char cpu_ver_string[] = CONFIG_XILINX_MICROBLAZE0_HW_VER;
+
+#define err_printk(x) \
+ early_printk("ERROR: Microblaze " x "- different for kernel and DTS\n");
+
+void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu)
+{
+ int i = 0;
+
+ ci->use_instr =
+ (fcpu(cpu, "xlnx,use-barrel") ? PVR0_USE_BARREL_MASK : 0) |
+ (fcpu(cpu, "xlnx,use-msr-instr") ? PVR2_USE_MSR_INSTR : 0) |
+ (fcpu(cpu, "xlnx,use-pcmp-instr") ? PVR2_USE_PCMP_INSTR : 0) |
+ (fcpu(cpu, "xlnx,use-div") ? PVR0_USE_DIV_MASK : 0);
+ if (CONFIG_XILINX_MICROBLAZE0_USE_BARREL)
+ i |= PVR0_USE_BARREL_MASK;
+ if (CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR)
+ i |= PVR2_USE_MSR_INSTR;
+ if (CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR)
+ i |= PVR2_USE_PCMP_INSTR;
+ if (CONFIG_XILINX_MICROBLAZE0_USE_DIV)
+ i |= PVR0_USE_DIV_MASK;
+ if (ci->use_instr != i)
+ err_printk("BARREL, MSR, PCMP or DIV");
+
+ ci->use_mult = fcpu(cpu, "xlnx,use-hw-mul");
+ if (ci->use_mult != CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL)
+ err_printk("HW_MUL");
+ ci->use_mult =
+ (ci->use_mult > 1 ?
+ (PVR2_USE_MUL64_MASK | PVR0_USE_HW_MUL_MASK) :
+ (ci->use_mult == 1 ? PVR0_USE_HW_MUL_MASK : 0));
+
+ ci->use_fpu = fcpu(cpu, "xlnx,use-fpu");
+ if (ci->use_fpu != CONFIG_XILINX_MICROBLAZE0_USE_FPU)
+ err_printk("HW_FPU");
+ ci->use_fpu = (ci->use_fpu > 1 ?
+ (PVR2_USE_FPU2_MASK | PVR0_USE_FPU_MASK) :
+ (ci->use_fpu == 1 ? PVR0_USE_FPU_MASK : 0));
+
+ ci->use_exc =
+ (fcpu(cpu, "xlnx,unaligned-exceptions") ?
+ PVR2_UNALIGNED_EXC_MASK : 0) |
+ (fcpu(cpu, "xlnx,ill-opcode-exception") ?
+ PVR2_ILL_OPCODE_EXC_MASK : 0) |
+ (fcpu(cpu, "xlnx,iopb-bus-exception") ?
+ PVR2_IOPB_BUS_EXC_MASK : 0) |
+ (fcpu(cpu, "xlnx,dopb-bus-exception") ?
+ PVR2_DOPB_BUS_EXC_MASK : 0) |
+ (fcpu(cpu, "xlnx,div-zero-exception") ?
+ PVR2_DIV_ZERO_EXC_MASK : 0) |
+ (fcpu(cpu, "xlnx,fpu-exception") ? PVR2_FPU_EXC_MASK : 0) |
+ (fcpu(cpu, "xlnx,fsl-exception") ? PVR2_USE_EXTEND_FSL : 0);
+
+ ci->use_icache = fcpu(cpu, "xlnx,use-icache");
+ ci->icache_tagbits = fcpu(cpu, "xlnx,addr-tag-bits");
+ ci->icache_write = fcpu(cpu, "xlnx,allow-icache-wr");
+ ci->icache_line = fcpu(cpu, "xlnx,icache-line-len") << 2;
+ if (!ci->icache_line) {
+ if (fcpu(cpu, "xlnx,icache-use-fsl"))
+ ci->icache_line = 4 << 2;
+ else
+ ci->icache_line = 1 << 2;
+ }
+ ci->icache_size = fcpu(cpu, "i-cache-size");
+ ci->icache_base = fcpu(cpu, "i-cache-baseaddr");
+ ci->icache_high = fcpu(cpu, "i-cache-highaddr");
+
+ ci->use_dcache = fcpu(cpu, "xlnx,use-dcache");
+ ci->dcache_tagbits = fcpu(cpu, "xlnx,dcache-addr-tag");
+ ci->dcache_write = fcpu(cpu, "xlnx,allow-dcache-wr");
+ ci->dcache_line = fcpu(cpu, "xlnx,dcache-line-len") << 2;
+ if (!ci->dcache_line) {
+ if (fcpu(cpu, "xlnx,dcache-use-fsl"))
+ ci->dcache_line = 4 << 2;
+ else
+ ci->dcache_line = 1 << 2;
+ }
+ ci->dcache_size = fcpu(cpu, "d-cache-size");
+ ci->dcache_base = fcpu(cpu, "d-cache-baseaddr");
+ ci->dcache_high = fcpu(cpu, "d-cache-highaddr");
+
+ ci->use_dopb = fcpu(cpu, "xlnx,d-opb");
+ ci->use_iopb = fcpu(cpu, "xlnx,i-opb");
+ ci->use_dlmb = fcpu(cpu, "xlnx,d-lmb");
+ ci->use_ilmb = fcpu(cpu, "xlnx,i-lmb");
+
+ ci->num_fsl = fcpu(cpu, "xlnx,fsl-links");
+ ci->irq_edge = fcpu(cpu, "xlnx,interrupt-is-edge");
+ ci->irq_positive = fcpu(cpu, "xlnx,edge-is-positive");
+ ci->area_optimised = 0;
+
+ ci->hw_debug = fcpu(cpu, "xlnx,debug-enabled");
+ ci->num_pc_brk = fcpu(cpu, "xlnx,number-of-pc-brk");
+ ci->num_rd_brk = fcpu(cpu, "xlnx,number-of-rd-addr-brk");
+ ci->num_wr_brk = fcpu(cpu, "xlnx,number-of-wr-addr-brk");
+
+ ci->cpu_clock_freq = fcpu(cpu, "timebase-frequency");
+
+ ci->pvr_user1 = fcpu(cpu, "xlnx,pvr-user1");
+ ci->pvr_user2 = fcpu(cpu, "xlnx,pvr-user2");
+
+ ci->mmu = fcpu(cpu, "xlnx,use-mmu");
+
+ ci->ver_code = 0;
+ ci->fpga_family_code = 0;
+
+ /* Do various fixups based on CPU version and FPGA family strings */
+
+ /* Resolved the CPU version code */
+ for (i = 0; cpu_ver_lookup[i].s != NULL; i++) {
+ if (strcmp(cpu_ver_lookup[i].s, cpu_ver_string) == 0)
+ ci->ver_code = cpu_ver_lookup[i].k;
+ }
+
+ /* Resolved the fpga family code */
+ for (i = 0; family_string_lookup[i].s != NULL; i++) {
+ if (strcmp(family_string_lookup[i].s, family_string) == 0)
+ ci->fpga_family_code = family_string_lookup[i].k;
+ }
+
+ /* FIXME - mb3 and spartan2 do not exist in PVR */
+ /* This is mb3 and on a non Spartan2 */
+ if (ci->ver_code == 0x20 && ci->fpga_family_code != 0xf0)
+ /* Hardware Multiplier in use */
+ ci->use_mult = 1;
+}
diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c
new file mode 100644
index 0000000..3cf2b3a
--- /dev/null
+++ b/arch/microblaze/kernel/cpu/cpuinfo.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2007-2008 Michal Simek <[email protected]>
+ * Copyright (C) 2007 John Williams <[email protected]>
+ * Copyright (C) 2007 PetaLogix
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <asm/cpuinfo.h>
+#include <asm/pvr.h>
+
+const struct cpu_ver_key cpu_ver_lookup[] = {
+ /* These key value are as per MBV field in PVR0 */
+ {"5.00.a", 0x01},
+ {"5.00.b", 0x02},
+ {"5.00.c", 0x03},
+ {"6.00.a", 0x04},
+ {"6.00.b", 0x06},
+ {"7.00.a", 0x05},
+ {"7.00.b", 0x07},
+ {"7.10.a", 0x08},
+ {"7.10.b", 0x09},
+ {"7.10.c", 0x0a},
+ {"7.10.d", 0x0b},
+ /* FIXME There is no keycode defined in MBV for these versions */
+ {"2.10.a", 0x10},
+ {"3.00.a", 0x20},
+ {"4.00.a", 0x30},
+ {"4.00.b", 0x40},
+ {NULL, 0},
+};
+
+/*
+ * FIXME Not sure if the actual key is defined by Xilinx in the PVR
+ */
+const struct family_string_key family_string_lookup[] = {
+ {"virtex2", 0x4},
+ {"virtex2pro", 0x5},
+ {"spartan3", 0x6},
+ {"virtex4", 0x7},
+ {"virtex5", 0x8},
+ {"spartan3e", 0x9},
+ {"spartan3a", 0xa},
+ {"spartan3an", 0xb},
+ {"spartan3adsp", 0xc},
+ /* FIXME There is no key code defined for spartan2 */
+ {"spartan2", 0xf0},
+ {NULL, 0},
+};
+
+struct cpuinfo cpuinfo;
+
+void __init setup_cpuinfo(void)
+{
+ struct device_node *cpu = NULL;
+
+ cpu = (struct device_node *) of_find_node_by_type(NULL, "cpu");
+ if (!cpu)
+ printk(KERN_ERR "You don't have cpu!!!\n");
+
+ printk(KERN_INFO "%s: initialising\n", __func__);
+
+ switch (cpu_has_pvr()) {
+ case 0:
+ printk(KERN_WARNING
+ "%s: No PVR support. Using static CPU info from FDT\n",
+ __func__);
+ set_cpuinfo_static(&cpuinfo, cpu);
+ break;
+/* FIXME I found weird behavior with MB 7.00.a/b
+ * please do not use FULL PVR with MMU */
+ case 1:
+ printk(KERN_INFO "%s: Using full CPU PVR support\n",
+ __func__);
+ set_cpuinfo_static(&cpuinfo, cpu);
+ set_cpuinfo_pvr_full(&cpuinfo, cpu);
+ break;
+ default:
+ printk(KERN_WARNING "%s: Unsupported PVR setting\n", __func__);
+ set_cpuinfo_static(&cpuinfo, cpu);
+ }
+}
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/of_device.h | 45 ++
arch/microblaze/include/asm/of_platform.h | 64 ++
arch/microblaze/include/asm/prom.h | 313 ++++++++
arch/microblaze/kernel/of_device.c | 115 +++
arch/microblaze/kernel/of_platform.c | 201 +++++
arch/microblaze/kernel/prom.c | 1147 +++++++++++++++++++++++++++++
arch/microblaze/kernel/prom_parse.c | 1025 ++++++++++++++++++++++++++
7 files changed, 2910 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/of_device.h
create mode 100644 arch/microblaze/include/asm/of_platform.h
create mode 100644 arch/microblaze/include/asm/prom.h
create mode 100644 arch/microblaze/kernel/of_device.c
create mode 100644 arch/microblaze/kernel/of_platform.c
create mode 100644 arch/microblaze/kernel/prom.c
create mode 100644 arch/microblaze/kernel/prom_parse.c
diff --git a/arch/microblaze/include/asm/of_device.h b/arch/microblaze/include/asm/of_device.h
new file mode 100644
index 0000000..ba917cf
--- /dev/null
+++ b/arch/microblaze/include/asm/of_device.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2007-2008 Michal Simek <[email protected]>
+ *
+ * based on PowerPC of_device.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_OF_DEVICE_H
+#define _ASM_MICROBLAZE_OF_DEVICE_H
+#ifdef __KERNEL__
+
+#include <linux/device.h>
+#include <linux/of.h>
+
+/*
+ * The of_device is a kind of "base class" that is a superset of
+ * struct device for use by devices attached to an OF node and
+ * probed using OF properties.
+ */
+struct of_device {
+ struct device_node *node; /* to be obsoleted */
+ u64 dma_mask; /* DMA mask */
+ struct device dev; /* Generic device interface */
+};
+
+extern ssize_t of_device_get_modalias(struct of_device *ofdev,
+ char *str, ssize_t len);
+
+extern struct of_device *of_device_alloc(struct device_node *np,
+ const char *bus_id,
+ struct device *parent);
+
+extern int of_device_uevent(struct device *dev,
+ struct kobj_uevent_env *env);
+
+extern void of_device_make_bus_id(struct of_device *dev);
+
+/* This is just here during the transition */
+#include <linux/of_device.h>
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_MICROBLAZE_OF_DEVICE_H */
diff --git a/arch/microblaze/include/asm/of_platform.h b/arch/microblaze/include/asm/of_platform.h
new file mode 100644
index 0000000..187c0ee
--- /dev/null
+++ b/arch/microblaze/include/asm/of_platform.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
+ * <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _ASM_MICROBLAZE_OF_PLATFORM_H
+#define _ASM_MICROBLAZE_OF_PLATFORM_H
+
+/* This is just here during the transition */
+#include <linux/of_platform.h>
+
+/*
+ * The list of OF IDs below is used for matching bus types in the
+ * system whose devices are to be exposed as of_platform_devices.
+ *
+ * This is the default list valid for most platforms. This file provides
+ * functions who can take an explicit list if necessary though
+ *
+ * The search is always performed recursively looking for children of
+ * the provided device_node and recursively if such a children matches
+ * a bus type in the list
+ */
+
+static const struct of_device_id of_default_bus_ids[] = {
+ { .type = "soc", },
+ { .compatible = "soc", },
+ { .type = "plb5", },
+ { .type = "plb4", },
+ { .type = "opb", },
+ { .type = "simple", },
+ {},
+};
+
+/* Platform drivers register/unregister */
+static inline int of_register_platform_driver(struct of_platform_driver *drv)
+{
+ return of_register_driver(drv, &of_platform_bus_type);
+}
+static inline void of_unregister_platform_driver(struct of_platform_driver *drv)
+{
+ of_unregister_driver(drv);
+}
+
+/* Platform devices and busses creation */
+extern struct of_device *of_platform_device_create(struct device_node *np,
+ const char *bus_id,
+ struct device *parent);
+/* pseudo "matches" value to not do deep probe */
+#define OF_NO_DEEP_PROBE ((struct of_device_id *)-1)
+
+extern int of_platform_bus_probe(struct device_node *root,
+ const struct of_device_id *matches,
+ struct device *parent);
+
+extern struct of_device *of_find_device_by_phandle(phandle ph);
+
+extern void of_instantiate_rtc(void);
+
+#endif /* _ASM_MICROBLAZE_OF_PLATFORM_H */
diff --git a/arch/microblaze/include/asm/prom.h b/arch/microblaze/include/asm/prom.h
new file mode 100644
index 0000000..20f7b3a
--- /dev/null
+++ b/arch/microblaze/include/asm/prom.h
@@ -0,0 +1,313 @@
+/*
+ * Definitions for talking to the Open Firmware PROM on
+ * Power Macintosh computers.
+ *
+ * Copyright (C) 1996-2005 Paul Mackerras.
+ *
+ * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _ASM_MICROBLAZE_PROM_H
+#define _ASM_MICROBLAZE_PROM_H
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/platform_device.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+
+#define OF_ROOT_NODE_ADDR_CELLS_DEFAULT 1
+#define OF_ROOT_NODE_SIZE_CELLS_DEFAULT 1
+
+#define of_compat_cmp(s1, s2, l) strncasecmp((s1), (s2), (l))
+#define of_prop_cmp(s1, s2) strcmp((s1), (s2))
+#define of_node_cmp(s1, s2) strcasecmp((s1), (s2))
+
+/* Definitions used by the flattened device tree */
+#define OF_DT_HEADER 0xd00dfeed /* marker */
+#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
+#define OF_DT_END_NODE 0x2 /* End node */
+#define OF_DT_PROP 0x3 /* Property: name off, size, content */
+#define OF_DT_NOP 0x4 /* nop */
+#define OF_DT_END 0x9
+
+#define OF_DT_VERSION 0x10
+
+/*
+ * This is what gets passed to the kernel by prom_init or kexec
+ *
+ * The dt struct contains the device tree structure, full pathes and
+ * property contents. The dt strings contain a separate block with just
+ * the strings for the property names, and is fully page aligned and
+ * self contained in a page, so that it can be kept around by the kernel,
+ * each property name appears only once in this page (cheap compression)
+ *
+ * the mem_rsvmap contains a map of reserved ranges of physical memory,
+ * passing it here instead of in the device-tree itself greatly simplifies
+ * the job of everybody. It's just a list of u64 pairs (base/size) that
+ * ends when size is 0
+ */
+struct boot_param_header {
+ u32 magic; /* magic word OF_DT_HEADER */
+ u32 totalsize; /* total size of DT block */
+ u32 off_dt_struct; /* offset to structure */
+ u32 off_dt_strings; /* offset to strings */
+ u32 off_mem_rsvmap; /* offset to memory reserve map */
+ u32 version; /* format version */
+ u32 last_comp_version; /* last compatible version */
+ /* version 2 fields below */
+ u32 boot_cpuid_phys; /* Physical CPU id we're booting on */
+ /* version 3 fields below */
+ u32 dt_strings_size; /* size of the DT strings block */
+ /* version 17 fields below */
+ u32 dt_struct_size; /* size of the DT structure block */
+};
+
+typedef u32 phandle;
+typedef u32 ihandle;
+
+struct property {
+ char *name;
+ int length;
+ void *value;
+ struct property *next;
+};
+
+struct device_node {
+ const char *name;
+ const char *type;
+ phandle node;
+ phandle linux_phandle;
+ char *full_name;
+
+ struct property *properties;
+ struct property *deadprops; /* removed properties */
+ struct device_node *parent;
+ struct device_node *child;
+ struct device_node *sibling;
+ struct device_node *next; /* next device of same type */
+ struct device_node *allnext; /* next in list of all nodes */
+ struct proc_dir_entry *pde; /* this node's proc directory */
+ struct kref kref;
+ unsigned long _flags;
+ void *data;
+};
+
+extern struct device_node *of_chosen;
+
+static inline int of_node_check_flag(struct device_node *n, unsigned long flag)
+{
+ return test_bit(flag, &n->_flags);
+}
+
+static inline void of_node_set_flag(struct device_node *n, unsigned long flag)
+{
+ set_bit(flag, &n->_flags);
+}
+
+#define HAVE_ARCH_DEVTREE_FIXUPS
+
+static inline void set_node_proc_entry(struct device_node *dn,
+ struct proc_dir_entry *de)
+{
+ dn->pde = de;
+}
+
+extern struct device_node *allnodes; /* temporary while merging */
+extern rwlock_t devtree_lock; /* temporary while merging */
+
+extern struct device_node *of_find_all_nodes(struct device_node *prev);
+extern struct device_node *of_node_get(struct device_node *node);
+extern void of_node_put(struct device_node *node);
+
+/* For scanning the flat device-tree at boot time */
+extern int __init of_scan_flat_dt(int (*it)(unsigned long node,
+ const char *uname, int depth,
+ void *data),
+ void *data);
+extern void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
+ unsigned long *size);
+extern int __init
+ of_flat_dt_is_compatible(unsigned long node, const char *name);
+extern unsigned long __init of_get_flat_dt_root(void);
+
+/* For updating the device tree at runtime */
+extern void of_attach_node(struct device_node *);
+extern void of_detach_node(struct device_node *);
+
+/* Other Prototypes */
+extern void finish_device_tree(void);
+extern void unflatten_device_tree(void);
+extern int early_uartlite_console(void);
+extern void early_init_devtree(void *);
+extern int machine_is_compatible(const char *compat);
+extern void print_properties(struct device_node *node);
+extern int prom_n_intr_cells(struct device_node *np);
+extern void prom_get_irq_senses(unsigned char *senses, int off, int max);
+extern int prom_add_property(struct device_node *np, struct property *prop);
+extern int prom_remove_property(struct device_node *np, struct property *prop);
+extern int prom_update_property(struct device_node *np,
+ struct property *newprop,
+ struct property *oldprop);
+
+extern struct resource *request_OF_resource(struct device_node *node,
+ int index, const char *name_postfix);
+extern int release_OF_resource(struct device_node *node, int index);
+
+/*
+ * OF address retreival & translation
+ */
+
+/* Helper to read a big number; size is in cells (not bytes) */
+static inline u64 of_read_number(const u32 *cell, int size)
+{
+ u64 r = 0;
+ while (size--)
+ r = (r << 32) | *(cell++);
+ return r;
+}
+
+/* Like of_read_number, but we want an unsigned long result */
+#define of_read_ulong(cell, size) of_read_number(cell, size)
+
+/* Translate an OF address block into a CPU physical address
+ */
+extern u64 of_translate_address(struct device_node *np, const u32 *addr);
+
+/* Extract an address from a device, returns the region size and
+ * the address space flags too. The PCI version uses a BAR number
+ * instead of an absolute index
+ */
+extern const u32 *of_get_address(struct device_node *dev, int index,
+ u64 *size, unsigned int *flags);
+extern const u32 *of_get_pci_address(struct device_node *dev, int bar_no,
+ u64 *size, unsigned int *flags);
+
+/* Get an address as a resource. Note that if your address is
+ * a PIO address, the conversion will fail if the physical address
+ * can't be internally converted to an IO token with
+ * pci_address_to_pio(), that is because it's either called to early
+ * or it can't be matched to any host bridge IO space
+ */
+extern int of_address_to_resource(struct device_node *dev, int index,
+ struct resource *r);
+extern int of_pci_address_to_resource(struct device_node *dev, int bar,
+ struct resource *r);
+
+/* Parse the ibm,dma-window property of an OF node into the busno, phys and
+ * size parameters.
+ */
+void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
+ unsigned long *busno, unsigned long *phys, unsigned long *size);
+
+extern void kdump_move_device_tree(void);
+
+/* CPU OF node matching */
+struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
+
+/* Get the MAC address */
+extern const void *of_get_mac_address(struct device_node *np);
+
+/*
+ * OF interrupt mapping
+ */
+
+/* This structure is returned when an interrupt is mapped. The controller
+ * field needs to be put() after use
+ */
+
+#define OF_MAX_IRQ_SPEC 4 /* We handle specifiers of at most 4 cells */
+
+struct of_irq {
+ struct device_node *controller; /* Interrupt controller node */
+ u32 size; /* Specifier size */
+ u32 specifier[OF_MAX_IRQ_SPEC]; /* Specifier copy */
+};
+
+/**
+ * of_irq_map_init - Initialize the irq remapper
+ * @flags: flags defining workarounds to enable
+ *
+ * Some machines have bugs in the device-tree which require certain workarounds
+ * to be applied. Call this before any interrupt mapping attempts to enable
+ * those workarounds.
+ */
+#define OF_IMAP_OLDWORLD_MAC 0x00000001
+#define OF_IMAP_NO_PHANDLE 0x00000002
+
+extern void of_irq_map_init(unsigned int flags);
+
+/**
+ * of_irq_map_raw - Low level interrupt tree parsing
+ * @parent: the device interrupt parent
+ * @intspec: interrupt specifier ("interrupts" property of the device)
+ * @ointsize: size of the passed in interrupt specifier
+ * @addr: address specifier (start of "reg" property of the device)
+ * @out_irq: structure of_irq filled by this function
+ *
+ * Returns 0 on success and a negative number on error
+ *
+ * This function is a low-level interrupt tree walking function. It
+ * can be used to do a partial walk with synthetized reg and interrupts
+ * properties, for example when resolving PCI interrupts when no device
+ * node exist for the parent.
+ *
+ */
+
+extern int of_irq_map_raw(struct device_node *parent, const u32 *intspec,
+ u32 ointsize, const u32 *addr,
+ struct of_irq *out_irq);
+
+/**
+ * of_irq_map_one - Resolve an interrupt for a device
+ * @device: the device whose interrupt is to be resolved
+ * @index: index of the interrupt to resolve
+ * @out_irq: structure of_irq filled by this function
+ *
+ * This function resolves an interrupt, walking the tree, for a given
+ * device-tree node. It's the high level pendant to of_irq_map_raw().
+ * It also implements the workarounds for OldWolrd Macs.
+ */
+extern int of_irq_map_one(struct device_node *device, int index,
+ struct of_irq *out_irq);
+
+/**
+ * of_irq_map_pci - Resolve the interrupt for a PCI device
+ * @pdev: the device whose interrupt is to be resolved
+ * @out_irq: structure of_irq filled by this function
+ *
+ * This function resolves the PCI interrupt for a given PCI device. If a
+ * device-node exists for a given pci_dev, it will use normal OF tree
+ * walking. If not, it will implement standard swizzling and walk up the
+ * PCI tree until an device-node is found, at which point it will finish
+ * resolving using the OF tree walking.
+ */
+struct pci_dev;
+extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq);
+
+extern int of_irq_to_resource(struct device_node *dev, int index,
+ struct resource *r);
+
+/**
+ * of_iomap - Maps the memory mapped IO for a given device_node
+ * @device: the device whose io range will be mapped
+ * @index: index of the io range
+ *
+ * Returns a pointer to the mapped memory
+ */
+extern void __iomem *of_iomap(struct device_node *device, int index);
+
+/*
+ * NB: This is here while we transition from using asm/prom.h
+ * to linux/of.h
+ */
+#include <linux/of.h>
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_MICROBLAZE_PROM_H */
diff --git a/arch/microblaze/kernel/of_device.c b/arch/microblaze/kernel/of_device.c
new file mode 100644
index 0000000..717edf4
--- /dev/null
+++ b/arch/microblaze/kernel/of_device.c
@@ -0,0 +1,115 @@
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/slab.h>
+#include <linux/of_device.h>
+
+#include <linux/errno.h>
+
+void of_device_make_bus_id(struct of_device *dev)
+{
+ static atomic_t bus_no_reg_magic;
+ struct device_node *node = dev->node;
+ char *name = dev->dev.bus_id;
+ const u32 *reg;
+ u64 addr;
+ int magic;
+
+ /*
+ * For MMIO, get the physical address
+ */
+ reg = of_get_property(node, "reg", NULL);
+ if (reg) {
+ addr = of_translate_address(node, reg);
+ if (addr != OF_BAD_ADDR) {
+ snprintf(name, BUS_ID_SIZE,
+ "%llx.%s", (unsigned long long)addr,
+ node->name);
+ return;
+ }
+ }
+
+ /*
+ * No BusID, use the node name and add a globally incremented
+ * counter (and pray...)
+ */
+ magic = atomic_add_return(1, &bus_no_reg_magic);
+ snprintf(name, BUS_ID_SIZE, "%s.%d", node->name, magic - 1);
+}
+EXPORT_SYMBOL(of_device_make_bus_id);
+
+struct of_device *of_device_alloc(struct device_node *np,
+ const char *bus_id,
+ struct device *parent)
+{
+ struct of_device *dev;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return NULL;
+
+ dev->node = of_node_get(np);
+ dev->dev.dma_mask = &dev->dma_mask;
+ dev->dev.parent = parent;
+ dev->dev.release = of_release_dev;
+ dev->dev.archdata.of_node = np;
+
+ if (bus_id)
+ strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
+ else
+ of_device_make_bus_id(dev);
+
+ return dev;
+}
+EXPORT_SYMBOL(of_device_alloc);
+
+int of_device_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+ struct of_device *ofdev;
+ const char *compat;
+ int seen = 0, cplen, sl;
+
+ if (!dev)
+ return -ENODEV;
+
+ ofdev = to_of_device(dev);
+
+ if (add_uevent_var(env, "OF_NAME=%s", ofdev->node->name))
+ return -ENOMEM;
+
+ if (add_uevent_var(env, "OF_TYPE=%s", ofdev->node->type))
+ return -ENOMEM;
+
+ /* Since the compatible field can contain pretty much anything
+ * it's not really legal to split it out with commas. We split it
+ * up using a number of environment variables instead. */
+
+ compat = of_get_property(ofdev->node, "compatible", &cplen);
+ while (compat && *compat && cplen > 0) {
+ if (add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat))
+ return -ENOMEM;
+
+ sl = strlen(compat) + 1;
+ compat += sl;
+ cplen -= sl;
+ seen++;
+ }
+
+ if (add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen))
+ return -ENOMEM;
+
+ /* modalias is trickier, we add it in 2 steps */
+ if (add_uevent_var(env, "MODALIAS="))
+ return -ENOMEM;
+ sl = of_device_get_modalias(ofdev, &env->buf[env->buflen-1],
+ sizeof(env->buf) - env->buflen);
+ if (sl >= (sizeof(env->buf) - env->buflen))
+ return -ENOMEM;
+ env->buflen += sl;
+
+ return 0;
+}
+EXPORT_SYMBOL(of_device_uevent);
diff --git a/arch/microblaze/kernel/of_platform.c b/arch/microblaze/kernel/of_platform.c
new file mode 100644
index 0000000..acf4574
--- /dev/null
+++ b/arch/microblaze/kernel/of_platform.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
+ * <[email protected]>
+ * and Arnd Bergmann, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+
+#include <linux/errno.h>
+#include <linux/topology.h>
+#include <asm/atomic.h>
+
+struct bus_type of_platform_bus_type = {
+ .uevent = of_device_uevent,
+};
+EXPORT_SYMBOL(of_platform_bus_type);
+
+static int __init of_bus_driver_init(void)
+{
+ return of_bus_type_init(&of_platform_bus_type, "of_platform");
+}
+postcore_initcall(of_bus_driver_init);
+
+struct of_device *of_platform_device_create(struct device_node *np,
+ const char *bus_id,
+ struct device *parent)
+{
+ struct of_device *dev;
+
+ dev = of_device_alloc(np, bus_id, parent);
+ if (!dev)
+ return NULL;
+
+ dev->dma_mask = 0xffffffffUL;
+ dev->dev.bus = &of_platform_bus_type;
+
+ /* We do not fill the DMA ops for platform devices by default.
+ * This is currently the responsibility of the platform code
+ * to do such, possibly using a device notifier
+ */
+
+ if (of_device_register(dev) != 0) {
+ of_device_free(dev);
+ return NULL;
+ }
+
+ return dev;
+}
+EXPORT_SYMBOL(of_platform_device_create);
+
+/**
+ * of_platform_bus_create - Create an OF device for a bus node and all its
+ * children. Optionally recursively instanciate matching busses.
+ * @bus: device node of the bus to instanciate
+ * @matches: match table, NULL to use the default, OF_NO_DEEP_PROBE to
+ * disallow recursive creation of child busses
+ */
+static int of_platform_bus_create(const struct device_node *bus,
+ const struct of_device_id *matches,
+ struct device *parent)
+{
+ struct device_node *child;
+ struct of_device *dev;
+ int rc = 0;
+
+ for_each_child_of_node(bus, child) {
+ pr_debug(" create child: %s\n", child->full_name);
+ dev = of_platform_device_create(child, NULL, parent);
+ if (dev == NULL)
+ rc = -ENOMEM;
+ else if (!of_match_node(matches, child))
+ continue;
+ if (rc == 0) {
+ pr_debug(" and sub busses\n");
+ rc = of_platform_bus_create(child, matches, &dev->dev);
+ }
+ if (rc) {
+ of_node_put(child);
+ break;
+ }
+ }
+ return rc;
+}
+
+
+/**
+ * of_platform_bus_probe - Probe the device-tree for platform busses
+ * @root: parent of the first level to probe or NULL for the root of the tree
+ * @matches: match table, NULL to use the default
+ * @parent: parent to hook devices from, NULL for toplevel
+ *
+ * Note that children of the provided root are not instanciated as devices
+ * unless the specified root itself matches the bus list and is not NULL.
+ */
+
+int of_platform_bus_probe(struct device_node *root,
+ const struct of_device_id *matches,
+ struct device *parent)
+{
+ struct device_node *child;
+ struct of_device *dev;
+ int rc = 0;
+
+ if (matches == NULL)
+ matches = of_default_bus_ids;
+ if (matches == OF_NO_DEEP_PROBE)
+ return -EINVAL;
+ if (root == NULL)
+ root = of_find_node_by_path("/");
+ else
+ of_node_get(root);
+
+ pr_debug("of_platform_bus_probe()\n");
+ pr_debug(" starting at: %s\n", root->full_name);
+
+ /* Do a self check of bus type, if there's a match, create
+ * children
+ */
+ if (of_match_node(matches, root)) {
+ pr_debug(" root match, create all sub devices\n");
+ dev = of_platform_device_create(root, NULL, parent);
+ if (dev == NULL) {
+ rc = -ENOMEM;
+ goto bail;
+ }
+ pr_debug(" create all sub busses\n");
+ rc = of_platform_bus_create(root, matches, &dev->dev);
+ goto bail;
+ }
+ for_each_child_of_node(root, child) {
+ if (!of_match_node(matches, child))
+ continue;
+
+ pr_debug(" match: %s\n", child->full_name);
+ dev = of_platform_device_create(child, NULL, parent);
+ if (dev == NULL)
+ rc = -ENOMEM;
+ else
+ rc = of_platform_bus_create(child, matches, &dev->dev);
+ if (rc) {
+ of_node_put(child);
+ break;
+ }
+ }
+ bail:
+ of_node_put(root);
+ return rc;
+}
+EXPORT_SYMBOL(of_platform_bus_probe);
+
+static int of_dev_node_match(struct device *dev, void *data)
+{
+ return to_of_device(dev)->node == data;
+}
+
+struct of_device *of_find_device_by_node(struct device_node *np)
+{
+ struct device *dev;
+
+ dev = bus_find_device(&of_platform_bus_type,
+ NULL, np, of_dev_node_match);
+ if (dev)
+ return to_of_device(dev);
+ return NULL;
+}
+EXPORT_SYMBOL(of_find_device_by_node);
+
+static int of_dev_phandle_match(struct device *dev, void *data)
+{
+ phandle *ph = data;
+ return to_of_device(dev)->node->linux_phandle == *ph;
+}
+
+struct of_device *of_find_device_by_phandle(phandle ph)
+{
+ struct device *dev;
+
+ dev = bus_find_device(&of_platform_bus_type,
+ NULL, &ph, of_dev_phandle_match);
+ if (dev)
+ return to_of_device(dev);
+ return NULL;
+}
+EXPORT_SYMBOL(of_find_device_by_phandle);
diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c
new file mode 100644
index 0000000..475b1fa
--- /dev/null
+++ b/arch/microblaze/kernel/prom.c
@@ -0,0 +1,1147 @@
+/*
+ * Procedures for creating, accessing and interpreting the device tree.
+ *
+ * Paul Mackerras August 1996.
+ * Copyright (C) 1996-2005 Paul Mackerras.
+ *
+ * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
+ * {engebret|bergner}@us.ibm.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <stdarg.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/threads.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/stringify.h>
+#include <linux/delay.h>
+#include <linux/initrd.h>
+#include <linux/bitops.h>
+#include <linux/module.h>
+#include <linux/kexec.h>
+#include <linux/debugfs.h>
+#include <linux/irq.h>
+#include <linux/lmb.h>
+
+#include <asm/prom.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+#include <asm/irq.h>
+#include <linux/io.h>
+#include <asm/system.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <linux/pci.h>
+#include <asm/sections.h>
+#include <asm/pci-bridge.h>
+
+static int __initdata dt_root_addr_cells;
+static int __initdata dt_root_size_cells;
+
+typedef u32 cell_t;
+
+static struct boot_param_header *initial_boot_params;
+
+/* export that to outside world */
+struct device_node *of_chosen;
+
+static inline char *find_flat_dt_string(u32 offset)
+{
+ return ((char *)initial_boot_params) +
+ initial_boot_params->off_dt_strings + offset;
+}
+
+/**
+ * This function is used to scan the flattened device-tree, it is
+ * used to extract the memory informations at boot before we can
+ * unflatten the tree
+ */
+int __init of_scan_flat_dt(int (*it)(unsigned long node,
+ const char *uname, int depth,
+ void *data),
+ void *data)
+{
+ unsigned long p = ((unsigned long)initial_boot_params) +
+ initial_boot_params->off_dt_struct;
+ int rc = 0;
+ int depth = -1;
+
+ do {
+ u32 tag = *((u32 *)p);
+ char *pathp;
+
+ p += 4;
+ if (tag == OF_DT_END_NODE) {
+ depth--;
+ continue;
+ }
+ if (tag == OF_DT_NOP)
+ continue;
+ if (tag == OF_DT_END)
+ break;
+ if (tag == OF_DT_PROP) {
+ u32 sz = *((u32 *)p);
+ p += 8;
+ if (initial_boot_params->version < 0x10)
+ p = _ALIGN(p, sz >= 8 ? 8 : 4);
+ p += sz;
+ p = _ALIGN(p, 4);
+ continue;
+ }
+ if (tag != OF_DT_BEGIN_NODE) {
+ printk(KERN_WARNING "Invalid tag %x scanning flattened"
+ " device tree !\n", tag);
+ return -EINVAL;
+ }
+ depth++;
+ pathp = (char *)p;
+ p = _ALIGN(p + strlen(pathp) + 1, 4);
+ if ((*pathp) == '/') {
+ char *lp, *np;
+ for (lp = NULL, np = pathp; *np; np++)
+ if ((*np) == '/')
+ lp = np+1;
+ if (lp != NULL)
+ pathp = lp;
+ }
+ rc = it(p, pathp, depth, data);
+ if (rc != 0)
+ break;
+ } while (1);
+
+ return rc;
+}
+
+unsigned long __init of_get_flat_dt_root(void)
+{
+ unsigned long p = ((unsigned long)initial_boot_params) +
+ initial_boot_params->off_dt_struct;
+
+ while (*((u32 *)p) == OF_DT_NOP)
+ p += 4;
+ BUG_ON(*((u32 *)p) != OF_DT_BEGIN_NODE);
+ p += 4;
+ return _ALIGN(p + strlen((char *)p) + 1, 4);
+}
+
+/**
+ * This function can be used within scan_flattened_dt callback to get
+ * access to properties
+ */
+void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
+ unsigned long *size)
+{
+ unsigned long p = node;
+
+ do {
+ u32 tag = *((u32 *)p);
+ u32 sz, noff;
+ const char *nstr;
+
+ p += 4;
+ if (tag == OF_DT_NOP)
+ continue;
+ if (tag != OF_DT_PROP)
+ return NULL;
+
+ sz = *((u32 *)p);
+ noff = *((u32 *)(p + 4));
+ p += 8;
+ if (initial_boot_params->version < 0x10)
+ p = _ALIGN(p, sz >= 8 ? 8 : 4);
+
+ nstr = find_flat_dt_string(noff);
+ if (nstr == NULL) {
+ printk(KERN_WARNING "Can't find property index"
+ " name !\n");
+ return NULL;
+ }
+ if (strcmp(name, nstr) == 0) {
+ if (size)
+ *size = sz;
+ return (void *)p;
+ }
+ p += sz;
+ p = _ALIGN(p, 4);
+ } while (1);
+}
+
+int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
+{
+ const char *cp;
+ unsigned long cplen, l;
+
+ cp = of_get_flat_dt_prop(node, "compatible", &cplen);
+ if (cp == NULL)
+ return 0;
+ while (cplen > 0) {
+ if (strncasecmp(cp, compat, strlen(compat)) == 0)
+ return 1;
+ l = strlen(cp) + 1;
+ cp += l;
+ cplen -= l;
+ }
+
+ return 0;
+}
+
+static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
+ unsigned long align)
+{
+ void *res;
+
+ *mem = _ALIGN(*mem, align);
+ res = (void *)*mem;
+ *mem += size;
+
+ return res;
+}
+
+static unsigned long __init unflatten_dt_node(unsigned long mem,
+ unsigned long *p,
+ struct device_node *dad,
+ struct device_node ***allnextpp,
+ unsigned long fpsize)
+{
+ struct device_node *np;
+ struct property *pp, **prev_pp = NULL;
+ char *pathp;
+ u32 tag;
+ unsigned int l, allocl;
+ int has_name = 0;
+ int new_format = 0;
+
+ tag = *((u32 *)(*p));
+ if (tag != OF_DT_BEGIN_NODE) {
+ printk("Weird tag at start of node: %x\n", tag);
+ return mem;
+ }
+ *p += 4;
+ pathp = (char *)*p;
+ l = allocl = strlen(pathp) + 1;
+ *p = _ALIGN(*p + l, 4);
+
+ /* version 0x10 has a more compact unit name here instead of the full
+ * path. we accumulate the full path size using "fpsize", we'll rebuild
+ * it later. We detect this because the first character of the name is
+ * not '/'.
+ */
+ if ((*pathp) != '/') {
+ new_format = 1;
+ if (fpsize == 0) {
+ /* root node: special case. fpsize accounts for path
+ * plus terminating zero. root node only has '/', so
+ * fpsize should be 2, but we want to avoid the first
+ * level nodes to have two '/' so we use fpsize 1 here
+ */
+ fpsize = 1;
+ allocl = 2;
+ } else {
+ /* account for '/' and path size minus terminal 0
+ * already in 'l'
+ */
+ fpsize += l;
+ allocl = fpsize;
+ }
+ }
+
+ np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
+ __alignof__(struct device_node));
+ if (allnextpp) {
+ memset(np, 0, sizeof(*np));
+ np->full_name = ((char *)np) + sizeof(struct device_node);
+ if (new_format) {
+ char *p2 = np->full_name;
+ /* rebuild full path for new format */
+ if (dad && dad->parent) {
+ strcpy(p2, dad->full_name);
+#ifdef DEBUG
+ if ((strlen(p2) + l + 1) != allocl) {
+ pr_debug("%s: p: %d, l: %d, a: %d\n",
+ pathp, (int)strlen(p2),
+ l, allocl);
+ }
+#endif
+ p2 += strlen(p2);
+ }
+ *(p2++) = '/';
+ memcpy(p2, pathp, l);
+ } else
+ memcpy(np->full_name, pathp, l);
+ prev_pp = &np->properties;
+ **allnextpp = np;
+ *allnextpp = &np->allnext;
+ if (dad != NULL) {
+ np->parent = dad;
+ /* we temporarily use the next field as `last_child'*/
+ if (dad->next == NULL)
+ dad->child = np;
+ else
+ dad->next->sibling = np;
+ dad->next = np;
+ }
+ kref_init(&np->kref);
+ }
+ while (1) {
+ u32 sz, noff;
+ char *pname;
+
+ tag = *((u32 *)(*p));
+ if (tag == OF_DT_NOP) {
+ *p += 4;
+ continue;
+ }
+ if (tag != OF_DT_PROP)
+ break;
+ *p += 4;
+ sz = *((u32 *)(*p));
+ noff = *((u32 *)((*p) + 4));
+ *p += 8;
+ if (initial_boot_params->version < 0x10)
+ *p = _ALIGN(*p, sz >= 8 ? 8 : 4);
+
+ pname = find_flat_dt_string(noff);
+ if (pname == NULL) {
+ printk(KERN_INFO
+ "Can't find property name in list !\n");
+ break;
+ }
+ if (strcmp(pname, "name") == 0)
+ has_name = 1;
+ l = strlen(pname) + 1;
+ pp = unflatten_dt_alloc(&mem, sizeof(struct property),
+ __alignof__(struct property));
+ if (allnextpp) {
+ if (strcmp(pname, "linux,phandle") == 0) {
+ np->node = *((u32 *)*p);
+ if (np->linux_phandle == 0)
+ np->linux_phandle = np->node;
+ }
+ if (strcmp(pname, "ibm,phandle") == 0)
+ np->linux_phandle = *((u32 *)*p);
+ pp->name = pname;
+ pp->length = sz;
+ pp->value = (void *)*p;
+ *prev_pp = pp;
+ prev_pp = &pp->next;
+ }
+ *p = _ALIGN((*p) + sz, 4);
+ }
+ /* with version 0x10 we may not have the name property, recreate
+ * it here from the unit name if absent
+ */
+ if (!has_name) {
+ char *p1 = pathp, *ps = pathp, *pa = NULL;
+ int sz;
+
+ while (*p1) {
+ if ((*p1) == '@')
+ pa = p1;
+ if ((*p1) == '/')
+ ps = p1 + 1;
+ p1++;
+ }
+ if (pa < ps)
+ pa = p1;
+ sz = (pa - ps) + 1;
+ pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz,
+ __alignof__(struct property));
+ if (allnextpp) {
+ pp->name = "name";
+ pp->length = sz;
+ pp->value = pp + 1;
+ *prev_pp = pp;
+ prev_pp = &pp->next;
+ memcpy(pp->value, ps, sz - 1);
+ ((char *)pp->value)[sz - 1] = 0;
+ pr_debug("fixed up name for %s -> %s\n", pathp,
+ (char *)pp->value);
+ }
+ }
+ if (allnextpp) {
+ *prev_pp = NULL;
+ np->name = of_get_property(np, "name", NULL);
+ np->type = of_get_property(np, "device_type", NULL);
+
+ if (!np->name)
+ np->name = "<NULL>";
+ if (!np->type)
+ np->type = "<NULL>";
+ }
+ while (tag == OF_DT_BEGIN_NODE) {
+ mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize);
+ tag = *((u32 *)(*p));
+ }
+ if (tag != OF_DT_END_NODE) {
+ printk(KERN_INFO "Weird tag at end of node: %x\n", tag);
+ return mem;
+ }
+ *p += 4;
+ return mem;
+}
+
+/**
+ * unflattens the device-tree passed by the firmware, creating the
+ * tree of struct device_node. It also fills the "name" and "type"
+ * pointers of the nodes so the normal device-tree walking functions
+ * can be used (this used to be done by finish_device_tree)
+ */
+void __init unflatten_device_tree(void)
+{
+ unsigned long start, mem, size;
+ struct device_node **allnextp = &allnodes;
+
+ pr_debug(" -> unflatten_device_tree()\n");
+
+ /* First pass, scan for size */
+ start = ((unsigned long)initial_boot_params) +
+ initial_boot_params->off_dt_struct;
+ size = unflatten_dt_node(0, &start, NULL, NULL, 0);
+ size = (size | 3) + 1;
+
+ pr_debug(" size is %lx, allocating...\n", size);
+
+ /* Allocate memory for the expanded device tree */
+ mem = lmb_alloc(size + 4, __alignof__(struct device_node));
+ mem = (unsigned long) __va(mem);
+
+ ((u32 *)mem)[size / 4] = 0xdeadbeef;
+
+ pr_debug(" unflattening %lx...\n", mem);
+
+ /* Second pass, do actual unflattening */
+ start = ((unsigned long)initial_boot_params) +
+ initial_boot_params->off_dt_struct;
+ unflatten_dt_node(mem, &start, NULL, &allnextp, 0);
+ if (*((u32 *)start) != OF_DT_END)
+ printk(KERN_WARNING "Weird tag at end of tree: %08x\n",
+ *((u32 *)start));
+ if (((u32 *)mem)[size / 4] != 0xdeadbeef)
+ printk(KERN_WARNING "End of tree marker overwritten: %08x\n",
+ ((u32 *)mem)[size / 4]);
+ *allnextp = NULL;
+
+ /* Get pointer to OF "/chosen" node for use everywhere */
+ of_chosen = of_find_node_by_path("/chosen");
+ if (of_chosen == NULL)
+ of_chosen = of_find_node_by_path("/chosen@0");
+
+ pr_debug(" <- unflatten_device_tree()\n");
+}
+
+#define early_init_dt_scan_drconf_memory(node) 0
+
+static int __init early_init_dt_scan_cpus(unsigned long node,
+ const char *uname, int depth,
+ void *data)
+{
+ static int logical_cpuid;
+ char *type = of_get_flat_dt_prop(node, "device_type", NULL);
+ const u32 *intserv;
+ int i, nthreads;
+ int found = 0;
+
+ /* We are scanning "cpu" nodes only */
+ if (type == NULL || strcmp(type, "cpu") != 0)
+ return 0;
+
+ /* Get physical cpuid */
+ intserv = of_get_flat_dt_prop(node, "reg", NULL);
+ nthreads = 1;
+
+ /*
+ * Now see if any of these threads match our boot cpu.
+ * NOTE: This must match the parsing done in smp_setup_cpu_maps.
+ */
+ for (i = 0; i < nthreads; i++) {
+ /*
+ * version 2 of the kexec param format adds the phys cpuid of
+ * booted proc.
+ */
+ if (initial_boot_params && initial_boot_params->version >= 2) {
+ if (intserv[i] ==
+ initial_boot_params->boot_cpuid_phys) {
+ found = 1;
+ break;
+ }
+ } else {
+ /*
+ * Check if it's the boot-cpu, set it's hw index now,
+ * unfortunately this format did not support booting
+ * off secondary threads.
+ */
+ if (of_get_flat_dt_prop(node,
+ "linux,boot-cpu", NULL) != NULL) {
+ found = 1;
+ break;
+ }
+ }
+
+#ifdef CONFIG_SMP
+ /* logical cpu id is always 0 on UP kernels */
+ logical_cpuid++;
+#endif
+ }
+
+ if (found) {
+ pr_debug("boot cpu: logical %d physical %d\n", logical_cpuid,
+ intserv[i]);
+ boot_cpuid = logical_cpuid;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+static void __init early_init_dt_check_for_initrd(unsigned long node)
+{
+ unsigned long l;
+ u32 *prop;
+
+ pr_debug("Looking for initrd properties... ");
+
+ prop = of_get_flat_dt_prop(node, "linux,initrd-start", &l);
+ if (prop) {
+ initrd_start = (unsigned long)__va(of_read_ulong(prop, l/4));
+
+ prop = of_get_flat_dt_prop(node, "linux,initrd-end", &l);
+ if (prop) {
+ initrd_end = (unsigned long)
+ __va(of_read_ulong(prop, l/4));
+ initrd_below_start_ok = 1;
+ } else {
+ initrd_start = 0;
+ }
+ }
+
+ pr_debug("initrd_start=0x%lx initrd_end=0x%lx\n",
+ initrd_start, initrd_end);
+}
+#else
+static inline void early_init_dt_check_for_initrd(unsigned long node)
+{
+}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+static int __init early_init_dt_scan_chosen(unsigned long node,
+ const char *uname, int depth, void *data)
+{
+ unsigned long l;
+ char *p;
+
+ pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
+
+ if (depth != 1 ||
+ (strcmp(uname, "chosen") != 0 &&
+ strcmp(uname, "chosen@0") != 0))
+ return 0;
+
+#ifdef CONFIG_KEXEC
+ lprop = (u64 *)of_get_flat_dt_prop(node,
+ "linux,crashkernel-base", NULL);
+ if (lprop)
+ crashk_res.start = *lprop;
+
+ lprop = (u64 *)of_get_flat_dt_prop(node,
+ "linux,crashkernel-size", NULL);
+ if (lprop)
+ crashk_res.end = crashk_res.start + *lprop - 1;
+#endif
+
+ early_init_dt_check_for_initrd(node);
+
+ /* Retreive command line */
+ p = of_get_flat_dt_prop(node, "bootargs", &l);
+ if (p != NULL && l > 0)
+ strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE));
+
+#ifdef CONFIG_CMDLINE
+ if (p == NULL || l == 0 || (l == 1 && (*p) == 0))
+ strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
+#endif /* CONFIG_CMDLINE */
+
+ pr_debug("Command line is: %s\n", cmd_line);
+
+ /* break now */
+ return 1;
+}
+
+static int __init early_init_dt_scan_root(unsigned long node,
+ const char *uname, int depth, void *data)
+{
+ u32 *prop;
+
+ if (depth != 0)
+ return 0;
+
+ prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
+ dt_root_size_cells = (prop == NULL) ? 1 : *prop;
+ pr_debug("dt_root_size_cells = %x\n", dt_root_size_cells);
+
+ prop = of_get_flat_dt_prop(node, "#address-cells", NULL);
+ dt_root_addr_cells = (prop == NULL) ? 2 : *prop;
+ pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells);
+
+ /* break now */
+ return 1;
+}
+
+static u64 __init dt_mem_next_cell(int s, cell_t **cellp)
+{
+ cell_t *p = *cellp;
+
+ *cellp = p + s;
+ return of_read_number(p, s);
+}
+
+static int __init early_init_dt_scan_memory(unsigned long node,
+ const char *uname, int depth, void *data)
+{
+ char *type = of_get_flat_dt_prop(node, "device_type", NULL);
+ cell_t *reg, *endp;
+ unsigned long l;
+
+ /* Look for the ibm,dynamic-reconfiguration-memory node */
+/* if (depth == 1 &&
+ strcmp(uname, "ibm,dynamic-reconfiguration-memory") == 0)
+ return early_init_dt_scan_drconf_memory(node);
+*/
+ /* We are scanning "memory" nodes only */
+ if (type == NULL) {
+ /*
+ * The longtrail doesn't have a device_type on the
+ * /memory node, so look for the node called /memory@0.
+ */
+ if (depth != 1 || strcmp(uname, "memory@0") != 0)
+ return 0;
+ } else if (strcmp(type, "memory") != 0)
+ return 0;
+
+ reg = (cell_t *)of_get_flat_dt_prop(node, "linux,usable-memory", &l);
+ if (reg == NULL)
+ reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l);
+ if (reg == NULL)
+ return 0;
+
+ endp = reg + (l / sizeof(cell_t));
+
+ pr_debug("memory scan node %s, reg size %ld, data: %x %x %x %x,\n",
+ uname, l, reg[0], reg[1], reg[2], reg[3]);
+
+ while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
+ u64 base, size;
+
+ base = dt_mem_next_cell(dt_root_addr_cells, ®);
+ size = dt_mem_next_cell(dt_root_size_cells, ®);
+
+ if (size == 0)
+ continue;
+ pr_debug(" - %llx , %llx\n", (unsigned long long)base,
+ (unsigned long long)size);
+
+ lmb_add(base, size);
+ }
+ return 0;
+}
+
+#ifdef CONFIG_PHYP_DUMP
+/**
+ * phyp_dump_calculate_reserve_size() - reserve variable boot area 5% or arg
+ *
+ * Function to find the largest size we need to reserve
+ * during early boot process.
+ *
+ * It either looks for boot param and returns that OR
+ * returns larger of 256 or 5% rounded down to multiples of 256MB.
+ *
+ */
+static inline unsigned long phyp_dump_calculate_reserve_size(void)
+{
+ unsigned long tmp;
+
+ if (phyp_dump_info->reserve_bootvar)
+ return phyp_dump_info->reserve_bootvar;
+
+ /* divide by 20 to get 5% of value */
+ tmp = lmb_end_of_DRAM();
+ do_div(tmp, 20);
+
+ /* round it down in multiples of 256 */
+ tmp = tmp & ~0x0FFFFFFFUL;
+
+ return (tmp > PHYP_DUMP_RMR_END ? tmp : PHYP_DUMP_RMR_END);
+}
+
+/**
+ * phyp_dump_reserve_mem() - reserve all not-yet-dumped mmemory
+ *
+ * This routine may reserve memory regions in the kernel only
+ * if the system is supported and a dump was taken in last
+ * boot instance or if the hardware is supported and the
+ * scratch area needs to be setup. In other instances it returns
+ * without reserving anything. The memory in case of dump being
+ * active is freed when the dump is collected (by userland tools).
+ */
+static void __init phyp_dump_reserve_mem(void)
+{
+ unsigned long base, size;
+ unsigned long variable_reserve_size;
+
+ if (!phyp_dump_info->phyp_dump_configured) {
+ printk(KERN_ERR "Phyp-dump not supported on this hardware\n");
+ return;
+ }
+
+ if (!phyp_dump_info->phyp_dump_at_boot) {
+ printk(KERN_INFO "Phyp-dump disabled at boot time\n");
+ return;
+ }
+
+ variable_reserve_size = phyp_dump_calculate_reserve_size();
+
+ if (phyp_dump_info->phyp_dump_is_active) {
+ /* Reserve *everything* above RMR.Area freed by userland tools*/
+ base = variable_reserve_size;
+ size = lmb_end_of_DRAM() - base;
+
+ /* XXX crashed_ram_end is wrong, since it may be beyond
+ * the memory_limit, it will need to be adjusted. */
+ lmb_reserve(base, size);
+
+ phyp_dump_info->init_reserve_start = base;
+ phyp_dump_info->init_reserve_size = size;
+ } else {
+ size = phyp_dump_info->cpu_state_size +
+ phyp_dump_info->hpte_region_size +
+ variable_reserve_size;
+ base = lmb_end_of_DRAM() - size;
+ lmb_reserve(base, size);
+ phyp_dump_info->init_reserve_start = base;
+ phyp_dump_info->init_reserve_size = size;
+ }
+}
+#else
+static inline void __init phyp_dump_reserve_mem(void) {}
+#endif /* CONFIG_PHYP_DUMP && CONFIG_PPC_RTAS */
+
+#ifdef CONFIG_EARLY_PRINTK
+/* MS this is Microblaze specifig function */
+static int __init early_init_dt_scan_serial(unsigned long node,
+ const char *uname, int depth, void *data)
+{
+ unsigned long l;
+ char *p;
+ int *addr;
+
+ pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
+
+/* find all serial nodes */
+ if (strncmp(uname, "serial", 6) != 0)
+ return 0;
+
+ early_init_dt_check_for_initrd(node);
+
+/* find compatible node with uartlite */
+ p = of_get_flat_dt_prop(node, "compatible", &l);
+ if ((strncmp(p, "xlnx,xps-uartlite", 17) != 0) &&
+ (strncmp(p, "xlnx,opb-uartlite", 17) != 0))
+ return 0;
+
+ addr = of_get_flat_dt_prop(node, "reg", &l);
+ return *addr; /* return address */
+}
+
+/* this function is looking for early uartlite console - Microblaze specific */
+int __init early_uartlite_console(void)
+{
+ return of_scan_flat_dt(early_init_dt_scan_serial, NULL);
+}
+#endif
+
+void __init early_init_devtree(void *params)
+{
+ pr_debug(" -> early_init_devtree(%p)\n", params);
+
+ /* Setup flat device-tree pointer */
+ initial_boot_params = params;
+
+#ifdef CONFIG_PHYP_DUMP
+ /* scan tree to see if dump occured during last boot */
+ of_scan_flat_dt(early_init_dt_scan_phyp_dump, NULL);
+#endif
+
+ /* Retrieve various informations from the /chosen node of the
+ * device-tree, including the platform type, initrd location and
+ * size, TCE reserve, and more ...
+ */
+ of_scan_flat_dt(early_init_dt_scan_chosen, NULL);
+
+ /* Scan memory nodes and rebuild LMBs */
+ lmb_init();
+ of_scan_flat_dt(early_init_dt_scan_root, NULL);
+ of_scan_flat_dt(early_init_dt_scan_memory, NULL);
+
+ /* Save command line for /proc/cmdline and then parse parameters */
+ strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
+ parse_early_param();
+
+ lmb_analyze();
+
+ pr_debug("Phys. mem: %lx\n", (unsigned long) lmb_phys_mem_size());
+
+ pr_debug("Scanning CPUs ...\n");
+
+ /* Retreive CPU related informations from the flat tree
+ * (altivec support, boot CPU ID, ...)
+ */
+ of_scan_flat_dt(early_init_dt_scan_cpus, NULL);
+
+ pr_debug(" <- early_init_devtree()\n");
+}
+
+/**
+ * Indicates whether the root node has a given value in its
+ * compatible property.
+ */
+int machine_is_compatible(const char *compat)
+{
+ struct device_node *root;
+ int rc = 0;
+
+ root = of_find_node_by_path("/");
+ if (root) {
+ rc = of_device_is_compatible(root, compat);
+ of_node_put(root);
+ }
+ return rc;
+}
+EXPORT_SYMBOL(machine_is_compatible);
+
+/*******
+ *
+ * New implementation of the OF "find" APIs, return a refcounted
+ * object, call of_node_put() when done. The device tree and list
+ * are protected by a rw_lock.
+ *
+ * Note that property management will need some locking as well,
+ * this isn't dealt with yet.
+ *
+ *******/
+
+/**
+ * of_find_node_by_phandle - Find a node given a phandle
+ * @handle: phandle of the node to find
+ *
+ * Returns a node pointer with refcount incremented, use
+ * of_node_put() on it when done.
+ */
+struct device_node *of_find_node_by_phandle(phandle handle)
+{
+ struct device_node *np;
+
+ read_lock(&devtree_lock);
+ for (np = allnodes; np != NULL; np = np->allnext)
+ if (np->linux_phandle == handle)
+ break;
+ of_node_get(np);
+ read_unlock(&devtree_lock);
+ return np;
+}
+EXPORT_SYMBOL(of_find_node_by_phandle);
+
+/**
+ * of_find_all_nodes - Get next node in global list
+ * @prev: Previous node or NULL to start iteration
+ * of_node_put() will be called on it
+ *
+ * Returns a node pointer with refcount incremented, use
+ * of_node_put() on it when done.
+ */
+struct device_node *of_find_all_nodes(struct device_node *prev)
+{
+ struct device_node *np;
+
+ read_lock(&devtree_lock);
+ np = prev ? prev->allnext : allnodes;
+ for (; np != NULL; np = np->allnext)
+ if (of_node_get(np))
+ break;
+ of_node_put(prev);
+ read_unlock(&devtree_lock);
+ return np;
+}
+EXPORT_SYMBOL(of_find_all_nodes);
+
+/**
+ * of_node_get - Increment refcount of a node
+ * @node: Node to inc refcount, NULL is supported to
+ * simplify writing of callers
+ *
+ * Returns node.
+ */
+struct device_node *of_node_get(struct device_node *node)
+{
+ if (node)
+ kref_get(&node->kref);
+ return node;
+}
+EXPORT_SYMBOL(of_node_get);
+
+static inline struct device_node *kref_to_device_node(struct kref *kref)
+{
+ return container_of(kref, struct device_node, kref);
+}
+
+/**
+ * of_node_release - release a dynamically allocated node
+ * @kref: kref element of the node to be released
+ *
+ * In of_node_put() this function is passed to kref_put()
+ * as the destructor.
+ */
+static void of_node_release(struct kref *kref)
+{
+ struct device_node *node = kref_to_device_node(kref);
+ struct property *prop = node->properties;
+
+ /* We should never be releasing nodes that haven't been detached. */
+ if (!of_node_check_flag(node, OF_DETACHED)) {
+ printk(KERN_INFO "WARNING: Bad of_node_put() on %s\n",
+ node->full_name);
+ dump_stack();
+ kref_init(&node->kref);
+ return;
+ }
+
+ if (!of_node_check_flag(node, OF_DYNAMIC))
+ return;
+
+ while (prop) {
+ struct property *next = prop->next;
+ kfree(prop->name);
+ kfree(prop->value);
+ kfree(prop);
+ prop = next;
+
+ if (!prop) {
+ prop = node->deadprops;
+ node->deadprops = NULL;
+ }
+ }
+ kfree(node->full_name);
+ kfree(node->data);
+ kfree(node);
+}
+
+/**
+ * of_node_put - Decrement refcount of a node
+ * @node: Node to dec refcount, NULL is supported to
+ * simplify writing of callers
+ *
+ */
+void of_node_put(struct device_node *node)
+{
+ if (node)
+ kref_put(&node->kref, of_node_release);
+}
+EXPORT_SYMBOL(of_node_put);
+
+/*
+ * Plug a device node into the tree and global list.
+ */
+void of_attach_node(struct device_node *np)
+{
+ unsigned long flags;
+
+ write_lock_irqsave(&devtree_lock, flags);
+ np->sibling = np->parent->child;
+ np->allnext = allnodes;
+ np->parent->child = np;
+ allnodes = np;
+ write_unlock_irqrestore(&devtree_lock, flags);
+}
+
+/*
+ * "Unplug" a node from the device tree. The caller must hold
+ * a reference to the node. The memory associated with the node
+ * is not freed until its refcount goes to zero.
+ */
+void of_detach_node(struct device_node *np)
+{
+ struct device_node *parent;
+ unsigned long flags;
+
+ write_lock_irqsave(&devtree_lock, flags);
+
+ parent = np->parent;
+ if (!parent)
+ goto out_unlock;
+
+ if (allnodes == np)
+ allnodes = np->allnext;
+ else {
+ struct device_node *prev;
+ for (prev = allnodes;
+ prev->allnext != np;
+ prev = prev->allnext)
+ ;
+ prev->allnext = np->allnext;
+ }
+
+ if (parent->child == np)
+ parent->child = np->sibling;
+ else {
+ struct device_node *prevsib;
+ for (prevsib = np->parent->child;
+ prevsib->sibling != np;
+ prevsib = prevsib->sibling)
+ ;
+ prevsib->sibling = np->sibling;
+ }
+
+ of_node_set_flag(np, OF_DETACHED);
+
+out_unlock:
+ write_unlock_irqrestore(&devtree_lock, flags);
+}
+
+/*
+ * Add a property to a node
+ */
+int prom_add_property(struct device_node *np, struct property *prop)
+{
+ struct property **next;
+ unsigned long flags;
+
+ prop->next = NULL;
+ write_lock_irqsave(&devtree_lock, flags);
+ next = &np->properties;
+ while (*next) {
+ if (strcmp(prop->name, (*next)->name) == 0) {
+ /* duplicate ! don't insert it */
+ write_unlock_irqrestore(&devtree_lock, flags);
+ return -1;
+ }
+ next = &(*next)->next;
+ }
+ *next = prop;
+ write_unlock_irqrestore(&devtree_lock, flags);
+
+#ifdef CONFIG_PROC_DEVICETREE
+ /* try to add to proc as well if it was initialized */
+ if (np->pde)
+ proc_device_tree_add_prop(np->pde, prop);
+#endif /* CONFIG_PROC_DEVICETREE */
+
+ return 0;
+}
+
+/*
+ * Remove a property from a node. Note that we don't actually
+ * remove it, since we have given out who-knows-how-many pointers
+ * to the data using get-property. Instead we just move the property
+ * to the "dead properties" list, so it won't be found any more.
+ */
+int prom_remove_property(struct device_node *np, struct property *prop)
+{
+ struct property **next;
+ unsigned long flags;
+ int found = 0;
+
+ write_lock_irqsave(&devtree_lock, flags);
+ next = &np->properties;
+ while (*next) {
+ if (*next == prop) {
+ /* found the node */
+ *next = prop->next;
+ prop->next = np->deadprops;
+ np->deadprops = prop;
+ found = 1;
+ break;
+ }
+ next = &(*next)->next;
+ }
+ write_unlock_irqrestore(&devtree_lock, flags);
+
+ if (!found)
+ return -ENODEV;
+
+#ifdef CONFIG_PROC_DEVICETREE
+ /* try to remove the proc node as well */
+ if (np->pde)
+ proc_device_tree_remove_prop(np->pde, prop);
+#endif /* CONFIG_PROC_DEVICETREE */
+
+ return 0;
+}
+
+/*
+ * Update a property in a node. Note that we don't actually
+ * remove it, since we have given out who-knows-how-many pointers
+ * to the data using get-property. Instead we just move the property
+ * to the "dead properties" list, and add the new property to the
+ * property list
+ */
+int prom_update_property(struct device_node *np,
+ struct property *newprop,
+ struct property *oldprop)
+{
+ struct property **next;
+ unsigned long flags;
+ int found = 0;
+
+ write_lock_irqsave(&devtree_lock, flags);
+ next = &np->properties;
+ while (*next) {
+ if (*next == oldprop) {
+ /* found the node */
+ newprop->next = oldprop->next;
+ *next = newprop;
+ oldprop->next = np->deadprops;
+ np->deadprops = oldprop;
+ found = 1;
+ break;
+ }
+ next = &(*next)->next;
+ }
+ write_unlock_irqrestore(&devtree_lock, flags);
+
+ if (!found)
+ return -ENODEV;
+
+#ifdef CONFIG_PROC_DEVICETREE
+ /* try to add to proc as well if it was initialized */
+ if (np->pde)
+ proc_device_tree_update_prop(np->pde, newprop, oldprop);
+#endif /* CONFIG_PROC_DEVICETREE */
+
+ return 0;
+}
+
+#if defined(CONFIG_DEBUG_FS) && defined(DEBUG)
+static struct debugfs_blob_wrapper flat_dt_blob;
+
+static int __init export_flat_device_tree(void)
+{
+ struct dentry *d;
+
+ flat_dt_blob.data = initial_boot_params;
+ flat_dt_blob.size = initial_boot_params->totalsize;
+
+ d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR,
+ of_debugfs_root, &flat_dt_blob);
+ if (!d)
+ return 1;
+
+ return 0;
+}
+device_initcall(export_flat_device_tree);
+#endif
diff --git a/arch/microblaze/kernel/prom_parse.c b/arch/microblaze/kernel/prom_parse.c
new file mode 100644
index 0000000..ae0352e
--- /dev/null
+++ b/arch/microblaze/kernel/prom_parse.c
@@ -0,0 +1,1025 @@
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/pci_regs.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/etherdevice.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+
+#define PRu64 "%llx"
+
+/* Max address size we deal with */
+#define OF_MAX_ADDR_CELLS 4
+#define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \
+ (ns) > 0)
+
+static struct of_bus *of_match_bus(struct device_node *np);
+static int __of_address_to_resource(struct device_node *dev,
+ const u32 *addrp, u64 size, unsigned int flags,
+ struct resource *r);
+
+/* Debug utility */
+#ifdef DEBUG
+static void of_dump_addr(const char *s, const u32 *addr, int na)
+{
+ printk(KERN_INFO "%s", s);
+ while (na--)
+ printk(KERN_INFO " %08x", *(addr++));
+ printk(KERN_INFO "\n");
+}
+#else
+static void of_dump_addr(const char *s, const u32 *addr, int na) { }
+#endif
+
+/* Callbacks for bus specific translators */
+struct of_bus {
+ const char *name;
+ const char *addresses;
+ int (*match)(struct device_node *parent);
+ void (*count_cells)(struct device_node *child,
+ int *addrc, int *sizec);
+ u64 (*map)(u32 *addr, const u32 *range,
+ int na, int ns, int pna);
+ int (*translate)(u32 *addr, u64 offset, int na);
+ unsigned int (*get_flags)(const u32 *addr);
+};
+
+/*
+ * Default translator (generic bus)
+ */
+
+static void of_bus_default_count_cells(struct device_node *dev,
+ int *addrc, int *sizec)
+{
+ if (addrc)
+ *addrc = of_n_addr_cells(dev);
+ if (sizec)
+ *sizec = of_n_size_cells(dev);
+}
+
+static u64 of_bus_default_map(u32 *addr, const u32 *range,
+ int na, int ns, int pna)
+{
+ u64 cp, s, da;
+
+ cp = of_read_number(range, na);
+ s = of_read_number(range + na + pna, ns);
+ da = of_read_number(addr, na);
+
+ pr_debug("OF: default map, cp="PRu64", s="PRu64", da="PRu64"\n",
+ cp, s, da);
+
+ if (da < cp || da >= (cp + s))
+ return OF_BAD_ADDR;
+ return da - cp;
+}
+
+static int of_bus_default_translate(u32 *addr, u64 offset, int na)
+{
+ u64 a = of_read_number(addr, na);
+ memset(addr, 0, na * 4);
+ a += offset;
+ if (na > 1)
+ addr[na - 2] = a >> 32;
+ addr[na - 1] = a & 0xffffffffu;
+
+ return 0;
+}
+
+static unsigned int of_bus_default_get_flags(const u32 *addr)
+{
+ return IORESOURCE_MEM;
+}
+
+#ifdef CONFIG_PCI
+/*
+ * PCI bus specific translator
+ */
+
+static int of_bus_pci_match(struct device_node *np)
+{
+ /* "vci" is for the /chaos bridge on 1st-gen PCI powermacs */
+ return !strcmp(np->type, "pci") || !strcmp(np->type, "vci");
+}
+
+static void of_bus_pci_count_cells(struct device_node *np,
+ int *addrc, int *sizec)
+{
+ if (addrc)
+ *addrc = 3;
+ if (sizec)
+ *sizec = 2;
+}
+
+static u64 of_bus_pci_map(u32 *addr, const u32 *range, int na, int ns, int pna)
+{
+ u64 cp, s, da;
+
+ /* Check address type match */
+ if ((addr[0] ^ range[0]) & 0x03000000)
+ return OF_BAD_ADDR;
+
+ /* Read address values, skipping high cell */
+ cp = of_read_number(range + 1, na - 1);
+ s = of_read_number(range + na + pna, ns);
+ da = of_read_number(addr + 1, na - 1);
+
+ pr_debug("OF: PCI map, cp="PRu64", s="PRu64", da="PRu64"\n", cp, s, da);
+
+ if (da < cp || da >= (cp + s))
+ return OF_BAD_ADDR;
+ return da - cp;
+}
+
+static int of_bus_pci_translate(u32 *addr, u64 offset, int na)
+{
+ return of_bus_default_translate(addr + 1, offset, na - 1);
+}
+
+static unsigned int of_bus_pci_get_flags(const u32 *addr)
+{
+ unsigned int flags = 0;
+ u32 w = addr[0];
+
+ switch ((w >> 24) & 0x03) {
+ case 0x01:
+ flags |= IORESOURCE_IO;
+ break;
+ case 0x02: /* 32 bits */
+ case 0x03: /* 64 bits */
+ flags |= IORESOURCE_MEM;
+ break;
+ }
+ if (w & 0x40000000)
+ flags |= IORESOURCE_PREFETCH;
+ return flags;
+}
+
+const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
+ unsigned int *flags)
+{
+ const u32 *prop;
+ unsigned int psize;
+ struct device_node *parent;
+ struct of_bus *bus;
+ int onesize, i, na, ns;
+
+ /* Get parent & match bus type */
+ parent = of_get_parent(dev);
+ if (parent == NULL)
+ return NULL;
+ bus = of_match_bus(parent);
+ if (strcmp(bus->name, "pci")) {
+ of_node_put(parent);
+ return NULL;
+ }
+ bus->count_cells(dev, &na, &ns);
+ of_node_put(parent);
+ if (!OF_CHECK_COUNTS(na, ns))
+ return NULL;
+
+ /* Get "reg" or "assigned-addresses" property */
+ prop = of_get_property(dev, bus->addresses, &psize);
+ if (prop == NULL)
+ return NULL;
+ psize /= 4;
+
+ onesize = na + ns;
+ for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++)
+ if ((prop[0] & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) {
+ if (size)
+ *size = of_read_number(prop + na, ns);
+ if (flags)
+ *flags = bus->get_flags(prop);
+ return prop;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL(of_get_pci_address);
+
+int of_pci_address_to_resource(struct device_node *dev, int bar,
+ struct resource *r)
+{
+ const u32 *addrp;
+ u64 size;
+ unsigned int flags;
+
+ addrp = of_get_pci_address(dev, bar, &size, &flags);
+ if (addrp == NULL)
+ return -EINVAL;
+ return __of_address_to_resource(dev, addrp, size, flags, r);
+}
+EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
+
+static u8 of_irq_pci_swizzle(u8 slot, u8 pin)
+{
+ return (((pin - 1) + slot) % 4) + 1;
+}
+
+int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
+{
+ struct device_node *dn, *ppnode;
+ struct pci_dev *ppdev;
+ u32 lspec;
+ u32 laddr[3];
+ u8 pin;
+ int rc;
+
+ /* Check if we have a device node, if yes, fallback to standard OF
+ * parsing
+ */
+ dn = pci_device_to_OF_node(pdev);
+ if (dn)
+ return of_irq_map_one(dn, 0, out_irq);
+
+ /* Ok, we don't, time to have fun. Let's start by building up an
+ * interrupt spec. we assume #interrupt-cells is 1, which is standard
+ * for PCI. If you do different, then don't use that routine.
+ */
+ rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
+ if (rc != 0)
+ return rc;
+ /* No pin, exit */
+ if (pin == 0)
+ return -ENODEV;
+
+ /* Now we walk up the PCI tree */
+ lspec = pin;
+ for (;;) {
+ /* Get the pci_dev of our parent */
+ ppdev = pdev->bus->self;
+
+ /* Ouch, it's a host bridge... */
+ if (ppdev == NULL) {
+ struct pci_controller *host;
+ host = pci_bus_to_host(pdev->bus);
+ ppnode = host ? host->arch_data : NULL;
+ /* No node for host bridge ? give up */
+ if (ppnode == NULL)
+ return -EINVAL;
+ } else
+ /* We found a P2P bridge, check if it has a node */
+ ppnode = pci_device_to_OF_node(ppdev);
+
+ /* Ok, we have found a parent with a device-node, hand over to
+ * the OF parsing code.
+ * We build a unit address from the linux device to be used for
+ * resolution. Note that we use the linux bus number which may
+ * not match your firmware bus numbering.
+ * Fortunately, in most cases, interrupt-map-mask doesn't
+ * include the bus number as part of the matching.
+ * You should still be careful about that though if you intend
+ * to rely on this function (you ship a firmware that doesn't
+ * create device nodes for all PCI devices).
+ */
+ if (ppnode)
+ break;
+
+ /* We can only get here if we hit a P2P bridge with no node,
+ * let's do standard swizzling and try again
+ */
+ lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec);
+ pdev = ppdev;
+ }
+
+ laddr[0] = (pdev->bus->number << 16)
+ | (pdev->devfn << 8);
+ laddr[1] = laddr[2] = 0;
+ return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
+}
+EXPORT_SYMBOL_GPL(of_irq_map_pci);
+#endif /* CONFIG_PCI */
+
+/*
+ * ISA bus specific translator
+ */
+
+static int of_bus_isa_match(struct device_node *np)
+{
+ return !strcmp(np->name, "isa");
+}
+
+static void of_bus_isa_count_cells(struct device_node *child,
+ int *addrc, int *sizec)
+{
+ if (addrc)
+ *addrc = 2;
+ if (sizec)
+ *sizec = 1;
+}
+
+static u64 of_bus_isa_map(u32 *addr, const u32 *range, int na, int ns, int pna)
+{
+ u64 cp, s, da;
+
+ /* Check address type match */
+ if ((addr[0] ^ range[0]) & 0x00000001)
+ return OF_BAD_ADDR;
+
+ /* Read address values, skipping high cell */
+ cp = of_read_number(range + 1, na - 1);
+ s = of_read_number(range + na + pna, ns);
+ da = of_read_number(addr + 1, na - 1);
+
+ pr_debug("OF: ISA map, cp="PRu64", s="PRu64", da="PRu64"\n", cp, s, da);
+
+ if (da < cp || da >= (cp + s))
+ return OF_BAD_ADDR;
+ return da - cp;
+}
+
+static int of_bus_isa_translate(u32 *addr, u64 offset, int na)
+{
+ return of_bus_default_translate(addr + 1, offset, na - 1);
+}
+
+static unsigned int of_bus_isa_get_flags(const u32 *addr)
+{
+ unsigned int flags = 0;
+ u32 w = addr[0];
+
+ if (w & 1)
+ flags |= IORESOURCE_IO;
+ else
+ flags |= IORESOURCE_MEM;
+ return flags;
+}
+
+/*
+ * Array of bus specific translators
+ */
+
+static struct of_bus of_busses[] = {
+#ifdef CONFIG_PCI
+ /* PCI */
+ {
+ .name = "pci",
+ .addresses = "assigned-addresses",
+ .match = of_bus_pci_match,
+ .count_cells = of_bus_pci_count_cells,
+ .map = of_bus_pci_map,
+ .translate = of_bus_pci_translate,
+ .get_flags = of_bus_pci_get_flags,
+ },
+#endif /* CONFIG_PCI */
+ /* ISA */
+ {
+ .name = "isa",
+ .addresses = "reg",
+ .match = of_bus_isa_match,
+ .count_cells = of_bus_isa_count_cells,
+ .map = of_bus_isa_map,
+ .translate = of_bus_isa_translate,
+ .get_flags = of_bus_isa_get_flags,
+ },
+ /* Default */
+ {
+ .name = "default",
+ .addresses = "reg",
+ .match = NULL,
+ .count_cells = of_bus_default_count_cells,
+ .map = of_bus_default_map,
+ .translate = of_bus_default_translate,
+ .get_flags = of_bus_default_get_flags,
+ },
+};
+
+static struct of_bus *of_match_bus(struct device_node *np)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(of_busses); i++)
+ if (!of_busses[i].match || of_busses[i].match(np))
+ return &of_busses[i];
+ BUG();
+ return NULL;
+}
+
+static int of_translate_one(struct device_node *parent, struct of_bus *bus,
+ struct of_bus *pbus, u32 *addr,
+ int na, int ns, int pna)
+{
+ const u32 *ranges;
+ unsigned int rlen;
+ int rone;
+ u64 offset = OF_BAD_ADDR;
+
+ /* Normally, an absence of a "ranges" property means we are
+ * crossing a non-translatable boundary, and thus the addresses
+ * below the current not cannot be converted to CPU physical ones.
+ * Unfortunately, while this is very clear in the spec, it's not
+ * what Apple understood, and they do have things like /uni-n or
+ * /ht nodes with no "ranges" property and a lot of perfectly
+ * useable mapped devices below them. Thus we treat the absence of
+ * "ranges" as equivalent to an empty "ranges" property which means
+ * a 1:1 translation at that level. It's up to the caller not to try
+ * to translate addresses that aren't supposed to be translated in
+ * the first place. --BenH.
+ */
+ ranges = of_get_property(parent, "ranges", (int *) &rlen);
+ if (ranges == NULL || rlen == 0) {
+ offset = of_read_number(addr, na);
+ memset(addr, 0, pna * 4);
+ pr_debug("OF: no ranges, 1:1 translation\n");
+ goto finish;
+ }
+
+ pr_debug("OF: walking ranges...\n");
+
+ /* Now walk through the ranges */
+ rlen /= 4;
+ rone = na + pna + ns;
+ for (; rlen >= rone; rlen -= rone, ranges += rone) {
+ offset = bus->map(addr, ranges, na, ns, pna);
+ if (offset != OF_BAD_ADDR)
+ break;
+ }
+ if (offset == OF_BAD_ADDR) {
+ pr_debug("OF: not found !\n");
+ return 1;
+ }
+ memcpy(addr, ranges + na, 4 * pna);
+
+ finish:
+ of_dump_addr("OF: parent translation for:", addr, pna);
+ pr_debug("OF: with offset: "PRu64"\n", offset);
+
+ /* Translate it into parent bus space */
+ return pbus->translate(addr, offset, pna);
+}
+
+/*
+ * Translate an address from the device-tree into a CPU physical address,
+ * this walks up the tree and applies the various bus mappings on the
+ * way.
+ *
+ * Note: We consider that crossing any level with #size-cells == 0 to mean
+ * that translation is impossible (that is we are not dealing with a value
+ * that can be mapped to a cpu physical address). This is not really specified
+ * that way, but this is traditionally the way IBM at least do things
+ */
+u64 of_translate_address(struct device_node *dev, const u32 *in_addr)
+{
+ struct device_node *parent = NULL;
+ struct of_bus *bus, *pbus;
+ u32 addr[OF_MAX_ADDR_CELLS];
+ int na, ns, pna, pns;
+ u64 result = OF_BAD_ADDR;
+
+ pr_debug("OF: ** translation for device %s **\n", dev->full_name);
+
+ /* Increase refcount at current level */
+ of_node_get(dev);
+
+ /* Get parent & match bus type */
+ parent = of_get_parent(dev);
+ if (parent == NULL)
+ goto bail;
+ bus = of_match_bus(parent);
+
+ /* Cound address cells & copy address locally */
+ bus->count_cells(dev, &na, &ns);
+ if (!OF_CHECK_COUNTS(na, ns)) {
+ printk(KERN_ERR "prom_parse: Bad cell count for %s\n",
+ dev->full_name);
+ goto bail;
+ }
+ memcpy(addr, in_addr, na * 4);
+
+ pr_debug("OF: bus is %s (na=%d, ns=%d) on %s\n",
+ bus->name, na, ns, parent->full_name);
+ of_dump_addr("OF: translating address:", addr, na);
+
+ /* Translate */
+ for (;;) {
+ /* Switch to parent bus */
+ of_node_put(dev);
+ dev = parent;
+ parent = of_get_parent(dev);
+
+ /* If root, we have finished */
+ if (parent == NULL) {
+ pr_debug("OF: reached root node\n");
+ result = of_read_number(addr, na);
+ break;
+ }
+
+ /* Get new parent bus and counts */
+ pbus = of_match_bus(parent);
+ pbus->count_cells(dev, &pna, &pns);
+ if (!OF_CHECK_COUNTS(pna, pns)) {
+ printk(KERN_ERR "prom_parse: Bad cell count for %s\n",
+ dev->full_name);
+ break;
+ }
+
+ pr_debug("OF: parent bus is %s (na=%d, ns=%d) on %s\n",
+ pbus->name, pna, pns, parent->full_name);
+
+ /* Apply bus translation */
+ if (of_translate_one(dev, bus, pbus, addr, na, ns, pna))
+ break;
+
+ /* Complete the move up one level */
+ na = pna;
+ ns = pns;
+ bus = pbus;
+
+ of_dump_addr("OF: one level translation:", addr, na);
+ }
+ bail:
+ of_node_put(parent);
+ of_node_put(dev);
+
+ return result;
+}
+EXPORT_SYMBOL(of_translate_address);
+
+const u32 *of_get_address(struct device_node *dev, int index, u64 *size,
+ unsigned int *flags)
+{
+ const u32 *prop;
+ unsigned int psize;
+ struct device_node *parent;
+ struct of_bus *bus;
+ int onesize, i, na, ns;
+
+ /* Get parent & match bus type */
+ parent = of_get_parent(dev);
+ if (parent == NULL)
+ return NULL;
+ bus = of_match_bus(parent);
+ bus->count_cells(dev, &na, &ns);
+ of_node_put(parent);
+ if (!OF_CHECK_COUNTS(na, ns))
+ return NULL;
+
+ /* Get "reg" or "assigned-addresses" property */
+ prop = of_get_property(dev, bus->addresses, (int *) &psize);
+ if (prop == NULL)
+ return NULL;
+ psize /= 4;
+
+ onesize = na + ns;
+ for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++)
+ if (i == index) {
+ if (size)
+ *size = of_read_number(prop + na, ns);
+ if (flags)
+ *flags = bus->get_flags(prop);
+ return prop;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL(of_get_address);
+
+static int __of_address_to_resource(struct device_node *dev, const u32 *addrp,
+ u64 size, unsigned int flags,
+ struct resource *r)
+{
+ u64 taddr;
+
+ if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
+ return -EINVAL;
+ taddr = of_translate_address(dev, addrp);
+ if (taddr == OF_BAD_ADDR)
+ return -EINVAL;
+ memset(r, 0, sizeof(struct resource));
+ if (flags & IORESOURCE_IO) {
+ unsigned long port;
+ port = -1; /* pci_address_to_pio(taddr); */
+ if (port == (unsigned long)-1)
+ return -EINVAL;
+ r->start = port;
+ r->end = port + size - 1;
+ } else {
+ r->start = taddr;
+ r->end = taddr + size - 1;
+ }
+ r->flags = flags;
+ r->name = dev->name;
+ return 0;
+}
+
+int of_address_to_resource(struct device_node *dev, int index,
+ struct resource *r)
+{
+ const u32 *addrp;
+ u64 size;
+ unsigned int flags;
+
+ addrp = of_get_address(dev, index, &size, &flags);
+ if (addrp == NULL)
+ return -EINVAL;
+ return __of_address_to_resource(dev, addrp, size, flags, r);
+}
+EXPORT_SYMBOL_GPL(of_address_to_resource);
+
+void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
+ unsigned long *busno, unsigned long *phys, unsigned long *size)
+{
+ const u32 *dma_window;
+ u32 cells;
+ const unsigned char *prop;
+
+ dma_window = dma_window_prop;
+
+ /* busno is always one cell */
+ *busno = *(dma_window++);
+
+ prop = of_get_property(dn, "ibm,#dma-address-cells", NULL);
+ if (!prop)
+ prop = of_get_property(dn, "#address-cells", NULL);
+
+ cells = prop ? *(u32 *)prop : of_n_addr_cells(dn);
+ *phys = of_read_number(dma_window, cells);
+
+ dma_window += cells;
+
+ prop = of_get_property(dn, "ibm,#dma-size-cells", NULL);
+ cells = prop ? *(u32 *)prop : of_n_size_cells(dn);
+ *size = of_read_number(dma_window, cells);
+}
+
+/*
+ * Interrupt remapper
+ */
+
+static unsigned int of_irq_workarounds;
+static struct device_node *of_irq_dflt_pic;
+
+static struct device_node *of_irq_find_parent(struct device_node *child)
+{
+ struct device_node *p;
+ const phandle *parp;
+
+ if (!of_node_get(child))
+ return NULL;
+
+ do {
+ parp = of_get_property(child, "interrupt-parent", NULL);
+ if (parp == NULL)
+ p = of_get_parent(child);
+ else {
+ if (of_irq_workarounds & OF_IMAP_NO_PHANDLE)
+ p = of_node_get(of_irq_dflt_pic);
+ else
+ p = of_find_node_by_phandle(*parp);
+ }
+ of_node_put(child);
+ child = p;
+ } while (p && of_get_property(p, "#interrupt-cells", NULL) == NULL);
+
+ return p;
+}
+
+/* This doesn't need to be called if you don't have any special workaround
+ * flags to pass
+ */
+void of_irq_map_init(unsigned int flags)
+{
+ of_irq_workarounds = flags;
+
+ /* OldWorld, don't bother looking at other things */
+ if (flags & OF_IMAP_OLDWORLD_MAC)
+ return;
+
+ /* If we don't have phandles, let's try to locate a default interrupt
+ * controller (happens when booting with BootX). We do a first match
+ * here, hopefully, that only ever happens on machines with one
+ * controller.
+ */
+ if (flags & OF_IMAP_NO_PHANDLE) {
+ struct device_node *np;
+
+ for (np = NULL; (np = of_find_all_nodes(np)) != NULL;) {
+ if (of_get_property(np, "interrupt-controller", NULL)
+ == NULL)
+ continue;
+ /* Skip /chosen/interrupt-controller */
+ if (strcmp(np->name, "chosen") == 0)
+ continue;
+ /* It seems like at least one person on this planet
+ * wants to use BootX on a machine with an AppleKiwi
+ * controller which happens to pretend to be an
+ * interrupt controller too.
+ */
+ if (strcmp(np->name, "AppleKiwi") == 0)
+ continue;
+ /* I think we found one ! */
+ of_irq_dflt_pic = np;
+ break;
+ }
+ }
+
+}
+
+int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize,
+ const u32 *addr, struct of_irq *out_irq)
+{
+ struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
+ const u32 *tmp, *imap, *imask;
+ u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
+ int imaplen, match, i;
+
+ pr_debug("of_irq_map_raw: par=%s,intspec=[0x%08x 0x%08x...],"
+ "ointsize=%d\n",
+ parent->full_name, intspec[0], intspec[1], ointsize);
+
+ ipar = of_node_get(parent);
+
+ /* First get the #interrupt-cells property of the current cursor
+ * that tells us how to interpret the passed-in intspec. If there
+ * is none, we are nice and just walk up the tree
+ */
+ do {
+ tmp = of_get_property(ipar, "#interrupt-cells", NULL);
+ if (tmp != NULL) {
+ intsize = *tmp;
+ break;
+ }
+ tnode = ipar;
+ ipar = of_irq_find_parent(ipar);
+ of_node_put(tnode);
+ } while (ipar);
+ if (ipar == NULL) {
+ pr_debug(" -> no parent found !\n");
+ goto fail;
+ }
+
+ pr_debug("of_irq_map_raw: ipar=%s, size=%d\n",
+ ipar->full_name, intsize);
+
+ if (ointsize != intsize)
+ return -EINVAL;
+
+ /* Look for this #address-cells. We have to implement the old linux
+ * trick of looking for the parent here as some device-trees rely on it
+ */
+ old = of_node_get(ipar);
+ do {
+ tmp = of_get_property(old, "#address-cells", NULL);
+ tnode = of_get_parent(old);
+ of_node_put(old);
+ old = tnode;
+ } while (old && tmp == NULL);
+ of_node_put(old);
+ old = NULL;
+ addrsize = (tmp == NULL) ? 2 : *tmp;
+
+ pr_debug(" -> addrsize=%d\n", addrsize);
+
+ /* Now start the actual "proper" walk of the interrupt tree */
+ while (ipar != NULL) {
+ /* Now check if cursor is an interrupt-controller and if it is
+ * then we are done
+ */
+ if (of_get_property(ipar, "interrupt-controller", NULL) !=
+ NULL) {
+ pr_debug(" -> got it !\n");
+ memcpy(out_irq->specifier, intspec,
+ intsize * sizeof(u32));
+ out_irq->size = intsize;
+ out_irq->controller = ipar;
+ of_node_put(old);
+ return 0;
+ }
+
+ /* Now look for an interrupt-map */
+ imap = of_get_property(ipar, "interrupt-map", &imaplen);
+ /* No interrupt map, check for an interrupt parent */
+ if (imap == NULL) {
+ pr_debug(" -> no map, getting parent\n");
+ newpar = of_irq_find_parent(ipar);
+ goto skiplevel;
+ }
+ imaplen /= sizeof(u32);
+
+ /* Look for a mask */
+ imask = of_get_property(ipar, "interrupt-map-mask", NULL);
+
+ /* If we were passed no "reg" property and we attempt to parse
+ * an interrupt-map, then #address-cells must be 0.
+ * Fail if it's not.
+ */
+ if (addr == NULL && addrsize != 0) {
+ pr_debug(" -> no reg passed in when needed !\n");
+ goto fail;
+ }
+
+ /* Parse interrupt-map */
+ match = 0;
+ while (imaplen > (addrsize + intsize + 1) && !match) {
+ /* Compare specifiers */
+ match = 1;
+ for (i = 0; i < addrsize && match; ++i) {
+ u32 mask = imask ? imask[i] : 0xffffffffu;
+ match = ((addr[i] ^ imap[i]) & mask) == 0;
+ }
+ for (; i < (addrsize + intsize) && match; ++i) {
+ u32 mask = imask ? imask[i] : 0xffffffffu;
+ match =
+ ((intspec[i-addrsize] ^ imap[i])
+ & mask) == 0;
+ }
+ imap += addrsize + intsize;
+ imaplen -= addrsize + intsize;
+
+ pr_debug(" -> match=%d (imaplen=%d)\n", match, imaplen);
+
+ /* Get the interrupt parent */
+ if (of_irq_workarounds & OF_IMAP_NO_PHANDLE)
+ newpar = of_node_get(of_irq_dflt_pic);
+ else
+ newpar =
+ of_find_node_by_phandle((phandle)*imap);
+ imap++;
+ --imaplen;
+
+ /* Check if not found */
+ if (newpar == NULL) {
+ pr_debug(" -> imap parent not found !\n");
+ goto fail;
+ }
+
+ /* Get #interrupt-cells and #address-cells of new
+ * parent
+ */
+ tmp = of_get_property(newpar, "#interrupt-cells", NULL);
+ if (tmp == NULL) {
+ pr_debug(" -> parent lacks "
+ "#interrupt-cells!\n");
+ goto fail;
+ }
+ newintsize = *tmp;
+ tmp = of_get_property(newpar, "#address-cells", NULL);
+ newaddrsize = (tmp == NULL) ? 0 : *tmp;
+
+ pr_debug(" -> newintsize=%d, newaddrsize=%d\n",
+ newintsize, newaddrsize);
+
+ /* Check for malformed properties */
+ if (imaplen < (newaddrsize + newintsize))
+ goto fail;
+
+ imap += newaddrsize + newintsize;
+ imaplen -= newaddrsize + newintsize;
+
+ pr_debug(" -> imaplen=%d\n", imaplen);
+ }
+ if (!match)
+ goto fail;
+
+ of_node_put(old);
+ old = of_node_get(newpar);
+ addrsize = newaddrsize;
+ intsize = newintsize;
+ intspec = imap - intsize;
+ addr = intspec - addrsize;
+
+skiplevel:
+ /* Iterate again with new parent */
+ pr_debug(" -> new parent: %s\n",
+ newpar ? newpar->full_name : "<>");
+ of_node_put(ipar);
+ ipar = newpar;
+ newpar = NULL;
+ }
+fail:
+ of_node_put(ipar);
+ of_node_put(old);
+ of_node_put(newpar);
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(of_irq_map_raw);
+
+int of_irq_map_one(struct device_node *device,
+ int index, struct of_irq *out_irq)
+{
+ struct device_node *p;
+ const u32 *intspec, *tmp, *addr;
+ u32 intsize, intlen;
+ int res;
+
+ pr_debug("of_irq_map_one: dev=%s, index=%d\n",
+ device->full_name, index);
+
+ /* Get the interrupts property */
+ intspec = of_get_property(device, "interrupts", (int *) &intlen);
+ if (intspec == NULL)
+ return -EINVAL;
+ intlen /= sizeof(u32);
+
+ pr_debug(" intspec=%d intlen=%d\n", *intspec, intlen);
+
+ /* Get the reg property (if any) */
+ addr = of_get_property(device, "reg", NULL);
+
+ /* Look for the interrupt parent. */
+ p = of_irq_find_parent(device);
+ if (p == NULL)
+ return -EINVAL;
+
+ /* Get size of interrupt specifier */
+ tmp = of_get_property(p, "#interrupt-cells", NULL);
+ if (tmp == NULL) {
+ of_node_put(p);
+ return -EINVAL;
+ }
+ intsize = *tmp;
+
+ pr_debug(" intsize=%d intlen=%d\n", intsize, intlen);
+
+ /* Check index */
+ if ((index + 1) * intsize > intlen)
+ return -EINVAL;
+
+ /* Get new specifier and map it */
+ res = of_irq_map_raw(p, intspec + index * intsize, intsize,
+ addr, out_irq);
+ of_node_put(p);
+ return res;
+}
+EXPORT_SYMBOL_GPL(of_irq_map_one);
+
+/**
+ * Search the device tree for the best MAC address to use. 'mac-address' is
+ * checked first, because that is supposed to contain to "most recent" MAC
+ * address. If that isn't set, then 'local-mac-address' is checked next,
+ * because that is the default address. If that isn't set, then the obsolete
+ * 'address' is checked, just in case we're using an old device tree.
+ *
+ * Note that the 'address' property is supposed to contain a virtual address of
+ * the register set, but some DTS files have redefined that property to be the
+ * MAC address.
+ *
+ * All-zero MAC addresses are rejected, because those could be properties that
+ * exist in the device tree, but were not set by U-Boot. For example, the
+ * DTS could define 'mac-address' and 'local-mac-address', with zero MAC
+ * addresses. Some older U-Boots only initialized 'local-mac-address'. In
+ * this case, the real MAC is in 'local-mac-address', and 'mac-address' exists
+ * but is all zeros.
+*/
+const void *of_get_mac_address(struct device_node *np)
+{
+ struct property *pp;
+
+ pp = of_find_property(np, "mac-address", NULL);
+ if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value))
+ return pp->value;
+
+ pp = of_find_property(np, "local-mac-address", NULL);
+ if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value))
+ return pp->value;
+
+ pp = of_find_property(np, "address", NULL);
+ if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value))
+ return pp->value;
+
+ return NULL;
+}
+EXPORT_SYMBOL(of_get_mac_address);
+
+int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
+{
+ struct of_irq out_irq;
+ int irq;
+ int res;
+
+ res = of_irq_map_one(dev, index, &out_irq);
+
+ /* Get irq for the device */
+ if (res) {
+ pr_debug("IRQ not found... code = %d", res);
+ return NO_IRQ;
+ }
+ /* Assuming single interrupt controller... */
+ irq = out_irq.specifier[0];
+
+ pr_debug("IRQ found = %d", irq);
+
+ /* Only dereference the resource if both the
+ * resource and the irq are valid. */
+ if (r && irq != NO_IRQ) {
+ r->start = r->end = irq;
+ r->flags = IORESOURCE_IRQ;
+ }
+
+ return irq;
+}
+EXPORT_SYMBOL_GPL(of_irq_to_resource);
+
+void __iomem *of_iomap(struct device_node *np, int index)
+{
+ struct resource res;
+
+ if (of_address_to_resource(np, index, &res))
+ return NULL;
+
+ return ioremap(res.start, 1 + res.end - res.start);
+}
+EXPORT_SYMBOL(of_iomap);
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/exceptions.h | 65 ++++
arch/microblaze/kernel/exceptions.c | 157 ++++++++
arch/microblaze/kernel/hw_exception_handler.S | 470 +++++++++++++++++++++++++
3 files changed, 692 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/exceptions.h
create mode 100644 arch/microblaze/kernel/exceptions.c
create mode 100644 arch/microblaze/kernel/hw_exception_handler.S
diff --git a/arch/microblaze/include/asm/exceptions.h b/arch/microblaze/include/asm/exceptions.h
new file mode 100644
index 0000000..cd41f6c
--- /dev/null
+++ b/arch/microblaze/include/asm/exceptions.h
@@ -0,0 +1,65 @@
+/*
+ * Preliminary support for HW exception handing for Microblaze
+ *
+ * Copyright (C) 2008 Michal Simek
+ * Copyright (C) 2008 PetaLogix
+ * Copyright (C) 2005 John Williams <[email protected]>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_EXCEPTIONS_H
+#define _ASM_MICROBLAZE_EXCEPTIONS_H
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+/* Macros to enable and disable HW exceptions in the MSR */
+/* Define MSR enable bit for HW exceptions */
+#define HWEX_MSR_BIT (1 << 8)
+
+#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
+#define __enable_hw_exceptions() \
+ __asm__ __volatile__ (" msrset r0, %0; \
+ nop;" \
+ : \
+ : "i" (HWEX_MSR_BIT) \
+ : "memory")
+
+#define __disable_hw_exceptions() \
+ __asm__ __volatile__ (" msrclr r0, %0; \
+ nop;" \
+ : \
+ : "i" (HWEX_MSR_BIT) \
+ : "memory")
+#else /* !CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */
+#define __enable_hw_exceptions() \
+ __asm__ __volatile__ (" \
+ mfs r12, rmsr; \
+ nop; \
+ ori r12, r12, %0; \
+ mts rmsr, r12; \
+ nop;" \
+ : \
+ : "i" (HWEX_MSR_BIT) \
+ : "memory", "r12")
+
+#define __disable_hw_exceptions() \
+ __asm__ __volatile__ (" \
+ mfs r12, rmsr; \
+ nop; \
+ andi r12, r12, ~%0; \
+ mts rmsr, r12; \
+ nop;" \
+ : \
+ : "i" (HWEX_MSR_BIT) \
+ : "memory", "r12")
+#endif /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */
+
+asmlinkage void full_exception(struct pt_regs *regs, unsigned int type, int fsr, int addr);
+
+#endif /*__ASSEMBLY__ */
+#endif /* __KERNEL__ */
+#endif /* _ASM_MICROBLAZE_EXCEPTIONS_H */
diff --git a/arch/microblaze/kernel/exceptions.c b/arch/microblaze/kernel/exceptions.c
new file mode 100644
index 0000000..223ce19
--- /dev/null
+++ b/arch/microblaze/kernel/exceptions.c
@@ -0,0 +1,157 @@
+/*
+ * arch/microblaze/kernel/exceptions.c - HW exception handling
+ *
+ * Copyright (C) 2008 Michal Simek
+ * Copyright (C) 2008 PetaLogix
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kallsyms.h>
+#include <linux/module.h>
+
+#include <asm/exceptions.h>
+#include <asm/entry.h> /* For KM CPU var */
+#include <asm/uaccess.h>
+#include <asm/errno.h>
+#include <asm/ptrace.h>
+#include <asm/current.h>
+
+#ifdef CONFIG_XMON
+extern void xmon(struct pt_regs *regs);
+extern int xmon_bpt(struct pt_regs *regs);
+extern int xmon_sstep(struct pt_regs *regs);
+extern int xmon_iabr_match(struct pt_regs *regs);
+extern int xmon_dabr_match(struct pt_regs *regs);
+extern void (*xmon_fault_handler)(struct pt_regs *regs);
+#endif
+
+#ifdef CONFIG_XMON
+void (*debugger)(struct pt_regs *regs) = xmon;
+int (*debugger_bpt)(struct pt_regs *regs) = xmon_bpt;
+int (*debugger_sstep)(struct pt_regs *regs) = xmon_sstep;
+int (*debugger_iabr_match)(struct pt_regs *regs) = xmon_iabr_match;
+int (*debugger_dabr_match)(struct pt_regs *regs) = xmon_dabr_match;
+void (*debugger_fault_handler)(struct pt_regs *regs);
+#else
+#ifdef CONFIG_KGDB
+void (*debugger)(struct pt_regs *regs);
+int (*debugger_bpt)(struct pt_regs *regs);
+int (*debugger_sstep)(struct pt_regs *regs);
+int (*debugger_iabr_match)(struct pt_regs *regs);
+int (*debugger_dabr_match)(struct pt_regs *regs);
+void (*debugger_fault_handler)(struct pt_regs *regs);
+#else
+#define debugger(regs) do { } while (0)
+#define debugger_bpt(regs) 0
+#define debugger_sstep(regs) 0
+#define debugger_iabr_match(regs) 0
+#define debugger_dabr_match(regs) 0
+#define debugger_fault_handler ((void (*)(struct pt_regs *))0)
+#endif
+#endif
+
+#define MICROBLAZE_ILL_OPCODE_EXCEPTION 0x02
+#define MICROBLAZE_IBUS_EXCEPTION 0x03
+#define MICROBLAZE_DBUS_EXCEPTION 0x04
+#define MICROBLAZE_DIV_ZERO_EXCEPTION 0x05
+#define MICROBLAZE_FPU_EXCEPTION 0x06
+#define MICROBLAZE_PRIVILEG_EXCEPTION 0x07
+
+static spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
+
+void die(const char* str, struct pt_regs* fp, long err)
+{
+ console_verbose();
+ spin_lock_irq(&die_lock);
+ printk("Oops: %s, sig: %ld\n", str, err);
+ show_regs(fp);
+ spin_unlock_irq(&die_lock);
+ /* do_exit() should take care of panic'ing from an interrupt
+ * context so we don't handle it here
+ */
+ do_exit(err);
+}
+
+void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
+{
+ siginfo_t info;
+
+ if (kernel_mode(regs)) {
+ debugger(regs);
+ die("Exception in kernel mode", regs, signr);
+ }
+ info.si_signo = signr;
+ info.si_errno = 0;
+ info.si_code = code;
+ info.si_addr = (void __user *) addr;
+ force_sig_info(signr, &info, current);
+}
+
+asmlinkage void full_exception(struct pt_regs *regs, unsigned int type, int fsr, int addr)
+{
+#if 0
+ printk(KERN_WARNING "Exception %02x in %s mode, FSR=%08x PC=%08x ESR=%08x\n",
+ type, user_mode(regs) ? "user" : "kernel", fsr,
+ (unsigned int) regs->pc, (unsigned int) regs->esr);
+#endif
+
+ switch (type & 0x1F) {
+ case MICROBLAZE_ILL_OPCODE_EXCEPTION:
+ _exception(SIGILL, regs, ILL_ILLOPC, addr);
+ break;
+ case MICROBLAZE_IBUS_EXCEPTION:
+ if (user_mode(regs)) {
+ printk("Instruction bus error exception in user mode.\n");
+ _exception(SIGBUS, regs, BUS_ADRERR, addr);
+ return;
+ }
+ printk("Instruction bus error exception in kernel mode.\n");
+ die("bus exception", regs, SIGBUS);
+ break;
+ case MICROBLAZE_DBUS_EXCEPTION:
+ if (user_mode(regs)) {
+ printk("Data bus error exception in user mode.\n");
+ _exception(SIGBUS, regs, BUS_ADRERR, addr);
+ return;
+ }
+ printk("Data bus error exception in kernel mode.\n");
+ die("bus exception", regs, SIGBUS);
+ break;
+ case MICROBLAZE_DIV_ZERO_EXCEPTION:
+ printk("Divide by zero exception\n");
+ _exception(SIGILL, regs, ILL_ILLOPC, addr);
+ break;
+
+ case MICROBLAZE_FPU_EXCEPTION:
+ /* IEEE FP exception */
+ /* I removed fsr variable and use code var for storing fsr */
+ if (fsr & FSR_IO)
+ fsr = FPE_FLTINV;
+ else if (fsr & FSR_OF)
+ fsr = FPE_FLTOVF;
+ else if (fsr & FSR_UF)
+ fsr = FPE_FLTUND;
+ else if (fsr & FSR_DZ)
+ fsr = FPE_FLTDIV;
+ else if (fsr & FSR_DO)
+ fsr = FPE_FLTRES;
+ _exception(SIGFPE, regs, fsr, addr);
+ break;
+
+ default:
+ printk(KERN_WARNING "Unexpected exception %02x in %s mode, PC=%08x\n",
+ type, kernel_mode(regs) ? "kernel" : "user",(unsigned int) addr);
+ }
+ return;
+}
diff --git a/arch/microblaze/kernel/hw_exception_handler.S b/arch/microblaze/kernel/hw_exception_handler.S
new file mode 100644
index 0000000..b6dd3ae
--- /dev/null
+++ b/arch/microblaze/kernel/hw_exception_handler.S
@@ -0,0 +1,470 @@
+/*
+ * arch/microblaze/kernel/hw_exception_handler.S
+ *
+ * Exception handling for Microblaze
+ *
+ * Rewriten interrupt handling
+ * Copyright (C) 2008 Michal Simek
+ * Copyright (C) 2008 PetaLogix
+ *
+ * uClinux customisation (C) 2005 John Williams
+ *
+ * MMU code derived from arch/ppc/kernel/head_4xx.S:
+ * Copyright (C) 1995-1996 Gary Thomas <[email protected]>
+ * Initial PowerPC version.
+ * Copyright (C) 1996 Cort Dougan <[email protected]>
+ * Rewritten for PReP
+ * Copyright (C) 1996 Paul Mackerras <[email protected]>
+ * Low-level exception handers, MMU support, and rewrite.
+ * Copyright (C) 1997 Dan Malek <[email protected]>
+ * PowerPC 8xx modifications.
+ * Copyright (C) 1998-1999 TiVo, Inc.
+ * PowerPC 403GCX modifications.
+ * Copyright (C) 1999 Grant Erickson <[email protected]>
+ * PowerPC 403GCX/405GP modifications.
+ * Copyright 2000 MontaVista Software Inc.
+ * PPC405 modifications
+ * PowerPC 403GCX/405GP modifications.
+ * Author: MontaVista Software, Inc.
+ * [email protected] or [email protected]
+ * [email protected]
+ *
+ * Original code
+ * Copyright (C) 2004 Xilinx, Inc. All rights reserved.
+ *
+ * Xilinx, Inc.
+ * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
+ * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
+ * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
+ * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
+ * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
+ * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
+ * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
+ * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
+ * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
+ * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id: hw_exception_handler.S,v 1.1.2.9 2007/12/07 10:41:28 vvlasov Exp $
+ *
+ *
+ * Here are the handlers which don't require enabling translation and calling other kernel code
+ * thus we can keep their design very simple and do all processing in real mode.
+ * All what they need is a valid current (that is an issue for the CONFIG_REGISTER_TASK_PTR case)
+ * This handlers use r3,r4,r5,r6 and optionally r[current] to work therefore these registers are saved/restored
+ * The handlers which require translation are in entry.S --KAA
+ *
+ * Microblaze HW Exception Handler
+ * - Non self-modifying exception handler for the following exception conditions
+ * - Unalignment
+ * - Instruction bus error
+ * - Data bus error
+ * - Illegal instruction opcode
+ * - Divide-by-zero
+ *
+ * Note we disable interrupts during exception handling, otherwise we will possibly
+ * get multiple re-entrancy if interrupt handles themselves cause exceptions. JW
+ */
+
+#include <asm/exceptions.h>
+#include <asm/unistd.h>
+#include <asm/page.h>
+
+#include <asm/entry.h>
+#include <asm/current.h>
+#include <linux/linkage.h>
+
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/asm-offsets.h>
+
+/* Helpful Macros */
+#define EX_HANDLER_STACK_SIZ (4*19)
+#define NUM_TO_REG(num) r ## num
+
+#define LWREG_NOP \
+ bri ex_handler_unhandled; \
+ nop;
+
+#define SWREG_NOP \
+ bri ex_handler_unhandled; \
+ nop;
+
+/* FIXME this is weird - for noMMU kernel is not possible to use brid
+ * instruction which can shorten executed time
+ */
+
+/* r3 is the source */
+#define R3_TO_LWREG_V(regnum) \
+ swi r3, r1, 4 * regnum; \
+ bri ex_handler_done;
+
+/* r3 is the source */
+#define R3_TO_LWREG(regnum) \
+ or NUM_TO_REG (regnum), r0, r3; \
+ bri ex_handler_done;
+
+/* r3 is the target */
+#define SWREG_TO_R3_V(regnum) \
+ lwi r3, r1, 4 * regnum; \
+ bri ex_sw_tail;
+
+/* r3 is the target */
+#define SWREG_TO_R3(regnum) \
+ or r3, r0, NUM_TO_REG (regnum); \
+ bri ex_sw_tail;
+
+.extern other_exception_handler /* Defined in exception.c */
+
+/*
+ * hw_exception_handler - Handler for exceptions
+ *
+ * Exception handler notes:
+ * - Handles all exceptions
+ * - Does not handle unaligned exceptions during load into r17, r1, r0.
+ * - Does not handle unaligned exceptions during store from r17 (cannot be
+ * done) and r1 (slows down common case)
+ *
+ * Relevant register structures
+ *
+ * EAR - |----|----|----|----|----|----|----|----|
+ * - < ## 32 bit faulting address ## >
+ *
+ * ESR - |----|----|----|----|----| - | - |-----|-----|
+ * - W S REG EXC
+ *
+ *
+ * STACK FRAME STRUCTURE (for NO_MMU)
+ * ---------------------------------
+ *
+ * +-------------+ + 0
+ * | MSR |
+ * +-------------+ + 4
+ * | r1 |
+ * | . |
+ * | . |
+ * | . |
+ * | . |
+ * | r18 |
+ * +-------------+ + 76
+ * | . |
+ * | . |
+ *
+ * NO_MMU kernel use the same r0_ram pointed space - look to vmlinux.lds.S
+ * which is used for storing register values - old style was, that value were
+ * stored in stack but in case of failure you lost information about register.
+ * Currently you can see register value in memory in specific place.
+ * In compare to with previous solution the speed should be the same.
+ *
+ * MMU exception handler has different handling compare to no MMU kernel.
+ * Exception handler use jump table for directing of what happen. For MMU kernel
+ * is this approach better because MMU relate exception are handled by asm code
+ * in this file. In compare to with MMU expect of unaligned exception is everything
+ * handled by C code.
+ */
+
+/* every of these handlers is entered having R3/4/5/6/11/current saved on stack and clobbered
+ * so care should be taken to restore them if someone is going to return from exception */
+
+/* wrappers to restore state before coming to entry.S */
+
+.global _hw_exception_handler
+.section .text
+.align 4
+.ent _hw_exception_handler
+_hw_exception_handler:
+ addik r1, r1, -(EX_HANDLER_STACK_SIZ); /* Create stack frame */
+ swi r3, r1, PT_R3
+ swi r4, r1, PT_R4
+ swi r5, r1, PT_R5
+ swi r6, r1, PT_R6
+
+ mfs r5, rmsr;
+ nop
+ swi r5, r1, 0;
+ mfs r4, rbtr /* Save BTR before jumping to handler */
+ nop
+ mfs r3, resr
+ nop
+
+ andi r5, r3, 0x1000; /* Check ESR[DS] */
+ beqi r5, not_in_delay_slot; /* Branch if ESR[DS] not set */
+ mfs r17, rbtr; /* ESR[DS] set - return address in BTR */
+ nop
+not_in_delay_slot:
+ swi r17, r1, PT_R17
+
+ andi r5, r3, 0x1F; /* Extract ESR[EXC] */
+
+ /* Exceptions enabled here. This will allow nested exceptions */
+ mfs r6, rmsr;
+ nop
+ swi r6, r1, 0; /* RMSR_OFFSET */
+ ori r6, r6, 0x100; /* Turn ON the EE bit */
+ andi r6, r6, ~2; /* Disable interrupts */
+ mts rmsr, r6;
+ nop
+
+ xori r6, r5, 1; /* 00001 = Unaligned Exception */
+ /* Jump to unalignment exception handler */
+ beqi r6, handle_unaligned_ex;
+
+handle_other_ex: /* Handle Other exceptions here */
+ /* Save other volatiles before we make procedure calls below */
+ swi r7, r1, PT_R7
+ swi r8, r1, PT_R8
+ swi r9, r1, PT_R9
+ swi r10, r1, PT_R10
+ swi r11, r1, PT_R11
+ swi r12, r1, PT_R12
+ swi r14, r1, PT_R14
+ swi r15, r1, PT_R15
+ swi r18, r1, PT_R18
+
+ or r5, r1, r0
+ andi r6, r3, 0x1F; /* Load ESR[EC] */
+ lwi r7, r0, PER_CPU(KM) /* MS: saving current kernel mode to regs */
+ swi r7, r1, PT_MODE
+ mfs r7, rfsr
+ nop
+ addk r8, r17, r0; /* Load exception address */
+ bralid r15, full_exception; /* Branch to the handler */
+ nop;
+
+ /*
+ * Trigger execution of the signal handler by enabling
+ * interrupts and calling an invalid syscall.
+ */
+ mfs r5, rmsr;
+ nop
+ ori r5, r5, 2;
+ mts rmsr, r5; /* enable interrupt */
+ nop
+ addi r12, r0, __NR_syscalls;
+ brki r14, 0x08;
+ mfs r5, rmsr; /* disable interrupt */
+ nop
+ andi r5, r5, ~2;
+ mts rmsr, r5;
+ nop
+
+ lwi r7, r1, PT_R7
+ lwi r8, r1, PT_R8
+ lwi r9, r1, PT_R9
+ lwi r10, r1, PT_R10
+ lwi r11, r1, PT_R11
+ lwi r12, r1, PT_R12
+ lwi r14, r1, PT_R14
+ lwi r15, r1, PT_R15
+ lwi r18, r1, PT_R18
+
+ bri ex_handler_done; /* Complete exception handling */
+
+/* 0x01 - Unaligned data access exception
+ * This occurs when a word access is not aligned on a word boundary,
+ * or when a 16-bit access is not aligned on a 16-bit boundary.
+ * This handler perform the access, and returns, except for MMU when
+ * the unaligned address is last on a 4k page or the physical address is
+ * not found in the page table, in which case unaligned_data_trap is called.
+ */
+handle_unaligned_ex:
+ /* Working registers already saved: R3, R4, R5, R6
+ * R3 = ESR
+ * R4 = BTR
+ */
+ mfs r4, rear;
+ nop
+
+ andi r6, r3, 0x3E0; /* Mask and extract the register operand */
+ srl r6, r6; /* r6 >> 5 */
+ srl r6, r6;
+ srl r6, r6;
+ srl r6, r6;
+ srl r6, r6;
+ /* Store the register operand in a temporary location */
+ sbi r6, r0, ex_reg_op;
+
+ andi r6, r3, 0x400; /* Extract ESR[S] */
+ bnei r6, ex_sw;
+ex_lw:
+ andi r6, r3, 0x800; /* Extract ESR[W] */
+ beqi r6, ex_lhw;
+ lbui r5, r4, 0; /* Exception address in r4 */
+ /* Load a word, byte-by-byte from destination address
+ and save it in tmp space */
+ sbi r5, r0, TOPHYS(ex_tmp_data_loc_0);
+ lbui r5, r4, 1;
+ sbi r5, r0, TOPHYS(ex_tmp_data_loc_1);
+ lbui r5, r4, 2;
+ sbi r5, r0, TOPHYS(ex_tmp_data_loc_2);
+ lbui r5, r4, 3;
+ sbi r5, r0, TOPHYS(ex_tmp_data_loc_3);
+ /* Get the destination register value into r3 */
+ lwi r3, r0, TOPHYS(ex_tmp_data_loc_0);
+ bri ex_lw_tail;
+ex_lhw:
+ lbui r5, r4, 0; /* Exception address in r4 */
+ /* Load a half-word, byte-by-byte from destination
+ address and save it in tmp space */
+ sbi r5, r0, TOPHYS(ex_tmp_data_loc_0);
+ lbui r5, r4, 1;
+ sbi r5, r0, TOPHYS(ex_tmp_data_loc_1);
+ /* Get the destination register value into r3 */
+ lhui r3, r0, TOPHYS(ex_tmp_data_loc_0);
+ex_lw_tail:
+ /* Get the destination register number into r5 */
+ lbui r5, r0, TOPHYS(ex_reg_op);
+ /* Form load_word jump table offset (lw_table + (8 * regnum)) */
+ la r6, r0, TOPHYS(lw_table);
+ addk r5, r5, r5;
+ addk r5, r5, r5;
+ addk r5, r5, r5;
+ addk r5, r5, r6;
+ bra r5;
+ex_lw_end: /* Exception handling of load word, ends */
+ex_sw:
+ /* Get the destination register number into r5 */
+ lbui r5, r0, TOPHYS(ex_reg_op);
+ /* Form store_word jump table offset (sw_table + (8 * regnum)) */
+ la r6, r0, TOPHYS(sw_table);
+ add r5, r5, r5;
+ add r5, r5, r5;
+ add r5, r5, r5;
+ add r5, r5, r6;
+ bra r5;
+ex_sw_tail:
+ mfs r6, resr;
+ nop
+ andi r6, r6, 0x800; /* Extract ESR[W] */
+ beqi r6, ex_shw;
+ swi r3, r0, TOPHYS(ex_tmp_data_loc_0); /* Get the word - delay slot */
+ /* Store the word, byte-by-byte into destination address */
+ lbui r3, r0, TOPHYS(ex_tmp_data_loc_0);
+ sbi r3, r4, 0;
+ lbui r3, r0, TOPHYS(ex_tmp_data_loc_1);
+ sbi r3, r4, 1;
+ lbui r3, r0, TOPHYS(ex_tmp_data_loc_2);
+ sbi r3, r4, 2;
+ lbui r3, r0, TOPHYS(ex_tmp_data_loc_3);
+ sbi r3, r4, 3;
+ bri ex_handler_done;
+
+ex_shw:
+ /* Store the lower half-word, byte-by-byte into destination address */
+ swi r3, r0, TOPHYS(ex_tmp_data_loc_0);
+ lbui r3, r0, TOPHYS(ex_tmp_data_loc_2);
+ sbi r3, r4, 0;
+ lbui r3, r0, TOPHYS(ex_tmp_data_loc_3);
+ sbi r3, r4, 1;
+ex_sw_end: /* Exception handling of store word, ends. */
+
+ex_handler_done:
+ lwi r5, r1, 0 /* RMSR */
+ mts rmsr, r5
+ nop
+ lwi r3, r1, PT_R3
+ lwi r4, r1, PT_R4
+ lwi r5, r1, PT_R5
+ lwi r6, r1, PT_R6
+ lwi r17, r1, PT_R17
+
+ rted r17, 0
+ addik r1, r1, (EX_HANDLER_STACK_SIZ); /* Restore stack frame */
+
+.end _hw_exception_handler
+
+ex_handler_unhandled:
+/* FIXME add handle function for unhandled exception - for example dump register */
+ bri 0
+
+/*
+ * hw_exception_handler Jump Table
+ * - Contains code snippets for each register that caused the unaligned exception
+ * - Hence exception handler is NOT self-modifying
+ * - Separate table for load exceptions and store exceptions.
+ * - Each table is of size: (8 * 32) = 256 bytes
+ */
+
+.section .text
+.align 4
+lw_table:
+lw_r0: R3_TO_LWREG (0);
+lw_r1: LWREG_NOP;
+lw_r2: R3_TO_LWREG (2);
+lw_r3: R3_TO_LWREG_V (3);
+lw_r4: R3_TO_LWREG_V (4);
+lw_r5: R3_TO_LWREG_V (5);
+lw_r6: R3_TO_LWREG_V (6);
+lw_r7: R3_TO_LWREG (7);
+lw_r8: R3_TO_LWREG (8);
+lw_r9: R3_TO_LWREG (9);
+lw_r10: R3_TO_LWREG (10);
+lw_r11: R3_TO_LWREG (11);
+lw_r12: R3_TO_LWREG (12);
+lw_r13: R3_TO_LWREG (13);
+lw_r14: R3_TO_LWREG (14);
+lw_r15: R3_TO_LWREG (15);
+lw_r16: R3_TO_LWREG (16);
+lw_r17: LWREG_NOP;
+lw_r18: R3_TO_LWREG (18);
+lw_r19: R3_TO_LWREG (19);
+lw_r20: R3_TO_LWREG (20);
+lw_r21: R3_TO_LWREG (21);
+lw_r22: R3_TO_LWREG (22);
+lw_r23: R3_TO_LWREG (23);
+lw_r24: R3_TO_LWREG (24);
+lw_r25: R3_TO_LWREG (25);
+lw_r26: R3_TO_LWREG (26);
+lw_r27: R3_TO_LWREG (27);
+lw_r28: R3_TO_LWREG (28);
+lw_r29: R3_TO_LWREG (29);
+lw_r30: R3_TO_LWREG (30);
+lw_r31: R3_TO_LWREG (31);
+
+sw_table:
+sw_r0: SWREG_TO_R3 (0);
+sw_r1: SWREG_NOP;
+sw_r2: SWREG_TO_R3 (2);
+sw_r3: SWREG_TO_R3_V (3);
+sw_r4: SWREG_TO_R3_V (4);
+sw_r5: SWREG_TO_R3_V (5);
+sw_r6: SWREG_TO_R3_V (6);
+sw_r7: SWREG_TO_R3 (7);
+sw_r8: SWREG_TO_R3 (8);
+sw_r9: SWREG_TO_R3 (9);
+sw_r10: SWREG_TO_R3 (10);
+sw_r11: SWREG_TO_R3 (11);
+sw_r12: SWREG_TO_R3 (12);
+sw_r13: SWREG_TO_R3 (13);
+sw_r14: SWREG_TO_R3 (14);
+sw_r15: SWREG_TO_R3 (15);
+sw_r16: SWREG_TO_R3 (16);
+sw_r17: SWREG_NOP;
+sw_r18: SWREG_TO_R3 (18);
+sw_r19: SWREG_TO_R3 (19);
+sw_r20: SWREG_TO_R3 (20);
+sw_r21: SWREG_TO_R3 (21);
+sw_r22: SWREG_TO_R3 (22);
+sw_r23: SWREG_TO_R3 (23);
+sw_r24: SWREG_TO_R3 (24);
+sw_r25: SWREG_TO_R3 (25);
+sw_r26: SWREG_TO_R3 (26);
+sw_r27: SWREG_TO_R3 (27);
+sw_r28: SWREG_TO_R3 (28);
+sw_r29: SWREG_TO_R3 (29);
+sw_r30: SWREG_TO_R3 (30);
+sw_r31: SWREG_TO_R3 (31);
+
+/* Temporary data structures used in the handler */
+.section .data
+.align 4
+ex_tmp_data_loc_0:
+ .byte 0
+ex_tmp_data_loc_1:
+ .byte 0
+ex_tmp_data_loc_2:
+ .byte 0
+ex_tmp_data_loc_3:
+ .byte 0
+ex_reg_op:
+ .byte 0
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/irq.h | 46 ++++++
arch/microblaze/include/asm/selfmod.h | 24 ++++
arch/microblaze/kernel/intc.c | 167 ++++++++++++++++++++++
arch/microblaze/kernel/irq.c | 102 ++++++++++++++
arch/microblaze/kernel/selfmod.c | 80 +++++++++++
arch/microblaze/kernel/timer.c | 246 +++++++++++++++++++++++++++++++++
6 files changed, 665 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/irq.h
create mode 100644 arch/microblaze/include/asm/selfmod.h
create mode 100644 arch/microblaze/kernel/intc.c
create mode 100644 arch/microblaze/kernel/irq.c
create mode 100644 arch/microblaze/kernel/selfmod.c
create mode 100644 arch/microblaze/kernel/timer.c
diff --git a/arch/microblaze/include/asm/irq.h b/arch/microblaze/include/asm/irq.h
new file mode 100644
index 0000000..c0b773f
--- /dev/null
+++ b/arch/microblaze/include/asm/irq.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_IRQ_H
+#define _ASM_MICROBLAZE_IRQ_H
+
+#define NR_IRQS 32
+
+#include <linux/interrupt.h>
+
+extern unsigned int nr_irq;
+
+#define NO_IRQ (-1)
+
+static inline int irq_canonicalize(int irq)
+{
+ return irq;
+}
+
+struct pt_regs;
+extern void do_IRQ(struct pt_regs *regs);
+
+/* irq_of_parse_and_map - Parse and Map an interrupt into linux virq space
+ * @device: Device node of the device whose interrupt is to be mapped
+ * @index: Index of the interrupt to map
+ *
+ * This function is a wrapper that chains of_irq_map_one() and
+ * irq_create_of_mapping() to make things easier to callers
+ */
+struct device_node;
+extern unsigned int irq_of_parse_and_map(struct device_node *dev, int index);
+
+/** FIXME - not implement
+ * irq_dispose_mapping - Unmap an interrupt
+ * @virq: linux virq number of the interrupt to unmap
+ */
+static inline void irq_dispose_mapping(unsigned int virq) {
+ return;
+}
+
+#endif /* _ASM_MICROBLAZE_IRQ_H */
diff --git a/arch/microblaze/include/asm/selfmod.h b/arch/microblaze/include/asm/selfmod.h
new file mode 100644
index 0000000..c42aff2
--- /dev/null
+++ b/arch/microblaze/include/asm/selfmod.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2007-2008 Michal Simek <[email protected]>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_SELFMOD_H
+#define _ASM_MICROBLAZE_SELFMOD_H
+
+/*
+ * BARRIER_BASE_ADDR is constant address for selfmod function.
+ * do not change this value - selfmod function is in
+ * arch/microblaze/kernel/selfmod.c: selfmod_function()
+ *
+ * last 16 bits is used for storing register offset
+ */
+
+#define BARRIER_BASE_ADDR 0x1234ff00
+
+void selfmod_function(const int *arr_fce, const unsigned int base);
+
+#endif /* _ASM_MICROBLAZE_SELFMOD_H */
diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c
new file mode 100644
index 0000000..9b57e47
--- /dev/null
+++ b/arch/microblaze/kernel/intc.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2007 Michal Simek <[email protected]>
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/page.h>
+#include <linux/io.h>
+
+#include <asm/prom.h>
+#include <asm/irq.h>
+
+#ifdef CONFIG_SELFMOD_INTC
+#include <asm/selfmod.h>
+#define INTC_BASE BARRIER_BASE_ADDR
+#else
+static unsigned int intc_baseaddr;
+#define INTC_BASE intc_baseaddr
+#endif
+
+unsigned int nr_irq;
+
+/* No one else should require these constants, so define them locally here. */
+#define ISR 0x00 /* Interrupt Status Register */
+#define IPR 0x04 /* Interrupt Pending Register */
+#define IER 0x08 /* Interrupt Enable Register */
+#define IAR 0x0c /* Interrupt Acknowledge Register */
+#define SIE 0x10 /* Set Interrupt Enable bits */
+#define CIE 0x14 /* Clear Interrupt Enable bits */
+#define IVR 0x18 /* Interrupt Vector Register */
+#define MER 0x1c /* Master Enable Register */
+
+#define MER_ME (1<<0)
+#define MER_HIE (1<<1)
+
+static void intc_enable(unsigned int irq)
+{
+ unsigned int mask = (0x00000001 << (irq & 31));
+ pr_debug("enable: %d\n", irq);
+ out_be32(INTC_BASE + SIE, mask);
+}
+
+static void intc_disable(unsigned int irq)
+{
+ unsigned long mask = (0x00000001 << (irq & 31));
+ pr_debug("disable: %d\n", irq);
+ out_be32(INTC_BASE + CIE, mask);
+}
+
+static void intc_disable_and_ack(unsigned int irq)
+{
+ unsigned long mask = (0x00000001 << (irq & 31));
+ pr_debug("disable_and_ack: %d\n", irq);
+ out_be32(INTC_BASE + CIE, mask);
+ /* ack edge triggered intr */
+ if (!(irq_desc[irq].status & IRQ_LEVEL))
+ out_be32(INTC_BASE + IAR, mask);
+}
+
+static void intc_end(unsigned int irq)
+{
+ unsigned long mask = (0x00000001 << (irq & 31));
+
+ pr_debug("end: %d\n", irq);
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+ out_be32(INTC_BASE + SIE, mask);
+ /* ack level sensitive intr */
+ if (irq_desc[irq].status & IRQ_LEVEL)
+ out_be32(INTC_BASE + IAR, mask);
+ }
+}
+
+static struct irq_chip intc_dev = {
+ .name = "INTC",
+ .enable = intc_enable,
+ .disable = intc_disable,
+ .ack = intc_disable_and_ack,
+ .end = intc_end,
+};
+
+unsigned int get_irq(struct pt_regs *regs)
+{
+ int irq;
+
+ /*
+ * NOTE: This function is the one that needs to be improved in
+ * order to handle multiple interrupt controllers. It currently
+ * is hardcoded to check for interrupts only on the first INTC.
+ */
+ irq = in_be32(INTC_BASE + IVR);
+ pr_debug("get_irq: %d\n", irq);
+
+ return irq;
+}
+
+void __init init_IRQ(void)
+{
+ u32 i, j, intr_type;
+ struct device_node *intc = NULL;
+#ifdef CONFIG_SELFMOD_INTC
+ unsigned int intc_baseaddr = 0;
+ static int arr_func[] = {
+ (int)&get_irq,
+ (int)&intc_enable,
+ (int)&intc_disable,
+ (int)&intc_disable_and_ack,
+ (int)&intc_end,
+ 0
+ };
+#endif
+ static char *intc_list[] = {
+ "xlnx,xps-intc-1.00.a",
+ "xlnx,opb-intc-1.00.c",
+ "xlnx,opb-intc-1.00.b",
+ "xlnx,opb-intc-1.00.a",
+ NULL
+ };
+
+ for (j = 0; intc_list[j] != NULL; j++) {
+ intc = of_find_compatible_node(NULL, NULL, intc_list[j]);
+ if (intc)
+ break;
+ }
+
+ intc_baseaddr = *(int *) of_get_property(intc, "reg", NULL);
+ intc_baseaddr = (unsigned long) ioremap(intc_baseaddr, PAGE_SIZE);
+ nr_irq = *(int *) of_get_property(intc, "xlnx,num-intr-inputs", NULL);
+
+ intr_type =
+ *(int *) of_get_property(intc, "xlnx,kind-of-intr", NULL);
+ if (intr_type >= (1 << nr_irq))
+ printk(" ERROR: Mishmash in king-of-intr parameter\n");
+
+#ifdef CONFIG_SELFMOD_INTC
+ selfmod_function((int *) arr_func, intc_baseaddr);
+#endif
+ printk(KERN_INFO "%s #0 at 0x%08x, num_irq=%d, edge=0x%x\n",
+ intc_list[j], intc_baseaddr, nr_irq, intr_type);
+
+ /*
+ * Disable all external interrupts until they are
+ * explicity requested.
+ */
+ out_be32(intc_baseaddr + IER, 0);
+
+ /* Acknowledge any pending interrupts just in case. */
+ out_be32(intc_baseaddr + IAR, 0xffffffff);
+
+ /* Turn on the Master Enable. */
+ out_be32(intc_baseaddr + MER, MER_HIE | MER_ME);
+
+ for (i = 0; i < nr_irq; ++i) {
+ if (intr_type & (0x00000001 << i)) {
+ set_irq_chip_and_handler_name(i, &intc_dev,
+ handle_edge_irq, intc_dev.name);
+ irq_desc[i].status &= ~IRQ_LEVEL;
+ } else {
+ set_irq_chip_and_handler_name(i, &intc_dev,
+ handle_level_irq, intc_dev.name);
+ irq_desc[i].status |= IRQ_LEVEL;
+ }
+ }
+}
diff --git a/arch/microblaze/kernel/irq.c b/arch/microblaze/kernel/irq.c
new file mode 100644
index 0000000..ff2d29f
--- /dev/null
+++ b/arch/microblaze/kernel/irq.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/hardirq.h>
+#include <linux/interrupt.h>
+#include <linux/irqflags.h>
+#include <linux/seq_file.h>
+#include <linux/kernel_stat.h>
+#include <linux/irq.h>
+
+#include <asm/prom.h>
+
+unsigned int irq_of_parse_and_map(struct device_node *dev, int index)
+{
+ struct of_irq oirq;
+
+ if (of_irq_map_one(dev, index, &oirq))
+ return NO_IRQ;
+
+ return oirq.specifier[0];
+}
+EXPORT_SYMBOL_GPL(irq_of_parse_and_map);
+
+/*
+ * 'what should we do if we get a hw irq event on an illegal vector'.
+ * each architecture has to answer this themselves.
+ */
+void ack_bad_irq(unsigned int irq)
+{
+ printk(KERN_WARNING "unexpected IRQ trap at vector %02x\n", irq);
+}
+
+static u32 concurrent_irq;
+
+void do_IRQ(struct pt_regs *regs)
+{
+ unsigned int irq;
+ struct pt_regs *old_regs = set_irq_regs(regs);
+
+ irq_enter();
+ irq = get_irq(regs);
+next_irq:
+ BUG_ON(irq == -1U);
+ __do_IRQ(irq);
+
+ irq = get_irq(regs);
+ if (irq != -1U) {
+ pr_debug("next irq: %d\n", irq);
+ ++concurrent_irq;
+ goto next_irq;
+ }
+
+ irq_exit();
+ set_irq_regs(old_regs);
+}
+
+int show_interrupts(struct seq_file *p, void *v)
+{
+ int i = *(loff_t *) v, j;
+ struct irqaction *action;
+ unsigned long flags;
+
+ if (i == 0) {
+ seq_printf(p, " ");
+ for_each_online_cpu(j)
+ seq_printf(p, "CPU%-8d", j);
+ seq_putc(p, '\n');
+ }
+
+ if (i < nr_irq) {
+ spin_lock_irqsave(&irq_desc[i].lock, flags);
+ action = irq_desc[i].action;
+ if (!action)
+ goto skip;
+ seq_printf(p, "%3d: ", i);
+#ifndef CONFIG_SMP
+ seq_printf(p, "%10u ", kstat_irqs(i));
+#else
+ for_each_online_cpu(j)
+ seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+#endif
+ seq_printf(p, " %8s", irq_desc[i].status &
+ IRQ_LEVEL ? "level" : "edge");
+ seq_printf(p, " %8s", irq_desc[i].chip->name);
+ seq_printf(p, " %s", action->name);
+
+ for (action = action->next; action; action = action->next)
+ seq_printf(p, ", %s", action->name);
+
+ seq_putc(p, '\n');
+skip:
+ spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+ }
+ return 0;
+}
diff --git a/arch/microblaze/kernel/selfmod.c b/arch/microblaze/kernel/selfmod.c
new file mode 100644
index 0000000..c0eb301
--- /dev/null
+++ b/arch/microblaze/kernel/selfmod.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007-2008 Michal Simek <[email protected]>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/interrupt.h>
+#include <asm/selfmod.h>
+
+#undef DEBUG
+
+#if __GNUC__ > 3
+#error GCC 4 unsupported SELFMOD. Please disable SELFMOD from menuconfig.
+#endif
+
+#define OPCODE_IMM 0xB0000000
+#define OPCODE_LWI 0xE8000000
+#define OPCODE_LWI_MASK 0xEC000000
+#define OPCODE_RTSD 0xB60F0008 /* return from func: rtsd r15, 8 */
+#define OPCODE_ADDIK 0x30000000
+#define OPCODE_ADDIK_MASK 0xFC000000
+
+#define IMM_BASE (OPCODE_IMM | (BARRIER_BASE_ADDR >> 16))
+#define LWI_BASE (OPCODE_LWI | (BARRIER_BASE_ADDR & 0x0000ff00))
+#define LWI_BASE_MASK (OPCODE_LWI_MASK | (BARRIER_BASE_ADDR & 0x0000ff00))
+#define ADDIK_BASE (OPCODE_ADDIK | (BARRIER_BASE_ADDR & 0x0000ff00))
+#define ADDIK_BASE_MASK (OPCODE_ADDIK_MASK | (BARRIER_BASE_ADDR & 0x0000ff00))
+
+#define MODIFY_INSTR { \
+ pr_debug("%s: curr instr, (%d):0x%x, next(%d):0x%x\n", \
+ __func__, i, addr[i], i + 1, addr[i + 1]); \
+ addr[i] = OPCODE_IMM + (base >> 16); \
+ /* keep instruction opcode and add only last 16bits */ \
+ addr[i + 1] = (addr[i + 1] & 0xffff00ff) + (base & 0xffff); \
+ __invalidate_icache(addr[i]); \
+ __invalidate_icache(addr[i + 1]); \
+ pr_debug("%s: hack instr, (%d):0x%x, next(%d):0x%x\n", \
+ __func__, i, addr[i], i + 1, addr[i + 1]); }
+
+/* NOTE
+ * self-modified part of code for improvement of interrupt controller
+ * save instruction in interrupt rutine
+ */
+void selfmod_function(const int *arr_fce, const unsigned int base)
+{
+ unsigned int flags, i, j, *addr = NULL;
+
+ local_irq_save(flags);
+ __disable_icache();
+
+ /* zero terminated array */
+ for (j = 0; arr_fce[j] != 0; j++) {
+ /* get start address of function */
+ addr = (unsigned int *) arr_fce[j];
+ pr_debug("%s: func(%d) at 0x%x\n",
+ __func__, j, (unsigned int) addr);
+ for (i = 0; ; i++) {
+ pr_debug("%s: instruction code at %d: 0x%x\n",
+ __func__, i, addr[i]);
+ if (addr[i] == IMM_BASE) {
+ /* detecting of lwi (0xE8) or swi (0xF8) instr
+ * I can detect both opcode with one mask */
+ if ((addr[i + 1] & LWI_BASE_MASK) == LWI_BASE) {
+ MODIFY_INSTR;
+ } else /* detection addik for ack */
+ if ((addr[i + 1] & ADDIK_BASE_MASK) ==
+ ADDIK_BASE) {
+ MODIFY_INSTR;
+ }
+ } else if (addr[i] == OPCODE_RTSD) {
+ /* return from function means end of function */
+ pr_debug("%s: end of array %d\n", __func__, i);
+ break;
+ }
+ }
+ }
+ local_irq_restore(flags);
+} /* end of self-modified code */
diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c
new file mode 100644
index 0000000..2dccd29
--- /dev/null
+++ b/arch/microblaze/kernel/timer.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2007-2008 Michal Simek <[email protected]>
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/interrupt.h>
+#include <linux/profile.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/io.h>
+#include <asm/cpuinfo.h>
+#include <asm/setup.h>
+#include <asm/prom.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#ifdef CONFIG_SELFMOD_TIMER
+#include <asm/selfmod.h>
+#define TIMER_BASE BARRIER_BASE_ADDR
+#else
+static unsigned int timer_baseaddr;
+#define TIMER_BASE timer_baseaddr
+#endif
+
+#define TCSR0 (0x00)
+#define TLR0 (0x04)
+#define TCR0 (0x08)
+
+#define TCSR_MDT (1<<0)
+#define TCSR_UDT (1<<1)
+#define TCSR_GENT (1<<2)
+#define TCSR_CAPT (1<<3)
+#define TCSR_ARHT (1<<4)
+#define TCSR_LOAD (1<<5)
+#define TCSR_ENIT (1<<6)
+#define TCSR_ENT (1<<7)
+#define TCSR_TINT (1<<8)
+#define TCSR_PWMA (1<<9)
+#define TCSR_ENALL (1<<10)
+
+static void timer_ack(void)
+{
+ out_be32(TIMER_BASE + TCSR0, in_be32(TIMER_BASE + TCSR0));
+}
+
+static cycle_t mb_tick_cnt; /* store counter ticks */
+
+static cycle_t microblaze_read(void)
+{
+ u64 temp = (u64)mb_tick_cnt + (u64)((u32)cpuinfo.freq_div_hz
+ - (u32)in_be32(TIMER_BASE + TCR0));
+ return temp;
+}
+
+static struct clocksource clocksource_microblaze = {
+ .name = "microblaze_counter",
+ .rating = 200,
+ .read = microblaze_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 13, /* I can shift it */
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int __init microblaze_clocksource_init(void)
+{
+ clocksource_microblaze.mult =
+ clocksource_hz2mult(cpuinfo.cpu_clock_freq,
+ clocksource_microblaze.shift);
+ if (clocksource_register(&clocksource_microblaze))
+ panic("failed to register clocksource");
+
+ return 0;
+}
+
+static inline void microblaze_timer_stop(void)
+{
+ out_be32(TIMER_BASE + TCSR0, in_be32(TIMER_BASE + TCSR0) & ~TCSR_ENT);
+}
+
+static inline void microblaze_timer_start(unsigned long load_val)
+{
+ if (!load_val)
+ load_val = 1;
+ out_be32(TIMER_BASE + TLR0, load_val); /* loading value to timer reg */
+
+ /* load the initial value */
+ out_be32(TIMER_BASE + TCSR0, TCSR_LOAD);
+
+ /* see timer data sheet for detail
+ * !ENALL - don't enable 'em all
+ * !PWMA - disable pwm
+ * TINT - clear interrupt status
+ * ENT- enable timer itself
+ * EINT - enable interrupt
+ * !LOAD - clear the bit to let go
+ * ARHT - auto reload
+ * !CAPT - no external trigger
+ * !GENT - no external signal
+ * UDT - set the timer as down counter
+ * !MDT0 - generate mode
+ */
+ out_be32(TIMER_BASE + TCSR0,
+ TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT);
+}
+
+static int microblaze_timer_set_next_event(unsigned long delta,
+ struct clock_event_device *dev)
+{
+ printk(KERN_INFO "next event, delta %x, %d\n", (u32)delta, (u32)delta);
+ microblaze_timer_start(delta);
+ return 0;
+}
+
+static void microblaze_timer_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ microblaze_timer_stop();
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ printk(KERN_INFO "%s: periodic\n", __func__);
+ microblaze_timer_start(cpuinfo.freq_div_hz);
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ printk(KERN_INFO "%s: oneshot\n", __func__);
+ break;
+ case CLOCK_EVT_MODE_UNUSED:
+ printk(KERN_INFO "%s: unused\n", __func__);
+ break;
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ printk(KERN_INFO "%s: shutdown\n", __func__);
+ microblaze_timer_stop();
+ break;
+ case CLOCK_EVT_MODE_RESUME:
+ printk(KERN_INFO "%s: resume\n", __func__);
+ break;
+ }
+}
+
+static struct clock_event_device clockevent_microblaze_timer = {
+ .name = "microblaze-timer",
+ .features = CLOCK_EVT_FEAT_PERIODIC,
+ .shift = 13,
+ .rating = 200,
+ .set_next_event = microblaze_timer_set_next_event,
+ .set_mode = microblaze_timer_set_mode,
+};
+
+static irqreturn_t timer_interrupt(int irq, void *dev_id)
+{
+ struct clock_event_device *evt = &clockevent_microblaze_timer;
+#ifdef CONFIG_HEART_BEAT
+ heartbeat();
+#endif
+ timer_ack();
+
+ mb_tick_cnt += cpuinfo.freq_div_hz;
+
+ evt->event_handler(evt);
+ return IRQ_HANDLED;
+}
+
+static struct irqaction timer_irqaction = {
+ .handler = timer_interrupt,
+ .flags = IRQF_DISABLED,
+ .name = "timer",
+ .dev_id = &clockevent_microblaze_timer,
+};
+
+static __init void microblaze_clockevent_init(void)
+{
+ clockevent_microblaze_timer.mult =
+ div_sc(cpuinfo.cpu_clock_freq, NSEC_PER_SEC,
+ clockevent_microblaze_timer.shift);
+ clockevent_microblaze_timer.max_delta_ns =
+ clockevent_delta2ns((u32)~0, &clockevent_microblaze_timer);
+ clockevent_microblaze_timer.min_delta_ns =
+ clockevent_delta2ns(1, &clockevent_microblaze_timer);
+ clockevent_microblaze_timer.cpumask = cpumask_of(0);
+ clockevents_register_device(&clockevent_microblaze_timer);
+}
+
+void __init time_init(void)
+{
+ int irq, j = 0;
+ struct device_node *timer = NULL;
+#ifdef CONFIG_SELFMOD_TIMER
+ unsigned int timer_baseaddr = 0;
+ int arr_func[] = {
+ (int)&timer_ack,
+ (int)µblaze_read,
+ (int)µblaze_timer_stop,
+ (int)µblaze_timer_start,
+ (int)µblaze_timer_set_mode,
+ 0
+ };
+#endif
+ char *timer_list[] = {
+ "xlnx,xps-timer-1.00.a",
+ "xlnx,opb-timer-1.00.b",
+ "xlnx,opb-timer-1.00.a",
+ NULL
+ };
+
+ for (j = 0; timer_list[j] != NULL; j++) {
+ timer = of_find_compatible_node(NULL, NULL, timer_list[j]);
+ if (timer)
+ break;
+ }
+
+ timer_baseaddr = *(int *) of_get_property(timer, "reg", NULL);
+ timer_baseaddr = (unsigned long) ioremap(timer_baseaddr, PAGE_SIZE);
+ irq = *(int *) of_get_property(timer, "interrupts", NULL);
+#ifdef CONFIG_SELFMOD_TIMER
+ selfmod_function((int *) arr_func, timer_baseaddr);
+#endif
+ printk(KERN_INFO "%s #0 at 0x%08x, irq=%d\n",
+ timer_list[j], timer_baseaddr, irq);
+
+ cpuinfo.freq_div_hz = cpuinfo.cpu_clock_freq / HZ;
+
+ setup_irq(irq, &timer_irqaction);
+#ifdef CONFIG_HEART_BEAT
+ setup_heartbeat();
+#endif
+ xtime.tv_sec = mktime(2007, 1, 1, 0, 0, 0);
+ xtime.tv_nsec = 0;
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
+
+ microblaze_clocksource_init();
+ microblaze_clockevent_init();
+}
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/module.h | 37 +++++++
arch/microblaze/kernel/microblaze_ksyms.c | 46 +++++++++
arch/microblaze/kernel/module.c | 148 +++++++++++++++++++++++++++++
3 files changed, 231 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/module.h
create mode 100644 arch/microblaze/kernel/microblaze_ksyms.c
create mode 100644 arch/microblaze/kernel/module.c
diff --git a/arch/microblaze/include/asm/module.h b/arch/microblaze/include/asm/module.h
new file mode 100644
index 0000000..914565a
--- /dev/null
+++ b/arch/microblaze/include/asm/module.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_MODULE_H
+#define _ASM_MICROBLAZE_MODULE_H
+
+/* Microblaze Relocations */
+#define R_MICROBLAZE_NONE 0
+#define R_MICROBLAZE_32 1
+#define R_MICROBLAZE_32_PCREL 2
+#define R_MICROBLAZE_64_PCREL 3
+#define R_MICROBLAZE_32_PCREL_LO 4
+#define R_MICROBLAZE_64 5
+#define R_MICROBLAZE_32_LO 6
+#define R_MICROBLAZE_SRO32 7
+#define R_MICROBLAZE_SRW32 8
+#define R_MICROBLAZE_64_NONE 9
+#define R_MICROBLAZE_32_SYM_OP_SYM 10
+/* Keep this the last entry. */
+#define R_MICROBLAZE_NUM 11
+
+struct mod_arch_specific {
+ int foo;
+};
+
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Ehdr Elf32_Ehdr
+
+typedef struct { volatile int counter; } module_t;
+
+#endif /* _ASM_MICROBLAZE_MODULE_H */
diff --git a/arch/microblaze/kernel/microblaze_ksyms.c b/arch/microblaze/kernel/microblaze_ksyms.c
new file mode 100644
index 0000000..e8ffb6f
--- /dev/null
+++ b/arch/microblaze/kernel/microblaze_ksyms.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008 Michal Simek <[email protected]>
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/cryptohash.h>
+#include <linux/delay.h>
+#include <linux/in6.h>
+#include <linux/syscalls.h>
+
+#include <asm/checksum.h>
+#include <linux/io.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <linux/uaccess.h>
+
+/*
+ * libgcc functions - functions that are used internally by the
+ * compiler... (prototypes are not correct though, but that
+ * doesn't really matter since they're not versioned).
+ */
+extern void __ashldi3(void);
+EXPORT_SYMBOL(__ashldi3);
+extern void __ashrdi3(void);
+EXPORT_SYMBOL(__ashrdi3);
+extern void __divsi3(void);
+EXPORT_SYMBOL(__divsi3);
+extern void __lshrdi3(void);
+EXPORT_SYMBOL(__lshrdi3);
+extern void __modsi3(void);
+EXPORT_SYMBOL(__modsi3);
+extern void __mulsi3(void);
+EXPORT_SYMBOL(__mulsi3);
+extern void __muldi3(void);
+EXPORT_SYMBOL(__muldi3);
+extern void __ucmpdi2(void);
+EXPORT_SYMBOL(__ucmpdi2);
+extern void __udivsi3(void);
+EXPORT_SYMBOL(__udivsi3);
+extern void __umodsi3(void);
+EXPORT_SYMBOL(__umodsi3);
diff --git a/arch/microblaze/kernel/module.c b/arch/microblaze/kernel/module.c
new file mode 100644
index 0000000..92549a2
--- /dev/null
+++ b/arch/microblaze/kernel/module.c
@@ -0,0 +1,148 @@
+/*
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleloader.h>
+#include <linux/kernel.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+
+#include <asm/pgtable.h>
+
+void *module_alloc(unsigned long size)
+{
+ void *ret;
+ ret = (size == 0) ? NULL : vmalloc(size);
+ pr_debug("module_alloc (%08lx@%08lx)\n", size, (unsigned long int)ret);
+ return ret;
+}
+
+void module_free(struct module *module, void *region)
+{
+ pr_debug("module_free(%s,%08lx)\n", module->name,
+ (unsigned long)region);
+ vfree(region);
+}
+
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+ Elf_Shdr *sechdrs,
+ char *secstrings,
+ struct module *mod)
+{
+ return 0;
+}
+
+int apply_relocate(Elf32_Shdr *sechdrs, const char *strtab,
+ unsigned int symindex, unsigned int relsec, struct module *module)
+{
+ printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
+ module->name);
+ return -ENOEXEC;
+}
+
+int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
+ unsigned int symindex, unsigned int relsec, struct module *module)
+{
+
+ unsigned int i;
+ Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
+ Elf32_Sym *sym;
+ unsigned long int *location;
+ unsigned long int locoffs;
+ unsigned long int value;
+#if __GNUC__ < 4
+ unsigned long int old_value;
+#endif
+
+ pr_debug("Applying add relocation section %u to %u\n",
+ relsec, sechdrs[relsec].sh_info);
+
+ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
+
+ location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr +
+ rela[i].r_offset;
+ sym = (Elf32_Sym *)sechdrs[symindex].sh_addr +
+ ELF32_R_SYM(rela[i].r_info);
+ value = sym->st_value + rela[i].r_addend;
+
+ switch (ELF32_R_TYPE(rela[i].r_info)) {
+
+ /*
+ * Be careful! mb-gcc / mb-ld splits the relocs between the
+ * text and the reloc table. In general this means we must
+ * read the current contents of (*location), add any offset
+ * then store the result back in
+ */
+
+ case R_MICROBLAZE_32:
+#if __GNUC__ < 4
+ old_value = *location;
+ *location = value + old_value;
+
+ pr_debug("R_MICROBLAZE_32 (%08lx->%08lx)\n",
+ old_value, value);
+#else
+ *location = value;
+#endif
+ break;
+
+ case R_MICROBLAZE_64:
+#if __GNUC__ < 4
+ /* Split relocs only required/used pre gcc4.1.1 */
+ old_value = ((location[0] & 0x0000FFFF) << 16) |
+ (location[1] & 0x0000FFFF);
+ value += old_value;
+#endif
+ location[0] = (location[0] & 0xFFFF0000) |
+ (value >> 16);
+ location[1] = (location[1] & 0xFFFF0000) |
+ (value & 0xFFFF);
+#if __GNUC__ < 4
+ pr_debug("R_MICROBLAZE_64 (%08lx->%08lx)\n",
+ old_value, value);
+#endif
+ break;
+
+ case R_MICROBLAZE_64_PCREL:
+ locoffs = (location[0] & 0xFFFF) << 16 |
+ (location[1] & 0xFFFF);
+ value -= (unsigned long int)(location) + 4 +
+ locoffs;
+ location[0] = (location[0] & 0xFFFF0000) |
+ (value >> 16);
+ location[1] = (location[1] & 0xFFFF0000) |
+ (value & 0xFFFF);
+ pr_debug("R_MICROBLAZE_64_PCREL (%08lx)\n",
+ value);
+ break;
+
+ case R_MICROBLAZE_NONE:
+ pr_debug("R_MICROBLAZE_NONE\n");
+ break;
+
+ default:
+ printk(KERN_ERR "module %s: "
+ "Unknown relocation: %u\n",
+ module->name,
+ ELF32_R_TYPE(rela->r_info));
+ return -ENOEXEC;
+ }
+ }
+ 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.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/cache.h | 43 +++++
arch/microblaze/include/asm/cacheflush.h | 85 ++++++++++
arch/microblaze/kernel/cpu/cache.c | 258 ++++++++++++++++++++++++++++++
3 files changed, 386 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/cache.h
create mode 100644 arch/microblaze/include/asm/cacheflush.h
create mode 100644 arch/microblaze/kernel/cpu/cache.c
diff --git a/arch/microblaze/include/asm/cache.h b/arch/microblaze/include/asm/cache.h
new file mode 100644
index 0000000..16a647d
--- /dev/null
+++ b/arch/microblaze/include/asm/cache.h
@@ -0,0 +1,43 @@
+/*
+ * Cache operations
+ *
+ * Copyright (C) 2007 Michal Simek <[email protected]>
+ * Copyright (C) 2003 John Williams <[email protected]>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_CACHE_H
+#define _ASM_MICROBLAZE_CACHE_H
+
+#include <asm/registers.h>
+
+#ifndef L1_CACHE_BYTES
+/* word-granular cache in microblaze */
+#define L1_CACHE_BYTES 4
+#endif
+
+void _enable_icache(void);
+void _disable_icache(void);
+void _invalidate_icache(unsigned int addr);
+
+#define __enable_icache() _enable_icache()
+#define __disable_icache() _disable_icache()
+#define __invalidate_icache(addr) _invalidate_icache(addr)
+
+void _enable_dcache(void);
+void _disable_dcache(void);
+void _invalidate_dcache(unsigned int addr);
+
+#define __enable_dcache() _enable_dcache()
+#define __disable_dcache() _disable_dcache()
+#define __invalidate_dcache(addr) _invalidate_dcache(addr)
+
+/* FIXME - I don't think this is right */
+#ifdef CONFIG_XILINX_UNCACHED_SHADOW
+#define UNCACHED_SHADOW_MASK (CONFIG_XILINX_ERAM_SIZE)
+#endif
+
+#endif /* _ASM_MICROBLAZE_CACHE_H */
diff --git a/arch/microblaze/include/asm/cacheflush.h b/arch/microblaze/include/asm/cacheflush.h
new file mode 100644
index 0000000..3300b78
--- /dev/null
+++ b/arch/microblaze/include/asm/cacheflush.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2007 PetaLogix
+ * Copyright (C) 2007 John Williams <[email protected]>
+ * based on v850 version which was
+ * Copyright (C) 2001,02,03 NEC Electronics Corporation
+ * Copyright (C) 2001,02,03 Miles Bader <[email protected]>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ */
+
+#ifndef _ASM_MICROBLAZE_CACHEFLUSH_H
+#define _ASM_MICROBLAZE_CACHEFLUSH_H
+
+/* Somebody depends on this; sigh... */
+#include <linux/mm.h>
+
+/*
+ * Cache handling functions.
+ * Microblaze has a write-through data cache, meaning that the data cache
+ * never needs to be flushed. The only flushing operations that are
+ * implemented are to invalidate the instruction cache. These are called
+ * after loading a user application into memory, we must invalidate the
+ * instruction cache to make sure we don't fetch old, bad code.
+ */
+
+/* FIXME for LL-temac driver */
+#define invalidate_dcache_range(start, end) \
+ __invalidate_dcache_range(start, end)
+
+#define flush_cache_all() __invalidate_cache_all()
+#define flush_cache_mm(mm) do { } while (0)
+#define flush_cache_range(vma, start, end) __invalidate_cache_all()
+#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
+
+#define flush_dcache_range(start, end) __invalidate_dcache_range(start, end)
+#define flush_dcache_page(page) do { } while (0)
+#define flush_dcache_mmap_lock(mapping) do { } while (0)
+#define flush_dcache_mmap_unlock(mapping) do { } while (0)
+
+#define flush_icache_range(start, len) __invalidate_icache_range(start, len)
+#define flush_icache_page(vma, pg) do { } while (0)
+
+#define flush_cache_vmap(start, end) do { } while (0)
+#define flush_cache_vunmap(start, end) do { } while (0)
+
+struct page;
+struct mm_struct;
+struct vm_area_struct;
+
+/* see arch/microblaze/kernel/cache.c */
+extern void __invalidate_icache_all(void);
+extern void __invalidate_icache_range(unsigned long start, unsigned long end);
+extern void __invalidate_icache_page(struct vm_area_struct *vma,
+ struct page *page);
+extern void __invalidate_icache_user_range(struct vm_area_struct *vma,
+ struct page *page,
+ unsigned long adr, int len);
+extern void __invalidate_cache_sigtramp(unsigned long addr);
+
+extern void __invalidate_dcache_all(void);
+extern void __invalidate_dcache_range(unsigned long start, unsigned long end);
+extern void __invalidate_dcache_page(struct vm_area_struct *vma,
+ struct page *page);
+extern void __invalidate_dcache_user_range(struct vm_area_struct *vma,
+ struct page *page,
+ unsigned long adr, int len);
+
+extern inline void __invalidate_cache_all(void)
+{
+ __invalidate_icache_all();
+ __invalidate_dcache_all();
+}
+
+#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
+do { memcpy((dst), (src), (len)); \
+ flush_icache_range((unsigned) (dst), (unsigned) (dst) + (len)); \
+} while (0)
+
+#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
+ memcpy((dst), (src), (len))
+
+#endif /* _ASM_MICROBLAZE_CACHEFLUSH_H */
diff --git a/arch/microblaze/kernel/cpu/cache.c b/arch/microblaze/kernel/cpu/cache.c
new file mode 100644
index 0000000..252195a
--- /dev/null
+++ b/arch/microblaze/kernel/cpu/cache.c
@@ -0,0 +1,258 @@
+/*
+ * Cache control for MicroBlaze cache memories
+ *
+ * Copyright (C) 2007 Michal Simek <[email protected]>
+ * Copyright (C) 2007 PetaLogix
+ * Copyright (C) 2007 John Williams <[email protected]>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
+ */
+
+#include <asm/cacheflush.h>
+#include <linux/cache.h>
+#include <asm/cpuinfo.h>
+
+/* Exported functions */
+
+void _enable_icache(void)
+{
+ if (cpuinfo.use_icache) {
+#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
+ __asm__ __volatile__ (" \
+ msrset r0, %0; \
+ nop; " \
+ : \
+ : "i" (MSR_ICE) \
+ : "memory");
+#else
+ __asm__ __volatile__ (" \
+ mfs r12, rmsr; \
+ nop; \
+ ori r12, r12, %0; \
+ mts rmsr, r12; \
+ nop; " \
+ : \
+ : "i" (MSR_ICE) \
+ : "memory", "r12");
+#endif
+ }
+}
+
+void _disable_icache(void)
+{
+ if (cpuinfo.use_icache) {
+#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
+ __asm__ __volatile__ (" \
+ msrclr r0, %0; \
+ nop; " \
+ : \
+ : "i" (MSR_ICE) \
+ : "memory");
+#else
+ __asm__ __volatile__ (" \
+ mfs r12, rmsr; \
+ nop; \
+ andi r12, r12, ~%0; \
+ mts rmsr, r12; \
+ nop; " \
+ : \
+ : "i" (MSR_ICE) \
+ : "memory", "r12");
+#endif
+ }
+}
+
+void _invalidate_icache(unsigned int addr)
+{
+ if (cpuinfo.use_icache) {
+ __asm__ __volatile__ (" \
+ wic %0, r0" \
+ : \
+ : "r" (addr));
+ }
+}
+
+void _enable_dcache(void)
+{
+ if (cpuinfo.use_dcache) {
+#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
+ __asm__ __volatile__ (" \
+ msrset r0, %0; \
+ nop; " \
+ : \
+ : "i" (MSR_DCE) \
+ : "memory");
+#else
+ __asm__ __volatile__ (" \
+ mfs r12, rmsr; \
+ nop; \
+ ori r12, r12, %0; \
+ mts rmsr, r12; \
+ nop; " \
+ : \
+ : "i" (MSR_DCE) \
+ : "memory", "r12");
+#endif
+ }
+}
+
+void _disable_dcache(void)
+{
+ if (cpuinfo.use_dcache) {
+#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
+ __asm__ __volatile__ (" \
+ msrclr r0, %0; \
+ nop; " \
+ : \
+ : "i" (MSR_DCE) \
+ : "memory");
+#else
+ __asm__ __volatile__ (" \
+ mfs r12, rmsr; \
+ nop; \
+ andi r12, r12, ~%0; \
+ mts rmsr, r12; \
+ nop; " \
+ : \
+ : "i" (MSR_DCE) \
+ : "memory", "r12");
+#endif
+ }
+}
+
+void _invalidate_dcache(unsigned int addr)
+{
+ if (cpuinfo.use_dcache)
+ __asm__ __volatile__ (" \
+ wdc %0, r0" \
+ : \
+ : "r" (addr));
+}
+
+void __invalidate_icache_all(void)
+{
+ unsigned int i;
+ unsigned flags;
+
+ if (cpuinfo.use_icache) {
+ local_irq_save(flags);
+ __disable_icache();
+
+ /* Just loop through cache size and invalidate, no need to add
+ CACHE_BASE address */
+ for (i = 0; i < cpuinfo.icache_size;
+ i += cpuinfo.icache_line)
+ __invalidate_icache(i);
+
+ __enable_icache();
+ local_irq_restore(flags);
+ }
+}
+
+void __invalidate_icache_range(unsigned long start, unsigned long end)
+{
+ unsigned int i;
+ unsigned flags;
+ unsigned int align;
+
+ if (cpuinfo.use_icache) {
+ /*
+ * No need to cover entire cache range,
+ * just cover cache footprint
+ */
+ end = min(start + cpuinfo.icache_size, end);
+ align = ~(cpuinfo.icache_line - 1);
+ start &= align; /* Make sure we are aligned */
+ /* Push end up to the next cache line */
+ end = ((end & align) + cpuinfo.icache_line);
+
+ local_irq_save(flags);
+ __disable_icache();
+
+ for (i = start; i < end; i += cpuinfo.icache_line)
+ __invalidate_icache(i);
+
+ __enable_icache();
+ local_irq_restore(flags);
+ }
+}
+
+void __invalidate_icache_page(struct vm_area_struct *vma, struct page *page)
+{
+ __invalidate_icache_all();
+}
+
+void __invalidate_icache_user_range(struct vm_area_struct *vma,
+ struct page *page, unsigned long adr,
+ int len)
+{
+ __invalidate_icache_all();
+}
+
+void __invalidate_cache_sigtramp(unsigned long addr)
+{
+ __invalidate_icache_range(addr, addr + 8);
+}
+
+void __invalidate_dcache_all(void)
+{
+ unsigned int i;
+ unsigned flags;
+
+ if (cpuinfo.use_dcache) {
+ local_irq_save(flags);
+ __disable_dcache();
+
+ /*
+ * Just loop through cache size and invalidate,
+ * no need to add CACHE_BASE address
+ */
+ for (i = 0; i < cpuinfo.dcache_size;
+ i += cpuinfo.dcache_line)
+ __invalidate_dcache(i);
+
+ __enable_dcache();
+ local_irq_restore(flags);
+ }
+}
+
+void __invalidate_dcache_range(unsigned long start, unsigned long end)
+{
+ unsigned int i;
+ unsigned flags;
+ unsigned int align;
+
+ if (cpuinfo.use_dcache) {
+ /*
+ * No need to cover entire cache range,
+ * just cover cache footprint
+ */
+ end = min(start + cpuinfo.dcache_size, end);
+ align = ~(cpuinfo.dcache_line - 1);
+ start &= align; /* Make sure we are aligned */
+ /* Push end up to the next cache line */
+ end = ((end & align) + cpuinfo.dcache_line);
+ local_irq_save(flags);
+ __disable_dcache();
+
+ for (i = start; i < end; i += cpuinfo.dcache_line)
+ __invalidate_dcache(i);
+
+ __enable_dcache();
+ local_irq_restore(flags);
+ }
+}
+
+void __invalidate_dcache_page(struct vm_area_struct *vma, struct page *page)
+{
+ __invalidate_dcache_all();
+}
+
+void __invalidate_dcache_user_range(struct vm_area_struct *vma,
+ struct page *page, unsigned long adr,
+ int len)
+{
+ __invalidate_dcache_all();
+}
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/lmb.h | 17 +++++++++++++++++
1 files changed, 17 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/lmb.h
diff --git a/arch/microblaze/include/asm/lmb.h b/arch/microblaze/include/asm/lmb.h
new file mode 100644
index 0000000..a0a0a92
--- /dev/null
+++ b/arch/microblaze/include/asm/lmb.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2008 Michal Simek <[email protected]>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_LMB_H
+#define _ASM_MICROBLAZE_LMB_H
+
+/* LMB limit is OFF */
+#define LMB_REAL_LIMIT 0xFFFFFFFF
+
+#endif /* _ASM_MICROBLAZE_LMB_H */
+
+
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/platform/generic/system.dts | 332 +++++++++++++++++++++++++++
1 files changed, 332 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/platform/generic/system.dts
diff --git a/arch/microblaze/platform/generic/system.dts b/arch/microblaze/platform/generic/system.dts
new file mode 100644
index 0000000..29993f6
--- /dev/null
+++ b/arch/microblaze/platform/generic/system.dts
@@ -0,0 +1,332 @@
+/*
+ * Device Tree Generator version: 1.1
+ *
+ * (C) Copyright 2007-2008 Xilinx, Inc.
+ * (C) Copyright 2007-2009 Michal Simek
+ *
+ * Michal SIMEK <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * CAUTION: This file is automatically generated by libgen.
+ * Version: Xilinx EDK 10.1.03 EDK_K_SP3.6
+ *
+ * XPS project directory: Xilinx-ML505-ll_temac-sgdma-MMU-FDT-edk101
+ */
+
+/dts-v1/;
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "xlnx,microblaze";
+ model = "testing";
+ DDR2_SDRAM: memory@90000000 {
+ device_type = "memory";
+ reg = < 0x90000000 0x10000000 >;
+ } ;
+ chosen {
+ bootargs = "console=ttyUL0,115200 highres=on";
+ linux,stdout-path = "/plb@0/serial@84000000";
+ } ;
+ cpus {
+ #address-cells = <1>;
+ #cpus = <0x1>;
+ #size-cells = <0>;
+ microblaze_0: cpu@0 {
+ clock-frequency = <125000000>;
+ compatible = "xlnx,microblaze-7.10.d";
+ d-cache-baseaddr = <0x90000000>;
+ d-cache-highaddr = <0x9fffffff>;
+ d-cache-line-size = <0x10>;
+ d-cache-size = <0x2000>;
+ device_type = "cpu";
+ i-cache-baseaddr = <0x90000000>;
+ i-cache-highaddr = <0x9fffffff>;
+ i-cache-line-size = <0x10>;
+ i-cache-size = <0x2000>;
+ model = "microblaze,7.10.d";
+ reg = <0>;
+ timebase-frequency = <125000000>;
+ xlnx,addr-tag-bits = <0xf>;
+ xlnx,allow-dcache-wr = <0x1>;
+ xlnx,allow-icache-wr = <0x1>;
+ xlnx,area-optimized = <0x0>;
+ xlnx,cache-byte-size = <0x2000>;
+ xlnx,d-lmb = <0x1>;
+ xlnx,d-opb = <0x0>;
+ xlnx,d-plb = <0x1>;
+ xlnx,data-size = <0x20>;
+ xlnx,dcache-addr-tag = <0xf>;
+ xlnx,dcache-always-used = <0x1>;
+ xlnx,dcache-byte-size = <0x2000>;
+ xlnx,dcache-line-len = <0x4>;
+ xlnx,dcache-use-fsl = <0x1>;
+ xlnx,debug-enabled = <0x1>;
+ xlnx,div-zero-exception = <0x1>;
+ xlnx,dopb-bus-exception = <0x0>;
+ xlnx,dynamic-bus-sizing = <0x1>;
+ xlnx,edge-is-positive = <0x1>;
+ xlnx,family = "virtex5";
+ xlnx,fpu-exception = <0x1>;
+ xlnx,fsl-data-size = <0x20>;
+ xlnx,fsl-exception = <0x0>;
+ xlnx,fsl-links = <0x0>;
+ xlnx,i-lmb = <0x1>;
+ xlnx,i-opb = <0x0>;
+ xlnx,i-plb = <0x1>;
+ xlnx,icache-always-used = <0x1>;
+ xlnx,icache-line-len = <0x4>;
+ xlnx,icache-use-fsl = <0x1>;
+ xlnx,ill-opcode-exception = <0x1>;
+ xlnx,instance = "microblaze_0";
+ xlnx,interconnect = <0x1>;
+ xlnx,interrupt-is-edge = <0x0>;
+ xlnx,iopb-bus-exception = <0x0>;
+ xlnx,mmu-dtlb-size = <0x4>;
+ xlnx,mmu-itlb-size = <0x2>;
+ xlnx,mmu-tlb-access = <0x3>;
+ xlnx,mmu-zones = <0x10>;
+ xlnx,number-of-pc-brk = <0x1>;
+ xlnx,number-of-rd-addr-brk = <0x0>;
+ xlnx,number-of-wr-addr-brk = <0x0>;
+ xlnx,opcode-0x0-illegal = <0x1>;
+ xlnx,pvr = <0x2>;
+ xlnx,pvr-user1 = <0x0>;
+ xlnx,pvr-user2 = <0x0>;
+ xlnx,reset-msr = <0x0>;
+ xlnx,sco = <0x0>;
+ xlnx,unaligned-exceptions = <0x1>;
+ xlnx,use-barrel = <0x1>;
+ xlnx,use-dcache = <0x1>;
+ xlnx,use-div = <0x1>;
+ xlnx,use-ext-brk = <0x1>;
+ xlnx,use-ext-nm-brk = <0x1>;
+ xlnx,use-extended-fsl-instr = <0x0>;
+ xlnx,use-fpu = <0x2>;
+ xlnx,use-hw-mul = <0x2>;
+ xlnx,use-icache = <0x1>;
+ xlnx,use-interrupt = <0x1>;
+ xlnx,use-mmu = <0x3>;
+ xlnx,use-msr-instr = <0x1>;
+ xlnx,use-pcmp-instr = <0x1>;
+ } ;
+ } ;
+ mb_plb: plb@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "xlnx,plb-v46-1.03.a", "simple-bus";
+ ranges ;
+ FLASH: flash@a0000000 {
+ bank-width = <2>;
+ compatible = "xlnx,xps-mch-emc-2.00.a", "cfi-flash";
+ reg = < 0xa0000000 0x2000000 >;
+ xlnx,family = "virtex5";
+ xlnx,include-datawidth-matching-0 = <0x1>;
+ xlnx,include-datawidth-matching-1 = <0x0>;
+ xlnx,include-datawidth-matching-2 = <0x0>;
+ xlnx,include-datawidth-matching-3 = <0x0>;
+ xlnx,include-negedge-ioregs = <0x0>;
+ xlnx,include-plb-ipif = <0x1>;
+ xlnx,include-wrbuf = <0x1>;
+ xlnx,max-mem-width = <0x10>;
+ xlnx,mch-native-dwidth = <0x20>;
+ xlnx,mch-plb-clk-period-ps = <0x1f40>;
+ xlnx,mch-splb-awidth = <0x20>;
+ xlnx,mch0-accessbuf-depth = <0x10>;
+ xlnx,mch0-protocol = <0x0>;
+ xlnx,mch0-rddatabuf-depth = <0x10>;
+ xlnx,mch1-accessbuf-depth = <0x10>;
+ xlnx,mch1-protocol = <0x0>;
+ xlnx,mch1-rddatabuf-depth = <0x10>;
+ xlnx,mch2-accessbuf-depth = <0x10>;
+ xlnx,mch2-protocol = <0x0>;
+ xlnx,mch2-rddatabuf-depth = <0x10>;
+ xlnx,mch3-accessbuf-depth = <0x10>;
+ xlnx,mch3-protocol = <0x0>;
+ xlnx,mch3-rddatabuf-depth = <0x10>;
+ xlnx,mem0-width = <0x10>;
+ xlnx,mem1-width = <0x20>;
+ xlnx,mem2-width = <0x20>;
+ xlnx,mem3-width = <0x20>;
+ xlnx,num-banks-mem = <0x1>;
+ xlnx,num-channels = <0x0>;
+ xlnx,priority-mode = <0x0>;
+ xlnx,synch-mem-0 = <0x0>;
+ xlnx,synch-mem-1 = <0x0>;
+ xlnx,synch-mem-2 = <0x0>;
+ xlnx,synch-mem-3 = <0x0>;
+ xlnx,synch-pipedelay-0 = <0x2>;
+ xlnx,synch-pipedelay-1 = <0x2>;
+ xlnx,synch-pipedelay-2 = <0x2>;
+ xlnx,synch-pipedelay-3 = <0x2>;
+ xlnx,tavdv-ps-mem-0 = <0x1adb0>;
+ xlnx,tavdv-ps-mem-1 = <0x3a98>;
+ xlnx,tavdv-ps-mem-2 = <0x3a98>;
+ xlnx,tavdv-ps-mem-3 = <0x3a98>;
+ xlnx,tcedv-ps-mem-0 = <0x1adb0>;
+ xlnx,tcedv-ps-mem-1 = <0x3a98>;
+ xlnx,tcedv-ps-mem-2 = <0x3a98>;
+ xlnx,tcedv-ps-mem-3 = <0x3a98>;
+ xlnx,thzce-ps-mem-0 = <0x88b8>;
+ xlnx,thzce-ps-mem-1 = <0x1b58>;
+ xlnx,thzce-ps-mem-2 = <0x1b58>;
+ xlnx,thzce-ps-mem-3 = <0x1b58>;
+ xlnx,thzoe-ps-mem-0 = <0x1b58>;
+ xlnx,thzoe-ps-mem-1 = <0x1b58>;
+ xlnx,thzoe-ps-mem-2 = <0x1b58>;
+ xlnx,thzoe-ps-mem-3 = <0x1b58>;
+ xlnx,tlzwe-ps-mem-0 = <0x88b8>;
+ xlnx,tlzwe-ps-mem-1 = <0x0>;
+ xlnx,tlzwe-ps-mem-2 = <0x0>;
+ xlnx,tlzwe-ps-mem-3 = <0x0>;
+ xlnx,twc-ps-mem-0 = <0x2af8>;
+ xlnx,twc-ps-mem-1 = <0x3a98>;
+ xlnx,twc-ps-mem-2 = <0x3a98>;
+ xlnx,twc-ps-mem-3 = <0x3a98>;
+ xlnx,twp-ps-mem-0 = <0x11170>;
+ xlnx,twp-ps-mem-1 = <0x2ee0>;
+ xlnx,twp-ps-mem-2 = <0x2ee0>;
+ xlnx,twp-ps-mem-3 = <0x2ee0>;
+ xlnx,xcl0-linesize = <0x4>;
+ xlnx,xcl0-writexfer = <0x1>;
+ xlnx,xcl1-linesize = <0x4>;
+ xlnx,xcl1-writexfer = <0x1>;
+ xlnx,xcl2-linesize = <0x4>;
+ xlnx,xcl2-writexfer = <0x1>;
+ xlnx,xcl3-linesize = <0x4>;
+ xlnx,xcl3-writexfer = <0x1>;
+ } ;
+ Hard_Ethernet_MAC: xps-ll-temac@81c00000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "xlnx,compound";
+ ethernet@81c00000 {
+ compatible = "xlnx,xps-ll-temac-1.01.b";
+ device_type = "network";
+ interrupt-parent = <&xps_intc_0>;
+ interrupts = < 5 2 >;
+ llink-connected = <&PIM3>;
+ local-mac-address = [ 02 00 00 00 00 00 ];
+ reg = < 0x81c00000 0x40 >;
+ xlnx,bus2core-clk-ratio = <0x1>;
+ xlnx,phy-type = <0x1>;
+ xlnx,phyaddr = <0x1>;
+ xlnx,rxcsum = <0x0>;
+ xlnx,rxfifo = <0x1000>;
+ xlnx,temac-type = <0x0>;
+ xlnx,txcsum = <0x0>;
+ xlnx,txfifo = <0x1000>;
+ } ;
+ } ;
+ IIC_EEPROM: i2c@81600000 {
+ compatible = "xlnx,xps-iic-2.00.a";
+ interrupt-parent = <&xps_intc_0>;
+ interrupts = < 6 2 >;
+ reg = < 0x81600000 0x10000 >;
+ xlnx,clk-freq = <0x7735940>;
+ xlnx,family = "virtex5";
+ xlnx,gpo-width = <0x1>;
+ xlnx,iic-freq = <0x186a0>;
+ xlnx,scl-inertial-delay = <0x0>;
+ xlnx,sda-inertial-delay = <0x0>;
+ xlnx,ten-bit-adr = <0x0>;
+ } ;
+ LEDs_8Bit: gpio@81400000 {
+ compatible = "xlnx,xps-gpio-1.00.a";
+ interrupt-parent = <&xps_intc_0>;
+ interrupts = < 7 2 >;
+ reg = < 0x81400000 0x10000 >;
+ xlnx,all-inputs = <0x0>;
+ xlnx,all-inputs-2 = <0x0>;
+ xlnx,dout-default = <0x0>;
+ xlnx,dout-default-2 = <0x0>;
+ xlnx,family = "virtex5";
+ xlnx,gpio-width = <0x8>;
+ xlnx,interrupt-present = <0x1>;
+ xlnx,is-bidir = <0x1>;
+ xlnx,is-bidir-2 = <0x1>;
+ xlnx,is-dual = <0x0>;
+ xlnx,tri-default = <0xffffffff>;
+ xlnx,tri-default-2 = <0xffffffff>;
+ } ;
+ RS232_Uart_1: serial@84000000 {
+ clock-frequency = <125000000>;
+ compatible = "xlnx,xps-uartlite-1.00.a";
+ current-speed = <115200>;
+ device_type = "serial";
+ interrupt-parent = <&xps_intc_0>;
+ interrupts = < 8 0 >;
+ port-number = <0>;
+ reg = < 0x84000000 0x10000 >;
+ xlnx,baudrate = <0x1c200>;
+ xlnx,data-bits = <0x8>;
+ xlnx,family = "virtex5";
+ xlnx,odd-parity = <0x0>;
+ xlnx,use-parity = <0x0>;
+ } ;
+ SysACE_CompactFlash: sysace@83600000 {
+ compatible = "xlnx,xps-sysace-1.00.a";
+ interrupt-parent = <&xps_intc_0>;
+ interrupts = < 4 2 >;
+ reg = < 0x83600000 0x10000 >;
+ xlnx,family = "virtex5";
+ xlnx,mem-width = <0x10>;
+ } ;
+ debug_module: debug@84400000 {
+ compatible = "xlnx,mdm-1.00.d";
+ reg = < 0x84400000 0x10000 >;
+ xlnx,family = "virtex5";
+ xlnx,interconnect = <0x1>;
+ xlnx,jtag-chain = <0x2>;
+ xlnx,mb-dbg-ports = <0x1>;
+ xlnx,uart-width = <0x8>;
+ xlnx,use-uart = <0x1>;
+ xlnx,write-fsl-ports = <0x0>;
+ } ;
+ mpmc@90000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "xlnx,mpmc-4.02.a";
+ PIM3: sdma@84600180 {
+ compatible = "xlnx,ll-dma-1.00.a";
+ interrupt-parent = <&xps_intc_0>;
+ interrupts = < 2 2 1 2 >;
+ reg = < 0x84600180 0x80 >;
+ } ;
+ } ;
+ xps_intc_0: interrupt-controller@81800000 {
+ #interrupt-cells = <0x2>;
+ compatible = "xlnx,xps-intc-1.00.a";
+ interrupt-controller ;
+ reg = < 0x81800000 0x10000 >;
+ xlnx,kind-of-intr = <0x100>;
+ xlnx,num-intr-inputs = <0x9>;
+ } ;
+ xps_timer_1: timer@83c00000 {
+ compatible = "xlnx,xps-timer-1.00.a";
+ interrupt-parent = <&xps_intc_0>;
+ interrupts = < 3 2 >;
+ reg = < 0x83c00000 0x10000 >;
+ xlnx,count-width = <0x20>;
+ xlnx,family = "virtex5";
+ xlnx,gen0-assert = <0x1>;
+ xlnx,gen1-assert = <0x1>;
+ xlnx,one-timer-only = <0x0>;
+ xlnx,trig0-assert = <0x1>;
+ xlnx,trig1-assert = <0x1>;
+ } ;
+ } ;
+} ;
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/pvr.h | 209 +++++++++++++++++++++++++++++++++++++
arch/microblaze/kernel/cpu/mb.c | 148 ++++++++++++++++++++++++++
arch/microblaze/kernel/cpu/pvr.c | 81 ++++++++++++++
3 files changed, 438 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/pvr.h
create mode 100644 arch/microblaze/kernel/cpu/mb.c
create mode 100644 arch/microblaze/kernel/cpu/pvr.c
diff --git a/arch/microblaze/include/asm/pvr.h b/arch/microblaze/include/asm/pvr.h
new file mode 100644
index 0000000..66f1b30
--- /dev/null
+++ b/arch/microblaze/include/asm/pvr.h
@@ -0,0 +1,209 @@
+/*
+ * Support for the MicroBlaze PVR (Processor Version Register)
+ *
+ * Copyright (C) 2009 Michal Simek <[email protected]>
+ * Copyright (C) 2007 John Williams <[email protected]>
+ * Copyright (C) 2007 - 2009 PetaLogix
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_PVR_H
+#define _ASM_MICROBLAZE_PVR_H
+
+#define PVR_MSR_BIT 0x400
+
+struct pvr_s {
+ unsigned pvr[16];
+};
+
+/* The following taken from Xilinx's standalone BSP pvr.h */
+
+/* Basic PVR mask */
+#define PVR0_PVR_FULL_MASK 0x80000000
+#define PVR0_USE_BARREL_MASK 0x40000000
+#define PVR0_USE_DIV_MASK 0x20000000
+#define PVR0_USE_HW_MUL_MASK 0x10000000
+#define PVR0_USE_FPU_MASK 0x08000000
+#define PVR0_USE_EXC_MASK 0x04000000
+#define PVR0_USE_ICACHE_MASK 0x02000000
+#define PVR0_USE_DCACHE_MASK 0x01000000
+#define PVR0_USE_MMU 0x00800000 /* new */
+#define PVR0_VERSION_MASK 0x0000FF00
+#define PVR0_USER1_MASK 0x000000FF
+
+/* User 2 PVR mask */
+#define PVR1_USER2_MASK 0xFFFFFFFF
+
+/* Configuration PVR masks */
+#define PVR2_D_OPB_MASK 0x80000000
+#define PVR2_D_LMB_MASK 0x40000000
+#define PVR2_I_OPB_MASK 0x20000000
+#define PVR2_I_LMB_MASK 0x10000000
+#define PVR2_INTERRUPT_IS_EDGE_MASK 0x08000000
+#define PVR2_EDGE_IS_POSITIVE_MASK 0x04000000
+#define PVR2_D_PLB_MASK 0x02000000 /* new */
+#define PVR2_I_PLB_MASK 0x01000000 /* new */
+#define PVR2_INTERCONNECT 0x00800000 /* new */
+#define PVR2_USE_EXTEND_FSL 0x00080000 /* new */
+#define PVR2_USE_FSL_EXC 0x00040000 /* new */
+#define PVR2_USE_MSR_INSTR 0x00020000
+#define PVR2_USE_PCMP_INSTR 0x00010000
+#define PVR2_AREA_OPTIMISED 0x00008000
+#define PVR2_USE_BARREL_MASK 0x00004000
+#define PVR2_USE_DIV_MASK 0x00002000
+#define PVR2_USE_HW_MUL_MASK 0x00001000
+#define PVR2_USE_FPU_MASK 0x00000800
+#define PVR2_USE_MUL64_MASK 0x00000400
+#define PVR2_USE_FPU2_MASK 0x00000200 /* new */
+#define PVR2_USE_IPLBEXC 0x00000100
+#define PVR2_USE_DPLBEXC 0x00000080
+#define PVR2_OPCODE_0x0_ILL_MASK 0x00000040
+#define PVR2_UNALIGNED_EXC_MASK 0x00000020
+#define PVR2_ILL_OPCODE_EXC_MASK 0x00000010
+#define PVR2_IOPB_BUS_EXC_MASK 0x00000008
+#define PVR2_DOPB_BUS_EXC_MASK 0x00000004
+#define PVR2_DIV_ZERO_EXC_MASK 0x00000002
+#define PVR2_FPU_EXC_MASK 0x00000001
+
+/* Debug and exception PVR masks */
+#define PVR3_DEBUG_ENABLED_MASK 0x80000000
+#define PVR3_NUMBER_OF_PC_BRK_MASK 0x1E000000
+#define PVR3_NUMBER_OF_RD_ADDR_BRK_MASK 0x00380000
+#define PVR3_NUMBER_OF_WR_ADDR_BRK_MASK 0x0000E000
+#define PVR3_FSL_LINKS_MASK 0x00000380
+
+/* ICache config PVR masks */
+#define PVR4_USE_ICACHE_MASK 0x80000000
+#define PVR4_ICACHE_ADDR_TAG_BITS_MASK 0x7C000000
+#define PVR4_ICACHE_USE_FSL_MASK 0x02000000
+#define PVR4_ICACHE_ALLOW_WR_MASK 0x01000000
+#define PVR4_ICACHE_LINE_LEN_MASK 0x00E00000
+#define PVR4_ICACHE_BYTE_SIZE_MASK 0x001F0000
+
+/* DCache config PVR masks */
+#define PVR5_USE_DCACHE_MASK 0x80000000
+#define PVR5_DCACHE_ADDR_TAG_BITS_MASK 0x7C000000
+#define PVR5_DCACHE_USE_FSL_MASK 0x02000000
+#define PVR5_DCACHE_ALLOW_WR_MASK 0x01000000
+#define PVR5_DCACHE_LINE_LEN_MASK 0x00E00000
+#define PVR5_DCACHE_BYTE_SIZE_MASK 0x001F0000
+
+/* ICache base address PVR mask */
+#define PVR6_ICACHE_BASEADDR_MASK 0xFFFFFFFF
+
+/* ICache high address PVR mask */
+#define PVR7_ICACHE_HIGHADDR_MASK 0xFFFFFFFF
+
+/* DCache base address PVR mask */
+#define PVR8_DCACHE_BASEADDR_MASK 0xFFFFFFFF
+
+/* DCache high address PVR mask */
+#define PVR9_DCACHE_HIGHADDR_MASK 0xFFFFFFFF
+
+/* Target family PVR mask */
+#define PVR10_TARGET_FAMILY_MASK 0xFF000000
+
+/* MMU descrtiption */
+#define PVR11_USE_MMU 0xC0000000
+#define PVR11_MMU_ITLB_SIZE 0x38000000
+#define PVR11_MMU_DTLB_SIZE 0x07000000
+#define PVR11_MMU_TLB_ACCESS 0x00C00000
+#define PVR11_MMU_ZONES 0x003C0000
+/* MSR Reset value PVR mask */
+#define PVR11_MSR_RESET_VALUE_MASK 0x000007FF
+
+
+/* PVR access macros */
+#define PVR_IS_FULL(pvr) (pvr.pvr[0] & PVR0_PVR_FULL_MASK)
+#define PVR_USE_BARREL(pvr) (pvr.pvr[0] & PVR0_USE_BARREL_MASK)
+#define PVR_USE_DIV(pvr) (pvr.pvr[0] & PVR0_USE_DIV_MASK)
+#define PVR_USE_HW_MUL(pvr) (pvr.pvr[0] & PVR0_USE_HW_MUL_MASK)
+#define PVR_USE_FPU(pvr) (pvr.pvr[0] & PVR0_USE_FPU_MASK)
+#define PVR_USE_FPU2(pvr) (pvr.pvr[2] & PVR2_USE_FPU2_MASK)
+#define PVR_USE_ICACHE(pvr) (pvr.pvr[0] & PVR0_USE_ICACHE_MASK)
+#define PVR_USE_DCACHE(pvr) (pvr.pvr[0] & PVR0_USE_DCACHE_MASK)
+#define PVR_VERSION(pvr) ((pvr.pvr[0] & PVR0_VERSION_MASK) >> 8)
+#define PVR_USER1(pvr) (pvr.pvr[0] & PVR0_USER1_MASK)
+#define PVR_USER2(pvr) (pvr.pvr[1] & PVR1_USER2_MASK)
+
+#define PVR_D_OPB(pvr) (pvr.pvr[2] & PVR2_D_OPB_MASK)
+#define PVR_D_LMB(pvr) (pvr.pvr[2] & PVR2_D_LMB_MASK)
+#define PVR_I_OPB(pvr) (pvr.pvr[2] & PVR2_I_OPB_MASK)
+#define PVR_I_LMB(pvr) (pvr.pvr[2] & PVR2_I_LMB_MASK)
+#define PVR_INTERRUPT_IS_EDGE(pvr) \
+ (pvr.pvr[2] & PVR2_INTERRUPT_IS_EDGE_MASK)
+#define PVR_EDGE_IS_POSITIVE(pvr) \
+ (pvr.pvr[2] & PVR2_EDGE_IS_POSITIVE_MASK)
+#define PVR_USE_MSR_INSTR(pvr) (pvr.pvr[2] & PVR2_USE_MSR_INSTR)
+#define PVR_USE_PCMP_INSTR(pvr) (pvr.pvr[2] & PVR2_USE_PCMP_INSTR)
+#define PVR_AREA_OPTIMISED(pvr) (pvr.pvr[2] & PVR2_AREA_OPTIMISED)
+#define PVR_USE_MUL64(pvr) (pvr.pvr[2] & PVR2_USE_MUL64_MASK)
+#define PVR_OPCODE_0x0_ILLEGAL(pvr) \
+ (pvr.pvr[2] & PVR2_OPCODE_0x0_ILL_MASK)
+#define PVR_UNALIGNED_EXCEPTION(pvr) \
+ (pvr.pvr[2] & PVR2_UNALIGNED_EXC_MASK)
+#define PVR_ILL_OPCODE_EXCEPTION(pvr) \
+ (pvr.pvr[2] & PVR2_ILL_OPCODE_EXC_MASK)
+#define PVR_IOPB_BUS_EXCEPTION(pvr) \
+ (pvr.pvr[2] & PVR2_IOPB_BUS_EXC_MASK)
+#define PVR_DOPB_BUS_EXCEPTION(pvr) \
+ (pvr.pvr[2] & PVR2_DOPB_BUS_EXC_MASK)
+#define PVR_DIV_ZERO_EXCEPTION(pvr) \
+ (pvr.pvr[2] & PVR2_DIV_ZERO_EXC_MASK)
+#define PVR_FPU_EXCEPTION(pvr) (pvr.pvr[2] & PVR2_FPU_EXC_MASK)
+#define PVR_FSL_EXCEPTION(pvr) (pvr.pvr[2] & PVR2_USE_EXTEND_FSL)
+
+#define PVR_DEBUG_ENABLED(pvr) (pvr.pvr[3] & PVR3_DEBUG_ENABLED_MASK)
+#define PVR_NUMBER_OF_PC_BRK(pvr) \
+ ((pvr.pvr[3] & PVR3_NUMBER_OF_PC_BRK_MASK) >> 25)
+#define PVR_NUMBER_OF_RD_ADDR_BRK(pvr) \
+ ((pvr.pvr[3] & PVR3_NUMBER_OF_RD_ADDR_BRK_MASK) >> 19)
+#define PVR_NUMBER_OF_WR_ADDR_BRK(pvr) \
+ ((pvr.pvr[3] & PVR3_NUMBER_OF_WR_ADDR_BRK_MASK) >> 13)
+#define PVR_FSL_LINKS(pvr) ((pvr.pvr[3] & PVR3_FSL_LINKS_MASK) >> 7)
+
+#define PVR_ICACHE_ADDR_TAG_BITS(pvr) \
+ ((pvr.pvr[4] & PVR4_ICACHE_ADDR_TAG_BITS_MASK) >> 26)
+#define PVR_ICACHE_USE_FSL(pvr) (pvr.pvr[4] & PVR4_ICACHE_USE_FSL_MASK)
+#define PVR_ICACHE_ALLOW_WR(pvr) (pvr.pvr[4] & PVR4_ICACHE_ALLOW_WR_MASK)
+#define PVR_ICACHE_LINE_LEN(pvr) \
+ (1 << ((pvr.pvr[4] & PVR4_ICACHE_LINE_LEN_MASK) >> 21))
+#define PVR_ICACHE_BYTE_SIZE(pvr) \
+ (1 << ((pvr.pvr[4] & PVR4_ICACHE_BYTE_SIZE_MASK) >> 16))
+
+#define PVR_DCACHE_ADDR_TAG_BITS(pvr) \
+ ((pvr.pvr[5] & PVR5_DCACHE_ADDR_TAG_BITS_MASK) >> 26)
+#define PVR_DCACHE_USE_FSL(pvr) (pvr.pvr[5] & PVR5_DCACHE_USE_FSL_MASK)
+#define PVR_DCACHE_ALLOW_WR(pvr) (pvr.pvr[5] & PVR5_DCACHE_ALLOW_WR_MASK)
+#define PVR_DCACHE_LINE_LEN(pvr) \
+ (1 << ((pvr.pvr[5] & PVR5_DCACHE_LINE_LEN_MASK) >> 21))
+#define PVR_DCACHE_BYTE_SIZE(pvr) \
+ (1 << ((pvr.pvr[5] & PVR5_DCACHE_BYTE_SIZE_MASK) >> 16))
+
+
+#define PVR_ICACHE_BASEADDR(pvr) (pvr.pvr[6] & PVR6_ICACHE_BASEADDR_MASK)
+#define PVR_ICACHE_HIGHADDR(pvr) (pvr.pvr[7] & PVR7_ICACHE_HIGHADDR_MASK)
+
+#define PVR_DCACHE_BASEADDR(pvr) (pvr.pvr[8] & PVR8_DCACHE_BASEADDR_MASK)
+#define PVR_DCACHE_HIGHADDR(pvr) (pvr.pvr[9] & PVR9_DCACHE_HIGHADDR_MASK)
+
+#define PVR_TARGET_FAMILY(pvr) ((pvr.pvr[10] & PVR10_TARGET_FAMILY_MASK) >> 24)
+
+#define PVR_MSR_RESET_VALUE(pvr) \
+ (pvr.pvr[11] & PVR11_MSR_RESET_VALUE_MASK)
+
+/* mmu */
+#define PVR_USE_MMU(pvr) ((pvr.pvr[11] & PVR11_USE_MMU) >> 30)
+#define PVR_MMU_ITLB_SIZE(pvr) (pvr.pvr[11] & PVR11_MMU_ITLB_SIZE)
+#define PVR_MMU_DTLB_SIZE(pvr) (pvr.pvr[11] & PVR11_MMU_DTLB_SIZE)
+#define PVR_MMU_TLB_ACCESS(pvr) (pvr.pvr[11] & PVR11_MMU_TLB_ACCESS)
+#define PVR_MMU_ZONES(pvr) (pvr.pvr[11] & PVR11_MMU_ZONES)
+
+
+int cpu_has_pvr(void);
+void get_pvr(struct pvr_s *pvr);
+
+#endif /* _ASM_MICROBLAZE_PVR_H */
diff --git a/arch/microblaze/kernel/cpu/mb.c b/arch/microblaze/kernel/cpu/mb.c
new file mode 100644
index 0000000..8c1b7ad
--- /dev/null
+++ b/arch/microblaze/kernel/cpu/mb.c
@@ -0,0 +1,148 @@
+/*
+ * CPU-version specific code
+ *
+ * Copyright (C) 2007 Michal Simek <[email protected]>
+ * Copyright (C) 2006 PetaLogix
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/seq_file.h>
+#include <linux/cpu.h>
+#include <linux/initrd.h>
+
+#include <linux/bug.h>
+#include <asm/cpuinfo.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <asm/page.h>
+#include <linux/param.h>
+#include <asm/pvr.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+ int count = 0;
+ char *fpga_family = "Unknown";
+ char *cpu_ver = "Unknown";
+ int i;
+
+ /* Denormalised to get the fpga family string */
+ for (i = 0; family_string_lookup[i].s != NULL; i++) {
+ if (cpuinfo.fpga_family_code == family_string_lookup[i].k) {
+ fpga_family = (char *)family_string_lookup[i].s;
+ break;
+ }
+ }
+
+ /* Denormalised to get the hw version string */
+ for (i = 0; cpu_ver_lookup[i].s != NULL; i++) {
+ if (cpuinfo.ver_code == cpu_ver_lookup[i].k) {
+ cpu_ver = (char *)cpu_ver_lookup[i].s;
+ break;
+ }
+ }
+
+ count = seq_printf(m,
+ "CPU-Family: MicroBlaze\n"
+ "FPGA-Arch: %s\n"
+ "CPU-Ver: %s\n"
+ "CPU-MHz: %d.%02d\n"
+ "BogoMips: %lu.%02lu\n",
+ fpga_family,
+ cpu_ver,
+ cpuinfo.cpu_clock_freq /
+ 1000000,
+ cpuinfo.cpu_clock_freq %
+ 1000000,
+ loops_per_jiffy / (500000 / HZ),
+ (loops_per_jiffy / (5000 / HZ)) % 100);
+
+ count += seq_printf(m,
+ "HW:\n Shift:\t\t%s\n"
+ " MSR:\t\t%s\n"
+ " PCMP:\t\t%s\n"
+ " DIV:\t\t%s\n",
+ (cpuinfo.use_instr & PVR0_USE_BARREL_MASK) ? "yes" : "no",
+ (cpuinfo.use_instr & PVR2_USE_MSR_INSTR) ? "yes" : "no",
+ (cpuinfo.use_instr & PVR2_USE_PCMP_INSTR) ? "yes" : "no",
+ (cpuinfo.use_instr & PVR0_USE_DIV_MASK) ? "yes" : "no");
+
+ count += seq_printf(m,
+ " MMU:\t\t%x\n",
+ cpuinfo.mmu);
+
+ count += seq_printf(m,
+ " MUL:\t\t%s\n"
+ " FPU:\t\t%s\n",
+ (cpuinfo.use_mult & PVR2_USE_MUL64_MASK) ? "v2" :
+ (cpuinfo.use_mult & PVR0_USE_HW_MUL_MASK) ? "v1" : "no",
+ (cpuinfo.use_fpu & PVR2_USE_FPU2_MASK) ? "v2" :
+ (cpuinfo.use_fpu & PVR0_USE_FPU_MASK) ? "v1" : "no");
+
+ count += seq_printf(m,
+ " Exc:\t\t%s%s%s%s%s%s%s%s\n",
+ (cpuinfo.use_exc & PVR2_OPCODE_0x0_ILL_MASK) ? "op0x0 " : "",
+ (cpuinfo.use_exc & PVR2_UNALIGNED_EXC_MASK) ? "unal " : "",
+ (cpuinfo.use_exc & PVR2_ILL_OPCODE_EXC_MASK) ? "ill " : "",
+ (cpuinfo.use_exc & PVR2_IOPB_BUS_EXC_MASK) ? "iopb " : "",
+ (cpuinfo.use_exc & PVR2_DOPB_BUS_EXC_MASK) ? "dopb " : "",
+ (cpuinfo.use_exc & PVR2_DIV_ZERO_EXC_MASK) ? "zero " : "",
+ (cpuinfo.use_exc & PVR2_FPU_EXC_MASK) ? "fpu " : "",
+ (cpuinfo.use_exc & PVR2_USE_FSL_EXC) ? "fsl " : "");
+
+ if (cpuinfo.use_icache)
+ count += seq_printf(m,
+ "Icache:\t\t%ukB\n",
+ cpuinfo.icache_size >> 10);
+ else
+ count += seq_printf(m, "Icache:\t\tno\n");
+
+ if (cpuinfo.use_dcache)
+ count += seq_printf(m,
+ "Dcache:\t\t%ukB\n",
+ cpuinfo.dcache_size >> 10);
+ else
+ count += seq_printf(m, "Dcache:\t\tno\n");
+
+ count += seq_printf(m,
+ "HW-Debug:\t%s\n",
+ cpuinfo.hw_debug ? "yes" : "no");
+
+ count += seq_printf(m,
+ "PVR-USR1:\t%x\n"
+ "PVR-USR2:\t%x\n",
+ cpuinfo.pvr_user1,
+ cpuinfo.pvr_user2);
+
+ return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+ int i = *pos;
+
+ return i < NR_CPUS ? (void *) (i + 1) : NULL;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ ++*pos;
+ return c_start(m, pos);
+}
+
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+
+const struct seq_operations cpuinfo_op = {
+ .start = c_start,
+ .next = c_next,
+ .stop = c_stop,
+ .show = show_cpuinfo,
+};
diff --git a/arch/microblaze/kernel/cpu/pvr.c b/arch/microblaze/kernel/cpu/pvr.c
new file mode 100644
index 0000000..88b3ad7
--- /dev/null
+++ b/arch/microblaze/kernel/cpu/pvr.c
@@ -0,0 +1,81 @@
+/*
+ * Support for MicroBlaze PVR (processor version register)
+ *
+ * Copyright (C) 2007 Michal Simek <[email protected]>
+ * Copyright (C) 2007 John Williams <[email protected]>
+ * Copyright (C) 2007 PetaLogix
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/compiler.h>
+#include <asm/system.h>
+#include <asm/exceptions.h>
+#include <asm/pvr.h>
+
+/*
+ * Until we get an assembler that knows about the pvr registers,
+ * this horrible cruft will have to do.
+ * That hardcoded opcode is mfs r3, rpvrNN
+ */
+
+#define get_single_pvr(pvrid, val) \
+{ \
+ register unsigned tmp __asm__("r3"); \
+ tmp = 0x0; /* Prevent warning about unused */ \
+ __asm__ __volatile__ ( \
+ ".byte 0x94,0x60,0xa0, " #pvrid "\n\t" \
+ : "=r" (tmp) : : "memory"); \
+ val = tmp; \
+}
+
+/*
+ * Does the CPU support the PVR register?
+ * return value:
+ * 0: no PVR
+ * 1: simple PVR
+ * 2: full PVR
+ *
+ * This must work on all CPU versions, including those before the
+ * PVR was even an option.
+ */
+
+int cpu_has_pvr(void)
+{
+ unsigned flags;
+ unsigned pvr0;
+
+ local_save_flags(flags);
+
+ /* PVR bit in MSR tells us if there is any support */
+ if (!(flags & PVR_MSR_BIT))
+ return 0;
+
+ get_single_pvr(0x00, pvr0);
+ pr_debug("%s: pvr0 is 0x%08x\n", __func__, pvr0);
+
+ if (pvr0 & PVR0_PVR_FULL_MASK)
+ return 1;
+
+ /* for partial PVR use static cpuinfo */
+ return 2;
+}
+
+void get_pvr(struct pvr_s *p)
+{
+ get_single_pvr(0, p->pvr[0]);
+ get_single_pvr(1, p->pvr[1]);
+ get_single_pvr(2, p->pvr[2]);
+ get_single_pvr(3, p->pvr[3]);
+ get_single_pvr(4, p->pvr[4]);
+ get_single_pvr(5, p->pvr[5]);
+ get_single_pvr(6, p->pvr[6]);
+ get_single_pvr(7, p->pvr[7]);
+ get_single_pvr(8, p->pvr[8]);
+ get_single_pvr(9, p->pvr[9]);
+ get_single_pvr(10, p->pvr[10]);
+ get_single_pvr(11, p->pvr[11]);
+}
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/signal.h | 165 +++++++++++
arch/microblaze/kernel/signal.c | 536 ++++++++++++++++++++++++++++++++++
2 files changed, 701 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/signal.h
create mode 100644 arch/microblaze/kernel/signal.c
diff --git a/arch/microblaze/include/asm/signal.h b/arch/microblaze/include/asm/signal.h
new file mode 100644
index 0000000..9676fad
--- /dev/null
+++ b/arch/microblaze/include/asm/signal.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ * Yasushi SHOJI <[email protected]>
+ * Tetsuya OHKAWA <[email protected]>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_SIGNAL_H
+#define _ASM_MICROBLAZE_SIGNAL_H
+
+#define SIGHUP 1
+#define SIGINT 2
+#define SIGQUIT 3
+#define SIGILL 4
+#define SIGTRAP 5
+#define SIGABRT 6
+#define SIGIOT 6
+#define SIGBUS 7
+#define SIGFPE 8
+#define SIGKILL 9
+#define SIGUSR1 10
+#define SIGSEGV 11
+#define SIGUSR2 12
+#define SIGPIPE 13
+#define SIGALRM 14
+#define SIGTERM 15
+#define SIGSTKFLT 16
+#define SIGCHLD 17
+#define SIGCONT 18
+#define SIGSTOP 19
+#define SIGTSTP 20
+#define SIGTTIN 21
+#define SIGTTOU 22
+#define SIGURG 23
+#define SIGXCPU 24
+#define SIGXFSZ 25
+#define SIGVTALRM 26
+#define SIGPROF 27
+#define SIGWINCH 28
+#define SIGIO 29
+#define SIGPOLL SIGIO
+/*
+#define SIGLOST 29
+*/
+#define SIGPWR 30
+#define SIGSYS 31
+#define SIGUNUSED 31
+
+/* These should not be considered constants from userland. */
+#define SIGRTMIN 32
+#define SIGRTMAX _NSIG
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_NOCLDSTOP 0x00000001
+#define SA_NOCLDWAIT 0x00000002
+#define SA_SIGINFO 0x00000004
+#define SA_ONSTACK 0x08000000
+#define SA_RESTART 0x10000000
+#define SA_NODEFER 0x40000000
+#define SA_RESETHAND 0x80000000
+
+#define SA_NOMASK SA_NODEFER
+#define SA_ONESHOT SA_RESETHAND
+
+#define SA_RESTORER 0x04000000
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK 1
+#define SS_DISABLE 2
+
+#define MINSIGSTKSZ 2048
+#define SIGSTKSZ 8192
+
+# ifndef __ASSEMBLY__
+# include <linux/types.h>
+# include <asm-generic/signal.h>
+
+/* Avoid too many header ordering problems. */
+struct siginfo;
+
+# ifdef __KERNEL__
+/*
+ * Most things should be clean enough to redefine this at will, if care
+ * is taken to make libc match.
+ */
+# define _NSIG 64
+# define _NSIG_BPW 32
+# define _NSIG_WORDS (_NSIG / _NSIG_BPW)
+
+typedef unsigned long old_sigset_t; /* at least 32 bits */
+
+typedef struct {
+ unsigned long sig[_NSIG_WORDS];
+} sigset_t;
+
+struct old_sigaction {
+ __sighandler_t sa_handler;
+ old_sigset_t sa_mask;
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+};
+
+struct sigaction {
+ __sighandler_t sa_handler;
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+ sigset_t sa_mask; /* mask last for extensibility */
+};
+
+struct k_sigaction {
+ struct sigaction sa;
+};
+
+# include <asm/sigcontext.h>
+# undef __HAVE_ARCH_SIG_BITOPS
+
+# define ptrace_signal_deliver(regs, cookie) do { } while (0)
+
+# else /* !__KERNEL__ */
+
+/* Here we must cater to libcs that poke about in kernel headers. */
+
+# define NSIG 32
+typedef unsigned long sigset_t;
+
+struct sigaction {
+ union {
+ __sighandler_t _sa_handler;
+ void (*_sa_sigaction)(int, struct siginfo *, void *);
+ } _u;
+ sigset_t sa_mask;
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+};
+
+# define sa_handler _u._sa_handler
+# define sa_sigaction _u._sa_sigaction
+
+# endif /* __KERNEL__ */
+
+typedef struct sigaltstack {
+ void *ss_sp;
+ int ss_flags;
+ size_t ss_size;
+} stack_t;
+
+# endif /* __ASSEMBLY__ */
+#endif /* _ASM_MICROBLAZE_SIGNAL_H */
diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c
new file mode 100644
index 0000000..8f82e23
--- /dev/null
+++ b/arch/microblaze/kernel/signal.c
@@ -0,0 +1,536 @@
+/*
+ * Signal handling
+ *
+ * Copyright (C) 2003,2004 John Williams <[email protected]>
+ * Copyright (C) 2001 NEC Corporation
+ * Copyright (C) 2001 Miles Bader <[email protected]>
+ * Copyright (C) 1999,2000 Niibe Yutaka & Kaz Kojima
+ * Copyright (C) 1991,1992 Linus Torvalds
+ *
+ * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
+ *
+ * This file was was derived from the sh version, arch/sh/kernel/signal.c
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/stddef.h>
+#include <linux/personality.h>
+#include <linux/percpu.h>
+#include <linux/linkage.h>
+#include <asm/entry.h>
+#include <asm/ucontext.h>
+#include <linux/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <linux/signal.h>
+#include <linux/syscalls.h>
+#include <asm/cacheflush.h>
+#include <asm/syscalls.h>
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall);
+
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+asmlinkage int
+sys_sigsuspend(old_sigset_t mask, struct pt_regs *regs)
+{
+ sigset_t saveset;
+
+ mask &= _BLOCKABLE;
+ spin_lock_irq(¤t->sighand->siglock);
+ saveset = current->blocked;
+ siginitset(¤t->blocked, mask);
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+
+ regs->r3 = -EINTR;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal(regs, &saveset, 1))
+ return -EINTR;
+ }
+}
+
+asmlinkage int
+sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize,
+ struct pt_regs *regs)
+{
+ sigset_t saveset, newset;
+
+ /* XXX: Don't preclude handling different sized sigset_t's. */
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+
+ if (copy_from_user(&newset, unewset, sizeof(newset)))
+ return -EFAULT;
+ sigdelsetmask(&newset, ~_BLOCKABLE);
+ spin_lock_irq(¤t->sighand->siglock);
+ saveset = current->blocked;
+ current->blocked = newset;
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+
+ regs->r3 = -EINTR;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal(regs, &saveset, 1))
+ return -EINTR;
+ }
+}
+
+asmlinkage int
+sys_sigaction(int sig, const struct old_sigaction *act,
+ struct old_sigaction *oact)
+{
+ struct k_sigaction new_ka, old_ka;
+ int ret;
+
+ if (act) {
+ old_sigset_t mask;
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
+ __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
+ __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
+ return -EFAULT;
+ __get_user(new_ka.sa.sa_flags, &act->sa_flags);
+ __get_user(mask, &act->sa_mask);
+ siginitset(&new_ka.sa.sa_mask, mask);
+ }
+
+ ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+ if (!ret && oact) {
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+ __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+ return -EFAULT;
+ __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+ __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+ }
+
+ return ret;
+}
+
+asmlinkage int
+sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
+ struct pt_regs *regs)
+{
+ return do_sigaltstack(uss, uoss, regs->r1);
+}
+
+/*
+ * Do a signal return; undo the signal stack.
+ */
+
+struct sigframe {
+ struct sigcontext sc;
+ unsigned long extramask[_NSIG_WORDS-1];
+ unsigned long tramp[2]; /* signal trampoline */
+};
+
+struct rt_sigframe {
+ struct siginfo info;
+ struct ucontext uc;
+ unsigned long tramp[2]; /* signal trampoline */
+};
+
+static int
+restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *rval_p)
+{
+ unsigned int err = 0;
+
+#define COPY(x) {err |= __get_user(regs->x, &sc->regs.x);}
+ COPY(r0);
+ COPY(r1);
+ COPY(r2); COPY(r3); COPY(r4); COPY(r5);
+ COPY(r6); COPY(r7); COPY(r8); COPY(r9);
+ COPY(r10); COPY(r11); COPY(r12); COPY(r13);
+ COPY(r14); COPY(r15); COPY(r16); COPY(r17);
+ COPY(r18); COPY(r19); COPY(r20); COPY(r21);
+ COPY(r22); COPY(r23); COPY(r24); COPY(r25);
+ COPY(r26); COPY(r27); COPY(r28); COPY(r29);
+ COPY(r30); COPY(r31);
+ COPY(pc); COPY(ear); COPY(esr); COPY(fsr);
+#undef COPY
+
+ *rval_p = regs->r3;
+
+ return err;
+}
+
+asmlinkage int sys_sigreturn(struct pt_regs *regs)
+{
+ struct sigframe *frame = (struct sigframe *)regs->r1;
+ sigset_t set;
+ int rval;
+
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+
+ if (__get_user(set.sig[0], &frame->sc.oldmask)
+ || (_NSIG_WORDS > 1
+ && __copy_from_user(&set.sig[1], &frame->extramask,
+ sizeof(frame->extramask))))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+
+ spin_lock_irq(¤t->sighand->siglock);
+ current->blocked = set;
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+
+ if (restore_sigcontext(regs, &frame->sc, &rval))
+ goto badframe;
+ return rval;
+
+badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+}
+
+asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
+{
+ struct rt_sigframe *frame = (struct rt_sigframe *)regs->r1;
+ sigset_t set;
+ stack_t st;
+ int rval;
+
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+
+ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(¤t->sighand->siglock);
+ current->blocked = set;
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+
+ if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval))
+ goto badframe;
+
+ if (__copy_from_user((void *)&st, &frame->uc.uc_stack, sizeof(st)))
+ goto badframe;
+ /* It is more difficult to avoid calling this function than to
+ call it and ignore errors. */
+ do_sigaltstack(&st, NULL, regs->r1);
+
+ return rval;
+
+badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+}
+
+/*
+ * Set up a signal frame.
+ */
+
+static int
+setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
+ unsigned long mask)
+{
+ int err = 0;
+
+#define COPY(x) {err |= __put_user(regs->x, &sc->regs.x);}
+ COPY(r0);
+ COPY(r1);
+ COPY(r2); COPY(r3); COPY(r4); COPY(r5);
+ COPY(r6); COPY(r7); COPY(r8); COPY(r9);
+ COPY(r10); COPY(r11); COPY(r12); COPY(r13);
+ COPY(r14); COPY(r15); COPY(r16); COPY(r17);
+ COPY(r18); COPY(r19); COPY(r20); COPY(r21);
+ COPY(r22); COPY(r23); COPY(r24); COPY(r25);
+ COPY(r26); COPY(r27); COPY(r28); COPY(r29);
+ COPY(r30); COPY(r31);
+ COPY(pc); COPY(ear); COPY(esr); COPY(fsr);
+#undef COPY
+
+ err |= __put_user(mask, &sc->oldmask);
+
+ return err;
+}
+
+/*
+ * Determine which stack to use..
+ */
+static inline void *
+get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
+{
+ /* Default to using normal stack */
+ unsigned long sp = regs->r1;
+
+ if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && !on_sig_stack(sp))
+ sp = current->sas_ss_sp + current->sas_ss_size;
+
+ return (void *)((sp - frame_size) & -8UL);
+}
+
+static void setup_frame(int sig, struct k_sigaction *ka,
+ sigset_t *set, struct pt_regs *regs)
+{
+ struct sigframe *frame;
+ int err = 0;
+ int signal;
+
+ frame = get_sigframe(ka, regs, sizeof(*frame));
+
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+ goto give_sigsegv;
+
+ signal = current_thread_info()->exec_domain
+ && current_thread_info()->exec_domain->signal_invmap
+ && sig < 32
+ ? current_thread_info()->exec_domain->signal_invmap[sig]
+ : sig;
+
+ err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
+
+ if (_NSIG_WORDS > 1) {
+ err |= __copy_to_user(frame->extramask, &set->sig[1],
+ sizeof(frame->extramask));
+ }
+
+ /* Set up to return from userspace. If provided, use a stub
+ already in userspace. */
+ /* minus 8 is offset to cater for "rtsd r15,8" offset */
+ if (ka->sa.sa_flags & SA_RESTORER) {
+ regs->r15 = ((unsigned long)ka->sa.sa_restorer)-8;
+ } else {
+ /* Note, these encodings are _big endian_! */
+
+ /* addi r12, r0, __NR_sigreturn */
+ err |= __put_user(0x31800000 | __NR_sigreturn ,
+ frame->tramp + 0);
+ /* brki r14, 0x8 */
+ err |= __put_user(0xb9cc0008, frame->tramp + 1);
+
+ /* Return from sighandler will jump to the tramp.
+ Negative 8 offset because return is rtsd r15, 8 */
+ regs->r15 = ((unsigned long)frame->tramp)-8;
+
+ __invalidate_cache_sigtramp((unsigned long)frame->tramp);
+ }
+
+ if (err)
+ goto give_sigsegv;
+
+ /* Set up registers for signal handler */
+ regs->r1 = (unsigned long) frame;
+ /* Signal handler args: */
+ regs->r5 = signal; /* Arg 0: signum */
+ regs->r6 = (unsigned long) &frame->sc; /* arg 1: sigcontext */
+
+ /* Offset of 4 to handle microblaze rtid r14, 0 */
+ regs->pc = (unsigned long)ka->sa.sa_handler;
+
+ set_fs(USER_DS);
+
+#ifdef DEBUG_SIG
+ printk(KERN_INFO "SIG deliver (%s:%d): sp=%p pc=%08lx\n",
+ current->comm, current->pid, frame, regs->pc);
+#endif
+
+ return;
+
+give_sigsegv:
+ if (sig == SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ force_sig(SIGSEGV, current);
+}
+
+static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *set, struct pt_regs *regs)
+{
+ struct rt_sigframe *frame;
+ int err = 0;
+ int signal;
+
+ frame = get_sigframe(ka, regs, sizeof(*frame));
+
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+ goto give_sigsegv;
+
+ signal = current_thread_info()->exec_domain
+ && current_thread_info()->exec_domain->signal_invmap
+ && sig < 32
+ ? current_thread_info()->exec_domain->signal_invmap[sig]
+ : sig;
+
+ err |= copy_siginfo_to_user(&frame->info, info);
+
+ /* Create the ucontext. */
+ err |= __put_user(0, &frame->uc.uc_flags);
+ err |= __put_user(0, &frame->uc.uc_link);
+ err |= __put_user((void *)current->sas_ss_sp,
+ &frame->uc.uc_stack.ss_sp);
+ err |= __put_user(sas_ss_flags(regs->r1),
+ &frame->uc.uc_stack.ss_flags);
+ err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+ err |= setup_sigcontext(&frame->uc.uc_mcontext,
+ regs, set->sig[0]);
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
+ /* Set up to return from userspace. If provided, use a stub
+ already in userspace. */
+ /* minus 8 is offset to cater for "rtsd r15,8" */
+ if (ka->sa.sa_flags & SA_RESTORER) {
+ regs->r15 = ((unsigned long)ka->sa.sa_restorer)-8;
+ } else {
+ /* addi r12, r0, __NR_sigreturn */
+ err |= __put_user(0x31800000 | __NR_rt_sigreturn ,
+ frame->tramp + 0);
+ /* brki r14, 0x8 */
+ err |= __put_user(0xb9cc0008, frame->tramp + 1);
+
+ /* Return from sighandler will jump to the tramp.
+ Negative 8 offset because return is rtsd r15, 8 */
+ regs->r15 = ((unsigned long)frame->tramp)-8;
+
+ __invalidate_cache_sigtramp((unsigned long)frame->tramp);
+ }
+
+ if (err)
+ goto give_sigsegv;
+
+ /* Set up registers for signal handler */
+ regs->r1 = (unsigned long) frame;
+ /* Signal handler args: */
+ regs->r5 = signal; /* arg 0: signum */
+ regs->r6 = (unsigned long) &frame->info; /* arg 1: siginfo */
+ regs->r7 = (unsigned long) &frame->uc; /* arg2: ucontext */
+ /* Offset to handle microblaze rtid r14, 0 */
+ regs->pc = (unsigned long)ka->sa.sa_handler;
+
+ set_fs(USER_DS);
+
+#ifdef DEBUG_SIG
+ printk(KERN_INFO "SIG deliver (%s:%d): sp=%p pc=%08lx\n",
+ current->comm, current->pid, frame, regs->pc);
+#endif
+
+ return;
+
+give_sigsegv:
+ if (sig == SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ force_sig(SIGSEGV, current);
+}
+
+/* Handle restarting system calls */
+static inline void
+handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
+{
+ switch (regs->r3) {
+ case -ERESTART_RESTARTBLOCK:
+ case -ERESTARTNOHAND:
+ if (!has_handler)
+ goto do_restart;
+ regs->r3 = -EINTR;
+ break;
+ case -ERESTARTSYS:
+ if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
+ regs->r3 = -EINTR;
+ break;
+ }
+ /* fallthrough */
+ case -ERESTARTNOINTR:
+do_restart:
+ /* offset of 4 bytes to re-execute trap (brki) instruction */
+ regs->pc -= 4;
+ break;
+ }
+}
+
+/*
+ * OK, we're invoking a handler
+ */
+
+static void
+handle_signal(unsigned long sig, struct k_sigaction *ka,
+ siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
+{
+ /* Set up the stack frame */
+ if (ka->sa.sa_flags & SA_SIGINFO)
+ setup_rt_frame(sig, ka, info, oldset, regs);
+ else
+ setup_frame(sig, ka, oldset, regs);
+
+ if (ka->sa.sa_flags & SA_ONESHOT)
+ ka->sa.sa_handler = SIG_DFL;
+
+ if (!(ka->sa.sa_flags & SA_NODEFER)) {
+ spin_lock_irq(¤t->sighand->siglock);
+ sigorsets(¤t->blocked,
+ ¤t->blocked, &ka->sa.sa_mask);
+ sigaddset(¤t->blocked, sig);
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+ }
+}
+
+/*
+ * 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.
+ */
+int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall)
+{
+ siginfo_t info;
+ int signr;
+ struct k_sigaction ka;
+#ifdef DEBUG_SIG
+ printk(KERN_INFO "do signal: %p %p %d\n", regs, oldset, in_syscall);
+ printk(KERN_INFO "do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1,
+ regs->r12, current_thread_info()->flags);
+#endif
+ /*
+ * We want the common case to go fast, which
+ * is why we may in certain cases get here from
+ * kernel mode. Just return without doing anything
+ * if so.
+ */
+ if (kernel_mode(regs))
+ return 1;
+
+ if (!oldset)
+ oldset = ¤t->blocked;
+
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+ if (signr > 0) {
+ /* Whee! Actually deliver the signal. */
+ if (in_syscall)
+ handle_restart(regs, &ka, 1);
+ handle_signal(signr, &ka, &info, oldset, regs);
+ return 1;
+ }
+
+ if (in_syscall)
+ handle_restart(regs, NULL, 0);
+
+ /* Did we come from a system call? */
+ return 0;
+}
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/configs/nommu_defconfig | 802 +++++++++++++++++++++++++++++++
1 files changed, 802 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/configs/nommu_defconfig
diff --git a/arch/microblaze/configs/nommu_defconfig b/arch/microblaze/configs/nommu_defconfig
new file mode 100644
index 0000000..c1ca9cc
--- /dev/null
+++ b/arch/microblaze/configs/nommu_defconfig
@@ -0,0 +1,802 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-rc8
+# Wed Mar 18 17:29:24 2009
+#
+CONFIG_MICROBLAZE=y
+# CONFIG_SWAP is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+# CONFIG_GENERIC_TIME_VSYSCALL is not set
+CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_PCI is not set
+# CONFIG_NO_DMA is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+# CONFIG_BASE_FULL is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=1
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
+# Platform options
+#
+CONFIG_PLATFORM_GENERIC=y
+# CONFIG_SELFMOD is not set
+# CONFIG_OPT_LIB_FUNCTION is not set
+# CONFIG_ALLOW_EDIT_AUTO is not set
+CONFIG_KERNEL_BASE_ADDR=0x90000000
+CONFIG_XILINX_MICROBLAZE0_FAMILY="virtex5"
+CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR=1
+CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR=1
+CONFIG_XILINX_MICROBLAZE0_USE_BARREL=1
+CONFIG_XILINX_MICROBLAZE0_USE_DIV=1
+CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL=2
+CONFIG_XILINX_MICROBLAZE0_USE_FPU=2
+CONFIG_XILINX_MICROBLAZE0_HW_VER="7.10.d"
+
+#
+# Processor type and features
+#
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_100=y
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+CONFIG_SCHED_HRTICK=y
+# CONFIG_MMU is not set
+CONFIG_NO_MMU=y
+
+#
+# Boot options
+#
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyUL0,115200"
+# CONFIG_CMDLINE_FORCE is not set
+CONFIG_OF=y
+CONFIG_OF_DEVICE=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+
+#
+# Exectuable file formats
+#
+CONFIG_BINFMT_FLAT=y
+# CONFIG_BINFMT_ZFLAT is not set
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=y
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_OLD_REGULATORY=y
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_LIB80211 is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_UCLINUX=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_NBD=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_UARTLITE=y
+CONFIG_SERIAL_UARTLITE_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_SOUND is not set
+CONFIG_USB_SUPPORT=y
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+
+#
+# Enable Host or Gadget support to see Inventra options
+#
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=1
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_OBJECTS=y
+CONFIG_DEBUG_OBJECTS_SELFTEST=y
+CONFIG_DEBUG_OBJECTS_FREE=y
+CONFIG_DEBUG_OBJECTS_TIMERS=y
+CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_NOMMU_REGIONS is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+CONFIG_DEBUG_LIST=y
+CONFIG_DEBUG_SG=y
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+
+#
+# Tracers
+#
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_EARLY_PRINTK=y
+CONFIG_HEART_BEAT=y
+# CONFIG_DEBUG_BOOTMEM is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+# CONFIG_CRC32 is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_HAVE_LMB=y
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/kernel/entry-nommu.S | 594 ++++++++++++++++++++++++++++++++
arch/microblaze/kernel/head.S | 55 +++
arch/microblaze/kernel/syscall_table.S | 365 ++++++++++++++++++++
3 files changed, 1014 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/kernel/entry-nommu.S
create mode 100644 arch/microblaze/kernel/head.S
create mode 100644 arch/microblaze/kernel/syscall_table.S
diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S
new file mode 100644
index 0000000..5678f17
--- /dev/null
+++ b/arch/microblaze/kernel/entry-nommu.S
@@ -0,0 +1,594 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/linkage.h>
+#include <asm/thread_info.h>
+#include <asm/errno.h>
+#include <asm/entry.h>
+#include <asm/asm-offsets.h>
+#include <asm/registers.h>
+#include <asm/unistd.h>
+#include <asm/percpu.h>
+#include <asm/signal.h>
+
+#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
+ .macro disable_irq
+ msrclr r0, MSR_IE
+ .endm
+
+ .macro enable_irq
+ msrset r0, MSR_IE
+ .endm
+
+ .macro clear_bip
+ msrclr r0, MSR_BIP
+ .endm
+#else
+ .macro disable_irq
+ mfs r11, rmsr
+ andi r11, r11, ~MSR_IE
+ mts rmsr, r11
+ .endm
+
+ .macro enable_irq
+ mfs r11, rmsr
+ ori r11, r11, MSR_IE
+ mts rmsr, r11
+ .endm
+
+ .macro clear_bip
+ mfs r11, rmsr
+ andi r11, r11, ~MSR_BIP
+ mts rmsr, r11
+ .endm
+#endif
+
+ENTRY(_interrupt)
+ swi r1, r0, PER_CPU(ENTRY_SP) /* save the current sp */
+ swi r11, r0, PER_CPU(R11_SAVE) /* temporarily save r11 */
+ lwi r11, r0, PER_CPU(KM) /* load mode indicator */
+ beqid r11, 1f
+ nop
+ brid 2f /* jump over */
+ addik r1, r1, (-PT_SIZE) /* room for pt_regs (delay slot) */
+1: /* switch to kernel stack */
+ lwi r1, r0, PER_CPU(CURRENT_SAVE) /* get the saved current */
+ lwi r1, r1, TS_THREAD_INFO /* get the thread info */
+ /* calculate kernel stack pointer */
+ addik r1, r1, THREAD_SIZE - PT_SIZE
+2:
+ swi r11, r1, PT_MODE /* store the mode */
+ lwi r11, r0, PER_CPU(R11_SAVE) /* reload r11 */
+ swi r2, r1, PT_R2
+ swi r3, r1, PT_R3
+ swi r4, r1, PT_R4
+ swi r5, r1, PT_R5
+ swi r6, r1, PT_R6
+ swi r7, r1, PT_R7
+ swi r8, r1, PT_R8
+ swi r9, r1, PT_R9
+ swi r10, r1, PT_R10
+ swi r11, r1, PT_R11
+ swi r12, r1, PT_R12
+ swi r13, r1, PT_R13
+ swi r14, r1, PT_R14
+ swi r14, r1, PT_PC
+ swi r15, r1, PT_R15
+ swi r16, r1, PT_R16
+ swi r17, r1, PT_R17
+ swi r18, r1, PT_R18
+ swi r19, r1, PT_R19
+ swi r20, r1, PT_R20
+ swi r21, r1, PT_R21
+ swi r22, r1, PT_R22
+ swi r23, r1, PT_R23
+ swi r24, r1, PT_R24
+ swi r25, r1, PT_R25
+ swi r26, r1, PT_R26
+ swi r27, r1, PT_R27
+ swi r28, r1, PT_R28
+ swi r29, r1, PT_R29
+ swi r30, r1, PT_R30
+ swi r31, r1, PT_R31
+ /* special purpose registers */
+ mfs r11, rmsr
+ swi r11, r1, PT_MSR
+ mfs r11, rear
+ swi r11, r1, PT_EAR
+ mfs r11, resr
+ swi r11, r1, PT_ESR
+ mfs r11, rfsr
+ swi r11, r1, PT_FSR
+ /* reload original stack pointer and save it */
+ lwi r11, r0, PER_CPU(ENTRY_SP)
+ swi r11, r1, PT_R1
+ /* update mode indicator we are in kernel mode */
+ addik r11, r0, 1
+ swi r11, r0, PER_CPU(KM)
+ /* restore r31 */
+ lwi r31, r0, PER_CPU(CURRENT_SAVE)
+ /* prepare the link register, the argument and jump */
+ la r15, r0, ret_from_intr - 8
+ addk r6, r0, r15
+ braid do_IRQ
+ add r5, r0, r1
+
+ret_from_intr:
+ lwi r11, r1, PT_MODE
+ bneid r11, 3f
+
+ lwi r6, r31, TS_THREAD_INFO /* get thread info */
+ lwi r19, r6, TI_FLAGS /* get flags in thread info */
+ /* do an extra work if any bits are set */
+
+ andi r11, r19, _TIF_NEED_RESCHED
+ beqi r11, 1f
+ bralid r15, schedule
+ nop
+1: andi r11, r19, _TIF_SIGPENDING
+ beqid r11, no_intr_reshed
+ addk r5, r1, r0
+ addk r7, r0, r0
+ bralid r15, do_signal
+ addk r6, r0, r0
+
+no_intr_reshed:
+ /* save mode indicator */
+ lwi r11, r1, PT_MODE
+3:
+ swi r11, r0, PER_CPU(KM)
+
+ /* save r31 */
+ swi r31, r0, PER_CPU(CURRENT_SAVE)
+restore_context:
+ /* special purpose registers */
+ lwi r11, r1, PT_FSR
+ mts rfsr, r11
+ lwi r11, r1, PT_ESR
+ mts resr, r11
+ lwi r11, r1, PT_EAR
+ mts rear, r11
+ lwi r11, r1, PT_MSR
+ mts rmsr, r11
+
+ lwi r31, r1, PT_R31
+ lwi r30, r1, PT_R30
+ lwi r29, r1, PT_R29
+ lwi r28, r1, PT_R28
+ lwi r27, r1, PT_R27
+ lwi r26, r1, PT_R26
+ lwi r25, r1, PT_R25
+ lwi r24, r1, PT_R24
+ lwi r23, r1, PT_R23
+ lwi r22, r1, PT_R22
+ lwi r21, r1, PT_R21
+ lwi r20, r1, PT_R20
+ lwi r19, r1, PT_R19
+ lwi r18, r1, PT_R18
+ lwi r17, r1, PT_R17
+ lwi r16, r1, PT_R16
+ lwi r15, r1, PT_R15
+ lwi r14, r1, PT_PC
+ lwi r13, r1, PT_R13
+ lwi r12, r1, PT_R12
+ lwi r11, r1, PT_R11
+ lwi r10, r1, PT_R10
+ lwi r9, r1, PT_R9
+ lwi r8, r1, PT_R8
+ lwi r7, r1, PT_R7
+ lwi r6, r1, PT_R6
+ lwi r5, r1, PT_R5
+ lwi r4, r1, PT_R4
+ lwi r3, r1, PT_R3
+ lwi r2, r1, PT_R2
+ lwi r1, r1, PT_R1
+ rtid r14, 0
+ nop
+
+ENTRY(_reset)
+ brai 0;
+
+ENTRY(_user_exception)
+ swi r1, r0, PER_CPU(ENTRY_SP) /* save the current sp */
+ swi r11, r0, PER_CPU(R11_SAVE) /* temporarily save r11 */
+ lwi r11, r0, PER_CPU(KM) /* load mode indicator */
+ beqid r11, 1f /* Already in kernel mode? */
+ nop
+ brid 2f /* jump over */
+ addik r1, r1, (-PT_SIZE) /* Room for pt_regs (delay slot) */
+1: /* Switch to kernel stack */
+ lwi r1, r0, PER_CPU(CURRENT_SAVE) /* get the saved current */
+ lwi r1, r1, TS_THREAD_INFO /* get the thread info */
+ /* calculate kernel stack pointer */
+ addik r1, r1, THREAD_SIZE - PT_SIZE
+ swi r11, r0, PER_CPU(R11_SAVE) /* temporarily save r11 */
+ lwi r11, r0, PER_CPU(KM) /* load mode indicator */
+2:
+ swi r11, r1, PT_MODE /* store the mode */
+ lwi r11, r0, PER_CPU(R11_SAVE) /* reload r11 */
+ /* save them on stack */
+ swi r2, r1, PT_R2
+ swi r3, r1, PT_R3 /* r3: _always_ in clobber list; see unistd.h */
+ swi r4, r1, PT_R4 /* r4: _always_ in clobber list; see unistd.h */
+ swi r5, r1, PT_R5
+ swi r6, r1, PT_R6
+ swi r7, r1, PT_R7
+ swi r8, r1, PT_R8
+ swi r9, r1, PT_R9
+ swi r10, r1, PT_R10
+ swi r11, r1, PT_R11
+ /* r12: _always_ in clobber list; see unistd.h */
+ swi r12, r1, PT_R12
+ swi r13, r1, PT_R13
+ /* r14: _always_ in clobber list; see unistd.h */
+ swi r14, r1, PT_R14
+ /* but we want to return to the next inst. */
+ addik r14, r14, 0x4
+ swi r14, r1, PT_PC /* increment by 4 and store in pc */
+ swi r15, r1, PT_R15
+ swi r16, r1, PT_R16
+ swi r17, r1, PT_R17
+ swi r18, r1, PT_R18
+ swi r19, r1, PT_R19
+ swi r20, r1, PT_R20
+ swi r21, r1, PT_R21
+ swi r22, r1, PT_R22
+ swi r23, r1, PT_R23
+ swi r24, r1, PT_R24
+ swi r25, r1, PT_R25
+ swi r26, r1, PT_R26
+ swi r27, r1, PT_R27
+ swi r28, r1, PT_R28
+ swi r29, r1, PT_R29
+ swi r30, r1, PT_R30
+ swi r31, r1, PT_R31
+
+ disable_irq
+ nop /* make sure IE bit is in effect */
+ clear_bip /* once IE is in effect it is safe to clear BIP */
+ nop
+
+ /* special purpose registers */
+ mfs r11, rmsr
+ swi r11, r1, PT_MSR
+ mfs r11, rear
+ swi r11, r1, PT_EAR
+ mfs r11, resr
+ swi r11, r1, PT_ESR
+ mfs r11, rfsr
+ swi r11, r1, PT_FSR
+ /* reload original stack pointer and save it */
+ lwi r11, r0, PER_CPU(ENTRY_SP)
+ swi r11, r1, PT_R1
+ /* update mode indicator we are in kernel mode */
+ addik r11, r0, 1
+ swi r11, r0, PER_CPU(KM)
+ /* restore r31 */
+ lwi r31, r0, PER_CPU(CURRENT_SAVE)
+ /* re-enable interrupts now we are in kernel mode */
+ enable_irq
+
+ /* See if the system call number is valid. */
+ addi r11, r12, -__NR_syscalls
+ bgei r11, 1f /* return to user if not valid */
+ /* Figure out which function to use for this system call. */
+ /* Note Microblaze barrel shift is optional, so don't rely on it */
+ add r12, r12, r12 /* convert num -> ptr */
+ add r12, r12, r12
+ lwi r12, r12, sys_call_table /* Get function pointer */
+ la r15, r0, ret_to_user-8 /* set return address */
+ bra r12 /* Make the system call. */
+ bri 0 /* won't reach here */
+1:
+ brid ret_to_user /* jump to syscall epilogue */
+ addi r3, r0, -ENOSYS /* set errno in delay slot */
+
+/*
+ * Debug traps are like a system call, but entered via brki r14, 0x60
+ * All we need to do is send the SIGTRAP signal to current, ptrace and do_signal
+ * will handle the rest
+ */
+ENTRY(_debug_exception)
+ swi r1, r0, PER_CPU(ENTRY_SP) /* save the current sp */
+ lwi r1, r0, PER_CPU(CURRENT_SAVE) /* get the saved current */
+ lwi r1, r1, TS_THREAD_INFO /* get the thread info */
+ addik r1, r1, THREAD_SIZE - PT_SIZE /* get the kernel stack */
+ swi r11, r0, PER_CPU(R11_SAVE) /* temporarily save r11 */
+ lwi r11, r0, PER_CPU(KM) /* load mode indicator */
+//save_context:
+ swi r11, r1, PT_MODE /* store the mode */
+ lwi r11, r0, PER_CPU(R11_SAVE) /* reload r11 */
+ /* save them on stack */
+ swi r2, r1, PT_R2
+ swi r3, r1, PT_R3 /* r3: _always_ in clobber list; see unistd.h */
+ swi r4, r1, PT_R4 /* r4: _always_ in clobber list; see unistd.h */
+ swi r5, r1, PT_R5
+ swi r6, r1, PT_R6
+ swi r7, r1, PT_R7
+ swi r8, r1, PT_R8
+ swi r9, r1, PT_R9
+ swi r10, r1, PT_R10
+ swi r11, r1, PT_R11
+ /* r12: _always_ in clobber list; see unistd.h */
+ swi r12, r1, PT_R12
+ swi r13, r1, PT_R13
+ /* r14: _always_ in clobber list; see unistd.h */
+ swi r14, r1, PT_R14
+ swi r14, r1, PT_PC /* Will return to interrupted instruction */
+ swi r15, r1, PT_R15
+ swi r16, r1, PT_R16
+ swi r17, r1, PT_R17
+ swi r18, r1, PT_R18
+ swi r19, r1, PT_R19
+ swi r20, r1, PT_R20
+ swi r21, r1, PT_R21
+ swi r22, r1, PT_R22
+ swi r23, r1, PT_R23
+ swi r24, r1, PT_R24
+ swi r25, r1, PT_R25
+ swi r26, r1, PT_R26
+ swi r27, r1, PT_R27
+ swi r28, r1, PT_R28
+ swi r29, r1, PT_R29
+ swi r30, r1, PT_R30
+ swi r31, r1, PT_R31
+
+ disable_irq
+ nop /* make sure IE bit is in effect */
+ clear_bip /* once IE is in effect it is safe to clear BIP */
+ nop
+
+ /* special purpose registers */
+ mfs r11, rmsr
+ swi r11, r1, PT_MSR
+ mfs r11, rear
+ swi r11, r1, PT_EAR
+ mfs r11, resr
+ swi r11, r1, PT_ESR
+ mfs r11, rfsr
+ swi r11, r1, PT_FSR
+ /* reload original stack pointer and save it */
+ lwi r11, r0, PER_CPU(ENTRY_SP)
+ swi r11, r1, PT_R1
+ /* update mode indicator we are in kernel mode */
+ addik r11, r0, 1
+ swi r11, r0, PER_CPU(KM)
+ /* restore r31 */
+ lwi r31, r0, PER_CPU(CURRENT_SAVE)
+ /* re-enable interrupts now we are in kernel mode */
+ enable_irq
+
+ addi r5, r0, SIGTRAP /* sending the trap signal */
+ add r6, r0, r31 /* to current */
+ bralid r15, send_sig
+ add r7, r0, r0 /* 3rd param zero */
+
+ /* Restore r3/r4 to work around how ret_to_user works */
+ lwi r3, r1, PT_R3
+ lwi r4, r1, PT_R4
+ bri ret_to_user
+
+ENTRY(_break)
+ bri 0
+
+/* struct task_struct *_switch_to(struct thread_info *prev,
+ struct thread_info *next); */
+ENTRY(_switch_to)
+ /* prepare return value */
+ addk r3, r0, r31
+
+ /* save registers in cpu_context */
+ /* use r11 and r12, volatile registers, as temp register */
+ addik r11, r5, TI_CPU_CONTEXT
+ swi r1, r11, CC_R1
+ swi r2, r11, CC_R2
+ /* skip volatile registers.
+ * they are saved on stack when we jumped to _switch_to() */
+ /* dedicated registers */
+ swi r13, r11, CC_R13
+ swi r14, r11, CC_R14
+ swi r15, r11, CC_R15
+ swi r16, r11, CC_R16
+ swi r17, r11, CC_R17
+ swi r18, r11, CC_R18
+ /* save non-volatile registers */
+ swi r19, r11, CC_R19
+ swi r20, r11, CC_R20
+ swi r21, r11, CC_R21
+ swi r22, r11, CC_R22
+ swi r23, r11, CC_R23
+ swi r24, r11, CC_R24
+ swi r25, r11, CC_R25
+ swi r26, r11, CC_R26
+ swi r27, r11, CC_R27
+ swi r28, r11, CC_R28
+ swi r29, r11, CC_R29
+ swi r30, r11, CC_R30
+ /* special purpose registers */
+ mfs r12, rmsr
+ swi r12, r11, CC_MSR
+ mfs r12, rear
+ swi r12, r11, CC_EAR
+ mfs r12, resr
+ swi r12, r11, CC_ESR
+ mfs r12, rfsr
+ swi r12, r11, CC_FSR
+
+ /* update r31, the current */
+ lwi r31, r6, TI_TASK
+ swi r31, r0, PER_CPU(CURRENT_SAVE)
+
+ /* get new process' cpu context and restore */
+ addik r11, r6, TI_CPU_CONTEXT
+
+ /* special purpose registers */
+ lwi r12, r11, CC_FSR
+ mts rfsr, r12
+ lwi r12, r11, CC_ESR
+ mts resr, r12
+ lwi r12, r11, CC_EAR
+ mts rear, r12
+ lwi r12, r11, CC_MSR
+ mts rmsr, r12
+ /* non-volatile registers */
+ lwi r30, r11, CC_R30
+ lwi r29, r11, CC_R29
+ lwi r28, r11, CC_R28
+ lwi r27, r11, CC_R27
+ lwi r26, r11, CC_R26
+ lwi r25, r11, CC_R25
+ lwi r24, r11, CC_R24
+ lwi r23, r11, CC_R23
+ lwi r22, r11, CC_R22
+ lwi r21, r11, CC_R21
+ lwi r20, r11, CC_R20
+ lwi r19, r11, CC_R19
+ /* dedicated registers */
+ lwi r18, r11, CC_R18
+ lwi r17, r11, CC_R17
+ lwi r16, r11, CC_R16
+ lwi r15, r11, CC_R15
+ lwi r14, r11, CC_R14
+ lwi r13, r11, CC_R13
+ /* skip volatile registers */
+ lwi r2, r11, CC_R2
+ lwi r1, r11, CC_R1
+
+ rtsd r15, 8
+ nop
+
+ENTRY(ret_from_fork)
+ addk r5, r0, r3
+ addk r6, r0, r1
+ brlid r15, schedule_tail
+ nop
+ swi r31, r1, PT_R31 /* save r31 in user context. */
+ /* will soon be restored to r31 in ret_to_user */
+ addk r3, r0, r0
+ brid ret_to_user
+ nop
+
+work_pending:
+ andi r11, r19, _TIF_NEED_RESCHED
+ beqi r11, 1f
+ bralid r15, schedule
+ nop
+1: andi r11, r19, _TIF_SIGPENDING
+ beqi r11, no_work_pending
+ addk r5, r1, r0
+ addik r7, r0, 1
+ bralid r15, do_signal
+ addk r6, r0, r0
+ bri no_work_pending
+
+ENTRY(ret_to_user)
+ disable_irq
+
+ swi r4, r1, PT_R4 /* return val */
+ swi r3, r1, PT_R3 /* return val */
+
+ lwi r6, r31, TS_THREAD_INFO /* get thread info */
+ lwi r19, r6, TI_FLAGS /* get flags in thread info */
+ bnei r19, work_pending /* do an extra work if any bits are set */
+no_work_pending:
+ disable_irq
+
+ /* save r31 */
+ swi r31, r0, PER_CPU(CURRENT_SAVE)
+ /* save mode indicator */
+ lwi r18, r1, PT_MODE
+ swi r18, r0, PER_CPU(KM)
+//restore_context:
+ /* special purpose registers */
+ lwi r18, r1, PT_FSR
+ mts rfsr, r18
+ lwi r18, r1, PT_ESR
+ mts resr, r18
+ lwi r18, r1, PT_EAR
+ mts rear, r18
+ lwi r18, r1, PT_MSR
+ mts rmsr, r18
+
+ lwi r31, r1, PT_R31
+ lwi r30, r1, PT_R30
+ lwi r29, r1, PT_R29
+ lwi r28, r1, PT_R28
+ lwi r27, r1, PT_R27
+ lwi r26, r1, PT_R26
+ lwi r25, r1, PT_R25
+ lwi r24, r1, PT_R24
+ lwi r23, r1, PT_R23
+ lwi r22, r1, PT_R22
+ lwi r21, r1, PT_R21
+ lwi r20, r1, PT_R20
+ lwi r19, r1, PT_R19
+ lwi r18, r1, PT_R18
+ lwi r17, r1, PT_R17
+ lwi r16, r1, PT_R16
+ lwi r15, r1, PT_R15
+ lwi r14, r1, PT_PC
+ lwi r13, r1, PT_R13
+ lwi r12, r1, PT_R12
+ lwi r11, r1, PT_R11
+ lwi r10, r1, PT_R10
+ lwi r9, r1, PT_R9
+ lwi r8, r1, PT_R8
+ lwi r7, r1, PT_R7
+ lwi r6, r1, PT_R6
+ lwi r5, r1, PT_R5
+ lwi r4, r1, PT_R4 /* return val */
+ lwi r3, r1, PT_R3 /* return val */
+ lwi r2, r1, PT_R2
+ lwi r1, r1, PT_R1
+
+ rtid r14, 0
+ nop
+
+sys_vfork_wrapper:
+ brid sys_vfork
+ addk r5, r1, r0
+
+sys_clone_wrapper:
+ brid sys_clone
+ addk r7, r1, r0
+
+sys_execve_wrapper:
+ brid sys_execve
+ addk r8, r1, r0
+
+sys_sigreturn_wrapper:
+ brid sys_sigreturn
+ addk r5, r1, r0
+
+sys_rt_sigreturn_wrapper:
+ brid sys_rt_sigreturn
+ addk r5, r1, r0
+
+sys_sigsuspend_wrapper:
+ brid sys_rt_sigsuspend
+ addk r6, r1, r0
+
+sys_rt_sigsuspend_wrapper:
+ brid sys_rt_sigsuspend
+ addk r7, r1, r0
+
+ /* Interrupt vector table */
+ .section .init.ivt, "ax"
+ .org 0x0
+ brai _reset
+ brai _user_exception
+ brai _interrupt
+ brai _break
+ brai _hw_exception_handler
+ .org 0x60
+ brai _debug_exception
+
+.section .rodata,"a"
+#include "syscall_table.S"
+
+syscall_table_size=(.-sys_call_table)
diff --git a/arch/microblaze/kernel/head.S b/arch/microblaze/kernel/head.S
new file mode 100644
index 0000000..434b8cb
--- /dev/null
+++ b/arch/microblaze/kernel/head.S
@@ -0,0 +1,55 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 Michal Simek <[email protected]>
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ */
+
+#include <linux/linkage.h>
+#include <asm/thread_info.h>
+#include <asm/page.h>
+
+ .text
+ENTRY(_start)
+ mfs r1, rmsr
+ andi r1, r1, ~2
+ mts rmsr, r1
+
+/* save fdt to kernel location */
+/* r7 stores pointer to fdt blob */
+ beqi r7, no_fdt_arg
+ or r11, r0, r0 /* incremment */
+ ori r4, r0, TOPHYS(_fdt_start) /* save bram context */
+ ori r3, r0, (0x4000 - 4)
+_copy_fdt:
+ lw r12, r7, r11 /* r12 = r7 + r11 */
+ sw r12, r4, r11 /* addr[r4 + r11] = r12 */
+ addik r11, r11, 4 /* increment counting */
+ bgtid r3, _copy_fdt /* loop for all entries */
+ addik r3, r3, -4 /* descrement loop */
+no_fdt_arg:
+
+ /* Initialize small data anchors */
+ la r13, r0, _KERNEL_SDA_BASE_
+ la r2, r0, _KERNEL_SDA2_BASE_
+
+ /* Initialize stack pointer */
+ la r1, r0, init_thread_union + THREAD_SIZE - 4
+
+ /* Initialize r31 with current task address */
+ la r31, r0, init_task
+
+ /*
+ * Call platform dependent initialize function.
+ * Please see $(ARCH)/mach-$(SUBARCH)/setup.c for
+ * the function.
+ */
+ la r8, r0, machine_early_init
+ brald r15, r8
+ nop
+
+ la r15, r0, machine_halt
+ braid start_kernel
+ nop
diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S
new file mode 100644
index 0000000..695710b
--- /dev/null
+++ b/arch/microblaze/kernel/syscall_table.S
@@ -0,0 +1,365 @@
+ENTRY(sys_call_table)
+ .long sys_restart_syscall /* 0 - old "setup()" system call,
+ * used for restarting */
+ .long sys_exit
+ .long sys_ni_syscall /* was fork */
+ .long sys_read
+ .long sys_write
+ .long sys_open /* 5 */
+ .long sys_close
+ .long sys_waitpid
+ .long sys_creat
+ .long sys_link
+ .long sys_unlink /* 10 */
+ .long sys_execve_wrapper
+ .long sys_chdir
+ .long sys_time
+ .long sys_mknod
+ .long sys_chmod /* 15 */
+ .long sys_lchown
+ .long sys_ni_syscall /* old break syscall holder */
+ .long sys_ni_syscall /* old stat */
+ .long sys_lseek
+ .long sys_getpid /* 20 */
+ .long sys_mount
+ .long sys_oldumount
+ .long sys_setuid
+ .long sys_getuid
+ .long sys_stime /* 25 */
+ .long sys_ptrace
+ .long sys_alarm
+ .long sys_ni_syscall /* oldfstat */
+ .long sys_pause
+ .long sys_utime /* 30 */
+ .long sys_ni_syscall /* old stty syscall holder */
+ .long sys_ni_syscall /* old gtty syscall holder */
+ .long sys_access
+ .long sys_nice
+ .long sys_ni_syscall /* 35 - old ftime syscall holder */
+ .long sys_sync
+ .long sys_kill
+ .long sys_rename
+ .long sys_mkdir
+ .long sys_rmdir /* 40 */
+ .long sys_dup
+ .long sys_pipe
+ .long sys_times
+ .long sys_ni_syscall /* old prof syscall holder */
+ .long sys_brk /* 45 */
+ .long sys_setgid
+ .long sys_getgid
+ .long sys_signal
+ .long sys_geteuid
+ .long sys_getegid /* 50 */
+ .long sys_acct
+ .long sys_umount /* recycled never used phys() */
+ .long sys_ni_syscall /* old lock syscall holder */
+ .long sys_ioctl
+ .long sys_fcntl /* 55 */
+ .long sys_ni_syscall /* old mpx syscall holder */
+ .long sys_setpgid
+ .long sys_ni_syscall /* old ulimit syscall holder */
+ .long sys_ni_syscall /* olduname */
+ .long sys_umask /* 60 */
+ .long sys_chroot
+ .long sys_ustat
+ .long sys_dup2
+ .long sys_getppid
+ .long sys_getpgrp /* 65 */
+ .long sys_setsid
+ .long sys_sigaction
+ .long sys_sgetmask
+ .long sys_ssetmask
+ .long sys_setreuid /* 70 */
+ .long sys_setregid
+ .long sys_sigsuspend_wrapper
+ .long sys_sigpending
+ .long sys_sethostname
+ .long sys_setrlimit /* 75 */
+ .long sys_ni_syscall /* old_getrlimit */
+ .long sys_getrusage
+ .long sys_gettimeofday
+ .long sys_settimeofday
+ .long sys_getgroups /* 80 */
+ .long sys_setgroups
+ .long sys_ni_syscall /* old_select */
+ .long sys_symlink
+ .long sys_ni_syscall /* oldlstat */
+ .long sys_readlink /* 85 */
+ .long sys_uselib
+ .long sys_swapon
+ .long sys_reboot
+ .long sys_ni_syscall /* old_readdir */
+ .long sys_mmap /* 90 */ /* old_mmap */
+ .long sys_munmap
+ .long sys_truncate
+ .long sys_ftruncate
+ .long sys_fchmod
+ .long sys_fchown /* 95 */
+ .long sys_getpriority
+ .long sys_setpriority
+ .long sys_ni_syscall /* old profil syscall holder */
+ .long sys_statfs
+ .long sys_fstatfs /* 100 */
+ .long sys_ni_syscall /* ioperm */
+ .long sys_socketcall
+ .long sys_syslog /* operation with system console */
+ .long sys_setitimer
+ .long sys_getitimer /* 105 */
+ .long sys_newstat
+ .long sys_newlstat
+ .long sys_newfstat
+ .long sys_ni_syscall /* uname */
+ .long sys_ni_syscall /* 110 */ /* iopl */
+ .long sys_vhangup
+ .long sys_ni_syscall /* old "idle" system call */
+ .long sys_ni_syscall /* old sys_vm86old */
+ .long sys_wait4
+ .long sys_swapoff /* 115 */
+ .long sys_sysinfo
+ .long sys_ipc
+ .long sys_fsync
+ .long sys_sigreturn_wrapper
+ .long sys_clone_wrapper /* 120 */
+ .long sys_setdomainname
+ .long sys_newuname
+ .long sys_ni_syscall /* modify_ldt */
+ .long sys_adjtimex
+ .long sys_mprotect /* 125: sys_mprotect */
+ .long sys_sigprocmask
+ .long sys_ni_syscall /* old "create_module" */
+ .long sys_init_module
+ .long sys_delete_module
+ .long sys_ni_syscall /* 130: old "get_kernel_syms" */
+ .long sys_quotactl
+ .long sys_getpgid
+ .long sys_fchdir
+ .long sys_bdflush
+ .long sys_sysfs /* 135 */
+ .long sys_personality
+ .long sys_ni_syscall /* reserved for afs_syscall */
+ .long sys_setfsuid
+ .long sys_setfsgid
+ .long sys_llseek /* 140 */
+ .long sys_getdents
+ .long sys_select
+ .long sys_flock
+ .long sys_msync
+ .long sys_readv /* 145 */
+ .long sys_writev
+ .long sys_getsid
+ .long sys_fdatasync
+ .long sys_sysctl
+ .long sys_mlock /* 150: sys_mlock */
+ .long sys_munlock
+ .long sys_mlockall
+ .long sys_munlockall
+ .long sys_sched_setparam
+ .long sys_sched_getparam /* 155 */
+ .long sys_sched_setscheduler
+ .long sys_sched_getscheduler
+ .long sys_sched_yield
+ .long sys_sched_get_priority_max
+ .long sys_sched_get_priority_min /* 160 */
+ .long sys_sched_rr_get_interval
+ .long sys_nanosleep
+ .long sys_mremap
+ .long sys_setresuid
+ .long sys_getresuid /* 165 */
+ .long sys_ni_syscall /* sys_vm86 */
+ .long sys_ni_syscall /* Old sys_query_module */
+ .long sys_poll
+ .long sys_nfsservctl
+ .long sys_setresgid /* 170 */
+ .long sys_getresgid
+ .long sys_prctl
+ .long sys_rt_sigreturn_wrapper
+ .long sys_rt_sigaction
+ .long sys_rt_sigprocmask /* 175 */
+ .long sys_rt_sigpending
+ .long sys_rt_sigtimedwait
+ .long sys_rt_sigqueueinfo
+ .long sys_rt_sigsuspend_wrapper
+ .long sys_pread64 /* 180 */
+ .long sys_pwrite64
+ .long sys_chown
+ .long sys_getcwd
+ .long sys_capget
+ .long sys_capset /* 185 */
+ .long sys_ni_syscall /* sigaltstack */
+ .long sys_sendfile
+ .long sys_ni_syscall /* reserved for streams1 */
+ .long sys_ni_syscall /* reserved for streams2 */
+ .long sys_vfork_wrapper /* 190 */
+ .long sys_getrlimit
+ .long sys_mmap2 /* mmap2 */
+ .long sys_truncate64
+ .long sys_ftruncate64
+ .long sys_stat64 /* 195 */
+ .long sys_lstat64
+ .long sys_fstat64
+ .long sys_lchown
+ .long sys_getuid
+ .long sys_getgid /* 200 */
+ .long sys_geteuid
+ .long sys_getegid
+ .long sys_setreuid
+ .long sys_setregid
+ .long sys_getgroups /* 205 */
+ .long sys_setgroups
+ .long sys_fchown
+ .long sys_setresuid
+ .long sys_getresuid
+ .long sys_setresgid /* 210 */
+ .long sys_getresgid
+ .long sys_chown
+ .long sys_setuid
+ .long sys_setgid
+ .long sys_setfsuid /* 215 */
+ .long sys_setfsgid
+ .long sys_pivot_root
+ .long sys_mincore
+ .long sys_madvise
+ .long sys_getdents64 /* 220 */
+ .long sys_fcntl64
+ .long sys_ni_syscall /* reserved for TUX */
+ .long sys_ni_syscall
+ .long sys_gettid
+ .long sys_readahead /* 225 */
+ .long sys_setxattr
+ .long sys_lsetxattr
+ .long sys_fsetxattr
+ .long sys_getxattr
+ .long sys_lgetxattr /* 230 */
+ .long sys_fgetxattr
+ .long sys_listxattr
+ .long sys_llistxattr
+ .long sys_flistxattr
+ .long sys_removexattr /* 235 */
+ .long sys_lremovexattr
+ .long sys_fremovexattr
+ .long sys_tkill
+ .long sys_sendfile64
+ .long sys_futex /* 240 */
+ .long sys_sched_setaffinity
+ .long sys_sched_getaffinity
+ .long sys_ni_syscall /* set_thread_area */
+ .long sys_ni_syscall /* get_thread_area */
+ .long sys_io_setup /* 245 */
+ .long sys_io_destroy
+ .long sys_io_getevents
+ .long sys_io_submit
+ .long sys_io_cancel
+ .long sys_fadvise64 /* 250 */
+ .long sys_ni_syscall
+ .long sys_exit_group
+ .long sys_lookup_dcookie
+ .long sys_epoll_create
+ .long sys_epoll_ctl /* 255 */
+ .long sys_epoll_wait
+ .long sys_remap_file_pages
+ .long sys_set_tid_address
+ .long sys_timer_create
+ .long sys_timer_settime /* 260 */
+ .long sys_timer_gettime
+ .long sys_timer_getoverrun
+ .long sys_timer_delete
+ .long sys_clock_settime
+ .long sys_clock_gettime /* 265 */
+ .long sys_clock_getres
+ .long sys_clock_nanosleep
+ .long sys_statfs64
+ .long sys_fstatfs64
+ .long sys_tgkill /* 270 */
+ .long sys_utimes
+ .long sys_fadvise64_64
+ .long sys_ni_syscall /* sys_vserver */
+ .long sys_mbind
+ .long sys_get_mempolicy
+ .long sys_set_mempolicy
+ .long sys_mq_open
+ .long sys_mq_unlink
+ .long sys_mq_timedsend
+ .long sys_mq_timedreceive /* 280 */
+ .long sys_mq_notify
+ .long sys_mq_getsetattr
+ .long sys_kexec_load
+ .long sys_waitid
+ .long sys_ni_syscall /* 285 */ /* available */
+ .long sys_add_key
+ .long sys_request_key
+ .long sys_keyctl
+ .long sys_ioprio_set
+ .long sys_ioprio_get /* 290 */
+ .long sys_inotify_init
+ .long sys_inotify_add_watch
+ .long sys_inotify_rm_watch
+ .long sys_ni_syscall /* sys_migrate_pages */
+ .long sys_openat /* 295 */
+ .long sys_mkdirat
+ .long sys_mknodat
+ .long sys_fchownat
+ .long sys_ni_syscall
+ .long sys_fstatat64 /* 300 */
+ .long sys_unlinkat
+ .long sys_renameat
+ .long sys_linkat
+ .long sys_symlinkat
+ .long sys_readlinkat /* 305 */
+ .long sys_fchmodat
+ .long sys_faccessat
+ .long sys_ni_syscall /* pselect6 */
+ .long sys_ni_syscall /* sys_ppoll */
+ .long sys_unshare /* 310 */
+ .long sys_set_robust_list
+ .long sys_get_robust_list
+ .long sys_splice
+ .long sys_sync_file_range
+ .long sys_tee /* 315 */
+ .long sys_vmsplice
+ .long sys_move_pages
+ .long sys_getcpu
+ .long sys_epoll_pwait
+ .long sys_utimensat /* 320 */
+ .long sys_signalfd
+ .long sys_timerfd_create
+ .long sys_eventfd
+ .long sys_fallocate
+ .long sys_semtimedop /* 325 */
+ .long sys_timerfd_settime
+ .long sys_timerfd_gettime
+ .long sys_semctl
+ .long sys_semget
+ .long sys_semop /* 330 */
+ .long sys_msgctl
+ .long sys_msgget
+ .long sys_msgrcv
+ .long sys_msgsnd
+ .long sys_shmat /* 335 */
+ .long sys_shmctl
+ .long sys_shmdt
+ .long sys_shmget
+ .long sys_signalfd4 /* new syscall */
+ .long sys_eventfd2 /* 340 */
+ .long sys_epoll_create1
+ .long sys_dup3
+ .long sys_pipe2
+ .long sys_inotify_init1
+ .long sys_socket /* 345 */
+ .long sys_socketpair
+ .long sys_bind
+ .long sys_listen
+ .long sys_accept
+ .long sys_connect /* 350 */
+ .long sys_getsockname
+ .long sys_getpeername
+ .long sys_sendto
+ .long sys_send
+ .long sys_recvfrom /* 355 */
+ .long sys_recv
+ .long sys_setsockopt
+ .long sys_getsockopt
+ .long sys_shutdown
+ .long sys_sendmsg /* 360 */
+ .long sys_recvmsg
+ .long sys_ni_syscall
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/kernel/vmlinux.lds.S | 163 ++++++++++++++++++++++++++++++++++
1 files changed, 163 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/kernel/vmlinux.lds.S
diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S
new file mode 100644
index 0000000..67c0e24
--- /dev/null
+++ b/arch/microblaze/kernel/vmlinux.lds.S
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2008 Michal Simek
+ * Copyright (C) 2008 PetaLogix
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+OUTPUT_FORMAT("elf32-microblaze", "elf32-microblaze", "elf32-microblaze")
+OUTPUT_ARCH(microblaze)
+ENTRY(_start)
+
+#include <asm-generic/vmlinux.lds.h>
+
+jiffies = jiffies_64 + 4;
+
+SECTIONS {
+ . = CONFIG_KERNEL_BASE_ADDR;
+
+ .text : {
+ _text = . ;
+ _stext = . ;
+ *(.text .text.*)
+ *(.fixup)
+
+ *(.exitcall.exit)
+ SCHED_TEXT
+ LOCK_TEXT
+ KPROBES_TEXT
+ . = ALIGN (4) ;
+ _etext = . ;
+ }
+
+ . = ALIGN (4) ;
+ _fdt_start = . ; /* place for fdt blob */
+ . = . + 0x4000;
+ _fdt_end = . ;
+
+ . = ALIGN(16);
+ RODATA
+ . = ALIGN(16);
+ __ex_table : {
+ __start___ex_table = .;
+ *(__ex_table)
+ __stop___ex_table = .;
+ }
+
+ /*
+ * sdata2 section can go anywhere, but must be word aligned
+ * and SDA2_BASE must point to the middle of it
+ */
+ .sdata2 : {
+ _ssrw = .;
+ . = ALIGN(4096); /* page aligned when MMU used - origin 0x8 */
+ *(.sdata2)
+ . = ALIGN(8);
+ _essrw = .;
+ _ssrw_size = _essrw - _ssrw;
+ _KERNEL_SDA2_BASE_ = _ssrw + (_ssrw_size / 2);
+ }
+
+ _sdata = . ;
+ .data ALIGN (4096) : { /* page aligned when MMU used - origin 0x4 */
+ *(.data)
+ }
+ . = ALIGN(32);
+ .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+ _edata = . ;
+
+ /* Reserve some low RAM for r0 based memory references */
+ . = ALIGN(0x4) ;
+ r0_ram = . ;
+ . = . + 4096; /* a page should be enough */
+
+ /* The initial task */
+ . = ALIGN(8192);
+ .data.init_task : { *(.data.init_task) }
+
+ /* Under the microblaze ABI, .sdata and .sbss must be contiguous */
+ . = ALIGN(8);
+ .sdata : {
+ _ssro = .;
+ *(.sdata)
+ }
+
+ .sbss : {
+ _ssbss = .;
+ *(.sbss)
+ _esbss = .;
+ _essro = .;
+ _ssro_size = _essro - _ssro ;
+ _KERNEL_SDA_BASE_ = _ssro + (_ssro_size / 2) ;
+ }
+
+ __init_begin = .;
+
+ . = ALIGN(4096);
+ .init.text : {
+ _sinittext = . ;
+ *(.init.text)
+ *(.exit.text)
+ *(.exit.data)
+ _einittext = .;
+ }
+
+ .init.data : { *(.init.data) }
+
+ . = ALIGN(4);
+ .init.ivt : {
+ __ivt_start = .;
+ *(.init.ivt)
+ __ivt_end = .;
+ }
+
+ .init.setup : {
+ __setup_start = .;
+ *(.init.setup)
+ __setup_end = .;
+ }
+
+ .initcall.init : {
+ __initcall_start = .;
+ INITCALLS
+ __initcall_end = .;
+ }
+
+ .con_initcall.init : {
+ __con_initcall_start = .;
+ *(.con_initcall.init)
+ __con_initcall_end = .;
+ }
+
+ __init_end_before_initramfs = .;
+
+ .init.ramfs ALIGN(4096) : {
+ __initramfs_start = .;
+ *(.init.ramfs)
+ __initramfs_end = .;
+ . = ALIGN(4);
+ LONG(0);
+/*
+ * FIXME this can break initramfs for MMU.
+ * Pad init.ramfs up to page boundary,
+ * so that __init_end == __bss_start. This will make image.elf
+ * consistent with the image.bin
+ */
+ /* . = ALIGN(4096); */
+ }
+ __init_end = .;
+
+ .bss ALIGN (4096) : { /* page aligned when MMU used */
+ __bss_start = . ;
+ *(.bss*)
+ *(COMMON)
+ . = ALIGN (4) ;
+ __bss_stop = . ;
+ _ebss = . ;
+ }
+ . = ALIGN(4096);
+ _end = .;
+}
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/kernel/heartbeat.c | 66 ++++++++++++++++++++++++++++++++++++
1 files changed, 66 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/kernel/heartbeat.c
diff --git a/arch/microblaze/kernel/heartbeat.c b/arch/microblaze/kernel/heartbeat.c
new file mode 100644
index 0000000..390bab7
--- /dev/null
+++ b/arch/microblaze/kernel/heartbeat.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2007-2008 Michal Simek <[email protected]>
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/sched.h>
+#include <linux/io.h>
+
+#include <asm/setup.h>
+#include <asm/page.h>
+#include <asm/prom.h>
+
+static unsigned int base_addr;
+
+void heartbeat(void)
+{
+ static unsigned int cnt, period, dist;
+
+ if (base_addr) {
+ if (cnt == 0 || cnt == dist)
+ out_be32(base_addr, 1);
+ else if (cnt == 7 || cnt == dist + 7)
+ out_be32(base_addr, 0);
+
+ if (++cnt > period) {
+ cnt = 0;
+ /*
+ * The hyperbolic function below modifies the heartbeat
+ * period length in dependency of the current (5min)
+ * load. It goes through the points f(0)=126, f(1)=86,
+ * f(5)=51, f(inf)->30.
+ */
+ period = ((672 << FSHIFT) / (5 * avenrun[0] +
+ (7 << FSHIFT))) + 30;
+ dist = period / 4;
+ }
+ }
+}
+
+void setup_heartbeat(void)
+{
+ struct device_node *gpio = NULL;
+ int j;
+ char *gpio_list[] = {
+ "xlnx,xps-gpio-1.00.a",
+ "xlnx,opb-gpio-1.00.a",
+ NULL
+ };
+
+ for (j = 0; gpio_list[j] != NULL; j++) {
+ gpio = of_find_compatible_node(NULL, NULL, gpio_list[j]);
+ if (gpio)
+ break;
+ }
+
+ base_addr = *(int *) of_get_property(gpio, "reg", NULL);
+ base_addr = (unsigned long) ioremap(base_addr, PAGE_SIZE);
+ printk(KERN_NOTICE "Heartbeat GPIO at 0x%x\n", base_addr);
+
+ if (*(int *) of_get_property(gpio, "xlnx,is-bidir", NULL))
+ out_be32(base_addr + 4, 0); /* GPIO is configured as output */
+}
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/bug.h | 15 +++++++++++++++
arch/microblaze/include/asm/bugs.h | 17 +++++++++++++++++
2 files changed, 32 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/bug.h
create mode 100644 arch/microblaze/include/asm/bugs.h
diff --git a/arch/microblaze/include/asm/bug.h b/arch/microblaze/include/asm/bug.h
new file mode 100644
index 0000000..8eb2cdd
--- /dev/null
+++ b/arch/microblaze/include/asm/bug.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_BUG_H
+#define _ASM_MICROBLAZE_BUG_H
+
+#include <linux/kernel.h>
+#include <asm-generic/bug.h>
+
+#endif /* _ASM_MICROBLAZE_BUG_H */
diff --git a/arch/microblaze/include/asm/bugs.h b/arch/microblaze/include/asm/bugs.h
new file mode 100644
index 0000000..f2c6593
--- /dev/null
+++ b/arch/microblaze/include/asm/bugs.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_BUGS_H
+#define _ASM_MICROBLAZE_BUGS_H
+
+static inline void check_bugs(void)
+{
+ /* nothing to do */
+}
+
+#endif /* _ASM_MICROBLAZE_BUGS_H */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/kernel/early_printk.c | 106 +++++++++++++++++++++++++++++++++
1 files changed, 106 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/kernel/early_printk.c
diff --git a/arch/microblaze/kernel/early_printk.c b/arch/microblaze/kernel/early_printk.c
new file mode 100644
index 0000000..4e2083b
--- /dev/null
+++ b/arch/microblaze/kernel/early_printk.c
@@ -0,0 +1,106 @@
+/*
+ * Early printk support for Microblaze.
+ *
+ * Copyright (C) 2007-2008 Michal Simek <[email protected]>
+ * Copyright (C) 2003-2006 Yasushi SHOJI <[email protected]>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/console.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/tty.h>
+#include <linux/io.h>
+#include <asm/processor.h>
+#include <linux/fcntl.h>
+#include <asm/setup.h>
+#include <asm/prom.h>
+
+static u32 early_console_initialized;
+static u32 base_addr;
+
+static void early_printk_putc(char c)
+{
+ /*
+ * Limit how many times we'll spin waiting for TX FIFO status.
+ * This will prevent lockups if the base address is incorrectly
+ * set, or any other issue on the UARTLITE.
+ * This limit is pretty arbitrary, unless we are at about 10 baud
+ * we'll never timeout on a working UART.
+ */
+
+ unsigned retries = 10000;
+ /* read status bit - 0x8 offset */
+ while (retries-- && (in_be32(base_addr + 8) & (1 << 3)))
+ ;
+
+ /* Only attempt the iowrite if we didn't timeout */
+ /* write to TX_FIFO - 0x4 offset */
+ if (retries)
+ out_be32(base_addr + 4, c & 0xff);
+}
+
+static void early_printk_write(struct console *unused,
+ const char *s, unsigned n)
+{
+ while (*s && n-- > 0) {
+ early_printk_putc(*s);
+ if (*s == '\n')
+ early_printk_putc('\r');
+ s++;
+ }
+}
+
+static struct console early_serial_console = {
+ .name = "earlyser",
+ .write = early_printk_write,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+};
+
+static struct console *early_console = &early_serial_console;
+
+void early_printk(const char *fmt, ...)
+{
+ char buf[512];
+ int n;
+ va_list ap;
+
+ if (early_console_initialized) {
+ va_start(ap, fmt);
+ n = vscnprintf(buf, 512, fmt, ap);
+ early_console->write(early_console, buf, n);
+ va_end(ap);
+ }
+}
+
+int __init setup_early_printk(char *opt)
+{
+ if (early_console_initialized)
+ return 1;
+
+ base_addr = early_uartlite_console();
+ if (base_addr) {
+ early_console_initialized = 1;
+ early_printk("early_printk_console is enabled at 0x%08x\n",
+ base_addr);
+
+ /* register_console(early_console); */
+
+ return 0;
+ } else
+ return 1;
+}
+
+void __init disable_early_printk(void)
+{
+ if (!early_console_initialized || !early_console)
+ return;
+ printk(KERN_WARNING "disabling early console\n");
+ unregister_console(early_console);
+ early_console_initialized = 0;
+}
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/namei.h | 22 ++++++++++++++++++++++
1 files changed, 22 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/namei.h
diff --git a/arch/microblaze/include/asm/namei.h b/arch/microblaze/include/asm/namei.h
new file mode 100644
index 0000000..61d60b8
--- /dev/null
+++ b/arch/microblaze/include/asm/namei.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_NAMEI_H
+#define _ASM_MICROBLAZE_NAMEI_H
+
+#ifdef __KERNEL__
+
+/* This dummy routine maybe changed to something useful
+ * for /usr/gnemul/ emulation stuff.
+ * Look at asm-sparc/namei.h for details.
+ */
+#define __emul_prefix() NULL
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_MICROBLAZE_NAMEI_H */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/kernel/traps.c | 105 ++++++++++++++++++++++++++++++++++++++++
1 files changed, 105 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/kernel/traps.c
diff --git a/arch/microblaze/kernel/traps.c b/arch/microblaze/kernel/traps.c
new file mode 100644
index 0000000..4863a57
--- /dev/null
+++ b/arch/microblaze/kernel/traps.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/kallsyms.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/debug_locks.h>
+
+#include <asm/exceptions.h>
+#include <asm/system.h>
+
+void trap_init(void)
+{
+ __enable_hw_exceptions();
+}
+
+void __bad_xchg(volatile void *ptr, int size)
+{
+ printk(KERN_INFO "xchg: bad data size: pc 0x%p, ptr 0x%p, size %d\n",
+ __builtin_return_address(0), ptr, size);
+ BUG();
+}
+EXPORT_SYMBOL(__bad_xchg);
+
+static int kstack_depth_to_print = 24;
+
+static int __init kstack_setup(char *s)
+{
+ kstack_depth_to_print = simple_strtoul(s, NULL, 0);
+
+ return 1;
+}
+__setup("kstack=", kstack_setup);
+
+void show_trace(struct task_struct *task, unsigned long *stack)
+{
+ unsigned long addr;
+
+ if (!stack)
+ stack = (unsigned long *)&stack;
+
+ printk(KERN_NOTICE "Call Trace: ");
+#ifdef CONFIG_KALLSYMS
+ printk(KERN_NOTICE "\n");
+#endif
+ while (!kstack_end(stack)) {
+ addr = *stack++;
+ /*
+ * If the address is either in the text segment of the
+ * kernel, or in the region which contains vmalloc'ed
+ * memory, it *may* be the address of a calling
+ * routine; if so, print it so that someone tracing
+ * down the cause of the crash will be able to figure
+ * out the call path that was taken.
+ */
+ if (kernel_text_address(addr))
+ print_ip_sym(addr);
+ }
+ printk(KERN_NOTICE "\n");
+
+ if (!task)
+ task = current;
+
+ debug_show_held_locks(task);
+}
+
+void show_stack(struct task_struct *task, unsigned long *sp)
+{
+ unsigned long *stack;
+ int i;
+
+ if (sp == NULL) {
+ if (task)
+ sp = (unsigned long *) ((struct thread_info *)
+ (task->stack))->cpu_context.r1;
+ else
+ sp = (unsigned long *)&sp;
+ }
+
+ stack = sp;
+
+ printk(KERN_INFO "\nStack:\n ");
+
+ for (i = 0; i < kstack_depth_to_print; i++) {
+ if (kstack_end(sp))
+ break;
+ if (i && ((i % 8) == 0))
+ printk("\n ");
+ printk("%08lx ", *sp++);
+ }
+ printk("\n");
+ show_trace(task, stack);
+}
+
+void dump_stack(void)
+{
+ show_stack(NULL, NULL);
+}
+EXPORT_SYMBOL(dump_stack);
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/pci-bridge.h | 1 +
arch/microblaze/include/asm/pci.h | 1 +
2 files changed, 2 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/pci-bridge.h
create mode 100644 arch/microblaze/include/asm/pci.h
diff --git a/arch/microblaze/include/asm/pci-bridge.h b/arch/microblaze/include/asm/pci-bridge.h
new file mode 100644
index 0000000..7ad28f6
--- /dev/null
+++ b/arch/microblaze/include/asm/pci-bridge.h
@@ -0,0 +1 @@
+#include <linux/pci.h>
diff --git a/arch/microblaze/include/asm/pci.h b/arch/microblaze/include/asm/pci.h
new file mode 100644
index 0000000..ca03794
--- /dev/null
+++ b/arch/microblaze/include/asm/pci.h
@@ -0,0 +1 @@
+#include <linux/io.h>
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/Kbuild | 26 ++++++++++++++++++++++++++
1 files changed, 26 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/Kbuild
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
new file mode 100644
index 0000000..31820df
--- /dev/null
+++ b/arch/microblaze/include/asm/Kbuild
@@ -0,0 +1,26 @@
+include include/asm-generic/Kbuild.asm
+
+header-y += auxvec.h
+header-y += errno.h
+header-y += fcntl.h
+header-y += ioctl.h
+header-y += ioctls.h
+header-y += ipcbuf.h
+header-y += linkage.h
+header-y += msgbuf.h
+header-y += poll.h
+header-y += resource.h
+header-y += sembuf.h
+header-y += shmbuf.h
+header-y += sigcontext.h
+header-y += siginfo.h
+header-y += socket.h
+header-y += sockios.h
+header-y += statfs.h
+header-y += stat.h
+header-y += termbits.h
+header-y += ucontext.h
+
+unifdef-y += cputable.h
+unifdef-y += elf.h
+unifdef-y += termios.h
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/sigcontext.h | 20 ++++++++++++++++++++
arch/microblaze/include/asm/siginfo.h | 15 +++++++++++++++
2 files changed, 35 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/sigcontext.h
create mode 100644 arch/microblaze/include/asm/siginfo.h
diff --git a/arch/microblaze/include/asm/sigcontext.h b/arch/microblaze/include/asm/sigcontext.h
new file mode 100644
index 0000000..55873c8
--- /dev/null
+++ b/arch/microblaze/include/asm/sigcontext.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_SIGCONTEXT_H
+#define _ASM_MICROBLAZE_SIGCONTEXT_H
+
+/* FIXME should be linux/ptrace.h */
+#include <asm/ptrace.h>
+
+struct sigcontext {
+ struct pt_regs regs;
+ unsigned long oldmask;
+};
+
+#endif /* _ASM_MICROBLAZE_SIGCONTEXT_H */
diff --git a/arch/microblaze/include/asm/siginfo.h b/arch/microblaze/include/asm/siginfo.h
new file mode 100644
index 0000000..f162911
--- /dev/null
+++ b/arch/microblaze/include/asm/siginfo.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_SIGINFO_H
+#define _ASM_MICROBLAZE_SIGINFO_H
+
+#include <linux/types.h>
+#include <asm-generic/siginfo.h>
+
+#endif /* _ASM_MICROBLAZE_SIGINFO_H */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
drivers/serial/Kconfig | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 7d7f576..131901b 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -833,7 +833,7 @@ config SERIAL_IMX_CONSOLE
config SERIAL_UARTLITE
tristate "Xilinx uartlite serial port support"
- depends on PPC32
+ depends on PPC32 || MICROBLAZE
select SERIAL_CORE
help
Say Y here if you want to use the Xilinx uartlite serial controller.
@@ -1319,7 +1319,7 @@ config SERIAL_NETX_CONSOLE
config SERIAL_OF_PLATFORM
tristate "Serial port on Open Firmware platform bus"
- depends on PPC_OF
+ depends on PPC_OF || MICROBLAZE
depends on SERIAL_8250 || SERIAL_OF_PLATFORM_NWPSERIAL
help
If you have a PowerPC based system that has serial ports
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/delay.h | 72 +++++++++++++++++++++++++++++++++++
arch/microblaze/include/asm/timex.h | 18 +++++++++
2 files changed, 90 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/delay.h
create mode 100644 arch/microblaze/include/asm/timex.h
diff --git a/arch/microblaze/include/asm/delay.h b/arch/microblaze/include/asm/delay.h
new file mode 100644
index 0000000..05b7d39
--- /dev/null
+++ b/arch/microblaze/include/asm/delay.h
@@ -0,0 +1,72 @@
+/*
+ * include/asm-microblaze/delay.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2008 Michal Simek
+ * Copyright (C) 2007 John Williams
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ */
+
+#ifndef _ASM_MICROBLAZE_DELAY_H
+#define _ASM_MICROBLAZE_DELAY_H
+
+extern inline void __delay(unsigned long loops)
+{
+ asm volatile ("# __delay \n\t" \
+ "1: addi %0, %0, -1\t\n" \
+ "bneid %0, 1b \t\n" \
+ "nop \t\n"
+ : "=r" (loops)
+ : "0" (loops));
+}
+
+/*
+ * Note that 19 * 226 == 4294 ==~ 2^32 / 10^6, so
+ * loops = (4294 * usecs * loops_per_jiffy * HZ) / 2^32.
+ *
+ * The mul instruction gives us loops = (a * b) / 2^32.
+ * We choose a = usecs * 19 * HZ and b = loops_per_jiffy * 226
+ * because this lets us support a wide range of HZ and
+ * loops_per_jiffy values without either a or b overflowing 2^32.
+ * Thus we need usecs * HZ <= (2^32 - 1) / 19 = 226050910 and
+ * loops_per_jiffy <= (2^32 - 1) / 226 = 19004280
+ * (which corresponds to ~3800 bogomips at HZ = 100).
+ * -- paulus
+ */
+#define __MAX_UDELAY (226050910UL/HZ) /* maximum udelay argument */
+#define __MAX_NDELAY (4294967295UL/HZ) /* maximum ndelay argument */
+
+extern unsigned long loops_per_jiffy;
+
+extern inline void __udelay(unsigned int x)
+{
+
+ unsigned long long tmp =
+ (unsigned long long)x * (unsigned long long)loops_per_jiffy \
+ * 226LL;
+ unsigned loops = tmp >> 32;
+
+/*
+ __asm__("mulxuu %0,%1,%2" : "=r" (loops) :
+ "r" (x), "r" (loops_per_jiffy * 226));
+*/
+ __delay(loops);
+}
+
+extern void __bad_udelay(void); /* deliberately undefined */
+extern void __bad_ndelay(void); /* deliberately undefined */
+
+#define udelay(n) (__builtin_constant_p(n) ? \
+ ((n) > __MAX_UDELAY ? __bad_udelay() : __udelay((n) * (19 * HZ))) : \
+ __udelay((n) * (19 * HZ)))
+
+#define ndelay(n) (__builtin_constant_p(n) ? \
+ ((n) > __MAX_NDELAY ? __bad_ndelay() : __udelay((n) * HZ)) : \
+ __udelay((n) * HZ))
+
+#define muldiv(a, b, c) (((a)*(b))/(c))
+
+#endif /* _ASM_MICROBLAZE_DELAY_H */
diff --git a/arch/microblaze/include/asm/timex.h b/arch/microblaze/include/asm/timex.h
new file mode 100644
index 0000000..678525d
--- /dev/null
+++ b/arch/microblaze/include/asm/timex.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_TIMEX_H
+#define _ASM_MICROBLAZE_TIMEX_H
+
+#define CLOCK_TICK_RATE 1000 /* Timer input freq. */
+
+typedef unsigned long cycles_t;
+
+#define get_cycles() (0)
+
+#endif /* _ASM_TIMEX_H */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/stat.h | 73 ++++++++++++++++++++++++++++++++++
arch/microblaze/include/asm/statfs.h | 1 +
2 files changed, 74 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/stat.h
create mode 100644 arch/microblaze/include/asm/statfs.h
diff --git a/arch/microblaze/include/asm/stat.h b/arch/microblaze/include/asm/stat.h
new file mode 100644
index 0000000..a4e148e
--- /dev/null
+++ b/arch/microblaze/include/asm/stat.h
@@ -0,0 +1,73 @@
+/*
+ * Microblaze stat structure
+ *
+ * Copyright (C) 2001,02,03 NEC Electronics Corporation
+ * Copyright (C) 2001,02,03 Miles Bader <[email protected]>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <[email protected]>
+ */
+
+#ifndef _ASM_MICROBLAZE_STAT_H
+#define _ASM_MICROBLAZE_STAT_H
+
+#include <linux/posix_types.h>
+
+struct stat {
+ unsigned int st_dev;
+ unsigned long st_ino;
+ unsigned int st_mode;
+ unsigned int st_nlink;
+ unsigned int st_uid;
+ unsigned int st_gid;
+ unsigned int st_rdev;
+ unsigned long st_size;
+ unsigned long st_blksize;
+ unsigned long st_blocks;
+ unsigned long st_atime;
+ unsigned long __unused1; /* unsigned long st_atime_nsec */
+ unsigned long st_mtime;
+ unsigned long __unused2; /* unsigned long st_mtime_nsec */
+ unsigned long st_ctime;
+ unsigned long __unused3; /* unsigned long st_ctime_nsec */
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
+
+struct stat64 {
+ unsigned long long st_dev;
+ unsigned long __unused1;
+
+ unsigned long long st_ino;
+
+ unsigned int st_mode;
+ unsigned int st_nlink;
+
+ unsigned int st_uid;
+ unsigned int st_gid;
+
+ unsigned long long st_rdev;
+ unsigned long __unused3;
+
+ long long st_size;
+ unsigned long st_blksize;
+
+ unsigned long st_blocks; /* No. of 512-byte blocks allocated */
+ unsigned long __unused4; /* future possible st_blocks high bits */
+
+ unsigned long st_atime;
+ unsigned long st_atime_nsec;
+
+ unsigned long st_mtime;
+ unsigned long st_mtime_nsec;
+
+ unsigned long st_ctime;
+ unsigned long st_ctime_nsec;
+
+ unsigned long __unused8;
+};
+
+#endif /* _ASM_MICROBLAZE_STAT_H */
diff --git a/arch/microblaze/include/asm/statfs.h b/arch/microblaze/include/asm/statfs.h
new file mode 100644
index 0000000..0b91fe1
--- /dev/null
+++ b/arch/microblaze/include/asm/statfs.h
@@ -0,0 +1 @@
+#include <asm-generic/statfs.h>
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/msgbuf.h | 31 +++++++++++++++++++++++
arch/microblaze/include/asm/shmbuf.h | 42 ++++++++++++++++++++++++++++++++
arch/microblaze/include/asm/shmparam.h | 6 ++++
3 files changed, 79 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/msgbuf.h
create mode 100644 arch/microblaze/include/asm/shmbuf.h
create mode 100644 arch/microblaze/include/asm/shmparam.h
diff --git a/arch/microblaze/include/asm/msgbuf.h b/arch/microblaze/include/asm/msgbuf.h
new file mode 100644
index 0000000..09dd970
--- /dev/null
+++ b/arch/microblaze/include/asm/msgbuf.h
@@ -0,0 +1,31 @@
+#ifndef _ASM_MICROBLAZE_MSGBUF_H
+#define _ASM_MICROBLAZE_MSGBUF_H
+
+/*
+ * The msqid64_ds structure for microblaze architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct msqid64_ds {
+ struct ipc64_perm msg_perm;
+ __kernel_time_t msg_stime; /* last msgsnd time */
+ unsigned long __unused1;
+ __kernel_time_t msg_rtime; /* last msgrcv time */
+ unsigned long __unused2;
+ __kernel_time_t msg_ctime; /* last change time */
+ unsigned long __unused3;
+ unsigned long msg_cbytes; /* current number of bytes on queue */
+ unsigned long msg_qnum; /* number of messages in queue */
+ unsigned long msg_qbytes; /* max number of bytes on queue */
+ __kernel_pid_t msg_lspid; /* pid of last msgsnd */
+ __kernel_pid_t msg_lrpid; /* last receive pid */
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
+
+#endif /* _ASM_MICROBLAZE_MSGBUF_H */
diff --git a/arch/microblaze/include/asm/shmbuf.h b/arch/microblaze/include/asm/shmbuf.h
new file mode 100644
index 0000000..f829c58
--- /dev/null
+++ b/arch/microblaze/include/asm/shmbuf.h
@@ -0,0 +1,42 @@
+#ifndef _ASM_MICROBLAZE_SHMBUF_H
+#define _ASM_MICROBLAZE_SHMBUF_H
+
+/*
+ * The shmid64_ds structure for microblaze architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct shmid64_ds {
+ struct ipc64_perm shm_perm; /* operation perms */
+ size_t shm_segsz; /* size of segment (bytes) */
+ __kernel_time_t shm_atime; /* last attach time */
+ unsigned long __unused1;
+ __kernel_time_t shm_dtime; /* last detach time */
+ unsigned long __unused2;
+ __kernel_time_t shm_ctime; /* last change time */
+ unsigned long __unused3;
+ __kernel_pid_t shm_cpid; /* pid of creator */
+ __kernel_pid_t shm_lpid; /* pid of last operator */
+ unsigned long shm_nattch; /* no. of current attaches */
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
+
+struct shminfo64 {
+ unsigned long shmmax;
+ unsigned long shmmin;
+ unsigned long shmmni;
+ unsigned long shmseg;
+ unsigned long shmall;
+ unsigned long __unused1;
+ unsigned long __unused2;
+ unsigned long __unused3;
+ unsigned long __unused4;
+};
+
+#endif /* _ASM_MICROBLAZE_SHMBUF_H */
diff --git a/arch/microblaze/include/asm/shmparam.h b/arch/microblaze/include/asm/shmparam.h
new file mode 100644
index 0000000..9f5fc2b
--- /dev/null
+++ b/arch/microblaze/include/asm/shmparam.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_MICROBLAZE_SHMPARAM_H
+#define _ASM_MICROBLAZE_SHMPARAM_H
+
+#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */
+
+#endif /* _ASM_MICROBLAZE_SHMPARAM_H */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/pgalloc.h | 14 ++++++++
arch/microblaze/include/asm/pgtable.h | 54 +++++++++++++++++++++++++++++++++
2 files changed, 68 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/pgalloc.h
create mode 100644 arch/microblaze/include/asm/pgtable.h
diff --git a/arch/microblaze/include/asm/pgalloc.h b/arch/microblaze/include/asm/pgalloc.h
new file mode 100644
index 0000000..2a4b354
--- /dev/null
+++ b/arch/microblaze/include/asm/pgalloc.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_PGALLOC_H
+#define _ASM_MICROBLAZE_PGALLOC_H
+
+#define check_pgt_cache() do {} while (0)
+
+#endif /* _ASM_MICROBLAZE_PGALLOC_H */
diff --git a/arch/microblaze/include/asm/pgtable.h b/arch/microblaze/include/asm/pgtable.h
new file mode 100644
index 0000000..4df31e4
--- /dev/null
+++ b/arch/microblaze/include/asm/pgtable.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_PGTABLE_H
+#define _ASM_MICROBLAZE_PGTABLE_H
+
+#include <asm/setup.h>
+
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+ remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+#define pgd_present(pgd) (1) /* pages are always present on non MMU */
+#define pgd_none(pgd) (0)
+#define pgd_bad(pgd) (0)
+#define pgd_clear(pgdp)
+#define kern_addr_valid(addr) (1)
+#define pmd_offset(a, b) ((void *) 0)
+
+#define PAGE_NONE __pgprot(0) /* these mean nothing to non MMU */
+#define PAGE_SHARED __pgprot(0) /* these mean nothing to non MMU */
+#define PAGE_COPY __pgprot(0) /* these mean nothing to non MMU */
+#define PAGE_READONLY __pgprot(0) /* these mean nothing to non MMU */
+#define PAGE_KERNEL __pgprot(0) /* these mean nothing to non MMU */
+
+#define __swp_type(x) (0)
+#define __swp_offset(x) (0)
+#define __swp_entry(typ, off) ((swp_entry_t) { ((typ) | ((off) << 7)) })
+#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
+#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
+
+#ifndef __ASSEMBLY__
+static inline int pte_file(pte_t pte) { return 0; }
+#endif /* __ASSEMBLY__ */
+
+#define ZERO_PAGE(vaddr) ({ BUG(); NULL; })
+
+#define swapper_pg_dir ((pgd_t *) NULL)
+
+#define pgtable_cache_init() do {} while (0)
+
+#define arch_enter_lazy_cpu_mode() do {} while (0)
+
+#ifndef __ASSEMBLY__
+#include <asm-generic/pgtable.h>
+
+void setup_memory(void);
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_MICROBLAZE_PGTABLE_H */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/ioctl.h | 1 +
arch/microblaze/include/asm/ioctls.h | 91 ++++++++++++++++++++++++++++++++++
2 files changed, 92 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/ioctl.h
create mode 100644 arch/microblaze/include/asm/ioctls.h
diff --git a/arch/microblaze/include/asm/ioctl.h b/arch/microblaze/include/asm/ioctl.h
new file mode 100644
index 0000000..b279fe0
--- /dev/null
+++ b/arch/microblaze/include/asm/ioctl.h
@@ -0,0 +1 @@
+#include <asm-generic/ioctl.h>
diff --git a/arch/microblaze/include/asm/ioctls.h b/arch/microblaze/include/asm/ioctls.h
new file mode 100644
index 0000000..03582b2
--- /dev/null
+++ b/arch/microblaze/include/asm/ioctls.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_IOCTLS_H
+#define _ASM_MICROBLAZE_IOCTLS_H
+
+#include <linux/ioctl.h>
+
+/* 0x54 is just a magic number to make these relatively unique ('T') */
+
+#define TCGETS 0x5401
+#define TCSETS 0x5402
+#define TCSETSW 0x5403
+#define TCSETSF 0x5404
+#define TCGETA 0x5405
+#define TCSETA 0x5406
+#define TCSETAW 0x5407
+#define TCSETAF 0x5408
+#define TCSBRK 0x5409
+#define TCXONC 0x540A
+#define TCFLSH 0x540B
+#define TIOCEXCL 0x540C
+#define TIOCNXCL 0x540D
+#define TIOCSCTTY 0x540E
+#define TIOCGPGRP 0x540F
+#define TIOCSPGRP 0x5410
+#define TIOCOUTQ 0x5411
+#define TIOCSTI 0x5412
+#define TIOCGWINSZ 0x5413
+#define TIOCSWINSZ 0x5414
+#define TIOCMGET 0x5415
+#define TIOCMBIS 0x5416
+#define TIOCMBIC 0x5417
+#define TIOCMSET 0x5418
+#define TIOCGSOFTCAR 0x5419
+#define TIOCSSOFTCAR 0x541A
+#define FIONREAD 0x541B
+#define TIOCINQ FIONREAD
+#define TIOCLINUX 0x541C
+#define TIOCCONS 0x541D
+#define TIOCGSERIAL 0x541E
+#define TIOCSSERIAL 0x541F
+#define TIOCPKT 0x5420
+#define FIONBIO 0x5421
+#define TIOCNOTTY 0x5422
+#define TIOCSETD 0x5423
+#define TIOCGETD 0x5424
+#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
+#define TIOCTTYGSTRUCT 0x5426 /* For debugging only */
+#define TIOCSBRK 0x5427 /* BSD compatibility */
+#define TIOCCBRK 0x5428 /* BSD compatibility */
+#define TIOCGSID 0x5429 /* Return the session ID of FD */
+/* Get Pty Number (of pty-mux device) */
+#define TIOCGPTN _IOR('T', 0x30, unsigned int)
+#define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */
+
+#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
+#define FIOCLEX 0x5451
+#define FIOASYNC 0x5452
+#define TIOCSERCONFIG 0x5453
+#define TIOCSERGWILD 0x5454
+#define TIOCSERSWILD 0x5455
+#define TIOCGLCKTRMIOS 0x5456
+#define TIOCSLCKTRMIOS 0x5457
+#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
+#define TIOCSERGETLSR 0x5459 /* Get line status register */
+#define TIOCSERGETMULTI 0x545A /* Get multiport config */
+#define TIOCSERSETMULTI 0x545B /* Set multiport config */
+
+#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
+#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
+
+#define FIOQSIZE 0x545E
+
+/* Used for packet mode */
+#define TIOCPKT_DATA 0
+#define TIOCPKT_FLUSHREAD 1
+#define TIOCPKT_FLUSHWRITE 2
+#define TIOCPKT_STOP 4
+#define TIOCPKT_START 8
+#define TIOCPKT_NOSTOP 16
+#define TIOCPKT_DOSTOP 32
+
+#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
+
+#endif /* _ASM_MICROBLAZE_IOCTLS_H */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/poll.h | 1 +
arch/microblaze/include/asm/socket.h | 66 ++++++++++++++++++++++++++++++++++
2 files changed, 67 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/poll.h
create mode 100644 arch/microblaze/include/asm/socket.h
diff --git a/arch/microblaze/include/asm/poll.h b/arch/microblaze/include/asm/poll.h
new file mode 100644
index 0000000..c98509d
--- /dev/null
+++ b/arch/microblaze/include/asm/poll.h
@@ -0,0 +1 @@
+#include <asm-generic/poll.h>
diff --git a/arch/microblaze/include/asm/socket.h b/arch/microblaze/include/asm/socket.h
new file mode 100644
index 0000000..f919b6b
--- /dev/null
+++ b/arch/microblaze/include/asm/socket.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_SOCKET_H
+#define _ASM_MICROBLAZE_SOCKET_H
+
+#include <asm/sockios.h>
+
+/* For setsockoptions(2) */
+#define SOL_SOCKET 1
+
+#define SO_DEBUG 1
+#define SO_REUSEADDR 2
+#define SO_TYPE 3
+#define SO_ERROR 4
+#define SO_DONTROUTE 5
+#define SO_BROADCAST 6
+#define SO_SNDBUF 7
+#define SO_RCVBUF 8
+#define SO_SNDBUFFORCE 32
+#define SO_RCVBUFFORCE 33
+#define SO_KEEPALIVE 9
+#define SO_OOBINLINE 10
+#define SO_NO_CHECK 11
+#define SO_PRIORITY 12
+#define SO_LINGER 13
+#define SO_BSDCOMPAT 14
+/* To add :#define SO_REUSEPORT 15 */
+#define SO_PASSCRED 16
+#define SO_PEERCRED 17
+#define SO_RCVLOWAT 18
+#define SO_SNDLOWAT 19
+#define SO_RCVTIMEO 20
+#define SO_SNDTIMEO 21
+
+/* Security levels - as per NRL IPv6 - don't actually do anything */
+#define SO_SECURITY_AUTHENTICATION 22
+#define SO_SECURITY_ENCRYPTION_TRANSPORT 23
+#define SO_SECURITY_ENCRYPTION_NETWORK 24
+
+#define SO_BINDTODEVICE 25
+
+/* Socket filtering */
+#define SO_ATTACH_FILTER 26
+#define SO_DETACH_FILTER 27
+
+#define SO_PEERNAME 28
+#define SO_TIMESTAMP 29
+#define SCM_TIMESTAMP SO_TIMESTAMP
+
+#define SO_ACCEPTCONN 30
+
+#define SO_PEERSEC 31
+#define SO_PASSSEC 34
+
+#define SO_TIMESTAMPNS 35
+#define SCM_TIMESTAMPNS SO_TIMESTAMPNS
+
+#define SO_MARK 36
+
+#endif /* _ASM_MICROBLAZE_SOCKET_H */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/syscalls.h | 45 ++++++++++++++++++++++++++++++++
1 files changed, 45 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/syscalls.h
diff --git a/arch/microblaze/include/asm/syscalls.h b/arch/microblaze/include/asm/syscalls.h
new file mode 100644
index 0000000..9cb4ff0
--- /dev/null
+++ b/arch/microblaze/include/asm/syscalls.h
@@ -0,0 +1,45 @@
+#ifndef __ASM_MICROBLAZE_SYSCALLS_H
+#define __ASM_MICROBLAZE_SYSCALLS_H
+#ifdef __KERNEL__
+
+#include <linux/compiler.h>
+#include <linux/linkage.h>
+#include <linux/types.h>
+#include <linux/signal.h>
+
+/* FIXME will be removed */
+asmlinkage int sys_ipc(uint call, int first, int second,
+ int third, void *ptr, long fifth);
+
+struct pt_regs;
+asmlinkage int sys_vfork(struct pt_regs *regs);
+asmlinkage int sys_clone(int flags, unsigned long stack, struct pt_regs *regs);
+asmlinkage int sys_execve(char __user *filenamei, char __user *__user *argv,
+ char __user *__user *envp, struct pt_regs *regs);
+
+asmlinkage unsigned long sys_mmap2(unsigned long addr, size_t len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long pgoff);
+
+asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, off_t offset);
+
+/* from signal.c */
+asmlinkage int sys_sigsuspend(old_sigset_t mask, struct pt_regs *regs);
+
+asmlinkage int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize,
+ struct pt_regs *regs);
+
+asmlinkage int sys_sigaction(int sig, const struct old_sigaction *act,
+ struct old_sigaction *oact);
+
+asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
+ struct pt_regs *regs);
+
+asmlinkage int sys_sigreturn(struct pt_regs *regs);
+
+asmlinkage int sys_rt_sigreturn(struct pt_regs *regs);
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_MICROBLAZE_SYSCALLS_H */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/clinkage.h | 1 +
arch/microblaze/include/asm/kmap_types.h | 29 +++++++++++++++++++++++++++++
arch/microblaze/include/asm/linkage.h | 15 +++++++++++++++
arch/microblaze/include/asm/sections.h | 25 +++++++++++++++++++++++++
4 files changed, 70 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/clinkage.h
create mode 100644 arch/microblaze/include/asm/kmap_types.h
create mode 100644 arch/microblaze/include/asm/linkage.h
create mode 100644 arch/microblaze/include/asm/sections.h
diff --git a/arch/microblaze/include/asm/clinkage.h b/arch/microblaze/include/asm/clinkage.h
new file mode 100644
index 0000000..9e21843
--- /dev/null
+++ b/arch/microblaze/include/asm/clinkage.h
@@ -0,0 +1 @@
+#include <linux/linkage.h>
diff --git a/arch/microblaze/include/asm/kmap_types.h b/arch/microblaze/include/asm/kmap_types.h
new file mode 100644
index 0000000..4d7e222
--- /dev/null
+++ b/arch/microblaze/include/asm/kmap_types.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_KMAP_TYPES_H
+#define _ASM_MICROBLAZE_KMAP_TYPES_H
+
+enum km_type {
+ KM_BOUNCE_READ,
+ KM_SKB_SUNRPC_DATA,
+ KM_SKB_DATA_SOFTIRQ,
+ KM_USER0,
+ KM_USER1,
+ KM_BIO_SRC_IRQ,
+ KM_BIO_DST_IRQ,
+ KM_PTE0,
+ KM_PTE1,
+ KM_IRQ0,
+ KM_IRQ1,
+ KM_SOFTIRQ0,
+ KM_SOFTIRQ1,
+ KM_TYPE_NR,
+};
+
+#endif /* _ASM_MICROBLAZE_KMAP_TYPES_H */
diff --git a/arch/microblaze/include/asm/linkage.h b/arch/microblaze/include/asm/linkage.h
new file mode 100644
index 0000000..3a8e36d
--- /dev/null
+++ b/arch/microblaze/include/asm/linkage.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_LINKAGE_H
+#define _ASM_MICROBLAZE_LINKAGE_H
+
+#define __ALIGN .align 4
+#define __ALIGN_STR ".align 4"
+
+#endif /* _ASM_MICROBLAZE_LINKAGE_H */
diff --git a/arch/microblaze/include/asm/sections.h b/arch/microblaze/include/asm/sections.h
new file mode 100644
index 0000000..8434a43
--- /dev/null
+++ b/arch/microblaze/include/asm/sections.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_SECTIONS_H
+#define _ASM_MICROBLAZE_SECTIONS_H
+
+#include <asm-generic/sections.h>
+
+# ifndef __ASSEMBLY__
+extern char _ssbss[], _esbss[];
+extern unsigned long __ivt_start[], __ivt_end[];
+
+# ifdef CONFIG_MTD_UCLINUX
+extern char *_ebss;
+# endif
+
+extern u32 _fdt_start[], _fdt_end[];
+
+# endif /* !__ASSEMBLY__ */
+#endif /* _ASM_MICROBLAZE_SECTIONS_H */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/fcntl.h | 1 +
arch/microblaze/include/asm/sockios.h | 23 +++++++++++++++++++++++
arch/microblaze/include/asm/ucontext.h | 22 ++++++++++++++++++++++
3 files changed, 46 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/fcntl.h
create mode 100644 arch/microblaze/include/asm/sockios.h
create mode 100644 arch/microblaze/include/asm/ucontext.h
diff --git a/arch/microblaze/include/asm/fcntl.h b/arch/microblaze/include/asm/fcntl.h
new file mode 100644
index 0000000..46ab12d
--- /dev/null
+++ b/arch/microblaze/include/asm/fcntl.h
@@ -0,0 +1 @@
+#include <asm-generic/fcntl.h>
diff --git a/arch/microblaze/include/asm/sockios.h b/arch/microblaze/include/asm/sockios.h
new file mode 100644
index 0000000..9fff57a
--- /dev/null
+++ b/arch/microblaze/include/asm/sockios.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_SOCKIOS_H
+#define _ASM_MICROBLAZE_SOCKIOS_H
+
+#include <linux/ioctl.h>
+
+/* Socket-level I/O control calls. */
+#define FIOSETOWN 0x8901
+#define SIOCSPGRP 0x8902
+#define FIOGETOWN 0x8903
+#define SIOCGPGRP 0x8904
+#define SIOCATMARK 0x8905
+#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */
+#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
+
+#endif /* _ASM_MICROBLAZE_SOCKIOS_H */
diff --git a/arch/microblaze/include/asm/ucontext.h b/arch/microblaze/include/asm/ucontext.h
new file mode 100644
index 0000000..11f6bb3
--- /dev/null
+++ b/arch/microblaze/include/asm/ucontext.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_UCONTEXT_H
+#define _ASM_MICROBLAZE_UCONTEXT_H
+
+#include <asm/sigcontext.h>
+
+struct ucontext {
+ unsigned long uc_flags;
+ struct ucontext *uc_link;
+ stack_t uc_stack;
+ struct sigcontext uc_mcontext;
+ sigset_t uc_sigmask; /* mask last for extensibility */
+};
+
+#endif /* _ASM_MICROBLAZE_UCONTEXT_H */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/device.h | 21 +++++++++++++++++++++
arch/microblaze/include/asm/param.h | 30 ++++++++++++++++++++++++++++++
arch/microblaze/include/asm/topology.h | 11 +++++++++++
3 files changed, 62 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/device.h
create mode 100644 arch/microblaze/include/asm/param.h
create mode 100644 arch/microblaze/include/asm/topology.h
diff --git a/arch/microblaze/include/asm/device.h b/arch/microblaze/include/asm/device.h
new file mode 100644
index 0000000..c042830
--- /dev/null
+++ b/arch/microblaze/include/asm/device.h
@@ -0,0 +1,21 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License v2. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_DEVICE_H
+#define _ASM_MICROBLAZE_DEVICE_H
+
+struct device_node;
+
+struct dev_archdata {
+ /* Optional pointer to an OF device node */
+ struct device_node *of_node;
+};
+
+#endif /* _ASM_MICROBLAZE_DEVICE_H */
+
+
diff --git a/arch/microblaze/include/asm/param.h b/arch/microblaze/include/asm/param.h
new file mode 100644
index 0000000..8c538a4
--- /dev/null
+++ b/arch/microblaze/include/asm/param.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_PARAM_H
+#define _ASM_MICROBLAZE_PARAM_H
+
+#ifdef __KERNEL__
+#define HZ CONFIG_HZ /* internal kernel timer frequency */
+#define USER_HZ 100 /* for user interfaces in "ticks" */
+#define CLOCKS_PER_SEC (USER_HZ) /* frequency at which times() counts */
+#endif /* __KERNEL__ */
+
+#ifndef HZ
+#define HZ 100
+#endif
+
+#define EXEC_PAGESIZE 4096
+
+#ifndef NOGROUP
+#define NOGROUP (-1)
+#endif
+
+#define MAXHOSTNAMELEN 64 /* max length of hostname */
+
+#endif /* _ASM_MICROBLAZE_PARAM_H */
diff --git a/arch/microblaze/include/asm/topology.h b/arch/microblaze/include/asm/topology.h
new file mode 100644
index 0000000..96bcea5
--- /dev/null
+++ b/arch/microblaze/include/asm/topology.h
@@ -0,0 +1,11 @@
+#include <asm-generic/topology.h>
+
+#ifndef _ASM_MICROBLAZE_TOPOLOGY_H
+#define _ASM_MICROBLAZE_TOPOLOGY_H
+
+struct device_node;
+static inline int of_node_to_nid(struct device_node *device)
+{
+ return 0;
+}
+#endif /* _ASM_MICROBLAZE_TOPOLOGY_H */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/elf.h | 30 ++++++++++++
arch/microblaze/include/asm/flat.h | 90 ++++++++++++++++++++++++++++++++++++
2 files changed, 120 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/elf.h
create mode 100644 arch/microblaze/include/asm/flat.h
diff --git a/arch/microblaze/include/asm/elf.h b/arch/microblaze/include/asm/elf.h
new file mode 100644
index 0000000..81337f2
--- /dev/null
+++ b/arch/microblaze/include/asm/elf.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_ELF_H
+#define _ASM_MICROBLAZE_ELF_H
+
+/*
+ * Note there is no "official" ELF designation for Microblaze.
+ * I've snaffled the value from the microblaze binutils source code
+ * /binutils/microblaze/include/elf/microblaze.h
+ */
+#define EM_XILINX_MICROBLAZE 0xbaab
+#define ELF_ARCH EM_XILINX_MICROBLAZE
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) ((x)->e_machine == EM_XILINX_MICROBLAZE)
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS ELFCLASS32
+
+#endif /* _ASM_MICROBLAZE_ELF_H */
diff --git a/arch/microblaze/include/asm/flat.h b/arch/microblaze/include/asm/flat.h
new file mode 100644
index 0000000..acf0da5
--- /dev/null
+++ b/arch/microblaze/include/asm/flat.h
@@ -0,0 +1,90 @@
+/*
+ * uClinux flat-format executables
+ *
+ * Copyright (C) 2005 John Williams <[email protected]>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_FLAT_H
+#define _ASM_MICROBLAZE_FLAT_H
+
+#include <asm/unaligned.h>
+
+#define flat_stack_align(sp) /* nothing needed */
+#define flat_argvp_envp_on_stack() 0
+#define flat_old_ram_flag(flags) (flags)
+#define flat_reloc_valid(reloc, size) ((reloc) <= (size))
+#define flat_set_persistent(relval, p) 0
+
+/*
+ * Microblaze works a little differently from other arches, because
+ * of the MICROBLAZE_64 reloc type. Here, a 32 bit address is split
+ * over two instructions, an 'imm' instruction which provides the top
+ * 16 bits, then the instruction "proper" which provides the low 16
+ * bits.
+ */
+
+/*
+ * Crack open a symbol reference and extract the address to be
+ * relocated. rp is a potentially unaligned pointer to the
+ * reference
+ */
+
+static inline unsigned long
+flat_get_addr_from_rp(unsigned long *rp, unsigned long relval,
+ unsigned long flags, unsigned long *persistent)
+{
+ unsigned long addr;
+ (void)flags;
+
+ /* Is it a split 64/32 reference? */
+ if (relval & 0x80000000) {
+ /* Grab the two halves of the reference */
+ unsigned long val_hi, val_lo;
+
+ val_hi = get_unaligned(rp);
+ val_lo = get_unaligned(rp+1);
+
+ /* Crack the address out */
+ addr = ((val_hi & 0xffff) << 16) + (val_lo & 0xffff);
+ } else {
+ /* Get the address straight out */
+ addr = get_unaligned(rp);
+ }
+
+ return addr;
+}
+
+/*
+ * Insert an address into the symbol reference at rp. rp is potentially
+ * unaligned.
+ */
+
+static inline void
+flat_put_addr_at_rp(unsigned long *rp, unsigned long addr, unsigned long relval)
+{
+ /* Is this a split 64/32 reloc? */
+ if (relval & 0x80000000) {
+ /* Get the two "halves" */
+ unsigned long val_hi = get_unaligned(rp);
+ unsigned long val_lo = get_unaligned(rp + 1);
+
+ /* insert the address */
+ val_hi = (val_hi & 0xffff0000) | addr >> 16;
+ val_lo = (val_lo & 0xffff0000) | (addr & 0xffff);
+
+ /* store the two halves back into memory */
+ put_unaligned(val_hi, rp);
+ put_unaligned(val_lo, rp+1);
+ } else {
+ /* Put it straight in, no messing around */
+ put_unaligned(addr, rp);
+ }
+}
+
+#define flat_get_relocate_addr(rel) (rel & 0x7fffffff)
+
+#endif /* _ASM_MICROBLAZE_FLAT_H */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/posix_types.h | 69 +++++++++++++++++++++++++++++
arch/microblaze/include/asm/types.h | 38 ++++++++++++++++
2 files changed, 107 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/posix_types.h
create mode 100644 arch/microblaze/include/asm/types.h
diff --git a/arch/microblaze/include/asm/posix_types.h b/arch/microblaze/include/asm/posix_types.h
new file mode 100644
index 0000000..c858eb7
--- /dev/null
+++ b/arch/microblaze/include/asm/posix_types.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_POSIX_TYPES_H
+#define _ASM_MICROBLAZE_POSIX_TYPES_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc. Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned long __kernel_ino_t;
+typedef unsigned int __kernel_mode_t;
+typedef unsigned int __kernel_nlink_t;
+typedef long __kernel_off_t;
+typedef int __kernel_pid_t;
+typedef unsigned int __kernel_ipc_pid_t;
+typedef unsigned int __kernel_uid_t;
+typedef unsigned int __kernel_gid_t;
+typedef unsigned long __kernel_size_t;
+typedef long __kernel_ssize_t;
+typedef int __kernel_ptrdiff_t;
+typedef long __kernel_time_t;
+typedef long __kernel_suseconds_t;
+typedef long __kernel_clock_t;
+typedef int __kernel_timer_t;
+typedef int __kernel_clockid_t;
+typedef int __kernel_daddr_t;
+typedef char * __kernel_caddr_t;
+typedef unsigned short __kernel_uid16_t;
+typedef unsigned short __kernel_gid16_t;
+typedef unsigned int __kernel_uid32_t;
+typedef unsigned int __kernel_gid32_t;
+
+#ifdef __GNUC__
+typedef long long __kernel_loff_t;
+#endif
+
+typedef struct {
+#if defined(__KERNEL__) || defined(__USE_ALL)
+ int val[2];
+#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+ int __val[2];
+#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+} __kernel_fsid_t;
+
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+
+#undef __FD_SET
+#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
+
+#undef __FD_CLR
+#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
+
+#undef __FD_ISSET
+#define __FD_ISSET(d, set) (!!((set)->fds_bits[__FDELT(d)] & __FDMASK(d)))
+
+#undef __FD_ZERO
+#define __FD_ZERO(fdsetp) (memset(fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
+
+#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+
+#endif /* _ASM_MICROBLAZE_POSIX_TYPES_H */
diff --git a/arch/microblaze/include/asm/types.h b/arch/microblaze/include/asm/types.h
new file mode 100644
index 0000000..bebc018
--- /dev/null
+++ b/arch/microblaze/include/asm/types.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_TYPES_H
+#define _ASM_MICROBLAZE_TYPES_H
+
+/*
+ * This file is never included by application software unless
+ * explicitly requested (e.g., via linux/types.h) in which case the
+ * application is Linux specific so (user-) name space pollution is
+ * not a major issue. However, for interoperability, libraries still
+ * need to be careful to avoid a name clashes.
+ */
+
+#include <asm-generic/int-ll64.h>
+
+# ifndef __ASSEMBLY__
+
+typedef unsigned short umode_t;
+
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+# ifdef __KERNEL__
+# define BITS_PER_LONG 32
+
+/* Dma addresses are 32-bits wide. */
+
+typedef u32 dma_addr_t;
+
+# endif/* __KERNEL__ */
+# endif /* __ASSEMBLY__ */
+#endif /* _ASM_MICROBLAZE_TYPES_H */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/kernel/asm-offsets.c | 115 ++++++++++++++++++++++++++++++++++
1 files changed, 115 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/kernel/asm-offsets.c
diff --git a/arch/microblaze/kernel/asm-offsets.c b/arch/microblaze/kernel/asm-offsets.c
new file mode 100644
index 0000000..799283a
--- /dev/null
+++ b/arch/microblaze/kernel/asm-offsets.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2007 PetaLogix
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/ptrace.h>
+#include <linux/hardirq.h>
+#include <linux/thread_info.h>
+#include <linux/kbuild.h>
+
+int main(int argc, char *argv[])
+{
+ /* struct pt_regs */
+ DEFINE(PT_SIZE, sizeof(struct pt_regs));
+ DEFINE(PT_MSR, offsetof(struct pt_regs, msr));
+ DEFINE(PT_EAR, offsetof(struct pt_regs, ear));
+ DEFINE(PT_ESR, offsetof(struct pt_regs, esr));
+ DEFINE(PT_FSR, offsetof(struct pt_regs, fsr));
+ DEFINE(PT_PC, offsetof(struct pt_regs, pc));
+ DEFINE(PT_R0, offsetof(struct pt_regs, r0));
+ DEFINE(PT_R1, offsetof(struct pt_regs, r1));
+ DEFINE(PT_R2, offsetof(struct pt_regs, r2));
+ DEFINE(PT_R3, offsetof(struct pt_regs, r3));
+ DEFINE(PT_R4, offsetof(struct pt_regs, r4));
+ DEFINE(PT_R5, offsetof(struct pt_regs, r5));
+ DEFINE(PT_R6, offsetof(struct pt_regs, r6));
+ DEFINE(PT_R7, offsetof(struct pt_regs, r7));
+ DEFINE(PT_R8, offsetof(struct pt_regs, r8));
+ DEFINE(PT_R9, offsetof(struct pt_regs, r9));
+ DEFINE(PT_R10, offsetof(struct pt_regs, r10));
+ DEFINE(PT_R11, offsetof(struct pt_regs, r11));
+ DEFINE(PT_R12, offsetof(struct pt_regs, r12));
+ DEFINE(PT_R13, offsetof(struct pt_regs, r13));
+ DEFINE(PT_R14, offsetof(struct pt_regs, r14));
+ DEFINE(PT_R15, offsetof(struct pt_regs, r15));
+ DEFINE(PT_R16, offsetof(struct pt_regs, r16));
+ DEFINE(PT_R17, offsetof(struct pt_regs, r17));
+ DEFINE(PT_R18, offsetof(struct pt_regs, r18));
+ DEFINE(PT_R19, offsetof(struct pt_regs, r19));
+ DEFINE(PT_R20, offsetof(struct pt_regs, r20));
+ DEFINE(PT_R21, offsetof(struct pt_regs, r21));
+ DEFINE(PT_R22, offsetof(struct pt_regs, r22));
+ DEFINE(PT_R23, offsetof(struct pt_regs, r23));
+ DEFINE(PT_R24, offsetof(struct pt_regs, r24));
+ DEFINE(PT_R25, offsetof(struct pt_regs, r25));
+ DEFINE(PT_R26, offsetof(struct pt_regs, r26));
+ DEFINE(PT_R27, offsetof(struct pt_regs, r27));
+ DEFINE(PT_R28, offsetof(struct pt_regs, r28));
+ DEFINE(PT_R29, offsetof(struct pt_regs, r29));
+ DEFINE(PT_R30, offsetof(struct pt_regs, r30));
+ DEFINE(PT_R31, offsetof(struct pt_regs, r31));
+ DEFINE(PT_MODE, offsetof(struct pt_regs, kernel_mode));
+ BLANK();
+
+ /* Magic offsets for PTRACE PEEK/POKE etc */
+ DEFINE(PT_TEXT_ADDR, sizeof(struct pt_regs) + 1);
+ DEFINE(PT_TEXT_LEN, sizeof(struct pt_regs) + 2);
+ DEFINE(PT_DATA_ADDR, sizeof(struct pt_regs) + 3);
+ BLANK();
+
+ /* struct task_struct */
+ DEFINE(TS_THREAD_INFO, offsetof(struct task_struct, stack));
+
+ /* struct thread_info */
+ DEFINE(TI_TASK, offsetof(struct thread_info, task));
+ DEFINE(TI_EXEC_DOMAIN, offsetof(struct thread_info, exec_domain));
+ DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+ DEFINE(TI_STATUS, offsetof(struct thread_info, status));
+ DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
+ DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count));
+ DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit));
+ DEFINE(TI_RESTART_BLOCK, offsetof(struct thread_info, restart_block));
+ DEFINE(TI_CPU_CONTEXT, offsetof(struct thread_info, cpu_context));
+ BLANK();
+
+ /* struct cpu_context */
+ DEFINE(CC_R1, offsetof(struct cpu_context, r1)); /* r1 */
+ DEFINE(CC_R2, offsetof(struct cpu_context, r2));
+ /* dedicated registers */
+ DEFINE(CC_R13, offsetof(struct cpu_context, r13));
+ DEFINE(CC_R14, offsetof(struct cpu_context, r14));
+ DEFINE(CC_R15, offsetof(struct cpu_context, r15));
+ DEFINE(CC_R16, offsetof(struct cpu_context, r16));
+ DEFINE(CC_R17, offsetof(struct cpu_context, r17));
+ DEFINE(CC_R18, offsetof(struct cpu_context, r18));
+ /* non-volatile registers */
+ DEFINE(CC_R19, offsetof(struct cpu_context, r19));
+ DEFINE(CC_R20, offsetof(struct cpu_context, r20));
+ DEFINE(CC_R21, offsetof(struct cpu_context, r21));
+ DEFINE(CC_R22, offsetof(struct cpu_context, r22));
+ DEFINE(CC_R23, offsetof(struct cpu_context, r23));
+ DEFINE(CC_R24, offsetof(struct cpu_context, r24));
+ DEFINE(CC_R25, offsetof(struct cpu_context, r25));
+ DEFINE(CC_R26, offsetof(struct cpu_context, r26));
+ DEFINE(CC_R27, offsetof(struct cpu_context, r27));
+ DEFINE(CC_R28, offsetof(struct cpu_context, r28));
+ DEFINE(CC_R29, offsetof(struct cpu_context, r29));
+ DEFINE(CC_R30, offsetof(struct cpu_context, r30));
+ /* special purpose registers */
+ DEFINE(CC_MSR, offsetof(struct cpu_context, msr));
+ DEFINE(CC_EAR, offsetof(struct cpu_context, ear));
+ DEFINE(CC_ESR, offsetof(struct cpu_context, esr));
+ DEFINE(CC_FSR, offsetof(struct cpu_context, fsr));
+ BLANK();
+
+ return 0;
+}
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/uaccess.h | 134 +++++++++++++++++++++++++++++++++
arch/microblaze/lib/uaccess.c | 41 ++++++++++
2 files changed, 175 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/uaccess.h
create mode 100644 arch/microblaze/lib/uaccess.c
diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h
new file mode 100644
index 0000000..5a3ffc3
--- /dev/null
+++ b/arch/microblaze/include/asm/uaccess.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_UACCESS_H
+#define _ASM_MICROBLAZE_UACCESS_H
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/sched.h> /* RLIMIT_FSIZE */
+#include <linux/mm.h>
+
+#include <asm/mmu.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/segment.h>
+#include <linux/string.h>
+
+#define VERIFY_READ 0
+#define VERIFY_WRITE 1
+
+extern int ___range_ok(unsigned long addr, unsigned long size);
+
+#define __range_ok(addr, size) \
+ ___range_ok((unsigned long)(addr), (unsigned long)(size))
+
+#define access_ok(type, addr, size) (__range_ok((addr), (size)) == 0)
+#define __access_ok(add, size) (__range_ok((addr), (size)) == 0)
+
+extern inline int bad_user_access_length(void)
+{
+ return 0;
+}
+/* FIXME this is function for optimalization -> memcpy */
+#define __get_user(var, ptr) \
+ ({ \
+ int __gu_err = 0; \
+ switch (sizeof(*(ptr))) { \
+ case 1: \
+ case 2: \
+ case 4: \
+ (var) = *(ptr); \
+ break; \
+ case 8: \
+ memcpy((void *) &(var), (ptr), 8); \
+ break; \
+ default: \
+ (var) = 0; \
+ __gu_err = __get_user_bad(); \
+ break; \
+ } \
+ __gu_err; \
+ })
+
+#define __get_user_bad() (bad_user_access_length(), (-EFAULT))
+
+#define __put_user(var, ptr) \
+ ({ \
+ int __pu_err = 0; \
+ switch (sizeof(*(ptr))) { \
+ case 1: \
+ case 2: \
+ case 4: \
+ *(ptr) = (var); \
+ break; \
+ case 8: { \
+ typeof(*(ptr)) __pu_val = var; \
+ memcpy(ptr, &__pu_val, sizeof(__pu_val));\
+ } \
+ break; \
+ default: \
+ __pu_err = __put_user_bad(); \
+ break; \
+ } \
+ __pu_err; \
+ })
+
+#define __put_user_bad() (bad_user_access_length(), (-EFAULT))
+
+#define put_user(x, ptr) __put_user(x, ptr)
+#define get_user(x, ptr) __get_user(x, ptr)
+
+#define copy_to_user(to, from, n) (memcpy(to, from, n), 0)
+#define copy_from_user(to, from, n) (memcpy(to, from, n), 0)
+
+#define __copy_to_user(to, from, n) (copy_to_user(to, from, n))
+#define __copy_from_user(to, from, n) (copy_from_user(to, from, n))
+#define __copy_to_user_inatomic(to, from, n) (__copy_to_user(to, from, n))
+#define __copy_from_user_inatomic(to, from, n) (__copy_from_user(to, from, n))
+
+#define __clear_user(addr, n) (memset((void *)addr, 0, n), 0)
+
+static inline unsigned long clear_user(void *addr, unsigned long size)
+{
+ if (access_ok(VERIFY_WRITE, addr, size))
+ size = __clear_user(addr, size);
+ return size;
+}
+
+/* Returns 0 if exception not found and fixup otherwise. */
+extern unsigned long search_exception_table(unsigned long);
+
+
+extern long strncpy_from_user(char *dst, const char __user *src, long count);
+extern long strnlen_user(const char __user *src, long count);
+extern long __strncpy_from_user(char *dst, const char __user *src, long count);
+
+/*
+ * 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;
+};
+
+#endif /* __ASSEMBLY__ */
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_MICROBLAZE_UACCESS_H */
diff --git a/arch/microblaze/lib/uaccess.c b/arch/microblaze/lib/uaccess.c
new file mode 100644
index 0000000..8eb9df5
--- /dev/null
+++ b/arch/microblaze/lib/uaccess.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/string.h>
+#include <asm/uaccess.h>
+
+#include <asm/bug.h>
+
+long strnlen_user(const char __user *src, long count)
+{
+ return strlen(src) + 1;
+}
+
+#define __do_strncpy_from_user(dst, src, count, res) \
+ do { \
+ char *tmp; \
+ strncpy(dst, src, count); \
+ for (tmp = dst; *tmp && count > 0; tmp++, count--) \
+ ; \
+ res = (tmp - dst); \
+ } while (0)
+
+long __strncpy_from_user(char *dst, const char __user *src, long count)
+{
+ long res;
+ __do_strncpy_from_user(dst, src, count, res);
+ return res;
+}
+
+long strncpy_from_user(char *dst, const char __user *src, long count)
+{
+ long res = -EFAULT;
+ if (access_ok(VERIFY_READ, src, 1))
+ __do_strncpy_from_user(dst, src, count, res);
+ return res;
+}
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/hardirq.h | 29 ++++++++
arch/microblaze/include/asm/irq_regs.h | 1 +
arch/microblaze/include/asm/irqflags.h | 123 ++++++++++++++++++++++++++++++++
3 files changed, 153 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/hardirq.h
create mode 100644 arch/microblaze/include/asm/hw_irq.h
create mode 100644 arch/microblaze/include/asm/irq_regs.h
create mode 100644 arch/microblaze/include/asm/irqflags.h
diff --git a/arch/microblaze/include/asm/hardirq.h b/arch/microblaze/include/asm/hardirq.h
new file mode 100644
index 0000000..0f2d6b0
--- /dev/null
+++ b/arch/microblaze/include/asm/hardirq.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_HARDIRQ_H
+#define _ASM_MICROBLAZE_HARDIRQ_H
+
+#include <linux/cache.h>
+#include <linux/irq.h>
+#include <asm/irq.h>
+#include <asm/current.h>
+#include <linux/ptrace.h>
+
+/* should be defined in each interrupt controller driver */
+extern unsigned int get_irq(struct pt_regs *regs);
+
+typedef struct {
+ unsigned int __softirq_pending;
+} ____cacheline_aligned irq_cpustat_t;
+
+void ack_bad_irq(unsigned int irq);
+
+#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
+
+#endif /* _ASM_MICROBLAZE_HARDIRQ_H */
diff --git a/arch/microblaze/include/asm/hw_irq.h b/arch/microblaze/include/asm/hw_irq.h
new file mode 100644
index 0000000..e69de29
diff --git a/arch/microblaze/include/asm/irq_regs.h b/arch/microblaze/include/asm/irq_regs.h
new file mode 100644
index 0000000..3dd9c0b
--- /dev/null
+++ b/arch/microblaze/include/asm/irq_regs.h
@@ -0,0 +1 @@
+#include <asm-generic/irq_regs.h>
diff --git a/arch/microblaze/include/asm/irqflags.h b/arch/microblaze/include/asm/irqflags.h
new file mode 100644
index 0000000..dea6564
--- /dev/null
+++ b/arch/microblaze/include/asm/irqflags.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_IRQFLAGS_H
+#define _ASM_MICROBLAZE_IRQFLAGS_H
+
+#include <linux/irqflags.h>
+
+# if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
+
+# define local_irq_save(flags) \
+ do { \
+ asm volatile ("# local_irq_save \n\t" \
+ "msrclr %0, %1 \n\t" \
+ "nop \n\t" \
+ : "=r"(flags) \
+ : "i"(MSR_IE) \
+ : "memory"); \
+ } while (0)
+
+# define local_irq_disable() \
+ do { \
+ asm volatile ("# local_irq_disable \n\t" \
+ "msrclr r0, %0 \n\t" \
+ "nop \n\t" \
+ : \
+ : "i"(MSR_IE) \
+ : "memory"); \
+ } while (0)
+
+# define local_irq_enable() \
+ do { \
+ asm volatile ("# local_irq_enable \n\t" \
+ "msrset r0, %0 \n\t" \
+ "nop \n\t" \
+ : \
+ : "i"(MSR_IE) \
+ : "memory"); \
+ } while (0)
+
+# else /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR == 0 */
+
+# define local_irq_save(flags) \
+ do { \
+ register unsigned tmp; \
+ asm volatile ("# local_irq_save \n\t" \
+ "mfs %0, rmsr \n\t" \
+ "nop \n\t" \
+ "andi %1, %0, %2 \n\t" \
+ "mts rmsr, %1 \n\t" \
+ "nop \n\t" \
+ : "=r"(flags), "=r" (tmp) \
+ : "i"(~MSR_IE) \
+ : "memory"); \
+ } while (0)
+
+# define local_irq_disable() \
+ do { \
+ register unsigned tmp; \
+ asm volatile ("# local_irq_disable \n\t" \
+ "mfs %0, rmsr \n\t" \
+ "nop \n\t" \
+ "andi %0, %0, %1 \n\t" \
+ "mts rmsr, %0 \n\t" \
+ "nop \n\t" \
+ : "=r"(tmp) \
+ : "i"(~MSR_IE) \
+ : "memory"); \
+ } while (0)
+
+# define local_irq_enable() \
+ do { \
+ register unsigned tmp; \
+ asm volatile ("# local_irq_enable \n\t" \
+ "mfs %0, rmsr \n\t" \
+ "nop \n\t" \
+ "ori %0, %0, %1 \n\t" \
+ "mts rmsr, %0 \n\t" \
+ "nop \n\t" \
+ : "=r"(tmp) \
+ : "i"(MSR_IE) \
+ : "memory"); \
+ } while (0)
+
+# endif /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */
+
+#define local_save_flags(flags) \
+ do { \
+ asm volatile ("# local_save_flags \n\t" \
+ "mfs %0, rmsr \n\t" \
+ "nop \n\t" \
+ : "=r"(flags) \
+ : \
+ : "memory"); \
+ } while (0)
+
+#define local_irq_restore(flags) \
+ do { \
+ asm volatile ("# local_irq_restore \n\t"\
+ "mts rmsr, %0 \n\t" \
+ "nop \n\t" \
+ : \
+ : "r"(flags) \
+ : "memory"); \
+ } while (0)
+
+static inline int irqs_disabled(void)
+{
+ unsigned long flags;
+
+ local_save_flags(flags);
+ return ((flags & MSR_IE) == 0);
+}
+
+#define raw_irqs_disabled irqs_disabled
+#define raw_irqs_disabled_flags(flags) ((flags) == 0)
+
+#endif /* _ASM_MICROBLAZE_IRQFLAGS_H */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/dma-mapping.h | 131 +++++++++++++++++++++++++++++
arch/microblaze/include/asm/dma.h | 16 ++++
arch/microblaze/include/asm/scatterlist.h | 28 ++++++
3 files changed, 175 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/dma-mapping.h
create mode 100644 arch/microblaze/include/asm/dma.h
create mode 100644 arch/microblaze/include/asm/scatterlist.h
diff --git a/arch/microblaze/include/asm/dma-mapping.h b/arch/microblaze/include/asm/dma-mapping.h
new file mode 100644
index 0000000..e6f1246
--- /dev/null
+++ b/arch/microblaze/include/asm/dma-mapping.h
@@ -0,0 +1,131 @@
+/*
+ * include/asm-microblaze/dma-mapping.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ */
+
+#ifndef _ASM_MICROBLAZE_DMA_MAPPING_H
+#define _ASM_MICROBLAZE_DMA_MAPPING_H
+
+#include <asm/cacheflush.h>
+#include <linux/io.h>
+#include <linux/bug.h>
+
+struct scatterlist;
+
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+
+/* FIXME */
+static inline int
+dma_supported(struct device *dev, u64 mask)
+{
+ return 1;
+}
+
+static inline dma_addr_t
+dma_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG();
+ return 0;
+}
+
+static inline void
+dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG();
+}
+
+static inline int
+dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction direction)
+{
+ BUG();
+ return 0;
+}
+
+static inline void
+dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+ enum dma_data_direction direction)
+{
+ BUG();
+}
+
+static inline void
+dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG();
+}
+
+static inline void
+dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
+ size_t size, enum dma_data_direction direction)
+{
+ BUG();
+}
+
+static inline void
+dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
+ enum dma_data_direction direction)
+{
+ BUG();
+}
+
+static inline void
+dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
+ enum dma_data_direction direction)
+{
+ BUG();
+}
+
+static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+ return 0;
+}
+
+static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, int flag)
+{
+ return NULL; /* consistent_alloc(flag, size, dma_handle); */
+}
+
+static inline void dma_free_coherent(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle)
+{
+ BUG();
+}
+
+static inline dma_addr_t
+dma_map_single(struct device *dev, void *ptr, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+
+ return virt_to_bus(ptr);
+}
+
+static inline void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
+ size_t size,
+ enum dma_data_direction direction)
+{
+ switch (direction) {
+ case DMA_FROM_DEVICE:
+ flush_dcache_range((unsigned)dma_addr,
+ (unsigned)dma_addr + size);
+ /* Fall through */
+ case DMA_TO_DEVICE:
+ break;
+ default:
+ BUG();
+ }
+}
+
+#endif /* _ASM_MICROBLAZE_DMA_MAPPING_H */
diff --git a/arch/microblaze/include/asm/dma.h b/arch/microblaze/include/asm/dma.h
new file mode 100644
index 0000000..0967fa0
--- /dev/null
+++ b/arch/microblaze/include/asm/dma.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_DMA_H
+#define _ASM_MICROBLAZE_DMA_H
+
+/* we don't have dma address limit. define it as zero to be
+ * unlimited. */
+#define MAX_DMA_ADDRESS (0)
+
+#endif /* _ASM_MICROBLAZE_DMA_H */
diff --git a/arch/microblaze/include/asm/scatterlist.h b/arch/microblaze/include/asm/scatterlist.h
new file mode 100644
index 0000000..08ff1d0
--- /dev/null
+++ b/arch/microblaze/include/asm/scatterlist.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2008 Michal Simek <[email protected]>
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_SCATTERLIST_H
+#define _ASM_MICROBLAZE_SCATTERLIST_H
+
+struct scatterlist {
+#ifdef CONFIG_DEBUG_SG
+ unsigned long sg_magic;
+#endif
+ unsigned long page_link;
+ dma_addr_t dma_address;
+ unsigned int offset;
+ unsigned int length;
+};
+
+#define sg_dma_address(sg) ((sg)->dma_address)
+#define sg_dma_len(sg) ((sg)->length)
+
+#define ISA_DMA_THRESHOLD (~0UL)
+
+#endif /* _ASM_MICROBLAZE_SCATTERLIST_H */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/atomic.h | 123 +++++++++++++++++++++++++++++++
arch/microblaze/include/asm/bitops.h | 27 +++++++
arch/microblaze/include/asm/byteorder.h | 6 ++
arch/microblaze/include/asm/swab.h | 8 ++
4 files changed, 164 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/atomic.h
create mode 100644 arch/microblaze/include/asm/bitops.h
create mode 100644 arch/microblaze/include/asm/byteorder.h
create mode 100644 arch/microblaze/include/asm/swab.h
diff --git a/arch/microblaze/include/asm/atomic.h b/arch/microblaze/include/asm/atomic.h
new file mode 100644
index 0000000..a448d94
--- /dev/null
+++ b/arch/microblaze/include/asm/atomic.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_ATOMIC_H
+#define _ASM_MICROBLAZE_ATOMIC_H
+
+#include <linux/types.h>
+#include <linux/compiler.h> /* likely */
+#include <asm/system.h> /* local_irq_XXX and friends */
+
+#define ATOMIC_INIT(i) { (i) }
+#define atomic_read(v) ((v)->counter)
+#define atomic_set(v, i) (((v)->counter) = (i))
+
+#define atomic_inc(v) (atomic_add_return(1, (v)))
+#define atomic_dec(v) (atomic_sub_return(1, (v)))
+
+#define atomic_add(i, v) (atomic_add_return(i, (v)))
+#define atomic_sub(i, v) (atomic_sub_return(i, (v)))
+
+#define atomic_inc_return(v) (atomic_add_return(1, (v)))
+#define atomic_dec_return(v) (atomic_sub_return(1, (v)))
+
+#define atomic_inc_and_test(v) (atomic_add_return(1, (v)) == 0)
+#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
+
+#define atomic_inc_not_zero(v) (atomic_add_unless((v), 1, 0))
+
+#define atomic_sub_and_test(i, v) (atomic_sub_return((i), (v)) == 0)
+
+static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
+{
+ int ret;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ ret = v->counter;
+ if (likely(ret == old))
+ v->counter = new;
+ local_irq_restore(flags);
+
+ return ret;
+}
+
+static inline int atomic_add_unless(atomic_t *v, int a, int u)
+{
+ int c, old;
+
+ c = atomic_read(v);
+ while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c)
+ c = old;
+ return c != u;
+}
+
+static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ *addr &= ~mask;
+ local_irq_restore(flags);
+}
+
+/**
+ * atomic_add_return - add and return
+ * @i: integer value to add
+ * @v: pointer of type atomic_t
+ *
+ * Atomically adds @i to @v and returns @i + @v
+ */
+static inline int atomic_add_return(int i, atomic_t *v)
+{
+ unsigned long flags;
+ int val;
+
+ local_irq_save(flags);
+ val = v->counter;
+ v->counter = val += i;
+ local_irq_restore(flags);
+
+ return val;
+}
+
+static inline int atomic_sub_return(int i, atomic_t *v)
+{
+ return atomic_add_return(-i, v);
+}
+
+/*
+ * Atomically test *v and decrement if it is greater than 0.
+ * The function returns the old value of *v minus 1.
+ */
+static inline int atomic_dec_if_positive(atomic_t *v)
+{
+ unsigned long flags;
+ int res;
+
+ local_irq_save(flags);
+ res = v->counter - 1;
+ if (res >= 0)
+ v->counter = res;
+ local_irq_restore(flags);
+
+ return res;
+}
+
+#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+
+/* Atomic operations are already serializing */
+#define smp_mb__before_atomic_dec() barrier()
+#define smp_mb__after_atomic_dec() barrier()
+#define smp_mb__before_atomic_inc() barrier()
+#define smp_mb__after_atomic_inc() barrier()
+
+#include <asm-generic/atomic.h>
+
+#endif /* _ASM_MICROBLAZE_ATOMIC_H */
diff --git a/arch/microblaze/include/asm/bitops.h b/arch/microblaze/include/asm/bitops.h
new file mode 100644
index 0000000..d6df1fd
--- /dev/null
+++ b/arch/microblaze/include/asm/bitops.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_BITOPS_H
+#define _ASM_MICROBLAZE_BITOPS_H
+
+/*
+ * Copyright 1992, Linus Torvalds.
+ */
+
+#include <asm/byteorder.h> /* swab32 */
+#include <asm/system.h> /* save_flags */
+
+/*
+ * clear_bit() doesn't provide any barrier for the compiler.
+ */
+#define smp_mb__before_clear_bit() barrier()
+#define smp_mb__after_clear_bit() barrier()
+#include <asm-generic/bitops.h>
+#include <asm-generic/bitops/__fls.h>
+
+#endif /* _ASM_MICROBLAZE_BITOPS_H */
diff --git a/arch/microblaze/include/asm/byteorder.h b/arch/microblaze/include/asm/byteorder.h
new file mode 100644
index 0000000..ce9c587
--- /dev/null
+++ b/arch/microblaze/include/asm/byteorder.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_MICROBLAZE_BYTEORDER_H
+#define _ASM_MICROBLAZE_BYTEORDER_H
+
+#include <linux/byteorder/big_endian.h>
+
+#endif /* _ASM_MICROBLAZE_BYTEORDER_H */
diff --git a/arch/microblaze/include/asm/swab.h b/arch/microblaze/include/asm/swab.h
new file mode 100644
index 0000000..b375d7b
--- /dev/null
+++ b/arch/microblaze/include/asm/swab.h
@@ -0,0 +1,8 @@
+#ifndef _ASM_MICROBLAZE_SWAB_H
+#define _ASM_MICROBLAZE_SWAB_H
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+#define __SWAB_64_THRU_32__
+#endif
+
+#endif /* _ASM_MICROBLAZE_SWAB_H */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/kernel/init_task.c | 27 +++++
arch/microblaze/kernel/process.c | 185 ++++++++++++++++++++++++++++++++++++
2 files changed, 212 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/kernel/init_task.c
create mode 100644 arch/microblaze/kernel/process.c
diff --git a/arch/microblaze/kernel/init_task.c b/arch/microblaze/kernel/init_task.c
new file mode 100644
index 0000000..1abdfdb
--- /dev/null
+++ b/arch/microblaze/kernel/init_task.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init_task.h>
+#include <linux/fs.h>
+#include <linux/mqueue.h>
+
+#include <asm/pgtable.h>
+
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+struct mm_struct init_mm = INIT_MM(init_mm);
+EXPORT_SYMBOL(init_mm);
+
+union thread_union init_thread_union
+ __attribute__((__section__(".data.init_task"))) =
+{ INIT_THREAD_INFO(init_task) };
+
+struct task_struct init_task = INIT_TASK(init_task);
+EXPORT_SYMBOL(init_task);
diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c
new file mode 100644
index 0000000..157893e
--- /dev/null
+++ b/arch/microblaze/kernel/process.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2008 Michal Simek
+ * Copyright (C) 2008 PetaLogix
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/pm.h>
+#include <linux/tick.h>
+#include <linux/bitops.h>
+#include <asm/system.h>
+#include <asm/pgalloc.h>
+
+void show_regs(struct pt_regs *regs)
+{
+ printk(KERN_INFO " Registers dump: mode=%X\r\n", regs->kernel_mode);
+ printk(KERN_INFO " r1=%08lX, r2=%08lX, r3=%08lX, r4=%08lX\n",
+ regs->r1, regs->r2, regs->r3, regs->r4);
+ printk(KERN_INFO " r5=%08lX, r6=%08lX, r7=%08lX, r8=%08lX\n",
+ regs->r5, regs->r6, regs->r7, regs->r8);
+ printk(KERN_INFO " r9=%08lX, r10=%08lX, r11=%08lX, r12=%08lX\n",
+ regs->r9, regs->r10, regs->r11, regs->r12);
+ printk(KERN_INFO " r13=%08lX, r14=%08lX, r15=%08lX, r16=%08lX\n",
+ regs->r13, regs->r14, regs->r15, regs->r16);
+ printk(KERN_INFO " r17=%08lX, r18=%08lX, r19=%08lX, r20=%08lX\n",
+ regs->r17, regs->r18, regs->r19, regs->r20);
+ printk(KERN_INFO " r21=%08lX, r22=%08lX, r23=%08lX, r24=%08lX\n",
+ regs->r21, regs->r22, regs->r23, regs->r24);
+ printk(KERN_INFO " r25=%08lX, r26=%08lX, r27=%08lX, r28=%08lX\n",
+ regs->r25, regs->r26, regs->r27, regs->r28);
+ printk(KERN_INFO " r29=%08lX, r30=%08lX, r31=%08lX, rPC=%08lX\n",
+ regs->r29, regs->r30, regs->r31, regs->pc);
+ printk(KERN_INFO " msr=%08lX, ear=%08lX, esr=%08lX, fsr=%08lX\n",
+ regs->msr, regs->ear, regs->esr, regs->fsr);
+ while(1);
+}
+
+void (*pm_idle)(void);
+void (*pm_power_off)(void) = NULL;
+EXPORT_SYMBOL(pm_power_off);
+
+static int hlt_counter = 1;
+
+void disable_hlt(void)
+{
+ hlt_counter++;
+}
+EXPORT_SYMBOL(disable_hlt);
+
+void enable_hlt(void)
+{
+ hlt_counter--;
+}
+EXPORT_SYMBOL(enable_hlt);
+
+static int __init nohlt_setup(char *__unused)
+{
+ hlt_counter = 1;
+ return 1;
+}
+__setup("nohlt", nohlt_setup);
+
+static int __init hlt_setup(char *__unused)
+{
+ hlt_counter = 0;
+ return 1;
+}
+__setup("hlt", hlt_setup);
+
+void default_idle(void)
+{
+ if (!hlt_counter) {
+ clear_thread_flag(TIF_POLLING_NRFLAG);
+ smp_mb__after_clear_bit();
+ local_irq_disable();
+ while (!need_resched())
+ cpu_sleep();
+ local_irq_enable();
+ set_thread_flag(TIF_POLLING_NRFLAG);
+ } else
+ while (!need_resched())
+ cpu_relax();
+}
+
+void cpu_idle(void)
+{
+ set_thread_flag(TIF_POLLING_NRFLAG);
+
+ /* endless idle loop with no priority at all */
+ while (1) {
+ void (*idle)(void) = pm_idle;
+
+ if (!idle)
+ idle = default_idle;
+
+ tick_nohz_stop_sched_tick(1);
+ while (!need_resched())
+ idle();
+ tick_nohz_restart_sched_tick();
+
+ preempt_enable_no_resched();
+ schedule();
+ preempt_disable();
+ check_pgt_cache();
+ }
+}
+
+void flush_thread(void)
+{
+}
+
+int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+ unsigned long unused,
+ struct task_struct *p, struct pt_regs *regs)
+{
+ struct pt_regs *childregs = task_pt_regs(p);
+ struct thread_info *ti = task_thread_info(p);
+
+ *childregs = *regs;
+ if (user_mode(regs))
+ childregs->r1 = usp;
+ else
+ childregs->r1 = ((unsigned long) ti) + THREAD_SIZE;
+
+ memset(&ti->cpu_context, 0, sizeof(struct cpu_context));
+ ti->cpu_context.r1 = (unsigned long)childregs;
+ ti->cpu_context.msr = (unsigned long)childregs->msr;
+ ti->cpu_context.r15 = (unsigned long)ret_from_fork - 8;
+
+ if (clone_flags & CLONE_SETTLS)
+ ;
+
+ return 0;
+}
+
+/*
+ * Return saved PC of a blocked thread.
+ */
+unsigned long thread_saved_pc(struct task_struct *tsk)
+{
+ struct cpu_context *ctx =
+ &(((struct thread_info *)(tsk->stack))->cpu_context);
+
+ /* Check whether the thread is blocked in resume() */
+ if (in_sched_functions(ctx->r15))
+ return (unsigned long)ctx->r15;
+ else
+ return ctx->r14;
+}
+
+static void kernel_thread_helper(int (*fn)(void *), void *arg)
+{
+ fn(arg);
+ do_exit(-1);
+}
+
+int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+ struct pt_regs regs;
+ int ret;
+
+ memset(®s, 0, sizeof(regs));
+ /* store them in non-volatile registers */
+ regs.r5 = (unsigned long)fn;
+ regs.r6 = (unsigned long)arg;
+ local_save_flags(regs.msr);
+ regs.pc = (unsigned long)kernel_thread_helper;
+ regs.kernel_mode = 1;
+
+ ret = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,
+ ®s, 0, NULL, NULL);
+
+ return ret;
+}
+
+unsigned long get_wchan(struct task_struct *p)
+{
+/* TBD (used by procfs) */
+ return 0;
+}
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/setup.h | 43 ++++++++
arch/microblaze/kernel/setup.c | 198 +++++++++++++++++++++++++++++++++++
2 files changed, 241 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/setup.h
create mode 100644 arch/microblaze/kernel/setup.c
diff --git a/arch/microblaze/include/asm/setup.h b/arch/microblaze/include/asm/setup.h
new file mode 100644
index 0000000..70075fe
--- /dev/null
+++ b/arch/microblaze/include/asm/setup.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2007-2008 Michal Simek <[email protected]>
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_SETUP_H
+#define _ASM_MICROBLAZE_SETUP_H
+
+# ifndef __ASSEMBLY__
+
+# ifdef __KERNEL__
+extern unsigned int boot_cpuid; /* move to smp.h */
+
+# define COMMAND_LINE_SIZE 256
+extern char cmd_line[COMMAND_LINE_SIZE];
+# endif/* __KERNEL__ */
+
+void early_printk(const char *fmt, ...);
+
+int setup_early_printk(char *opt);
+void disable_early_printk(void);
+
+void heartbeat(void);
+void setup_heartbeat(void);
+
+unsigned long long sched_clock(void);
+
+void time_init(void);
+void init_IRQ(void);
+void machine_early_init(const char *cmdline, unsigned int ram,
+ unsigned int fdt);
+
+void machine_restart(char *cmd);
+void machine_shutdown(void);
+void machine_halt(void);
+void machine_power_off(void);
+
+# endif /* __ASSEMBLY__ */
+#endif /* _ASM_MICROBLAZE_SETUP_H */
diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c
new file mode 100644
index 0000000..d50184b
--- /dev/null
+++ b/arch/microblaze/kernel/setup.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2007-2008 Michal Simek <[email protected]>
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/seq_file.h>
+#include <linux/cpu.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/debugfs.h>
+
+#include <asm/setup.h>
+#include <asm/sections.h>
+#include <asm/page.h>
+#include <linux/io.h>
+#include <linux/bug.h>
+#include <linux/param.h>
+#include <linux/cache.h>
+#include <asm/cacheflush.h>
+#include <asm/entry.h>
+#include <asm/cpuinfo.h>
+
+#include <asm/system.h>
+#include <asm/prom.h>
+#include <asm/pgtable.h>
+
+DEFINE_PER_CPU(unsigned int, KSP); /* Saved kernel stack pointer */
+DEFINE_PER_CPU(unsigned int, KM); /* Kernel/user mode */
+DEFINE_PER_CPU(unsigned int, ENTRY_SP); /* Saved SP on kernel entry */
+DEFINE_PER_CPU(unsigned int, R11_SAVE); /* Temp variable for entry */
+DEFINE_PER_CPU(unsigned int, CURRENT_SAVE); /* Saved current pointer */
+
+unsigned int boot_cpuid;
+char cmd_line[COMMAND_LINE_SIZE];
+
+void __init setup_arch(char **cmdline_p)
+{
+#ifdef CONFIG_CMDLINE_FORCE
+ strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
+ strlcpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
+#endif
+ *cmdline_p = cmd_line;
+
+ console_verbose();
+
+ unflatten_device_tree();
+
+ /* NOTE I think that this function is not necessary to call */
+ /* irq_early_init(); */
+ setup_cpuinfo();
+
+ __invalidate_icache_all();
+ __enable_icache();
+
+ __invalidate_dcache_all();
+ __enable_dcache();
+
+ panic_timeout = 120;
+
+ setup_memory();
+
+#if defined(CONFIG_SELFMOD_INTC) || defined(CONFIG_SELFMOD_TIMER)
+ printk(KERN_NOTICE "Self modified code enable\n");
+#endif
+
+#ifdef CONFIG_VT
+#if defined(CONFIG_XILINX_CONSOLE)
+ conswitchp = &xil_con;
+#elif defined(CONFIG_DUMMY_CONSOLE)
+ conswitchp = &dummy_con;
+#endif
+#endif
+}
+
+#ifdef CONFIG_MTD_UCLINUX
+/* Handle both romfs and cramfs types, without generating unnecessary
+ code (ie no point checking for CRAMFS if it's not even enabled) */
+inline unsigned get_romfs_len(unsigned *addr)
+{
+#ifdef CONFIG_ROMFS_FS
+ if (memcmp(&addr[0], "-rom1fs-", 8) == 0) /* romfs */
+ return be32_to_cpu(addr[2]);
+#endif
+
+#ifdef CONFIG_CRAMFS
+ if (addr[0] == le32_to_cpu(0x28cd3d45)) /* cramfs */
+ return le32_to_cpu(addr[1]);
+#endif
+ return 0;
+}
+#endif /* CONFIG_MTD_UCLINUX_EBSS */
+
+void __init machine_early_init(const char *cmdline, unsigned int ram,
+ unsigned int fdt)
+{
+ unsigned long *src, *dst = (unsigned long *)0x0;
+
+/* clearing bss section */
+ memset(__bss_start, 0, __bss_stop-__bss_start);
+ memset(_ssbss, 0, _esbss-_ssbss);
+
+ /*
+ * Copy command line passed from bootloader, or use default
+ * if none provided, or forced
+ */
+#ifndef CONFIG_CMDLINE_BOOL
+ if (cmdline && cmdline[0] != '\0')
+ strlcpy(cmd_line, cmdline, COMMAND_LINE_SIZE);
+#endif
+
+/* initialize device tree for usage in early_printk */
+ early_init_devtree((void *)_fdt_start);
+
+#ifdef CONFIG_EARLY_PRINTK
+ setup_early_printk(NULL);
+#endif
+
+ early_printk("Ramdisk addr 0x%08x, FDT 0x%08x\n", ram, fdt);
+ printk(KERN_NOTICE "Found FDT at 0x%08x\n", fdt);
+
+#ifdef CONFIG_MTD_UCLINUX
+ {
+ int size;
+ unsigned int romfs_base;
+ romfs_base = (ram ? ram : (unsigned int)&__init_end);
+ /* if CONFIG_MTD_UCLINUX_EBSS is defined, assume ROMFS is at the
+ * end of kernel, which is ROMFS_LOCATION defined above. */
+ size = PAGE_ALIGN(get_romfs_len((unsigned *)romfs_base));
+ early_printk("Found romfs @ 0x%08x (0x%08x)\n",
+ romfs_base, size);
+ early_printk("#### klimit %p ####\n", klimit);
+ BUG_ON(size < 0); /* What else can we do? */
+
+ /* Use memmove to handle likely case of memory overlap */
+ early_printk("Moving 0x%08x bytes from 0x%08x to 0x%08x\n",
+ size, romfs_base, (unsigned)&_ebss);
+ memmove(&_ebss, (int *)romfs_base, size);
+
+ /* update klimit */
+ klimit += PAGE_ALIGN(size);
+ early_printk("New klimit: 0x%08x\n", (unsigned)klimit);
+ }
+#endif
+
+ for (src = __ivt_start; src < __ivt_end; src++, dst++)
+ *dst = *src;
+
+ /* Initialize global data */
+ per_cpu(KM, 0) = 0x1; /* We start in kernel mode */
+ per_cpu(CURRENT_SAVE, 0) = (unsigned long)current;
+}
+
+#ifdef CONFIG_DEBUG_FS
+struct dentry *of_debugfs_root;
+
+static int microblaze_debugfs_init(void)
+{
+ of_debugfs_root = debugfs_create_dir("microblaze", NULL);
+
+ return of_debugfs_root == NULL;
+}
+arch_initcall(microblaze_debugfs_init);
+#endif
+
+void machine_restart(char *cmd)
+{
+ printk(KERN_NOTICE "Machine restart...\n");
+ dump_stack();
+ while (1)
+ ;
+}
+
+void machine_shutdown(void)
+{
+ printk(KERN_NOTICE "Machine shutdown...\n");
+ while (1)
+ ;
+}
+
+void machine_halt(void)
+{
+ printk(KERN_NOTICE "Machine halt...\n");
+ while (1)
+ ;
+}
+
+void machine_power_off(void)
+{
+ printk(KERN_NOTICE "Machine power off...\n");
+ while (1)
+ ;
+}
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/processor.h | 93 +++++++++++++++++++++++++++++++
arch/microblaze/include/asm/system.h | 91 ++++++++++++++++++++++++++++++
2 files changed, 184 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/processor.h
create mode 100644 arch/microblaze/include/asm/system.h
diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h
new file mode 100644
index 0000000..d8e1543
--- /dev/null
+++ b/arch/microblaze/include/asm/processor.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2008 Michal Simek
+ * Copyright (C) 2008 PetaLogix
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_PROCESSOR_H
+#define _ASM_MICROBLAZE_PROCESSOR_H
+
+#include <asm/ptrace.h>
+#include <asm/setup.h>
+#include <asm/registers.h>
+#include <asm/segment.h>
+
+# ifndef __ASSEMBLY__
+/* from kernel/cpu/mb.c */
+extern const struct seq_operations cpuinfo_op;
+
+# define cpu_relax() barrier()
+# define cpu_sleep() do {} while (0)
+# define prepare_to_copy(tsk) do {} while (0)
+
+# endif /* __ASSEMBLY__ */
+
+/*
+ * User space process size: memory size
+ *
+ * TASK_SIZE on MMU cpu is usually 1GB. However, on no-MMU arch, both
+ * user processes and the kernel is on the same memory region. They
+ * both share the memory space and that is limited by the amount of
+ * physical memory. thus, we set TASK_SIZE == amount of total memory.
+ */
+# define TASK_SIZE (0x81000000 - 0x80000000)
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+# define current_text_addr() ({ __label__ _l; _l: &&_l; })
+
+/*
+ * This decides where the kernel will search for a free chunk of vm
+ * space during mmap's. We won't be using it
+ */
+# define TASK_UNMAPPED_BASE 0
+
+/* definition in include/linux/sched.h */
+struct task_struct;
+
+/* thread_struct is gone. use thread_info instead. */
+struct thread_struct { };
+# define INIT_THREAD { }
+
+/* Do necessary setup to start up a newly executed thread. */
+static inline void start_thread(struct pt_regs *regs,
+ unsigned long pc,
+ unsigned long usp)
+{
+ regs->pc = pc;
+ regs->r1 = usp;
+ regs->kernel_mode = 0;
+}
+
+/* Free all resources held by a thread. */
+static inline void release_thread(struct task_struct *dead_task)
+{
+}
+
+/* Free all resources held by a thread. */
+static inline void exit_thread(void)
+{
+}
+
+extern unsigned long thread_saved_pc(struct task_struct *t);
+
+extern unsigned long get_wchan(struct task_struct *p);
+
+/*
+ * create a kernel thread without removing it from tasklists
+ */
+extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+
+# define task_pt_regs(tsk) \
+ (((struct pt_regs *)(THREAD_SIZE + task_stack_page(tsk))) - 1)
+
+# define KSTK_EIP(tsk) (0)
+# define KSTK_ESP(tsk) (0)
+
+#endif /* _ASM_MICROBLAZE_PROCESSOR_H */
diff --git a/arch/microblaze/include/asm/system.h b/arch/microblaze/include/asm/system.h
new file mode 100644
index 0000000..c4e3088
--- /dev/null
+++ b/arch/microblaze/include/asm/system.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_SYSTEM_H
+#define _ASM_MICROBLAZE_SYSTEM_H
+
+#include <asm/registers.h>
+#include <asm/setup.h>
+#include <asm/irqflags.h>
+
+struct task_struct;
+struct thread_info;
+
+extern struct task_struct *_switch_to(struct thread_info *prev,
+ struct thread_info *next);
+
+#define switch_to(prev, next, last) \
+ do { \
+ (last) = _switch_to(task_thread_info(prev), \
+ task_thread_info(next)); \
+ } while (0)
+
+#define smp_read_barrier_depends() do {} while (0)
+#define read_barrier_depends() do {} while (0)
+
+#define nop() asm volatile ("nop")
+#define mb() barrier()
+#define rmb() mb()
+#define wmb() mb()
+#define set_mb(var, value) do { var = value; mb(); } while (0)
+#define set_wmb(var, value) do { var = value; wmb(); } while (0)
+
+#define smp_mb() mb()
+#define smp_rmb() rmb()
+#define smp_wmb() wmb()
+
+void show_trace(struct task_struct *task, unsigned long *stack);
+void __bad_xchg(volatile void *ptr, int size);
+
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
+ int size)
+{
+ unsigned long ret;
+ unsigned long flags;
+
+ switch (size) {
+ case 1:
+ local_irq_save(flags);
+ ret = *(volatile unsigned char *)ptr;
+ *(volatile unsigned char *)ptr = x;
+ local_irq_restore(flags);
+ break;
+
+ case 4:
+ local_irq_save(flags);
+ ret = *(volatile unsigned long *)ptr;
+ *(volatile unsigned long *)ptr = x;
+ local_irq_restore(flags);
+ break;
+ default:
+ __bad_xchg(ptr, size), ret = 0;
+ break;
+ }
+
+ return ret;
+}
+
+void disable_hlt(void);
+void enable_hlt(void);
+void default_idle(void);
+
+#define xchg(ptr, x) \
+ ((__typeof__(*(ptr))) __xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
+
+void free_init_pages(char *what, unsigned long begin, unsigned long end);
+void free_initmem(void);
+extern char *klimit;
+extern void ret_from_fork(void);
+
+#ifdef CONFIG_DEBUG_FS
+extern struct dentry *of_debugfs_root;
+#endif
+
+#define arch_align_stack(x) (x)
+
+#endif /* _ASM_MICROBLAZE_SYSTEM_H */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/checksum.h | 98 +++++++++++++++++++
arch/microblaze/lib/checksum.c | 166 ++++++++++++++++++++++++++++++++
2 files changed, 264 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/checksum.h
create mode 100644 arch/microblaze/lib/checksum.c
diff --git a/arch/microblaze/include/asm/checksum.h b/arch/microblaze/include/asm/checksum.h
new file mode 100644
index 0000000..92b3076
--- /dev/null
+++ b/arch/microblaze/include/asm/checksum.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2008 Michal Simek <[email protected]>
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_CHECKSUM_H
+#define _ASM_MICROBLAZE_CHECKSUM_H
+
+#include <linux/in6.h>
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline __wsum
+csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
+ unsigned short proto, __wsum sum)
+{
+ __asm__("add %0, %0, %1\n\t"
+ "addc %0, %0, %2\n\t"
+ "addc %0, %0, %3\n\t"
+ "addc %0, %0, r0\n\t"
+ : "+&d" (sum)
+ : "d" (saddr), "d" (daddr), "d" (len + proto));
+
+ return sum;
+}
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+extern __wsum csum_partial(const void *buff, int len, __wsum sum);
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+extern __wsum csum_partial_copy(const char *src, char *dst, int len, int sum);
+
+/*
+ * the same as csum_partial_copy, but copies from user space.
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+extern __wsum csum_partial_copy_from_user(const char *src, char *dst,
+ int len, int sum, int *csum_err);
+
+#define csum_partial_copy_nocheck(src, dst, len, sum) \
+ csum_partial_copy((src), (dst), (len), (sum))
+
+/*
+ * This is a version of ip_compute_csum() optimized for IP headers,
+ * which always checksum on 4 octet boundaries.
+ *
+ */
+extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl);
+
+/*
+ * Fold a partial checksum
+ */
+static inline __sum16 csum_fold(unsigned int sum)
+{
+ sum = (sum & 0xffff) + (sum >> 16);
+ sum = (sum & 0xffff) + (sum >> 16);
+ return ~sum;
+}
+
+static inline __sum16
+csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
+ unsigned short proto, __wsum sum)
+{
+ return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+extern __sum16 ip_compute_csum(const unsigned char *buff, int len);
+
+#endif /* _ASM_MICROBLAZE_CHECKSUM_H */
diff --git a/arch/microblaze/lib/checksum.c b/arch/microblaze/lib/checksum.c
new file mode 100644
index 0000000..ac7c214
--- /dev/null
+++ b/arch/microblaze/lib/checksum.c
@@ -0,0 +1,166 @@
+/*
+ * arch/microblaze/lib/checksum.c
+ *
+ * Copyright (C) 2008 Michal Simek <[email protected]>
+ *
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * IP/TCP/UDP checksumming routines
+ *
+ * Authors: Jorge Cwik, <[email protected]>
+ * Arnt Gulbrandsen, <[email protected]>
+ * Tom May, <[email protected]>
+ * Andreas Schwab, <[email protected]>
+ * Lots of code moved from tcp.c and ip.c; see those files
+ * for more names.
+ *
+ * 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek:
+ * Fixed some nasty bugs, causing some horrible crashes.
+ * A: At some points, the sum (%0) was used as
+ * length-counter instead of the length counter
+ * (%1). Thanks to Roman Hodek for pointing this out.
+ * B: GCC seems to mess up if one uses too many
+ * data-registers to hold input values and one tries to
+ * specify d0 and d1 as scratch registers. Letting gcc
+ * choose these registers itself solves the problem.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+/* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access
+ kills, so most of the assembly has to go. */
+
+#include <net/checksum.h>
+#include <asm/checksum.h>
+#include <linux/module.h>
+
+static inline unsigned short from32to16(unsigned long x)
+{
+ /* add up 16-bit and 16-bit for 16+c bit */
+ x = (x & 0xffff) + (x >> 16);
+ /* add up carry.. */
+ x = (x & 0xffff) + (x >> 16);
+ return x;
+}
+
+static unsigned int do_csum(const unsigned char *buff, int len)
+{
+ int odd, count;
+ unsigned long result = 0;
+
+ if (len <= 0)
+ goto out;
+ odd = 1 & (unsigned long) buff;
+ if (odd) {
+ result = *buff;
+ len--;
+ buff++;
+ }
+ count = len >> 1; /* nr of 16-bit words.. */
+ if (count) {
+ if (2 & (unsigned long) buff) {
+ result += *(unsigned short *) buff;
+ count--;
+ len -= 2;
+ buff += 2;
+ }
+ count >>= 1; /* nr of 32-bit words.. */
+ if (count) {
+ unsigned long carry = 0;
+ do {
+ unsigned long w = *(unsigned long *) buff;
+ count--;
+ buff += 4;
+ result += carry;
+ result += w;
+ carry = (w > result);
+ } while (count);
+ result += carry;
+ result = (result & 0xffff) + (result >> 16);
+ }
+ if (len & 2) {
+ result += *(unsigned short *) buff;
+ buff += 2;
+ }
+ }
+ if (len & 1)
+ result += (*buff << 8);
+ result = from32to16(result);
+ if (odd)
+ result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
+out:
+ return result;
+}
+
+/*
+ * This is a version of ip_compute_csum() optimized for IP headers,
+ * which always checksum on 4 octet boundaries.
+ */
+__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+{
+ return (__force __sum16)~do_csum(iph,ihl*4);
+}
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+__wsum csum_partial(const void *buff, int len, __wsum sum)
+{
+ unsigned int result = do_csum(buff, len);
+
+ /* add in old sum, and carry.. */
+ result += sum;
+ if (sum > result)
+ result += 1;
+ return result;
+}
+EXPORT_SYMBOL(csum_partial);
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+__sum16 ip_compute_csum(const unsigned char *buff, int len)
+{
+ return ~do_csum(buff, len);
+}
+EXPORT_SYMBOL(ip_compute_csum);
+
+/*
+ * copy from fs while checksumming, otherwise like csum_partial
+ */
+__wsum
+csum_partial_copy_from_user(const char __user *src, char *dst, int len,
+ int sum, int *csum_err)
+{
+ if (csum_err)
+ *csum_err = 0;
+ memcpy(dst, src, len);
+ return csum_partial(dst, len, sum);
+}
+EXPORT_SYMBOL(csum_partial_copy_from_user);
+
+/*
+ * copy from ds while checksumming, otherwise like csum_partial
+ */
+__wsum
+csum_partial_copy(const char *src, char *dst, int len, int sum)
+{
+ memcpy(dst, src, len);
+ return csum_partial(dst, len, sum);
+}
+EXPORT_SYMBOL(csum_partial_copy);
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/page.h | 139 +++++++++++++++++++++++++++++++
arch/microblaze/include/asm/segment.h | 43 ++++++++++
arch/microblaze/include/asm/unaligned.h | 22 +++++
3 files changed, 204 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/page.h
create mode 100644 arch/microblaze/include/asm/segment.h
create mode 100644 arch/microblaze/include/asm/unaligned.h
diff --git a/arch/microblaze/include/asm/page.h b/arch/microblaze/include/asm/page.h
new file mode 100644
index 0000000..15db1ea
--- /dev/null
+++ b/arch/microblaze/include/asm/page.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2008 Michal Simek
+ * Copyright (C) 2008 PetaLogix
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ * Changes for MMU support:
+ * Copyright (C) 2007 Xilinx, Inc. All rights reserved.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_PAGE_H
+#define _ASM_MICROBLAZE_PAGE_H
+
+#include <linux/pfn.h>
+#include <asm/setup.h>
+
+/* PAGE_SHIFT determines the page size */
+#define PAGE_SHIFT (12)
+#define PAGE_SIZE (1UL << PAGE_SHIFT)
+#define PAGE_MASK (~(PAGE_SIZE-1))
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+
+#define PAGE_UP(addr) (((addr)+((PAGE_SIZE)-1))&(~((PAGE_SIZE)-1)))
+#define PAGE_DOWN(addr) ((addr)&(~((PAGE_SIZE)-1)))
+
+/* align addr on a size boundary - adjust address up/down if needed */
+#define _ALIGN_UP(addr, size) (((addr)+((size)-1))&(~((size)-1)))
+#define _ALIGN_DOWN(addr, size) ((addr)&(~((size)-1)))
+
+/* align addr on a size boundary - adjust address up if needed */
+#define _ALIGN(addr, size) _ALIGN_UP(addr, size)
+
+/*
+ * PAGE_OFFSET -- the first address of the first page of memory. When not
+ * using MMU this corresponds to the first free page in physical memory (aligned
+ * on a page boundary).
+ */
+extern unsigned int __page_offset;
+#define PAGE_OFFSET __page_offset
+
+#define copy_page(to, from) memcpy((to), (from), PAGE_SIZE)
+#define get_user_page(vaddr) __get_free_page(GFP_KERNEL)
+#define free_user_page(page, addr) free_page(addr)
+
+#define clear_page(pgaddr) memset((pgaddr), 0, PAGE_SIZE)
+
+
+#define clear_user_page(pgaddr, vaddr, page) memset((pgaddr), 0, PAGE_SIZE)
+#define copy_user_page(vto, vfrom, vaddr, topg) \
+ memcpy((vto), (vfrom), PAGE_SIZE)
+
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct page *pgtable_t;
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+typedef struct { unsigned long ste[64]; } pmd_t;
+typedef struct { pmd_t pue[1]; } pud_t;
+typedef struct { pud_t pge[1]; } pgd_t;
+
+
+#define pte_val(x) ((x).pte)
+#define pgprot_val(x) ((x).pgprot)
+#define pmd_val(x) ((x).ste[0])
+#define pud_val(x) ((x).pue[0])
+#define pgd_val(x) ((x).pge[0])
+
+#define __pte(x) ((pte_t) { (x) })
+#define __pmd(x) ((pmd_t) { (x) })
+#define __pgd(x) ((pgd_t) { (x) })
+#define __pgprot(x) ((pgprot_t) { (x) })
+
+/**
+ * Conversions for virtual address, physical address, pfn, and struct
+ * page are defined in the following files.
+ *
+ * virt -+
+ * | asm-microblaze/page.h
+ * phys -+
+ * | linux/pfn.h
+ * pfn -+
+ * | asm-generic/memory_model.h
+ * page -+
+ *
+ */
+
+extern unsigned long max_low_pfn;
+extern unsigned long min_low_pfn;
+extern unsigned long max_pfn;
+
+#define __pa(vaddr) ((unsigned long) (vaddr))
+#define __va(paddr) ((void *) (paddr))
+
+#define phys_to_pfn(phys) (PFN_DOWN(phys))
+#define pfn_to_phys(pfn) (PFN_PHYS(pfn))
+
+#define virt_to_pfn(vaddr) (phys_to_pfn((__pa(vaddr))))
+#define pfn_to_virt(pfn) __va(pfn_to_phys((pfn)))
+
+#define virt_to_page(vaddr) (pfn_to_page(virt_to_pfn(vaddr)))
+#define page_to_virt(page) (pfn_to_virt(page_to_pfn(page)))
+
+#define page_to_phys(page) (pfn_to_phys(page_to_pfn(page)))
+#define page_to_bus(page) (page_to_phys(page))
+#define phys_to_page(paddr) (pfn_to_page(phys_to_pfn(paddr)))
+
+extern unsigned int memory_start;
+extern unsigned int memory_end;
+extern unsigned int memory_size;
+
+#define pfn_valid(pfn) ((pfn) >= min_low_pfn && (pfn) < max_mapnr)
+
+#define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT)
+
+#endif /* __ASSEMBLY__ */
+
+#define virt_addr_valid(vaddr) (pfn_valid(virt_to_pfn(vaddr)))
+
+/* Convert between virtual and physical address for MMU. */
+/* Handle MicroBlaze processor with virtual memory. */
+#define __virt_to_phys(addr) addr
+#define __phys_to_virt(addr) addr
+#define tophys(rd,rs) addik rd,rs,0
+#define tovirt(rd,rs) addik rd,rs,0
+
+#define TOPHYS(addr) __virt_to_phys(addr)
+
+#endif /* __KERNEL__ */
+
+#include <asm-generic/memory_model.h>
+#include <asm-generic/page.h>
+
+#endif /* _ASM_MICROBLAZE_PAGE_H */
diff --git a/arch/microblaze/include/asm/segment.h b/arch/microblaze/include/asm/segment.h
new file mode 100644
index 0000000..7f5dcc5
--- /dev/null
+++ b/arch/microblaze/include/asm/segment.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2008 Michal Simek
+ * Copyright (C) 2008 PetaLogix
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_SEGMENT_H
+#define _ASM_MICROBLAZE_SEGMENT_H
+
+#ifndef __ASSEMBLY__
+
+typedef struct {
+ unsigned long seg;
+} mm_segment_t;
+
+/*
+ * On Microblaze the fs value is actually the top of the corresponding
+ * address space.
+ *
+ * The fs value determines whether argument validity checking should be
+ * performed or not. If get_fs() == USER_DS, checking is performed, with
+ * get_fs() == KERNEL_DS, checking is bypassed.
+ *
+ * For historical reasons, these macros are grossly misnamed.
+ *
+ * For non-MMU arch like Microblaze, KERNEL_DS and USER_DS is equal.
+ */
+# define KERNEL_DS ((mm_segment_t){0})
+# define USER_DS KERNEL_DS
+
+# define get_ds() (KERNEL_DS)
+# define get_fs() (current_thread_info()->addr_limit)
+# define set_fs(x) \
+ do { current_thread_info()->addr_limit = (x); } while (0)
+
+# define segment_eq(a, b) ((a).seg == (b).seg)
+
+# endif /* __ASSEMBLY__ */
+#endif /* _ASM_MICROBLAZE_SEGMENT_H */
diff --git a/arch/microblaze/include/asm/unaligned.h b/arch/microblaze/include/asm/unaligned.h
new file mode 100644
index 0000000..9d66b64
--- /dev/null
+++ b/arch/microblaze/include/asm/unaligned.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2008 Michal Simek <[email protected]>
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_UNALIGNED_H
+#define _ASM_MICROBLAZE_UNALIGNED_H
+
+# ifdef __KERNEL__
+
+# include <linux/unaligned/access_ok.h>
+# include <linux/unaligned/generic.h>
+
+# define get_unaligned __get_unaligned_be
+# define put_unaligned __put_unaligned_be
+
+# endif /* __KERNEL__ */
+#endif /* _ASM_MICROBLAZE_UNALIGNED_H */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/io.h | 209 ++++++++++++++++++++++++++++++++++++++
1 files changed, 209 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/io.h
diff --git a/arch/microblaze/include/asm/io.h b/arch/microblaze/include/asm/io.h
new file mode 100644
index 0000000..4ff514e
--- /dev/null
+++ b/arch/microblaze/include/asm/io.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_IO_H
+#define _ASM_MICROBLAZE_IO_H
+
+#include <asm/byteorder.h>
+#include <asm/page.h>
+#include <linux/types.h>
+#include <asm/page.h>
+
+#define IO_SPACE_LIMIT ~(0UL)
+
+static inline unsigned char __raw_readb(const volatile void __iomem *addr)
+{
+ return *(volatile unsigned char __force *)addr;
+}
+static inline unsigned short __raw_readw(const volatile void __iomem *addr)
+{
+ return *(volatile unsigned short __force *)addr;
+}
+static inline unsigned int __raw_readl(const volatile void __iomem *addr)
+{
+ return *(volatile unsigned int __force *)addr;
+}
+static inline unsigned long __raw_readq(const volatile void __iomem *addr)
+{
+ return *(volatile unsigned long __force *)addr;
+}
+static inline void __raw_writeb(unsigned char v, volatile void __iomem *addr)
+{
+ *(volatile unsigned char __force *)addr = v;
+}
+static inline void __raw_writew(unsigned short v, volatile void __iomem *addr)
+{
+ *(volatile unsigned short __force *)addr = v;
+}
+static inline void __raw_writel(unsigned int v, volatile void __iomem *addr)
+{
+ *(volatile unsigned int __force *)addr = v;
+}
+static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr)
+{
+ *(volatile unsigned long __force *)addr = v;
+}
+
+/*
+ * read (readb, readw, readl, readq) and write (writeb, writew,
+ * writel, writeq) accessors are for PCI and thus littel endian.
+ * Linux 2.4 for Microblaze had this wrong.
+ */
+static inline unsigned char readb(const volatile void __iomem *addr)
+{
+ return *(volatile unsigned char __force *)addr;
+}
+static inline unsigned short readw(const volatile void __iomem *addr)
+{
+ return le16_to_cpu(*(volatile unsigned short __force *)addr);
+}
+static inline unsigned int readl(const volatile void __iomem *addr)
+{
+ return le32_to_cpu(*(volatile unsigned int __force *)addr);
+}
+static inline void writeb(unsigned char v, volatile void __iomem *addr)
+{
+ *(volatile unsigned char __force *)addr = v;
+}
+static inline void writew(unsigned short v, volatile void __iomem *addr)
+{
+ *(volatile unsigned short __force *)addr = cpu_to_le16(v);
+}
+static inline void writel(unsigned int v, volatile void __iomem *addr)
+{
+ *(volatile unsigned int __force *)addr = cpu_to_le32(v);
+}
+
+/* ioread and iowrite variants. thease are for now same as __raw_
+ * variants of accessors. we might check for endianess in the feature
+ */
+#define ioread8(addr) __raw_readb((u8 *)(addr))
+#define ioread16(addr) __raw_readw((u16 *)(addr))
+#define ioread32(addr) __raw_readl((u32 *)(addr))
+#define iowrite8(v, addr) __raw_writeb((u8)(v), (u8 *)(addr))
+#define iowrite16(v, addr) __raw_writew((u16)(v), (u16 *)(addr))
+#define iowrite32(v, addr) __raw_writel((u32)(v), (u32 *)(addr))
+
+/* These are the definitions for the x86 IO instructions
+ * inb/inw/inl/outb/outw/outl, the "string" versions
+ * insb/insw/insl/outsb/outsw/outsl, and the "pausing" versions
+ * inb_p/inw_p/...
+ * The macros don't do byte-swapping.
+ */
+#define inb(port) readb((u8 *)((port)))
+#define outb(val, port) writeb((val), (u8 *)((unsigned long)(port)))
+#define inw(port) readw((u16 *)((port)))
+#define outw(val, port) writew((val), (u16 *)((unsigned long)(port)))
+#define inl(port) readl((u32 *)((port)))
+#define outl(val, port) writel((val), (u32 *)((unsigned long)(port)))
+
+#define inb_p(port) inb((port))
+#define outb_p(val, port) outb((val), (port))
+#define inw_p(port) inw((port))
+#define outw_p(val, port) outw((val), (port))
+#define inl_p(port) inl((port))
+#define outl_p(val, port) outl((val), (port))
+
+#define memset_io(a, b, c) memset((void *)(a), (b), (c))
+#define memcpy_fromio(a, b, c) memcpy((a), (void *)(b), (c))
+#define memcpy_toio(a, b, c) memcpy((void *)(a), (b), (c))
+
+/**
+ * virt_to_phys - map virtual addresses to physical
+ * @address: address to remap
+ *
+ * The returned physical address is the physical (CPU) mapping for
+ * the memory address given. It is only valid to use this function on
+ * addresses directly mapped or allocated via kmalloc.
+ *
+ * This function does not give bus mappings for DMA transfers. In
+ * almost all conceivable cases a device driver should not be using
+ * this function
+ */
+static inline unsigned long __iomem virt_to_phys(volatile void *address)
+{
+ return __pa((unsigned long)address);
+}
+
+#define virt_to_bus virt_to_phys
+
+/**
+ * phys_to_virt - map physical address to virtual
+ * @address: address to remap
+ *
+ * The returned virtual address is a current CPU mapping for
+ * the memory address given. It is only valid to use this function on
+ * addresses that have a kernel mapping
+ *
+ * This function does not handle bus mappings for DMA transfers. In
+ * almost all conceivable cases a device driver should not be using
+ * this function
+ */
+static inline void *phys_to_virt(unsigned long address)
+{
+ return (void *)__va(address);
+}
+
+#define bus_to_virt(a) phys_to_virt(a)
+
+static inline void __iomem *__ioremap(phys_addr_t address, unsigned long size,
+ unsigned long flags)
+{
+ return (void *)address;
+}
+
+#define ioremap(physaddr, size) ((void __iomem *)(unsigned long)(physaddr))
+#define iounmap(addr) ((void)0)
+#define ioremap_nocache(physaddr, size) ioremap(physaddr, size)
+
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
+/*
+ * Big Endian
+ */
+#define out_be32(a, v) __raw_writel((v), (void __iomem __force *)(a))
+#define out_be16(a, v) __raw_writew((v), (a))
+
+#define in_be32(a) __raw_readl((const void __iomem __force *)(a))
+#define in_be16(a) __raw_readw(a)
+
+/*
+ * Little endian
+ */
+
+#define out_le32(a, v) __raw_writel(__cpu_to_le32(v), (a));
+#define out_le16(a, v) __raw_writew(__cpu_to_le16(v), (a))
+
+#define in_le32(a) __le32_to_cpu(__raw_readl(a))
+#define in_le16(a) __le16_to_cpu(__raw_readw(a))
+
+/* Byte ops */
+#define out_8(a, v) __raw_writeb((v), (a))
+#define in_8(a) __raw_readb(a)
+
+/* FIXME */
+static inline void __iomem *ioport_map(unsigned long port, unsigned int len)
+{
+ return (void __iomem *) (port);
+}
+
+static inline void ioport_unmap(void __iomem *addr)
+{
+ /* Nothing to do */
+}
+
+#endif /* _ASM_MICROBLAZE_IO_H */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/string.h | 24 +++++
arch/microblaze/include/asm/thread_info.h | 152 +++++++++++++++++++++++++++++
2 files changed, 176 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/string.h
create mode 100644 arch/microblaze/include/asm/thread_info.h
diff --git a/arch/microblaze/include/asm/string.h b/arch/microblaze/include/asm/string.h
new file mode 100644
index 0000000..f7728c9
--- /dev/null
+++ b/arch/microblaze/include/asm/string.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_STRING_H
+#define _ASM_MICROBLAZE_STRING_H
+
+#ifndef __KERNEL__
+
+#define __HAVE_ARCH_MEMSET
+#define __HAVE_ARCH_MEMCPY
+#define __HAVE_ARCH_MEMMOVE
+
+extern void *memset(void *, int, __kernel_size_t);
+extern void *memcpy(void *, const void *, __kernel_size_t);
+extern void *memmove(void *, const void *, __kernel_size_t);
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_MICROBLAZE_STRING_H */
diff --git a/arch/microblaze/include/asm/thread_info.h b/arch/microblaze/include/asm/thread_info.h
new file mode 100644
index 0000000..95605b8
--- /dev/null
+++ b/arch/microblaze/include/asm/thread_info.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_THREAD_INFO_H
+#define _ASM_MICROBLAZE_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+/* we have 8k stack */
+#define THREAD_SHIFT 13
+#define THREAD_SIZE (1 << THREAD_SHIFT)
+#define THREAD_SIZE_ORDER 1
+
+#ifndef __ASSEMBLY__
+# include <linux/types.h>
+# include <asm/processor.h>
+# include <asm/segment.h>
+
+/*
+ * low level task data that entry.S needs immediate access to
+ * - this struct should fit entirely inside of one cache line
+ * - this struct shares the supervisor stack pages
+ * - if the contents of this structure are changed, the assembly constants
+ * must also be changed
+ */
+
+struct cpu_context {
+ __u32 r1; /* stack pointer */
+ __u32 r2;
+ /* dedicated registers */
+ __u32 r13;
+ __u32 r14;
+ __u32 r15;
+ __u32 r16;
+ __u32 r17;
+ __u32 r18;
+ /* non-volatile registers */
+ __u32 r19;
+ __u32 r20;
+ __u32 r21;
+ __u32 r22;
+ __u32 r23;
+ __u32 r24;
+ __u32 r25;
+ __u32 r26;
+ __u32 r27;
+ __u32 r28;
+ __u32 r29;
+ __u32 r30;
+ /* r31 is used as current task pointer */
+ /* special purpose registers */
+ __u32 msr;
+ __u32 ear;
+ __u32 esr;
+ __u32 fsr;
+};
+
+struct thread_info {
+ struct task_struct *task; /* main task structure */
+ struct exec_domain *exec_domain; /* execution domain */
+ unsigned long flags; /* low level flags */
+ unsigned long status; /* thread-synchronous flags */
+ __u32 cpu; /* current CPU */
+ __s32 preempt_count; /* 0 => preemptable,< 0 => BUG*/
+ mm_segment_t addr_limit; /* thread address space */
+ struct restart_block restart_block;
+
+ struct cpu_context cpu_context;
+};
+
+/*
+ * macros/functions for gaining access to the thread information structure
+ *
+ * preempt_count needs to be 1 initially, until the scheduler is functional.
+ */
+#define INIT_THREAD_INFO(tsk) \
+{ \
+ .task = &tsk, \
+ .exec_domain = &default_exec_domain, \
+ .flags = 0, \
+ .cpu = 0, \
+ .preempt_count = 1, \
+ .addr_limit = KERNEL_DS, \
+ .restart_block = { \
+ .fn = do_no_restart_syscall, \
+ }, \
+}
+
+#define init_thread_info (init_thread_union.thread_info)
+#define init_stack (init_thread_union.stack)
+
+/* how to get the thread information struct from C */
+static inline struct thread_info *current_thread_info(void)
+{
+ register unsigned long sp asm("r1");
+
+ return (struct thread_info *)(sp & ~(THREAD_SIZE-1));
+}
+
+/* thread information allocation */
+#endif /* __ASSEMBLY__ */
+
+#define PREEMPT_ACTIVE 0x10000000
+
+/*
+ * thread information flags
+ * - these are process state flags that various assembly files may
+ * need to access
+ * - pending work-to-be-done flags are in LSW
+ * - other flags in MSW
+ */
+#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
+#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
+#define TIF_SIGPENDING 2 /* signal pending */
+#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
+/* restore singlestep on return to user mode */
+#define TIF_SINGLESTEP 4
+#define TIF_IRET 5 /* return with iret */
+#define TIF_MEMDIE 6
+/* true if poll_idle() is polling TIF_NEED_RESCHED */
+#define TIF_POLLING_NRFLAG 16
+
+#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
+#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
+#define _TIF_IRET (1<<TIF_IRET)
+#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
+
+/* work to do on interrupt/exception return */
+#define _TIF_WORK_MASK 0x0000FFFE
+/* work to do on any return to u-space */
+#define _TIF_ALLWORK_MASK 0x0000FFFF
+
+/*
+ * Thread-synchronous status.
+ *
+ * This is different from the flags in that nobody else
+ * ever touches our thread-synchronous status, so we don't
+ * have to worry about atomic accesses.
+ */
+/* FPU was used by this task this quantum (SMP) */
+#define TS_USEDFPU 0x0001
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_MICROBLAZE_THREAD_INFO_H */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/cputime.h | 1 +
arch/microblaze/include/asm/div64.h | 1 +
arch/microblaze/include/asm/emergency-restart.h | 1 +
arch/microblaze/include/asm/errno.h | 1 +
arch/microblaze/include/asm/futex.h | 1 +
arch/microblaze/include/asm/gpio.h | 56 +++++++++++++++++++++++
arch/microblaze/include/asm/kdebug.h | 1 +
arch/microblaze/include/asm/local.h | 1 +
arch/microblaze/include/asm/mutex.h | 1 +
arch/microblaze/include/asm/percpu.h | 1 +
arch/microblaze/include/asm/resource.h | 1 +
arch/microblaze/include/asm/serial.h | 14 ++++++
12 files changed, 80 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/auxvec.h
create mode 100644 arch/microblaze/include/asm/cputable.h
create mode 100644 arch/microblaze/include/asm/cputime.h
create mode 100644 arch/microblaze/include/asm/div64.h
create mode 100644 arch/microblaze/include/asm/emergency-restart.h
create mode 100644 arch/microblaze/include/asm/errno.h
create mode 100644 arch/microblaze/include/asm/futex.h
create mode 100644 arch/microblaze/include/asm/gpio.h
create mode 100644 arch/microblaze/include/asm/kdebug.h
create mode 100644 arch/microblaze/include/asm/local.h
create mode 100644 arch/microblaze/include/asm/mutex.h
create mode 100644 arch/microblaze/include/asm/percpu.h
create mode 100644 arch/microblaze/include/asm/resource.h
create mode 100644 arch/microblaze/include/asm/serial.h
create mode 100644 arch/microblaze/include/asm/user.h
diff --git a/arch/microblaze/include/asm/auxvec.h b/arch/microblaze/include/asm/auxvec.h
new file mode 100644
index 0000000..e69de29
diff --git a/arch/microblaze/include/asm/cputable.h b/arch/microblaze/include/asm/cputable.h
new file mode 100644
index 0000000..e69de29
diff --git a/arch/microblaze/include/asm/cputime.h b/arch/microblaze/include/asm/cputime.h
new file mode 100644
index 0000000..6d68ad7
--- /dev/null
+++ b/arch/microblaze/include/asm/cputime.h
@@ -0,0 +1 @@
+#include <asm-generic/cputime.h>
diff --git a/arch/microblaze/include/asm/div64.h b/arch/microblaze/include/asm/div64.h
new file mode 100644
index 0000000..6cd978c
--- /dev/null
+++ b/arch/microblaze/include/asm/div64.h
@@ -0,0 +1 @@
+#include <asm-generic/div64.h>
diff --git a/arch/microblaze/include/asm/emergency-restart.h b/arch/microblaze/include/asm/emergency-restart.h
new file mode 100644
index 0000000..3711bd9
--- /dev/null
+++ b/arch/microblaze/include/asm/emergency-restart.h
@@ -0,0 +1 @@
+#include <asm-generic/emergency-restart.h>
diff --git a/arch/microblaze/include/asm/errno.h b/arch/microblaze/include/asm/errno.h
new file mode 100644
index 0000000..4c82b50
--- /dev/null
+++ b/arch/microblaze/include/asm/errno.h
@@ -0,0 +1 @@
+#include <asm-generic/errno.h>
diff --git a/arch/microblaze/include/asm/futex.h b/arch/microblaze/include/asm/futex.h
new file mode 100644
index 0000000..0b74582
--- /dev/null
+++ b/arch/microblaze/include/asm/futex.h
@@ -0,0 +1 @@
+#include <asm-generic/futex.h>
diff --git a/arch/microblaze/include/asm/gpio.h b/arch/microblaze/include/asm/gpio.h
new file mode 100644
index 0000000..ea04632
--- /dev/null
+++ b/arch/microblaze/include/asm/gpio.h
@@ -0,0 +1,56 @@
+/*
+ * Generic GPIO API implementation for PowerPC.
+ *
+ * Copyright (c) 2007-2008 MontaVista Software, Inc.
+ *
+ * Author: Anton Vorontsov <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __ASM_POWERPC_GPIO_H
+#define __ASM_POWERPC_GPIO_H
+
+#include <linux/errno.h>
+#include <asm-generic/gpio.h>
+
+#ifdef CONFIG_GPIOLIB
+
+/*
+ * We don't (yet) implement inlined/rapid versions for on-chip gpios.
+ * Just call gpiolib.
+ */
+static inline int gpio_get_value(unsigned int gpio)
+{
+ return __gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned int gpio, int value)
+{
+ __gpio_set_value(gpio, value);
+}
+
+static inline int gpio_cansleep(unsigned int gpio)
+{
+ return __gpio_cansleep(gpio);
+}
+
+/*
+ * Not implemented, yet.
+ */
+static inline int gpio_to_irq(unsigned int gpio)
+{
+ return -ENOSYS;
+}
+
+static inline int irq_to_gpio(unsigned int irq)
+{
+ return -EINVAL;
+}
+
+#endif /* CONFIG_GPIOLIB */
+
+#endif /* __ASM_POWERPC_GPIO_H */
diff --git a/arch/microblaze/include/asm/kdebug.h b/arch/microblaze/include/asm/kdebug.h
new file mode 100644
index 0000000..6ece1b0
--- /dev/null
+++ b/arch/microblaze/include/asm/kdebug.h
@@ -0,0 +1 @@
+#include <asm-generic/kdebug.h>
diff --git a/arch/microblaze/include/asm/local.h b/arch/microblaze/include/asm/local.h
new file mode 100644
index 0000000..c11c530
--- /dev/null
+++ b/arch/microblaze/include/asm/local.h
@@ -0,0 +1 @@
+#include <asm-generic/local.h>
diff --git a/arch/microblaze/include/asm/mutex.h b/arch/microblaze/include/asm/mutex.h
new file mode 100644
index 0000000..ff6101a
--- /dev/null
+++ b/arch/microblaze/include/asm/mutex.h
@@ -0,0 +1 @@
+#include <asm-generic/mutex-dec.h>
diff --git a/arch/microblaze/include/asm/percpu.h b/arch/microblaze/include/asm/percpu.h
new file mode 100644
index 0000000..06a959d
--- /dev/null
+++ b/arch/microblaze/include/asm/percpu.h
@@ -0,0 +1 @@
+#include <asm-generic/percpu.h>
diff --git a/arch/microblaze/include/asm/resource.h b/arch/microblaze/include/asm/resource.h
new file mode 100644
index 0000000..04bc4db
--- /dev/null
+++ b/arch/microblaze/include/asm/resource.h
@@ -0,0 +1 @@
+#include <asm-generic/resource.h>
diff --git a/arch/microblaze/include/asm/serial.h b/arch/microblaze/include/asm/serial.h
new file mode 100644
index 0000000..39bfc8c
--- /dev/null
+++ b/arch/microblaze/include/asm/serial.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2009 Michal Simek <[email protected]>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_SERIAL_H
+#define _ASM_MICROBLAZE_SERIAL_H
+
+# define BASE_BAUD (1843200 / 16)
+
+#endif /* _ASM_MICROBLAZE_SERIAL_H */
diff --git a/arch/microblaze/include/asm/user.h b/arch/microblaze/include/asm/user.h
new file mode 100644
index 0000000..e69de29
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/ipc.h | 1 +
arch/microblaze/include/asm/ipcbuf.h | 36 +++++
arch/microblaze/kernel/sys_microblaze.c | 226 +++++++++++++++++++++++++++++++
3 files changed, 263 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/ipc.h
create mode 100644 arch/microblaze/include/asm/ipcbuf.h
create mode 100644 arch/microblaze/kernel/sys_microblaze.c
diff --git a/arch/microblaze/include/asm/ipc.h b/arch/microblaze/include/asm/ipc.h
new file mode 100644
index 0000000..a46e3d9
--- /dev/null
+++ b/arch/microblaze/include/asm/ipc.h
@@ -0,0 +1 @@
+#include <asm-generic/ipc.h>
diff --git a/arch/microblaze/include/asm/ipcbuf.h b/arch/microblaze/include/asm/ipcbuf.h
new file mode 100644
index 0000000..b056fa4
--- /dev/null
+++ b/arch/microblaze/include/asm/ipcbuf.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_IPCBUF_H
+#define _ASM_MICROBLAZE_IPCBUF_H
+
+/*
+ * The user_ipc_perm structure for microblaze architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 32-bit mode_t and seq
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct ipc64_perm {
+ __kernel_key_t key;
+ __kernel_uid32_t uid;
+ __kernel_gid32_t gid;
+ __kernel_uid32_t cuid;
+ __kernel_gid32_t cgid;
+ __kernel_mode_t mode;
+ unsigned short __pad1;
+ unsigned short seq;
+ unsigned short __pad2;
+ unsigned long __unused1;
+ unsigned long __unused2;
+};
+
+#endif /* _ASM_MICROBLAZE_IPCBUF_H */
diff --git a/arch/microblaze/kernel/sys_microblaze.c b/arch/microblaze/kernel/sys_microblaze.c
new file mode 100644
index 0000000..831fc31
--- /dev/null
+++ b/arch/microblaze/kernel/sys_microblaze.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2007 PetaLogix
+ * John Williams <[email protected]>
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ * Yasushi SHOJI <[email protected]>
+ * Tetsuya OHKAWA <[email protected]>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/syscalls.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/stat.h>
+#include <linux/mman.h>
+#include <linux/sys.h>
+#include <linux/ipc.h>
+#include <linux/utsname.h>
+#include <linux/file.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/ipc.h>
+#include <linux/semaphore.h>
+#include <linux/syscalls.h>
+#include <linux/uaccess.h>
+#include <linux/unistd.h>
+
+#include <asm/syscalls.h>
+/*
+ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+ *
+ * This is really horribly ugly. This will be remove with new toolchain.
+ */
+asmlinkage int
+sys_ipc(uint call, int first, int second, int third, void *ptr, long fifth)
+{
+ int version, ret;
+
+ version = call >> 16; /* hack for backward compatibility */
+ call &= 0xffff;
+
+ ret = -EINVAL;
+ switch (call) {
+ case SEMOP:
+ ret = sys_semop(first, (struct sembuf *)ptr, second);
+ break;
+ case SEMGET:
+ ret = sys_semget(first, second, third);
+ break;
+ case SEMCTL:
+ {
+ union semun fourth;
+
+ if (!ptr)
+ break;
+ if ((ret = access_ok(VERIFY_READ, ptr,
+ sizeof(long)) ? 0 : -EFAULT)
+ || (ret = get_user(fourth.__pad, (void **)ptr)))
+ break;
+ ret = sys_semctl(first, second, third, fourth);
+ break;
+ }
+ case MSGSND:
+ ret = sys_msgsnd(first, (struct msgbuf *) ptr, second, third);
+ break;
+ case MSGRCV:
+ switch (version) {
+ case 0: {
+ struct ipc_kludge tmp;
+
+ if (!ptr)
+ break;
+ if ((ret = access_ok(VERIFY_READ, ptr,
+ sizeof(tmp)) ? 0 : -EFAULT)
+ || (ret = copy_from_user(&tmp,
+ (struct ipc_kludge *) ptr,
+ sizeof(tmp))))
+ break;
+ ret = sys_msgrcv(first, tmp.msgp, second, tmp.msgtyp,
+ third);
+ break;
+ }
+ default:
+ ret = sys_msgrcv(first, (struct msgbuf *) ptr,
+ second, fifth, third);
+ break;
+ }
+ break;
+ case MSGGET:
+ ret = sys_msgget((key_t) first, second);
+ break;
+ case MSGCTL:
+ ret = sys_msgctl(first, second, (struct msqid_ds *) ptr);
+ break;
+ case SHMAT:
+ switch (version) {
+ default: {
+ ulong raddr;
+
+ if ((ret = access_ok(VERIFY_WRITE, (ulong *) third,
+ sizeof(ulong)) ? 0 : -EFAULT))
+ break;
+ ret = do_shmat(first, (char *) ptr, second, &raddr);
+ if (ret)
+ break;
+ ret = put_user(raddr, (ulong *) third);
+ break;
+ }
+ case 1: /* iBCS2 emulator entry point */
+ if (!segment_eq(get_fs(), get_ds()))
+ break;
+ ret = do_shmat(first, (char *) ptr, second,
+ (ulong *) third);
+ break;
+ }
+ break;
+ case SHMDT:
+ ret = sys_shmdt((char *)ptr);
+ break;
+ case SHMGET:
+ ret = sys_shmget(first, second, third);
+ break;
+ case SHMCTL:
+ ret = sys_shmctl(first, second, (struct shmid_ds *) ptr);
+ break;
+ }
+ return -EINVAL;
+}
+
+asmlinkage int sys_vfork(struct pt_regs *regs)
+{
+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->r1,
+ regs, 0, NULL, NULL);
+}
+
+asmlinkage int sys_clone(int flags, unsigned long stack, struct pt_regs *regs)
+{
+ if (!stack)
+ stack = regs->r1;
+ return do_fork(flags, stack, regs, 0, NULL, NULL);
+}
+
+asmlinkage int sys_execve(char __user *filenamei, char __user *__user *argv,
+ char __user *__user *envp, struct pt_regs *regs)
+{
+ int error;
+ char *filename;
+
+ filename = getname(filenamei);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ goto out;
+ error = do_execve(filename, argv, envp, regs);
+ putname(filename);
+out:
+ return error;
+}
+
+asmlinkage unsigned long
+sys_mmap2(unsigned long addr, size_t len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long pgoff)
+{
+ struct file *file = NULL;
+ int ret = -EBADF;
+
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ if (!(flags & MAP_ANONYMOUS)) {
+ file = fget(fd);
+ if (!file) {
+ printk(KERN_INFO "no fd in mmap\r\n");
+ goto out;
+ }
+ }
+
+ down_write(¤t->mm->mmap_sem);
+ ret = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+ up_write(¤t->mm->mmap_sem);
+ if (file)
+ fput(file);
+out:
+ return ret;
+}
+
+asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, off_t offset)
+{
+ int err = -EINVAL;
+
+ if (offset & ~PAGE_MASK) {
+ printk(KERN_INFO "no pagemask in mmap\r\n");
+ goto out;
+ }
+
+ err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+out:
+ return err;
+}
+
+/*
+ * Do a system call from kernel instead of calling sys_execve so we
+ * end up with proper pt_regs.
+ */
+int kernel_execve(const char *filename, char *const argv[], char *const envp[])
+{
+ register const char *__a __asm__("r5") = filename;
+ register const void *__b __asm__("r6") = argv;
+ register const void *__c __asm__("r7") = envp;
+ register unsigned long __syscall __asm__("r12") = __NR_execve;
+ register unsigned long __ret __asm__("r3");
+ __asm__ __volatile__ ("brki r14, 0x8"
+ : "=r" (__ret), "=r" (__syscall)
+ : "1" (__syscall), "r" (__a), "r" (__b), "r" (__c)
+ : "r4", "r8", "r9",
+ "r10", "r11", "r14", "cc", "memory");
+ return __ret;
+}
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/current.h | 21 ++++++++++++++++++
arch/microblaze/include/asm/entry.h | 35 +++++++++++++++++++++++++++++++
arch/microblaze/include/asm/mman.h | 25 ++++++++++++++++++++++
arch/microblaze/include/asm/registers.h | 33 +++++++++++++++++++++++++++++
arch/microblaze/include/asm/sembuf.h | 34 ++++++++++++++++++++++++++++++
5 files changed, 148 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/current.h
create mode 100644 arch/microblaze/include/asm/entry.h
create mode 100644 arch/microblaze/include/asm/mman.h
create mode 100644 arch/microblaze/include/asm/registers.h
create mode 100644 arch/microblaze/include/asm/sembuf.h
diff --git a/arch/microblaze/include/asm/current.h b/arch/microblaze/include/asm/current.h
new file mode 100644
index 0000000..8375ea9
--- /dev/null
+++ b/arch/microblaze/include/asm/current.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_CURRENT_H
+#define _ASM_MICROBLAZE_CURRENT_H
+
+# ifndef __ASSEMBLY__
+/*
+ * Dedicate r31 to keeping the current task pointer
+ */
+register struct task_struct *current asm("r31");
+
+# define get_current() current
+# endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_MICROBLAZE_CURRENT_H */
diff --git a/arch/microblaze/include/asm/entry.h b/arch/microblaze/include/asm/entry.h
new file mode 100644
index 0000000..7f57e42
--- /dev/null
+++ b/arch/microblaze/include/asm/entry.h
@@ -0,0 +1,35 @@
+/*
+ * Definitions used by low-level trap handlers
+ *
+ * Copyright (C) 2008 Michal Simek
+ * Copyright (C) 2007 - 2008 PetaLogix
+ * Copyright (C) 2007 John Williams <[email protected]>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_ENTRY_H
+#define _ASM_MICROBLAZE_ENTRY_H
+
+#include <asm/percpu.h>
+#include <asm/ptrace.h>
+
+/*
+ * These are per-cpu variables required in entry.S, among other
+ * places
+ */
+
+#define PER_CPU(var) per_cpu__##var
+
+# ifndef __ASSEMBLY__
+DECLARE_PER_CPU(unsigned int, KSP); /* Saved kernel stack pointer */
+DECLARE_PER_CPU(unsigned int, KM); /* Kernel/user mode */
+DECLARE_PER_CPU(unsigned int, ENTRY_SP); /* Saved SP on kernel entry */
+DECLARE_PER_CPU(unsigned int, R11_SAVE); /* Temp variable for entry */
+DECLARE_PER_CPU(unsigned int, CURRENT_SAVE); /* Saved current pointer */
+DECLARE_PER_CPU(unsigned int, SYSCALL_SAVE); /* Saved syscall number */
+# endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_MICROBLAZE_ENTRY_H */
diff --git a/arch/microblaze/include/asm/mman.h b/arch/microblaze/include/asm/mman.h
new file mode 100644
index 0000000..4914b13
--- /dev/null
+++ b/arch/microblaze/include/asm/mman.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_MMAN_H
+#define _ASM_MICROBLAZE_MMAN_H
+
+#include <asm-generic/mman.h>
+
+#define MAP_GROWSDOWN 0x0100 /* stack-like segment */
+#define MAP_DENYWRITE 0x0800 /* ETXTBSY */
+#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
+#define MAP_LOCKED 0x2000 /* pages are locked */
+#define MAP_NORESERVE 0x4000 /* don't check for reservations */
+#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
+#define MAP_NONBLOCK 0x10000 /* do not block on IO */
+
+#define MCL_CURRENT 1 /* lock all current mappings */
+#define MCL_FUTURE 2 /* lock all future mappings */
+
+#endif /* _ASM_MICROBLAZE_MMAN_H */
diff --git a/arch/microblaze/include/asm/registers.h b/arch/microblaze/include/asm/registers.h
new file mode 100644
index 0000000..834142d
--- /dev/null
+++ b/arch/microblaze/include/asm/registers.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2008 Michal Simek
+ * Copyright (C) 2008 PetaLogix
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_REGISTERS_H
+#define _ASM_MICROBLAZE_REGISTERS_H
+
+#define MSR_BE (1<<0) /* 0x001 */
+#define MSR_IE (1<<1) /* 0x002 */
+#define MSR_C (1<<2) /* 0x004 */
+#define MSR_BIP (1<<3) /* 0x008 */
+#define MSR_FSL (1<<4) /* 0x010 */
+#define MSR_ICE (1<<5) /* 0x020 */
+#define MSR_DZ (1<<6) /* 0x040 */
+#define MSR_DCE (1<<7) /* 0x080 */
+#define MSR_EE (1<<8) /* 0x100 */
+#define MSR_EIP (1<<9) /* 0x200 */
+#define MSR_CC (1<<31)
+
+/* Floating Point Status Register (FSR) Bits */
+#define FSR_IO (1<<4) /* Invalid operation */
+#define FSR_DZ (1<<3) /* Divide-by-zero */
+#define FSR_OF (1<<2) /* Overflow */
+#define FSR_UF (1<<1) /* Underflow */
+#define FSR_DO (1<<0) /* Denormalized operand error */
+
+#endif /* _ASM_MICROBLAZE_REGISTERS_H */
diff --git a/arch/microblaze/include/asm/sembuf.h b/arch/microblaze/include/asm/sembuf.h
new file mode 100644
index 0000000..b804ed7
--- /dev/null
+++ b/arch/microblaze/include/asm/sembuf.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_SEMBUF_H
+#define _ASM_MICROBLAZE_SEMBUF_H
+
+/*
+ * The semid64_ds structure for microblaze architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct semid64_ds {
+ struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
+ __kernel_time_t sem_otime; /* last semop time */
+ unsigned long __unused1;
+ __kernel_time_t sem_ctime; /* last change time */
+ unsigned long __unused2;
+ unsigned long sem_nsems; /* no. of semaphores in array */
+ unsigned long __unused3;
+ unsigned long __unused4;
+};
+
+
+#endif /* _ASM_MICROBLAZE_SEMBUF_H */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/termbits.h | 203 ++++++++++++++++++++++++++++++++
arch/microblaze/include/asm/termios.h | 88 ++++++++++++++
2 files changed, 291 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/termbits.h
create mode 100644 arch/microblaze/include/asm/termios.h
diff --git a/arch/microblaze/include/asm/termbits.h b/arch/microblaze/include/asm/termbits.h
new file mode 100644
index 0000000..a1b64bc
--- /dev/null
+++ b/arch/microblaze/include/asm/termbits.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_TERMBITS_H
+#define _ASM_MICROBLAZE_TERMBITS_H
+
+#include <linux/posix_types.h>
+
+typedef unsigned char cc_t;
+typedef unsigned int speed_t;
+typedef unsigned int tcflag_t;
+
+#define NCCS 19
+struct termios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+};
+
+struct ktermios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+};
+
+/* c_cc characters */
+
+#define VINTR 0
+#define VQUIT 1
+#define VERASE 2
+#define VKILL 3
+#define VEOF 4
+#define VTIME 5
+#define VMIN 6
+#define VSWTC 7
+#define VSTART 8
+#define VSTOP 9
+#define VSUSP 10
+#define VEOL 11
+#define VREPRINT 12
+#define VDISCARD 13
+#define VWERASE 14
+#define VLNEXT 15
+#define VEOL2 16
+
+/* c_iflag bits */
+
+#define IGNBRK 0000001
+#define BRKINT 0000002
+#define IGNPAR 0000004
+#define PARMRK 0000010
+#define INPCK 0000020
+#define ISTRIP 0000040
+#define INLCR 0000100
+#define IGNCR 0000200
+#define ICRNL 0000400
+#define IUCLC 0001000
+#define IXON 0002000
+#define IXANY 0004000
+#define IXOFF 0010000
+#define IMAXBEL 0020000
+#define IUTF8 0040000
+
+/* c_oflag bits */
+
+#define OPOST 0000001
+#define OLCUC 0000002
+#define ONLCR 0000004
+#define OCRNL 0000010
+#define ONOCR 0000020
+#define ONLRET 0000040
+#define OFILL 0000100
+#define OFDEL 0000200
+#define NLDLY 0000400
+#define NL0 0000000
+#define NL1 0000400
+#define CRDLY 0003000
+#define CR0 0000000
+#define CR1 0001000
+#define CR2 0002000
+#define CR3 0003000
+#define TABDLY 0014000
+#define TAB0 0000000
+#define TAB1 0004000
+#define TAB2 0010000
+#define TAB3 0014000
+#define XTABS 0014000
+#define BSDLY 0020000
+#define BS0 0000000
+#define BS1 0020000
+#define VTDLY 0040000
+#define VT0 0000000
+#define VT1 0040000
+#define FFDLY 0100000
+#define FF0 0000000
+#define FF1 0100000
+
+/* c_cflag bit meaning */
+
+#define CBAUD 0010017
+#define B0 0000000 /* hang up */
+#define B50 0000001
+#define B75 0000002
+#define B110 0000003
+#define B134 0000004
+#define B150 0000005
+#define B200 0000006
+#define B300 0000007
+#define B600 0000010
+#define B1200 0000011
+#define B1800 0000012
+#define B2400 0000013
+#define B4800 0000014
+#define B9600 0000015
+#define B19200 0000016
+#define B38400 0000017
+#define EXTA B19200
+#define EXTB B38400
+#define CSIZE 0000060
+#define CS5 0000000
+#define CS6 0000020
+#define CS7 0000040
+#define CS8 0000060
+#define CSTOPB 0000100
+#define CREAD 0000200
+#define PARENB 0000400
+#define PARODD 0001000
+#define HUPCL 0002000
+#define CLOCAL 0004000
+#define CBAUDEX 0010000
+#define B57600 0010001
+#define B115200 0010002
+#define B230400 0010003
+#define B460800 0010004
+#define B500000 0010005
+#define B576000 0010006
+#define B921600 0010007
+#define BOTHER 0010000
+#define B1000000 0010010
+#define B1152000 0010011
+#define B1500000 0010012
+#define B2000000 0010013
+#define B2500000 0010014
+#define B3000000 0010015
+#define B3500000 0010016
+#define B4000000 0010017
+#define CIBAUD 002003600000 /* input baud rate (not used) */
+#define CMSPAR 010000000000 /* mark or space (stick) parity */
+#define CRTSCTS 020000000000 /* flow control */
+
+#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */
+
+/* c_lflag bits */
+
+#define ISIG 0000001
+#define ICANON 0000002
+#define XCASE 0000004
+#define ECHO 0000010
+#define ECHOE 0000020
+#define ECHOK 0000040
+#define ECHONL 0000100
+#define NOFLSH 0000200
+#define TOSTOP 0000400
+#define ECHOCTL 0001000
+#define ECHOPRT 0002000
+#define ECHOKE 0004000
+#define FLUSHO 0010000
+#define PENDIN 0040000
+#define IEXTEN 0100000
+
+/* tcflow() and TCXONC use these */
+
+#define TCOOFF 0
+#define TCOON 1
+#define TCIOFF 2
+#define TCION 3
+
+/* tcflush() and TCFLSH use these */
+
+#define TCIFLUSH 0
+#define TCOFLUSH 1
+#define TCIOFLUSH 2
+
+/* tcsetattr uses these */
+
+#define TCSANOW 0
+#define TCSADRAIN 1
+#define TCSAFLUSH 2
+
+#endif /* _ASM_MICROBLAZE_TERMBITS_H */
diff --git a/arch/microblaze/include/asm/termios.h b/arch/microblaze/include/asm/termios.h
new file mode 100644
index 0000000..102d772
--- /dev/null
+++ b/arch/microblaze/include/asm/termios.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_TERMIOS_H
+#define _ASM_MICROBLAZE_TERMIOS_H
+
+#include <linux/string.h>
+#include <asm/termbits.h>
+#include <asm/ioctls.h>
+
+struct winsize {
+ unsigned short ws_row;
+ unsigned short ws_col;
+ unsigned short ws_xpixel;
+ unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+ unsigned short c_iflag; /* input mode flags */
+ unsigned short c_oflag; /* output mode flags */
+ unsigned short c_cflag; /* control mode flags */
+ unsigned short c_lflag; /* local mode flags */
+ unsigned char c_line; /* line discipline */
+ unsigned char c_cc[NCC]; /* control characters */
+};
+
+#ifdef __KERNEL__
+/* intr=^C quit=^| erase=del kill=^U
+ eof=^D vtime=\0 vmin=\1 sxtc=\0
+ start=^Q stop=^S susp=^Z eol=\0
+ reprint=^R discard=^U werase=^W lnext=^V
+ eol2=\0
+*/
+#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
+#endif
+
+/* Modem lines */
+
+#define TIOCM_LE 0x001
+#define TIOCM_DTR 0x002
+#define TIOCM_RTS 0x004
+#define TIOCM_ST 0x008
+#define TIOCM_SR 0x010
+#define TIOCM_CTS 0x020
+#define TIOCM_CAR 0x040
+#define TIOCM_RNG 0x080
+#define TIOCM_DSR 0x100
+#define TIOCM_CD TIOCM_CAR
+#define TIOCM_RI TIOCM_RNG
+#define TIOCM_OUT1 0x2000
+#define TIOCM_OUT2 0x4000
+#define TIOCM_LOOP 0x8000
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+
+/* Line disciplines */
+
+#define N_TTY 0
+#define N_SLIP 1
+#define N_MOUSE 2
+#define N_PPP 3
+#define N_STRIP 4
+#define N_AX25 5
+#define N_X25 6 /* X.25 async */
+#define N_6PACK 7
+#define N_MASC 8 /* Reserved for Mobitex module <[email protected]> */
+#define N_R3964 9 /* Reserved for Simatic R3964 module */
+#define N_PROFIBUS_FDL 10 /* Reserved for Profibus <[email protected]> */
+#define N_IRDA 11 /* Linux IR - http://irda.sourceforge.net/ */
+#define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards
+ about SMS messages */
+#define N_HDLC 13 /* synchronous HDLC */
+#define N_SYNC_PPP 14
+#define N_HCI 15 /* Bluetooth HCI UART */
+
+#ifdef __KERNEL__
+
+#include <asm-generic/termios.h>
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_MICROBLAZE_TERMIOS_H */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/ptrace.h | 68 +++++++++
arch/microblaze/kernel/ptrace.c | 252 ++++++++++++++++++++++++++++++++++
2 files changed, 320 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/ptrace.h
create mode 100644 arch/microblaze/kernel/ptrace.c
diff --git a/arch/microblaze/include/asm/ptrace.h b/arch/microblaze/include/asm/ptrace.h
new file mode 100644
index 0000000..f1f0348
--- /dev/null
+++ b/arch/microblaze/include/asm/ptrace.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_PTRACE_H
+#define _ASM_MICROBLAZE_PTRACE_H
+
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+
+typedef unsigned long microblaze_reg_t;
+
+struct pt_regs {
+ microblaze_reg_t r0;
+ microblaze_reg_t r1;
+ microblaze_reg_t r2;
+ microblaze_reg_t r3;
+ microblaze_reg_t r4;
+ microblaze_reg_t r5;
+ microblaze_reg_t r6;
+ microblaze_reg_t r7;
+ microblaze_reg_t r8;
+ microblaze_reg_t r9;
+ microblaze_reg_t r10;
+ microblaze_reg_t r11;
+ microblaze_reg_t r12;
+ microblaze_reg_t r13;
+ microblaze_reg_t r14;
+ microblaze_reg_t r15;
+ microblaze_reg_t r16;
+ microblaze_reg_t r17;
+ microblaze_reg_t r18;
+ microblaze_reg_t r19;
+ microblaze_reg_t r20;
+ microblaze_reg_t r21;
+ microblaze_reg_t r22;
+ microblaze_reg_t r23;
+ microblaze_reg_t r24;
+ microblaze_reg_t r25;
+ microblaze_reg_t r26;
+ microblaze_reg_t r27;
+ microblaze_reg_t r28;
+ microblaze_reg_t r29;
+ microblaze_reg_t r30;
+ microblaze_reg_t r31;
+ microblaze_reg_t pc;
+ microblaze_reg_t msr;
+ microblaze_reg_t ear;
+ microblaze_reg_t esr;
+ microblaze_reg_t fsr;
+ int kernel_mode;
+};
+
+#define kernel_mode(regs) ((regs)->kernel_mode)
+#define user_mode(regs) (!kernel_mode(regs))
+
+#define instruction_pointer(regs) ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
+
+void show_regs(struct pt_regs *);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_MICROBLAZE_PTRACE_H */
diff --git a/arch/microblaze/kernel/ptrace.c b/arch/microblaze/kernel/ptrace.c
new file mode 100644
index 0000000..b046309
--- /dev/null
+++ b/arch/microblaze/kernel/ptrace.c
@@ -0,0 +1,252 @@
+/*
+ * `ptrace' system call
+ *
+ * Copyright (C) 2008 Michal Simek <[email protected]>
+ * Copyright (C) 2007 PetaLogix
+ * Copyright (C) 2004-07 John Williams <[email protected]>
+ *
+ * derived from arch/v850/kernel/ptrace.c
+ *
+ * Copyright (C) 2002,03 NEC Electronics Corporation
+ * Copyright (C) 2002,03 Miles Bader <[email protected]>
+ *
+ * Derived from arch/mips/kernel/ptrace.c:
+ *
+ * Copyright (C) 1992 Ross Biro
+ * Copyright (C) Linus Torvalds
+ * Copyright (C) 1994, 95, 96, 97, 98, 2000 Ralf Baechle
+ * Copyright (C) 1996 David S. Miller
+ * Kevin D. Kissell, [email protected] and Carsten Langgaard, [email protected]
+ * Copyright (C) 1999 MIPS Technologies, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/ptrace.h>
+#include <linux/signal.h>
+
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <asm/processor.h>
+#include <linux/uaccess.h>
+#include <asm/asm-offsets.h>
+
+/* Returns the address where the register at REG_OFFS in P is stashed away. */
+static microblaze_reg_t *reg_save_addr(unsigned reg_offs,
+ struct task_struct *t)
+{
+ struct pt_regs *regs;
+
+ /*
+ * Three basic cases:
+ *
+ * (1) A register normally saved before calling the scheduler, is
+ * available in the kernel entry pt_regs structure at the top
+ * of the kernel stack. The kernel trap/irq exit path takes
+ * care to save/restore almost all registers for ptrace'd
+ * processes.
+ *
+ * (2) A call-clobbered register, where the process P entered the
+ * kernel via [syscall] trap, is not stored anywhere; that's
+ * OK, because such registers are not expected to be preserved
+ * when the trap returns anyway (so we don't actually bother to
+ * test for this case).
+ *
+ * (3) A few registers not used at all by the kernel, and so
+ * normally never saved except by context-switches, are in the
+ * context switch state.
+ */
+
+ /* Register saved during kernel entry (or not available). */
+ regs = task_pt_regs(t);
+
+ return (microblaze_reg_t *)((char *)regs + reg_offs);
+}
+
+#if 0
+static inline microblaze_reg_t getreg(struct task_struct *child, unsigned reg_off)
+{
+ microblaze_reg_t *reg_addr = reg_save_addr(reg_off, child);
+ return *reg_addr;
+}
+
+static inline void putreg(struct task_struct *child, unsigned reg_off, microblaze_reg_t reg_val)
+{
+ microblaze_reg_t *reg_addr = reg_save_addr(reg_off, child);
+ *reg_addr = reg_val;
+}
+#endif
+
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+{
+ int rval;
+ unsigned long val = 0;
+ unsigned long copied;
+
+ switch (request) {
+ case PTRACE_PEEKTEXT: /* read word at location addr. */
+ case PTRACE_PEEKDATA:
+ pr_debug("PEEKTEXT/PEEKDATA at %08lX\n", addr);
+ copied = access_process_vm(child, addr, &val, sizeof(val), 0);
+ rval = -EIO;
+ if (copied != sizeof(val))
+ break;
+ rval = put_user(val, (unsigned long *)data);
+ break;
+
+ case PTRACE_POKETEXT: /* write the word at location addr. */
+ case PTRACE_POKEDATA:
+ pr_debug("POKETEXT/POKEDATA to %08lX\n", addr);
+ rval = 0;
+ if (access_process_vm(child, addr, &data, sizeof(data), 1)
+ == sizeof(data))
+ break;
+ rval = -EIO;
+ break;
+
+ /* Read/write the word at location ADDR in the registers. */
+ case PTRACE_PEEKUSR:
+ case PTRACE_POKEUSR:
+ pr_debug("PEEKUSR/POKEUSR : 0x%08lx\n", addr);
+ rval = 0;
+ if (addr >= PT_SIZE && request == PTRACE_PEEKUSR) {
+ /*
+ * Special requests that don't actually correspond
+ * to offsets in struct pt_regs.
+ */
+ if (addr == PT_TEXT_ADDR) {
+ val = child->mm->start_code;
+ } else if (addr == PT_DATA_ADDR) {
+ val = child->mm->start_data;
+ } else if (addr == PT_TEXT_LEN) {
+ val = child->mm->end_code
+ - child->mm->start_code;
+ } else {
+ rval = -EIO;
+ }
+ } else if (addr >= 0 && addr < PT_SIZE && (addr & 0x3) == 0) {
+ microblaze_reg_t *reg_addr = reg_save_addr(addr, child);
+ if (request == PTRACE_PEEKUSR)
+ val = *reg_addr;
+ else
+ *reg_addr = data;
+ } else
+ rval = -EIO;
+
+ if (rval == 0 && request == PTRACE_PEEKUSR)
+ rval = put_user(val, (unsigned long *)data);
+ break;
+ /* Continue and stop at next (return from) syscall */
+ case PTRACE_SYSCALL:
+ pr_debug("PTRACE_SYSCALL\n");
+ case PTRACE_SINGLESTEP:
+ pr_debug("PTRACE_SINGLESTEP\n");
+ /* Restart after a signal. */
+ case PTRACE_CONT:
+ pr_debug("PTRACE_CONT\n");
+ rval = -EIO;
+ if (!valid_signal(data))
+ break;
+
+ if (request == PTRACE_SYSCALL)
+ set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ else
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+
+ child->exit_code = data;
+ pr_debug("wakeup_process\n");
+ wake_up_process(child);
+ rval = 0;
+ break;
+
+ /*
+ * make the child exit. Best I can do is send it a sigkill.
+ * perhaps it should be put in the status that it wants to
+ * exit.
+ */
+ case PTRACE_KILL:
+ pr_debug("PTRACE_KILL\n");
+ rval = 0;
+ if (child->exit_state == EXIT_ZOMBIE) /* already dead */
+ break;
+ child->exit_code = SIGKILL;
+ wake_up_process(child);
+ break;
+
+ case PTRACE_DETACH: /* detach a process that was attached. */
+ pr_debug("PTRACE_DETACH\n");
+ rval = ptrace_detach(child, data);
+ break;
+
+#if 0
+/* #define PTRACE_GETREGS 12*/
+ case PTRACE_GETREGS: /* get gp regs from the tracee */
+ if (!access_ok(VERIFY_WRITE, datap, PT_SIZE)) {
+ rval = -EIO;
+ break;
+ }
+ for (i = 0; i < PT_SIZE; i += sizeof(long)) {
+ __put_user(getreg(child, i), datap++);
+ }
+ rval = 0;
+ break;
+#endif
+
+#if 0
+/* #define PTRACE_SETREGS 13*/
+ case PTRACE_SETREGS: /* Set gp regs for the tracee */
+ if (!access_ok(VERIFY_READ, datap, PT_SIZE)) {
+ rval = -EIO;
+ break;
+ }
+ for (i = 0; i < PT_SIZE; i += sizeof(long)) {
+ __get_user(val, datap++);
+ if (i == PT_MSR) { /* may only change C and CC bits in MSR */
+ val = (val & 0x80000004) | (getreg(child,i) & ~0x80000004);
+ }
+ putreg(child, i, val);
+ }
+ rval = 0;
+ break;
+#endif
+
+ default:
+ /* rval = ptrace_request(child, request, addr, data); noMMU */
+ rval = -EIO;
+ }
+ return rval;
+}
+
+#if 0
+static asmlinkage void syscall_trace(void)
+{
+ if (!test_thread_flag(TIF_SYSCALL_TRACE))
+ return;
+ if (!(current->ptrace & PT_PTRACED))
+ return;
+ /* The 0x80 provides a way for the tracing parent to distinguish
+ between a syscall stop and SIGTRAP delivery */
+ ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+ ? 0x80 : 0));
+ /*
+ * this isn't the same as continuing with a signal, but it will do
+ * for normal use. strace only continues with a signal if the
+ * stopping signal is not SIGTRAP. -brl
+ */
+ if (current->exit_code) {
+ send_sig(current->exit_code, current, 1);
+ current->exit_code = 0;
+ }
+}
+#endif
+
+void ptrace_disable(struct task_struct *child)
+{
+ /* nothing to do */
+}
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/unistd.h | 419 ++++++++++++++++++++++++++++++++++
1 files changed, 419 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/unistd.h
diff --git a/arch/microblaze/include/asm/unistd.h b/arch/microblaze/include/asm/unistd.h
new file mode 100644
index 0000000..7191fa0
--- /dev/null
+++ b/arch/microblaze/include/asm/unistd.h
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2007-2008 Michal Simek <[email protected]>
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_UNISTD_H
+#define _ASM_MICROBLAZE_UNISTD_H
+
+#define __NR_restart_syscall 0 /* ok */
+#define __NR_exit 1 /* ok */
+#define __NR_fork 2 /* not for no MMU - weird */
+#define __NR_read 3 /* ok */
+#define __NR_write 4 /* ok */
+#define __NR_open 5 /* openat */
+#define __NR_close 6 /* ok */
+#define __NR_waitpid 7 /* waitid */
+#define __NR_creat 8 /* openat */
+#define __NR_link 9 /* linkat */
+#define __NR_unlink 10 /* unlinkat */
+#define __NR_execve 11 /* ok */
+#define __NR_chdir 12 /* ok */
+#define __NR_time 13 /* obsolete -> sys_gettimeofday */
+#define __NR_mknod 14 /* mknodat */
+#define __NR_chmod 15 /* fchmodat */
+#define __NR_lchown 16 /* ok */
+#define __NR_break 17 /* don't know */
+#define __NR_oldstat 18 /* remove */
+#define __NR_lseek 19 /* ok */
+#define __NR_getpid 20 /* ok */
+#define __NR_mount 21 /* ok */
+#define __NR_umount 22 /* ok */ /* use only umount2 */
+#define __NR_setuid 23 /* ok */
+#define __NR_getuid 24 /* ok */
+#define __NR_stime 25 /* obsolete -> sys_settimeofday */
+#define __NR_ptrace 26 /* ok */
+#define __NR_alarm 27 /* obsolete -> sys_setitimer */
+#define __NR_oldfstat 28 /* remove */
+#define __NR_pause 29 /* obsolete -> sys_rt_sigtimedwait */
+#define __NR_utime 30 /* obsolete -> sys_utimesat */
+#define __NR_stty 31 /* remove */
+#define __NR_gtty 32 /* remove */
+#define __NR_access 33 /* faccessat */
+#define __NR_nice 34 /* can be implemented by sys_setpriority */
+#define __NR_ftime 35 /* remove */
+#define __NR_sync 36 /* ok */
+#define __NR_kill 37 /* ok */
+#define __NR_rename 38 /* renameat */
+#define __NR_mkdir 39 /* mkdirat */
+#define __NR_rmdir 40 /* unlinkat */
+#define __NR_dup 41 /* ok */
+#define __NR_pipe 42 /* ok */
+#define __NR_times 43 /* ok */
+#define __NR_prof 44 /* remove */
+#define __NR_brk 45 /* ok -mmu, nommu specific */
+#define __NR_setgid 46 /* ok */
+#define __NR_getgid 47 /* ok */
+#define __NR_signal 48 /* obsolete -> sys_rt_sigaction */
+#define __NR_geteuid 49 /* ok */
+#define __NR_getegid 50 /* ok */
+#define __NR_acct 51 /* add it and then I can disable it */
+#define __NR_umount2 52 /* remove */
+#define __NR_lock 53 /* remove */
+#define __NR_ioctl 54 /* ok */
+#define __NR_fcntl 55 /* ok -> 64bit version*/
+#define __NR_mpx 56 /* remove */
+#define __NR_setpgid 57 /* ok */
+#define __NR_ulimit 58 /* remove */
+#define __NR_oldolduname 59 /* remove */
+#define __NR_umask 60 /* ok */
+#define __NR_chroot 61 /* ok */
+#define __NR_ustat 62 /* obsolete -> statfs64 */
+#define __NR_dup2 63 /* ok */
+#define __NR_getppid 64 /* ok */
+#define __NR_getpgrp 65 /* obsolete -> sys_getpgid */
+#define __NR_setsid 66 /* ok */
+#define __NR_sigaction 67 /* obsolete -> rt_sigaction */
+#define __NR_sgetmask 68 /* obsolete -> sys_rt_sigprocmask */
+#define __NR_ssetmask 69 /* obsolete ->sys_rt_sigprocmask */
+#define __NR_setreuid 70 /* ok */
+#define __NR_setregid 71 /* ok */
+#define __NR_sigsuspend 72 /* obsolete -> rt_sigsuspend */
+#define __NR_sigpending 73 /* obsolete -> sys_rt_sigpending */
+#define __NR_sethostname 74 /* ok */
+#define __NR_setrlimit 75 /* ok */
+#define __NR_getrlimit 76 /* ok Back compatible 2Gig limited rlimit */
+#define __NR_getrusage 77 /* ok */
+#define __NR_gettimeofday 78 /* ok */
+#define __NR_settimeofday 79 /* ok */
+#define __NR_getgroups 80 /* ok */
+#define __NR_setgroups 81 /* ok */
+#define __NR_select 82 /* obsolete -> sys_pselect7 */
+#define __NR_symlink 83 /* symlinkat */
+#define __NR_oldlstat 84 /* remove */
+#define __NR_readlink 85 /* obsolete -> sys_readlinkat */
+#define __NR_uselib 86 /* remove */
+#define __NR_swapon 87 /* ok */
+#define __NR_reboot 88 /* ok */
+#define __NR_readdir 89 /* remove ? */
+#define __NR_mmap 90 /* obsolete -> sys_mmap2 */
+#define __NR_munmap 91 /* ok - mmu and nommu */
+#define __NR_truncate 92 /* ok or truncate64 */
+#define __NR_ftruncate 93 /* ok or ftruncate64 */
+#define __NR_fchmod 94 /* ok */
+#define __NR_fchown 95 /* ok */
+#define __NR_getpriority 96 /* ok */
+#define __NR_setpriority 97 /* ok */
+#define __NR_profil 98 /* remove */
+#define __NR_statfs 99 /* ok or statfs64 */
+#define __NR_fstatfs 100 /* ok or fstatfs64 */
+#define __NR_ioperm 101 /* remove */
+#define __NR_socketcall 102 /* remove */
+#define __NR_syslog 103 /* ok */
+#define __NR_setitimer 104 /* ok */
+#define __NR_getitimer 105 /* ok */
+#define __NR_stat 106 /* remove */
+#define __NR_lstat 107 /* remove */
+#define __NR_fstat 108 /* remove */
+#define __NR_olduname 109 /* remove */
+#define __NR_iopl 110 /* remove */
+#define __NR_vhangup 111 /* ok */
+#define __NR_idle 112 /* remove */
+#define __NR_vm86old 113 /* remove */
+#define __NR_wait4 114 /* obsolete -> waitid */
+#define __NR_swapoff 115 /* ok */
+#define __NR_sysinfo 116 /* ok */
+#define __NR_ipc 117 /* remove - direct call */
+#define __NR_fsync 118 /* ok */
+#define __NR_sigreturn 119 /* obsolete -> sys_rt_sigreturn */
+#define __NR_clone 120 /* ok */
+#define __NR_setdomainname 121 /* ok */
+#define __NR_uname 122 /* remove */
+#define __NR_modify_ldt 123 /* remove */
+#define __NR_adjtimex 124 /* ok */
+#define __NR_mprotect 125 /* remove */
+#define __NR_sigprocmask 126 /* obsolete -> sys_rt_sigprocmask */
+#define __NR_create_module 127 /* remove */
+#define __NR_init_module 128 /* ok */
+#define __NR_delete_module 129 /* ok */
+#define __NR_get_kernel_syms 130 /* remove */
+#define __NR_quotactl 131 /* ok */
+#define __NR_getpgid 132 /* ok */
+#define __NR_fchdir 133 /* ok */
+#define __NR_bdflush 134 /* remove */
+#define __NR_sysfs 135 /* needed for busybox */
+#define __NR_personality 136 /* ok */
+#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
+#define __NR_setfsuid 138 /* ok */
+#define __NR_setfsgid 139 /* ok */
+#define __NR__llseek 140 /* remove only lseek */
+#define __NR_getdents 141 /* ok or getdents64 */
+#define __NR__newselect 142 /* remove */
+#define __NR_flock 143 /* ok */
+#define __NR_msync 144 /* remove */
+#define __NR_readv 145 /* ok */
+#define __NR_writev 146 /* ok */
+#define __NR_getsid 147 /* ok */
+#define __NR_fdatasync 148 /* ok */
+#define __NR__sysctl 149 /* remove */
+#define __NR_mlock 150 /* ok - nommu or mmu */
+#define __NR_munlock 151 /* ok - nommu or mmu */
+#define __NR_mlockall 152 /* ok - nommu or mmu */
+#define __NR_munlockall 153 /* ok - nommu or mmu */
+#define __NR_sched_setparam 154 /* ok */
+#define __NR_sched_getparam 155 /* ok */
+#define __NR_sched_setscheduler 156 /* ok */
+#define __NR_sched_getscheduler 157 /* ok */
+#define __NR_sched_yield 158 /* ok */
+#define __NR_sched_get_priority_max 159 /* ok */
+#define __NR_sched_get_priority_min 160 /* ok */
+#define __NR_sched_rr_get_interval 161 /* ok */
+#define __NR_nanosleep 162 /* ok */
+#define __NR_mremap 163 /* ok - nommu or mmu */
+#define __NR_setresuid 164 /* ok */
+#define __NR_getresuid 165 /* ok */
+#define __NR_vm86 166 /* remove */
+#define __NR_query_module 167 /* ok */
+#define __NR_poll 168 /* obsolete -> sys_ppoll */
+#define __NR_nfsservctl 169 /* ok */
+#define __NR_setresgid 170 /* ok */
+#define __NR_getresgid 171 /* ok */
+#define __NR_prctl 172 /* ok */
+#define __NR_rt_sigreturn 173 /* ok */
+#define __NR_rt_sigaction 174 /* ok */
+#define __NR_rt_sigprocmask 175 /* ok */
+#define __NR_rt_sigpending 176 /* ok */
+#define __NR_rt_sigtimedwait 177 /* ok */
+#define __NR_rt_sigqueueinfo 178 /* ok */
+#define __NR_rt_sigsuspend 179 /* ok */
+#define __NR_pread64 180 /* ok */
+#define __NR_pwrite64 181 /* ok */
+#define __NR_chown 182 /* obsolete -> fchownat */
+#define __NR_getcwd 183 /* ok */
+#define __NR_capget 184 /* ok */
+#define __NR_capset 185 /* ok */
+#define __NR_sigaltstack 186 /* remove */
+#define __NR_sendfile 187 /* ok -> exist 64bit version*/
+#define __NR_getpmsg 188 /* remove - some people actually want streams */
+#define __NR_putpmsg 189 /* remove - some people actually want streams */
+#define __NR_vfork 190 /* for noMMU - group with clone -> maybe remove */
+#define __NR_ugetrlimit 191 /* remove - SuS compliant getrlimit */
+#define __NR_mmap2 192 /* ok */
+#define __NR_truncate64 193 /* ok */
+#define __NR_ftruncate64 194 /* ok */
+#define __NR_stat64 195 /* remove _ARCH_WANT_STAT64 */
+#define __NR_lstat64 196 /* remove _ARCH_WANT_STAT64 */
+#define __NR_fstat64 197 /* remove _ARCH_WANT_STAT64 */
+#define __NR_lchown32 198 /* ok - without 32 */
+#define __NR_getuid32 199 /* ok - without 32 */
+#define __NR_getgid32 200 /* ok - without 32 */
+#define __NR_geteuid32 201 /* ok - without 32 */
+#define __NR_getegid32 202 /* ok - without 32 */
+#define __NR_setreuid32 203 /* ok - without 32 */
+#define __NR_setregid32 204 /* ok - without 32 */
+#define __NR_getgroups32 205 /* ok - without 32 */
+#define __NR_setgroups32 206 /* ok - without 32 */
+#define __NR_fchown32 207 /* ok - without 32 */
+#define __NR_setresuid32 208 /* ok - without 32 */
+#define __NR_getresuid32 209 /* ok - without 32 */
+#define __NR_setresgid32 210 /* ok - without 32 */
+#define __NR_getresgid32 211 /* ok - without 32 */
+#define __NR_chown32 212 /* ok - without 32 -obsolete -> fchownat */
+#define __NR_setuid32 213 /* ok - without 32 */
+#define __NR_setgid32 214 /* ok - without 32 */
+#define __NR_setfsuid32 215 /* ok - without 32 */
+#define __NR_setfsgid32 216 /* ok - without 32 */
+#define __NR_pivot_root 217 /* ok */
+#define __NR_mincore 218 /* ok */
+#define __NR_madvise 219 /* ok */
+//#define __NR_madvise1 219 /* remove delete when C lib stub is removed */
+#define __NR_getdents64 220 /* ok */
+#define __NR_fcntl64 221 /* ok */
+/* 223 is unused */
+#define __NR_gettid 224 /* ok */
+#define __NR_readahead 225 /* ok */
+#define __NR_setxattr 226 /* ok */
+#define __NR_lsetxattr 227 /* ok */
+#define __NR_fsetxattr 228 /* ok */
+#define __NR_getxattr 229 /* ok */
+#define __NR_lgetxattr 230 /* ok */
+#define __NR_fgetxattr 231 /* ok */
+#define __NR_listxattr 232 /* ok */
+#define __NR_llistxattr 233 /* ok */
+#define __NR_flistxattr 234 /* ok */
+#define __NR_removexattr 235 /* ok */
+#define __NR_lremovexattr 236 /* ok */
+#define __NR_fremovexattr 237 /* ok */
+#define __NR_tkill 238 /* ok */
+#define __NR_sendfile64 239 /* ok */
+#define __NR_futex 240 /* ok */
+#define __NR_sched_setaffinity 241 /* ok */
+#define __NR_sched_getaffinity 242 /* ok */
+#define __NR_set_thread_area 243 /* remove */
+#define __NR_get_thread_area 244 /* remove */
+#define __NR_io_setup 245 /* ok */
+#define __NR_io_destroy 246 /* ok */
+#define __NR_io_getevents 247 /* ok */
+#define __NR_io_submit 248 /* ok */
+#define __NR_io_cancel 249 /* ok */
+#define __NR_fadvise64 250 /* remove -> sys_fadvise64_64 */
+/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */
+#define __NR_exit_group 252 /* ok */
+#define __NR_lookup_dcookie 253 /* ok */
+#define __NR_epoll_create 254 /* ok */
+#define __NR_epoll_ctl 255 /* ok */
+#define __NR_epoll_wait 256 /* obsolete -> sys_epoll_pwait */
+#define __NR_remap_file_pages 257 /* only for mmu */
+#define __NR_set_tid_address 258 /* ok */
+#define __NR_timer_create 259 /* ok */
+#define __NR_timer_settime (__NR_timer_create+1) /* 260 */ /* ok */
+#define __NR_timer_gettime (__NR_timer_create+2) /* 261 */ /* ok */
+#define __NR_timer_getoverrun (__NR_timer_create+3) /* 262 */ /* ok */
+#define __NR_timer_delete (__NR_timer_create+4) /* 263 */ /* ok */
+#define __NR_clock_settime (__NR_timer_create+5) /* 264 */ /* ok */
+#define __NR_clock_gettime (__NR_timer_create+6) /* 265 */ /* ok */
+#define __NR_clock_getres (__NR_timer_create+7) /* 266 */ /* ok */
+#define __NR_clock_nanosleep (__NR_timer_create+8) /* 267 */ /* ok */
+#define __NR_statfs64 268 /* ok */
+#define __NR_fstatfs64 269 /* ok */
+#define __NR_tgkill 270 /* ok */
+#define __NR_utimes 271 /* obsolete -> sys_futimesat */
+#define __NR_fadvise64_64 272 /* ok */
+#define __NR_vserver 273 /* ok */
+#define __NR_mbind 274 /* only for mmu */
+#define __NR_get_mempolicy 275 /* only for mmu */
+#define __NR_set_mempolicy 276 /* only for mmu */
+#define __NR_mq_open 277 /* ok */
+#define __NR_mq_unlink (__NR_mq_open+1) /* 278 */ /* ok */
+#define __NR_mq_timedsend (__NR_mq_open+2) /* 279 */ /* ok */
+#define __NR_mq_timedreceive (__NR_mq_open+3) /* 280 */ /* ok */
+#define __NR_mq_notify (__NR_mq_open+4) /* 281 */ /* ok */
+#define __NR_mq_getsetattr (__NR_mq_open+5) /* 282 */ /* ok */
+#define __NR_kexec_load 283 /* ok */
+#define __NR_waitid 284 /* ok */
+/* #define __NR_sys_setaltroot 285 */
+#define __NR_add_key 286 /* ok */
+#define __NR_request_key 287 /* ok */
+#define __NR_keyctl 288 /* ok */
+#define __NR_ioprio_set 289 /* ok */
+#define __NR_ioprio_get 290 /* ok */
+#define __NR_inotify_init 291 /* ok */
+#define __NR_inotify_add_watch 292 /* ok */
+#define __NR_inotify_rm_watch 293 /* ok */
+#define __NR_migrate_pages 294 /* mmu */
+#define __NR_openat 295 /* ok */
+#define __NR_mkdirat 296 /* ok */
+#define __NR_mknodat 297 /* ok */
+#define __NR_fchownat 298 /* ok */
+#define __NR_futimesat 299 /* obsolete -> sys_utimesat */
+#define __NR_fstatat64 300 /* stat64 */
+#define __NR_unlinkat 301 /* ok */
+#define __NR_renameat 302 /* ok */
+#define __NR_linkat 303 /* ok */
+#define __NR_symlinkat 304 /* ok */
+#define __NR_readlinkat 305 /* ok */
+#define __NR_fchmodat 306 /* ok */
+#define __NR_faccessat 307 /* ok */
+#define __NR_pselect6 308 /* obsolete -> sys_pselect7 */
+#define __NR_ppoll 309 /* ok */
+#define __NR_unshare 310 /* ok */
+#define __NR_set_robust_list 311 /* ok */
+#define __NR_get_robust_list 312 /* ok */
+#define __NR_splice 313 /* ok */
+#define __NR_sync_file_range 314 /* ok */
+#define __NR_tee 315 /* ok */
+#define __NR_vmsplice 316 /* ok */
+#define __NR_move_pages 317 /* mmu */
+#define __NR_getcpu 318 /* ok */
+#define __NR_epoll_pwait 319 /* ok */
+#define __NR_utimensat 320 /* ok */
+#define __NR_signalfd 321 /* ok */
+#define __NR_timerfd_create 322 /* ok */
+#define __NR_eventfd 323 /* ok */
+#define __NR_fallocate 324 /* ok */
+#define __NR_semtimedop 325 /* ok - semaphore group */
+#define __NR_timerfd_settime 326 /* ok */
+#define __NR_timerfd_gettime 327 /* ok */
+/* sysv ipc syscalls */
+#define __NR_semctl 328 /* ok */
+#define __NR_semget 329 /* ok */
+#define __NR_semop 330 /* ok */
+#define __NR_msgctl 331 /* ok */
+#define __NR_msgget 332 /* ok */
+#define __NR_msgrcv 333 /* ok */
+#define __NR_msgsnd 334 /* ok */
+#define __NR_shmat 335 /* ok */
+#define __NR_shmctl 336 /* ok */
+#define __NR_shmdt 337 /* ok */
+#define __NR_shmget 338 /* ok */
+
+
+#define __NR_signalfd4 339 /* new */
+#define __NR_eventfd2 340 /* new */
+#define __NR_epoll_create1 341 /* new */
+#define __NR_dup3 342 /* new */
+#define __NR_pipe2 343 /* new */
+#define __NR_inotify_init1 344 /* new */
+#define __NR_socket 345 /* new */
+#define __NR_socketpair 346 /* new */
+#define __NR_bind 347 /* new */
+#define __NR_listen 348 /* new */
+#define __NR_accept 349 /* new */
+#define __NR_connect 350 /* new */
+#define __NR_getsockname 351 /* new */
+#define __NR_getpeername 352 /* new */
+#define __NR_sendto 353 /* new */
+#define __NR_send 354 /* new */
+#define __NR_recvfrom 355 /* new */
+#define __NR_recv 356 /* new */
+#define __NR_setsockopt 357 /* new */
+#define __NR_getsockopt 358 /* new */
+#define __NR_shutdown 359 /* new */
+#define __NR_sendmsg 360 /* new */
+#define __NR_recvmsg 361 /* new */
+#define __NR_accept04 362 /* new */
+
+#define __NR_syscalls 363
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+#define __ARCH_WANT_IPC_PARSE_VERSION
+/* #define __ARCH_WANT_OLD_READDIR */
+/* #define __ARCH_WANT_OLD_STAT */
+#define __ARCH_WANT_STAT64
+#define __ARCH_WANT_SYS_ALARM
+#define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_SYS_PAUSE
+#define __ARCH_WANT_SYS_SGETMASK
+#define __ARCH_WANT_SYS_SIGNAL
+#define __ARCH_WANT_SYS_TIME
+#define __ARCH_WANT_SYS_UTIME
+#define __ARCH_WANT_SYS_WAITPID
+#define __ARCH_WANT_SYS_SOCKETCALL
+#define __ARCH_WANT_SYS_FADVISE64
+#define __ARCH_WANT_SYS_GETPGRP
+#define __ARCH_WANT_SYS_LLSEEK
+#define __ARCH_WANT_SYS_NICE
+/* #define __ARCH_WANT_SYS_OLD_GETRLIMIT */
+#define __ARCH_WANT_SYS_OLDUMOUNT
+#define __ARCH_WANT_SYS_SIGPENDING
+#define __ARCH_WANT_SYS_SIGPROCMASK
+#define __ARCH_WANT_SYS_RT_SIGACTION
+/* #define __ARCH_WANT_SYS_RT_SIGSUSPEND */
+
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+
+#endif /* __ASSEMBLY__ */
+#endif /* __KERNEL__ */
+#endif /* _ASM_MICROBLAZE_UNISTD_H */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/lib/fastcopy.S | 660 ++++++++++++++++++++++++++++++++++++++++
arch/microblaze/lib/memcpy.c | 160 ++++++++++
arch/microblaze/lib/memmove.c | 174 +++++++++++
arch/microblaze/lib/memset.c | 81 +++++
4 files changed, 1075 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/lib/fastcopy.S
create mode 100644 arch/microblaze/lib/memcpy.c
create mode 100644 arch/microblaze/lib/memmove.c
create mode 100644 arch/microblaze/lib/memset.c
diff --git a/arch/microblaze/lib/fastcopy.S b/arch/microblaze/lib/fastcopy.S
new file mode 100644
index 0000000..df5e4ad
--- /dev/null
+++ b/arch/microblaze/lib/fastcopy.S
@@ -0,0 +1,660 @@
+/*
+ * Copyright 2008 (c) Jim Law - Iris LP All rights reserved.
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Jim Law <[email protected]>
+ *
+ * intended to replace:
+ * memcpy in memcpy.c and
+ * memmove in memmove.c
+ * ... in arch/microblaze/lib
+ *
+ *
+ * assly_fastcopy.S
+ *
+ * Attempt at quicker memcpy and memmove for MicroBlaze
+ * Input : Operand1 in Reg r5 - destination address
+ * Operand2 in Reg r6 - source address
+ * Operand3 in Reg r7 - number of bytes to transfer
+ * Output: Result in Reg r3 - starting destinaition address
+ *
+ *
+ * Explanation:
+ * Perform (possibly unaligned) copy of a block of memory
+ * between mem locations with size of xfer spec'd in bytes
+ */
+
+#include <linux/linkage.h>
+
+ .globl memcpy
+ .ent memcpy
+
+memcpy:
+fast_memcpy_ascending:
+ /* move d to return register as value of function */
+ addi r3, r5, 0
+
+ addi r4, r0, 4 /* n = 4 */
+ cmpu r4, r4, r7 /* n = c - n (unsigned) */
+ blti r4, a_xfer_end /* if n < 0, less than one word to transfer */
+
+ /* transfer first 0~3 bytes to get aligned dest address */
+ andi r4, r5, 3 /* n = d & 3 */
+ /* if zero, destination already aligned */
+ beqi r4, a_dalign_done
+ /* n = 4 - n (yields 3, 2, 1 transfers for 1, 2, 3 addr offset) */
+ rsubi r4, r4, 4
+ rsub r7, r4, r7 /* c = c - n adjust c */
+
+a_xfer_first_loop:
+ /* if no bytes left to transfer, transfer the bulk */
+ beqi r4, a_dalign_done
+ lbui r11, r6, 0 /* h = *s */
+ sbi r11, r5, 0 /* *d = h */
+ addi r6, r6, 1 /* s++ */
+ addi r5, r5, 1 /* d++ */
+ brid a_xfer_first_loop /* loop */
+ addi r4, r4, -1 /* n-- (IN DELAY SLOT) */
+
+a_dalign_done:
+ addi r4, r0, 32 /* n = 32 */
+ cmpu r4, r4, r7 /* n = c - n (unsigned) */
+ /* if n < 0, less than one block to transfer */
+ blti r4, a_block_done
+
+a_block_xfer:
+ andi r4, r7, 0xffffffe0 /* n = c & ~31 */
+ rsub r7, r4, r7 /* c = c - n */
+
+ andi r9, r6, 3 /* t1 = s & 3 */
+ /* if temp != 0, unaligned transfers needed */
+ bnei r9, a_block_unaligned
+
+a_block_aligned:
+ lwi r9, r6, 0 /* t1 = *(s + 0) */
+ lwi r10, r6, 4 /* t2 = *(s + 4) */
+ lwi r11, r6, 8 /* t3 = *(s + 8) */
+ lwi r12, r6, 12 /* t4 = *(s + 12) */
+ swi r9, r5, 0 /* *(d + 0) = t1 */
+ swi r10, r5, 4 /* *(d + 4) = t2 */
+ swi r11, r5, 8 /* *(d + 8) = t3 */
+ swi r12, r5, 12 /* *(d + 12) = t4 */
+ lwi r9, r6, 16 /* t1 = *(s + 16) */
+ lwi r10, r6, 20 /* t2 = *(s + 20) */
+ lwi r11, r6, 24 /* t3 = *(s + 24) */
+ lwi r12, r6, 28 /* t4 = *(s + 28) */
+ swi r9, r5, 16 /* *(d + 16) = t1 */
+ swi r10, r5, 20 /* *(d + 20) = t2 */
+ swi r11, r5, 24 /* *(d + 24) = t3 */
+ swi r12, r5, 28 /* *(d + 28) = t4 */
+ addi r6, r6, 32 /* s = s + 32 */
+ addi r4, r4, -32 /* n = n - 32 */
+ bneid r4, a_block_aligned /* while (n) loop */
+ addi r5, r5, 32 /* d = d + 32 (IN DELAY SLOT) */
+ bri a_block_done
+
+a_block_unaligned:
+ andi r8, r6, 0xfffffffc /* as = s & ~3 */
+ add r6, r6, r4 /* s = s + n */
+ lwi r11, r8, 0 /* h = *(as + 0) */
+
+ addi r9, r9, -1
+ beqi r9, a_block_u1 /* t1 was 1 => 1 byte offset */
+ addi r9, r9, -1
+ beqi r9, a_block_u2 /* t1 was 2 => 2 byte offset */
+
+a_block_u3:
+ bslli r11, r11, 24 /* h = h << 24 */
+a_bu3_loop:
+ lwi r12, r8, 4 /* v = *(as + 4) */
+ bsrli r9, r12, 8 /* t1 = v >> 8 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 0 /* *(d + 0) = t1 */
+ bslli r11, r12, 24 /* h = v << 24 */
+ lwi r12, r8, 8 /* v = *(as + 8) */
+ bsrli r9, r12, 8 /* t1 = v >> 8 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 4 /* *(d + 4) = t1 */
+ bslli r11, r12, 24 /* h = v << 24 */
+ lwi r12, r8, 12 /* v = *(as + 12) */
+ bsrli r9, r12, 8 /* t1 = v >> 8 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 8 /* *(d + 8) = t1 */
+ bslli r11, r12, 24 /* h = v << 24 */
+ lwi r12, r8, 16 /* v = *(as + 16) */
+ bsrli r9, r12, 8 /* t1 = v >> 8 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 12 /* *(d + 12) = t1 */
+ bslli r11, r12, 24 /* h = v << 24 */
+ lwi r12, r8, 20 /* v = *(as + 20) */
+ bsrli r9, r12, 8 /* t1 = v >> 8 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 16 /* *(d + 16) = t1 */
+ bslli r11, r12, 24 /* h = v << 24 */
+ lwi r12, r8, 24 /* v = *(as + 24) */
+ bsrli r9, r12, 8 /* t1 = v >> 8 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 20 /* *(d + 20) = t1 */
+ bslli r11, r12, 24 /* h = v << 24 */
+ lwi r12, r8, 28 /* v = *(as + 28) */
+ bsrli r9, r12, 8 /* t1 = v >> 8 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 24 /* *(d + 24) = t1 */
+ bslli r11, r12, 24 /* h = v << 24 */
+ lwi r12, r8, 32 /* v = *(as + 32) */
+ bsrli r9, r12, 8 /* t1 = v >> 8 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 28 /* *(d + 28) = t1 */
+ bslli r11, r12, 24 /* h = v << 24 */
+ addi r8, r8, 32 /* as = as + 32 */
+ addi r4, r4, -32 /* n = n - 32 */
+ bneid r4, a_bu3_loop /* while (n) loop */
+ addi r5, r5, 32 /* d = d + 32 (IN DELAY SLOT) */
+ bri a_block_done
+
+a_block_u1:
+ bslli r11, r11, 8 /* h = h << 8 */
+a_bu1_loop:
+ lwi r12, r8, 4 /* v = *(as + 4) */
+ bsrli r9, r12, 24 /* t1 = v >> 24 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 0 /* *(d + 0) = t1 */
+ bslli r11, r12, 8 /* h = v << 8 */
+ lwi r12, r8, 8 /* v = *(as + 8) */
+ bsrli r9, r12, 24 /* t1 = v >> 24 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 4 /* *(d + 4) = t1 */
+ bslli r11, r12, 8 /* h = v << 8 */
+ lwi r12, r8, 12 /* v = *(as + 12) */
+ bsrli r9, r12, 24 /* t1 = v >> 24 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 8 /* *(d + 8) = t1 */
+ bslli r11, r12, 8 /* h = v << 8 */
+ lwi r12, r8, 16 /* v = *(as + 16) */
+ bsrli r9, r12, 24 /* t1 = v >> 24 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 12 /* *(d + 12) = t1 */
+ bslli r11, r12, 8 /* h = v << 8 */
+ lwi r12, r8, 20 /* v = *(as + 20) */
+ bsrli r9, r12, 24 /* t1 = v >> 24 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 16 /* *(d + 16) = t1 */
+ bslli r11, r12, 8 /* h = v << 8 */
+ lwi r12, r8, 24 /* v = *(as + 24) */
+ bsrli r9, r12, 24 /* t1 = v >> 24 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 20 /* *(d + 20) = t1 */
+ bslli r11, r12, 8 /* h = v << 8 */
+ lwi r12, r8, 28 /* v = *(as + 28) */
+ bsrli r9, r12, 24 /* t1 = v >> 24 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 24 /* *(d + 24) = t1 */
+ bslli r11, r12, 8 /* h = v << 8 */
+ lwi r12, r8, 32 /* v = *(as + 32) */
+ bsrli r9, r12, 24 /* t1 = v >> 24 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 28 /* *(d + 28) = t1 */
+ bslli r11, r12, 8 /* h = v << 8 */
+ addi r8, r8, 32 /* as = as + 32 */
+ addi r4, r4, -32 /* n = n - 32 */
+ bneid r4, a_bu1_loop /* while (n) loop */
+ addi r5, r5, 32 /* d = d + 32 (IN DELAY SLOT) */
+ bri a_block_done
+
+a_block_u2:
+ bslli r11, r11, 16 /* h = h << 16 */
+a_bu2_loop:
+ lwi r12, r8, 4 /* v = *(as + 4) */
+ bsrli r9, r12, 16 /* t1 = v >> 16 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 0 /* *(d + 0) = t1 */
+ bslli r11, r12, 16 /* h = v << 16 */
+ lwi r12, r8, 8 /* v = *(as + 8) */
+ bsrli r9, r12, 16 /* t1 = v >> 16 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 4 /* *(d + 4) = t1 */
+ bslli r11, r12, 16 /* h = v << 16 */
+ lwi r12, r8, 12 /* v = *(as + 12) */
+ bsrli r9, r12, 16 /* t1 = v >> 16 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 8 /* *(d + 8) = t1 */
+ bslli r11, r12, 16 /* h = v << 16 */
+ lwi r12, r8, 16 /* v = *(as + 16) */
+ bsrli r9, r12, 16 /* t1 = v >> 16 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 12 /* *(d + 12) = t1 */
+ bslli r11, r12, 16 /* h = v << 16 */
+ lwi r12, r8, 20 /* v = *(as + 20) */
+ bsrli r9, r12, 16 /* t1 = v >> 16 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 16 /* *(d + 16) = t1 */
+ bslli r11, r12, 16 /* h = v << 16 */
+ lwi r12, r8, 24 /* v = *(as + 24) */
+ bsrli r9, r12, 16 /* t1 = v >> 16 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 20 /* *(d + 20) = t1 */
+ bslli r11, r12, 16 /* h = v << 16 */
+ lwi r12, r8, 28 /* v = *(as + 28) */
+ bsrli r9, r12, 16 /* t1 = v >> 16 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 24 /* *(d + 24) = t1 */
+ bslli r11, r12, 16 /* h = v << 16 */
+ lwi r12, r8, 32 /* v = *(as + 32) */
+ bsrli r9, r12, 16 /* t1 = v >> 16 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 28 /* *(d + 28) = t1 */
+ bslli r11, r12, 16 /* h = v << 16 */
+ addi r8, r8, 32 /* as = as + 32 */
+ addi r4, r4, -32 /* n = n - 32 */
+ bneid r4, a_bu2_loop /* while (n) loop */
+ addi r5, r5, 32 /* d = d + 32 (IN DELAY SLOT) */
+
+a_block_done:
+ addi r4, r0, 4 /* n = 4 */
+ cmpu r4, r4, r7 /* n = c - n (unsigned) */
+ blti r4, a_xfer_end /* if n < 0, less than one word to transfer */
+
+a_word_xfer:
+ andi r4, r7, 0xfffffffc /* n = c & ~3 */
+ addi r10, r0, 0 /* offset = 0 */
+
+ andi r9, r6, 3 /* t1 = s & 3 */
+ /* if temp != 0, unaligned transfers needed */
+ bnei r9, a_word_unaligned
+
+a_word_aligned:
+ lw r9, r6, r10 /* t1 = *(s+offset) */
+ sw r9, r5, r10 /* *(d+offset) = t1 */
+ addi r4, r4,-4 /* n-- */
+ bneid r4, a_word_aligned /* loop */
+ addi r10, r10, 4 /* offset++ (IN DELAY SLOT) */
+
+ bri a_word_done
+
+a_word_unaligned:
+ andi r8, r6, 0xfffffffc /* as = s & ~3 */
+ lwi r11, r8, 0 /* h = *(as + 0) */
+ addi r8, r8, 4 /* as = as + 4 */
+
+ addi r9, r9, -1
+ beqi r9, a_word_u1 /* t1 was 1 => 1 byte offset */
+ addi r9, r9, -1
+ beqi r9, a_word_u2 /* t1 was 2 => 2 byte offset */
+
+a_word_u3:
+ bslli r11, r11, 24 /* h = h << 24 */
+a_wu3_loop:
+ lw r12, r8, r10 /* v = *(as + offset) */
+ bsrli r9, r12, 8 /* t1 = v >> 8 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ sw r9, r5, r10 /* *(d + offset) = t1 */
+ bslli r11, r12, 24 /* h = v << 24 */
+ addi r4, r4,-4 /* n = n - 4 */
+ bneid r4, a_wu3_loop /* while (n) loop */
+ addi r10, r10, 4 /* offset = ofset + 4 (IN DELAY SLOT) */
+
+ bri a_word_done
+
+a_word_u1:
+ bslli r11, r11, 8 /* h = h << 8 */
+a_wu1_loop:
+ lw r12, r8, r10 /* v = *(as + offset) */
+ bsrli r9, r12, 24 /* t1 = v >> 24 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ sw r9, r5, r10 /* *(d + offset) = t1 */
+ bslli r11, r12, 8 /* h = v << 8 */
+ addi r4, r4,-4 /* n = n - 4 */
+ bneid r4, a_wu1_loop /* while (n) loop */
+ addi r10, r10, 4 /* offset = ofset + 4 (IN DELAY SLOT) */
+
+ bri a_word_done
+
+a_word_u2:
+ bslli r11, r11, 16 /* h = h << 16 */
+a_wu2_loop:
+ lw r12, r8, r10 /* v = *(as + offset) */
+ bsrli r9, r12, 16 /* t1 = v >> 16 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ sw r9, r5, r10 /* *(d + offset) = t1 */
+ bslli r11, r12, 16 /* h = v << 16 */
+ addi r4, r4,-4 /* n = n - 4 */
+ bneid r4, a_wu2_loop /* while (n) loop */
+ addi r10, r10, 4 /* offset = ofset + 4 (IN DELAY SLOT) */
+
+a_word_done:
+ add r5, r5, r10 /* d = d + offset */
+ add r6, r6, r10 /* s = s + offset */
+ rsub r7, r10, r7 /* c = c - offset */
+
+a_xfer_end:
+a_xfer_end_loop:
+ beqi r7, a_done /* while (c) */
+ lbui r9, r6, 0 /* t1 = *s */
+ addi r6, r6, 1 /* s++ */
+ sbi r9, r5, 0 /* *d = t1 */
+ addi r7, r7, -1 /* c-- */
+ brid a_xfer_end_loop /* loop */
+ addi r5, r5, 1 /* d++ (IN DELAY SLOT) */
+
+a_done:
+ rtsd r15, 8
+ nop
+
+.end memcpy
+/*----------------------------------------------------------------------------*/
+ .globl memmove
+ .ent memmove
+
+memmove:
+ cmpu r4, r5, r6 /* n = s - d */
+ bgei r4,fast_memcpy_ascending
+
+fast_memcpy_descending:
+ /* move d to return register as value of function */
+ addi r3, r5, 0
+
+ add r5, r5, r7 /* d = d + c */
+ add r6, r6, r7 /* s = s + c */
+
+ addi r4, r0, 4 /* n = 4 */
+ cmpu r4, r4, r7 /* n = c - n (unsigned) */
+ blti r4,d_xfer_end /* if n < 0, less than one word to transfer */
+
+ /* transfer first 0~3 bytes to get aligned dest address */
+ andi r4, r5, 3 /* n = d & 3 */
+ /* if zero, destination already aligned */
+ beqi r4,d_dalign_done
+ rsub r7, r4, r7 /* c = c - n adjust c */
+
+d_xfer_first_loop:
+ /* if no bytes left to transfer, transfer the bulk */
+ beqi r4,d_dalign_done
+ addi r6, r6, -1 /* s-- */
+ addi r5, r5, -1 /* d-- */
+ lbui r11, r6, 0 /* h = *s */
+ sbi r11, r5, 0 /* *d = h */
+ brid d_xfer_first_loop /* loop */
+ addi r4, r4, -1 /* n-- (IN DELAY SLOT) */
+
+d_dalign_done:
+ addi r4, r0, 32 /* n = 32 */
+ cmpu r4, r4, r7 /* n = c - n (unsigned) */
+ /* if n < 0, less than one block to transfer */
+ blti r4, d_block_done
+
+d_block_xfer:
+ andi r4, r7, 0xffffffe0 /* n = c & ~31 */
+ rsub r7, r4, r7 /* c = c - n */
+
+ andi r9, r6, 3 /* t1 = s & 3 */
+ /* if temp != 0, unaligned transfers needed */
+ bnei r9, d_block_unaligned
+
+d_block_aligned:
+ addi r6, r6, -32 /* s = s - 32 */
+ addi r5, r5, -32 /* d = d - 32 */
+ lwi r9, r6, 28 /* t1 = *(s + 28) */
+ lwi r10, r6, 24 /* t2 = *(s + 24) */
+ lwi r11, r6, 20 /* t3 = *(s + 20) */
+ lwi r12, r6, 16 /* t4 = *(s + 16) */
+ swi r9, r5, 28 /* *(d + 28) = t1 */
+ swi r10, r5, 24 /* *(d + 24) = t2 */
+ swi r11, r5, 20 /* *(d + 20) = t3 */
+ swi r12, r5, 16 /* *(d + 16) = t4 */
+ lwi r9, r6, 12 /* t1 = *(s + 12) */
+ lwi r10, r6, 8 /* t2 = *(s + 8) */
+ lwi r11, r6, 4 /* t3 = *(s + 4) */
+ lwi r12, r6, 0 /* t4 = *(s + 0) */
+ swi r9, r5, 12 /* *(d + 12) = t1 */
+ swi r10, r5, 8 /* *(d + 8) = t2 */
+ swi r11, r5, 4 /* *(d + 4) = t3 */
+ addi r4, r4, -32 /* n = n - 32 */
+ bneid r4, d_block_aligned /* while (n) loop */
+ swi r12, r5, 0 /* *(d + 0) = t4 (IN DELAY SLOT) */
+ bri d_block_done
+
+d_block_unaligned:
+ andi r8, r6, 0xfffffffc /* as = s & ~3 */
+ rsub r6, r4, r6 /* s = s - n */
+ lwi r11, r8, 0 /* h = *(as + 0) */
+
+ addi r9, r9, -1
+ beqi r9,d_block_u1 /* t1 was 1 => 1 byte offset */
+ addi r9, r9, -1
+ beqi r9,d_block_u2 /* t1 was 2 => 2 byte offset */
+
+d_block_u3:
+ bsrli r11, r11, 8 /* h = h >> 8 */
+d_bu3_loop:
+ addi r8, r8, -32 /* as = as - 32 */
+ addi r5, r5, -32 /* d = d - 32 */
+ lwi r12, r8, 28 /* v = *(as + 28) */
+ bslli r9, r12, 24 /* t1 = v << 24 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 28 /* *(d + 28) = t1 */
+ bsrli r11, r12, 8 /* h = v >> 8 */
+ lwi r12, r8, 24 /* v = *(as + 24) */
+ bslli r9, r12, 24 /* t1 = v << 24 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 24 /* *(d + 24) = t1 */
+ bsrli r11, r12, 8 /* h = v >> 8 */
+ lwi r12, r8, 20 /* v = *(as + 20) */
+ bslli r9, r12, 24 /* t1 = v << 24 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 20 /* *(d + 20) = t1 */
+ bsrli r11, r12, 8 /* h = v >> 8 */
+ lwi r12, r8, 16 /* v = *(as + 16) */
+ bslli r9, r12, 24 /* t1 = v << 24 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 16 /* *(d + 16) = t1 */
+ bsrli r11, r12, 8 /* h = v >> 8 */
+ lwi r12, r8, 12 /* v = *(as + 12) */
+ bslli r9, r12, 24 /* t1 = v << 24 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 12 /* *(d + 112) = t1 */
+ bsrli r11, r12, 8 /* h = v >> 8 */
+ lwi r12, r8, 8 /* v = *(as + 8) */
+ bslli r9, r12, 24 /* t1 = v << 24 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 8 /* *(d + 8) = t1 */
+ bsrli r11, r12, 8 /* h = v >> 8 */
+ lwi r12, r8, 4 /* v = *(as + 4) */
+ bslli r9, r12, 24 /* t1 = v << 24 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 4 /* *(d + 4) = t1 */
+ bsrli r11, r12, 8 /* h = v >> 8 */
+ lwi r12, r8, 0 /* v = *(as + 0) */
+ bslli r9, r12, 24 /* t1 = v << 24 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 0 /* *(d + 0) = t1 */
+ addi r4, r4, -32 /* n = n - 32 */
+ bneid r4, d_bu3_loop /* while (n) loop */
+ bsrli r11, r12, 8 /* h = v >> 8 (IN DELAY SLOT) */
+ bri d_block_done
+
+d_block_u1:
+ bsrli r11, r11, 24 /* h = h >> 24 */
+d_bu1_loop:
+ addi r8, r8, -32 /* as = as - 32 */
+ addi r5, r5, -32 /* d = d - 32 */
+ lwi r12, r8, 28 /* v = *(as + 28) */
+ bslli r9, r12, 8 /* t1 = v << 8 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 28 /* *(d + 28) = t1 */
+ bsrli r11, r12, 24 /* h = v >> 24 */
+ lwi r12, r8, 24 /* v = *(as + 24) */
+ bslli r9, r12, 8 /* t1 = v << 8 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 24 /* *(d + 24) = t1 */
+ bsrli r11, r12, 24 /* h = v >> 24 */
+ lwi r12, r8, 20 /* v = *(as + 20) */
+ bslli r9, r12, 8 /* t1 = v << 8 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 20 /* *(d + 20) = t1 */
+ bsrli r11, r12, 24 /* h = v >> 24 */
+ lwi r12, r8, 16 /* v = *(as + 16) */
+ bslli r9, r12, 8 /* t1 = v << 8 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 16 /* *(d + 16) = t1 */
+ bsrli r11, r12, 24 /* h = v >> 24 */
+ lwi r12, r8, 12 /* v = *(as + 12) */
+ bslli r9, r12, 8 /* t1 = v << 8 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 12 /* *(d + 112) = t1 */
+ bsrli r11, r12, 24 /* h = v >> 24 */
+ lwi r12, r8, 8 /* v = *(as + 8) */
+ bslli r9, r12, 8 /* t1 = v << 8 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 8 /* *(d + 8) = t1 */
+ bsrli r11, r12, 24 /* h = v >> 24 */
+ lwi r12, r8, 4 /* v = *(as + 4) */
+ bslli r9, r12, 8 /* t1 = v << 8 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 4 /* *(d + 4) = t1 */
+ bsrli r11, r12, 24 /* h = v >> 24 */
+ lwi r12, r8, 0 /* v = *(as + 0) */
+ bslli r9, r12, 8 /* t1 = v << 8 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 0 /* *(d + 0) = t1 */
+ addi r4, r4, -32 /* n = n - 32 */
+ bneid r4, d_bu1_loop /* while (n) loop */
+ bsrli r11, r12, 24 /* h = v >> 24 (IN DELAY SLOT) */
+ bri d_block_done
+
+d_block_u2:
+ bsrli r11, r11, 16 /* h = h >> 16 */
+d_bu2_loop:
+ addi r8, r8, -32 /* as = as - 32 */
+ addi r5, r5, -32 /* d = d - 32 */
+ lwi r12, r8, 28 /* v = *(as + 28) */
+ bslli r9, r12, 16 /* t1 = v << 16 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 28 /* *(d + 28) = t1 */
+ bsrli r11, r12, 16 /* h = v >> 16 */
+ lwi r12, r8, 24 /* v = *(as + 24) */
+ bslli r9, r12, 16 /* t1 = v << 16 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 24 /* *(d + 24) = t1 */
+ bsrli r11, r12, 16 /* h = v >> 16 */
+ lwi r12, r8, 20 /* v = *(as + 20) */
+ bslli r9, r12, 16 /* t1 = v << 16 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 20 /* *(d + 20) = t1 */
+ bsrli r11, r12, 16 /* h = v >> 16 */
+ lwi r12, r8, 16 /* v = *(as + 16) */
+ bslli r9, r12, 16 /* t1 = v << 16 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 16 /* *(d + 16) = t1 */
+ bsrli r11, r12, 16 /* h = v >> 16 */
+ lwi r12, r8, 12 /* v = *(as + 12) */
+ bslli r9, r12, 16 /* t1 = v << 16 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 12 /* *(d + 112) = t1 */
+ bsrli r11, r12, 16 /* h = v >> 16 */
+ lwi r12, r8, 8 /* v = *(as + 8) */
+ bslli r9, r12, 16 /* t1 = v << 16 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 8 /* *(d + 8) = t1 */
+ bsrli r11, r12, 16 /* h = v >> 16 */
+ lwi r12, r8, 4 /* v = *(as + 4) */
+ bslli r9, r12, 16 /* t1 = v << 16 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 4 /* *(d + 4) = t1 */
+ bsrli r11, r12, 16 /* h = v >> 16 */
+ lwi r12, r8, 0 /* v = *(as + 0) */
+ bslli r9, r12, 16 /* t1 = v << 16 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ swi r9, r5, 0 /* *(d + 0) = t1 */
+ addi r4, r4, -32 /* n = n - 32 */
+ bneid r4, d_bu2_loop /* while (n) loop */
+ bsrli r11, r12, 16 /* h = v >> 16 (IN DELAY SLOT) */
+
+d_block_done:
+ addi r4, r0, 4 /* n = 4 */
+ cmpu r4, r4, r7 /* n = c - n (unsigned) */
+ blti r4,d_xfer_end /* if n < 0, less than one word to transfer */
+
+d_word_xfer:
+ andi r4, r7, 0xfffffffc /* n = c & ~3 */
+ rsub r5, r4, r5 /* d = d - n */
+ rsub r6, r4, r6 /* s = s - n */
+ rsub r7, r4, r7 /* c = c - n */
+
+ andi r9, r6, 3 /* t1 = s & 3 */
+ /* if temp != 0, unaligned transfers needed */
+ bnei r9, d_word_unaligned
+
+d_word_aligned:
+ addi r4, r4,-4 /* n-- */
+ lw r9, r6, r4 /* t1 = *(s+n) */
+ bneid r4, d_word_aligned /* loop */
+ sw r9, r5, r4 /* *(d+n) = t1 (IN DELAY SLOT) */
+
+ bri d_word_done
+
+d_word_unaligned:
+ andi r8, r6, 0xfffffffc /* as = s & ~3 */
+ lw r11, r8, r4 /* h = *(as + n) */
+
+ addi r9, r9, -1
+ beqi r9,d_word_u1 /* t1 was 1 => 1 byte offset */
+ addi r9, r9, -1
+ beqi r9,d_word_u2 /* t1 was 2 => 2 byte offset */
+
+d_word_u3:
+ bsrli r11, r11, 8 /* h = h >> 8 */
+d_wu3_loop:
+ addi r4, r4,-4 /* n = n - 4 */
+ lw r12, r8, r4 /* v = *(as + n) */
+ bslli r9, r12, 24 /* t1 = v << 24 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ sw r9, r5, r4 /* *(d + n) = t1 */
+ bneid r4, d_wu3_loop /* while (n) loop */
+ bsrli r11, r12, 8 /* h = v >> 8 (IN DELAY SLOT) */
+
+ bri d_word_done
+
+d_word_u1:
+ bsrli r11, r11, 24 /* h = h >> 24 */
+d_wu1_loop:
+ addi r4, r4,-4 /* n = n - 4 */
+ lw r12, r8, r4 /* v = *(as + n) */
+ bslli r9, r12, 8 /* t1 = v << 8 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ sw r9, r5, r4 /* *(d + n) = t1 */
+ bneid r4, d_wu1_loop /* while (n) loop */
+ bsrli r11, r12, 24 /* h = v >> 24 (IN DELAY SLOT) */
+
+ bri d_word_done
+
+d_word_u2:
+ bsrli r11, r11, 16 /* h = h >> 16 */
+d_wu2_loop:
+ addi r4, r4,-4 /* n = n - 4 */
+ lw r12, r8, r4 /* v = *(as + n) */
+ bslli r9, r12, 16 /* t1 = v << 16 */
+ or r9, r11, r9 /* t1 = h | t1 */
+ sw r9, r5, r4 /* *(d + n) = t1 */
+ bneid r4, d_wu2_loop /* while (n) loop */
+ bsrli r11, r12, 16 /* h = v >> 16 (IN DELAY SLOT) */
+
+d_word_done:
+
+d_xfer_end:
+d_xfer_end_loop:
+ beqi r7, a_done /* while (c) */
+ addi r6, r6, -1 /* s-- */
+ lbui r9, r6, 0 /* t1 = *s */
+ addi r5, r5, -1 /* d-- */
+ sbi r9, r5, 0 /* *d = t1 */
+ brid d_xfer_end_loop /* loop */
+ addi r7, r7, -1 /* c-- (IN DELAY SLOT) */
+
+d_done:
+ rtsd r15, 8
+ nop
+
+.end memmove
diff --git a/arch/microblaze/lib/memcpy.c b/arch/microblaze/lib/memcpy.c
new file mode 100644
index 0000000..8cb3dec
--- /dev/null
+++ b/arch/microblaze/lib/memcpy.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2008 Michal Simek <[email protected]>
+ * Copyright (C) 2007 John Williams
+ *
+ * Reasonably optimised generic C-code for memcpy on Microblaze
+ * This is generic C code to do efficient, alignment-aware memcpy.
+ *
+ * It is based on demo code originally Copyright 2001 by Intel Corp, taken from
+ * http://www.embedded.com/showArticle.jhtml?articleID=19205567
+ *
+ * Attempts were made, unsuccesfully, to contact the original
+ * author of this code (Michael Morrow, Intel). Below is the original
+ * copyright notice.
+ *
+ * This software has been developed by Intel Corporation.
+ * Intel specifically disclaims all warranties, express or
+ * implied, and all liability, including consequential and
+ * other indirect damages, for the use of this program, including
+ * liability for infringement of any proprietary rights,
+ * and including the warranties of merchantability and fitness
+ * for a particular purpose. Intel does not assume any
+ * responsibility for and errors which may appear in this program
+ * not any responsibility to update it.
+ */
+
+#include <linux/types.h>
+#include <linux/stddef.h>
+#include <linux/compiler.h>
+#include <linux/module.h>
+
+#include <linux/string.h>
+#include <asm/system.h>
+
+#ifdef __HAVE_ARCH_MEMCPY
+void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
+{
+ const char *src = v_src;
+ char *dst = v_dst;
+#ifndef CONFIG_OPT_LIB_FUNCTION
+ /* Simple, byte oriented memcpy. */
+ while (c--)
+ *dst++ = *src++;
+
+ return v_dst;
+#else
+ /* The following code tries to optimize the copy by using unsigned
+ * alignment. This will work fine if both source and destination are
+ * aligned on the same boundary. However, if they are aligned on
+ * different boundaries shifts will be necessary. This might result in
+ * bad performance on MicroBlaze systems without a barrel shifter.
+ */
+ const uint32_t *i_src;
+ uint32_t *i_dst;
+
+ if (c >= 4) {
+ unsigned value, buf_hold;
+
+ /* Align the dstination to a word boundry. */
+ /* This is done in an endian independant manner. */
+ switch ((unsigned long)dst & 3) {
+ case 1:
+ *dst++ = *src++;
+ --c;
+ case 2:
+ *dst++ = *src++;
+ --c;
+ case 3:
+ *dst++ = *src++;
+ --c;
+ }
+
+ i_dst = (void *)dst;
+
+ /* Choose a copy scheme based on the source */
+ /* alignment relative to dstination. */
+ switch ((unsigned long)src & 3) {
+ case 0x0: /* Both byte offsets are aligned */
+ i_src = (const void *)src;
+
+ for (; c >= 4; c -= 4)
+ *i_dst++ = *i_src++;
+
+ src = (const void *)i_src;
+ break;
+ case 0x1: /* Unaligned - Off by 1 */
+ /* Word align the source */
+ i_src = (const void *) ((unsigned)src & ~3);
+
+ /* Load the holding buffer */
+ buf_hold = *i_src++ << 8;
+
+ for (; c >= 4; c -= 4) {
+ value = *i_src++;
+ *i_dst++ = buf_hold | value >> 24;
+ buf_hold = value << 8;
+ }
+
+ /* Realign the source */
+ src = (const void *)i_src;
+ src -= 3;
+ break;
+ case 0x2: /* Unaligned - Off by 2 */
+ /* Word align the source */
+ i_src = (const void *) ((unsigned)src & ~3);
+
+ /* Load the holding buffer */
+ buf_hold = *i_src++ << 16;
+
+ for (; c >= 4; c -= 4) {
+ value = *i_src++;
+ *i_dst++ = buf_hold | value >> 16;
+ buf_hold = value << 16;
+ }
+
+ /* Realign the source */
+ src = (const void *)i_src;
+ src -= 2;
+ break;
+ case 0x3: /* Unaligned - Off by 3 */
+ /* Word align the source */
+ i_src = (const void *) ((unsigned)src & ~3);
+
+ /* Load the holding buffer */
+ buf_hold = *i_src++ << 24;
+
+ for (; c >= 4; c -= 4) {
+ value = *i_src++;
+ *i_dst++ = buf_hold | value >> 8;
+ buf_hold = value << 24;
+ }
+
+ /* Realign the source */
+ src = (const void *)i_src;
+ src -= 1;
+ break;
+ }
+ dst = (void *)i_dst;
+ }
+
+ /* Finish off any remaining bytes */
+ /* simple fast copy, ... unless a cache boundry is crossed */
+ switch (c) {
+ case 3:
+ *dst++ = *src++;
+ case 2:
+ *dst++ = *src++;
+ case 1:
+ *dst++ = *src++;
+ }
+
+ return v_dst;
+#endif
+}
+EXPORT_SYMBOL(memcpy);
+#endif /* __HAVE_ARCH_MEMCPY */
+
+void *cacheable_memcpy(void *d, const void *s, __kernel_size_t c)
+{
+ return memcpy(d, s, c);
+}
diff --git a/arch/microblaze/lib/memmove.c b/arch/microblaze/lib/memmove.c
new file mode 100644
index 0000000..87d17b2
--- /dev/null
+++ b/arch/microblaze/lib/memmove.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2008 Michal Simek <[email protected]>
+ * Copyright (C) 2007 John Williams
+ *
+ * Reasonably optimised generic C-code for memcpy on Microblaze
+ * This is generic C code to do efficient, alignment-aware memmove.
+ *
+ * It is based on demo code originally Copyright 2001 by Intel Corp, taken from
+ * http://www.embedded.com/showArticle.jhtml?articleID=19205567
+ *
+ * Attempts were made, unsuccesfully, to contact the original
+ * author of this code (Michael Morrow, Intel). Below is the original
+ * copyright notice.
+ *
+ * This software has been developed by Intel Corporation.
+ * Intel specifically disclaims all warranties, express or
+ * implied, and all liability, including consequential and
+ * other indirect damages, for the use of this program, including
+ * liability for infringement of any proprietary rights,
+ * and including the warranties of merchantability and fitness
+ * for a particular purpose. Intel does not assume any
+ * responsibility for and errors which may appear in this program
+ * not any responsibility to update it.
+ */
+
+#include <linux/types.h>
+#include <linux/stddef.h>
+#include <linux/compiler.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#ifdef __HAVE_ARCH_MEMMOVE
+void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
+{
+ const char *src = v_src;
+ char *dst = v_dst;
+
+#ifdef CONFIG_OPT_LIB_FUNCTION
+ const uint32_t *i_src;
+ uint32_t *i_dst;
+#endif
+
+ if (!c)
+ return v_dst;
+
+ /* Use memcpy when source is higher than dest */
+ if (v_dst <= v_src)
+ return memcpy(v_dst, v_src, c);
+
+#ifndef CONFIG_OPT_LIB_FUNCTION
+ /* copy backwards, from end to beginning */
+ src += c;
+ dst += c;
+
+ /* Simple, byte oriented memmove. */
+ while (c--)
+ *--dst = *--src;
+
+ return v_dst;
+#else
+ /* The following code tries to optimize the copy by using unsigned
+ * alignment. This will work fine if both source and destination are
+ * aligned on the same boundary. However, if they are aligned on
+ * different boundaries shifts will be necessary. This might result in
+ * bad performance on MicroBlaze systems without a barrel shifter.
+ */
+ /* FIXME this part needs more test */
+ /* Do a descending copy - this is a bit trickier! */
+ dst += c;
+ src += c;
+
+ if (c >= 4) {
+ unsigned value, buf_hold;
+
+ /* Align the destination to a word boundry. */
+ /* This is done in an endian independant manner. */
+
+ switch ((unsigned long)dst & 3) {
+ case 3:
+ *--dst = *--src;
+ --c;
+ case 2:
+ *--dst = *--src;
+ --c;
+ case 1:
+ *--dst = *--src;
+ --c;
+ }
+
+ i_dst = (void *)dst;
+ /* Choose a copy scheme based on the source */
+ /* alignment relative to dstination. */
+ switch ((unsigned long)src & 3) {
+ case 0x0: /* Both byte offsets are aligned */
+
+ i_src = (const void *)src;
+
+ for (; c >= 4; c -= 4)
+ *--i_dst = *--i_src;
+
+ src = (const void *)i_src;
+ break;
+ case 0x1: /* Unaligned - Off by 1 */
+ /* Word align the source */
+ i_src = (const void *) (((unsigned)src + 4) & ~3);
+
+ /* Load the holding buffer */
+ buf_hold = *--i_src >> 24;
+
+ for (; c >= 4; c -= 4) {
+ value = *--i_src;
+ *--i_dst = buf_hold << 8 | value;
+ buf_hold = value >> 24;
+ }
+
+ /* Realign the source */
+ src = (const void *)i_src;
+ src += 1;
+ break;
+ case 0x2: /* Unaligned - Off by 2 */
+ /* Word align the source */
+ i_src = (const void *) (((unsigned)src + 4) & ~3);
+
+ /* Load the holding buffer */
+ buf_hold = *--i_src >> 16;
+
+ for (; c >= 4; c -= 4) {
+ value = *--i_src;
+ *--i_dst = buf_hold << 16 | value;
+ buf_hold = value >> 16;
+ }
+
+ /* Realign the source */
+ src = (const void *)i_src;
+ src += 2;
+ break;
+ case 0x3: /* Unaligned - Off by 3 */
+ /* Word align the source */
+ i_src = (const void *) (((unsigned)src + 4) & ~3);
+
+ /* Load the holding buffer */
+ buf_hold = *--i_src >> 8;
+
+ for (; c >= 4; c -= 4) {
+ value = *--i_src;
+ *--i_dst = buf_hold << 24 | value;
+ buf_hold = value >> 8;
+ }
+
+ /* Realign the source */
+ src = (const void *)i_src;
+ src += 3;
+ break;
+ }
+ dst = (void *)i_dst;
+ }
+
+ /* simple fast copy, ... unless a cache boundry is crossed */
+ /* Finish off any remaining bytes */
+ switch (c) {
+ case 4:
+ *--dst = *--src;
+ case 3:
+ *--dst = *--src;
+ case 2:
+ *--dst = *--src;
+ case 1:
+ *--dst = *--src;
+ }
+ return v_dst;
+#endif
+}
+EXPORT_SYMBOL(memmove);
+#endif /* __HAVE_ARCH_MEMMOVE */
diff --git a/arch/microblaze/lib/memset.c b/arch/microblaze/lib/memset.c
new file mode 100644
index 0000000..8cd4f38
--- /dev/null
+++ b/arch/microblaze/lib/memset.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2008 Michal Simek <[email protected]>
+ * Copyright (C) 2007 John Williams
+ *
+ * Reasonably optimised generic C-code for memset on Microblaze
+ * This is generic C code to do efficient, alignment-aware memcpy.
+ *
+ * It is based on demo code originally Copyright 2001 by Intel Corp, taken from
+ * http://www.embedded.com/showArticle.jhtml?articleID=19205567
+ *
+ * Attempts were made, unsuccesfully, to contact the original
+ * author of this code (Michael Morrow, Intel). Below is the original
+ * copyright notice.
+ *
+ * This software has been developed by Intel Corporation.
+ * Intel specifically disclaims all warranties, express or
+ * implied, and all liability, including consequential and
+ * other indirect damages, for the use of this program, including
+ * liability for infringement of any proprietary rights,
+ * and including the warranties of merchantability and fitness
+ * for a particular purpose. Intel does not assume any
+ * responsibility for and errors which may appear in this program
+ * not any responsibility to update it.
+ */
+
+#include <linux/types.h>
+#include <linux/stddef.h>
+#include <linux/compiler.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#ifdef __HAVE_ARCH_MEMSET
+void *memset(void *v_src, int c, __kernel_size_t n)
+{
+
+ char *src = v_src;
+#ifdef CONFIG_OPT_LIB_FUNCTION
+ uint32_t *i_src;
+ uint32_t w32;
+#endif
+ /* Truncate c to 8 bits */
+ c = (c & 0xFF);
+
+#ifdef CONFIG_OPT_LIB_FUNCTION
+ /* Make a repeating word out of it */
+ w32 = c;
+ w32 |= w32 << 8;
+ w32 |= w32 << 16;
+
+ if (n >= 4) {
+ /* Align the destination to a word boundary */
+ /* This is done in an endian independant manner */
+ switch ((unsigned) src & 3) {
+ case 1:
+ *src++ = c;
+ --n;
+ case 2:
+ *src++ = c;
+ --n;
+ case 3:
+ *src++ = c;
+ --n;
+ }
+
+ i_src = (void *)src;
+
+ /* Do as many full-word copies as we can */
+ for (; n >= 4; n -= 4)
+ *i_src++ = w32;
+
+ src = (void *)i_src;
+ }
+#endif
+ /* Simple, byte oriented memset or the rest of count. */
+ while (n--)
+ *src++ = c;
+
+ return v_src;
+}
+EXPORT_SYMBOL(memset);
+#endif /* __HAVE_ARCH_MEMSET */
--
1.5.5.1
From: Michal Simek <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/microblaze/include/asm/mmu.h | 19 +++
arch/microblaze/include/asm/mmu_context.h | 21 +++
arch/microblaze/include/asm/tlb.h | 16 +++
arch/microblaze/include/asm/tlbflush.h | 20 +++
arch/microblaze/mm/init.c | 197 +++++++++++++++++++++++++++++
5 files changed, 273 insertions(+), 0 deletions(-)
create mode 100644 arch/microblaze/include/asm/mmu.h
create mode 100644 arch/microblaze/include/asm/mmu_context.h
create mode 100644 arch/microblaze/include/asm/tlb.h
create mode 100644 arch/microblaze/include/asm/tlbflush.h
create mode 100644 arch/microblaze/mm/init.c
diff --git a/arch/microblaze/include/asm/mmu.h b/arch/microblaze/include/asm/mmu.h
new file mode 100644
index 0000000..0e0431d
--- /dev/null
+++ b/arch/microblaze/include/asm/mmu.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_MMU_H
+#define _ASM_MICROBLAZE_MMU_H
+
+#ifndef __ASSEMBLY__
+typedef struct {
+ struct vm_list_struct *vmlist;
+ unsigned long end_brk;
+} mm_context_t;
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_MICROBLAZE_MMU_H */
diff --git a/arch/microblaze/include/asm/mmu_context.h b/arch/microblaze/include/asm/mmu_context.h
new file mode 100644
index 0000000..150ca01
--- /dev/null
+++ b/arch/microblaze/include/asm/mmu_context.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_MMU_CONTEXT_H
+#define _ASM_MICROBLAZE_MMU_CONTEXT_H
+
+# define init_new_context(tsk, mm) ({ 0; })
+
+# define enter_lazy_tlb(mm, tsk) do {} while (0)
+# define change_mm_context(old, ctx, _pml4) do {} while (0)
+# define destroy_context(mm) do {} while (0)
+# define deactivate_mm(tsk, mm) do {} while (0)
+# define switch_mm(prev, next, tsk) do {} while (0)
+# define activate_mm(prev, next) do {} while (0)
+
+#endif /* _ASM_MICROBLAZE_MMU_CONTEXT_H */
diff --git a/arch/microblaze/include/asm/tlb.h b/arch/microblaze/include/asm/tlb.h
new file mode 100644
index 0000000..d1dfe37
--- /dev/null
+++ b/arch/microblaze/include/asm/tlb.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_TLB_H
+#define _ASM_MICROBLAZE_TLB_H
+
+#define tlb_flush(tlb) do {} while (0)
+
+#include <asm-generic/tlb.h>
+
+#endif /* _ASM_MICROBLAZE_TLB_H */
diff --git a/arch/microblaze/include/asm/tlbflush.h b/arch/microblaze/include/asm/tlbflush.h
new file mode 100644
index 0000000..d7fe762
--- /dev/null
+++ b/arch/microblaze/include/asm/tlbflush.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _ASM_MICROBLAZE_TLBFLUSH_H
+#define _ASM_MICROBLAZE_TLBFLUSH_H
+
+#define flush_tlb() BUG()
+#define flush_tlb_all() BUG()
+#define flush_tlb_mm(mm) BUG()
+#define flush_tlb_page(vma, addr) BUG()
+#define flush_tlb_range(mm, start, end) BUG()
+#define flush_tlb_pgtables(mm, start, end) BUG()
+#define flush_tlb_kernel_range(start, end) BUG()
+
+#endif /* _ASM_MICROBLAZE_TLBFLUSH_H */
diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c
new file mode 100644
index 0000000..430d85e
--- /dev/null
+++ b/arch/microblaze/mm/init.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2007-2008 Michal Simek <[email protected]>
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/bootmem.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/lmb.h>
+#include <linux/mm.h> /* mem_init */
+#include <linux/initrd.h>
+#include <linux/pagemap.h>
+#include <linux/pfn.h>
+#include <linux/swap.h>
+
+#include <asm/page.h>
+#include <asm/mmu_context.h>
+#include <asm/pgalloc.h>
+#include <asm/sections.h>
+#include <asm/tlb.h>
+
+unsigned int __page_offset;
+/* EXPORT_SYMBOL(__page_offset); */
+
+char *klimit = _end;
+
+/*
+ * Initialize the bootmem system and give it all the memory we
+ * have available.
+ */
+unsigned int memory_start;
+unsigned int memory_end; /* due to mm/nommu.c */
+unsigned int memory_size;
+
+/*
+ * paging_init() sets up the page tables - in fact we've already done this.
+ */
+static void __init paging_init(void)
+{
+ int i;
+ unsigned long zones_size[MAX_NR_ZONES];
+
+ /*
+ * old: we can DMA to/from any address.put all page into ZONE_DMA
+ * We use only ZONE_NORMAL
+ */
+ zones_size[ZONE_NORMAL] = max_mapnr;
+
+ /* every other zones are empty */
+ for (i = 1; i < MAX_NR_ZONES; i++)
+ zones_size[i] = 0;
+
+ free_area_init(zones_size);
+}
+
+void __init setup_memory(void)
+{
+ int i;
+ unsigned long map_size;
+ u32 kernel_align_start, kernel_align_size;
+
+ /* Find main memory where is the kernel */
+ for (i = 0; i < lmb.memory.cnt; i++) {
+ memory_start = (u32) lmb.memory.region[i].base;
+ memory_end = (u32) lmb.memory.region[i].base + (u32) lmb.memory.region[i].size;
+ if ((memory_start <= (u32)_text) && ((u32)_text <= memory_end)) {
+ memory_size = memory_end - memory_start;
+ PAGE_OFFSET = memory_start;
+ printk("%s: Main mem: 0x%x-0x%x, size 0x%08x\n", __func__,
+ memory_start, memory_end, memory_size);
+ break;
+ }
+ }
+
+ if (!memory_start || !memory_end) {
+ panic("%s: Missing memory setting 0x%08x-0x%08x\n",
+ __func__, memory_start, memory_end);
+ }
+
+ /* reservation of region where is the kernel */
+ kernel_align_start = PAGE_DOWN((u32)_text);
+ /* ALIGN can be remove because _end in vmlinux.lds.S is align */
+ kernel_align_size = PAGE_UP((u32)klimit) - kernel_align_start;
+ lmb_reserve(kernel_align_start, kernel_align_size);
+ printk("%s: kernel addr=0x%08x-0x%08x size=0x%08x\n", __func__,
+ kernel_align_start, kernel_align_start + kernel_align_size,
+ kernel_align_size);
+
+ /*
+ * Kernel:
+ * start: base phys address of kernel - page align
+ * end: base phys address of kernel - page align
+ *
+ * min_low_pfn - the first page (mm/bootmem.c - node_boot_start)
+ * max_low_pfn
+ * max_mapnr - the first unused page (mm/bootmem.c - node_low_pfn)
+ * num_physpages - number of all pages
+ */
+
+ /* memory start is from the kernel end of memory aligned to higher addr */
+ min_low_pfn = memory_start >> PAGE_SHIFT; /* minimum for allocation */
+ num_physpages = max_mapnr = memory_size >> PAGE_SHIFT; /* RAM is assumed contiguous */
+ max_pfn = max_low_pfn = memory_end >> PAGE_SHIFT;
+
+ printk(KERN_INFO "%s: max_mapnr: %#lx\n", __func__, max_mapnr);
+ printk(KERN_INFO "%s: min_low_pfn: %#lx\n", __func__, min_low_pfn);
+ printk(KERN_INFO "%s: max_low_pfn: %#lx\n", __func__, max_low_pfn);
+
+ /*
+ * Find an area to use for the bootmem bitmap.
+ * We look for the first area which is at least
+ * 128kB in length (128kB is enough for a bitmap
+ * for 4GB of memory, using 4kB pages), plus 1 page
+ * (in case the address isn't page-aligned).
+ */
+ map_size = init_bootmem_node(NODE_DATA(0), PFN_UP(TOPHYS((u32)_end)),
+ min_low_pfn, max_low_pfn);
+
+ lmb_reserve(PFN_UP(TOPHYS((u32)_end)) << PAGE_SHIFT, map_size);
+
+ /* free bootmem is whole main memory */
+ free_bootmem(memory_start, memory_size);
+
+ /* reserve allocate blocks */
+ for (i = 0; i < lmb.reserved.cnt; i++) {
+ pr_debug("reserved %d - 0x%08x-0x%08x\n", i,
+ (u32) lmb.reserved.region[i].base,
+ (u32) lmb_size_bytes(&lmb.reserved, i));
+ reserve_bootmem(lmb.reserved.region[i].base,
+ lmb_size_bytes(&lmb.reserved, i) - 1, BOOTMEM_DEFAULT);
+ }
+ paging_init();
+}
+
+void free_init_pages(char *what, unsigned long begin, unsigned long end)
+{
+ unsigned long addr;
+
+ for (addr = begin; addr < end; addr += PAGE_SIZE) {
+ ClearPageReserved(virt_to_page(addr));
+ init_page_count(virt_to_page(addr));
+ memset((void *)addr, 0xcc, PAGE_SIZE);
+ free_page(addr);
+ totalram_pages++;
+ }
+ printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+ int pages = 0;
+ for (; start < end; start += PAGE_SIZE) {
+ ClearPageReserved(virt_to_page(start));
+ init_page_count(virt_to_page(start));
+ free_page(start);
+ totalram_pages++;
+ pages++;
+ }
+ printk(KERN_NOTICE "Freeing initrd memory: %dk freed\n", pages);
+}
+#endif
+
+void free_initmem(void)
+{
+ free_init_pages("unused kernel memory",
+ (unsigned long)(&__init_begin),
+ (unsigned long)(&__init_end));
+}
+
+/* FIXME from arch/powerpc/mm/mem.c*/
+void show_mem(void)
+{
+ printk(KERN_NOTICE "%s\n", __func__);
+}
+
+void __init mem_init(void)
+{
+ high_memory = (void *)__va(memory_end);
+ /* this will put all memory onto the freelists */
+ totalram_pages += free_all_bootmem();
+
+ printk(KERN_INFO "Memory: %luk/%luk available\n",
+ (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
+ num_physpages << (PAGE_SHIFT-10));
+}
+
+/* Check against bounds of physical memory */
+int ___range_ok(unsigned long addr, unsigned long size)
+{
+ return ((addr < memory_start) ||
+ ((addr + size) > memory_end));
+}
--
1.5.5.1
* [email protected] <[email protected]> wrote:
> Hi all,
>
> I think that is the right time to send you next pack with
> Microblaze support. It is seventh pack - some previous packs
> was review by community and I hope there are not any big faults.
I have not done a deep review, but there's a lot of avoidable easy
style bugs in the patches. All the patches together, passed through
scripts/checkpatch.pl give ~200 errors:
total: 40 errors, 146 warnings, 15737 lines checked
A quick look suggests that most of the warnings pinpoint real
problems. (and you can ignore false positives)
Thanks,
Ingo
Hi Ingo,
>> Hi all,
>>
>> I think that is the right time to send you next pack with
>> Microblaze support. It is seventh pack - some previous packs
>> was review by community and I hope there are not any big faults.
>
> I have not done a deep review, but there's a lot of avoidable easy
> style bugs in the patches. All the patches together, passed through
> scripts/checkpatch.pl give ~200 errors:
>
> total: 40 errors, 146 warnings, 15737 lines checked
>
> A quick look suggests that most of the warnings pinpoint real
> problems. (and you can ignore false positives)
I fixed coding style issue which was there. Some of them are false positive.
I don't want to disturb people with next big pack and next version that's why I
updated only branch on git (Patches has name microblaze_v8-pre)
Below is part of log with faults which are announcing with checkpatch.pl script
+ my comments. I remove patches without any fault.
Thanks for noticing me in cases where I am wrong.
Thanks,
Michal
>
> Thanks,
>
> Ingo
ERROR: spaces prohibited around that ':' (ctx:WxW)
#2588: FILE: arch/microblaze/kernel/prom_parse.c:637:
+ cells = prop ? *(u32 *)prop : of_n_addr_cells(dn);
^
ERROR: spaces prohibited around that ':' (ctx:WxW)
#2594: FILE: arch/microblaze/kernel/prom_parse.c:643:
+ cells = prop ? *(u32 *)prop : of_n_size_cells(dn);
^
total: 2 errors, 0 warnings, 2910 lines checked
0004-microblaze_v8-pre-Open-firmware-files.patch has style problems, please
review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
I think that this is correct coding style (Same for PowerPC)
-------------------------------------------------------------------------------------------
WARNING: do not add new typedefs
#127: FILE: arch/microblaze/include/asm/signal.h:107:
+typedef unsigned long old_sigset_t; /* at least 32 bits */
WARNING: do not add new typedefs
#129: FILE: arch/microblaze/include/asm/signal.h:109:
+typedef struct {
WARNING: do not add new typedefs
#161: FILE: arch/microblaze/include/asm/signal.h:141:
+typedef unsigned long sigset_t;
WARNING: do not add new typedefs
#178: FILE: arch/microblaze/include/asm/signal.h:158:
+typedef struct sigaltstack {
total: 0 errors, 4 warnings, 701 lines checked
0007-microblaze_v8-pre-Signal-support.patch has style problems, please review.
If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
False positive.
-------------------------------------------------------------------------------------------
WARNING: do not add new typedefs
#57: FILE: arch/microblaze/include/asm/module.h:35:
+typedef struct { volatile int counter; } module_t;
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#57: FILE: arch/microblaze/include/asm/module.h:35:
+typedef struct { volatile int counter; } module_t;
WARNING: externs should be avoided in .c files
#92: FILE: arch/microblaze/kernel/microblaze_ksyms.c:27:
+extern void __ashldi3(void);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
#93: FILE: arch/microblaze/kernel/microblaze_ksyms.c:28:
+EXPORT_SYMBOL(__ashldi3);
WARNING: externs should be avoided in .c files
#94: FILE: arch/microblaze/kernel/microblaze_ksyms.c:29:
+extern void __ashrdi3(void);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
#95: FILE: arch/microblaze/kernel/microblaze_ksyms.c:30:
+EXPORT_SYMBOL(__ashrdi3);
WARNING: externs should be avoided in .c files
#96: FILE: arch/microblaze/kernel/microblaze_ksyms.c:31:
+extern void __divsi3(void);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
#97: FILE: arch/microblaze/kernel/microblaze_ksyms.c:32:
+EXPORT_SYMBOL(__divsi3);
WARNING: externs should be avoided in .c files
#98: FILE: arch/microblaze/kernel/microblaze_ksyms.c:33:
+extern void __lshrdi3(void);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
#99: FILE: arch/microblaze/kernel/microblaze_ksyms.c:34:
+EXPORT_SYMBOL(__lshrdi3);
WARNING: externs should be avoided in .c files
#100: FILE: arch/microblaze/kernel/microblaze_ksyms.c:35:
+extern void __modsi3(void);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
#101: FILE: arch/microblaze/kernel/microblaze_ksyms.c:36:
+EXPORT_SYMBOL(__modsi3);
WARNING: externs should be avoided in .c files
#102: FILE: arch/microblaze/kernel/microblaze_ksyms.c:37:
+extern void __mulsi3(void);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
#103: FILE: arch/microblaze/kernel/microblaze_ksyms.c:38:
+EXPORT_SYMBOL(__mulsi3);
WARNING: externs should be avoided in .c files
#104: FILE: arch/microblaze/kernel/microblaze_ksyms.c:39:
+extern void __muldi3(void);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
#105: FILE: arch/microblaze/kernel/microblaze_ksyms.c:40:
+EXPORT_SYMBOL(__muldi3);
WARNING: externs should be avoided in .c files
#106: FILE: arch/microblaze/kernel/microblaze_ksyms.c:41:
+extern void __ucmpdi2(void);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
#107: FILE: arch/microblaze/kernel/microblaze_ksyms.c:42:
+EXPORT_SYMBOL(__ucmpdi2);
WARNING: externs should be avoided in .c files
#108: FILE: arch/microblaze/kernel/microblaze_ksyms.c:43:
+extern void __udivsi3(void);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
#109: FILE: arch/microblaze/kernel/microblaze_ksyms.c:44:
+EXPORT_SYMBOL(__udivsi3);
WARNING: externs should be avoided in .c files
#110: FILE: arch/microblaze/kernel/microblaze_ksyms.c:45:
+extern void __umodsi3(void);
WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
#111: FILE: arch/microblaze/kernel/microblaze_ksyms.c:46:
+EXPORT_SYMBOL(__umodsi3);
total: 0 errors, 22 warnings, 231 lines checked
0011-microblaze_v8-pre-kernel-modules-support.patch has style problems, please
review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
False positive
-------------------------------------------------------------------------------------------
WARNING: usage of NR_CPUS is often wrong - consider using cpu_possible(),
num_possible_cpus(), for_each_possible_cpu(), etc
#367: FILE: arch/microblaze/kernel/cpu/mb.c:130:
+ return i < NR_CPUS ? (void *) (i + 1) : NULL;
total: 0 errors, 1 warnings, 438 lines checked
0013-microblaze_v8-pre-PVR-support-cpuinfo-support.patch has style problems,
please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
NR_CPUS is used almost in all arch (x86 use it too)
-------------------------------------------------------------------------------------------
ERROR: Don't use kernel_thread(): see Documentation/feature-removal-schedule.txt
#216: FILE: arch/microblaze/kernel/process.c:163:
+int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
total: 1 errors, 0 warnings, 213 lines checked
0024-microblaze_v8-pre-process-and-init-task-function.patch has style problems,
please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
I am not sure but I found implementation of kernel_thread in x86, powerpc has
asm implementation. Arm use C implementation as we have for MB.
-------------------------------------------------------------------------------------------
WARNING: do not add new typedefs
#112: FILE: arch/microblaze/include/asm/timex.h:14:
+typedef unsigned long cycles_t;
total: 0 errors, 1 warnings, 90 lines checked
0025-microblaze_v8-pre-delay.h-timex.h.patch has style problems, please review.
If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
WARNING: do not add new typedefs
#35: FILE: arch/microblaze/include/asm/ptrace.h:15:
+typedef unsigned long microblaze_reg_t;
total: 0 errors, 1 warnings, 250 lines checked
0026-microblaze_v8-pre-ptrace-support.patch has style problems, please review.
If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
False positive
-------------------------------------------------------------------------------------------
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#41: FILE: arch/microblaze/kernel/traps.c:23:
+void __bad_xchg(volatile void *ptr, int size)
total: 0 errors, 1 warnings, 105 lines checked
0028-microblaze_v8-pre-traps-support.patch has style problems, please review.
If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
ARM has the same implemtation - I think that's ok.
-------------------------------------------------------------------------------------------
WARNING: do not add new typedefs
#39: FILE: arch/microblaze/include/asm/mmu.h:13:
+typedef struct {
total: 0 errors, 1 warnings, 277 lines checked
0029-microblaze_v8-pre-memory-inicialization-MMU-TLB.patch has style problems,
please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
false positive
-------------------------------------------------------------------------------------------
WARNING: do not add new typedefs
#82: FILE: arch/microblaze/include/asm/page.h:60:
+typedef struct page *pgtable_t;
WARNING: do not add new typedefs
#83: FILE: arch/microblaze/include/asm/page.h:61:
+typedef struct { unsigned long pte; } pte_t;
WARNING: do not add new typedefs
#84: FILE: arch/microblaze/include/asm/page.h:62:
+typedef struct { unsigned long pgprot; } pgprot_t;
WARNING: do not add new typedefs
#85: FILE: arch/microblaze/include/asm/page.h:63:
+typedef struct { unsigned long ste[64]; } pmd_t;
WARNING: do not add new typedefs
#86: FILE: arch/microblaze/include/asm/page.h:64:
+typedef struct { pmd_t pue[1]; } pud_t;
WARNING: do not add new typedefs
#87: FILE: arch/microblaze/include/asm/page.h:65:
+typedef struct { pud_t pge[1]; } pgd_t;
WARNING: do not add new typedefs
#184: FILE: arch/microblaze/include/asm/segment.h:16:
+typedef struct {
total: 0 errors, 7 warnings, 205 lines checked
0030-microblaze_v8-pre-page.h-segment.h-unaligned.h.patch has style problems,
please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
false positive
-------------------------------------------------------------------------------------------
WARNING: do not add new typedefs
#38: FILE: arch/microblaze/include/asm/posix_types.h:18:
+typedef unsigned long __kernel_ino_t;
WARNING: do not add new typedefs
#39: FILE: arch/microblaze/include/asm/posix_types.h:19:
+typedef unsigned int __kernel_mode_t;
WARNING: do not add new typedefs
#40: FILE: arch/microblaze/include/asm/posix_types.h:20:
+typedef unsigned int __kernel_nlink_t;
WARNING: do not add new typedefs
#41: FILE: arch/microblaze/include/asm/posix_types.h:21:
+typedef long __kernel_off_t;
WARNING: do not add new typedefs
#42: FILE: arch/microblaze/include/asm/posix_types.h:22:
+typedef int __kernel_pid_t;
WARNING: do not add new typedefs
#43: FILE: arch/microblaze/include/asm/posix_types.h:23:
+typedef unsigned int __kernel_ipc_pid_t;
WARNING: do not add new typedefs
#44: FILE: arch/microblaze/include/asm/posix_types.h:24:
+typedef unsigned int __kernel_uid_t;
WARNING: do not add new typedefs
#45: FILE: arch/microblaze/include/asm/posix_types.h:25:
+typedef unsigned int __kernel_gid_t;
WARNING: do not add new typedefs
#46: FILE: arch/microblaze/include/asm/posix_types.h:26:
+typedef unsigned long __kernel_size_t;
WARNING: do not add new typedefs
#47: FILE: arch/microblaze/include/asm/posix_types.h:27:
+typedef long __kernel_ssize_t;
WARNING: do not add new typedefs
#48: FILE: arch/microblaze/include/asm/posix_types.h:28:
+typedef int __kernel_ptrdiff_t;
WARNING: do not add new typedefs
#49: FILE: arch/microblaze/include/asm/posix_types.h:29:
+typedef long __kernel_time_t;
WARNING: do not add new typedefs
#50: FILE: arch/microblaze/include/asm/posix_types.h:30:
+typedef long __kernel_suseconds_t;
WARNING: do not add new typedefs
#51: FILE: arch/microblaze/include/asm/posix_types.h:31:
+typedef long __kernel_clock_t;
WARNING: do not add new typedefs
#52: FILE: arch/microblaze/include/asm/posix_types.h:32:
+typedef int __kernel_timer_t;
WARNING: do not add new typedefs
#53: FILE: arch/microblaze/include/asm/posix_types.h:33:
+typedef int __kernel_clockid_t;
WARNING: do not add new typedefs
#54: FILE: arch/microblaze/include/asm/posix_types.h:34:
+typedef int __kernel_daddr_t;
WARNING: do not add new typedefs
#55: FILE: arch/microblaze/include/asm/posix_types.h:35:
+typedef char *__kernel_caddr_t;
WARNING: do not add new typedefs
#56: FILE: arch/microblaze/include/asm/posix_types.h:36:
+typedef unsigned short __kernel_uid16_t;
WARNING: do not add new typedefs
#57: FILE: arch/microblaze/include/asm/posix_types.h:37:
+typedef unsigned short __kernel_gid16_t;
WARNING: do not add new typedefs
#58: FILE: arch/microblaze/include/asm/posix_types.h:38:
+typedef unsigned int __kernel_uid32_t;
WARNING: do not add new typedefs
#59: FILE: arch/microblaze/include/asm/posix_types.h:39:
+typedef unsigned int __kernel_gid32_t;
WARNING: do not add new typedefs
#62: FILE: arch/microblaze/include/asm/posix_types.h:42:
+typedef long long __kernel_loff_t;
WARNING: do not add new typedefs
#65: FILE: arch/microblaze/include/asm/posix_types.h:45:
+typedef struct {
WARNING: do not add new typedefs
#119: FILE: arch/microblaze/include/asm/types.h:24:
+typedef unsigned short umode_t;
false positive
-------------------------------------------------------------------------------------------
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#37: FILE: arch/microblaze/include/asm/io.h:19:
+static inline unsigned char __raw_readb(const volatile void __iomem *addr)
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#39: FILE: arch/microblaze/include/asm/io.h:21:
+ return *(volatile unsigned char __force *)addr;
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#41: FILE: arch/microblaze/include/asm/io.h:23:
+static inline unsigned short __raw_readw(const volatile void __iomem *addr)
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#43: FILE: arch/microblaze/include/asm/io.h:25:
+ return *(volatile unsigned short __force *)addr;
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#45: FILE: arch/microblaze/include/asm/io.h:27:
+static inline unsigned int __raw_readl(const volatile void __iomem *addr)
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#47: FILE: arch/microblaze/include/asm/io.h:29:
+ return *(volatile unsigned int __force *)addr;
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#49: FILE: arch/microblaze/include/asm/io.h:31:
+static inline unsigned long __raw_readq(const volatile void __iomem *addr)
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#51: FILE: arch/microblaze/include/asm/io.h:33:
+ return *(volatile unsigned long __force *)addr;
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#53: FILE: arch/microblaze/include/asm/io.h:35:
+static inline void __raw_writeb(unsigned char v, volatile void __iomem *addr)
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#55: FILE: arch/microblaze/include/asm/io.h:37:
+ *(volatile unsigned char __force *)addr = v;
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#57: FILE: arch/microblaze/include/asm/io.h:39:
+static inline void __raw_writew(unsigned short v, volatile void __iomem *addr)
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#59: FILE: arch/microblaze/include/asm/io.h:41:
+ *(volatile unsigned short __force *)addr = v;
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#61: FILE: arch/microblaze/include/asm/io.h:43:
+static inline void __raw_writel(unsigned int v, volatile void __iomem *addr)
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#63: FILE: arch/microblaze/include/asm/io.h:45:
+ *(volatile unsigned int __force *)addr = v;
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#65: FILE: arch/microblaze/include/asm/io.h:47:
+static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr)
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#67: FILE: arch/microblaze/include/asm/io.h:49:
+ *(volatile unsigned long __force *)addr = v;
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#75: FILE: arch/microblaze/include/asm/io.h:57:
+static inline unsigned char readb(const volatile void __iomem *addr)
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#77: FILE: arch/microblaze/include/asm/io.h:59:
+ return *(volatile unsigned char __force *)addr;
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#79: FILE: arch/microblaze/include/asm/io.h:61:
+static inline unsigned short readw(const volatile void __iomem *addr)
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#81: FILE: arch/microblaze/include/asm/io.h:63:
+ return le16_to_cpu(*(volatile unsigned short __force *)addr);
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#83: FILE: arch/microblaze/include/asm/io.h:65:
+static inline unsigned int readl(const volatile void __iomem *addr)
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#85: FILE: arch/microblaze/include/asm/io.h:67:
+ return le32_to_cpu(*(volatile unsigned int __force *)addr);
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#87: FILE: arch/microblaze/include/asm/io.h:69:
+static inline void writeb(unsigned char v, volatile void __iomem *addr)
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#89: FILE: arch/microblaze/include/asm/io.h:71:
+ *(volatile unsigned char __force *)addr = v;
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#91: FILE: arch/microblaze/include/asm/io.h:73:
+static inline void writew(unsigned short v, volatile void __iomem *addr)
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#93: FILE: arch/microblaze/include/asm/io.h:75:
+ *(volatile unsigned short __force *)addr = cpu_to_le16(v);
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#95: FILE: arch/microblaze/include/asm/io.h:77:
+static inline void writel(unsigned int v, volatile void __iomem *addr)
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#97: FILE: arch/microblaze/include/asm/io.h:79:
+ *(volatile unsigned int __force *)addr = cpu_to_le32(v);
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#146: FILE: arch/microblaze/include/asm/io.h:128:
+static inline unsigned long __iomem virt_to_phys(volatile void *address)
total: 0 errors, 29 warnings, 209 lines checked
0035-microblaze_v8-pre-io.h-IO-operations.patch has style problems, please
review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
false positive - same as powerpc
-------------------------------------------------------------------------------------------
WARNING: do not add new typedefs
#44: FILE: arch/microblaze/include/asm/hardirq.h:21:
+typedef struct {
total: 0 errors, 1 warnings, 153 lines checked
0038-microblaze_v8-pre-headers-for-irq.patch has style problems, please review.
If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
false positive
-------------------------------------------------------------------------------------------
ERROR: Don't use kernel_thread(): see Documentation/feature-removal-schedule.txt
#105: FILE: arch/microblaze/include/asm/processor.h:85:
+extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#162: FILE: arch/microblaze/include/asm/system.h:43:
+void __bad_xchg(volatile void *ptr, int size);
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#164: FILE: arch/microblaze/include/asm/system.h:45:
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#173: FILE: arch/microblaze/include/asm/system.h:54:
+ ret = *(volatile unsigned char *)ptr;
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#174: FILE: arch/microblaze/include/asm/system.h:55:
+ *(volatile unsigned char *)ptr = x;
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#180: FILE: arch/microblaze/include/asm/system.h:61:
+ ret = *(volatile unsigned long *)ptr;
WARNING: Use of volatile is usually wrong: see
Documentation/volatile-considered-harmful.txt
#181: FILE: arch/microblaze/include/asm/system.h:62:
+ *(volatile unsigned long *)ptr = x;
total: 1 errors, 6 warnings, 184 lines checked
0041-microblaze_v8-pre-system.h-processor.h.patch has style problems, please
review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
kernel thread - as above. xchg -> sam as arm. Am I right?
-------------------------------------------------------------------------------------------
WARNING: do not add new typedefs
#34: FILE: arch/microblaze/include/asm/termbits.h:14:
+typedef unsigned char cc_t;
WARNING: do not add new typedefs
#35: FILE: arch/microblaze/include/asm/termbits.h:15:
+typedef unsigned int speed_t;
WARNING: do not add new typedefs
#36: FILE: arch/microblaze/include/asm/termbits.h:16:
+typedef unsigned int tcflag_t;
total: 0 errors, 3 warnings, 291 lines checked
0044-microblaze_v8-pre-termbits.h-termios.h.patch has style problems, please
review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
false positive
-------------------------------------------------------------------------------------------
ERROR: Aspace prohibited after that '&' (ctx:WxW)
#152: FILE: arch/microblaze/include/asm/thread_info.h:102:
+ return (struct thread_info *)(sp & ~(THREAD_SIZE-1));
^
total: 1 errors, 0 warnings, 176 lines checked
0053-microblaze_v8-pre-string.h-thread_info.h.patch has style problems, please
review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
I think here is correct coding style.
-------------------------------------------------------------------------------------------
That's all.
M
--
Michal Simek, Ing. (M.Eng)
w: http://www.monstr.eu p: +42-0-721842854
* Michal Simek <[email protected]> wrote:
> WARNING: externs should be avoided in .c files
> #92: FILE: arch/microblaze/kernel/microblaze_ksyms.c:27:
> +extern void __ashldi3(void);
>
> WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
> #93: FILE: arch/microblaze/kernel/microblaze_ksyms.c:28:
> +EXPORT_SYMBOL(__ashldi3);
>
> WARNING: externs should be avoided in .c files
> #94: FILE: arch/microblaze/kernel/microblaze_ksyms.c:29:
> +extern void __ashrdi3(void);
>
> WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
> #95: FILE: arch/microblaze/kernel/microblaze_ksyms.c:30:
> +EXPORT_SYMBOL(__ashrdi3);
>
> WARNING: externs should be avoided in .c files
> #96: FILE: arch/microblaze/kernel/microblaze_ksyms.c:31:
> +extern void __divsi3(void);
>
> WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
> #97: FILE: arch/microblaze/kernel/microblaze_ksyms.c:32:
> +EXPORT_SYMBOL(__divsi3);
>
> WARNING: externs should be avoided in .c files
> #98: FILE: arch/microblaze/kernel/microblaze_ksyms.c:33:
> +extern void __lshrdi3(void);
>
> WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
> #99: FILE: arch/microblaze/kernel/microblaze_ksyms.c:34:
> +EXPORT_SYMBOL(__lshrdi3);
>
> WARNING: externs should be avoided in .c files
> #100: FILE: arch/microblaze/kernel/microblaze_ksyms.c:35:
> +extern void __modsi3(void);
>
> WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
> #101: FILE: arch/microblaze/kernel/microblaze_ksyms.c:36:
> +EXPORT_SYMBOL(__modsi3);
>
> WARNING: externs should be avoided in .c files
> #102: FILE: arch/microblaze/kernel/microblaze_ksyms.c:37:
> +extern void __mulsi3(void);
>
> WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
> #103: FILE: arch/microblaze/kernel/microblaze_ksyms.c:38:
> +EXPORT_SYMBOL(__mulsi3);
>
> WARNING: externs should be avoided in .c files
> #104: FILE: arch/microblaze/kernel/microblaze_ksyms.c:39:
> +extern void __muldi3(void);
>
> WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
> #105: FILE: arch/microblaze/kernel/microblaze_ksyms.c:40:
> +EXPORT_SYMBOL(__muldi3);
>
> WARNING: externs should be avoided in .c files
> #106: FILE: arch/microblaze/kernel/microblaze_ksyms.c:41:
> +extern void __ucmpdi2(void);
>
> WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
> #107: FILE: arch/microblaze/kernel/microblaze_ksyms.c:42:
> +EXPORT_SYMBOL(__ucmpdi2);
>
> WARNING: externs should be avoided in .c files
> #108: FILE: arch/microblaze/kernel/microblaze_ksyms.c:43:
> +extern void __udivsi3(void);
>
> WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
> #109: FILE: arch/microblaze/kernel/microblaze_ksyms.c:44:
> +EXPORT_SYMBOL(__udivsi3);
>
> WARNING: externs should be avoided in .c files
> #110: FILE: arch/microblaze/kernel/microblaze_ksyms.c:45:
> +extern void __umodsi3(void);
>
> WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
> #111: FILE: arch/microblaze/kernel/microblaze_ksyms.c:46:
> +EXPORT_SYMBOL(__umodsi3);
externs should be in header files.
The rest indeed looks like false positives. Thanks for addressing
these things so quickly!
Ingo
Hi Ingo,
> * Michal Simek <[email protected]> wrote:
>
>> WARNING: externs should be avoided in .c files
>> #110: FILE: arch/microblaze/kernel/microblaze_ksyms.c:45:
>> +extern void __umodsi3(void);
>>
>> WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
>> #111: FILE: arch/microblaze/kernel/microblaze_ksyms.c:46:
>> +EXPORT_SYMBOL(__umodsi3);
>
> externs should be in header files.
>
> The rest indeed looks like false positives. Thanks for addressing
> these things so quickly!
you are welcome - I can quickly test and add all changes to git.
Is it good style separate extern definition and EXPORT_SYMBOL?
I have three choices?
1. keep extern + EXPORT_SYMBOL below - current style
2. move only extern to header file
3. move extern and EXPORT_SYMBOL to header.
What is preferable way?
Thanks,
Michal
>
> Ingo
--
Michal Simek, Ing. (M.Eng)
w: http://www.monstr.eu p: +42-0-721842854
On Thu, 2009-03-19 at 11:26 +0100, Michal Simek wrote:
> you are welcome - I can quickly test and add all changes to git.
>
> Is it good style separate extern definition and EXPORT_SYMBOL?
>
> I have three choices?
> 1. keep extern + EXPORT_SYMBOL below - current style
> 2. move only extern to header file
> 3. move extern and EXPORT_SYMBOL to header.
>
> What is preferable way?
externs should be in header files
EXPORT_SYMBOL should immediately follow its function/variable should
normally be in source files like : arch/x86/kernel/process.c
and if required can also be defined in header files like:
arch/x86/include/asm/percpu.h
--
JSR
* Michal Simek <[email protected]> wrote:
> Hi Ingo,
> > * Michal Simek <[email protected]> wrote:
> >
> >> WARNING: externs should be avoided in .c files
> >> #110: FILE: arch/microblaze/kernel/microblaze_ksyms.c:45:
> >> +extern void __umodsi3(void);
> >>
> >> WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
> >> #111: FILE: arch/microblaze/kernel/microblaze_ksyms.c:46:
> >> +EXPORT_SYMBOL(__umodsi3);
> >
> > externs should be in header files.
> >
> > The rest indeed looks like false positives. Thanks for addressing
> > these things so quickly!
>
> you are welcome - I can quickly test and add all changes to git.
>
> Is it good style separate extern definition and EXPORT_SYMBOL?
>
> I have three choices?
> 1. keep extern + EXPORT_SYMBOL below - current style
> 2. move only extern to header file
> 3. move extern and EXPORT_SYMBOL to header.
>
> What is preferable way?
Where are the symbols defined - by gcc's library?
Ingo
Ingo Molnar wrote:
> * Michal Simek <[email protected]> wrote:
>
>> Hi Ingo,
>>> * Michal Simek <[email protected]> wrote:
>>>
>>>> WARNING: externs should be avoided in .c files
>>>> #110: FILE: arch/microblaze/kernel/microblaze_ksyms.c:45:
>>>> +extern void __umodsi3(void);
>>>>
>>>> WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
>>>> #111: FILE: arch/microblaze/kernel/microblaze_ksyms.c:46:
>>>> +EXPORT_SYMBOL(__umodsi3);
>>> externs should be in header files.
>>>
>>> The rest indeed looks like false positives. Thanks for addressing
>>> these things so quickly!
>> you are welcome - I can quickly test and add all changes to git.
>>
>> Is it good style separate extern definition and EXPORT_SYMBOL?
>>
>> I have three choices?
>> 1. keep extern + EXPORT_SYMBOL below - current style
>> 2. move only extern to header file
>> 3. move extern and EXPORT_SYMBOL to header.
>>
>> What is preferable way?
>
> Where are the symbols defined - by gcc's library?
yes.
M
> Ingo
--
Michal Simek, Ing. (M.Eng)
w: http://www.monstr.eu p: +42-0-721842854
* Michal Simek <[email protected]> wrote:
> Ingo Molnar wrote:
> > * Michal Simek <[email protected]> wrote:
> >
> >> Hi Ingo,
> >>> * Michal Simek <[email protected]> wrote:
> >>>
> >>>> WARNING: externs should be avoided in .c files
> >>>> #110: FILE: arch/microblaze/kernel/microblaze_ksyms.c:45:
> >>>> +extern void __umodsi3(void);
> >>>>
> >>>> WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
> >>>> #111: FILE: arch/microblaze/kernel/microblaze_ksyms.c:46:
> >>>> +EXPORT_SYMBOL(__umodsi3);
> >>> externs should be in header files.
> >>>
> >>> The rest indeed looks like false positives. Thanks for addressing
> >>> these things so quickly!
> >> you are welcome - I can quickly test and add all changes to git.
> >>
> >> Is it good style separate extern definition and EXPORT_SYMBOL?
> >>
> >> I have three choices?
> >> 1. keep extern + EXPORT_SYMBOL below - current style
> >> 2. move only extern to header file
> >> 3. move extern and EXPORT_SYMBOL to header.
> >>
> >> What is preferable way?
> >
> > Where are the symbols defined - by gcc's library?
>
> yes.
i suspect it's borderline in that case, and your solution is fine.
The other solution would be to stuff the externs into a header and
have a continuous block of exports with a comment that says:
/*
* GCC library functions:
*/
EXPORT_SYMBOL(...);
EXPORT_SYMBOL(...);
EXPORT_SYMBOL(...);
Ingo
Ingo Molnar wrote:
> * Michal Simek <[email protected]> wrote:
>
>> Ingo Molnar wrote:
>>> * Michal Simek <[email protected]> wrote:
>>>
>>>> Hi Ingo,
>>>>> * Michal Simek <[email protected]> wrote:
>>>>>
>>>>>> WARNING: externs should be avoided in .c files
>>>>>> #110: FILE: arch/microblaze/kernel/microblaze_ksyms.c:45:
>>>>>> +extern void __umodsi3(void);
>>>>>>
>>>>>> WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable
>>>>>> #111: FILE: arch/microblaze/kernel/microblaze_ksyms.c:46:
>>>>>> +EXPORT_SYMBOL(__umodsi3);
>>>>> externs should be in header files.
>>>>>
>>>>> The rest indeed looks like false positives. Thanks for addressing
>>>>> these things so quickly!
>>>> you are welcome - I can quickly test and add all changes to git.
>>>>
>>>> Is it good style separate extern definition and EXPORT_SYMBOL?
>>>>
>>>> I have three choices?
>>>> 1. keep extern + EXPORT_SYMBOL below - current style
>>>> 2. move only extern to header file
>>>> 3. move extern and EXPORT_SYMBOL to header.
>>>>
>>>> What is preferable way?
>>> Where are the symbols defined - by gcc's library?
>> yes.
>
> i suspect it's borderline in that case, and your solution is fine.
> The other solution would be to stuff the externs into a header and
> have a continuous block of exports with a comment that says:
>
> /*
> * GCC library functions:
> */
> EXPORT_SYMBOL(...);
> EXPORT_SYMBOL(...);
> EXPORT_SYMBOL(...);
Ok. I keep it in current style. Everything is one file and there is comment
about.
Thanks,
Michal
> Ingo
Jaswinder Singh Rajput wrote:
> On Thu, 2009-03-19 at 11:26 +0100, Michal Simek wrote:
>
>> you are welcome - I can quickly test and add all changes to git.
>>
>> Is it good style separate extern definition and EXPORT_SYMBOL?
>>
>> I have three choices?
>> 1. keep extern + EXPORT_SYMBOL below - current style
>> 2. move only extern to header file
>> 3. move extern and EXPORT_SYMBOL to header.
>>
>> What is preferable way?
>
> externs should be in header files
>
> EXPORT_SYMBOL should immediately follow its function/variable should
> normally be in source files like : arch/x86/kernel/process.c
Yes, I know -> is should be in all microblaze code (for example
arch/microblaze/lib folder)
> and if required can also be defined in header files like:
> arch/x86/include/asm/percpu.h
As wrote Ingo this is a little bit different case.
Thanks for you comments,
Michal
>
> --
> JSR
>
--
Michal Simek, Ing. (M.Eng)
w: http://www.monstr.eu p: +42-0-721842854
Michal,
On Wed, 18 Mar 2009, [email protected] wrote:
> +static u32 concurrent_irq;
> +
> +void do_IRQ(struct pt_regs *regs)
> +{
> + unsigned int irq;
> + struct pt_regs *old_regs = set_irq_regs(regs);
> +
> + irq_enter();
> + irq = get_irq(regs);
> +next_irq:
> + BUG_ON(irq == -1U);
> + __do_IRQ(irq);
You use irq chips now and you set the type handlers (edge/level), but
you still call __do_IRQ() the all in one fits nothing handler, which
is going to be deprecated and removed.
Please call
generic_handle_irq(irq);
which will call the correct flow handlers.
> +static int microblaze_timer_set_next_event(unsigned long delta,
> + struct clock_event_device *dev)
> +{
> + printk(KERN_INFO "next event, delta %x, %d\n", (u32)delta, (u32)delta);
This should be pr_debug() or do you want to flood the syslog in
every timer interrupt ?
> + microblaze_timer_start(delta);
> + return 0;
> +}
> +
> +static void microblaze_timer_set_mode(enum clock_event_mode mode,
> + struct clock_event_device *evt)
> +{
> + microblaze_timer_stop();
> +
> + switch (mode) {
> + case CLOCK_EVT_MODE_PERIODIC:
> + printk(KERN_INFO "%s: periodic\n", __func__);
pr_debug as well. That's not very informative
> +static irqreturn_t timer_interrupt(int irq, void *dev_id)
> +{
> + struct clock_event_device *evt = &clockevent_microblaze_timer;
> +#ifdef CONFIG_HEART_BEAT
> + heartbeat();
> +#endif
> + timer_ack();
> +
> + mb_tick_cnt += cpuinfo.freq_div_hz;
Hmm. How does that work with oneshot timers ?
> + evt->event_handler(evt);
> + return IRQ_HANDLED;
> +}
> +
> +static struct irqaction timer_irqaction = {
> + .handler = timer_interrupt,
> + .flags = IRQF_DISABLED,
IRQF_DISABLED | IRQF_TIMER,
> + xtime.tv_sec = mktime(2007, 1, 1, 0, 0, 0);
> + xtime.tv_nsec = 0;
> + set_normalized_timespec(&wall_to_monotonic,
> + -xtime.tv_sec, -xtime.tv_nsec);
Yuck. What's that ? wall_to_monotonic is maintained by the generic
code.
Thanks,
tglx
Hi Thomas,
>
>> +static u32 concurrent_irq;
>> +
>> +void do_IRQ(struct pt_regs *regs)
>> +{
>> + unsigned int irq;
>> + struct pt_regs *old_regs = set_irq_regs(regs);
>> +
>> + irq_enter();
>> + irq = get_irq(regs);
>> +next_irq:
>> + BUG_ON(irq == -1U);
>> + __do_IRQ(irq);
>
> You use irq chips now and you set the type handlers (edge/level), but
> you still call __do_IRQ() the all in one fits nothing handler, which
> is going to be deprecated and removed.
I know about.
>
> Please call
> generic_handle_irq(irq);
>
> which will call the correct flow handlers.
I would like to use it but don't work with edge interrupt.
__do_IRQ handle it in right way.
I used this implementation but I did some change edge/level handling and I can't
use it.
http://developer.petalogix.com/git/gitweb.cgi?p=linux-2.6-microblaze.git;a=blob_plain;f=arch/microblaze/kernel/irq.c;hb=3645d887ad6443a262bbeddf384038321172db2b
Any hints what could be wrong?
First of all I have one question to you about MB timer.c.
It is about this function - microblaze_read.
static cycle_t mb_tick_cnt; /* store counter ticks */
static cycle_t microblaze_read(void)
{
u64 temp = (u64)mb_tick_cnt + (u64)((u32)cpuinfo.freq_div_hz
- (u32)in_be32(TIMER_BASE + TCR0));
return temp;
}
MB has 32bit periodic down counter and I need to use u64 value that's why
I do these operation above. cpuinfo.freq_div_hz store freq/HZ value - number of
ticks for 1/HZ. I subtract current timer value + mb_tick_cnt which store number
of count. The problem I have is that gettimeofday LTP test failed on it ->
announce that time is going backward.
Simple returning only mb_tick_cnt pass this test but of course I am losing
information about time till 1/HZ.
Do I have to add any specific amount of time which take counting of it?
And the second question is about shift and rating values.
I wrote one message in past http://lkml.org/lkml/2009/1/11/291
Here is the important of part of that message.
...
And the second part is about shift and rating values. Rating is
describe(linux/clocksource.h) and seems to me that should be
corresponded with CONFIG_HZ value,right?
And I found any explanation of shift value -> max value for equation
(2-5) * freq << shift / NSEC_PER_SEC should be for my case still 32bit
number, where (2-5s) are because of NTP
The second thing which seems to me weird in comparing with others log I
have seen is .resolution value. Full (proc/timer_lists is below) My
.resolution: 10000000 nsecs which
is 1/HZ in nsec. (On others log I saw 1nsec values). My the lowest
resolution is 1/freq = 8nsec (for 125MHz). Is that OK or not.
...
>
>> +static int microblaze_timer_set_next_event(unsigned long delta,
>> + struct clock_event_device *dev)
>> +{
>> + printk(KERN_INFO "next event, delta %x, %d\n", (u32)delta, (u32)delta);
>
> This should be pr_debug() or do you want to flood the syslog in
> every timer interrupt ?
This not flood the syslog. I don't know why (maybe because of missing ONESHOT)
but this code is never called in periodic mode. But you are right if this
function is called a lot it is necessary to use pr_debug -> but this is not my
case in this implementation.
>
>> + microblaze_timer_start(delta);
>> + return 0;
>> +}
>> +
>> +static void microblaze_timer_set_mode(enum clock_event_mode mode,
>> + struct clock_event_device *evt)
>> +{
>> + microblaze_timer_stop();
>> +
>> + switch (mode) {
>> + case CLOCK_EVT_MODE_PERIODIC:
>> + printk(KERN_INFO "%s: periodic\n", __func__);
>
> pr_debug as well. That's not very informative
It is only information that timer work in periodic mode.
Part of kernel log which is there - nothing more.
microblaze_timer_set_mode: shutdown
microblaze_timer_set_mode: periodic
>
>> +static irqreturn_t timer_interrupt(int irq, void *dev_id)
>> +{
>> + struct clock_event_device *evt = &clockevent_microblaze_timer;
>> +#ifdef CONFIG_HEART_BEAT
>> + heartbeat();
>> +#endif
>> + timer_ack();
>> +
>> + mb_tick_cnt += cpuinfo.freq_div_hz;
>
> Hmm. How does that work with oneshot timers ?
Oneshot is not supported yet - only periodic mode. I had to add it mb_tick_cnt
counting because
I don't know reason but without it ( kernel and timer in periodic mode )not
update system time.
>
>> + evt->event_handler(evt);
>> + return IRQ_HANDLED;
>> +}
>> +
>> +static struct irqaction timer_irqaction = {
>> + .handler = timer_interrupt,
>> + .flags = IRQF_DISABLED,
>
> IRQF_DISABLED | IRQF_TIMER,
OK. I'll add it.
>
>
>> + xtime.tv_sec = mktime(2007, 1, 1, 0, 0, 0);
>> + xtime.tv_nsec = 0;
>> + set_normalized_timespec(&wall_to_monotonic,
>> + -xtime.tv_sec, -xtime.tv_nsec);
>
> Yuck. What's that ? wall_to_monotonic is maintained by the generic
> code.
I take this part of code from arch/blackfin/kernel/time-ts.c:217-219.
arch/x86/xen/time.c use it too. And arch/arm/kernel/time.c use similar
implemetation.
Thanks,
Michal
>
> Thanks,
>
> tglx
>
>
--
Michal Simek, Ing. (M.Eng)
w: http://www.monstr.eu p: +42-0-721842854
[email protected] wrote:
> Hi all,
>
> I think that is the right time to send you next pack with
> Microblaze support. It is seventh pack - some previous packs
> was review by community and I hope there are not any big faults.
>
> We tested this kernel on some boards.
> We have GIT server up and gitweb is available at http://developer.petalogix.com/git/gitweb.cgi
>
> All information about git clone you can find on gitweb.
> This pack is available in for-linus branch. Information about other branches are on gitweb too.
>
> More information about microblaze fdt kernel you can find at http://www.monstr.eu/fdt/
> If you want to test kernel with microblaze toolchain let me know.
Hi Michal,
Is there an x86-hosted cross-tool chain available?
If so, where?
> I added only uart16550 and uartlite support - that's enought for first merge.
>
>
> Thanks for you comments and especially for your ACK,
Thanks,
--
~Randy
Hi Randy,
> [email protected] wrote:
>> Hi all,
>>
>> I think that is the right time to send you next pack with
>> Microblaze support. It is seventh pack - some previous packs
>> was review by community and I hope there are not any big faults.
>>
>> We tested this kernel on some boards.
>> We have GIT server up and gitweb is available at http://developer.petalogix.com/git/gitweb.cgi
>>
>> All information about git clone you can find on gitweb.
>> This pack is available in for-linus branch. Information about other branches are on gitweb too.
>>
>> More information about microblaze fdt kernel you can find at http://www.monstr.eu/fdt/
>> If you want to test kernel with microblaze toolchain let me know.
>
> Hi Michal,
>
> Is there an x86-hosted cross-tool chain available?
> If so, where?
yes it is. I use old 3.4.1 gcc and we are preparing 4.1.2 version.(We have 4.1.2
for MMU with glibc). I hope will be ready soon. Of course is possible to compile
kernel with that tool too.
The first way is download that code from svn server.
Here is the link directly to svn folder (Name guest, without password)
https://developer.petalogix.com/pr/internal/petalinux/trunk/tools/linux-i386/microblaze-uclinux-tools/
The second way is download full distribution (360MB)
http://developer.petalogix.com/downloads/petalinux-v0.30-rc1.tar.gz
There is . setting.sh script which only add toolchain to your patches or you can
add it by hand. (Location is in tools/linux-i386/microblaze-uclinux-tools).
If you want gcc 4.1.2 pack for MMU (Just for kernel build) I can provide you
prebuilt package too.
Thanks,
Michal
>
>> I added only uart16550 and uartlite support - that's enought for first merge.
>>
>>
>> Thanks for you comments and especially for your ACK,
>
> Thanks,
--
Michal Simek, Ing. (M.Eng)
w: http://www.monstr.eu p: +42-0-721842854
Michal,
On Thu, 19 Mar 2009, Michal Simek wrote:
> >> + __do_IRQ(irq);
> >
> > You use irq chips now and you set the type handlers (edge/level), but
> > you still call __do_IRQ() the all in one fits nothing handler, which
> > is going to be deprecated and removed.
>
> I know about.
> >
> > Please call
> > generic_handle_irq(irq);
> >
> > which will call the correct flow handlers.
>
> I would like to use it but don't work with edge interrupt.
> __do_IRQ handle it in right way.
>
> I used this implementation but I did some change edge/level handling and I can't
> use it.
> http://developer.petalogix.com/git/gitweb.cgi?p=linux-2.6-microblaze.git;a=blob_plain;f=arch/microblaze/kernel/irq.c;hb=3645d887ad6443a262bbeddf384038321172db2b
>
> Any hints what could be wrong?
Look at the different handling schemes of __do_IRQ and handle_edge_irq
vs. the chip functions:
__do_IRQ() does:
{
chip->ack();
handle_IRQ_event();
chip->end();
}
handle_edge_irq() does:
{
if ((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) ||
!desc->action)) {
desc->status |= (IRQ_PENDING | IRQ_MASKED);
mask_ack_irq(desc, irq);
goto out_unlock;
}
chip->ack();
handle_IRQ_event();
}
I guess the problem is in your chip->xxx functions.
> First of all I have one question to you about MB timer.c.
> It is about this function - microblaze_read.
>
> static cycle_t mb_tick_cnt; /* store counter ticks */
>
> static cycle_t microblaze_read(void)
> {
> u64 temp = (u64)mb_tick_cnt + (u64)((u32)cpuinfo.freq_div_hz
> - (u32)in_be32(TIMER_BASE + TCR0));
> return temp;
> }
>
>
> MB has 32bit periodic down counter and I need to use u64 value that's why
> I do these operation above. cpuinfo.freq_div_hz store freq/HZ value - number of
> ticks for 1/HZ. I subtract current timer value + mb_tick_cnt which store number
> of count. The problem I have is that gettimeofday LTP test failed on it ->
> announce that time is going backward.
> Simple returning only mb_tick_cnt pass this test but of course I am losing
> information about time till 1/HZ.
> Do I have to add any specific amount of time which take counting of it?
You do not neeed 64 bit values. The return value is masked with the
clocksource->mask anyway. So when your clocksource has less than 64
bits it's covered.
So if your timer counts down from 0xFFFFFFFF to 0 and wraps around you
just need to return (cycle_t) ~(timer->count);
But I think I know where your real problem is. You use the same timer
for both timekeeping and the periodic tick. That's why you can not
support one shot mode. I bet the machine has two timers.
So the best way to handle this is:
Use timer A in free running mode - up or down counting does not
matter - for the timekeeping. That way you have an ever increasing
monotonic time.
Use timer B either for periodic mode or for one shot and all your
problems are gone. In periodic mode use autoreload and in one shot
mode just follow the instructions of the generic code via the
timer_set_next_event() function.
> And the second question is about shift and rating values.
> I wrote one message in past http://lkml.org/lkml/2009/1/11/291
> Here is the important of part of that message.
>
> ...
>
> And the second part is about shift and rating values. Rating is
> describe(linux/clocksource.h) and seems to me that should be
> corresponded with CONFIG_HZ value,right?
> And I found any explanation of shift value -> max value for equation
> (2-5) * freq << shift / NSEC_PER_SEC should be for my case still 32bit
> number, where (2-5s) are because of NTP
@John, can you explain the shift vlaue please ?
> The second thing which seems to me weird in comparing with others log I
> have seen is .resolution value. Full (proc/timer_lists is below) My
> .resolution: 10000000 nsecs which
> is 1/HZ in nsec. (On others log I saw 1nsec values). My the lowest
> resolution is 1/freq = 8nsec (for 125MHz). Is that OK or not.
> ...
The 1ns is theoretical and indicates that the kernel has high resolution
timer support. Your resolution is just HZ.
> >
> >> +static int microblaze_timer_set_next_event(unsigned long delta,
> >> + struct clock_event_device *dev)
> >> +{
> >> + printk(KERN_INFO "next event, delta %x, %d\n", (u32)delta, (u32)delta);
> >
> > This should be pr_debug() or do you want to flood the syslog in
> > every timer interrupt ?
>
> This not flood the syslog. I don't know why (maybe because of missing ONESHOT)
> but this code is never called in periodic mode. But you are right if this
> function is called a lot it is necessary to use pr_debug -> but this is not my
> case in this implementation.
Well. Either you have one shot mode, then better make it work and
useable or just remove the one shot support until you figure out how
to do it.
> >
> >> + microblaze_timer_start(delta);
> >> + return 0;
> >> +}
> >> +
> >> +static void microblaze_timer_set_mode(enum clock_event_mode mode,
> >> + struct clock_event_device *evt)
> >> +{
> >> + microblaze_timer_stop();
> >> +
> >> + switch (mode) {
> >> + case CLOCK_EVT_MODE_PERIODIC:
> >> + printk(KERN_INFO "%s: periodic\n", __func__);
> >
> > pr_debug as well. That's not very informative
>
> It is only information that timer work in periodic mode.
>
> Part of kernel log which is there - nothing more.
>
> microblaze_timer_set_mode: shutdown
> microblaze_timer_set_mode: periodic
Nothing a normal user is interested in I guess, but ok.
> >> +static irqreturn_t timer_interrupt(int irq, void *dev_id)
> >> +{
> >> + struct clock_event_device *evt = &clockevent_microblaze_timer;
> >> +#ifdef CONFIG_HEART_BEAT
> >> + heartbeat();
> >> +#endif
> >> + timer_ack();
> >> +
> >> + mb_tick_cnt += cpuinfo.freq_div_hz;
> >
> > Hmm. How does that work with oneshot timers ?
>
> Oneshot is not supported yet - only periodic mode. I had to add it mb_tick_cnt
> counting because
> I don't know reason but without it ( kernel and timer in periodic mode )not
> update system time.
I don't know how that timer works. Do you have a pointer to hardware
docs + chapter reference ?
> >> + xtime.tv_sec = mktime(2007, 1, 1, 0, 0, 0);
> >> + xtime.tv_nsec = 0;
> >> + set_normalized_timespec(&wall_to_monotonic,
> >> + -xtime.tv_sec, -xtime.tv_nsec);
> >
> > Yuck. What's that ? wall_to_monotonic is maintained by the generic
> > code.
>
> I take this part of code from arch/blackfin/kernel/time-ts.c:217-219.
> arch/x86/xen/time.c use it too. And arch/arm/kernel/time.c use similar
> implemetation.
Right. All of them are similar nonsense. If we want a 1/1/2007 base
date if there is no RTC which tells us the real date/time then we
should do this in the generic code and not implement 10 variations all
over the place.
tglx
On Thu, 2009-03-19 at 22:47 +0100, Thomas Gleixner wrote:
> On Thu, 19 Mar 2009, Michal Simek wrote:
> > And the second question is about shift and rating values.
> > I wrote one message in past http://lkml.org/lkml/2009/1/11/291
> > Here is the important of part of that message.
> >
> > ...
> >
> > And the second part is about shift and rating values. Rating is
> > describe(linux/clocksource.h) and seems to me that should be
> > corresponded with CONFIG_HZ value,right?
Not sure where the idea of correspondence w/ CONFIG_HZ came from. The
rating value just provides a relative ordering of preferences between
possible clocksources. Since different hardware may have a number of
different clocksources available, we just need to have a method of
selecting a preferred clocksource, and the rating value is used for
that.
The guide in linux/clocksource.h is just a guide. Most arches, which
only have one or two clocksource options probably won't need much care,
and a rating of 200 or 300 will probably suffice. Or if there really
isn't any option about it and there is only one which is a must-use
clocksource, 400.
> > And I found any explanation of shift value -> max value for equation
> > (2-5) * freq << shift / NSEC_PER_SEC should be for my case still 32bit
> > number, where (2-5s) are because of NTP
>
> @John, can you explain the shift vlaue please ?
The shift value is a bit more difficult to explain. The algorithm you
describe above is used by sparc to generate shift, and I think it will
work, but may not be optimal.
This question comes up over and over, so I figured I should sit down and
really solve it.
Basically the constraint is you want to calculate a mult value using the
highest shift possible. However we have to be careful not to overflow
64bits when we multiply ~5second worth of cycles times the mult value.
So I finally put this down into code and here it is. No promises that it
is 100% right, but from my simple test examples it worked ok.
Let me know if it helps.
thanks
-john
Add helper functions to calculate ideal clocksource shift values given
its frequency (either hz or khz). Lightly tested, use with care.
Also fixes a few old-old-old timesource (well, timsource) references my
find and replace attempts failed on.
Signed-off-by: John Stultz <[email protected]>
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index f88d32f..9ef062d 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -116,7 +116,7 @@ extern struct clocksource *clock; /* current clocksource */
* @khz: Clocksource frequency in KHz
* @shift_constant: Clocksource shift factor
*
- * Helper functions that converts a khz counter frequency to a timsource
+ * Helper functions that converts a khz counter frequency to a clocksource
* multiplier, given the clocksource shift value
*/
static inline u32 clocksource_khz2mult(u32 khz, u32 shift_constant)
@@ -142,7 +142,7 @@ static inline u32 clocksource_khz2mult(u32 khz, u32 shift_constant)
* @shift_constant: Clocksource shift factor
*
* Helper functions that converts a hz counter
- * frequency to a timsource multiplier, given the
+ * frequency to a clocksource multiplier, given the
* clocksource shift value
*/
static inline u32 clocksource_hz2mult(u32 hz, u32 shift_constant)
@@ -162,6 +162,10 @@ static inline u32 clocksource_hz2mult(u32 hz, u32 shift_constant)
return (u32)tmp;
}
+extern u32 clocksource_khz2shift(u32 freq_khz);
+extern u32 clocksource_hz2shift(u32 freq_hz);
+
+
/**
* clocksource_read: - Access the clocksource's current cycle value
* @cs: pointer to clocksource being read
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index ca89e15..0a2538d 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -212,6 +212,83 @@ static void clocksource_check_watchdog(struct clocksource *cs)
static inline void clocksource_resume_watchdog(void) { }
#endif
+
+/* Maximum seconds worth of cycles we consider valid */
+#define MAX_SEC_OF_CYCLES 5ULL
+
+/**
+ * clocksource_khz2shift - calculates shift from khz
+ * @freq_khz: Clocksource frequency in KHz
+ *
+ * Helper functions that converts a khz counter
+ * frequency to a clocksource shift.
+ */
+u32 clocksource_khz2shift(u32 freq_khz)
+{
+ s32 shift = 32;
+ u32 mult;
+
+ while (1) {
+ s64 tmp;
+ u64 cycles;
+ mult = clocksource_khz2mult(freq_khz, shift);
+
+ cycles = (u64)freq_khz*1000*MAX_SEC_OF_CYCLES;
+ tmp = (cycles * mult) >> shift;
+
+ tmp = (MAX_SEC_OF_CYCLES*NSEC_PER_SEC) - tmp;
+ if (tmp < 0)
+ tmp = -tmp;
+
+ /* if we are witin one mult unit, we're good */
+ if (tmp < cycles>>shift)
+ break;
+
+ shift--;
+ if (shift < 1)
+ BUG();
+ }
+ return shift;
+}
+
+/**
+ * clocksource_hz2shift - calculates shift from hz
+ * @freq_hz: Clocksource frequency in Hz
+ *
+ * Helper functions that converts a hz counter
+ * frequency to a clocksource shift.
+ */
+
+u32 clocksource_hz2shift(u32 freq_hz)
+{
+ s32 shift = 32;
+ u32 mult;
+
+ while (1) {
+ s64 tmp;
+ u64 cycles;
+ mult = clocksource_hz2mult(freq_hz, shift);
+
+ cycles = (u64)freq_hz*MAX_SEC_OF_CYCLES;
+ tmp = (cycles * mult) >> shift;
+
+ tmp = MAX_SEC_OF_CYCLES*NSEC_PER_SEC - tmp;
+ if (tmp < 0)
+ tmp = -tmp;
+
+ /* if we are witin one mult unit, we're good */
+ if (tmp < cycles>>shift)
+ break;
+
+ shift--;
+ if (shift < 1)
+ BUG();
+ }
+ return shift;
+}
+
+
+
/**
* clocksource_resume - resume the clocksource(s)
*/
Hi Thomas,
> Michal,
>
> On Thu, 19 Mar 2009, Michal Simek wrote:
>>>> + __do_IRQ(irq);
>>> You use irq chips now and you set the type handlers (edge/level), but
>>> you still call __do_IRQ() the all in one fits nothing handler, which
>>> is going to be deprecated and removed.
>> I know about.
>>> Please call
>>> generic_handle_irq(irq);
>>>
>>> which will call the correct flow handlers.
>> I would like to use it but don't work with edge interrupt.
>> __do_IRQ handle it in right way.
>>
>> I used this implementation but I did some change edge/level handling and I can't
>> use it.
>> http://developer.petalogix.com/git/gitweb.cgi?p=linux-2.6-microblaze.git;a=blob_plain;f=arch/microblaze/kernel/irq.c;hb=3645d887ad6443a262bbeddf384038321172db2b
>>
>> Any hints what could be wrong?
>
> Look at the different handling schemes of __do_IRQ and handle_edge_irq
> vs. the chip functions:
>
> __do_IRQ() does:
> {
> chip->ack();
>
> handle_IRQ_event();
>
> chip->end();
> }
>
> handle_edge_irq() does:
> {
> if ((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) ||
> !desc->action)) {
> desc->status |= (IRQ_PENDING | IRQ_MASKED);
> mask_ack_irq(desc, irq);
> goto out_unlock;
> }
>
> chip->ack();
> handle_IRQ_event();
>
> }
>
> I guess the problem is in your chip->xxx functions.
OK. I look at it in detail.
>
>> First of all I have one question to you about MB timer.c.
>> It is about this function - microblaze_read.
>>
>> static cycle_t mb_tick_cnt; /* store counter ticks */
>>
>> static cycle_t microblaze_read(void)
>> {
>> u64 temp = (u64)mb_tick_cnt + (u64)((u32)cpuinfo.freq_div_hz
>> - (u32)in_be32(TIMER_BASE + TCR0));
>> return temp;
>> }
>>
>>
>> MB has 32bit periodic down counter and I need to use u64 value that's why
>> I do these operation above. cpuinfo.freq_div_hz store freq/HZ value - number of
>> ticks for 1/HZ. I subtract current timer value + mb_tick_cnt which store number
>> of count. The problem I have is that gettimeofday LTP test failed on it ->
>> announce that time is going backward.
>> Simple returning only mb_tick_cnt pass this test but of course I am losing
>> information about time till 1/HZ.
>> Do I have to add any specific amount of time which take counting of it?
>
> You do not neeed 64 bit values. The return value is masked with the
> clocksource->mask anyway. So when your clocksource has less than 64
> bits it's covered.
>
> So if your timer counts down from 0xFFFFFFFF to 0 and wraps around you
> just need to return (cycle_t) ~(timer->count);
Counts down from specific value to 0. That specific value and number of tick for
1/HZ. That mean that I need (cycle_t) (specific_value - timer->count)
>
> But I think I know where your real problem is. You use the same timer
> for both timekeeping and the periodic tick. That's why you can not
> support one shot mode. I bet the machine has two timers.
yes. I have no problem to use another counter too. It is FPGA and my timer IP
support two independent timers. ( Her is the link to doc
http://www.xilinx.com/support/documentation/ip_documentation/xps_timer.pdf)
>
> So the best way to handle this is:
>
> Use timer A in free running mode - up or down counting does not
> matter - for the timekeeping. That way you have an ever increasing
> monotonic time.
>
> Use timer B either for periodic mode or for one shot and all your
> problems are gone. In periodic mode use autoreload and in one shot
> mode just follow the instructions of the generic code via the
> timer_set_next_event() function.
OK. That mean you timer A as clocksource and the second clock as event device.
I try to do it.
>
>> And the second question is about shift and rating values.
>> I wrote one message in past http://lkml.org/lkml/2009/1/11/291
>> Here is the important of part of that message.
>>
>> ...
>>
>> And the second part is about shift and rating values. Rating is
>> describe(linux/clocksource.h) and seems to me that should be
>> corresponded with CONFIG_HZ value,right?
>> And I found any explanation of shift value -> max value for equation
>> (2-5) * freq << shift / NSEC_PER_SEC should be for my case still 32bit
>> number, where (2-5s) are because of NTP
>
> @John, can you explain the shift vlaue please ?
>
>> The second thing which seems to me weird in comparing with others log I
>> have seen is .resolution value. Full (proc/timer_lists is below) My
>> .resolution: 10000000 nsecs which
>> is 1/HZ in nsec. (On others log I saw 1nsec values). My the lowest
>> resolution is 1/freq = 8nsec (for 125MHz). Is that OK or not.
>> ...
>
> The 1ns is theoretical and indicates that the kernel has high resolution
> timer support. Your resolution is just HZ.
>
>>>> +static int microblaze_timer_set_next_event(unsigned long delta,
>>>> + struct clock_event_device *dev)
>>>> +{
>>>> + printk(KERN_INFO "next event, delta %x, %d\n", (u32)delta, (u32)delta);
>>> This should be pr_debug() or do you want to flood the syslog in
>>> every timer interrupt ?
>> This not flood the syslog. I don't know why (maybe because of missing ONESHOT)
>> but this code is never called in periodic mode. But you are right if this
>> function is called a lot it is necessary to use pr_debug -> but this is not my
>> case in this implementation.
>
> Well. Either you have one shot mode, then better make it work and
> useable or just remove the one shot support until you figure out how
> to do it.
I don't have it - this feature is not there. There is only printk message in
set_mode function.
What is the best timer implementation in kernel? (For inspiration)
>
>>>> + microblaze_timer_start(delta);
>>>> + return 0;
>>>> +}
>>>> +
>>>> +static void microblaze_timer_set_mode(enum clock_event_mode mode,
>>>> + struct clock_event_device *evt)
>>>> +{
>>>> + microblaze_timer_stop();
>>>> +
>>>> + switch (mode) {
>>>> + case CLOCK_EVT_MODE_PERIODIC:
>>>> + printk(KERN_INFO "%s: periodic\n", __func__);
>>> pr_debug as well. That's not very informative
>> It is only information that timer work in periodic mode.
>>
>> Part of kernel log which is there - nothing more.
>>
>> microblaze_timer_set_mode: shutdown
>> microblaze_timer_set_mode: periodic
>
> Nothing a normal user is interested in I guess, but ok.
ok
>
>>>> +static irqreturn_t timer_interrupt(int irq, void *dev_id)
>>>> +{
>>>> + struct clock_event_device *evt = &clockevent_microblaze_timer;
>>>> +#ifdef CONFIG_HEART_BEAT
>>>> + heartbeat();
>>>> +#endif
>>>> + timer_ack();
>>>> +
>>>> + mb_tick_cnt += cpuinfo.freq_div_hz;
>>> Hmm. How does that work with oneshot timers ?
>> Oneshot is not supported yet - only periodic mode. I had to add it mb_tick_cnt
>> counting because
>> I don't know reason but without it ( kernel and timer in periodic mode )not
>> update system time.
>
> I don't know how that timer works. Do you have a pointer to hardware
> docs + chapter reference ?
Look at link above. Look at programming model chapter.
>
>>>> + xtime.tv_sec = mktime(2007, 1, 1, 0, 0, 0);
>>>> + xtime.tv_nsec = 0;
>>>> + set_normalized_timespec(&wall_to_monotonic,
>>>> + -xtime.tv_sec, -xtime.tv_nsec);
>>> Yuck. What's that ? wall_to_monotonic is maintained by the generic
>>> code.
>> I take this part of code from arch/blackfin/kernel/time-ts.c:217-219.
>> arch/x86/xen/time.c use it too. And arch/arm/kernel/time.c use similar
>> implemetation.
>
> Right. All of them are similar nonsense. If we want a 1/1/2007 base
> date if there is no RTC which tells us the real date/time then we
> should do this in the generic code and not implement 10 variations all
> over the place.
I have no problem to start from 1970 and remove this part of code. Do nothing
important to me.
Thanks,
Michal
>
> tglx
--
Michal Simek, Ing. (M.Eng)
w: http://www.monstr.eu p: +42-0-721842854
Hi John S,
> On Thu, 2009-03-19 at 22:47 +0100, Thomas Gleixner wrote:
>> On Thu, 19 Mar 2009, Michal Simek wrote:
>>> And the second question is about shift and rating values.
>>> I wrote one message in past http://lkml.org/lkml/2009/1/11/291
>>> Here is the important of part of that message.
>>>
>>> ...
>>>
>>> And the second part is about shift and rating values. Rating is
>>> describe(linux/clocksource.h) and seems to me that should be
>>> corresponded with CONFIG_HZ value,right?
>
> Not sure where the idea of correspondence w/ CONFIG_HZ came from. The
> rating value just provides a relative ordering of preferences between
> possible clocksources. Since different hardware may have a number of
> different clocksources available, we just need to have a method of
> selecting a preferred clocksource, and the rating value is used for
> that.
>
> The guide in linux/clocksource.h is just a guide. Most arches, which
> only have one or two clocksource options probably won't need much care,
> and a rating of 200 or 300 will probably suffice. Or if there really
> isn't any option about it and there is only one which is a must-use
> clocksource, 400.
ok. That mean that for my case (only one clocksource) I should set rating to 400
- I have one clocksource and is perfect for me.
>
>
>>> And I found any explanation of shift value -> max value for equation
>>> (2-5) * freq << shift / NSEC_PER_SEC should be for my case still 32bit
>>> number, where (2-5s) are because of NTP
>> @John, can you explain the shift vlaue please ?
>
> The shift value is a bit more difficult to explain. The algorithm you
> describe above is used by sparc to generate shift, and I think it will
> work, but may not be optimal.
>
> This question comes up over and over, so I figured I should sit down and
> really solve it.
>
> Basically the constraint is you want to calculate a mult value using the
> highest shift possible. However we have to be careful not to overflow
> 64bits when we multiply ~5second worth of cycles times the mult value.
>
> So I finally put this down into code and here it is. No promises that it
> is 100% right, but from my simple test examples it worked ok.
OK. Please check my case of that value.
MB can run from 5Mhz till 150MHz I think.
I need generic approach that's why I have to calculate with max value (150MHz).
My timer can tick on that freq too. (There is no different time bases in HW).
I need to find out how many ticks takes ~5s.
150MHz means that I need for 1sec 150 000 000 timer ticks.
One tick takes 1/150MHz = ~6-7ns - in the best case I can recognize and set
6-7ns (this is only theoretical value because of overhead)
~5s takes 750 000 000 ticks = 0x2CB4 1780. And I have 32bit counter.
That my question is how big could be a shift of value above till overflow.
0x2CB4 1780 << shift not exceed 0xffff ffff ffff ffff.
Here is that table for my case
shift
0 = 0x2CB4 1780
1 = 0x5968 2F00
2 = 0xB2D0 5E00
3 = 0x1 65A0 BC00
4 = 0x2 CB41 7800
5 = 0x5 9682 F000
6 = 0xB 2D05 E000
7 = 0x16 5A0B C000
>From first value I can tell that I can shift that value with 32 + 3 => 35 is the
first shift with overflow 64bit. Am I right?
If yes, I haven't found that big value in any arch.
For example avr has shift 16, rating 50 (arch/avr32/kernel/time.c) (BTW: Sets
time from 2007 too)
And the next my question is about difference in clocksource and clock event
value. Situation is the same. Is it mean that I should set the same rating and
shift value for both. (It doesn't matter if I use one or two timer -> they are
the same).
And about high resolution timer. I can recognize in the best case ~6-7ns. That
mean that measuring values around 100-200ns make sense and should work. Could I
use it?
Thanks,
Michal
> Let me know if it helps.
>
> thanks
> -john
>
>
> Add helper functions to calculate ideal clocksource shift values given
> its frequency (either hz or khz). Lightly tested, use with care.
> Also fixes a few old-old-old timesource (well, timsource) references my
> find and replace attempts failed on.
>
> Signed-off-by: John Stultz <[email protected]>
>
> diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
> index f88d32f..9ef062d 100644
> --- a/include/linux/clocksource.h
> +++ b/include/linux/clocksource.h
> @@ -116,7 +116,7 @@ extern struct clocksource *clock; /* current clocksource */
> * @khz: Clocksource frequency in KHz
> * @shift_constant: Clocksource shift factor
> *
> - * Helper functions that converts a khz counter frequency to a timsource
> + * Helper functions that converts a khz counter frequency to a clocksource
> * multiplier, given the clocksource shift value
> */
> static inline u32 clocksource_khz2mult(u32 khz, u32 shift_constant)
> @@ -142,7 +142,7 @@ static inline u32 clocksource_khz2mult(u32 khz, u32 shift_constant)
> * @shift_constant: Clocksource shift factor
> *
> * Helper functions that converts a hz counter
> - * frequency to a timsource multiplier, given the
> + * frequency to a clocksource multiplier, given the
> * clocksource shift value
> */
> static inline u32 clocksource_hz2mult(u32 hz, u32 shift_constant)
> @@ -162,6 +162,10 @@ static inline u32 clocksource_hz2mult(u32 hz, u32 shift_constant)
> return (u32)tmp;
> }
>
> +extern u32 clocksource_khz2shift(u32 freq_khz);
> +extern u32 clocksource_hz2shift(u32 freq_hz);
> +
> +
> /**
> * clocksource_read: - Access the clocksource's current cycle value
> * @cs: pointer to clocksource being read
> diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
> index ca89e15..0a2538d 100644
> --- a/kernel/time/clocksource.c
> +++ b/kernel/time/clocksource.c
> @@ -212,6 +212,83 @@ static void clocksource_check_watchdog(struct clocksource *cs)
> static inline void clocksource_resume_watchdog(void) { }
> #endif
>
> +
> +/* Maximum seconds worth of cycles we consider valid */
> +#define MAX_SEC_OF_CYCLES 5ULL
> +
> +/**
> + * clocksource_khz2shift - calculates shift from khz
> + * @freq_khz: Clocksource frequency in KHz
> + *
> + * Helper functions that converts a khz counter
> + * frequency to a clocksource shift.
> + */
> +u32 clocksource_khz2shift(u32 freq_khz)
> +{
> + s32 shift = 32;
> + u32 mult;
> +
> + while (1) {
> + s64 tmp;
> + u64 cycles;
> + mult = clocksource_khz2mult(freq_khz, shift);
> +
> + cycles = (u64)freq_khz*1000*MAX_SEC_OF_CYCLES;
> + tmp = (cycles * mult) >> shift;
> +
> + tmp = (MAX_SEC_OF_CYCLES*NSEC_PER_SEC) - tmp;
> + if (tmp < 0)
> + tmp = -tmp;
> +
> + /* if we are witin one mult unit, we're good */
> + if (tmp < cycles>>shift)
> + break;
> +
> + shift--;
> + if (shift < 1)
> + BUG();
> + }
> + return shift;
> +}
> +
> +/**
> + * clocksource_hz2shift - calculates shift from hz
> + * @freq_hz: Clocksource frequency in Hz
> + *
> + * Helper functions that converts a hz counter
> + * frequency to a clocksource shift.
> + */
> +
> +u32 clocksource_hz2shift(u32 freq_hz)
> +{
> + s32 shift = 32;
> + u32 mult;
> +
> + while (1) {
> + s64 tmp;
> + u64 cycles;
> + mult = clocksource_hz2mult(freq_hz, shift);
> +
> + cycles = (u64)freq_hz*MAX_SEC_OF_CYCLES;
> + tmp = (cycles * mult) >> shift;
> +
> + tmp = MAX_SEC_OF_CYCLES*NSEC_PER_SEC - tmp;
> + if (tmp < 0)
> + tmp = -tmp;
> +
> + /* if we are witin one mult unit, we're good */
> + if (tmp < cycles>>shift)
> + break;
> +
> + shift--;
> + if (shift < 1)
> + BUG();
> + }
> + return shift;
> +}
> +
> +
> +
> /**
> * clocksource_resume - resume the clocksource(s)
> */
>
>
--
Michal Simek, Ing. (M.Eng)
w: http://www.monstr.eu p: +42-0-721842854
Thomas,
just one other question.
For me will be useful to use second timer which is inside timer IP core.
There are two timers with one interrupt line. And I can of course resolve which
counter cause it. That's no problem.
My question is about timer_irqaction where is dev_id. What should be there?
Point to clocksource structure or clockevent?
static struct irqaction timer_irqaction = {
.handler = timer_interrupt,
.flags = IRQF_DISABLED | IRQF_TIMER,
.name = "timer",
.dev_id = &clocksource_microblaze,
};
Thanks,
Michal
> Michal,
>
> On Thu, 19 Mar 2009, Michal Simek wrote:
>>>> + __do_IRQ(irq);
>>> You use irq chips now and you set the type handlers (edge/level), but
>>> you still call __do_IRQ() the all in one fits nothing handler, which
>>> is going to be deprecated and removed.
>> I know about.
>>> Please call
>>> generic_handle_irq(irq);
>>>
>>> which will call the correct flow handlers.
>> I would like to use it but don't work with edge interrupt.
>> __do_IRQ handle it in right way.
>>
>> I used this implementation but I did some change edge/level handling and I can't
>> use it.
>> http://developer.petalogix.com/git/gitweb.cgi?p=linux-2.6-microblaze.git;a=blob_plain;f=arch/microblaze/kernel/irq.c;hb=3645d887ad6443a262bbeddf384038321172db2b
>>
>> Any hints what could be wrong?
>
> Look at the different handling schemes of __do_IRQ and handle_edge_irq
> vs. the chip functions:
>
> __do_IRQ() does:
> {
> chip->ack();
>
> handle_IRQ_event();
>
> chip->end();
> }
>
> handle_edge_irq() does:
> {
> if ((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) ||
> !desc->action)) {
> desc->status |= (IRQ_PENDING | IRQ_MASKED);
> mask_ack_irq(desc, irq);
> goto out_unlock;
> }
>
> chip->ack();
> handle_IRQ_event();
>
> }
>
> I guess the problem is in your chip->xxx functions.
>
>> First of all I have one question to you about MB timer.c.
>> It is about this function - microblaze_read.
>>
>> static cycle_t mb_tick_cnt; /* store counter ticks */
>>
>> static cycle_t microblaze_read(void)
>> {
>> u64 temp = (u64)mb_tick_cnt + (u64)((u32)cpuinfo.freq_div_hz
>> - (u32)in_be32(TIMER_BASE + TCR0));
>> return temp;
>> }
>>
>>
>> MB has 32bit periodic down counter and I need to use u64 value that's why
>> I do these operation above. cpuinfo.freq_div_hz store freq/HZ value - number of
>> ticks for 1/HZ. I subtract current timer value + mb_tick_cnt which store number
>> of count. The problem I have is that gettimeofday LTP test failed on it ->
>> announce that time is going backward.
>> Simple returning only mb_tick_cnt pass this test but of course I am losing
>> information about time till 1/HZ.
>> Do I have to add any specific amount of time which take counting of it?
>
> You do not neeed 64 bit values. The return value is masked with the
> clocksource->mask anyway. So when your clocksource has less than 64
> bits it's covered.
>
> So if your timer counts down from 0xFFFFFFFF to 0 and wraps around you
> just need to return (cycle_t) ~(timer->count);
>
> But I think I know where your real problem is. You use the same timer
> for both timekeeping and the periodic tick. That's why you can not
> support one shot mode. I bet the machine has two timers.
>
> So the best way to handle this is:
>
> Use timer A in free running mode - up or down counting does not
> matter - for the timekeeping. That way you have an ever increasing
> monotonic time.
>
> Use timer B either for periodic mode or for one shot and all your
> problems are gone. In periodic mode use autoreload and in one shot
> mode just follow the instructions of the generic code via the
> timer_set_next_event() function.
>
>> And the second question is about shift and rating values.
>> I wrote one message in past http://lkml.org/lkml/2009/1/11/291
>> Here is the important of part of that message.
>>
>> ...
>>
>> And the second part is about shift and rating values. Rating is
>> describe(linux/clocksource.h) and seems to me that should be
>> corresponded with CONFIG_HZ value,right?
>> And I found any explanation of shift value -> max value for equation
>> (2-5) * freq << shift / NSEC_PER_SEC should be for my case still 32bit
>> number, where (2-5s) are because of NTP
>
> @John, can you explain the shift vlaue please ?
>
>> The second thing which seems to me weird in comparing with others log I
>> have seen is .resolution value. Full (proc/timer_lists is below) My
>> .resolution: 10000000 nsecs which
>> is 1/HZ in nsec. (On others log I saw 1nsec values). My the lowest
>> resolution is 1/freq = 8nsec (for 125MHz). Is that OK or not.
>> ...
>
> The 1ns is theoretical and indicates that the kernel has high resolution
> timer support. Your resolution is just HZ.
>
>>>> +static int microblaze_timer_set_next_event(unsigned long delta,
>>>> + struct clock_event_device *dev)
>>>> +{
>>>> + printk(KERN_INFO "next event, delta %x, %d\n", (u32)delta, (u32)delta);
>>> This should be pr_debug() or do you want to flood the syslog in
>>> every timer interrupt ?
>> This not flood the syslog. I don't know why (maybe because of missing ONESHOT)
>> but this code is never called in periodic mode. But you are right if this
>> function is called a lot it is necessary to use pr_debug -> but this is not my
>> case in this implementation.
>
> Well. Either you have one shot mode, then better make it work and
> useable or just remove the one shot support until you figure out how
> to do it.
>
>>>> + microblaze_timer_start(delta);
>>>> + return 0;
>>>> +}
>>>> +
>>>> +static void microblaze_timer_set_mode(enum clock_event_mode mode,
>>>> + struct clock_event_device *evt)
>>>> +{
>>>> + microblaze_timer_stop();
>>>> +
>>>> + switch (mode) {
>>>> + case CLOCK_EVT_MODE_PERIODIC:
>>>> + printk(KERN_INFO "%s: periodic\n", __func__);
>>> pr_debug as well. That's not very informative
>> It is only information that timer work in periodic mode.
>>
>> Part of kernel log which is there - nothing more.
>>
>> microblaze_timer_set_mode: shutdown
>> microblaze_timer_set_mode: periodic
>
> Nothing a normal user is interested in I guess, but ok.
>
>>>> +static irqreturn_t timer_interrupt(int irq, void *dev_id)
>>>> +{
>>>> + struct clock_event_device *evt = &clockevent_microblaze_timer;
>>>> +#ifdef CONFIG_HEART_BEAT
>>>> + heartbeat();
>>>> +#endif
>>>> + timer_ack();
>>>> +
>>>> + mb_tick_cnt += cpuinfo.freq_div_hz;
>>> Hmm. How does that work with oneshot timers ?
>> Oneshot is not supported yet - only periodic mode. I had to add it mb_tick_cnt
>> counting because
>> I don't know reason but without it ( kernel and timer in periodic mode )not
>> update system time.
>
> I don't know how that timer works. Do you have a pointer to hardware
> docs + chapter reference ?
>
>>>> + xtime.tv_sec = mktime(2007, 1, 1, 0, 0, 0);
>>>> + xtime.tv_nsec = 0;
>>>> + set_normalized_timespec(&wall_to_monotonic,
>>>> + -xtime.tv_sec, -xtime.tv_nsec);
>>> Yuck. What's that ? wall_to_monotonic is maintained by the generic
>>> code.
>> I take this part of code from arch/blackfin/kernel/time-ts.c:217-219.
>> arch/x86/xen/time.c use it too. And arch/arm/kernel/time.c use similar
>> implemetation.
>
> Right. All of them are similar nonsense. If we want a 1/1/2007 base
> date if there is no RTC which tells us the real date/time then we
> should do this in the generic code and not implement 10 variations all
> over the place.
>
> tglx
--
Michal Simek, Ing. (M.Eng)
w: http://www.monstr.eu p: +42-0-721842854
On Fri, 20 Mar 2009, Michal Simek wrote:
> Thomas,
>
> just one other question.
> For me will be useful to use second timer which is inside timer IP core.
> There are two timers with one interrupt line. And I can of course resolve which
> counter cause it. That's no problem.
>
> My question is about timer_irqaction where is dev_id. What should be there?
> Point to clocksource structure or clockevent?
>
> static struct irqaction timer_irqaction = {
> .handler = timer_interrupt,
> .flags = IRQF_DISABLED | IRQF_TIMER,
> .name = "timer",
> .dev_id = &clocksource_microblaze,
> };
The clockevent of course. It's the one which emits the interrupts.
Just for clarification. The clocksource is basically a counter to read
out the current time. Such a counter usually does not deliver
interrupts. It wraps at some point, but that is handled by the generic
time keeping code. If you setup the 32 bit counter to count up and let
it run free then the counter will wrap from 0xffffffff to 0. Nothing
you have to worry about. You just provide a function to read it.
The clockevent is the device which delivers either periodic or oneshot
interrupts. Sa you dont have to worry about the shared interrupt line
in that case.
Thanks,
tglx
On Fri, 20 Mar 2009, Michal Simek wrote:
> > Well. Either you have one shot mode, then better make it work and
> > useable or just remove the one shot support until you figure out how
> > to do it.
>
> I don't have it - this feature is not there. There is only printk message in
> set_mode function.
>
> What is the best timer implementation in kernel? (For inspiration)
There is no best :) All timers have usualy some weird hardware
constraints so that code is always ugly. But just as an example:
static int lapic_next_event(unsigned long delta, struct clock_event_device *evt)
{
apic_write(APIC_TMICT, delta);
return 0;
}
I think that's pretty close to your hardware. delta is the number of
timer cycles until the next event. There is no other magic with the
one shot mode :)
Thanks,
tglx
Hi Thomas,
> On Fri, 20 Mar 2009, Michal Simek wrote:
>
>> Thomas,
>>
>> just one other question.
>> For me will be useful to use second timer which is inside timer IP core.
>> There are two timers with one interrupt line. And I can of course resolve which
>> counter cause it. That's no problem.
>>
>> My question is about timer_irqaction where is dev_id. What should be there?
>> Point to clocksource structure or clockevent?
>>
>> static struct irqaction timer_irqaction = {
>> .handler = timer_interrupt,
>> .flags = IRQF_DISABLED | IRQF_TIMER,
>> .name = "timer",
>> .dev_id = &clocksource_microblaze,
>> };
>
> The clockevent of course. It's the one which emits the interrupts.
>
> Just for clarification. The clocksource is basically a counter to read
> out the current time. Such a counter usually does not deliver
> interrupts. It wraps at some point, but that is handled by the generic
> time keeping code. If you setup the 32 bit counter to count up and let
> it run free then the counter will wrap from 0xffffffff to 0. Nothing
> you have to worry about. You just provide a function to read it.
That's is crucial information which I haven't found.
>
> The clockevent is the device which delivers either periodic or oneshot
> interrupts. Sa you dont have to worry about the shared interrupt line
> in that case.
I have working implementation. I just need to clear some thing relate with HW -
some checking mechanism that two timer must be there + some selfmod test. I'll
send it soon and do some LTP test too but I believe that I clean that code. I
take a look at irq code too.
Below is timer_list log.
I can paste current my code but people don't like it attachment and in-line
code.I'll do regular one patch with git and send it.
Why is my .resolution: 10000000 nsecs? It seems to me weird.
I'll wait for John's answer for fixing shift and rating values too.
Thanks a lot,
Michal
>
> Thanks,
>
> tglx
# cat /proc/timer_list
Timer List Version: v0.4
HRTIMER_MAX_CLOCK_BASES: 2
now at 193684779856 nsecs
cpu: 0
clock 0:
.base: 902774d0
.index: 0
.resolution: 10000000 nsecs
.get_time: ktime_get_real
active timers:
clock 1:
.base: 902774f4
.index: 1
.resolution: 10000000 nsecs
.get_time: ktime_get
active timers:
#0: <9e2d3a48>, hrtimer_wakeup, S:01, <9e2d3a48>, inetd/54
# expires at 194110626631-194111626591 nsecs [in 425846775 to 426846735 nsecs]
#1: <9e0e5a48>, hrtimer_wakeup, S:01, <9e0e5a48>, thttpd/50
# expires at 249711205338-249811205338 nsecs [in 56026425482 to 56126425482 nsecs]
Tick Device: mode: 0
Per CPU device: 0
Clock Event Device: microblaze_clockevent
max_delta_ns: 2147483647
min_delta_ns: 1000
mult: 536870912
shift: 32
mode: 2
next_event: 2147483646999999999 nsecs
set_next_event: microblaze_timer_set_next_event
set_mode: microblaze_timer_set_mode
event_handler: tick_handle_periodic
# cat /proc/timer_list
Timer List Version: v0.4
HRTIMER_MAX_CLOCK_BASES: 2
now at 198714389017 nsecs
cpu: 0
clock 0:
.base: 902774d0
.index: 0
.resolution: 10000000 nsecs
.get_time: ktime_get_real
active timers:
clock 1:
.base: 902774f4
.index: 1
.resolution: 10000000 nsecs
.get_time: ktime_get
active timers:
#0: <9e2d3a48>, hrtimer_wakeup, S:01, <9e2d3a48>, inetd/54
# expires at 199160628442-199161628402 nsecs [in 446239425 to 447239385 nsecs]
#1: <9e0e5a48>, hrtimer_wakeup, S:01, <9e0e5a48>, thttpd/50
# expires at 249711205338-249811205338 nsecs [in 50996816321 to 51096816321 nsecs]
Tick Device: mode: 0
Per CPU device: 0
Clock Event Device: microblaze_clockevent
max_delta_ns: 2147483647
min_delta_ns: 1000
mult: 536870912
shift: 32
mode: 2
next_event: 2147483646999999999 nsecs
set_next_event: microblaze_timer_set_next_event
set_mode: microblaze_timer_set_mode
event_handler: tick_handle_periodic
#
On Fri, 20 Mar 2009, Michal Simek wrote:
> Why is my .resolution: 10000000 nsecs? It seems to me weird.
Well. The resulution there is the granularity which the kernel uses to
expire application timers. Once the kernel switches to high resolution
mode it sets the granularity to 1ns.
To get high resolution mode you need two things:
1) a suitable clocksource - which needs to have the
CLOCK_SOURCE_IS_CONTINUOUS flag set
2) a clock event device which has CLOCK_EVT_FEAT_PERIODIC flag set.
3) CONFIG_HIGH_RES_TIMERS=y
Thanks,
tglx
Thomas Gleixner wrote:
> On Fri, 20 Mar 2009, Michal Simek wrote:
>> Why is my .resolution: 10000000 nsecs? It seems to me weird.
>
> Well. The resulution there is the granularity which the kernel uses to
> expire application timers. Once the kernel switches to high resolution
> mode it sets the granularity to 1ns.
>
> To get high resolution mode you need two things:
>
> 1) a suitable clocksource - which needs to have the
> CLOCK_SOURCE_IS_CONTINUOUS flag set
>
> 2) a clock event device which has CLOCK_EVT_FEAT_PERIODIC flag set.
You meant ONESHOT feature, right?
> 3) CONFIG_HIGH_RES_TIMERS=y
Below are kernel logs which I am getting.
Thanks,
Michal
> Thanks,
>
> tglx
Here is .config fragment
#
# Processor type and features
#
CONFIG_TICK_ONESHOT=y
# CONFIG_NO_HZ is not set
CONFIG_HIGH_RES_TIMERS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
CONFIG_HZ_100=y
# CONFIG_HZ_250 is not set
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=100
CONFIG_SCHED_HRTICK=y
Only Periodic mode
early_printk_console is enabled at 0x84000000
Ramdisk addr 0x90c80040, FDT 0x90780000
Found romfs @ 0x90c80040 (0x001bf000)
#### klimit 902f5000 ####
Moving 0x001bf000 bytes from 0x90c80040 to 0x902f42a8
New klimit: 0x904b4000
Found FDT at 0x90780000
Linux version 2.6.29-rc8-00471-g965e2a5-dirty ([email protected]) (gcc version
3.4.1 ( PetaLinux 0.20 Build -rc1 050607 )) #46 Fri Mar 20 12:20:22 CET 2009
setup_cpuinfo: initialising
setup_cpuinfo: Using full CPU PVR support
setup_memory: Main mem: 0x90000000-0xa0000000, size 0x10000000
setup_memory: kernel addr=0x90000000-0x904b4000 size=0x004b4000
setup_memory: max_mapnr: 0x10000
setup_memory: min_low_pfn: 0x90000
setup_memory: max_low_pfn: 0xa0000
On node 0 totalpages: 65536
free_area_init_node: node 0, pgdat 902842f0, node_mem_map 904b4000
Normal zone: 512 pages used for memmap
Normal zone: 0 pages reserved
Normal zone: 65024 pages, LIFO batch:15
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 65024
Kernel command line: console=ttyUL0,115200 highres=on
xlnx,xps-intc-1.00.a #0 at 0x81800000, num_irq=9, edge=0x100
PID hash table entries: 1024 (order: 10, 4096 bytes)
xlnx,xps-timer-1.00.a #0 at 0x83c00000, irq=3
Heartbeat GPIO at 0x81400000
microblaze_timer_set_mode: shutdown
microblaze_timer_set_mode: periodic
periodic mode
--------------------------------------------------------------------------------------
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
Memory: 254848k/262144k available
ODEBUG: selftest passed
Calibrating delay loop... 61.64 BogoMIPS (lpj=308224)
Mount-cache hash table entries: 512
net_namespace: 544 bytes
NET: Registered protocol family 16
bio: create slab <bio-0> at 0
NET: Registered protocol family 2
IP route cache hash table entries: 2048 (order: 1, 8192 bytes)
TCP established hash table entries: 8192 (order: 4, 65536 bytes)
TCP bind hash table entries: 8192 (order: 3, 32768 bytes)
TCP: Hash tables configured (established 8192 bind 8192)
TCP reno registered
NET: Registered protocol family 1
msgmni has been set to 498
io scheduler noop registered
io scheduler anticipatory registered
io scheduler deadline registered
io scheduler cfq registered (default)
84000000.serial: ttyUL0 at MMIO 0x84000003 (irq = 8) is a uartlite
console [ttyUL0] enabled
brd: module loaded
nbd: registered device at major 43
uclinux[mtd]: RAM probe address=0x902f42a8 size=0x1bf000
Creating 1 MTD partitions on "RAM":
0x000000000000-0x0000001bf000 : "ROMfs"
uclinux[mtd]: set ROMfs to be root filesystem index=0
TCP cubic registered
NET: Registered protocol family 17
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
VFS: Mounted root (romfs filesystem) readonly on device 31:0.
Freeing unused kernel memory: 96k freed
Mounting proc:
Mounting var:
Populating /var:
Running local start scripts.
Mounting /etc/config:
Populating /etc/config:
flatfsd: Nonexistent or bad flatfs (-48), creating new one...
flatfsd: Failed to write flatfs (-48): No such device
flatfsd: Created 6 configuration files (310 bytes)
Mounting sysfs:
Setting hostname:
Setting up interface lo:
Setting up interface eth0:
SIOCSIFADDR: No such device
Starting thttpd:
uclinux login: root
Password:
# cat /proc/timer_list
Timer List Version: v0.4
HRTIMER_MAX_CLOCK_BASES: 2
now at 21135463800 nsecs
cpu: 0
clock 0:
.base: 9027a4d0
.index: 0
.resolution: 10000000 nsecs
.get_time: ktime_get_real
.offset: 0 nsecs
active timers:
clock 1:
.base: 9027a4fc
.index: 1
.resolution: 10000000 nsecs
.get_time: ktime_get
.offset: 0 nsecs
active timers:
#0: <9f2d3a48>, hrtimer_wakeup, S:01, <9f2d3a48>, inetd/54
# expires at 21380356677-21381356634 nsecs [in 244892877 to 245892834 nsecs]
#1: <9e127a48>, hrtimer_wakeup, S:01, <9e127a48>, thttpd/50
# expires at 129627877707-129727877707 nsecs [in 108492413907 to 108592413907
nsecs]
.expires_next : 2147483646999999999 nsecs
.hres_active : 0
.nr_events : 0
.nohz_mode : 0
.idle_tick : 0 nsecs
.tick_stopped : 0
.idle_jiffies : 0
.idle_calls : 0
.idle_sleeps : 0
.idle_entrytime : 0 nsecs
.idle_waketime : 0 nsecs
.idle_exittime : 0 nsecs
.idle_sleeptime : 0 nsecs
.last_jiffies : 0
.next_jiffies : 0
.idle_expires : 0 nsecs
jiffies: 4294939392
Tick Device: mode: 0
Per CPU device: 0
Clock Event Device: microblaze_clockevent
max_delta_ns: 2147483647
min_delta_ns: 1000
mult: 536870912
shift: 32
mode: 2
next_event: 2147483646999999999 nsecs
set_next_event: microblaze_timer_set_next_event
set_mode: microblaze_timer_set_mode
event_handler: tick_handle_periodic
#
--------------------------------------------------------------------------------------
only shot mode
early_printk_console is enabled at 0x84000000
Ramdisk addr 0x90c80040, FDT 0x90780000
Found romfs @ 0x90c80040 (0x001bf000)
#### klimit 902f5000 ####
Moving 0x001bf000 bytes from 0x90c80040 to 0x902f42a8
New klimit: 0x904b4000
Found FDT at 0x90780000
Linux version 2.6.29-rc8-00471-g965e2a5-dirty ([email protected]) (gcc version
3.4.1 ( PetaLinux 0.20 Build -rc1 050607 )) #47 Fri Mar 20 12:23:08 CET 2009
setup_cpuinfo: initialising
setup_cpuinfo: Using full CPU PVR support
setup_memory: Main mem: 0x90000000-0xa0000000, size 0x10000000
setup_memory: kernel addr=0x90000000-0x904b4000 size=0x004b4000
setup_memory: max_mapnr: 0x10000
setup_memory: min_low_pfn: 0x90000
setup_memory: max_low_pfn: 0xa0000
On node 0 totalpages: 65536
free_area_init_node: node 0, pgdat 902842f0, node_mem_map 904b4000
Normal zone: 512 pages used for memmap
Normal zone: 0 pages reserved
Normal zone: 65024 pages, LIFO batch:15
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 65024
Kernel command line: console=ttyUL0,115200 highres=on
xlnx,xps-intc-1.00.a #0 at 0x81800000, num_irq=9, edge=0x100
PID hash table entries: 1024 (order: 10, 4096 bytes)
xlnx,xps-timer-1.00.a #0 at 0x83c00000, irq=3
Heartbeat GPIO at 0x81400000
microblaze_timer_set_mode: shutdown
microblaze_timer_set_mode: oneshot
one shot mode here
--------------------------------------------------------------------------------------
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
Memory: 254848k/262144k available
ODEBUG: selftest passed
Calibrating delay loop... 62.25 BogoMIPS (lpj=311296)
Mount-cache hash table entries: 512
net_namespace: 544 bytes
NET: Registered protocol family 16
bio: create slab <bio-0> at 0
Switched to high resolution mode on CPU 0
NET: Registered protocol family 2
IP route cache hash table entries: 2048 (order: 1, 8192 bytes)
TCP established hash table entries: 8192 (order: 4, 65536 bytes)
TCP bind hash table entries: 8192 (order: 3, 32768 bytes)
TCP: Hash tables configured (established 8192 bind 8192)
TCP reno registered
NET: Registered protocol family 1
msgmni has been set to 498
io scheduler noop registered
io scheduler anticipatory registered
io scheduler deadline registered
io scheduler cfq registered (default)
84000000.serial: ttyUL0 at MMIO 0x84000003 (irq = 8) is a uartlite
console [ttyUL0] enabled
brd: module loaded
nbd: registered device at major 43
uclinux[mtd]: RAM probe address=0x902f42a8 size=0x1bf000
Creating 1 MTD partitions on "RAM":
0x000000000000-0x0000001bf000 : "ROMfs"
uclinux[mtd]: set ROMfs to be root filesystem index=0
TCP cubic registered
NET: Registered protocol family 17
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
VFS: Mounted root (romfs filesystem) readonly on device 31:0.
Freeing unused kernel memory: 96k freed
Mounting proc:
Mounting var:
Populating /var:
Running local start scripts.
Mounting /etc/config:
Populating /etc/config:
flatfsd: Nonexistent or bad flatfs (-48), creating new one...
flatfsd: Failed to write flatfs (-48): No such device
flatfsd: Created 6 configuration files (310 bytes)
Mounting sysfs:
Setting hostname:
Setting up interface lo:
Setting up interface eth0:
SIOCSIFADDR: No such device
Starting thttpd:
uclinux login: root
Password:
# cat /proc/timer_list
Timer List Version: v0.4
HRTIMER_MAX_CLOCK_BASES: 2
now at 20996421657 nsecs
cpu: 0
clock 0:
.base: 9027a4d0
.index: 0
.resolution: 1 nsecs
.get_time: ktime_get_real
.offset: 0 nsecs
active timers:
clock 1:
.base: 9027a4fc
.index: 1
.resolution: 1 nsecs
.get_time: ktime_get
.offset: 0 nsecs
active timers:
#0: per_cpu__tick_cpu_sched, tick_sched_timer, S:01, <800005a6>, swapper/1
# expires at 21000000000-21000000000 nsecs [in 3578343 to 3578343 nsecs]
#1: <9f2d3a48>, hrtimer_wakeup, S:01, <9f2d3a48>, inetd/54
# expires at 21467819124-21468819081 nsecs [in 471397467 to 472397424 nsecs]
#2: <9e127a48>, hrtimer_wakeup, S:01, <9e127a48>, thttpd/50
# expires at 129753940928-129853940928 nsecs [in 108757519271 to 108857519271
nsecs]
.expires_next : 21000000000 nsecs
.hres_active : 1
.nr_events : 2011
.nohz_mode : 0
.idle_tick : 0 nsecs
.tick_stopped : 0
.idle_jiffies : 0
.idle_calls : 0
.idle_sleeps : 0
.idle_entrytime : 0 nsecs
.idle_waketime : 0 nsecs
.idle_exittime : 0 nsecs
.idle_sleeptime : 0 nsecs
.last_jiffies : 0
.next_jiffies : 0
.idle_expires : 0 nsecs
jiffies: 4294939395
Tick Device: mode: 1
Per CPU device: 0
Clock Event Device: microblaze_clockevent
max_delta_ns: 2147483647
min_delta_ns: 1000
mult: 536870912
shift: 32
mode: 3
next_event: 21000000000 nsecs
set_next_event: microblaze_timer_set_next_event
set_mode: microblaze_timer_set_mode
event_handler: hrtimer_interrupt
#
---------------------------------------------------------------------------------------------
both mode in features
early_printk_console is enabled at 0x84000000
Ramdisk addr 0x90c80040, FDT 0x90780000
Found romfs @ 0x90c80040 (0x001bf000)
#### klimit 902f5000 ####
Moving 0x001bf000 bytes from 0x90c80040 to 0x902f42a8
New klimit: 0x904b4000
Found FDT at 0x90780000
Linux version 2.6.29-rc8-00471-g965e2a5-dirty ([email protected]) (gcc version
3.4.1 ( PetaLinux 0.20 Build -rc1 050607 )) #48 Fri Mar 20 12:26:44 CET 2009
setup_cpuinfo: initialising
setup_cpuinfo: Using full CPU PVR support
setup_memory: Main mem: 0x90000000-0xa0000000, size 0x10000000
setup_memory: kernel addr=0x90000000-0x904b4000 size=0x004b4000
setup_memory: max_mapnr: 0x10000
setup_memory: min_low_pfn: 0x90000
setup_memory: max_low_pfn: 0xa0000
On node 0 totalpages: 65536
free_area_init_node: node 0, pgdat 902842f0, node_mem_map 904b4000
Normal zone: 512 pages used for memmap
Normal zone: 0 pages reserved
Normal zone: 65024 pages, LIFO batch:15
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 65024
Kernel command line: console=ttyUL0,115200 highres=on
xlnx,xps-intc-1.00.a #0 at 0x81800000, num_irq=9, edge=0x100
PID hash table entries: 1024 (order: 10, 4096 bytes)
xlnx,xps-timer-1.00.a #0 at 0x83c00000, irq=3
Heartbeat GPIO at 0x81400000
microblaze_timer_set_mode: shutdown
microblaze_timer_set_mode: periodic
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
Memory: 254848k/262144k available
ODEBUG: selftest passed
Calibrating delay loop... 61.64 BogoMIPS (lpj=308224)
Mount-cache hash table entries: 512
net_namespace: 544 bytes
NET: Registered protocol family 16
bio: create slab <bio-0> at 0
microblaze_timer_set_mode: oneshot
Switched to high resolution mode on CPU 0
NET: Registered protocol family 2
IP route cache hash table entries: 2048 (order: 1, 8192 bytes)
TCP established hash table entries: 8192 (order: 4, 65536 bytes)
TCP bind hash table entries: 8192 (order: 3, 32768 bytes)
TCP: Hash tables configured (established 8192 bind 8192)
TCP reno registered
NET: Registered protocol family 1
msgmni has been set to 498
io scheduler noop registered
io scheduler anticipatory registered
io scheduler deadline registered
io scheduler cfq registered (default)
84000000.serial: ttyUL0 at MMIO 0x84000003 (irq = 8) is a uartlite
console [ttyUL0] enabled
brd: module loaded
nbd: registered device at major 43
uclinux[mtd]: RAM probe address=0x902f42a8 size=0x1bf000
Creating 1 MTD partitions on "RAM":
0x000000000000-0x0000001bf000 : "ROMfs"
uclinux[mtd]: set ROMfs to be root filesystem index=0
TCP cubic registered
NET: Registered protocol family 17
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
VFS: Mounted root (romfs filesystem) readonly on device 31:0.
Freeing unused kernel memory: 96k freed
Mounting proc:
Mounting var:
Populating /var:
Running local start scripts.
Mounting /etc/config:
Populating /etc/config:
flatfsd: Nonexistent or bad flatfs (-48), creating new one...
flatfsd: Failed to write flatfs (-48): No such device
flatfsd: Created 6 configuration files (310 bytes)
Mounting sysfs:
Setting hostname:
Setting up interface lo:
Setting up interface eth0:
SIOCSIFADDR: No such device
Starting thttpd:
uclinux login: root
Password:
# cat /proc/timer_list
Timer List Version: v0.4
HRTIMER_MAX_CLOCK_BASES: 2
now at 17205889582 nsecs
cpu: 0
clock 0:
.base: 9027a4d0
.index: 0
.resolution: 1 nsecs
.get_time: ktime_get_real
.offset: 0 nsecs
active timers:
clock 1:
.base: 9027a4fc
.index: 1
.resolution: 1 nsecs
.get_time: ktime_get
.offset: 0 nsecs
active timers:
#0: per_cpu__tick_cpu_sched, tick_sched_timer, S:01, <800005a6>, swapper/1
# expires at 17210000000-17210000000 nsecs [in 4110418 to 4110418 nsecs]
#1: <9f2d3a48>, hrtimer_wakeup, S:01, <9f2d3a48>, inetd/54
# expires at 17430563969-17431563926 nsecs [in 224674387 to 225674344 nsecs]
#2: <9e127a48>, hrtimer_wakeup, S:01, <9e127a48>, thttpd/50
# expires at 129748538823-129848538823 nsecs [in 112542649241 to 112642649241
nsecs]
.expires_next : 17210000000 nsecs
.hres_active : 1
.nr_events : 1627
.nohz_mode : 0
.idle_tick : 0 nsecs
.tick_stopped : 0
.idle_jiffies : 0
.idle_calls : 0
.idle_sleeps : 0
.idle_entrytime : 0 nsecs
.idle_waketime : 0 nsecs
.idle_exittime : 0 nsecs
.idle_sleeptime : 0 nsecs
.last_jiffies : 0
.next_jiffies : 0
.idle_expires : 0 nsecs
jiffies: 4294939016
Tick Device: mode: 1
Per CPU device: 0
Clock Event Device: microblaze_clockevent
max_delta_ns: 2147483647
min_delta_ns: 1000
mult: 536870912
shift: 32
mode: 3
next_event: 17210000000 nsecs
set_next_event: microblaze_timer_set_next_event
set_mode: microblaze_timer_set_mode
event_handler: hrtimer_interrupt
#
On Fri, 20 Mar 2009, Michal Simek wrote:
> > 2) a clock event device which has CLOCK_EVT_FEAT_PERIODIC flag set.
>
> You meant ONESHOT feature, right?
Sure :)
> # cat /proc/timer_list
> Timer List Version: v0.4
> HRTIMER_MAX_CLOCK_BASES: 2
> now at 17205889582 nsecs
>
> cpu: 0
> clock 0:
> .base: 9027a4d0
> .index: 0
> .resolution: 1 nsecs
> .get_time: ktime_get_real
> .offset: 0 nsecs
> active timers:
> clock 1:
> .base: 9027a4fc
> .index: 1
> .resolution: 1 nsecs
> .get_time: ktime_get
> .offset: 0 nsecs
> active timers:
> #0: per_cpu__tick_cpu_sched, tick_sched_timer, S:01, <800005a6>, swapper/1
> # expires at 17210000000-17210000000 nsecs [in 4110418 to 4110418 nsecs]
> #1: <9f2d3a48>, hrtimer_wakeup, S:01, <9f2d3a48>, inetd/54
> # expires at 17430563969-17431563926 nsecs [in 224674387 to 225674344 nsecs]
> #2: <9e127a48>, hrtimer_wakeup, S:01, <9e127a48>, thttpd/50
> # expires at 129748538823-129848538823 nsecs [in 112542649241 to 112642649241
> nsecs]
> .expires_next : 17210000000 nsecs
> .hres_active : 1
Looks good. Now you can enable CONFIG_NOHZ as well. :) That needs just
the following extras in your idle loop:
--> tick_nohz_stop_sched_tick(1);
while (!need_resched())
idle();
--> tick_nohz_restart_sched_tick();
Thanks,
tglx
Thomas Gleixner wrote:
> On Fri, 20 Mar 2009, Michal Simek wrote:
>>> 2) a clock event device which has CLOCK_EVT_FEAT_PERIODIC flag set.
>> You meant ONESHOT feature, right?
>
> Sure :)
>
>> # cat /proc/timer_list
>> Timer List Version: v0.4
>> HRTIMER_MAX_CLOCK_BASES: 2
>> now at 17205889582 nsecs
>>
>> cpu: 0
>> clock 0:
>> .base: 9027a4d0
>> .index: 0
>> .resolution: 1 nsecs
>> .get_time: ktime_get_real
>> .offset: 0 nsecs
>> active timers:
>> clock 1:
>> .base: 9027a4fc
>> .index: 1
>> .resolution: 1 nsecs
>> .get_time: ktime_get
>> .offset: 0 nsecs
>> active timers:
>> #0: per_cpu__tick_cpu_sched, tick_sched_timer, S:01, <800005a6>, swapper/1
>> # expires at 17210000000-17210000000 nsecs [in 4110418 to 4110418 nsecs]
>> #1: <9f2d3a48>, hrtimer_wakeup, S:01, <9f2d3a48>, inetd/54
>> # expires at 17430563969-17431563926 nsecs [in 224674387 to 225674344 nsecs]
>> #2: <9e127a48>, hrtimer_wakeup, S:01, <9e127a48>, thttpd/50
>> # expires at 129748538823-129848538823 nsecs [in 112542649241 to 112642649241
>> nsecs]
>> .expires_next : 17210000000 nsecs
>> .hres_active : 1
>
> Looks good. Now you can enable CONFIG_NOHZ as well. :) That needs just
> the following extras in your idle loop:
>
> --> tick_nohz_stop_sched_tick(1);
> while (!need_resched())
> idle();
> --> tick_nohz_restart_sched_tick();
>
Yes, it is already in cpu_idle function. ->arch/microblaze/kernel/process.c file
Seems that work too. Look below. I am going to take a look at __do_IRQ issue.
Thanks,
Michal
> Thanks,
>
> tglx
early_printk_console is enabled at 0x84000000
Ramdisk addr 0x90c80040, FDT 0x90780000
Found romfs @ 0x90c80040 (0x001bf000)
#### klimit 902f7000 ####
Moving 0x001bf000 bytes from 0x90c80040 to 0x902f62ac
New klimit: 0x904b6000
Found FDT at 0x90780000
Linux version 2.6.29-rc8-00473-g1219507-dirty ([email protected]) (gcc version
3.4.1 ( PetaLinux 0.20 Build -rc1 050607 )) #51 Fri Mar 20 12:56:11 CET 2009
setup_cpuinfo: initialising
setup_cpuinfo: Using full CPU PVR support
setup_memory: Main mem: 0x90000000-0xa0000000, size 0x10000000
setup_memory: kernel addr=0x90000000-0x904b6000 size=0x004b6000
setup_memory: max_mapnr: 0x10000
setup_memory: min_low_pfn: 0x90000
setup_memory: max_low_pfn: 0xa0000
On node 0 totalpages: 65536
free_area_init_node: node 0, pgdat 902852f4, node_mem_map 904b6000
Normal zone: 512 pages used for memmap
Normal zone: 0 pages reserved
Normal zone: 65024 pages, LIFO batch:15
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 65024
Kernel command line: console=ttyUL0,115200 highres=on
xlnx,xps-intc-1.00.a #0 at 0x81800000, num_irq=9, edge=0x100
PID hash table entries: 1024 (order: 10, 4096 bytes)
xlnx,xps-timer-1.00.a #0 at 0x83c00000, irq=3
Heartbeat GPIO at 0x81400000
microblaze_timer_set_mode: shutdown
microblaze_timer_set_mode: periodic
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
Memory: 254848k/262144k available
ODEBUG: selftest passed
Calibrating delay loop... 61.44 BogoMIPS (lpj=307200)
Mount-cache hash table entries: 512
net_namespace: 544 bytes
NET: Registered protocol family 16
bio: create slab <bio-0> at 0
microblaze_timer_set_mode: oneshot
Switched to high resolution mode on CPU 0
NET: Registered protocol family 2
IP route cache hash table entries: 2048 (order: 1, 8192 bytes)
TCP established hash table entries: 8192 (order: 4, 65536 bytes)
TCP bind hash table entries: 8192 (order: 3, 32768 bytes)
TCP: Hash tables configured (established 8192 bind 8192)
TCP reno registered
NET: Registered protocol family 1
msgmni has been set to 498
io scheduler noop registered
io scheduler anticipatory registered
io scheduler deadline registered
io scheduler cfq registered (default)
84000000.serial: ttyUL0 at MMIO 0x84000003 (irq = 8) is a uartlite
console [ttyUL0] enabled
brd: module loaded
nbd: registered device at major 43
uclinux[mtd]: RAM probe address=0x902f62ac size=0x1bf000
Creating 1 MTD partitions on "RAM":
0x000000000000-0x0000001bf000 : "ROMfs"
uclinux[mtd]: set ROMfs to be root filesystem index=0
TCP cubic registered
NET: Registered protocol family 17
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
VFS: Mounted root (romfs filesystem) readonly on device 31:0.
Freeing unused kernel memory: 96k freed
Mounting proc:
Mounting var:
Populating /var:
Running local start scripts.
Mounting /etc/config:
Populating /etc/config:
flatfsd: Nonexistent or bad flatfs (-48), creating new one...
flatfsd: Failed to write flatfs (-48): No such device
flatfsd: Created 6 configuration files (310 bytes)
Mounting sysfs:
Setting hostname:
Setting up interface lo:
Setting up interface eth0:
SIOCSIFADDR: No such device
Starting thttpd:
uclinux login: root
Password:
# ls
bin dev etc home lib mnt proc sys tmp usr var
# uptime
00:00:19 up 0 min, load average: 0.21, 0.04, 0.01
# uptime
00:00:20 up 0 min, load average: 0.19, 0.04, 0.01
# uptime
00:00:21 up 0 min, load average: 0.19, 0.04, 0.01
# gunzip < /proc/config.gz
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.29-rc8
# Fri Mar 20 12:52:15 2009
#
CONFIG_MICROBLAZE=y
# CONFIG_SWAP is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_TIME=y
# CONFIG_GENERIC_TIME_VSYSCALL is not set
CONFIG_GENERIC_CLOCKEVENTS=y
# CONFIG_PCI is not set
# CONFIG_NO_DMA is not set
...
#
# Processor type and features
#
CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
CONFIG_HZ_100=y
# CONFIG_HZ_250 is not set
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=100
CONFIG_SCHED_HRTICK=y
Hi Thomas,
> On Thu, 19 Mar 2009, Michal Simek wrote:
>>>> + __do_IRQ(irq);
>>> You use irq chips now and you set the type handlers (edge/level), but
>>> you still call __do_IRQ() the all in one fits nothing handler, which
>>> is going to be deprecated and removed.
>> I know about.
>>> Please call
>>> generic_handle_irq(irq);
>>>
>>> which will call the correct flow handlers.
>> I would like to use it but don't work with edge interrupt.
>> __do_IRQ handle it in right way.
>>
>> I used this implementation but I did some change edge/level handling and I can't
>> use it.
>> http://developer.petalogix.com/git/gitweb.cgi?p=linux-2.6-microblaze.git;a=blob_plain;f=arch/microblaze/kernel/irq.c;hb=3645d887ad6443a262bbeddf384038321172db2b
>>
>> Any hints what could be wrong?
>
> Look at the different handling schemes of __do_IRQ and handle_edge_irq
> vs. the chip functions:
>
> __do_IRQ() does:
> {
> chip->ack();
>
> handle_IRQ_event();
>
> chip->end();
> }
>
> handle_edge_irq() does:
> {
> if ((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) ||
> !desc->action)) {
> desc->status |= (IRQ_PENDING | IRQ_MASKED);
> mask_ack_irq(desc, irq);
> goto out_unlock;
> }
>
> chip->ack();
> handle_IRQ_event();
>
> }
>
> I guess the problem is in your chip->xxx functions.
I fixed it. There were one additional line.
+ I set GENERIC_HARDIRQS_NO__DO_IRQ=y.
BTW: Below is full chip description where function enable is unmask
and disable is mask. Do I have keep there enable and disable function pointers?
I commented them and works without them too.
static struct irq_chip intc_dev = {
.name = "Xilinx INTC",
.enable = intc_enable_or_unmask,
.unmask = intc_enable_or_unmask,
.disable = intc_disable_or_mask,
.mask = intc_disable_or_mask,
.ack = intc_ack,
.mask_ack = intc_mask_ack,
.end = intc_end,
};
Thanks,
Michal
Michal,
On Fri, 20 Mar 2009, Michal Simek wrote:
> > I guess the problem is in your chip->xxx functions.
>
> I fixed it. There were one additional line.
> + I set GENERIC_HARDIRQS_NO__DO_IRQ=y.
Cool.
> BTW: Below is full chip description where function enable is unmask
> and disable is mask. Do I have keep there enable and disable function pointers?
> I commented them and works without them too.
Right. The generic code does:
if (!chip->enable)
chip->enable = default_enable;
if (!chip->disable)
chip->disable = default_disable;
Thanks,
tglx
Thomas,
> Michal,
>
> On Fri, 20 Mar 2009, Michal Simek wrote:
>>> I guess the problem is in your chip->xxx functions.
>> I fixed it. There were one additional line.
>> + I set GENERIC_HARDIRQS_NO__DO_IRQ=y.
>
> Cool.
:-)
NO_HZ works too. Here is the log.
# cat /proc/interrupts
CPU0
3: 3827 level INTC timer
8: 1834 edge INTC uartlite
# uptime
00:16:47 up 16 min, load average: 0.00, 0.00, 0.00
# uptime
00:17:53 up 17 min, load average: 0.00, 0.00, 0.00
# cat /proc/interrupts
CPU0
3: 4105 level INTC timer
8: 1913 edge INTC uartlite
# uptime
00:21:44 up 21 min, load average: 0.00, 0.00, 0.00
# cat /proc/interrupts
CPU0
3: 4615 level INTC timer
8: 1970 edge INTC uartlite
#
>
>> BTW: Below is full chip description where function enable is unmask
>> and disable is mask. Do I have keep there enable and disable function pointers?
>> I commented them and works without them too.
>
> Right. The generic code does:
>
> if (!chip->enable)
> chip->enable = default_enable;
> if (!chip->disable)
> chip->disable = default_disable;
I look at default implementation and seems to me that I can save some
instruction when I use my enable function not generic one and for disabling is
default function faster because do nothing.
I am going to send one email with full intc.c + 2 changes - one in irq.c and
second in Kconfig.
Thanks,
Michal
>
> Thanks,
>
> tglx
--
Michal Simek, Ing. (M.Eng)
w: http://www.monstr.eu p: +42-0-721842854
On Fri, 2009-03-20 at 08:27 +0100, Michal Simek wrote:
> Hi John S,
>
> > On Thu, 2009-03-19 at 22:47 +0100, Thomas Gleixner wrote:
> >> On Thu, 19 Mar 2009, Michal Simek wrote:
> >>> And the second question is about shift and rating values.
> >>> I wrote one message in past http://lkml.org/lkml/2009/1/11/291
> >>> Here is the important of part of that message.
> >>>
> >>> ...
> >>>
> >>> And the second part is about shift and rating values. Rating is
> >>> describe(linux/clocksource.h) and seems to me that should be
> >>> corresponded with CONFIG_HZ value,right?
> >
> > Not sure where the idea of correspondence w/ CONFIG_HZ came from. The
> > rating value just provides a relative ordering of preferences between
> > possible clocksources. Since different hardware may have a number of
> > different clocksources available, we just need to have a method of
> > selecting a preferred clocksource, and the rating value is used for
> > that.
> >
> > The guide in linux/clocksource.h is just a guide. Most arches, which
> > only have one or two clocksource options probably won't need much care,
> > and a rating of 200 or 300 will probably suffice. Or if there really
> > isn't any option about it and there is only one which is a must-use
> > clocksource, 400.
>
> ok. That mean that for my case (only one clocksource) I should set rating to 400
> - I have one clocksource and is perfect for me.
As long as there will never be another clocksource used on that
architecture, 400 is probably ok. Since its sometimes hard to tell, you
might want to pick a more moderate 300.
But again, its a relative scale and doesn't matter all that much, as
long as the right clocksource is always selected at boot for the
hardware.
> >>> And I found any explanation of shift value -> max value for equation
> >>> (2-5) * freq << shift / NSEC_PER_SEC should be for my case still 32bit
> >>> number, where (2-5s) are because of NTP
> >> @John, can you explain the shift vlaue please ?
> >
> > The shift value is a bit more difficult to explain. The algorithm you
> > describe above is used by sparc to generate shift, and I think it will
> > work, but may not be optimal.
> >
> > This question comes up over and over, so I figured I should sit down and
> > really solve it.
> >
> > Basically the constraint is you want to calculate a mult value using the
> > highest shift possible. However we have to be careful not to overflow
> > 64bits when we multiply ~5second worth of cycles times the mult value.
> >
> > So I finally put this down into code and here it is. No promises that it
> > is 100% right, but from my simple test examples it worked ok.
>
> OK. Please check my case of that value.
> MB can run from 5Mhz till 150MHz I think.
> I need generic approach that's why I have to calculate with max value (150MHz).
> My timer can tick on that freq too. (There is no different time bases in HW).
>
> I need to find out how many ticks takes ~5s.
> 150MHz means that I need for 1sec 150 000 000 timer ticks.
I think you mean counter cycles instead of timer ticks. Timer tick
terminology usually describes a timer based interrupt.
> One tick takes 1/150MHz = ~6-7ns - in the best case I can recognize and set
> 6-7ns (this is only theoretical value because of overhead)
>
> ~5s takes 750 000 000 ticks = 0x2CB4 1780. And I have 32bit counter.
>
> That my question is how big could be a shift of value above till overflow.
> 0x2CB4 1780 << shift not exceed 0xffff ffff ffff ffff.
Almost. Its not the shift that causes the problem right off, but the
resulting mult value calculated from a shift. Again, the key points are,
you want to make sure that:
1) that mult value for the given shift fits in 32 bits.
and
2) mult * 5sec of cycles doesn't overflow 64bits (really is only an
issue for very very fast counters that run faster then 1Ghz).
So let's follow my algorithm and start by picking a shift value of 32.
We calculate the mult, which would be (using clocksource_khz2mult()):
(1Million * 2^32) / 150,000 = 28633115307 which overflows 32bits.
BZZZZZZ.
1Million * 2^31 / 150,000 = 14316557653 (to big. BZZZZZZZ)
1Million * 2^30 / 150,000 = 7158278827 (to big. BZZZZZZZ)
1Million * 2^29 / 150,000 = 3579139413 (BING! it fits!)
Now the test:
(750000000 * 3579139413)>>29 ?= 5 seconds
2684354559750000000 (doesn't overflow!) >> 29
4999999999ns ?= 5seconds (within the error range, so we're good!)
Now take care, because the slower the clocksource, often the lower the
shift value we can use, because the nsecs per cycle value that mult
approximates is much larger.
So for 5mhz (using
1Million * 2^29 / 5,000 = 107374182400 (32bit overflow!)
...
1Million * 2^24 / 5,000 = 3355443200 (fits!)
Now the test:
(25000000 * 3355443200)>>24 ?= 5 seconds
83886080000000000 (doesn't overflow!) >> 24 ?=
5000000000ns ?= 5seconds (BING!)
So you can either dynamically calculate the best shift value for the
actual freq using the helper functions I provided, or just use 24 and be
safe, your pick.
> For example avr has shift 16, rating 50 (arch/avr32/kernel/time.c) (BTW: Sets
> time from 2007 too)
Most arches probably low ball the shift to be safe. Mainly because
explaining how to calculate the optimal shift was hard and there weren't
helper functions.
As an aside (feel free to ignore for the microblaze bits):
Some complexity may grow here as well, since 5 seconds of cycles may
prove too short as folks become more interested running w/ NOHZ and
avoiding interrupts for extreme lengths of time (I've heard 30
minutes!?). For those situations we will need lower shift values, since
30 minutes of cycles * a large mult value close to (1<<32) will likely
overflow 64bits. But that trades off how finely we can tweak the clock
steering. Probably converting folks to use the helper functions will be
the best approach, as it will allow us to configure that depending on
NOHZ or not.
thanks
-john
Hi John,
> On Fri, 2009-03-20 at 08:27 +0100, Michal Simek wrote:
>> Hi John S,
>>
>>> On Thu, 2009-03-19 at 22:47 +0100, Thomas Gleixner wrote:
>>>> On Thu, 19 Mar 2009, Michal Simek wrote:
>>>>> And the second question is about shift and rating values.
>>>>> I wrote one message in past http://lkml.org/lkml/2009/1/11/291
>>>>> Here is the important of part of that message.
>>>>>
>>>>> ...
>>>>>
>>>>> And the second part is about shift and rating values. Rating is
>>>>> describe(linux/clocksource.h) and seems to me that should be
>>>>> corresponded with CONFIG_HZ value,right?
>>> Not sure where the idea of correspondence w/ CONFIG_HZ came from. The
>>> rating value just provides a relative ordering of preferences between
>>> possible clocksources. Since different hardware may have a number of
>>> different clocksources available, we just need to have a method of
>>> selecting a preferred clocksource, and the rating value is used for
>>> that.
>>>
>>> The guide in linux/clocksource.h is just a guide. Most arches, which
>>> only have one or two clocksource options probably won't need much care,
>>> and a rating of 200 or 300 will probably suffice. Or if there really
>>> isn't any option about it and there is only one which is a must-use
>>> clocksource, 400.
>> ok. That mean that for my case (only one clocksource) I should set rating to 400
>> - I have one clocksource and is perfect for me.
>
> As long as there will never be another clocksource used on that
> architecture, 400 is probably ok. Since its sometimes hard to tell, you
> might want to pick a more moderate 300.
>
> But again, its a relative scale and doesn't matter all that much, as
> long as the right clocksource is always selected at boot for the
> hardware.
OK that mean that rating do the same work for clockevent sources too, right?
>
>
>>>>> And I found any explanation of shift value -> max value for equation
>>>>> (2-5) * freq << shift / NSEC_PER_SEC should be for my case still 32bit
>>>>> number, where (2-5s) are because of NTP
>>>> @John, can you explain the shift vlaue please ?
>>> The shift value is a bit more difficult to explain. The algorithm you
>>> describe above is used by sparc to generate shift, and I think it will
>>> work, but may not be optimal.
>>>
>>> This question comes up over and over, so I figured I should sit down and
>>> really solve it.
>>>
>>> Basically the constraint is you want to calculate a mult value using the
>>> highest shift possible. However we have to be careful not to overflow
>>> 64bits when we multiply ~5second worth of cycles times the mult value.
>>>
>>> So I finally put this down into code and here it is. No promises that it
>>> is 100% right, but from my simple test examples it worked ok.
>> OK. Please check my case of that value.
>> MB can run from 5Mhz till 150MHz I think.
>> I need generic approach that's why I have to calculate with max value (150MHz).
>> My timer can tick on that freq too. (There is no different time bases in HW).
>>
>> I need to find out how many ticks takes ~5s.
>> 150MHz means that I need for 1sec 150 000 000 timer ticks.
>
> I think you mean counter cycles instead of timer ticks. Timer tick
> terminology usually describes a timer based interrupt.
yes.
>
>> One tick takes 1/150MHz = ~6-7ns - in the best case I can recognize and set
>> 6-7ns (this is only theoretical value because of overhead)
>>
>> ~5s takes 750 000 000 ticks = 0x2CB4 1780. And I have 32bit counter.
>>
>> That my question is how big could be a shift of value above till overflow.
>> 0x2CB4 1780 << shift not exceed 0xffff ffff ffff ffff.
>
> Almost. Its not the shift that causes the problem right off, but the
> resulting mult value calculated from a shift. Again, the key points are,
> you want to make sure that:
>
> 1) that mult value for the given shift fits in 32 bits.
> and
ok. Formula.
For mult 1GHz * 2^shift/timer_freq < (u32)
=> const=1GHz/timer_freq, const * 2^shift < (u32)
2^30=0x4000 0000
2^29=0x2000 0000
2^28=0x1000 0000
2^26=0x 400 0000
2^25=0x 200 0000
2^24=0x 100 0000
For shift in test
2^20=0x 10 0000
2^8= 0x 100
For 150MHz ->const = 6,6666 -> 30 is over, 29 fits.
For 5MHz -> const = 200 -> 25 is over, 24 fits.
For 1GHz -> const = 1 -> 32 is over, 31 fits - that's correct
For your test case below ->
(5 * timer_freq * 1GHz * 2^shift/timer_freq)>>shift <= 5sec in ns
=>(5 * 1GHz * 2^shift )>>shift <= 5sec in ns
=>( 5GHz * 2^shift )>>shift <= 5sec in ns
=>( 1GHz * 2^shift )>>shift <= 1sec in ns
=> 1GHz <= 1sec in ns
=> I think this is no test -> this is equal for every values.
Am I right?
If yes.
min_delta_ns is set to (const<1000 ? 1000 : const) -> I think that only for
slower machines than 1MHx uses const value.
max_delta_ns is for 32bit timer 2^31 -1 and for 64bit arch 2^63 - 1
> 2) mult * 5sec of cycles doesn't overflow 64bits (really is only an
> issue for very very fast counters that run faster then 1Ghz).
>
>
> So let's follow my algorithm and start by picking a shift value of 32.
>
> We calculate the mult, which would be (using clocksource_khz2mult()):
>
> (1Million * 2^32) / 150,000 = 28633115307 which overflows 32bits.
> BZZZZZZ.
>
> 1Million * 2^31 / 150,000 = 14316557653 (to big. BZZZZZZZ)
>
>
> 1Million * 2^30 / 150,000 = 7158278827 (to big. BZZZZZZZ)
>
>
> 1Million * 2^29 / 150,000 = 3579139413 (BING! it fits!)
>
> Now the test:
> (750 000 000 * 3 579 139 413)>>29 ?= 5 seconds
> 2684354559750000000 (doesn't overflow!) >> 29
> 4999999999ns ?= 5seconds (within the error range, so we're good!)
>
>
> Now take care, because the slower the clocksource, often the lower the
> shift value we can use, because the nsecs per cycle value that mult
> approximates is much larger.
>
>
> So for 5mhz (using
>
> 1Million * 2^29 / 5,000 = 107374182400 (32bit overflow!)
> ...
> 1Million * 2^24 / 5,000 = 3355443200 (fits!)
>
> Now the test:
> (25000000 * 3355443200)>>24 ?= 5 seconds
> 83886080000000000 (doesn't overflow!) >> 24 ?=
> 5000000000ns ?= 5seconds (BING!)
>
>
> So you can either dynamically calculate the best shift value for the
> actual freq using the helper functions I provided, or just use 24 and be
> safe, your pick.
ok. we will talk what the smaller freq is.
>
>
>
>> For example avr has shift 16, rating 50 (arch/avr32/kernel/time.c) (BTW: Sets
>> time from 2007 too)
>
> Most arches probably low ball the shift to be safe. Mainly because
> explaining how to calculate the optimal shift was hard and there weren't
> helper functions.
I hope that our discussion clear this.
>
> As an aside (feel free to ignore for the microblaze bits):
> Some complexity may grow here as well, since 5 seconds of cycles may
> prove too short as folks become more interested running w/ NOHZ and
> avoiding interrupts for extreme lengths of time (I've heard 30
> minutes!?). For those situations we will need lower shift values, since
> 30 minutes of cycles * a large mult value close to (1<<32) will likely
> overflow 64bits. But that trades off how finely we can tweak the clock
> steering. Probably converting folks to use the helper functions will be
> the best approach, as it will allow us to configure that depending on
> NOHZ or not.
ok.Let's talk about NOHZ case.
I enabled NOHZ choice in menuconfig. I am sourcing source two Kconfigs
(kernel/time/Kconfig and kernel/Kconfig.hz)
Here is the fragment from my .config file.
CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_PREEMPT_NONE=y
...
CONFIG_HZ_100=y
# CONFIG_HZ_250 is not set
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=100
For NO_HZ val I shouldn't use HZ value because of NO_HZ and HZ values shouldn't
be in .config file. Am I right?
If yes I have still problem in my code.
I have there these two parts.
Just counting value for periodic mode but depends on HZ value.
cpuinfo.freq_div_hz = cpuinfo.cpu_clock_freq / HZ;
+ usage in periodic mode.
case CLOCK_EVT_MODE_PERIODIC:
printk(KERN_INFO "%s: periodic\n", __func__);
microblaze_timer0_start_periodic(cpuinfo.freq_div_hz);
break;
Here is the part of my kernel log. At the beginning is setup periodic mode and
then is switched to oneshot mode. And for periodic mode I use HZ value which
shouldn't be there.
microblaze_timer_set_mode: shutdown
microblaze_timer_set_mode: periodic
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
Memory: 254848k/262144k available
ODEBUG: selftest passed
Calibrating delay loop... 60.82 BogoMIPS (lpj=304128)
Mount-cache hash table entries: 512
net_namespace: 544 bytes
NET: Registered protocol family 16
bio: create slab <bio-0> at 0
NET: Registered protocol family 2
microblaze_timer_set_mode: oneshot ------------------------- switch to oneshot
Switched to high resolution mode on CPU 0
What is the correct solution for NO_HZ case?
BTW: I just tried to remove Kconfig.hz sourcing and I am getting faults in
include/linux/jiffies.h and I expect the problems in other code too.
Thanks,
Michal
>
> thanks
> -john
>
>
--
Michal Simek, Ing. (M.Eng)
w: http://www.monstr.eu p: +42-0-721842854
On Sat, 21 Mar 2009, Michal Simek wrote:
> CONFIG_HZ_100=y
> # CONFIG_HZ_250 is not set
> # CONFIG_HZ_300 is not set
> # CONFIG_HZ_1000 is not set
> CONFIG_HZ=100
>
> For NO_HZ val I shouldn't use HZ value because of NO_HZ and HZ values shouldn't
> be in .config file. Am I right?
No. NO_HZ does not remove the HZ value from the kernel. There is way
too much code depending on it. What NO_HZ does is to supress the
periodic tick when the system goes idle and the next timer expiry is
farther away than 1 HZ. When the system is non idle then the periodic
tick runs again. NO_HZ is merily for power saving.
In a normal kernel when the machine is idle then we wake up every HZ
to find out that there is no work to do and we go idle again. But if
you think about it then this is stupid, because the kernel knows when
the next timer is due to expire. So if the next timer expiry is
e.g. 100ms away, then we can sleep for full 100ms instead of sleeping
10 * 10ms (HZ=100) or 100 * 1ms (HZ=1000). This allows systems to go
into deeper power saving states.
You should be able to observe the difference by monitoring
/proc/interrupts. A nohz enabled kernel should have significantly less
timer interrupts on an idle system.
Thanks,
tglx
Thomas Gleixner wrote:
> On Sat, 21 Mar 2009, Michal Simek wrote:
>> CONFIG_HZ_100=y
>> # CONFIG_HZ_250 is not set
>> # CONFIG_HZ_300 is not set
>> # CONFIG_HZ_1000 is not set
>> CONFIG_HZ=100
>>
>> For NO_HZ val I shouldn't use HZ value because of NO_HZ and HZ values shouldn't
>> be in .config file. Am I right?
>
> No. NO_HZ does not remove the HZ value from the kernel. There is way
> too much code depending on it. What NO_HZ does is to supress the
> periodic tick when the system goes idle and the next timer expiry is
> farther away than 1 HZ. When the system is non idle then the periodic
> tick runs again. NO_HZ is merily for power saving.
>
> In a normal kernel when the machine is idle then we wake up every HZ
> to find out that there is no work to do and we go idle again. But if
> you think about it then this is stupid, because the kernel knows when
> the next timer is due to expire. So if the next timer expiry is
> e.g. 100ms away, then we can sleep for full 100ms instead of sleeping
> 10 * 10ms (HZ=100) or 100 * 1ms (HZ=1000). This allows systems to go
> into deeper power saving states.
>
> You should be able to observe the difference by monitoring
> /proc/interrupts. A nohz enabled kernel should have significantly less
> timer interrupts on an idle system.
Yes, I see it. I think I sent my log in any previous email in this thread too +
I see it on my heartbeat led too.
Thanks for explanation,
Michal
>
> Thanks,
>
> tglx
--
Michal Simek, Ing. (M.Eng)
w: http://www.monstr.eu p: +42-0-721842854
On Sat, 21 Mar 2009, Michal Simek wrote:
> Yes, I see it. I think I sent my log in any previous email in this thread too +
> I see it on my heartbeat led too.
>
> Thanks for explanation,
Welcome. Thanks for working on the review issues. I looked through
your timer and interrupt code and I'm quite happy with it.
Please add: Reviewed-by: Thomas Gleixner <[email protected]>
to both.
Thanks,
tglx
Thomas Gleixner wrote:
> On Sat, 21 Mar 2009, Michal Simek wrote:
>> Yes, I see it. I think I sent my log in any previous email in this thread too +
>> I see it on my heartbeat led too.
>>
>> Thanks for explanation,
>
> Welcome. Thanks for working on the review issues. I looked through
> your timer and interrupt code and I'm quite happy with it.
>
> Please add: Reviewed-by: Thomas Gleixner <[email protected]>
>
> to both.
I want to fix rating and shift value nothing other.
I'll add it.
Thanks for your help,
Michal
>
> Thanks,
>
> tglx
--
Michal Simek, Ing. (M.Eng)
w: http://www.monstr.eu p: +42-0-721842854
On Wednesday 18 March 2009, [email protected] wrote:
> From: Michal Simek <[email protected]>
>
>
> Signed-off-by: Michal Simek <[email protected]>
> ---
> ?arch/microblaze/include/asm/of_device.h ? | ? 45 ++
> ?arch/microblaze/include/asm/of_platform.h | ? 64 ++
> ?arch/microblaze/include/asm/prom.h ? ? ? ?| ?313 ++++++++
> ?arch/microblaze/kernel/of_device.c ? ? ? ?| ?115 +++
> ?arch/microblaze/kernel/of_platform.c ? ? ?| ?201 +++++
> ?arch/microblaze/kernel/prom.c ? ? ? ? ? ? | 1147 +++++++++++++++++++++++++++++
> ?arch/microblaze/kernel/prom_parse.c ? ? ? | 1025 ++++++++++++++++++++++++++
> ?7 files changed, 2910 insertions(+), 0 deletions(-)
> ?create mode 100644 arch/microblaze/include/asm/of_device.h
> ?create mode 100644 arch/microblaze/include/asm/of_platform.h
> ?create mode 100644 arch/microblaze/include/asm/prom.h
> ?create mode 100644 arch/microblaze/kernel/of_device.c
> ?create mode 100644 arch/microblaze/kernel/of_platform.c
> ?create mode 100644 arch/microblaze/kernel/prom.c
> ?create mode 100644 arch/microblaze/kernel/prom_parse.c
Since these files are derived from the powerpc versions, what is the
plan on them? IIRC, you had them in a common directory in an earlier
version. Are you planning to merge them at some point in the future
or do you intend to maintain a fork?
Arnd <><
On Wednesday 18 March 2009, [email protected] wrote:
> From: Michal Simek <[email protected]>
>
>
> Signed-off-by: Michal Simek <[email protected]>
> ---
> ?arch/microblaze/include/asm/signal.h | ?165 +++++++++++
> ?arch/microblaze/kernel/signal.c ? ? ?| ?536 ++++++++++++++++++++++++++++++++++
> ?2 files changed, 701 insertions(+), 0 deletions(-)
> ?create mode 100644 arch/microblaze/include/asm/signal.h
> ?create mode 100644 arch/microblaze/kernel/signal.c
> From: Michal Simek <[email protected]>
>
>
> Signed-off-by: Michal Simek <[email protected]>
> ---
> arch/microblaze/include/asm/ipc.h | 1 +
> arch/microblaze/include/asm/ipcbuf.h | 36 +++++
> arch/microblaze/kernel/sys_microblaze.c | 226 +++++++++++++++++++++++++++++++
> 3 files changed, 263 insertions(+), 0 deletions(-)
> create mode 100644 arch/microblaze/include/asm/ipc.h
> create mode 100644 arch/microblaze/include/asm/ipcbuf.h
> create mode 100644 arch/microblaze/kernel/sys_microblaze.c
I don't quite remember what the outcome of this discussion was the last
time, but what is your plan for the deprecated syscalls like the
legacy syscalls you add here?
Have you tried changing uClibc and/or glibc so you don't need them?
Are you planning to remove them soon once they are not needed any
more?
What about the syscalls that are not needed but you just get from
common code (e.g. oldumount, time, old_readdir, ...)?
Arnd <><
On Wednesday 18 March 2009, [email protected] wrote:
> From: Michal Simek <[email protected]>
>
>
> Signed-off-by: Michal Simek <[email protected]>
> ---
> ?arch/microblaze/include/asm/termbits.h | ?203 ++++++++++++++++++++++++++++++++
> ?arch/microblaze/include/asm/termios.h ?| ? 88 ++++++++++++++
> ?2 files changed, 291 insertions(+), 0 deletions(-)
> ?create mode 100644 arch/microblaze/include/asm/termbits.h
> ?create mode 100644 arch/microblaze/include/asm/termios.h
Did you take at the header files I have in git://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground.git/#generic-headers?
I haven't gotten around to posting them for review, but I still think
it would be great if we can at least make sure they are identical
so we can remove your versions as soon as we have the asm-generic ones.
Arnd <><
On Mon, Mar 23, 2009 at 07:51:23PM +0100, Arnd Bergmann wrote:
> On Wednesday 18 March 2009, [email protected] wrote:
> > From: Michal Simek <[email protected]>
> >
> >
> > Signed-off-by: Michal Simek <[email protected]>
> > ---
> > arch/microblaze/include/asm/of_device.h | 45 ++
> > arch/microblaze/include/asm/of_platform.h | 64 ++
> > arch/microblaze/include/asm/prom.h | 313 ++++++++
> > arch/microblaze/kernel/of_device.c | 115 +++
> > arch/microblaze/kernel/of_platform.c | 201 +++++
> > arch/microblaze/kernel/prom.c | 1147 +++++++++++++++++++++++++++++
> > arch/microblaze/kernel/prom_parse.c | 1025 ++++++++++++++++++++++++++
> > 7 files changed, 2910 insertions(+), 0 deletions(-)
> > create mode 100644 arch/microblaze/include/asm/of_device.h
> > create mode 100644 arch/microblaze/include/asm/of_platform.h
> > create mode 100644 arch/microblaze/include/asm/prom.h
> > create mode 100644 arch/microblaze/kernel/of_device.c
> > create mode 100644 arch/microblaze/kernel/of_platform.c
> > create mode 100644 arch/microblaze/kernel/prom.c
> > create mode 100644 arch/microblaze/kernel/prom_parse.c
>
> Since these files are derived from the powerpc versions, what is the
> plan on them? IIRC, you had them in a common directory in an earlier
> version. Are you planning to merge them at some point in the future
> or do you intend to maintain a fork?
Actually, it's trivial to factor out all the common code out of
arch/powerpc/ to drivers/of/.
It took me approx. 4 hours to factor out the code and make a
proof-of-concept FDT support for a little-endian ARM platform. ;-)
(The device tree was only describing a cpu and a nor flash, though.
No support for interrupt- and gpio-controllers. And no support for
U-Boot, I just built the dtb file into the kernel).
I never got around to clean it up and send though, but for sure,
there is absolutely no reason to duplicate the code across the
platforms.
Thanks,
--
Anton Vorontsov
email: [email protected]
irc://irc.freenode.net/bd2
Arnd Bergmann wrote:
> On Wednesday 18 March 2009, [email protected] wrote:
>> From: Michal Simek <[email protected]>
>>
>>
>> Signed-off-by: Michal Simek <[email protected]>
>> ---
>> arch/microblaze/include/asm/signal.h | 165 +++++++++++
>> arch/microblaze/kernel/signal.c | 536 ++++++++++++++++++++++++++++++++++
>> 2 files changed, 701 insertions(+), 0 deletions(-)
>> create mode 100644 arch/microblaze/include/asm/signal.h
>> create mode 100644 arch/microblaze/kernel/signal.c
>
>> From: Michal Simek <[email protected]>
>>
>>
>> Signed-off-by: Michal Simek <[email protected]>
>> ---
>> arch/microblaze/include/asm/ipc.h | 1 +
>> arch/microblaze/include/asm/ipcbuf.h | 36 +++++
>> arch/microblaze/kernel/sys_microblaze.c | 226 +++++++++++++++++++++++++++++++
>> 3 files changed, 263 insertions(+), 0 deletions(-)
>> create mode 100644 arch/microblaze/include/asm/ipc.h
>> create mode 100644 arch/microblaze/include/asm/ipcbuf.h
>> create mode 100644 arch/microblaze/kernel/sys_microblaze.c
>
> I don't quite remember what the outcome of this discussion was the last
> time, but what is your plan for the deprecated syscalls like the
> legacy syscalls you add here?
>
> Have you tried changing uClibc and/or glibc so you don't need them?
> Are you planning to remove them soon once they are not needed any
> more?
>
> What about the syscalls that are not needed but you just get from
> common code (e.g. oldumount, time, old_readdir, ...)?
I think that my emails from yesterday don't go through.
Here are our updated results in this area.
We have noMMU and MMU microblaze version and we use almost the same syscall
table for them. That's not correct in all cases but we have it.
>From noMMU and uClibc perspective. We are still using gcc 3.4.1 and we are
working on gcc 4.1.2 with latest uClibc.
>From uClibc perspective. is almost all clear. We have latest version and when
new gcc are ready I start to work on it and of course add new syscall to uClibc
will take a time but I believe that is only work which is not so hard.
>From MMU and glibc perspective. We have and use gcc 4.1.2 with any ancient glibc
version.
Glibc version with Microblaze support is not based on any public version and we
can't easily create patches and upgrade them to latest version. We are preparing
work on it but this will be a long time project.
I am trying to add only noMMU kernel because MMU kernel is still new (only 2
month with FDT) and I do LTP test on it MMU kernel share a lot of code with
noMMU version and reviewing is easier. MMU version will come in future for
reviewing too.
That's the current state.
I don't like this situation but I have to work with it. On the base on
information which are above I have only some choices.
1. Wait till both tools are ready for syscall cleanup and then try to add
microblaze to kernel.org.
2. Update only uClibc but latest uClibc version needs newer gcc which I don't
have now.
3. Keep old syscalls and sys_ipc for example which are tested and are used for a
long time.
I hope you understand our situation. That's why I decided to have old syscalls.
Both version(noMMU and MMU) work. And we are working on new libcs. They will
need a time for testing too.
For me is better to have working stable version and in future remove old
syscalls and clean code (for example sys_ipc).
Thanks,
Michal
> Arnd <><
--
Michal Simek, Ing. (M.Eng)
w: http://www.monstr.eu p: +42-0-721842854
Arnd Bergmann wrote:
> On Wednesday 18 March 2009, [email protected] wrote:
>> From: Michal Simek <[email protected]>
>>
>>
>> Signed-off-by: Michal Simek <[email protected]>
>> ---
>> arch/microblaze/include/asm/of_device.h | 45 ++
>> arch/microblaze/include/asm/of_platform.h | 64 ++
>> arch/microblaze/include/asm/prom.h | 313 ++++++++
>> arch/microblaze/kernel/of_device.c | 115 +++
>> arch/microblaze/kernel/of_platform.c | 201 +++++
>> arch/microblaze/kernel/prom.c | 1147 +++++++++++++++++++++++++++++
>> arch/microblaze/kernel/prom_parse.c | 1025 ++++++++++++++++++++++++++
>> 7 files changed, 2910 insertions(+), 0 deletions(-)
>> create mode 100644 arch/microblaze/include/asm/of_device.h
>> create mode 100644 arch/microblaze/include/asm/of_platform.h
>> create mode 100644 arch/microblaze/include/asm/prom.h
>> create mode 100644 arch/microblaze/kernel/of_device.c
>> create mode 100644 arch/microblaze/kernel/of_platform.c
>> create mode 100644 arch/microblaze/kernel/prom.c
>> create mode 100644 arch/microblaze/kernel/prom_parse.c
>
> Since these files are derived from the powerpc versions, what is the
> plan on them? IIRC, you had them in a common directory in an earlier
> version. Are you planning to merge them at some point in the future
> or do you intend to maintain a fork?
yes, these files are defived from PPC version. Yes, I added them to generic
location and in this version are in arch folder. It is easier for me to have
them in arch folder till Microblaze will be in linus tree.
And then create patch which will synchronize them.
I prefer to have this code in generic location as much as possible but first
stage from my perspective should be add microblaze code to tree and then add it
to generic location and remove it from all archs which use it.
Thanks,
Michal
> Arnd <><
--
Michal Simek, Ing. (M.Eng)
w: http://www.monstr.eu p: +42-0-721842854
Arnd Bergmann wrote:
> On Wednesday 18 March 2009, [email protected] wrote:
>> From: Michal Simek <[email protected]>
>>
>>
>> Signed-off-by: Michal Simek <[email protected]>
>> ---
>> arch/microblaze/include/asm/termbits.h | 203 ++++++++++++++++++++++++++++++++
>> arch/microblaze/include/asm/termios.h | 88 ++++++++++++++
>> 2 files changed, 291 insertions(+), 0 deletions(-)
>> create mode 100644 arch/microblaze/include/asm/termbits.h
>> create mode 100644 arch/microblaze/include/asm/termios.h
>
> Did you take at the header files I have in git://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground.git/#generic-headers?
> I haven't gotten around to posting them for review, but I still think
> it would be great if we can at least make sure they are identical
> so we can remove your versions as soon as we have the asm-generic ones.
I tested it some min ago. I just take your termios.h and termbits.h from
asm-generic folder. I miss there only #include <asm/uaccess.h> in termion.h.
Compilation is OK and kernel works with your files too. For me is easy to use
your version. If they are there, I'll use them.
Thanks,
Michal
> Arnd <><
--
Michal Simek, Ing. (M.Eng)
w: http://www.monstr.eu p: +42-0-721842854
On Tuesday 24 March 2009, Michal Simek wrote:
> > I haven't gotten around to posting them for review, but I still think
> > it would be great if we can at least make sure they are identical
> > so we can remove your versions as soon as we have the asm-generic ones.
>
> I tested it some min ago. I just take your termios.h and termbits.h from
> asm-generic folder. I miss there only #include <asm/uaccess.h> in termion.h.
>
> Compilation is OK and kernel works with your files too. For me is easy to use
> your version. If they are there, I'll use them.
Ok. I did not just mean these specific files, but all the headers in
general. I assume that you have not had a chance to look into the
other header files, which is ok. Remis is currently cleaning up bits
of the generic header files in Linux based on my work, and I asked
him to look into your tree to see how much can be shared.
Note that there is a problem of binary compatibility with certain headers.
If e.g. the constants from termbits.h or some data structures slightly
change, user space will still compile but no longer be compatible
with other kernel versions, so this needs to be done very carefully.
Arnd <><
Hi Arnd,
On Tue, Mar 24, 2009 at 11:57 PM, Arnd Bergmann <[email protected]> wrote:
> On Tuesday 24 March 2009, Michal Simek wrote:
>> > I haven't gotten around to posting them for review, but I still think
>> > it would be great if we can at least make sure they are identical
>> > so we can remove your versions as soon as we have the asm-generic ones.
>>
>> I tested it some min ago. I just take your termios.h and termbits.h from
>> asm-generic folder. I miss there only #include <asm/uaccess.h> in termion.h.
>>
>> Compilation is OK and kernel works with your files too. For me is easy to use
>> your version. If they are there, I'll use them.
>
> Ok. I did not just mean these specific files, but all the headers in
> general. I assume that you have not had a chance to look into the
> other header files, which is ok. Remis is currently cleaning up bits
> of the generic header files in Linux based on my work, and I asked
> him to look into your tree to see how much can be shared.
>
> Note that there is a problem of binary compatibility with certain headers.
> If e.g. the constants from termbits.h or some data structures slightly
> change, user space will still compile but no longer be compatible
> with other kernel versions, so this needs to be done very carefully.
We are viewing this kernel as a clean break from the past (2.6.20
maintained outside kernel.org).
There will be a new toolchain/glibc/uClibc built against these modern
kernel headers, so I think the binary compatibility issue will have
minimal impact on the existing userbase. They will just have to
rebuild their apps. In the space where MicroBlaze finds itself, it's
typical to rebuild an entire system image from source. Certainly I'm
not aware of anyone moving RPMs around containing MicroBlaze binaries!
Regards,
John
--
John Williams,
PetaLogix - Linux Solutions for a Reconfigurable World
w: http://www.petalogix.com p: +61-7-30090663 f: +61-7-30090663
Arnd Bergmann wrote:
> On Tuesday 24 March 2009, Michal Simek wrote:
>>> I haven't gotten around to posting them for review, but I still think
>>> it would be great if we can at least make sure they are identical
>>> so we can remove your versions as soon as we have the asm-generic ones.
>> I tested it some min ago. I just take your termios.h and termbits.h from
>> asm-generic folder. I miss there only #include <asm/uaccess.h> in termion.h.
>>
>> Compilation is OK and kernel works with your files too. For me is easy to use
>> your version. If they are there, I'll use them.
>
> Ok. I did not just mean these specific files, but all the headers in
> general. I assume that you have not had a chance to look into the
> other header files, which is ok. Remis is currently cleaning up bits
> of the generic header files in Linux based on my work, and I asked
> him to look into your tree to see how much can be shared.
>
> Note that there is a problem of binary compatibility with certain headers.
> If e.g. the constants from termbits.h or some data structures slightly
> change, user space will still compile but no longer be compatible
> with other kernel versions, so this needs to be done very carefully.
As John wrote. It is completely new kernel and we do (will do) new toolchain
against new headers. I am open to use all generic approaches which will be in
kernel.
Thanks,
Michal
>
> Arnd <><
--
Michal Simek, Ing. (M.Eng)
w: http://www.monstr.eu p: +42-0-721842854
> -----Original Message-----
> From: Michal Simek [mailto:[email protected]]
> Sent: Tuesday, March 24, 2009 9:27 AM
> To: [email protected]
> Cc: [email protected]; [email protected]; John
Linn; Arnd Bergmann; Thomas
> Gleixner; Randy Dunlap; Ingo Molnar; [email protected]
> Subject: Re: Microblaze linux support
>
> Hi all,
> > Hi all,
> >
> > I think that is the right time to send you next pack with
> > Microblaze support. It is seventh pack - some previous packs
> > was review by community and I hope there are not any big faults.
> >
> > We tested this kernel on some boards.
> > We have GIT server up and gitweb is available at
http://developer.petalogix.com/git/gitweb.cgi
> >
> > All information about git clone you can find on gitweb.
> > This pack is available in for-linus branch. Information about other
branches are on gitweb too.
> >
> > More information about microblaze fdt kernel you can find at
http://www.monstr.eu/fdt/
> > If you want to test kernel with microblaze toolchain let me know.
> >
> > I added only uart16550 and uartlite support - that's enought for
first merge.
> >
> >
> > Thanks for you comments and especially for your ACK,
> > Michal
> >
> It is a week ago when I sent v7 pack to LKML for reviewing.
>
> I have got ACK from John Williams who is the best person from
microblaze
> linux community.
> I got ACK from Randy Dunlap for Kconfig and Makefile patches.
> Thomas Gleixner reviewed IRQ and Timer code.
> Ingo Molnar confirms me that all coding style violation (checking with
> checkpatch.pl) are false positive.
>
> John L: Could you give me ACK from Xilinx?
Acked-by: John Linn <[email protected]>
Thanks for all your work to move this forward.
-- John
>
> Thanks,
> Michal
>
>
>
> >
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe
linux-kernel" in
> > the body of a message to [email protected]
> > More majordomo info at http://vger.kernel.org/majordomo-info.html
> > Please read the FAQ at http://www.tux.org/lkml/
> >
>
>
> --
> Michal Simek, Ing. (M.Eng)
> w: http://www.monstr.eu p: +42-0-721842854
>
This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.
John Linn wrote:
>> Hi all,
>>> Hi all,
>>>
>>> I think that is the right time to send you next pack with
>>> Microblaze support. It is seventh pack - some previous packs
>>> was review by community and I hope there are not any big faults.
>>>
>>> We tested this kernel on some boards.
>>> We have GIT server up and gitweb is available at
> http://developer.petalogix.com/git/gitweb.cgi
>>> All information about git clone you can find on gitweb.
>>> This pack is available in for-linus branch. Information about other
> branches are on gitweb too.
>>> More information about microblaze fdt kernel you can find at
> http://www.monstr.eu/fdt/
>>> If you want to test kernel with microblaze toolchain let me know.
>>>
>>> I added only uart16550 and uartlite support - that's enought for
> first merge.
>>>
>>> Thanks for you comments and especially for your ACK,
>>> Michal
>>>
>> It is a week ago when I sent v7 pack to LKML for reviewing.
>>
>> I have got ACK from John Williams who is the best person from
> microblaze
>> linux community.
>> I got ACK from Randy Dunlap for Kconfig and Makefile patches.
>> Thomas Gleixner reviewed IRQ and Timer code.
>> Ingo Molnar confirms me that all coding style violation (checking with
>> checkpatch.pl) are false positive.
>>
>> John L: Could you give me ACK from Xilinx?
>
> Acked-by: John Linn <[email protected]>
>
> Thanks for all your work to move this forward.
Thanks too.
Michal
>
> -- John
>
>> Thanks,
>> Michal
>>
Hi all,
> Hi all,
>
> I think that is the right time to send you next pack with
> Microblaze support. It is seventh pack - some previous packs
> was review by community and I hope there are not any big faults.
>
> We tested this kernel on some boards.
> We have GIT server up and gitweb is available at http://developer.petalogix.com/git/gitweb.cgi
>
> All information about git clone you can find on gitweb.
> This pack is available in for-linus branch. Information about other branches are on gitweb too.
>
> More information about microblaze fdt kernel you can find at http://www.monstr.eu/fdt/
> If you want to test kernel with microblaze toolchain let me know.
>
> I added only uart16550 and uartlite support - that's enought for first merge.
>
>
> Thanks for you comments and especially for your ACK,
> Michal
>
It is a week ago when I sent v7 pack to LKML for reviewing.
I have got ACK from John Williams who is the best person from microblaze
linux community.
I got ACK from Randy Dunlap for Kconfig and Makefile patches.
Thomas Gleixner reviewed IRQ and Timer code.
Ingo Molnar confirms me that all coding style violation (checking with
checkpatch.pl) are false positive.
John L: Could you give me ACK from Xilinx?
Thanks,
Michal
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>
--
Michal Simek, Ing. (M.Eng)
w: http://www.monstr.eu p: +42-0-721842854
Hi all,
Here is the small part of code which enable uartlite and serial of code
driver for Microblaze cpu.
Peter: I got ack from you in past. I believe that I still have it. Could
I keep your ACK there?
Thanks,
Michal
> From: Michal Simek <[email protected]>
>
>
> Signed-off-by: Michal Simek <[email protected]>
> ---
> drivers/serial/Kconfig | 4 ++--
> 1 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
> index 7d7f576..131901b 100644
> --- a/drivers/serial/Kconfig
> +++ b/drivers/serial/Kconfig
> @@ -833,7 +833,7 @@ config SERIAL_IMX_CONSOLE
>
> config SERIAL_UARTLITE
> tristate "Xilinx uartlite serial port support"
> - depends on PPC32
> + depends on PPC32 || MICROBLAZE
> select SERIAL_CORE
> help
> Say Y here if you want to use the Xilinx uartlite serial controller.
> @@ -1319,7 +1319,7 @@ config SERIAL_NETX_CONSOLE
>
> config SERIAL_OF_PLATFORM
> tristate "Serial port on Open Firmware platform bus"
> - depends on PPC_OF
> + depends on PPC_OF || MICROBLAZE
> depends on SERIAL_8250 || SERIAL_OF_PLATFORM_NWPSERIAL
> help
> If you have a PowerPC based system that has serial ports
>
--
Michal Simek, Ing. (M.Eng)
PetaLogix - Linux Solutions for a Reconfigurable World
w: http://www.petalogix.com p: +61-7-30090663,+42-0-721842854 f: +61-7-30090663
On Wed, Mar 25, 2009 at 2:03 AM, Michal Simek
<[email protected]> wrote:
>> ?config SERIAL_OF_PLATFORM
>> ? ? ? tristate "Serial port on Open Firmware platform bus"
>> - ? ? depends on PPC_OF
>> + ? ? depends on PPC_OF || MICROBLAZE
>> ? ? ? depends on SERIAL_8250 || SERIAL_OF_PLATFORM_NWPSERIAL
>> ? ? ? help
>> ? ? ? ? If you have a PowerPC based system that has serial ports
Trivial tweak - update the help text to "PowerPC or MicroBlaze"
John
>>>>> "Michal" == Michal Simek <[email protected]> writes:
Michal> Hi all,
Michal> Here is the small part of code which enable uartlite and serial of code
Michal> driver for Microblaze cpu.
Michal> Peter: I got ack from you in past. I believe that I still have it. Could
Michal> I keep your ACK there?
Yes, Acked-by: Peter Korsgaard <[email protected]>
--
Bye, Peter Korsgaard
> -----Original Message-----
> From: [email protected]
> [mailto:[email protected]] On Behalf Of
> Michal Simek
> Sent: Tuesday, March 24, 2009 8:27 AM
> To: [email protected]
> Cc: [email protected];
> [email protected]; John Linn; Arnd Bergmann; Thomas
> Gleixner; Randy Dunlap; Ingo Molnar; [email protected]
> Subject: [microblaze-uclinux] Re: Microblaze linux support
>
> Hi all,
> > Hi all,
> >
> > I think that is the right time to send you next pack with
> > Microblaze support. It is seventh pack - some previous packs
> > was review by community and I hope there are not any big faults.
> >
> > We tested this kernel on some boards.
> > We have GIT server up and gitweb is available at
> http://developer.petalogix.com/git/gitweb.cgi
> >
> > All information about git clone you can find on gitweb.
> > This pack is available in for-linus branch. Information
> about other branches are on gitweb too.
> >
> > More information about microblaze fdt kernel you can find
> at http://www.monstr.eu/fdt/
> > If you want to test kernel with microblaze toolchain let me know.
> >
> > I added only uart16550 and uartlite support - that's
> enought for first merge.
> >
> >
> > Thanks for you comments and especially for your ACK,
> > Michal
> >
> It is a week ago when I sent v7 pack to LKML for reviewing.
>
> I have got ACK from John Williams who is the best person from
> microblaze
> linux community.
> I got ACK from Randy Dunlap for Kconfig and Makefile patches.
> Thomas Gleixner reviewed IRQ and Timer code.
> Ingo Molnar confirms me that all coding style violation (checking with
> checkpatch.pl) are false positive.
>
> John L: Could you give me ACK from Xilinx?
>
> Thanks,
> Michal
Acked-by: Stephen Neuendorffer <[email protected]>
Steve
This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.
On Wednesday 18 March 2009, [email protected] wrote:
> From: Michal Simek <[email protected]>
>
>
> Signed-off-by: Michal Simek <[email protected]>
> ---
> ?arch/microblaze/Kconfig ? ? ? ? ? ? ? ? ? ? ? | ?136 +++++++++++++++++++++++++
> ?arch/microblaze/Kconfig.debug ? ? ? ? ? ? ? ? | ? 26 +++++
> ?arch/microblaze/platform/Kconfig.platform ? ? | ? 85 +++++++++++++++
> ?arch/microblaze/platform/generic/Kconfig.auto | ? 62 +++++++++++
> ?4 files changed, 309 insertions(+), 0 deletions(-)
> ?create mode 100644 arch/microblaze/Kconfig
> ?create mode 100644 arch/microblaze/Kconfig.debug
> ?create mode 100644 arch/microblaze/platform/Kconfig.platform
> ?create mode 100644 arch/microblaze/platform/generic/Kconfig.auto
As a general rule for future updates, you should make sure that
the order of your patches is so that you don't get a broken
version in the middle. In your current series, it's not important,
because nothing works really until all your patches are in there.
Arnd <><
Arnd Bergmann wrote:
> On Wednesday 18 March 2009, [email protected] wrote:
>> From: Michal Simek <[email protected]>
>>
>>
>> Signed-off-by: Michal Simek <[email protected]>
>> ---
>> arch/microblaze/Kconfig | 136 +++++++++++++++++++++++++
>> arch/microblaze/Kconfig.debug | 26 +++++
>> arch/microblaze/platform/Kconfig.platform | 85 +++++++++++++++
>> arch/microblaze/platform/generic/Kconfig.auto | 62 +++++++++++
>> 4 files changed, 309 insertions(+), 0 deletions(-)
>> create mode 100644 arch/microblaze/Kconfig
>> create mode 100644 arch/microblaze/Kconfig.debug
>> create mode 100644 arch/microblaze/platform/Kconfig.platform
>> create mode 100644 arch/microblaze/platform/generic/Kconfig.auto
>
> As a general rule for future updates, you should make sure that
> the order of your patches is so that you don't get a broken
> version in the middle. In your current series, it's not important,
> because nothing works really until all your patches are in there.
Thanks for your advice.
I am trying to do in all project where I work.
Thanks,
Michal
> Arnd <><
--
Michal Simek, Ing. (M.Eng)
w: http://www.monstr.eu p: +42-0-721842854
On Mon, 2009-03-23 at 23:53 +0300, Anton Vorontsov wrote:
> It took me approx. 4 hours to factor out the code and make a
> proof-of-concept FDT support for a little-endian ARM platform. ;-)
> (The device tree was only describing a cpu and a nor flash, though.
> No support for interrupt- and gpio-controllers. And no support for
> U-Boot, I just built the dtb file into the kernel).
ARM could benefit tremendously I believe from a similar virtualized
interrupt mapping & OF tree to powerpc for their gazillions of weirdly
cascaded interrupt controller setups :-)
Ben.