aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-realview/realview_eb.c2
-rw-r--r--arch/arm/vfp/vfpmodule.c1
-rw-r--r--arch/blackfin/mach-common/pm.c6
-rw-r--r--arch/i386/xen/enlighten.c4
-rw-r--r--arch/mips/dec/setup.c2
-rw-r--r--arch/mips/kernel/cpu-bugs64.c4
-rw-r--r--arch/mips/kernel/cpu-probe.c9
-rw-r--r--arch/mips/kernel/rtlx.c4
-rw-r--r--arch/mips/kernel/scall64-n32.S2
-rw-r--r--arch/mips/kernel/time.c1
-rw-r--r--arch/mips/mips-boards/malta/malta_int.c2
-rw-r--r--arch/mips/mm/tlbex.c26
-rw-r--r--arch/powerpc/kernel/time.c8
-rw-r--r--arch/powerpc/kernel/vdso.c12
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c4
-rw-r--r--arch/sparc64/defconfig16
-rw-r--r--arch/sparc64/kernel/head.S35
-rw-r--r--arch/sparc64/kernel/mdesc.c6
-rw-r--r--arch/sparc64/kernel/prom.c6
-rw-r--r--arch/sparc64/kernel/trampoline.S33
-rw-r--r--arch/sparc64/prom/misc.c16
-rw-r--r--arch/um/include/kern_util.h2
-rw-r--r--arch/um/kernel/irq.c7
-rw-r--r--arch/um/os-Linux/file.c3
-rw-r--r--arch/um/os-Linux/signal.c4
-rw-r--r--arch/x86_64/mm/fault.c7
-rw-r--r--arch/xtensa/Makefile7
-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
-rw-r--r--arch/xtensa/mm/Makefile6
-rw-r--r--arch/xtensa/mm/cache.c256
-rw-r--r--arch/xtensa/mm/fault.c6
-rw-r--r--arch/xtensa/mm/init.c252
-rw-r--r--arch/xtensa/mm/misc.S306
-rw-r--r--arch/xtensa/platform-iss/console.c1
45 files changed, 1143 insertions, 491 deletions
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index 3dba666151db..ecec2f85c4cd 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -165,7 +165,7 @@ static void __init gic_init_irq(void)
165#endif 165#endif
166 gic_dist_init(0, __io_address(REALVIEW_GIC_DIST_BASE), 29); 166 gic_dist_init(0, __io_address(REALVIEW_GIC_DIST_BASE), 29);
167 gic_cpu_init(0, __io_address(REALVIEW_GIC_CPU_BASE)); 167 gic_cpu_init(0, __io_address(REALVIEW_GIC_CPU_BASE));
168#ifdef CONFIG_REALVIEW_MPCORE 168#if defined(CONFIG_REALVIEW_MPCORE) && !defined(CONFIG_REALVIEW_MPCORE_REVB)
169 gic_dist_init(1, __io_address(REALVIEW_GIC1_DIST_BASE), 64); 169 gic_dist_init(1, __io_address(REALVIEW_GIC1_DIST_BASE), 64);
170 gic_cpu_init(1, __io_address(REALVIEW_GIC1_CPU_BASE)); 170 gic_cpu_init(1, __io_address(REALVIEW_GIC1_CPU_BASE));
171 gic_cascade_irq(1, IRQ_EB_IRQ1); 171 gic_cascade_irq(1, IRQ_EB_IRQ1);
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 04ddab2bd876..eea3f50743d5 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -323,6 +323,7 @@ static int __init vfp_init(void)
323 * we just need to read the VFPSID register. 323 * we just need to read the VFPSID register.
324 */ 324 */
325 vfp_vector = vfp_testing_entry; 325 vfp_vector = vfp_testing_entry;
326 barrier();
326 vfpsid = fmrx(FPSID); 327 vfpsid = fmrx(FPSID);
327 barrier(); 328 barrier();
328 vfp_vector = vfp_null_entry; 329 vfp_vector = vfp_null_entry;
diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c
index 1772d8d2c1a7..b10302722202 100644
--- a/arch/blackfin/mach-common/pm.c
+++ b/arch/blackfin/mach-common/pm.c
@@ -158,10 +158,16 @@ static int bfin_pm_finish(suspend_state_t state)
158 return 0; 158 return 0;
159} 159}
160 160
161static int bfin_pm_valid(suspend_state_t state)
162{
163 return (state == PM_SUSPEND_STANDBY);
164}
165
161struct pm_ops bfin_pm_ops = { 166struct pm_ops bfin_pm_ops = {
162 .prepare = bfin_pm_prepare, 167 .prepare = bfin_pm_prepare,
163 .enter = bfin_pm_enter, 168 .enter = bfin_pm_enter,
164 .finish = bfin_pm_finish, 169 .finish = bfin_pm_finish,
170 .valid = bfin_pm_valid,
165}; 171};
166 172
167static int __init bfin_pm_init(void) 173static int __init bfin_pm_init(void)
diff --git a/arch/i386/xen/enlighten.c b/arch/i386/xen/enlighten.c
index f0c37511d8da..f01bfcd4bdee 100644
--- a/arch/i386/xen/enlighten.c
+++ b/arch/i386/xen/enlighten.c
@@ -623,8 +623,8 @@ static unsigned long xen_read_cr2_direct(void)
623 623
624static void xen_write_cr4(unsigned long cr4) 624static void xen_write_cr4(unsigned long cr4)
625{ 625{
626 /* never allow TSC to be disabled */ 626 /* Just ignore cr4 changes; Xen doesn't allow us to do
627 native_write_cr4(cr4 & ~X86_CR4_TSD); 627 anything anyway. */
628} 628}
629 629
630static unsigned long xen_read_cr3(void) 630static unsigned long xen_read_cr3(void)
diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c
index b8a5e75ba0ab..3e634f2f5443 100644
--- a/arch/mips/dec/setup.c
+++ b/arch/mips/dec/setup.c
@@ -55,7 +55,7 @@ EXPORT_SYMBOL(dec_kn_slot_size);
55 55
56int dec_tc_bus; 56int dec_tc_bus;
57 57
58spinlock_t ioasic_ssr_lock; 58DEFINE_SPINLOCK(ioasic_ssr_lock);
59 59
60volatile u32 *ioasic_base; 60volatile u32 *ioasic_base;
61 61
diff --git a/arch/mips/kernel/cpu-bugs64.c b/arch/mips/kernel/cpu-bugs64.c
index ac04f0adc408..6648fde20b96 100644
--- a/arch/mips/kernel/cpu-bugs64.c
+++ b/arch/mips/kernel/cpu-bugs64.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2003, 2004 Maciej W. Rozycki 2 * Copyright (C) 2003, 2004, 2007 Maciej W. Rozycki
3 * 3 *
4 * This program is free software; you can redistribute it and/or 4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License 5 * modify it under the terms of the GNU General Public License
@@ -29,7 +29,7 @@ static inline void align_mod(const int align, const int mod)
29 ".endr\n\t" 29 ".endr\n\t"
30 ".set pop" 30 ".set pop"
31 : 31 :
32 : "rn" (align), "rn" (mod)); 32 : GCC_IMM_ASM (align), GCC_IMM_ASM (mod));
33} 33}
34 34
35static inline void mult_sh_align_mod(long *v1, long *v2, long *w, 35static inline void mult_sh_align_mod(long *v1, long *v2, long *w,
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 06448a9656dc..3e004161ebd5 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -199,7 +199,14 @@ static inline void check_wait(void)
199 if ((c->processor_id & 0xff) <= 0x64) 199 if ((c->processor_id & 0xff) <= 0x64)
200 break; 200 break;
201 201
202 cpu_wait = r4k_wait; 202 /*
203 * Another rev is incremeting c0_count at a reduced clock
204 * rate while in WAIT mode. So we basically have the choice
205 * between using the cp0 timer as clocksource or avoiding
206 * the WAIT instruction. Until more details are known,
207 * disable the use of WAIT for 20Kc entirely.
208 cpu_wait = r4k_wait;
209 */
203 break; 210 break;
204 case CPU_RM9000: 211 case CPU_RM9000:
205 if ((c->processor_id & 0x00ff) >= 0x40) 212 if ((c->processor_id & 0x00ff) >= 0x40)
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index aab89e97abb5..1ba00c15505b 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -56,8 +56,6 @@ static struct chan_waitqueues {
56 struct mutex mutex; 56 struct mutex mutex;
57} channel_wqs[RTLX_CHANNELS]; 57} channel_wqs[RTLX_CHANNELS];
58 58
59static struct irqaction irq;
60static int irq_num;
61static struct vpe_notifications notify; 59static struct vpe_notifications notify;
62static int sp_stopping = 0; 60static int sp_stopping = 0;
63 61
@@ -111,7 +109,7 @@ static void __used dump_rtlx(void)
111static int rtlx_init(struct rtlx_info *rtlxi) 109static int rtlx_init(struct rtlx_info *rtlxi)
112{ 110{
113 if (rtlxi->id != RTLX_ID) { 111 if (rtlxi->id != RTLX_ID) {
114 printk(KERN_ERR "no valid RTLX id at 0x%p 0x%x\n", rtlxi, rtlxi->id); 112 printk(KERN_ERR "no valid RTLX id at 0x%p 0x%lx\n", rtlxi, rtlxi->id);
115 return -ENOEXEC; 113 return -ENOEXEC;
116 } 114 }
117 115
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 53d7a977193c..118be24224f2 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -375,7 +375,7 @@ EXPORT(sysn32_call_table)
375 PTR sys_mkdirat 375 PTR sys_mkdirat
376 PTR sys_mknodat 376 PTR sys_mknodat
377 PTR sys_fchownat 377 PTR sys_fchownat
378 PTR sys_futimesat /* 6255 */ 378 PTR compat_sys_futimesat /* 6255 */
379 PTR sys_newfstatat 379 PTR sys_newfstatat
380 PTR sys_unlinkat 380 PTR sys_unlinkat
381 PTR sys_renameat 381 PTR sys_renameat
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index d48d1d5bea0a..9a5596bf8571 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -16,6 +16,7 @@
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/sched.h> 17#include <linux/sched.h>
18#include <linux/param.h> 18#include <linux/param.h>
19#include <linux/profile.h>
19#include <linux/time.h> 20#include <linux/time.h>
20#include <linux/timex.h> 21#include <linux/timex.h>
21#include <linux/smp.h> 22#include <linux/smp.h>
diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c
index 97aeb8c4e601..b73f21823c5e 100644
--- a/arch/mips/mips-boards/malta/malta_int.c
+++ b/arch/mips/mips-boards/malta/malta_int.c
@@ -256,7 +256,7 @@ asmlinkage void plat_irq_dispatch(void)
256 256
257 if (irq == MIPSCPU_INT_I8259A) 257 if (irq == MIPSCPU_INT_I8259A)
258 malta_hw0_irqdispatch(); 258 malta_hw0_irqdispatch();
259 else if (irq > 0) 259 else if (irq >= 0)
260 do_IRQ(MIPS_CPU_IRQ_BASE + irq); 260 do_IRQ(MIPS_CPU_IRQ_BASE + irq);
261 else 261 else
262 spurious_interrupt(); 262 spurious_interrupt();
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 9cb39644b6f1..6c425b052442 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -58,6 +58,21 @@ static __init int __maybe_unused r10000_llsc_war(void)
58} 58}
59 59
60/* 60/*
61 * Found by experiment: At least some revisions of the 4kc throw under
62 * some circumstances a machine check exception, triggered by invalid
63 * values in the index register. Delaying the tlbp instruction until
64 * after the next branch, plus adding an additional nop in front of
65 * tlbwi/tlbwr avoids the invalid index register values. Nobody knows
66 * why; it's not an issue caused by the core RTL.
67 *
68 */
69static __init int __attribute__((unused)) m4kc_tlbp_war(void)
70{
71 return (current_cpu_data.processor_id & 0xffff00) ==
72 (PRID_COMP_MIPS | PRID_IMP_4KC);
73}
74
75/*
61 * A little micro-assembler, intended for TLB refill handler 76 * A little micro-assembler, intended for TLB refill handler
62 * synthesizing. It is intentionally kept simple, does only support 77 * synthesizing. It is intentionally kept simple, does only support
63 * a subset of instructions, and does not try to hide pipeline effects 78 * a subset of instructions, and does not try to hide pipeline effects
@@ -894,6 +909,8 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l,
894 case CPU_20KC: 909 case CPU_20KC:
895 case CPU_25KF: 910 case CPU_25KF:
896 case CPU_LOONGSON2: 911 case CPU_LOONGSON2:
912 if (m4kc_tlbp_war())
913 i_nop(p);
897 tlbw(p); 914 tlbw(p);
898 break; 915 break;
899 916
@@ -1705,7 +1722,8 @@ build_r4000_tlbchange_handler_head(u32 **p, struct label **l,
1705 l_smp_pgtable_change(l, *p); 1722 l_smp_pgtable_change(l, *p);
1706# endif 1723# endif
1707 iPTE_LW(p, l, pte, ptr); /* get even pte */ 1724 iPTE_LW(p, l, pte, ptr); /* get even pte */
1708 build_tlb_probe_entry(p); 1725 if (!m4kc_tlbp_war())
1726 build_tlb_probe_entry(p);
1709} 1727}
1710 1728
1711static void __init 1729static void __init
@@ -1747,6 +1765,8 @@ static void __init build_r4000_tlb_load_handler(void)
1747 1765
1748 build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1); 1766 build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
1749 build_pte_present(&p, &l, &r, K0, K1, label_nopage_tlbl); 1767 build_pte_present(&p, &l, &r, K0, K1, label_nopage_tlbl);
1768 if (m4kc_tlbp_war())
1769 build_tlb_probe_entry(&p);
1750 build_make_valid(&p, &r, K0, K1); 1770 build_make_valid(&p, &r, K0, K1);
1751 build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1); 1771 build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
1752 1772
@@ -1781,6 +1801,8 @@ static void __init build_r4000_tlb_store_handler(void)
1781 1801
1782 build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1); 1802 build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
1783 build_pte_writable(&p, &l, &r, K0, K1, label_nopage_tlbs); 1803 build_pte_writable(&p, &l, &r, K0, K1, label_nopage_tlbs);
1804 if (m4kc_tlbp_war())
1805 build_tlb_probe_entry(&p);
1784 build_make_write(&p, &r, K0, K1); 1806 build_make_write(&p, &r, K0, K1);
1785 build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1); 1807 build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
1786 1808
@@ -1815,6 +1837,8 @@ static void __init build_r4000_tlb_modify_handler(void)
1815 1837
1816 build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1); 1838 build_r4000_tlbchange_handler_head(&p, &l, &r, K0, K1);
1817 build_pte_modifiable(&p, &l, &r, K0, K1, label_nopage_tlbm); 1839 build_pte_modifiable(&p, &l, &r, K0, K1, label_nopage_tlbm);
1840 if (m4kc_tlbp_war())
1841 build_tlb_probe_entry(&p);
1818 /* Present and writable bits set, set accessed and dirty bits. */ 1842 /* Present and writable bits set, set accessed and dirty bits. */
1819 build_make_write(&p, &r, K0, K1); 1843 build_make_write(&p, &r, K0, K1);
1820 build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1); 1844 build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index b5944d8e3802..d95e68c0a6b3 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -238,7 +238,7 @@ static void snapshot_tb_and_purr(void *data)
238 struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data); 238 struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data);
239 239
240 local_irq_save(flags); 240 local_irq_save(flags);
241 p->tb = mftb(); 241 p->tb = get_tb_or_rtc();
242 p->purr = mfspr(SPRN_PURR); 242 p->purr = mfspr(SPRN_PURR);
243 wmb(); 243 wmb();
244 p->initialized = 1; 244 p->initialized = 1;
@@ -316,7 +316,7 @@ static void snapshot_purr(void)
316 */ 316 */
317void snapshot_timebase(void) 317void snapshot_timebase(void)
318{ 318{
319 __get_cpu_var(last_jiffy) = get_tb(); 319 __get_cpu_var(last_jiffy) = get_tb_or_rtc();
320 snapshot_purr(); 320 snapshot_purr();
321} 321}
322 322
@@ -683,6 +683,8 @@ void timer_interrupt(struct pt_regs * regs)
683 683
684 write_seqlock(&xtime_lock); 684 write_seqlock(&xtime_lock);
685 tb_next_jiffy = tb_last_jiffy + tb_ticks_per_jiffy; 685 tb_next_jiffy = tb_last_jiffy + tb_ticks_per_jiffy;
686 if (__USE_RTC() && tb_next_jiffy >= 1000000000)
687 tb_next_jiffy -= 1000000000;
686 if (per_cpu(last_jiffy, cpu) >= tb_next_jiffy) { 688 if (per_cpu(last_jiffy, cpu) >= tb_next_jiffy) {
687 tb_last_jiffy = tb_next_jiffy; 689 tb_last_jiffy = tb_next_jiffy;
688 do_timer(1); 690 do_timer(1);
@@ -976,7 +978,7 @@ void __init time_init(void)
976 tb_to_ns_scale = scale; 978 tb_to_ns_scale = scale;
977 tb_to_ns_shift = shift; 979 tb_to_ns_shift = shift;
978 /* Save the current timebase to pretty up CONFIG_PRINTK_TIME */ 980 /* Save the current timebase to pretty up CONFIG_PRINTK_TIME */
979 boot_tb = get_tb(); 981 boot_tb = get_tb_or_rtc();
980 982
981 tm = get_boot_time(); 983 tm = get_boot_time();
982 984
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index cef01e4e8989..213fa31ac537 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -98,6 +98,18 @@ static struct vdso_patch_def vdso_patches[] = {
98 CPU_FTR_USE_TB, 0, 98 CPU_FTR_USE_TB, 0,
99 "__kernel_gettimeofday", NULL 99 "__kernel_gettimeofday", NULL
100 }, 100 },
101 {
102 CPU_FTR_USE_TB, 0,
103 "__kernel_clock_gettime", NULL
104 },
105 {
106 CPU_FTR_USE_TB, 0,
107 "__kernel_clock_getres", NULL
108 },
109 {
110 CPU_FTR_USE_TB, 0,
111 "__kernel_get_tbfreq", NULL
112 },
101}; 113};
102 114
103/* 115/*
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 17806e001e50..4d257b3f9336 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -594,7 +594,7 @@ static struct spu *find_victim(struct spu_context *ctx)
594 list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list) { 594 list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list) {
595 struct spu_context *tmp = spu->ctx; 595 struct spu_context *tmp = spu->ctx;
596 596
597 if (tmp->prio > ctx->prio && 597 if (tmp && tmp->prio > ctx->prio &&
598 (!victim || tmp->prio > victim->prio)) 598 (!victim || tmp->prio > victim->prio))
599 victim = spu->ctx; 599 victim = spu->ctx;
600 } 600 }
@@ -626,9 +626,9 @@ static struct spu *find_victim(struct spu_context *ctx)
626 626
627 mutex_lock(&cbe_spu_info[node].list_mutex); 627 mutex_lock(&cbe_spu_info[node].list_mutex);
628 cbe_spu_info[node].nr_active--; 628 cbe_spu_info[node].nr_active--;
629 spu_unbind_context(spu, victim);
629 mutex_unlock(&cbe_spu_info[node].list_mutex); 630 mutex_unlock(&cbe_spu_info[node].list_mutex);
630 631
631 spu_unbind_context(spu, victim);
632 victim->stats.invol_ctx_switch++; 632 victim->stats.invol_ctx_switch++;
633 spu->stats.invol_ctx_switch++; 633 spu->stats.invol_ctx_switch++;
634 mutex_unlock(&victim->state_mutex); 634 mutex_unlock(&victim->state_mutex);
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 68338a601f70..7d07297db878 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -1,7 +1,7 @@
1# 1#
2# Automatically generated make config: don't edit 2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.23-rc1 3# Linux kernel version: 2.6.23-rc6
4# Sun Jul 22 19:24:37 2007 4# Sun Sep 16 09:52:11 2007
5# 5#
6CONFIG_SPARC=y 6CONFIG_SPARC=y
7CONFIG_SPARC64=y 7CONFIG_SPARC64=y
@@ -32,15 +32,11 @@ CONFIG_HZ=100
32CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" 32CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
33 33
34# 34#
35# Code maturity level options 35# General setup
36# 36#
37CONFIG_EXPERIMENTAL=y 37CONFIG_EXPERIMENTAL=y
38CONFIG_BROKEN_ON_SMP=y 38CONFIG_BROKEN_ON_SMP=y
39CONFIG_INIT_ENV_ARG_LIMIT=32 39CONFIG_INIT_ENV_ARG_LIMIT=32
40
41#
42# General setup
43#
44CONFIG_LOCALVERSION="" 40CONFIG_LOCALVERSION=""
45# CONFIG_LOCALVERSION_AUTO is not set 41# CONFIG_LOCALVERSION_AUTO is not set
46CONFIG_SWAP=y 42CONFIG_SWAP=y
@@ -555,6 +551,7 @@ CONFIG_E1000_NAPI=y
555# CONFIG_SIS190 is not set 551# CONFIG_SIS190 is not set
556# CONFIG_SKGE is not set 552# CONFIG_SKGE is not set
557# CONFIG_SKY2 is not set 553# CONFIG_SKY2 is not set
554# CONFIG_SK98LIN is not set
558# CONFIG_VIA_VELOCITY is not set 555# CONFIG_VIA_VELOCITY is not set
559CONFIG_TIGON3=m 556CONFIG_TIGON3=m
560CONFIG_BNX2=m 557CONFIG_BNX2=m
@@ -809,6 +806,7 @@ CONFIG_HWMON=y
809# CONFIG_SENSORS_SMSC47M1 is not set 806# CONFIG_SENSORS_SMSC47M1 is not set
810# CONFIG_SENSORS_SMSC47M192 is not set 807# CONFIG_SENSORS_SMSC47M192 is not set
811# CONFIG_SENSORS_SMSC47B397 is not set 808# CONFIG_SENSORS_SMSC47B397 is not set
809# CONFIG_SENSORS_THMC50 is not set
812# CONFIG_SENSORS_VIA686A is not set 810# CONFIG_SENSORS_VIA686A is not set
813# CONFIG_SENSORS_VT1211 is not set 811# CONFIG_SENSORS_VT1211 is not set
814# CONFIG_SENSORS_VT8231 is not set 812# CONFIG_SENSORS_VT8231 is not set
@@ -1162,10 +1160,6 @@ CONFIG_USB_STORAGE=m
1162# CONFIG_MMC is not set 1160# CONFIG_MMC is not set
1163# CONFIG_NEW_LEDS is not set 1161# CONFIG_NEW_LEDS is not set
1164# CONFIG_INFINIBAND is not set 1162# CONFIG_INFINIBAND is not set
1165
1166#
1167# Real Time Clock
1168#
1169# CONFIG_RTC_CLASS is not set 1163# CONFIG_RTC_CLASS is not set
1170 1164
1171# 1165#
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
index 63144ad476f6..c4147ad8677b 100644
--- a/arch/sparc64/kernel/head.S
+++ b/arch/sparc64/kernel/head.S
@@ -98,7 +98,7 @@ sparc64_boot:
98 .globl prom_boot_mapped_pc, prom_boot_mapping_mode 98 .globl prom_boot_mapped_pc, prom_boot_mapping_mode
99 .globl prom_boot_mapping_phys_high, prom_boot_mapping_phys_low 99 .globl prom_boot_mapping_phys_high, prom_boot_mapping_phys_low
100 .globl prom_compatible_name, prom_cpu_path, prom_cpu_compatible 100 .globl prom_compatible_name, prom_cpu_path, prom_cpu_compatible
101 .globl is_sun4v, sun4v_chip_type 101 .globl is_sun4v, sun4v_chip_type, prom_set_trap_table_name
102prom_peer_name: 102prom_peer_name:
103 .asciz "peer" 103 .asciz "peer"
104prom_compatible_name: 104prom_compatible_name:
@@ -121,6 +121,8 @@ prom_map_name:
121 .asciz "map" 121 .asciz "map"
122prom_unmap_name: 122prom_unmap_name:
123 .asciz "unmap" 123 .asciz "unmap"
124prom_set_trap_table_name:
125 .asciz "SUNW,set-trap-table"
124prom_sun4v_name: 126prom_sun4v_name:
125 .asciz "sun4v" 127 .asciz "sun4v"
126prom_niagara_prefix: 128prom_niagara_prefix:
@@ -691,15 +693,38 @@ setup_trap_table:
691 sethi %hi(kern_base), %g3 693 sethi %hi(kern_base), %g3
692 ldx [%g3 + %lo(kern_base)], %g3 694 ldx [%g3 + %lo(kern_base)], %g3
693 add %g2, %g3, %o1 695 add %g2, %g3, %o1
696 sethi %hi(sparc64_ttable_tl0), %o0
694 697
695 call prom_set_trap_table_sun4v 698 set prom_set_trap_table_name, %g2
696 sethi %hi(sparc64_ttable_tl0), %o0 699 stx %g2, [%sp + 2047 + 128 + 0x00]
700 mov 2, %g2
701 stx %g2, [%sp + 2047 + 128 + 0x08]
702 mov 0, %g2
703 stx %g2, [%sp + 2047 + 128 + 0x10]
704 stx %o0, [%sp + 2047 + 128 + 0x18]
705 stx %o1, [%sp + 2047 + 128 + 0x20]
706 sethi %hi(p1275buf), %g2
707 or %g2, %lo(p1275buf), %g2
708 ldx [%g2 + 0x08], %o1
709 call %o1
710 add %sp, (2047 + 128), %o0
697 711
698 ba,pt %xcc, 2f 712 ba,pt %xcc, 2f
699 nop 713 nop
700 714
7011: call prom_set_trap_table 7151: sethi %hi(sparc64_ttable_tl0), %o0
702 sethi %hi(sparc64_ttable_tl0), %o0 716 set prom_set_trap_table_name, %g2
717 stx %g2, [%sp + 2047 + 128 + 0x00]
718 mov 1, %g2
719 stx %g2, [%sp + 2047 + 128 + 0x08]
720 mov 0, %g2
721 stx %g2, [%sp + 2047 + 128 + 0x10]
722 stx %o0, [%sp + 2047 + 128 + 0x18]
723 sethi %hi(p1275buf), %g2
724 or %g2, %lo(p1275buf), %g2
725 ldx [%g2 + 0x08], %o1
726 call %o1
727 add %sp, (2047 + 128), %o0
703 728
704 /* Start using proper page size encodings in ctx register. */ 729 /* Start using proper page size encodings in ctx register. */
7052: sethi %hi(sparc64_kern_pri_context), %g3 7302: sethi %hi(sparc64_kern_pri_context), %g3
diff --git a/arch/sparc64/kernel/mdesc.c b/arch/sparc64/kernel/mdesc.c
index 9f22e4ff6015..856659bb1311 100644
--- a/arch/sparc64/kernel/mdesc.c
+++ b/arch/sparc64/kernel/mdesc.c
@@ -777,8 +777,12 @@ void __devinit mdesc_fill_in_cpu_data(cpumask_t mask)
777 cpuid = *id; 777 cpuid = *id;
778 778
779#ifdef CONFIG_SMP 779#ifdef CONFIG_SMP
780 if (cpuid >= NR_CPUS) 780 if (cpuid >= NR_CPUS) {
781 printk(KERN_WARNING "Ignoring CPU %d which is "
782 ">= NR_CPUS (%d)\n",
783 cpuid, NR_CPUS);
781 continue; 784 continue;
785 }
782 if (!cpu_isset(cpuid, mask)) 786 if (!cpu_isset(cpuid, mask))
783 continue; 787 continue;
784#else 788#else
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c
index d1a78c976cef..0614dff63d7c 100644
--- a/arch/sparc64/kernel/prom.c
+++ b/arch/sparc64/kernel/prom.c
@@ -1583,8 +1583,12 @@ static void __init of_fill_in_cpu_data(void)
1583 ncpus_probed++; 1583 ncpus_probed++;
1584 1584
1585#ifdef CONFIG_SMP 1585#ifdef CONFIG_SMP
1586 if (cpuid >= NR_CPUS) 1586 if (cpuid >= NR_CPUS) {
1587 printk(KERN_WARNING "Ignoring CPU %d which is "
1588 ">= NR_CPUS (%d)\n",
1589 cpuid, NR_CPUS);
1587 continue; 1590 continue;
1591 }
1588#else 1592#else
1589 /* On uniprocessor we only want the values for the 1593 /* On uniprocessor we only want the values for the
1590 * real physical cpu the kernel booted onto, however 1594 * real physical cpu the kernel booted onto, however
diff --git a/arch/sparc64/kernel/trampoline.S b/arch/sparc64/kernel/trampoline.S
index 9533a25ce5d2..04e81dda13d0 100644
--- a/arch/sparc64/kernel/trampoline.S
+++ b/arch/sparc64/kernel/trampoline.S
@@ -345,7 +345,7 @@ after_lock_tlb:
345 sethi %hi(tramp_stack), %g1 345 sethi %hi(tramp_stack), %g1
346 or %g1, %lo(tramp_stack), %g1 346 or %g1, %lo(tramp_stack), %g1
347 add %g1, TRAMP_STACK_SIZE, %g1 347 add %g1, TRAMP_STACK_SIZE, %g1
348 sub %g1, STACKFRAME_SZ + STACK_BIAS, %sp 348 sub %g1, STACKFRAME_SZ + STACK_BIAS + 256, %sp
349 mov 0, %fp 349 mov 0, %fp
350 350
351 /* Put garbage in these registers to trap any access to them. */ 351 /* Put garbage in these registers to trap any access to them. */
@@ -411,15 +411,38 @@ after_lock_tlb:
411 sethi %hi(kern_base), %g3 411 sethi %hi(kern_base), %g3
412 ldx [%g3 + %lo(kern_base)], %g3 412 ldx [%g3 + %lo(kern_base)], %g3
413 add %g2, %g3, %o1 413 add %g2, %g3, %o1
414 sethi %hi(sparc64_ttable_tl0), %o0
414 415
415 call prom_set_trap_table_sun4v 416 set prom_set_trap_table_name, %g2
416 sethi %hi(sparc64_ttable_tl0), %o0 417 stx %g2, [%sp + 2047 + 128 + 0x00]
418 mov 2, %g2
419 stx %g2, [%sp + 2047 + 128 + 0x08]
420 mov 0, %g2
421 stx %g2, [%sp + 2047 + 128 + 0x10]
422 stx %o0, [%sp + 2047 + 128 + 0x18]
423 stx %o1, [%sp + 2047 + 128 + 0x20]
424 sethi %hi(p1275buf), %g2
425 or %g2, %lo(p1275buf), %g2
426 ldx [%g2 + 0x08], %o1
427 call %o1
428 add %sp, (2047 + 128), %o0
417 429
418 ba,pt %xcc, 2f 430 ba,pt %xcc, 2f
419 nop 431 nop
420 432
4211: call prom_set_trap_table 4331: sethi %hi(sparc64_ttable_tl0), %o0
422 sethi %hi(sparc64_ttable_tl0), %o0 434 set prom_set_trap_table_name, %g2
435 stx %g2, [%sp + 2047 + 128 + 0x00]
436 mov 1, %g2
437 stx %g2, [%sp + 2047 + 128 + 0x08]
438 mov 0, %g2
439 stx %g2, [%sp + 2047 + 128 + 0x10]
440 stx %o0, [%sp + 2047 + 128 + 0x18]
441 sethi %hi(p1275buf), %g2
442 or %g2, %lo(p1275buf), %g2
443 ldx [%g2 + 0x08], %o1
444 call %o1
445 add %sp, (2047 + 128), %o0
423 446
4242: ldx [%l0], %g6 4472: ldx [%l0], %g6
425 ldx [%g6 + TI_TASK], %g4 448 ldx [%g6 + TI_TASK], %g4
diff --git a/arch/sparc64/prom/misc.c b/arch/sparc64/prom/misc.c
index 68c83ad04ad9..bbec7522826c 100644
--- a/arch/sparc64/prom/misc.c
+++ b/arch/sparc64/prom/misc.c
@@ -143,22 +143,6 @@ unsigned char prom_get_idprom(char *idbuf, int num_bytes)
143 return 0xff; 143 return 0xff;
144} 144}
145 145
146/* Install Linux trap table so PROM uses that instead of its own. */
147void prom_set_trap_table(unsigned long tba)
148{
149 p1275_cmd("SUNW,set-trap-table",
150 (P1275_ARG(0, P1275_ARG_IN_64B) |
151 P1275_INOUT(1, 0)), tba);
152}
153
154void prom_set_trap_table_sun4v(unsigned long tba, unsigned long mmfsa)
155{
156 p1275_cmd("SUNW,set-trap-table",
157 (P1275_ARG(0, P1275_ARG_IN_64B) |
158 P1275_ARG(1, P1275_ARG_IN_64B) |
159 P1275_INOUT(2, 0)), tba, mmfsa);
160}
161
162int prom_get_mmu_ihandle(void) 146int prom_get_mmu_ihandle(void)
163{ 147{
164 int node, ret; 148 int node, ret;
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index 8d7f7c1cb9c6..6c2be26f1d7d 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -117,7 +117,7 @@ extern void sigio_handler(int sig, union uml_pt_regs *regs);
117 117
118extern void copy_sc(union uml_pt_regs *regs, void *from); 118extern void copy_sc(union uml_pt_regs *regs, void *from);
119 119
120unsigned long to_irq_stack(int sig, unsigned long *mask_out); 120extern unsigned long to_irq_stack(unsigned long *mask_out);
121unsigned long from_irq_stack(int nested); 121unsigned long from_irq_stack(int nested);
122 122
123#endif 123#endif
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index 9870febdbead..cf0dd9cf8c43 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -518,13 +518,13 @@ int init_aio_irq(int irq, char *name, irq_handler_t handler)
518 518
519static unsigned long pending_mask; 519static unsigned long pending_mask;
520 520
521unsigned long to_irq_stack(int sig, unsigned long *mask_out) 521unsigned long to_irq_stack(unsigned long *mask_out)
522{ 522{
523 struct thread_info *ti; 523 struct thread_info *ti;
524 unsigned long mask, old; 524 unsigned long mask, old;
525 int nested; 525 int nested;
526 526
527 mask = xchg(&pending_mask, 1 << sig); 527 mask = xchg(&pending_mask, *mask_out);
528 if(mask != 0){ 528 if(mask != 0){
529 /* If any interrupts come in at this point, we want to 529 /* If any interrupts come in at this point, we want to
530 * make sure that their bits aren't lost by our 530 * make sure that their bits aren't lost by our
@@ -534,7 +534,7 @@ unsigned long to_irq_stack(int sig, unsigned long *mask_out)
534 * and pending_mask contains a bit for each interrupt 534 * and pending_mask contains a bit for each interrupt
535 * that came in. 535 * that came in.
536 */ 536 */
537 old = 1 << sig; 537 old = *mask_out;
538 do { 538 do {
539 old |= mask; 539 old |= mask;
540 mask = xchg(&pending_mask, old); 540 mask = xchg(&pending_mask, old);
@@ -550,6 +550,7 @@ unsigned long to_irq_stack(int sig, unsigned long *mask_out)
550 550
551 task = cpu_tasks[ti->cpu].task; 551 task = cpu_tasks[ti->cpu].task;
552 tti = task_thread_info(task); 552 tti = task_thread_info(task);
553
553 *ti = *tti; 554 *ti = *tti;
554 ti->real_thread = tti; 555 ti->real_thread = tti;
555 task->stack = ti; 556 task->stack = ti;
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index 6f92f732d253..c3ecc2a84e0c 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -320,7 +320,8 @@ int os_file_size(char *file, unsigned long long *size_out)
320 } 320 }
321 321
322 if(S_ISBLK(buf.ust_mode)){ 322 if(S_ISBLK(buf.ust_mode)){
323 int fd, blocks; 323 int fd;
324 long blocks;
324 325
325 fd = os_open_file(file, of_read(OPENFLAGS()), 0); 326 fd = os_open_file(file, of_read(OPENFLAGS()), 0);
326 if(fd < 0){ 327 if(fd < 0){
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index 18e5c8b67eb8..b98f7ea2d2f6 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -119,7 +119,7 @@ void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
119 119
120void handle_signal(int sig, struct sigcontext *sc) 120void handle_signal(int sig, struct sigcontext *sc)
121{ 121{
122 unsigned long pending = 0; 122 unsigned long pending = 1UL << sig;
123 123
124 do { 124 do {
125 int nested, bail; 125 int nested, bail;
@@ -134,7 +134,7 @@ void handle_signal(int sig, struct sigcontext *sc)
134 * have to return, and the upper handler will deal 134 * have to return, and the upper handler will deal
135 * with this interrupt. 135 * with this interrupt.
136 */ 136 */
137 bail = to_irq_stack(sig, &pending); 137 bail = to_irq_stack(&pending);
138 if(bail) 138 if(bail)
139 return; 139 return;
140 140
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c
index 327c9f2fa626..54816adb8e93 100644
--- a/arch/x86_64/mm/fault.c
+++ b/arch/x86_64/mm/fault.c
@@ -374,6 +374,13 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
374 if (unlikely(in_atomic() || !mm)) 374 if (unlikely(in_atomic() || !mm))
375 goto bad_area_nosemaphore; 375 goto bad_area_nosemaphore;
376 376
377 /*
378 * User-mode registers count as a user access even for any
379 * potential system fault or CPU buglet.
380 */
381 if (user_mode_vm(regs))
382 error_code |= PF_USER;
383
377 again: 384 again:
378 /* When running in the kernel we expect faults to occur only to 385 /* When running in the kernel we expect faults to occur only to
379 * addresses in user space. All other faults represent errors in the 386 * addresses in user space. All other faults represent errors in the
diff --git a/arch/xtensa/Makefile b/arch/xtensa/Makefile
index 95f836db38fa..acf05be24929 100644
--- a/arch/xtensa/Makefile
+++ b/arch/xtensa/Makefile
@@ -27,7 +27,12 @@ platform-$(CONFIG_XTENSA_PLATFORM_ISS) := iss
27PLATFORM = $(platform-y) 27PLATFORM = $(platform-y)
28export PLATFORM 28export PLATFORM
29 29
30CFLAGS += -pipe -mlongcalls 30# temporarily until string.h is fixed
31cflags-y += -ffreestanding
32
33cflags-y += -pipe -mlongcalls
34
35CFLAGS += $(cflags-y)
31 36
32KBUILD_DEFCONFIG := iss_defconfig 37KBUILD_DEFCONFIG := iss_defconfig
33 38
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
diff --git a/arch/xtensa/mm/Makefile b/arch/xtensa/mm/Makefile
index a5aed5932d7b..10aec22a8f98 100644
--- a/arch/xtensa/mm/Makefile
+++ b/arch/xtensa/mm/Makefile
@@ -5,9 +5,5 @@
5# removes any old dependencies. DON'T put your own dependencies here 5# removes any old dependencies. DON'T put your own dependencies here
6# unless it's something special (ie not a .c file). 6# unless it's something special (ie not a .c file).
7# 7#
8# Note 2! The CFLAGS definition is now in the main makefile...
9 8
10obj-y := init.o fault.o tlb.o misc.o 9obj-y := init.o fault.o tlb.o misc.o cache.o
11obj-m :=
12obj-n :=
13obj- :=
diff --git a/arch/xtensa/mm/cache.c b/arch/xtensa/mm/cache.c
new file mode 100644
index 000000000000..9a1fa9478ae7
--- /dev/null
+++ b/arch/xtensa/mm/cache.c
@@ -0,0 +1,256 @@
1/*
2 * arch/xtensa/mm/cache.c
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2001-2006 Tensilica Inc.
9 *
10 * Chris Zankel <chris@zankel.net>
11 * Joe Taylor
12 * Marc Gauthier
13 *
14 */
15
16#include <linux/init.h>
17#include <linux/signal.h>
18#include <linux/sched.h>
19#include <linux/kernel.h>
20#include <linux/errno.h>
21#include <linux/string.h>
22#include <linux/types.h>
23#include <linux/ptrace.h>
24#include <linux/bootmem.h>
25#include <linux/swap.h>
26#include <linux/pagemap.h>
27
28#include <asm/pgtable.h>
29#include <asm/bootparam.h>
30#include <asm/mmu_context.h>
31#include <asm/tlb.h>
32#include <asm/tlbflush.h>
33#include <asm/page.h>
34#include <asm/pgalloc.h>
35#include <asm/pgtable.h>
36
37//#define printd(x...) printk(x)
38#define printd(x...) do { } while(0)
39
40/*
41 * Note:
42 * The kernel provides one architecture bit PG_arch_1 in the page flags that
43 * can be used for cache coherency.
44 *
45 * I$-D$ coherency.
46 *
47 * The Xtensa architecture doesn't keep the instruction cache coherent with
48 * the data cache. We use the architecture bit to indicate if the caches
49 * are coherent. The kernel clears this bit whenever a page is added to the
50 * page cache. At that time, the caches might not be in sync. We, therefore,
51 * define this flag as 'clean' if set.
52 *
53 * D-cache aliasing.
54 *
55 * With cache aliasing, we have to always flush the cache when pages are
56 * unmapped (see tlb_start_vma(). So, we use this flag to indicate a dirty
57 * page.
58 *
59 *
60 *
61 */
62
63#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
64
65/*
66 * Any time the kernel writes to a user page cache page, or it is about to
67 * read from a page cache page this routine is called.
68 *
69 */
70
71void flush_dcache_page(struct page *page)
72{
73 struct address_space *mapping = page_mapping(page);
74
75 /*
76 * If we have a mapping but the page is not mapped to user-space
77 * yet, we simply mark this page dirty and defer flushing the
78 * caches until update_mmu().
79 */
80
81 if (mapping && !mapping_mapped(mapping)) {
82 if (!test_bit(PG_arch_1, &page->flags))
83 set_bit(PG_arch_1, &page->flags);
84 return;
85
86 } else {
87
88 unsigned long phys = page_to_phys(page);
89 unsigned long temp = page->index << PAGE_SHIFT;
90 unsigned long alias = !(DCACHE_ALIAS_EQ(temp, phys));
91 unsigned long virt;
92
93 /*
94 * Flush the page in kernel space and user space.
95 * Note that we can omit that step if aliasing is not
96 * an issue, but we do have to synchronize I$ and D$
97 * if we have a mapping.
98 */
99
100 if (!alias && !mapping)
101 return;
102
103 __flush_invalidate_dcache_page((long)page_address(page));
104
105 virt = TLBTEMP_BASE_1 + (temp & DCACHE_ALIAS_MASK);
106
107 if (alias)
108 __flush_invalidate_dcache_page_alias(virt, phys);
109
110 if (mapping)
111 __invalidate_icache_page_alias(virt, phys);
112 }
113
114 /* There shouldn't be an entry in the cache for this page anymore. */
115}
116
117
118/*
119 * For now, flush the whole cache. FIXME??
120 */
121
122void flush_cache_range(struct vm_area_struct* vma,
123 unsigned long start, unsigned long end)
124{
125 __flush_invalidate_dcache_all();
126 __invalidate_icache_all();
127}
128
129/*
130 * Remove any entry in the cache for this page.
131 *
132 * Note that this function is only called for user pages, so use the
133 * alias versions of the cache flush functions.
134 */
135
136void flush_cache_page(struct vm_area_struct* vma, unsigned long address,
137 unsigned long pfn)
138{
139 /* Note that we have to use the 'alias' address to avoid multi-hit */
140
141 unsigned long phys = page_to_phys(pfn_to_page(pfn));
142 unsigned long virt = TLBTEMP_BASE_1 + (address & DCACHE_ALIAS_MASK);
143
144 __flush_invalidate_dcache_page_alias(virt, phys);
145 __invalidate_icache_page_alias(virt, phys);
146}
147
148#endif
149
150void
151update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t pte)
152{
153 unsigned long pfn = pte_pfn(pte);
154 struct page *page;
155
156 if (!pfn_valid(pfn))
157 return;
158
159 page = pfn_to_page(pfn);
160
161 /* Invalidate old entry in TLBs */
162
163 invalidate_itlb_mapping(addr);
164 invalidate_dtlb_mapping(addr);
165
166#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
167
168 if (!PageReserved(page) && test_bit(PG_arch_1, &page->flags)) {
169
170 unsigned long vaddr = TLBTEMP_BASE_1 + (addr & DCACHE_ALIAS_MASK);
171 unsigned long paddr = (unsigned long) page_address(page);
172 unsigned long phys = page_to_phys(page);
173
174 __flush_invalidate_dcache_page(paddr);
175
176 __flush_invalidate_dcache_page_alias(vaddr, phys);
177 __invalidate_icache_page_alias(vaddr, phys);
178
179 clear_bit(PG_arch_1, &page->flags);
180 }
181#else
182 if (!PageReserved(page) && !test_bit(PG_arch_1, &page->flags)
183 && (vma->vm_flags & VM_EXEC) != 0) {
184 unsigned long vaddr = addr & PAGE_MASK;
185 __flush_dcache_page(vaddr);
186 __invalidate_icache_page(vaddr);
187 set_bit(PG_arch_1, &page->flags);
188 }
189#endif
190}
191
192/*
193 * access_process_vm() has called get_user_pages(), which has done a
194 * flush_dcache_page() on the page.
195 */
196
197#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
198
199void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
200 unsigned long vaddr, void *dst, const void *src,
201 unsigned long len)
202{
203 unsigned long phys = page_to_phys(page);
204 unsigned long alias = !(DCACHE_ALIAS_EQ(vaddr, phys));
205
206 /* Flush and invalidate user page if aliased. */
207
208 if (alias) {
209 unsigned long temp = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK);
210 __flush_invalidate_dcache_page_alias(temp, phys);
211 }
212
213 /* Copy data */
214
215 memcpy(dst, src, len);
216
217 /*
218 * Flush and invalidate kernel page if aliased and synchronize
219 * data and instruction caches for executable pages.
220 */
221
222 if (alias) {
223 unsigned long temp = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK);
224
225 __flush_invalidate_dcache_range((unsigned long) dst, len);
226 if ((vma->vm_flags & VM_EXEC) != 0) {
227 __invalidate_icache_page_alias(temp, phys);
228 }
229
230 } else if ((vma->vm_flags & VM_EXEC) != 0) {
231 __flush_dcache_range((unsigned long)dst,len);
232 __invalidate_icache_range((unsigned long) dst, len);
233 }
234}
235
236extern void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
237 unsigned long vaddr, void *dst, const void *src,
238 unsigned long len)
239{
240 unsigned long phys = page_to_phys(page);
241 unsigned long alias = !(DCACHE_ALIAS_EQ(vaddr, phys));
242
243 /*
244 * Flush user page if aliased.
245 * (Note: a simply flush would be sufficient)
246 */
247
248 if (alias) {
249 unsigned long temp = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK);
250 __flush_invalidate_dcache_page_alias(temp, phys);
251 }
252
253 memcpy(dst, src, len);
254}
255
256#endif
diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c
index 16004067add3..45d28f217c03 100644
--- a/arch/xtensa/mm/fault.c
+++ b/arch/xtensa/mm/fault.c
@@ -24,6 +24,8 @@
24unsigned long asid_cache = ASID_USER_FIRST; 24unsigned long asid_cache = ASID_USER_FIRST;
25void bad_page_fault(struct pt_regs*, unsigned long, int); 25void bad_page_fault(struct pt_regs*, unsigned long, int);
26 26
27#undef DEBUG_PAGE_FAULT
28
27/* 29/*
28 * This routine handles page faults. It determines the address, 30 * This routine handles page faults. It determines the address,
29 * and the problem, and then passes it off to one of the appropriate 31 * and the problem, and then passes it off to one of the appropriate
@@ -64,7 +66,7 @@ void do_page_fault(struct pt_regs *regs)
64 exccause == EXCCAUSE_ITLB_MISS || 66 exccause == EXCCAUSE_ITLB_MISS ||
65 exccause == EXCCAUSE_FETCH_CACHE_ATTRIBUTE) ? 1 : 0; 67 exccause == EXCCAUSE_FETCH_CACHE_ATTRIBUTE) ? 1 : 0;
66 68
67#if 0 69#ifdef DEBUG_PAGE_FAULT
68 printk("[%s:%d:%08x:%d:%08x:%s%s]\n", current->comm, current->pid, 70 printk("[%s:%d:%08x:%d:%08x:%s%s]\n", current->comm, current->pid,
69 address, exccause, regs->pc, is_write? "w":"", is_exec? "x":""); 71 address, exccause, regs->pc, is_write? "w":"", is_exec? "x":"");
70#endif 72#endif
@@ -219,7 +221,7 @@ bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
219 221
220 /* Are we prepared to handle this kernel fault? */ 222 /* Are we prepared to handle this kernel fault? */
221 if ((entry = search_exception_tables(regs->pc)) != NULL) { 223 if ((entry = search_exception_tables(regs->pc)) != NULL) {
222#if 1 224#ifdef DEBUG_PAGE_FAULT
223 printk(KERN_DEBUG "%s: Exception at pc=%#010lx (%lx)\n", 225 printk(KERN_DEBUG "%s: Exception at pc=%#010lx (%lx)\n",
224 current->comm, regs->pc, entry->fixup); 226 current->comm, regs->pc, entry->fixup);
225#endif 227#endif
diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c
index 8415c76f11c2..b3086f34a8e7 100644
--- a/arch/xtensa/mm/init.c
+++ b/arch/xtensa/mm/init.c
@@ -15,40 +15,24 @@
15 * Kevin Chea 15 * Kevin Chea
16 */ 16 */
17 17
18#include <linux/init.h>
19#include <linux/signal.h>
20#include <linux/sched.h>
21#include <linux/kernel.h> 18#include <linux/kernel.h>
22#include <linux/errno.h> 19#include <linux/errno.h>
23#include <linux/string.h>
24#include <linux/types.h>
25#include <linux/ptrace.h>
26#include <linux/bootmem.h> 20#include <linux/bootmem.h>
27#include <linux/swap.h> 21#include <linux/swap.h>
22#include <linux/mman.h>
23#include <linux/nodemask.h>
24#include <linux/mm.h>
25#include <linux/slab.h>
28 26
29#include <asm/pgtable.h> 27#include <asm/pgtable.h>
30#include <asm/bootparam.h> 28#include <asm/bootparam.h>
31#include <asm/mmu_context.h> 29#include <asm/mmu_context.h>
32#include <asm/tlb.h> 30#include <asm/tlb.h>
33#include <asm/tlbflush.h>
34#include <asm/page.h> 31#include <asm/page.h>
35#include <asm/pgalloc.h> 32#include <asm/pgalloc.h>
36#include <asm/pgtable.h>
37
38 33
39#define DEBUG 0
40 34
41DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); 35DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
42//static DEFINE_SPINLOCK(tlb_lock);
43
44/*
45 * This flag is used to indicate that the page was mapped and modified in
46 * kernel space, so the cache is probably dirty at that address.
47 * If cache aliasing is enabled and the page color mismatches, update_mmu_cache
48 * synchronizes the caches if this bit is set.
49 */
50
51#define PG_cache_clean PG_arch_1
52 36
53/* References to section boundaries */ 37/* References to section boundaries */
54 38
@@ -323,228 +307,22 @@ void show_mem(void)
323 printk("%d free pages\n", free); 307 printk("%d free pages\n", free);
324} 308}
325 309
326/* ------------------------------------------------------------------------- */ 310struct kmem_cache *pgtable_cache __read_mostly;
327
328#if (DCACHE_WAY_SIZE > PAGE_SIZE)
329
330/*
331 * With cache aliasing, the page color of the page in kernel space and user
332 * space might mismatch. We temporarily map the page to a different virtual
333 * address with the same color and clear the page there.
334 */
335
336void clear_user_page(void *kaddr, unsigned long vaddr, struct page* page)
337{
338
339 /* There shouldn't be any entries for this page. */
340
341 __flush_invalidate_dcache_page_phys(__pa(page_address(page)));
342
343 if (!PAGE_COLOR_EQ(vaddr, kaddr)) {
344 unsigned long v, p;
345
346 /* Temporarily map page to DTLB_WAY_DCACHE_ALIAS0. */
347
348 spin_lock(&tlb_lock);
349
350 p = (unsigned long)pte_val((mk_pte(page,PAGE_KERNEL)));
351 kaddr = (void*)PAGE_COLOR_MAP0(vaddr);
352 v = (unsigned long)kaddr | DTLB_WAY_DCACHE_ALIAS0;
353 __asm__ __volatile__("wdtlb %0,%1; dsync" : :"a" (p), "a" (v));
354
355 clear_page(kaddr);
356
357 spin_unlock(&tlb_lock);
358 } else {
359 clear_page(kaddr);
360 }
361
362 /* We need to make sure that i$ and d$ are coherent. */
363
364 clear_bit(PG_cache_clean, &page->flags);
365}
366
367/*
368 * With cache aliasing, we have to make sure that the page color of the page
369 * in kernel space matches that of the virtual user address before we read
370 * the page. If the page color differ, we create a temporary DTLB entry with
371 * the corrent page color and use this 'temporary' address as the source.
372 * We then use the same approach as in clear_user_page and copy the data
373 * to the kernel space and clear the PG_cache_clean bit to synchronize caches
374 * later.
375 *
376 * Note:
377 * Instead of using another 'way' for the temporary DTLB entry, we could
378 * probably use the same entry that points to the kernel address (after
379 * saving the original value and restoring it when we are done).
380 */
381 311
382void copy_user_page(void* to, void* from, unsigned long vaddr, 312static void pgd_ctor(void *addr, struct kmem_cache *cache, unsigned long flags)
383 struct page* to_page)
384{ 313{
385 /* There shouldn't be any entries for the new page. */ 314 pte_t* ptep = (pte_t*)addr;
386 315 int i;
387 __flush_invalidate_dcache_page_phys(__pa(page_address(to_page)));
388
389 spin_lock(&tlb_lock);
390
391 if (!PAGE_COLOR_EQ(vaddr, from)) {
392 unsigned long v, p, t;
393
394 __asm__ __volatile__ ("pdtlb %1,%2; rdtlb1 %0,%1"
395 : "=a"(p), "=a"(t) : "a"(from));
396 from = (void*)PAGE_COLOR_MAP0(vaddr);
397 v = (unsigned long)from | DTLB_WAY_DCACHE_ALIAS0;
398 __asm__ __volatile__ ("wdtlb %0,%1; dsync" ::"a" (p), "a" (v));
399 }
400
401 if (!PAGE_COLOR_EQ(vaddr, to)) {
402 unsigned long v, p;
403
404 p = (unsigned long)pte_val((mk_pte(to_page,PAGE_KERNEL)));
405 to = (void*)PAGE_COLOR_MAP1(vaddr);
406 v = (unsigned long)to | DTLB_WAY_DCACHE_ALIAS1;
407 __asm__ __volatile__ ("wdtlb %0,%1; dsync" ::"a" (p), "a" (v));
408 }
409 copy_page(to, from);
410
411 spin_unlock(&tlb_lock);
412
413 /* We need to make sure that i$ and d$ are coherent. */
414
415 clear_bit(PG_cache_clean, &to_page->flags);
416}
417
418
419
420/*
421 * Any time the kernel writes to a user page cache page, or it is about to
422 * read from a page cache page this routine is called.
423 *
424 * Note:
425 * The kernel currently only provides one architecture bit in the page
426 * flags that we use for I$/D$ coherency. Maybe, in future, we can
427 * use a sepearte bit for deferred dcache aliasing:
428 * If the page is not mapped yet, we only need to set a flag,
429 * if mapped, we need to invalidate the page.
430 */
431// FIXME: we probably need this for WB caches not only for Page Coloring..
432
433void flush_dcache_page(struct page *page)
434{
435 unsigned long addr = __pa(page_address(page));
436 struct address_space *mapping = page_mapping(page);
437
438 __flush_invalidate_dcache_page_phys(addr);
439
440 if (!test_bit(PG_cache_clean, &page->flags))
441 return;
442
443 /* If this page hasn't been mapped, yet, handle I$/D$ coherency later.*/
444#if 0
445 if (mapping && !mapping_mapped(mapping))
446 clear_bit(PG_cache_clean, &page->flags);
447 else
448#endif
449 __invalidate_icache_page_phys(addr);
450}
451
452void flush_cache_range(struct vm_area_struct* vma, unsigned long s,
453 unsigned long e)
454{
455 __flush_invalidate_cache_all();
456}
457
458void flush_cache_page(struct vm_area_struct* vma, unsigned long address,
459 unsigned long pfn)
460{
461 struct page *page = pfn_to_page(pfn);
462
463 /* Remove any entry for the old mapping. */
464
465 if (current->active_mm == vma->vm_mm) {
466 unsigned long addr = __pa(page_address(page));
467 __flush_invalidate_dcache_page_phys(addr);
468 if ((vma->vm_flags & VM_EXEC) != 0)
469 __invalidate_icache_page_phys(addr);
470 } else {
471 BUG();
472 }
473}
474
475#endif /* (DCACHE_WAY_SIZE > PAGE_SIZE) */
476
477
478pte_t* pte_alloc_one_kernel (struct mm_struct* mm, unsigned long addr)
479{
480 pte_t* pte = (pte_t*)__get_free_pages(GFP_KERNEL|__GFP_REPEAT, 0);
481 if (likely(pte)) {
482 pte_t* ptep = (pte_t*)(pte_val(*pte) + PAGE_OFFSET);
483 int i;
484 for (i = 0; i < 1024; i++, ptep++)
485 pte_clear(mm, addr, ptep);
486 }
487 return pte;
488}
489
490struct page* pte_alloc_one(struct mm_struct *mm, unsigned long addr)
491{
492 struct page *page;
493
494 page = alloc_pages(GFP_KERNEL | __GFP_REPEAT, 0);
495
496 if (likely(page)) {
497 pte_t* ptep = kmap_atomic(page, KM_USER0);
498 int i;
499 316
500 for (i = 0; i < 1024; i++, ptep++) 317 for (i = 0; i < 1024; i++, ptep++)
501 pte_clear(mm, addr, ptep); 318 pte_clear(NULL, 0, ptep);
502 319
503 kunmap_atomic(ptep, KM_USER0);
504 }
505 return page;
506} 320}
507 321
508 322void __init pgtable_cache_init(void)
509/*
510 * Handle D$/I$ coherency.
511 *
512 * Note:
513 * We only have one architecture bit for the page flags, so we cannot handle
514 * cache aliasing, yet.
515 */
516
517void
518update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t pte)
519{ 323{
520 unsigned long pfn = pte_pfn(pte); 324 pgtable_cache = kmem_cache_create("pgd",
521 struct page *page; 325 PAGE_SIZE, PAGE_SIZE,
522 unsigned long vaddr = addr & PAGE_MASK; 326 SLAB_HWCACHE_ALIGN,
523 327 pgd_ctor);
524 if (!pfn_valid(pfn))
525 return;
526
527 page = pfn_to_page(pfn);
528
529 invalidate_itlb_mapping(addr);
530 invalidate_dtlb_mapping(addr);
531
532 /* We have a new mapping. Use it. */
533
534 write_dtlb_entry(pte, dtlb_probe(addr));
535
536 /* If the processor can execute from this page, synchronize D$/I$. */
537
538 if ((vma->vm_flags & VM_EXEC) != 0) {
539
540 write_itlb_entry(pte, itlb_probe(addr));
541
542 /* Synchronize caches, if not clean. */
543
544 if (!test_and_set_bit(PG_cache_clean, &page->flags)) {
545 __flush_dcache_page(vaddr);
546 __invalidate_icache_page(vaddr);
547 }
548 }
549} 328}
550
diff --git a/arch/xtensa/mm/misc.S b/arch/xtensa/mm/misc.S
index ae085332c607..e1f880368e32 100644
--- a/arch/xtensa/mm/misc.S
+++ b/arch/xtensa/mm/misc.S
@@ -7,29 +7,33 @@
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 - 2007 Tensilica Inc.
11 * 11 *
12 * Chris Zankel <chris@zankel.net> 12 * Chris Zankel <chris@zankel.net>
13 */ 13 */
14 14
15/* Note: we might want to implement some of the loops as zero-overhead-loops,
16 * where applicable and if supported by the processor.
17 */
18 15
19#include <linux/linkage.h> 16#include <linux/linkage.h>
20#include <asm/page.h> 17#include <asm/page.h>
21#include <asm/pgtable.h> 18#include <asm/pgtable.h>
22#include <asm/asmmacro.h> 19#include <asm/asmmacro.h>
23#include <asm/cacheasm.h> 20#include <asm/cacheasm.h>
21#include <asm/tlbflush.h>
22
24 23
25/* clear_page (page) */ 24/*
25 * clear_page and clear_user_page are the same for non-cache-aliased configs.
26 *
27 * clear_page (unsigned long page)
28 * a2
29 */
26 30
27ENTRY(clear_page) 31ENTRY(clear_page)
28 entry a1, 16 32 entry a1, 16
29 addi a4, a2, PAGE_SIZE
30 movi a3, 0
31 33
321: s32i a3, a2, 0 34 movi a3, 0
35 __loopi a2, a7, PAGE_SIZE, 32
36 s32i a3, a2, 0
33 s32i a3, a2, 4 37 s32i a3, a2, 4
34 s32i a3, a2, 8 38 s32i a3, a2, 8
35 s32i a3, a2, 12 39 s32i a3, a2, 12
@@ -37,42 +41,277 @@ ENTRY(clear_page)
37 s32i a3, a2, 20 41 s32i a3, a2, 20
38 s32i a3, a2, 24 42 s32i a3, a2, 24
39 s32i a3, a2, 28 43 s32i a3, a2, 28
40 addi a2, a2, 32 44 __endla a2, a7, 32
41 blt a2, a4, 1b
42 45
43 retw 46 retw
44 47
45/* 48/*
49 * copy_page and copy_user_page are the same for non-cache-aliased configs.
50 *
46 * copy_page (void *to, void *from) 51 * copy_page (void *to, void *from)
47 * a2 a3 52 * a2 a3
48 */ 53 */
49 54
50ENTRY(copy_page) 55ENTRY(copy_page)
51 entry a1, 16 56 entry a1, 16
52 addi a4, a2, PAGE_SIZE
53
541: l32i a5, a3, 0
55 l32i a6, a3, 4
56 l32i a7, a3, 8
57 s32i a5, a2, 0
58 s32i a6, a2, 4
59 s32i a7, a2, 8
60 l32i a5, a3, 12
61 l32i a6, a3, 16
62 l32i a7, a3, 20
63 s32i a5, a2, 12
64 s32i a6, a2, 16
65 s32i a7, a2, 20
66 l32i a5, a3, 24
67 l32i a6, a3, 28
68 s32i a5, a2, 24
69 s32i a6, a2, 28
70 addi a2, a2, 32
71 addi a3, a3, 32
72 blt a2, a4, 1b
73 57
58 __loopi a2, a4, PAGE_SIZE, 32
59
60 l32i a8, a3, 0
61 l32i a9, a3, 4
62 s32i a8, a2, 0
63 s32i a9, a2, 4
64
65 l32i a8, a3, 8
66 l32i a9, a3, 12
67 s32i a8, a2, 8
68 s32i a9, a2, 12
69
70 l32i a8, a3, 16
71 l32i a9, a3, 20
72 s32i a8, a2, 16
73 s32i a9, a2, 20
74
75 l32i a8, a3, 24
76 l32i a9, a3, 28
77 s32i a8, a2, 24
78 s32i a9, a2, 28
79
80 addi a2, a2, 32
81 addi a3, a3, 32
82
83 __endl a2, a4
84
85 retw
86
87/*
88 * If we have to deal with cache aliasing, we use temporary memory mappings
89 * to ensure that the source and destination pages have the same color as
90 * the virtual address. We use way 0 and 1 for temporary mappings in such cases.
91 *
92 * The temporary DTLB entries shouldn't be flushed by interrupts, but are
93 * flushed by preemptive task switches. Special code in the
94 * fast_second_level_miss handler re-established the temporary mapping.
95 * It requires that the PPNs for the destination and source addresses are
96 * in a6, and a7, respectively.
97 */
98
99/* TLB miss exceptions are treated special in the following region */
100
101ENTRY(__tlbtemp_mapping_start)
102
103#if (DCACHE_WAY_SIZE > PAGE_SIZE)
104
105/*
106 * clear_user_page (void *addr, unsigned long vaddr, struct page *page)
107 * a2 a3 a4
108 */
109
110ENTRY(clear_user_page)
111 entry a1, 32
112
113 /* Mark page dirty and determine alias. */
114
115 movi a7, (1 << PG_ARCH_1)
116 l32i a5, a4, PAGE_FLAGS
117 xor a6, a2, a3
118 extui a3, a3, PAGE_SHIFT, DCACHE_ALIAS_ORDER
119 extui a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER
120 or a5, a5, a7
121 slli a3, a3, PAGE_SHIFT
122 s32i a5, a4, PAGE_FLAGS
123
124 /* Skip setting up a temporary DTLB if not aliased. */
125
126 beqz a6, 1f
127
128 /* Invalidate kernel page. */
129
130 mov a10, a2
131 call8 __invalidate_dcache_page
132
133 /* Setup a temporary DTLB with the color of the VPN */
134
135 movi a4, -PAGE_OFFSET + (PAGE_KERNEL | _PAGE_HW_WRITE)
136 movi a5, TLBTEMP_BASE_1 # virt
137 add a6, a2, a4 # ppn
138 add a2, a5, a3 # add 'color'
139
140 wdtlb a6, a2
141 dsync
142
1431: movi a3, 0
144 __loopi a2, a7, PAGE_SIZE, 32
145 s32i a3, a2, 0
146 s32i a3, a2, 4
147 s32i a3, a2, 8
148 s32i a3, a2, 12
149 s32i a3, a2, 16
150 s32i a3, a2, 20
151 s32i a3, a2, 24
152 s32i a3, a2, 28
153 __endla a2, a7, 32
154
155 bnez a6, 1f
156 retw
157
158 /* We need to invalidate the temporary idtlb entry, if any. */
159
1601: addi a2, a2, -PAGE_SIZE
161 idtlb a2
162 dsync
163
164 retw
165
166/*
167 * copy_page_user (void *to, void *from, unsigned long vaddr, struct page *page)
168 * a2 a3 a4 a5
169 */
170
171ENTRY(copy_user_page)
172
173 entry a1, 32
174
175 /* Mark page dirty and determine alias for destination. */
176
177 movi a8, (1 << PG_ARCH_1)
178 l32i a9, a5, PAGE_FLAGS
179 xor a6, a2, a4
180 xor a7, a3, a4
181 extui a4, a4, PAGE_SHIFT, DCACHE_ALIAS_ORDER
182 extui a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER
183 extui a7, a7, PAGE_SHIFT, DCACHE_ALIAS_ORDER
184 or a9, a9, a8
185 slli a4, a4, PAGE_SHIFT
186 s32i a9, a5, PAGE_FLAGS
187 movi a5, -PAGE_OFFSET + (PAGE_KERNEL | _PAGE_HW_WRITE)
188
189 beqz a6, 1f
190
191 /* Invalidate dcache */
192
193 mov a10, a2
194 call8 __invalidate_dcache_page
195
196 /* Setup a temporary DTLB with a matching color. */
197
198 movi a8, TLBTEMP_BASE_1 # base
199 add a6, a2, a5 # ppn
200 add a2, a8, a4 # add 'color'
201
202 wdtlb a6, a2
203 dsync
204
205 /* Skip setting up a temporary DTLB for destination if not aliased. */
206
2071: beqz a7, 1f
208
209 /* Setup a temporary DTLB with a matching color. */
210
211 movi a8, TLBTEMP_BASE_2 # base
212 add a7, a3, a5 # ppn
213 add a3, a8, a4
214 addi a8, a3, 1 # way1
215
216 wdtlb a7, a8
217 dsync
218
2191: __loopi a2, a4, PAGE_SIZE, 32
220
221 l32i a8, a3, 0
222 l32i a9, a3, 4
223 s32i a8, a2, 0
224 s32i a9, a2, 4
225
226 l32i a8, a3, 8
227 l32i a9, a3, 12
228 s32i a8, a2, 8
229 s32i a9, a2, 12
230
231 l32i a8, a3, 16
232 l32i a9, a3, 20
233 s32i a8, a2, 16
234 s32i a9, a2, 20
235
236 l32i a8, a3, 24
237 l32i a9, a3, 28
238 s32i a8, a2, 24
239 s32i a9, a2, 28
240
241 addi a2, a2, 32
242 addi a3, a3, 32
243
244 __endl a2, a4
245
246 /* We need to invalidate any temporary mapping! */
247
248 bnez a6, 1f
249 bnez a7, 2f
250 retw
251
2521: addi a2, a2, -PAGE_SIZE
253 idtlb a2
254 dsync
255 bnez a7, 2f
256 retw
257
2582: addi a3, a3, -PAGE_SIZE+1
259 idtlb a3
260 dsync
261
262 retw
263
264#endif
265
266#if (DCACHE_WAY_SIZE > PAGE_SIZE)
267
268/*
269 * void __flush_invalidate_dcache_page_alias (addr, phys)
270 * a2 a3
271 */
272
273ENTRY(__flush_invalidate_dcache_page_alias)
274 entry sp, 16
275
276 movi a7, 0 # required for exception handler
277 addi a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
278 mov a4, a2
279 wdtlb a6, a2
280 dsync
281
282 ___flush_invalidate_dcache_page a2 a3
283
284 idtlb a4
285 dsync
286
287 retw
288
289#endif
290
291ENTRY(__tlbtemp_mapping_itlb)
292
293#if (ICACHE_WAY_SIZE > PAGE_SIZE)
294
295ENTRY(__invalidate_icache_page_alias)
296 entry sp, 16
297
298 addi a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
299 mov a4, a2
300 witlb a6, a2
301 isync
302
303 ___invalidate_icache_page a2 a3
304
305 iitlb a4
306 isync
74 retw 307 retw
75 308
309#endif
310
311/* End of special treatment in tlb miss exception */
312
313ENTRY(__tlbtemp_mapping_end)
314
76/* 315/*
77 * void __invalidate_icache_page(ulong start) 316 * void __invalidate_icache_page(ulong start)
78 */ 317 */
@@ -121,8 +360,6 @@ ENTRY(__flush_dcache_page)
121 dsync 360 dsync
122 retw 361 retw
123 362
124
125
126/* 363/*
127 * void __invalidate_icache_range(ulong start, ulong size) 364 * void __invalidate_icache_range(ulong start, ulong size)
128 */ 365 */
@@ -168,7 +405,6 @@ ENTRY(__invalidate_dcache_range)
168 405
169 ___invalidate_dcache_range a2 a3 a4 406 ___invalidate_dcache_range a2 a3 a4
170 407
171
172 retw 408 retw
173 409
174/* 410/*
diff --git a/arch/xtensa/platform-iss/console.c b/arch/xtensa/platform-iss/console.c
index 2f4f20ffe666..854677d0c3f6 100644
--- a/arch/xtensa/platform-iss/console.c
+++ b/arch/xtensa/platform-iss/console.c
@@ -20,7 +20,6 @@
20#include <linux/param.h> 20#include <linux/param.h>
21#include <linux/serial.h> 21#include <linux/serial.h>
22#include <linux/serialP.h> 22#include <linux/serialP.h>
23#include <linux/console.h>
24 23
25#include <asm/uaccess.h> 24#include <asm/uaccess.h>
26#include <asm/irq.h> 25#include <asm/irq.h>