aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYoshinori Sato <ysato@users.sourceforge.jp>2015-01-27 12:46:20 -0500
committerYoshinori Sato <ysato@users.sourceforge.jp>2015-06-23 00:35:53 -0400
commit4e0c20981ec16d13cfebaad7ed6245a472df2ed0 (patch)
treef576a7dfabb2541731d451248beb1f94bf6055d2
parentfe54616d857da4ccb482eb40fef0e0f3b3d0efaf (diff)
h8300: miscellaneous functions
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
-rw-r--r--arch/h8300/kernel/asm-offsets.c67
-rw-r--r--arch/h8300/kernel/dma.c69
-rw-r--r--arch/h8300/kernel/h8300_ksyms.c36
-rw-r--r--arch/h8300/kernel/module.c70
-rw-r--r--arch/h8300/kernel/sim-console.c79
-rw-r--r--arch/h8300/kernel/syscalls.c14
6 files changed, 335 insertions, 0 deletions
diff --git a/arch/h8300/kernel/asm-offsets.c b/arch/h8300/kernel/asm-offsets.c
new file mode 100644
index 000000000000..dc2d16ce8a0d
--- /dev/null
+++ b/arch/h8300/kernel/asm-offsets.c
@@ -0,0 +1,67 @@
1/*
2 * This program is used to generate definitions needed by
3 * assembly language modules.
4 *
5 * We use the technique used in the OSF Mach kernel code:
6 * generate asm statements containing #defines,
7 * compile this file to assembler, and then extract the
8 * #defines from the assembly-language output.
9 */
10
11#include <linux/stddef.h>
12#include <linux/sched.h>
13#include <linux/kernel_stat.h>
14#include <linux/ptrace.h>
15#include <linux/hardirq.h>
16#include <linux/kbuild.h>
17#include <asm/irq.h>
18#include <asm/ptrace.h>
19
20int main(void)
21{
22 /* offsets into the task struct */
23 OFFSET(TASK_STATE, task_struct, state);
24 OFFSET(TASK_FLAGS, task_struct, flags);
25 OFFSET(TASK_PTRACE, task_struct, ptrace);
26 OFFSET(TASK_BLOCKED, task_struct, blocked);
27 OFFSET(TASK_THREAD, task_struct, thread);
28 OFFSET(TASK_THREAD_INFO, task_struct, stack);
29 OFFSET(TASK_MM, task_struct, mm);
30 OFFSET(TASK_ACTIVE_MM, task_struct, active_mm);
31
32 /* offsets into the irq_cpustat_t struct */
33 DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t,
34 __softirq_pending));
35
36 /* offsets into the thread struct */
37 OFFSET(THREAD_KSP, thread_struct, ksp);
38 OFFSET(THREAD_USP, thread_struct, usp);
39 OFFSET(THREAD_CCR, thread_struct, ccr);
40
41 /* offsets into the pt_regs struct */
42 DEFINE(LER0, offsetof(struct pt_regs, er0) - sizeof(long));
43 DEFINE(LER1, offsetof(struct pt_regs, er1) - sizeof(long));
44 DEFINE(LER2, offsetof(struct pt_regs, er2) - sizeof(long));
45 DEFINE(LER3, offsetof(struct pt_regs, er3) - sizeof(long));
46 DEFINE(LER4, offsetof(struct pt_regs, er4) - sizeof(long));
47 DEFINE(LER5, offsetof(struct pt_regs, er5) - sizeof(long));
48 DEFINE(LER6, offsetof(struct pt_regs, er6) - sizeof(long));
49 DEFINE(LORIG, offsetof(struct pt_regs, orig_er0) - sizeof(long));
50 DEFINE(LSP, offsetof(struct pt_regs, sp) - sizeof(long));
51 DEFINE(LCCR, offsetof(struct pt_regs, ccr) - sizeof(long));
52 DEFINE(LVEC, offsetof(struct pt_regs, vector) - sizeof(long));
53#if defined(CONFIG_CPU_H8S)
54 DEFINE(LEXR, offsetof(struct pt_regs, exr) - sizeof(long));
55#endif
56 DEFINE(LRET, offsetof(struct pt_regs, pc) - sizeof(long));
57
58 DEFINE(PT_PTRACED, PT_PTRACED);
59
60 /* offsets in thread_info structure */
61 OFFSET(TI_TASK, thread_info, task);
62 OFFSET(TI_FLAGS, thread_info, flags);
63 OFFSET(TI_CPU, thread_info, cpu);
64 OFFSET(TI_PRE, thread_info, preempt_count);
65
66 return 0;
67}
diff --git a/arch/h8300/kernel/dma.c b/arch/h8300/kernel/dma.c
new file mode 100644
index 000000000000..eeb13d3f2424
--- /dev/null
+++ b/arch/h8300/kernel/dma.c
@@ -0,0 +1,69 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file COPYING in the main directory of this archive
4 * for more details.
5 */
6
7#include <linux/dma-mapping.h>
8#include <linux/kernel.h>
9#include <linux/scatterlist.h>
10#include <linux/module.h>
11#include <asm/pgalloc.h>
12
13static void *dma_alloc(struct device *dev, size_t size,
14 dma_addr_t *dma_handle, gfp_t gfp,
15 struct dma_attrs *attrs)
16{
17 void *ret;
18
19 /* ignore region specifiers */
20 gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
21
22 if (dev == NULL || (*dev->dma_mask < 0xffffffff))
23 gfp |= GFP_DMA;
24 ret = (void *)__get_free_pages(gfp, get_order(size));
25
26 if (ret != NULL) {
27 memset(ret, 0, size);
28 *dma_handle = virt_to_phys(ret);
29 }
30 return ret;
31}
32
33static void dma_free(struct device *dev, size_t size,
34 void *vaddr, dma_addr_t dma_handle,
35 struct dma_attrs *attrs)
36
37{
38 free_pages((unsigned long)vaddr, get_order(size));
39}
40
41static dma_addr_t map_page(struct device *dev, struct page *page,
42 unsigned long offset, size_t size,
43 enum dma_data_direction direction,
44 struct dma_attrs *attrs)
45{
46 return page_to_phys(page) + offset;
47}
48
49static int map_sg(struct device *dev, struct scatterlist *sgl,
50 int nents, enum dma_data_direction direction,
51 struct dma_attrs *attrs)
52{
53 struct scatterlist *sg;
54 int i;
55
56 for_each_sg(sgl, sg, nents, i) {
57 sg->dma_address = sg_phys(sg);
58 }
59
60 return nents;
61}
62
63struct dma_map_ops h8300_dma_map_ops = {
64 .alloc = dma_alloc,
65 .free = dma_free,
66 .map_page = map_page,
67 .map_sg = map_sg,
68};
69EXPORT_SYMBOL(h8300_dma_map_ops);
diff --git a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c
new file mode 100644
index 000000000000..a9033c838968
--- /dev/null
+++ b/arch/h8300/kernel/h8300_ksyms.c
@@ -0,0 +1,36 @@
1#include <linux/module.h>
2#include <linux/linkage.h>
3
4/*
5 * libgcc functions - functions that are used internally by the
6 * compiler... (prototypes are not correct though, but that
7 * doesn't really matter since they're not versioned).
8 */
9asmlinkage long __ucmpdi2(long long, long long);
10asmlinkage long long __ashldi3(long long, int);
11asmlinkage long long __ashrdi3(long long, int);
12asmlinkage long long __lshrdi3(long long, int);
13asmlinkage long __divsi3(long, long);
14asmlinkage long __modsi3(long, long);
15asmlinkage unsigned long __umodsi3(unsigned long, unsigned long);
16asmlinkage long long __muldi3(long long, long long);
17asmlinkage long __mulsi3(long, long);
18asmlinkage long __udivsi3(long, long);
19asmlinkage void *memcpy(void *, const void *, size_t);
20asmlinkage void *memset(void *, int, size_t);
21asmlinkage long strncpy_from_user(void *to, void *from, size_t n);
22
23 /* gcc lib functions */
24EXPORT_SYMBOL(__ucmpdi2);
25EXPORT_SYMBOL(__ashldi3);
26EXPORT_SYMBOL(__ashrdi3);
27EXPORT_SYMBOL(__lshrdi3);
28EXPORT_SYMBOL(__divsi3);
29EXPORT_SYMBOL(__modsi3);
30EXPORT_SYMBOL(__umodsi3);
31EXPORT_SYMBOL(__muldi3);
32EXPORT_SYMBOL(__mulsi3);
33EXPORT_SYMBOL(__udivsi3);
34EXPORT_SYMBOL(memcpy);
35EXPORT_SYMBOL(memset);
36EXPORT_SYMBOL(strncpy_from_user);
diff --git a/arch/h8300/kernel/module.c b/arch/h8300/kernel/module.c
new file mode 100644
index 000000000000..515f6c4e8d80
--- /dev/null
+++ b/arch/h8300/kernel/module.c
@@ -0,0 +1,70 @@
1#include <linux/moduleloader.h>
2#include <linux/elf.h>
3#include <linux/vmalloc.h>
4#include <linux/fs.h>
5#include <linux/string.h>
6#include <linux/kernel.h>
7
8int apply_relocate_add(Elf32_Shdr *sechdrs,
9 const char *strtab,
10 unsigned int symindex,
11 unsigned int relsec,
12 struct module *me)
13{
14 unsigned int i;
15 Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
16
17 pr_debug("Applying relocate section %u to %u\n", relsec,
18 sechdrs[relsec].sh_info);
19 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
20 /* This is where to make the change */
21 uint32_t *loc =
22 (uint32_t *)(sechdrs[sechdrs[relsec].sh_info].sh_addr
23 + rela[i].r_offset);
24 /* This is the symbol it is referring to. Note that all
25 undefined symbols have been resolved. */
26 Elf32_Sym *sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
27 + ELF32_R_SYM(rela[i].r_info);
28 uint32_t v = sym->st_value + rela[i].r_addend;
29
30 switch (ELF32_R_TYPE(rela[i].r_info)) {
31 case R_H8_DIR24R8:
32 loc = (uint32_t *)((uint32_t)loc - 1);
33 *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
34 break;
35 case R_H8_DIR24A8:
36 if (ELF32_R_SYM(rela[i].r_info))
37 *loc += v;
38 break;
39 case R_H8_DIR32:
40 case R_H8_DIR32A16:
41 *loc += v;
42 break;
43 case R_H8_PCREL16:
44 v -= (unsigned long)loc + 2;
45 if ((Elf32_Sword)v > 0x7fff ||
46 (Elf32_Sword)v < -(Elf32_Sword)0x8000)
47 goto overflow;
48 else
49 *(unsigned short *)loc = v;
50 break;
51 case R_H8_PCREL8:
52 v -= (unsigned long)loc + 1;
53 if ((Elf32_Sword)v > 0x7f ||
54 (Elf32_Sword)v < -(Elf32_Sword)0x80)
55 goto overflow;
56 else
57 *(unsigned char *)loc = v;
58 break;
59 default:
60 pr_err("module %s: Unknown relocation: %u\n",
61 me->name, ELF32_R_TYPE(rela[i].r_info));
62 return -ENOEXEC;
63 }
64 }
65 return 0;
66 overflow:
67 pr_err("module %s: relocation offset overflow: %08x\n",
68 me->name, rela[i].r_offset);
69 return -ENOEXEC;
70}
diff --git a/arch/h8300/kernel/sim-console.c b/arch/h8300/kernel/sim-console.c
new file mode 100644
index 000000000000..a15edf0565d9
--- /dev/null
+++ b/arch/h8300/kernel/sim-console.c
@@ -0,0 +1,79 @@
1/*
2 * arch/h8300/kernel/early_printk.c
3 *
4 * Copyright (C) 2009 Yoshinori Sato <ysato@users.sourceforge.jp>
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10#include <linux/console.h>
11#include <linux/tty.h>
12#include <linux/init.h>
13#include <linux/io.h>
14#include <linux/platform_device.h>
15
16static void sim_write(struct console *co, const char *ptr,
17 unsigned len)
18{
19 register const int fd __asm__("er0") = 1; /* stdout */
20 register const char *_ptr __asm__("er1") = ptr;
21 register const unsigned _len __asm__("er2") = len;
22
23 __asm__(".byte 0x5e,0x00,0x00,0xc7\n\t" /* jsr @0xc7 (sys_write) */
24 : : "g"(fd), "g"(_ptr), "g"(_len));
25}
26
27static struct console sim_console = {
28 .name = "sim_console",
29 .write = sim_write,
30 .setup = NULL,
31 .flags = CON_PRINTBUFFER,
32 .index = -1,
33};
34
35static char sim_console_buf[32];
36
37static int sim_probe(struct platform_device *pdev)
38{
39 if (sim_console.data)
40 return -EEXIST;
41
42 if (!strstr(sim_console_buf, "keep"))
43 sim_console.flags |= CON_BOOT;
44
45 register_console(&sim_console);
46 return 0;
47}
48
49static int sim_remove(struct platform_device *pdev)
50{
51 return 0;
52}
53
54static struct platform_driver sim_driver = {
55 .probe = sim_probe,
56 .remove = sim_remove,
57 .driver = {
58 .name = "h8300-sim",
59 .owner = THIS_MODULE,
60 },
61};
62
63early_platform_init_buffer("earlyprintk", &sim_driver,
64 sim_console_buf, ARRAY_SIZE(sim_console_buf));
65
66static struct platform_device sim_console_device = {
67 .name = "h8300-sim",
68 .id = 0,
69};
70
71static struct platform_device *devices[] __initdata = {
72 &sim_console_device,
73};
74
75void __init sim_console_register(void)
76{
77 early_platform_add_devices(devices,
78 ARRAY_SIZE(devices));
79}
diff --git a/arch/h8300/kernel/syscalls.c b/arch/h8300/kernel/syscalls.c
new file mode 100644
index 000000000000..1f9123a013d3
--- /dev/null
+++ b/arch/h8300/kernel/syscalls.c
@@ -0,0 +1,14 @@
1#include <linux/syscalls.h>
2#include <linux/signal.h>
3#include <linux/unistd.h>
4
5#undef __SYSCALL
6#define __SYSCALL(nr, call) [nr] = (call),
7
8#define sys_mmap2 sys_mmap_pgoff
9
10asmlinkage int sys_rt_sigreturn(void);
11
12void *_sys_call_table[__NR_syscalls] = {
13#include <asm/unistd.h>
14};