mirror of https://gitee.com/openkylin/linux.git
h8300 pull request for 4.2
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJVi5eKAAoJEEdC8EELKDmcZWoQANh4UC+JGcP3XJ+AWyJpX1Rg VQMmSAiF/QZr3ty9sbU/6v3pNK5B1s2etY7lWzzCsp7GMhYln83OjwJn8pkcAvRk 4GoEio4Yp0RMTOYk1nvKEhUGnxLwpma+xX5ulZkSTaYhZl++eX8HUGmfHhpxMcK9 Unz1Y7vRIRaNUIawZECijxVj9yvteczwdwjWBp7AH2HChZ3LWJGo2xikd1Jwizx8 zPv+mdaHkV9gbORS53hvqVaXXjiZVmLKQEz6LlWHubuWysf98YcBzNAhSKpjQzqW cwjXyw3MNc5fPjliwUstN/9ImWFdRJgwmdQ0DJ1v6kWPbHMQ4lCxeasy02YJ7l0R TWUOTyTSGT7Hd8CRrryo7akQ3nt8g7fZAR6nVujexbjkSt9ZbBSplAikiSKRbjU2 7jkolYSM1ADqEeBBwcDnG2O45Pv8PxKGa4/8MV2hkcvrkkJp2lW+KybY0qp19MWb Dw09QYzFb5u6sKqD6AsjJQ6GKxLxNn3yBKk16V1yF0kAvQRdIj0XPgtMnGUgdkAw QA1nRQM25CLyOtH9SVWogRLof8UTZUlPtUCxKRww2//pAVkKGHg/afnnkqN933Yc Kv7/Mz2es6Km+D4qkQetnXF/IOxWfVUvnQa23Oe7gmkg4KNNrGO6bo7iQXDjDrHa LuNfJZRG5DzDjbdcp2t3 =fE8E -----END PGP SIGNATURE----- Merge tag 'for-4.2' of git://git.sourceforge.jp/gitroot/uclinux-h8/linux Pull Renesas H8/300 architecture re-introduction from Yoshinori Sato. We dropped arch/h8300 two years ago as stale and old, this is a new and more modern rewritten arch support for the same architecture. * tag 'for-4.2' of git://git.sourceforge.jp/gitroot/uclinux-h8/linux: (27 commits) h8300: fix typo. h8300: Always build dtb h8300: Remove ARCH_WANT_IPC_PARSE_VERSION sh-sci: Get register size from platform device clk: h8300: fix error handling in h8s2678_pll_clk_setup() h8300: Symbol name fix h8300: devicetree source h8300: configs h8300: IRQ chip driver h8300: clocksource h8300: clock driver h8300: Build scripts h8300: library functions h8300: Memory management h8300: miscellaneous functions h8300: process helpers h8300: compressed image support h8300: Low level entry h8300: kernel startup h8300: Interrupt and exceptions ...
This commit is contained in:
commit
55a7d4b85c
5
CREDITS
5
CREDITS
|
@ -3219,11 +3219,6 @@ N: Dipankar Sarma
|
|||
E: dipankar@in.ibm.com
|
||||
D: RCU
|
||||
|
||||
N: Yoshinori Sato
|
||||
E: ysato@users.sourceforge.jp
|
||||
D: uClinux for Renesas H8/300 (H8300)
|
||||
D: http://uclinux-h8.sourceforge.jp/
|
||||
|
||||
N: Hannu Savolainen
|
||||
E: hannu@opensound.com
|
||||
D: Maintainer of the sound drivers until 2.1.x days.
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
* Renesas H8/300 divider clock
|
||||
|
||||
Required Properties:
|
||||
|
||||
- compatible: Must be "renesas,sh73a0-h8300-div-clock"
|
||||
|
||||
- clocks: Reference to the parent clocks ("extal1" and "extal2")
|
||||
|
||||
- #clock-cells: Must be 1
|
||||
|
||||
- reg: Base address and length of the divide rate selector
|
||||
|
||||
- renesas,width: bit width of selector
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
cclk: cclk {
|
||||
compatible = "renesas,h8300-div-clock";
|
||||
clocks = <&xclk>;
|
||||
#clock-cells = <0>;
|
||||
reg = <0xfee01b 2>;
|
||||
renesas,width = <2>;
|
||||
};
|
|
@ -0,0 +1,23 @@
|
|||
Renesas H8S2678 PLL clock
|
||||
|
||||
This device is Clock multiplyer
|
||||
|
||||
Required Properties:
|
||||
|
||||
- compatible: Must be "renesas,h8s2678-pll-clock"
|
||||
|
||||
- clocks: Reference to the parent clocks
|
||||
|
||||
- #clock-cells: Must be 0
|
||||
|
||||
- reg: Two rate selector (Multiply / Divide) register address
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
pllclk: pllclk {
|
||||
compatible = "renesas,h8s2678-pll-clock";
|
||||
clocks = <&xclk>;
|
||||
#clock-cells = <0>;
|
||||
reg = <0xfee03b 2>, <0xfee045 2>;
|
||||
};
|
|
@ -0,0 +1,13 @@
|
|||
* H8/300 CPU bindings
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: Compatible property value should be "renesas,h8300".
|
||||
- clock-frequency: Contains the clock frequency for CPU, in Hz.
|
||||
|
||||
Example:
|
||||
|
||||
cpu@0 {
|
||||
compatible = "renesas,h8300";
|
||||
clock-frequency = <20000000>;
|
||||
};
|
|
@ -0,0 +1,22 @@
|
|||
* H8/300H Interrupt controller
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: has to be "renesas,h8300h-intc", "renesas,h8300-intc" as fallback.
|
||||
- #interrupt-cells: has to be <2>: an interrupt index and flags, as defined in
|
||||
interrupts.txt in this directory
|
||||
- regs: Base address of interrupt controller registers.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- any properties, listed in interrupts.txt, and any standard resource allocation
|
||||
properties
|
||||
|
||||
Example:
|
||||
|
||||
h8intc: interrupt-controller@fee012 {
|
||||
compatible = "renesas,h8300h-intc", "renesas,h8300-intc";
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-controller;
|
||||
reg = <0xfee012 7>;
|
||||
};
|
|
@ -0,0 +1,22 @@
|
|||
* H8S Interrupt controller
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: has to be "renesas,h8s-intc", "renesas,h8300-intc" as fallback.
|
||||
- #interrupt-cells: has to be <2>: an interrupt index and flags, as defined in
|
||||
interrupts.txt in this directory
|
||||
- regs: Base address of interrupt controller registers.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- any properties, listed in interrupts.txt, and any standard resource allocation
|
||||
properties
|
||||
|
||||
Example:
|
||||
|
||||
h8intc: interrupt-controller@fffe00 {
|
||||
compatible = "renesas,h8s-intc", "renesas,h8300-intc";
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-controller;
|
||||
reg = <0xfffe00 24>;
|
||||
};
|
|
@ -0,0 +1,12 @@
|
|||
* H8/300 bus controller
|
||||
|
||||
Required properties:
|
||||
- compatible: Must be "renesas,h8300-bsc".
|
||||
- reg: Base address and length of BSC registers.
|
||||
|
||||
Example.
|
||||
bsc: memory-controller@fee01e {
|
||||
compatible = "renesas,h8300h-bsc", "renesas,h8300-bsc";
|
||||
reg = <0xfee01e 8>;
|
||||
};
|
||||
|
|
@ -29,6 +29,7 @@ Required properties:
|
|||
- "renesas,scifa" for generic SCIFA compatible UART.
|
||||
- "renesas,scifb" for generic SCIFB compatible UART.
|
||||
- "renesas,hscif" for generic HSCIF compatible UART.
|
||||
- "renesas,sci" for generic SCI compatible UART.
|
||||
|
||||
When compatible with the generic version, nodes must list the
|
||||
SoC-specific version corresponding to the platform first followed by the
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
* Renesas H8/300 16bit timer
|
||||
|
||||
The 16bit timer is a 16bit timer/counter with configurable clock inputs and
|
||||
programmable compare match.
|
||||
|
||||
Required Properties:
|
||||
|
||||
- compatible: must contain "renesas,16bit-timer"
|
||||
- reg: base address and length of the registers block for the timer module.
|
||||
- interrupts: interrupt-specifier for the timer, IMIA
|
||||
- clocks: a list of phandle, one for each entry in clock-names.
|
||||
- clock-names: must contain "peripheral_clk" for the functional clock.
|
||||
- renesas,channel: timer channel number.
|
||||
|
||||
Example:
|
||||
|
||||
timer16: timer@ffff68 {
|
||||
compatible = "reneas,16bit-timer";
|
||||
reg = <0xffff68 8>, <0xffff60 8>;
|
||||
interrupts = <24>;
|
||||
renesas,channel = <0>;
|
||||
clocks = <&pclk>;
|
||||
clock-names = "peripheral_clk";
|
||||
};
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
* Renesas H8/300 8bit timer
|
||||
|
||||
The 8bit timer is a 8bit timer/counter with configurable clock inputs and
|
||||
programmable compare match.
|
||||
|
||||
This implement only supported cascade mode.
|
||||
|
||||
Required Properties:
|
||||
|
||||
- compatible: must contain "renesas,8bit-timer"
|
||||
- reg: base address and length of the registers block for the timer module.
|
||||
- interrupts: interrupt-specifier for the timer, CMIA and TOVI
|
||||
- clocks: a list of phandle, one for each entry in clock-names.
|
||||
- clock-names: must contain "fck" for the functional clock.
|
||||
|
||||
Example:
|
||||
|
||||
timer8_0: timer@ffff80 {
|
||||
compatible = "renesas,8bit-timer";
|
||||
reg = <0xffff80 10>;
|
||||
interrupts = <36>;
|
||||
clocks = <&fclk>;
|
||||
clock-names = "fck";
|
||||
};
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
* Renesas H8/300 Timer Pluse Unit
|
||||
|
||||
The TPU is a 16bit timer/counter with configurable clock inputs and
|
||||
programmable compare match.
|
||||
This implementation support only cascade mode.
|
||||
|
||||
Required Properties:
|
||||
|
||||
- compatible: must contain "renesas,tpu"
|
||||
- reg: base address and length of the registers block in 2 channel.
|
||||
- clocks: a list of phandle, one for each entry in clock-names.
|
||||
- clock-names: must contain "peripheral_clk" for the functional clock.
|
||||
|
||||
|
||||
Example:
|
||||
tpu: tpu@ffffe0 {
|
||||
compatible = "renesas,tpu";
|
||||
reg = <0xffffe0 16>, <0xfffff0 12>;
|
||||
clocks = <&pclk>;
|
||||
clock-names = "peripheral_clk";
|
||||
};
|
11
MAINTAINERS
11
MAINTAINERS
|
@ -4549,6 +4549,17 @@ T: git git://linuxtv.org/media_tree.git
|
|||
S: Maintained
|
||||
F: drivers/media/usb/stk1160/
|
||||
|
||||
H8/300 ARCHITECTURE
|
||||
M: Yoshinori Sato <ysato@users.sourceforge.jp>
|
||||
L: uclinux-h8-devel@lists.sourceforge.jp
|
||||
W: http://uclinux-h8.sourceforge.jp
|
||||
T: git git://git.sourceforge.jp/gitroot/uclinux-h8/linux.git
|
||||
S: Maintained
|
||||
F: arch/h8300/
|
||||
F: drivers/clocksource/h8300_*.c
|
||||
F: drivers/clk/h8300/
|
||||
F: drivers/irqchip/irq-renesas-h8*.c
|
||||
|
||||
HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
|
||||
M: Frank Seidel <frank@f-seidel.de>
|
||||
L: platform-driver-x86@vger.kernel.org
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
config H8300
|
||||
def_bool y
|
||||
select GENERIC_ATOMIC64
|
||||
select HAVE_UID16
|
||||
select VIRT_TO_BUS
|
||||
select GENERIC_IRQ_SHOW
|
||||
select FRAME_POINTER
|
||||
select GENERIC_CPU_DEVICES
|
||||
select MODULES_USE_ELF_RELA
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select CLKDEV_LOOKUP
|
||||
select COMMON_CLK
|
||||
select ARCH_WANT_FRAME_POINTERS
|
||||
select OF
|
||||
select OF_IRQ
|
||||
select OF_EARLY_FLATTREE
|
||||
select HAVE_MEMBLOCK
|
||||
select HAVE_DMA_ATTRS
|
||||
|
||||
config RWSEM_GENERIC_SPINLOCK
|
||||
def_bool y
|
||||
|
||||
config GENERIC_HWEIGHT
|
||||
def_bool y
|
||||
|
||||
config NO_IOPORT_MAP
|
||||
def_bool y
|
||||
|
||||
config GENERIC_CSUM
|
||||
def_bool y
|
||||
|
||||
config HZ
|
||||
int
|
||||
default 100
|
||||
|
||||
config NR_CPUS
|
||||
int
|
||||
default 1
|
||||
|
||||
source "init/Kconfig"
|
||||
|
||||
source "kernel/Kconfig.freezer"
|
||||
|
||||
source "arch/h8300/Kconfig.cpu"
|
||||
|
||||
menu "Kernel Features"
|
||||
|
||||
source "kernel/Kconfig.preempt"
|
||||
|
||||
source "mm/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Executable file formats"
|
||||
|
||||
source "fs/Kconfig.binfmt"
|
||||
|
||||
endmenu
|
||||
|
||||
source "net/Kconfig"
|
||||
|
||||
source "drivers/Kconfig"
|
||||
|
||||
source "fs/Kconfig"
|
||||
|
||||
menu "Kernel hacking"
|
||||
|
||||
source "lib/Kconfig.debug"
|
||||
|
||||
endmenu
|
||||
|
||||
source "security/Kconfig"
|
||||
|
||||
source "crypto/Kconfig"
|
||||
|
||||
source "lib/Kconfig"
|
|
@ -0,0 +1,99 @@
|
|||
config CPU_H8300H
|
||||
bool
|
||||
|
||||
config CPU_H8S
|
||||
bool
|
||||
|
||||
config H83069
|
||||
bool
|
||||
select CPU_H8300H
|
||||
select H8300_TMR16
|
||||
select RENESAS_H8300H_INTC
|
||||
|
||||
config H8S2678
|
||||
bool
|
||||
select CPU_H8S
|
||||
select H8300_TPU
|
||||
select RENESAS_H8S_INTC
|
||||
|
||||
config RAMKERNEL
|
||||
bool
|
||||
|
||||
config ROMKERNEL
|
||||
bool
|
||||
|
||||
menu "Processor type and features"
|
||||
|
||||
choice
|
||||
prompt "H8/300 platform"
|
||||
|
||||
config H8300_AE3068
|
||||
bool "AE-3068/69"
|
||||
select H83069
|
||||
select RAMKERNEL
|
||||
help
|
||||
AKI-H8/3068F / AKI-H8/3069F Flashmicom LAN Board Support
|
||||
More Information. (Japanese Only)
|
||||
<http://akizukidenshi.com/catalog/default.aspx>
|
||||
AE-3068/69 Evaluation Board Support
|
||||
More Information.
|
||||
<http://www.microtronique.com/ae3069lan.htm>
|
||||
|
||||
config H8300_H8MAX
|
||||
bool "H8MAX"
|
||||
select H83069
|
||||
select RAMKERNEL
|
||||
select HAVE_IDE
|
||||
help
|
||||
H8MAX Evaluation Board Support
|
||||
More Information. (Japanese Only)
|
||||
<http://strawberry-linux.com/h8/index.html>
|
||||
|
||||
config H8300_KANEBEBE
|
||||
bool "KaneBebe"
|
||||
select H83069
|
||||
select RAMKERNEL
|
||||
help
|
||||
KaneBebe Evalition Board Support
|
||||
More Information. (Japanese Only)
|
||||
<http://www.nissin-tech.com/2009/10/uclinuxkane-bebe-h83069f.html>
|
||||
|
||||
config H8300H_SIM
|
||||
bool "H8/300H GDB Simulator"
|
||||
select H83069
|
||||
select ROMKERNEL
|
||||
help
|
||||
GDB Simulator Support
|
||||
More Information.
|
||||
<http://sourceware.org/sid/>
|
||||
|
||||
config H8S_EDOSK2674
|
||||
bool "EDOSK-2674"
|
||||
select H8S2678
|
||||
select RAMKERNEL
|
||||
help
|
||||
Renesas EDOSK-2674 Evaluation Board Support
|
||||
More Information.
|
||||
<http://www.azpower.com/H8-uClinux/index.html>
|
||||
<http://www.renesas.eu/products/tools/introductory_evaluation_tools/evaluation_development_os_kits/edosk2674r/edosk2674r_software_tools_root.jsp>
|
||||
|
||||
config H8S_SIM
|
||||
bool "H8S GDB Simulator"
|
||||
select H8S2678
|
||||
select ROMKERNEL
|
||||
help
|
||||
GDB Simulator Support
|
||||
More Information.
|
||||
<http://sourceware.org/sid/>
|
||||
|
||||
endchoice
|
||||
|
||||
config H8300_BUILTIN_DTB
|
||||
string "Builtin DTB"
|
||||
default ""
|
||||
|
||||
config OFFSET
|
||||
hex "Load offset"
|
||||
default 0
|
||||
|
||||
endmenu
|
|
@ -0,0 +1,55 @@
|
|||
#
|
||||
# arch/h8300/Makefile
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# (C) Copyright 2002-2015 Yoshinori Sato <ysato@users.sourceforge.jp>
|
||||
#
|
||||
|
||||
cflags-$(CONFIG_CPU_H8300H) := -mh
|
||||
aflags-$(CONFIG_CPU_H8300H) := -mh -Wa,--mach=h8300h
|
||||
ldflags-$(CONFIG_CPU_H8300H) := -mh8300helf_linux
|
||||
cflags-$(CONFIG_CPU_H8S) := -ms
|
||||
aflags-$(CONFIG_CPU_H8S) := -ms -Wa,--mach=h8300s
|
||||
ldflags-$(CONFIG_CPU_H8S) := -mh8300self_linux
|
||||
|
||||
KBUILD_CFLAGS += $(cflags-y)
|
||||
KBUILD_CFLAGS += -mint32 -fno-builtin
|
||||
KBUILD_CFLAGS += -D__linux__
|
||||
KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\"
|
||||
KBUILD_AFLAGS += $(aflags-y)
|
||||
LDFLAGS += $(ldflags-y)
|
||||
|
||||
CROSS_COMPILE := h8300-unknown-linux-
|
||||
|
||||
core-y += arch/$(ARCH)/kernel/ arch/$(ARCH)/mm/
|
||||
ifneq '$(CONFIG_H8300_BUILTIN_DTB)' '""'
|
||||
core-y += arch/h8300/boot/dts/
|
||||
endif
|
||||
|
||||
libs-y += arch/$(ARCH)/lib/
|
||||
|
||||
boot := arch/h8300/boot
|
||||
|
||||
%.dtb %.dtb.S %.dtb.o: | scripts
|
||||
$(Q)$(MAKE) $(build)=arch/h8300/boot/dts arch/h8300/boot/dts/$@
|
||||
|
||||
PHONY += dtbs
|
||||
dtbs: scripts
|
||||
$(Q)$(MAKE) $(build)=arch/h8300/boot/dts
|
||||
|
||||
archmrproper:
|
||||
|
||||
archclean:
|
||||
$(Q)$(MAKE) $(clean)=$(boot)
|
||||
|
||||
vmlinux.srec vmlinux.bin zImage uImage.bin: vmlinux
|
||||
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
|
||||
|
||||
define archhelp
|
||||
@echo 'vmlinux.bin - Create raw binary'
|
||||
@echo 'vmlinux.srec - Create srec binary'
|
||||
@echo 'zImage - Compressed kernel image'
|
||||
endef
|
|
@ -0,0 +1,26 @@
|
|||
# arch/h8300/boot/Makefile
|
||||
|
||||
targets := vmlinux.srec vmlinux.bin zImage
|
||||
subdir- := compressed
|
||||
|
||||
OBJCOPYFLAGS_vmlinux.srec := -Osrec
|
||||
OBJCOPYFLAGS_vmlinux.bin := -Obinary
|
||||
OBJCOPYFLAGS_zImage := -O binary -R .note -R .comment -R .stab -R .stabstr -S
|
||||
|
||||
UIMAGE_LOADADDR = $(CONFIG_RAMBASE)
|
||||
UIMAGE_ENTRYADDR = $(shell /bin/bash -c 'printf "0x%08x" \
|
||||
$$[$(CONFIG_RAMBASE) + $(CONFIG_OFFSET)]')
|
||||
|
||||
$(obj)/vmlinux.srec $(obj)/vmlinux.bin: vmlinux FORCE
|
||||
$(call if_changed,objcopy)
|
||||
|
||||
$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
|
||||
$(call if_changed,objcopy)
|
||||
|
||||
$(obj)/compressed/vmlinux: FORCE
|
||||
$(Q)$(MAKE) $(build)=$(obj)/compressed $@
|
||||
|
||||
$(obj)/uImage.bin: $(obj)/vmlinux.bin
|
||||
$(call if_changed,uimage,none)
|
||||
|
||||
CLEAN_FILES += arch/$(ARCH)/vmlinux.bin arch/$(ARCH)/vmlinux.srec arch/$(ARCH)/uImage.bin
|
|
@ -0,0 +1,37 @@
|
|||
#
|
||||
# linux/arch/sh/boot/compressed/Makefile
|
||||
#
|
||||
# create a compressed vmlinux image from the original vmlinux
|
||||
#
|
||||
|
||||
targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
|
||||
|
||||
OBJECTS = $(obj)/head.o $(obj)/misc.o
|
||||
|
||||
#
|
||||
# IMAGE_OFFSET is the load offset of the compression loader
|
||||
# Assign dummy values if these 2 variables are not defined,
|
||||
# in order to suppress error message.
|
||||
#
|
||||
CONFIG_MEMORY_START ?= 0x00400000
|
||||
CONFIG_BOOT_LINK_OFFSET ?= 0x00140000
|
||||
IMAGE_OFFSET := $(shell printf "0x%08x" $$(($(CONFIG_MEMORY_START)+$(CONFIG_BOOT_LINK_OFFSET))))
|
||||
|
||||
LIBGCC := $(shell $(CROSS-COMPILE)$(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
|
||||
LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -estartup $(obj)/vmlinux.lds
|
||||
|
||||
$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(LIBGCC) FORCE
|
||||
$(call if_changed,ld)
|
||||
@:
|
||||
|
||||
$(obj)/vmlinux.bin: vmlinux FORCE
|
||||
$(call if_changed,objcopy)
|
||||
|
||||
$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
|
||||
$(call if_changed,gzip)
|
||||
|
||||
LDFLAGS_piggy.o := -r --format binary --oformat elf32-h8300-linux -T
|
||||
OBJCOPYFLAGS := -O binary
|
||||
|
||||
$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE
|
||||
$(call if_changed,ld)
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* linux/arch/h8300/boot/compressed/head.S
|
||||
*
|
||||
* Copyright (C) 2006 Yoshinori Sato
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
|
||||
.section .text..startup,"ax"
|
||||
.global startup
|
||||
startup:
|
||||
mov.l er0, er4
|
||||
mov.l er0, sp
|
||||
mov.l #__sbss, er0
|
||||
mov.l #__ebss, er1
|
||||
sub.l er0, er1
|
||||
shlr er1
|
||||
shlr er1
|
||||
sub.l er2, er2
|
||||
1:
|
||||
mov.l er2, @er0
|
||||
adds #4, er0
|
||||
dec.l #1, er1
|
||||
bne 1b
|
||||
jsr @decompress_kernel
|
||||
mov.l er4, er0
|
||||
jmp @0x400000
|
||||
|
||||
.align 9
|
||||
fake_headers_as_bzImage:
|
||||
.word 0
|
||||
.ascii "HdrS" ; header signature
|
||||
.word 0x0202 ; header version number (>= 0x0105)
|
||||
; or else old loadlin-1.5 will fail)
|
||||
.word 0 ; default_switch
|
||||
.word 0 ; SETUPSEG
|
||||
.word 0x1000
|
||||
.word 0 ; pointing to kernel version string
|
||||
.byte 0 ; = 0, old one (LILO, Loadlin,
|
||||
; 0xTV: T=0 for LILO
|
||||
; V = version
|
||||
.byte 1 ; Load flags bzImage=1
|
||||
.word 0x8000 ; size to move, when setup is not
|
||||
.long 0x100000 ; 0x100000 = default for big kernel
|
||||
.long 0 ; address of loaded ramdisk image
|
||||
.long 0 ; its size in bytes
|
||||
|
||||
.end
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* arch/h8300/boot/compressed/misc.c
|
||||
*
|
||||
* This is a collection of several routines from gzip-1.0.3
|
||||
* adapted for Linux.
|
||||
*
|
||||
* malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
|
||||
*
|
||||
* Adapted for h8300 by Yoshinori Sato 2006
|
||||
*/
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
/*
|
||||
* gzip declarations
|
||||
*/
|
||||
|
||||
#define OF(args) args
|
||||
#define STATIC static
|
||||
|
||||
#undef memset
|
||||
#undef memcpy
|
||||
#define memzero(s, n) memset((s), (0), (n))
|
||||
|
||||
extern int _end;
|
||||
static unsigned long free_mem_ptr;
|
||||
static unsigned long free_mem_end_ptr;
|
||||
|
||||
extern char input_data[];
|
||||
extern int input_len;
|
||||
static unsigned char *output;
|
||||
|
||||
#define HEAP_SIZE 0x10000
|
||||
|
||||
#include "../../../../lib/decompress_inflate.c"
|
||||
|
||||
void *memset(void *s, int c, size_t n)
|
||||
{
|
||||
int i;
|
||||
char *ss = (char *)s;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
ss[i] = c;
|
||||
return s;
|
||||
}
|
||||
|
||||
void *memcpy(void *dest, const void *src, size_t n)
|
||||
{
|
||||
int i;
|
||||
char *d = (char *)dest, *s = (char *)src;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
d[i] = s[i];
|
||||
return dest;
|
||||
}
|
||||
|
||||
static void error(char *x)
|
||||
{
|
||||
|
||||
while (1)
|
||||
; /* Halt */
|
||||
}
|
||||
|
||||
#define STACK_SIZE (4096)
|
||||
long user_stack[STACK_SIZE];
|
||||
long *stack_start = &user_stack[STACK_SIZE];
|
||||
|
||||
void decompress_kernel(void)
|
||||
{
|
||||
free_mem_ptr = (unsigned long)&_end;
|
||||
free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
|
||||
|
||||
decompress(input_data, input_len, NULL, NULL, output, NULL, error);
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
__stext = . ;
|
||||
__text = .;
|
||||
*(.text..startup)
|
||||
*(.text)
|
||||
__etext = . ;
|
||||
}
|
||||
|
||||
.rodata :
|
||||
{
|
||||
*(.rodata)
|
||||
}
|
||||
.data :
|
||||
|
||||
{
|
||||
__sdata = . ;
|
||||
___data_start = . ;
|
||||
*(.data.*)
|
||||
}
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(0x4) ;
|
||||
__sbss = . ;
|
||||
*(.bss*)
|
||||
. = ALIGN(0x4) ;
|
||||
__ebss = . ;
|
||||
__end = . ;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
SECTIONS
|
||||
{
|
||||
.data : {
|
||||
input_len = .;
|
||||
LONG(input_data_end - input_data) input_data = .;
|
||||
*(.data)
|
||||
input_data_end = .;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
ifneq '$(CONFIG_H8300_BUILTIN_DTB)' '""'
|
||||
BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_H8300_BUILTIN_DTB)).dtb.o
|
||||
endif
|
||||
|
||||
obj-y += $(BUILTIN_DTB)
|
||||
|
||||
dtb-$(CONFIG_H8300H_SIM) := h8300h_sim.dtb
|
||||
dtb-$(CONFIG_H8S_SIM) := h8s_sim.dtb
|
||||
dtb-$(CONFIG_H8S_EDOSK2674) := edosk2674.dtb
|
||||
|
||||
always := $(dtb-y)
|
||||
clean-files := *.dtb.S *.dtb
|
|
@ -0,0 +1,107 @@
|
|||
/dts-v1/;
|
||||
/ {
|
||||
compatible = "renesas,edosk2674";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
interrupt-parent = <&h8intc>;
|
||||
|
||||
chosen {
|
||||
bootargs = "console=ttySC2,38400";
|
||||
stdout-path = <&sci2>;
|
||||
};
|
||||
aliases {
|
||||
serial0 = &sci0;
|
||||
serial1 = &sci1;
|
||||
serial2 = &sci2;
|
||||
};
|
||||
|
||||
xclk: oscillator {
|
||||
#clock-cells = <0>;
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <33333333>;
|
||||
clock-output-names = "xtal";
|
||||
};
|
||||
pllclk: pllclk {
|
||||
compatible = "renesas,h8s2678-pll-clock";
|
||||
clocks = <&xclk>;
|
||||
#clock-cells = <0>;
|
||||
reg = <0xfee03b 2>, <0xfee045 2>;
|
||||
};
|
||||
core_clk: core_clk {
|
||||
compatible = "renesas,h8300-div-clock";
|
||||
clocks = <&pllclk>;
|
||||
#clock-cells = <0>;
|
||||
reg = <0xfee03b 2>;
|
||||
renesas,width = <3>;
|
||||
};
|
||||
fclk: fclk {
|
||||
compatible = "fixed-factor-clock";
|
||||
clocks = <&core_clk>;
|
||||
#clock-cells = <0>;
|
||||
clock-div = <1>;
|
||||
clock-mult = <1>;
|
||||
};
|
||||
|
||||
memory@400000 {
|
||||
device_type = "memory";
|
||||
reg = <0x400000 0x800000>;
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cpu@0 {
|
||||
compatible = "renesas,h8300";
|
||||
clock-frequency = <33333333>;
|
||||
};
|
||||
};
|
||||
|
||||
h8intc: interrupt-controller@fffe00 {
|
||||
compatible = "renesas,h8s-intc", "renesas,h8300-intc";
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-controller;
|
||||
reg = <0xfffe00 24>;
|
||||
};
|
||||
|
||||
bsc: memory-controller@fffec0 {
|
||||
compatible = "renesas,h8s-bsc", "renesas,h8300-bsc";
|
||||
reg = <0xfffec0 24>;
|
||||
};
|
||||
|
||||
tpu: timer@ffffe0 {
|
||||
compatible = "renesas,tpu";
|
||||
reg = <0xffffe0 16>, <0xfffff0 12>;
|
||||
clocks = <&fclk>;
|
||||
clock-names = "fck";
|
||||
};
|
||||
|
||||
timer8: timer@ffffb0 {
|
||||
compatible = "renesas,8bit-timer";
|
||||
reg = <0xffffb0 10>;
|
||||
interrupts = <72 0>;
|
||||
clocks = <&fclk>;
|
||||
clock-names = "fck";
|
||||
};
|
||||
|
||||
sci0: serial@ffff78 {
|
||||
compatible = "renesas,sci";
|
||||
reg = <0xffff78 8>;
|
||||
interrupts = <88 0>, <89 0>, <90 0>, <91 0>;
|
||||
clocks = <&fclk>;
|
||||
clock-names = "sci_ick";
|
||||
};
|
||||
sci1: serial@ffff80 {
|
||||
compatible = "renesas,sci";
|
||||
reg = <0xffff80 8>;
|
||||
interrupts = <92 0>, <93 0>, <94 0>, <95 0>;
|
||||
clocks = <&fclk>;
|
||||
clock-names = "sci_ick";
|
||||
};
|
||||
sci2: serial@ffff88 {
|
||||
compatible = "renesas,sci";
|
||||
reg = <0xffff88 8>;
|
||||
interrupts = <96 0>, <97 0>, <98 0>, <99 0>;
|
||||
clocks = <&fclk>;
|
||||
clock-names = "sci_ick";
|
||||
};
|
||||
};
|
|
@ -0,0 +1,96 @@
|
|||
/dts-v1/;
|
||||
/ {
|
||||
compatible = "gnu,gdbsim";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
interrupt-parent = <&h8intc>;
|
||||
|
||||
chosen {
|
||||
bootargs = "earlyprintk=h8300-sim";
|
||||
stdout-path = <&sci0>;
|
||||
};
|
||||
aliases {
|
||||
serial0 = &sci0;
|
||||
serial1 = &sci1;
|
||||
};
|
||||
|
||||
xclk: oscillator {
|
||||
#clock-cells = <0>;
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <20000000>;
|
||||
clock-output-names = "xtal";
|
||||
};
|
||||
core_clk: core_clk {
|
||||
compatible = "renesas,h8300-div-clock";
|
||||
clocks = <&xclk>;
|
||||
#clock-cells = <0>;
|
||||
reg = <0xfee01b 2>;
|
||||
renesas,width = <2>;
|
||||
};
|
||||
fclk: fclk {
|
||||
compatible = "fixed-factor-clock";
|
||||
clocks = <&core_clk>;
|
||||
#clock-cells = <0>;
|
||||
clock-div = <1>;
|
||||
clock-mult = <1>;
|
||||
};
|
||||
|
||||
memory@400000 {
|
||||
device_type = "memory";
|
||||
reg = <0x400000 0x400000>;
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cpu@0 {
|
||||
compatible = "renesas,h8300";
|
||||
clock-frequency = <20000000>;
|
||||
};
|
||||
};
|
||||
|
||||
h8intc: interrupt-controller@fee012 {
|
||||
compatible = "renesas,h8300h-intc", "renesas,h8300-intc";
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-controller;
|
||||
reg = <0xfee012 7>;
|
||||
};
|
||||
|
||||
bsc: memory-controller@fee01e {
|
||||
compatible = "renesas,h8300h-bsc", "renesas,h8300-bsc";
|
||||
reg = <0xfee01e 8>;
|
||||
};
|
||||
|
||||
timer8: timer@ffff80 {
|
||||
compatible = "renesas,8bit-timer";
|
||||
reg = <0xffff80 10>;
|
||||
interrupts = <36 0>;
|
||||
clocks = <&fclk>;
|
||||
clock-names = "fck";
|
||||
};
|
||||
|
||||
timer16: timer@ffff68 {
|
||||
compatible = "renesas,16bit-timer";
|
||||
reg = <0xffff68 8>, <0xffff60 8>;
|
||||
interrupts = <24 0>;
|
||||
renesas,channel = <0>;
|
||||
clocks = <&fclk>;
|
||||
clock-names = "fck";
|
||||
};
|
||||
|
||||
sci0: serial@ffffb0 {
|
||||
compatible = "renesas,sci";
|
||||
reg = <0xffffb0 8>;
|
||||
interrupts = <52 0>, <53 0>, <54 0>, <55 0>;
|
||||
clocks = <&fclk>;
|
||||
clock-names = "sci_ick";
|
||||
};
|
||||
|
||||
sci1: serial@ffffb8 {
|
||||
compatible = "renesas,sci";
|
||||
reg = <0xffffb8 8>;
|
||||
interrupts = <56 0>, <57 0>, <58 0>, <59 0>;
|
||||
clocks = <&fclk>;
|
||||
clock-names = "sci_ick";
|
||||
};
|
||||
};
|
|
@ -0,0 +1,99 @@
|
|||
/dts-v1/;
|
||||
/ {
|
||||
compatible = "gnu,gdbsim";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
interrupt-parent = <&h8intc>;
|
||||
|
||||
chosen {
|
||||
bootargs = "earlyprintk=h8300-sim";
|
||||
stdout-path = <&sci0>;
|
||||
};
|
||||
aliases {
|
||||
serial0 = &sci0;
|
||||
serial1 = &sci1;
|
||||
};
|
||||
|
||||
xclk: oscillator {
|
||||
#clock-cells = <0>;
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <33333333>;
|
||||
clock-output-names = "xtal";
|
||||
};
|
||||
pllclk: pllclk {
|
||||
compatible = "renesas,h8s2678-pll-clock";
|
||||
clocks = <&xclk>;
|
||||
#clock-cells = <0>;
|
||||
reg = <0xfee03b 2>, <0xfee045 2>;
|
||||
};
|
||||
core_clk: core_clk {
|
||||
compatible = "renesas,h8300-div-clock";
|
||||
clocks = <&pllclk>;
|
||||
#clock-cells = <0>;
|
||||
reg = <0xfee03b 2>;
|
||||
renesas,width = <3>;
|
||||
};
|
||||
fclk: fclk {
|
||||
compatible = "fixed-factor-clock";
|
||||
clocks = <&core_clk>;
|
||||
#clock-cells = <0>;
|
||||
clock-div = <1>;
|
||||
clock-mult = <1>;
|
||||
};
|
||||
|
||||
memory@400000 {
|
||||
device_type = "memory";
|
||||
reg = <0x400000 0x800000>;
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cpu@0 {
|
||||
compatible = "renesas,h8300";
|
||||
clock-frequency = <33333333>;
|
||||
};
|
||||
};
|
||||
|
||||
h8intc: interrupt-controller@fffe00 {
|
||||
compatible = "renesas,h8s-intc", "renesas,h8300-intc";
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-controller;
|
||||
reg = <0xfffe00 24>;
|
||||
};
|
||||
|
||||
bsc: memory-controller@fffec0 {
|
||||
compatible = "renesas,h8s-bsc", "renesas,h8300-bsc";
|
||||
reg = <0xfffec0 24>;
|
||||
};
|
||||
|
||||
tpu: timer@ffffe0 {
|
||||
compatible = "renesas,tpu";
|
||||
reg = <0xffffe0 16>, <0xfffff0 12>;
|
||||
clocks = <&fclk>;
|
||||
clock-names = "fck";
|
||||
};
|
||||
|
||||
timer8: timer@ffffb0 {
|
||||
compatible = "renesas,8bit-timer";
|
||||
reg = <0xffffb0 10>;
|
||||
interrupts = <72 0>;
|
||||
clocks = <&fclk>;
|
||||
clock-names = "fck";
|
||||
};
|
||||
|
||||
sci0: serial@ffff78 {
|
||||
compatible = "renesas,sci";
|
||||
reg = <0xffff78 8>;
|
||||
interrupts = <88 0>, <89 0>, <90 0>, <91 0>;
|
||||
clocks = <&fclk>;
|
||||
clock-names = "sci_ick";
|
||||
};
|
||||
sci1: serial@ffff80 {
|
||||
compatible = "renesas,sci";
|
||||
reg = <0xffff80 8>;
|
||||
interrupts = <92 0>, <93 0>, <94 0>, <95 0>;
|
||||
clocks = <&fclk>;
|
||||
clock-names = "sci_ick";
|
||||
};
|
||||
};
|
|
@ -0,0 +1,49 @@
|
|||
# CONFIG_LOCALVERSION_AUTO is not set
|
||||
# CONFIG_USELIB is not set
|
||||
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
|
||||
# CONFIG_UID16 is not set
|
||||
# CONFIG_SYSFS_SYSCALL is not set
|
||||
# CONFIG_KALLSYMS is not set
|
||||
# CONFIG_BASE_FULL is not set
|
||||
# CONFIG_FUTEX is not set
|
||||
# CONFIG_EPOLL is not set
|
||||
# CONFIG_SIGNALFD is not set
|
||||
# CONFIG_TIMERFD is not set
|
||||
# CONFIG_EVENTFD is not set
|
||||
# CONFIG_AIO is not set
|
||||
# CONFIG_ADVISE_SYSCALLS is not set
|
||||
CONFIG_EMBEDDED=y
|
||||
# CONFIG_VM_EVENT_COUNTERS is not set
|
||||
# CONFIG_COMPAT_BRK is not set
|
||||
CONFIG_SLOB=y
|
||||
# CONFIG_BLOCK is not set
|
||||
CONFIG_H8S_SIM=y
|
||||
CONFIG_H8300_BUILTIN_DTB="h8s_sim"
|
||||
# CONFIG_BINFMT_SCRIPT is not set
|
||||
CONFIG_BINFMT_FLAT=y
|
||||
# CONFIG_COREDUMP is not set
|
||||
# CONFIG_UEVENT_HELPER is not set
|
||||
# CONFIG_STANDALONE is not set
|
||||
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
|
||||
# CONFIG_FW_LOADER is not set
|
||||
# CONFIG_ALLOW_DEV_COREDUMP is not set
|
||||
# CONFIG_INPUT is not set
|
||||
# CONFIG_SERIO is not set
|
||||
# CONFIG_VT is not set
|
||||
# CONFIG_UNIX98_PTYS is not set
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_DEVKMEM is not set
|
||||
CONFIG_SERIAL_SH_SCI=y
|
||||
CONFIG_SERIAL_SH_SCI_CONSOLE=y
|
||||
# CONFIG_HW_RANDOM is not set
|
||||
# CONFIG_HWMON is not set
|
||||
# CONFIG_USB_SUPPORT is not set
|
||||
# CONFIG_FILE_LOCKING is not set
|
||||
# CONFIG_DNOTIFY is not set
|
||||
# CONFIG_INOTIFY_USER is not set
|
||||
# CONFIG_PROC_FS is not set
|
||||
# CONFIG_SYSFS is not set
|
||||
# CONFIG_MISC_FILESYSTEMS is not set
|
||||
CONFIG_DEBUG_INFO=y
|
||||
# CONFIG_ENABLE_WARN_DEPRECATED is not set
|
||||
# CONFIG_ENABLE_MUST_CHECK is not set
|
|
@ -0,0 +1,49 @@
|
|||
# CONFIG_LOCALVERSION_AUTO is not set
|
||||
# CONFIG_USELIB is not set
|
||||
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
|
||||
# CONFIG_UID16 is not set
|
||||
# CONFIG_SYSFS_SYSCALL is not set
|
||||
# CONFIG_KALLSYMS is not set
|
||||
# CONFIG_BASE_FULL is not set
|
||||
# CONFIG_FUTEX is not set
|
||||
# CONFIG_EPOLL is not set
|
||||
# CONFIG_SIGNALFD is not set
|
||||
# CONFIG_TIMERFD is not set
|
||||
# CONFIG_EVENTFD is not set
|
||||
# CONFIG_AIO is not set
|
||||
# CONFIG_ADVISE_SYSCALLS is not set
|
||||
CONFIG_EMBEDDED=y
|
||||
# CONFIG_VM_EVENT_COUNTERS is not set
|
||||
# CONFIG_COMPAT_BRK is not set
|
||||
CONFIG_SLOB=y
|
||||
# CONFIG_BLOCK is not set
|
||||
CONFIG_H8300H_SIM=y
|
||||
CONFIG_H8300_BUILTIN_DTB="h8300h_sim"
|
||||
# CONFIG_BINFMT_SCRIPT is not set
|
||||
CONFIG_BINFMT_FLAT=y
|
||||
# CONFIG_COREDUMP is not set
|
||||
# CONFIG_UEVENT_HELPER is not set
|
||||
# CONFIG_STANDALONE is not set
|
||||
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
|
||||
# CONFIG_FW_LOADER is not set
|
||||
# CONFIG_ALLOW_DEV_COREDUMP is not set
|
||||
# CONFIG_INPUT is not set
|
||||
# CONFIG_SERIO is not set
|
||||
# CONFIG_VT is not set
|
||||
# CONFIG_UNIX98_PTYS is not set
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_DEVKMEM is not set
|
||||
CONFIG_SERIAL_SH_SCI=y
|
||||
CONFIG_SERIAL_SH_SCI_CONSOLE=y
|
||||
# CONFIG_HW_RANDOM is not set
|
||||
# CONFIG_HWMON is not set
|
||||
# CONFIG_USB_SUPPORT is not set
|
||||
# CONFIG_FILE_LOCKING is not set
|
||||
# CONFIG_DNOTIFY is not set
|
||||
# CONFIG_INOTIFY_USER is not set
|
||||
# CONFIG_PROC_FS is not set
|
||||
# CONFIG_SYSFS is not set
|
||||
# CONFIG_MISC_FILESYSTEMS is not set
|
||||
CONFIG_DEBUG_INFO=y
|
||||
# CONFIG_ENABLE_WARN_DEPRECATED is not set
|
||||
# CONFIG_ENABLE_MUST_CHECK is not set
|
|
@ -0,0 +1,49 @@
|
|||
# CONFIG_LOCALVERSION_AUTO is not set
|
||||
# CONFIG_USELIB is not set
|
||||
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
|
||||
# CONFIG_UID16 is not set
|
||||
# CONFIG_SYSFS_SYSCALL is not set
|
||||
# CONFIG_KALLSYMS is not set
|
||||
# CONFIG_BASE_FULL is not set
|
||||
# CONFIG_FUTEX is not set
|
||||
# CONFIG_EPOLL is not set
|
||||
# CONFIG_SIGNALFD is not set
|
||||
# CONFIG_TIMERFD is not set
|
||||
# CONFIG_EVENTFD is not set
|
||||
# CONFIG_AIO is not set
|
||||
# CONFIG_ADVISE_SYSCALLS is not set
|
||||
CONFIG_EMBEDDED=y
|
||||
# CONFIG_VM_EVENT_COUNTERS is not set
|
||||
# CONFIG_COMPAT_BRK is not set
|
||||
CONFIG_SLOB=y
|
||||
# CONFIG_BLOCK is not set
|
||||
CONFIG_H8S_SIM=y
|
||||
CONFIG_H8300_BUILTIN_DTB="h8s_sim"
|
||||
# CONFIG_BINFMT_SCRIPT is not set
|
||||
CONFIG_BINFMT_FLAT=y
|
||||
# CONFIG_COREDUMP is not set
|
||||
# CONFIG_UEVENT_HELPER is not set
|
||||
# CONFIG_STANDALONE is not set
|
||||
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
|
||||
# CONFIG_FW_LOADER is not set
|
||||
# CONFIG_ALLOW_DEV_COREDUMP is not set
|
||||
# CONFIG_INPUT is not set
|
||||
# CONFIG_SERIO is not set
|
||||
# CONFIG_VT is not set
|
||||
# CONFIG_UNIX98_PTYS is not set
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_DEVKMEM is not set
|
||||
CONFIG_SERIAL_SH_SCI=y
|
||||
CONFIG_SERIAL_SH_SCI_CONSOLE=y
|
||||
# CONFIG_HW_RANDOM is not set
|
||||
# CONFIG_HWMON is not set
|
||||
# CONFIG_USB_SUPPORT is not set
|
||||
# CONFIG_FILE_LOCKING is not set
|
||||
# CONFIG_DNOTIFY is not set
|
||||
# CONFIG_INOTIFY_USER is not set
|
||||
# CONFIG_PROC_FS is not set
|
||||
# CONFIG_SYSFS is not set
|
||||
# CONFIG_MISC_FILESYSTEMS is not set
|
||||
CONFIG_DEBUG_INFO=y
|
||||
# CONFIG_ENABLE_WARN_DEPRECATED is not set
|
||||
# CONFIG_ENABLE_MUST_CHECK is not set
|
|
@ -0,0 +1,75 @@
|
|||
generic-y += asm-offsets.h
|
||||
generic-y += auxvec.h
|
||||
generic-y += barrier.h
|
||||
generic-y += bugs.h
|
||||
generic-y += cacheflush.h
|
||||
generic-y += checksum.h
|
||||
generic-y += clkdev.h
|
||||
generic-y += cputime.h
|
||||
generic-y += current.h
|
||||
generic-y += delay.h
|
||||
generic-y += device.h
|
||||
generic-y += div64.h
|
||||
generic-y += dma.h
|
||||
generic-y += emergency-restart.h
|
||||
generic-y += errno.h
|
||||
generic-y += exec.h
|
||||
generic-y += fb.h
|
||||
generic-y += fcntl.h
|
||||
generic-y += ftrace.h
|
||||
generic-y += futex.h
|
||||
generic-y += hardirq.h
|
||||
generic-y += hash.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 += irq_work.h
|
||||
generic-y += kdebug.h
|
||||
generic-y += kmap_types.h
|
||||
generic-y += kvm_para.h
|
||||
generic-y += linkage.h
|
||||
generic-y += local.h
|
||||
generic-y += local64.h
|
||||
generic-y += mcs_spinlock.h
|
||||
generic-y += mman.h
|
||||
generic-y += mmu.h
|
||||
generic-y += mmu_context.h
|
||||
generic-y += module.h
|
||||
generic-y += msgbuf.h
|
||||
generic-y += param.h
|
||||
generic-y += parport.h
|
||||
generic-y += percpu.h
|
||||
generic-y += pgalloc.h
|
||||
generic-y += poll.h
|
||||
generic-y += posix_types.h
|
||||
generic-y += preempt.h
|
||||
generic-y += resource.h
|
||||
generic-y += scatterlist.h
|
||||
generic-y += sections.h
|
||||
generic-y += sembuf.h
|
||||
generic-y += serial.h
|
||||
generic-y += setup.h
|
||||
generic-y += shmbuf.h
|
||||
generic-y += shmparam.h
|
||||
generic-y += siginfo.h
|
||||
generic-y += sizes.h
|
||||
generic-y += socket.h
|
||||
generic-y += sockios.h
|
||||
generic-y += spinlock.h
|
||||
generic-y += stat.h
|
||||
generic-y += statfs.h
|
||||
generic-y += swab.h
|
||||
generic-y += termbits.h
|
||||
generic-y += termios.h
|
||||
generic-y += timex.h
|
||||
generic-y += tlbflush.h
|
||||
generic-y += trace_clock.h
|
||||
generic-y += topology.h
|
||||
generic-y += types.h
|
||||
generic-y += uaccess.h
|
||||
generic-y += ucontext.h
|
||||
generic-y += unaligned.h
|
||||
generic-y += vga.h
|
||||
generic-y += xor.h
|
|
@ -0,0 +1,159 @@
|
|||
#ifndef __ARCH_H8300_ATOMIC__
|
||||
#define __ARCH_H8300_ATOMIC__
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <asm/cmpxchg.h>
|
||||
|
||||
/*
|
||||
* Atomic operations that C can't guarantee us. Useful for
|
||||
* resource counting etc..
|
||||
*/
|
||||
|
||||
#define ATOMIC_INIT(i) { (i) }
|
||||
|
||||
#define atomic_read(v) ACCESS_ONCE((v)->counter)
|
||||
#define atomic_set(v, i) (((v)->counter) = i)
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
static inline int atomic_add_return(int i, atomic_t *v)
|
||||
{
|
||||
h8300flags flags;
|
||||
int ret;
|
||||
|
||||
flags = arch_local_irq_save();
|
||||
ret = v->counter += i;
|
||||
arch_local_irq_restore(flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define atomic_add(i, v) atomic_add_return(i, v)
|
||||
#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
|
||||
|
||||
static inline int atomic_sub_return(int i, atomic_t *v)
|
||||
{
|
||||
h8300flags flags;
|
||||
int ret;
|
||||
|
||||
flags = arch_local_irq_save();
|
||||
ret = v->counter -= i;
|
||||
arch_local_irq_restore(flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define atomic_sub(i, v) atomic_sub_return(i, v)
|
||||
#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0)
|
||||
|
||||
static inline int atomic_inc_return(atomic_t *v)
|
||||
{
|
||||
h8300flags flags;
|
||||
int ret;
|
||||
|
||||
flags = arch_local_irq_save();
|
||||
v->counter++;
|
||||
ret = v->counter;
|
||||
arch_local_irq_restore(flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define atomic_inc(v) atomic_inc_return(v)
|
||||
|
||||
/*
|
||||
* atomic_inc_and_test - increment and test
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically increments @v by 1
|
||||
* and returns true if the result is zero, or false for all
|
||||
* other cases.
|
||||
*/
|
||||
#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
|
||||
|
||||
static inline int atomic_dec_return(atomic_t *v)
|
||||
{
|
||||
h8300flags flags;
|
||||
int ret;
|
||||
|
||||
flags = arch_local_irq_save();
|
||||
--v->counter;
|
||||
ret = v->counter;
|
||||
arch_local_irq_restore(flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define atomic_dec(v) atomic_dec_return(v)
|
||||
|
||||
static inline int atomic_dec_and_test(atomic_t *v)
|
||||
{
|
||||
h8300flags flags;
|
||||
int ret;
|
||||
|
||||
flags = arch_local_irq_save();
|
||||
--v->counter;
|
||||
ret = v->counter;
|
||||
arch_local_irq_restore(flags);
|
||||
return ret == 0;
|
||||
}
|
||||
|
||||
static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
|
||||
{
|
||||
int ret;
|
||||
h8300flags flags;
|
||||
|
||||
flags = arch_local_irq_save();
|
||||
ret = v->counter;
|
||||
if (likely(ret == old))
|
||||
v->counter = new;
|
||||
arch_local_irq_restore(flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int __atomic_add_unless(atomic_t *v, int a, int u)
|
||||
{
|
||||
int ret;
|
||||
h8300flags flags;
|
||||
|
||||
flags = arch_local_irq_save();
|
||||
ret = v->counter;
|
||||
if (ret != u)
|
||||
v->counter += a;
|
||||
arch_local_irq_restore(flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void atomic_clear_mask(unsigned long mask, unsigned long *v)
|
||||
{
|
||||
unsigned char ccr;
|
||||
unsigned long tmp;
|
||||
|
||||
__asm__ __volatile__("stc ccr,%w3\n\t"
|
||||
"orc #0x80,ccr\n\t"
|
||||
"mov.l %0,%1\n\t"
|
||||
"and.l %2,%1\n\t"
|
||||
"mov.l %1,%0\n\t"
|
||||
"ldc %w3,ccr"
|
||||
: "=m"(*v), "=r"(tmp)
|
||||
: "g"(~(mask)), "r"(ccr));
|
||||
}
|
||||
|
||||
static inline void atomic_set_mask(unsigned long mask, unsigned long *v)
|
||||
{
|
||||
unsigned char ccr;
|
||||
unsigned long tmp;
|
||||
|
||||
__asm__ __volatile__("stc ccr,%w3\n\t"
|
||||
"orc #0x80,ccr\n\t"
|
||||
"mov.l %0,%1\n\t"
|
||||
"or.l %2,%1\n\t"
|
||||
"mov.l %1,%0\n\t"
|
||||
"ldc %w3,ccr"
|
||||
: "=m"(*v), "=r"(tmp)
|
||||
: "g"(~(mask)), "r"(ccr));
|
||||
}
|
||||
|
||||
/* Atomic operations are already serializing */
|
||||
#define smp_mb__before_atomic_dec() barrier()
|
||||
#define smp_mb__after_atomic_dec() barrier()
|
||||
#define smp_mb__before_atomic_inc() barrier()
|
||||
#define smp_mb__after_atomic_inc() barrier()
|
||||
|
||||
#endif /* __ARCH_H8300_ATOMIC __ */
|
|
@ -0,0 +1,185 @@
|
|||
#ifndef _H8300_BITOPS_H
|
||||
#define _H8300_BITOPS_H
|
||||
|
||||
/*
|
||||
* Copyright 1992, Linus Torvalds.
|
||||
* Copyright 2002, Yoshinori Sato
|
||||
*/
|
||||
|
||||
#include <linux/compiler.h>
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#ifndef _LINUX_BITOPS_H
|
||||
#error only <linux/bitops.h> can be included directly
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Function prototypes to keep gcc -Wall happy
|
||||
*/
|
||||
|
||||
/*
|
||||
* ffz = Find First Zero in word. Undefined if no zero exists,
|
||||
* so code should check against ~0UL first..
|
||||
*/
|
||||
static inline unsigned long ffz(unsigned long word)
|
||||
{
|
||||
unsigned long result;
|
||||
|
||||
result = -1;
|
||||
__asm__("1:\n\t"
|
||||
"shlr.l %2\n\t"
|
||||
"adds #1,%0\n\t"
|
||||
"bcs 1b"
|
||||
: "=r"(result)
|
||||
: "0"(result), "r"(word));
|
||||
return result;
|
||||
}
|
||||
|
||||
#define H8300_GEN_BITOP(FNAME, OP) \
|
||||
static inline void FNAME(int nr, volatile unsigned long *addr) \
|
||||
{ \
|
||||
unsigned char *b_addr; \
|
||||
unsigned char bit = nr & 7; \
|
||||
\
|
||||
b_addr = (unsigned char *)addr + ((nr >> 3) ^ 3); \
|
||||
if (__builtin_constant_p(nr)) { \
|
||||
__asm__(OP " %1,%0" : "+WU"(*b_addr) : "i"(nr & 7)); \
|
||||
} else { \
|
||||
__asm__(OP " %s1,%0" : "+WU"(*b_addr) : "r"(bit)); \
|
||||
} \
|
||||
}
|
||||
|
||||
/*
|
||||
* clear_bit() doesn't provide any barrier for the compiler.
|
||||
*/
|
||||
#define smp_mb__before_clear_bit() barrier()
|
||||
#define smp_mb__after_clear_bit() barrier()
|
||||
|
||||
H8300_GEN_BITOP(set_bit, "bset")
|
||||
H8300_GEN_BITOP(clear_bit, "bclr")
|
||||
H8300_GEN_BITOP(change_bit, "bnot")
|
||||
#define __set_bit(nr, addr) set_bit((nr), (addr))
|
||||
#define __clear_bit(nr, addr) clear_bit((nr), (addr))
|
||||
#define __change_bit(nr, addr) change_bit((nr), (addr))
|
||||
|
||||
#undef H8300_GEN_BITOP
|
||||
|
||||
static inline int test_bit(int nr, const unsigned long *addr)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned char *b_addr;
|
||||
unsigned char bit = nr & 7;
|
||||
|
||||
b_addr = (unsigned char *)addr + ((nr >> 3) ^ 3);
|
||||
if (__builtin_constant_p(nr)) {
|
||||
__asm__("bld %Z2,%1\n\t"
|
||||
"rotxl %0\n\t"
|
||||
: "=r"(ret)
|
||||
: "WU"(*b_addr), "i"(nr & 7), "0"(ret) : "cc");
|
||||
} else {
|
||||
__asm__("btst %w2,%1\n\t"
|
||||
"beq 1f\n\t"
|
||||
"inc.l #1,%0\n"
|
||||
"1:"
|
||||
: "=r"(ret)
|
||||
: "WU"(*b_addr), "r"(bit), "0"(ret) : "cc");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define __test_bit(nr, addr) test_bit(nr, addr)
|
||||
|
||||
#define H8300_GEN_TEST_BITOP(FNNAME, OP) \
|
||||
static inline int FNNAME(int nr, void *addr) \
|
||||
{ \
|
||||
int retval = 0; \
|
||||
char ccrsave; \
|
||||
unsigned char *b_addr; \
|
||||
unsigned char bit = nr & 7; \
|
||||
\
|
||||
b_addr = (unsigned char *)addr + ((nr >> 3) ^ 3); \
|
||||
if (__builtin_constant_p(nr)) { \
|
||||
__asm__("stc ccr,%s2\n\t" \
|
||||
"orc #0x80,ccr\n\t" \
|
||||
"bld %4,%1\n\t" \
|
||||
OP " %4,%1\n\t" \
|
||||
"rotxl.l %0\n\t" \
|
||||
"ldc %s2,ccr" \
|
||||
: "=r"(retval), "+WU" (*b_addr), "=&r"(ccrsave) \
|
||||
: "0"(retval), "i"(nr & 7) : "cc"); \
|
||||
} else { \
|
||||
__asm__("stc ccr,%t3\n\t" \
|
||||
"orc #0x80,ccr\n\t" \
|
||||
"btst %s3,%1\n\t" \
|
||||
OP " %s3,%1\n\t" \
|
||||
"beq 1f\n\t" \
|
||||
"inc.l #1,%0\n\t" \
|
||||
"1:\n" \
|
||||
"ldc %t3,ccr" \
|
||||
: "=r"(retval), "+WU" (*b_addr) \
|
||||
: "0" (retval), "r"(bit) : "cc"); \
|
||||
} \
|
||||
return retval; \
|
||||
} \
|
||||
\
|
||||
static inline int __ ## FNNAME(int nr, void *addr) \
|
||||
{ \
|
||||
int retval = 0; \
|
||||
unsigned char *b_addr; \
|
||||
unsigned char bit = nr & 7; \
|
||||
\
|
||||
b_addr = (unsigned char *)addr + ((nr >> 3) ^ 3); \
|
||||
if (__builtin_constant_p(nr)) { \
|
||||
__asm__("bld %3,%1\n\t" \
|
||||
OP " %3,%1\n\t" \
|
||||
"rotxl.l %0\n\t" \
|
||||
: "=r"(retval), "+WU"(*b_addr) \
|
||||
: "0" (retval), "i"(nr & 7)); \
|
||||
} else { \
|
||||
__asm__("btst %s3,%1\n\t" \
|
||||
OP " %s3,%1\n\t" \
|
||||
"beq 1f\n\t" \
|
||||
"inc.l #1,%0\n\t" \
|
||||
"1:" \
|
||||
: "=r"(retval), "+WU"(*b_addr) \
|
||||
: "0" (retval), "r"(bit)); \
|
||||
} \
|
||||
return retval; \
|
||||
}
|
||||
|
||||
H8300_GEN_TEST_BITOP(test_and_set_bit, "bset")
|
||||
H8300_GEN_TEST_BITOP(test_and_clear_bit, "bclr")
|
||||
H8300_GEN_TEST_BITOP(test_and_change_bit, "bnot")
|
||||
#undef H8300_GEN_TEST_BITOP
|
||||
|
||||
#include <asm-generic/bitops/ffs.h>
|
||||
|
||||
static inline unsigned long __ffs(unsigned long word)
|
||||
{
|
||||
unsigned long result;
|
||||
|
||||
result = -1;
|
||||
__asm__("1:\n\t"
|
||||
"shlr.l %2\n\t"
|
||||
"adds #1,%0\n\t"
|
||||
"bcc 1b"
|
||||
: "=r" (result)
|
||||
: "0"(result), "r"(word));
|
||||
return result;
|
||||
}
|
||||
|
||||
#include <asm-generic/bitops/find.h>
|
||||
#include <asm-generic/bitops/sched.h>
|
||||
#include <asm-generic/bitops/hweight.h>
|
||||
#include <asm-generic/bitops/lock.h>
|
||||
#include <asm-generic/bitops/le.h>
|
||||
#include <asm-generic/bitops/ext2-atomic.h>
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#include <asm-generic/bitops/fls.h>
|
||||
#include <asm-generic/bitops/__fls.h>
|
||||
#include <asm-generic/bitops/fls64.h>
|
||||
|
||||
#endif /* _H8300_BITOPS_H */
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef __ASM_H8300_BITS_PER_LONG
|
||||
#define __ASM_H8300_BITS_PER_LONG
|
||||
|
||||
#include <asm-generic/bitsperlong.h>
|
||||
|
||||
#if !defined(__ASSEMBLY__)
|
||||
/* h8300-unknown-linux required long */
|
||||
#define __kernel_size_t __kernel_size_t
|
||||
typedef unsigned long __kernel_size_t;
|
||||
typedef long __kernel_ssize_t;
|
||||
typedef long __kernel_ptrdiff_t;
|
||||
#endif
|
||||
|
||||
#endif /* __ASM_H8300_BITS_PER_LONG */
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef _H8300_BUG_H
|
||||
#define _H8300_BUG_H
|
||||
|
||||
/* always true */
|
||||
#define is_valid_bugaddr(addr) (1)
|
||||
|
||||
#include <asm-generic/bug.h>
|
||||
|
||||
struct pt_regs;
|
||||
extern void die(const char *str, struct pt_regs *fp, unsigned long err);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef __H8300_BYTEORDER_H__
|
||||
#define __H8300_BYTEORDER_H__
|
||||
|
||||
#define __BIG_ENDIAN __ORDER_BIG_ENDIAN__
|
||||
#include <linux/byteorder/big_endian.h>
|
||||
|
||||
#endif
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef __ARCH_H8300_CACHE_H
|
||||
#define __ARCH_H8300_CACHE_H
|
||||
|
||||
/* bytes per L1 cache line */
|
||||
#define L1_CACHE_SHIFT 2
|
||||
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
|
||||
|
||||
#define __cacheline_aligned
|
||||
#define ____cacheline_aligned
|
||||
|
||||
#endif
|
|
@ -0,0 +1,65 @@
|
|||
#ifndef __ARCH_H8300_CMPXCHG__
|
||||
#define __ARCH_H8300_CMPXCHG__
|
||||
|
||||
#include <linux/irqflags.h>
|
||||
|
||||
#define xchg(ptr, x) \
|
||||
((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), \
|
||||
sizeof(*(ptr))))
|
||||
|
||||
struct __xchg_dummy { unsigned long a[100]; };
|
||||
#define __xg(x) ((volatile struct __xchg_dummy *)(x))
|
||||
|
||||
static inline unsigned long __xchg(unsigned long x,
|
||||
volatile void *ptr, int size)
|
||||
{
|
||||
unsigned long tmp, flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
__asm__ __volatile__
|
||||
("mov.b %2,%0\n\t"
|
||||
"mov.b %1,%2"
|
||||
: "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)));
|
||||
break;
|
||||
case 2:
|
||||
__asm__ __volatile__
|
||||
("mov.w %2,%0\n\t"
|
||||
"mov.w %1,%2"
|
||||
: "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)));
|
||||
break;
|
||||
case 4:
|
||||
__asm__ __volatile__
|
||||
("mov.l %2,%0\n\t"
|
||||
"mov.l %1,%2"
|
||||
: "=&r" (tmp) : "r" (x), "m" (*__xg(ptr)));
|
||||
break;
|
||||
default:
|
||||
tmp = 0;
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
#include <asm-generic/cmpxchg-local.h>
|
||||
|
||||
/*
|
||||
* cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
|
||||
* them available.
|
||||
*/
|
||||
#define cmpxchg_local(ptr, o, n) \
|
||||
((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), \
|
||||
(unsigned long)(o), \
|
||||
(unsigned long)(n), \
|
||||
sizeof(*(ptr))))
|
||||
#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
#include <asm-generic/cmpxchg.h>
|
||||
#endif
|
||||
|
||||
#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
|
||||
|
||||
#endif /* __ARCH_H8300_CMPXCHG__ */
|
|
@ -0,0 +1,57 @@
|
|||
#ifndef _H8300_DMA_MAPPING_H
|
||||
#define _H8300_DMA_MAPPING_H
|
||||
|
||||
#include <asm-generic/dma-coherent.h>
|
||||
|
||||
extern struct dma_map_ops h8300_dma_map_ops;
|
||||
|
||||
static inline struct dma_map_ops *get_dma_ops(struct device *dev)
|
||||
{
|
||||
return &h8300_dma_map_ops;
|
||||
}
|
||||
|
||||
#include <asm-generic/dma-mapping-common.h>
|
||||
|
||||
static inline int dma_supported(struct device *dev, u64 mask)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int dma_set_mask(struct device *dev, u64 mask)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#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)
|
||||
|
||||
#define dma_alloc_coherent(d, s, h, f) dma_alloc_attrs(d, s, h, f, NULL)
|
||||
|
||||
static inline void *dma_alloc_attrs(struct device *dev, size_t size,
|
||||
dma_addr_t *dma_handle, gfp_t flag,
|
||||
struct dma_attrs *attrs)
|
||||
{
|
||||
struct dma_map_ops *ops = get_dma_ops(dev);
|
||||
void *memory;
|
||||
|
||||
memory = ops->alloc(dev, size, dma_handle, flag, attrs);
|
||||
return memory;
|
||||
}
|
||||
|
||||
#define dma_free_coherent(d, s, c, h) dma_free_attrs(d, s, c, h, NULL)
|
||||
|
||||
static inline void dma_free_attrs(struct device *dev, size_t size,
|
||||
void *cpu_addr, dma_addr_t dma_handle,
|
||||
struct dma_attrs *attrs)
|
||||
{
|
||||
struct dma_map_ops *ops = get_dma_ops(dev);
|
||||
|
||||
ops->free(dev, size, cpu_addr, dma_handle, attrs);
|
||||
}
|
||||
|
||||
static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,101 @@
|
|||
#ifndef __ASM_H8300_ELF_H
|
||||
#define __ASM_H8300_ELF_H
|
||||
|
||||
/*
|
||||
* ELF register definitions..
|
||||
*/
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/user.h>
|
||||
|
||||
typedef unsigned long elf_greg_t;
|
||||
|
||||
#define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t))
|
||||
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
|
||||
typedef unsigned long elf_fpregset_t;
|
||||
|
||||
/*
|
||||
* This is used to ensure we don't load something for the wrong architecture.
|
||||
*/
|
||||
#define elf_check_arch(x) ((x)->e_machine == EM_H8_300)
|
||||
|
||||
/*
|
||||
* These are used to set parameters in the core dumps.
|
||||
*/
|
||||
#define ELF_CLASS ELFCLASS32
|
||||
#define ELF_DATA ELFDATA2MSB
|
||||
#define ELF_ARCH EM_H8_300
|
||||
#if defined(CONFIG_CPU_H8300H)
|
||||
#define ELF_CORE_EFLAGS 0x810000
|
||||
#endif
|
||||
#if defined(CONFIG_CPU_H8S)
|
||||
#define ELF_CORE_EFLAGS 0x820000
|
||||
#endif
|
||||
|
||||
#define ELF_PLAT_INIT(_r) do { (_r)->er1 = 0; } while (0)
|
||||
|
||||
#define ELF_EXEC_PAGESIZE 4096
|
||||
|
||||
/* 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 0xD0000000UL
|
||||
|
||||
/* This yields a mask that user programs can use to figure out what
|
||||
instruction set this cpu supports. */
|
||||
|
||||
#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. */
|
||||
|
||||
#define ELF_PLATFORM (NULL)
|
||||
|
||||
#define R_H8_NONE 0
|
||||
#define R_H8_DIR32 1
|
||||
#define R_H8_DIR32_28 2
|
||||
#define R_H8_DIR32_24 3
|
||||
#define R_H8_DIR32_16 4
|
||||
#define R_H8_DIR32U 6
|
||||
#define R_H8_DIR32U_28 7
|
||||
#define R_H8_DIR32U_24 8
|
||||
#define R_H8_DIR32U_20 9
|
||||
#define R_H8_DIR32U_16 10
|
||||
#define R_H8_DIR24 11
|
||||
#define R_H8_DIR24_20 12
|
||||
#define R_H8_DIR24_16 13
|
||||
#define R_H8_DIR24U 14
|
||||
#define R_H8_DIR24U_20 15
|
||||
#define R_H8_DIR24U_16 16
|
||||
#define R_H8_DIR16 17
|
||||
#define R_H8_DIR16U 18
|
||||
#define R_H8_DIR16S_32 19
|
||||
#define R_H8_DIR16S_28 20
|
||||
#define R_H8_DIR16S_24 21
|
||||
#define R_H8_DIR16S_20 22
|
||||
#define R_H8_DIR16S 23
|
||||
#define R_H8_DIR8 24
|
||||
#define R_H8_DIR8U 25
|
||||
#define R_H8_DIR8Z_32 26
|
||||
#define R_H8_DIR8Z_28 27
|
||||
#define R_H8_DIR8Z_24 28
|
||||
#define R_H8_DIR8Z_20 29
|
||||
#define R_H8_DIR8Z_16 30
|
||||
#define R_H8_PCREL16 31
|
||||
#define R_H8_PCREL8 32
|
||||
#define R_H8_BPOS 33
|
||||
#define R_H8_PCREL32 34
|
||||
#define R_H8_GOT32O 35
|
||||
#define R_H8_GOT16O 36
|
||||
#define R_H8_DIR16A8 59
|
||||
#define R_H8_DIR16R8 60
|
||||
#define R_H8_DIR24A8 61
|
||||
#define R_H8_DIR24R8 62
|
||||
#define R_H8_DIR32A16 63
|
||||
#define R_H8_ABS32 65
|
||||
#define R_H8_ABS32A16 127
|
||||
|
||||
#endif
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* arch/h8300/asm/include/flat.h -- uClinux flat-format executables
|
||||
*/
|
||||
|
||||
#ifndef __H8300_FLAT_H__
|
||||
#define __H8300_FLAT_H__
|
||||
|
||||
#define flat_argvp_envp_on_stack() 1
|
||||
#define flat_old_ram_flag(flags) 1
|
||||
#define flat_reloc_valid(reloc, size) ((reloc) <= (size))
|
||||
#define flat_set_persistent(relval, p) 0
|
||||
|
||||
/*
|
||||
* on the H8 a couple of the relocations have an instruction in the
|
||||
* top byte. As there can only be 24bits of address space, we just
|
||||
* always preserve that 8bits at the top, when it isn't an instruction
|
||||
* is is 0 (davidm@snapgear.com)
|
||||
*/
|
||||
|
||||
#define flat_get_relocate_addr(rel) (rel & ~0x00000001)
|
||||
#define flat_get_addr_from_rp(rp, relval, flags, persistent) \
|
||||
({(void)persistent; \
|
||||
get_unaligned(rp) & (((flags) & FLAT_FLAG_GOTPIC) ? \
|
||||
0xffffffff : 0x00ffffff); })
|
||||
#define flat_put_addr_at_rp(rp, addr, rel) \
|
||||
put_unaligned(((*(char *)(rp)) << 24) | ((addr) & 0x00ffffff), (rp))
|
||||
|
||||
#endif /* __H8300_FLAT_H__ */
|
|
@ -0,0 +1,57 @@
|
|||
#ifndef _H8300_IO_H
|
||||
#define _H8300_IO_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <asm-generic/io.h>
|
||||
|
||||
/* H8/300 internal I/O functions */
|
||||
static inline unsigned char ctrl_inb(unsigned long addr)
|
||||
{
|
||||
return *(volatile unsigned char *)addr;
|
||||
}
|
||||
|
||||
static inline unsigned short ctrl_inw(unsigned long addr)
|
||||
{
|
||||
return *(volatile unsigned short *)addr;
|
||||
}
|
||||
|
||||
static inline unsigned long ctrl_inl(unsigned long addr)
|
||||
{
|
||||
return *(volatile unsigned long *)addr;
|
||||
}
|
||||
|
||||
static inline void ctrl_outb(unsigned char b, unsigned long addr)
|
||||
{
|
||||
*(volatile unsigned char *)addr = b;
|
||||
}
|
||||
|
||||
static inline void ctrl_outw(unsigned short b, unsigned long addr)
|
||||
{
|
||||
*(volatile unsigned short *)addr = b;
|
||||
}
|
||||
|
||||
static inline void ctrl_outl(unsigned long b, unsigned long addr)
|
||||
{
|
||||
*(volatile unsigned long *)addr = b;
|
||||
}
|
||||
|
||||
static inline void ctrl_bclr(int b, unsigned long addr)
|
||||
{
|
||||
if (__builtin_constant_p(b))
|
||||
__asm__("bclr %1,%0" : : "WU"(addr), "i"(b));
|
||||
else
|
||||
__asm__("bclr %w1,%0" : : "WU"(addr), "r"(b));
|
||||
}
|
||||
|
||||
static inline void ctrl_bset(int b, unsigned long addr)
|
||||
{
|
||||
if (__builtin_constant_p(b))
|
||||
__asm__("bset %1,%0" : : "WU"(addr), "i"(b));
|
||||
else
|
||||
__asm__("bset %w1,%0" : : "WU"(addr), "r"(b));
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _H8300_IO_H */
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef _H8300_IRQ_H_
|
||||
#define _H8300_IRQ_H_
|
||||
|
||||
#include <linux/irqchip.h>
|
||||
|
||||
#if defined(CONFIG_CPU_H8300H)
|
||||
#define NR_IRQS 64
|
||||
#define IRQ_CHIP h8300h_irq_chip
|
||||
#define EXT_IRQ0 12
|
||||
#define EXT_IRQS 6
|
||||
#elif defined(CONFIG_CPU_H8S)
|
||||
#define NR_IRQS 128
|
||||
#define IRQ_CHIP h8s_irq_chip
|
||||
#define EXT_IRQ0 16
|
||||
#define EXT_IRQS 16
|
||||
#endif
|
||||
|
||||
static inline int irq_canonicalize(int irq)
|
||||
{
|
||||
return irq;
|
||||
}
|
||||
|
||||
void h8300_init_ipr(void);
|
||||
extern struct irq_chip h8300h_irq_chip;
|
||||
extern struct irq_chip h8s_irq_chip;
|
||||
#endif /* _H8300_IRQ_H_ */
|
|
@ -0,0 +1,96 @@
|
|||
#ifndef _H8300_IRQFLAGS_H
|
||||
#define _H8300_IRQFLAGS_H
|
||||
|
||||
#ifdef CONFIG_CPU_H8300H
|
||||
typedef unsigned char h8300flags;
|
||||
|
||||
static inline h8300flags arch_local_save_flags(void)
|
||||
{
|
||||
h8300flags flags;
|
||||
|
||||
__asm__ volatile ("stc ccr,%w0" : "=r" (flags));
|
||||
return flags;
|
||||
}
|
||||
|
||||
static inline void arch_local_irq_disable(void)
|
||||
{
|
||||
__asm__ volatile ("orc #0xc0,ccr");
|
||||
}
|
||||
|
||||
static inline void arch_local_irq_enable(void)
|
||||
{
|
||||
__asm__ volatile ("andc #0x3f,ccr");
|
||||
}
|
||||
|
||||
static inline h8300flags arch_local_irq_save(void)
|
||||
{
|
||||
h8300flags flags;
|
||||
|
||||
__asm__ volatile ("stc ccr,%w0\n\t"
|
||||
"orc #0xc0,ccr" : "=r" (flags));
|
||||
return flags;
|
||||
}
|
||||
|
||||
static inline void arch_local_irq_restore(h8300flags flags)
|
||||
{
|
||||
__asm__ volatile ("ldc %w0,ccr" : : "r" (flags) : "cc");
|
||||
}
|
||||
|
||||
static inline int arch_irqs_disabled_flags(unsigned long flags)
|
||||
{
|
||||
return (flags & 0xc0) == 0xc0;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_CPU_H8S
|
||||
typedef unsigned short h8300flags;
|
||||
|
||||
static inline h8300flags arch_local_save_flags(void)
|
||||
{
|
||||
h8300flags flags;
|
||||
|
||||
__asm__ volatile ("stc ccr,%w0\n\tstc exr,%x0" : "=r" (flags));
|
||||
return flags;
|
||||
}
|
||||
|
||||
static inline void arch_local_irq_disable(void)
|
||||
{
|
||||
__asm__ volatile ("orc #0x80,ccr\n\t");
|
||||
}
|
||||
|
||||
static inline void arch_local_irq_enable(void)
|
||||
{
|
||||
__asm__ volatile ("andc #0x7f,ccr\n\t"
|
||||
"andc #0xf0,exr\n\t");
|
||||
}
|
||||
|
||||
static inline h8300flags arch_local_irq_save(void)
|
||||
{
|
||||
h8300flags flags;
|
||||
|
||||
__asm__ volatile ("stc ccr,%w0\n\t"
|
||||
"stc exr,%x0\n\t"
|
||||
"orc #0x80,ccr\n\t"
|
||||
: "=r" (flags));
|
||||
return flags;
|
||||
}
|
||||
|
||||
static inline void arch_local_irq_restore(h8300flags flags)
|
||||
{
|
||||
__asm__ volatile ("ldc %w0,ccr\n\t"
|
||||
"ldc %x0,exr"
|
||||
: : "r" (flags) : "cc");
|
||||
}
|
||||
|
||||
static inline int arch_irqs_disabled_flags(h8300flags flags)
|
||||
{
|
||||
return (flags & 0x0080) == 0x0080;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static inline int arch_irqs_disabled(void)
|
||||
{
|
||||
return arch_irqs_disabled_flags(arch_local_save_flags());
|
||||
}
|
||||
|
||||
#endif /* _H8300_IRQFLAGS_H */
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* Machine dependent access functions for RTC registers.
|
||||
*/
|
||||
#ifndef _H8300_MC146818RTC_H
|
||||
#define _H8300_MC146818RTC_H
|
||||
|
||||
/* empty include file to satisfy the include in genrtc.c/ide-geometry.c */
|
||||
|
||||
#endif /* _H8300_MC146818RTC_H */
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* 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>
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef _H8300_PAGE_H
|
||||
#define _H8300_PAGE_H
|
||||
|
||||
#include <asm-generic/page.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define MAP_NR(addr) (((uintptr_t)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)
|
||||
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
|
||||
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
extern unsigned long rom_length;
|
||||
extern unsigned long memory_start;
|
||||
extern unsigned long memory_end;
|
||||
extern unsigned long _ramend;
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
#define PAGE_OFFSET_RAW 0x00000000
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef _ASM_H8300_PCI_H
|
||||
#define _ASM_H8300_PCI_H
|
||||
|
||||
/*
|
||||
* asm-h8300/pci.h - H8/300 specific PCI declarations.
|
||||
*
|
||||
* Yoshinori Sato <ysato@users.sourceforge.jp>
|
||||
*/
|
||||
|
||||
#define pcibios_assign_all_busses() 0
|
||||
|
||||
static inline void pcibios_penalize_isa_irq(int irq, int active)
|
||||
{
|
||||
/* We don't do dynamic PCI IRQ allocation */
|
||||
}
|
||||
|
||||
#define PCI_DMA_BUS_IS_PHYS (1)
|
||||
|
||||
#endif /* _ASM_H8300_PCI_H */
|
|
@ -0,0 +1,49 @@
|
|||
#ifndef _H8300_PGTABLE_H
|
||||
#define _H8300_PGTABLE_H
|
||||
#include <asm-generic/pgtable-nopud.h>
|
||||
#include <asm-generic/pgtable.h>
|
||||
#define pgtable_cache_init() do { } while (0)
|
||||
extern void paging_init(void);
|
||||
#define PAGE_NONE __pgprot(0) /* these mean nothing to NO_MM */
|
||||
#define PAGE_SHARED __pgprot(0) /* these mean nothing to NO_MM */
|
||||
#define PAGE_COPY __pgprot(0) /* these mean nothing to NO_MM */
|
||||
#define PAGE_READONLY __pgprot(0) /* these mean nothing to NO_MM */
|
||||
#define PAGE_KERNEL __pgprot(0) /* these mean nothing to NO_MM */
|
||||
#define __swp_type(x) (0)
|
||||
#define __swp_offset(x) (0)
|
||||
#define __swp_entry(typ, off) ((swp_entry_t) { ((typ) | ((off) << 7)) })
|
||||
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
|
||||
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
|
||||
#define kern_addr_valid(addr) (1)
|
||||
#define pgprot_writecombine(prot) (prot)
|
||||
#define pgprot_noncached pgprot_writecombine
|
||||
|
||||
static inline int pte_file(pte_t pte) { return 0; }
|
||||
#define swapper_pg_dir ((pgd_t *) 0)
|
||||
/*
|
||||
* ZERO_PAGE is a global shared page that is always zero: used
|
||||
* for zero-mapped memory areas etc..
|
||||
*/
|
||||
#define ZERO_PAGE(vaddr) (virt_to_page(0))
|
||||
|
||||
/*
|
||||
* These would be in other places but having them here reduces the diffs.
|
||||
*/
|
||||
extern unsigned int kobjsize(const void *objp);
|
||||
extern int is_in_rom(unsigned long);
|
||||
|
||||
/*
|
||||
* No page table caches to initialise
|
||||
*/
|
||||
#define pgtable_cache_init() do { } while (0)
|
||||
|
||||
/*
|
||||
* All 32bit addresses are effectively valid for vmalloc...
|
||||
* Sort of meaningless for non-VM targets.
|
||||
*/
|
||||
#define VMALLOC_START 0
|
||||
#define VMALLOC_END 0xffffffff
|
||||
|
||||
#define arch_enter_lazy_cpu_mode() do {} while (0)
|
||||
|
||||
#endif /* _H8300_PGTABLE_H */
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* include/asm-h8300/processor.h
|
||||
*
|
||||
* Copyright (C) 2002 Yoshinori Sato
|
||||
*
|
||||
* Based on: linux/asm-m68nommu/processor.h
|
||||
*
|
||||
* Copyright (C) 1995 Hamish Macdonald
|
||||
*/
|
||||
|
||||
#ifndef __ASM_H8300_PROCESSOR_H
|
||||
#define __ASM_H8300_PROCESSOR_H
|
||||
|
||||
/*
|
||||
* Default implementation of macro that returns current
|
||||
* instruction pointer ("program counter").
|
||||
*/
|
||||
#define current_text_addr() ({ __label__ _l; _l: &&_l; })
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/current.h>
|
||||
|
||||
static inline unsigned long rdusp(void)
|
||||
{
|
||||
extern unsigned int _sw_usp;
|
||||
|
||||
return _sw_usp;
|
||||
}
|
||||
|
||||
static inline void wrusp(unsigned long usp)
|
||||
{
|
||||
extern unsigned int _sw_usp;
|
||||
|
||||
_sw_usp = usp;
|
||||
}
|
||||
|
||||
/*
|
||||
* User space process size: 3.75GB. This is hardcoded into a few places,
|
||||
* so don't change it unless you know what you are doing.
|
||||
*/
|
||||
#define TASK_SIZE (0xFFFFFFFFUL)
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#define STACK_TOP TASK_SIZE
|
||||
#define STACK_TOP_MAX STACK_TOP
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This decides where the kernel will search for a free chunk of vm
|
||||
* space during mmap's. We won't be using it
|
||||
*/
|
||||
#define TASK_UNMAPPED_BASE 0
|
||||
|
||||
struct thread_struct {
|
||||
unsigned long ksp; /* kernel stack pointer */
|
||||
unsigned long usp; /* user stack pointer */
|
||||
unsigned long ccr; /* saved status register */
|
||||
unsigned long esp0; /* points to SR of stack frame */
|
||||
struct {
|
||||
unsigned short *addr;
|
||||
unsigned short inst;
|
||||
} breakinfo;
|
||||
};
|
||||
|
||||
#define INIT_THREAD { \
|
||||
.ksp = sizeof(init_stack) + (unsigned long)init_stack, \
|
||||
.usp = 0, \
|
||||
.ccr = PS_S, \
|
||||
.esp0 = 0, \
|
||||
.breakinfo = { \
|
||||
.addr = (unsigned short *)-1, \
|
||||
.inst = 0 \
|
||||
} \
|
||||
}
|
||||
|
||||
/*
|
||||
* Do necessary setup to start up a newly executed thread.
|
||||
*
|
||||
* pass the data segment into user programs if it exists,
|
||||
* it can't hurt anything as far as I can tell
|
||||
*/
|
||||
#if defined(CONFIG_CPU_H8300H)
|
||||
#define start_thread(_regs, _pc, _usp) \
|
||||
do { \
|
||||
(_regs)->pc = (_pc); \
|
||||
(_regs)->ccr = 0x00; /* clear all flags */ \
|
||||
(_regs)->er5 = current->mm->start_data; /* GOT base */ \
|
||||
(_regs)->sp = ((unsigned long)(_usp)) - sizeof(unsigned long) * 3; \
|
||||
} while (0)
|
||||
#endif
|
||||
#if defined(CONFIG_CPU_H8S)
|
||||
#define start_thread(_regs, _pc, _usp) \
|
||||
do { \
|
||||
(_regs)->pc = (_pc); \
|
||||
(_regs)->ccr = 0x00; /* clear kernel flag */ \
|
||||
(_regs)->exr = 0x78; /* enable all interrupts */ \
|
||||
(_regs)->er5 = current->mm->start_data; /* GOT base */ \
|
||||
/* 14 = space for retaddr(4), vector(4), er0(4) and exr(2) on stack */ \
|
||||
(_regs)->sp = ((unsigned long)(_usp)) - 14; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/* Forward declaration, a strange C thing */
|
||||
struct task_struct;
|
||||
|
||||
/* Free all resources held by a thread. */
|
||||
static inline void release_thread(struct task_struct *dead_task)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Free current thread data structures etc..
|
||||
*/
|
||||
static inline void exit_thread(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Return saved PC of a blocked thread.
|
||||
*/
|
||||
unsigned long thread_saved_pc(struct task_struct *tsk);
|
||||
unsigned long get_wchan(struct task_struct *p);
|
||||
|
||||
#define KSTK_EIP(tsk) \
|
||||
({ \
|
||||
unsigned long eip = 0; \
|
||||
if ((tsk)->thread.esp0 > PAGE_SIZE && \
|
||||
MAP_NR((tsk)->thread.esp0) < max_mapnr) \
|
||||
eip = ((struct pt_regs *) (tsk)->thread.esp0)->pc; \
|
||||
eip; })
|
||||
|
||||
#define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp)
|
||||
|
||||
#define cpu_relax() barrier()
|
||||
#define cpu_relax_lowlatency() cpu_relax()
|
||||
|
||||
#define HARD_RESET_NOW() ({ \
|
||||
local_irq_disable(); \
|
||||
asm("jmp @@0"); \
|
||||
})
|
||||
|
||||
#endif
|
|
@ -0,0 +1,36 @@
|
|||
#ifndef _H8300_PTRACE_H
|
||||
#define _H8300_PTRACE_H
|
||||
|
||||
#include <uapi/asm/ptrace.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifndef PS_S
|
||||
#define PS_S (0x10)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CPU_H8300H)
|
||||
#define H8300_REGS_NO 11
|
||||
#endif
|
||||
#if defined(CONFIG_CPU_H8S)
|
||||
#define H8300_REGS_NO 12
|
||||
#endif
|
||||
|
||||
#define arch_has_single_step() (1)
|
||||
|
||||
#define user_mode(regs) (!((regs)->ccr & PS_S))
|
||||
#define instruction_pointer(regs) ((regs)->pc)
|
||||
#define profile_pc(regs) instruction_pointer(regs)
|
||||
#define user_stack_pointer(regs) ((regs)->sp)
|
||||
#define current_pt_regs() ((struct pt_regs *) \
|
||||
(THREAD_SIZE + (unsigned long)current_thread_info()) - 1)
|
||||
#define signal_pt_regs() ((struct pt_regs *)current->thread.esp0)
|
||||
#define current_user_stack_pointer() rdusp()
|
||||
#define task_pt_regs(task) \
|
||||
((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE) - 1)
|
||||
|
||||
extern long h8300_get_reg(struct task_struct *task, int regno);
|
||||
extern int h8300_put_reg(struct task_struct *task, int regno,
|
||||
unsigned long data);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* _H8300_PTRACE_H */
|
|
@ -0,0 +1,45 @@
|
|||
#ifndef _H8300_SEGMENT_H
|
||||
#define _H8300_SEGMENT_H
|
||||
|
||||
/* define constants */
|
||||
#define USER_DATA (1)
|
||||
#ifndef __USER_DS
|
||||
#define __USER_DS (USER_DATA)
|
||||
#endif
|
||||
#define USER_PROGRAM (2)
|
||||
#define SUPER_DATA (3)
|
||||
#ifndef __KERNEL_DS
|
||||
#define __KERNEL_DS (SUPER_DATA)
|
||||
#endif
|
||||
#define SUPER_PROGRAM (4)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
typedef struct {
|
||||
unsigned long seg;
|
||||
} mm_segment_t;
|
||||
|
||||
#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
|
||||
#define USER_DS MAKE_MM_SEG(__USER_DS)
|
||||
#define KERNEL_DS MAKE_MM_SEG(__KERNEL_DS)
|
||||
|
||||
/*
|
||||
* Get/set the SFC/DFC registers for MOVES instructions
|
||||
*/
|
||||
|
||||
static inline mm_segment_t get_fs(void)
|
||||
{
|
||||
return USER_DS;
|
||||
}
|
||||
|
||||
static inline mm_segment_t get_ds(void)
|
||||
{
|
||||
/* return the supervisor data space code */
|
||||
return KERNEL_DS;
|
||||
}
|
||||
|
||||
#define segment_eq(a, b) ((a).seg == (b).seg)
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _H8300_SEGMENT_H */
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef _H8300_SIGNAL_H
|
||||
#define _H8300_SIGNAL_H
|
||||
|
||||
#include <uapi/asm/signal.h>
|
||||
|
||||
/* Most things should be clean enough to redefine this at will, if care
|
||||
is taken to make libc match. */
|
||||
|
||||
#define _NSIG 64
|
||||
#define _NSIG_BPW 32
|
||||
#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
|
||||
|
||||
typedef unsigned long old_sigset_t; /* at least 32 bits */
|
||||
|
||||
typedef struct {
|
||||
unsigned long sig[_NSIG_WORDS];
|
||||
} sigset_t;
|
||||
|
||||
#define __ARCH_HAS_SA_RESTORER
|
||||
#include <asm/sigcontext.h>
|
||||
|
||||
#endif /* _H8300_SIGNAL_H */
|
|
@ -0,0 +1 @@
|
|||
/* nothing required here yet */
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef _H8300_STRING_H_
|
||||
#define _H8300_STRING_H_
|
||||
|
||||
#ifdef __KERNEL__ /* only set these up for kernel code */
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
#define __HAVE_ARCH_MEMSET
|
||||
extern void *memset(void *s, int c, size_t count);
|
||||
|
||||
#define __HAVE_ARCH_MEMCPY
|
||||
extern void *memcpy(void *d, const void *s, size_t count);
|
||||
|
||||
#endif /* KERNEL */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,51 @@
|
|||
#ifndef _H8300_SWITCH_TO_H
|
||||
#define _H8300_SWITCH_TO_H
|
||||
|
||||
/*
|
||||
* switch_to(n) should switch tasks to task ptr, first checking that
|
||||
* ptr isn't the current task, in which case it does nothing. This
|
||||
* also clears the TS-flag if the task we switched to has used the
|
||||
* math co-processor latest.
|
||||
*/
|
||||
/*
|
||||
* switch_to() saves the extra registers, that are not saved
|
||||
* automatically by SAVE_SWITCH_STACK in resume(), ie. d0-d5 and
|
||||
* a0-a1. Some of these are used by schedule() and its predecessors
|
||||
* and so we might get see unexpected behaviors when a task returns
|
||||
* with unexpected register values.
|
||||
*
|
||||
* syscall stores these registers itself and none of them are used
|
||||
* by syscall after the function in the syscall has been called.
|
||||
*
|
||||
* Beware that resume now expects *next to be in d1 and the offset of
|
||||
* tss to be in a1. This saves a few instructions as we no longer have
|
||||
* to push them onto the stack and read them back right after.
|
||||
*
|
||||
* 02/17/96 - Jes Sorensen (jds@kom.auc.dk)
|
||||
*
|
||||
* Changed 96/09/19 by Andreas Schwab
|
||||
* pass prev in a0, next in a1, offset of tss in d1, and whether
|
||||
* the mm structures are shared in d2 (to avoid atc flushing).
|
||||
*
|
||||
* H8/300 Porting 2002/09/04 Yoshinori Sato
|
||||
*/
|
||||
|
||||
asmlinkage void resume(void);
|
||||
#define switch_to(prev, next, last) \
|
||||
do { \
|
||||
void *_last; \
|
||||
__asm__ __volatile__( \
|
||||
"mov.l %1, er0\n\t" \
|
||||
"mov.l %2, er1\n\t" \
|
||||
"mov.l %3, er2\n\t" \
|
||||
"jsr @_resume\n\t" \
|
||||
"mov.l er2,%0\n\t" \
|
||||
: "=r" (_last) \
|
||||
: "r" (&(prev->thread)), \
|
||||
"r" (&(next->thread)), \
|
||||
"g" (prev) \
|
||||
: "cc", "er0", "er1", "er2", "er3"); \
|
||||
(last) = _last; \
|
||||
} while (0)
|
||||
|
||||
#endif /* _H8300_SWITCH_TO_H */
|
|
@ -0,0 +1,56 @@
|
|||
#ifndef __ASM_H8300_SYSCALLS_32_H
|
||||
#define __ASM_H8300_SYSCALLS_32_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/ptrace.h>
|
||||
|
||||
static inline int
|
||||
syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
|
||||
{
|
||||
return regs->orig_er0;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
while (n > 0) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
*args++ = regs->er1;
|
||||
break;
|
||||
case 1:
|
||||
*args++ = regs->er2;
|
||||
break;
|
||||
case 2:
|
||||
*args++ = regs->er3;
|
||||
break;
|
||||
case 3:
|
||||
*args++ = regs->er4;
|
||||
break;
|
||||
case 4:
|
||||
*args++ = regs->er5;
|
||||
break;
|
||||
case 5:
|
||||
*args++ = regs->er6;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Misc syscall related bits */
|
||||
asmlinkage long do_syscall_trace_enter(struct pt_regs *regs);
|
||||
asmlinkage void do_syscall_trace_leave(struct pt_regs *regs);
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* __ASM_H8300_SYSCALLS_32_H */
|
|
@ -0,0 +1,111 @@
|
|||
/* thread_info.h: h8300 low-level thread information
|
||||
* adapted from the i386 and PPC versions by Yoshinori Sato <ysato@users.sourceforge.jp>
|
||||
*
|
||||
* Copyright (C) 2002 David Howells (dhowells@redhat.com)
|
||||
* - Incorporating suggestions made by Linus Torvalds and Dave Miller
|
||||
*/
|
||||
|
||||
#ifndef _ASM_THREAD_INFO_H
|
||||
#define _ASM_THREAD_INFO_H
|
||||
|
||||
#include <asm/page.h>
|
||||
#include <asm/segment.h>
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/*
|
||||
* low level task data.
|
||||
* If you change this, change the TI_* offsets below to match.
|
||||
*/
|
||||
struct thread_info {
|
||||
struct task_struct *task; /* main task structure */
|
||||
unsigned long flags; /* low level flags */
|
||||
int cpu; /* cpu we're on */
|
||||
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
||||
mm_segment_t addr_limit;
|
||||
struct restart_block restart_block;
|
||||
};
|
||||
|
||||
/*
|
||||
* macros/functions for gaining access to the thread information structure
|
||||
*/
|
||||
#define INIT_THREAD_INFO(tsk) \
|
||||
{ \
|
||||
.task = &tsk, \
|
||||
.flags = 0, \
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define init_thread_info (init_thread_union.thread_info)
|
||||
#define init_stack (init_thread_union.stack)
|
||||
|
||||
|
||||
/*
|
||||
* Size of kernel stack for each process. This must be a power of 2...
|
||||
*/
|
||||
#define THREAD_SIZE_ORDER 1
|
||||
#define THREAD_SIZE 8192 /* 2 pages */
|
||||
|
||||
|
||||
/* how to get the thread information struct from C */
|
||||
static inline struct thread_info *current_thread_info(void)
|
||||
{
|
||||
struct thread_info *ti;
|
||||
|
||||
__asm__("mov.l sp, %0\n\t"
|
||||
"and.w %1, %T0"
|
||||
: "=&r"(ti)
|
||||
: "i" (~(THREAD_SIZE-1) & 0xffff));
|
||||
return ti;
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/*
|
||||
* thread information flag bit numbers
|
||||
*/
|
||||
#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
|
||||
#define TIF_SIGPENDING 1 /* signal pending */
|
||||
#define TIF_NEED_RESCHED 2 /* rescheduling necessary */
|
||||
#define TIF_SINGLESTEP 3 /* singlestepping active */
|
||||
#define TIF_MEMDIE 4 /* is terminating due to OOM killer */
|
||||
#define TIF_RESTORE_SIGMASK 5 /* restore signal mask in do_signal() */
|
||||
#define TIF_NOTIFY_RESUME 6 /* callback before returning to user */
|
||||
#define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */
|
||||
#define TIF_SYSCALL_TRACEPOINT 8 /* for ftrace syscall instrumentation */
|
||||
#define TIF_POLLING_NRFLAG 9 /* true if poll_idle() is polling TIF_NEED_RESCHED */
|
||||
|
||||
/* as above, but as bit values */
|
||||
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
|
||||
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
|
||||
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
|
||||
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
|
||||
#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
|
||||
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
|
||||
#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
|
||||
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
|
||||
|
||||
/* work to do in syscall trace */
|
||||
#define _TIF_WORK_SYSCALL_MASK (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | \
|
||||
_TIF_SYSCALL_AUDIT | _TIF_SYSCALL_TRACEPOINT)
|
||||
|
||||
/* work to do on any return to u-space */
|
||||
#define _TIF_ALLWORK_MASK (_TIF_SYSCALL_TRACE | _TIF_SIGPENDING | \
|
||||
_TIF_NEED_RESCHED | _TIF_SYSCALL_AUDIT | \
|
||||
_TIF_SINGLESTEP | _TIF_NOTIFY_RESUME | \
|
||||
_TIF_SYSCALL_TRACEPOINT)
|
||||
|
||||
/* work to do on interrupt/exception return */
|
||||
#define _TIF_WORK_MASK (_TIF_ALLWORK_MASK & ~(_TIF_SYSCALL_TRACE | \
|
||||
_TIF_SYSCALL_AUDIT | _TIF_SINGLESTEP))
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _ASM_THREAD_INFO_H */
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef __H8300_TLB_H__
|
||||
#define __H8300_TLB_H__
|
||||
|
||||
#define tlb_flush(tlb) do { } while (0)
|
||||
|
||||
#include <asm-generic/tlb.h>
|
||||
|
||||
#endif
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* linux/include/asm-h8300/traps.h
|
||||
*
|
||||
* Copyright (C) 2003 Yoshinori Sato <ysato@users.sourceforge.jp>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file COPYING in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#ifndef _H8300_TRAPS_H
|
||||
#define _H8300_TRAPS_H
|
||||
|
||||
extern void _system_call(void);
|
||||
extern void _interrupt_entry(void);
|
||||
extern void _trace_break(void);
|
||||
extern void _nmi(void);
|
||||
extern void _interrupt_entry(void);
|
||||
|
||||
extern unsigned long *_interrupt_redirect_table;
|
||||
|
||||
#define JMP_OP 0x5a000000
|
||||
#define JSR_OP 0x5e000000
|
||||
#define VECTOR(address) ((JMP_OP)|((unsigned long)address))
|
||||
#define REDIRECT(address) ((JSR_OP)|((unsigned long)address))
|
||||
#define CPU_VECTOR ((unsigned long *)0x000000)
|
||||
#define ADDR_MASK (0xffffff)
|
||||
|
||||
#define TRACE_VEC 5
|
||||
|
||||
#define TRAP0_VEC 8
|
||||
#define TRAP1_VEC 9
|
||||
#define TRAP2_VEC 10
|
||||
#define TRAP3_VEC 11
|
||||
|
||||
extern char _start, _etext;
|
||||
#define check_kernel_text(addr) \
|
||||
((addr >= (unsigned long)(&_start)) && \
|
||||
(addr < (unsigned long)(&_etext)))
|
||||
|
||||
#endif /* _H8300_TRAPS_H */
|
|
@ -0,0 +1,74 @@
|
|||
#ifndef _H8300_USER_H
|
||||
#define _H8300_USER_H
|
||||
|
||||
#include <asm/page.h>
|
||||
|
||||
/* Core file format: The core file is written in such a way that gdb
|
||||
can understand it and provide useful information to the user (under
|
||||
linux we use the 'trad-core' bfd). There are quite a number of
|
||||
obstacles to being able to view the contents of the floating point
|
||||
registers, and until these are solved you will not be able to view the
|
||||
contents of them. Actually, you can read in the core file and look at
|
||||
the contents of the user struct to find out what the floating point
|
||||
registers contain.
|
||||
The actual file contents are as follows:
|
||||
UPAGE: 1 page consisting of a user struct that tells gdb what is present
|
||||
in the file. Directly after this is a copy of the task_struct, which
|
||||
is currently not used by gdb, but it may come in useful at some point.
|
||||
All of the registers are stored as part of the upage. The upage should
|
||||
always be only one page.
|
||||
DATA: The data area is stored. We use current->end_text to
|
||||
current->brk to pick up all of the user variables, plus any memory
|
||||
that may have been malloced. No attempt is made to determine if a page
|
||||
is demand-zero or if a page is totally unused, we just cover the entire
|
||||
range. All of the addresses are rounded in such a way that an integral
|
||||
number of pages is written.
|
||||
STACK: We need the stack information in order to get a meaningful
|
||||
backtrace. We need to write the data from (esp) to
|
||||
current->start_stack, so we round each of these off in order to be able
|
||||
to write an integer number of pages.
|
||||
The minimum core file size is 3 pages, or 12288 bytes.
|
||||
*/
|
||||
|
||||
/* This is the old layout of "struct pt_regs" as of Linux 1.x, and
|
||||
is still the layout used by user (the new pt_regs doesn't have
|
||||
all registers). */
|
||||
struct user_regs_struct {
|
||||
long er1, er2, er3, er4, er5, er6;
|
||||
long er0;
|
||||
long usp;
|
||||
long orig_er0;
|
||||
long ccr;
|
||||
long pc;
|
||||
};
|
||||
|
||||
/* When the kernel dumps core, it starts by dumping the user struct -
|
||||
this will be used by gdb to figure out where the data and stack segments
|
||||
are within the file, and what virtual addresses to use. */
|
||||
struct user {
|
||||
/* We start with the registers, to mimic the way that "memory" is returned
|
||||
from the ptrace(3,...) function. */
|
||||
struct user_regs_struct regs; /* Where the registers are actually stored */
|
||||
/* ptrace does not yet supply these. Someday.... */
|
||||
/* The rest of this junk is to help gdb figure out what goes where */
|
||||
unsigned long int u_tsize; /* Text segment size (pages). */
|
||||
unsigned long int u_dsize; /* Data segment size (pages). */
|
||||
unsigned long int u_ssize; /* Stack segment size (pages). */
|
||||
unsigned long start_code; /* Starting virtual address of text. */
|
||||
unsigned long start_stack; /* Starting virtual address of stack area.
|
||||
This is actually the bottom of the stack,
|
||||
the top of the stack is always found in the
|
||||
esp register. */
|
||||
long int signal; /* Signal that caused the core dump. */
|
||||
int reserved; /* No longer used */
|
||||
unsigned long u_ar0; /* Used by gdb to help find the values for */
|
||||
/* the registers. */
|
||||
unsigned long magic; /* To uniquely identify a core file */
|
||||
char u_comm[32]; /* User command that was responsible */
|
||||
};
|
||||
#define NBPG PAGE_SIZE
|
||||
#define UPAGES 1
|
||||
#define HOST_TEXT_START_ADDR (u.start_code)
|
||||
#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,30 @@
|
|||
# UAPI Header export list
|
||||
include include/uapi/asm-generic/Kbuild.asm
|
||||
|
||||
header-y += auxvec.h
|
||||
header-y += bitsperlong.h
|
||||
header-y += errno.h
|
||||
header-y += fcntl.h
|
||||
header-y += ioctl.h
|
||||
header-y += ioctls.h
|
||||
header-y += ipcbuf.h
|
||||
header-y += kvm_para.h
|
||||
header-y += mman.h
|
||||
header-y += msgbuf.h
|
||||
header-y += param.h
|
||||
header-y += poll.h
|
||||
header-y += posix_types.h
|
||||
header-y += resource.h
|
||||
header-y += sembuf.h
|
||||
header-y += setup.h
|
||||
header-y += shmbuf.h
|
||||
header-y += siginfo.h
|
||||
header-y += socket.h
|
||||
header-y += sockios.h
|
||||
header-y += stat.h
|
||||
header-y += statfs.h
|
||||
header-y += swab.h
|
||||
header-y += termbits.h
|
||||
header-y += termios.h
|
||||
header-y += types.h
|
||||
header-y += unistd.h
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef _H8300_BYTEORDER_H
|
||||
#define _H8300_BYTEORDER_H
|
||||
|
||||
#include <linux/byteorder/big_endian.h>
|
||||
|
||||
#endif /* _H8300_BYTEORDER_H */
|
|
@ -0,0 +1,42 @@
|
|||
#ifndef _UAPI_H8300_PTRACE_H
|
||||
#define _UAPI_H8300_PTRACE_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#define PT_ER1 0
|
||||
#define PT_ER2 1
|
||||
#define PT_ER3 2
|
||||
#define PT_ER4 3
|
||||
#define PT_ER5 4
|
||||
#define PT_ER6 5
|
||||
#define PT_ER0 6
|
||||
#define PT_USP 7
|
||||
#define PT_ORIG_ER0 8
|
||||
#define PT_CCR 9
|
||||
#define PT_PC 10
|
||||
#define PT_EXR 11
|
||||
|
||||
/* this struct defines the way the registers are stored on the
|
||||
stack during a system call. */
|
||||
|
||||
struct pt_regs {
|
||||
long retpc;
|
||||
long er4;
|
||||
long er5;
|
||||
long er6;
|
||||
long er3;
|
||||
long er2;
|
||||
long er1;
|
||||
long orig_er0;
|
||||
long sp;
|
||||
unsigned short ccr;
|
||||
long er0;
|
||||
long vector;
|
||||
#if defined(__H8300S__)
|
||||
unsigned short exr;
|
||||
#endif
|
||||
unsigned long pc;
|
||||
} __attribute__((aligned(2), packed));
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* _UAPI_H8300_PTRACE_H */
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef _ASM_H8300_SIGCONTEXT_H
|
||||
#define _ASM_H8300_SIGCONTEXT_H
|
||||
|
||||
struct sigcontext {
|
||||
unsigned long sc_mask; /* old sigmask */
|
||||
unsigned long sc_usp; /* old user stack pointer */
|
||||
unsigned long sc_er0;
|
||||
unsigned long sc_er1;
|
||||
unsigned long sc_er2;
|
||||
unsigned long sc_er3;
|
||||
unsigned long sc_er4;
|
||||
unsigned long sc_er5;
|
||||
unsigned long sc_er6;
|
||||
unsigned short sc_ccr;
|
||||
unsigned long sc_pc;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,115 @@
|
|||
#ifndef _UAPI_H8300_SIGNAL_H
|
||||
#define _UAPI_H8300_SIGNAL_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* Avoid too many header ordering problems. */
|
||||
struct siginfo;
|
||||
|
||||
#ifndef __KERNEL__
|
||||
/* Here we must cater to libcs that poke about in kernel headers. */
|
||||
|
||||
#define NSIG 32
|
||||
typedef unsigned long sigset_t;
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#define SIGHUP 1
|
||||
#define SIGINT 2
|
||||
#define SIGQUIT 3
|
||||
#define SIGILL 4
|
||||
#define SIGTRAP 5
|
||||
#define SIGABRT 6
|
||||
#define SIGIOT 6
|
||||
#define SIGBUS 7
|
||||
#define SIGFPE 8
|
||||
#define SIGKILL 9
|
||||
#define SIGUSR1 10
|
||||
#define SIGSEGV 11
|
||||
#define SIGUSR2 12
|
||||
#define SIGPIPE 13
|
||||
#define SIGALRM 14
|
||||
#define SIGTERM 15
|
||||
#define SIGSTKFLT 16
|
||||
#define SIGCHLD 17
|
||||
#define SIGCONT 18
|
||||
#define SIGSTOP 19
|
||||
#define SIGTSTP 20
|
||||
#define SIGTTIN 21
|
||||
#define SIGTTOU 22
|
||||
#define SIGURG 23
|
||||
#define SIGXCPU 24
|
||||
#define SIGXFSZ 25
|
||||
#define SIGVTALRM 26
|
||||
#define SIGPROF 27
|
||||
#define SIGWINCH 28
|
||||
#define SIGIO 29
|
||||
#define SIGPOLL SIGIO
|
||||
/*
|
||||
#define SIGLOST 29
|
||||
*/
|
||||
#define SIGPWR 30
|
||||
#define SIGSYS 31
|
||||
#define SIGUNUSED 31
|
||||
|
||||
/* These should not be considered constants from userland. */
|
||||
#define SIGRTMIN 32
|
||||
#define SIGRTMAX _NSIG
|
||||
|
||||
/*
|
||||
* SA_FLAGS values:
|
||||
*
|
||||
* SA_ONSTACK indicates that a registered stack_t will be used.
|
||||
* SA_RESTART flag to get restarting signals (which were the default long ago)
|
||||
* SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
|
||||
* SA_RESETHAND clears the handler when the signal is delivered.
|
||||
* SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
|
||||
* SA_NODEFER prevents the current signal from being masked in the handler.
|
||||
*
|
||||
* SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
|
||||
* Unix names RESETHAND and NODEFER respectively.
|
||||
*/
|
||||
#define SA_NOCLDSTOP 0x00000001
|
||||
#define SA_NOCLDWAIT 0x00000002 /* not supported yet */
|
||||
#define SA_SIGINFO 0x00000004
|
||||
#define SA_ONSTACK 0x08000000
|
||||
#define SA_RESTART 0x10000000
|
||||
#define SA_NODEFER 0x40000000
|
||||
#define SA_RESETHAND 0x80000000
|
||||
|
||||
#define SA_NOMASK SA_NODEFER
|
||||
#define SA_ONESHOT SA_RESETHAND
|
||||
|
||||
#define SA_RESTORER 0x04000000
|
||||
|
||||
#define MINSIGSTKSZ 2048
|
||||
#define SIGSTKSZ 8192
|
||||
|
||||
#include <asm-generic/signal-defs.h>
|
||||
|
||||
#ifndef __KERNEL__
|
||||
/* Here we must cater to libcs that poke about in kernel headers. */
|
||||
|
||||
struct sigaction {
|
||||
union {
|
||||
__sighandler_t _sa_handler;
|
||||
void (*_sa_sigaction)(int, struct siginfo *, void *);
|
||||
} _u;
|
||||
sigset_t sa_mask;
|
||||
unsigned long sa_flags;
|
||||
void (*sa_restorer)(void);
|
||||
};
|
||||
|
||||
#define sa_handler _u._sa_handler
|
||||
#define sa_sigaction _u._sa_sigaction
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
typedef struct sigaltstack {
|
||||
void *ss_sp;
|
||||
int ss_flags;
|
||||
size_t ss_size;
|
||||
} stack_t;
|
||||
|
||||
|
||||
#endif /* _UAPI_H8300_SIGNAL_H */
|
|
@ -0,0 +1,3 @@
|
|||
#define __ARCH_NOMMU
|
||||
|
||||
#include <asm-generic/unistd.h>
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# Makefile for the linux kernel.
|
||||
#
|
||||
|
||||
extra-y := vmlinux.lds
|
||||
|
||||
obj-y := process.o traps.o ptrace.o \
|
||||
signal.o setup.o syscalls.o \
|
||||
irq.o entry.o dma.o
|
||||
|
||||
obj-$(CONFIG_ROMKERNEL) += head_rom.o
|
||||
obj-$(CONFIG_RAMKERNEL) += head_ram.o
|
||||
|
||||
obj-$(CONFIG_MODULES) += module.o h8300_ksyms.o
|
||||
obj-$(CONFIG_H8300H_SIM) += sim-console.o
|
||||
obj-$(CONFIG_H8S_SIM) += sim-console.o
|
||||
|
||||
obj-$(CONFIG_CPU_H8300H) += ptrace_h.o
|
||||
obj-$(CONFIG_CPU_H8S) += ptrace_s.o
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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/stddef.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/kbuild.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* offsets into the task struct */
|
||||
OFFSET(TASK_STATE, task_struct, state);
|
||||
OFFSET(TASK_FLAGS, task_struct, flags);
|
||||
OFFSET(TASK_PTRACE, task_struct, ptrace);
|
||||
OFFSET(TASK_BLOCKED, task_struct, blocked);
|
||||
OFFSET(TASK_THREAD, task_struct, thread);
|
||||
OFFSET(TASK_THREAD_INFO, task_struct, stack);
|
||||
OFFSET(TASK_MM, task_struct, mm);
|
||||
OFFSET(TASK_ACTIVE_MM, task_struct, active_mm);
|
||||
|
||||
/* offsets into the irq_cpustat_t struct */
|
||||
DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t,
|
||||
__softirq_pending));
|
||||
|
||||
/* offsets into the thread struct */
|
||||
OFFSET(THREAD_KSP, thread_struct, ksp);
|
||||
OFFSET(THREAD_USP, thread_struct, usp);
|
||||
OFFSET(THREAD_CCR, thread_struct, ccr);
|
||||
|
||||
/* offsets into the pt_regs struct */
|
||||
DEFINE(LER0, offsetof(struct pt_regs, er0) - sizeof(long));
|
||||
DEFINE(LER1, offsetof(struct pt_regs, er1) - sizeof(long));
|
||||
DEFINE(LER2, offsetof(struct pt_regs, er2) - sizeof(long));
|
||||
DEFINE(LER3, offsetof(struct pt_regs, er3) - sizeof(long));
|
||||
DEFINE(LER4, offsetof(struct pt_regs, er4) - sizeof(long));
|
||||
DEFINE(LER5, offsetof(struct pt_regs, er5) - sizeof(long));
|
||||
DEFINE(LER6, offsetof(struct pt_regs, er6) - sizeof(long));
|
||||
DEFINE(LORIG, offsetof(struct pt_regs, orig_er0) - sizeof(long));
|
||||
DEFINE(LSP, offsetof(struct pt_regs, sp) - sizeof(long));
|
||||
DEFINE(LCCR, offsetof(struct pt_regs, ccr) - sizeof(long));
|
||||
DEFINE(LVEC, offsetof(struct pt_regs, vector) - sizeof(long));
|
||||
#if defined(CONFIG_CPU_H8S)
|
||||
DEFINE(LEXR, offsetof(struct pt_regs, exr) - sizeof(long));
|
||||
#endif
|
||||
DEFINE(LRET, offsetof(struct pt_regs, pc) - sizeof(long));
|
||||
|
||||
DEFINE(PT_PTRACED, PT_PTRACED);
|
||||
|
||||
/* offsets in thread_info structure */
|
||||
OFFSET(TI_TASK, thread_info, task);
|
||||
OFFSET(TI_FLAGS, thread_info, flags);
|
||||
OFFSET(TI_CPU, thread_info, cpu);
|
||||
OFFSET(TI_PRE, thread_info, preempt_count);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file COPYING in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/module.h>
|
||||
#include <asm/pgalloc.h>
|
||||
|
||||
static void *dma_alloc(struct device *dev, size_t size,
|
||||
dma_addr_t *dma_handle, gfp_t gfp,
|
||||
struct dma_attrs *attrs)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
/* ignore region specifiers */
|
||||
gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
|
||||
|
||||
if (dev == NULL || (*dev->dma_mask < 0xffffffff))
|
||||
gfp |= GFP_DMA;
|
||||
ret = (void *)__get_free_pages(gfp, get_order(size));
|
||||
|
||||
if (ret != NULL) {
|
||||
memset(ret, 0, size);
|
||||
*dma_handle = virt_to_phys(ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dma_free(struct device *dev, size_t size,
|
||||
void *vaddr, dma_addr_t dma_handle,
|
||||
struct dma_attrs *attrs)
|
||||
|
||||
{
|
||||
free_pages((unsigned long)vaddr, get_order(size));
|
||||
}
|
||||
|
||||
static dma_addr_t map_page(struct device *dev, struct page *page,
|
||||
unsigned long offset, size_t size,
|
||||
enum dma_data_direction direction,
|
||||
struct dma_attrs *attrs)
|
||||
{
|
||||
return page_to_phys(page) + offset;
|
||||
}
|
||||
|
||||
static int map_sg(struct device *dev, struct scatterlist *sgl,
|
||||
int nents, enum dma_data_direction direction,
|
||||
struct dma_attrs *attrs)
|
||||
{
|
||||
struct scatterlist *sg;
|
||||
int i;
|
||||
|
||||
for_each_sg(sgl, sg, nents, i) {
|
||||
sg->dma_address = sg_phys(sg);
|
||||
}
|
||||
|
||||
return nents;
|
||||
}
|
||||
|
||||
struct dma_map_ops h8300_dma_map_ops = {
|
||||
.alloc = dma_alloc,
|
||||
.free = dma_free,
|
||||
.map_page = map_page,
|
||||
.map_sg = map_sg,
|
||||
};
|
||||
EXPORT_SYMBOL(h8300_dma_map_ops);
|
|
@ -0,0 +1,414 @@
|
|||
/*
|
||||
*
|
||||
* linux/arch/h8300/kernel/entry.S
|
||||
*
|
||||
* Yoshinori Sato <ysato@users.sourceforge.jp>
|
||||
* David McCullough <davidm@snapgear.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* entry.S
|
||||
* include exception/interrupt gateway
|
||||
* system call entry
|
||||
*/
|
||||
|
||||
#include <linux/sys.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/linkage.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/errno.h>
|
||||
|
||||
#if defined(CONFIG_CPU_H8300H)
|
||||
#define USERRET 8
|
||||
INTERRUPTS = 64
|
||||
.h8300h
|
||||
.macro SHLL2 reg
|
||||
shll.l \reg
|
||||
shll.l \reg
|
||||
.endm
|
||||
.macro SHLR2 reg
|
||||
shlr.l \reg
|
||||
shlr.l \reg
|
||||
.endm
|
||||
.macro SAVEREGS
|
||||
mov.l er0,@-sp
|
||||
mov.l er1,@-sp
|
||||
mov.l er2,@-sp
|
||||
mov.l er3,@-sp
|
||||
.endm
|
||||
.macro RESTOREREGS
|
||||
mov.l @sp+,er3
|
||||
mov.l @sp+,er2
|
||||
.endm
|
||||
.macro SAVEEXR
|
||||
.endm
|
||||
.macro RESTOREEXR
|
||||
.endm
|
||||
#endif
|
||||
#if defined(CONFIG_CPU_H8S)
|
||||
#define USERRET 10
|
||||
#define USEREXR 8
|
||||
INTERRUPTS = 128
|
||||
.h8300s
|
||||
.macro SHLL2 reg
|
||||
shll.l #2,\reg
|
||||
.endm
|
||||
.macro SHLR2 reg
|
||||
shlr.l #2,\reg
|
||||
.endm
|
||||
.macro SAVEREGS
|
||||
stm.l er0-er3,@-sp
|
||||
.endm
|
||||
.macro RESTOREREGS
|
||||
ldm.l @sp+,er2-er3
|
||||
.endm
|
||||
.macro SAVEEXR
|
||||
mov.w @(USEREXR:16,er0),r1
|
||||
mov.w r1,@(LEXR-LER3:16,sp) /* copy EXR */
|
||||
.endm
|
||||
.macro RESTOREEXR
|
||||
mov.w @(LEXR-LER1:16,sp),r1 /* restore EXR */
|
||||
mov.b r1l,r1h
|
||||
mov.w r1,@(USEREXR:16,er0)
|
||||
.endm
|
||||
#endif
|
||||
|
||||
|
||||
/* CPU context save/restore macros. */
|
||||
|
||||
.macro SAVE_ALL
|
||||
mov.l er0,@-sp
|
||||
stc ccr,r0l /* check kernel mode */
|
||||
btst #4,r0l
|
||||
bne 5f
|
||||
|
||||
/* user mode */
|
||||
mov.l sp,@_sw_usp
|
||||
mov.l @sp,er0 /* restore saved er0 */
|
||||
orc #0x10,ccr /* switch kernel stack */
|
||||
mov.l @_sw_ksp,sp
|
||||
sub.l #(LRET-LORIG),sp /* allocate LORIG - LRET */
|
||||
SAVEREGS
|
||||
mov.l @_sw_usp,er0
|
||||
mov.l @(USERRET:16,er0),er1 /* copy the RET addr */
|
||||
mov.l er1,@(LRET-LER3:16,sp)
|
||||
SAVEEXR
|
||||
|
||||
mov.l @(LORIG-LER3:16,sp),er0
|
||||
mov.l er0,@(LER0-LER3:16,sp) /* copy ER0 */
|
||||
mov.w e1,r1 /* e1 highbyte = ccr */
|
||||
and #0xef,r1h /* mask mode? flag */
|
||||
bra 6f
|
||||
5:
|
||||
/* kernel mode */
|
||||
mov.l @sp,er0 /* restore saved er0 */
|
||||
subs #2,sp /* set dummy ccr */
|
||||
subs #4,sp /* set dummp sp */
|
||||
SAVEREGS
|
||||
mov.w @(LRET-LER3:16,sp),r1 /* copy old ccr */
|
||||
6:
|
||||
mov.b r1h,r1l
|
||||
mov.b #0,r1h
|
||||
mov.w r1,@(LCCR-LER3:16,sp) /* set ccr */
|
||||
mov.l @_sw_usp,er2
|
||||
mov.l er2,@(LSP-LER3:16,sp) /* set usp */
|
||||
mov.l er6,@-sp /* syscall arg #6 */
|
||||
mov.l er5,@-sp /* syscall arg #5 */
|
||||
mov.l er4,@-sp /* syscall arg #4 */
|
||||
.endm /* r1 = ccr */
|
||||
|
||||
.macro RESTORE_ALL
|
||||
mov.l @sp+,er4
|
||||
mov.l @sp+,er5
|
||||
mov.l @sp+,er6
|
||||
RESTOREREGS
|
||||
mov.w @(LCCR-LER1:16,sp),r0 /* check kernel mode */
|
||||
btst #4,r0l
|
||||
bne 7f
|
||||
|
||||
orc #0xc0,ccr
|
||||
mov.l @(LSP-LER1:16,sp),er0
|
||||
mov.l @(LER0-LER1:16,sp),er1 /* restore ER0 */
|
||||
mov.l er1,@er0
|
||||
RESTOREEXR
|
||||
mov.w @(LCCR-LER1:16,sp),r1 /* restore the RET addr */
|
||||
mov.b r1l,r1h
|
||||
mov.b @(LRET+1-LER1:16,sp),r1l
|
||||
mov.w r1,e1
|
||||
mov.w @(LRET+2-LER1:16,sp),r1
|
||||
mov.l er1,@(USERRET:16,er0)
|
||||
|
||||
mov.l @sp+,er1
|
||||
add.l #(LRET-LER1),sp /* remove LORIG - LRET */
|
||||
mov.l sp,@_sw_ksp
|
||||
andc #0xef,ccr /* switch to user mode */
|
||||
mov.l er0,sp
|
||||
bra 8f
|
||||
7:
|
||||
mov.l @sp+,er1
|
||||
add.l #10,sp
|
||||
8:
|
||||
mov.l @sp+,er0
|
||||
adds #4,sp /* remove the sw created LVEC */
|
||||
rte
|
||||
.endm
|
||||
|
||||
.globl _system_call
|
||||
.globl ret_from_exception
|
||||
.globl ret_from_fork
|
||||
.globl ret_from_kernel_thread
|
||||
.globl ret_from_interrupt
|
||||
.globl _interrupt_redirect_table
|
||||
.globl _sw_ksp,_sw_usp
|
||||
.globl _resume
|
||||
.globl _interrupt_entry
|
||||
.globl _trace_break
|
||||
.globl _nmi
|
||||
|
||||
#if defined(CONFIG_ROMKERNEL)
|
||||
.section .int_redirect,"ax"
|
||||
_interrupt_redirect_table:
|
||||
#if defined(CONFIG_CPU_H8300H)
|
||||
.rept 7
|
||||
.long 0
|
||||
.endr
|
||||
#endif
|
||||
#if defined(CONFIG_CPU_H8S)
|
||||
.rept 5
|
||||
.long 0
|
||||
.endr
|
||||
jmp @_trace_break
|
||||
.long 0
|
||||
#endif
|
||||
|
||||
jsr @_interrupt_entry /* NMI */
|
||||
jmp @_system_call /* TRAPA #0 (System call) */
|
||||
.long 0
|
||||
.long 0
|
||||
jmp @_trace_break /* TRAPA #3 (breakpoint) */
|
||||
.rept INTERRUPTS-12
|
||||
jsr @_interrupt_entry
|
||||
.endr
|
||||
#endif
|
||||
#if defined(CONFIG_RAMKERNEL)
|
||||
.globl _interrupt_redirect_table
|
||||
.section .bss
|
||||
_interrupt_redirect_table:
|
||||
.space 4
|
||||
#endif
|
||||
|
||||
.section .text
|
||||
.align 2
|
||||
_interrupt_entry:
|
||||
SAVE_ALL
|
||||
/* r1l is saved ccr */
|
||||
mov.l sp,er0
|
||||
add.l #LVEC,er0
|
||||
btst #4,r1l
|
||||
bne 1f
|
||||
/* user LVEC */
|
||||
mov.l @_sw_usp,er0
|
||||
adds #4,er0
|
||||
1:
|
||||
mov.l @er0,er0 /* LVEC address */
|
||||
#if defined(CONFIG_ROMKERNEL)
|
||||
sub.l #_interrupt_redirect_table,er0
|
||||
#endif
|
||||
#if defined(CONFIG_RAMKERNEL)
|
||||
mov.l @_interrupt_redirect_table,er1
|
||||
sub.l er1,er0
|
||||
#endif
|
||||
SHLR2 er0
|
||||
dec.l #1,er0
|
||||
mov.l sp,er1
|
||||
subs #4,er1 /* adjust ret_pc */
|
||||
#if defined(CONFIG_CPU_H8S)
|
||||
orc #7,exr
|
||||
#endif
|
||||
jsr @do_IRQ
|
||||
jmp @ret_from_interrupt
|
||||
|
||||
_system_call:
|
||||
subs #4,sp /* dummy LVEC */
|
||||
SAVE_ALL
|
||||
/* er0: syscall nr */
|
||||
andc #0xbf,ccr
|
||||
mov.l er0,er4
|
||||
|
||||
/* save top of frame */
|
||||
mov.l sp,er0
|
||||
jsr @set_esp0
|
||||
mov.l sp,er2
|
||||
and.w #0xe000,r2
|
||||
mov.l @(TI_FLAGS:16,er2),er2
|
||||
and.w #_TIF_WORK_SYSCALL_MASK,r2
|
||||
beq 1f
|
||||
mov.l sp,er0
|
||||
jsr @do_syscall_trace_enter
|
||||
1:
|
||||
cmp.l #__NR_syscalls,er4
|
||||
bcc badsys
|
||||
SHLL2 er4
|
||||
mov.l #_sys_call_table,er0
|
||||
add.l er4,er0
|
||||
mov.l @er0,er4
|
||||
beq ret_from_exception:16
|
||||
mov.l @(LER1:16,sp),er0
|
||||
mov.l @(LER2:16,sp),er1
|
||||
mov.l @(LER3:16,sp),er2
|
||||
jsr @er4
|
||||
mov.l er0,@(LER0:16,sp) /* save the return value */
|
||||
mov.l sp,er2
|
||||
and.w #0xe000,r2
|
||||
mov.l @(TI_FLAGS:16,er2),er2
|
||||
and.w #_TIF_WORK_SYSCALL_MASK,r2
|
||||
beq 2f
|
||||
mov.l sp,er0
|
||||
jsr @do_syscall_trace_leave
|
||||
2:
|
||||
orc #0xc0,ccr
|
||||
bra resume_userspace
|
||||
|
||||
badsys:
|
||||
mov.l #-ENOSYS,er0
|
||||
mov.l er0,@(LER0:16,sp)
|
||||
bra resume_userspace
|
||||
|
||||
#if !defined(CONFIG_PREEMPT)
|
||||
#define resume_kernel restore_all
|
||||
#endif
|
||||
|
||||
ret_from_exception:
|
||||
#if defined(CONFIG_PREEMPT)
|
||||
orc #0xc0,ccr
|
||||
#endif
|
||||
ret_from_interrupt:
|
||||
mov.b @(LCCR+1:16,sp),r0l
|
||||
btst #4,r0l
|
||||
bne resume_kernel:16 /* return from kernel */
|
||||
resume_userspace:
|
||||
andc #0xbf,ccr
|
||||
mov.l sp,er4
|
||||
and.w #0xe000,r4 /* er4 <- current thread info */
|
||||
mov.l @(TI_FLAGS:16,er4),er1
|
||||
and.l #_TIF_WORK_MASK,er1
|
||||
beq restore_all:8
|
||||
work_pending:
|
||||
btst #TIF_NEED_RESCHED,r1l
|
||||
bne work_resched:8
|
||||
/* work notifysig */
|
||||
mov.l sp,er0
|
||||
subs #4,er0 /* er0: pt_regs */
|
||||
jsr @do_notify_resume
|
||||
bra resume_userspace:8
|
||||
work_resched:
|
||||
mov.l sp,er0
|
||||
jsr @set_esp0
|
||||
jsr @schedule
|
||||
bra resume_userspace:8
|
||||
restore_all:
|
||||
RESTORE_ALL /* Does RTE */
|
||||
|
||||
#if defined(CONFIG_PREEMPT)
|
||||
resume_kernel:
|
||||
mov.l @(TI_PRE_COUNT:16,er4),er0
|
||||
bne restore_all:8
|
||||
need_resched:
|
||||
mov.l @(TI_FLAGS:16,er4),er0
|
||||
btst #TIF_NEED_RESCHED,r0l
|
||||
beq restore_all:8
|
||||
mov.b @(LCCR+1:16,sp),r0l /* Interrupt Enabled? */
|
||||
bmi restore_all:8
|
||||
mov.l sp,er0
|
||||
jsr @set_esp0
|
||||
jsr @preempt_schedule_irq
|
||||
bra need_resched:8
|
||||
#endif
|
||||
|
||||
ret_from_fork:
|
||||
mov.l er2,er0
|
||||
jsr @schedule_tail
|
||||
jmp @ret_from_exception
|
||||
|
||||
ret_from_kernel_thread:
|
||||
mov.l er2,er0
|
||||
jsr @schedule_tail
|
||||
mov.l @(LER4:16,sp),er0
|
||||
mov.l @(LER5:16,sp),er1
|
||||
jsr @er1
|
||||
jmp @ret_from_exception
|
||||
|
||||
_resume:
|
||||
/*
|
||||
* Beware - when entering resume, offset of tss is in d1,
|
||||
* prev (the current task) is in a0, next (the new task)
|
||||
* is in a1 and d2.b is non-zero if the mm structure is
|
||||
* shared between the tasks, so don't change these
|
||||
* registers until their contents are no longer needed.
|
||||
*/
|
||||
|
||||
/* save sr */
|
||||
sub.w r3,r3
|
||||
stc ccr,r3l
|
||||
mov.w r3,@(THREAD_CCR+2:16,er0)
|
||||
|
||||
/* disable interrupts */
|
||||
orc #0xc0,ccr
|
||||
mov.l @_sw_usp,er3
|
||||
mov.l er3,@(THREAD_USP:16,er0)
|
||||
mov.l sp,@(THREAD_KSP:16,er0)
|
||||
|
||||
/* Skip address space switching if they are the same. */
|
||||
/* FIXME: what did we hack out of here, this does nothing! */
|
||||
|
||||
mov.l @(THREAD_USP:16,er1),er0
|
||||
mov.l er0,@_sw_usp
|
||||
mov.l @(THREAD_KSP:16,er1),sp
|
||||
|
||||
/* restore status register */
|
||||
mov.w @(THREAD_CCR+2:16,er1),r3
|
||||
|
||||
ldc r3l,ccr
|
||||
rts
|
||||
|
||||
_trace_break:
|
||||
subs #4,sp
|
||||
SAVE_ALL
|
||||
sub.l er1,er1
|
||||
dec.l #1,er1
|
||||
mov.l er1,@(LORIG,sp)
|
||||
mov.l sp,er0
|
||||
jsr @set_esp0
|
||||
mov.l @_sw_usp,er0
|
||||
mov.l @er0,er1
|
||||
mov.w @(-2:16,er1),r2
|
||||
cmp.w #0x5730,r2
|
||||
beq 1f
|
||||
subs #2,er1
|
||||
mov.l er1,@er0
|
||||
1:
|
||||
and.w #0xff,e1
|
||||
mov.l er1,er0
|
||||
jsr @trace_trap
|
||||
jmp @ret_from_exception
|
||||
|
||||
_nmi:
|
||||
subs #4, sp
|
||||
mov.l er0, @-sp
|
||||
mov.l @_interrupt_redirect_table, er0
|
||||
add.l #8*4, er0
|
||||
mov.l er0, @(4,sp)
|
||||
mov.l @sp+, er0
|
||||
jmp @_interrupt_entry
|
||||
|
||||
.section .bss
|
||||
_sw_ksp:
|
||||
.space 4
|
||||
_sw_usp:
|
||||
.space 4
|
||||
|
||||
.end
|
|
@ -0,0 +1,36 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
/*
|
||||
* libgcc functions - functions that are used internally by the
|
||||
* compiler... (prototypes are not correct though, but that
|
||||
* doesn't really matter since they're not versioned).
|
||||
*/
|
||||
asmlinkage long __ucmpdi2(long long, long long);
|
||||
asmlinkage long long __ashldi3(long long, int);
|
||||
asmlinkage long long __ashrdi3(long long, int);
|
||||
asmlinkage long long __lshrdi3(long long, int);
|
||||
asmlinkage long __divsi3(long, long);
|
||||
asmlinkage long __modsi3(long, long);
|
||||
asmlinkage unsigned long __umodsi3(unsigned long, unsigned long);
|
||||
asmlinkage long long __muldi3(long long, long long);
|
||||
asmlinkage long __mulsi3(long, long);
|
||||
asmlinkage long __udivsi3(long, long);
|
||||
asmlinkage void *memcpy(void *, const void *, size_t);
|
||||
asmlinkage void *memset(void *, int, size_t);
|
||||
asmlinkage long strncpy_from_user(void *to, void *from, size_t n);
|
||||
|
||||
/* gcc lib functions */
|
||||
EXPORT_SYMBOL(__ucmpdi2);
|
||||
EXPORT_SYMBOL(__ashldi3);
|
||||
EXPORT_SYMBOL(__ashrdi3);
|
||||
EXPORT_SYMBOL(__lshrdi3);
|
||||
EXPORT_SYMBOL(__divsi3);
|
||||
EXPORT_SYMBOL(__modsi3);
|
||||
EXPORT_SYMBOL(__umodsi3);
|
||||
EXPORT_SYMBOL(__muldi3);
|
||||
EXPORT_SYMBOL(__mulsi3);
|
||||
EXPORT_SYMBOL(__udivsi3);
|
||||
EXPORT_SYMBOL(memcpy);
|
||||
EXPORT_SYMBOL(memset);
|
||||
EXPORT_SYMBOL(strncpy_from_user);
|
|
@ -0,0 +1,60 @@
|
|||
|
||||
#include <linux/sys.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/linkage.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/errno.h>
|
||||
|
||||
#if defined(CONFIG_CPU_H8300H)
|
||||
.h8300h
|
||||
#define SYSCR 0xfee012
|
||||
#define IRAMTOP 0xffff20
|
||||
#endif
|
||||
#if defined(CONFIG_CPU_H8S)
|
||||
.h8300s
|
||||
#define INTCR 0xffff31
|
||||
#define IRAMTOP 0xffc000
|
||||
#endif
|
||||
|
||||
__HEAD
|
||||
.global _start
|
||||
_start:
|
||||
mov.l #IRAMTOP,sp
|
||||
/* .bss clear */
|
||||
mov.l #_sbss,er5
|
||||
mov.l #_ebss,er4
|
||||
sub.l er5,er4
|
||||
shlr er4
|
||||
shlr er4
|
||||
sub.l er2,er2
|
||||
1:
|
||||
mov.l er2,@er5
|
||||
adds #4,er5
|
||||
dec.l #1,er4
|
||||
bne 1b
|
||||
jsr @h8300_fdt_init
|
||||
|
||||
/* linux kernel start */
|
||||
#if defined(CONFIG_CPU_H8300H)
|
||||
ldc #0xd0,ccr /* running kernel */
|
||||
mov.l #SYSCR,er0
|
||||
bclr #3,@er0
|
||||
#endif
|
||||
#if defined(CONFIG_CPU_H8S)
|
||||
ldc #0x07,exr
|
||||
bclr #4,@INTCR:8
|
||||
bset #5,@INTCR:8 /* Interrupt mode 2 */
|
||||
ldc #0x90,ccr /* running kernel */
|
||||
#endif
|
||||
mov.l #init_thread_union,sp
|
||||
add.l #0x2000,sp
|
||||
jsr @start_kernel
|
||||
|
||||
1:
|
||||
bra 1b
|
||||
|
||||
.end
|
|
@ -0,0 +1,110 @@
|
|||
#include <linux/init.h>
|
||||
#include <asm/thread_info.h>
|
||||
|
||||
#if defined(CONFIG_CPU_H8300H)
|
||||
.h8300h
|
||||
#define SYSCR 0xfee012
|
||||
#define IRAMTOP 0xffff20
|
||||
#define NR_INT 64
|
||||
#endif
|
||||
#if defined(CONFIG_CPU_H8S)
|
||||
.h8300s
|
||||
#define INTCR 0xffff31
|
||||
#define IRAMTOP 0xffc000
|
||||
#define NR_INT 128
|
||||
#endif
|
||||
|
||||
__HEAD
|
||||
.global _start
|
||||
_start:
|
||||
mov.l #IRAMTOP,sp
|
||||
#if !defined(CONFIG_H8300H_SIM) && \
|
||||
!defined(CONFIG_H8S_SIM)
|
||||
jsr @lowlevel_init
|
||||
|
||||
/* copy .data */
|
||||
mov.l #_begin_data,er5
|
||||
mov.l #_sdata,er6
|
||||
mov.l #_edata,er4
|
||||
sub.l er6,er4
|
||||
shlr.l er4
|
||||
shlr.l er4
|
||||
1:
|
||||
mov.l @er5+,er0
|
||||
mov.l er0,@er6
|
||||
adds #4,er6
|
||||
dec.l #1,er4
|
||||
bne 1b
|
||||
/* .bss clear */
|
||||
mov.l #_sbss,er5
|
||||
mov.l #_ebss,er4
|
||||
sub.l er5,er4
|
||||
shlr er4
|
||||
shlr er4
|
||||
sub.l er0,er0
|
||||
1:
|
||||
mov.l er0,@er5
|
||||
adds #4,er5
|
||||
dec.l #1,er4
|
||||
bne 1b
|
||||
#else
|
||||
/* get cmdline from gdb */
|
||||
jsr @0xcc
|
||||
;; er0 - argc
|
||||
;; er1 - argv
|
||||
mov.l #command_line,er3
|
||||
adds #4,er1
|
||||
dec.l #1,er0
|
||||
beq 4f
|
||||
1:
|
||||
mov.l @er1+,er2
|
||||
2:
|
||||
mov.b @er2+,r4l
|
||||
beq 3f
|
||||
mov.b r4l,@er3
|
||||
adds #1,er3
|
||||
bra 2b
|
||||
3:
|
||||
mov.b #' ',r4l
|
||||
mov.b r4l,@er3
|
||||
adds #1,er3
|
||||
dec.l #1,er0
|
||||
bne 1b
|
||||
subs #1,er3
|
||||
mov.b #0,r4l
|
||||
mov.b r4l,@er3
|
||||
4:
|
||||
#endif
|
||||
sub.l er0,er0
|
||||
jsr @h8300_fdt_init
|
||||
/* linux kernel start */
|
||||
#if defined(CONFIG_CPU_H8300H)
|
||||
ldc #0xd0,ccr /* running kernel */
|
||||
mov.l #SYSCR,er0
|
||||
bclr #3,@er0
|
||||
#endif
|
||||
#if defined(CONFIG_CPU_H8S)
|
||||
ldc #0x07,exr
|
||||
bclr #4,@INTCR:8
|
||||
bset #5,@INTCR:8 /* Interrupt mode 2 */
|
||||
ldc #0x90,ccr /* running kernel */
|
||||
#endif
|
||||
mov.l #init_thread_union,sp
|
||||
add.l #0x2000,sp
|
||||
jsr @start_kernel
|
||||
|
||||
1:
|
||||
bra 1b
|
||||
|
||||
#if defined(CONFIG_ROMKERNEL)
|
||||
/* interrupt vector */
|
||||
.section .vectors,"ax"
|
||||
.long _start
|
||||
.long _start
|
||||
vector = 2
|
||||
.rept NR_INT - 2
|
||||
.long _interrupt_redirect_table+vector*4
|
||||
vector = vector + 1
|
||||
.endr
|
||||
#endif
|
||||
.end
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* linux/arch/h8300/kernel/irq.c
|
||||
*
|
||||
* Copyright 2014-2015 Yoshinori Sato <ysato@users.sourceforge.jp>
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <asm/traps.h>
|
||||
|
||||
#ifdef CONFIG_RAMKERNEL
|
||||
typedef void (*h8300_vector)(void);
|
||||
|
||||
static const h8300_vector __initconst trap_table[] = {
|
||||
0, 0, 0, 0,
|
||||
_trace_break,
|
||||
0, 0,
|
||||
_nmi,
|
||||
_system_call,
|
||||
0, 0,
|
||||
_trace_break,
|
||||
};
|
||||
|
||||
static unsigned long __init *get_vector_address(void)
|
||||
{
|
||||
unsigned long *rom_vector = CPU_VECTOR;
|
||||
unsigned long base, tmp;
|
||||
int vec_no;
|
||||
|
||||
base = rom_vector[EXT_IRQ0] & ADDR_MASK;
|
||||
|
||||
/* check romvector format */
|
||||
for (vec_no = EXT_IRQ0 + 1; vec_no <= EXT_IRQ0+EXT_IRQS; vec_no++) {
|
||||
if ((base+(vec_no - EXT_IRQ0)*4) !=
|
||||
(rom_vector[vec_no] & ADDR_MASK))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ramvector base address */
|
||||
base -= EXT_IRQ0*4;
|
||||
|
||||
/* writerble? */
|
||||
tmp = ~(*(volatile unsigned long *)base);
|
||||
(*(volatile unsigned long *)base) = tmp;
|
||||
if ((*(volatile unsigned long *)base) != tmp)
|
||||
return NULL;
|
||||
return (unsigned long *)base;
|
||||
}
|
||||
|
||||
static void __init setup_vector(void)
|
||||
{
|
||||
int i;
|
||||
unsigned long *ramvec, *ramvec_p;
|
||||
const h8300_vector *trap_entry;
|
||||
|
||||
ramvec = get_vector_address();
|
||||
if (ramvec == NULL)
|
||||
panic("interrupt vector serup failed.");
|
||||
else
|
||||
pr_debug("virtual vector at 0x%p\n", ramvec);
|
||||
|
||||
/* create redirect table */
|
||||
ramvec_p = ramvec;
|
||||
trap_entry = trap_table;
|
||||
for (i = 0; i < NR_IRQS; i++) {
|
||||
if (i < 12) {
|
||||
if (*trap_entry)
|
||||
*ramvec_p = VECTOR(*trap_entry);
|
||||
ramvec_p++;
|
||||
trap_entry++;
|
||||
} else
|
||||
*ramvec_p++ = REDIRECT(_interrupt_entry);
|
||||
}
|
||||
_interrupt_redirect_table = ramvec;
|
||||
}
|
||||
#else
|
||||
void setup_vector(void)
|
||||
{
|
||||
/* noting do */
|
||||
}
|
||||
#endif
|
||||
|
||||
void __init init_IRQ(void)
|
||||
{
|
||||
setup_vector();
|
||||
irqchip_init();
|
||||
}
|
||||
|
||||
asmlinkage void do_IRQ(int irq)
|
||||
{
|
||||
irq_enter();
|
||||
generic_handle_irq(irq);
|
||||
irq_exit();
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
#include <linux/moduleloader.h>
|
||||
#include <linux/elf.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/kernel.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 *rela = (void *)sechdrs[relsec].sh_addr;
|
||||
|
||||
pr_debug("Applying relocate section %u to %u\n", relsec,
|
||||
sechdrs[relsec].sh_info);
|
||||
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
|
||||
/* This is where to make the change */
|
||||
uint32_t *loc =
|
||||
(uint32_t *)(sechdrs[sechdrs[relsec].sh_info].sh_addr
|
||||
+ rela[i].r_offset);
|
||||
/* This is the symbol it is referring to. Note that all
|
||||
undefined symbols have been resolved. */
|
||||
Elf32_Sym *sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
|
||||
+ ELF32_R_SYM(rela[i].r_info);
|
||||
uint32_t v = sym->st_value + rela[i].r_addend;
|
||||
|
||||
switch (ELF32_R_TYPE(rela[i].r_info)) {
|
||||
case R_H8_DIR24R8:
|
||||
loc = (uint32_t *)((uint32_t)loc - 1);
|
||||
*loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
|
||||
break;
|
||||
case R_H8_DIR24A8:
|
||||
if (ELF32_R_SYM(rela[i].r_info))
|
||||
*loc += v;
|
||||
break;
|
||||
case R_H8_DIR32:
|
||||
case R_H8_DIR32A16:
|
||||
*loc += v;
|
||||
break;
|
||||
case R_H8_PCREL16:
|
||||
v -= (unsigned long)loc + 2;
|
||||
if ((Elf32_Sword)v > 0x7fff ||
|
||||
(Elf32_Sword)v < -(Elf32_Sword)0x8000)
|
||||
goto overflow;
|
||||
else
|
||||
*(unsigned short *)loc = v;
|
||||
break;
|
||||
case R_H8_PCREL8:
|
||||
v -= (unsigned long)loc + 1;
|
||||
if ((Elf32_Sword)v > 0x7f ||
|
||||
(Elf32_Sword)v < -(Elf32_Sword)0x80)
|
||||
goto overflow;
|
||||
else
|
||||
*(unsigned char *)loc = v;
|
||||
break;
|
||||
default:
|
||||
pr_err("module %s: Unknown relocation: %u\n",
|
||||
me->name, ELF32_R_TYPE(rela[i].r_info));
|
||||
return -ENOEXEC;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
overflow:
|
||||
pr_err("module %s: relocation offset overflow: %08x\n",
|
||||
me->name, rela[i].r_offset);
|
||||
return -ENOEXEC;
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* linux/arch/h8300/kernel/process.c
|
||||
*
|
||||
* Yoshinori Sato <ysato@users.sourceforge.jp>
|
||||
*
|
||||
* Based on:
|
||||
*
|
||||
* linux/arch/m68knommu/kernel/process.c
|
||||
*
|
||||
* Copyright (C) 1998 D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca>,
|
||||
* Kenneth Albanowski <kjahds@kjahds.com>,
|
||||
* The Silver Hammer Group, Ltd.
|
||||
*
|
||||
* linux/arch/m68k/kernel/process.c
|
||||
*
|
||||
* Copyright (C) 1995 Hamish Macdonald
|
||||
*
|
||||
* 68060 fixes by Jesper Skov
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file handles the architecture-dependent parts of process handling..
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/module.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/user.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/rcupdate.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/traps.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
||||
void (*pm_power_off)(void) = NULL;
|
||||
EXPORT_SYMBOL(pm_power_off);
|
||||
|
||||
asmlinkage void ret_from_fork(void);
|
||||
asmlinkage void ret_from_kernel_thread(void);
|
||||
|
||||
/*
|
||||
* The idle loop on an H8/300..
|
||||
*/
|
||||
void arch_cpu_idle(void)
|
||||
{
|
||||
local_irq_enable();
|
||||
__asm__("sleep");
|
||||
}
|
||||
|
||||
void machine_restart(char *__unused)
|
||||
{
|
||||
local_irq_disable();
|
||||
__asm__("jmp @@0");
|
||||
}
|
||||
|
||||
void machine_halt(void)
|
||||
{
|
||||
local_irq_disable();
|
||||
__asm__("sleep");
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
|
||||
void machine_power_off(void)
|
||||
{
|
||||
local_irq_disable();
|
||||
__asm__("sleep");
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
|
||||
void show_regs(struct pt_regs *regs)
|
||||
{
|
||||
show_regs_print_info(KERN_DEFAULT);
|
||||
|
||||
pr_notice("\n");
|
||||
pr_notice("PC: %08lx Status: %02x\n",
|
||||
regs->pc, regs->ccr);
|
||||
pr_notice("ORIG_ER0: %08lx ER0: %08lx ER1: %08lx\n",
|
||||
regs->orig_er0, regs->er0, regs->er1);
|
||||
pr_notice("ER2: %08lx ER3: %08lx ER4: %08lx ER5: %08lx\n",
|
||||
regs->er2, regs->er3, regs->er4, regs->er5);
|
||||
pr_notice("ER6' %08lx ", regs->er6);
|
||||
if (user_mode(regs))
|
||||
printk("USP: %08lx\n", rdusp());
|
||||
else
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
void flush_thread(void)
|
||||
{
|
||||
}
|
||||
|
||||
int copy_thread(unsigned long clone_flags,
|
||||
unsigned long usp, unsigned long topstk,
|
||||
struct task_struct *p)
|
||||
{
|
||||
struct pt_regs *childregs;
|
||||
|
||||
childregs = (struct pt_regs *) (THREAD_SIZE + task_stack_page(p)) - 1;
|
||||
|
||||
if (unlikely(p->flags & PF_KTHREAD)) {
|
||||
memset(childregs, 0, sizeof(struct pt_regs));
|
||||
childregs->retpc = (unsigned long) ret_from_kernel_thread;
|
||||
childregs->er4 = topstk; /* arg */
|
||||
childregs->er5 = usp; /* fn */
|
||||
} else {
|
||||
*childregs = *current_pt_regs();
|
||||
childregs->er0 = 0;
|
||||
childregs->retpc = (unsigned long) ret_from_fork;
|
||||
p->thread.usp = usp ?: rdusp();
|
||||
}
|
||||
p->thread.ksp = (unsigned long)childregs;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long thread_saved_pc(struct task_struct *tsk)
|
||||
{
|
||||
return ((struct pt_regs *)tsk->thread.esp0)->pc;
|
||||
}
|
||||
|
||||
unsigned long get_wchan(struct task_struct *p)
|
||||
{
|
||||
unsigned long fp, pc;
|
||||
unsigned long stack_page;
|
||||
int count = 0;
|
||||
|
||||
if (!p || p == current || p->state == TASK_RUNNING)
|
||||
return 0;
|
||||
|
||||
stack_page = (unsigned long)p;
|
||||
fp = ((struct pt_regs *)p->thread.ksp)->er6;
|
||||
do {
|
||||
if (fp < stack_page+sizeof(struct thread_info) ||
|
||||
fp >= 8184+stack_page)
|
||||
return 0;
|
||||
pc = ((unsigned long *)fp)[1];
|
||||
if (!in_sched_functions(pc))
|
||||
return pc;
|
||||
fp = *(unsigned long *) fp;
|
||||
} while (count++ < 16);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* generic sys_clone is not enough registers */
|
||||
asmlinkage int sys_clone(unsigned long __user *args)
|
||||
{
|
||||
unsigned long clone_flags;
|
||||
unsigned long newsp;
|
||||
uintptr_t parent_tidptr;
|
||||
uintptr_t child_tidptr;
|
||||
|
||||
get_user(clone_flags, &args[0]);
|
||||
get_user(newsp, &args[1]);
|
||||
get_user(parent_tidptr, &args[2]);
|
||||
get_user(child_tidptr, &args[3]);
|
||||
return do_fork(clone_flags, newsp, 0,
|
||||
(int __user *)parent_tidptr, (int __user *)child_tidptr);
|
||||
}
|
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* linux/arch/h8300/kernel/ptrace.c
|
||||
*
|
||||
* Copyright 2015 Yoshinori Sato <ysato@users.sourceforge.jp>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General
|
||||
* Public License. See the file COPYING in the main directory of
|
||||
* this archive for more details.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/audit.h>
|
||||
#include <linux/tracehook.h>
|
||||
#include <linux/regset.h>
|
||||
#include <linux/elf.h>
|
||||
|
||||
#define CCR_MASK 0x6f /* mode/imask not set */
|
||||
#define EXR_MASK 0x80 /* modify only T */
|
||||
|
||||
#define PT_REG(r) offsetof(struct pt_regs, r)
|
||||
|
||||
extern void user_disable_single_step(struct task_struct *child);
|
||||
|
||||
/* Mapping from PT_xxx to the stack offset at which the register is
|
||||
saved. Notice that usp has no stack-slot and needs to be treated
|
||||
specially (see get_reg/put_reg below). */
|
||||
static const int register_offset[] = {
|
||||
PT_REG(er1), PT_REG(er2), PT_REG(er3), PT_REG(er4),
|
||||
PT_REG(er5), PT_REG(er6), PT_REG(er0), -1,
|
||||
PT_REG(orig_er0), PT_REG(ccr), PT_REG(pc),
|
||||
#if defined(CONFIG_CPU_H8S)
|
||||
PT_REG(exr),
|
||||
#endif
|
||||
};
|
||||
|
||||
/* read register */
|
||||
long h8300_get_reg(struct task_struct *task, int regno)
|
||||
{
|
||||
switch (regno) {
|
||||
case PT_USP:
|
||||
return task->thread.usp + sizeof(long)*2;
|
||||
case PT_CCR:
|
||||
case PT_EXR:
|
||||
return *(unsigned short *)(task->thread.esp0 +
|
||||
register_offset[regno]);
|
||||
default:
|
||||
return *(unsigned long *)(task->thread.esp0 +
|
||||
register_offset[regno]);
|
||||
}
|
||||
}
|
||||
|
||||
int h8300_put_reg(struct task_struct *task, int regno, unsigned long data)
|
||||
{
|
||||
unsigned short oldccr;
|
||||
unsigned short oldexr;
|
||||
|
||||
switch (regno) {
|
||||
case PT_USP:
|
||||
task->thread.usp = data - sizeof(long)*2;
|
||||
case PT_CCR:
|
||||
oldccr = *(unsigned short *)(task->thread.esp0 +
|
||||
register_offset[regno]);
|
||||
oldccr &= ~CCR_MASK;
|
||||
data &= CCR_MASK;
|
||||
data |= oldccr;
|
||||
*(unsigned short *)(task->thread.esp0 +
|
||||
register_offset[regno]) = data;
|
||||
break;
|
||||
case PT_EXR:
|
||||
oldexr = *(unsigned short *)(task->thread.esp0 +
|
||||
register_offset[regno]);
|
||||
oldccr &= ~EXR_MASK;
|
||||
data &= EXR_MASK;
|
||||
data |= oldexr;
|
||||
*(unsigned short *)(task->thread.esp0 +
|
||||
register_offset[regno]) = data;
|
||||
break;
|
||||
default:
|
||||
*(unsigned long *)(task->thread.esp0 +
|
||||
register_offset[regno]) = data;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int regs_get(struct task_struct *target,
|
||||
const struct user_regset *regset,
|
||||
unsigned int pos, unsigned int count,
|
||||
void *kbuf, void __user *ubuf)
|
||||
{
|
||||
int r;
|
||||
struct user_regs_struct regs;
|
||||
long *reg = (long *)®s;
|
||||
|
||||
/* build user regs in buffer */
|
||||
for (r = 0; r < ARRAY_SIZE(register_offset); r++)
|
||||
*reg++ = h8300_get_reg(target, r);
|
||||
|
||||
return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
||||
®s, 0, sizeof(regs));
|
||||
}
|
||||
|
||||
static int regs_set(struct task_struct *target,
|
||||
const struct user_regset *regset,
|
||||
unsigned int pos, unsigned int count,
|
||||
const void *kbuf, const void __user *ubuf)
|
||||
{
|
||||
int r;
|
||||
int ret;
|
||||
struct user_regs_struct regs;
|
||||
long *reg;
|
||||
|
||||
/* build user regs in buffer */
|
||||
for (reg = (long *)®s, r = 0; r < ARRAY_SIZE(register_offset); r++)
|
||||
*reg++ = h8300_get_reg(target, r);
|
||||
|
||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||
®s, 0, sizeof(regs));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* write back to pt_regs */
|
||||
for (reg = (long *)®s, r = 0; r < ARRAY_SIZE(register_offset); r++)
|
||||
h8300_put_reg(target, r, *reg++);
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum h8300_regset {
|
||||
REGSET_GENERAL,
|
||||
};
|
||||
|
||||
static const struct user_regset h8300_regsets[] = {
|
||||
[REGSET_GENERAL] = {
|
||||
.core_note_type = NT_PRSTATUS,
|
||||
.n = ELF_NGREG,
|
||||
.size = sizeof(long),
|
||||
.align = sizeof(long),
|
||||
.get = regs_get,
|
||||
.set = regs_set,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct user_regset_view user_h8300_native_view = {
|
||||
.name = "h8300",
|
||||
.e_machine = EM_H8_300,
|
||||
.regsets = h8300_regsets,
|
||||
.n = ARRAY_SIZE(h8300_regsets),
|
||||
};
|
||||
|
||||
const struct user_regset_view *task_user_regset_view(struct task_struct *task)
|
||||
{
|
||||
return &user_h8300_native_view;
|
||||
}
|
||||
|
||||
void ptrace_disable(struct task_struct *child)
|
||||
{
|
||||
user_disable_single_step(child);
|
||||
}
|
||||
|
||||
long arch_ptrace(struct task_struct *child, long request,
|
||||
unsigned long addr, unsigned long data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (request) {
|
||||
default:
|
||||
ret = ptrace_request(child, request, addr, data);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
|
||||
{
|
||||
long ret = 0;
|
||||
|
||||
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
|
||||
tracehook_report_syscall_entry(regs))
|
||||
/*
|
||||
* Tracing decided this syscall should not happen.
|
||||
* We'll return a bogus call number to get an ENOSYS
|
||||
* error, but leave the original number in regs->regs[0].
|
||||
*/
|
||||
ret = -1L;
|
||||
|
||||
audit_syscall_entry(regs->er1, regs->er2, regs->er3,
|
||||
regs->er4, regs->er5);
|
||||
|
||||
return ret ?: regs->er0;
|
||||
}
|
||||
|
||||
asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
|
||||
{
|
||||
int step;
|
||||
|
||||
audit_syscall_exit(regs);
|
||||
|
||||
step = test_thread_flag(TIF_SINGLESTEP);
|
||||
if (step || test_thread_flag(TIF_SYSCALL_TRACE))
|
||||
tracehook_report_syscall_exit(regs, step);
|
||||
}
|
|
@ -0,0 +1,256 @@
|
|||
/*
|
||||
* ptrace cpu depend helper functions
|
||||
*
|
||||
* Copyright 2003, 2015 Yoshinori Sato <ysato@users.sourceforge.jp>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General
|
||||
* Public License. See the file COPYING in the main directory of
|
||||
* this archive for more details.
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/sched.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
#define BREAKINST 0x5730 /* trapa #3 */
|
||||
|
||||
/* disable singlestep */
|
||||
void user_disable_single_step(struct task_struct *child)
|
||||
{
|
||||
if ((long)child->thread.breakinfo.addr != -1L) {
|
||||
*(child->thread.breakinfo.addr) = child->thread.breakinfo.inst;
|
||||
child->thread.breakinfo.addr = (unsigned short *)-1L;
|
||||
}
|
||||
}
|
||||
|
||||
/* calculate next pc */
|
||||
enum jump_type {none, /* normal instruction */
|
||||
jabs, /* absolute address jump */
|
||||
ind, /* indirect address jump */
|
||||
ret, /* return to subrutine */
|
||||
reg, /* register indexed jump */
|
||||
relb, /* pc relative jump (byte offset) */
|
||||
relw, /* pc relative jump (word offset) */
|
||||
};
|
||||
|
||||
/* opcode decode table define
|
||||
ptn: opcode pattern
|
||||
msk: opcode bitmask
|
||||
len: instruction length (<0 next table index)
|
||||
jmp: jump operation mode */
|
||||
struct optable {
|
||||
unsigned char bitpattern;
|
||||
unsigned char bitmask;
|
||||
signed char length;
|
||||
signed char type;
|
||||
} __packed __aligned(1);
|
||||
|
||||
#define OPTABLE(ptn, msk, len, jmp) \
|
||||
{ \
|
||||
.bitpattern = ptn, \
|
||||
.bitmask = msk, \
|
||||
.length = len, \
|
||||
.type = jmp, \
|
||||
}
|
||||
|
||||
static const struct optable optable_0[] = {
|
||||
OPTABLE(0x00, 0xff, 1, none), /* 0x00 */
|
||||
OPTABLE(0x01, 0xff, -1, none), /* 0x01 */
|
||||
OPTABLE(0x02, 0xfe, 1, none), /* 0x02-0x03 */
|
||||
OPTABLE(0x04, 0xee, 1, none), /* 0x04-0x05/0x14-0x15 */
|
||||
OPTABLE(0x06, 0xfe, 1, none), /* 0x06-0x07 */
|
||||
OPTABLE(0x08, 0xea, 1, none), /* 0x08-0x09/0x0c-0x0d/0x18-0x19/0x1c-0x1d */
|
||||
OPTABLE(0x0a, 0xee, 1, none), /* 0x0a-0x0b/0x1a-0x1b */
|
||||
OPTABLE(0x0e, 0xee, 1, none), /* 0x0e-0x0f/0x1e-0x1f */
|
||||
OPTABLE(0x10, 0xfc, 1, none), /* 0x10-0x13 */
|
||||
OPTABLE(0x16, 0xfe, 1, none), /* 0x16-0x17 */
|
||||
OPTABLE(0x20, 0xe0, 1, none), /* 0x20-0x3f */
|
||||
OPTABLE(0x40, 0xf0, 1, relb), /* 0x40-0x4f */
|
||||
OPTABLE(0x50, 0xfc, 1, none), /* 0x50-0x53 */
|
||||
OPTABLE(0x54, 0xfd, 1, ret), /* 0x54/0x56 */
|
||||
OPTABLE(0x55, 0xff, 1, relb), /* 0x55 */
|
||||
OPTABLE(0x57, 0xff, 1, none), /* 0x57 */
|
||||
OPTABLE(0x58, 0xfb, 2, relw), /* 0x58/0x5c */
|
||||
OPTABLE(0x59, 0xfb, 1, reg), /* 0x59/0x5b */
|
||||
OPTABLE(0x5a, 0xfb, 2, jabs), /* 0x5a/0x5e */
|
||||
OPTABLE(0x5b, 0xfb, 2, ind), /* 0x5b/0x5f */
|
||||
OPTABLE(0x60, 0xe8, 1, none), /* 0x60-0x67/0x70-0x77 */
|
||||
OPTABLE(0x68, 0xfa, 1, none), /* 0x68-0x69/0x6c-0x6d */
|
||||
OPTABLE(0x6a, 0xfe, -2, none), /* 0x6a-0x6b */
|
||||
OPTABLE(0x6e, 0xfe, 2, none), /* 0x6e-0x6f */
|
||||
OPTABLE(0x78, 0xff, 4, none), /* 0x78 */
|
||||
OPTABLE(0x79, 0xff, 2, none), /* 0x79 */
|
||||
OPTABLE(0x7a, 0xff, 3, none), /* 0x7a */
|
||||
OPTABLE(0x7b, 0xff, 2, none), /* 0x7b */
|
||||
OPTABLE(0x7c, 0xfc, 2, none), /* 0x7c-0x7f */
|
||||
OPTABLE(0x80, 0x80, 1, none), /* 0x80-0xff */
|
||||
};
|
||||
|
||||
static const struct optable optable_1[] = {
|
||||
OPTABLE(0x00, 0xff, -3, none), /* 0x0100 */
|
||||
OPTABLE(0x40, 0xf0, -3, none), /* 0x0140-0x14f */
|
||||
OPTABLE(0x80, 0xf0, 1, none), /* 0x0180-0x018f */
|
||||
OPTABLE(0xc0, 0xc0, 2, none), /* 0x01c0-0x01ff */
|
||||
};
|
||||
|
||||
static const struct optable optable_2[] = {
|
||||
OPTABLE(0x00, 0x20, 2, none), /* 0x6a0?/0x6a8?/0x6b0?/0x6b8? */
|
||||
OPTABLE(0x20, 0x20, 3, none), /* 0x6a2?/0x6aa?/0x6b2?/0x6ba? */
|
||||
};
|
||||
|
||||
static const struct optable optable_3[] = {
|
||||
OPTABLE(0x69, 0xfb, 2, none), /* 0x010069/0x01006d/014069/0x01406d */
|
||||
OPTABLE(0x6b, 0xff, -4, none), /* 0x01006b/0x01406b */
|
||||
OPTABLE(0x6f, 0xff, 3, none), /* 0x01006f/0x01406f */
|
||||
OPTABLE(0x78, 0xff, 5, none), /* 0x010078/0x014078 */
|
||||
};
|
||||
|
||||
static const struct optable optable_4[] = {
|
||||
/* 0x0100690?/0x01006d0?/0140690?/0x01406d0?/
|
||||
0x0100698?/0x01006d8?/0140698?/0x01406d8? */
|
||||
OPTABLE(0x00, 0x78, 3, none),
|
||||
/* 0x0100692?/0x01006d2?/0140692?/0x01406d2?/
|
||||
0x010069a?/0x01006da?/014069a?/0x01406da? */
|
||||
OPTABLE(0x20, 0x78, 4, none),
|
||||
};
|
||||
|
||||
static const struct optables_list {
|
||||
const struct optable *ptr;
|
||||
int size;
|
||||
} optables[] = {
|
||||
#define OPTABLES(no) \
|
||||
{ \
|
||||
.ptr = optable_##no, \
|
||||
.size = sizeof(optable_##no) / sizeof(struct optable), \
|
||||
}
|
||||
OPTABLES(0),
|
||||
OPTABLES(1),
|
||||
OPTABLES(2),
|
||||
OPTABLES(3),
|
||||
OPTABLES(4),
|
||||
|
||||
};
|
||||
|
||||
const unsigned char condmask[] = {
|
||||
0x00, 0x40, 0x01, 0x04, 0x02, 0x08, 0x10, 0x20
|
||||
};
|
||||
|
||||
static int isbranch(struct task_struct *task, int reson)
|
||||
{
|
||||
unsigned char cond = h8300_get_reg(task, PT_CCR);
|
||||
|
||||
/* encode complex conditions */
|
||||
/* B4: N^V
|
||||
B5: Z|(N^V)
|
||||
B6: C|Z */
|
||||
__asm__("bld #3,%w0\n\t"
|
||||
"bxor #1,%w0\n\t"
|
||||
"bst #4,%w0\n\t"
|
||||
"bor #2,%w0\n\t"
|
||||
"bst #5,%w0\n\t"
|
||||
"bld #2,%w0\n\t"
|
||||
"bor #0,%w0\n\t"
|
||||
"bst #6,%w0\n\t"
|
||||
: "=&r"(cond) : "0"(cond) : "cc");
|
||||
cond &= condmask[reson >> 1];
|
||||
if (!(reson & 1))
|
||||
return cond == 0;
|
||||
else
|
||||
return cond != 0;
|
||||
}
|
||||
|
||||
static unsigned short *decode(struct task_struct *child,
|
||||
const struct optable *op,
|
||||
char *fetch_p, unsigned short *pc,
|
||||
unsigned char inst)
|
||||
{
|
||||
unsigned long addr;
|
||||
unsigned long *sp;
|
||||
int regno;
|
||||
|
||||
switch (op->type) {
|
||||
case none:
|
||||
return (unsigned short *)pc + op->length;
|
||||
case jabs:
|
||||
addr = *(unsigned long *)pc;
|
||||
return (unsigned short *)(addr & 0x00ffffff);
|
||||
case ind:
|
||||
addr = *pc & 0xff;
|
||||
return (unsigned short *)(*(unsigned long *)addr);
|
||||
case ret:
|
||||
sp = (unsigned long *)h8300_get_reg(child, PT_USP);
|
||||
/* user stack frames
|
||||
| er0 | temporary saved
|
||||
+--------+
|
||||
| exp | exception stack frames
|
||||
+--------+
|
||||
| ret pc | userspace return address
|
||||
*/
|
||||
return (unsigned short *)(*(sp+2) & 0x00ffffff);
|
||||
case reg:
|
||||
regno = (*pc >> 4) & 0x07;
|
||||
if (regno == 0)
|
||||
addr = h8300_get_reg(child, PT_ER0);
|
||||
else
|
||||
addr = h8300_get_reg(child, regno-1 + PT_ER1);
|
||||
return (unsigned short *)addr;
|
||||
case relb:
|
||||
if (inst == 0x55 || isbranch(child, inst & 0x0f))
|
||||
pc = (unsigned short *)((unsigned long)pc +
|
||||
((signed char)(*fetch_p)));
|
||||
return pc+1; /* skip myself */
|
||||
case relw:
|
||||
if (inst == 0x5c || isbranch(child, (*fetch_p & 0xf0) >> 4))
|
||||
pc = (unsigned short *)((unsigned long)pc +
|
||||
((signed short)(*(pc+1))));
|
||||
return pc+2; /* skip myself */
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned short *nextpc(struct task_struct *child, unsigned short *pc)
|
||||
{
|
||||
const struct optable *op;
|
||||
unsigned char *fetch_p;
|
||||
int op_len;
|
||||
unsigned char inst;
|
||||
|
||||
op = optables[0].ptr;
|
||||
op_len = optables[0].size;
|
||||
fetch_p = (unsigned char *)pc;
|
||||
inst = *fetch_p++;
|
||||
do {
|
||||
if ((inst & op->bitmask) == op->bitpattern) {
|
||||
if (op->length < 0) {
|
||||
op = optables[-op->length].ptr;
|
||||
op_len = optables[-op->length].size + 1;
|
||||
inst = *fetch_p++;
|
||||
} else
|
||||
return decode(child, op, fetch_p, pc, inst);
|
||||
} else
|
||||
op++;
|
||||
} while (--op_len > 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Set breakpoint(s) to simulate a single step from the current PC. */
|
||||
|
||||
void user_enable_single_step(struct task_struct *child)
|
||||
{
|
||||
unsigned short *next;
|
||||
|
||||
next = nextpc(child, (unsigned short *)h8300_get_reg(child, PT_PC));
|
||||
child->thread.breakinfo.addr = next;
|
||||
child->thread.breakinfo.inst = *next;
|
||||
*next = BREAKINST;
|
||||
}
|
||||
|
||||
asmlinkage void trace_trap(unsigned long bp)
|
||||
{
|
||||
if ((unsigned long)current->thread.breakinfo.addr == bp) {
|
||||
user_disable_single_step(current);
|
||||
force_sig(SIGTRAP, current);
|
||||
} else
|
||||
force_sig(SIGILL, current);
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* linux/arch/h8300/kernel/ptrace_h8s.c
|
||||
* ptrace cpu depend helper functions
|
||||
*
|
||||
* Yoshinori Sato <ysato@users.sourceforge.jp>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General
|
||||
* Public License. See the file COPYING in the main directory of
|
||||
* this archive for more details.
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
#define CCR_MASK 0x6f
|
||||
#define EXR_TRACE 0x80
|
||||
|
||||
/* disable singlestep */
|
||||
void user_disable_single_step(struct task_struct *child)
|
||||
{
|
||||
unsigned char exr;
|
||||
|
||||
exr = h8300_get_reg(child, PT_EXR);
|
||||
exr &= ~EXR_TRACE;
|
||||
h8300_put_reg(child, PT_EXR, exr);
|
||||
}
|
||||
|
||||
/* enable singlestep */
|
||||
void user_enable_single_step(struct task_struct *child)
|
||||
{
|
||||
unsigned char exr;
|
||||
|
||||
exr = h8300_get_reg(child, PT_EXR);
|
||||
exr |= EXR_TRACE;
|
||||
h8300_put_reg(child, PT_EXR, exr);
|
||||
}
|
||||
|
||||
asmlinkage void trace_trap(unsigned long bp)
|
||||
{
|
||||
(void)bp;
|
||||
force_sig(SIGTRAP, current);
|
||||
}
|
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
* linux/arch/h8300/kernel/setup.c
|
||||
*
|
||||
* Copyright (C) 2001-2014 Yoshinori Sato <ysato@users.sourceforge.jp>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file handles the architecture-dependent parts of system setup
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/screen_info.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
#if defined(CONFIG_CPU_H8300H)
|
||||
#define CPU "H8/300H"
|
||||
#elif defined(CONFIG_CPU_H8S)
|
||||
#define CPU "H8S"
|
||||
#else
|
||||
#define CPU "Unknown"
|
||||
#endif
|
||||
|
||||
unsigned long memory_start;
|
||||
unsigned long memory_end;
|
||||
EXPORT_SYMBOL(memory_end);
|
||||
static unsigned long freq;
|
||||
extern char __dtb_start[];
|
||||
|
||||
#ifdef CONFIG_VT
|
||||
struct screen_info screen_info;
|
||||
#endif
|
||||
|
||||
char __initdata command_line[COMMAND_LINE_SIZE];
|
||||
|
||||
void sim_console_register(void);
|
||||
|
||||
void __init h8300_fdt_init(void *fdt, char *bootargs)
|
||||
{
|
||||
if (!fdt)
|
||||
fdt = __dtb_start;
|
||||
else
|
||||
strcpy(command_line, bootargs);
|
||||
|
||||
early_init_dt_scan(fdt);
|
||||
memblock_allow_resize();
|
||||
}
|
||||
|
||||
static void __init bootmem_init(void)
|
||||
{
|
||||
int bootmap_size;
|
||||
unsigned long ram_start_pfn;
|
||||
unsigned long free_ram_start_pfn;
|
||||
unsigned long ram_end_pfn;
|
||||
struct memblock_region *region;
|
||||
|
||||
memory_end = memory_start = 0;
|
||||
|
||||
/* Find main memory where is the kernel */
|
||||
for_each_memblock(memory, region) {
|
||||
memory_start = region->base;
|
||||
memory_end = region->base + region->size;
|
||||
}
|
||||
|
||||
if (!memory_end)
|
||||
panic("No memory!");
|
||||
|
||||
ram_start_pfn = PFN_UP(memory_start);
|
||||
/* free_ram_start_pfn is first page after kernel */
|
||||
free_ram_start_pfn = PFN_UP(__pa(_end));
|
||||
ram_end_pfn = PFN_DOWN(memblock_end_of_DRAM());
|
||||
|
||||
max_pfn = ram_end_pfn;
|
||||
|
||||
/*
|
||||
* give all the memory to the bootmap allocator, tell it to put the
|
||||
* boot mem_map at the start of memory
|
||||
*/
|
||||
bootmap_size = init_bootmem_node(NODE_DATA(0),
|
||||
free_ram_start_pfn,
|
||||
0,
|
||||
ram_end_pfn);
|
||||
/*
|
||||
* free the usable memory, we have to make sure we do not free
|
||||
* the bootmem bitmap so we then reserve it after freeing it :-)
|
||||
*/
|
||||
free_bootmem(PFN_PHYS(free_ram_start_pfn),
|
||||
(ram_end_pfn - free_ram_start_pfn) << PAGE_SHIFT);
|
||||
reserve_bootmem(PFN_PHYS(free_ram_start_pfn), bootmap_size,
|
||||
BOOTMEM_DEFAULT);
|
||||
|
||||
for_each_memblock(reserved, region) {
|
||||
reserve_bootmem(region->base, region->size, BOOTMEM_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
void __init setup_arch(char **cmdline_p)
|
||||
{
|
||||
unflatten_and_copy_device_tree();
|
||||
|
||||
init_mm.start_code = (unsigned long) _stext;
|
||||
init_mm.end_code = (unsigned long) _etext;
|
||||
init_mm.end_data = (unsigned long) _edata;
|
||||
init_mm.brk = (unsigned long) 0;
|
||||
|
||||
pr_notice("\r\n\nuClinux " CPU "\n");
|
||||
pr_notice("Flat model support (C) 1998,1999 Kenneth Albanowski, D. Jeff Dionne\n");
|
||||
|
||||
if (*command_line)
|
||||
strcpy(boot_command_line, command_line);
|
||||
*cmdline_p = boot_command_line;
|
||||
|
||||
parse_early_param();
|
||||
|
||||
bootmem_init();
|
||||
#if defined(CONFIG_H8300H_SIM) || defined(CONFIG_H8S_SIM)
|
||||
sim_console_register();
|
||||
#endif
|
||||
|
||||
early_platform_driver_probe("earlyprintk", 1, 0);
|
||||
/*
|
||||
* get kmalloc into gear
|
||||
*/
|
||||
paging_init();
|
||||
}
|
||||
|
||||
/*
|
||||
* Get CPU information for use by the procfs.
|
||||
*/
|
||||
|
||||
static int show_cpuinfo(struct seq_file *m, void *v)
|
||||
{
|
||||
char *cpu;
|
||||
|
||||
cpu = CPU;
|
||||
|
||||
seq_printf(m, "CPU:\t\t%s\n"
|
||||
"Clock:\t\t%lu.%1luMHz\n"
|
||||
"BogoMips:\t%lu.%02lu\n"
|
||||
"Calibration:\t%lu loops\n",
|
||||
cpu,
|
||||
freq/1000, freq%1000,
|
||||
(loops_per_jiffy*HZ)/500000,
|
||||
((loops_per_jiffy*HZ)/5000)%100,
|
||||
(loops_per_jiffy*HZ));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *c_start(struct seq_file *m, loff_t *pos)
|
||||
{
|
||||
return *pos < num_possible_cpus() ?
|
||||
((void *) 0x12345678) : NULL;
|
||||
}
|
||||
|
||||
static void *c_next(struct seq_file *m, void *v, loff_t *pos)
|
||||
{
|
||||
++*pos;
|
||||
return c_start(m, pos);
|
||||
}
|
||||
|
||||
static void c_stop(struct seq_file *m, void *v)
|
||||
{
|
||||
}
|
||||
|
||||
const struct seq_operations cpuinfo_op = {
|
||||
.start = c_start,
|
||||
.next = c_next,
|
||||
.stop = c_stop,
|
||||
.show = show_cpuinfo,
|
||||
};
|
||||
|
||||
static int __init device_probe(void)
|
||||
{
|
||||
of_platform_populate(NULL, NULL, NULL, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
device_initcall(device_probe);
|
||||
|
||||
#if defined(CONFIG_CPU_H8300H)
|
||||
#define get_wait(base, addr) ({ \
|
||||
int baddr; \
|
||||
baddr = ((addr) / 0x200000 * 2); \
|
||||
w *= (ctrl_inw((unsigned long)(base) + 2) & (3 << baddr)) + 1; \
|
||||
})
|
||||
#endif
|
||||
#if defined(CONFIG_CPU_H8S)
|
||||
#define get_wait(base, addr) ({ \
|
||||
int baddr; \
|
||||
baddr = ((addr) / 0x200000 * 16); \
|
||||
w *= (ctrl_inl((unsigned long)(base) + 2) & (7 << baddr)) + 1; \
|
||||
})
|
||||
#endif
|
||||
|
||||
static __init int access_timing(void)
|
||||
{
|
||||
struct device_node *bsc;
|
||||
void __iomem *base;
|
||||
unsigned long addr = (unsigned long)&__delay;
|
||||
int bit = 1 << (addr / 0x200000);
|
||||
int w;
|
||||
|
||||
bsc = of_find_compatible_node(NULL, NULL, "renesas,h8300-bsc");
|
||||
base = of_iomap(bsc, 0);
|
||||
w = (ctrl_inb((unsigned long)base + 0) & bit)?2:1;
|
||||
if (ctrl_inb((unsigned long)base + 1) & bit)
|
||||
w *= get_wait(base, addr);
|
||||
else
|
||||
w *= 2;
|
||||
return w * 3 / 2;
|
||||
}
|
||||
|
||||
void __init calibrate_delay(void)
|
||||
{
|
||||
struct device_node *cpu;
|
||||
int freq;
|
||||
|
||||
cpu = of_find_compatible_node(NULL, NULL, "renesas,h8300");
|
||||
of_property_read_s32(cpu, "clock-frequency", &freq);
|
||||
loops_per_jiffy = freq / HZ / (access_timing() * 2);
|
||||
pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n",
|
||||
loops_per_jiffy / (500000 / HZ),
|
||||
(loops_per_jiffy / (5000 / HZ)) % 100, loops_per_jiffy);
|
||||
}
|
||||
|
||||
|
||||
void __init time_init(void)
|
||||
{
|
||||
of_clk_init(NULL);
|
||||
}
|
|
@ -0,0 +1,289 @@
|
|||
/*
|
||||
* linux/arch/h8300/kernel/signal.c
|
||||
*
|
||||
* Copyright (C) 1991, 1992 Linus Torvalds
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* uClinux H8/300 support by Yoshinori Sato <ysato@users.sourceforge.jp>
|
||||
* and David McCullough <davidm@snapgear.com>
|
||||
*
|
||||
* Based on
|
||||
* Linux/m68k by Hamish Macdonald
|
||||
*/
|
||||
|
||||
/*
|
||||
* ++roman (07/09/96): implemented signal stacks (specially for tosemu on
|
||||
* Atari :-) Current limitation: Only one sigstack can be active at one time.
|
||||
* If a second signal with SA_ONSTACK set arrives while working on a sigstack,
|
||||
* SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
|
||||
* signal handlers!
|
||||
*/
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/highuid.h>
|
||||
#include <linux/personality.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/binfmts.h>
|
||||
#include <linux/tracehook.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/traps.h>
|
||||
#include <asm/ucontext.h>
|
||||
|
||||
/*
|
||||
* Do a signal return; undo the signal stack.
|
||||
*
|
||||
* Keep the return code on the stack quadword aligned!
|
||||
* That makes the cache flush below easier.
|
||||
*/
|
||||
|
||||
struct rt_sigframe {
|
||||
long dummy_er0;
|
||||
long dummy_vector;
|
||||
#if defined(CONFIG_CPU_H8S)
|
||||
short dummy_exr;
|
||||
#endif
|
||||
long dummy_pc;
|
||||
char *pretcode;
|
||||
struct siginfo *pinfo;
|
||||
void *puc;
|
||||
unsigned char retcode[8];
|
||||
struct siginfo info;
|
||||
struct ucontext uc;
|
||||
int sig;
|
||||
} __packed __aligned(2);
|
||||
|
||||
static inline int
|
||||
restore_sigcontext(struct sigcontext *usc, int *pd0)
|
||||
{
|
||||
struct pt_regs *regs = current_pt_regs();
|
||||
int err = 0;
|
||||
unsigned int ccr;
|
||||
unsigned int usp;
|
||||
unsigned int er0;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
/* restore passed registers */
|
||||
#define COPY(r) do { err |= get_user(regs->r, &usc->sc_##r); } while (0)
|
||||
COPY(er1);
|
||||
COPY(er2);
|
||||
COPY(er3);
|
||||
COPY(er5);
|
||||
COPY(pc);
|
||||
ccr = regs->ccr & 0x10;
|
||||
COPY(ccr);
|
||||
#undef COPY
|
||||
regs->ccr &= 0xef;
|
||||
regs->ccr |= ccr;
|
||||
regs->orig_er0 = -1; /* disable syscall checks */
|
||||
err |= __get_user(usp, &usc->sc_usp);
|
||||
wrusp(usp);
|
||||
|
||||
err |= __get_user(er0, &usc->sc_er0);
|
||||
*pd0 = er0;
|
||||
return err;
|
||||
}
|
||||
|
||||
asmlinkage int sys_rt_sigreturn(void)
|
||||
{
|
||||
unsigned long usp = rdusp();
|
||||
struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4);
|
||||
sigset_t set;
|
||||
int er0;
|
||||
|
||||
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
|
||||
goto badframe;
|
||||
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
|
||||
goto badframe;
|
||||
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(&frame->uc.uc_mcontext, &er0))
|
||||
goto badframe;
|
||||
|
||||
if (restore_altstack(&frame->uc.uc_stack))
|
||||
goto badframe;
|
||||
|
||||
return er0;
|
||||
|
||||
badframe:
|
||||
force_sig(SIGSEGV, current);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
|
||||
unsigned long mask)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
err |= __put_user(regs->er0, &sc->sc_er0);
|
||||
err |= __put_user(regs->er1, &sc->sc_er1);
|
||||
err |= __put_user(regs->er2, &sc->sc_er2);
|
||||
err |= __put_user(regs->er3, &sc->sc_er3);
|
||||
err |= __put_user(regs->er4, &sc->sc_er4);
|
||||
err |= __put_user(regs->er5, &sc->sc_er5);
|
||||
err |= __put_user(regs->er6, &sc->sc_er6);
|
||||
err |= __put_user(rdusp(), &sc->sc_usp);
|
||||
err |= __put_user(regs->pc, &sc->sc_pc);
|
||||
err |= __put_user(regs->ccr, &sc->sc_ccr);
|
||||
err |= __put_user(mask, &sc->sc_mask);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline void __user *
|
||||
get_sigframe(struct ksignal *ksig, struct pt_regs *regs, size_t frame_size)
|
||||
{
|
||||
return (void __user *)((sigsp(rdusp(), ksig) - frame_size) & -8UL);
|
||||
}
|
||||
|
||||
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct rt_sigframe *frame;
|
||||
int err = 0;
|
||||
unsigned char *ret;
|
||||
|
||||
frame = get_sigframe(ksig, regs, sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
return -EFAULT;
|
||||
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
|
||||
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
|
||||
|
||||
/* Create the ucontext. */
|
||||
err |= __put_user(0, &frame->uc.uc_flags);
|
||||
err |= __put_user(0, &frame->uc.uc_link);
|
||||
err |= __save_altstack(&frame->uc.uc_stack, rdusp());
|
||||
err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]);
|
||||
err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
|
||||
if (err)
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up to return from userspace. */
|
||||
ret = frame->retcode;
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER)
|
||||
ret = (unsigned char *)(ksig->ka.sa.sa_restorer);
|
||||
else {
|
||||
/* sub.l er0,er0; mov.b #__NR_rt_sigreturn,r0l; trapa #0 */
|
||||
err |= __put_user(0x1a80f800 + (__NR_rt_sigreturn & 0xff),
|
||||
(unsigned long *)(frame->retcode + 0));
|
||||
err |= __put_user(0x5700,
|
||||
(unsigned short *)(frame->retcode + 4));
|
||||
}
|
||||
err |= __put_user(ret, &frame->pretcode);
|
||||
|
||||
if (err)
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up registers for signal handler */
|
||||
wrusp((unsigned long) frame);
|
||||
regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
regs->er0 = ksig->sig;
|
||||
regs->er1 = (unsigned long)&(frame->info);
|
||||
regs->er2 = (unsigned long)&frame->uc;
|
||||
regs->er5 = current->mm->start_data; /* GOT base */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_restart(struct pt_regs *regs, struct k_sigaction *ka)
|
||||
{
|
||||
switch (regs->er0) {
|
||||
case -ERESTARTNOHAND:
|
||||
if (!ka)
|
||||
goto do_restart;
|
||||
regs->er0 = -EINTR;
|
||||
break;
|
||||
case -ERESTART_RESTARTBLOCK:
|
||||
if (!ka) {
|
||||
regs->er0 = __NR_restart_syscall;
|
||||
regs->pc -= 2;
|
||||
} else
|
||||
regs->er0 = -EINTR;
|
||||
break;
|
||||
case -ERESTARTSYS:
|
||||
if (!(ka->sa.sa_flags & SA_RESTART)) {
|
||||
regs->er0 = -EINTR;
|
||||
break;
|
||||
}
|
||||
/* fallthrough */
|
||||
case -ERESTARTNOINTR:
|
||||
do_restart:
|
||||
regs->er0 = regs->orig_er0;
|
||||
regs->pc -= 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* OK, we're invoking a handler
|
||||
*/
|
||||
static void
|
||||
handle_signal(struct ksignal *ksig, struct pt_regs *regs)
|
||||
{
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
int ret;
|
||||
/* are we from a system call? */
|
||||
if (regs->orig_er0 >= 0)
|
||||
handle_restart(regs, &ksig->ka);
|
||||
|
||||
ret = setup_rt_frame(ksig, oldset, regs);
|
||||
|
||||
signal_setup_done(ret, ksig, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that 'init' is a special process: it doesn't get signals it doesn't
|
||||
* want to handle. Thus you cannot kill init even with a SIGKILL even by
|
||||
* mistake.
|
||||
*/
|
||||
static void do_signal(struct pt_regs *regs)
|
||||
{
|
||||
struct ksignal ksig;
|
||||
|
||||
current->thread.esp0 = (unsigned long) regs;
|
||||
|
||||
if (get_signal(&ksig)) {
|
||||
/* Whee! Actually deliver the signal. */
|
||||
handle_signal(&ksig, regs);
|
||||
return;
|
||||
}
|
||||
/* Did we come from a system call? */
|
||||
if (regs->orig_er0 >= 0)
|
||||
handle_restart(regs, NULL);
|
||||
|
||||
/* If there's no signal to deliver, we just restore the saved mask. */
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
|
||||
{
|
||||
if (thread_info_flags & _TIF_SIGPENDING)
|
||||
do_signal(regs);
|
||||
|
||||
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
|
||||
clear_thread_flag(TIF_NOTIFY_RESUME);
|
||||
tracehook_notify_resume(regs);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* arch/h8300/kernel/early_printk.c
|
||||
*
|
||||
* Copyright (C) 2009 Yoshinori Sato <ysato@users.sourceforge.jp>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
#include <linux/console.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
static void sim_write(struct console *co, const char *ptr,
|
||||
unsigned len)
|
||||
{
|
||||
register const int fd __asm__("er0") = 1; /* stdout */
|
||||
register const char *_ptr __asm__("er1") = ptr;
|
||||
register const unsigned _len __asm__("er2") = len;
|
||||
|
||||
__asm__(".byte 0x5e,0x00,0x00,0xc7\n\t" /* jsr @0xc7 (sys_write) */
|
||||
: : "g"(fd), "g"(_ptr), "g"(_len));
|
||||
}
|
||||
|
||||
static struct console sim_console = {
|
||||
.name = "sim_console",
|
||||
.write = sim_write,
|
||||
.setup = NULL,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = -1,
|
||||
};
|
||||
|
||||
static char sim_console_buf[32];
|
||||
|
||||
static int sim_probe(struct platform_device *pdev)
|
||||
{
|
||||
if (sim_console.data)
|
||||
return -EEXIST;
|
||||
|
||||
if (!strstr(sim_console_buf, "keep"))
|
||||
sim_console.flags |= CON_BOOT;
|
||||
|
||||
register_console(&sim_console);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sim_remove(struct platform_device *pdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver sim_driver = {
|
||||
.probe = sim_probe,
|
||||
.remove = sim_remove,
|
||||
.driver = {
|
||||
.name = "h8300-sim",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
early_platform_init_buffer("earlyprintk", &sim_driver,
|
||||
sim_console_buf, ARRAY_SIZE(sim_console_buf));
|
||||
|
||||
static struct platform_device sim_console_device = {
|
||||
.name = "h8300-sim",
|
||||
.id = 0,
|
||||
};
|
||||
|
||||
static struct platform_device *devices[] __initdata = {
|
||||
&sim_console_device,
|
||||
};
|
||||
|
||||
void __init sim_console_register(void)
|
||||
{
|
||||
early_platform_add_devices(devices,
|
||||
ARRAY_SIZE(devices));
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#include <linux/syscalls.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/unistd.h>
|
||||
|
||||
#undef __SYSCALL
|
||||
#define __SYSCALL(nr, call) [nr] = (call),
|
||||
|
||||
#define sys_mmap2 sys_mmap_pgoff
|
||||
|
||||
asmlinkage int sys_rt_sigreturn(void);
|
||||
|
||||
void *_sys_call_table[__NR_syscalls] = {
|
||||
#include <asm/unistd.h>
|
||||
};
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* linux/arch/h8300/boot/traps.c -- general exception handling code
|
||||
* H8/300 support Yoshinori Sato <ysato@users.sourceforge.jp>
|
||||
*
|
||||
* Cloned from Linux/m68k.
|
||||
*
|
||||
* No original Copyright holder listed,
|
||||
* Probable original (C) Roman Zippel (assigned DJD, 1999)
|
||||
*
|
||||
* Copyright 1999-2000 D. Jeff Dionne, <jeff@rt-control.com>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file COPYING in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/bug.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <asm/traps.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
static DEFINE_SPINLOCK(die_lock);
|
||||
|
||||
/*
|
||||
* this must be called very early as the kernel might
|
||||
* use some instruction that are emulated on the 060
|
||||
*/
|
||||
|
||||
void __init base_trap_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void __init trap_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
asmlinkage void set_esp0(unsigned long ssp)
|
||||
{
|
||||
current->thread.esp0 = ssp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic dumping code. Used for panic and debug.
|
||||
*/
|
||||
|
||||
static void dump(struct pt_regs *fp)
|
||||
{
|
||||
unsigned long *sp;
|
||||
unsigned char *tp;
|
||||
int i;
|
||||
|
||||
pr_info("\nCURRENT PROCESS:\n\n");
|
||||
pr_info("COMM=%s PID=%d\n", current->comm, current->pid);
|
||||
if (current->mm) {
|
||||
pr_info("TEXT=%08x-%08x DATA=%08x-%08x BSS=%08x-%08x\n",
|
||||
(int) current->mm->start_code,
|
||||
(int) current->mm->end_code,
|
||||
(int) current->mm->start_data,
|
||||
(int) current->mm->end_data,
|
||||
(int) current->mm->end_data,
|
||||
(int) current->mm->brk);
|
||||
pr_info("USER-STACK=%08x KERNEL-STACK=%08lx\n\n",
|
||||
(int) current->mm->start_stack,
|
||||
(int) PAGE_SIZE+(unsigned long)current);
|
||||
}
|
||||
|
||||
show_regs(fp);
|
||||
pr_info("\nCODE:");
|
||||
tp = ((unsigned char *) fp->pc) - 0x20;
|
||||
for (sp = (unsigned long *) tp, i = 0; (i < 0x40); i += 4) {
|
||||
if ((i % 0x10) == 0)
|
||||
pr_info("\n%08x: ", (int) (tp + i));
|
||||
pr_info("%08x ", (int) *sp++);
|
||||
}
|
||||
pr_info("\n");
|
||||
|
||||
pr_info("\nKERNEL STACK:");
|
||||
tp = ((unsigned char *) fp) - 0x40;
|
||||
for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) {
|
||||
if ((i % 0x10) == 0)
|
||||
pr_info("\n%08x: ", (int) (tp + i));
|
||||
pr_info("%08x ", (int) *sp++);
|
||||
}
|
||||
pr_info("\n");
|
||||
if (STACK_MAGIC != *(unsigned long *)((unsigned long)current+PAGE_SIZE))
|
||||
pr_info("(Possibly corrupted stack page??)\n");
|
||||
|
||||
pr_info("\n\n");
|
||||
}
|
||||
|
||||
void die(const char *str, struct pt_regs *fp, unsigned long err)
|
||||
{
|
||||
static int diecount;
|
||||
|
||||
oops_enter();
|
||||
|
||||
console_verbose();
|
||||
spin_lock_irq(&die_lock);
|
||||
report_bug(fp->pc, fp);
|
||||
pr_crit("%s: %04lx [#%d] ", str, err & 0xffff, ++diecount);
|
||||
dump(fp);
|
||||
|
||||
spin_unlock_irq(&die_lock);
|
||||
do_exit(SIGSEGV);
|
||||
}
|
||||
|
||||
static int kstack_depth_to_print = 24;
|
||||
|
||||
void show_stack(struct task_struct *task, unsigned long *esp)
|
||||
{
|
||||
unsigned long *stack, addr;
|
||||
int i;
|
||||
|
||||
if (esp == NULL)
|
||||
esp = (unsigned long *) &esp;
|
||||
|
||||
stack = esp;
|
||||
|
||||
pr_info("Stack from %08lx:", (unsigned long)stack);
|
||||
for (i = 0; i < kstack_depth_to_print; i++) {
|
||||
if (((unsigned long)stack & (THREAD_SIZE - 1)) == 0)
|
||||
break;
|
||||
if (i % 8 == 0)
|
||||
pr_info("\n ");
|
||||
pr_info(" %08lx", *stack++);
|
||||
}
|
||||
|
||||
pr_info("\nCall Trace:");
|
||||
i = 0;
|
||||
stack = esp;
|
||||
while (((unsigned long)stack & (THREAD_SIZE - 1)) != 0) {
|
||||
addr = *stack++;
|
||||
/*
|
||||
* If the address is either in the text segment of the
|
||||
* kernel, or in the region which contains vmalloc'ed
|
||||
* memory, it *may* be the address of a calling
|
||||
* routine; if so, print it so that someone tracing
|
||||
* down the cause of the crash will be able to figure
|
||||
* out the call path that was taken.
|
||||
*/
|
||||
if (check_kernel_text(addr)) {
|
||||
if (i % 4 == 0)
|
||||
pr_info("\n ");
|
||||
pr_info(" [<%08lx>]", addr);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
pr_info("\n");
|
||||
}
|
||||
|
||||
void show_trace_task(struct task_struct *tsk)
|
||||
{
|
||||
show_stack(tsk, (unsigned long *)tsk->thread.esp0);
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
#include <asm-generic/vmlinux.lds.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
#define ROMTOP 0x000000
|
||||
#define RAMTOP 0x400000
|
||||
|
||||
jiffies = jiffies_64 + 4;
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
#if defined(CONFIG_ROMKERNEL)
|
||||
. = ROMTOP;
|
||||
.vectors :
|
||||
{
|
||||
_vector = . ;
|
||||
*(.vector*)
|
||||
}
|
||||
#else
|
||||
. = RAMTOP;
|
||||
_ramstart = .;
|
||||
. = . + CONFIG_OFFSET;
|
||||
#endif
|
||||
_text = .;
|
||||
HEAD_TEXT_SECTION
|
||||
.text : {
|
||||
_stext = . ;
|
||||
TEXT_TEXT
|
||||
SCHED_TEXT
|
||||
LOCK_TEXT
|
||||
#if defined(CONFIG_ROMKERNEL)
|
||||
*(.int_redirect)
|
||||
#endif
|
||||
_etext = . ;
|
||||
}
|
||||
EXCEPTION_TABLE(16)
|
||||
NOTES
|
||||
RO_DATA_SECTION(4)
|
||||
ROMEND = .;
|
||||
#if defined(CONFIG_ROMKERNEL)
|
||||
. = RAMTOP;
|
||||
_ramstart = .;
|
||||
#define ADDR(x) ROMEND
|
||||
#else
|
||||
#endif
|
||||
_sdata = . ;
|
||||
__data_start = . ;
|
||||
RW_DATA_SECTION(0,0,0)
|
||||
#if defined(CONFIG_ROMKERNEL)
|
||||
#undef ADDR
|
||||
#endif
|
||||
. = ALIGN(0x4) ;
|
||||
__init_begin = .;
|
||||
INIT_TEXT_SECTION(4)
|
||||
INIT_DATA_SECTION(4)
|
||||
SECURITY_INIT
|
||||
__init_end = .;
|
||||
_edata = . ;
|
||||
_begin_data = LOADADDR(.data);
|
||||
_sbss =.;
|
||||
BSS_SECTION(0, 0 ,0)
|
||||
_ebss =.;
|
||||
_ramend = .;
|
||||
_end = .;
|
||||
DISCARDS
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
#
|
||||
# Makefile for H8/300-specific library files..
|
||||
#
|
||||
|
||||
lib-y = memcpy.o memset.o abs.o strncpy.o \
|
||||
mulsi3.o udivsi3.o muldi3.o moddivsi3.o \
|
||||
ashldi3.o lshrdi3.o ashrdi3.o ucmpdi2.o \
|
||||
delay.o
|
|
@ -0,0 +1,20 @@
|
|||
;;; abs.S
|
||||
|
||||
#include <asm/linkage.h>
|
||||
|
||||
#if defined(CONFIG_CPU_H8300H)
|
||||
.h8300h
|
||||
#endif
|
||||
#if defined(CONFIG_CPU_H8S)
|
||||
.h8300s
|
||||
#endif
|
||||
.text
|
||||
.global _abs
|
||||
|
||||
;;; int abs(int n)
|
||||
_abs:
|
||||
mov.l er0,er0
|
||||
bpl 1f
|
||||
neg.l er0
|
||||
1:
|
||||
rts
|
|
@ -0,0 +1,24 @@
|
|||
#include "libgcc.h"
|
||||
|
||||
DWtype
|
||||
__ashldi3(DWtype u, word_type b)
|
||||
{
|
||||
const DWunion uu = {.ll = u};
|
||||
const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
|
||||
DWunion w;
|
||||
|
||||
if (b == 0)
|
||||
return u;
|
||||
|
||||
if (bm <= 0) {
|
||||
w.s.low = 0;
|
||||
w.s.high = (UWtype) uu.s.low << -bm;
|
||||
} else {
|
||||
const UWtype carries = (UWtype) uu.s.low >> bm;
|
||||
|
||||
w.s.low = (UWtype) uu.s.low << b;
|
||||
w.s.high = ((UWtype) uu.s.high << b) | carries;
|
||||
}
|
||||
|
||||
return w.ll;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
#include "libgcc.h"
|
||||
|
||||
DWtype __ashrdi3(DWtype u, word_type b)
|
||||
{
|
||||
const DWunion uu = {.ll = u};
|
||||
const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
|
||||
DWunion w;
|
||||
|
||||
if (b == 0)
|
||||
return u;
|
||||
|
||||
if (bm <= 0) {
|
||||
/* w.s.high = 1..1 or 0..0 */
|
||||
w.s.high = uu.s.high >> (sizeof (Wtype) * BITS_PER_UNIT - 1);
|
||||
w.s.low = uu.s.high >> -bm;
|
||||
} else {
|
||||
const UWtype carries = (UWtype) uu.s.high << bm;
|
||||
|
||||
w.s.high = uu.s.high >> b;
|
||||
w.s.low = ((UWtype) uu.s.low >> b) | carries;
|
||||
}
|
||||
|
||||
return w.ll;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* delay loops
|
||||
*
|
||||
* Copyright (C) 2015 Yoshinori Sato
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/param.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/timex.h>
|
||||
|
||||
void __delay(unsigned long cycles)
|
||||
{
|
||||
__asm__ volatile ("1: dec.l #1,%0\n\t"
|
||||
"bne 1b":"=r"(cycles):"0"(cycles));
|
||||
}
|
||||
EXPORT_SYMBOL(__delay);
|
||||
|
||||
void __const_udelay(unsigned long xloops)
|
||||
{
|
||||
u64 loops;
|
||||
|
||||
loops = (u64)xloops * loops_per_jiffy * HZ;
|
||||
|
||||
__delay(loops >> 32);
|
||||
}
|
||||
EXPORT_SYMBOL(__const_udelay);
|
||||
|
||||
void __udelay(unsigned long usecs)
|
||||
{
|
||||
__const_udelay(usecs * 0x10C7UL); /* 2**32 / 1000000 (rounded up) */
|
||||
}
|
||||
EXPORT_SYMBOL(__udelay);
|
||||
|
||||
void __ndelay(unsigned long nsecs)
|
||||
{
|
||||
__const_udelay(nsecs * 0x5UL); /* 2**32 / 1000000000 (rounded up) */
|
||||
}
|
||||
EXPORT_SYMBOL(__ndelay);
|
|
@ -0,0 +1,77 @@
|
|||
#ifndef __H8300_LIBGCC_H__
|
||||
#define __H8300_LIBGCC_H__
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
#define A0 r0
|
||||
#define A0L r0l
|
||||
#define A0H r0h
|
||||
|
||||
#define A1 r1
|
||||
#define A1L r1l
|
||||
#define A1H r1h
|
||||
|
||||
#define A2 r2
|
||||
#define A2L r2l
|
||||
#define A2H r2h
|
||||
|
||||
#define A3 r3
|
||||
#define A3L r3l
|
||||
#define A3H r3h
|
||||
|
||||
#define S0 r4
|
||||
#define S0L r4l
|
||||
#define S0H r4h
|
||||
|
||||
#define S1 r5
|
||||
#define S1L r5l
|
||||
#define S1H r5h
|
||||
|
||||
#define S2 r6
|
||||
#define S2L r6l
|
||||
#define S2H r6h
|
||||
|
||||
#define PUSHP push.l
|
||||
#define POPP pop.l
|
||||
|
||||
#define A0P er0
|
||||
#define A1P er1
|
||||
#define A2P er2
|
||||
#define A3P er3
|
||||
#define S0P er4
|
||||
#define S1P er5
|
||||
#define S2P er6
|
||||
|
||||
#define A0E e0
|
||||
#define A1E e1
|
||||
#define A2E e2
|
||||
#define A3E e3
|
||||
#else
|
||||
#define Wtype SItype
|
||||
#define UWtype USItype
|
||||
#define HWtype SItype
|
||||
#define UHWtype USItype
|
||||
#define DWtype DItype
|
||||
#define UDWtype UDItype
|
||||
#define UWtype USItype
|
||||
#define Wtype SItype
|
||||
#define UWtype USItype
|
||||
#define W_TYPE_SIZE (4 * BITS_PER_UNIT)
|
||||
#define BITS_PER_UNIT (8)
|
||||
|
||||
typedef int SItype __attribute__ ((mode (SI)));
|
||||
typedef unsigned int USItype __attribute__ ((mode (SI)));
|
||||
typedef int DItype __attribute__ ((mode (DI)));
|
||||
typedef unsigned int UDItype __attribute__ ((mode (DI)));
|
||||
struct DWstruct {
|
||||
Wtype high, low;
|
||||
};
|
||||
typedef union {
|
||||
struct DWstruct s;
|
||||
DWtype ll;
|
||||
} DWunion;
|
||||
|
||||
typedef int word_type __attribute__ ((mode (__word__)));
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,23 @@
|
|||
#include "libgcc.h"
|
||||
|
||||
DWtype __lshrdi3(DWtype u, word_type b)
|
||||
{
|
||||
const DWunion uu = {.ll = u};
|
||||
const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
|
||||
DWunion w;
|
||||
|
||||
if (b == 0)
|
||||
return u;
|
||||
|
||||
if (bm <= 0) {
|
||||
w.s.high = 0;
|
||||
w.s.low = (UWtype) uu.s.high >> -bm;
|
||||
} else {
|
||||
const UWtype carries = (UWtype) uu.s.high << bm;
|
||||
|
||||
w.s.high = (UWtype) uu.s.high >> b;
|
||||
w.s.low = ((UWtype) uu.s.low >> b) | carries;
|
||||
}
|
||||
|
||||
return w.ll;
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
;;; memcpy.S
|
||||
|
||||
#include <asm/linkage.h>
|
||||
|
||||
#if defined(CONFIG_CPU_H8300H)
|
||||
.h8300h
|
||||
#endif
|
||||
#if defined(CONFIG_CPU_H8S)
|
||||
.h8300s
|
||||
#endif
|
||||
.text
|
||||
.global memcpy
|
||||
|
||||
;;; void *memcpy(void *to, void *from, size_t n)
|
||||
memcpy:
|
||||
mov.l er2,er2
|
||||
bne 1f
|
||||
rts
|
||||
1:
|
||||
;; address check
|
||||
bld #0,r0l
|
||||
bxor #0,r1l
|
||||
bcs 4f
|
||||
mov.l er4,@-sp
|
||||
mov.l er0,@-sp
|
||||
btst #0,r0l
|
||||
beq 1f
|
||||
;; (aligned even) odd address
|
||||
mov.b @er1,r3l
|
||||
mov.b r3l,@er0
|
||||
adds #1,er1
|
||||
adds #1,er0
|
||||
dec.l #1,er2
|
||||
beq 3f
|
||||
1:
|
||||
;; n < sizeof(unsigned long) check
|
||||
sub.l er4,er4
|
||||
adds #4,er4 ; loop count check value
|
||||
cmp.l er4,er2
|
||||
blo 2f
|
||||
;; unsigned long copy
|
||||
1:
|
||||
mov.l @er1,er3
|
||||
mov.l er3,@er0
|
||||
adds #4,er0
|
||||
adds #4,er1
|
||||
subs #4,er2
|
||||
cmp.l er4,er2
|
||||
bcc 1b
|
||||
;; rest
|
||||
2:
|
||||
mov.l er2,er2
|
||||
beq 3f
|
||||
1:
|
||||
mov.b @er1,r3l
|
||||
mov.b r3l,@er0
|
||||
adds #1,er1
|
||||
adds #1,er0
|
||||
dec.l #1,er2
|
||||
bne 1b
|
||||
3:
|
||||
mov.l @sp+,er0
|
||||
mov.l @sp+,er4
|
||||
rts
|
||||
|
||||
;; odd <- even / even <- odd
|
||||
4:
|
||||
mov.l er4,er3
|
||||
mov.l er2,er4
|
||||
mov.l er5,er2
|
||||
mov.l er1,er5
|
||||
mov.l er6,er1
|
||||
mov.l er0,er6
|
||||
1:
|
||||
eepmov.w
|
||||
mov.w r4,r4
|
||||
bne 1b
|
||||
dec.w #1,e4
|
||||
bpl 1b
|
||||
mov.l er1,er6
|
||||
mov.l er2,er5
|
||||
mov.l er3,er4
|
||||
rts
|
||||
|
||||
.end
|
|
@ -0,0 +1,69 @@
|
|||
/* memset.S */
|
||||
|
||||
#include <asm/linkage.h>
|
||||
|
||||
#if defined(CONFIG_CPU_H8300H)
|
||||
.h8300h
|
||||
#endif
|
||||
#if defined(CONFIG_CPU_H8S)
|
||||
.h8300s
|
||||
#endif
|
||||
.text
|
||||
|
||||
.global memset
|
||||
.global clear_user
|
||||
|
||||
;;void *memset(*ptr, int c, size_t count)
|
||||
;; ptr = er0
|
||||
;; c = er1(r1l)
|
||||
;; count = er2
|
||||
memset:
|
||||
btst #0,r0l
|
||||
beq 2f
|
||||
|
||||
;; odd address
|
||||
1:
|
||||
mov.b r1l,@er0
|
||||
adds #1,er0
|
||||
dec.l #1,er2
|
||||
beq 6f
|
||||
|
||||
;; even address
|
||||
2:
|
||||
mov.l er2,er3
|
||||
cmp.l #4,er2
|
||||
blo 4f
|
||||
;; count>=4 -> count/4
|
||||
#if defined(CONFIG_CPU_H8300H)
|
||||
shlr.l er2
|
||||
shlr.l er2
|
||||
#endif
|
||||
#if defined(CONFIG_CPU_H8S)
|
||||
shlr.l #2,er2
|
||||
#endif
|
||||
;; byte -> long
|
||||
mov.b r1l,r1h
|
||||
mov.w r1,e1
|
||||
3:
|
||||
mov.l er1,@er0
|
||||
adds #4,er0
|
||||
dec.l #1,er2
|
||||
bne 3b
|
||||
4:
|
||||
;; count % 4
|
||||
and.b #3,r3l
|
||||
beq 6f
|
||||
5:
|
||||
mov.b r1l,@er0
|
||||
adds #1,er0
|
||||
dec.b r3l
|
||||
bne 5b
|
||||
6:
|
||||
rts
|
||||
|
||||
clear_user:
|
||||
mov.l er1, er2
|
||||
sub.l er1, er1
|
||||
bra memset
|
||||
|
||||
.end
|
|
@ -0,0 +1,72 @@
|
|||
#include "libgcc.h"
|
||||
|
||||
; numerator in A0/A1
|
||||
; denominator in A2/A3
|
||||
.global __modsi3
|
||||
__modsi3:
|
||||
PUSHP S2P
|
||||
bsr modnorm
|
||||
bsr __divsi3
|
||||
mov.l er3,er0
|
||||
bra exitdiv
|
||||
|
||||
.global __umodsi3
|
||||
__umodsi3:
|
||||
bsr __udivsi3:16
|
||||
mov.l er3,er0
|
||||
rts
|
||||
|
||||
.global __divsi3
|
||||
__divsi3:
|
||||
PUSHP S2P
|
||||
bsr divnorm
|
||||
bsr __udivsi3:16
|
||||
|
||||
; examine what the sign should be
|
||||
exitdiv:
|
||||
btst #3,S2L
|
||||
beq reti
|
||||
|
||||
; should be -ve
|
||||
neg.l A0P
|
||||
|
||||
reti:
|
||||
POPP S2P
|
||||
rts
|
||||
|
||||
divnorm:
|
||||
mov.l A0P,A0P ; is the numerator -ve
|
||||
stc ccr,S2L ; keep the sign in bit 3 of S2L
|
||||
bge postive
|
||||
|
||||
neg.l A0P ; negate arg
|
||||
|
||||
postive:
|
||||
mov.l A1P,A1P ; is the denominator -ve
|
||||
bge postive2
|
||||
|
||||
neg.l A1P ; negate arg
|
||||
xor.b #0x08,S2L ; toggle the result sign
|
||||
|
||||
postive2:
|
||||
rts
|
||||
|
||||
;; Basically the same, except that the sign of the divisor determines
|
||||
;; the sign.
|
||||
modnorm:
|
||||
mov.l A0P,A0P ; is the numerator -ve
|
||||
stc ccr,S2L ; keep the sign in bit 3 of S2L
|
||||
bge mpostive
|
||||
|
||||
neg.l A0P ; negate arg
|
||||
|
||||
mpostive:
|
||||
mov.l A1P,A1P ; is the denominator -ve
|
||||
bge mpostive2
|
||||
|
||||
neg.l A1P ; negate arg
|
||||
|
||||
mpostive2:
|
||||
rts
|
||||
|
||||
.end
|
|
@ -0,0 +1,72 @@
|
|||
#include "libgcc.h"
|
||||
|
||||
; numerator in A0/A1
|
||||
; denominator in A2/A3
|
||||
.global __modsi3
|
||||
__modsi3:
|
||||
PUSHP S2P
|
||||
bsr modnorm
|
||||
bsr __divsi3
|
||||
mov.l er3,er0
|
||||
bra exitdiv
|
||||
|
||||
.global __umodsi3
|
||||
__umodsi3:
|
||||
bsr __udivsi3
|
||||
mov.l er3,er0
|
||||
rts
|
||||
|
||||
.global __divsi3
|
||||
__divsi3:
|
||||
PUSHP S2P
|
||||
jsr divnorm
|
||||
bsr __udivsi3
|
||||
|
||||
; examine what the sign should be
|
||||
exitdiv:
|
||||
btst #3,S2L
|
||||
beq reti
|
||||
|
||||
; should be -ve
|
||||
neg.l A0P
|
||||
|
||||
reti:
|
||||
POPP S2P
|
||||
rts
|
||||
|
||||
divnorm:
|
||||
mov.l A0P,A0P ; is the numerator -ve
|
||||
stc ccr,S2L ; keep the sign in bit 3 of S2L
|
||||
bge postive
|
||||
|
||||
neg.l A0P ; negate arg
|
||||
|
||||
postive:
|
||||
mov.l A1P,A1P ; is the denominator -ve
|
||||
bge postive2
|
||||
|
||||
neg.l A1P ; negate arg
|
||||
xor.b #0x08,S2L ; toggle the result sign
|
||||
|
||||
postive2:
|
||||
rts
|
||||
|
||||
;; Basically the same, except that the sign of the divisor determines
|
||||
;; the sign.
|
||||
modnorm:
|
||||
mov.l A0P,A0P ; is the numerator -ve
|
||||
stc ccr,S2L ; keep the sign in bit 3 of S2L
|
||||
bge mpostive
|
||||
|
||||
neg.l A0P ; negate arg
|
||||
|
||||
mpostive:
|
||||
mov.l A1P,A1P ; is the denominator -ve
|
||||
bge mpostive2
|
||||
|
||||
neg.l A1P ; negate arg
|
||||
|
||||
mpostive2:
|
||||
rts
|
||||
|
||||
.end
|
|
@ -0,0 +1,44 @@
|
|||
#include "libgcc.h"
|
||||
|
||||
#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
|
||||
#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
|
||||
#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
|
||||
|
||||
#define umul_ppmm(w1, w0, u, v) \
|
||||
do { \
|
||||
UWtype __x0, __x1, __x2, __x3; \
|
||||
UHWtype __ul, __vl, __uh, __vh; \
|
||||
__ul = __ll_lowpart(u); \
|
||||
__uh = __ll_highpart(u); \
|
||||
__vl = __ll_lowpart(v); \
|
||||
__vh = __ll_highpart(v); \
|
||||
__x0 = (UWtype) __ul * __vl; \
|
||||
__x1 = (UWtype) __ul * __vh; \
|
||||
__x2 = (UWtype) __uh * __vl; \
|
||||
__x3 = (UWtype) __uh * __vh; \
|
||||
__x1 += __ll_highpart(__x0); \
|
||||
__x1 += __x2; \
|
||||
if (__x1 < __x2) \
|
||||
__x3 += __ll_B; \
|
||||
(w1) = __x3 + __ll_highpart(__x1); \
|
||||
(w0) = __ll_lowpart(__x1) * __ll_B + __ll_lowpart(__x0); \
|
||||
} while (0)
|
||||
|
||||
#define __umulsidi3(u, v) ( \
|
||||
{ \
|
||||
DWunion __w; \
|
||||
umul_ppmm(__w.s.high, __w.s.low, u, v); \
|
||||
__w.ll; } \
|
||||
)
|
||||
|
||||
DWtype __muldi3(DWtype u, DWtype v)
|
||||
{
|
||||
const DWunion uu = {.ll = u};
|
||||
const DWunion vv = {.ll = v};
|
||||
DWunion w = {.ll = __umulsidi3(uu.s.low, vv.s.low)};
|
||||
|
||||
w.s.high += ((UWtype) uu.s.low * (UWtype) vv.s.high
|
||||
+ (UWtype) uu.s.high * (UWtype) vv.s.low);
|
||||
|
||||
return w.ll;
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
;
|
||||
; mulsi3 for H8/300H - based on Renesas SH implementation
|
||||
;
|
||||
; by Toshiyasu Morita
|
||||
;
|
||||
; Old code:
|
||||
;
|
||||
; 16b * 16b = 372 states (worst case)
|
||||
; 32b * 32b = 724 states (worst case)
|
||||
;
|
||||
; New code:
|
||||
;
|
||||
; 16b * 16b = 48 states
|
||||
; 16b * 32b = 72 states
|
||||
; 32b * 32b = 92 states
|
||||
;
|
||||
|
||||
.global __mulsi3
|
||||
__mulsi3:
|
||||
mov.w r1,r2 ; ( 2 states) b * d
|
||||
mulxu r0,er2 ; (22 states)
|
||||
|
||||
mov.w e0,r3 ; ( 2 states) a * d
|
||||
beq L_skip1 ; ( 4 states)
|
||||
mulxu r1,er3 ; (22 states)
|
||||
add.w r3,e2 ; ( 2 states)
|
||||
|
||||
L_skip1:
|
||||
mov.w e1,r3 ; ( 2 states) c * b
|
||||
beq L_skip2 ; ( 4 states)
|
||||
mulxu r0,er3 ; (22 states)
|
||||
add.w r3,e2 ; ( 2 states)
|
||||
|
||||
L_skip2:
|
||||
mov.l er2,er0 ; ( 2 states)
|
||||
rts ; (10 states)
|
||||
|
||||
.end
|
|
@ -0,0 +1,34 @@
|
|||
;;; strncpy.S
|
||||
|
||||
#include <asm/linkage.h>
|
||||
|
||||
.text
|
||||
.global strncpy_from_user
|
||||
|
||||
;;; long strncpy_from_user(void *to, void *from, size_t n)
|
||||
strncpy_from_user:
|
||||
mov.l er2,er2
|
||||
bne 1f
|
||||
sub.l er0,er0
|
||||
rts
|
||||
1:
|
||||
mov.l er4,@-sp
|
||||
sub.l er3,er3
|
||||
2:
|
||||
mov.b @er1+,r4l
|
||||
mov.b r4l,@er0
|
||||
adds #1,er0
|
||||
beq 3f
|
||||
inc.l #1,er3
|
||||
dec.l #1,er2
|
||||
bne 2b
|
||||
3:
|
||||
dec.l #1,er2
|
||||
4:
|
||||
mov.b r4l,@er0
|
||||
adds #1,er0
|
||||
dec.l #1,er2
|
||||
bne 4b
|
||||
mov.l er3,er0
|
||||
mov.l @sp+,er4
|
||||
rts
|
|
@ -0,0 +1,17 @@
|
|||
#include "libgcc.h"
|
||||
|
||||
word_type __ucmpdi2(DWtype a, DWtype b)
|
||||
{
|
||||
const DWunion au = {.ll = a};
|
||||
const DWunion bu = {.ll = b};
|
||||
|
||||
if ((UWtype) au.s.high < (UWtype) bu.s.high)
|
||||
return 0;
|
||||
else if ((UWtype) au.s.high > (UWtype) bu.s.high)
|
||||
return 2;
|
||||
if ((UWtype) au.s.low < (UWtype) bu.s.low)
|
||||
return 0;
|
||||
else if ((UWtype) au.s.low > (UWtype) bu.s.low)
|
||||
return 2;
|
||||
return 1;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue