]> err.no Git - linux-2.6/commitdiff
Support for MIPSsim, the cycle accurate MIPS simulator.
authorRalf Baechle <ralf@linux-mips.org>
Fri, 30 Sep 2005 12:59:37 +0000 (13:59 +0100)
committerRalf Baechle <ralf@linux-mips.org>
Sat, 29 Oct 2005 18:32:30 +0000 (19:32 +0100)
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
17 files changed:
arch/mips/Kconfig
arch/mips/Makefile
arch/mips/kernel/head.S
arch/mips/mips-boards/sim/Makefile [new file with mode: 0644]
arch/mips/mips-boards/sim/cmdline.c [new file with mode: 0644]
arch/mips/mips-boards/sim/sim_IRQ.c [new file with mode: 0644]
arch/mips/mips-boards/sim/sim_cmdline.c [new file with mode: 0644]
arch/mips/mips-boards/sim/sim_int.c [new file with mode: 0644]
arch/mips/mips-boards/sim/sim_irq.S [new file with mode: 0644]
arch/mips/mips-boards/sim/sim_mem.c [new file with mode: 0644]
arch/mips/mips-boards/sim/sim_printf.c [new file with mode: 0644]
arch/mips/mips-boards/sim/sim_setup.c [new file with mode: 0644]
arch/mips/mips-boards/sim/sim_smp.c [new file with mode: 0644]
arch/mips/mips-boards/sim/sim_time.c [new file with mode: 0644]
include/asm-mips/mach-sim/cpu-feature-overrides.h [new file with mode: 0644]
include/asm-mips/mips-boards/sim.h [new file with mode: 0644]
include/asm-mips/mips-boards/simint.h [new file with mode: 0644]

index bca73426b6f183bf9357ca1e5364512219ca2828..b11ed7ff0afd52f1a4bbd3b3ec7bb93292d080f3 100644 (file)
@@ -448,6 +448,17 @@ config MOMENCO_OCELOT_3
          The Ocelot-3 is based off Discovery III System Controller and
          PMC-Sierra Rm79000 core.
 
+config MIPS_SIM
+       bool 'Support for MIPS simulator (MIPSsim)'
+       select DMA_NONCOHERENT
+       select IRQ_CPU
+       select SYS_SUPPORTS_32BIT_KERNEL
+       select SYS_SUPPORTS_BIG_ENDIAN
+       select SYS_SUPPORTS_LITTLE_ENDIAN
+       help
+         This option enables support for MIPS Technologies MIPSsim software
+         emulator.
+
 config MOMENCO_JAGUAR_ATX
        bool "Support for Momentum Jaguar board"
        select BOOT_ELF32
index 3dc2fb81fb2801f452076c8efbbe6d467ec481b9..4d0645cb572545210e5aea3bdb6067d9ae0d297c 100644 (file)
@@ -436,6 +436,13 @@ load-$(CONFIG_MIPS_MALTA)  += 0xffffffff80100000
 core-$(CONFIG_MIPS_SEAD)       += arch/mips/mips-boards/sead/
 load-$(CONFIG_MIPS_SEAD)       += 0xffffffff80100000
 
+#
+# MIPS SIM
+#
+core-$(CONFIG_MIPS_SIM)                += arch/mips/mips-boards/sim/
+cflags-$(CONFIG_MIPS_SIM)      += -Iinclude/asm-mips/mach-sim
+load-$(CONFIG_MIPS_SIM)                += 0x80100000
+
 #
 # Momentum Ocelot board
 #
index d2de5d025dbf328e84a96721e90ad05d84a5a9ad..2e9122a4213a2215480637903b0948910ef6128c 100644 (file)
 EXPORT(stext)                                  # used for profiling
 EXPORT(_stext)
 
