aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r--arch/mips/kernel/Makefile1
-rw-r--r--arch/mips/kernel/cevt-gt641xx.c12
-rw-r--r--arch/mips/kernel/cevt-r4k.c45
-rw-r--r--arch/mips/kernel/cevt-txx9.c171
-rw-r--r--arch/mips/kernel/irixsig.c8
-rw-r--r--arch/mips/kernel/ptrace.c18
-rw-r--r--arch/mips/kernel/ptrace32.c4
-rw-r--r--arch/mips/kernel/smtc.c57
-rw-r--r--arch/mips/kernel/syscall.c9
-rw-r--r--arch/mips/kernel/time.c17
-rw-r--r--arch/mips/kernel/vmlinux.lds.S32
-rw-r--r--arch/mips/kernel/vpe.c4
12 files changed, 307 insertions, 71 deletions
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index d7745c8976f6..3196509a28d5 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -10,6 +10,7 @@ obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \
10 10
11obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o 11obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o
12obj-$(CONFIG_CEVT_GT641XX) += cevt-gt641xx.o 12obj-$(CONFIG_CEVT_GT641XX) += cevt-gt641xx.o
13obj-$(CONFIG_CEVT_TXX9) += cevt-txx9.o
13 14
14binfmt_irix-objs := irixelf.o irixinv.o irixioctl.o irixsig.o \ 15binfmt_irix-objs := irixelf.o irixinv.o irixioctl.o irixsig.o \
15 irix5sys.o sysirix.o 16 irix5sys.o sysirix.o
diff --git a/arch/mips/kernel/cevt-gt641xx.c b/arch/mips/kernel/cevt-gt641xx.c
index 4c651b2680f9..c36772631fe0 100644
--- a/arch/mips/kernel/cevt-gt641xx.c
+++ b/arch/mips/kernel/cevt-gt641xx.c
@@ -49,10 +49,9 @@ int gt641xx_timer0_state(void)
49static int gt641xx_timer0_set_next_event(unsigned long delta, 49static int gt641xx_timer0_set_next_event(unsigned long delta,
50 struct clock_event_device *evt) 50 struct clock_event_device *evt)
51{ 51{
52 unsigned long flags;
53 u32 ctrl; 52 u32 ctrl;
54 53
55 spin_lock_irqsave(&gt641xx_timer_lock, flags); 54 spin_lock(&gt641xx_timer_lock);
56 55
57 ctrl = GT_READ(GT_TC_CONTROL_OFS); 56 ctrl = GT_READ(GT_TC_CONTROL_OFS);
58 ctrl &= ~(GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK); 57 ctrl &= ~(GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK);
@@ -61,7 +60,7 @@ static int gt641xx_timer0_set_next_event(unsigned long delta,
61 GT_WRITE(GT_TC0_OFS, delta); 60 GT_WRITE(GT_TC0_OFS, delta);
62 GT_WRITE(GT_TC_CONTROL_OFS, ctrl); 61 GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
63 62
64 spin_unlock_irqrestore(&gt641xx_timer_lock, flags); 63 spin_unlock(&gt641xx_timer_lock);
65 64
66 return 0; 65 return 0;
67} 66}
@@ -69,10 +68,9 @@ static int gt641xx_timer0_set_next_event(unsigned long delta,
69static void gt641xx_timer0_set_mode(enum clock_event_mode mode, 68static void gt641xx_timer0_set_mode(enum clock_event_mode mode,
70 struct clock_event_device *evt) 69 struct clock_event_device *evt)
71{ 70{
72 unsigned long flags;
73 u32 ctrl; 71 u32 ctrl;
74 72
75 spin_lock_irqsave(&gt641xx_timer_lock, flags); 73 spin_lock(&gt641xx_timer_lock);
76 74
77 ctrl = GT_READ(GT_TC_CONTROL_OFS); 75 ctrl = GT_READ(GT_TC_CONTROL_OFS);
78 ctrl &= ~(GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK); 76 ctrl &= ~(GT_TC_CONTROL_ENTC0_MSK | GT_TC_CONTROL_SELTC0_MSK);
@@ -90,7 +88,7 @@ static void gt641xx_timer0_set_mode(enum clock_event_mode mode,
90 88
91 GT_WRITE(GT_TC_CONTROL_OFS, ctrl); 89 GT_WRITE(GT_TC_CONTROL_OFS, ctrl);
92 90
93 spin_unlock_irqrestore(&gt641xx_timer_lock, flags); 91 spin_unlock(&gt641xx_timer_lock);
94} 92}
95 93
96static void gt641xx_timer0_event_handler(struct clock_event_device *dev) 94static void gt641xx_timer0_event_handler(struct clock_event_device *dev)
@@ -133,9 +131,9 @@ static int __init gt641xx_timer0_clockevent_init(void)
133 131
134 cd = &gt641xx_timer0_clockevent; 132 cd = &gt641xx_timer0_clockevent;
135 cd->rating = 200 + gt641xx_base_clock / 10000000; 133 cd->rating = 200 + gt641xx_base_clock / 10000000;
134 clockevent_set_clock(cd, gt641xx_base_clock);
136 cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); 135 cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
137 cd->min_delta_ns = clockevent_delta2ns(0x300, cd); 136 cd->min_delta_ns = clockevent_delta2ns(0x300, cd);
138 clockevent_set_clock(cd, gt641xx_base_clock);
139 137
140 clockevents_register_device(&gt641xx_timer0_clockevent); 138 clockevents_register_device(&gt641xx_timer0_clockevent);
141 139
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index ae2984fff580..bab935a3d74b 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -28,7 +28,7 @@ static int mips_next_event(unsigned long delta,
28 cnt = read_c0_count(); 28 cnt = read_c0_count();
29 cnt += delta; 29 cnt += delta;
30 write_c0_compare(cnt); 30 write_c0_compare(cnt);
31 res = ((long)(read_c0_count() - cnt ) > 0) ? -ETIME : 0; 31 res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0;
32#ifdef CONFIG_MIPS_MT_SMTC 32#ifdef CONFIG_MIPS_MT_SMTC
33 evpe(vpflags); 33 evpe(vpflags);
34 local_irq_restore(flags); 34 local_irq_restore(flags);
@@ -179,7 +179,7 @@ static int c0_compare_int_pending(void)
179 179
180static int c0_compare_int_usable(void) 180static int c0_compare_int_usable(void)
181{ 181{
182 const unsigned int delta = 0x300000; 182 unsigned int delta;
183 unsigned int cnt; 183 unsigned int cnt;
184 184
185 /* 185 /*
@@ -192,11 +192,17 @@ static int c0_compare_int_usable(void)
192 return 0; 192 return 0;
193 } 193 }
194 194
195 cnt = read_c0_count(); 195 for (delta = 0x10; delta <= 0x400000; delta <<= 1) {
196 cnt += delta; 196 cnt = read_c0_count();
197 write_c0_compare(cnt); 197 cnt += delta;
198 write_c0_compare(cnt);
199 irq_disable_hazard();
200 if ((int)(read_c0_count() - cnt) < 0)
201 break;
202 /* increase delta if the timer was already expired */
203 }
198 204
199 while ((long)(read_c0_count() - cnt) <= 0) 205 while ((int)(read_c0_count() - cnt) <= 0)
200 ; /* Wait for expiry */ 206 ; /* Wait for expiry */
201 207
202 if (!c0_compare_int_pending()) 208 if (!c0_compare_int_pending())
@@ -218,9 +224,9 @@ void __cpuinit mips_clockevent_init(void)
218 uint64_t mips_freq = mips_hpt_frequency; 224 uint64_t mips_freq = mips_hpt_frequency;
219 unsigned int cpu = smp_processor_id(); 225 unsigned int cpu = smp_processor_id();
220 struct clock_event_device *cd; 226 struct clock_event_device *cd;
221 unsigned int irq = MIPS_CPU_IRQ_BASE + 7; 227 unsigned int irq;
222 228
223 if (!cpu_has_counter) 229 if (!cpu_has_counter || !mips_hpt_frequency)
224 return; 230 return;
225 231
226#ifdef CONFIG_MIPS_MT_SMTC 232#ifdef CONFIG_MIPS_MT_SMTC
@@ -237,6 +243,15 @@ void __cpuinit mips_clockevent_init(void)
237 if (!c0_compare_int_usable()) 243 if (!c0_compare_int_usable())
238 return; 244 return;
239 245
246 /*
247 * With vectored interrupts things are getting platform specific.
248 * get_c0_compare_int is a hook to allow a platform to return the
249 * interrupt number of it's liking.
250 */
251 irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
252 if (get_c0_compare_int)
253 irq = get_c0_compare_int();
254
240 cd = &per_cpu(mips_clockevent_device, cpu); 255 cd = &per_cpu(mips_clockevent_device, cpu);
241 256
242 cd->name = "MIPS"; 257 cd->name = "MIPS";
@@ -261,13 +276,15 @@ void __cpuinit mips_clockevent_init(void)
261 276
262 clockevents_register_device(cd); 277 clockevents_register_device(cd);
263 278
264 if (!cp0_timer_irq_installed) { 279 if (!cp0_timer_irq_installed)
280 return;
281
282 cp0_timer_irq_installed = 1;
283
265#ifdef CONFIG_MIPS_MT_SMTC 284#ifdef CONFIG_MIPS_MT_SMTC
266#define CPUCTR_IMASKBIT (0x100 << cp0_compare_irq) 285#define CPUCTR_IMASKBIT (0x100 << cp0_compare_irq)
267 setup_irq_smtc(irq, &c0_compare_irqaction, CPUCTR_IMASKBIT); 286 setup_irq_smtc(irq, &c0_compare_irqaction, CPUCTR_IMASKBIT);
268#else 287#else
269 setup_irq(irq, &c0_compare_irqaction); 288 setup_irq(irq, &c0_compare_irqaction);
270#endif /* CONFIG_MIPS_MT_SMTC */ 289#endif
271 cp0_timer_irq_installed = 1;
272 }
273} 290}
diff --git a/arch/mips/kernel/cevt-txx9.c b/arch/mips/kernel/cevt-txx9.c
new file mode 100644
index 000000000000..795cb8fb0d74
--- /dev/null
+++ b/arch/mips/kernel/cevt-txx9.c
@@ -0,0 +1,171 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Based on linux/arch/mips/kernel/cevt-r4k.c,
7 * linux/arch/mips/jmr3927/rbhma3100/setup.c
8 *
9 * Copyright 2001 MontaVista Software Inc.
10 * Copyright (C) 2000-2001 Toshiba Corporation
11 * Copyright (C) 2007 MIPS Technologies, Inc.
12 * Copyright (C) 2007 Ralf Baechle <ralf@linux-mips.org>
13 */
14#include <linux/init.h>
15#include <linux/interrupt.h>
16#include <asm/time.h>
17#include <asm/txx9tmr.h>
18
19#define TCR_BASE (TXx9_TMTCR_CCDE | TXx9_TMTCR_CRE | TXx9_TMTCR_TMODE_ITVL)
20#define TIMER_CCD 0 /* 1/2 */
21#define TIMER_CLK(imclk) ((imclk) / (2 << TIMER_CCD))
22
23static struct txx9_tmr_reg __iomem *txx9_cs_tmrptr;
24
25static cycle_t txx9_cs_read(void)
26{
27 return __raw_readl(&txx9_cs_tmrptr->trr);
28}
29
30/* Use 1 bit smaller width to use full bits in that width */
31#define TXX9_CLOCKSOURCE_BITS (TXX9_TIMER_BITS - 1)
32
33static struct clocksource txx9_clocksource = {
34 .name = "TXx9",
35 .rating = 200,
36 .read = txx9_cs_read,
37 .mask = CLOCKSOURCE_MASK(TXX9_CLOCKSOURCE_BITS),
38 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
39};
40
41void __init txx9_clocksource_init(unsigned long baseaddr,
42 unsigned int imbusclk)
43{
44 struct txx9_tmr_reg __iomem *tmrptr;
45
46 clocksource_set_clock(&txx9_clocksource, TIMER_CLK(imbusclk));
47 clocksource_register(&txx9_clocksource);
48
49 tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg));
50 __raw_writel(TCR_BASE, &tmrptr->tcr);
51 __raw_writel(0, &tmrptr->tisr);
52 __raw_writel(TIMER_CCD, &tmrptr->ccdr);
53 __raw_writel(TXx9_TMITMR_TZCE, &tmrptr->itmr);
54 __raw_writel(1 << TXX9_CLOCKSOURCE_BITS, &tmrptr->cpra);
55 __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr);
56 txx9_cs_tmrptr = tmrptr;
57}
58
59static struct txx9_tmr_reg __iomem *txx9_tmrptr;
60
61static void txx9tmr_stop_and_clear(struct txx9_tmr_reg __iomem *tmrptr)
62{
63 /* stop and reset counter */
64 __raw_writel(TCR_BASE, &tmrptr->tcr);
65 /* clear pending interrupt */
66 __raw_writel(0, &tmrptr->tisr);
67}
68
69static void txx9tmr_set_mode(enum clock_event_mode mode,
70 struct clock_event_device *evt)
71{
72 struct txx9_tmr_reg __iomem *tmrptr = txx9_tmrptr;
73
74 txx9tmr_stop_and_clear(tmrptr);
75 switch (mode) {
76 case CLOCK_EVT_MODE_PERIODIC:
77 __raw_writel(TXx9_TMITMR_TIIE | TXx9_TMITMR_TZCE,
78 &tmrptr->itmr);
79 /* start timer */
80 __raw_writel(((u64)(NSEC_PER_SEC / HZ) * evt->mult) >>
81 evt->shift,
82 &tmrptr->cpra);
83 __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr);
84 break;
85 case CLOCK_EVT_MODE_SHUTDOWN:
86 case CLOCK_EVT_MODE_UNUSED:
87 __raw_writel(0, &tmrptr->itmr);
88 break;
89 case CLOCK_EVT_MODE_ONESHOT:
90 __raw_writel(TXx9_TMITMR_TIIE, &tmrptr->itmr);
91 break;
92 case CLOCK_EVT_MODE_RESUME:
93 __raw_writel(TIMER_CCD, &tmrptr->ccdr);
94 __raw_writel(0, &tmrptr->itmr);
95 break;
96 }
97}
98
99static int txx9tmr_set_next_event(unsigned long delta,
100 struct clock_event_device *evt)
101{
102 struct txx9_tmr_reg __iomem *tmrptr = txx9_tmrptr;
103
104 txx9tmr_stop_and_clear(tmrptr);
105 /* start timer */
106 __raw_writel(delta, &tmrptr->cpra);
107 __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr);
108 return 0;
109}
110
111static struct clock_event_device txx9tmr_clock_event_device = {
112 .name = "TXx9",
113 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
114 .rating = 200,
115 .cpumask = CPU_MASK_CPU0,
116 .set_mode = txx9tmr_set_mode,
117 .set_next_event = txx9tmr_set_next_event,
118};
119
120static irqreturn_t txx9tmr_interrupt(int irq, void *dev_id)
121{
122 struct clock_event_device *cd = &txx9tmr_clock_event_device;
123 struct txx9_tmr_reg __iomem *tmrptr = txx9_tmrptr;
124
125 __raw_writel(0, &tmrptr->tisr); /* ack interrupt */
126 cd->event_handler(cd);
127 return IRQ_HANDLED;
128}
129
130static struct irqaction txx9tmr_irq = {
131 .handler = txx9tmr_interrupt,
132 .flags = IRQF_DISABLED | IRQF_PERCPU,
133 .name = "txx9tmr",
134};
135
136void __init txx9_clockevent_init(unsigned long baseaddr, int irq,
137 unsigned int imbusclk)
138{
139 struct clock_event_device *cd = &txx9tmr_clock_event_device;
140 struct txx9_tmr_reg __iomem *tmrptr;
141
142 tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg));
143 txx9tmr_stop_and_clear(tmrptr);
144 __raw_writel(TIMER_CCD, &tmrptr->ccdr);
145 __raw_writel(0, &tmrptr->itmr);
146 txx9_tmrptr = tmrptr;
147
148 clockevent_set_clock(cd, TIMER_CLK(imbusclk));
149 cd->max_delta_ns =
150 clockevent_delta2ns(0xffffffff >> (32 - TXX9_TIMER_BITS), cd);
151 cd->min_delta_ns = clockevent_delta2ns(0xf, cd);
152 cd->irq = irq;
153 clockevents_register_device(cd);
154 setup_irq(irq, &txx9tmr_irq);
155 printk(KERN_INFO "TXx9: clockevent device at 0x%lx, irq %d\n",
156 baseaddr, irq);
157}
158
159void __init txx9_tmr_init(unsigned long baseaddr)
160{
161 struct txx9_tmr_reg __iomem *tmrptr;
162
163 tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg));
164 __raw_writel(TXx9_TMTCR_CRE, &tmrptr->tcr);
165 __raw_writel(0, &tmrptr->tisr);
166 __raw_writel(0xffffffff, &tmrptr->cpra);
167 __raw_writel(0, &tmrptr->itmr);
168 __raw_writel(0, &tmrptr->ccdr);
169 __raw_writel(0, &tmrptr->pgmr);
170 iounmap(tmrptr);
171}
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
index a0a91056fda7..33506ff25910 100644
--- a/arch/mips/kernel/irixsig.c
+++ b/arch/mips/kernel/irixsig.c
@@ -24,8 +24,12 @@
24 24
25#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) 25#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
26 26
27#define _IRIX_NSIG 128
28#define _IRIX_NSIG_BPW BITS_PER_LONG
29#define _IRIX_NSIG_WORDS (_IRIX_NSIG / _IRIX_NSIG_BPW)
30
27typedef struct { 31typedef struct {
28 unsigned long sig[4]; 32 unsigned long sig[_IRIX_NSIG_WORDS];
29} irix_sigset_t; 33} irix_sigset_t;
30 34
31struct sigctx_irix5 { 35struct sigctx_irix5 {
@@ -527,7 +531,7 @@ asmlinkage int irix_sigpoll_sys(unsigned long __user *set,
527 531
528 expire = schedule_timeout_interruptible(expire); 532 expire = schedule_timeout_interruptible(expire);
529 533
530 for (i=0; i<=4; i++) 534 for (i=0; i < _IRIX_NSIG_WORDS; i++)
531 tmp |= (current->pending.signal.sig[i] & kset.sig[i]); 535 tmp |= (current->pending.signal.sig[i] & kset.sig[i]);
532 536
533 if (tmp) 537 if (tmp)
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 999f7853de26..35234b92b9a5 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -65,13 +65,13 @@ int ptrace_getregs(struct task_struct *child, __s64 __user *data)
65 regs = task_pt_regs(child); 65 regs = task_pt_regs(child);
66 66
67 for (i = 0; i < 32; i++) 67 for (i = 0; i < 32; i++)
68 __put_user(regs->regs[i], data + i); 68 __put_user((long)regs->regs[i], data + i);
69 __put_user(regs->lo, data + EF_LO - EF_R0); 69 __put_user((long)regs->lo, data + EF_LO - EF_R0);
70 __put_user(regs->hi, data + EF_HI - EF_R0); 70 __put_user((long)regs->hi, data + EF_HI - EF_R0);
71 __put_user(regs->cp0_epc, data + EF_CP0_EPC - EF_R0); 71 __put_user((long)regs->cp0_epc, data + EF_CP0_EPC - EF_R0);
72 __put_user(regs->cp0_badvaddr, data + EF_CP0_BADVADDR - EF_R0); 72 __put_user((long)regs->cp0_badvaddr, data + EF_CP0_BADVADDR - EF_R0);
73 __put_user(regs->cp0_status, data + EF_CP0_STATUS - EF_R0); 73 __put_user((long)regs->cp0_status, data + EF_CP0_STATUS - EF_R0);
74 __put_user(regs->cp0_cause, data + EF_CP0_CAUSE - EF_R0); 74 __put_user((long)regs->cp0_cause, data + EF_CP0_CAUSE - EF_R0);
75 75
76 return 0; 76 return 0;
77} 77}
@@ -390,11 +390,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
390 } 390 }
391 391
392 case PTRACE_GETREGS: 392 case PTRACE_GETREGS:
393 ret = ptrace_getregs(child, (__u64 __user *) data); 393 ret = ptrace_getregs(child, (__s64 __user *) data);
394 break; 394 break;
395 395
396 case PTRACE_SETREGS: 396 case PTRACE_SETREGS:
397 ret = ptrace_setregs(child, (__u64 __user *) data); 397 ret = ptrace_setregs(child, (__s64 __user *) data);
398 break; 398 break;
399 399
400 case PTRACE_GETFPREGS: 400 case PTRACE_GETFPREGS:
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index f2bffed94fa3..76818be6ba7c 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -346,11 +346,11 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
346 } 346 }
347 347
348 case PTRACE_GETREGS: 348 case PTRACE_GETREGS:
349 ret = ptrace_getregs(child, (__u64 __user *) (__u64) data); 349 ret = ptrace_getregs(child, (__s64 __user *) (__u64) data);
350 break; 350 break;
351 351
352 case PTRACE_SETREGS: 352 case PTRACE_SETREGS:
353 ret = ptrace_setregs(child, (__u64 __user *) (__u64) data); 353 ret = ptrace_setregs(child, (__s64 __user *) (__u64) data);
354 break; 354 break;
355 355
356 case PTRACE_GETFPREGS: 356 case PTRACE_GETFPREGS:
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index a8c1a698d588..9c92d42996cb 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -88,11 +88,19 @@ unsigned int smtc_status = 0;
88 88
89/* Boot command line configuration overrides */ 89/* Boot command line configuration overrides */
90 90
91static int vpe0limit;
91static int ipibuffers = 0; 92static int ipibuffers = 0;
92static int nostlb = 0; 93static int nostlb = 0;
93static int asidmask = 0; 94static int asidmask = 0;
94unsigned long smtc_asid_mask = 0xff; 95unsigned long smtc_asid_mask = 0xff;
95 96
97static int __init vpe0tcs(char *str)
98{
99 get_option(&str, &vpe0limit);
100
101 return 1;
102}
103
96static int __init ipibufs(char *str) 104static int __init ipibufs(char *str)
97{ 105{
98 get_option(&str, &ipibuffers); 106 get_option(&str, &ipibuffers);
@@ -125,6 +133,7 @@ static int __init asidmask_set(char *str)
125 return 1; 133 return 1;
126} 134}
127 135
136__setup("vpe0tcs=", vpe0tcs);
128__setup("ipibufs=", ipibufs); 137__setup("ipibufs=", ipibufs);
129__setup("nostlb", stlb_disable); 138__setup("nostlb", stlb_disable);
130__setup("asidmask=", asidmask_set); 139__setup("asidmask=", asidmask_set);
@@ -340,7 +349,7 @@ static void smtc_tc_setup(int vpe, int tc, int cpu)
340 349
341void mipsmt_prepare_cpus(void) 350void mipsmt_prepare_cpus(void)
342{ 351{
343 int i, vpe, tc, ntc, nvpe, tcpervpe, slop, cpu; 352 int i, vpe, tc, ntc, nvpe, tcpervpe[NR_CPUS], slop, cpu;
344 unsigned long flags; 353 unsigned long flags;
345 unsigned long val; 354 unsigned long val;
346 int nipi; 355 int nipi;
@@ -401,8 +410,39 @@ void mipsmt_prepare_cpus(void)
401 ntc = NR_CPUS; 410 ntc = NR_CPUS;
402 if (tclimit > 0 && ntc > tclimit) 411 if (tclimit > 0 && ntc > tclimit)
403 ntc = tclimit; 412 ntc = tclimit;
404 tcpervpe = ntc / nvpe; 413 slop = ntc % nvpe;
405 slop = ntc % nvpe; /* Residual TCs, < NVPE */ 414 for (i = 0; i < nvpe; i++) {
415 tcpervpe[i] = ntc / nvpe;
416 if (slop) {
417 if((slop - i) > 0) tcpervpe[i]++;
418 }
419 }
420 /* Handle command line override for VPE0 */
421 if (vpe0limit > ntc) vpe0limit = ntc;
422 if (vpe0limit > 0) {
423 int slopslop;
424 if (vpe0limit < tcpervpe[0]) {
425 /* Reducing TC count - distribute to others */
426 slop = tcpervpe[0] - vpe0limit;
427 slopslop = slop % (nvpe - 1);
428 tcpervpe[0] = vpe0limit;
429 for (i = 1; i < nvpe; i++) {
430 tcpervpe[i] += slop / (nvpe - 1);
431 if(slopslop && ((slopslop - (i - 1) > 0)))
432 tcpervpe[i]++;
433 }
434 } else if (vpe0limit > tcpervpe[0]) {
435 /* Increasing TC count - steal from others */
436 slop = vpe0limit - tcpervpe[0];
437 slopslop = slop % (nvpe - 1);
438 tcpervpe[0] = vpe0limit;
439 for (i = 1; i < nvpe; i++) {
440 tcpervpe[i] -= slop / (nvpe - 1);
441 if(slopslop && ((slopslop - (i - 1) > 0)))
442 tcpervpe[i]--;
443 }
444 }
445 }
406 446
407 /* Set up shared TLB */ 447 /* Set up shared TLB */
408 smtc_configure_tlb(); 448 smtc_configure_tlb();
@@ -416,7 +456,7 @@ void mipsmt_prepare_cpus(void)
416 if (vpe != 0) 456 if (vpe != 0)
417 printk(", "); 457 printk(", ");
418 printk("VPE %d: TC", vpe); 458 printk("VPE %d: TC", vpe);
419 for (i = 0; i < tcpervpe; i++) { 459 for (i = 0; i < tcpervpe[vpe]; i++) {
420 /* 460 /*
421 * TC 0 is bound to VPE 0 at reset, 461 * TC 0 is bound to VPE 0 at reset,
422 * and is presumably executing this 462 * and is presumably executing this
@@ -429,15 +469,6 @@ void mipsmt_prepare_cpus(void)
429 printk(" %d", tc); 469 printk(" %d", tc);
430 tc++; 470 tc++;
431 } 471 }
432 if (slop) {
433 if (tc != 0) {
434 smtc_tc_setup(vpe, tc, cpu);
435 cpu++;
436 }
437 printk(" %d", tc);
438 tc++;
439 slop--;
440 }
441 if (vpe != 0) { 472 if (vpe != 0) {
442 /* 473 /*
443 * Clear any stale software interrupts from VPE's Cause 474 * Clear any stale software interrupts from VPE's Cause
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index b95fe93dd646..af1bdc897488 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -73,7 +73,14 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
73 73
74 task_size = STACK_TOP; 74 task_size = STACK_TOP;
75 75
76 if (len > task_size)
77 return -ENOMEM;
78
76 if (flags & MAP_FIXED) { 79 if (flags & MAP_FIXED) {
80 /* Even MAP_FIXED mappings must reside within task_size. */
81 if (task_size - len < addr)
82 return -EINVAL;
83
77 /* 84 /*
78 * We do not accept a shared mapping if it would violate 85 * We do not accept a shared mapping if it would violate
79 * cache aliasing constraints. 86 * cache aliasing constraints.
@@ -83,8 +90,6 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
83 return addr; 90 return addr;
84 } 91 }
85 92
86 if (len > task_size)
87 return -ENOMEM;
88 do_color_align = 0; 93 do_color_align = 0;
89 if (filp || (flags & MAP_SHARED)) 94 if (filp || (flags & MAP_SHARED))
90 do_color_align = 1; 95 do_color_align = 1;
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 6c6849a8f136..27228f583dae 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -11,6 +11,7 @@
11 * Free Software Foundation; either version 2 of the License, or (at your 11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version. 12 * option) any later version.
13 */ 13 */
14#include <linux/bug.h>
14#include <linux/clockchips.h> 15#include <linux/clockchips.h>
15#include <linux/types.h> 16#include <linux/types.h>
16#include <linux/kernel.h> 17#include <linux/kernel.h>
@@ -115,10 +116,6 @@ EXPORT_SYMBOL(perf_irq);
115 * (only needed if you intended to use cpu counter as timer interrupt 116 * (only needed if you intended to use cpu counter as timer interrupt
116 * source) 117 * source)
117 * 2) calculate a couple of cached variables for later usage 118 * 2) calculate a couple of cached variables for later usage
118 * 3) plat_timer_setup() -
119 * a) (optional) over-write any choices made above by time_init().
120 * b) machine specific code should setup the timer irqaction.
121 * c) enable the timer interrupt
122 */ 119 */
123 120
124unsigned int mips_hpt_frequency; 121unsigned int mips_hpt_frequency;
@@ -221,8 +218,18 @@ void __init __weak plat_time_init(void)
221{ 218{
222} 219}
223 220
224void __init __weak plat_timer_setup(struct irqaction *irq) 221/*
222 * This function exists in order to cause an error due to a duplicate
223 * definition if platform code should have its own implementation. The hook
224 * to use instead is plat_time_init. plat_time_init does not receive the
225 * irqaction pointer argument anymore. This is because any function which
226 * initializes an interrupt timer now takes care of its own request_irq rsp.
227 * setup_irq calls and each clock_event_device should use its own
228 * struct irqrequest.
229 */
230void __init plat_timer_setup(struct irqaction *irq)
225{ 231{
232 BUG();
226} 233}
227 234
228void __init time_init(void) 235void __init time_init(void)
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 2781cff1485e..5fc2398bdb76 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -63,21 +63,23 @@ SECTIONS
63 63
64 /* writeable */ 64 /* writeable */
65 .data : { /* Data */ 65 .data : { /* Data */
66 . = . + DATAOFFSET; /* for CONFIG_MAPPED_KERNEL */ 66 . = . + DATAOFFSET; /* for CONFIG_MAPPED_KERNEL */
67 /* 67 /*
68 * This ALIGN is needed as a workaround for a bug a gcc bug upto 4.1 which 68 * This ALIGN is needed as a workaround for a bug a
69 * limits the maximum alignment to at most 32kB and results in the following 69 * gcc bug upto 4.1 which limits the maximum alignment
70 * warning: 70 * to at most 32kB and results in the following
71 * 71 * warning:
72 * CC arch/mips/kernel/init_task.o 72 *
73 * arch/mips/kernel/init_task.c:30: warning: alignment of ‘init_thread_union’ 73 * CC arch/mips/kernel/init_task.o
74 * is greater than maximum object file alignment. Using 32768 74 * arch/mips/kernel/init_task.c:30: warning: alignment
75 */ 75 * of ‘init_thread_union’ is greater than maximum
76 . = ALIGN(_PAGE_SIZE); 76 * object file alignment. Using 32768
77 *(.data.init_task) 77 */
78 78 . = ALIGN(_PAGE_SIZE);
79 DATA_DATA 79 *(.data.init_task)
80 CONSTRUCTORS 80
81 DATA_DATA
82 CONSTRUCTORS
81 } 83 }
82 _gp = . + 0x8000; 84 _gp = . + 0x8000;
83 .lit8 : { 85 .lit8 : {
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index df8cbe4c7c0d..436a64ff3989 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -942,8 +942,8 @@ static int vpe_elfload(struct vpe * v)
942 if (phdr->p_type != PT_LOAD) 942 if (phdr->p_type != PT_LOAD)
943 continue; 943 continue;
944 944
945 memcpy((void *)phdr->p_vaddr, (char *)hdr + phdr->p_offset, phdr->p_filesz); 945 memcpy((void *)phdr->p_paddr, (char *)hdr + phdr->p_offset, phdr->p_filesz);
946 memset((void *)phdr->p_vaddr + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz); 946 memset((void *)phdr->p_paddr + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz);
947 phdr++; 947 phdr++;
948 } 948 }
949 949