diff options
-rw-r--r-- | arch/mips64/kernel/head.S | 219 |
1 files changed, 92 insertions, 127 deletions
diff --git a/arch/mips64/kernel/head.S b/arch/mips64/kernel/head.S index bf74a983e..6703ad6bc 100644 --- a/arch/mips64/kernel/head.S +++ b/arch/mips64/kernel/head.S @@ -1,131 +1,96 @@ +/* $Id: head.S,v 1.6 2000/03/27 21:05:04 ulfc Exp $ + * + * 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. + * + * Head.S contains the MIPS exception handler and startup code. + * + * Copyright (C) 1994, 1995 Waldorf Electronics + * Written by Ralf Baechle and Andreas Busse + * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999 Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + */ +#define __ASSEMBLY__ #include <linux/config.h> #include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/threads.h> -#include <linux/time.h> -#include <linux/timex.h> -#include <linux/sched.h> - -#include <asm/atomic.h> +#include <asm/asm.h> +#include <asm/regdef.h> #include <asm/processor.h> -#include <asm/system.h> -#include <asm/hardirq.h> - -#ifdef CONFIG_SGI_IP27 - -#include <asm/sn/arch.h> -#include <asm/sn/intr.h> -#include <asm/sn/addrs.h> -#include <asm/sn/agent.h> - -#define DOACTION 0xab - -static void sendintr(int destid, unsigned char status) -{ - int level; - -#if (CPUS_PER_NODE == 2) - /* - * CPU slice A gets level CPU_ACTION_A - * CPU slice B gets level CPU_ACTION_B - */ - if (status == DOACTION) - level = CPU_ACTION_A + cputoslice(destid); - else /* DOTLBACTION */ - level = N_INTPEND_BITS + TLB_INTR_A + cputoslice(destid); - - /* - * Convert the compact hub number to the NASID to get the correct - * part of the address space. Then set the interrupt bit associated - * with the CPU we want to send the interrupt to. - */ - REMOTE_HUB_SEND_INTR(COMPACT_TO_NASID_NODEID(cputocnode(destid)), level); -#else - << Bomb! Must redefine this for more than 2 CPUS. >> +#include <asm/mipsregs.h> +#include <asm/stackframe.h> + + .text + +EXPORT(stext) # used for profiling +EXPORT(_stext) + + __INIT + +NESTED(kernel_entry, 16, sp) # kernel entry point + +#ifdef CONFIG_ARC64 + /* We get launched at a XKPHYS address but the kernel is linked to + run at a KSEG0 address, so jump there. */ + la t0, 1f + jr t0 +1: #endif -} - -#endif /* CONFIG_SGI_IP27 */ - -/* The 'big kernel lock' */ -spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED; -int smp_threads_ready = 0; /* Not used */ -static atomic_t smp_commenced = ATOMIC_INIT(0); -struct cpuinfo_mips cpu_data[NR_CPUS]; -int smp_num_cpus; /* Number that came online. */ -int __cpu_number_map[NR_CPUS]; -int __cpu_logical_map[NR_CPUS]; -cycles_t cacheflush_time; - -static void smp_tune_scheduling (void) -{ -} - -void __init smp_boot_cpus(void) -{ - global_irq_holder = 0; - current->processor = 0; - init_idle(); - smp_tune_scheduling(); - smp_num_cpus = 1; /* for now */ - allowboot(); -} - -void __init smp_commence(void) -{ - wmb(); - atomic_set(&smp_commenced,1); -} - -static void stop_this_cpu(void *dummy) -{ - /* - * Remove this CPU - */ - for (;;); -} - -void smp_send_stop(void) -{ - smp_call_function(stop_this_cpu, NULL, 1, 0); - smp_num_cpus = 1; -} - -/* - * this function sends a 'reschedule' IPI to another CPU. - * it goes straight through and wastes no time serializing - * anything. Worst case is that we lose a reschedule ... - */ -void smp_send_reschedule(int cpu) -{ - panic("smp_send_reschedule\n"); -} - -/* Not really SMP stuff ... */ -int setup_profiling_timer(unsigned int multiplier) -{ -} - -/* - * Run a function on all other CPUs. - * <func> The function to run. This must be fast and non-blocking. - * <info> An arbitrary pointer to pass to the function. - * <retry> If true, keep retrying until ready. - * <wait> If true, wait until function has completed on other CPUs. - * [RETURNS] 0 on success, else a negative status code. - * - * Does not return until remote CPUs are nearly ready to execute <func> - * or are or have executed. - */ -int -smp_call_function (void (*func) (void *info), void *info, int retry, int wait) -{ - /* XXX - kinda important ;-) */ - panic("smp_call_function\n"); -} - -void flush_tlb_others (unsigned long cpumask, struct mm_struct *mm, - unsigned long va) -{ - panic("flush_tlb_others\n"); -} + + ori sp, 0xf # align stack on 16 byte. + xori sp, 0xf + + /* Note that all firmware passed argument registers still + have their values. */ + jal prom_init # initialize firmware + + CLI # disable interrupts + + mfc0 t0, CP0_STATUS + li t1, ~(ST0_CU1|ST0_CU2|ST0_CU3) + and t0, t1 + or t0, (ST0_CU0|ST0_KX|ST0_SX|ST0_FR) + mtc0 t0, CP0_STATUS + + la $28, init_task_union # init current pointer + daddiu t0, $28, KERNEL_STACK_SIZE-32 + sd t0, kernelsp + dsubu sp, t0, 4*SZREG # init stack pointer + + jal start_kernel +1: b 1b # just in case ... + END(kernel_entry) + +NESTED(bootstrap, 16, sp) +#ifdef CONFIG_ARC64 + /* We get launched at a XKPHYS address but the kernel is linked to + run at a KSEG0 address, so jump there. */ + la t0, 1f + jr t0 +1: +#endif + jal cboot + END(bootstrap) + + __FINIT + + .comm kernelsp, 8, 8 # current stackpointer + .comm current_pgd, 8, 8 # current page tables + +#define PAGE_SIZE 0x1000 + + .macro page name, order=0 + .globl \name + .org . + (PAGE_SIZE << \order) +\name: .size \name, (PAGE_SIZE << \order) + .type \name, @object + .endm + + .align 12 + .data + + page swapper_pg_dir, 1 + page invalid_pte_table, 1 + page invalid_pmd_table, 1 + page empty_bad_page_table, 1 + page empty_bad_page |