aboutsummaryrefslogtreecommitdiffstats
path: root/arch/xtensa/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/xtensa/kernel')
-rw-r--r--arch/xtensa/kernel/Makefile2
-rw-r--r--arch/xtensa/kernel/asm-offsets.c13
-rw-r--r--arch/xtensa/kernel/entry.S115
-rw-r--r--arch/xtensa/kernel/init_task.c38
-rw-r--r--arch/xtensa/kernel/io.c75
-rw-r--r--arch/xtensa/kernel/module.c195
-rw-r--r--arch/xtensa/kernel/pci.c69
-rw-r--r--arch/xtensa/kernel/process.c14
-rw-r--r--arch/xtensa/kernel/semaphore.c2
-rw-r--r--arch/xtensa/kernel/syscall.c5
-rw-r--r--arch/xtensa/kernel/time.c46
-rw-r--r--arch/xtensa/kernel/traps.c4
12 files changed, 432 insertions, 146 deletions
diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index 71f733c4f66d..f582d6a24ec2 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -7,7 +7,7 @@ extra-y := head.o vmlinux.lds
7 7
8obj-y := align.o entry.o irq.o coprocessor.o process.o ptrace.o semaphore.o \ 8obj-y := align.o entry.o irq.o coprocessor.o process.o ptrace.o semaphore.o \
9 setup.o signal.o syscall.o time.o traps.o vectors.o platform.o \ 9 setup.o signal.o syscall.o time.o traps.o vectors.o platform.o \
10 pci-dma.o 10 pci-dma.o init_task.o io.o
11 11
12## windowspill.o 12## windowspill.o
13 13
diff --git a/arch/xtensa/kernel/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c
index d0323cd6a2ea..d5ffe7b6443e 100644
--- a/arch/xtensa/kernel/asm-offsets.c
+++ b/arch/xtensa/kernel/asm-offsets.c
@@ -18,12 +18,13 @@
18#include <linux/stddef.h> 18#include <linux/stddef.h>
19#include <linux/thread_info.h> 19#include <linux/thread_info.h>
20#include <linux/ptrace.h> 20#include <linux/ptrace.h>
21#include <linux/mm.h>
22
21#include <asm/ptrace.h> 23#include <asm/ptrace.h>
22#include <asm/processor.h> 24#include <asm/processor.h>
23#include <asm/uaccess.h> 25#include <asm/uaccess.h>
24 26
25#define DEFINE(sym, val) asm volatile("\n->" #sym " %0 " #val : : "i" (val)) 27#define DEFINE(sym, val) asm volatile("\n->" #sym " %0 " #val : : "i" (val))
26#define BLANK() asm volatile("\n->" : : )
27 28
28int main(void) 29int main(void)
29{ 30{
@@ -63,7 +64,6 @@ int main(void)
63 DEFINE(PT_SIZE, sizeof(struct pt_regs)); 64 DEFINE(PT_SIZE, sizeof(struct pt_regs));
64 DEFINE(PT_AREG_END, offsetof (struct pt_regs, areg[XCHAL_NUM_AREGS])); 65 DEFINE(PT_AREG_END, offsetof (struct pt_regs, areg[XCHAL_NUM_AREGS]));
65 DEFINE(PT_USER_SIZE, offsetof(struct pt_regs, areg[XCHAL_NUM_AREGS])); 66 DEFINE(PT_USER_SIZE, offsetof(struct pt_regs, areg[XCHAL_NUM_AREGS]));
66 BLANK();
67 67
68 /* struct task_struct */ 68 /* struct task_struct */
69 DEFINE(TASK_PTRACE, offsetof (struct task_struct, ptrace)); 69 DEFINE(TASK_PTRACE, offsetof (struct task_struct, ptrace));
@@ -73,27 +73,26 @@ int main(void)
73 DEFINE(TASK_THREAD, offsetof (struct task_struct, thread)); 73 DEFINE(TASK_THREAD, offsetof (struct task_struct, thread));
74 DEFINE(TASK_THREAD_INFO, offsetof (struct task_struct, stack)); 74 DEFINE(TASK_THREAD_INFO, offsetof (struct task_struct, stack));
75 DEFINE(TASK_STRUCT_SIZE, sizeof (struct task_struct)); 75 DEFINE(TASK_STRUCT_SIZE, sizeof (struct task_struct));
76 BLANK();
77 76
78 /* struct thread_info (offset from start_struct) */ 77 /* struct thread_info (offset from start_struct) */
79 DEFINE(THREAD_RA, offsetof (struct task_struct, thread.ra)); 78 DEFINE(THREAD_RA, offsetof (struct task_struct, thread.ra));
80 DEFINE(THREAD_SP, offsetof (struct task_struct, thread.sp)); 79 DEFINE(THREAD_SP, offsetof (struct task_struct, thread.sp));
81 DEFINE(THREAD_CP_SAVE, offsetof (struct task_struct, thread.cp_save)); 80 DEFINE(THREAD_CP_SAVE, offsetof (struct task_struct, thread.cp_save));
82 DEFINE(THREAD_CURRENT_DS, offsetof (struct task_struct, thread.current_ds)); 81 DEFINE(THREAD_CURRENT_DS, offsetof (struct task_struct, thread.current_ds));
83 BLANK();
84 82
85 /* struct mm_struct */ 83 /* struct mm_struct */
86 DEFINE(MM_USERS, offsetof(struct mm_struct, mm_users)); 84 DEFINE(MM_USERS, offsetof(struct mm_struct, mm_users));
87 DEFINE(MM_PGD, offsetof (struct mm_struct, pgd)); 85 DEFINE(MM_PGD, offsetof (struct mm_struct, pgd));
88 DEFINE(MM_CONTEXT, offsetof (struct mm_struct, context)); 86 DEFINE(MM_CONTEXT, offsetof (struct mm_struct, context));
89 BLANK(); 87
90 DEFINE(PT_SINGLESTEP_BIT, PT_SINGLESTEP_BIT); 88 /* struct page */
89 DEFINE(PAGE_FLAGS, offsetof(struct page, flags));
91 90
92 /* constants */ 91 /* constants */
93 DEFINE(_CLONE_VM, CLONE_VM); 92 DEFINE(_CLONE_VM, CLONE_VM);
94 DEFINE(_CLONE_UNTRACED, CLONE_UNTRACED); 93 DEFINE(_CLONE_UNTRACED, CLONE_UNTRACED);
94 DEFINE(PG_ARCH_1, PG_arch_1);
95 95
96 return 0; 96 return 0;
97} 97}
98 98
99
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 8dc7a2c26ff9..91a689eca43d 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -7,7 +7,7 @@
7 * License. See the file "COPYING" in the main directory of this archive 7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details. 8 * for more details.
9 * 9 *
10 * Copyright (C) 2004-2005 by Tensilica Inc. 10 * Copyright (C) 2004-2007 by Tensilica Inc.
11 * 11 *
12 * Chris Zankel <chris@zankel.net> 12 * Chris Zankel <chris@zankel.net>
13 * 13 *
@@ -169,7 +169,7 @@ _user_exception:
169 * We have to save all registers up to the first '1' from 169 * We have to save all registers up to the first '1' from
170 * the right, except the current frame (bit 0). 170 * the right, except the current frame (bit 0).
171 * Assume a2 is: 001001000110001 171 * Assume a2 is: 001001000110001
172 * All regiser frames starting from the top fiel to the marked '1' 172 * All register frames starting from the top field to the marked '1'
173 * must be saved. 173 * must be saved.
174 */ 174 */
175 175
@@ -1572,10 +1572,12 @@ ENTRY(fast_second_level_miss)
1572 l32i a0, a1, TASK_MM # tsk->mm 1572 l32i a0, a1, TASK_MM # tsk->mm
1573 beqz a0, 9f 1573 beqz a0, 9f
1574 1574
15758: rsr a1, EXCVADDR # fault address 1575
1576 _PGD_OFFSET(a0, a1, a1) 1576 /* We deliberately destroy a3 that holds the exception table. */
1577
15788: rsr a3, EXCVADDR # fault address
1579 _PGD_OFFSET(a0, a3, a1)
1577 l32i a0, a0, 0 # read pmdval 1580 l32i a0, a0, 0 # read pmdval
1578 //beqi a0, _PAGE_USER, 2f
1579 beqz a0, 2f 1581 beqz a0, 2f
1580 1582
1581 /* Read ptevaddr and convert to top of page-table page. 1583 /* Read ptevaddr and convert to top of page-table page.
@@ -1588,7 +1590,7 @@ ENTRY(fast_second_level_miss)
1588 * The messy computation for 'pteval' above really simplifies 1590 * The messy computation for 'pteval' above really simplifies
1589 * into the following: 1591 * into the following:
1590 * 1592 *
1591 * pteval = ((pmdval - PAGE_OFFSET) & PAGE_MASK) | PAGE_KERNEL 1593 * pteval = ((pmdval - PAGE_OFFSET) & PAGE_MASK) | PAGE_DIRECTORY
1592 */ 1594 */
1593 1595
1594 movi a1, -PAGE_OFFSET 1596 movi a1, -PAGE_OFFSET
@@ -1596,20 +1598,34 @@ ENTRY(fast_second_level_miss)
1596 extui a1, a0, 0, PAGE_SHIFT # ... & PAGE_MASK 1598 extui a1, a0, 0, PAGE_SHIFT # ... & PAGE_MASK
1597 xor a0, a0, a1 1599 xor a0, a0, a1
1598 1600
1599 1601 movi a1, _PAGE_DIRECTORY
1600 movi a1, PAGE_DIRECTORY
1601 or a0, a0, a1 # ... | PAGE_DIRECTORY 1602 or a0, a0, a1 # ... | PAGE_DIRECTORY
1602 1603
1604 /*
1605 * We utilize all three wired-ways (7-9) to hold pmd translations.
1606 * Memory regions are mapped to the DTLBs according to bits 28 and 29.
1607 * This allows to map the three most common regions to three different
1608 * DTLBs:
1609 * 0,1 -> way 7 program (0040.0000) and virtual (c000.0000)
1610 * 2 -> way 8 shared libaries (2000.0000)
1611 * 3 -> way 0 stack (3000.0000)
1612 */
1613
1614 extui a3, a3, 28, 2 # addr. bit 28 and 29 0,1,2,3
1603 rsr a1, PTEVADDR 1615 rsr a1, PTEVADDR
1616 addx2 a3, a3, a3 # -> 0,3,6,9
1604 srli a1, a1, PAGE_SHIFT 1617 srli a1, a1, PAGE_SHIFT
1618 extui a3, a3, 2, 2 # -> 0,0,1,2
1605 slli a1, a1, PAGE_SHIFT # ptevaddr & PAGE_MASK 1619 slli a1, a1, PAGE_SHIFT # ptevaddr & PAGE_MASK
1606 addi a1, a1, DTLB_WAY_PGD # ... + way_number 1620 addi a3, a3, DTLB_WAY_PGD
1621 add a1, a1, a3 # ... + way_number
1607 1622
1608 wdtlb a0, a1 16233: wdtlb a0, a1
1609 dsync 1624 dsync
1610 1625
1611 /* Exit critical section. */ 1626 /* Exit critical section. */
1612 1627
16284: movi a3, exc_table # restore a3
1613 movi a0, 0 1629 movi a0, 0
1614 s32i a0, a3, EXC_TABLE_FIXUP 1630 s32i a0, a3, EXC_TABLE_FIXUP
1615 1631
@@ -1636,8 +1652,76 @@ ENTRY(fast_second_level_miss)
16369: l32i a0, a1, TASK_ACTIVE_MM # unlikely case mm == 0 16529: l32i a0, a1, TASK_ACTIVE_MM # unlikely case mm == 0
1637 j 8b 1653 j 8b
1638 1654
1655#if (DCACHE_WAY_SIZE > PAGE_SIZE)
1656
16572: /* Special case for cache aliasing.
1658 * We (should) only get here if a clear_user_page, copy_user_page
1659 * or the aliased cache flush functions got preemptively interrupted
1660 * by another task. Re-establish temporary mapping to the
1661 * TLBTEMP_BASE areas.
1662 */
1663
1664 /* We shouldn't be in a double exception */
1665
1666 l32i a0, a2, PT_DEPC
1667 bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, 2f
1668
1669 /* Make sure the exception originated in the special functions */
1670
1671 movi a0, __tlbtemp_mapping_start
1672 rsr a3, EPC_1
1673 bltu a3, a0, 2f
1674 movi a0, __tlbtemp_mapping_end
1675 bgeu a3, a0, 2f
1676
1677 /* Check if excvaddr was in one of the TLBTEMP_BASE areas. */
1678
1679 movi a3, TLBTEMP_BASE_1
1680 rsr a0, EXCVADDR
1681 bltu a0, a3, 2f
1682
1683 addi a1, a0, -(2 << (DCACHE_ALIAS_ORDER + PAGE_SHIFT))
1684 bgeu a1, a3, 2f
1685
1686 /* Check if we have to restore an ITLB mapping. */
1687
1688 movi a1, __tlbtemp_mapping_itlb
1689 rsr a3, EPC_1
1690 sub a3, a3, a1
1691
1692 /* Calculate VPN */
1693
1694 movi a1, PAGE_MASK
1695 and a1, a1, a0
1696
1697 /* Jump for ITLB entry */
1698
1699 bgez a3, 1f
1700
1701 /* We can use up to two TLBTEMP areas, one for src and one for dst. */
1702
1703 extui a3, a0, PAGE_SHIFT + DCACHE_ALIAS_ORDER, 1
1704 add a1, a3, a1
1705
1706 /* PPN is in a6 for the first TLBTEMP area and in a7 for the second. */
1707
1708 mov a0, a6
1709 movnez a0, a7, a3
1710 j 3b
1711
1712 /* ITLB entry. We only use dst in a6. */
1713
17141: witlb a6, a1
1715 isync
1716 j 4b
1717
1718
1719#endif // DCACHE_WAY_SIZE > PAGE_SIZE
1720
1721
16392: /* Invalid PGD, default exception handling */ 17222: /* Invalid PGD, default exception handling */
1640 1723
1724 movi a3, exc_table
1641 rsr a1, DEPC 1725 rsr a1, DEPC
1642 xsr a3, EXCSAVE_1 1726 xsr a3, EXCSAVE_1
1643 s32i a1, a2, PT_AREG2 1727 s32i a1, a2, PT_AREG2
@@ -1682,15 +1766,15 @@ ENTRY(fast_store_prohibited)
16828: rsr a1, EXCVADDR # fault address 17668: rsr a1, EXCVADDR # fault address
1683 _PGD_OFFSET(a0, a1, a4) 1767 _PGD_OFFSET(a0, a1, a4)
1684 l32i a0, a0, 0 1768 l32i a0, a0, 0
1685 //beqi a0, _PAGE_USER, 2f # FIXME use _PAGE_INVALID
1686 beqz a0, 2f 1769 beqz a0, 2f
1687 1770
1771 /* Note that we assume _PAGE_WRITABLE_BIT is only set if pte is valid.*/
1772
1688 _PTE_OFFSET(a0, a1, a4) 1773 _PTE_OFFSET(a0, a1, a4)
1689 l32i a4, a0, 0 # read pteval 1774 l32i a4, a0, 0 # read pteval
1690 movi a1, _PAGE_VALID | _PAGE_RW 1775 bbci.l a4, _PAGE_WRITABLE_BIT, 2f
1691 bnall a4, a1, 2f
1692 1776
1693 movi a1, _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_WRENABLE 1777 movi a1, _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_HW_WRITE
1694 or a4, a4, a1 1778 or a4, a4, a1
1695 rsr a1, EXCVADDR 1779 rsr a1, EXCVADDR
1696 s32i a4, a0, 0 1780 s32i a4, a0, 0
@@ -1700,10 +1784,7 @@ ENTRY(fast_store_prohibited)
1700 dhwb a0, 0 1784 dhwb a0, 0
1701#endif 1785#endif
1702 pdtlb a0, a1 1786 pdtlb a0, a1
1703 beqz a0, 1f
1704 idtlb a0 // FIXME do we need this?
1705 wdtlb a4, a0 1787 wdtlb a4, a0
17061:
1707 1788
1708 /* Exit critical section. */ 1789 /* Exit critical section. */
1709 1790
diff --git a/arch/xtensa/kernel/init_task.c b/arch/xtensa/kernel/init_task.c
new file mode 100644
index 000000000000..021b4f46ff94
--- /dev/null
+++ b/arch/xtensa/kernel/init_task.c
@@ -0,0 +1,38 @@
1/*
2 * arch/xtensa/kernel/init_task.c
3 *
4 * Xtensa Processor version.
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 * Copyright (C) 2007 Tensilica Inc.
11 *
12 * Chris Zankel <chris@zankel.net>
13 */
14
15#include <linux/mm.h>
16#include <linux/fs.h>
17#include <linux/init.h>
18#include <linux/init_task.h>
19#include <linux/module.h>
20#include <linux/mqueue.h>
21
22#include <asm/uaccess.h>
23
24static struct fs_struct init_fs = INIT_FS;
25static struct files_struct init_files = INIT_FILES;
26static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
27static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
28struct mm_struct init_mm = INIT_MM(init_mm);
29
30EXPORT_SYMBOL(init_mm);
31
32union thread_union init_thread_union
33 __attribute__((__section__(".data.init_task"))) =
34{ INIT_THREAD_INFO(init_task) };
35
36struct task_struct init_task = INIT_TASK(init_task);
37
38EXPORT_SYMBOL(init_task);
diff --git a/arch/xtensa/kernel/io.c b/arch/xtensa/kernel/io.c
new file mode 100644
index 000000000000..5b65269b1d2f
--- /dev/null
+++ b/arch/xtensa/kernel/io.c
@@ -0,0 +1,75 @@
1/*
2 * arch/xtensa/io.c
3 *
4 * IO primitives
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * Copied from sparc.
12 *
13 * Chris Zankel <chris@zankel.net>
14 *
15 */
16
17#include <asm/io.h>
18#include <asm/byteorder.h>
19
20void outsb(unsigned long addr, const void *src, unsigned long count) {
21 while (count) {
22 count -= 1;
23 writeb(*(const char *)src, addr);
24 src += 1;
25 addr += 1;
26 }
27}
28
29void outsw(unsigned long addr, const void *src, unsigned long count) {
30 while (count) {
31 count -= 2;
32 writew(*(const short *)src, addr);
33 src += 2;
34 addr += 2;
35 }
36}
37
38void outsl(unsigned long addr, const void *src, unsigned long count) {
39 while (count) {
40 count -= 4;
41 writel(*(const long *)src, addr);
42 src += 4;
43 addr += 4;
44 }
45}
46
47void insb(unsigned long addr, void *dst, unsigned long count) {
48 while (count) {
49 count -= 1;
50 *(unsigned char *)dst = readb(addr);
51 dst += 1;
52 addr += 1;
53 }
54}
55
56void insw(unsigned long addr, void *dst, unsigned long count) {
57 while (count) {
58 count -= 2;
59 *(unsigned short *)dst = readw(addr);
60 dst += 2;
61 addr += 2;
62 }
63}
64
65void insl(unsigned long addr, void *dst, unsigned long count) {
66 while (count) {
67 count -= 4;
68 /*
69 * XXX I am sure we are in for an unaligned trap here.
70 */
71 *(unsigned long *)dst = readl(addr);
72 dst += 4;
73 addr += 4;
74 }
75}
diff --git a/arch/xtensa/kernel/module.c b/arch/xtensa/kernel/module.c
index 2ea1755a0858..ddf14dcf2ad9 100644
--- a/arch/xtensa/kernel/module.c
+++ b/arch/xtensa/kernel/module.c
@@ -7,7 +7,7 @@
7 * License. See the file "COPYING" in the main directory of this archive 7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details. 8 * for more details.
9 * 9 *
10 * Copyright (C) 2001 - 2005 Tensilica Inc. 10 * Copyright (C) 2001 - 2006 Tensilica Inc.
11 * 11 *
12 * Chris Zankel <chris@zankel.net> 12 * Chris Zankel <chris@zankel.net>
13 * 13 *
@@ -22,57 +22,216 @@
22#include <linux/kernel.h> 22#include <linux/kernel.h>
23#include <linux/cache.h> 23#include <linux/cache.h>
24 24
25LIST_HEAD(module_buf_list); 25#undef DEBUG_RELOCATE
26 26
27void *module_alloc(unsigned long size) 27void *module_alloc(unsigned long size)
28{ 28{
29 panic("module_alloc not implemented"); 29 if (size == 0)
30 return NULL;
31 return vmalloc(size);
30} 32}
31 33
32void module_free(struct module *mod, void *module_region) 34void module_free(struct module *mod, void *module_region)
33{ 35{
34 panic("module_free not implemented"); 36 vfree(module_region);
37 /* FIXME: If module_region == mod->init_region, trim exception
38 table entries. */
35} 39}
36 40
37int module_frob_arch_sections(Elf32_Ehdr *hdr, 41int module_frob_arch_sections(Elf32_Ehdr *hdr,
38 Elf32_Shdr *sechdrs, 42 Elf32_Shdr *sechdrs,
39 char *secstrings, 43 char *secstrings,
40 struct module *me) 44 struct module *mod)
41{ 45{
42 panic("module_frob_arch_sections not implemented"); 46 return 0;
47}
48
49static int
50decode_calln_opcode (unsigned char *location)
51{
52#ifdef __XTENSA_EB__
53 return (location[0] & 0xf0) == 0x50;
54#endif
55#ifdef __XTENSA_EL__
56 return (location[0] & 0xf) == 0x5;
57#endif
58}
59
60static int
61decode_l32r_opcode (unsigned char *location)
62{
63#ifdef __XTENSA_EB__
64 return (location[0] & 0xf0) == 0x10;
65#endif
66#ifdef __XTENSA_EL__
67 return (location[0] & 0xf) == 0x1;
68#endif
43} 69}
44 70
45int apply_relocate(Elf32_Shdr *sechdrs, 71int apply_relocate(Elf32_Shdr *sechdrs,
46 const char *strtab, 72 const char *strtab,
47 unsigned int symindex, 73 unsigned int symindex,
48 unsigned int relsec, 74 unsigned int relsec,
49 struct module *module) 75 struct module *mod)
50{ 76{
51 panic ("apply_relocate not implemented"); 77 printk(KERN_ERR "module %s: REL RELOCATION unsupported\n",
78 mod->name);
79 return -ENOEXEC;
80
52} 81}
53 82
54int apply_relocate_add(Elf32_Shdr *sechdrs, 83int apply_relocate_add(Elf32_Shdr *sechdrs,
55 const char *strtab, 84 const char *strtab,
56 unsigned int symindex, 85 unsigned int symindex,
57 unsigned int relsec, 86 unsigned int relsec,
58 struct module *module) 87 struct module *mod)
59{ 88{
60 panic("apply_relocate_add not implemented"); 89 unsigned int i;
90 Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
91 Elf32_Sym *sym;
92 unsigned char *location;
93 uint32_t value;
94
95#ifdef DEBUG_RELOCATE
96 printk("Applying relocate section %u to %u\n", relsec,
97 sechdrs[relsec].sh_info);
98#endif
99 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
100 location = (char *)sechdrs[sechdrs[relsec].sh_info].sh_addr
101 + rela[i].r_offset;
102 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
103 + ELF32_R_SYM(rela[i].r_info);
104 value = sym->st_value + rela[i].r_addend;
105
106 switch (ELF32_R_TYPE(rela[i].r_info)) {
107 case R_XTENSA_NONE:
108 case R_XTENSA_DIFF8:
109 case R_XTENSA_DIFF16:
110 case R_XTENSA_DIFF32:
111 case R_XTENSA_ASM_EXPAND:
112 break;
113
114 case R_XTENSA_32:
115 case R_XTENSA_PLT:
116 *(uint32_t *)location += value;
117 break;
118
119 case R_XTENSA_SLOT0_OP:
120 if (decode_calln_opcode(location)) {
121 value -= ((unsigned long)location & -4) + 4;
122 if ((value & 3) != 0 ||
123 ((value + (1 << 19)) >> 20) != 0) {
124 printk("%s: relocation out of range, "
125 "section %d reloc %d "
126 "sym '%s'\n",
127 mod->name, relsec, i,
128 strtab + sym->st_name);
129 return -ENOEXEC;
130 }
131 value = (signed int)value >> 2;
132#ifdef __XTENSA_EB__
133 location[0] = ((location[0] & ~0x3) |
134 ((value >> 16) & 0x3));
135 location[1] = (value >> 8) & 0xff;
136 location[2] = value & 0xff;
137#endif
138#ifdef __XTENSA_EL__
139 location[0] = ((location[0] & ~0xc0) |
140 ((value << 6) & 0xc0));
141 location[1] = (value >> 2) & 0xff;
142 location[2] = (value >> 10) & 0xff;
143#endif
144 } else if (decode_l32r_opcode(location)) {
145 value -= (((unsigned long)location + 3) & -4);
146 if ((value & 3) != 0 ||
147 (signed int)value >> 18 != -1) {
148 printk("%s: relocation out of range, "
149 "section %d reloc %d "
150 "sym '%s'\n",
151 mod->name, relsec, i,
152 strtab + sym->st_name);
153 return -ENOEXEC;
154 }
155 value = (signed int)value >> 2;
156
157#ifdef __XTENSA_EB__
158 location[1] = (value >> 8) & 0xff;
159 location[2] = value & 0xff;
160#endif
161#ifdef __XTENSA_EL__
162 location[1] = value & 0xff;
163 location[2] = (value >> 8) & 0xff;
164#endif
165 }
166 /* FIXME: Ignore any other opcodes. The Xtensa
167 assembler currently assumes that the linker will
168 always do relaxation and so all PC-relative
169 operands need relocations. (The assembler also
170 writes out the tentative PC-relative values,
171 assuming no link-time relaxation, so it is usually
172 safe to ignore the relocations.) If the
173 assembler's "--no-link-relax" flag can be made to
174 work, and if all kernel modules can be assembled
175 with that flag, then unexpected relocations could
176 be detected here. */
177 break;
178
179 case R_XTENSA_SLOT1_OP:
180 case R_XTENSA_SLOT2_OP:
181 case R_XTENSA_SLOT3_OP:
182 case R_XTENSA_SLOT4_OP:
183 case R_XTENSA_SLOT5_OP:
184 case R_XTENSA_SLOT6_OP:
185 case R_XTENSA_SLOT7_OP:
186 case R_XTENSA_SLOT8_OP:
187 case R_XTENSA_SLOT9_OP:
188 case R_XTENSA_SLOT10_OP:
189 case R_XTENSA_SLOT11_OP:
190 case R_XTENSA_SLOT12_OP:
191 case R_XTENSA_SLOT13_OP:
192 case R_XTENSA_SLOT14_OP:
193 printk("%s: unexpected FLIX relocation: %u\n",
194 mod->name,
195 ELF32_R_TYPE(rela[i].r_info));
196 return -ENOEXEC;
197
198 case R_XTENSA_SLOT0_ALT:
199 case R_XTENSA_SLOT1_ALT:
200 case R_XTENSA_SLOT2_ALT:
201 case R_XTENSA_SLOT3_ALT:
202 case R_XTENSA_SLOT4_ALT:
203 case R_XTENSA_SLOT5_ALT:
204 case R_XTENSA_SLOT6_ALT:
205 case R_XTENSA_SLOT7_ALT:
206 case R_XTENSA_SLOT8_ALT:
207 case R_XTENSA_SLOT9_ALT:
208 case R_XTENSA_SLOT10_ALT:
209 case R_XTENSA_SLOT11_ALT:
210 case R_XTENSA_SLOT12_ALT:
211 case R_XTENSA_SLOT13_ALT:
212 case R_XTENSA_SLOT14_ALT:
213 printk("%s: unexpected ALT relocation: %u\n",
214 mod->name,
215 ELF32_R_TYPE(rela[i].r_info));
216 return -ENOEXEC;
217
218 default:
219 printk("%s: unexpected relocation: %u\n",
220 mod->name,
221 ELF32_R_TYPE(rela[i].r_info));
222 return -ENOEXEC;
223 }
224 }
225 return 0;
61} 226}
62 227
63int module_finalize(const Elf_Ehdr *hdr, 228int module_finalize(const Elf_Ehdr *hdr,
64 const Elf_Shdr *sechdrs, 229 const Elf_Shdr *sechdrs,
65 struct module *me) 230 struct module *mod)
66{ 231{
67 panic ("module_finalize not implemented"); 232 return 0;
68} 233}
69 234
70void module_arch_cleanup(struct module *mod) 235void module_arch_cleanup(struct module *mod)
71{ 236{
72 panic("module_arch_cleanup not implemented");
73}
74
75struct bug_entry *module_find_bug(unsigned long bugaddr)
76{
77 panic("module_find_bug not implemented");
78} 237}
diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c
index 77deae5290f0..b7c073484e01 100644
--- a/arch/xtensa/kernel/pci.c
+++ b/arch/xtensa/kernel/pci.c
@@ -394,72 +394,3 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
394 394
395 return ret; 395 return ret;
396} 396}
397
398/*
399 * This probably belongs here rather than ioport.c because
400 * we do not want this crud linked into SBus kernels.
401 * Also, think for a moment about likes of floppy.c that
402 * include architecture specific parts. They may want to redefine ins/outs.
403 *
404 * We do not use horrible macros here because we want to
405 * advance pointer by sizeof(size).
406 */
407void outsb(unsigned long addr, const void *src, unsigned long count) {
408 while (count) {
409 count -= 1;
410 writeb(*(const char *)src, addr);
411 src += 1;
412 addr += 1;
413 }
414}
415
416void outsw(unsigned long addr, const void *src, unsigned long count) {
417 while (count) {
418 count -= 2;
419 writew(*(const short *)src, addr);
420 src += 2;
421 addr += 2;
422 }
423}
424
425void outsl(unsigned long addr, const void *src, unsigned long count) {
426 while (count) {
427 count -= 4;
428 writel(*(const long *)src, addr);
429 src += 4;
430 addr += 4;
431 }
432}
433
434void insb(unsigned long addr, void *dst, unsigned long count) {
435 while (count) {
436 count -= 1;
437 *(unsigned char *)dst = readb(addr);
438 dst += 1;
439 addr += 1;
440 }
441}
442
443void insw(unsigned long addr, void *dst, unsigned long count) {
444 while (count) {
445 count -= 2;
446 *(unsigned short *)dst = readw(addr);
447 dst += 2;
448 addr += 2;
449 }
450}
451
452void insl(unsigned long addr, void *dst, unsigned long count) {
453 while (count) {
454 count -= 4;
455 /*
456 * XXX I am sure we are in for an unaligned trap here.
457 */
458 *(unsigned long *)dst = readl(addr);
459 dst += 4;
460 addr += 4;
461 }
462}
463
464
465
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c
index dd498f1604e1..f53d7bd9dfb2 100644
--- a/arch/xtensa/kernel/process.c
+++ b/arch/xtensa/kernel/process.c
@@ -46,20 +46,6 @@
46 46
47extern void ret_from_fork(void); 47extern void ret_from_fork(void);
48 48
49static struct fs_struct init_fs = INIT_FS;
50static struct files_struct init_files = INIT_FILES;
51static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
52static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
53struct mm_struct init_mm = INIT_MM(init_mm);
54EXPORT_SYMBOL(init_mm);
55
56union thread_union init_thread_union
57 __attribute__((__section__(".data.init_task"))) =
58{ INIT_THREAD_INFO(init_task) };
59
60struct task_struct init_task = INIT_TASK(init_task);
61EXPORT_SYMBOL(init_task);
62
63struct task_struct *current_set[NR_CPUS] = {&init_task, }; 49struct task_struct *current_set[NR_CPUS] = {&init_task, };
64 50
65void (*pm_power_off)(void) = NULL; 51void (*pm_power_off)(void) = NULL;
diff --git a/arch/xtensa/kernel/semaphore.c b/arch/xtensa/kernel/semaphore.c
index d40f4b1b75ac..995c6410ae10 100644
--- a/arch/xtensa/kernel/semaphore.c
+++ b/arch/xtensa/kernel/semaphore.c
@@ -100,7 +100,7 @@ static __inline__ int waking_non_zero_trylock(struct semaphore *sem)
100 return ret; 100 return ret;
101} 101}
102 102
103spinlock_t semaphore_wake_lock; 103DEFINE_SPINLOCK(semaphore_wake_lock);
104 104
105/* 105/*
106 * Semaphores are implemented using a two-way counter: 106 * Semaphores are implemented using a two-way counter:
diff --git a/arch/xtensa/kernel/syscall.c b/arch/xtensa/kernel/syscall.c
index fe3834bc1dbf..f3e16efcd47a 100644
--- a/arch/xtensa/kernel/syscall.c
+++ b/arch/xtensa/kernel/syscall.c
@@ -93,3 +93,8 @@ asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)
93 return (long)ret; 93 return (long)ret;
94} 94}
95 95
96asmlinkage long xtensa_fadvise64_64(int fd, int advice, unsigned long long offset, unsigned long long len)
97{
98 return sys_fadvise64_64(fd, offset, len, advice);
99}
100
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c
index 22949be4a5d8..60d29fe0b1bd 100644
--- a/arch/xtensa/kernel/time.c
+++ b/arch/xtensa/kernel/time.c
@@ -32,12 +32,20 @@ EXPORT_SYMBOL(rtc_lock);
32 32
33#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT 33#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
34unsigned long ccount_per_jiffy; /* per 1/HZ */ 34unsigned long ccount_per_jiffy; /* per 1/HZ */
35unsigned long ccount_nsec; /* nsec per ccount increment */ 35unsigned long nsec_per_ccount; /* nsec per ccount increment */
36#endif 36#endif
37 37
38unsigned int last_ccount_stamp;
39static long last_rtc_update = 0; 38static long last_rtc_update = 0;
40 39
40/*
41 * Scheduler clock - returns current tim in nanosec units.
42 */
43
44unsigned long long sched_clock(void)
45{
46 return (unsigned long long)jiffies * (1000000000 / HZ);
47}
48
41static irqreturn_t timer_interrupt(int irq, void *dev_id); 49static irqreturn_t timer_interrupt(int irq, void *dev_id);
42static struct irqaction timer_irqaction = { 50static struct irqaction timer_irqaction = {
43 .handler = timer_interrupt, 51 .handler = timer_interrupt,
@@ -69,7 +77,6 @@ void __init time_init(void)
69 77
70 xtime.tv_nsec = 0; 78 xtime.tv_nsec = 0;
71 last_rtc_update = xtime.tv_sec = sec_n; 79 last_rtc_update = xtime.tv_sec = sec_n;
72 last_ccount_stamp = get_ccount();
73 80
74 set_normalized_timespec(&wall_to_monotonic, 81 set_normalized_timespec(&wall_to_monotonic,
75 -xtime.tv_sec, -xtime.tv_nsec); 82 -xtime.tv_sec, -xtime.tv_nsec);
@@ -85,7 +92,7 @@ int do_settimeofday(struct timespec *tv)
85{ 92{
86 time_t wtm_sec, sec = tv->tv_sec; 93 time_t wtm_sec, sec = tv->tv_sec;
87 long wtm_nsec, nsec = tv->tv_nsec; 94 long wtm_nsec, nsec = tv->tv_nsec;
88 unsigned long ccount; 95 unsigned long delta;
89 96
90 if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) 97 if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
91 return -EINVAL; 98 return -EINVAL;
@@ -97,8 +104,10 @@ int do_settimeofday(struct timespec *tv)
97 * wall time. Discover what correction gettimeofday() would have 104 * wall time. Discover what correction gettimeofday() would have
98 * made, and then undo it! 105 * made, and then undo it!
99 */ 106 */
100 ccount = get_ccount(); 107
101 nsec -= (ccount - last_ccount_stamp) * CCOUNT_NSEC; 108 delta = CCOUNT_PER_JIFFY;
109 delta += get_ccount() - get_linux_timer();
110 nsec -= delta * NSEC_PER_CCOUNT;
102 111
103 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); 112 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
104 wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); 113 wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
@@ -117,17 +126,21 @@ EXPORT_SYMBOL(do_settimeofday);
117void do_gettimeofday(struct timeval *tv) 126void do_gettimeofday(struct timeval *tv)
118{ 127{
119 unsigned long flags; 128 unsigned long flags;
120 unsigned long sec, usec, delta, seq; 129 unsigned long volatile sec, usec, delta, seq;
121 130
122 do { 131 do {
123 seq = read_seqbegin_irqsave(&xtime_lock, flags); 132 seq = read_seqbegin_irqsave(&xtime_lock, flags);
124 133
125 delta = get_ccount() - last_ccount_stamp;
126 sec = xtime.tv_sec; 134 sec = xtime.tv_sec;
127 usec = (xtime.tv_nsec / NSEC_PER_USEC); 135 usec = (xtime.tv_nsec / NSEC_PER_USEC);
136
137 delta = get_linux_timer() - get_ccount();
138
128 } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); 139 } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
129 140
130 usec += (delta * CCOUNT_NSEC) / NSEC_PER_USEC; 141 usec += (((unsigned long) CCOUNT_PER_JIFFY - delta)
142 * (unsigned long) NSEC_PER_CCOUNT) / NSEC_PER_USEC;
143
131 for (; usec >= 1000000; sec++, usec -= 1000000) 144 for (; usec >= 1000000; sec++, usec -= 1000000)
132 ; 145 ;
133 146
@@ -158,9 +171,12 @@ again:
158 171
159 write_seqlock(&xtime_lock); 172 write_seqlock(&xtime_lock);
160 173
161 last_ccount_stamp = next; 174 do_timer(1); /* Linux handler in kernel/timer.c */
175
176 /* Note that writing CCOMPARE clears the interrupt. */
177
162 next += CCOUNT_PER_JIFFY; 178 next += CCOUNT_PER_JIFFY;
163 do_timer (1); /* Linux handler in kernel/timer.c */ 179 set_linux_timer(next);
164 180
165 if (ntp_synced() && 181 if (ntp_synced() &&
166 xtime.tv_sec - last_rtc_update >= 659 && 182 xtime.tv_sec - last_rtc_update >= 659 &&
@@ -175,19 +191,15 @@ again:
175 write_sequnlock(&xtime_lock); 191 write_sequnlock(&xtime_lock);
176 } 192 }
177 193
178 /* NOTE: writing CCOMPAREn clears the interrupt. */ 194 /* Allow platform to do something useful (Wdog). */
179 195
180 set_linux_timer (next); 196 platform_heartbeat();
181 197
182 /* Make sure we didn't miss any tick... */ 198 /* Make sure we didn't miss any tick... */
183 199
184 if ((signed long)(get_ccount() - next) > 0) 200 if ((signed long)(get_ccount() - next) > 0)
185 goto again; 201 goto again;
186 202
187 /* Allow platform to do something useful (Wdog). */
188
189 platform_heartbeat();
190
191 return IRQ_HANDLED; 203 return IRQ_HANDLED;
192} 204}
193 205
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index c5e62f9d9f50..8be99c777d9d 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -83,7 +83,7 @@ typedef struct {
83 void* handler; 83 void* handler;
84} dispatch_init_table_t; 84} dispatch_init_table_t;
85 85
86dispatch_init_table_t __init dispatch_init_table[] = { 86static dispatch_init_table_t __initdata dispatch_init_table[] = {
87 87
88{ EXCCAUSE_ILLEGAL_INSTRUCTION, 0, do_illegal_instruction}, 88{ EXCCAUSE_ILLEGAL_INSTRUCTION, 0, do_illegal_instruction},
89{ EXCCAUSE_SYSTEM_CALL, KRNL, fast_syscall_kernel }, 89{ EXCCAUSE_SYSTEM_CALL, KRNL, fast_syscall_kernel },
@@ -305,7 +305,7 @@ do_debug(struct pt_regs *regs)
305 305
306#define set_handler(idx,handler) (exc_table[idx] = (unsigned long) (handler)) 306#define set_handler(idx,handler) (exc_table[idx] = (unsigned long) (handler))
307 307
308void trap_init(void) 308void __init trap_init(void)
309{ 309{
310 int i; 310 int i;
311 311