提交 ff0c4ad2 编写于 作者: L Linus Torvalds

Merge branch 'for-upstream' of git://openrisc.net/jonas/linux

* 'for-upstream' of git://openrisc.net/jonas/linux: (24 commits)
  OpenRISC: Add MAINTAINERS entry
  OpenRISC: Miscellaneous
  OpenRISC: Library routines
  OpenRISC: Headers
  OpenRISC: Traps
  OpenRISC: Module support
  OpenRISC: GPIO
  OpenRISC: Scheduling/Process management
  OpenRISC: Idle/Power management
  OpenRISC: System calls
  OpenRISC: IRQ
  OpenRISC: Timekeeping
  OpenRISC: DMA
  OpenRISC: PTrace
  OpenRISC: Build infrastructure
  OpenRISC: Signal handling
  OpenRISC: Memory management
  OpenRISC: Device tree
  OpenRISC: Boot code
  iomap: make IOPORT/PCI mapping functions conditional
  ...
......@@ -4688,6 +4688,14 @@ F: drivers/of
F: include/linux/of*.h
K: of_get_property
OPENRISC ARCHITECTURE
M: Jonas Bonn <jonas@southpole.se>
W: http://openrisc.net
L: linux@lists.openrisc.net
S: Maintained
T: git git://openrisc.net/~jonas/linux
F: arch/openrisc
OPL4 DRIVER
M: Clemens Ladisch <clemens@ladisch.de>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
......
#ifndef __ASM_AVR32_DELAY_H
#define __ASM_AVR32_DELAY_H
/*
* Copyright (C) 1993 Linus Torvalds
*
* Delay routines calling functions in arch/avr32/lib/delay.c
*/
extern void __bad_udelay(void);
extern void __bad_ndelay(void);
extern void __udelay(unsigned long usecs);
extern void __ndelay(unsigned long nsecs);
extern void __const_udelay(unsigned long xloops);
extern void __delay(unsigned long loops);
#define udelay(n) (__builtin_constant_p(n) ? \
((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c6ul)) : \
__udelay(n))
#define ndelay(n) (__builtin_constant_p(n) ? \
((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
__ndelay(n))
#endif /* __ASM_AVR32_DELAY_H */
#include <asm-generic/delay.h>
#ifndef _ASM_M32R_DELAY_H
#define _ASM_M32R_DELAY_H
/*
* Copyright (C) 1993 Linus Torvalds
*
* Delay routines calling functions in arch/m32r/lib/delay.c
*/
extern void __bad_udelay(void);
extern void __bad_ndelay(void);
extern void __udelay(unsigned long usecs);
extern void __ndelay(unsigned long nsecs);
extern void __const_udelay(unsigned long xloops);
extern void __delay(unsigned long loops);
#define udelay(n) (__builtin_constant_p(n) ? \
((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \
__udelay(n))
#define ndelay(n) (__builtin_constant_p(n) ? \
((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
__ndelay(n))
#endif /* _ASM_M32R_DELAY_H */
#include <asm-generic/delay.h>
#
# For a description of the syntax of this configuration file,
# see Documentation/kbuild/config-language.txt.
#
config OPENRISC
def_bool y
select OF
select OF_EARLY_FLATTREE
select HAVE_MEMBLOCK
select ARCH_WANT_OPTIONAL_GPIOLIB
select HAVE_ARCH_TRACEHOOK
select HAVE_GENERIC_HARDIRQS
select GENERIC_IRQ_CHIP
select GENERIC_IRQ_PROBE
select GENERIC_IRQ_SHOW
select GENERIC_IOMAP
config MMU
def_bool y
config WISHBONE_BUS_BIG_ENDIAN
def_bool y
config SYMBOL_PREFIX
string
default ""
config HAVE_DMA_ATTRS
def_bool y
config UID16
def_bool y
config RWSEM_GENERIC_SPINLOCK
def_bool y
config RWSEM_XCHGADD_ALGORITHM
def_bool n
config GENERIC_HWEIGHT
def_bool y
config GENERIC_IOMAP
def_bool y
config NO_IOPORT
def_bool y
config GENERIC_GPIO
def_bool y
config GENERIC_CLOCKEVENTS
def_bool y
config TRACE_IRQFLAGS_SUPPORT
def_bool y
# For now, use generic checksum functions
#These can be reimplemented in assembly later if so inclined
config GENERIC_CSUM
def_bool y
config GENERIC_FIND_NEXT_BIT
def_bool y
source "init/Kconfig"
menu "Processor type and features"
choice
prompt "Subarchitecture"
default OR1K_1200
config OR1K_1200
bool "OR1200"
help
Generic OpenRISC 1200 architecture
endchoice
config OPENRISC_BUILTIN_DTB
string "Builtin DTB"
default ""
menu "Class II Instructions"
config OPENRISC_HAVE_INST_FF1
bool "Have instruction l.ff1"
default y
help
Select this if your implementation has the Class II instruction l.ff1
config OPENRISC_HAVE_INST_FL1
bool "Have instruction l.fl1"
default y
help
Select this if your implementation has the Class II instruction l.fl1
config OPENRISC_HAVE_INST_MUL
bool "Have instruction l.mul for hardware multiply"
default y
help
Select this if your implementation has a hardware multiply instruction
config OPENRISC_HAVE_INST_DIV
bool "Have instruction l.div for hardware divide"
default y
help
Select this if your implementation has a hardware divide instruction
endmenu
source "kernel/time/Kconfig"
source kernel/Kconfig.hz
source kernel/Kconfig.preempt
source "mm/Kconfig"
config OPENRISC_NO_SPR_SR_DSX
bool "use SPR_SR_DSX software emulation" if OR1K_1200
default y
help
SPR_SR_DSX bit is status register bit indicating whether
the last exception has happened in delay slot.
OpenRISC architecture makes it optional to have it implemented
in hardware and the OR1200 does not have it.
Say N here if you know that your OpenRISC processor has
SPR_SR_DSX bit implemented. Say Y if you are unsure.
config CMDLINE
string "Default kernel command string"
default ""
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.
menu "Debugging options"
config DEBUG_STACKOVERFLOW
bool "Check for kernel stack overflow"
default y
help
Make extra checks for space avaliable on stack in some
critical functions. This will cause kernel to run a bit slower,
but will catch most of kernel stack overruns and exit gracefuly.
Say Y if you are unsure.
config JUMP_UPON_UNHANDLED_EXCEPTION
bool "Try to die gracefully"
default y
help
Now this puts kernel into infinite loop after first oops. Till
your kernel crashes this doesn't have any influence.
Say Y if you are unsure.
config OPENRISC_EXCEPTION_DEBUG
bool "Print processor state at each exception"
default n
help
This option will make your kernel unusable for all but kernel
debugging.
Say N if you are unsure.
config OPENRISC_ESR_EXCEPTION_BUG_CHECK
bool "Check for possible ESR exception bug"
default n
help
This option enables some checks that might expose some problems
in kernel.
Say N if you are unsure.
endmenu
endmenu
menu "Executable file formats"
source "fs/Kconfig.binfmt"
endmenu
source "net/Kconfig"
source "drivers/Kconfig"
source "fs/Kconfig"
source "security/Kconfig"
source "crypto/Kconfig"
source "lib/Kconfig"
menu "Kernel hacking"
source "lib/Kconfig.debug"
endmenu
# BK Id: %F% %I% %G% %U% %#%
#
# This file is included by the global makefile so that you can add your own
# architecture-specific flags and dependencies. Remember to do have actions
# for "archclean" and "archdep" for cleaning up and making dependencies for
# this architecture
#
# 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) 1994 by Linus Torvalds
# Modifications for the OpenRISC architecture:
# Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
# Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
#
# Based on:
# arch/i386/Makefile
KBUILD_DEFCONFIG := or1ksim_defconfig
LDFLAGS :=
OBJCOPYFLAGS := -O binary -R .note -R .comment -S
LDFLAGS_vmlinux :=
LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
KBUILD_CFLAGS += -pipe -ffixed-r10
ifeq ($(CONFIG_OPENRISC_HAVE_INST_MUL),y)
KBUILD_CFLAGS += $(call cc-option,-mhard-mul)
else
KBUILD_CFLAGS += $(call cc-option,-msoft-mul)
endif
ifeq ($(CONFIG_OPENRISC_HAVE_INST_DIV),y)
KBUILD_CFLAGS += $(call cc-option,-mhard-div)
else
KBUILD_CFLAGS += $(call cc-option,-msoft-div)
endif
head-y := arch/openrisc/kernel/head.o arch/openrisc/kernel/init_task.o
core-y += arch/openrisc/lib/ \
arch/openrisc/kernel/ \
arch/openrisc/mm/
libs-y += $(LIBGCC)
ifneq '$(CONFIG_OPENRISC_BUILTIN_DTB)' '""'
BUILTIN_DTB := y
else
BUILTIN_DTB := n
endif
core-$(BUILTIN_DTB) += arch/openrisc/boot/
all: vmlinux
OpenRISC Linux
==============
This is a port of Linux to the OpenRISC class of microprocessors; the initial
target architecture, specifically, is the 32-bit OpenRISC 1000 family (or1k).
For information about OpenRISC processors and ongoing development:
website http://openrisc.net
For more information about Linux on OpenRISC, please contact South Pole AB.
email: info@southpole.se
website: http://southpole.se
http://southpoleconsulting.com
---------------------------------------------------------------------
Build instructions for OpenRISC toolchain and Linux
===================================================
In order to build and run Linux for OpenRISC, you'll need at least a basic
toolchain and, perhaps, the architectural simulator. Steps to get these bits
in place are outlined here.
1) The toolchain can be obtained from openrisc.net. Instructions for building
a toolchain can be found at:
http://openrisc.net/toolchain-build.html
2) or1ksim (optional)
or1ksim is the architectural simulator which will allow you to actually run
your OpenRISC Linux kernel if you don't have an OpenRISC processor at hand.
git clone git://openrisc.net/jonas/or1ksim-svn
cd or1ksim
./configure --prefix=$OPENRISC_PREFIX
make
make install
3) Linux kernel
Build the kernel as usual
make ARCH=openrisc defconfig
make ARCH=openrisc
4) Run in architectural simulator
Grab the or1ksim platform configuration file (from the or1ksim source) and
together with your freshly built vmlinux, run your kernel with the following
incantation:
sim -f arch/openrisc/or1ksim.cfg vmlinux
---------------------------------------------------------------------
Terminology
===========
In the code, the following particles are used on symbols to limit the scope
to more or less specific processor implementations:
openrisc: the OpenRISC class of processors
or1k: the OpenRISC 1000 family of processors
or1200: the OpenRISC 1200 processor
---------------------------------------------------------------------
History
========
18. 11. 2003 Matjaz Breskvar (phoenix@bsemi.com)
initial port of linux to OpenRISC/or32 architecture.
all the core stuff is implemented and seams usable.
08. 12. 2003 Matjaz Breskvar (phoenix@bsemi.com)
complete change of TLB miss handling.
rewrite of exceptions handling.
fully functional sash-3.6 in default initrd.
a much improved version with changes all around.
10. 04. 2004 Matjaz Breskvar (phoenix@bsemi.com)
alot of bugfixes all over.
ethernet support, functional http and telnet servers.
running many standard linux apps.
26. 06. 2004 Matjaz Breskvar (phoenix@bsemi.com)
port to 2.6.x
30. 11. 2004 Matjaz Breskvar (phoenix@bsemi.com)
lots of bugfixes and enhancments.
added opencores framebuffer driver.
09. 10. 2010 Jonas Bonn (jonas@southpole.se)
major rewrite to bring up to par with upstream Linux 2.6.36
The OpenRISC Linux port is fully functional and has been tracking upstream
since 2.6.35. There are, however, remaining items to be completed within
the coming months. Here's a list of known-to-be-less-than-stellar items
that are due for investigation shortly, i.e. our TODO list:
-- Implement the rest of the DMA API... dma_map_sg, etc.
-- Consolidate usage of memblock and bootmem... move everything over to
memblock.
-- Finish the renaming cleanup... there are references to or32 in the code
which was an older name for the architecture. The name we've settled on is
or1k and this change is slowly trickling through the stack. For the time
being, or32 is equivalent to or1k.
-- Implement optimized version of memcpy and memset
ifneq '$(CONFIG_OPENRISC_BUILTIN_DTB)' '""'
BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_OPENRISC_BUILTIN_DTB)).dtb.o
else
BUILTIN_DTB :=
endif
obj-y += $(BUILTIN_DTB)
clean-files := *.dtb.S
#DTC_FLAGS ?= -p 1024
$(obj)/%.dtb: $(src)/dts/%.dts
$(call cmd,dtc)
/dts-v1/;
/ {
compatible = "opencores,or1ksim";
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&pic>;
chosen {
bootargs = "console=uart,mmio,0x90000000,115200";
};
memory@0 {
device_type = "memory";
reg = <0x00000000 0x02000000>;
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
compatible = "opencores,or1200-rtlsvn481";
reg = <0>;
clock-frequency = <20000000>;
};
};
/*
* OR1K PIC is built into CPU and accessed via special purpose
* registers. It is not addressable and, hence, has no 'reg'
* property.
*/
pic: pic {
compatible = "opencores,or1k-pic";
#interrupt-cells = <1>;
interrupt-controller;
};
serial0: serial@90000000 {
compatible = "opencores,uart16550-rtlsvn105", "ns16550a";
reg = <0x90000000 0x100>;
interrupts = <2>;
clock-frequency = <20000000>;
};
enet0: ethoc@92000000 {
compatible = "opencores,ethmac-rtlsvn338";
reg = <0x92000000 0x100>;
interrupts = <4>;
};
};
CONFIG_CROSS_COMPILE="or32-linux-"
CONFIG_LOG_BUF_SHIFT=14
CONFIG_BLK_DEV_INITRD=y
# CONFIG_RD_GZIP is not set
CONFIG_EXPERT=y
# CONFIG_SYSCTL_SYSCALL is not set
# CONFIG_KALLSYMS is not set
# CONFIG_EPOLL is not set
# CONFIG_TIMERFD is not set
# CONFIG_EVENTFD is not set
# CONFIG_AIO is not set
# CONFIG_VM_EVENT_COUNTERS is not set
# CONFIG_COMPAT_BRK is not set
CONFIG_SLOB=y
CONFIG_MODULES=y
# CONFIG_BLOCK is not set
CONFIG_OPENRISC_BUILTIN_DTB="or1ksim"
CONFIG_NO_HZ=y
CONFIG_HZ_100=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_INET=y
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_LRO is not set
# CONFIG_INET_DIAG is not set
CONFIG_TCP_CONG_ADVANCED=y
# CONFIG_TCP_CONG_BIC is not set
# CONFIG_TCP_CONG_CUBIC is not set
# CONFIG_TCP_CONG_WESTWOOD is not set
# CONFIG_TCP_CONG_HTCP is not set
# CONFIG_IPV6 is not set
# CONFIG_WIRELESS is not set
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
# CONFIG_FW_LOADER is not set
CONFIG_PROC_DEVICETREE=y
CONFIG_NETDEVICES=y
CONFIG_MICREL_PHY=y
CONFIG_NET_ETHERNET=y
CONFIG_ETHOC=y
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_WLAN is not set
# CONFIG_INPUT is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_DEVKMEM is not set
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_OF_PLATFORM=y
# CONFIG_HW_RANDOM is not set
# CONFIG_HWMON is not set
# CONFIG_MFD_SUPPORT is not set
# CONFIG_USB_SUPPORT is not set
# CONFIG_DNOTIFY is not set
CONFIG_TMPFS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_ENABLE_WARN_DEPRECATED is not set
# CONFIG_ENABLE_MUST_CHECK is not set
include include/asm-generic/Kbuild.asm
header-y += spr_defs.h
generic-y += atomic.h
generic-y += auxvec.h
generic-y += bitsperlong.h
generic-y += bug.h
generic-y += bugs.h
generic-y += cacheflush.h
generic-y += checksum.h
generic-y += cmpxchg.h
generic-y += cmpxchg-local.h
generic-y += cpumask.h
generic-y += cputime.h
generic-y += current.h
generic-y += device.h
generic-y += div64.h
generic-y += dma.h
generic-y += emergency-restart.h
generic-y += errno.h
generic-y += fb.h
generic-y += fcntl.h
generic-y += ftrace.h
generic-y += futex.h
generic-y += hardirq.h
generic-y += hw_irq.h
generic-y += ioctl.h
generic-y += ioctls.h
generic-y += ipcbuf.h
generic-y += irq_regs.h
generic-y += kdebug.h
generic-y += kmap_types.h
generic-y += local.h
generic-y += mman.h
generic-y += module.h
generic-y += msgbuf.h
generic-y += pci.h
generic-y += percpu.h
generic-y += poll.h
generic-y += posix_types.h
generic-y += resource.h
generic-y += rmap.h
generic-y += scatterlist.h
generic-y += sections.h
generic-y += segment.h
generic-y += sembuf.h
generic-y += setup.h
generic-y += shmbuf.h
generic-y += shmparam.h
generic-y += siginfo.h
generic-y += signal.h
generic-y += socket.h
generic-y += sockios.h
generic-y += statfs.h
generic-y += stat.h
generic-y += string.h
generic-y += swab.h
generic-y += termbits.h
generic-y += termios.h
generic-y += topology.h
generic-y += types.h
generic-y += ucontext.h
generic-y += user.h
#include <generated/asm-offsets.h>
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_BITOPS_H
#define __ASM_OPENRISC_BITOPS_H
/*
* Where we haven't written assembly versions yet, we fall back to the
* generic implementations. Otherwise, we pull in our (hopefully)
* optimized versions.
*/
#include <linux/irqflags.h>
#include <linux/compiler.h>
/*
* clear_bit may not imply a memory barrier
*/
#ifndef smp_mb__before_clear_bit
#define smp_mb__before_clear_bit() smp_mb()
#define smp_mb__after_clear_bit() smp_mb()
#endif
#include <asm/bitops/__ffs.h>
#include <asm-generic/bitops/ffz.h>
#include <asm/bitops/fls.h>
#include <asm/bitops/__fls.h>
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/find.h>
#ifndef _LINUX_BITOPS_H
#error only <linux/bitops.h> can be included directly
#endif
#include <asm-generic/bitops/sched.h>
#include <asm/bitops/ffs.h>
#include <asm-generic/bitops/hweight.h>
#include <asm-generic/bitops/lock.h>
#include <asm-generic/bitops/atomic.h>
#include <asm-generic/bitops/non-atomic.h>
#include <asm-generic/bitops/ext2-atomic.h>
#endif /* __ASM_GENERIC_BITOPS_H */
/*
* OpenRISC Linux
*
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
*
* 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_OPENRISC___FFS_H
#define __ASM_OPENRISC___FFS_H
#ifdef CONFIG_OPENRISC_HAVE_INST_FF1
static inline unsigned long __ffs(unsigned long x)
{
int ret;
__asm__ ("l.ff1 %0,%1"
: "=r" (ret)
: "r" (x));
return ret-1;
}
#else
#include <asm-generic/bitops/__ffs.h>
#endif
#endif /* __ASM_OPENRISC___FFS_H */
/*
* OpenRISC Linux
*
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
*
* 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_OPENRISC___FLS_H
#define __ASM_OPENRISC___FLS_H
#ifdef CONFIG_OPENRISC_HAVE_INST_FL1
static inline unsigned long __fls(unsigned long x)
{
int ret;
__asm__ ("l.fl1 %0,%1"
: "=r" (ret)
: "r" (x));
return ret-1;
}
#else
#include <asm-generic/bitops/__fls.h>
#endif
#endif /* __ASM_OPENRISC___FLS_H */
/*
* OpenRISC Linux
*
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
*
* 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_OPENRISC_FFS_H
#define __ASM_OPENRISC_FFS_H
#ifdef CONFIG_OPENRISC_HAVE_INST_FF1
static inline int ffs(int x)
{
int ret;
__asm__ ("l.ff1 %0,%1"
: "=r" (ret)
: "r" (x));
return ret;
}
#else
#include <asm-generic/bitops/ffs.h>
#endif
#endif /* __ASM_OPENRISC_FFS_H */
/*
* OpenRISC Linux
*
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
*
* 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_OPENRISC_FLS_H
#define __ASM_OPENRISC_FLS_H
#ifdef CONFIG_OPENRISC_HAVE_INST_FL1
static inline int fls(int x)
{
int ret;
__asm__ ("l.fl1 %0,%1"
: "=r" (ret)
: "r" (x));
return ret;
}
#else
#include <asm-generic/bitops/fls.h>
#endif
#endif /* __ASM_OPENRISC_FLS_H */
#include <linux/byteorder/big_endian.h>
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_CACHE_H
#define __ASM_OPENRISC_CACHE_H
/* FIXME: How can we replace these with values from the CPU...
* they shouldn't be hard-coded!
*/
#define L1_CACHE_BYTES 16
#define L1_CACHE_SHIFT 4
#endif /* __ASM_OPENRISC_CACHE_H */
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_CPUINFO_H
#define __ASM_OPENRISC_CPUINFO_H
struct cpuinfo {
u32 clock_frequency;
u32 icache_size;
u32 icache_block_size;
u32 dcache_size;
u32 dcache_block_size;
};
extern struct cpuinfo cpuinfo;
#endif /* __ASM_OPENRISC_CPUINFO_H */
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
*
* 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_OPENRISC_DELAY_H
#define __ASM_OPENRISC_DELAY_H
#include <asm-generic/delay.h>
extern unsigned long loops_per_jiffy;
#endif
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
*
* 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_OPENRISC_DMA_MAPPING_H
#define __ASM_OPENRISC_DMA_MAPPING_H
/*
* See Documentation/PCI/PCI-DMA-mapping.txt and
* Documentation/DMA-API.txt for documentation.
*
* This file is written with the intention of eventually moving over
* to largely using asm-generic/dma-mapping-common.h in its place.
*/
#include <linux/dma-debug.h>
#include <asm-generic/dma-coherent.h>
#include <linux/kmemcheck.h>
#define DMA_ERROR_CODE (~(dma_addr_t)0x0)
int dma_mapping_error(struct device *dev, dma_addr_t dma_addr);
#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)
void *or1k_dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag);
void or1k_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_handle);
dma_addr_t or1k_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
struct dma_attrs *attrs);
void or1k_unmap_page(struct device *dev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction dir,
struct dma_attrs *attrs);
void or1k_sync_single_for_cpu(struct device *dev,
dma_addr_t dma_handle, size_t size,
enum dma_data_direction dir);
void or1k_sync_single_for_device(struct device *dev,
dma_addr_t dma_handle, size_t size,
enum dma_data_direction dir);
static inline void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
{
void *memory;
memory = or1k_dma_alloc_coherent(dev, size, dma_handle, flag);
debug_dma_alloc_coherent(dev, size, *dma_handle, memory);
return memory;
}
static inline void dma_free_coherent(struct device *dev, size_t size,
void *cpu_addr, dma_addr_t dma_handle)
{
debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
or1k_dma_free_coherent(dev, size, cpu_addr, dma_handle);
}
static inline dma_addr_t dma_map_single(struct device *dev, void *ptr,
size_t size,
enum dma_data_direction dir)
{
dma_addr_t addr;
kmemcheck_mark_initialized(ptr, size);
BUG_ON(!valid_dma_direction(dir));
addr = or1k_map_page(dev, virt_to_page(ptr),
(unsigned long)ptr & ~PAGE_MASK, size,
dir, NULL);
debug_dma_map_page(dev, virt_to_page(ptr),
(unsigned long)ptr & ~PAGE_MASK, size,
dir, addr, true);
return addr;
}
static inline void dma_unmap_single(struct device *dev, dma_addr_t addr,
size_t size,
enum dma_data_direction dir)
{
BUG_ON(!valid_dma_direction(dir));
or1k_unmap_page(dev, addr, size, dir, NULL);
debug_dma_unmap_page(dev, addr, size, dir, true);
}
static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
size_t size,
enum dma_data_direction dir)
{
BUG_ON(!valid_dma_direction(dir));
or1k_sync_single_for_cpu(dev, addr, size, dir);
debug_dma_sync_single_for_cpu(dev, addr, size, dir);
}
static inline void dma_sync_single_for_device(struct device *dev,
dma_addr_t addr, size_t size,
enum dma_data_direction dir)
{
BUG_ON(!valid_dma_direction(dir));
or1k_sync_single_for_device(dev, addr, size, dir);
debug_dma_sync_single_for_device(dev, addr, size, dir);
}
static inline int dma_supported(struct device *dev, u64 dma_mask)
{
/* Support 32 bit DMA mask exclusively */
return dma_mask == 0xffffffffULL;
}
static inline int dma_set_mask(struct device *dev, u64 dma_mask)
{
if (!dev->dma_mask || !dma_supported(dev, dma_mask))
return -EIO;
*dev->dma_mask = dma_mask;
return 0;
}
#endif /* __ASM_OPENRISC_DMA_MAPPING_H */
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_ELF_H
#define __ASM_OPENRISC_ELF_H
/*
* ELF register definitions..
*/
#include <linux/types.h>
#include <linux/ptrace.h>
/* The OR1K relocation types... not all relevant for module loader */
#define R_OR32_NONE 0
#define R_OR32_32 1
#define R_OR32_16 2
#define R_OR32_8 3
#define R_OR32_CONST 4
#define R_OR32_CONSTH 5
#define R_OR32_JUMPTARG 6
#define R_OR32_VTINHERIT 7
#define R_OR32_VTENTRY 8
typedef unsigned long elf_greg_t;
/*
* Note that NGREG is defined to ELF_NGREG in include/linux/elfcore.h, and is
* thus exposed to user-space.
*/
#define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t))
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
/* A placeholder; OR32 does not have fp support yes, so no fp regs for now. */
typedef unsigned long elf_fpregset_t;
/* This should be moved to include/linux/elf.h */
#define EM_OR32 0x8472
#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */
/*
* These are used to set parameters in the core dumps.
*/
#define ELF_ARCH EM_OR32
#define ELF_CLASS ELFCLASS32
#define ELF_DATA ELFDATA2MSB
#ifdef __KERNEL__
/*
* This is used to ensure we don't load something for the wrong architecture.
*/
#define elf_check_arch(x) \
(((x)->e_machine == EM_OR32) || ((x)->e_machine == EM_OPENRISC))
/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
use of this is to invoke "./ld.so someprog" to test out a new version of
the loader. We need to make sure that it is out of the way of the program
that it will "exec", and that there is sufficient room for the brk. */
#define ELF_ET_DYN_BASE (0x08000000)
/*
* Enable dump using regset.
* This covers all of general/DSP/FPU regs.
*/
#define CORE_DUMP_USE_REGSET
#define ELF_EXEC_PAGESIZE 8192
extern void dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt);
#define ELF_CORE_COPY_REGS(dest, regs) dump_elf_thread(dest, regs);
/* This yields a mask that user programs can use to figure out what
instruction set this cpu supports. This could be done in userspace,
but it's not easy, and we've already done it here. */
#define ELF_HWCAP (0)
/* This yields a string that ld.so will use to load implementation
specific libraries for optimization. This is more specific in
intent than poking at uname or /proc/cpuinfo.
For the moment, we have only optimizations for the Intel generations,
but that could change... */
#define ELF_PLATFORM (NULL)
#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
#endif /* __KERNEL__ */
#endif
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_FIXMAP_H
#define __ASM_OPENRISC_FIXMAP_H
/* Why exactly do we need 2 empty pages between the top of the fixed
* addresses and the top of virtual memory? Something is using that
* memory space but not sure what right now... If you find it, leave
* a comment here.
*/
#define FIXADDR_TOP ((unsigned long) (-2*PAGE_SIZE))
#include <linux/kernel.h>
#include <asm/page.h>
/*
* On OpenRISC we use these special fixed_addresses for doing ioremap
* early in the boot process before memory initialization is complete.
* This is used, in particular, by the early serial console code.
*
* It's not really 'fixmap', per se, but fits loosely into the same
* paradigm.
*/
enum fixed_addresses {
/*
* FIX_IOREMAP entries are useful for mapping physical address
* space before ioremap() is useable, e.g. really early in boot
* before kmalloc() is working.
*/
#define FIX_N_IOREMAPS 32
FIX_IOREMAP_BEGIN,
FIX_IOREMAP_END = FIX_IOREMAP_BEGIN + FIX_N_IOREMAPS - 1,
__end_of_fixed_addresses
};
#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
/* FIXADDR_BOTTOM might be a better name here... */
#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
/*
* 'index to address' translation. If anyone tries to use the idx
* directly without tranlation, we catch the bug with a NULL-deference
* kernel oops. Illegal ranges of incoming indices are caught too.
*/
static __always_inline unsigned long fix_to_virt(const unsigned int idx)
{
/*
* this branch gets completely eliminated after inlining,
* except when someone tries to use fixaddr indices in an
* illegal way. (such as mixing up address types or using
* out-of-range indices).
*
* If it doesn't get removed, the linker will complain
* loudly with a reasonably clear error message..
*/
if (idx >= __end_of_fixed_addresses)
BUG();
return __fix_to_virt(idx);
}
static inline unsigned long virt_to_fix(const unsigned long vaddr)
{
BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
return __virt_to_fix(vaddr);
}
#endif
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_GPIO_H
#define __ASM_OPENRISC_GPIO_H
#include <linux/errno.h>
#include <asm-generic/gpio.h>
#ifdef CONFIG_GPIOLIB
/*
* OpenRISC (or1k) does not have on-chip GPIO's so there is not really
* any standardized implementation that makes sense here. If passing
* through gpiolib becomes a bottleneck then it may make sense, on a
* case-by-case basis, to implement these inlined/rapid versions.
*
* 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_OPENRISC_GPIO_H */
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_IO_H
#define __ASM_OPENRISC_IO_H
/*
* PCI: can we really do 0 here if we have no port IO?
*/
#define IO_SPACE_LIMIT 0
/* OpenRISC has no port IO */
#define HAVE_ARCH_PIO_SIZE 1
#define PIO_RESERVED 0X0UL
#define PIO_OFFSET 0
#define PIO_MASK 0
#include <asm-generic/io.h>
extern void __iomem *__ioremap(phys_addr_t offset, unsigned long size,
pgprot_t prot);
static inline void __iomem *ioremap(phys_addr_t offset, unsigned long size)
{
return __ioremap(offset, size, PAGE_KERNEL);
}
/* #define _PAGE_CI 0x002 */
static inline void __iomem *ioremap_nocache(phys_addr_t offset,
unsigned long size)
{
return __ioremap(offset, size,
__pgprot(pgprot_val(PAGE_KERNEL) | _PAGE_CI));
}
extern void iounmap(void *addr);
#endif
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_IRQ_H__
#define __ASM_OPENRISC_IRQ_H__
#define NR_IRQS 32
#include <asm-generic/irq.h>
#define NO_IRQ (-1)
#endif /* __ASM_OPENRISC_IRQ_H__ */
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_IRQFLAGS_H
#define ___ASM_OPENRISC_IRQFLAGS_H
#include <asm/spr_defs.h>
#define ARCH_IRQ_DISABLED 0x00
#define ARCH_IRQ_ENABLED (SPR_SR_IEE|SPR_SR_TEE)
#include <asm-generic/irqflags.h>
#endif /* ___ASM_OPENRISC_IRQFLAGS_H */
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_LINKAGE_H
#define __ASM_OPENRISC_LINKAGE_H
#define __ALIGN .align 0
#define __ALIGN_STR ".align 0"
#endif /* __ASM_OPENRISC_LINKAGE_H */
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_MEMBLOCK_H
#define __ASM_OPENRISC_MEMBLOCK_H
/* empty */
#endif /* __ASM_OPENRISC_MEMBLOCK_H */
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_MMU_H
#define __ASM_OPENRISC_MMU_H
#ifndef __ASSEMBLY__
typedef unsigned long mm_context_t;
#endif
#endif
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_MMU_CONTEXT_H
#define __ASM_OPENRISC_MMU_CONTEXT_H
#include <asm-generic/mm_hooks.h>
extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
extern void destroy_context(struct mm_struct *mm);
extern void switch_mm(struct mm_struct *prev, struct mm_struct *next,
struct task_struct *tsk);
#define deactivate_mm(tsk, mm) do { } while (0)
#define activate_mm(prev, next) switch_mm((prev), (next), NULL)
/* current active pgd - this is similar to other processors pgd
* registers like cr3 on the i386
*/
extern volatile pgd_t *current_pgd; /* defined in arch/openrisc/mm/fault.c */
static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
}
#endif
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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.
*/
/*
* Pull in the generic implementation for the mutex fastpath.
*
* TODO: implement optimized primitives instead, or leave the generic
* implementation in place, or pick the atomic_xchg() based generic
* implementation. (see asm-generic/mutex-xchg.h for details)
*/
#include <asm-generic/mutex-dec.h>
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_PAGE_H
#define __ASM_OPENRISC_PAGE_H
/* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT 13
#ifdef __ASSEMBLY__
#define PAGE_SIZE (1 << PAGE_SHIFT)
#else
#define PAGE_SIZE (1UL << PAGE_SHIFT)
#endif
#define PAGE_MASK (~(PAGE_SIZE-1))
#define PAGE_OFFSET 0xc0000000
#define KERNELBASE PAGE_OFFSET
/* This is not necessarily the right place for this, but it's needed by
* drivers/of/fdt.c
*/
#include <asm/setup.h>
#ifndef __ASSEMBLY__
#define get_user_page(vaddr) __get_free_page(GFP_KERNEL)
#define free_user_page(page, addr) free_page(addr)
#define clear_page(page) memset((page), 0, PAGE_SIZE)
#define copy_page(to, from) memcpy((to), (from), PAGE_SIZE)
#define clear_user_page(page, vaddr, pg) clear_page(page)
#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
/*
* These are used to make use of C type-checking..
*/
typedef struct {
unsigned long pte;
} pte_t;
typedef struct {
unsigned long pgd;
} pgd_t;
typedef struct {
unsigned long pgprot;
} pgprot_t;
typedef struct page *pgtable_t;
#define pte_val(x) ((x).pte)
#define pgd_val(x) ((x).pgd)
#define pgprot_val(x) ((x).pgprot)
#define __pte(x) ((pte_t) { (x) })
#define __pgd(x) ((pgd_t) { (x) })
#define __pgprot(x) ((pgprot_t) { (x) })
extern unsigned long memory_start;
extern unsigned long memory_end;
#endif /* !__ASSEMBLY__ */
#ifndef __ASSEMBLY__
#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET))
#define __pa(x) ((unsigned long) (x) - PAGE_OFFSET)
#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT)
#define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT)
#define virt_to_page(addr) \
(mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT))
#define page_to_virt(page) \
((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
#define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
#define pfn_valid(pfn) ((pfn) < max_mapnr)
#define virt_addr_valid(kaddr) (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \
((void *)(kaddr) < (void *)memory_end))
#endif /* __ASSEMBLY__ */
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
#include <asm-generic/memory_model.h>
#include <asm-generic/getorder.h>
#endif /* __ASM_OPENRISC_PAGE_H */
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_PARAM_H
#define __ASM_OPENRISC_PARAM_H
#define EXEC_PAGESIZE 8192
#include <asm-generic/param.h>
#endif /* __ASM_OPENRISC_PARAM_H */
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_PGALLOC_H
#define __ASM_OPENRISC_PGALLOC_H
#include <asm/page.h>
#include <linux/threads.h>
#include <linux/mm.h>
#include <linux/memblock.h>
#include <linux/bootmem.h>
extern int mem_init_done;
#define pmd_populate_kernel(mm, pmd, pte) \
set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte)))
static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
struct page *pte)
{
set_pmd(pmd, __pmd(_KERNPG_TABLE +
((unsigned long)page_to_pfn(pte) <<
(unsigned long) PAGE_SHIFT)));
}
/*
* Allocate and free page tables.
*/
static inline pgd_t *pgd_alloc(struct mm_struct *mm)
{
pgd_t *ret = (pgd_t *)__get_free_page(GFP_KERNEL);
if (ret) {
memset(ret, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
memcpy(ret + USER_PTRS_PER_PGD,
swapper_pg_dir + USER_PTRS_PER_PGD,
(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
}
return ret;
}
#if 0
/* FIXME: This seems to be the preferred style, but we are using
* current_pgd (from mm->pgd) to load kernel pages so we need it
* initialized. This needs to be looked into.
*/
extern inline pgd_t *pgd_alloc(struct mm_struct *mm)
{
return (pgd_t *)get_zeroed_page(GFP_KERNEL);
}
#endif
static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{
free_page((unsigned long)pgd);
}
extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address);
static inline struct page *pte_alloc_one(struct mm_struct *mm,
unsigned long address)
{
struct page *pte;
pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0);
if (pte)
clear_page(page_address(pte));
return pte;
}
static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
{
free_page((unsigned long)pte);
}
static inline void pte_free(struct mm_struct *mm, struct page *pte)
{
__free_page(pte);
}
#define __pte_free_tlb(tlb, pte, addr) tlb_remove_page((tlb), (pte))
#define pmd_pgtable(pmd) pmd_page(pmd)
#define check_pgt_cache() do { } while (0)
#endif
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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.
*/
/* or32 pgtable.h - macros and functions to manipulate page tables
*
* Based on:
* include/asm-cris/pgtable.h
*/
#ifndef __ASM_OPENRISC_PGTABLE_H
#define __ASM_OPENRISC_PGTABLE_H
#include <asm-generic/pgtable-nopmd.h>
#ifndef __ASSEMBLY__
#include <asm/mmu.h>
#include <asm/fixmap.h>
/*
* The Linux memory management assumes a three-level page table setup. On
* or32, we use that, but "fold" the mid level into the top-level page
* table. Since the MMU TLB is software loaded through an interrupt, it
* supports any page table structure, so we could have used a three-level
* setup, but for the amounts of memory we normally use, a two-level is
* probably more efficient.
*
* This file contains the functions and defines necessary to modify and use
* the or32 page table tree.
*/
extern void paging_init(void);
/* Certain architectures need to do special things when pte's
* within a page table are directly modified. Thus, the following
* hook is made available.
*/
#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval)
/*
* (pmds are folded into pgds so this doesn't get actually called,
* but the define is needed for a generic inline function.)
*/
#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval)
#define PGDIR_SHIFT (PAGE_SHIFT + (PAGE_SHIFT-2))
#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
#define PGDIR_MASK (~(PGDIR_SIZE-1))
/*
* entries per page directory level: we use a two-level, so
* we don't really have any PMD directory physically.
* pointers are 4 bytes so we can use the page size and
* divide it by 4 (shift by 2).
*/
#define PTRS_PER_PTE (1UL << (PAGE_SHIFT-2))
#define PTRS_PER_PGD (1UL << (PAGE_SHIFT-2))
/* calculate how many PGD entries a user-level program can use
* the first mappable virtual address is 0
* (TASK_SIZE is the maximum virtual address space)
*/
#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
#define FIRST_USER_ADDRESS 0
/*
* Kernels own virtual memory area.
*/
/*
* The size and location of the vmalloc area are chosen so that modules
* placed in this area aren't more than a 28-bit signed offset from any
* kernel functions that they may need. This greatly simplifies handling
* of the relocations for l.j and l.jal instructions as we don't need to
* introduce any trampolines for reaching "distant" code.
*
* 64 MB of vmalloc area is comparable to what's available on other arches.
*/
#define VMALLOC_START (PAGE_OFFSET-0x04000000)
#define VMALLOC_END (PAGE_OFFSET)
#define VMALLOC_VMADDR(x) ((unsigned long)(x))
/* Define some higher level generic page attributes.
*
* If you change _PAGE_CI definition be sure to change it in
* io.h for ioremap_nocache() too.
*/
/*
* An OR32 PTE looks like this:
*
* | 31 ... 10 | 9 | 8 ... 6 | 5 | 4 | 3 | 2 | 1 | 0 |
* Phys pg.num L PP Index D A WOM WBC CI CC
*
* L : link
* PPI: Page protection index
* D : Dirty
* A : Accessed
* WOM: Weakly ordered memory
* WBC: Write-back cache
* CI : Cache inhibit
* CC : Cache coherent
*
* The protection bits below should correspond to the layout of the actual
* PTE as per above
*/
#define _PAGE_CC 0x001 /* software: pte contains a translation */
#define _PAGE_CI 0x002 /* cache inhibit */
#define _PAGE_WBC 0x004 /* write back cache */
#define _PAGE_FILE 0x004 /* set: pagecache, unset: swap (when !PRESENT) */
#define _PAGE_WOM 0x008 /* weakly ordered memory */
#define _PAGE_A 0x010 /* accessed */
#define _PAGE_D 0x020 /* dirty */
#define _PAGE_URE 0x040 /* user read enable */
#define _PAGE_UWE 0x080 /* user write enable */
#define _PAGE_SRE 0x100 /* superuser read enable */
#define _PAGE_SWE 0x200 /* superuser write enable */
#define _PAGE_EXEC 0x400 /* software: page is executable */
#define _PAGE_U_SHARED 0x800 /* software: page is shared in user space */
/* 0x001 is cache coherency bit, which should always be set to
* 1 - for SMP (when we support it)
* 0 - otherwise
*
* we just reuse this bit in software for _PAGE_PRESENT and
* force it to 0 when loading it into TLB.
*/
#define _PAGE_PRESENT _PAGE_CC
#define _PAGE_USER _PAGE_URE
#define _PAGE_WRITE (_PAGE_UWE | _PAGE_SWE)
#define _PAGE_DIRTY _PAGE_D
#define _PAGE_ACCESSED _PAGE_A
#define _PAGE_NO_CACHE _PAGE_CI
#define _PAGE_SHARED _PAGE_U_SHARED
#define _PAGE_READ (_PAGE_URE | _PAGE_SRE)
#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
#define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED)
#define _PAGE_ALL (_PAGE_PRESENT | _PAGE_ACCESSED)
#define _KERNPG_TABLE \
(_PAGE_BASE | _PAGE_SRE | _PAGE_SWE | _PAGE_ACCESSED | _PAGE_DIRTY)
#define PAGE_NONE __pgprot(_PAGE_ALL)
#define PAGE_READONLY __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE)
#define PAGE_READONLY_X __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE | _PAGE_EXEC)
#define PAGE_SHARED \
__pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE | _PAGE_UWE | _PAGE_SWE \
| _PAGE_SHARED)
#define PAGE_SHARED_X \
__pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE | _PAGE_UWE | _PAGE_SWE \
| _PAGE_SHARED | _PAGE_EXEC)
#define PAGE_COPY __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE)
#define PAGE_COPY_X __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE | _PAGE_EXEC)
#define PAGE_KERNEL \
__pgprot(_PAGE_ALL | _PAGE_SRE | _PAGE_SWE \
| _PAGE_SHARED | _PAGE_DIRTY | _PAGE_EXEC)
#define PAGE_KERNEL_RO \
__pgprot(_PAGE_ALL | _PAGE_SRE \
| _PAGE_SHARED | _PAGE_DIRTY | _PAGE_EXEC)
#define PAGE_KERNEL_NOCACHE \
__pgprot(_PAGE_ALL | _PAGE_SRE | _PAGE_SWE \
| _PAGE_SHARED | _PAGE_DIRTY | _PAGE_EXEC | _PAGE_CI)
#define __P000 PAGE_NONE
#define __P001 PAGE_READONLY_X
#define __P010 PAGE_COPY
#define __P011 PAGE_COPY_X
#define __P100 PAGE_READONLY
#define __P101 PAGE_READONLY_X
#define __P110 PAGE_COPY
#define __P111 PAGE_COPY_X
#define __S000 PAGE_NONE
#define __S001 PAGE_READONLY_X
#define __S010 PAGE_SHARED
#define __S011 PAGE_SHARED_X
#define __S100 PAGE_READONLY
#define __S101 PAGE_READONLY_X
#define __S110 PAGE_SHARED
#define __S111 PAGE_SHARED_X
/* zero page used for uninitialized stuff */
extern unsigned long empty_zero_page[2048];
#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
/* number of bits that fit into a memory pointer */
#define BITS_PER_PTR (8*sizeof(unsigned long))
/* to align the pointer to a pointer address */
#define PTR_MASK (~(sizeof(void *)-1))
/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
/* 64-bit machines, beware! SRB. */
#define SIZEOF_PTR_LOG2 2
/* to find an entry in a page-table */
#define PAGE_PTR(address) \
((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
/* to set the page-dir */
#define SET_PAGE_DIR(tsk, pgdir)
#define pte_none(x) (!pte_val(x))
#define pte_present(x) (pte_val(x) & _PAGE_PRESENT)
#define pte_clear(mm, addr, xp) do { pte_val(*(xp)) = 0; } while (0)
#define pmd_none(x) (!pmd_val(x))
#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK)) != _KERNPG_TABLE)
#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
#define pmd_clear(xp) do { pmd_val(*(xp)) = 0; } while (0)
/*
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_EXEC; }
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
static inline int pte_special(pte_t pte) { return 0; }
static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
static inline pte_t pte_wrprotect(pte_t pte)
{
pte_val(pte) &= ~(_PAGE_WRITE);
return pte;
}
static inline pte_t pte_rdprotect(pte_t pte)
{
pte_val(pte) &= ~(_PAGE_READ);
return pte;
}
static inline pte_t pte_exprotect(pte_t pte)
{
pte_val(pte) &= ~(_PAGE_EXEC);
return pte;
}
static inline pte_t pte_mkclean(pte_t pte)
{
pte_val(pte) &= ~(_PAGE_DIRTY);
return pte;
}
static inline pte_t pte_mkold(pte_t pte)
{
pte_val(pte) &= ~(_PAGE_ACCESSED);
return pte;
}
static inline pte_t pte_mkwrite(pte_t pte)
{
pte_val(pte) |= _PAGE_WRITE;
return pte;
}
static inline pte_t pte_mkread(pte_t pte)
{
pte_val(pte) |= _PAGE_READ;
return pte;
}
static inline pte_t pte_mkexec(pte_t pte)
{
pte_val(pte) |= _PAGE_EXEC;
return pte;
}
static inline pte_t pte_mkdirty(pte_t pte)
{
pte_val(pte) |= _PAGE_DIRTY;
return pte;
}
static inline pte_t pte_mkyoung(pte_t pte)
{
pte_val(pte) |= _PAGE_ACCESSED;
return pte;
}
/*
* Conversion functions: convert a page and protection to a page entry,
* and a page entry and page directory to the page they refer to.
*/
/* What actually goes as arguments to the various functions is less than
* obvious, but a rule of thumb is that struct page's goes as struct page *,
* really physical DRAM addresses are unsigned long's, and DRAM "virtual"
* addresses (the 0xc0xxxxxx's) goes as void *'s.
*/
static inline pte_t __mk_pte(void *page, pgprot_t pgprot)
{
pte_t pte;
/* the PTE needs a physical address */
pte_val(pte) = __pa(page) | pgprot_val(pgprot);
return pte;
}
#define mk_pte(page, pgprot) __mk_pte(page_address(page), (pgprot))
#define mk_pte_phys(physpage, pgprot) \
({ \
pte_t __pte; \
\
pte_val(__pte) = (physpage) + pgprot_val(pgprot); \
__pte; \
})
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
return pte;
}
/*
* pte_val refers to a page in the 0x0xxxxxxx physical DRAM interval
* __pte_page(pte_val) refers to the "virtual" DRAM interval
* pte_pagenr refers to the page-number counted starting from the virtual
* DRAM start
*/
static inline unsigned long __pte_page(pte_t pte)
{
/* the PTE contains a physical address */
return (unsigned long)__va(pte_val(pte) & PAGE_MASK);
}
#define pte_pagenr(pte) ((__pte_page(pte) - PAGE_OFFSET) >> PAGE_SHIFT)
/* permanent address of a page */
#define __page_address(page) (PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT))
#define pte_page(pte) (mem_map+pte_pagenr(pte))
/*
* only the pte's themselves need to point to physical DRAM (see above)
* the pagetable links are purely handled within the kernel SW and thus
* don't need the __pa and __va transformations.
*/
static inline void pmd_set(pmd_t *pmdp, pte_t *ptep)
{
pmd_val(*pmdp) = _KERNPG_TABLE | (unsigned long) ptep;
}
#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
#define pmd_page_kernel(pmd) ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
/* to find an entry in a page-table-directory. */
#define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
#define __pgd_offset(address) pgd_index(address)
#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
/* to find an entry in a kernel page-table-directory */
#define pgd_offset_k(address) pgd_offset(&init_mm, address)
#define __pmd_offset(address) \
(((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
/*
* the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE]
*
* this macro returns the index of the entry in the pte page which would
* control the given virtual address
*/
#define __pte_offset(address) \
(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
#define pte_offset_kernel(dir, address) \
((pte_t *) pmd_page_kernel(*(dir)) + __pte_offset(address))
#define pte_offset_map(dir, address) \
((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
#define pte_offset_map_nested(dir, address) \
pte_offset_map(dir, address)
#define pte_unmap(pte) do { } while (0)
#define pte_unmap_nested(pte) do { } while (0)
#define pte_pfn(x) ((unsigned long)(((x).pte)) >> PAGE_SHIFT)
#define pfn_pte(pfn, prot) __pte((((pfn) << PAGE_SHIFT)) | pgprot_val(prot))
#define pte_ERROR(e) \
printk(KERN_ERR "%s:%d: bad pte %p(%08lx).\n", \
__FILE__, __LINE__, &(e), pte_val(e))
#define pgd_ERROR(e) \
printk(KERN_ERR "%s:%d: bad pgd %p(%08lx).\n", \
__FILE__, __LINE__, &(e), pgd_val(e))
extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; /* defined in head.S */
/*
* or32 doesn't have any external MMU info: the kernel page
* tables contain all the necessary information.
*
* Actually I am not sure on what this could be used for.
*/
static inline void update_mmu_cache(struct vm_area_struct *vma,
unsigned long address, pte_t *pte)
{
}
/* __PHX__ FIXME, SWAP, this probably doesn't work */
/* Encode and de-code a swap entry (must be !pte_none(e) && !pte_present(e)) */
/* Since the PAGE_PRESENT bit is bit 4, we can use the bits above */
#define __swp_type(x) (((x).val >> 5) & 0x7f)
#define __swp_offset(x) ((x).val >> 12)
#define __swp_entry(type, offset) \
((swp_entry_t) { ((type) << 5) | ((offset) << 12) })
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
/* Encode and decode a nonlinear file mapping entry */
#define PTE_FILE_MAX_BITS 26
#define pte_to_pgoff(x) (pte_val(x) >> 6)
#define pgoff_to_pte(x) __pte(((x) << 6) | _PAGE_FILE)
#define kern_addr_valid(addr) (1)
#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
remap_pfn_range(vma, vaddr, pfn, size, prot)
#include <asm-generic/pgtable.h>
/*
* No page table caches to initialise
*/
#define pgtable_cache_init() do { } while (0)
#define io_remap_page_range remap_page_range
typedef pte_t *pte_addr_t;
#endif /* __ASSEMBLY__ */
#endif /* __ASM_OPENRISC_PGTABLE_H */
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_PROCESSOR_H
#define __ASM_OPENRISC_PROCESSOR_H
#include <asm/spr_defs.h>
#include <asm/page.h>
#include <asm/ptrace.h>
#define STACK_TOP TASK_SIZE
#define STACK_TOP_MAX STACK_TOP
/* Kernel and user SR register setting */
#define KERNEL_SR (SPR_SR_DME | SPR_SR_IME | SPR_SR_ICE \
| SPR_SR_DCE | SPR_SR_SM)
#define USER_SR (SPR_SR_DME | SPR_SR_IME | SPR_SR_ICE \
| SPR_SR_DCE | SPR_SR_IEE | SPR_SR_TEE)
/*
* Default implementation of macro that returns current
* instruction pointer ("program counter").
*/
#define current_text_addr() ({ __label__ _l; _l: &&_l; })
/*
* User space process size. This is hardcoded into a few places,
* so don't change it unless you know what you are doing.
*/
#define TASK_SIZE (0x80000000UL)
/* This decides where the kernel will search for a free chunk of vm
* space during mmap's.
*/
#define TASK_UNMAPPED_BASE (TASK_SIZE / 8 * 3)
#ifndef __ASSEMBLY__
struct task_struct;
struct thread_struct {
};
/*
* At user->kernel entry, the pt_regs struct is stacked on the top of the
* kernel-stack. This macro allows us to find those regs for a task.
* Notice that subsequent pt_regs stackings, like recursive interrupts
* occurring while we're in the kernel, won't affect this - only the first
* user->kernel transition registers are reached by this (i.e. not regs
* for running signal handler)
*/
#define user_regs(thread_info) (((struct pt_regs *)((unsigned long)(thread_info) + THREAD_SIZE - STACK_FRAME_OVERHEAD)) - 1)
/*
* Dito but for the currently running task
*/
#define task_pt_regs(task) user_regs(task_thread_info(task))
#define current_regs() user_regs(current_thread_info())
extern inline void prepare_to_copy(struct task_struct *tsk)
{
}
#define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack)
#define INIT_THREAD { }
#define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc);
#define KSTK_ESP(tsk) (task_pt_regs(tsk)->sp);
extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp);
void release_thread(struct task_struct *);
unsigned long get_wchan(struct task_struct *p);
/*
* Free current thread data structures etc..
*/
extern inline void exit_thread(void)
{
/* Nothing needs to be done. */
}
/*
* Return saved PC of a blocked thread. For now, this is the "user" PC
*/
extern unsigned long thread_saved_pc(struct task_struct *t);
#define init_stack (init_thread_union.stack)
#define cpu_relax() do { } while (0)
#endif /* __ASSEMBLY__ */
#endif /* __ASM_OPENRISC_PROCESSOR_H */
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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 <linux/of.h> /* linux/of.h gets to determine #include ordering */
#ifndef _ASM_OPENRISC_PROM_H
#define _ASM_OPENRISC_PROM_H
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
#include <linux/types.h>
#include <asm/irq.h>
#include <linux/atomic.h>
#include <linux/of_irq.h>
#include <linux/of_fdt.h>
#include <linux/of_address.h>
#include <linux/proc_fs.h>
#include <linux/platform_device.h>
#define HAVE_ARCH_DEVTREE_FIXUPS
/* Other Prototypes */
extern int early_uartlite_console(void);
/* 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_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);
/* This routine is here to provide compatibility with how powerpc
* handles IRQ mapping for OF device nodes. We precompute and permanently
* register them in the platform_device objects, whereas powerpc computes them
* on request.
*/
static inline void irq_dispose_mapping(unsigned int virq)
{
}
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
#endif /* _ASM_OPENRISC_PROM_H */
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_PTRACE_H
#define __ASM_OPENRISC_PTRACE_H
#include <asm/spr_defs.h>
#ifndef __ASSEMBLY__
/*
* This is the layout of the regset returned by the GETREGSET ptrace call
*/
struct user_regs_struct {
/* GPR R0-R31... */
unsigned long gpr[32];
unsigned long pc;
unsigned long sr;
unsigned long pad1;
unsigned long pad2;
};
#endif
#ifdef __KERNEL__
/*
* Make kernel PTrace/register structures opaque to userspace... userspace can
* access thread state via the regset mechanism. This allows us a bit of
* flexibility in how we order the registers on the stack, permitting some
* optimizations like packing call-clobbered registers together so that
* they share a cacheline (not done yet, though... future optimization).
*/
#ifndef __ASSEMBLY__
/*
* This struct describes how the registers are laid out on the kernel stack
* during a syscall or other kernel entry.
*
* This structure should always be cacheline aligned on the stack.
* FIXME: I don't think that's the case right now. The alignment is
* taken care of elsewhere... head.S, process.c, etc.
*/
struct pt_regs {
union {
struct {
/* Named registers */
long sr; /* Stored in place of r0 */
long sp; /* r1 */
};
struct {
/* Old style */
long offset[2];
long gprs[30];
};
struct {
/* New style */
long gpr[32];
};
};
long pc;
long orig_gpr11; /* For restarting system calls */
long syscallno; /* Syscall number (used by strace) */
long dummy; /* Cheap alignment fix */
};
#endif /* __ASSEMBLY__ */
/* TODO: Rename this to REDZONE because that's what it is */
#define STACK_FRAME_OVERHEAD 128 /* size of minimum stack frame */
#define instruction_pointer(regs) ((regs)->pc)
#define user_mode(regs) (((regs)->sr & SPR_SR_SM) == 0)
#define user_stack_pointer(regs) ((unsigned long)(regs)->sp)
#define profile_pc(regs) instruction_pointer(regs)
/*
* Offsets used by 'ptrace' system call interface.
*/
#define PT_SR 0
#define PT_SP 4
#define PT_GPR2 8
#define PT_GPR3 12
#define PT_GPR4 16
#define PT_GPR5 20
#define PT_GPR6 24
#define PT_GPR7 28
#define PT_GPR8 32
#define PT_GPR9 36
#define PT_GPR10 40
#define PT_GPR11 44
#define PT_GPR12 48
#define PT_GPR13 52
#define PT_GPR14 56
#define PT_GPR15 60
#define PT_GPR16 64
#define PT_GPR17 68
#define PT_GPR18 72
#define PT_GPR19 76
#define PT_GPR20 80
#define PT_GPR21 84
#define PT_GPR22 88
#define PT_GPR23 92
#define PT_GPR24 96
#define PT_GPR25 100
#define PT_GPR26 104
#define PT_GPR27 108
#define PT_GPR28 112
#define PT_GPR29 116
#define PT_GPR30 120
#define PT_GPR31 124
#define PT_PC 128
#define PT_ORIG_GPR11 132
#define PT_SYSCALLNO 136
#endif /* __KERNEL__ */
#endif /* __ASM_OPENRISC_PTRACE_H */
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_SERIAL_H
#define __ASM_OPENRISC_SERIAL_H
#ifdef __KERNEL__
#include <asm/cpuinfo.h>
/* There's a generic version of this file, but it assumes a 1.8MHz UART clk...
* this, on the other hand, assumes the UART clock is tied to the system
* clock... 8250_early.c (early 8250 serial console) actually uses this, so
* it needs to be correct to get the early console working.
*/
#define BASE_BAUD (cpuinfo.clock_frequency/16)
#endif /* __KERNEL__ */
#endif /* __ASM_OPENRISC_SERIAL_H */
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_SIGCONTEXT_H
#define __ASM_OPENRISC_SIGCONTEXT_H
#include <asm/ptrace.h>
/* This struct is saved by setup_frame in signal.c, to keep the current
context while a signal handler is executed. It's restored by sys_sigreturn.
To keep things simple, we use pt_regs here even though normally you just
specify the list of regs to save. Then we can use copy_from_user on the
entire regs instead of a bunch of get_user's as well...
*/
struct sigcontext {
struct pt_regs regs; /* needs to be first */
unsigned long oldmask;
unsigned long usp; /* usp before stacking this gunk on it */
};
#endif /* __ASM_OPENRISC_SIGCONTEXT_H */
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_SPINLOCK_H
#define __ASM_OPENRISC_SPINLOCK_H
#error "or32 doesn't do SMP yet"
#endif
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
*
* 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_OPENRISC_SPR_H
#define __ASM_OPENRISC_SPR_H
#define mtspr(_spr, _val) __asm__ __volatile__ ( \
"l.mtspr r0,%1,%0" \
: : "K" (_spr), "r" (_val))
#define mtspr_off(_spr, _off, _val) __asm__ __volatile__ ( \
"l.mtspr %0,%1,%2" \
: : "r" (_off), "r" (_val), "K" (_spr))
static inline unsigned long mfspr(unsigned long add)
{
unsigned long ret;
__asm__ __volatile__ ("l.mfspr %0,r0,%1" : "=r" (ret) : "K" (add));
return ret;
}
static inline unsigned long mfspr_off(unsigned long add, unsigned long offset)
{
unsigned long ret;
__asm__ __volatile__ ("l.mfspr %0,%1,%2" : "=r" (ret)
: "r" (offset), "K" (add));
return ret;
}
#endif
此差异已折叠。
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_SYSCALL_H__
#define __ASM_OPENRISC_SYSCALL_H__
#include <linux/err.h>
#include <linux/sched.h>
static inline int
syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
{
return regs->syscallno ? regs->syscallno : -1;
}
static inline void
syscall_rollback(struct task_struct *task, struct pt_regs *regs)
{
regs->gpr[11] = regs->orig_gpr11;
}
static inline long
syscall_get_error(struct task_struct *task, struct pt_regs *regs)
{
return IS_ERR_VALUE(regs->gpr[11]) ? regs->gpr[11] : 0;
}
static inline long
syscall_get_return_value(struct task_struct *task, struct pt_regs *regs)
{
return regs->gpr[11];
}
static inline void
syscall_set_return_value(struct task_struct *task, struct pt_regs *regs,
int error, long val)
{
if (error)
regs->gpr[11] = -error;
else
regs->gpr[11] = val;
}
static inline void
syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
unsigned int i, unsigned int n, unsigned long *args)
{
BUG_ON(i + n > 6);
memcpy(args, &regs->gpr[3 + i], n * sizeof(args[0]));
}
static inline void
syscall_set_arguments(struct task_struct *task, struct pt_regs *regs,
unsigned int i, unsigned int n, const unsigned long *args)
{
BUG_ON(i + n > 6);
memcpy(&regs->gpr[3 + i], args, n * sizeof(args[0]));
}
#endif
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_SYSCALLS_H
#define __ASM_OPENRISC_SYSCALLS_H
asmlinkage long sys_or1k_atomic(unsigned long type, unsigned long *v1,
unsigned long *v2);
#include <asm-generic/syscalls.h>
#endif /* __ASM_OPENRISC_SYSCALLS_H */
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_SYSTEM_H
#define __ASM_OPENRISC_SYSTEM_H
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
#include <asm/spr.h>
#include <asm-generic/system.h>
/* We probably need this definition, but the generic system.h provides it
* and it's not used on our arch anyway...
*/
/*#define nop() __asm__ __volatile__ ("l.nop"::)*/
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
#endif /* __ASM_OPENRISC_SYSTEM_H */
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_THREAD_INFO_H
#define _ASM_THREAD_INFO_H
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
#include <asm/types.h>
#include <asm/processor.h>
#endif
/* THREAD_SIZE is the size of the task_struct/kernel_stack combo.
* normally, the stack is found by doing something like p + THREAD_SIZE
* in or32, a page is 8192 bytes, which seems like a sane size
*/
#define THREAD_SIZE_ORDER 0
#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
/*
* 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
*/
#ifndef __ASSEMBLY__
typedef unsigned long mm_segment_t;
struct thread_info {
struct task_struct *task; /* main task structure */
struct exec_domain *exec_domain; /* execution domain */
unsigned long flags; /* low level flags */
__u32 cpu; /* current CPU */
__s32 preempt_count; /* 0 => preemptable, <0 => BUG */
mm_segment_t addr_limit; /* thread address space:
0-0x7FFFFFFF for user-thead
0-0xFFFFFFFF for kernel-thread
*/
struct restart_block restart_block;
__u8 supervisor_stack[0];
/* saved context data */
unsigned long ksp;
};
#endif
/*
* macros/functions for gaining access to the thread information structure
*
* preempt_count needs to be 1 initially, until the scheduler is functional.
*/
#ifndef __ASSEMBLY__
#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, \
}, \
.ksp = 0, \
}
#define init_thread_info (init_thread_union.thread_info)
/* how to get the thread information struct from C */
register struct thread_info *current_thread_info_reg asm("r10");
#define current_thread_info() (current_thread_info_reg)
#define get_thread_info(ti) get_task_struct((ti)->task)
#define put_thread_info(ti) put_task_struct((ti)->task)
#endif /* !__ASSEMBLY__ */
/*
* 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 */
#define TIF_SINGLESTEP 4 /* restore singlestep on return to user
* mode
*/
#define TIF_SYSCALL_TRACEPOINT 8 /* for ftrace syscall instrumentation */
#define TIF_RESTORE_SIGMASK 9
#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling * TIF_NEED_RESCHED
*/
#define TIF_MEMDIE 17
#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_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
/* Work to do when returning from interrupt/exception */
/* For OpenRISC, this is anything in the LSW other than syscall trace */
#define _TIF_WORK_MASK (0xff & ~(_TIF_SYSCALL_TRACE|_TIF_SINGLESTEP))
#endif /* __KERNEL__ */
#endif /* _ASM_THREAD_INFO_H */
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
*
* 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_OPENRISC_TIMEX_H
#define __ASM_OPENRISC_TIMEX_H
#define get_cycles get_cycles
#include <asm-generic/timex.h>
#include <asm/spr.h>
#include <asm/spr_defs.h>
static inline cycles_t get_cycles(void)
{
return mfspr(SPR_TTCR);
}
/* This isn't really used any more */
#define CLOCK_TICK_RATE 1000
#define ARCH_HAS_READ_CURRENT_TIMER
#endif
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_TLB_H__
#define __ASM_OPENRISC_TLB_H__
/*
* or32 doesn't need any special per-pte or
* per-vma handling..
*/
#define tlb_start_vma(tlb, vma) do { } while (0)
#define tlb_end_vma(tlb, vma) do { } while (0)
#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
#include <linux/pagemap.h>
#include <asm-generic/tlb.h>
#endif /* __ASM_OPENRISC_TLB_H__ */
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_TLBFLUSH_H
#define __ASM_OPENRISC_TLBFLUSH_H
#include <linux/mm.h>
#include <asm/processor.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <asm/current.h>
#include <linux/sched.h>
/*
* - flush_tlb() flushes the current mm struct TLBs
* - flush_tlb_all() flushes all processes TLBs
* - flush_tlb_mm(mm) flushes the specified mm context TLB's
* - flush_tlb_page(vma, vmaddr) flushes one page
* - flush_tlb_range(mm, start, end) flushes a range of pages
*/
void flush_tlb_all(void);
void flush_tlb_mm(struct mm_struct *mm);
void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr);
void flush_tlb_range(struct vm_area_struct *vma,
unsigned long start,
unsigned long end);
static inline void flush_tlb(void)
{
flush_tlb_mm(current->mm);
}
static inline void flush_tlb_kernel_range(unsigned long start,
unsigned long end)
{
flush_tlb_range(NULL, start, end);
}
#endif /* __ASM_OPENRISC_TLBFLUSH_H */
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_UACCESS_H
#define __ASM_OPENRISC_UACCESS_H
/*
* User space memory access functions
*/
#include <linux/errno.h>
#include <linux/thread_info.h>
#include <linux/prefetch.h>
#include <linux/string.h>
#include <linux/thread_info.h>
#include <asm/page.h>
#define VERIFY_READ 0
#define VERIFY_WRITE 1
/*
* 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.
*/
/* addr_limit is the maximum accessible address for the task. we misuse
* the KERNEL_DS and USER_DS values to both assign and compare the
* addr_limit values through the equally misnamed get/set_fs macros.
* (see above)
*/
#define KERNEL_DS (~0UL)
#define get_ds() (KERNEL_DS)
#define USER_DS (TASK_SIZE)
#define get_fs() (current_thread_info()->addr_limit)
#define set_fs(x) (current_thread_info()->addr_limit = (x))
#define segment_eq(a, b) ((a) == (b))
/* Ensure that the range from addr to addr+size is all within the process'
* address space
*/
#define __range_ok(addr, size) (size <= get_fs() && addr <= (get_fs()-size))
/* Ensure that addr is below task's addr_limit */
#define __addr_ok(addr) ((unsigned long) addr < get_fs())
#define access_ok(type, addr, size) \
__range_ok((unsigned long)addr, (unsigned long)size)
/*
* 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;
};
/* Returns 0 if exception not found and fixup otherwise. */
extern unsigned long search_exception_table(unsigned long);
extern void sort_exception_table(void);
/*
* These are the main single-value transfer routines. They automatically
* use the right size if we just have the right pointer type.
*
* This gets kind of ugly. We want to return _two_ values in "get_user()"
* and yet we don't want to do any pointers, because that is too much
* of a performance impact. Thus we have a few rather ugly macros here,
* and hide all the uglyness from the user.
*
* The "__xxx" versions of the user access functions are versions that
* do not verify the address space, that must have been done previously
* with a separate "access_ok()" call (this is used when we do multiple
* accesses to the same area of user memory).
*
* As we use the same address space for kernel and user data on the
* PowerPC, we can just do these as direct assignments. (Of course, the
* exception handling means that it's no longer "just"...)
*/
#define get_user(x, ptr) \
__get_user_check((x), (ptr), sizeof(*(ptr)))
#define put_user(x, ptr) \
__put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
#define __get_user(x, ptr) \
__get_user_nocheck((x), (ptr), sizeof(*(ptr)))
#define __put_user(x, ptr) \
__put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
extern long __put_user_bad(void);
#define __put_user_nocheck(x, ptr, size) \
({ \
long __pu_err; \
__put_user_size((x), (ptr), (size), __pu_err); \
__pu_err; \
})
#define __put_user_check(x, ptr, size) \
({ \
long __pu_err = -EFAULT; \
__typeof__(*(ptr)) *__pu_addr = (ptr); \
if (access_ok(VERIFY_WRITE, __pu_addr, size)) \
__put_user_size((x), __pu_addr, (size), __pu_err); \
__pu_err; \
})
#define __put_user_size(x, ptr, size, retval) \
do { \
retval = 0; \
switch (size) { \
case 1: __put_user_asm(x, ptr, retval, "l.sb"); break; \
case 2: __put_user_asm(x, ptr, retval, "l.sh"); break; \
case 4: __put_user_asm(x, ptr, retval, "l.sw"); break; \
case 8: __put_user_asm2(x, ptr, retval); break; \
default: __put_user_bad(); \
} \
} while (0)
struct __large_struct {
unsigned long buf[100];
};
#define __m(x) (*(struct __large_struct *)(x))
/*
* We don't tell gcc that we are accessing memory, but this is OK
* because we do not write to any memory gcc knows about, so there
* are no aliasing issues.
*/
#define __put_user_asm(x, addr, err, op) \
__asm__ __volatile__( \
"1: "op" 0(%2),%1\n" \
"2:\n" \
".section .fixup,\"ax\"\n" \
"3: l.addi %0,r0,%3\n" \
" l.j 2b\n" \
" l.nop\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 2\n" \
" .long 1b,3b\n" \
".previous" \
: "=r"(err) \
: "r"(x), "r"(addr), "i"(-EFAULT), "0"(err))
#define __put_user_asm2(x, addr, err) \
__asm__ __volatile__( \
"1: l.sw 0(%2),%1\n" \
"2: l.sw 4(%2),%H1\n" \
"3:\n" \
".section .fixup,\"ax\"\n" \
"4: l.addi %0,r0,%3\n" \
" l.j 3b\n" \
" l.nop\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 2\n" \
" .long 1b,4b\n" \
" .long 2b,4b\n" \
".previous" \
: "=r"(err) \
: "r"(x), "r"(addr), "i"(-EFAULT), "0"(err))
#define __get_user_nocheck(x, ptr, size) \
({ \
long __gu_err, __gu_val; \
__get_user_size(__gu_val, (ptr), (size), __gu_err); \
(x) = (__typeof__(*(ptr)))__gu_val; \
__gu_err; \
})
#define __get_user_check(x, ptr, size) \
({ \
long __gu_err = -EFAULT, __gu_val = 0; \
const __typeof__(*(ptr)) * __gu_addr = (ptr); \
if (access_ok(VERIFY_READ, __gu_addr, size)) \
__get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
(x) = (__typeof__(*(ptr)))__gu_val; \
__gu_err; \
})
extern long __get_user_bad(void);
#define __get_user_size(x, ptr, size, retval) \
do { \
retval = 0; \
switch (size) { \
case 1: __get_user_asm(x, ptr, retval, "l.lbz"); break; \
case 2: __get_user_asm(x, ptr, retval, "l.lhz"); break; \
case 4: __get_user_asm(x, ptr, retval, "l.lwz"); break; \
case 8: __get_user_asm2(x, ptr, retval); \
default: (x) = __get_user_bad(); \
} \
} while (0)
#define __get_user_asm(x, addr, err, op) \
__asm__ __volatile__( \
"1: "op" %1,0(%2)\n" \
"2:\n" \
".section .fixup,\"ax\"\n" \
"3: l.addi %0,r0,%3\n" \
" l.addi %1,r0,0\n" \
" l.j 2b\n" \
" l.nop\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 2\n" \
" .long 1b,3b\n" \
".previous" \
: "=r"(err), "=r"(x) \
: "r"(addr), "i"(-EFAULT), "0"(err))
#define __get_user_asm2(x, addr, err) \
__asm__ __volatile__( \
"1: l.lwz %1,0(%2)\n" \
"2: l.lwz %H1,4(%2)\n" \
"3:\n" \
".section .fixup,\"ax\"\n" \
"4: l.addi %0,r0,%3\n" \
" l.addi %1,r0,0\n" \
" l.addi %H1,r0,0\n" \
" l.j 3b\n" \
" l.nop\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 2\n" \
" .long 1b,4b\n" \
" .long 2b,4b\n" \
".previous" \
: "=r"(err), "=&r"(x) \
: "r"(addr), "i"(-EFAULT), "0"(err))
/* more complex routines */
extern unsigned long __must_check
__copy_tofrom_user(void *to, const void *from, unsigned long size);
#define __copy_from_user(to, from, size) \
__copy_tofrom_user(to, from, size)
#define __copy_to_user(to, from, size) \
__copy_tofrom_user(to, from, size)
#define __copy_to_user_inatomic __copy_to_user
#define __copy_from_user_inatomic __copy_from_user
static inline unsigned long
copy_from_user(void *to, const void *from, unsigned long n)
{
unsigned long over;
if (access_ok(VERIFY_READ, from, n))
return __copy_tofrom_user(to, from, n);
if ((unsigned long)from < TASK_SIZE) {
over = (unsigned long)from + n - TASK_SIZE;
return __copy_tofrom_user(to, from, n - over) + over;
}
return n;
}
static inline unsigned long
copy_to_user(void *to, const void *from, unsigned long n)
{
unsigned long over;
if (access_ok(VERIFY_WRITE, to, n))
return __copy_tofrom_user(to, from, n);
if ((unsigned long)to < TASK_SIZE) {
over = (unsigned long)to + n - TASK_SIZE;
return __copy_tofrom_user(to, from, n - over) + over;
}
return n;
}
extern unsigned long __clear_user(void *addr, unsigned long size);
static inline __must_check unsigned long
clear_user(void *addr, unsigned long size)
{
if (access_ok(VERIFY_WRITE, addr, size))
return __clear_user(addr, size);
if ((unsigned long)addr < TASK_SIZE) {
unsigned long over = (unsigned long)addr + size - TASK_SIZE;
return __clear_user(addr, size - over) + over;
}
return size;
}
extern int __strncpy_from_user(char *dst, const char *src, long count);
static inline long strncpy_from_user(char *dst, const char *src, long count)
{
if (access_ok(VERIFY_READ, src, 1))
return __strncpy_from_user(dst, src, count);
return -EFAULT;
}
/*
* Return the size of a string (including the ending 0)
*
* Return 0 for error
*/
extern int __strnlen_user(const char *str, long len, unsigned long top);
/*
* Returns the length of the string at str (including the null byte),
* or 0 if we hit a page we can't access,
* or something > len if we didn't find a null byte.
*
* The `top' parameter to __strnlen_user is to make sure that
* we can never overflow from the user area into kernel space.
*/
static inline long strnlen_user(const char __user *str, long len)
{
unsigned long top = (unsigned long)get_fs();
unsigned long res = 0;
if (__addr_ok(str))
res = __strnlen_user(str, len, top);
return res;
}
#define strlen_user(str) strnlen_user(str, TASK_SIZE-1)
#endif /* __ASM_OPENRISC_UACCESS_H */
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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_OPENRISC_UNALIGNED_H
#define __ASM_OPENRISC_UNALIGNED_H
/*
* This is copied from the generic implementation and the C-struct
* variant replaced with the memmove variant. The GCC compiler
* for the OR32 arch optimizes too aggressively for the C-struct
* variant to work, so use the memmove variant instead.
*
* It may be worth considering implementing the unaligned access
* exception handler and allowing unaligned accesses (access_ok.h)...
* not sure if it would be much of a performance win without further
* investigation.
*/
#include <asm/byteorder.h>
#if defined(__LITTLE_ENDIAN)
# include <linux/unaligned/le_memmove.h>
# include <linux/unaligned/be_byteshift.h>
# include <linux/unaligned/generic.h>
# define get_unaligned __get_unaligned_le
# define put_unaligned __put_unaligned_le
#elif defined(__BIG_ENDIAN)
# include <linux/unaligned/be_memmove.h>
# include <linux/unaligned/le_byteshift.h>
# include <linux/unaligned/generic.h>
# define get_unaligned __get_unaligned_be
# define put_unaligned __put_unaligned_be
#else
# error need to define endianess
#endif
#endif /* __ASM_OPENRISC_UNALIGNED_H */
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* OpenRISC implementation:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
* et al.
*
* 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.
*/
#if !defined(__ASM_OPENRISC_UNISTD_H) || defined(__SYSCALL)
#define __ASM_OPENRISC_UNISTD_H
#define __ARCH_HAVE_MMU
#define sys_mmap2 sys_mmap_pgoff
#include <asm-generic/unistd.h>
#define __NR_or1k_atomic __NR_arch_specific_syscall
__SYSCALL(__NR_or1k_atomic, sys_or1k_atomic)
#endif /* __ASM_OPENRISC_UNISTD_H */
#
# Makefile for the linux kernel.
#
extra-y := head.o vmlinux.lds init_task.o
obj-y := setup.o idle.o or32_ksyms.o process.o dma.o \
traps.o time.o irq.o entry.o ptrace.o signal.o sys_or32.o \
sys_call_table.o
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_OF) += prom.o
clean:
/*
* OpenRISC asm-offsets.c
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* Modifications for the OpenRISC architecture:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
*
* 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 used to generate definitions needed by
* assembly language modules.
*
* We use the technique used in the OSF Mach kernel code:
* generate asm statements containing #defines,
* compile this file to assembler, and then extract the
* #defines from the assembly-language output.
*/
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/io.h>
#include <linux/thread_info.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
#define DEFINE(sym, val) \
asm volatile("\n->" #sym " %0 " #val : : "i" (val))
#define BLANK() asm volatile("\n->" : : )
int main(void)
{
/* offsets into the task_struct */
DEFINE(TASK_STATE, offsetof(struct task_struct, state));
DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
DEFINE(TASK_MM, offsetof(struct task_struct, mm));
DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
/* offsets into thread_info */
DEFINE(TI_TASK, offsetof(struct thread_info, task));
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
DEFINE(TI_KSP, offsetof(struct thread_info, ksp));
DEFINE(PT_SIZE, sizeof(struct pt_regs));
/* Interrupt register frame */
DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD);
DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs));
DEFINE(NUM_USER_SEGMENTS, TASK_SIZE >> 28);
return 0;
}
/*
* OpenRISC Linux
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* Modifications for the OpenRISC architecture:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
*
* 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.
*
* DMA mapping callbacks...
* As alloc_coherent is the only DMA callback being used currently, that's
* the only thing implemented properly. The rest need looking into...
*/
#include <linux/dma-mapping.h>
#include <linux/dma-debug.h>
#include <asm/cpuinfo.h>
#include <asm/spr_defs.h>
#include <asm/tlbflush.h>
static int page_set_nocache(pte_t *pte, unsigned long addr,
unsigned long next, struct mm_walk *walk)
{
unsigned long cl;
pte_val(*pte) |= _PAGE_CI;
/*
* Flush the page out of the TLB so that the new page flags get
* picked up next time there's an access
*/
flush_tlb_page(NULL, addr);
/* Flush page out of dcache */
for (cl = __pa(addr); cl < __pa(next); cl += cpuinfo.dcache_block_size)
mtspr(SPR_DCBFR, cl);
return 0;
}
static int page_clear_nocache(pte_t *pte, unsigned long addr,
unsigned long next, struct mm_walk *walk)
{
pte_val(*pte) &= ~_PAGE_CI;
/*
* Flush the page out of the TLB so that the new page flags get
* picked up next time there's an access
*/
flush_tlb_page(NULL, addr);
return 0;
}
/*
* Alloc "coherent" memory, which for OpenRISC means simply uncached.
*
* This function effectively just calls __get_free_pages, sets the
* cache-inhibit bit on those pages, and makes sure that the pages are
* flushed out of the cache before they are used.
*
*/
void *or1k_dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp)
{
unsigned long va;
void *page;
struct mm_walk walk = {
.pte_entry = page_set_nocache,
.mm = &init_mm
};
page = alloc_pages_exact(size, gfp);
if (!page)
return NULL;
/* This gives us the real physical address of the first page. */
*dma_handle = __pa(page);
va = (unsigned long)page;
/*
* We need to iterate through the pages, clearing the dcache for
* them and setting the cache-inhibit bit.
*/
if (walk_page_range(va, va + size, &walk)) {
free_pages_exact(page, size);
return NULL;
}
return (void *)va;
}
void or1k_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_handle)
{
unsigned long va = (unsigned long)vaddr;
struct mm_walk walk = {
.pte_entry = page_clear_nocache,
.mm = &init_mm
};
/* walk_page_range shouldn't be able to fail here */
WARN_ON(walk_page_range(va, va + size, &walk));
free_pages_exact(vaddr, size);
}
dma_addr_t or1k_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
struct dma_attrs *attrs)
{
unsigned long cl;
dma_addr_t addr = page_to_phys(page) + offset;
switch (dir) {
case DMA_TO_DEVICE:
/* Flush the dcache for the requested range */
for (cl = addr; cl < addr + size;
cl += cpuinfo.dcache_block_size)
mtspr(SPR_DCBFR, cl);
break;
case DMA_FROM_DEVICE:
/* Invalidate the dcache for the requested range */
for (cl = addr; cl < addr + size;
cl += cpuinfo.dcache_block_size)
mtspr(SPR_DCBIR, cl);
break;
default:
/*
* NOTE: If dir == DMA_BIDIRECTIONAL then there's no need to
* flush nor invalidate the cache here as the area will need
* to be manually synced anyway.
*/
break;
}
return addr;
}
void or1k_unmap_page(struct device *dev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction dir,
struct dma_attrs *attrs)
{
/* Nothing special to do here... */
}
void or1k_sync_single_for_cpu(struct device *dev,
dma_addr_t dma_handle, size_t size,
enum dma_data_direction dir)
{
unsigned long cl;
dma_addr_t addr = dma_handle;
/* Invalidate the dcache for the requested range */
for (cl = addr; cl < addr + size; cl += cpuinfo.dcache_block_size)
mtspr(SPR_DCBIR, cl);
}
void or1k_sync_single_for_device(struct device *dev,
dma_addr_t dma_handle, size_t size,
enum dma_data_direction dir)
{
unsigned long cl;
dma_addr_t addr = dma_handle;
/* Flush the dcache for the requested range */
for (cl = addr; cl < addr + size; cl += cpuinfo.dcache_block_size)
mtspr(SPR_DCBFR, cl);
}
/* Number of entries preallocated for DMA-API debugging */
#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
static int __init dma_init(void)
{
dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
return 0;
}
fs_initcall(dma_init);
此差异已折叠。
此差异已折叠。
/*
* OpenRISC idle.c
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* Modifications for the OpenRISC architecture:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
*
* 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.
*
* Idle daemon for or32. Idle daemon will handle any action
* that needs to be taken when the system becomes idle.
*/
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/tick.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/mmu.h>
#include <asm/cache.h>
#include <asm/pgalloc.h>
void (*powersave) (void) = NULL;
static inline void pm_idle(void)
{
barrier();
}
void cpu_idle(void)
{
set_thread_flag(TIF_POLLING_NRFLAG);
/* endless idle loop with no priority at all */
while (1) {
tick_nohz_stop_sched_tick(1);
while (!need_resched()) {
check_pgt_cache();
rmb();
clear_thread_flag(TIF_POLLING_NRFLAG);
local_irq_disable();
/* Don't trace irqs off for idle */
stop_critical_timings();
if (!need_resched() && powersave != NULL)
powersave();
start_critical_timings();
local_irq_enable();
set_thread_flag(TIF_POLLING_NRFLAG);
}
tick_nohz_restart_sched_tick();
preempt_enable_no_resched();
schedule();
preempt_disable();
}
}
/*
* OpenRISC init_task.c
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* Modifications for the OpenRISC architecture:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
*
* 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 <linux/init_task.h>
#include <linux/mqueue.h>
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
/*
* Initial thread structure.
*
* We need to make sure that this is THREAD_SIZE aligned due to the
* way process stacks are handled. This is done by having a special
* "init_task" linker map entry..
*/
union thread_union init_thread_union __init_task_data = {
INIT_THREAD_INFO(init_task)
};
/*
* Initial task structure.
*
* All other task structs will be allocated on slabs in fork.c
*/
struct task_struct init_task = INIT_TASK(init_task);
EXPORT_SYMBOL(init_task);
/*
* OpenRISC irq.c
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* Modifications for the OpenRISC architecture:
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
*
* 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 <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/ftrace.h>
#include <linux/irq.h>
#include <linux/seq_file.h>
#include <linux/kernel_stat.h>
#include <linux/irqflags.h>
/* read interrupt enabled status */
unsigned long arch_local_save_flags(void)
{
return mfspr(SPR_SR) & (SPR_SR_IEE|SPR_SR_TEE);
}
EXPORT_SYMBOL(arch_local_save_flags);
/* set interrupt enabled status */
void arch_local_irq_restore(unsigned long flags)
{
mtspr(SPR_SR, ((mfspr(SPR_SR) & ~(SPR_SR_IEE|SPR_SR_TEE)) | flags));
}
EXPORT_SYMBOL(arch_local_irq_restore);
/* OR1K PIC implementation */
/* We're a couple of cycles faster than the generic implementations with
* these 'fast' versions.
*/
static void or1k_pic_mask(struct irq_data *data)
{
mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->irq));
}
static void or1k_pic_unmask(struct irq_data *data)
{
mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (1UL << data->irq));
}
static void or1k_pic_ack(struct irq_data *data)
{
/* EDGE-triggered interrupts need to be ack'ed in order to clear
* the latch.
* LEVER-triggered interrupts do not need to be ack'ed; however,
* ack'ing the interrupt has no ill-effect and is quicker than
* trying to figure out what type it is...
*/
/* The OpenRISC 1000 spec says to write a 1 to the bit to ack the
* interrupt, but the OR1200 does this backwards and requires a 0
* to be written...
*/
#ifdef CONFIG_OR1K_1200
/* There are two oddities with the OR1200 PIC implementation:
* i) LEVEL-triggered interrupts are latched and need to be cleared
* ii) the interrupt latch is cleared by writing a 0 to the bit,
* as opposed to a 1 as mandated by the spec
*/
mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->irq));
#else
WARN(1, "Interrupt handling possibily broken\n");
mtspr(SPR_PICSR, (1UL << irq));
#endif
}
static void or1k_pic_mask_ack(struct irq_data *data)
{
/* Comments for pic_ack apply here, too */
#ifdef CONFIG_OR1K_1200
mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->irq));
#else
WARN(1, "Interrupt handling possibily broken\n");
mtspr(SPR_PICSR, (1UL << irq));
#endif
}
static int or1k_pic_set_type(struct irq_data *data, unsigned int flow_type)
{
/* There's nothing to do in the PIC configuration when changing
* flow type. Level and edge-triggered interrupts are both
* supported, but it's PIC-implementation specific which type
* is handled. */
return irq_setup_alt_chip(data, flow_type);
}
static inline int pic_get_irq(int first)
{
int irq;
irq = ffs(mfspr(SPR_PICSR) >> first);
return irq ? irq + first - 1 : NO_IRQ;
}
static void __init or1k_irq_init(void)
{
struct irq_chip_generic *gc;
struct irq_chip_type *ct;
/* Disable all interrupts until explicitly requested */
mtspr(SPR_PICMR, (0UL));
gc = irq_alloc_generic_chip("or1k-PIC", 1, 0, 0, handle_level_irq);
ct = gc->chip_types;
ct->chip.irq_unmask = or1k_pic_unmask;
ct->chip.irq_mask = or1k_pic_mask;
ct->chip.irq_ack = or1k_pic_ack;
ct->chip.irq_mask_ack = or1k_pic_mask_ack;
ct->chip.irq_set_type = or1k_pic_set_type;
/* The OR1K PIC can handle both level and edge trigged
* interrupts in roughly the same manner
*/
#if 0
/* FIXME: chip.type??? */
ct->chip.type = IRQ_TYPE_EDGE_BOTH | IRQ_TYPE_LEVEL_MASK;
#endif
irq_setup_generic_chip(gc, IRQ_MSK(NR_IRQS), 0,
IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
}
void __init init_IRQ(void)
{
or1k_irq_init();
}
void __irq_entry do_IRQ(struct pt_regs *regs)
{
int irq = -1;
struct pt_regs *old_regs = set_irq_regs(regs);
irq_enter();
while ((irq = pic_get_irq(irq + 1)) != NO_IRQ)
generic_handle_irq(irq);
irq_exit();
set_irq_regs(old_regs);
}
unsigned int irq_create_of_mapping(struct device_node *controller,
const u32 *intspec, unsigned int intsize)
{
return intspec[0];
}
EXPORT_SYMBOL_GPL(irq_create_of_mapping);
/*
* OpenRISC module.c
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* Modifications for the OpenRISC architecture:
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
*
* 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 <linux/moduleloader.h>
#include <linux/elf.h>
int apply_relocate_add(Elf32_Shdr *sechdrs,
const char *strtab,
unsigned int symindex,
unsigned int relsec,
struct module *me)
{
unsigned int i;
Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
Elf32_Sym *sym;
uint32_t *location;
uint32_t value;
pr_debug("Applying relocate section %u to %u\n", relsec,
sechdrs[relsec].sh_info);
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
/* This is where to make the change */
location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+ rel[i].r_offset;
/* This is the symbol it is referring to. Note that all
undefined symbols have been resolved. */
sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+ ELF32_R_SYM(rel[i].r_info);
value = sym->st_value + rel[i].r_addend;
switch (ELF32_R_TYPE(rel[i].r_info)) {
case R_OR32_32:
*location = value;
break;
case R_OR32_CONST:
location = (uint16_t *)location + 1;
*((uint16_t *)location) = (uint16_t) (value);
break;
case R_OR32_CONSTH:
location = (uint16_t *)location + 1;
*((uint16_t *)location) = (uint16_t) (value >> 16);
break;
case R_OR32_JUMPTARG:
value -= (uint32_t)location;
value >>= 2;
value &= 0x03ffffff;
value |= *location & 0xfc000000;
*location = value;
break;
default:
pr_err("module %s: Unknown relocation: %u\n",
me->name, ELF32_R_TYPE(rel[i].r_info));
break;
}
}
return 0;
}
/*
* OpenRISC or32_ksyms.c
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* Modifications for the OpenRISC architecture:
* Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
*
* 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 <linux/module.h>
#include <linux/elfcore.h>
#include <linux/sched.h>
#include <linux/in6.h>
#include <linux/interrupt.h>
#include <linux/vmalloc.h>
#include <linux/semaphore.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/checksum.h>
#include <asm/io.h>
#include <asm/hardirq.h>
#include <asm/delay.h>
#include <asm/pgalloc.h>
#define DECLARE_EXPORT(name) extern void name(void); EXPORT_SYMBOL(name)
/* compiler generated symbols */
DECLARE_EXPORT(__udivsi3);
DECLARE_EXPORT(__divsi3);
DECLARE_EXPORT(__umodsi3);
DECLARE_EXPORT(__modsi3);
DECLARE_EXPORT(__muldi3);
DECLARE_EXPORT(__ashrdi3);
DECLARE_EXPORT(__ashldi3);
DECLARE_EXPORT(__lshrdi3);
EXPORT_SYMBOL(__copy_tofrom_user);
此差异已折叠。
/*
* OpenRISC prom.c
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* Modifications for the OpenRISC architecture:
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
*
* 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.
*
* Architecture specific procedures for creating, accessing and
* interpreting the device tree.
*
*/
#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/memblock.h>
#include <linux/of_fdt.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 <asm/sections.h>
#include <asm/setup.h>
extern char cmd_line[COMMAND_LINE_SIZE];
void __init early_init_dt_add_memory_arch(u64 base, u64 size)
{
size &= PAGE_MASK;
memblock_add(base, size);
}
void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
{
return __va(memblock_alloc(size, align));
}
void __init early_init_devtree(void *params)
{
void *alloc;
/* Setup flat device-tree pointer */
initial_boot_params = params;
/* 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, cmd_line);
/* Scan memory nodes and rebuild MEMBLOCKs */
memblock_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);
memblock_analyze();
/* We must copy the flattend device tree from init memory to regular
* memory because the device tree references the strings in it
* directly.
*/
alloc = __va(memblock_alloc(initial_boot_params->totalsize, PAGE_SIZE));
memcpy(alloc, initial_boot_params, initial_boot_params->totalsize);
initial_boot_params = alloc;
}
#ifdef CONFIG_BLK_DEV_INITRD
void __init early_init_dt_setup_initrd_arch(unsigned long start,
unsigned long end)
{
initrd_start = (unsigned long)__va(start);
initrd_end = (unsigned long)__va(end);
initrd_below_start_ok = 1;
}
#endif
此差异已折叠。
此差异已折叠。
此差异已折叠。
/*
* OpenRISC sys_call_table.c
*
* Linux architectural port borrowing liberally from similar works of
* others. All original copyrights apply as per the original source
* declaration.
*
* Modifications for the OpenRISC architecture:
* Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
*
* 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 <linux/syscalls.h>
#include <linux/signal.h>
#include <linux/unistd.h>
#include <asm/syscalls.h>
#undef __SYSCALL
#define __SYSCALL(nr, call) [nr] = (call),
void *sys_call_table[__NR_syscalls] = {
#include <asm/unistd.h>
};
此差异已折叠。
此差异已折叠。
此差异已折叠。
#ifndef __OPENRISC_VMLINUX_H_
#define __OPENRISC_VMLINUX_H_
extern char _stext, _etext, _edata, _end;
#ifdef CONFIG_BLK_DEV_INITRD
extern char __initrd_start, __initrd_end;
extern char __initramfs_start;
#endif
extern u32 __dtb_start[];
#endif
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册