-#ifdef CONFIG_QEMU
+#if defined(CONFIG_QEMU) || defined(CONFIG_MIPS_SIM)
        /*
         * Give us a fighting chance of running if execution beings at the
         * kernel load address.  This is needed because this platform does
diff --git a/arch/mips/mips-boards/sim/Makefile b/arch/mips/mips-boards/sim/Makefile
new file mode 100644 (file)
index 0000000..5b977de
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+#
+# This program is free software; you can distribute it and/or modify it
+# under the terms of the GNU General Public License (Version 2) as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+
+obj-y := sim_setup.o sim_mem.o sim_time.o sim_printf.o sim_int.o sim_irq.o \
+       sim_cmdline.o
+obj-$(CONFIG_SMP) += sim_smp.o
diff --git a/arch/mips/mips-boards/sim/cmdline.c b/arch/mips/mips-boards/sim/cmdline.c
new file mode 100644 (file)
index 0000000..fef9fbd
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Kernel command line creation using the prom monitor (YAMON) argc/argv.
+ */
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+
+extern int prom_argc;
+extern int *_prom_argv;
+
+/*
+ * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
+ * This macro take care of sign extension.
+ */
+#define prom_argv(index) ((char *)(((int *)(int)_prom_argv)[(index)]))
+
+char arcs_cmdline[CL_SIZE];
+
+char * __init prom_getcmdline(void)
+{
+       return &(arcs_cmdline[0]);
+}
+
+
+void  __init prom_init_cmdline(void)
+{
+       char *cp;
+       int actr;
+
+       actr = 1; /* Always ignore argv[0] */
+
+       cp = &(arcs_cmdline[0]);
+       while(actr < prom_argc) {
+               strcpy(cp, prom_argv(actr));
+               cp += strlen(prom_argv(actr));
+               *cp++ = ' ';
+               actr++;
+       }
+       if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
+               --cp;
+       *cp = '\0';
+}
diff --git a/arch/mips/mips-boards/sim/sim_IRQ.c b/arch/mips/mips-boards/sim/sim_IRQ.c
new file mode 100644 (file)
index 0000000..9987a85
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999, 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Interrupt exception dispatch code.
+ */
+#include <linux/config.h>
+
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/* A lot of complication here is taken away because:
+ *
+ * 1) We handle one interrupt and return, sitting in a loop and moving across
+ *    all the pending IRQ bits in the cause register is _NOT_ the answer, the
+ *    common case is one pending IRQ so optimize in that direction.
+ *
+ * 2) We need not check against bits in the status register IRQ mask, that
+ *    would make this routine slow as hell.
+ *
+ * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
+ *    between like BSD spl() brain-damage.
+ *
+ * Furthermore, the IRQs on the MIPS board look basically (barring software
+ * IRQs which we don't use at all and all external interrupt sources are
+ * combined together on hardware interrupt 0 (MIPS IRQ 2)) like:
+ *
+ *     MIPS IRQ        Source
+ *      --------        ------
+ *             0       Software (ignored)
+ *             1        Software (ignored)
+ *             2        Combined hardware interrupt (hw0)
+ *             3        Hardware (ignored)
+ *             4        Hardware (ignored)
+ *             5        Hardware (ignored)
+ *             6        Hardware (ignored)
+ *             7        R4k timer (what we use)
+ *
+ * Note: On the SEAD board thing are a little bit different.
+ *       Here IRQ 2 (hw0) is wired to the UART0 and IRQ 3 (hw1) is wired
+ *       wired to UART1.
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ----     R4k Timer
+ * Lowest  ----     Combined hardware interrupt
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+
+       .text
+       .set    noreorder
+       .set    noat
+       .align  5
+       NESTED(mipsIRQ, PT_SIZE, sp)
+       SAVE_ALL
+       CLI
+       .set    at
+
+       mfc0    s0, CP0_CAUSE           # get irq bits
+       mfc0    s1, CP0_STATUS          # get irq mask
+       and     s0, s1
+
+       /* First we check for r4k counter/timer IRQ. */
+       andi    a0, s0, CAUSEF_IP7
+       beq     a0, zero, 1f
+        andi   a0, s0, CAUSEF_IP2      # delay slot, check hw0 interrupt
+
+       /* Wheee, a timer interrupt. */
+       move    a0, sp
+       jal     mips_timer_interrupt
+        nop
+
+       j       ret_from_irq
+        nop
+
+1:
+#if defined(CONFIG_MIPS_SEAD)
+       beq     a0, zero, 1f
+        andi   a0, s0, CAUSEF_IP3      # delay slot, check hw1 interrupt
+#else
+       beq     a0, zero, 1f            # delay slot, check hw3 interrupt
+        andi   a0, s0, CAUSEF_IP5
+#endif
+
+       /* Wheee, combined hardware level zero interrupt. */
+#if defined(CONFIG_MIPS_ATLAS)
+       jal     atlas_hw0_irqdispatch
+#elif defined(CONFIG_MIPS_MALTA)
+       jal     malta_hw0_irqdispatch
+#elif defined(CONFIG_MIPS_SEAD)
+       jal     sead_hw0_irqdispatch
+#else
+#error "MIPS board not supported\n"
+#endif
+        move   a0, sp                  # delay slot
+
+       j       ret_from_irq
+        nop                            # delay slot
+
+1:
+#if defined(CONFIG_MIPS_SEAD)
+       beq     a0, zero, 1f
+        andi   a0, s0, CAUSEF_IP5      # delay slot, check hw3 interrupt
+       jal     sead_hw1_irqdispatch
+        move   a0, sp                  # delay slot
+       j       ret_from_irq
+        nop                            # delay slot
+1:
+#endif
+#if defined(CONFIG_MIPS_MALTA)
+       beq     a0, zero, 1f            # check hw3 (coreHI) interrupt
+        nop
+       jal     corehi_irqdispatch
+        move   a0, sp
+       j       ret_from_irq
+        nop
+1:
+#endif
+       /*
+        * Here by mistake?  This is possible, what can happen is that by the
+        * time we take the exception the IRQ pin goes low, so just leave if
+        * this is the case.
+        */
+       move    a1,s0
+       PRINT("Got interrupt: c0_cause = %08x\n")
+       mfc0    a1, CP0_EPC
+       PRINT("c0_epc = %08x\n")
+
+       j       ret_from_irq
+        nop
+       END(mipsIRQ)
diff --git a/arch/mips/mips-boards/sim/sim_cmdline.c b/arch/mips/mips-boards/sim/sim_cmdline.c
new file mode 100644 (file)
index 0000000..9df37c6
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ */
+#include <linux/init.h>
+#include <linux/string.h>
+#include <asm/bootinfo.h>
+
+extern char arcs_cmdline[];
+
+char * __init prom_getcmdline(void)
+{
+       return arcs_cmdline;
+}
+
+
+void  __init prom_init_cmdline(void)
+{
+    /* nothing to do */
+}
diff --git a/arch/mips/mips-boards/sim/sim_int.c b/arch/mips/mips-boards/sim/sim_int.c
new file mode 100644 (file)
index 0000000..a4d0a2c
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 1999, 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ */
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <asm/mips-boards/simint.h>
+
+
+extern void mips_cpu_irq_init(int);
+
+extern asmlinkage void simIRQ(void);
+
+asmlinkage void sim_hw0_irqdispatch(struct pt_regs *regs)
+{
+       do_IRQ(2, regs);
+}
+
+void __init arch_init_irq(void)
+{
+       /* Now safe to set the exception vector. */
+       set_except_vector(0, simIRQ);
+
+       mips_cpu_irq_init(MIPSCPU_INT_BASE);
+}
diff --git a/arch/mips/mips-boards/sim/sim_irq.S b/arch/mips/mips-boards/sim/sim_irq.S
new file mode 100644 (file)
index 0000000..835f038
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 1999, 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Interrupt exception dispatch code.
+ *
+ */
+#include <linux/config.h>
+
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+#include <asm/mips-boards/simint.h>
+
+
+       .text
+       .set    noreorder
+       .set    noat
+       .align  5
+       NESTED(simIRQ, PT_SIZE, sp)
+       SAVE_ALL
+       CLI
+       .set    at
+
+       mfc0    s0, CP0_CAUSE           # get irq bits
+       mfc0    s1, CP0_STATUS          # get irq mask
+       andi    s0, ST0_IM              # CAUSE.CE may be non-zero!
+       and     s0, s1
+
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+       .set    mips32
+       clz     a0, s0
+       .set    mips0
+       negu    a0
+       addu    a0, 31-CAUSEB_IP
+       bltz    a0, spurious
+#else
+       beqz    s0, spurious
+        li     a0, 7
+
+       and     t0, s0, 0xf000
+       sltiu   t0, t0, 1
+       sll     t0, 2
+       subu    a0, t0
+       sll     s0, t0
+
+       and     t0, s0, 0xc000
+       sltiu   t0, t0, 1
+       sll     t0, 1
+       subu    a0, t0
+       sll     s0, t0
+
+       and     t0, s0, 0x8000
+       sltiu   t0, t0, 1
+       # sll   t0, 0
+       subu    a0, t0
+       # sll   s0, t0
+#endif
+
+#ifdef CASCADE_IRQ
+        li     a1, CASCADE_IRQ
+       bne     a0, a1, 1f
+        addu   a0, MIPSCPU_INT_BASE
+
+       jal     CASCADE_DISPATCH
+        move    a0, sp
+
+       j       ret_from_irq
+        nop
+1:
+#else
+        addu   a0, MIPSCPU_INT_BASE
+#endif
+
+       jal     do_IRQ
+        move   a1, sp
+
+       j       ret_from_irq
+        nop
+
+
+spurious:
+       j       spurious_interrupt
+        nop
+       END(simIRQ)
diff --git a/arch/mips/mips-boards/sim/sim_mem.c b/arch/mips/mips-boards/sim/sim_mem.c
new file mode 100644 (file)
index 0000000..0dbd743
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+
+#include <asm/mips-boards/prom.h>
+
+/*#define DEBUG*/
+
+enum simmem_memtypes {
+       simmem_reserved = 0,
+       simmem_free,
+};
+struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
+
+#ifdef DEBUG
+static char *mtypes[3] = {
+       "SIM reserved memory",
+       "SIM free memory",
+};
+#endif
+
+/* References to section boundaries */
+extern char _end;
+
+#define PFN_ALIGN(x)    (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
+
+
+struct prom_pmemblock * __init prom_getmdesc(void)
+{
+       unsigned int memsize;
+
+       memsize = 0x02000000;
+       prom_printf("Setting default memory size 0x%08x\n", memsize);
+
+       memset(mdesc, 0, sizeof(mdesc));
+
+       mdesc[0].type = simmem_reserved;
+       mdesc[0].base = 0x00000000;
+       mdesc[0].size = 0x00001000;
+
+       mdesc[1].type = simmem_free;
+       mdesc[1].base = 0x00001000;
+       mdesc[1].size = 0x000ff000;
+
+       mdesc[2].type = simmem_reserved;
+       mdesc[2].base = 0x00100000;
+       mdesc[2].size = CPHYSADDR(PFN_ALIGN(&_end)) - mdesc[2].base;
+
+       mdesc[3].type = simmem_free;
+       mdesc[3].base = CPHYSADDR(PFN_ALIGN(&_end));
+       mdesc[3].size = memsize - mdesc[3].base;
+
+       return &mdesc[0];
+}
+
+static int __init prom_memtype_classify (unsigned int type)
+{
+       switch (type) {
+       case simmem_free:
+               return BOOT_MEM_RAM;
+       case simmem_reserved:
+       default:
+               return BOOT_MEM_RESERVED;
+       }
+}
+
+void __init prom_meminit(void)
+{
+       struct prom_pmemblock *p;
+
+       p = prom_getmdesc();
+
+       while (p->size) {
+               long type;
+               unsigned long base, size;
+
+               type = prom_memtype_classify (p->type);
+               base = p->base;
+               size = p->size;
+
+               add_memory_region(base, size, type);
+                p++;
+       }
+}
+
+unsigned long __init prom_free_prom_memory(void)
+{
+       int i;
+       unsigned long freed = 0;
+       unsigned long addr;
+
+       for (i = 0; i < boot_mem_map.nr_map; i++) {
+               if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
+                       continue;
+
+               addr = boot_mem_map.map[i].addr;
+               while (addr < boot_mem_map.map[i].addr
+                             + boot_mem_map.map[i].size) {
+                       ClearPageReserved(virt_to_page(__va(addr)));
+                       set_page_count(virt_to_page(__va(addr)), 1);
+                       free_page((unsigned long)__va(addr));
+                       addr += PAGE_SIZE;
+                       freed += PAGE_SIZE;
+               }
+       }
+       printk("Freeing prom memory: %ldkb freed\n", freed >> 10);
+
+       return freed;
+}
diff --git a/arch/mips/mips-boards/sim/sim_printf.c b/arch/mips/mips-boards/sim/sim_printf.c
new file mode 100644 (file)
index 0000000..3ee5a0b
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Putting things on the screen/serial line using YAMONs facilities.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/serial_reg.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+static inline unsigned int serial_in(int offset)
+{
+       return inb(0x3f8 + offset);
+}
+
+static inline void serial_out(int offset, int value)
+{
+       outb(value, 0x3f8 + offset);
+}
+
+int putPromChar(char c)
+{
+       while ((serial_in(UART_LSR) & UART_LSR_THRE) == 0)
+               ;
+
+       serial_out(UART_TX, c);
+
+       return 1;
+}
+
+char getPromChar(void)
+{
+       while (!(serial_in(UART_LSR) & 1))
+               ;
+
+       return serial_in(UART_RX);
+}
+
+void prom_printf(char *fmt, ...)
+{
+       va_list args;
+       int l;
+       char *p, *buf_end;
+       char buf[1024];
+
+       va_start(args, fmt);
+       l = vsprintf(buf, fmt, args); /* hopefully i < sizeof(buf) */
+       va_end(args);
+
+       buf_end = buf + l;
+
+       for (p = buf; p < buf_end; p++) {
+               /* Crude cr/nl handling is better than none */
+               if (*p == '\n')
+                       putPromChar('\r');
+               putPromChar(*p);
+       }
+}
diff --git a/arch/mips/mips-boards/sim/sim_setup.c b/arch/mips/mips-boards/sim/sim_setup.c
new file mode 100644 (file)
index 0000000..485d5a5
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/prom.h>
+#include <asm/serial.h>
+#include <asm/io.h>
+#include <asm/time.h>
+#include <asm/mips-boards/sim.h>
+#include <asm/mips-boards/simint.h>
+
+
+extern void sim_time_init(void);
+extern void sim_timer_setup(struct irqaction *irq);
+static void __init serial_init(void);
+unsigned int _isbonito = 0;
+
+extern void __init sanitize_tlb_entries(void);
+
+
+const char *get_system_type(void)
+{
+       return "MIPSsim";
+}
+
+void __init plat_setup(void)
+{
+       set_io_port_base(0xbfd00000);
+
+       serial_init();
+
+       board_time_init = sim_time_init;
+       board_timer_setup = sim_timer_setup;
+       prom_printf("Linux started...\n");
+
+#ifdef CONFIG_MT_SMP
+       sanitize_tlb_entries();
+#endif
+}
+
+void prom_init(void)
+{
+       set_io_port_base(0xbfd00000);
+
+       prom_printf("\nLINUX started...\n");
+       prom_init_cmdline();
+       prom_meminit();
+}
+
+
+static void __init serial_init(void)
+{
+#ifdef CONFIG_SERIAL_8250
+       struct uart_port s;
+
+       memset(&s, 0, sizeof(s));
+
+       s.iobase = 0x3f8;
+
+       /* hardware int 4 - the serial int, is CPU int 6
+        but poll for now */
+       s.irq =  0;
+       s.uartclk = BASE_BAUD * 16;
+       s.flags = ASYNC_BOOT_AUTOCONF | UPF_SKIP_TEST;
+       s.iotype = SERIAL_IO_PORT | ASYNC_SKIP_TEST;
+       s.regshift = 0;
+       s.timeout = 4;
+
+       if (early_serial_setup(&s) != 0) {
+               prom_printf(KERN_ERR "Serial setup failed!\n");
+       }
+
+#endif
+}
diff --git a/arch/mips/mips-boards/sim/sim_smp.c b/arch/mips/mips-boards/sim/sim_smp.c
new file mode 100644 (file)
index 0000000..1982435
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ */
+/*
+ * Simulator Platform-specific hooks for SMP operation
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/interrupt.h>
+#include <asm/atomic.h>
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/hardirq.h>
+#include <asm/mmu_context.h>
+#include <asm/smp.h>
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/smtc_ipi.h>
+#endif /* CONFIG_MIPS_MT_SMTC */
+
+/* VPE/SMP Prototype implements platform interfaces directly */
+#if !defined(CONFIG_MIPS_MT_SMP)
+
+/*
+ * Cause the specified action to be performed on a targeted "CPU"
+ */
+
+void core_send_ipi(int cpu, unsigned int action)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+       void smtc_send_ipi(int, int, unsigned int);
+
+       smtc_send_ipi(cpu, LINUX_SMP_IPI, action);
+#endif /* CONFIG_MIPS_MT_SMTC */
+/* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */
+
+}
+
+/*
+ * Detect available CPUs/VPEs/TCs and populate phys_cpu_present_map
+ */
+
+void __init prom_build_cpu_map(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+       extern int mipsmt_build_cpu_map(int startslot);
+       int nextslot;
+
+       cpus_clear(phys_cpu_present_map);
+
+       /* Register the boot CPU */
+
+       smp_prepare_boot_cpu();
+
+       /*
+        * As of November, 2004, MIPSsim only simulates one core
+        * at a time.  However, that core may be a MIPS MT core
+        * with multiple virtual processors and thread contexts.
+        */
+
+       if (read_c0_config3() & (1<<2)) {
+               nextslot = mipsmt_build_cpu_map(1);
+       }
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Platform "CPU" startup hook
+ */
+
+void prom_boot_secondary(int cpu, struct task_struct *idle)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+       extern void smtc_boot_secondary(int cpu, struct task_struct *t);
+
+       smtc_boot_secondary(cpu, idle);
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Post-config but pre-boot cleanup entry point
+ */
+
+void prom_init_secondary(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+       void smtc_init_secondary(void);
+
+       smtc_init_secondary();
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Platform SMP pre-initialization
+ */
+
+void prom_prepare_cpus(unsigned int max_cpus)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+       void mipsmt_prepare_cpus(int c);
+       /*
+        * As noted above, we can assume a single CPU for now
+        * but it may be multithreaded.
+        */
+
+       if (read_c0_config3() & (1<<2)) {
+               mipsmt_prepare_cpus(max_cpus);
+       }
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * SMP initialization finalization entry point
+ */
+
+void prom_smp_finish(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+       void smtc_smp_finish(void);
+
+       smtc_smp_finish();
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Hook for after all CPUs are online
+ */
+
+void prom_cpus_done(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+#endif /* CONFIG_MIPS32R2_MT_SMP */
diff --git a/arch/mips/mips-boards/sim/sim_time.c b/arch/mips/mips-boards/sim/sim_time.c
new file mode 100644 (file)
index 0000000..18b968c
--- /dev/null
@@ -0,0 +1,215 @@
+#include <linux/types.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+
+#include <asm/mipsregs.h>
+#include <asm/ptrace.h>
+#include <asm/hardirq.h>
+#include <asm/div64.h>
+#include <asm/cpu.h>
+#include <asm/time.h>
+
+#include <linux/interrupt.h>
+#include <linux/mc146818rtc.h>
+#include <linux/timex.h>
+#include <asm/mipsregs.h>
+#include <asm/ptrace.h>
+#include <asm/hardirq.h>
+#include <asm/irq.h>
+#include <asm/div64.h>
+#include <asm/cpu.h>
+#include <asm/time.h>
+#include <asm/mc146818-time.h>
+#include <asm/msc01_ic.h>
+
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/prom.h>
+#include <asm/mips-boards/simint.h>
+#include <asm/mc146818-time.h>
+#include <asm/smp.h>
+
+
+unsigned long cpu_khz;
+
+extern asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs);
+
+irqreturn_t sim_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+#ifdef CONFIG_SMP
+       int cpu = smp_processor_id();
+
+       /*
+        * CPU 0 handles the global timer interrupt job
+        * resets count/compare registers to trigger next timer int.
+        */
+#ifndef CONFIG_MIPS_MT_SMTC
+       if (cpu == 0) {
+               timer_interrupt(irq, dev_id, regs);
+       }
+       else {
+               /* Everyone else needs to reset the timer int here as
+                  ll_local_timer_interrupt doesn't */
+               /*
+                * FIXME: need to cope with counter underflow.
+                * More support needs to be added to kernel/time for
+                * counter/timer interrupts on multiple CPU's
+                */
+               write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
+       }
+#else /* SMTC */
+       /*
+        *  In SMTC system, one Count/Compare set exists per VPE.
+        *  Which TC within a VPE gets the interrupt is essentially
+        *  random - we only know that it shouldn't be one with
+        *  IXMT set. Whichever TC gets the interrupt needs to
+        *  send special interprocessor interrupts to the other
+        *  TCs to make sure that they schedule, etc.
+        *
+        *  That code is specific to the SMTC kernel, not to
+        *  the simulation platform, so it's invoked from
+        *  the general MIPS timer_interrupt routine.
+        *
+        * We have a problem in that the interrupt vector code
+        * had to turn off the timer IM bit to avoid redundant
+        * entries, but we may never get to mips_cpu_irq_end
+        * to turn it back on again if the scheduler gets
+        * involved.  So we clear the pending timer here,
+        * and re-enable the mask...
+        */
+
+       int vpflags = dvpe();
+       write_c0_compare (read_c0_count() - 1);
+       clear_c0_cause(0x100 << MIPSCPU_INT_CPUCTR);
+       set_c0_status(0x100 << MIPSCPU_INT_CPUCTR);
+       irq_enable_hazard();
+       evpe(vpflags);
+
+       if(cpu_data[cpu].vpe_id == 0) timer_interrupt(irq, dev_id, regs);
+       else write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
+       smtc_timer_broadcast(cpu_data[cpu].vpe_id);
+
+#endif /* CONFIG_MIPS_MT_SMTC */
+
+       /*
+        * every CPU should do profiling and process accounting
+        */
+       local_timer_interrupt (irq, dev_id, regs);
+       return IRQ_HANDLED;
+#else
+       return timer_interrupt (irq, dev_id, regs);
+#endif
+}
+
+
+
+/*
+ * Estimate CPU frequency.  Sets mips_counter_frequency as a side-effect
+ */
+static unsigned int __init estimate_cpu_frequency(void)
+{
+       unsigned int prid = read_c0_prid() & 0xffff00;
+       unsigned int count;
+
+#if 1
+       /*
+        * hardwire the board frequency to 12MHz.
+        */
+
+       if ((prid == (PRID_COMP_MIPS | PRID_IMP_20KC)) ||
+           (prid == (PRID_COMP_MIPS | PRID_IMP_25KF)))
+               count = 12000000;
+       else
+               count =  6000000;
+#else
+       unsigned int flags;
+
+       local_irq_save(flags);
+
+       /* Start counter exactly on falling edge of update flag */
+       while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+       while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
+
+       /* Start r4k counter. */
+       write_c0_count(0);
+
+       /* Read counter exactly on falling edge of update flag */
+       while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+       while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
+
+       count = read_c0_count();
+
+       /* restore interrupts */
+       local_irq_restore(flags);
+#endif
+
+       mips_hpt_frequency = count;
+
+       if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) &&
+           (prid != (PRID_COMP_MIPS | PRID_IMP_25KF)))
+               count *= 2;
+
+       count += 5000;    /* round */
+       count -= count%10000;
+
+       return count;
+}
+
+void __init sim_time_init(void)
+{
+       unsigned int est_freq, flags;
+
+       local_irq_save(flags);
+
+
+        /* Set Data mode - binary. */
+       CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL);
+
+
+       est_freq = estimate_cpu_frequency ();
+
+       printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
+              (est_freq%1000000)*100/1000000);
+
+        cpu_khz = est_freq / 1000;
+
+       local_irq_restore(flags);
+}
+
+static int mips_cpu_timer_irq;
+
+static void mips_timer_dispatch (struct pt_regs *regs)
+{
+       do_IRQ (mips_cpu_timer_irq, regs);
+}
+
+
+void __init sim_timer_setup(struct irqaction *irq)
+{
+       if (cpu_has_veic) {
+               set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch);
+               mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR;
+       }
+       else {
+               if (cpu_has_vint)
+                       set_vi_handler(MIPSCPU_INT_CPUCTR, mips_timer_dispatch);
+               mips_cpu_timer_irq = MIPSCPU_INT_BASE + MIPSCPU_INT_CPUCTR;
+       }
+
+       /* we are using the cpu counter for timer interrupts */
+       irq->handler = sim_timer_interrupt;
+       setup_irq(mips_cpu_timer_irq, irq);
+
+#ifdef CONFIG_SMP
+       /* irq_desc(riptor) is a global resource, when the interrupt overlaps
+          on seperate cpu's the first one tries to handle the second interrupt.
+          The effect is that the int remains disabled on the second cpu.
+          Mark the interrupt with IRQ_PER_CPU to avoid any confusion */
+       irq_desc[mips_cpu_timer_irq].status |= IRQ_PER_CPU;
+#endif
+
+       /* to generate the first timer interrupt */
+       write_c0_compare(read_c0_count() + (mips_hpt_frequency/HZ));
+}
diff --git a/include/asm-mips/mach-sim/cpu-feature-overrides.h b/include/asm-mips/mach-sim/cpu-feature-overrides.h
new file mode 100644 (file)
index 0000000..0945721
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003, 2004 Chris Dearman
+ */
+#ifndef __ASM_MACH_SIM_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_SIM_CPU_FEATURE_OVERRIDES_H
+
+#include <linux/config.h>
+
+/*
+ * CPU feature overrides for MIPS boards
+ */
+#ifdef CONFIG_CPU_MIPS32
+#define cpu_has_tlb            1
+#define cpu_has_4kex           1
+#define cpu_has_4ktlb          1
+#define cpu_has_fpu            0
+/* #define cpu_has_32fpr       ? */
+#define cpu_has_counter                1
+/* #define cpu_has_watch       ? */
+#define cpu_has_divec          1
+#define cpu_has_vce            0
+/* #define cpu_has_cache_cdex_p        ? */
+/* #define cpu_has_cache_cdex_s        ? */
+/* #define cpu_has_prefetch    ? */
+#define cpu_has_mcheck         1
+/* #define cpu_has_ejtag       ? */
+#define cpu_has_llsc           1
+/* #define cpu_has_vtag_icache ? */
+/* #define cpu_has_dc_aliases  ? */
+/* #define cpu_has_ic_fills_f_dc ? */
+#define cpu_has_nofpuex                0
+/* #define cpu_has_64bits      ? */
+/* #define cpu_has_64bit_zero_reg ? */
+/* #define cpu_has_subset_pcaches ? */
+#endif
+
+#ifdef CONFIG_CPU_MIPS64
+#define cpu_has_tlb            1
+#define cpu_has_4kex           1
+#define cpu_has_4ktlb          1
+/* #define cpu_has_fpu         ? */
+/* #define cpu_has_32fpr       ? */
+#define cpu_has_counter                1
+/* #define cpu_has_watch       ? */
+#define cpu_has_divec          1
+#define cpu_has_vce            0
+/* #define cpu_has_cache_cdex_p        ? */
+/* #define cpu_has_cache_cdex_s        ? */
+/* #define cpu_has_prefetch    ? */
+#define cpu_has_mcheck         1
+/* #define cpu_has_ejtag       ? */
+#define cpu_has_llsc           1
+/* #define cpu_has_vtag_icache ? */
+/* #define cpu_has_dc_aliases  ? */
+/* #define cpu_has_ic_fills_f_dc ? */
+#define cpu_has_nofpuex                0
+/* #define cpu_has_64bits      ? */
+/* #define cpu_has_64bit_zero_reg ? */
+/* #define cpu_has_subset_pcaches ? */
+#endif
+
+#endif /* __ASM_MACH_MIPS_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mips-boards/sim.h b/include/asm-mips/mips-boards/sim.h
new file mode 100644 (file)
index 0000000..acb7c23
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ */
+
+#ifndef _ASM_MIPS_BOARDS_SIM_H
+#define _ASM_MIPS_BOARDS_SIM_H
+
+#define STATS_ON        1
+#define STATS_OFF       2
+#define STATS_CLEAR     3
+#define STATS_DUMP      4
+#define TRACE_ON               5
+#define TRACE_OFF       6
+
+
+#define simcfg(code)                                           \
+({                                        \
+       __asm__  __volatile__( \
+        "sltiu $0,$0, %0" \
+               ::"i"(code)                                     \
+               ); \
+})
+
+
+
+#endif
diff --git a/include/asm-mips/mips-boards/simint.h b/include/asm-mips/mips-boards/simint.h
new file mode 100644 (file)
index 0000000..4952e0b
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+#ifndef _MIPS_SIMINT_H
+#define _MIPS_SIMINT_H
+
+
+#define SIM_INT_BASE           0
+#define MIPSCPU_INT_MB0                2
+#define MIPSCPU_INT_BASE       16
+#define MIPS_CPU_TIMER_IRQ     7
+
+
+#define MIPSCPU_INT_CPUCTR     7
+
+#define MSC01E_INT_BASE                64
+
+#define MIPSCPU_INT_CPUCTR     7
+#define MSC01E_INT_CPUCTR      11
+
+#endif