b145c9d7c6d7ff4f3534ed29a09f49f270f91a88
[openwrt.git] / target / linux / lantiq / patches-3.2 / 0057-MIPS-lantiq-VPE-extensions.patch
1 From 587ca6b21ab64ab014625b1cacb36ef711c74962 Mon Sep 17 00:00:00 2001
2 From: John Crispin <blogic@openwrt.org>
3 Date: Thu, 29 Sep 2011 20:30:40 +0200
4 Subject: [PATCH 57/70] MIPS: lantiq: VPE extensions
5
6 ---
7  arch/mips/Kconfig                  |   22 +++
8  arch/mips/include/asm/mipsmtregs.h |   54 +++++++
9  arch/mips/kernel/Makefile          |    3 +-
10  arch/mips/kernel/mips-mt.c         |   97 +++++++++++--
11  arch/mips/kernel/mtsched_proc.c    |  279 ++++++++++++++++++++++++++++++++++++
12  arch/mips/kernel/perf_proc.c       |  191 ++++++++++++++++++++++++
13  arch/mips/kernel/proc.c            |   17 +++
14  arch/mips/kernel/smtc.c            |    7 +
15  arch/mips/kernel/vpe.c             |  250 ++++++++++++++++++++++++++++++++-
16  9 files changed, 905 insertions(+), 15 deletions(-)
17  create mode 100644 arch/mips/kernel/mtsched_proc.c
18  create mode 100644 arch/mips/kernel/perf_proc.c
19
20 --- a/arch/mips/Kconfig
21 +++ b/arch/mips/Kconfig
22 @@ -1909,6 +1909,28 @@ config MIPS_VPE_LOADER
23           Includes a loader for loading an elf relocatable object
24           onto another VPE and running it.
25  
26 +config IFX_VPE_EXT
27 +       bool "IFX APRP Extensions"
28 +       depends on MIPS_VPE_LOADER
29 +       default y
30 +       help
31 +         IFX included extensions in APRP
32 +
33 +config PERFCTRS
34 +       bool "34K Performance counters"
35 +       depends on MIPS_MT && PROC_FS
36 +       default n
37 +       help
38 +         34K Performance counter through /proc
39 +
40 +config MTSCHED
41 +       bool "Support mtsched priority configuration for TCs"
42 +       depends on MIPS_MT && PROC_FS
43 +       default y
44 +       help
45 +         Support for mtsched priority configuration for TCs through
46 +         /proc/mips/mtsched
47 +
48  config MIPS_MT_SMTC_IM_BACKSTOP
49         bool "Use per-TC register bits as backstop for inhibited IM bits"
50         depends on MIPS_MT_SMTC
51 --- a/arch/mips/include/asm/mipsmtregs.h
52 +++ b/arch/mips/include/asm/mipsmtregs.h
53 @@ -28,14 +28,34 @@
54  #define read_c0_vpeconf0()             __read_32bit_c0_register($1, 2)
55  #define write_c0_vpeconf0(val)         __write_32bit_c0_register($1, 2, val)
56  
57 +#define read_c0_vpeconf1()              __read_32bit_c0_register($1, 3)
58 +#define write_c0_vpeconf1(val)          __write_32bit_c0_register($1, 3, val)
59 +
60 +#define read_c0_vpeschedule()           __read_32bit_c0_register($1, 5)
61 +#define write_c0_vpeschedule(val)       __write_32bit_c0_register($1, 5, val)
62 +
63 +#define read_c0_vpeschefback()         __read_32bit_c0_register($1, 6)
64 +#define write_c0_vpeschefback(val)     __write_32bit_c0_register($1, 6, val)
65 +
66 +#define read_c0_vpeopt()              __read_32bit_c0_register($1, 7)
67 +#define write_c0_vpeopt(val)          __write_32bit_c0_register($1, 7, val)
68 +
69  #define read_c0_tcstatus()             __read_32bit_c0_register($2, 1)
70  #define write_c0_tcstatus(val)         __write_32bit_c0_register($2, 1, val)
71  
72  #define read_c0_tcbind()               __read_32bit_c0_register($2, 2)
73 +#define write_c0_tcbind(val)           __write_32bit_c0_register($2, 2, val)
74  
75  #define read_c0_tccontext()            __read_32bit_c0_register($2, 5)
76  #define write_c0_tccontext(val)                __write_32bit_c0_register($2, 5, val)
77  
78 +#define read_c0_tcschedule()           __read_32bit_c0_register($2, 6)
79 +#define write_c0_tcschedule(val)       __write_32bit_c0_register($2, 6, val)
80 +
81 +#define read_c0_tcschefback()          __read_32bit_c0_register($2, 7)
82 +#define write_c0_tcschefback(val)      __write_32bit_c0_register($2, 7, val)
83 +
84 +
85  #else /* Assembly */
86  /*
87   * Macros for use in assembly language code
88 @@ -74,6 +94,8 @@
89  #define MVPCONTROL_STLB_SHIFT  2
90  #define MVPCONTROL_STLB                (_ULCAST_(1) << MVPCONTROL_STLB_SHIFT)
91  
92 +#define MVPCONTROL_CPA_SHIFT   3
93 +#define MVPCONTROL_CPA         (_ULCAST_(1) << MVPCONTROL_CPA_SHIFT)
94  
95  /* MVPConf0 fields */
96  #define MVPCONF0_PTC_SHIFT     0
97 @@ -84,6 +106,8 @@
98  #define MVPCONF0_TCA           ( _ULCAST_(1) << MVPCONF0_TCA_SHIFT)
99  #define MVPCONF0_PTLBE_SHIFT   16
100  #define MVPCONF0_PTLBE         (_ULCAST_(0x3ff) << MVPCONF0_PTLBE_SHIFT)
101 +#define MVPCONF0_PCP_SHIFT     27
102 +#define MVPCONF0_PCP           (_ULCAST_(1) << MVPCONF0_PCP_SHIFT)
103  #define MVPCONF0_TLBS_SHIFT    29
104  #define MVPCONF0_TLBS          (_ULCAST_(1) << MVPCONF0_TLBS_SHIFT)
105  #define MVPCONF0_M_SHIFT       31
106 @@ -121,9 +145,25 @@
107  #define VPECONF0_VPA           (_ULCAST_(1) << VPECONF0_VPA_SHIFT)
108  #define VPECONF0_MVP_SHIFT     1
109  #define VPECONF0_MVP           (_ULCAST_(1) << VPECONF0_MVP_SHIFT)
110 +#define VPECONF0_ICS_SHIFT      16
111 +#define VPECONF0_ICS           (_ULCAST_(1) << VPECONF0_ICS_SHIFT)
112 +#define VPECONF0_DCS_SHIFT      17
113 +#define VPECONF0_DCS            (_ULCAST_(1) << VPECONF0_DCS_SHIFT)
114  #define VPECONF0_XTC_SHIFT     21
115  #define VPECONF0_XTC           (_ULCAST_(0xff) << VPECONF0_XTC_SHIFT)
116  
117 +/* VPEOpt fields */
118 +#define VPEOPT_DWX_SHIFT       0
119 +#define VPEOPT_IWX_SHIFT       8
120 +#define VPEOPT_IWX0            ( _ULCAST_(0x1) << VPEOPT_IWX_SHIFT)
121 +#define VPEOPT_IWX1            ( _ULCAST_(0x2) << VPEOPT_IWX_SHIFT)
122 +#define VPEOPT_IWX2            ( _ULCAST_(0x4) << VPEOPT_IWX_SHIFT)
123 +#define VPEOPT_IWX3            ( _ULCAST_(0x8) << VPEOPT_IWX_SHIFT)
124 +#define VPEOPT_DWX0            ( _ULCAST_(0x1) << VPEOPT_DWX_SHIFT)
125 +#define VPEOPT_DWX1            ( _ULCAST_(0x2) << VPEOPT_DWX_SHIFT)
126 +#define VPEOPT_DWX2            ( _ULCAST_(0x4) << VPEOPT_DWX_SHIFT)
127 +#define VPEOPT_DWX3            ( _ULCAST_(0x8) << VPEOPT_DWX_SHIFT)
128 +
129  /* TCStatus fields (per TC) */
130  #define TCSTATUS_TASID         (_ULCAST_(0xff))
131  #define TCSTATUS_IXMT_SHIFT    10
132 @@ -350,6 +390,14 @@ do {                                                                       \
133  #define write_vpe_c0_vpecontrol(val)   mttc0(1, 1, val)
134  #define read_vpe_c0_vpeconf0()         mftc0(1, 2)
135  #define write_vpe_c0_vpeconf0(val)     mttc0(1, 2, val)
136 +#define read_vpe_c0_vpeschedule()      mftc0(1, 5)
137 +#define write_vpe_c0_vpeschedule(val)  mttc0(1, 5, val)
138 +#define read_vpe_c0_vpeschefback()     mftc0(1, 6)
139 +#define write_vpe_c0_vpeschefback(val) mttc0(1, 6, val)
140 +#define read_vpe_c0_vpeopt()            mftc0(1, 7)
141 +#define write_vpe_c0_vpeopt(val)        mttc0(1, 7, val)
142 +#define read_vpe_c0_wired()            mftc0(6, 0)
143 +#define write_vpe_c0_wired(val)                mttc0(6, 0, val)
144  #define read_vpe_c0_count()            mftc0(9, 0)
145  #define write_vpe_c0_count(val)                mttc0(9, 0, val)
146  #define read_vpe_c0_status()           mftc0(12, 0)
147 @@ -381,6 +429,12 @@ do {                                                                       \
148  #define write_tc_c0_tchalt(val)                mttc0(2, 4, val)
149  #define read_tc_c0_tccontext()         mftc0(2, 5)
150  #define write_tc_c0_tccontext(val)     mttc0(2, 5, val)
151 +#define read_tc_c0_tcschedule()                mftc0(2, 6)
152 +#define write_tc_c0_tcschedule(val)    mttc0(2, 6, val)
153 +#define read_tc_c0_tcschefback()       mftc0(2, 7)
154 +#define write_tc_c0_tcschefback(val)   mttc0(2, 7, val)
155 +#define read_tc_c0_entryhi()            mftc0(10, 0)
156 +#define write_tc_c0_entryhi(val)        mttc0(10, 0, val)
157  
158  /* GPR */
159  #define read_tc_gpr_sp()               mftgpr(29)
160 --- a/arch/mips/kernel/Makefile
161 +++ b/arch/mips/kernel/Makefile
162 @@ -88,7 +88,8 @@ obj-$(CONFIG_MIPS32_O32)      += binfmt_elfo3
163  
164  obj-$(CONFIG_KGDB)             += kgdb.o
165  obj-$(CONFIG_PROC_FS)          += proc.o
166 -
167 +obj-$(CONFIG_MTSCHED)          += mtsched_proc.o
168 +obj-$(CONFIG_PERFCTRS)         += perf_proc.o
169  obj-$(CONFIG_64BIT)            += cpu-bugs64.o
170  
171  obj-$(CONFIG_I8253)            += i8253.o
172 --- a/arch/mips/kernel/mips-mt.c
173 +++ b/arch/mips/kernel/mips-mt.c
174 @@ -21,26 +21,96 @@
175  #include <asm/cacheflush.h>
176  
177  int vpelimit;
178 -
179  static int __init maxvpes(char *str)
180  {
181         get_option(&str, &vpelimit);
182 -
183         return 1;
184  }
185 -
186  __setup("maxvpes=", maxvpes);
187  
188  int tclimit;
189 -
190  static int __init maxtcs(char *str)
191  {
192         get_option(&str, &tclimit);
193 +       return 1;
194 +}
195 +__setup("maxtcs=", maxtcs);
196  
197 +#ifdef CONFIG_IFX_VPE_EXT
198 +int stlb;
199 +static int __init istlbshared(char *str)
200 +{
201 +       get_option(&str, &stlb);
202         return 1;
203  }
204 +__setup("vpe_tlb_shared=", istlbshared);
205  
206 -__setup("maxtcs=", maxtcs);
207 +int vpe0_wired;
208 +static int __init vpe0wired(char *str)
209 +{
210 +       get_option(&str, &vpe0_wired);
211 +       return 1;
212 +}
213 +__setup("vpe0_wired_tlb_entries=", vpe0wired);
214 +
215 +int vpe1_wired;
216 +static int __init vpe1wired(char *str)
217 +{
218 +       get_option(&str, &vpe1_wired);
219 +       return 1;
220 +}
221 +__setup("vpe1_wired_tlb_entries=", vpe1wired);
222 +
223 +#ifdef CONFIG_MIPS_MT_SMTC
224 +extern int nostlb;
225 +#endif
226 +void configure_tlb(void)
227 +{
228 +       int vpeflags, tcflags, tlbsiz;
229 +       unsigned int config1val;
230 +       vpeflags = dvpe();
231 +       tcflags = dmt();
232 +       write_c0_vpeconf0((read_c0_vpeconf0() | VPECONF0_MVP));
233 +       write_c0_mvpcontrol((read_c0_mvpcontrol() | MVPCONTROL_VPC));
234 +       mips_ihb();
235 +       //printk("stlb = %d, vpe0_wired = %d vpe1_wired=%d\n", stlb,vpe0_wired, vpe1_wired);
236 +       if (stlb) {
237 +               if (!(read_c0_mvpconf0() & MVPCONF0_TLBS)) {
238 +                       emt(tcflags);
239 +                       evpe(vpeflags);
240 +                       return;
241 +               }
242 +
243 +               write_c0_mvpcontrol(read_c0_mvpcontrol() | MVPCONTROL_STLB);
244 +               write_c0_wired(vpe0_wired + vpe1_wired);
245 +               if (((read_vpe_c0_config() & MIPS_CONF_MT) >> 7) == 1) {
246 +                       config1val = read_vpe_c0_config1();
247 +                       tlbsiz = (((config1val >> 25) & 0x3f) + 1);
248 +                       if (tlbsiz > 64)
249 +                               tlbsiz = 64;
250 +                       cpu_data[0].tlbsize = tlbsiz;
251 +                       current_cpu_data.tlbsize = tlbsiz;
252 +               }
253 +
254 +       }
255 +       else {
256 +               write_c0_mvpcontrol(read_c0_mvpcontrol() & ~MVPCONTROL_STLB);
257 +               write_c0_wired(vpe0_wired);
258 +       }
259 +
260 +       ehb();
261 +       write_c0_mvpcontrol((read_c0_mvpcontrol() & ~MVPCONTROL_VPC));
262 +       ehb();
263 +       local_flush_tlb_all();
264 +
265 +       printk("Wired TLB entries for Linux read_c0_wired() = %d\n", read_c0_wired());
266 +#ifdef CONFIG_MIPS_MT_SMTC
267 +       nostlb = !stlb;
268 +#endif
269 +       emt(tcflags);
270 +       evpe(vpeflags);
271 +}
272 +#endif
273  
274  /*
275   * Dump new MIPS MT state for the core. Does not leave TCs halted.
276 @@ -78,18 +148,18 @@ void mips_mt_regdump(unsigned long mvpct
277                         if ((read_tc_c0_tcbind() & TCBIND_CURVPE) == i) {
278                                 printk("  VPE %d\n", i);
279                                 printk("   VPEControl : %08lx\n",
280 -                                      read_vpe_c0_vpecontrol());
281 +                                       read_vpe_c0_vpecontrol());
282                                 printk("   VPEConf0 : %08lx\n",
283 -                                      read_vpe_c0_vpeconf0());
284 +                                       read_vpe_c0_vpeconf0());
285                                 printk("   VPE%d.Status : %08lx\n",
286 -                                      i, read_vpe_c0_status());
287 +                                       i, read_vpe_c0_status());
288                                 printk("   VPE%d.EPC : %08lx %pS\n",
289 -                                      i, read_vpe_c0_epc(),
290 -                                      (void *) read_vpe_c0_epc());
291 +                                       i, read_vpe_c0_epc(),
292 +                                       (void *) read_vpe_c0_epc());
293                                 printk("   VPE%d.Cause : %08lx\n",
294 -                                      i, read_vpe_c0_cause());
295 +                                       i, read_vpe_c0_cause());
296                                 printk("   VPE%d.Config7 : %08lx\n",
297 -                                      i, read_vpe_c0_config7());
298 +                                       i, read_vpe_c0_config7());
299                                 break; /* Next VPE */
300                         }
301                 }
302 @@ -287,6 +357,9 @@ void mips_mt_set_cpuoptions(void)
303                 printk("Mapped %ld ITC cells starting at 0x%08x\n",
304                         ((itcblkgrn & 0x7fe00000) >> 20), itc_base);
305         }
306 +#ifdef CONFIG_IFX_VPE_EXT
307 +       configure_tlb();
308 +#endif
309  }
310  
311  /*
312 --- /dev/null
313 +++ b/arch/mips/kernel/mtsched_proc.c
314 @@ -0,0 +1,279 @@
315 +/*
316 + * /proc hooks for MIPS MT scheduling policy management for 34K cores
317 + *
318 + *  This program is free software; you can distribute it and/or modify it
319 + *  under the terms of the GNU General Public License (Version 2) as
320 + *  published by the Free Software Foundation.
321 + *
322 + *  This program is distributed in the hope it will be useful, but WITHOUT
323 + *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
324 + *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
325 + *  for more details.
326 + *
327 + *  You should have received a copy of the GNU General Public License along
328 + *  with this program; if not, write to the Free Software Foundation, Inc.,
329 + *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
330 + *
331 + * Copyright (C) 2006 Mips Technologies, Inc
332 + */
333 +
334 +#include <linux/kernel.h>
335 +
336 +#include <asm/cpu.h>
337 +#include <asm/processor.h>
338 +#include <asm/system.h>
339 +#include <asm/mipsregs.h>
340 +#include <asm/mipsmtregs.h>
341 +#include <asm/uaccess.h>
342 +#include <linux/proc_fs.h>
343 +
344 +static struct proc_dir_entry *mtsched_proc;
345 +
346 +#ifndef CONFIG_MIPS_MT_SMTC
347 +#define NTCS 2
348 +#else
349 +#define NTCS NR_CPUS
350 +#endif
351 +#define NVPES 2
352 +
353 +int lastvpe = 1;
354 +int lasttc = 8;
355 +
356 +static int proc_read_mtsched(char *page, char **start, off_t off,
357 +                       int count, int *eof, void *data)
358 +{
359 +       int totalen = 0;
360 +       int len;
361 +
362 +       int i;
363 +       int vpe;
364 +       int mytc;
365 +       unsigned long flags;
366 +       unsigned int mtflags;
367 +       unsigned int haltstate;
368 +       unsigned int vpes_checked[NVPES];
369 +       unsigned int vpeschedule[NVPES];
370 +       unsigned int vpeschefback[NVPES];
371 +       unsigned int tcschedule[NTCS];
372 +       unsigned int tcschefback[NTCS];
373 +
374 +       /* Dump the state of the MIPS MT scheduling policy manager */
375 +       /* Inititalize control state */
376 +       for(i = 0; i < NVPES; i++) {
377 +               vpes_checked[i] = 0;
378 +               vpeschedule[i] = 0;
379 +               vpeschefback[i] = 0;
380 +       }
381 +       for(i = 0; i < NTCS; i++) {
382 +               tcschedule[i] = 0;
383 +               tcschefback[i] = 0;
384 +       }
385 +
386 +       /* Disable interrupts and multithreaded issue */
387 +       local_irq_save(flags);
388 +       mtflags = dvpe();
389 +
390 +       /* Then go through the TCs, halt 'em, and extract the values */
391 +       mytc = (read_c0_tcbind() & TCBIND_CURTC) >> TCBIND_CURTC_SHIFT;
392 +       for(i = 0; i < NTCS; i++) {
393 +               if(i == mytc) {
394 +                       /* No need to halt ourselves! */
395 +                       tcschedule[i] = read_c0_tcschedule();
396 +                       tcschefback[i] = read_c0_tcschefback();
397 +                       /* If VPE bound to TC hasn't been checked, do it */
398 +                       vpe = read_c0_tcbind() & TCBIND_CURVPE;
399 +                       if(!vpes_checked[vpe]) {
400 +                               vpeschedule[vpe] = read_c0_vpeschedule();
401 +                               vpeschefback[vpe] = read_c0_vpeschefback();
402 +                               vpes_checked[vpe] = 1;
403 +                       }
404 +               } else {
405 +                       settc(i);
406 +                       haltstate = read_tc_c0_tchalt();
407 +                       write_tc_c0_tchalt(TCHALT_H);
408 +                       mips_ihb();
409 +                       tcschedule[i] = read_tc_c0_tcschedule();
410 +                       tcschefback[i] = read_tc_c0_tcschefback();
411 +                       /* If VPE bound to TC hasn't been checked, do it */
412 +                       vpe = read_tc_c0_tcbind() & TCBIND_CURVPE;
413 +                       if(!vpes_checked[vpe]) {
414 +                           vpeschedule[vpe] = read_vpe_c0_vpeschedule();
415 +                           vpeschefback[vpe] = read_vpe_c0_vpeschefback();
416 +                           vpes_checked[vpe] = 1;
417 +                       }
418 +                       if(!haltstate) write_tc_c0_tchalt(0);
419 +               }
420 +       }
421 +       /* Re-enable MT and interrupts */
422 +       evpe(mtflags);
423 +       local_irq_restore(flags);
424 +
425 +       for(vpe=0; vpe < NVPES; vpe++) {
426 +               len = sprintf(page, "VPE[%d].VPEschedule  = 0x%08x\n",
427 +                       vpe, vpeschedule[vpe]);
428 +               totalen += len;
429 +               page += len;
430 +               len = sprintf(page, "VPE[%d].VPEschefback = 0x%08x\n",
431 +                       vpe, vpeschefback[vpe]);
432 +               totalen += len;
433 +               page += len;
434 +       }
435 +       for(i=0; i < NTCS; i++) {
436 +               len = sprintf(page, "TC[%d].TCschedule    = 0x%08x\n",
437 +                       i, tcschedule[i]);
438 +               totalen += len;
439 +               page += len;
440 +               len = sprintf(page, "TC[%d].TCschefback   = 0x%08x\n",
441 +                       i, tcschefback[i]);
442 +               totalen += len;
443 +               page += len;
444 +       }
445 +       return totalen;
446 +}
447 +
448 +/*
449 + * Write to perf counter registers based on text input
450 + */
451 +
452 +#define TXTBUFSZ 100
453 +
454 +static int proc_write_mtsched(struct file *file, const char *buffer,
455 +                               unsigned long count, void *data)
456 +{
457 +       int len = 0;
458 +       char mybuf[TXTBUFSZ];
459 +       /* At most, we will set up 9 TCs and 2 VPEs, 11 entries in all */
460 +       char entity[1];   //, entity1[1];
461 +       int number[1];
462 +       unsigned long value[1];
463 +       int nparsed = 0 , index = 0;
464 +       unsigned long flags;
465 +       unsigned int mtflags;
466 +       unsigned int haltstate;
467 +       unsigned int tcbindval;
468 +
469 +       if(count >= TXTBUFSZ) len = TXTBUFSZ-1;
470 +       else len = count;
471 +       memset(mybuf,0,TXTBUFSZ);
472 +       if(copy_from_user(mybuf, buffer, len)) return -EFAULT;
473 +
474 +       nparsed = sscanf(mybuf, "%c%d %lx",
475 +                &entity[0] ,&number[0], &value[0]);
476 +
477 +       /*
478 +        * Having acquired the inputs, which might have
479 +        * generated exceptions and preemptions,
480 +        * program the registers.
481 +        */
482 +       /* Disable interrupts and multithreaded issue */
483 +       local_irq_save(flags);
484 +       mtflags = dvpe();
485 +
486 +       if(entity[index] == 't' ) {
487 +               /* Set TCSchedule or TCScheFBack of specified TC */
488 +               if(number[index] > NTCS) goto skip;
489 +               /* If it's our own TC, do it direct */
490 +               if(number[index] ==
491 +                               ((read_c0_tcbind() & TCBIND_CURTC)
492 +                               >> TCBIND_CURTC_SHIFT)) {
493 +                       if(entity[index] == 't')
494 +                                write_c0_tcschedule(value[index]);
495 +                       else
496 +                               write_c0_tcschefback(value[index]);
497 +               } else {
498 +               /* Otherwise, we do it via MTTR */
499 +                       settc(number[index]);
500 +                       haltstate = read_tc_c0_tchalt();
501 +                       write_tc_c0_tchalt(TCHALT_H);
502 +                       mips_ihb();
503 +                       if(entity[index] == 't')
504 +                                write_tc_c0_tcschedule(value[index]);
505 +                       else
506 +                               write_tc_c0_tcschefback(value[index]);
507 +                       mips_ihb();
508 +                       if(!haltstate) write_tc_c0_tchalt(0);
509 +               }
510 +       } else if(entity[index] == 'v') {
511 +               /* Set VPESchedule of specified VPE */
512 +               if(number[index] > NVPES) goto skip;
513 +               tcbindval = read_c0_tcbind();
514 +               /* Are we doing this to our current VPE? */
515 +               if((tcbindval & TCBIND_CURVPE) == number[index]) {
516 +                       /* Then life is simple */
517 +                       write_c0_vpeschedule(value[index]);
518 +               } else {
519 +                       /*
520 +                        * Bind ourselves to the other VPE long enough
521 +                        * to program the bind value.
522 +                        */
523 +                       write_c0_tcbind((tcbindval & ~TCBIND_CURVPE)
524 +                                          | number[index]);
525 +                       mips_ihb();
526 +                       write_c0_vpeschedule(value[index]);
527 +                       mips_ihb();
528 +                       /* Restore previous binding */
529 +                       write_c0_tcbind(tcbindval);
530 +                       mips_ihb();
531 +               }
532 +       }
533 +
534 +       else if(entity[index] == 'r') {
535 +               unsigned int vpes_checked[2], vpe ,i , mytc;
536 +               vpes_checked[0] = vpes_checked[1] = 0;
537 +
538 +               /* Then go through the TCs, halt 'em, and extract the values */
539 +               mytc = (read_c0_tcbind() & TCBIND_CURTC) >> TCBIND_CURTC_SHIFT;
540 +
541 +               for(i = 0; i < NTCS; i++) {
542 +                       if(i == mytc) {
543 +                               /* No need to halt ourselves! */
544 +                               write_c0_vpeschefback(0);
545 +                               write_c0_tcschefback(0);
546 +                       } else {
547 +                               settc(i);
548 +                               haltstate = read_tc_c0_tchalt();
549 +                               write_tc_c0_tchalt(TCHALT_H);
550 +                               mips_ihb();
551 +                               write_tc_c0_tcschefback(0);
552 +                               /* If VPE bound to TC hasn't been checked, do it */
553 +                               vpe = read_tc_c0_tcbind() & TCBIND_CURVPE;
554 +                               if(!vpes_checked[vpe]) {
555 +                                   write_vpe_c0_vpeschefback(0);
556 +                                   vpes_checked[vpe] = 1;
557 +                               }
558 +                               if(!haltstate) write_tc_c0_tchalt(0);
559 +                       }
560 +               }
561 +       }
562 +       else {
563 +               printk ("\n Usage : <t/v><0/1> <Hex Value>\n Example : t0 0x01\n");
564 +       }
565 +
566 +skip:
567 +       /* Re-enable MT and interrupts */
568 +       evpe(mtflags);
569 +       local_irq_restore(flags);
570 +       return (len);
571 +}
572 +
573 +static int __init init_mtsched_proc(void)
574 +{
575 +       extern struct proc_dir_entry *get_mips_proc_dir(void);
576 +       struct proc_dir_entry *mips_proc_dir;
577 +
578 +       if (!cpu_has_mipsmt) {
579 +               printk("mtsched: not a MIPS MT capable processor\n");
580 +               return -ENODEV;
581 +       }
582 +
583 +       mips_proc_dir = get_mips_proc_dir();
584 +
585 +       mtsched_proc = create_proc_entry("mtsched", 0644, mips_proc_dir);
586 +       mtsched_proc->read_proc = proc_read_mtsched;
587 +       mtsched_proc->write_proc = proc_write_mtsched;
588 +
589 +       return 0;
590 +}
591 +
592 +/* Automagically create the entry */
593 +module_init(init_mtsched_proc);
594 --- /dev/null
595 +++ b/arch/mips/kernel/perf_proc.c
596 @@ -0,0 +1,191 @@
597 +/*
598 + * /proc hooks for CPU performance counter support for SMTC kernel
599 + * (and ultimately others)
600 + * Copyright (C) 2006 Mips Technologies, Inc
601 + */
602 +
603 +#include <linux/kernel.h>
604 +
605 +#include <asm/cpu.h>
606 +#include <asm/processor.h>
607 +#include <asm/system.h>
608 +#include <asm/mipsregs.h>
609 +#include <asm/uaccess.h>
610 +#include <linux/proc_fs.h>
611 +
612 +/*
613 + * /proc diagnostic and statistics hooks
614 + */
615 +
616 +
617 +/* Internal software-extended event counters */
618 +
619 +static unsigned long long extencount[4] = {0,0,0,0};
620 +
621 +static struct proc_dir_entry *perf_proc;
622 +
623 +static int proc_read_perf(char *page, char **start, off_t off,
624 +                               int count, int *eof, void *data)
625 +{
626 +       int totalen = 0;
627 +       int len;
628 +
629 +       len = sprintf(page, "PerfCnt[0].Ctl : 0x%08x\n", read_c0_perfctrl0());
630 +       totalen += len;
631 +       page += len;
632 +       len = sprintf(page, "PerfCnt[0].Cnt : %Lu\n",
633 +               extencount[0] + (unsigned long long)((unsigned)read_c0_perfcntr0()));
634 +       totalen += len;
635 +       page += len;
636 +       len = sprintf(page, "PerfCnt[1].Ctl : 0x%08x\n", read_c0_perfctrl1());
637 +       totalen += len;
638 +       page += len;
639 +       len = sprintf(page, "PerfCnt[1].Cnt : %Lu\n",
640 +               extencount[1] + (unsigned long long)((unsigned)read_c0_perfcntr1()));
641 +       totalen += len;
642 +       page += len;
643 +       len = sprintf(page, "PerfCnt[2].Ctl : 0x%08x\n", read_c0_perfctrl2());
644 +       totalen += len;
645 +       page += len;
646 +       len = sprintf(page, "PerfCnt[2].Cnt : %Lu\n",
647 +               extencount[2] + (unsigned long long)((unsigned)read_c0_perfcntr2()));
648 +       totalen += len;
649 +       page += len;
650 +       len = sprintf(page, "PerfCnt[3].Ctl : 0x%08x\n", read_c0_perfctrl3());
651 +       totalen += len;
652 +       page += len;
653 +       len = sprintf(page, "PerfCnt[3].Cnt : %Lu\n",
654 +               extencount[3] + (unsigned long long)((unsigned)read_c0_perfcntr3()));
655 +       totalen += len;
656 +       page += len;
657 +
658 +       return totalen;
659 +}
660 +
661 +/*
662 + * Write to perf counter registers based on text input
663 + */
664 +
665 +#define TXTBUFSZ 100
666 +
667 +static int proc_write_perf(struct file *file, const char *buffer,
668 +                               unsigned long count, void *data)
669 +{
670 +       int len;
671 +       int nparsed;
672 +       int index;
673 +       char mybuf[TXTBUFSZ];
674 +
675 +       int which[4];
676 +       unsigned long control[4];
677 +       long long ctrdata[4];
678 +
679 +       if(count >= TXTBUFSZ) len = TXTBUFSZ-1;
680 +       else len = count;
681 +       memset(mybuf,0,TXTBUFSZ);
682 +       if(copy_from_user(mybuf, buffer, len)) return -EFAULT;
683 +
684 +       nparsed = sscanf(mybuf,
685 +                       "%d %lx %Ld %d %lx %Ld %d %lx %Ld %d %lx %Ld",
686 +                               &which[0], &control[0], &ctrdata[0],
687 +                               &which[1], &control[1], &ctrdata[1],
688 +                               &which[2], &control[2], &ctrdata[2],
689 +                               &which[3], &control[3], &ctrdata[3]);
690 +
691 +       for(index = 0; nparsed >= 3; index++) {
692 +               switch (which[index]) {
693 +               case 0:
694 +                       write_c0_perfctrl0(control[index]);
695 +                       if(ctrdata[index] != -1) {
696 +                           extencount[0] = (unsigned long long)ctrdata[index];
697 +                           write_c0_perfcntr0((unsigned long)0);
698 +                       }
699 +                       break;
700 +               case 1:
701 +                       write_c0_perfctrl1(control[index]);
702 +                       if(ctrdata[index] != -1) {
703 +                           extencount[1] = (unsigned long long)ctrdata[index];
704 +                           write_c0_perfcntr1((unsigned long)0);
705 +                       }
706 +                       break;
707 +               case 2:
708 +                       write_c0_perfctrl2(control[index]);
709 +                       if(ctrdata[index] != -1) {
710 +                           extencount[2] = (unsigned long long)ctrdata[index];
711 +                           write_c0_perfcntr2((unsigned long)0);
712 +                       }
713 +                       break;
714 +               case 3:
715 +                       write_c0_perfctrl3(control[index]);
716 +                       if(ctrdata[index] != -1) {
717 +                           extencount[3] = (unsigned long long)ctrdata[index];
718 +                           write_c0_perfcntr3((unsigned long)0);
719 +                       }
720 +                       break;
721 +               }
722 +               nparsed -= 3;
723 +       }
724 +       return (len);
725 +}
726 +
727 +extern int (*perf_irq)(void);
728 +
729 +/*
730 + * Invoked when timer interrupt vector picks up a perf counter overflow
731 + */
732 +
733 +static int perf_proc_irq(void)
734 +{
735 +       unsigned long snapshot;
736 +
737 +       /*
738 +        * It would be nice to do this as a loop, but we don't have
739 +        * indirect access to CP0 registers.
740 +        */
741 +       snapshot = read_c0_perfcntr0();
742 +       if ((long)snapshot < 0) {
743 +               extencount[0] +=
744 +                       (unsigned long long)((unsigned)read_c0_perfcntr0());
745 +               write_c0_perfcntr0(0);
746 +       }
747 +       snapshot = read_c0_perfcntr1();
748 +       if ((long)snapshot < 0) {
749 +               extencount[1] +=
750 +                       (unsigned long long)((unsigned)read_c0_perfcntr1());
751 +               write_c0_perfcntr1(0);
752 +       }
753 +       snapshot = read_c0_perfcntr2();
754 +       if ((long)snapshot < 0) {
755 +               extencount[2] +=
756 +                       (unsigned long long)((unsigned)read_c0_perfcntr2());
757 +               write_c0_perfcntr2(0);
758 +       }
759 +       snapshot = read_c0_perfcntr3();
760 +       if ((long)snapshot < 0) {
761 +               extencount[3] +=
762 +                       (unsigned long long)((unsigned)read_c0_perfcntr3());
763 +               write_c0_perfcntr3(0);
764 +       }
765 +       return 0;
766 +}
767 +
768 +static int __init init_perf_proc(void)
769 +{
770 +       extern struct proc_dir_entry *get_mips_proc_dir(void);
771 +
772 +       struct proc_dir_entry *mips_proc_dir = get_mips_proc_dir();
773 +
774 +       write_c0_perfcntr0(0);
775 +       write_c0_perfcntr1(0);
776 +       write_c0_perfcntr2(0);
777 +       write_c0_perfcntr3(0);
778 +       perf_proc = create_proc_entry("perf", 0644, mips_proc_dir);
779 +       perf_proc->read_proc = proc_read_perf;
780 +       perf_proc->write_proc = proc_write_perf;
781 +       perf_irq = perf_proc_irq;
782 +
783 +       return 0;
784 +}
785 +
786 +/* Automagically create the entry */
787 +module_init(init_perf_proc);
788 --- a/arch/mips/kernel/proc.c
789 +++ b/arch/mips/kernel/proc.c
790 @@ -7,6 +7,7 @@
791  #include <linux/kernel.h>
792  #include <linux/sched.h>
793  #include <linux/seq_file.h>
794 +#include <linux/proc_fs.h>
795  #include <asm/bootinfo.h>
796  #include <asm/cpu.h>
797  #include <asm/cpu-features.h>
798 @@ -110,3 +111,19 @@ const struct seq_operations cpuinfo_op =
799         .stop   = c_stop,
800         .show   = show_cpuinfo,
801  };
802 +
803 +/*
804 + * Support for MIPS/local /proc hooks in /proc/mips/
805 + */
806 +
807 +static struct proc_dir_entry *mips_proc = NULL;
808 +
809 +struct proc_dir_entry *get_mips_proc_dir(void)
810 +{
811 +       /*
812 +        * This ought not to be preemptable.
813 +        */
814 +       if(mips_proc == NULL)
815 +               mips_proc = proc_mkdir("mips", NULL);
816 +       return(mips_proc);
817 +}
818 --- a/arch/mips/kernel/smtc.c
819 +++ b/arch/mips/kernel/smtc.c
820 @@ -1334,6 +1334,13 @@ void smtc_get_new_mmu_context(struct mm_
821         asid = asid_cache(cpu);
822  
823         do {
824 +#ifdef CONFIG_IFX_VPE_EXT
825 +               /* If TLB is shared between AP and RP (AP is running SMTC),
826 +                  leave out max ASID i.e., ASID_MASK for RP
827 +                */
828 +               if (!nostlb && ((asid & ASID_MASK) == (ASID_MASK - 1)))
829 +                       asid++;
830 +#endif
831                 if (!((asid += ASID_INC) & ASID_MASK) ) {
832                         if (cpu_has_vtag_icache)
833                                 flush_icache_all();
834 --- a/arch/mips/kernel/vpe.c
835 +++ b/arch/mips/kernel/vpe.c
836 @@ -75,6 +75,58 @@ static struct kspd_notifications kspd_ev
837  static int kspd_events_reqd;
838  #endif
839  
840 +#ifdef CONFIG_IFX_VPE_EXT
841 +static int is_sdepgm;
842 +extern int stlb;
843 +extern int vpe0_wired;
844 +extern int vpe1_wired;
845 +unsigned int vpe1_load_addr;
846 +
847 +static int __init load_address(char *str)
848 +{
849 +       get_option(&str, &vpe1_load_addr);
850 +       return 1;
851 +}
852 +__setup("vpe1_load_addr=", load_address);
853 +
854 +#include <asm/mipsmtregs.h>
855 +#define write_vpe_c0_wired(val)                mttc0(6, 0, val)
856 +
857 +#ifndef COMMAND_LINE_SIZE
858 +#      define COMMAND_LINE_SIZE        512
859 +#endif
860 +
861 +char command_line[COMMAND_LINE_SIZE * 2];
862 +
863 +static unsigned int vpe1_mem;
864 +static int __init vpe1mem(char *str)
865 +{
866 +       vpe1_mem = memparse(str, &str);
867 +       return 1;
868 +}
869 +__setup("vpe1_mem=", vpe1mem);
870 +
871 +uint32_t vpe1_wdog_ctr;
872 +static int __init wdog_ctr(char *str)
873 +{
874 +       get_option(&str, &vpe1_wdog_ctr);
875 +       return 1;
876 +}
877 +
878 +__setup("vpe1_wdog_ctr_addr=", wdog_ctr);
879 +EXPORT_SYMBOL(vpe1_wdog_ctr);
880 +
881 +uint32_t vpe1_wdog_timeout;
882 +static int __init wdog_timeout(char *str)
883 +{
884 +        get_option(&str, &vpe1_wdog_timeout);
885 +        return 1;
886 +}
887 +
888 +__setup("vpe1_wdog_timeout=", wdog_timeout);
889 +EXPORT_SYMBOL(vpe1_wdog_timeout);
890 +
891 +#endif
892  /* grab the likely amount of memory we will need. */
893  #ifdef CONFIG_MIPS_VPE_LOADER_TOM
894  #define P_SIZE (2 * 1024 * 1024)
895 @@ -267,6 +319,13 @@ static void *alloc_progmem(unsigned long
896         void *addr;
897  
898  #ifdef CONFIG_MIPS_VPE_LOADER_TOM
899 +#ifdef CONFIG_IFX_VPE_EXT
900 +       if (vpe1_load_addr) {
901 +               memset((void *)vpe1_load_addr, 0, len);
902 +               return (void *)vpe1_load_addr;
903 +       }
904 +#endif
905 +
906         /*
907          * This means you must tell Linux to use less memory than you
908          * physically have, for example by passing a mem= boot argument.
909 @@ -745,6 +804,12 @@ static int vpe_run(struct vpe * v)
910         }
911  
912         /* Write the address we want it to start running from in the TCPC register. */
913 +#if defined(CONFIG_IFX_VPE_EXT) && 0
914 +       if (stlb)
915 +               write_vpe_c0_wired(vpe0_wired + vpe1_wired);
916 +       else
917 +               write_vpe_c0_wired(vpe1_wired);
918 +#endif
919         write_tc_c0_tcrestart((unsigned long)v->__start);
920         write_tc_c0_tccontext((unsigned long)0);
921  
922 @@ -758,6 +823,20 @@ static int vpe_run(struct vpe * v)
923  
924         write_tc_c0_tchalt(read_tc_c0_tchalt() & ~TCHALT_H);
925  
926 +#if defined(CONFIG_IFX_VPE_EXT) && 0
927 +       /*
928 +        * $a2 & $a3 are used to pass command line parameters to VPE1. $a2
929 +        * points to the start of the command line string and $a3 points to
930 +        * the end of the string. This convention is identical to the Linux
931 +        * kernel boot parameter passing mechanism. Please note that $a3 is
932 +        * used to pass physical memory size or 0 in SDE tool kit. So, if you
933 +        * are passing comand line parameters through $a2 & $a3 SDE programs
934 +        * don't work as desired.
935 +        */
936 +       mttgpr(6, command_line);
937 +       mttgpr(7, (command_line + strlen(command_line)));
938 +       if (is_sdepgm)
939 +#endif
940         /*
941          * The sde-kit passes 'memsize' to __start in $a3, so set something
942          * here...  Or set $a3 to zero and define DFLT_STACK_SIZE and
943 @@ -832,6 +911,9 @@ static int find_vpe_symbols(struct vpe *
944         if ( (v->__start == 0) || (v->shared_ptr == NULL))
945                 return -1;
946  
947 +#ifdef CONFIG_IFX_VPE_EXT
948 +       is_sdepgm = 1;
949 +#endif
950         return 0;
951  }
952  
953 @@ -993,6 +1075,15 @@ static int vpe_elfload(struct vpe * v)
954                            (unsigned long)v->load_addr + v->len);
955  
956         if ((find_vpe_symbols(v, sechdrs, symindex, strtab, &mod)) < 0) {
957 +#ifdef CONFIG_IFX_VPE_EXT
958 +               if (vpe1_load_addr) {
959 +                       /* Conversion to KSEG1 is required ??? */
960 +                       v->__start = KSEG1ADDR(vpe1_load_addr);
961 +                       is_sdepgm = 0;
962 +                       return 0;
963 +               }
964 +#endif
965 +
966                 if (v->__start == 0) {
967                         printk(KERN_WARNING "VPE loader: program does not contain "
968                                "a __start symbol\n");
969 @@ -1063,6 +1154,9 @@ static int vpe_open(struct inode *inode,
970         struct vpe_notifications *not;
971         struct vpe *v;
972         int ret;
973 +#ifdef CONFIG_IFX_VPE_EXT
974 +   int progsize;
975 +#endif
976  
977         if (minor != iminor(inode)) {
978                 /* assume only 1 device at the moment. */
979 @@ -1088,7 +1182,12 @@ static int vpe_open(struct inode *inode,
980                 release_progmem(v->load_addr);
981                 cleanup_tc(get_tc(tclimit));
982         }
983 -
984 +#ifdef CONFIG_IFX_VPE_EXT
985 +       progsize = (vpe1_mem  != 0) ? vpe1_mem : P_SIZE;
986 +       //printk("progsize = %x\n", progsize);
987 +       v->pbuffer = vmalloc(progsize);
988 +       v->plen = progsize;
989 +#else
990         /* this of-course trashes what was there before... */
991         v->pbuffer = vmalloc(P_SIZE);
992         if (!v->pbuffer) {
993 @@ -1096,11 +1195,14 @@ static int vpe_open(struct inode *inode,
994                 return -ENOMEM;
995         }
996         v->plen = P_SIZE;
997 +#endif
998         v->load_addr = NULL;
999         v->len = 0;
1000  
1001 +#if 0
1002         v->uid = filp->f_cred->fsuid;
1003         v->gid = filp->f_cred->fsgid;
1004 +#endif
1005  
1006  #ifdef CONFIG_MIPS_APSP_KSPD
1007         /* get kspd to tell us when a syscall_exit happens */
1008 @@ -1348,6 +1450,133 @@ static void kspd_sp_exit( int sp_id)
1009         cleanup_tc(get_tc(sp_id));
1010  }
1011  #endif
1012 +#ifdef CONFIG_IFX_VPE_EXT
1013 +int32_t vpe1_sw_start(void* sw_start_addr, uint32_t tcmask, uint32_t flags)
1014 +{
1015 +       enum vpe_state state;
1016 +       struct vpe *v = get_vpe(tclimit);
1017 +       struct vpe_notifications *not;
1018 +
1019 +       if (tcmask || flags) {
1020 +               printk(KERN_WARNING "Currently tcmask and flags should be 0.\
1021 +                               other values not supported\n");
1022 +               return -1;
1023 +       }
1024 +
1025 +       state = xchg(&v->state, VPE_STATE_INUSE);
1026 +       if (state != VPE_STATE_UNUSED) {
1027 +               vpe_stop(v);
1028 +
1029 +               list_for_each_entry(not, &v->notify, list) {
1030 +                       not->stop(tclimit);
1031 +               }
1032 +       }
1033 +
1034 +       v->__start = (unsigned long)sw_start_addr;
1035 +       is_sdepgm = 0;
1036 +
1037 +       if (!vpe_run(v)) {
1038 +               printk(KERN_DEBUG "VPE loader: VPE1 running successfully\n");
1039 +               return 0;
1040 +       }
1041 +       return -1;
1042 +}
1043 +
1044 +EXPORT_SYMBOL(vpe1_sw_start);
1045 +
1046 +int32_t vpe1_sw_stop(uint32_t flags)
1047 +{
1048 +       struct vpe *v = get_vpe(tclimit);
1049 +
1050 +       if (!vpe_free(v)) {
1051 +               printk(KERN_DEBUG "RP Stopped\n");
1052 +               return 0;
1053 +       }
1054 +       else
1055 +               return -1;
1056 +}
1057 +
1058 +EXPORT_SYMBOL(vpe1_sw_stop);
1059 +
1060 +uint32_t vpe1_get_load_addr (uint32_t flags)
1061 +{
1062 +       return vpe1_load_addr;
1063 +}
1064 +
1065 +EXPORT_SYMBOL(vpe1_get_load_addr);
1066 +
1067 +uint32_t vpe1_get_max_mem (uint32_t flags)
1068 +{
1069 +       if (!vpe1_mem)
1070 +               return P_SIZE;
1071 +       else
1072 +               return vpe1_mem;
1073 +}
1074 +
1075 +EXPORT_SYMBOL(vpe1_get_max_mem);
1076 +
1077 +void* vpe1_get_cmdline_argument(void)
1078 +{
1079 +       return saved_command_line;
1080 +}
1081 +
1082 +EXPORT_SYMBOL(vpe1_get_cmdline_argument);
1083 +
1084 +int32_t vpe1_set_boot_param(char *field, char *value, char flags)
1085 +{
1086 +       char *ptr, string[64];
1087 +       int start_off, end_off;
1088 +       if (!field)
1089 +               return -1;
1090 +       strcpy(string, field);
1091 +       if (value) {
1092 +               strcat(string, "=");
1093 +               strcat(string, value);
1094 +               strcat(command_line, " ");
1095 +               strcat(command_line, string);
1096 +       }
1097 +       else {
1098 +               ptr = strstr(command_line, string);
1099 +               if (ptr) {
1100 +                       start_off = ptr - command_line;
1101 +                       ptr += strlen(string);
1102 +                       while ((*ptr != ' ') && (*ptr != '\0'))
1103 +                               ptr++;
1104 +                       end_off = ptr - command_line;
1105 +                       command_line[start_off] = '\0';
1106 +                       strcat (command_line, command_line+end_off);
1107 +               }
1108 +       }
1109 +       return 0;
1110 +}
1111 +
1112 +EXPORT_SYMBOL(vpe1_set_boot_param);
1113 +
1114 +int32_t vpe1_get_boot_param(char *field, char **value, char flags)
1115 +{
1116 +       char *ptr, string[64];
1117 +       int i = 0;
1118 +       if (!field)
1119 +               return -1;
1120 +       if ((ptr = strstr(command_line, field))) {
1121 +               ptr += strlen(field) + 1; /* including = */
1122 +               while ((*ptr != ' ') && (*ptr != '\0'))
1123 +                       string[i++] = *ptr++;
1124 +               string[i] = '\0';
1125 +               *value = kmalloc((strlen(string) + 1), GFP_KERNEL);
1126 +               if (*value != NULL)
1127 +                       strcpy(*value, string);
1128 +       }
1129 +       else
1130 +               *value = NULL;
1131 +
1132 +       return 0;
1133 +}
1134 +
1135 +EXPORT_SYMBOL(vpe1_get_boot_param);
1136 +
1137 +extern void configure_tlb(void);
1138 +#endif
1139  
1140  static ssize_t store_kill(struct device *dev, struct device_attribute *attr,
1141                           const char *buf, size_t len)
1142 @@ -1429,6 +1658,18 @@ static int __init vpe_module_init(void)
1143                 printk("VPE loader: not a MIPS MT capable processor\n");
1144                 return -ENODEV;
1145         }
1146 +#ifdef CONFIG_IFX_VPE_EXT
1147 +#ifndef CONFIG_MIPS_MT_SMTC
1148 +       configure_tlb();
1149 +#endif
1150 +#endif
1151 +
1152 +#ifndef CONFIG_MIPS_MT_SMTC
1153 +       if (!vpelimit)
1154 +               vpelimit = 1;
1155 +       if (!tclimit)
1156 +               tclimit = 1;
1157 +#endif
1158  
1159         if (vpelimit == 0) {
1160                 printk(KERN_WARNING "No VPEs reserved for AP/SP, not "
1161 @@ -1473,10 +1714,12 @@ static int __init vpe_module_init(void)
1162         mtflags = dmt();
1163         vpflags = dvpe();
1164  
1165 +       back_to_back_c0_hazard();
1166 +
1167         /* Put MVPE's into 'configuration state' */
1168         set_c0_mvpcontrol(MVPCONTROL_VPC);
1169  
1170 -       /* dump_mtregs(); */
1171 +       dump_mtregs();
1172  
1173         val = read_c0_mvpconf0();
1174         hw_tcs = (val & MVPCONF0_PTC) + 1;
1175 @@ -1488,6 +1731,7 @@ static int __init vpe_module_init(void)
1176                  * reschedule send IPIs or similar we might hang.
1177                  */
1178                 clear_c0_mvpcontrol(MVPCONTROL_VPC);
1179 +               back_to_back_c0_hazard();
1180                 evpe(vpflags);
1181                 emt(mtflags);
1182                 local_irq_restore(flags);
1183 @@ -1513,6 +1757,7 @@ static int __init vpe_module_init(void)
1184                         }
1185  
1186                         v->ntcs = hw_tcs - tclimit;
1187 +                        write_tc_c0_tcbind((read_tc_c0_tcbind() & ~TCBIND_CURVPE) | 1);
1188  
1189                         /* add the tc to the list of this vpe's tc's. */
1190                         list_add(&t->tc, &v->tc);
1191 @@ -1581,6 +1826,7 @@ static int __init vpe_module_init(void)
1192  out_reenable:
1193         /* release config state */
1194         clear_c0_mvpcontrol(MVPCONTROL_VPC);
1195 +       back_to_back_c0_hazard();
1196  
1197         evpe(vpflags);
1198         emt(mtflags);