Merge tag 'for-linus' of git://github.com/openrisc/linux

Pull OpenRISC updates from Stafford Horne:
 "The OpenRISC work is a bit more interesting this time, adding SMP
  support and a few general cleanups.

  Small Things:

   - Move OpenRISC docs into Documentation and clean them up

   - Document previously undocumented devicetree bindings

   - Update the or1ksim dts to use stdout-path

  OpenRISC SMP support details:

   - First the "use shadow registers" and "define CPU_BIG_ENDIAN as
     true" get the architecture ready for SMP.

   - The "add 1 and 2 byte cmpxchg support" and "use qspinlocks and
     qrwlocks" add the SMP locking infrastructure as needed. Using the
     qspinlocks and qrwlocks as suggested by Peter Z while reviewing the
     original spinlocks implementation.

   - The "support for ompic" adds a new irqchip device which is used for
     IPI communication to support SMP.

   - The "initial SMP support" adds smp.c and makes changes to all of
     the necessary data-structures to be per-cpu.

  The remaining patches are bug fixes and debug helpers which I wanted
  to keep separate from the "initial SMP support" in order to allow them
  to be reviewed on their own. This includes:

   - add cacheflush support to fix icache aliasing

   - fix initial preempt state for secondary cpu tasks

   - sleep instead of spin on secondary wait

   - support framepointers and STACKTRACE_SUPPORT

   - enable LOCKDEP_SUPPORT and irqflags tracing

   - timer sync: Add tick timer sync logic

   - fix possible deadlock in timer sync, pointed out by mips guys

  Note: the irqchip patch was reviewed with Marc and we agreed to push
  it together with these patches"

* tag 'for-linus' of git://github.com/openrisc/linux:
  openrisc: fix possible deadlock scenario during timer sync
  openrisc: pass endianness info to sparse
  openrisc: add tick timer multi-core sync logic
  openrisc: enable LOCKDEP_SUPPORT and irqflags tracing
  openrisc: support framepointers and STACKTRACE_SUPPORT
  openrisc: add simple_smp dts and defconfig for simulators
  openrisc: add cacheflush support to fix icache aliasing
  openrisc: sleep instead of spin on secondary wait
  openrisc: fix initial preempt state for secondary cpu tasks
  openrisc: initial SMP support
  irqchip: add initial support for ompic
  dt-bindings: add openrisc to vendor prefixes list
  openrisc: use qspinlocks and qrwlocks
  openrisc: add 1 and 2 byte cmpxchg support
  openrisc: use shadow registers to save regs on exception
  dt-bindings: openrisc: Add OpenRISC platform SoC
  Documentation: openrisc: Updates to README
  Documentation: Move OpenRISC docs out of arch/
  MAINTAINERS: Add OpenRISC pic maintainer
  openrisc: dts: or1ksim: Add stdout-path
