Initial Spring 2016 commit.
This commit is contained in:
79
kern/arch/mips/conf/conf.arch
Normal file
79
kern/arch/mips/conf/conf.arch
Normal file
@@ -0,0 +1,79 @@
|
||||
|
||||
#
|
||||
# The machine dependent sources for MIPS.
|
||||
#
|
||||
|
||||
# Standard C functions
|
||||
machine mips file ../common/libc/arch/mips/setjmp.S
|
||||
|
||||
# 64-bit integer ops support for gcc
|
||||
machine mips file ../common/gcc-millicode/adddi3.c
|
||||
machine mips file ../common/gcc-millicode/anddi3.c
|
||||
machine mips file ../common/gcc-millicode/ashldi3.c
|
||||
machine mips file ../common/gcc-millicode/ashrdi3.c
|
||||
machine mips file ../common/gcc-millicode/cmpdi2.c
|
||||
machine mips file ../common/gcc-millicode/divdi3.c
|
||||
machine mips file ../common/gcc-millicode/iordi3.c
|
||||
machine mips file ../common/gcc-millicode/lshldi3.c
|
||||
machine mips file ../common/gcc-millicode/lshrdi3.c
|
||||
machine mips file ../common/gcc-millicode/moddi3.c
|
||||
machine mips file ../common/gcc-millicode/muldi3.c
|
||||
machine mips file ../common/gcc-millicode/negdi2.c
|
||||
machine mips file ../common/gcc-millicode/notdi2.c
|
||||
machine mips file ../common/gcc-millicode/qdivrem.c
|
||||
machine mips file ../common/gcc-millicode/subdi3.c
|
||||
machine mips file ../common/gcc-millicode/ucmpdi2.c
|
||||
machine mips file ../common/gcc-millicode/udivdi3.c
|
||||
machine mips file ../common/gcc-millicode/umoddi3.c
|
||||
machine mips file ../common/gcc-millicode/xordi3.c
|
||||
|
||||
#
|
||||
# Low-level stuff ("locore")
|
||||
# The platform should select cache handling and exception handling from
|
||||
# among these:
|
||||
#
|
||||
# cache-mips1.S
|
||||
# cache-mips161.S
|
||||
# cache-mips32.S
|
||||
#
|
||||
# exception-mips1.S
|
||||
# exception-mips32.S
|
||||
#
|
||||
|
||||
machine mips file arch/mips/locore/trap.c # Common trap handler.
|
||||
|
||||
#
|
||||
# Thread subsystem
|
||||
#
|
||||
|
||||
machine mips file arch/mips/thread/cpu.c # CPU control.
|
||||
machine mips file arch/mips/thread/switch.S # Thread context switch
|
||||
machine mips file arch/mips/thread/switchframe.c # New thread prep
|
||||
machine mips file arch/mips/thread/thread_machdep.c # MD thread code
|
||||
machine mips file arch/mips/thread/threadstart.S # New thread startup
|
||||
|
||||
#
|
||||
# VM system
|
||||
# The platform should select TLB handling from among these:
|
||||
#
|
||||
# tlb-mips1.S
|
||||
# tlb-mips161.S
|
||||
# tlb-mips32.S
|
||||
#
|
||||
|
||||
machine mips file arch/mips/vm/ram.c # Physical memory accounting
|
||||
|
||||
# This is included here rather than in conf.kern because
|
||||
# it may not be suitable for all architectures.
|
||||
machine mips file vm/copyinout.c # copyin/out et al.
|
||||
|
||||
# For the early assignments, we supply a very stupid MIPS-only skeleton
|
||||
# of a VM system. It is just barely capable of running a single userlevel
|
||||
# program as long as that program's not very large.
|
||||
defoption dumbvm
|
||||
machine mips optfile dumbvm arch/mips/vm/dumbvm.c
|
||||
|
||||
#
|
||||
# System call layer
|
||||
#
|
||||
machine mips file arch/mips/syscall/syscall.c # System call handler
|
98
kern/arch/mips/conf/ldscript
Normal file
98
kern/arch/mips/conf/ldscript
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* This is a pile of crap that tells the linker how to link the kernel,
|
||||
* because it's too stupid to be able to work it out on its own.
|
||||
*/
|
||||
ENTRY(__start)
|
||||
|
||||
_DYNAMIC_LINK = 0;
|
||||
SECTIONS
|
||||
{
|
||||
/*
|
||||
* Base address for the kernel.
|
||||
*/
|
||||
. = 0x80000200;
|
||||
|
||||
/*
|
||||
* Read-only loaded sections.
|
||||
*/
|
||||
|
||||
/* code */
|
||||
.text : { *(.text) }
|
||||
|
||||
/* linker-provided symbol for end of code */
|
||||
_etext = .;
|
||||
|
||||
/* read-only data */
|
||||
.rodata : { *(.rodata) *(.rodata.*) }
|
||||
|
||||
/* MIPS register-usage blather */
|
||||
.reginfo : { *(.reginfo) }
|
||||
|
||||
/*
|
||||
* Move to a fresh page. This method puts read-only and
|
||||
* read-write material on separate pages without having to
|
||||
* waste space on page-alignment in the on-disk file; the
|
||||
* on-disk page that contains both text and data is mapped
|
||||
* twice.
|
||||
*
|
||||
* For mips kernels we can't write-protect the text anyhow so
|
||||
* there's no point doing it.
|
||||
*/
|
||||
/* . = . + 0x1000; */
|
||||
|
||||
/*
|
||||
* Read-write loaded sections.
|
||||
*/
|
||||
|
||||
/* initialized data */
|
||||
.data : {
|
||||
*(.data)
|
||||
CONSTRUCTORS
|
||||
}
|
||||
|
||||
/* Value for GP register */
|
||||
_gp = ALIGN(16) + 0x7ff0;
|
||||
|
||||
/* Small data accessed via GP register */
|
||||
.lit8 : { *(.lit8) }
|
||||
.lit4 : { *(.lit4) }
|
||||
.sdata : { *(.sdata) }
|
||||
|
||||
/* cleared-to-zero data */
|
||||
.sbss : { *(.sbss *.scommon) }
|
||||
.bss : { *(.bss) *(COMMON) }
|
||||
|
||||
/* linker-provided symbol for end of program */
|
||||
_end = .;
|
||||
|
||||
/*
|
||||
* Debug info
|
||||
*/
|
||||
|
||||
/* stabs debug sections */
|
||||
.stab 0: { *(.stab) }
|
||||
.stabstr 0: { *(.stabstr) }
|
||||
|
||||
/* DWARF debug sections */
|
||||
.debug 0: { *(.debug) }
|
||||
.line 0: { *(.line) }
|
||||
.debug_srcinfo 0: { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0: { *(.debug_sfnames) }
|
||||
.debug_aranges 0: { *(.debug_aranges) }
|
||||
.debug_pubnames 0: { *(.debug_pubnames) }
|
||||
.debug_info 0: { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0: { *(.debug_abbrev) }
|
||||
.debug_line 0: { *(.debug_line) }
|
||||
.debug_frame 0: { *(.debug_frame) }
|
||||
.debug_str 0: { *(.debug_str) }
|
||||
.debug_loc 0: { *(.debug_loc) }
|
||||
.debug_macinfo 0: { *(.debug_macinfo) }
|
||||
.debug_weaknames 0: { *(.debug_weaknames) }
|
||||
.debug_funcnames 0: { *(.debug_funcnames) }
|
||||
.debug_typenames 0: { *(.debug_typenames) }
|
||||
.debug_varnames 0: { *(.debug_varnames) }
|
||||
|
||||
/* These must appear regardless of . */
|
||||
.gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
|
||||
.gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
|
||||
}
|
73
kern/arch/mips/include/current.h
Normal file
73
kern/arch/mips/include/current.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _MIPS_CURRENT_H_
|
||||
#define _MIPS_CURRENT_H_
|
||||
|
||||
|
||||
/*
|
||||
* Macro for current thread, or current cpu.
|
||||
*
|
||||
* This file should only be included via <current.h> (q.v.)
|
||||
*
|
||||
* On mips we track the current thread. There's an architectural
|
||||
* issue that informs this choice: there's no easy way to find the
|
||||
* current cpu, the current thread, or even the kernel stack of the
|
||||
* current thread when entering the kernel at trap time. (On most CPUs
|
||||
* there's a canonical way to find at least the stack.)
|
||||
*
|
||||
* Therefore we do the following:
|
||||
*
|
||||
* - We misuse a kernel-settable field of a nonessential MMU register
|
||||
* to hold the CPU number.
|
||||
*
|
||||
* - On trap entry we use this number to index an array that gets us
|
||||
* both the kernel stack and curthread.
|
||||
*
|
||||
* - We tell the compiler not to use the s7 register and keep
|
||||
* curthread there.
|
||||
*
|
||||
* Note that if you want to change this scheme to use a different
|
||||
* register, or change to a different scheme, you need to touch three
|
||||
* places: here, the mips-specific kernel CFLAGS in the makefiles, and
|
||||
* the trap entry and return code.
|
||||
*/
|
||||
|
||||
#ifdef __GNUC__
|
||||
register struct thread *curthread __asm("$23"); /* s7 register */
|
||||
#else
|
||||
#error "Don't know how to declare curthread in this compiler"
|
||||
#endif
|
||||
#undef __NEED_CURTHREAD
|
||||
#define __NEED_CURCPU
|
||||
|
||||
/* For how we've defined it, curthread gets set first, then curcpu. */
|
||||
#define INIT_CURCPU(cpu, thread) (curthread = (thread), curcpu = (cpu))
|
||||
|
||||
#endif /* _MIPS_CURRENT_H_ */
|
58
kern/arch/mips/include/elf.h
Normal file
58
kern/arch/mips/include/elf.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _MIPS_ELF_H_
|
||||
#define _MIPS_ELF_H_
|
||||
|
||||
/*
|
||||
* MIPS machine-dependent definitions for the ELF binary format.
|
||||
*/
|
||||
|
||||
|
||||
/* The ELF executable type. */
|
||||
#define EM_MACHINE EM_MIPS
|
||||
|
||||
/* Linker relocation codes. SIZE DESCRIPTION */
|
||||
#define R_MIPS_NONE 0 /* --- nop */
|
||||
#define R_MIPS_16 1 /* u16 value */
|
||||
#define R_MIPS_32 2 /* u32 value */
|
||||
#define R_MIPS_REL32 3 /* u32 value relative to patched address */
|
||||
#define R_MIPS_26 4 /* u26 j/jal instruction address field */
|
||||
#define R_MIPS_HI16 5 /* u16 %hi(sym) as below */
|
||||
#define R_MIPS_LO16 6 /* s16 %lo(sym) as below */
|
||||
#define R_MIPS_GPREL16 7 /* s16 offset from GP register */
|
||||
#define R_MIPS_LITERAL 8 /* s16 GPREL16 for file-local symbols (?) */
|
||||
#define R_MIPS_GOT16 9 /* u16 offset into global offset table */
|
||||
#define R_MIPS_PC16 10 /* s16 PC-relative reference */
|
||||
#define R_MIPS_CALL16 11 /* u16 call through global offset table */
|
||||
#define R_MIPS_GPREL32 12 /* s32 offset from GP register */
|
||||
/* %hi/%lo are defined so %hi(sym) << 16 + %lo(sym) = sym */
|
||||
|
||||
|
||||
#endif /* _MIPS_ELF_H_ */
|
44
kern/arch/mips/include/kern/endian.h
Normal file
44
kern/arch/mips/include/kern/endian.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _KERN_MIPS_ENDIAN_H_
|
||||
#define _KERN_MIPS_ENDIAN_H_
|
||||
|
||||
/*
|
||||
* Endianness. While the MIPS can be either big-endian (mipseb) or
|
||||
* little-endian (mipsel), at least for now we only do mipseb.
|
||||
*
|
||||
* This file should only be included via <kern/endian.h> which in turn
|
||||
* should be gotten via <endian.h> in the kernel or <arpa/inet.h> in
|
||||
* userland.
|
||||
*/
|
||||
|
||||
#define _BYTE_ORDER _BIG_ENDIAN
|
||||
|
||||
#endif /* _KERN_MIPS_ENDIAN_H_ */
|
74
kern/arch/mips/include/kern/regdefs.h
Normal file
74
kern/arch/mips/include/kern/regdefs.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Macros for general-purpose register numbers for MIPS.
|
||||
*
|
||||
* Exported to userlevel because it's ~standard for that architecture.
|
||||
*/
|
||||
|
||||
#ifndef _KERN_MIPS_REGDEFS_H_
|
||||
#define _KERN_MIPS_REGDEFS_H_
|
||||
|
||||
|
||||
#define z0 $0 /* always zero register */
|
||||
#define AT $1 /* assembler temp register */
|
||||
#define v0 $2 /* value 0 */
|
||||
#define v1 $3 /* value 1 */
|
||||
#define a0 $4 /* argument 0 */
|
||||
#define a1 $5 /* argument 1 */
|
||||
#define a2 $6 /* argument 2 */
|
||||
#define a3 $7 /* argument 3 */
|
||||
#define t0 $8 /* temporary (caller-save) 0 */
|
||||
#define t1 $9 /* temporary (caller-save) 1 */
|
||||
#define t2 $10 /* temporary (caller-save) 2 */
|
||||
#define t3 $11 /* temporary (caller-save) 3 */
|
||||
#define t4 $12 /* temporary (caller-save) 4 */
|
||||
#define t5 $13 /* temporary (caller-save) 5 */
|
||||
#define t6 $14 /* temporary (caller-save) 6 */
|
||||
#define t7 $15 /* temporary (caller-save) 7 */
|
||||
#define s0 $16 /* saved (callee-save) 0 */
|
||||
#define s1 $17 /* saved (callee-save) 1 */
|
||||
#define s2 $18 /* saved (callee-save) 2 */
|
||||
#define s3 $19 /* saved (callee-save) 3 */
|
||||
#define s4 $20 /* saved (callee-save) 4 */
|
||||
#define s5 $21 /* saved (callee-save) 5 */
|
||||
#define s6 $22 /* saved (callee-save) 6 */
|
||||
#define s7 $23 /* saved (callee-save) 7 */
|
||||
#define t8 $24 /* temporary (caller-save) 8 */
|
||||
#define t9 $25 /* temporary (caller-save) 9 */
|
||||
#define k0 $26 /* kernel temporary 0 */
|
||||
#define k1 $27 /* kernel temporary 1 */
|
||||
#define gp $28 /* global pointer */
|
||||
#define sp $29 /* stack pointer */
|
||||
#define s8 $30 /* saved (callee-save) 8 = frame pointer */
|
||||
#define ra $31 /* return address */
|
||||
|
||||
|
||||
#endif /* _KERN_MIPS_REGDEFS_H_ */
|
47
kern/arch/mips/include/kern/setjmp.h
Normal file
47
kern/arch/mips/include/kern/setjmp.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _MIPS_SETJMP_H_
|
||||
#define _MIPS_SETJMP_H_
|
||||
|
||||
/*
|
||||
* MIPS jmp_buf definition.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Must save: s0-s8, sp, ra (11 registers)
|
||||
* Don't change __JB_REGS without adjusting mips_setjmp.S accordingly.
|
||||
*/
|
||||
#define __JB_REGS 11
|
||||
|
||||
/* A jmp_buf is an array of __JB_REGS registers */
|
||||
typedef uint32_t jmp_buf[__JB_REGS];
|
||||
|
||||
|
||||
#endif /* _MIPS_SETJMP_H_ */
|
45
kern/arch/mips/include/kern/signal.h
Normal file
45
kern/arch/mips/include/kern/signal.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _KERN_MIPS_SIGNAL_H_
|
||||
#define _KERN_MIPS_SIGNAL_H_
|
||||
|
||||
/*
|
||||
* Structure used to hold the register values for returning from a
|
||||
* userland signal handler - basically the saved register values from
|
||||
* whatever userlevel execution context the signal interrupted. Fill
|
||||
* this in as needed, if you ever implement signal handlers. (Which you
|
||||
* probably won't.)
|
||||
*/
|
||||
struct sigcontext {
|
||||
/* Dummy. */
|
||||
};
|
||||
|
||||
#endif /* _KERN_MIPS_SIGNAL_H_ */
|
78
kern/arch/mips/include/kern/types.h
Normal file
78
kern/arch/mips/include/kern/types.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _KERN_MIPS_TYPES_H_
|
||||
#define _KERN_MIPS_TYPES_H_
|
||||
|
||||
/*
|
||||
* Machine-dependent types visible to userland.
|
||||
* (Kernel-only types should go in mips/types.h.)
|
||||
* 32-bit MIPS version.
|
||||
*
|
||||
* See kern/types.h for an explanation of the underscores.
|
||||
*/
|
||||
|
||||
|
||||
/* Sized integer types, with convenient short names */
|
||||
typedef char __i8; /* 8-bit signed integer */
|
||||
typedef short __i16; /* 16-bit signed integer */
|
||||
typedef int __i32; /* 32-bit signed integer */
|
||||
typedef long long __i64; /* 64-bit signed integer */
|
||||
|
||||
typedef unsigned char __u8; /* 8-bit unsigned integer */
|
||||
typedef unsigned short __u16; /* 16-bit unsigned integer */
|
||||
typedef unsigned int __u32; /* 32-bit unsigned integer */
|
||||
typedef unsigned long long __u64; /* 64-bit unsigned integer */
|
||||
|
||||
/* Further standard C types */
|
||||
typedef long __intptr_t; /* Signed pointer-sized integer */
|
||||
typedef unsigned long __uintptr_t; /* Unsigned pointer-sized integer */
|
||||
|
||||
/*
|
||||
* Since we're a 32-bit platform, size_t, ssize_t, and ptrdiff_t can
|
||||
* correctly be either (unsigned) int or (unsigned) long. However, if we
|
||||
* don't define it to the same one gcc is using, gcc will get
|
||||
* upset. If you switch compilers and see otherwise unexplicable type
|
||||
* errors involving size_t, try changing this.
|
||||
*/
|
||||
#if 1
|
||||
typedef unsigned __size_t; /* Size of a memory region */
|
||||
typedef int __ssize_t; /* Signed type of same size */
|
||||
typedef int __ptrdiff_t; /* Difference of two pointers */
|
||||
#else
|
||||
typedef unsigned long __size_t; /* Size of a memory region */
|
||||
typedef long __ssize_t; /* Signed type of same size */
|
||||
typedef long __ptrdiff_t; /* Difference of two pointers */
|
||||
#endif
|
||||
|
||||
/* Number of bits per byte. */
|
||||
#define __CHAR_BIT 8
|
||||
|
||||
|
||||
#endif /* _KERN_MIPS_TYPES_H_ */
|
63
kern/arch/mips/include/membar.h
Normal file
63
kern/arch/mips/include/membar.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2013
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _MIPS_MEMBAR_H_
|
||||
#define _MIPS_MEMBAR_H_
|
||||
|
||||
/*
|
||||
* On the mips there's only one memory barrier instruction, so these
|
||||
* are all the same. This is not true on many other CPUs (x86, arm,
|
||||
* sparc, powerpc, etc.) We also mark the instruction as a compiler-
|
||||
* level barrier by telling gcc that it destroys memory; this prevents
|
||||
* gcc from reordering loads and stores around it.
|
||||
*
|
||||
* See include/membar.h for further information.
|
||||
*/
|
||||
|
||||
MEMBAR_INLINE
|
||||
void
|
||||
membar_any_any(void)
|
||||
{
|
||||
__asm volatile(
|
||||
".set push;" /* save assembler mode */
|
||||
".set mips32;" /* allow MIPS32 instructions */
|
||||
"sync;" /* do it */
|
||||
".set pop" /* restore assembler mode */
|
||||
: /* no outputs */
|
||||
: /* no inputs */
|
||||
: "memory"); /* "changes" memory */
|
||||
}
|
||||
|
||||
MEMBAR_INLINE void membar_load_load(void) { membar_any_any(); }
|
||||
MEMBAR_INLINE void membar_store_store(void) { membar_any_any(); }
|
||||
MEMBAR_INLINE void membar_store_any(void) { membar_any_any(); }
|
||||
MEMBAR_INLINE void membar_any_store(void) { membar_any_any(); }
|
||||
|
||||
|
||||
#endif /* _MIPS_MEMBAR_H_ */
|
117
kern/arch/mips/include/specialreg.h
Normal file
117
kern/arch/mips/include/specialreg.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _MIPS_SPECIALREG_H_
|
||||
#define _MIPS_SPECIALREG_H_
|
||||
|
||||
|
||||
/*
|
||||
* Coprocessor 0 (system processor) register numbers
|
||||
*/
|
||||
#define c0_index $0 /* TLB entry index register */
|
||||
#define c0_random $1 /* TLB random slot register */
|
||||
#define c0_entrylo $2 /* TLB entry contents (low-order half) */
|
||||
/* c0_entrylo0 $2 */ /* MIPS-II and up only */
|
||||
/* c0_entrylo1 $3 */ /* MIPS-II and up only */
|
||||
#define c0_context $4 /* some precomputed pagetable stuff */
|
||||
/* c0_pagemask $5 */ /* MIPS-II and up only */
|
||||
/* c0_wired $6 */ /* MIPS-II and up only */
|
||||
#define c0_vaddr $8 /* virtual addr of failing memory access */
|
||||
#define c0_count $9 /* cycle counter (MIPS-II and up) */
|
||||
#define c0_entryhi $10 /* TLB entry contents (high-order half) */
|
||||
#define c0_compare $11 /* on-chip timer control (MIPS-II and up) */
|
||||
#define c0_status $12 /* processor status register */
|
||||
#define c0_cause $13 /* exception cause register */
|
||||
#define c0_epc $14 /* exception PC register */
|
||||
#define c0_prid $15 /* processor ID register */
|
||||
/* c0_config $16 */ /* MIPS-II and up only */
|
||||
/* c0_lladdr $17 */ /* MIPS-II and up only */
|
||||
/* c0_watchlo $18 */ /* MIPS-II and up only */
|
||||
/* c0_watchhi $19 */ /* MIPS-II and up only */
|
||||
|
||||
/*
|
||||
* Mode bits in c0_status
|
||||
*/
|
||||
#define CST_IEc 0x00000001 /* current: interrupt enable */
|
||||
#define CST_KUc 0x00000002 /* current: user mode */
|
||||
#define CST_IEp 0x00000004 /* previous: interrupt enable */
|
||||
#define CST_KUp 0x00000008 /* previous: user mode */
|
||||
#define CST_IEo 0x00000010 /* old: interrupt enable */
|
||||
#define CST_KUo 0x00000020 /* old: user mode */
|
||||
#define CST_MODEMASK 0x0000003f /* mask for the above */
|
||||
#define CST_IRQMASK 0x0000ff00 /* mask for the individual irq enable bits */
|
||||
#define CST_BEV 0x00400000 /* bootstrap exception vectors flag */
|
||||
|
||||
/*
|
||||
* Fields of the c0_cause register
|
||||
*/
|
||||
#define CCA_UTLB 0x00000001 /* true if UTLB exception (set by our asm) */
|
||||
#define CCA_CODE 0x0000003c /* EX_foo in trapframe.h */
|
||||
#define CCA_IRQS 0x0000ff00 /* Currently pending interrupts */
|
||||
#define CCA_COPN 0x30000000 /* Coprocessor number for EX_CPU */
|
||||
#define CCA_JD 0x80000000 /* True if exception happened in jump delay */
|
||||
|
||||
#define CCA_CODESHIFT 2 /* shift for CCA_CODE field */
|
||||
|
||||
/*
|
||||
* Fields of the c0_index register
|
||||
*/
|
||||
#define CIN_P 0x80000000 /* nonzero -> TLB probe found nothing */
|
||||
#define CIN_INDEX 0x00003f00 /* 6-bit index into TLB */
|
||||
|
||||
#define CIN_INDEXSHIFT 8 /* shift for CIN_INDEX field */
|
||||
|
||||
/*
|
||||
* Fields of the c0_context register
|
||||
*
|
||||
* The intent of c0_context is that you can manage virtually-mapped
|
||||
* page tables in kseg2; then you load the base address of the current
|
||||
* page table into c0_context. On a TLB miss the failing address is
|
||||
* masked and shifted and appears in the VSHIFT field, and c0_context
|
||||
* thereby contains the address of the page table entry you need to
|
||||
* load into the TLB. This can be used to make TLB refill very fast.
|
||||
*
|
||||
* However, in OS/161 we use CTX_PTBASE to hold the current CPU
|
||||
* number. This (or something like it) is fairly important to have and
|
||||
* there's no other good place in the chip to put it. See discussions
|
||||
* elsewhere.
|
||||
*/
|
||||
#define CTX_VSHIFT 0x001ffffc /* shifted/masked copy of c0_vaddr */
|
||||
#define CTX_PTBASE 0xffe00000 /* page table base address */
|
||||
|
||||
#define CTX_PTBASESHIFT 21 /* shift for CTX_PBASE field */
|
||||
|
||||
/*
|
||||
* Hardwired exception handler addresses.
|
||||
*/
|
||||
#define EXADDR_UTLB 0x80000000
|
||||
#define EXADDR_GENERAL 0x80000080
|
||||
|
||||
|
||||
#endif /* _MIPS_SPECIALREG_H_ */
|
122
kern/arch/mips/include/spinlock.h
Normal file
122
kern/arch/mips/include/spinlock.h
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _MIPS_SPINLOCK_H_
|
||||
#define _MIPS_SPINLOCK_H_
|
||||
|
||||
#include <cdefs.h>
|
||||
|
||||
|
||||
/* Type of value needed to actually spin on */
|
||||
typedef unsigned spinlock_data_t;
|
||||
|
||||
/* Initializer for use by SPINLOCK_INITIALIZER */
|
||||
#define SPINLOCK_DATA_INITIALIZER 0
|
||||
|
||||
/* Atomic operations on spinlock_data_t */
|
||||
SPINLOCK_INLINE
|
||||
void spinlock_data_set(volatile spinlock_data_t *sd, unsigned val);
|
||||
SPINLOCK_INLINE
|
||||
spinlock_data_t spinlock_data_get(volatile spinlock_data_t *sd);
|
||||
SPINLOCK_INLINE
|
||||
spinlock_data_t spinlock_data_testandset(volatile spinlock_data_t *sd);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* Assign a spinlock_data_t. On mips assigment of a plain 32-bit value
|
||||
* is one instruction, and instructions are atomic with respect to
|
||||
* memory.
|
||||
*/
|
||||
SPINLOCK_INLINE
|
||||
void
|
||||
spinlock_data_set(volatile spinlock_data_t *sd, unsigned val)
|
||||
{
|
||||
*sd = val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a spinlock_data_t. On mips reading a plain 32-bit value is one
|
||||
* instruction, and instructions are atomic with respect to memory.
|
||||
*/
|
||||
SPINLOCK_INLINE
|
||||
spinlock_data_t
|
||||
spinlock_data_get(volatile spinlock_data_t *sd)
|
||||
{
|
||||
return *sd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test-and-set a spinlock_data_t. Use the LL/SC instructions to
|
||||
* make it atomic.
|
||||
*
|
||||
* LL (load linked) loads a machine word from memory, and marks the
|
||||
* address. SC (store conditional) stores a machine word to memory,
|
||||
* but succeeds only if the address is marked from a previous LL on
|
||||
* the same processor. Stores from other processors clear that mark,
|
||||
* as do traps on the current processor. Note that there may be no
|
||||
* other memory accesses (besides instruction fetches) between the LL
|
||||
* and the SC or the behavior is *undefined*. You can only use LL/SC
|
||||
* to atomically update one machine word.
|
||||
*/
|
||||
SPINLOCK_INLINE
|
||||
spinlock_data_t
|
||||
spinlock_data_testandset(volatile spinlock_data_t *sd)
|
||||
{
|
||||
spinlock_data_t x;
|
||||
spinlock_data_t y;
|
||||
|
||||
/*
|
||||
* Test-and-set using LL/SC.
|
||||
*
|
||||
* Load the existing value into X, and use Y to store 1.
|
||||
* After the SC, Y contains 1 if the store succeeded,
|
||||
* 0 if it failed.
|
||||
*
|
||||
* On failure, return 1 to pretend that the spinlock
|
||||
* was already held.
|
||||
*/
|
||||
|
||||
y = 1;
|
||||
__asm volatile(
|
||||
".set push;" /* save assembler mode */
|
||||
".set mips32;" /* allow MIPS32 instructions */
|
||||
".set volatile;" /* avoid unwanted optimization */
|
||||
"ll %0, 0(%2);" /* x = *sd */
|
||||
"sc %1, 0(%2);" /* *sd = y; y = success? */
|
||||
".set pop" /* restore assembler mode */
|
||||
: "=&r" (x), "+r" (y) : "r" (sd));
|
||||
if (y == 0) {
|
||||
return 1;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
#endif /* _MIPS_SPINLOCK_H_ */
|
48
kern/arch/mips/include/thread.h
Normal file
48
kern/arch/mips/include/thread.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _MIPS_THREAD_H_
|
||||
#define _MIPS_THREAD_H_
|
||||
|
||||
|
||||
/*
|
||||
* Machine-dependent thread bits.
|
||||
*/
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
typedef void (*badfaultfunc_t)(void);
|
||||
|
||||
struct thread_machdep {
|
||||
badfaultfunc_t tm_badfaultfunc; /* fault hook used by copyin/out */
|
||||
jmp_buf tm_copyjmp; /* longjmp area used by copyin/out */
|
||||
};
|
||||
|
||||
|
||||
#endif /* _MIPS_THREAD_H_ */
|
105
kern/arch/mips/include/tlb.h
Normal file
105
kern/arch/mips/include/tlb.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _MIPS_TLB_H_
|
||||
#define _MIPS_TLB_H_
|
||||
|
||||
/*
|
||||
* MIPS-specific TLB access functions.
|
||||
*
|
||||
* tlb_random: write the TLB entry specified by ENTRYHI and ENTRYLO
|
||||
* into a "random" TLB slot chosen by the processor.
|
||||
*
|
||||
* IMPORTANT NOTE: never write more than one TLB entry with the
|
||||
* same virtual page field.
|
||||
*
|
||||
* tlb_write: same as tlb_random, but you choose the slot.
|
||||
*
|
||||
* tlb_read: read a TLB entry out of the TLB into ENTRYHI and ENTRYLO.
|
||||
* INDEX specifies which one to get.
|
||||
*
|
||||
* tlb_probe: look for an entry matching the virtual page in ENTRYHI.
|
||||
* Returns the index, or a negative number if no matching entry
|
||||
* was found. ENTRYLO is not actually used, but must be set; 0
|
||||
* should be passed.
|
||||
*
|
||||
* IMPORTANT NOTE: An entry may be matching even if the valid bit
|
||||
* is not set. To completely invalidate the TLB, load it with
|
||||
* translations for addresses in one of the unmapped address
|
||||
* ranges - these will never be matched.
|
||||
*/
|
||||
|
||||
void tlb_random(uint32_t entryhi, uint32_t entrylo);
|
||||
void tlb_write(uint32_t entryhi, uint32_t entrylo, uint32_t index);
|
||||
void tlb_read(uint32_t *entryhi, uint32_t *entrylo, uint32_t index);
|
||||
int tlb_probe(uint32_t entryhi, uint32_t entrylo);
|
||||
|
||||
/*
|
||||
* TLB entry fields.
|
||||
*
|
||||
* Note that the MIPS has support for a 6-bit address space ID. In the
|
||||
* interests of simplicity, we don't use it. The fields related to it
|
||||
* (TLBLO_GLOBAL and TLBHI_PID) can be left always zero, as can the
|
||||
* bits that aren't assigned a meaning.
|
||||
*
|
||||
* The TLBLO_DIRTY bit is actually a write privilege bit - it is not
|
||||
* ever set by the processor. If you set it, writes are permitted. If
|
||||
* you don't set it, you'll get a "TLB Modify" exception when a write
|
||||
* is attempted.
|
||||
*
|
||||
* There is probably no reason in the course of CS161 to use TLBLO_NOCACHE.
|
||||
*/
|
||||
|
||||
/* Fields in the high-order word */
|
||||
#define TLBHI_VPAGE 0xfffff000
|
||||
/* TLBHI_PID 0x00000fc0 */
|
||||
|
||||
/* Fields in the low-order word */
|
||||
#define TLBLO_PPAGE 0xfffff000
|
||||
#define TLBLO_NOCACHE 0x00000800
|
||||
#define TLBLO_DIRTY 0x00000400
|
||||
#define TLBLO_VALID 0x00000200
|
||||
/* TLBLO_GLOBAL 0x00000100 */
|
||||
|
||||
/*
|
||||
* Values for completely invalid TLB entries. The TLB entry index should
|
||||
* be passed to TLBHI_INVALID; this prevents loading the same invalid
|
||||
* entry into multiple TLB slots.
|
||||
*/
|
||||
#define TLBHI_INVALID(entryno) ((0x80000+(entryno))<<12)
|
||||
#define TLBLO_INVALID() (0)
|
||||
|
||||
/*
|
||||
* Number of TLB entries in the processor.
|
||||
*/
|
||||
|
||||
#define NUM_TLB 64
|
||||
|
||||
|
||||
#endif /* _MIPS_TLB_H_ */
|
110
kern/arch/mips/include/trapframe.h
Normal file
110
kern/arch/mips/include/trapframe.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _MIPS_TRAPFRAME_H_
|
||||
#define _MIPS_TRAPFRAME_H_
|
||||
|
||||
/*
|
||||
* Structure describing what is saved on the stack during entry to
|
||||
* the exception handler.
|
||||
*
|
||||
* This must agree with the code in exception-*.S.
|
||||
*/
|
||||
|
||||
struct trapframe {
|
||||
uint32_t tf_vaddr; /* coprocessor 0 vaddr register */
|
||||
uint32_t tf_status; /* coprocessor 0 status register */
|
||||
uint32_t tf_cause; /* coprocessor 0 cause register */
|
||||
uint32_t tf_lo;
|
||||
uint32_t tf_hi;
|
||||
uint32_t tf_ra; /* Saved register 31 */
|
||||
uint32_t tf_at; /* Saved register 1 (AT) */
|
||||
uint32_t tf_v0; /* Saved register 2 (v0) */
|
||||
uint32_t tf_v1; /* etc. */
|
||||
uint32_t tf_a0;
|
||||
uint32_t tf_a1;
|
||||
uint32_t tf_a2;
|
||||
uint32_t tf_a3;
|
||||
uint32_t tf_t0;
|
||||
uint32_t tf_t1;
|
||||
uint32_t tf_t2;
|
||||
uint32_t tf_t3;
|
||||
uint32_t tf_t4;
|
||||
uint32_t tf_t5;
|
||||
uint32_t tf_t6;
|
||||
uint32_t tf_t7;
|
||||
uint32_t tf_s0;
|
||||
uint32_t tf_s1;
|
||||
uint32_t tf_s2;
|
||||
uint32_t tf_s3;
|
||||
uint32_t tf_s4;
|
||||
uint32_t tf_s5;
|
||||
uint32_t tf_s6;
|
||||
uint32_t tf_s7;
|
||||
uint32_t tf_t8;
|
||||
uint32_t tf_t9;
|
||||
uint32_t tf_k0; /* dummy (see exception-mips1.S comments) */
|
||||
uint32_t tf_k1; /* dummy */
|
||||
uint32_t tf_gp;
|
||||
uint32_t tf_sp;
|
||||
uint32_t tf_s8;
|
||||
uint32_t tf_epc; /* coprocessor 0 epc register */
|
||||
};
|
||||
|
||||
/*
|
||||
* MIPS exception codes.
|
||||
*/
|
||||
#define EX_IRQ 0 /* Interrupt */
|
||||
#define EX_MOD 1 /* TLB Modify (write to read-only page) */
|
||||
#define EX_TLBL 2 /* TLB miss on load */
|
||||
#define EX_TLBS 3 /* TLB miss on store */
|
||||
#define EX_ADEL 4 /* Address error on load */
|
||||
#define EX_ADES 5 /* Address error on store */
|
||||
#define EX_IBE 6 /* Bus error on instruction fetch */
|
||||
#define EX_DBE 7 /* Bus error on data load *or* store */
|
||||
#define EX_SYS 8 /* Syscall */
|
||||
#define EX_BP 9 /* Breakpoint */
|
||||
#define EX_RI 10 /* Reserved (illegal) instruction */
|
||||
#define EX_CPU 11 /* Coprocessor unusable */
|
||||
#define EX_OVF 12 /* Arithmetic overflow */
|
||||
|
||||
/*
|
||||
* Function to enter user mode. Does not return. The trapframe must
|
||||
* be on the thread's own stack or bad things will happen.
|
||||
*/
|
||||
__DEAD void mips_usermode(struct trapframe *tf);
|
||||
|
||||
/*
|
||||
* Arrays used to load the kernel stack and curthread on trap entry.
|
||||
*/
|
||||
extern vaddr_t cpustacks[];
|
||||
extern vaddr_t cputhreads[];
|
||||
|
||||
|
||||
#endif /* _MIPS_TRAPFRAME_H_ */
|
46
kern/arch/mips/include/types.h
Normal file
46
kern/arch/mips/include/types.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _MIPS_TYPES_H_
|
||||
#define _MIPS_TYPES_H_
|
||||
|
||||
/*
|
||||
* Machine-dependent types that are *not* made visible to userland.
|
||||
* Those that are made visible are found in kern/machine/types.h.
|
||||
* 32-bit MIPS version.
|
||||
*
|
||||
* (Use the underscore versions of the base type names because this
|
||||
* file is included by types.h before the non-underscore versions are
|
||||
* defined.)
|
||||
*/
|
||||
|
||||
typedef __u32 paddr_t;
|
||||
typedef __u32 vaddr_t;
|
||||
|
||||
#endif /* _MIPS_TYPES_H_ */
|
129
kern/arch/mips/include/vm.h
Normal file
129
kern/arch/mips/include/vm.h
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _MIPS_VM_H_
|
||||
#define _MIPS_VM_H_
|
||||
|
||||
|
||||
/*
|
||||
* Machine-dependent VM system definitions.
|
||||
*/
|
||||
|
||||
#define PAGE_SIZE 4096 /* size of VM page */
|
||||
#define PAGE_FRAME 0xfffff000 /* mask for getting page number from addr */
|
||||
|
||||
/*
|
||||
* MIPS-I hardwired memory layout:
|
||||
* 0xc0000000 - 0xffffffff kseg2 (kernel, tlb-mapped)
|
||||
* 0xa0000000 - 0xbfffffff kseg1 (kernel, unmapped, uncached)
|
||||
* 0x80000000 - 0x9fffffff kseg0 (kernel, unmapped, cached)
|
||||
* 0x00000000 - 0x7fffffff kuseg (user, tlb-mapped)
|
||||
*
|
||||
* (mips32 is a little different)
|
||||
*/
|
||||
|
||||
#define MIPS_KUSEG 0x00000000
|
||||
#define MIPS_KSEG0 0x80000000
|
||||
#define MIPS_KSEG1 0xa0000000
|
||||
#define MIPS_KSEG2 0xc0000000
|
||||
|
||||
/*
|
||||
* The first 512 megs of physical space can be addressed in both kseg0 and
|
||||
* kseg1. We use kseg0 for the kernel. This macro returns the kernel virtual
|
||||
* address of a given physical address within that range. (We assume we're
|
||||
* not using systems with more physical space than that anyway.)
|
||||
*
|
||||
* N.B. If you, say, call a function that returns a paddr or 0 on error,
|
||||
* check the paddr for being 0 *before* you use this macro. While paddr 0
|
||||
* is not legal for memory allocation or memory management (it holds
|
||||
* exception handler code) when converted to a vaddr it's *not* NULL, *is*
|
||||
* a valid address, and will make a *huge* mess if you scribble on it.
|
||||
*/
|
||||
#define PADDR_TO_KVADDR(paddr) ((paddr)+MIPS_KSEG0)
|
||||
|
||||
/*
|
||||
* The top of user space. (Actually, the address immediately above the
|
||||
* last valid user address.)
|
||||
*/
|
||||
#define USERSPACETOP MIPS_KSEG0
|
||||
|
||||
/*
|
||||
* The starting value for the stack pointer at user level. Because
|
||||
* the stack is subtract-then-store, this can start as the next
|
||||
* address after the stack area.
|
||||
*
|
||||
* We put the stack at the very top of user virtual memory because it
|
||||
* grows downwards.
|
||||
*/
|
||||
#define USERSTACK USERSPACETOP
|
||||
|
||||
/*
|
||||
* Interface to the low-level module that looks after the amount of
|
||||
* physical memory we have.
|
||||
*
|
||||
* ram_getsize returns one past the highest valid physical
|
||||
* address. (This value is page-aligned.) The extant RAM ranges from
|
||||
* physical address 0 up to but not including this address.
|
||||
*
|
||||
* ram_getfirstfree returns the lowest valid physical address. (It is
|
||||
* also page-aligned.) Memory at this address and above is available
|
||||
* for use during operation, and excludes the space the kernel is
|
||||
* loaded into and memory that is grabbed in the very early stages of
|
||||
* bootup. Memory below this address is already in use and should be
|
||||
* reserved or otherwise not managed by the VM system. It should be
|
||||
* called exactly once when the VM system initializes to take over
|
||||
* management of physical memory.
|
||||
*
|
||||
* ram_stealmem can be used before ram_getsize is called to allocate
|
||||
* memory that cannot be freed later. This is intended for use early
|
||||
* in bootup before VM initialization is complete.
|
||||
*/
|
||||
|
||||
void ram_bootstrap(void);
|
||||
paddr_t ram_stealmem(unsigned long npages);
|
||||
paddr_t ram_getsize(void);
|
||||
paddr_t ram_getfirstfree(void);
|
||||
|
||||
/*
|
||||
* TLB shootdown bits.
|
||||
*
|
||||
* We'll take up to 16 invalidations before just flushing the whole TLB.
|
||||
*/
|
||||
|
||||
struct tlbshootdown {
|
||||
/*
|
||||
* Change this to what you need for your VM design.
|
||||
*/
|
||||
int ts_placeholder;
|
||||
};
|
||||
|
||||
#define TLBSHOOTDOWN_MAX 16
|
||||
|
||||
|
||||
#endif /* _MIPS_VM_H_ */
|
49
kern/arch/mips/locore/cache-mips161.S
Normal file
49
kern/arch/mips/locore/cache-mips161.S
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <kern/mips/regdefs.h>
|
||||
|
||||
/*
|
||||
* Cache flushing code for the System/161 MIPS variant, which
|
||||
* (for now at least) has magically coherent caches. Almost all
|
||||
* real MIPS processors require explicit cache control of one
|
||||
* form or another; it can be quite a nuisance. (It is particularly
|
||||
* nasty on the MIPS-1, that is, r2000/r3000.)
|
||||
*/
|
||||
|
||||
.text
|
||||
.set noreorder
|
||||
|
||||
.globl mips_flushicache
|
||||
.type mips_flushicache,@function
|
||||
.ent mips_flushicache
|
||||
mips_flushicache:
|
||||
j ra
|
||||
nop
|
||||
.end mips_flushicache
|
355
kern/arch/mips/locore/exception-mips1.S
Normal file
355
kern/arch/mips/locore/exception-mips1.S
Normal file
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <kern/mips/regdefs.h>
|
||||
#include <mips/specialreg.h>
|
||||
|
||||
/*
|
||||
* Entry points for exceptions.
|
||||
*
|
||||
* MIPS-1 (r2000/r3000) style exception handling, with the "rfe"
|
||||
* instruction rather than "eret", and the three sets of status bits.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Do not allow the assembler to use $1 (at), because we need to be
|
||||
* able to save it.
|
||||
*/
|
||||
.set noat
|
||||
.set noreorder
|
||||
|
||||
/*
|
||||
* UTLB exception handler.
|
||||
*
|
||||
* This code is copied to address 0x80000000, where the MIPS processor
|
||||
* automatically invokes it.
|
||||
*
|
||||
* To avoid colliding with the other exception code, it must not
|
||||
* exceed 128 bytes (32 instructions).
|
||||
*
|
||||
* This is the special entry point for the fast-path TLB refill for
|
||||
* faults in the user address space. We don't implement fast-path TLB
|
||||
* refill by default. Note that if you do, you either need to make
|
||||
* sure the refill code doesn't fault or write extra code in
|
||||
* common_exception to tidy up after such faults.
|
||||
*/
|
||||
|
||||
.text
|
||||
.globl mips_utlb_handler
|
||||
.type mips_utlb_handler,@function
|
||||
.ent mips_utlb_handler
|
||||
mips_utlb_handler:
|
||||
j common_exception /* Don't need to do anything special */
|
||||
nop /* Delay slot */
|
||||
.globl mips_utlb_end
|
||||
mips_utlb_end:
|
||||
.end mips_utlb_handler
|
||||
|
||||
/*
|
||||
* General exception handler.
|
||||
*
|
||||
* This code is copied to address 0x80000080, where
|
||||
* the MIPS processor automatically invokes it.
|
||||
*/
|
||||
|
||||
.text
|
||||
.globl mips_general_handler
|
||||
.type mips_general_handler,@function
|
||||
.ent mips_general_handler
|
||||
mips_general_handler:
|
||||
j common_exception /* Don't need to do anything special */
|
||||
nop /* Delay slot */
|
||||
.globl mips_general_end
|
||||
mips_general_end:
|
||||
.end mips_general_handler
|
||||
|
||||
/* This keeps gdb from conflating common_exception and mips_general_end */
|
||||
nop /* padding */
|
||||
|
||||
|
||||
/*
|
||||
* Shared exception code for both handlers.
|
||||
*/
|
||||
|
||||
.text
|
||||
.type common_exception,@function
|
||||
.ent common_exception
|
||||
common_exception:
|
||||
mfc0 k0, c0_status /* Get status register */
|
||||
andi k0, k0, CST_KUp /* Check the we-were-in-user-mode bit */
|
||||
beq k0, $0, 1f /* If clear, from kernel, already have stack */
|
||||
nop /* delay slot */
|
||||
|
||||
/* Coming from user mode - find kernel stack */
|
||||
mfc0 k1, c0_context /* we keep the CPU number here */
|
||||
srl k1, k1, CTX_PTBASESHIFT /* shift it to get just the CPU number */
|
||||
sll k1, k1, 2 /* shift it back to make an array index */
|
||||
lui k0, %hi(cpustacks) /* get base address of cpustacks[] */
|
||||
addu k0, k0, k1 /* index it */
|
||||
move k1, sp /* Save previous stack pointer in k1 */
|
||||
b 2f /* Skip to common code */
|
||||
lw sp, %lo(cpustacks)(k0) /* Load kernel stack pointer (in delay slot) */
|
||||
1:
|
||||
/* Coming from kernel mode - just save previous stuff */
|
||||
move k1, sp /* Save previous stack in k1 (delay slot) */
|
||||
2:
|
||||
/*
|
||||
* At this point:
|
||||
* Interrupts are off. (The processor did this for us.)
|
||||
* k0 contains the value for curthread, to go into s7.
|
||||
* k1 contains the old stack pointer.
|
||||
* sp points into the kernel stack.
|
||||
* All other registers are untouched.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Allocate stack space for 37 words to hold the trap frame,
|
||||
* plus four more words for a minimal argument block, plus
|
||||
* one more for proper (64-bit) stack alignment.
|
||||
*/
|
||||
addi sp, sp, -168
|
||||
|
||||
/*
|
||||
* Save general registers.
|
||||
* We exclude k0/k1, which the kernel is free to clobber (and which
|
||||
* we already have clobbered), and $0, whose value is fixed.
|
||||
*
|
||||
* The order here must match mips/include/trapframe.h.
|
||||
*
|
||||
* gdb disassembles this code to try to figure out what registers
|
||||
* are where, and it isn't very bright. So in order to make gdb be
|
||||
* able to trace the stack back through here, we play some silly
|
||||
* games.
|
||||
*
|
||||
* In particular:
|
||||
* (1) We store the return address register into the epc slot,
|
||||
* which makes gdb think it's the return address slot. Then
|
||||
* we store the real epc value over that.
|
||||
* (2) We store the current sp into the sp slot, which makes gdb
|
||||
* think it's the stack pointer slot. Then we store the real
|
||||
* value.
|
||||
* (3) gdb also assumes that saved registers in a function are
|
||||
* saved in order. This is why we put epc where it is, and
|
||||
* handle the real value of ra afterwards.
|
||||
* (4) Because gdb will think we're saving k0 and k1, we need to
|
||||
* leave slots for them in the trap frame, even though the
|
||||
* stuff we save there is useless.
|
||||
*
|
||||
* This logic has not been tested against a recent gdb and has
|
||||
* probably bitrotted. Someone(TM) should figure out what gdb
|
||||
* currently expects -- or maybe even patch gdb to understand a
|
||||
* better form of this that doesn't waste so many cycles.
|
||||
*/
|
||||
sw ra, 160(sp) /* dummy for gdb */
|
||||
sw s8, 156(sp) /* save s8 */
|
||||
sw sp, 152(sp) /* dummy for gdb */
|
||||
sw gp, 148(sp) /* save gp */
|
||||
sw k1, 144(sp) /* dummy for gdb */
|
||||
sw k0, 140(sp) /* dummy for gdb */
|
||||
|
||||
sw k1, 152(sp) /* real saved sp */
|
||||
nop /* delay slot for store */
|
||||
|
||||
mfc0 k1, c0_epc /* Copr.0 reg 13 == PC for exception */
|
||||
sw k1, 160(sp) /* real saved PC */
|
||||
|
||||
sw t9, 136(sp)
|
||||
sw t8, 132(sp)
|
||||
sw s7, 128(sp)
|
||||
sw s6, 124(sp)
|
||||
sw s5, 120(sp)
|
||||
sw s4, 116(sp)
|
||||
sw s3, 112(sp)
|
||||
sw s2, 108(sp)
|
||||
sw s1, 104(sp)
|
||||
sw s0, 100(sp)
|
||||
sw t7, 96(sp)
|
||||
sw t6, 92(sp)
|
||||
sw t5, 88(sp)
|
||||
sw t4, 84(sp)
|
||||
sw t3, 80(sp)
|
||||
sw t2, 76(sp)
|
||||
sw t1, 72(sp)
|
||||
sw t0, 68(sp)
|
||||
sw a3, 64(sp)
|
||||
sw a2, 60(sp)
|
||||
sw a1, 56(sp)
|
||||
sw a0, 52(sp)
|
||||
sw v1, 48(sp)
|
||||
sw v0, 44(sp)
|
||||
sw AT, 40(sp)
|
||||
|
||||
sw ra, 36(sp)
|
||||
|
||||
/*
|
||||
* Save special registers.
|
||||
*/
|
||||
mfhi t0
|
||||
mflo t1
|
||||
sw t0, 32(sp)
|
||||
sw t1, 28(sp)
|
||||
|
||||
/*
|
||||
* Save remaining exception context information.
|
||||
*/
|
||||
|
||||
mfc0 t2, c0_status /* Copr.0 reg 11 == status */
|
||||
sw t2, 20(sp)
|
||||
mfc0 t3, c0_vaddr /* Copr.0 reg 8 == faulting vaddr */
|
||||
sw t3, 16(sp)
|
||||
mfc0 t4, c0_cause
|
||||
sw t4, 24(sp) /* Copr.0 reg 13 == exception cause */
|
||||
|
||||
/*
|
||||
* Pretend to save $0 for gdb's benefit.
|
||||
*/
|
||||
sw $0, 12(sp)
|
||||
|
||||
/*
|
||||
* Load the curthread register if coming from user mode.
|
||||
*/
|
||||
andi k0, t2, CST_KUp /* Check the we-were-in-user-mode bit */
|
||||
beq k0, $0, 3f /* If clear, were in kernel, skip ahead */
|
||||
nop /* delay slot */
|
||||
|
||||
mfc0 k1, c0_context /* we keep the CPU number here */
|
||||
srl k1, k1, CTX_PTBASESHIFT /* shift it to get just the CPU number */
|
||||
sll k1, k1, 2 /* shift it back to make an array index */
|
||||
lui k0, %hi(cputhreads) /* get base address of cputhreads[] */
|
||||
addu k0, k0, k1 /* index it */
|
||||
lw s7, %lo(cputhreads)(k0) /* Load curthread value */
|
||||
3:
|
||||
|
||||
/*
|
||||
* Load the kernel GP value.
|
||||
*/
|
||||
la gp, _gp
|
||||
|
||||
/*
|
||||
* Prepare to call mips_trap(struct trapframe *)
|
||||
*/
|
||||
|
||||
addiu a0, sp, 16 /* set argument - pointer to the trapframe */
|
||||
jal mips_trap /* call it */
|
||||
nop /* delay slot */
|
||||
|
||||
/* Something must be here or gdb doesn't find the stack frame. */
|
||||
nop
|
||||
|
||||
/*
|
||||
* Now restore stuff and return from the exception.
|
||||
* Interrupts should be off.
|
||||
*/
|
||||
exception_return:
|
||||
|
||||
/* 16(sp) no need to restore tf_vaddr */
|
||||
lw t0, 20(sp) /* load status register value into t0 */
|
||||
nop /* load delay slot */
|
||||
mtc0 t0, c0_status /* store it back to coprocessor 0 */
|
||||
/* 24(sp) no need to restore tf_cause */
|
||||
|
||||
/* restore special registers */
|
||||
lw t1, 28(sp)
|
||||
lw t0, 32(sp)
|
||||
mtlo t1
|
||||
mthi t0
|
||||
|
||||
/* load the general registers */
|
||||
lw ra, 36(sp)
|
||||
|
||||
lw AT, 40(sp)
|
||||
lw v0, 44(sp)
|
||||
lw v1, 48(sp)
|
||||
lw a0, 52(sp)
|
||||
lw a1, 56(sp)
|
||||
lw a2, 60(sp)
|
||||
lw a3, 64(sp)
|
||||
lw t0, 68(sp)
|
||||
lw t1, 72(sp)
|
||||
lw t2, 76(sp)
|
||||
lw t3, 80(sp)
|
||||
lw t4, 84(sp)
|
||||
lw t5, 88(sp)
|
||||
lw t6, 92(sp)
|
||||
lw t7, 96(sp)
|
||||
lw s0, 100(sp)
|
||||
lw s1, 104(sp)
|
||||
lw s2, 108(sp)
|
||||
lw s3, 112(sp)
|
||||
lw s4, 116(sp)
|
||||
lw s5, 120(sp)
|
||||
lw s6, 124(sp)
|
||||
lw s7, 128(sp)
|
||||
lw t8, 132(sp)
|
||||
lw t9, 136(sp)
|
||||
|
||||
/* 140(sp) "saved" k0 was dummy garbage anyway */
|
||||
/* 144(sp) "saved" k1 was dummy garbage anyway */
|
||||
|
||||
lw gp, 148(sp) /* restore gp */
|
||||
/* 152(sp) stack pointer - below */
|
||||
lw s8, 156(sp) /* restore s8 */
|
||||
lw k0, 160(sp) /* fetch exception return PC into k0 */
|
||||
|
||||
lw sp, 152(sp) /* fetch saved sp (must be last) */
|
||||
|
||||
/* done */
|
||||
jr k0 /* jump back */
|
||||
rfe /* in delay slot */
|
||||
.end common_exception
|
||||
|
||||
/*
|
||||
* Code to enter user mode for the first time.
|
||||
* Does not return.
|
||||
*
|
||||
* This is called from mips_usermode().
|
||||
* Interrupts on this processor should be off.
|
||||
*/
|
||||
|
||||
.text
|
||||
.globl asm_usermode
|
||||
.type asm_usermode,@function
|
||||
.ent asm_usermode
|
||||
asm_usermode:
|
||||
/*
|
||||
* a0 is the address of a trapframe to use for exception "return".
|
||||
* It's allocated on our stack.
|
||||
*
|
||||
* Move it to the stack pointer - we don't need the actual stack
|
||||
* position any more. (When we come back from usermode, cpustacks[]
|
||||
* will be used to reinitialize our stack pointer, and that was
|
||||
* set by mips_usermode.)
|
||||
*
|
||||
* Then just jump to the exception return code above.
|
||||
*/
|
||||
|
||||
j exception_return
|
||||
addiu sp, a0, -16 /* in delay slot */
|
||||
.end asm_usermode
|
438
kern/arch/mips/locore/trap.c
Normal file
438
kern/arch/mips/locore/trap.c
Normal file
@@ -0,0 +1,438 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <types.h>
|
||||
#include <signal.h>
|
||||
#include <lib.h>
|
||||
#include <mips/specialreg.h>
|
||||
#include <mips/trapframe.h>
|
||||
#include <cpu.h>
|
||||
#include <spl.h>
|
||||
#include <thread.h>
|
||||
#include <current.h>
|
||||
#include <vm.h>
|
||||
#include <mainbus.h>
|
||||
#include <syscall.h>
|
||||
|
||||
|
||||
/* in exception-*.S */
|
||||
extern __DEAD void asm_usermode(struct trapframe *tf);
|
||||
|
||||
/* called only from assembler, so not declared in a header */
|
||||
void mips_trap(struct trapframe *tf);
|
||||
|
||||
|
||||
/* Names for trap codes */
|
||||
#define NTRAPCODES 13
|
||||
static const char *const trapcodenames[NTRAPCODES] = {
|
||||
"Interrupt",
|
||||
"TLB modify trap",
|
||||
"TLB miss on load",
|
||||
"TLB miss on store",
|
||||
"Address error on load",
|
||||
"Address error on store",
|
||||
"Bus error on code",
|
||||
"Bus error on data",
|
||||
"System call",
|
||||
"Break instruction",
|
||||
"Illegal instruction",
|
||||
"Coprocessor unusable",
|
||||
"Arithmetic overflow",
|
||||
};
|
||||
|
||||
/*
|
||||
* Function called when user-level code hits a fatal fault.
|
||||
*/
|
||||
static
|
||||
void
|
||||
kill_curthread(vaddr_t epc, unsigned code, vaddr_t vaddr)
|
||||
{
|
||||
int sig = 0;
|
||||
|
||||
KASSERT(code < NTRAPCODES);
|
||||
switch (code) {
|
||||
case EX_IRQ:
|
||||
case EX_IBE:
|
||||
case EX_DBE:
|
||||
case EX_SYS:
|
||||
/* should not be seen */
|
||||
KASSERT(0);
|
||||
sig = SIGABRT;
|
||||
break;
|
||||
case EX_MOD:
|
||||
case EX_TLBL:
|
||||
case EX_TLBS:
|
||||
sig = SIGSEGV;
|
||||
break;
|
||||
case EX_ADEL:
|
||||
case EX_ADES:
|
||||
sig = SIGBUS;
|
||||
break;
|
||||
case EX_BP:
|
||||
sig = SIGTRAP;
|
||||
break;
|
||||
case EX_RI:
|
||||
sig = SIGILL;
|
||||
break;
|
||||
case EX_CPU:
|
||||
sig = SIGSEGV;
|
||||
break;
|
||||
case EX_OVF:
|
||||
sig = SIGFPE;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* You will probably want to change this.
|
||||
*/
|
||||
|
||||
kprintf("Fatal user mode trap %u sig %d (%s, epc 0x%x, vaddr 0x%x)\n",
|
||||
code, sig, trapcodenames[code], epc, vaddr);
|
||||
panic("I don't know how to handle this\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* General trap (exception) handling function for mips.
|
||||
* This is called by the assembly-language exception handler once
|
||||
* the trapframe has been set up.
|
||||
*/
|
||||
void
|
||||
mips_trap(struct trapframe *tf)
|
||||
{
|
||||
uint32_t code;
|
||||
/*bool isutlb; -- not used */
|
||||
bool iskern;
|
||||
int spl;
|
||||
|
||||
/* The trap frame is supposed to be 37 registers long. */
|
||||
KASSERT(sizeof(struct trapframe)==(37*4));
|
||||
|
||||
/*
|
||||
* Extract the exception code info from the register fields.
|
||||
*/
|
||||
code = (tf->tf_cause & CCA_CODE) >> CCA_CODESHIFT;
|
||||
/*isutlb = (tf->tf_cause & CCA_UTLB) != 0;*/
|
||||
iskern = (tf->tf_status & CST_KUp) == 0;
|
||||
|
||||
KASSERT(code < NTRAPCODES);
|
||||
|
||||
/* Make sure we haven't run off our stack */
|
||||
if (curthread != NULL && curthread->t_stack != NULL) {
|
||||
KASSERT((vaddr_t)tf > (vaddr_t)curthread->t_stack);
|
||||
KASSERT((vaddr_t)tf < (vaddr_t)(curthread->t_stack
|
||||
+ STACK_SIZE));
|
||||
}
|
||||
|
||||
/* Interrupt? Call the interrupt handler and return. */
|
||||
if (code == EX_IRQ) {
|
||||
int old_in;
|
||||
bool doadjust;
|
||||
|
||||
old_in = curthread->t_in_interrupt;
|
||||
curthread->t_in_interrupt = 1;
|
||||
|
||||
/*
|
||||
* The processor has turned interrupts off; if the
|
||||
* currently recorded interrupt state is interrupts on
|
||||
* (spl of 0), adjust the recorded state to match, and
|
||||
* restore after processing the interrupt.
|
||||
*
|
||||
* How can we get an interrupt if the recorded state
|
||||
* is interrupts off? Well, as things currently stand
|
||||
* when the CPU finishes idling it flips interrupts on
|
||||
* and off to allow things to happen, but leaves
|
||||
* curspl high while doing so.
|
||||
*
|
||||
* While we're here, assert that the interrupt
|
||||
* handling code hasn't leaked a spinlock or an
|
||||
* splhigh().
|
||||
*/
|
||||
|
||||
if (curthread->t_curspl == 0) {
|
||||
KASSERT(curthread->t_curspl == 0);
|
||||
KASSERT(curthread->t_iplhigh_count == 0);
|
||||
curthread->t_curspl = IPL_HIGH;
|
||||
curthread->t_iplhigh_count++;
|
||||
doadjust = true;
|
||||
}
|
||||
else {
|
||||
doadjust = false;
|
||||
}
|
||||
|
||||
mainbus_interrupt(tf);
|
||||
|
||||
if (doadjust) {
|
||||
KASSERT(curthread->t_curspl == IPL_HIGH);
|
||||
KASSERT(curthread->t_iplhigh_count == 1);
|
||||
curthread->t_iplhigh_count--;
|
||||
curthread->t_curspl = 0;
|
||||
}
|
||||
|
||||
curthread->t_in_interrupt = old_in;
|
||||
goto done2;
|
||||
}
|
||||
|
||||
/*
|
||||
* The processor turned interrupts off when it took the trap.
|
||||
*
|
||||
* While we're in the kernel, and not actually handling an
|
||||
* interrupt, restore the interrupt state to where it was in
|
||||
* the previous context, which may be low (interrupts on).
|
||||
*
|
||||
* Do this by forcing splhigh(), which may do a redundant
|
||||
* cpu_irqoff() but forces the stored MI interrupt state into
|
||||
* sync, then restoring the previous state.
|
||||
*/
|
||||
spl = splhigh();
|
||||
splx(spl);
|
||||
|
||||
/* Syscall? Call the syscall handler and return. */
|
||||
if (code == EX_SYS) {
|
||||
/* Interrupts should have been on while in user mode. */
|
||||
KASSERT(curthread->t_curspl == 0);
|
||||
KASSERT(curthread->t_iplhigh_count == 0);
|
||||
|
||||
DEBUG(DB_SYSCALL, "syscall: #%d, args %x %x %x %x\n",
|
||||
tf->tf_v0, tf->tf_a0, tf->tf_a1, tf->tf_a2, tf->tf_a3);
|
||||
|
||||
syscall(tf);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ok, it wasn't any of the really easy cases.
|
||||
* Call vm_fault on the TLB exceptions.
|
||||
* Panic on the bus error exceptions.
|
||||
*/
|
||||
switch (code) {
|
||||
case EX_MOD:
|
||||
if (vm_fault(VM_FAULT_READONLY, tf->tf_vaddr)==0) {
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case EX_TLBL:
|
||||
if (vm_fault(VM_FAULT_READ, tf->tf_vaddr)==0) {
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case EX_TLBS:
|
||||
if (vm_fault(VM_FAULT_WRITE, tf->tf_vaddr)==0) {
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case EX_IBE:
|
||||
case EX_DBE:
|
||||
/*
|
||||
* This means you loaded invalid TLB entries, or
|
||||
* touched invalid parts of the direct-mapped
|
||||
* segments. These are serious kernel errors, so
|
||||
* panic.
|
||||
*
|
||||
* The MIPS won't even tell you what invalid address
|
||||
* caused the bus error.
|
||||
*/
|
||||
panic("Bus error exception, PC=0x%x\n", tf->tf_epc);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we get to this point, it's a fatal fault - either it's
|
||||
* one of the other exceptions, like illegal instruction, or
|
||||
* it was a page fault we couldn't handle.
|
||||
*/
|
||||
|
||||
if (!iskern) {
|
||||
/*
|
||||
* Fatal fault in user mode.
|
||||
* Kill the current user process.
|
||||
*/
|
||||
kill_curthread(tf->tf_epc, code, tf->tf_vaddr);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fatal fault in kernel mode.
|
||||
*
|
||||
* If pcb_badfaultfunc is set, we do not panic; badfaultfunc is
|
||||
* set by copyin/copyout and related functions to signify that
|
||||
* the addresses they're accessing are userlevel-supplied and
|
||||
* not trustable. What we actually want to do is resume
|
||||
* execution at the function pointed to by badfaultfunc. That's
|
||||
* going to be "copyfail" (see copyinout.c), which longjmps
|
||||
* back to copyin/copyout or wherever and returns EFAULT.
|
||||
*
|
||||
* Note that we do not just *call* this function, because that
|
||||
* won't necessarily do anything. We want the control flow
|
||||
* that is currently executing in copyin (or whichever), and
|
||||
* is stopped while we process the exception, to *teleport* to
|
||||
* copyfail.
|
||||
*
|
||||
* This is accomplished by changing tf->tf_epc and returning
|
||||
* from the exception handler.
|
||||
*/
|
||||
|
||||
if (curthread != NULL &&
|
||||
curthread->t_machdep.tm_badfaultfunc != NULL) {
|
||||
tf->tf_epc = (vaddr_t) curthread->t_machdep.tm_badfaultfunc;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Really fatal kernel-mode fault.
|
||||
*/
|
||||
|
||||
kprintf("panic: Fatal exception %u (%s) in kernel mode\n", code,
|
||||
trapcodenames[code]);
|
||||
kprintf("panic: EPC 0x%x, exception vaddr 0x%x\n",
|
||||
tf->tf_epc, tf->tf_vaddr);
|
||||
|
||||
panic("I can't handle this... I think I'll just die now...\n");
|
||||
|
||||
done:
|
||||
/*
|
||||
* Turn interrupts off on the processor, without affecting the
|
||||
* stored interrupt state.
|
||||
*/
|
||||
cpu_irqoff();
|
||||
done2:
|
||||
|
||||
/*
|
||||
* The boot thread can get here (e.g. on interrupt return) but
|
||||
* since it doesn't go to userlevel, it can't be returning to
|
||||
* userlevel, so there's no need to set cputhreads[] and
|
||||
* cpustacks[]. Just return.
|
||||
*/
|
||||
if (curthread->t_stack == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
cputhreads[curcpu->c_number] = (vaddr_t)curthread;
|
||||
cpustacks[curcpu->c_number] = (vaddr_t)curthread->t_stack + STACK_SIZE;
|
||||
|
||||
/*
|
||||
* This assertion will fail if either
|
||||
* (1) curthread->t_stack is corrupted, or
|
||||
* (2) the trap frame is somehow on the wrong kernel stack.
|
||||
*
|
||||
* If cpustacks[] is corrupted, the next trap back to the
|
||||
* kernel will (most likely) hang the system, so it's better
|
||||
* to find out now.
|
||||
*/
|
||||
KASSERT(SAME_STACK(cpustacks[curcpu->c_number]-1, (vaddr_t)tf));
|
||||
}
|
||||
|
||||
/*
|
||||
* Function for entering user mode.
|
||||
*
|
||||
* This should not be used by threads returning from traps - they
|
||||
* should just return from mips_trap(). It should be used by threads
|
||||
* entering user mode for the first time - whether the child thread in
|
||||
* a fork(), or into a brand-new address space after exec(), or when
|
||||
* starting the first userlevel program.
|
||||
*
|
||||
* It works by jumping into the exception return code.
|
||||
*
|
||||
* mips_usermode is common code for this. It cannot usefully be called
|
||||
* outside the mips port, but should be called from one of the
|
||||
* following places:
|
||||
* - enter_new_process, for use by exec and equivalent.
|
||||
* - enter_forked_process, in syscall.c, for use by fork.
|
||||
*/
|
||||
void
|
||||
mips_usermode(struct trapframe *tf)
|
||||
{
|
||||
|
||||
/*
|
||||
* Interrupts should be off within the kernel while entering
|
||||
* user mode. However, while in user mode, interrupts should
|
||||
* be on. To interact properly with the spl-handling logic
|
||||
* above, we explicitly call spl0() and then call cpu_irqoff().
|
||||
*/
|
||||
spl0();
|
||||
cpu_irqoff();
|
||||
|
||||
cputhreads[curcpu->c_number] = (vaddr_t)curthread;
|
||||
cpustacks[curcpu->c_number] = (vaddr_t)curthread->t_stack + STACK_SIZE;
|
||||
|
||||
/*
|
||||
* This assertion will fail if either
|
||||
* (1) cpustacks[] is corrupted, or
|
||||
* (2) the trap frame is not on our own kernel stack, or
|
||||
* (3) the boot thread tries to enter user mode.
|
||||
*
|
||||
* If cpustacks[] is corrupted, the next trap back to the
|
||||
* kernel will (most likely) hang the system, so it's better
|
||||
* to find out now.
|
||||
*
|
||||
* It's necessary for the trap frame used here to be on the
|
||||
* current thread's own stack. It cannot correctly be on
|
||||
* either another thread's stack or in the kernel heap.
|
||||
* (Exercise: why?)
|
||||
*/
|
||||
KASSERT(SAME_STACK(cpustacks[curcpu->c_number]-1, (vaddr_t)tf));
|
||||
|
||||
/*
|
||||
* This actually does it. See exception-*.S.
|
||||
*/
|
||||
asm_usermode(tf);
|
||||
}
|
||||
|
||||
/*
|
||||
* enter_new_process: go to user mode after loading an executable.
|
||||
*
|
||||
* Performs the necessary initialization so that the user program will
|
||||
* get the arguments supplied in argc/argv (note that argv must be a
|
||||
* user-level address) and the environment pointer env (ditto), and
|
||||
* begin executing at the specified entry point. The stack pointer is
|
||||
* initialized from the stackptr argument. Note that passing argc/argv
|
||||
* may use additional stack space on some other platforms (but not on
|
||||
* mips).
|
||||
*
|
||||
* Unless you implement execve() that passes environments around, just
|
||||
* pass NULL for the environment.
|
||||
*
|
||||
* Works by creating an ersatz trapframe.
|
||||
*/
|
||||
void
|
||||
enter_new_process(int argc, userptr_t argv, userptr_t env,
|
||||
vaddr_t stack, vaddr_t entry)
|
||||
{
|
||||
struct trapframe tf;
|
||||
|
||||
bzero(&tf, sizeof(tf));
|
||||
|
||||
tf.tf_status = CST_IRQMASK | CST_IEp | CST_KUp;
|
||||
tf.tf_epc = entry;
|
||||
tf.tf_a0 = argc;
|
||||
tf.tf_a1 = (vaddr_t)argv;
|
||||
tf.tf_a2 = (vaddr_t)env;
|
||||
tf.tf_sp = stack;
|
||||
|
||||
mips_usermode(&tf);
|
||||
}
|
161
kern/arch/mips/syscall/syscall.c
Normal file
161
kern/arch/mips/syscall/syscall.c
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <types.h>
|
||||
#include <kern/errno.h>
|
||||
#include <kern/syscall.h>
|
||||
#include <lib.h>
|
||||
#include <mips/trapframe.h>
|
||||
#include <thread.h>
|
||||
#include <current.h>
|
||||
#include <syscall.h>
|
||||
|
||||
|
||||
/*
|
||||
* System call dispatcher.
|
||||
*
|
||||
* A pointer to the trapframe created during exception entry (in
|
||||
* exception-*.S) is passed in.
|
||||
*
|
||||
* The calling conventions for syscalls are as follows: Like ordinary
|
||||
* function calls, the first 4 32-bit arguments are passed in the 4
|
||||
* argument registers a0-a3. 64-bit arguments are passed in *aligned*
|
||||
* pairs of registers, that is, either a0/a1 or a2/a3. This means that
|
||||
* if the first argument is 32-bit and the second is 64-bit, a1 is
|
||||
* unused.
|
||||
*
|
||||
* This much is the same as the calling conventions for ordinary
|
||||
* function calls. In addition, the system call number is passed in
|
||||
* the v0 register.
|
||||
*
|
||||
* On successful return, the return value is passed back in the v0
|
||||
* register, or v0 and v1 if 64-bit. This is also like an ordinary
|
||||
* function call, and additionally the a3 register is also set to 0 to
|
||||
* indicate success.
|
||||
*
|
||||
* On an error return, the error code is passed back in the v0
|
||||
* register, and the a3 register is set to 1 to indicate failure.
|
||||
* (Userlevel code takes care of storing the error code in errno and
|
||||
* returning the value -1 from the actual userlevel syscall function.
|
||||
* See src/user/lib/libc/arch/mips/syscalls-mips.S and related files.)
|
||||
*
|
||||
* Upon syscall return the program counter stored in the trapframe
|
||||
* must be incremented by one instruction; otherwise the exception
|
||||
* return code will restart the "syscall" instruction and the system
|
||||
* call will repeat forever.
|
||||
*
|
||||
* If you run out of registers (which happens quickly with 64-bit
|
||||
* values) further arguments must be fetched from the user-level
|
||||
* stack, starting at sp+16 to skip over the slots for the
|
||||
* registerized values, with copyin().
|
||||
*/
|
||||
void
|
||||
syscall(struct trapframe *tf)
|
||||
{
|
||||
int callno;
|
||||
int32_t retval;
|
||||
int err;
|
||||
|
||||
KASSERT(curthread != NULL);
|
||||
KASSERT(curthread->t_curspl == 0);
|
||||
KASSERT(curthread->t_iplhigh_count == 0);
|
||||
|
||||
callno = tf->tf_v0;
|
||||
|
||||
/*
|
||||
* Initialize retval to 0. Many of the system calls don't
|
||||
* really return a value, just 0 for success and -1 on
|
||||
* error. Since retval is the value returned on success,
|
||||
* initialize it to 0 by default; thus it's not necessary to
|
||||
* deal with it except for calls that return other values,
|
||||
* like write.
|
||||
*/
|
||||
|
||||
retval = 0;
|
||||
|
||||
switch (callno) {
|
||||
case SYS_reboot:
|
||||
err = sys_reboot(tf->tf_a0);
|
||||
break;
|
||||
|
||||
case SYS___time:
|
||||
err = sys___time((userptr_t)tf->tf_a0,
|
||||
(userptr_t)tf->tf_a1);
|
||||
break;
|
||||
|
||||
/* Add stuff here */
|
||||
|
||||
default:
|
||||
kprintf("Unknown syscall %d\n", callno);
|
||||
err = ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (err) {
|
||||
/*
|
||||
* Return the error code. This gets converted at
|
||||
* userlevel to a return value of -1 and the error
|
||||
* code in errno.
|
||||
*/
|
||||
tf->tf_v0 = err;
|
||||
tf->tf_a3 = 1; /* signal an error */
|
||||
}
|
||||
else {
|
||||
/* Success. */
|
||||
tf->tf_v0 = retval;
|
||||
tf->tf_a3 = 0; /* signal no error */
|
||||
}
|
||||
|
||||
/*
|
||||
* Now, advance the program counter, to avoid restarting
|
||||
* the syscall over and over again.
|
||||
*/
|
||||
|
||||
tf->tf_epc += 4;
|
||||
|
||||
/* Make sure the syscall code didn't forget to lower spl */
|
||||
KASSERT(curthread->t_curspl == 0);
|
||||
/* ...or leak any spinlocks */
|
||||
KASSERT(curthread->t_iplhigh_count == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enter user mode for a newly forked process.
|
||||
*
|
||||
* This function is provided as a reminder. You need to write
|
||||
* both it and the code that calls it.
|
||||
*
|
||||
* Thus, you can trash it and do things another way if you prefer.
|
||||
*/
|
||||
void
|
||||
enter_forked_process(struct trapframe *tf)
|
||||
{
|
||||
(void)tf;
|
||||
}
|
301
kern/arch/mips/thread/cpu.c
Normal file
301
kern/arch/mips/thread/cpu.c
Normal file
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* CPU control functions.
|
||||
*/
|
||||
|
||||
#include <types.h>
|
||||
#include <lib.h>
|
||||
#include <mips/specialreg.h>
|
||||
#include <mips/trapframe.h>
|
||||
#include <platform/maxcpus.h>
|
||||
#include <cpu.h>
|
||||
#include <thread.h>
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* Startup and exception-time stack hook.
|
||||
*
|
||||
* The MIPS lacks a good way to find the current CPU, current thread,
|
||||
* or current thread stack upon trap entry from user mode. To deal
|
||||
* with this, we store the CPU number (our number, not the hardware
|
||||
* number) in a nonessential field in the MMU, which is about the only
|
||||
* place possible, and then use that to index cpustacks[]. This gets
|
||||
* us the value to load as the stack pointer. We can then also load
|
||||
* curthread from cputhreads[] by parallel indexing.
|
||||
*
|
||||
* These arrays are also used to start up new CPUs, for roughly the
|
||||
* same reasons.
|
||||
*/
|
||||
|
||||
vaddr_t cpustacks[MAXCPUS];
|
||||
vaddr_t cputhreads[MAXCPUS];
|
||||
|
||||
/*
|
||||
* Do machine-dependent initialization of the cpu structure or things
|
||||
* associated with a new cpu. Note that we're not running on the new
|
||||
* cpu when this is called.
|
||||
*/
|
||||
void
|
||||
cpu_machdep_init(struct cpu *c)
|
||||
{
|
||||
vaddr_t stackpointer;
|
||||
|
||||
KASSERT(c->c_number < MAXCPUS);
|
||||
|
||||
if (c->c_curthread->t_stack == NULL) {
|
||||
/* boot cpu; don't need to do anything here */
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Stick the stack in cpustacks[], and thread pointer
|
||||
* in cputhreads[].
|
||||
*/
|
||||
|
||||
/* stack base address */
|
||||
stackpointer = (vaddr_t) c->c_curthread->t_stack;
|
||||
/* since stacks grow down, get the top */
|
||||
stackpointer += STACK_SIZE;
|
||||
|
||||
cpustacks[c->c_number] = stackpointer;
|
||||
cputhreads[c->c_number] = (vaddr_t)c->c_curthread;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* Return the type name of the currently running CPU.
|
||||
*
|
||||
* For now, assume we're running on System/161 so we can use the
|
||||
* System/161 processor-ID values.
|
||||
*/
|
||||
|
||||
#define SYS161_PRID_ORIG 0x000003ff
|
||||
#define SYS161_PRID_2X 0x000000a1
|
||||
|
||||
static inline
|
||||
uint32_t
|
||||
cpu_getprid(void)
|
||||
{
|
||||
uint32_t prid;
|
||||
|
||||
__asm volatile("mfc0 %0,$15" : "=r" (prid));
|
||||
return prid;
|
||||
}
|
||||
|
||||
static inline
|
||||
uint32_t
|
||||
cpu_getfeatures(void)
|
||||
{
|
||||
uint32_t features;
|
||||
|
||||
__asm volatile(".set push;" /* save assembler mode */
|
||||
".set mips32;" /* allow mips32 instructions */
|
||||
"mfc0 %0,$15,1;" /* get cop0 reg 15 sel 1 */
|
||||
".set pop" /* restore assembler mode */
|
||||
: "=r" (features));
|
||||
return features;
|
||||
}
|
||||
|
||||
static inline
|
||||
uint32_t
|
||||
cpu_getifeatures(void)
|
||||
{
|
||||
uint32_t features;
|
||||
|
||||
__asm volatile(".set push;" /* save assembler mode */
|
||||
".set mips32;" /* allow mips32 instructions */
|
||||
"mfc0 %0,$15,2;" /* get cop0 reg 15 sel 2 */
|
||||
".set pop" /* restore assembler mode */
|
||||
: "=r" (features));
|
||||
return features;
|
||||
}
|
||||
|
||||
void
|
||||
cpu_identify(char *buf, size_t max)
|
||||
{
|
||||
uint32_t prid;
|
||||
uint32_t features;
|
||||
|
||||
prid = cpu_getprid();
|
||||
switch (prid) {
|
||||
case SYS161_PRID_ORIG:
|
||||
snprintf(buf, max, "MIPS/161 (System/161 1.x and pre-2.x)");
|
||||
break;
|
||||
case SYS161_PRID_2X:
|
||||
features = cpu_getfeatures();
|
||||
snprintf(buf, max, "MIPS/161 (System/161 2.x) features 0x%x",
|
||||
features);
|
||||
features = cpu_getifeatures();
|
||||
if (features != 0) {
|
||||
kprintf("WARNING: unknown CPU incompatible features "
|
||||
"0x%x\n", features);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
snprintf(buf, max, "32-bit MIPS (unknown type, CPU ID 0x%x)",
|
||||
prid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* Interrupt control.
|
||||
*
|
||||
* While the mips actually has on-chip interrupt priority masking, in
|
||||
* the interests of simplicity, we don't use it. Instead we use
|
||||
* coprocessor 0 register 12 (the system coprocessor "status"
|
||||
* register) bit 0, IEc, which is the global interrupt enable flag.
|
||||
* (IEc stands for interrupt-enable-current.)
|
||||
*/
|
||||
|
||||
/*
|
||||
* gcc inline assembly to get at the status register.
|
||||
*
|
||||
* Pipeline hazards:
|
||||
* - there must be at least one cycle between GET_STATUS
|
||||
* and SET_STATUS;
|
||||
* - it may take up to three cycles after SET_STATUS for the
|
||||
* interrupt state to really change.
|
||||
*
|
||||
* These considerations do not (currently) apply to System/161,
|
||||
* however.
|
||||
*/
|
||||
#define GET_STATUS(x) __asm volatile("mfc0 %0,$12" : "=r" (x))
|
||||
#define SET_STATUS(x) __asm volatile("mtc0 %0,$12" :: "r" (x))
|
||||
|
||||
/*
|
||||
* Interrupts on.
|
||||
*/
|
||||
void
|
||||
cpu_irqon(void)
|
||||
{
|
||||
uint32_t x;
|
||||
|
||||
GET_STATUS(x);
|
||||
x |= CST_IEc;
|
||||
SET_STATUS(x);
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupts off.
|
||||
*/
|
||||
void
|
||||
cpu_irqoff(void)
|
||||
{
|
||||
uint32_t x;
|
||||
|
||||
GET_STATUS(x);
|
||||
x &= ~(uint32_t)CST_IEc;
|
||||
SET_STATUS(x);
|
||||
}
|
||||
|
||||
/*
|
||||
* Used below.
|
||||
*/
|
||||
static
|
||||
void
|
||||
cpu_irqonoff(void)
|
||||
{
|
||||
uint32_t x, xon, xoff;
|
||||
|
||||
GET_STATUS(x);
|
||||
xon = x | CST_IEc;
|
||||
xoff = x & ~(uint32_t)CST_IEc;
|
||||
SET_STATUS(xon);
|
||||
__asm volatile("nop; nop; nop; nop");
|
||||
SET_STATUS(xoff);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* Idling.
|
||||
*/
|
||||
|
||||
/*
|
||||
* gcc inline assembly for the WAIT instruction.
|
||||
*
|
||||
* mips r2k/r3k has no idle instruction at all.
|
||||
*
|
||||
* However, to avoid completely overloading the computing cluster, we
|
||||
* appropriate the mips32 WAIT instruction.
|
||||
*/
|
||||
|
||||
static
|
||||
inline
|
||||
void
|
||||
wait(void)
|
||||
{
|
||||
/*
|
||||
* The WAIT instruction goes into powersave mode until an
|
||||
* interrupt is trying to occur.
|
||||
*
|
||||
* Then switch interrupts on and off again, so we actually
|
||||
* take the interrupt.
|
||||
*
|
||||
* Note that the precise behavior of this instruction in the
|
||||
* System/161 simulator is partly guesswork. This code may not
|
||||
* work on a real mips.
|
||||
*/
|
||||
__asm volatile(
|
||||
".set push;" /* save assembler mode */
|
||||
".set mips32;" /* allow MIPS32 instructions */
|
||||
".set volatile;" /* avoid unwanted optimization */
|
||||
"wait;" /* suspend until interrupted */
|
||||
".set pop" /* restore assembler mode */
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Idle the processor until something happens.
|
||||
*/
|
||||
void
|
||||
cpu_idle(void)
|
||||
{
|
||||
wait();
|
||||
cpu_irqonoff();
|
||||
}
|
||||
|
||||
/*
|
||||
* Halt the CPU permanently.
|
||||
*/
|
||||
void
|
||||
cpu_halt(void)
|
||||
{
|
||||
cpu_irqoff();
|
||||
while (1) {
|
||||
wait();
|
||||
}
|
||||
}
|
99
kern/arch/mips/thread/switch.S
Normal file
99
kern/arch/mips/thread/switch.S
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Assembly language context switch code.
|
||||
*/
|
||||
|
||||
#include <kern/mips/regdefs.h>
|
||||
|
||||
.text
|
||||
.set noreorder
|
||||
|
||||
.globl switchframe_switch
|
||||
.type switchframe_switch,@function
|
||||
.ent switchframe_switch
|
||||
switchframe_switch:
|
||||
/*
|
||||
* a0 contains the address of the switchframe pointer in the old thread.
|
||||
* a1 contains the address of the switchframe pointer in the new thread.
|
||||
*
|
||||
* The switchframe pointer is really the stack pointer. The other
|
||||
* registers get saved on the stack, namely:
|
||||
*
|
||||
* s0-s6, s8
|
||||
* gp, ra
|
||||
*
|
||||
* The order must match <mips/switchframe.h>.
|
||||
*
|
||||
* Note that while we'd ordinarily need to save s7 too, because we
|
||||
* use it to hold curthread saving it would interfere with the way
|
||||
* curthread is managed by thread.c. So we'll just let thread.c
|
||||
* manage it.
|
||||
*/
|
||||
|
||||
/* Allocate stack space for saving 10 registers. 10*4 = 40 */
|
||||
addi sp, sp, -40
|
||||
|
||||
/* Save the registers */
|
||||
sw ra, 36(sp)
|
||||
sw gp, 32(sp)
|
||||
sw s8, 28(sp)
|
||||
sw s6, 24(sp)
|
||||
sw s5, 20(sp)
|
||||
sw s4, 16(sp)
|
||||
sw s3, 12(sp)
|
||||
sw s2, 8(sp)
|
||||
sw s1, 4(sp)
|
||||
sw s0, 0(sp)
|
||||
|
||||
/* Store the old stack pointer in the old thread */
|
||||
sw sp, 0(a0)
|
||||
|
||||
/* Get the new stack pointer from the new thread */
|
||||
lw sp, 0(a1)
|
||||
nop /* delay slot for load */
|
||||
|
||||
/* Now, restore the registers */
|
||||
lw s0, 0(sp)
|
||||
lw s1, 4(sp)
|
||||
lw s2, 8(sp)
|
||||
lw s3, 12(sp)
|
||||
lw s4, 16(sp)
|
||||
lw s5, 20(sp)
|
||||
lw s6, 24(sp)
|
||||
lw s8, 28(sp)
|
||||
lw gp, 32(sp)
|
||||
lw ra, 36(sp)
|
||||
nop /* delay slot for load */
|
||||
|
||||
/* and return. */
|
||||
j ra
|
||||
addi sp, sp, 40 /* in delay slot */
|
||||
.end switchframe_switch
|
98
kern/arch/mips/thread/switchframe.c
Normal file
98
kern/arch/mips/thread/switchframe.c
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <types.h>
|
||||
#include <lib.h>
|
||||
#include <thread.h>
|
||||
#include <threadprivate.h>
|
||||
|
||||
#include "switchframe.h"
|
||||
|
||||
/* in threadstart.S */
|
||||
extern void mips_threadstart(/* arguments are in unusual registers */);
|
||||
|
||||
|
||||
/*
|
||||
* Function to initialize the switchframe of a new thread, which is
|
||||
* *not* the one that is currently running.
|
||||
*
|
||||
* The new thread should, when it is run the first time, end up calling
|
||||
* thread_startup(entrypoint, data1, data2).
|
||||
*
|
||||
* We arrange for this by creating a phony switchframe for
|
||||
* switchframe_switch() to switch to. The only trouble is that the
|
||||
* switchframe doesn't include the argument registers a0-a3. So we
|
||||
* store the arguments in the s* registers, and use a bit of asm
|
||||
* (mips_threadstart) to move them and then jump to thread_startup.
|
||||
*/
|
||||
void
|
||||
switchframe_init(struct thread *thread,
|
||||
void (*entrypoint)(void *data1, unsigned long data2),
|
||||
void *data1, unsigned long data2)
|
||||
{
|
||||
vaddr_t stacktop;
|
||||
struct switchframe *sf;
|
||||
|
||||
/*
|
||||
* MIPS stacks grow down. t_stack is just a hunk of memory, so
|
||||
* get the other end of it. Then set up a switchframe on the
|
||||
* top of the stack.
|
||||
*/
|
||||
stacktop = ((vaddr_t)thread->t_stack) + STACK_SIZE;
|
||||
sf = ((struct switchframe *) stacktop) - 1;
|
||||
|
||||
/* Zero out the switchframe. */
|
||||
bzero(sf, sizeof(*sf));
|
||||
|
||||
/*
|
||||
* Now set the important parts: pass through the three arguments,
|
||||
* and set the return address register to the place we want
|
||||
* execution to begin.
|
||||
*
|
||||
* Thus, when switchframe_switch does its "j ra", it will
|
||||
* actually jump to mips_threadstart, which will move the
|
||||
* arguments into the right register and jump to
|
||||
* thread_startup().
|
||||
*
|
||||
* Note that this means that when we call switchframe_switch()
|
||||
* in thread_switch(), we may not come back out the same way
|
||||
* in the next thread. (Though we will come back out the same
|
||||
* way when we later come back to the same thread again.)
|
||||
*
|
||||
* This has implications for code at the bottom of
|
||||
* thread_switch, described in thread.c.
|
||||
*/
|
||||
sf->sf_s0 = (uint32_t)entrypoint;
|
||||
sf->sf_s1 = (uint32_t)data1;
|
||||
sf->sf_s2 = (uint32_t)data2;
|
||||
sf->sf_ra = (uint32_t)mips_threadstart;
|
||||
|
||||
/* Set ->t_context, and we're done. */
|
||||
thread->t_context = sf;
|
||||
}
|
52
kern/arch/mips/thread/switchframe.h
Normal file
52
kern/arch/mips/thread/switchframe.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _MIPS_SWITCHFRAME_H_
|
||||
#define _MIPS_SWITCHFRAME_H_
|
||||
|
||||
/*
|
||||
* Structure describing what is saved on the stack during a context switch.
|
||||
*
|
||||
* This must agree with the code in switch.S.
|
||||
*/
|
||||
|
||||
struct switchframe {
|
||||
uint32_t sf_s0;
|
||||
uint32_t sf_s1;
|
||||
uint32_t sf_s2;
|
||||
uint32_t sf_s3;
|
||||
uint32_t sf_s4;
|
||||
uint32_t sf_s5;
|
||||
uint32_t sf_s6;
|
||||
uint32_t sf_s8;
|
||||
uint32_t sf_gp;
|
||||
uint32_t sf_ra;
|
||||
};
|
||||
|
||||
#endif /* _MIPS_SWITCHFRAME_H_ */
|
49
kern/arch/mips/thread/thread_machdep.c
Normal file
49
kern/arch/mips/thread/thread_machdep.c
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Functions for handling struct thread_machdep.
|
||||
*/
|
||||
|
||||
#include <types.h>
|
||||
#include <lib.h>
|
||||
#include <thread.h>
|
||||
#include <threadprivate.h>
|
||||
|
||||
void
|
||||
thread_machdep_init(struct thread_machdep *tm)
|
||||
{
|
||||
tm->tm_badfaultfunc = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
thread_machdep_cleanup(struct thread_machdep *tm)
|
||||
{
|
||||
KASSERT(tm->tm_badfaultfunc == NULL);
|
||||
}
|
68
kern/arch/mips/thread/threadstart.S
Normal file
68
kern/arch/mips/thread/threadstart.S
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Assembler-level thread startup trampoline.
|
||||
*/
|
||||
|
||||
#include <kern/mips/regdefs.h>
|
||||
|
||||
.text
|
||||
.set noreorder
|
||||
|
||||
.globl mips_threadstart
|
||||
.type mips_threadstart,@function
|
||||
.ent mips_threadstart
|
||||
mips_threadstart:
|
||||
|
||||
/*
|
||||
* This code doesn't take normal arguments. It's reached when
|
||||
* switchframe_switch switches to a new thread. switchframe_switch
|
||||
* does "j ra"; ra gets preloaded in switchframe_init to come here.
|
||||
*
|
||||
* Our arguments are in callee-save registers, as follows:
|
||||
*
|
||||
* s0 entrypoint
|
||||
* s1 data1
|
||||
* s2 data2
|
||||
*
|
||||
* We need to rearrange these so as to call the normal C function
|
||||
* thread_startup(void (*entrypoint)(), void *data1, unsigned long data2).
|
||||
*/
|
||||
|
||||
addiu sp, sp, -16 /* make our stack frame */
|
||||
|
||||
move ra, $0 /* clear return addr so we're top of the call stack */
|
||||
|
||||
move a0, s0 /* load arguments and call */
|
||||
move a1, s1
|
||||
j thread_startup
|
||||
move a2, s2 /* (in delay slot) */
|
||||
|
||||
.end mips_threadstart
|
433
kern/arch/mips/vm/dumbvm.c
Normal file
433
kern/arch/mips/vm/dumbvm.c
Normal file
@@ -0,0 +1,433 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <types.h>
|
||||
#include <kern/errno.h>
|
||||
#include <lib.h>
|
||||
#include <spl.h>
|
||||
#include <cpu.h>
|
||||
#include <spinlock.h>
|
||||
#include <proc.h>
|
||||
#include <current.h>
|
||||
#include <mips/tlb.h>
|
||||
#include <addrspace.h>
|
||||
#include <vm.h>
|
||||
|
||||
/*
|
||||
* Dumb MIPS-only "VM system" that is intended to only be just barely
|
||||
* enough to struggle off the ground. You should replace all of this
|
||||
* code while doing the VM assignment. In fact, starting in that
|
||||
* assignment, this file is not included in your kernel!
|
||||
*
|
||||
* NOTE: it's been found over the years that students often begin on
|
||||
* the VM assignment by copying dumbvm.c and trying to improve it.
|
||||
* This is not recommended. dumbvm is (more or less intentionally) not
|
||||
* a good design reference. The first recommendation would be: do not
|
||||
* look at dumbvm at all. The second recommendation would be: if you
|
||||
* do, be sure to review it from the perspective of comparing it to
|
||||
* what a VM system is supposed to do, and understanding what corners
|
||||
* it's cutting (there are many) and why, and more importantly, how.
|
||||
*/
|
||||
|
||||
/* under dumbvm, always have 72k of user stack */
|
||||
/* (this must be > 64K so argument blocks of size ARG_MAX will fit) */
|
||||
#define DUMBVM_STACKPAGES 18
|
||||
|
||||
/*
|
||||
* Wrap ram_stealmem in a spinlock.
|
||||
*/
|
||||
static struct spinlock stealmem_lock = SPINLOCK_INITIALIZER;
|
||||
|
||||
void
|
||||
vm_bootstrap(void)
|
||||
{
|
||||
/* Do nothing. */
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if we're in a context that can sleep. While most of the
|
||||
* operations in dumbvm don't in fact sleep, in a real VM system many
|
||||
* of them would. In those, assert that sleeping is ok. This helps
|
||||
* avoid the situation where syscall-layer code that works ok with
|
||||
* dumbvm starts blowing up during the VM assignment.
|
||||
*/
|
||||
static
|
||||
void
|
||||
dumbvm_can_sleep(void)
|
||||
{
|
||||
if (CURCPU_EXISTS()) {
|
||||
/* must not hold spinlocks */
|
||||
KASSERT(curcpu->c_spinlocks == 0);
|
||||
|
||||
/* must not be in an interrupt handler */
|
||||
KASSERT(curthread->t_in_interrupt == 0);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
paddr_t
|
||||
getppages(unsigned long npages)
|
||||
{
|
||||
paddr_t addr;
|
||||
|
||||
spinlock_acquire(&stealmem_lock);
|
||||
|
||||
addr = ram_stealmem(npages);
|
||||
|
||||
spinlock_release(&stealmem_lock);
|
||||
return addr;
|
||||
}
|
||||
|
||||
/* Allocate/free some kernel-space virtual pages */
|
||||
vaddr_t
|
||||
alloc_kpages(unsigned npages)
|
||||
{
|
||||
paddr_t pa;
|
||||
|
||||
dumbvm_can_sleep();
|
||||
pa = getppages(npages);
|
||||
if (pa==0) {
|
||||
return 0;
|
||||
}
|
||||
return PADDR_TO_KVADDR(pa);
|
||||
}
|
||||
|
||||
void
|
||||
free_kpages(vaddr_t addr)
|
||||
{
|
||||
/* nothing - leak the memory. */
|
||||
|
||||
(void)addr;
|
||||
}
|
||||
|
||||
void
|
||||
vm_tlbshootdown_all(void)
|
||||
{
|
||||
panic("dumbvm tried to do tlb shootdown?!\n");
|
||||
}
|
||||
|
||||
void
|
||||
vm_tlbshootdown(const struct tlbshootdown *ts)
|
||||
{
|
||||
(void)ts;
|
||||
panic("dumbvm tried to do tlb shootdown?!\n");
|
||||
}
|
||||
|
||||
int
|
||||
vm_fault(int faulttype, vaddr_t faultaddress)
|
||||
{
|
||||
vaddr_t vbase1, vtop1, vbase2, vtop2, stackbase, stacktop;
|
||||
paddr_t paddr;
|
||||
int i;
|
||||
uint32_t ehi, elo;
|
||||
struct addrspace *as;
|
||||
int spl;
|
||||
|
||||
faultaddress &= PAGE_FRAME;
|
||||
|
||||
DEBUG(DB_VM, "dumbvm: fault: 0x%x\n", faultaddress);
|
||||
|
||||
switch (faulttype) {
|
||||
case VM_FAULT_READONLY:
|
||||
/* We always create pages read-write, so we can't get this */
|
||||
panic("dumbvm: got VM_FAULT_READONLY\n");
|
||||
case VM_FAULT_READ:
|
||||
case VM_FAULT_WRITE:
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (curproc == NULL) {
|
||||
/*
|
||||
* No process. This is probably a kernel fault early
|
||||
* in boot. Return EFAULT so as to panic instead of
|
||||
* getting into an infinite faulting loop.
|
||||
*/
|
||||
return EFAULT;
|
||||
}
|
||||
|
||||
as = proc_getas();
|
||||
if (as == NULL) {
|
||||
/*
|
||||
* No address space set up. This is probably also a
|
||||
* kernel fault early in boot.
|
||||
*/
|
||||
return EFAULT;
|
||||
}
|
||||
|
||||
/* Assert that the address space has been set up properly. */
|
||||
KASSERT(as->as_vbase1 != 0);
|
||||
KASSERT(as->as_pbase1 != 0);
|
||||
KASSERT(as->as_npages1 != 0);
|
||||
KASSERT(as->as_vbase2 != 0);
|
||||
KASSERT(as->as_pbase2 != 0);
|
||||
KASSERT(as->as_npages2 != 0);
|
||||
KASSERT(as->as_stackpbase != 0);
|
||||
KASSERT((as->as_vbase1 & PAGE_FRAME) == as->as_vbase1);
|
||||
KASSERT((as->as_pbase1 & PAGE_FRAME) == as->as_pbase1);
|
||||
KASSERT((as->as_vbase2 & PAGE_FRAME) == as->as_vbase2);
|
||||
KASSERT((as->as_pbase2 & PAGE_FRAME) == as->as_pbase2);
|
||||
KASSERT((as->as_stackpbase & PAGE_FRAME) == as->as_stackpbase);
|
||||
|
||||
vbase1 = as->as_vbase1;
|
||||
vtop1 = vbase1 + as->as_npages1 * PAGE_SIZE;
|
||||
vbase2 = as->as_vbase2;
|
||||
vtop2 = vbase2 + as->as_npages2 * PAGE_SIZE;
|
||||
stackbase = USERSTACK - DUMBVM_STACKPAGES * PAGE_SIZE;
|
||||
stacktop = USERSTACK;
|
||||
|
||||
if (faultaddress >= vbase1 && faultaddress < vtop1) {
|
||||
paddr = (faultaddress - vbase1) + as->as_pbase1;
|
||||
}
|
||||
else if (faultaddress >= vbase2 && faultaddress < vtop2) {
|
||||
paddr = (faultaddress - vbase2) + as->as_pbase2;
|
||||
}
|
||||
else if (faultaddress >= stackbase && faultaddress < stacktop) {
|
||||
paddr = (faultaddress - stackbase) + as->as_stackpbase;
|
||||
}
|
||||
else {
|
||||
return EFAULT;
|
||||
}
|
||||
|
||||
/* make sure it's page-aligned */
|
||||
KASSERT((paddr & PAGE_FRAME) == paddr);
|
||||
|
||||
/* Disable interrupts on this CPU while frobbing the TLB. */
|
||||
spl = splhigh();
|
||||
|
||||
for (i=0; i<NUM_TLB; i++) {
|
||||
tlb_read(&ehi, &elo, i);
|
||||
if (elo & TLBLO_VALID) {
|
||||
continue;
|
||||
}
|
||||
ehi = faultaddress;
|
||||
elo = paddr | TLBLO_DIRTY | TLBLO_VALID;
|
||||
DEBUG(DB_VM, "dumbvm: 0x%x -> 0x%x\n", faultaddress, paddr);
|
||||
tlb_write(ehi, elo, i);
|
||||
splx(spl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
kprintf("dumbvm: Ran out of TLB entries - cannot handle page fault\n");
|
||||
splx(spl);
|
||||
return EFAULT;
|
||||
}
|
||||
|
||||
struct addrspace *
|
||||
as_create(void)
|
||||
{
|
||||
struct addrspace *as = kmalloc(sizeof(struct addrspace));
|
||||
if (as==NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
as->as_vbase1 = 0;
|
||||
as->as_pbase1 = 0;
|
||||
as->as_npages1 = 0;
|
||||
as->as_vbase2 = 0;
|
||||
as->as_pbase2 = 0;
|
||||
as->as_npages2 = 0;
|
||||
as->as_stackpbase = 0;
|
||||
|
||||
return as;
|
||||
}
|
||||
|
||||
void
|
||||
as_destroy(struct addrspace *as)
|
||||
{
|
||||
dumbvm_can_sleep();
|
||||
kfree(as);
|
||||
}
|
||||
|
||||
void
|
||||
as_activate(void)
|
||||
{
|
||||
int i, spl;
|
||||
struct addrspace *as;
|
||||
|
||||
as = proc_getas();
|
||||
if (as == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Disable interrupts on this CPU while frobbing the TLB. */
|
||||
spl = splhigh();
|
||||
|
||||
for (i=0; i<NUM_TLB; i++) {
|
||||
tlb_write(TLBHI_INVALID(i), TLBLO_INVALID(), i);
|
||||
}
|
||||
|
||||
splx(spl);
|
||||
}
|
||||
|
||||
void
|
||||
as_deactivate(void)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
int
|
||||
as_define_region(struct addrspace *as, vaddr_t vaddr, size_t sz,
|
||||
int readable, int writeable, int executable)
|
||||
{
|
||||
size_t npages;
|
||||
|
||||
dumbvm_can_sleep();
|
||||
|
||||
/* Align the region. First, the base... */
|
||||
sz += vaddr & ~(vaddr_t)PAGE_FRAME;
|
||||
vaddr &= PAGE_FRAME;
|
||||
|
||||
/* ...and now the length. */
|
||||
sz = (sz + PAGE_SIZE - 1) & PAGE_FRAME;
|
||||
|
||||
npages = sz / PAGE_SIZE;
|
||||
|
||||
/* We don't use these - all pages are read-write */
|
||||
(void)readable;
|
||||
(void)writeable;
|
||||
(void)executable;
|
||||
|
||||
if (as->as_vbase1 == 0) {
|
||||
as->as_vbase1 = vaddr;
|
||||
as->as_npages1 = npages;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (as->as_vbase2 == 0) {
|
||||
as->as_vbase2 = vaddr;
|
||||
as->as_npages2 = npages;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Support for more than two regions is not available.
|
||||
*/
|
||||
kprintf("dumbvm: Warning: too many regions\n");
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
as_zero_region(paddr_t paddr, unsigned npages)
|
||||
{
|
||||
bzero((void *)PADDR_TO_KVADDR(paddr), npages * PAGE_SIZE);
|
||||
}
|
||||
|
||||
int
|
||||
as_prepare_load(struct addrspace *as)
|
||||
{
|
||||
KASSERT(as->as_pbase1 == 0);
|
||||
KASSERT(as->as_pbase2 == 0);
|
||||
KASSERT(as->as_stackpbase == 0);
|
||||
|
||||
dumbvm_can_sleep();
|
||||
|
||||
as->as_pbase1 = getppages(as->as_npages1);
|
||||
if (as->as_pbase1 == 0) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
as->as_pbase2 = getppages(as->as_npages2);
|
||||
if (as->as_pbase2 == 0) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
as->as_stackpbase = getppages(DUMBVM_STACKPAGES);
|
||||
if (as->as_stackpbase == 0) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
as_zero_region(as->as_pbase1, as->as_npages1);
|
||||
as_zero_region(as->as_pbase2, as->as_npages2);
|
||||
as_zero_region(as->as_stackpbase, DUMBVM_STACKPAGES);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
as_complete_load(struct addrspace *as)
|
||||
{
|
||||
dumbvm_can_sleep();
|
||||
(void)as;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
as_define_stack(struct addrspace *as, vaddr_t *stackptr)
|
||||
{
|
||||
KASSERT(as->as_stackpbase != 0);
|
||||
|
||||
*stackptr = USERSTACK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
as_copy(struct addrspace *old, struct addrspace **ret)
|
||||
{
|
||||
struct addrspace *new;
|
||||
|
||||
dumbvm_can_sleep();
|
||||
|
||||
new = as_create();
|
||||
if (new==NULL) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
new->as_vbase1 = old->as_vbase1;
|
||||
new->as_npages1 = old->as_npages1;
|
||||
new->as_vbase2 = old->as_vbase2;
|
||||
new->as_npages2 = old->as_npages2;
|
||||
|
||||
/* (Mis)use as_prepare_load to allocate some physical memory. */
|
||||
if (as_prepare_load(new)) {
|
||||
as_destroy(new);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
KASSERT(new->as_pbase1 != 0);
|
||||
KASSERT(new->as_pbase2 != 0);
|
||||
KASSERT(new->as_stackpbase != 0);
|
||||
|
||||
memmove((void *)PADDR_TO_KVADDR(new->as_pbase1),
|
||||
(const void *)PADDR_TO_KVADDR(old->as_pbase1),
|
||||
old->as_npages1*PAGE_SIZE);
|
||||
|
||||
memmove((void *)PADDR_TO_KVADDR(new->as_pbase2),
|
||||
(const void *)PADDR_TO_KVADDR(old->as_pbase2),
|
||||
old->as_npages2*PAGE_SIZE);
|
||||
|
||||
memmove((void *)PADDR_TO_KVADDR(new->as_stackpbase),
|
||||
(const void *)PADDR_TO_KVADDR(old->as_stackpbase),
|
||||
DUMBVM_STACKPAGES*PAGE_SIZE);
|
||||
|
||||
*ret = new;
|
||||
return 0;
|
||||
}
|
153
kern/arch/mips/vm/ram.c
Normal file
153
kern/arch/mips/vm/ram.c
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <types.h>
|
||||
#include <lib.h>
|
||||
#include <vm.h>
|
||||
#include <mainbus.h>
|
||||
|
||||
|
||||
vaddr_t firstfree; /* first free virtual address; set by start.S */
|
||||
|
||||
static paddr_t firstpaddr; /* address of first free physical page */
|
||||
static paddr_t lastpaddr; /* one past end of last free physical page */
|
||||
|
||||
/*
|
||||
* Called very early in system boot to figure out how much physical
|
||||
* RAM is available.
|
||||
*/
|
||||
void
|
||||
ram_bootstrap(void)
|
||||
{
|
||||
size_t ramsize;
|
||||
|
||||
/* Get size of RAM. */
|
||||
ramsize = mainbus_ramsize();
|
||||
|
||||
/*
|
||||
* This is the same as the last physical address, as long as
|
||||
* we have less than 512 megabytes of memory. If we had more,
|
||||
* we wouldn't be able to access it all through kseg0 and
|
||||
* everything would get a lot more complicated. This is not a
|
||||
* case we are going to worry about.
|
||||
*/
|
||||
if (ramsize > 512*1024*1024) {
|
||||
ramsize = 512*1024*1024;
|
||||
}
|
||||
|
||||
lastpaddr = ramsize;
|
||||
|
||||
/*
|
||||
* Get first free virtual address from where start.S saved it.
|
||||
* Convert to physical address.
|
||||
*/
|
||||
firstpaddr = firstfree - MIPS_KSEG0;
|
||||
|
||||
kprintf("%uk physical memory available\n",
|
||||
(lastpaddr-firstpaddr)/1024);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is for allocating physical memory prior to VM
|
||||
* initialization.
|
||||
*
|
||||
* The pages it hands back will not be reported to the VM system when
|
||||
* the VM system calls ram_getsize(). If it's desired to free up these
|
||||
* pages later on after bootup is complete, some mechanism for adding
|
||||
* them to the VM system's page management must be implemented.
|
||||
* Alternatively, one can do enough VM initialization early so that
|
||||
* this function is never needed.
|
||||
*
|
||||
* Note: while the error return value of 0 is a legal physical address,
|
||||
* it's not a legal *allocatable* physical address, because it's the
|
||||
* page with the exception handlers on it.
|
||||
*
|
||||
* This function should not be called once the VM system is initialized,
|
||||
* so it is not synchronized.
|
||||
*/
|
||||
paddr_t
|
||||
ram_stealmem(unsigned long npages)
|
||||
{
|
||||
size_t size;
|
||||
paddr_t paddr;
|
||||
|
||||
size = npages * PAGE_SIZE;
|
||||
|
||||
if (firstpaddr + size > lastpaddr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
paddr = firstpaddr;
|
||||
firstpaddr += size;
|
||||
|
||||
return paddr;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is intended to be called by the VM system when it
|
||||
* initializes in order to find out what memory it has available to
|
||||
* manage. Physical memory begins at physical address 0 and ends with
|
||||
* the address returned by this function. We assume that physical
|
||||
* memory is contiguous. This is not universally true, but is true on
|
||||
* the MIPS platforms we intend to run on.
|
||||
*
|
||||
* lastpaddr is constant once set by ram_bootstrap(), so this function
|
||||
* need not be synchronized.
|
||||
*
|
||||
* It is recommended, however, that this function be used only to
|
||||
* initialize the VM system, after which the VM system should take
|
||||
* charge of knowing what memory exists.
|
||||
*/
|
||||
paddr_t
|
||||
ram_getsize(void)
|
||||
{
|
||||
return lastpaddr;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is intended to be called by the VM system when it
|
||||
* initializes in order to find out what memory it has available to
|
||||
* manage.
|
||||
*
|
||||
* It can only be called once, and once called ram_stealmem() will
|
||||
* no longer work, as that would invalidate the result it returned
|
||||
* and lead to multiple things using the same memory.
|
||||
*
|
||||
* This function should not be called once the VM system is initialized,
|
||||
* so it is not synchronized.
|
||||
*/
|
||||
paddr_t
|
||||
ram_getfirstfree(void)
|
||||
{
|
||||
paddr_t ret;
|
||||
|
||||
ret = firstpaddr;
|
||||
firstpaddr = lastpaddr = 0;
|
||||
return ret;
|
||||
}
|
204
kern/arch/mips/vm/tlb-mips161.S
Normal file
204
kern/arch/mips/vm/tlb-mips161.S
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <kern/mips/regdefs.h>
|
||||
#include <mips/specialreg.h>
|
||||
|
||||
/*
|
||||
* TLB handling for the MIPS-161.
|
||||
*
|
||||
* The MIPS-161 uses the simpler MIPS-1 (r2000/r3000) TLB rather
|
||||
* than the paired-page TLB of later MIPS models.
|
||||
*
|
||||
* However, we handle MIPS32 pipeline hazards. If you want to run on
|
||||
* a real MIPS-1, change the ssnops to plain nops and check where and
|
||||
* how many you need in the matching processor docs.
|
||||
*
|
||||
* (ssnop means "superscalar nop"; it exists because the pipeline
|
||||
* hazards require a fixed number of cycles, and a superscalar CPU can
|
||||
* potentially issue arbitrarily many nops in one cycle.)
|
||||
*/
|
||||
|
||||
.text
|
||||
.set noreorder
|
||||
.set mips32 /* so we can use ssnop */
|
||||
|
||||
/*
|
||||
* tlb_random: use the "tlbwr" instruction to write a TLB entry
|
||||
* into a (very pseudo-) random slot in the TLB.
|
||||
*
|
||||
* Pipeline hazard: must wait between setting entryhi/lo and
|
||||
* doing the tlbwr. Use two cycles; some processors may vary.
|
||||
*/
|
||||
.globl tlb_random
|
||||
.type tlb_random,@function
|
||||
.ent tlb_random
|
||||
tlb_random:
|
||||
mtc0 a0, c0_entryhi /* store the passed entry into the */
|
||||
mtc0 a1, c0_entrylo /* tlb entry registers */
|
||||
ssnop /* wait for pipeline hazard */
|
||||
ssnop
|
||||
tlbwr /* do it */
|
||||
j ra
|
||||
nop
|
||||
.end tlb_random
|
||||
|
||||
/*
|
||||
* tlb_write: use the "tlbwi" instruction to write a TLB entry
|
||||
* into a selected slot in the TLB.
|
||||
*
|
||||
* Pipeline hazard: must wait between setting entryhi/lo and
|
||||
* doing the tlbwi. Use two cycles; some processors may vary.
|
||||
*/
|
||||
.text
|
||||
.globl tlb_write
|
||||
.type tlb_write,@function
|
||||
.ent tlb_write
|
||||
tlb_write:
|
||||
mtc0 a0, c0_entryhi /* store the passed entry into the */
|
||||
mtc0 a1, c0_entrylo /* tlb entry registers */
|
||||
sll t0, a2, CIN_INDEXSHIFT /* shift the passed index into place */
|
||||
mtc0 t0, c0_index /* store the shifted index into the index register */
|
||||
ssnop /* wait for pipeline hazard */
|
||||
ssnop
|
||||
tlbwi /* do it */
|
||||
j ra
|
||||
nop
|
||||
.end tlb_write
|
||||
|
||||
/*
|
||||
* tlb_read: use the "tlbr" instruction to read a TLB entry
|
||||
* from a selected slot in the TLB.
|
||||
*
|
||||
* Pipeline hazard: must wait between setting c0_index and
|
||||
* doing the tlbr. Use two cycles; some processors may vary.
|
||||
* Similarly, three more cycles before reading c0_entryhi/lo.
|
||||
*/
|
||||
.text
|
||||
.globl tlb_read
|
||||
.type tlb_read,@function
|
||||
.ent tlb_read
|
||||
tlb_read:
|
||||
sll t0, a2, CIN_INDEXSHIFT /* shift the passed index into place */
|
||||
mtc0 t0, c0_index /* store the shifted index into the index register */
|
||||
ssnop /* wait for pipeline hazard */
|
||||
ssnop
|
||||
tlbr /* do it */
|
||||
ssnop /* wait for pipeline hazard */
|
||||
ssnop
|
||||
ssnop
|
||||
mfc0 t0, c0_entryhi /* get the tlb entry out of the */
|
||||
mfc0 t1, c0_entrylo /* tlb entry registers */
|
||||
sw t0, 0(a0) /* store through the passed pointer */
|
||||
j ra
|
||||
sw t1, 0(a1) /* store (in delay slot) */
|
||||
.end tlb_read
|
||||
|
||||
/*
|
||||
* tlb_probe: use the "tlbp" instruction to find the index in the
|
||||
* TLB of a TLB entry matching the relevant parts of the one supplied.
|
||||
*
|
||||
* Pipeline hazard: must wait between setting c0_entryhi/lo and
|
||||
* doing the tlbp. Use two cycles; some processors may vary.
|
||||
* Similarly, two more cycles before reading c0_index.
|
||||
*/
|
||||
.text
|
||||
.globl tlb_probe
|
||||
.type tlb_probe,@function
|
||||
.ent tlb_probe
|
||||
tlb_probe:
|
||||
mtc0 a0, c0_entryhi /* store the passed entry into the */
|
||||
mtc0 a1, c0_entrylo /* tlb entry registers */
|
||||
ssnop /* wait for pipeline hazard */
|
||||
ssnop
|
||||
tlbp /* do it */
|
||||
ssnop /* wait for pipeline hazard */
|
||||
ssnop
|
||||
mfc0 t0, c0_index /* fetch the index back in t0 */
|
||||
|
||||
/*
|
||||
* If the high bit (CIN_P) of c0_index is set, the probe failed.
|
||||
* The high bit is not set <--> c0_index (now in t0) >= 0.
|
||||
*/
|
||||
|
||||
bgez t0, 1f /* did probe succeed? if so, skip forward */
|
||||
nop /* delay slot */
|
||||
addi v0, z0, -1 /* set return value to -1 to indicate failure */
|
||||
j ra /* done */
|
||||
nop /* delay slot */
|
||||
|
||||
1:
|
||||
/* succeeded - get the index field from the index register value */
|
||||
andi t1, t0, CIN_INDEX /* mask off the field */
|
||||
j ra /* done */
|
||||
sra v0, t1, CIN_INDEXSHIFT /* shift it (in delay slot) */
|
||||
.end tlb_probe
|
||||
|
||||
|
||||
/*
|
||||
* tlb_reset
|
||||
*
|
||||
* Initialize the TLB. At processor startup, the TLB state is completely
|
||||
* undefined. So be sure to avoid creating any duplicates. Also make sure
|
||||
* that the initialization entries don't duplicate the INVALID entries
|
||||
* defined in tlb.h. (This way you can write the invalid entries in
|
||||
* without having to use tlbp to find out if they're going to cause dups.)
|
||||
*
|
||||
* This function is not defined in tlb.h because it's only called from
|
||||
* start.S.
|
||||
*
|
||||
* Pipeline hazards are as above.
|
||||
*/
|
||||
.text
|
||||
.globl tlb_reset
|
||||
.type tlb_reset,@function
|
||||
.ent tlb_reset
|
||||
tlb_reset:
|
||||
li t0, 0 /* t0 <- tlb index number (shifted) */
|
||||
li t1, 0x81000000 /* t1 <- tlb reset vaddr */
|
||||
1:
|
||||
mtc0 $0, c0_entrylo /* set up proposed tlb entry for reset */
|
||||
mtc0 t1, c0_entryhi
|
||||
ssnop /* wait for pipeline hazard */
|
||||
ssnop
|
||||
tlbp /* check if it already exists */
|
||||
ssnop /* wait for pipeline hazard */
|
||||
ssnop
|
||||
mfc0 t2, c0_index
|
||||
bgez t2, 1b /* if it does, loop back */
|
||||
addiu t1, t1, 0x1000 /* next vaddr (in delay slot) */
|
||||
mtc0 t0, c0_index /* doesn't exist, set index to write to */
|
||||
ssnop /* wait for pipeline hazard */
|
||||
ssnop
|
||||
addiu t0, t0, 0x100 /* next tlb index (shifted) */
|
||||
bne t0, 0x4000, 1b /* if it's not the last tlb index, loop */
|
||||
tlbwi /* write tlb entry (in delay slot) */
|
||||
j ra /* done */
|
||||
nop /* delay slot */
|
||||
.end tlb_reset
|
Reference in New Issue
Block a user