This commit is contained in:
Linus Torvalds
2017-11-13 12:12:00 -08:00
46 changed files with 1944 additions and 266 deletions
@@ -0,0 +1,22 @@
Open Multi-Processor Interrupt Controller
Required properties:
- compatible : This should be "openrisc,ompic"
- reg : Specifies base physical address and size of the register space. The
size is based on the number of cores the controller has been configured
to handle, this should be set to 8 bytes per cpu core.
- interrupt-controller : Identifies the node as an interrupt controller.
- #interrupt-cells : This should be set to 0 as this will not be an irq
parent.
- interrupts : Specifies the interrupt line to which the ompic is wired.
Example:
ompic: interrupt-controller@98000000 {
compatible = "openrisc,ompic";
reg = <0x98000000 16>;
interrupt-controller;
#interrupt-cells = <0>;
interrupts = <1>;
};
@@ -0,0 +1,39 @@
OpenRISC Generic SoC
====================
Boards and FPGA SoC's which support the OpenRISC standard platform. The
platform essentially follows the conventions of the OpenRISC architecture
specification, however some aspects, such as the boot protocol have been defined
by the Linux port.
Required properties
-------------------
- compatible: Must include "opencores,or1ksim"
CPU nodes:
----------
A "cpus" node is required. Required properties:
- #address-cells: Must be 1.
- #size-cells: Must be 0.
A CPU sub-node is also required for at least CPU 0. Since the topology may
be probed via CPS, it is not necessary to specify secondary CPUs. Required
properties:
- compatible: Must be "opencores,or1200-rtlsvn481".
- reg: CPU number.
- clock-frequency: The CPU clock frequency in Hz.
Example:
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
compatible = "opencores,or1200-rtlsvn481";
reg = <0>;
clock-frequency = <20000000>;
};
};
Boot protocol
-------------
The bootloader may pass the following arguments to the kernel:
- r3: address of a flattened device-tree blob or 0x0.
@@ -246,6 +246,7 @@ onion Onion Corporation
onnn ON Semiconductor Corp. onnn ON Semiconductor Corp.
ontat On Tat Industrial Company ontat On Tat Industrial Company
opencores OpenCores.org opencores OpenCores.org
openrisc OpenRISC.io
option Option NV option Option NV
ORCL Oracle Corporation ORCL Oracle Corporation
ortustech Ortus Technology Co., Ltd. ortustech Ortus Technology Co., Ltd.
@@ -7,13 +7,7 @@ target architecture, specifically, is the 32-bit OpenRISC 1000 family (or1k).
For information about OpenRISC processors and ongoing development: For information about OpenRISC processors and ongoing development:
website http://openrisc.io website http://openrisc.io
email openrisc@lists.librecores.org
For more information about Linux on OpenRISC, please contact South Pole AB.
email: info@southpole.se
website: http://southpole.se
http://southpoleconsulting.com
--------------------------------------------------------------------- ---------------------------------------------------------------------
@@ -24,37 +18,54 @@ 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 toolchain and, perhaps, the architectural simulator. Steps to get these bits
in place are outlined here. in place are outlined here.
1) The toolchain can be obtained from openrisc.io. Instructions for building 1) Toolchain
a toolchain can be found at:
https://github.com/openrisc/tutorials Toolchain binaries can be obtained from openrisc.io or our github releases page.
Instructions for building the different toolchains can be found on openrisc.io
or Stafford's toolchain build and release scripts.
2) or1ksim (optional) binaries https://github.com/openrisc/or1k-gcc/releases
toolchains https://openrisc.io/software
building https://github.com/stffrdhrn/or1k-toolchain-build
or1ksim is the architectural simulator which will allow you to actually run 2) Building
your OpenRISC Linux kernel if you don't have an OpenRISC processor at hand.
git clone https://github.com/openrisc/or1ksim.git Build the Linux kernel as usual
cd or1ksim
./configure --prefix=$OPENRISC_PREFIX
make
make install
3) Linux kernel
Build the kernel as usual
make ARCH=openrisc defconfig make ARCH=openrisc defconfig
make ARCH=openrisc make ARCH=openrisc
4) Run in architectural simulator 3) Running on FPGA (optional)
Grab the or1ksim platform configuration file (from the or1ksim source) and The OpenRISC community typically uses FuseSoC to manage building and programming
together with your freshly built vmlinux, run your kernel with the following an SoC into an FPGA. The below is an example of programming a De0 Nano
incantation: development board with the OpenRISC SoC. During the build FPGA RTL is code
downloaded from the FuseSoC IP cores repository and built using the FPGA vendor
tools. Binaries are loaded onto the board with openocd.
sim -f arch/openrisc/or1ksim.cfg vmlinux git clone https://github.com/olofk/fusesoc
cd fusesoc
sudo pip install -e .
fusesoc init
fusesoc build de0_nano
fusesoc pgm de0_nano
openocd -f interface/altera-usb-blaster.cfg \
-f board/or1k_generic.cfg
telnet localhost 4444
> init
> halt; load_image vmlinux ; reset
4) Running on a Simulator (optional)
QEMU is a processor emulator which we recommend for simulating the OpenRISC
platform. Please follow the OpenRISC instructions on the QEMU website to get
Linux running on QEMU. You can build QEMU yourself, but your Linux distribution
likely provides binary packages to support OpenRISC.
qemu openrisc https://wiki.qemu.org/Documentation/Platforms/OpenRISC
--------------------------------------------------------------------- ---------------------------------------------------------------------
+4
View File
@@ -10037,7 +10037,11 @@ T: git git://github.com/openrisc/linux.git
L: openrisc@lists.librecores.org L: openrisc@lists.librecores.org
W: http://openrisc.io W: http://openrisc.io
S: Maintained S: Maintained
F: Documentation/devicetree/bindings/openrisc/
F: Documentation/openrisc/
F: arch/openrisc/ F: arch/openrisc/
F: drivers/irqchip/irq-ompic.c
F: drivers/irqchip/irq-or1k-*
OPENVSWITCH OPENVSWITCH
M: Pravin Shelar <pshelar@nicira.com> M: Pravin Shelar <pshelar@nicira.com>
+47 -2
View File
@@ -22,13 +22,19 @@ config OPENRISC
select HAVE_UID16 select HAVE_UID16
select GENERIC_ATOMIC64 select GENERIC_ATOMIC64
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select GENERIC_CLOCKEVENTS_BROADCAST
select GENERIC_STRNCPY_FROM_USER select GENERIC_STRNCPY_FROM_USER
select GENERIC_STRNLEN_USER select GENERIC_STRNLEN_USER
select GENERIC_SMP_IDLE_THREAD
select MODULES_USE_ELF_RELA select MODULES_USE_ELF_RELA
select HAVE_DEBUG_STACKOVERFLOW select HAVE_DEBUG_STACKOVERFLOW
select OR1K_PIC select OR1K_PIC
select CPU_NO_EFFICIENT_FFS if !OPENRISC_HAVE_INST_FF1 select CPU_NO_EFFICIENT_FFS if !OPENRISC_HAVE_INST_FF1
select NO_BOOTMEM select NO_BOOTMEM
select ARCH_USE_QUEUED_SPINLOCKS
select ARCH_USE_QUEUED_RWLOCKS
select OMPIC if SMP
select ARCH_WANT_FRAME_POINTERS
config CPU_BIG_ENDIAN config CPU_BIG_ENDIAN
def_bool y def_bool y
@@ -56,6 +62,12 @@ config TRACE_IRQFLAGS_SUPPORT
config GENERIC_CSUM config GENERIC_CSUM
def_bool y def_bool y
config STACKTRACE_SUPPORT
def_bool y
config LOCKDEP_SUPPORT
def_bool y
source "init/Kconfig" source "init/Kconfig"
source "kernel/Kconfig.freezer" source "kernel/Kconfig.freezer"
@@ -73,6 +85,17 @@ config OR1K_1200
endchoice endchoice
config DCACHE_WRITETHROUGH
bool "Have write through data caches"
default n
help
Select this if your implementation features write through data caches.
Selecting 'N' here will allow the kernel to force flushing of data
caches at relevant times. Most OpenRISC implementations support write-
through data caches.
If unsure say N here
config OPENRISC_BUILTIN_DTB config OPENRISC_BUILTIN_DTB
string "Builtin DTB" string "Builtin DTB"
default "" default ""
@@ -105,8 +128,19 @@ config OPENRISC_HAVE_INST_DIV
endmenu endmenu
config NR_CPUS config NR_CPUS
int int "Maximum number of CPUs (2-32)"
default "1" range 2 32
depends on SMP
default "2"
config SMP
bool "Symmetric Multi-Processing support"
help
This enables support for systems with more than one CPU. If you have
a system with only one CPU, say N. If you have a system with more
than one CPU, say Y.
If you don't know what to do here, say N.
source kernel/Kconfig.hz source kernel/Kconfig.hz
source kernel/Kconfig.preempt source kernel/Kconfig.preempt
@@ -125,6 +159,17 @@ config OPENRISC_NO_SPR_SR_DSX
Say N here if you know that your OpenRISC processor has Say N here if you know that your OpenRISC processor has
SPR_SR_DSX bit implemented. Say Y if you are unsure. SPR_SR_DSX bit implemented. Say Y if you are unsure.
config OPENRISC_HAVE_SHADOW_GPRS
bool "Support for shadow gpr files" if !SMP
default y if SMP
help
Say Y here if your OpenRISC processor features shadowed
register files. They will in such case be used as a
scratch reg storage on exception entry.
On SMP systems, this feature is mandatory.
On a unicore system it's safe to say N here if you are unsure.
config CMDLINE config CMDLINE
string "Default kernel command string" string "Default kernel command string"
default "" default ""
+1
View File
@@ -25,6 +25,7 @@ LDFLAGS_vmlinux :=
LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
KBUILD_CFLAGS += -pipe -ffixed-r10 -D__linux__ KBUILD_CFLAGS += -pipe -ffixed-r10 -D__linux__
CHECKFLAGS += -mbig-endian
ifeq ($(CONFIG_OPENRISC_HAVE_INST_MUL),y) ifeq ($(CONFIG_OPENRISC_HAVE_INST_MUL),y)
KBUILD_CFLAGS += $(call cc-option,-mhard-mul) KBUILD_CFLAGS += $(call cc-option,-mhard-mul)
+6 -1
View File
@@ -6,8 +6,13 @@
#size-cells = <1>; #size-cells = <1>;
interrupt-parent = <&pic>; interrupt-parent = <&pic>;
aliases {
uart0 = &serial0;
};
chosen { chosen {
bootargs = "console=uart,mmio,0x90000000,115200"; bootargs = "earlycon";
stdout-path = "uart0:115200";
}; };
memory@0 { memory@0 {
+63
View File
@@ -0,0 +1,63 @@
/dts-v1/;
/ {
compatible = "opencores,or1ksim";
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&pic>;
aliases {
uart0 = &serial0;
};
chosen {
bootargs = "earlycon";
stdout-path = "uart0: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>;
};
cpu@1 {
compatible = "opencores,or1200-rtlsvn481";
reg = <1>;
clock-frequency = <20000000>;
};
};
ompic: ompic@98000000 {
compatible = "openrisc,ompic";
reg = <0x98000000 16>;
interrupt-controller;
#interrupt-cells = <0>;
interrupts = <1>;
};
/*
* 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-level";
#interrupt-cells = <1>;
interrupt-controller;
};
serial0: serial@90000000 {
compatible = "opencores,uart16550-rtlsvn105", "ns16550a";
reg = <0x90000000 0x100>;
interrupts = <2>;
clock-frequency = <20000000>;
};
};
@@ -0,0 +1,66 @@
CONFIG_CROSS_COMPILE="or1k-linux-"
CONFIG_LOCALVERSION="-simple-smp"
CONFIG_NO_HZ=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_BLK_DEV_INITRD=y
# CONFIG_RD_GZIP is not set
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
# CONFIG_RD_XZ is not set
# CONFIG_RD_LZO is not set
# CONFIG_RD_LZ4 is not set
CONFIG_EXPERT=y
# 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="simple_smp"
CONFIG_SMP=y
CONFIG_HZ_100=y
CONFIG_OPENRISC_HAVE_SHADOW_GPRS=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_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_NETDEVICES=y
CONFIG_ETHOC=y
CONFIG_MICREL_PHY=y
# 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_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_USB_SUPPORT is not set
# CONFIG_DNOTIFY is not set
CONFIG_TMPFS=y
CONFIG_NFS_FS=y
CONFIG_XZ_DEC=y
# CONFIG_ENABLE_WARN_DEPRECATED is not set
# CONFIG_ENABLE_MUST_CHECK is not set
# CONFIG_RCU_TRACE is not set
+4 -1
View File
@@ -1,7 +1,6 @@
generic-y += barrier.h generic-y += barrier.h
generic-y += bug.h generic-y += bug.h
generic-y += bugs.h generic-y += bugs.h
generic-y += cacheflush.h
generic-y += checksum.h generic-y += checksum.h
generic-y += clkdev.h generic-y += clkdev.h
generic-y += current.h generic-y += current.h
@@ -28,6 +27,10 @@ generic-y += module.h
generic-y += pci.h generic-y += pci.h
generic-y += percpu.h generic-y += percpu.h
generic-y += preempt.h generic-y += preempt.h
generic-y += qspinlock_types.h
generic-y += qspinlock.h
generic-y += qrwlock_types.h
generic-y += qrwlock.h
generic-y += sections.h generic-y += sections.h
generic-y += segment.h generic-y += segment.h
generic-y += string.h generic-y += string.h
+96
View File
@@ -0,0 +1,96 @@
/*
* 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) Jan Henrik Weinstock <jan.weinstock@rwth-aachen.de>
* 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_CACHEFLUSH_H
#define __ASM_CACHEFLUSH_H
#include <linux/mm.h>
/*
* Helper function for flushing or invalidating entire pages from data
* and instruction caches. SMP needs a little extra work, since we need
* to flush the pages on all cpus.
*/
extern void local_dcache_page_flush(struct page *page);
extern void local_icache_page_inv(struct page *page);
/*
* Data cache flushing always happen on the local cpu. Instruction cache
* invalidations need to be broadcasted to all other cpu in the system in
* case of SMP configurations.
*/
#ifndef CONFIG_SMP
#define dcache_page_flush(page) local_dcache_page_flush(page)
#define icache_page_inv(page) local_icache_page_inv(page)
#else /* CONFIG_SMP */
#define dcache_page_flush(page) local_dcache_page_flush(page)
#define icache_page_inv(page) smp_icache_page_inv(page)
extern void smp_icache_page_inv(struct page *page);
#endif /* CONFIG_SMP */
/*
* Synchronizes caches. Whenever a cpu writes executable code to memory, this
* should be called to make sure the processor sees the newly written code.
*/
static inline void sync_icache_dcache(struct page *page)
{
if (!IS_ENABLED(CONFIG_DCACHE_WRITETHROUGH))
dcache_page_flush(page);
icache_page_inv(page);
}
/*
* Pages with this bit set need not be flushed/invalidated, since
* they have not changed since last flush. New pages start with
* PG_arch_1 not set and are therefore dirty by default.
*/
#define PG_dc_clean PG_arch_1
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
static inline void flush_dcache_page(struct page *page)
{
clear_bit(PG_dc_clean, &page->flags);
}
/*
* Other interfaces are not required since we do not have virtually
* indexed or tagged caches. So we can use the default here.
*/
#define flush_cache_all() do { } while (0)
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_dup_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
#define flush_icache_range(start, end) do { } while (0)
#define flush_icache_page(vma, pg) do { } while (0)
#define flush_icache_user_range(vma, pg, adr, len) do { } while (0)
#define flush_cache_vmap(start, end) do { } while (0)
#define flush_cache_vunmap(start, end) do { } while (0)
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
do { \
memcpy(dst, src, len); \
if (vma->vm_flags & VM_EXEC) \
sync_icache_dcache(page); \
} while (0)
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
memcpy(dst, src, len)
#endif /* __ASM_CACHEFLUSH_H */
+119 -36
View File
@@ -1,32 +1,29 @@
/* /*
* 1,2 and 4 byte cmpxchg and xchg implementations for OpenRISC.
*
* Copyright (C) 2014 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi> * Copyright (C) 2014 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
* Copyright (C) 2017 Stafford Horne <shorne@gmail.com>
* *
* This file is licensed under the terms of the GNU General Public License * This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any * version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied. * kind, whether express or implied.
*
* Note:
* The portable implementations of 1 and 2 byte xchg and cmpxchg using a 4
* byte cmpxchg is sourced heavily from the sh and mips implementations.
*/ */
#ifndef __ASM_OPENRISC_CMPXCHG_H #ifndef __ASM_OPENRISC_CMPXCHG_H
#define __ASM_OPENRISC_CMPXCHG_H #define __ASM_OPENRISC_CMPXCHG_H
#include <linux/types.h> #include <linux/types.h>
#include <linux/bitops.h>
/*
* This function doesn't exist, so you'll get a linker error
* if something tries to do an invalid cmpxchg().
*/
extern void __cmpxchg_called_with_bad_pointer(void);
#define __HAVE_ARCH_CMPXCHG 1 #define __HAVE_ARCH_CMPXCHG 1
static inline unsigned long static inline unsigned long cmpxchg_u32(volatile void *ptr,
__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) unsigned long old, unsigned long new)
{ {
if (size != 4) {
__cmpxchg_called_with_bad_pointer();
return old;
}
__asm__ __volatile__( __asm__ __volatile__(
"1: l.lwa %0, 0(%1) \n" "1: l.lwa %0, 0(%1) \n"
" l.sfeq %0, %2 \n" " l.sfeq %0, %2 \n"
@@ -43,28 +40,9 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
return old; return old;
} }
#define cmpxchg(ptr, o, n) \ static inline unsigned long xchg_u32(volatile void *ptr,
({ \ unsigned long val)
(__typeof__(*(ptr))) __cmpxchg((ptr), \
(unsigned long)(o), \
(unsigned long)(n), \
sizeof(*(ptr))); \
})
/*
* This function doesn't exist, so you'll get a linker error if
* something tries to do an invalidly-sized xchg().
*/
extern void __xchg_called_with_bad_pointer(void);
static inline unsigned long __xchg(unsigned long val, volatile void *ptr,
int size)
{ {
if (size != 4) {
__xchg_called_with_bad_pointer();
return val;
}
__asm__ __volatile__( __asm__ __volatile__(
"1: l.lwa %0, 0(%1) \n" "1: l.lwa %0, 0(%1) \n"
" l.swa 0(%1), %2 \n" " l.swa 0(%1), %2 \n"
@@ -77,10 +55,115 @@ static inline unsigned long __xchg(unsigned long val, volatile void *ptr,
return val; return val;
} }
static inline u32 cmpxchg_small(volatile void *ptr, u32 old, u32 new,
int size)
{
int off = (unsigned long)ptr % sizeof(u32);
volatile u32 *p = ptr - off;
#ifdef __BIG_ENDIAN
int bitoff = (sizeof(u32) - size - off) * BITS_PER_BYTE;
#else
int bitoff = off * BITS_PER_BYTE;
#endif
u32 bitmask = ((0x1 << size * BITS_PER_BYTE) - 1) << bitoff;
u32 load32, old32, new32;
u32 ret;
load32 = READ_ONCE(*p);
while (true) {
ret = (load32 & bitmask) >> bitoff;
if (old != ret)
return ret;
old32 = (load32 & ~bitmask) | (old << bitoff);
new32 = (load32 & ~bitmask) | (new << bitoff);
/* Do 32 bit cmpxchg */
load32 = cmpxchg_u32(p, old32, new32);
if (load32 == old32)
return old;
}
}
/* xchg */
static inline u32 xchg_small(volatile void *ptr, u32 x, int size)
{
int off = (unsigned long)ptr % sizeof(u32);
volatile u32 *p = ptr - off;
#ifdef __BIG_ENDIAN
int bitoff = (sizeof(u32) - size - off) * BITS_PER_BYTE;
#else
int bitoff = off * BITS_PER_BYTE;
#endif
u32 bitmask = ((0x1 << size * BITS_PER_BYTE) - 1) << bitoff;
u32 oldv, newv;
u32 ret;
do {
oldv = READ_ONCE(*p);
ret = (oldv & bitmask) >> bitoff;
newv = (oldv & ~bitmask) | (x << bitoff);
} while (cmpxchg_u32(p, oldv, newv) != oldv);
return ret;
}
/*
* This function doesn't exist, so you'll get a linker error
* if something tries to do an invalid cmpxchg().
*/
extern unsigned long __cmpxchg_called_with_bad_pointer(void)
__compiletime_error("Bad argument size for cmpxchg");
static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
unsigned long new, int size)
{
switch (size) {
case 1:
case 2:
return cmpxchg_small(ptr, old, new, size);
case 4:
return cmpxchg_u32(ptr, old, new);
default:
return __cmpxchg_called_with_bad_pointer();
}
}
#define cmpxchg(ptr, o, n) \
({ \
(__typeof__(*(ptr))) __cmpxchg((ptr), \
(unsigned long)(o), \
(unsigned long)(n), \
sizeof(*(ptr))); \
})
/*
* This function doesn't exist, so you'll get a linker error if
* something tries to do an invalidly-sized xchg().
*/
extern unsigned long __xchg_called_with_bad_pointer(void)
__compiletime_error("Bad argument size for xchg");
static inline unsigned long __xchg(volatile void *ptr, unsigned long with,
int size)
{
switch (size) {
case 1:
case 2:
return xchg_small(ptr, with, size);
case 4:
return xchg_u32(ptr, with);
default:
return __xchg_called_with_bad_pointer();
}
}
#define xchg(ptr, with) \ #define xchg(ptr, with) \
({ \ ({ \
(__typeof__(*(ptr))) __xchg((unsigned long)(with), \ (__typeof__(*(ptr))) __xchg((ptr), \
(ptr), \ (unsigned long)(with), \
sizeof(*(ptr))); \ sizeof(*(ptr))); \
}) })
+5 -2
View File
@@ -19,7 +19,7 @@
#ifndef __ASM_OPENRISC_CPUINFO_H #ifndef __ASM_OPENRISC_CPUINFO_H
#define __ASM_OPENRISC_CPUINFO_H #define __ASM_OPENRISC_CPUINFO_H
struct cpuinfo { struct cpuinfo_or1k {
u32 clock_frequency; u32 clock_frequency;
u32 icache_size; u32 icache_size;
@@ -29,8 +29,11 @@ struct cpuinfo {
u32 dcache_size; u32 dcache_size;
u32 dcache_block_size; u32 dcache_block_size;
u32 dcache_ways; u32 dcache_ways;
u16 coreid;
}; };
extern struct cpuinfo cpuinfo; extern struct cpuinfo_or1k cpuinfo_or1k[NR_CPUS];
extern void setup_cpuinfo(void);
#endif /* __ASM_OPENRISC_CPUINFO_H */ #endif /* __ASM_OPENRISC_CPUINFO_H */
+1 -1
View File
@@ -34,7 +34,7 @@ extern void switch_mm(struct mm_struct *prev, struct mm_struct *next,
* registers like cr3 on the i386 * registers like cr3 on the i386
*/ */
extern volatile pgd_t *current_pgd; /* defined in arch/openrisc/mm/fault.c */ 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) static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{ {
+11 -7
View File
@@ -94,7 +94,7 @@ extern void paging_init(void);
* 64 MB of vmalloc area is comparable to what's available on other arches. * 64 MB of vmalloc area is comparable to what's available on other arches.
*/ */
#define VMALLOC_START (PAGE_OFFSET-0x04000000) #define VMALLOC_START (PAGE_OFFSET-0x04000000UL)
#define VMALLOC_END (PAGE_OFFSET) #define VMALLOC_END (PAGE_OFFSET)
#define VMALLOC_VMADDR(x) ((unsigned long)(x)) #define VMALLOC_VMADDR(x) ((unsigned long)(x))
@@ -416,15 +416,19 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; /* defined in head.S */
struct vm_area_struct; struct vm_area_struct;
/* static inline void update_tlb(struct vm_area_struct *vma,
* or32 doesn't have any external MMU info: the kernel page unsigned long address, pte_t *pte)
* tables contain all the necessary information. {
* }
* Actually I am not sure on what this could be used for.
*/ extern void update_cache(struct vm_area_struct *vma,
unsigned long address, pte_t *pte);
static inline void update_mmu_cache(struct vm_area_struct *vma, static inline void update_mmu_cache(struct vm_area_struct *vma,
unsigned long address, pte_t *pte) unsigned long address, pte_t *pte)
{ {
update_tlb(vma, address, pte);
update_cache(vma, address, pte);
} }
/* __PHX__ FIXME, SWAP, this probably doesn't work */ /* __PHX__ FIXME, SWAP, this probably doesn't work */
+1 -1
View File
@@ -29,7 +29,7 @@
* it needs to be correct to get the early console working. * it needs to be correct to get the early console working.
*/ */
#define BASE_BAUD (cpuinfo.clock_frequency/16) #define BASE_BAUD (cpuinfo_or1k[smp_processor_id()].clock_frequency/16)
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
+26
View File
@@ -0,0 +1,26 @@
/*
* Copyright (C) 2014 Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*/
#ifndef __ASM_OPENRISC_SMP_H
#define __ASM_OPENRISC_SMP_H
#include <asm/spr.h>
#include <asm/spr_defs.h>
#define raw_smp_processor_id() (current_thread_info()->cpu)
#define hard_smp_processor_id() mfspr(SPR_COREID)
extern void smp_init_cpus(void);
extern void arch_send_call_function_single_ipi(int cpu);
extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
extern void set_smp_cross_call(void (*)(const struct cpumask *, unsigned int));
extern void handle_IPI(unsigned int ipi_msg);
#endif /* __ASM_OPENRISC_SMP_H */
+11 -1
View File
@@ -19,6 +19,16 @@
#ifndef __ASM_OPENRISC_SPINLOCK_H #ifndef __ASM_OPENRISC_SPINLOCK_H
#define __ASM_OPENRISC_SPINLOCK_H #define __ASM_OPENRISC_SPINLOCK_H
#error "or32 doesn't do SMP yet" #include <asm/qspinlock.h>
#include <asm/qrwlock.h>
#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
#define arch_spin_relax(lock) cpu_relax()
#define arch_read_relax(lock) cpu_relax()
#define arch_write_relax(lock) cpu_relax()
#endif #endif

Some files were not shown because too many files have changed in this diff Show More