initial commit

This commit is contained in:
minhtrannhat 2025-03-01 00:01:05 -05:00
commit 8654300ef4
Signed by: minhtrannhat
GPG Key ID: E13CFA85C53F8062
725 changed files with 94011 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
kern/compile/
build/

1986
CHANGES Normal file

File diff suppressed because it is too large Load Diff

72
Makefile Normal file
View File

@ -0,0 +1,72 @@
#
# Toplevel makefile for OS/161.
#
#
# Main rules:
# all (default): depend and compile system; install into staging area
# rebuild: likewise, but start with a clean slate.
# fullrebuild: likewise, but start with a very clean slate.
#
# What all does, in order:
# tools: depend and compile the tools used in build.
# includes: install header files.
# build: depend and compile the system.
#
# Other targets:
# depend: just update make dependency information.
# tags: generate/regenerate "tags" files.
# install: install into $(OSTREE).
# clean: remove generated files.
# distclean: remove all generated files.
#
TOP=.
.include "$(TOP)/mk/os161.config.mk"
all:; # make this first
MKDIRS=$(OSTREE)
.include "$(TOP)/mk/os161.mkdirs.mk"
all: tools .WAIT includes .WAIT build
rebuild:
$(MAKE) clean
$(MAKE) all
fullrebuild:
$(MAKE) distclean
$(MAKE) all
# currently no tools required, hence no tools/ dir or work to do
tools:
@true
build:
(cd userland && $(MAKE) build)
(cd man && $(MAKE) install-staging)
(cd testscripts && $(MAKE) build)
includes tags depend:
(cd kern && $(MAKE) $@)
(cd userland && $(MAKE) $@)
clean:
(cd kern && $(MAKE) $@)
(cd userland && $(MAKE) $@)
rm -rf $(INSTALLTOP)
distclean: clean
rm -rf $(WORKDIR)
install: $(OSTREE)
(cd $(INSTALLTOP) && tar -cf - .) | (cd $(OSTREE) && tar -xvf -)
.PHONY: all rebuild fullrebuild tools build includes tags depend
.PHONY: clean distclean
# old BSD name, same as distclean
cleandir: distclean
.PHONY: cleandir

View File

@ -0,0 +1,7 @@
These are support functions needed by gcc to perform operations on
64-bit integer types on 32-bit machines. The names are meaningful to
the gcc back end. The term "millicode" is sometimes used to describe
such compiler support code.
This code was taken from NetBSD's src/common/lib/libc/quad, and
polished some for OS/161.

View File

@ -0,0 +1,56 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
*
* 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 REGENTS 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 REGENTS 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.
*
* From:
* @(#)adddi3.c 8.1 (Berkeley) 6/4/93
* NetBSD: adddi3.c,v 1.1 2005/12/20 19:28:51 christos Exp
*/
#include "longlong.h"
/*
* Add two long longs. This is trivial since a one-bit carry from a
* single unsigned int addition x+y occurs if and only if the sum x+y
* is less than either x or y (the choice to compare with x or y is
* arbitrary).
*/
long long
__adddi3(long long a, long long b)
{
union uu aa, bb, sum;
aa.ll = a;
bb.ll = b;
sum.ui[L] = aa.ui[L] + bb.ui[L];
sum.ui[H] = aa.ui[H] + bb.ui[H] + (sum.ui[L] < bb.ui[L]);
return (sum.ll);
}

View File

@ -0,0 +1,53 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
*
* 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 REGENTS 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 REGENTS 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.
*
* From:
* @(#)anddi3.c 8.1 (Berkeley) 6/4/93
* NetBSD: anddi3.c,v 1.1 2005/12/20 19:28:51 christos Exp
*/
#include "longlong.h"
/*
* Return a & b, in long long.
*/
long long
__anddi3(long long a, long long b)
{
union uu aa, bb;
aa.ll = a;
bb.ll = b;
aa.ui[0] &= bb.ui[0];
aa.ui[1] &= bb.ui[1];
return (aa.ll);
}

View File

@ -0,0 +1,61 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
*
* 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 REGENTS 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 REGENTS 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.
*
* From:
* @(#)ashldi3.c 8.1 (Berkeley) 6/4/93
* NetBSD: ashldi3.c,v 1.1 2005/12/20 19:28:51 christos Exp
*/
#include "longlong.h"
/*
* Shift a (signed) long long value left (arithmetic shift left).
* This is the same as logical shift left!
*/
long long
__ashldi3(long long a, unsigned int shift)
{
union uu aa;
if (shift == 0)
return(a);
aa.ll = a;
if (shift >= INT_BITS) {
aa.ui[H] = aa.ui[L] << (shift - INT_BITS);
aa.ui[L] = 0;
} else {
aa.ui[H] = (aa.ui[H] << shift) |
(aa.ui[L] >> (INT_BITS - shift));
aa.ui[L] <<= shift;
}
return (aa.ll);
}

View File

@ -0,0 +1,73 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
*
* 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 REGENTS 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 REGENTS 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.
*
* From:
* @(#)ashrdi3.c 8.1 (Berkeley) 6/4/93
* NetBSD: ashrdi3.c,v 1.1 2005/12/20 19:28:51 christos Exp
*/
#include "longlong.h"
/*
* Shift a (signed) long long value right (arithmetic shift right).
*/
long long
__ashrdi3(long long a, unsigned int shift)
{
union uu aa;
if (shift == 0)
return(a);
aa.ll = a;
if (shift >= INT_BITS) {
int s;
/*
* Smear bits rightward using the machine's right-shift
* method, whether that is sign extension or zero fill,
* to get the `sign word' s. Note that shifting by
* INT_BITS is undefined, so we shift (INT_BITS-1),
* then 1 more, to get our answer.
*/
/* LINTED inherits machine dependency */
s = (aa.si[H] >> (INT_BITS - 1)) >> 1;
/* LINTED inherits machine dependency*/
aa.ui[L] = aa.si[H] >> (shift - INT_BITS);
aa.ui[H] = s;
} else {
aa.ui[L] = (aa.ui[L] >> shift) |
(aa.ui[H] << (INT_BITS - shift));
/* LINTED inherits machine dependency */
aa.si[H] >>= shift;
}
return (aa.ll);
}

View File

@ -0,0 +1,54 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
*
* 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 REGENTS 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 REGENTS 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.
*
* From:
* @(#)cmpdi2.c 8.1 (Berkeley) 6/4/93
* NetBSD: cmpdi2.c,v 1.1 2005/12/20 19:28:51 christos Exp
*/
#include "longlong.h"
/*
* Return 0, 1, or 2 as a <, =, > b respectively.
* Both a and b are considered signed---which means only the high word is
* signed.
*/
int
__cmpdi2(long long a, long long b)
{
union uu aa, bb;
aa.ll = a;
bb.ll = b;
return (aa.si[H] < bb.si[H] ? 0 : aa.si[H] > bb.si[H] ? 2 :
aa.ui[L] < bb.ui[L] ? 0 : aa.ui[L] > bb.ui[L] ? 2 : 1);
}

View File

@ -0,0 +1,62 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
*
* 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 REGENTS 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 REGENTS 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.
*
* From:
* @(#)divdi3.c 8.1 (Berkeley) 6/4/93
* NetBSD: divdi3.c,v 1.1 2005/12/20 19:28:51 christos Exp
*/
#include "longlong.h"
/*
* Divide two signed long longs.
* ??? if -1/2 should produce -1 on this machine, this code is wrong
*/
long long
__divdi3(long long a, long long b)
{
unsigned long long ua, ub, uq;
int neg = 0;
ua = a;
ub = b;
if (a < 0)
ua = -ua, neg ^= 1;
if (b < 0)
ub = -ub, neg ^= 1;
uq = __qdivrem(ua, ub, NULL);
if (neg)
uq = - uq;
return uq;
}

View File

@ -0,0 +1,53 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
*
* 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 REGENTS 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 REGENTS 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.
*
* From:
* @(#)iordi3.c 8.1 (Berkeley) 6/4/93
* NetBSD: iordi3.c,v 1.1 2005/12/20 19:28:51 christos Exp
*/
#include "longlong.h"
/*
* Return a | b, in long long.
*/
long long
__iordi3(long long a, long long b)
{
union uu aa, bb;
aa.ll = a;
bb.ll = b;
aa.ui[0] |= bb.ui[0];
aa.ui[1] |= bb.ui[1];
return (aa.ll);
}

View File

@ -0,0 +1,144 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
*
* 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 REGENTS 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 REGENTS 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.
*
* From:
* @(#)quad.h 8.1 (Berkeley) 6/4/93
* NetBSD: quad.h,v 1.1 2005/12/20 20:29:40 christos Exp
*/
/*
* Long long arithmetic.
*
* This library makes the following assumptions:
*
* - The type long long exists.
*
* - A long long variable is exactly twice as long as `int'.
*
* - The machine's arithmetic is two's complement.
*
* This library can provide 128-bit arithmetic on a machine with
* 128-bit long longs and 64-bit ints, for instance, or 96-bit
* arithmetic on machines with 48-bit ints.
*
* The names are built into gcc.
*/
#if defined(_KERNEL)
#include <types.h>
#include <endian.h>
#else
#include <sys/types.h>
#include <sys/endian.h>
#endif
#include <limits.h>
/*
* Depending on the desired operation, we view a `long long' in
* one or more of the following formats.
*/
union uu {
long long ll; /* as a (signed) long long */
unsigned long long ull; /* as an unsigned long long */
int si[2]; /* as two (signed) ints */
unsigned int ui[2]; /* as two unsigned ints */
};
/*
* Define high and low parts of a long long.
*/
#if _BYTE_ORDER == _LITTLE_ENDIAN
#define H 1
#define L 0
#endif
#if _BYTE_ORDER == _BIG_ENDIAN
#define H 0
#define L 1
#endif
/*
* Total number of bits in a long long and in the pieces that make it up.
* These are used for shifting, and also below for halfword extraction
* and assembly.
*/
#define LONGLONG_BITS (sizeof(long long) * CHAR_BIT)
#define INT_BITS (sizeof(int) * CHAR_BIT)
#define HALF_BITS (sizeof(int) * CHAR_BIT / 2)
/*
* Extract high and low shortwords from longword, and move low shortword of
* longword to upper half of long, i.e., produce the upper longword of
* ((long long)(x) << (number_of_bits_in_int/2)).
* [`x' must actually be unsigned int.]
*
* These are used in the multiply code, to split a longword into upper
* and lower halves, and to reassemble a product as a long long, shifted
* left (sizeof(int)*CHAR_BIT/2).
*/
#define HHALF(x) ((unsigned int)(x) >> HALF_BITS)
#define LHALF(x) ((unsigned int)(x) & (((int)1 << HALF_BITS) - 1))
#define LHUP(x) ((unsigned int)(x) << HALF_BITS)
long long __adddi3 ( long long, long long);
long long __anddi3 ( long long, long long);
long long __ashldi3 ( long long, unsigned int);
long long __ashrdi3 ( long long, unsigned int);
int __cmpdi2 ( long long, long long);
long long __divdi3 ( long long, long long);
long long __iordi3 ( long long, long long);
long long __lshldi3 ( long long, unsigned int);
long long __lshrdi3 ( long long, unsigned int);
long long __moddi3 ( long long, long long);
long long __muldi3 ( long long, long long);
long long __negdi2 ( long long);
long long __one_cmpldi2 ( long long);
long long __subdi3 ( long long, long long);
int __ucmpdi2 (unsigned long long, unsigned long long);
unsigned long long __udivdi3 (unsigned long long, unsigned long long);
unsigned long long __umoddi3 (unsigned long long, unsigned long long);
long long __xordi3 ( long long, long long);
#ifndef _KERNEL
long long __fixdfdi (double);
long long __fixsfdi (float);
unsigned long long __fixunsdfdi (double);
unsigned long long __fixunssfdi (float);
double __floatdidf (long long);
float __floatdisf (long long);
double __floatunsdidf(unsigned long long);
#endif
unsigned long long __qdivrem (unsigned long long, unsigned long long,
unsigned long long *);

View File

@ -0,0 +1,61 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
*
* 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 REGENTS 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 REGENTS 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.
*
* From:
* @(#)lshldi3.c 8.1 (Berkeley) 6/4/93
* NetBSD: lshldi3.c,v 1.1 2005/12/20 19:28:51 christos Exp
*/
#include "longlong.h"
/*
* Shift an (unsigned) long long value left (logical shift left).
* This is the same as arithmetic shift left!
*/
long long
__lshldi3(long long a, unsigned int shift)
{
union uu aa;
if (shift == 0)
return(a);
aa.ll = a;
if (shift >= INT_BITS) {
aa.ui[H] = aa.ui[L] << (shift - INT_BITS);
aa.ui[L] = 0;
} else {
aa.ui[H] = (aa.ui[H] << shift) |
(aa.ui[L] >> (INT_BITS - shift));
aa.ui[L] <<= shift;
}
return (aa.ll);
}

View File

@ -0,0 +1,60 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
*
* 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 REGENTS 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 REGENTS 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.
*
* From:
* @(#)lshrdi3.c 8.1 (Berkeley) 6/4/93
* $NetBSD: lshrdi3.c,v 1.1 2005/12/20 19:28:51 christos Exp
*/
#include "longlong.h"
/*
* Shift an (unsigned) long long value right (logical shift right).
*/
long long
__lshrdi3(long long a, unsigned int shift)
{
union uu aa;
if (shift == 0)
return(a);
aa.ll = a;
if (shift >= INT_BITS) {
aa.ui[L] = aa.ui[H] >> (shift - INT_BITS);
aa.ui[H] = 0;
} else {
aa.ui[L] = (aa.ui[L] >> shift) |
(aa.ui[H] << (INT_BITS - shift));
aa.ui[H] >>= shift;
}
return (aa.ll);
}

View File

@ -0,0 +1,62 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
*
* 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 REGENTS 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 REGENTS 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.
*
* From:
* @(#)moddi3.c 8.1 (Berkeley) 6/4/93
* NetBSD: moddi3.c,v 1.1 2005/12/20 19:28:51 christos Exp
*/
#include "longlong.h"
/*
* Return remainder after dividing two signed long longs.
*
* XXX we assume a % b < 0 iff a < 0, but this is actually machine-dependent.
*/
long long
__moddi3(long long a, long long b)
{
unsigned long long ua, ub, ur;
int neg = 0;
ua = a;
ub = b;
if (a < 0)
ua = -ua, neg ^= 1;
if (b < 0)
ub = -ub;
(void)__qdivrem(ua, ub, &ur);
if (neg)
ur = -ur;
return (ur);
}

View File

@ -0,0 +1,241 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
*
* 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 REGENTS 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 REGENTS 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.
*
* From:
* @(#)muldi3.c 8.1 (Berkeley) 6/4/93
* NetBSD: muldi3.c,v 1.1 2005/12/20 19:28:51 christos Exp
*/
#include "longlong.h"
/*
* Multiply two long longs.
*
* Our algorithm is based on the following. Split incoming long long
* values u and v (where u,v >= 0) into
*
* u = 2^n u1 * u0 (n = number of bits in `unsigned int', usu. 32)
*
* and
*
* v = 2^n v1 * v0
*
* Then
*
* uv = 2^2n u1 v1 + 2^n u1 v0 + 2^n v1 u0 + u0 v0
* = 2^2n u1 v1 + 2^n (u1 v0 + v1 u0) + u0 v0
*
* Now add 2^n u1 v1 to the first term and subtract it from the middle,
* and add 2^n u0 v0 to the last term and subtract it from the middle.
* This gives:
*
* uv = (2^2n + 2^n) (u1 v1) +
* (2^n) (u1 v0 - u1 v1 + u0 v1 - u0 v0) +
* (2^n + 1) (u0 v0)
*
* Factoring the middle a bit gives us:
*
* uv = (2^2n + 2^n) (u1 v1) + [u1v1 = high]
* (2^n) (u1 - u0) (v0 - v1) + [(u1-u0)... = mid]
* (2^n + 1) (u0 v0) [u0v0 = low]
*
* The terms (u1 v1), (u1 - u0) (v0 - v1), and (u0 v0) can all be done
* in just half the precision of the original. (Note that either or both
* of (u1 - u0) or (v0 - v1) may be negative.)
*
* This algorithm is from Knuth vol. 2 (2nd ed), section 4.3.3, p. 278.
*
* Since C does not give us a `int * int = long long' operator, we split
* our input long longs into two ints, then split the two ints into two
* shorts. We can then calculate `short * short = int' in native
* arithmetic.
*
* Our product should, strictly speaking, be a `long long long', with
* 128 bits, but we are going to discard the upper 64. In other words,
* we are not interested in uv, but rather in (uv mod 2^2n). This
* makes some of the terms above vanish, and we get:
*
* (2^n)(high) + (2^n)(mid) + (2^n + 1)(low)
*
* or
*
* (2^n)(high + mid + low) + low
*
* Furthermore, `high' and `mid' can be computed mod 2^n, as any factor
* of 2^n in either one will also vanish. Only `low' need be computed
* mod 2^2n, and only because of the final term above.
*/
static long long __lmulq(unsigned int, unsigned int);
long long
__muldi3(long long a, long long b)
{
union uu u, v, low, prod;
unsigned int high, mid, udiff, vdiff;
int negall, negmid;
#define u1 u.ui[H]
#define u0 u.ui[L]
#define v1 v.ui[H]
#define v0 v.ui[L]
/*
* Get u and v such that u, v >= 0. When this is finished,
* u1, u0, v1, and v0 will be directly accessible through the
* int fields.
*/
if (a >= 0)
u.ll = a, negall = 0;
else
u.ll = -a, negall = 1;
if (b >= 0)
v.ll = b;
else
v.ll = -b, negall ^= 1;
if (u1 == 0 && v1 == 0) {
/*
* An (I hope) important optimization occurs when u1 and v1
* are both 0. This should be common since most numbers
* are small. Here the product is just u0*v0.
*/
prod.ll = __lmulq(u0, v0);
} else {
/*
* Compute the three intermediate products, remembering
* whether the middle term is negative. We can discard
* any upper bits in high and mid, so we can use native
* unsigned int * unsigned int => unsigned int arithmetic.
*/
low.ll = __lmulq(u0, v0);
if (u1 >= u0)
negmid = 0, udiff = u1 - u0;
else
negmid = 1, udiff = u0 - u1;
if (v0 >= v1)
vdiff = v0 - v1;
else
vdiff = v1 - v0, negmid ^= 1;
mid = udiff * vdiff;
high = u1 * v1;
/*
* Assemble the final product.
*/
prod.ui[H] = high + (negmid ? -mid : mid) + low.ui[L] +
low.ui[H];
prod.ui[L] = low.ui[L];
}
return (negall ? -prod.ll : prod.ll);
#undef u1
#undef u0
#undef v1
#undef v0
}
/*
* Multiply two 2N-bit ints to produce a 4N-bit long long, where N is
* half the number of bits in an int (whatever that is---the code
* below does not care as long as the header file does its part of the
* bargain---but typically N==16).
*
* We use the same algorithm from Knuth, but this time the modulo refinement
* does not apply. On the other hand, since N is half the size of an int,
* we can get away with native multiplication---none of our input terms
* exceeds (UINT_MAX >> 1).
*
* Note that, for unsigned int l, the quad-precision (long long) result
*
* l << N
*
* splits into high and low ints as HHALF(l) and LHUP(l) respectively.
*/
static long long
__lmulq(unsigned int u, unsigned int v)
{
unsigned int u1, u0, v1, v0, udiff, vdiff, high, mid, low;
unsigned int prodh, prodl, was;
union uu prod;
int neg;
u1 = HHALF(u);
u0 = LHALF(u);
v1 = HHALF(v);
v0 = LHALF(v);
low = u0 * v0;
/* This is the same small-number optimization as before. */
if (u1 == 0 && v1 == 0)
return (low);
if (u1 >= u0)
udiff = u1 - u0, neg = 0;
else
udiff = u0 - u1, neg = 1;
if (v0 >= v1)
vdiff = v0 - v1;
else
vdiff = v1 - v0, neg ^= 1;
mid = udiff * vdiff;
high = u1 * v1;
/* prod = (high << 2N) + (high << N); */
prodh = high + HHALF(high);
prodl = LHUP(high);
/* if (neg) prod -= mid << N; else prod += mid << N; */
if (neg) {
was = prodl;
prodl -= LHUP(mid);
prodh -= HHALF(mid) + (prodl > was);
} else {
was = prodl;
prodl += LHUP(mid);
prodh += HHALF(mid) + (prodl < was);
}
/* prod += low << N */
was = prodl;
prodl += LHUP(low);
prodh += HHALF(low) + (prodl < was);
/* ... + low; */
if ((prodl += low) < low)
prodh++;
/* return 4N-bit product */
prod.ui[H] = prodh;
prod.ui[L] = prodl;
return (prod.ll);
}

View File

@ -0,0 +1,52 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
*
* 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 REGENTS 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 REGENTS 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.
*
* From:
* @(#)negdi2.c 8.1 (Berkeley) 6/4/93
* NetBSD: negdi2.c,v 1.1 2005/12/20 19:28:51 christos Exp
*/
#include "longlong.h"
/*
* Return -a (or, equivalently, 0 - a), in long long. See subdi3.c.
*/
long long
__negdi2(long long a)
{
union uu aa, res;
aa.ll = a;
res.ui[L] = -aa.ui[L];
res.ui[H] = -aa.ui[H] - (res.ui[L] > 0);
return (res.ll);
}

View File

@ -0,0 +1,53 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
*
* 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 REGENTS 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 REGENTS 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.
*
* From:
* @(#)notdi2.c 8.1 (Berkeley) 6/4/93
* NetBSD: notdi2.c,v 1.1 2005/12/20 19:28:51 christos Exp
*/
#include "longlong.h"
/*
* Return ~a. For some reason gcc calls this `one's complement' rather
* than `not'.
*/
long long
__one_cmpldi2(long long a)
{
union uu aa;
aa.ll = a;
aa.ui[0] = ~aa.ui[0];
aa.ui[1] = ~aa.ui[1];
return (aa.ll);
}

View File

@ -0,0 +1,279 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
*
* 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 REGENTS 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 REGENTS 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.
*
* From:
* @(#)qdivrem.c 8.1 (Berkeley) 6/4/93
* NetBSD: qdivrem.c,v 1.1 2005/12/20 19:28:51 christos Exp
*/
/*
* Multiprecision divide. This algorithm is from Knuth vol. 2 (2nd ed),
* section 4.3.1, pp. 257--259.
*/
#include "longlong.h"
#define B ((int)1 << HALF_BITS) /* digit base */
/* Combine two `digits' to make a single two-digit number. */
#define COMBINE(a, b) (((unsigned int)(a) << HALF_BITS) | (b))
/* select a type for digits in base B: use unsigned short if they fit */
#if UINT_MAX == 0xffffffffU && USHRT_MAX >= 0xffff
typedef unsigned short digit;
#else
typedef unsigned int digit;
#endif
static void shl(digit *p, int len, int sh);
/*
* __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to u%v.
*
* We do this in base 2-sup-HALF_BITS, so that all intermediate
* products fit within unsigned int. As a consequence, the maximum
* length dividend and divisor are 4 `digits' in this base (they are
* shorter if they have leading zeros).
*/
unsigned long long
__qdivrem(unsigned long long ull, unsigned long long vll,
unsigned long long *arq)
{
union uu tmp;
digit *u, *v, *q;
digit v1, v2;
unsigned int qhat, rhat, t;
int m, n, d, j, i;
digit uspace[5], vspace[5], qspace[5];
/*
* Take care of special cases: divide by zero, and u < v.
*/
if (vll == 0) {
/* divide by zero. */
static volatile const unsigned int zero = 0;
tmp.ui[H] = tmp.ui[L] = 1 / zero;
if (arq)
*arq = ull;
return (tmp.ll);
}
if (ull < vll) {
if (arq)
*arq = ull;
return (0);
}
u = &uspace[0];
v = &vspace[0];
q = &qspace[0];
/*
* Break dividend and divisor into digits in base B, then
* count leading zeros to determine m and n. When done, we
* will have:
* u = (u[1]u[2]...u[m+n]) sub B
* v = (v[1]v[2]...v[n]) sub B
* v[1] != 0
* 1 < n <= 4 (if n = 1, we use a different division algorithm)
* m >= 0 (otherwise u < v, which we already checked)
* m + n = 4
* and thus
* m = 4 - n <= 2
*/
tmp.ull = ull;
u[0] = 0;
u[1] = (digit)HHALF(tmp.ui[H]);
u[2] = (digit)LHALF(tmp.ui[H]);
u[3] = (digit)HHALF(tmp.ui[L]);
u[4] = (digit)LHALF(tmp.ui[L]);
tmp.ull = vll;
v[1] = (digit)HHALF(tmp.ui[H]);
v[2] = (digit)LHALF(tmp.ui[H]);
v[3] = (digit)HHALF(tmp.ui[L]);
v[4] = (digit)LHALF(tmp.ui[L]);
for (n = 4; v[1] == 0; v++) {
if (--n == 1) {
unsigned int rbj; /* r*B+u[j] (not root boy jim) */
digit q1, q2, q3, q4;
/*
* Change of plan, per exercise 16.
* r = 0;
* for j = 1..4:
* q[j] = floor((r*B + u[j]) / v),
* r = (r*B + u[j]) % v;
* We unroll this completely here.
*/
t = v[2]; /* nonzero, by definition */
q1 = (digit)(u[1] / t);
rbj = COMBINE(u[1] % t, u[2]);
q2 = (digit)(rbj / t);
rbj = COMBINE(rbj % t, u[3]);
q3 = (digit)(rbj / t);
rbj = COMBINE(rbj % t, u[4]);
q4 = (digit)(rbj / t);
if (arq)
*arq = rbj % t;
tmp.ui[H] = COMBINE(q1, q2);
tmp.ui[L] = COMBINE(q3, q4);
return (tmp.ll);
}
}
/*
* By adjusting q once we determine m, we can guarantee that
* there is a complete four-digit quotient at &qspace[1] when
* we finally stop.
*/
for (m = 4 - n; u[1] == 0; u++)
m--;
for (i = 4 - m; --i >= 0;)
q[i] = 0;
q += 4 - m;
/*
* Here we run Program D, translated from MIX to C and acquiring
* a few minor changes.
*
* D1: choose multiplier 1 << d to ensure v[1] >= B/2.
*/
d = 0;
for (t = v[1]; t < B / 2; t <<= 1)
d++;
if (d > 0) {
shl(&u[0], m + n, d); /* u <<= d */
shl(&v[1], n - 1, d); /* v <<= d */
}
/*
* D2: j = 0.
*/
j = 0;
v1 = v[1]; /* for D3 -- note that v[1..n] are constant */
v2 = v[2]; /* for D3 */
do {
digit uj0, uj1, uj2;
/*
* D3: Calculate qhat (\^q, in TeX notation).
* Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and
* let rhat = (u[j]*B + u[j+1]) mod v[1].
* While rhat < B and v[2]*qhat > rhat*B+u[j+2],
* decrement qhat and increase rhat correspondingly.
* Note that if rhat >= B, v[2]*qhat < rhat*B.
*/
uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */
uj1 = u[j + 1]; /* for D3 only */
uj2 = u[j + 2]; /* for D3 only */
if (uj0 == v1) {
qhat = B;
rhat = uj1;
goto qhat_too_big;
} else {
unsigned int nn = COMBINE(uj0, uj1);
qhat = nn / v1;
rhat = nn % v1;
}
while (v2 * qhat > COMBINE(rhat, uj2)) {
qhat_too_big:
qhat--;
if ((rhat += v1) >= B)
break;
}
/*
* D4: Multiply and subtract.
* The variable `t' holds any borrows across the loop.
* We split this up so that we do not require v[0] = 0,
* and to eliminate a final special case.
*/
for (t = 0, i = n; i > 0; i--) {
t = u[i + j] - v[i] * qhat - t;
u[i + j] = (digit)LHALF(t);
t = (B - HHALF(t)) & (B - 1);
}
t = u[j] - t;
u[j] = (digit)LHALF(t);
/*
* D5: test remainder.
* There is a borrow if and only if HHALF(t) is nonzero;
* in that (rare) case, qhat was too large (by exactly 1).
* Fix it by adding v[1..n] to u[j..j+n].
*/
if (HHALF(t)) {
qhat--;
for (t = 0, i = n; i > 0; i--) { /* D6: add back. */
t += u[i + j] + v[i];
u[i + j] = (digit)LHALF(t);
t = HHALF(t);
}
u[j] = (digit)LHALF(u[j] + t);
}
q[j] = (digit)qhat;
} while (++j <= m); /* D7: loop on j. */
/*
* If caller wants the remainder, we have to calculate it as
* u[m..m+n] >> d (this is at most n digits and thus fits in
* u[m+1..m+n], but we may need more source digits).
*/
if (arq) {
if (d) {
for (i = m + n; i > m; --i)
u[i] = (digit)(((unsigned int)u[i] >> d) |
LHALF((unsigned int)u[i - 1] <<
(HALF_BITS - d)));
u[i] = 0;
}
tmp.ui[H] = COMBINE(uspace[1], uspace[2]);
tmp.ui[L] = COMBINE(uspace[3], uspace[4]);
*arq = tmp.ll;
}
tmp.ui[H] = COMBINE(qspace[1], qspace[2]);
tmp.ui[L] = COMBINE(qspace[3], qspace[4]);
return (tmp.ll);
}
/*
* Shift p[0]..p[len] left `sh' bits, ignoring any bits that
* `fall out' the left (there never will be any such anyway).
* We may assume len >= 0. NOTE THAT THIS WRITES len+1 DIGITS.
*/
static void
shl(digit *p, int len, int sh)
{
int i;
for (i = 0; i < len; i++)
p[i] = (digit)(LHALF((unsigned int)p[i] << sh) |
((unsigned int)p[i + 1] >> (HALF_BITS - sh)));
p[i] = (digit)(LHALF((unsigned int)p[i] << sh));
}

View File

@ -0,0 +1,55 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
*
* 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 REGENTS 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 REGENTS 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.
*
* From:
* @(#)subdi3.c 8.1 (Berkeley) 6/4/93
* NetBSD: subdi3.c,v 1.1 2005/12/20 19:28:51 christos Exp
*/
#include "longlong.h"
/*
* Subtract two long long values. This is trivial since a one-bit
* carry from a single unsigned int difference x-y occurs if and only
* if (x-y) > x.
*/
long long
__subdi3(long long a, long long b)
{
union uu aa, bb, diff;
aa.ll = a;
bb.ll = b;
diff.ui[L] = aa.ui[L] - bb.ui[L];
diff.ui[H] = aa.ui[H] - bb.ui[H] - (diff.ui[L] > aa.ui[L]);
return (diff.ll);
}

View File

@ -0,0 +1,53 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
*
* 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 REGENTS 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 REGENTS 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.
*
* From:
* @(#)ucmpdi2.c 8.1 (Berkeley) 6/4/93
* NetBSD: ucmpdi2.c,v 1.1 2005/12/20 19:28:51 christos Exp
*/
#include "longlong.h"
/*
* Return 0, 1, or 2 as a <, =, > b respectively.
* Neither a nor b are considered signed.
*/
int
__ucmpdi2(unsigned long long a, unsigned long long b)
{
union uu aa, bb;
aa.ull = a;
bb.ull = b;
return (aa.ui[H] < bb.ui[H] ? 0 : aa.ui[H] > bb.ui[H] ? 2 :
aa.ui[L] < bb.ui[L] ? 0 : aa.ui[L] > bb.ui[L] ? 2 : 1);
}

View File

@ -0,0 +1,48 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
*
* 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 REGENTS 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 REGENTS 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.
*
* From:
* @(#)udivdi3.c 8.1 (Berkeley) 6/4/93
* NetBSD: udivdi3.c,v 1.1 2005/12/20 19:28:51 christos Exp
*/
#include "longlong.h"
/*
* Divide two unsigned long longs.
*/
unsigned long long
__udivdi3(unsigned long long a, unsigned long long b)
{
return __qdivrem(a, b, NULL);
}

View File

@ -0,0 +1,50 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
*
* 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 REGENTS 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 REGENTS 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.
*
* From:
* @(#)umoddi3.c 8.1 (Berkeley) 6/4/93
* NetBSD: umoddi3.c,v 1.1 2005/12/20 19:28:51 christos Exp
*/
#include "longlong.h"
/*
* Return remainder after dividing two unsigned long longs.
*/
unsigned long long
__umoddi3(unsigned long long a, unsigned long long b)
{
unsigned long long r;
(void)__qdivrem(a, b, &r);
return (r);
}

View File

@ -0,0 +1,53 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
*
* 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 REGENTS 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 REGENTS 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.
*
* From:
* @(#)xordi3.c 8.1 (Berkeley) 6/4/93
* NetBSD: xordi3.c,v 1.1 2005/12/20 19:28:51 christos Exp
*/
#include "longlong.h"
/*
* Return a ^ b, in long long.
*/
long long
__xordi3(long long a, long long b)
{
union uu aa, bb;
aa.ll = a;
bb.ll = b;
aa.ui[0] ^= bb.ui[0];
aa.ui[1] ^= bb.ui[1];
return (aa.ll);
}

View File

@ -0,0 +1,104 @@
/*
* 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.
*/
/*
* setjmp and longjmp for MIPS.
*/
#include <kern/mips/regdefs.h>
.text
.set noreorder
/*
* int setjmp(jmp_buf jb);
*
* Save the current state so we can return again from the call later
* if/when longjmp is called. (If the function that called setjmp
* returns before longjmp is called, the results are undefined. We
* only need to save registers, not the whole contents of the stack.)
*/
.globl setjmp
.type setjmp,@function
.ent setjmp
setjmp:
/*
* jmp_buf is in a0. We need to save s0-s8, sp, and ra in it.
* Don't store more registers without adjusting machine/setjmp.h.
*/
sw sp, 0(a0) /* save registers */
sw ra, 4(a0)
sw s0, 8(a0)
sw s1, 12(a0)
sw s2, 16(a0)
sw s3, 20(a0)
sw s4, 24(a0)
sw s5, 28(a0)
sw s6, 32(a0)
sw s7, 36(a0)
sw s8, 40(a0)
j ra /* done */
li v0, 0 /* return 0 (in delay slot) */
.end setjmp
/*
* void longjmp(jmp_buf jb, int code);
*/
.globl longjmp
.type longjmp,@function
.ent longjmp
longjmp:
/*
* jmp_buf is in a0. Return code is in a1.
* We need to restore s0-s8, sp, and ra from the jmp_buf.
* The return code is forced to 1 if 0 is passed in.
*/
sltiu t0, a1, 1 /* set t0 to 1 if return code is 0... otherwise 0 */
addu a1, a1, t0 /* update the return code */
lw sp, 0(a0) /* restore registers */
lw ra, 4(a0)
lw s0, 8(a0)
lw s1, 12(a0)
lw s2, 16(a0)
lw s3, 20(a0)
lw s4, 24(a0)
lw s5, 28(a0)
lw s6, 32(a0)
lw s7, 36(a0)
lw s8, 40(a0)
j ra /* return, to where setjmp was called from */
move v0, a1 /* set return value */
.end longjmp

View File

@ -0,0 +1,592 @@
/*
* Copyright (c) 1997, 1998, 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.
*/
/*
* Guts of printf.
*
* This file is used in both libc and the kernel and needs to work in both
* contexts. This makes a few things a bit awkward.
*
* This is a slightly simplified version of the real-life printf
* originally used in the VINO kernel.
*/
#ifdef _KERNEL
#include <types.h>
#include <lib.h>
#define assert KASSERT
#else
#include <sys/types.h>
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#endif
#include <stdarg.h>
/*
* Do we want to support "long long" types with %lld?
*
* Using 64-bit types with gcc causes gcc to emit calls to functions
* like __moddi3 and __divdi3. These need to be provided at link time,
* which can be a hassle; this switch is provided to help avoid
* needing them.
*/
#define USE_LONGLONG
/*
* Define a type that holds the longest signed integer we intend to support.
*/
#ifdef USE_LONGLONG
#define INTTYPE long long
#else
#define INTTYPE long
#endif
/*
* Space for a long long in base 8, plus a NUL, plus one
* character extra for slop.
*
* CHAR_BIT is the number of bits in a char; thus sizeof(long long)*CHAR_BIT
* is the number of bits in a long long. Each octal digit prints 3 bits.
* Values printed in larger bases will be shorter strings.
*/
#define NUMBER_BUF_SIZE ((sizeof(INTTYPE) * CHAR_BIT) / 3 + 2)
/*
* Structure holding the state for printf.
*/
typedef struct {
/* Callback for sending printed string data */
void (*sendfunc)(void *clientdata, const char *str, size_t len);
void *clientdata;
/* The varargs argument pointer */
va_list ap;
/* Total count of characters printed */
int charcount;
/* Flag that's true if we are currently looking in a %-format */
int in_pct;
/* Size of the integer argument to retrieve */
enum {
INTSZ,
LONGSZ,
#ifdef USE_LONGLONG
LLONGSZ,
#endif
SIZETSZ,
} size;
/* The value of the integer argument retrieved */
unsigned INTTYPE num;
/* Sign of the integer argument (0 = positive; -1 = negative) */
int sign;
/* Field width (number of spaces) */
int spacing;
/* Flag: align to left in field instead of right */
int rightspc;
/* Character to pad to field size with (space or 0) */
int fillchar;
/* Number base to print the integer argument in (8, 10, 16) */
int base;
/* Flag: if set, print 0x before hex and 0 before octal numbers */
int baseprefix;
/* Flag: alternative output format selected with %#... */
int altformat;
} PF;
/*
* Send some text onward to the output.
*
* We count the total length we send out so we can return it from __vprintf,
* since that's what most printf-like functions want to return.
*/
static
void
__pf_print(PF *pf, const char *txt, size_t len)
{
pf->sendfunc(pf->clientdata, txt, len);
pf->charcount += len;
}
/*
* Reset the state for the next %-field.
*/
static
void
__pf_endfield(PF *pf)
{
pf->in_pct = 0;
pf->size = INTSZ;
pf->num = 0;
pf->sign = 0;
pf->spacing = 0;
pf->rightspc = 0;
pf->fillchar = ' ';
pf->base = 0;
pf->baseprefix = 0;
pf->altformat = 0;
}
/*
* Process modifier chars (between the % and the type specifier)
* # use "alternate display format"
* - left align in field instead of right align
* l value is long (ll = long long)
* z value is size_t
* 0-9 field width
* leading 0 pad with zeros instead of spaces
*/
static
void
__pf_modifier(PF *pf, int ch)
{
switch (ch) {
case '#':
pf->altformat = 1;
break;
case '-':
pf->rightspc = 1;
break;
case 'l':
if (pf->size==LONGSZ) {
#ifdef USE_LONGLONG
pf->size = LLONGSZ;
#endif
}
else {
pf->size = LONGSZ;
}
break;
case 'z':
pf->size = SIZETSZ;
break;
case '0':
if (pf->spacing>0) {
/*
* Already seen some digits; this is part of the
* field size.
*/
pf->spacing = pf->spacing*10;
}
else {
/*
* Leading zero; set the padding character to 0.
*/
pf->fillchar = '0';
}
break;
default:
/*
* Invalid characters should be filtered out by a
* higher-level function, so if this assert goes off
* it's our fault.
*/
assert(ch>'0' && ch<='9');
/*
* Got a digit; accumulate the field size.
*/
pf->spacing = pf->spacing*10 + (ch-'0');
break;
}
}
/*
* Retrieve a numeric argument from the argument list and store it
* in pf->num, according to the size recorded in pf->size and using
* the numeric type specified by ch.
*/
static
void
__pf_getnum(PF *pf, int ch)
{
if (ch=='p') {
/*
* Pointer.
*
* uintptr_t is a C99 standard type that's an unsigned
* integer the same size as a pointer.
*/
pf->num = (uintptr_t) va_arg(pf->ap, void *);
}
else if (ch=='d') {
/* signed integer */
INTTYPE signednum=0;
switch (pf->size) {
case INTSZ:
/* %d */
signednum = va_arg(pf->ap, int);
break;
case LONGSZ:
/* %ld */
signednum = va_arg(pf->ap, long);
break;
#ifdef USE_LONGLONG
case LLONGSZ:
/* %lld */
signednum = va_arg(pf->ap, long long);
break;
#endif
case SIZETSZ:
/* %zd */
signednum = va_arg(pf->ap, ssize_t);
break;
}
/*
* Check for negative numbers.
*/
if (signednum < 0) {
pf->sign = -1;
pf->num = -signednum;
}
else {
pf->num = signednum;
}
}
else {
/* unsigned integer */
switch (pf->size) {
case INTSZ:
/* %u (or %o, %x) */
pf->num = va_arg(pf->ap, unsigned int);
break;
case LONGSZ:
/* %lu (or %lo, %lx) */
pf->num = va_arg(pf->ap, unsigned long);
break;
#ifdef USE_LONGLONG
case LLONGSZ:
/* %llu, %llo, %llx */
pf->num = va_arg(pf->ap, unsigned long long);
break;
#endif
case SIZETSZ:
/* %zu, %zo, %zx */
pf->num = va_arg(pf->ap, size_t);
break;
}
}
}
/*
* Set the printing base based on the numeric type specified in ch.
* %o octal
* %d,%u decimal
* %x hex
* %p pointer (print as hex)
*
* If the "alternate format" was requested, or always for pointers,
* note to print the C prefix for the type.
*/
static
void
__pf_setbase(PF *pf, int ch)
{
switch (ch) {
case 'd':
case 'u':
pf->base = 10;
break;
case 'x':
case 'p':
pf->base = 16;
break;
case 'o':
pf->base = 8;
break;
}
if (pf->altformat || ch=='p') {
pf->baseprefix = 1;
}
}
/*
* Function to print "spc" instances of the fill character.
*/
static
void
__pf_fill(PF *pf, int spc)
{
char f = pf->fillchar;
int i;
for (i=0; i<spc; i++) {
__pf_print(pf, &f, 1);
}
}
/*
* General printing function. Prints the string "stuff".
* The two prefixes (in practice one is a type prefix, such as "0x",
* and the other is the sign) get printed *after* space padding but
* *before* zero padding, if padding is on the left.
*/
static
void
__pf_printstuff(PF *pf,
const char *prefix, const char *prefix2,
const char *stuff)
{
/* Total length to print. */
int len = strlen(prefix)+strlen(prefix2)+strlen(stuff);
/* Get field width and compute amount of padding in "spc". */
int spc = pf->spacing;
if (spc > len) {
spc -= len;
}
else {
spc = 0;
}
/* If padding on left and the fill char is not 0, pad first. */
if (spc > 0 && pf->rightspc==0 && pf->fillchar!='0') {
__pf_fill(pf, spc);
}
/* Print the prefixes. */
__pf_print(pf, prefix, strlen(prefix));
__pf_print(pf, prefix2, strlen(prefix2));
/* If padding on left and the fill char *is* 0, pad here. */
if (spc > 0 && pf->rightspc==0 && pf->fillchar=='0') {
__pf_fill(pf, spc);
}
/* Print the actual string. */
__pf_print(pf, stuff, strlen(stuff));
/* If padding on the right, pad afterwards. */
if (spc > 0 && pf->rightspc!=0) {
__pf_fill(pf, spc);
}
}
/*
* Function to convert a number to ascii and then print it.
*
* Works from right to left in a buffer of NUMBER_BUF_SIZE bytes.
* NUMBER_BUF_SIZE is set so that the longest number string we can
* generate (a long long printed in octal) will fit. See above.
*/
static
void
__pf_printnum(PF *pf)
{
/* Digits to print with. */
const char *const digits = "0123456789abcdef";
char buf[NUMBER_BUF_SIZE]; /* Accumulation buffer for string. */
char *x; /* Current pointer into buf. */
unsigned INTTYPE xnum; /* Current value to print. */
const char *bprefix; /* Base prefix (0, 0x, or nothing) */
const char *sprefix; /* Sign prefix (- or nothing) */
/* Start in the last slot of the buffer. */
x = buf+sizeof(buf)-1;
/* Insert null terminator. */
*x-- = 0;
/* Initialize value. */
xnum = pf->num;
/*
* Convert a single digit.
* Do this loop at least once - that way 0 prints as 0 and not "".
*/
do {
/*
* Get the digit character for the least significant
* part of xnum.
*/
*x = digits[xnum % pf->base];
/*
* Back up the pointer to point to the next space to the left.
*/
x--;
/*
* Drop the value of the digit we just printed from xnum.
*/
xnum = xnum / pf->base;
/*
* If xnum hits 0 there's no more number left.
*/
} while (xnum > 0);
/*
* x points to the *next* slot in the buffer to use.
* However, we're done printing the number. So it's pointing
* one slot *before* the start of the actual number text.
* So advance it by one so it actually points at the number.
*/
x++;
/*
* If a base prefix was requested, select it.
*/
if (pf->baseprefix && pf->base==16) {
bprefix = "0x";
}
else if (pf->baseprefix && pf->base==8) {
bprefix = "0";
}
else {
bprefix = "";
}
/*
* Choose the sign prefix.
*/
sprefix = pf->sign ? "-" : "";
/*
* Now actually print the string we just generated.
*/
__pf_printstuff(pf, sprefix, bprefix, x);
}
/*
* Process a single character out of the format string.
*/
static
void
__pf_send(PF *pf, int ch)
{
/* Cannot get NULs here. */
assert(ch!=0);
if (pf->in_pct==0 && ch!='%') {
/*
* Not currently in a format, and not a %. Just send
* the character on through.
*/
char c = ch;
__pf_print(pf, &c, 1);
}
else if (pf->in_pct==0) {
/*
* Not in a format, but got a %. Start a format.
*/
pf->in_pct = 1;
}
else if (strchr("#-lz0123456789", ch)) {
/*
* These are the modifier characters we recognize.
* (These are the characters between the % and the type.)
*/
__pf_modifier(pf, ch);
}
else if (strchr("doupx", ch)) {
/*
* Integer types.
* Fetch the number, set the base, print it, then
* reset for the next format.
*/
__pf_getnum(pf, ch);
__pf_setbase(pf, ch);
__pf_printnum(pf);
__pf_endfield(pf);
}
else if (ch=='s') {
/*
* Print a string.
*/
const char *str = va_arg(pf->ap, const char *);
if (str==NULL) {
str = "(null)";
}
__pf_printstuff(pf, "", "", str);
__pf_endfield(pf);
}
else {
/*
* %%, %c, or illegal character.
* Illegal characters are printed like %%.
* for example, %5k prints " k".
*/
char x[2];
if (ch=='c') {
x[0] = va_arg(pf->ap, int);
}
else {
x[0] = ch;
}
x[1] = 0;
__pf_printstuff(pf, "", "", x);
__pf_endfield(pf);
}
}
/*
* Do a whole printf session.
* Create and initialize a printf state object,
* then send it each character from the format string.
*/
int
__vprintf(void (*func)(void *clientdata, const char *str, size_t len),
void *clientdata, const char *format, va_list ap)
{
PF pf;
int i;
pf.sendfunc = func;
pf.clientdata = clientdata;
#ifdef va_copy
va_copy(pf.ap, ap);
#else
pf.ap = ap;
#endif
pf.charcount = 0;
__pf_endfield(&pf);
for (i=0; format[i]; i++) {
__pf_send(&pf, format[i]);
}
return pf.charcount;
}

View File

@ -0,0 +1,157 @@
/*
* 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.
*/
/*
* This file is shared between libc and the kernel, so don't put anything
* in here that won't work in both contexts.
*/
#ifdef _KERNEL
#include <types.h>
#include <lib.h>
#else
#include <stdio.h>
#endif /* _KERNEL */
#include <stdarg.h>
/*
* Standard C string/IO function: printf into a character buffer.
*/
/*
* Context structure for snprintf: buffer to print into, maximum
* length, and index of the next character to write.
*
* Note that while the length argument to snprintf includes space for
* a null terminator, SNP.buflen does not. This is to make something
* vaguely reasonable happen if a length of 0 is passed to snprintf.
*/
typedef struct {
char *buf;
size_t buflen;
size_t bufpos;
} SNP;
/*
* Send function for snprintf. This is the function handed to the
* printf guts. It gets called with mydata pointing to the context,
* and some string data of length LEN in DATA. DATA is not necessarily
* null-terminated.
*/
static
void
__snprintf_send(void *mydata, const char *data, size_t len)
{
SNP *snp = mydata;
unsigned i;
/* For each character we're sent... */
for (i=0; i<len; i++) {
/* If we aren't past the length, */
if (snp->bufpos < snp->buflen) {
/* store the character */
snp->buf[snp->bufpos] = data[i];
/* and increment the position. */
snp->bufpos++;
}
}
}
/*
* The va_list version of snprintf.
*/
int
vsnprintf(char *buf, size_t len, const char *fmt, va_list ap)
{
int chars;
SNP snp;
/*
* Fill in the context structure.
* We set snp.buflen to the number of characters that can be
* written (excluding the null terminator) so as not to have
* to special-case the possibility that we got passed a length
* of zero elsewhere.
*/
snp.buf = buf;
if (len==0) {
snp.buflen = 0;
}
else {
snp.buflen = len-1;
}
snp.bufpos = 0;
/* Call __vprintf to do the actual work. */
chars = __vprintf(__snprintf_send, &snp, fmt, ap);
/*
* Add a null terminator. If the length *we were passed* is greater
* than zero, we reserved a space in the buffer for the terminator,
* so this won't overflow. If the length we were passed is zero,
* nothing will have been or should be written anyway, and buf
* might even be NULL. (C99 explicitly endorses this possibility.)
*/
if (len > 0) {
buf[snp.bufpos] = 0;
}
/*
* Return the number of characters __vprintf processed.
* According to C99, snprintf should return this number, not
* the number of characters actually stored, and should not
* return -1 on overflow but only on other errors. (All none
* of them since we don't do multibyte characters...)
*/
return chars;
}
/*
* snprintf - hand off to vsnprintf.
*/
int
snprintf(char *buf, size_t len, const char *fmt, ...)
{
int chars;
va_list ap;
va_start(ap, fmt);
chars = vsnprintf(buf, len, fmt, ap);
va_end(ap);
return chars;
}

101
common/libc/stdlib/atoi.c Normal file
View File

@ -0,0 +1,101 @@
/*
* 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.
*/
/*
* This file is shared between libc and the kernel, so don't put anything
* in here that won't work in both contexts.
*/
#ifdef _KERNEL
#include <types.h>
#include <lib.h>
#else
#include <stdlib.h>
#include <string.h>
#endif
/*
* Standard C function: parse a string that represents a decimal integer.
* Leading whitespace is allowed. Trailing gunk is allowed too. Doesn't
* really report syntax errors or overflow in any useful way.
*/
int
atoi(const char *s)
{
static const char digits[] = "0123456789"; /* legal digits in order */
unsigned val=0; /* value we're accumulating */
int neg=0; /* set to true if we see a minus sign */
/* skip whitespace */
while (*s==' ' || *s=='\t') {
s++;
}
/* check for sign */
if (*s=='-') {
neg=1;
s++;
}
else if (*s=='+') {
s++;
}
/* process each digit */
while (*s) {
const char *where;
unsigned digit;
/* look for the digit in the list of digits */
where = strchr(digits, *s);
if (where==NULL) {
/* not found; not a digit, so stop */
break;
}
/* get the index into the digit list, which is the value */
digit = (where - digits);
/* could (should?) check for overflow here */
/* shift the number over and add in the new digit */
val = val*10 + digit;
/* look at the next character */
s++;
}
/* handle negative numbers */
if (neg) {
return -val;
}
/* done */
return val;
}

View File

@ -0,0 +1,76 @@
/*
* 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.
*/
/*
* This file is shared between libc and the kernel, so don't put anything
* in here that won't work in both contexts.
*/
#ifdef _KERNEL
#include <types.h>
#include <lib.h>
#else
#include <stdint.h>
#include <string.h>
#endif
/*
* Standard (well, semi-standard) C string function - zero a block of
* memory.
*/
void
bzero(void *vblock, size_t len)
{
char *block = vblock;
size_t i;
/*
* For performance, optimize the common case where the pointer
* and the length are word-aligned, and write word-at-a-time
* instead of byte-at-a-time. Otherwise, write bytes.
*
* The alignment logic here should be portable. We rely on the
* compiler to be reasonably intelligent about optimizing the
* divides and moduli out. Fortunately, it is.
*/
if ((uintptr_t)block % sizeof(long) == 0 &&
len % sizeof(long) == 0) {
long *lb = (long *)block;
for (i=0; i<len/sizeof(long); i++) {
lb[i] = 0;
}
}
else {
for (i=0; i<len; i++) {
block[i] = 0;
}
}
}

View File

@ -0,0 +1,86 @@
/*
* 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.
*/
/*
* This file is shared between libc and the kernel, so don't put anything
* in here that won't work in both contexts.
*/
#ifdef _KERNEL
#include <types.h>
#include <lib.h>
#else
#include <stdint.h>
#include <string.h>
#endif
/*
* C standard function - copy a block of memory.
*/
void *
memcpy(void *dst, const void *src, size_t len)
{
size_t i;
/*
* memcpy does not support overlapping buffers, so always do it
* forwards. (Don't change this without adjusting memmove.)
*
* For speedy copying, optimize the common case where both pointers
* and the length are word-aligned, and copy word-at-a-time instead
* of byte-at-a-time. Otherwise, copy by bytes.
*
* The alignment logic below should be portable. We rely on
* the compiler to be reasonably intelligent about optimizing
* the divides and modulos out. Fortunately, it is.
*/
if ((uintptr_t)dst % sizeof(long) == 0 &&
(uintptr_t)src % sizeof(long) == 0 &&
len % sizeof(long) == 0) {
long *d = dst;
const long *s = src;
for (i=0; i<len/sizeof(long); i++) {
d[i] = s[i];
}
}
else {
char *d = dst;
const char *s = src;
for (i=0; i<len; i++) {
d[i] = s[i];
}
}
return dst;
}

View 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.
*/
/*
* This file is shared between libc and the kernel, so don't put anything
* in here that won't work in both contexts.
*/
#ifdef _KERNEL
#include <types.h>
#include <lib.h>
#else
#include <stdint.h>
#include <string.h>
#endif
/*
* C standard function - copy a block of memory, handling overlapping
* regions correctly.
*/
void *
memmove(void *dst, const void *src, size_t len)
{
size_t i;
/*
* If the buffers don't overlap, it doesn't matter what direction
* we copy in. If they do, it does, so just assume they always do.
* We don't concern ourselves with the possibility that the region
* to copy might roll over across the top of memory, because it's
* not going to happen.
*
* If the destination is above the source, we have to copy
* back to front to avoid overwriting the data we want to
* copy.
*
* dest: dddddddd
* src: ssssssss ^
* | ^ |___|
* |___|
*
* If the destination is below the source, we have to copy
* front to back.
*
* dest: dddddddd
* src: ^ ssssssss
* |___| ^ |
* |___|
*/
if ((uintptr_t)dst < (uintptr_t)src) {
/*
* As author/maintainer of libc, take advantage of the
* fact that we know memcpy copies forwards.
*/
return memcpy(dst, src, len);
}
/*
* Copy by words in the common case. Look in memcpy.c for more
* information.
*/
if ((uintptr_t)dst % sizeof(long) == 0 &&
(uintptr_t)src % sizeof(long) == 0 &&
len % sizeof(long) == 0) {
long *d = dst;
const long *s = src;
/*
* The reason we copy index i-1 and test i>0 is that
* i is unsigned -- so testing i>=0 doesn't work.
*/
for (i=len/sizeof(long); i>0; i--) {
d[i-1] = s[i-1];
}
}
else {
char *d = dst;
const char *s = src;
for (i=len; i>0; i--) {
d[i-1] = s[i-1];
}
}
return dst;
}

View 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.
*/
#ifdef _KERNEL
#include <types.h>
#include <lib.h>
#else
#include <string.h>
#endif
/*
* C standard function - initialize a block of memory
*/
void *
memset(void *ptr, int ch, size_t len)
{
char *p = ptr;
size_t i;
for (i=0; i<len; i++) {
p[i] = ch;
}
return ptr;
}

View File

@ -0,0 +1,54 @@
/*
* 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.
*/
/*
* This file is shared between libc and the kernel, so don't put anything
* in here that won't work in both contexts.
*/
#ifdef _KERNEL
#include <types.h>
#include <lib.h>
#else
#include <string.h>
#endif
/*
* Standard C string function: append one string to another.
*/
char *
strcat(char *dest, const char *src)
{
size_t offset;
offset = strlen(dest);
strcpy(dest+offset, src);
return dest;
}

View 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.
*/
/*
* This file is shared between libc and the kernel, so don't put anything
* in here that won't work in both contexts.
*/
#ifdef _KERNEL
#include <types.h>
#include <lib.h>
#else
#include <string.h>
#endif
/*
* C standard string function: find leftmost instance of a character
* in a string.
*/
char *
strchr(const char *s, int ch_arg)
{
/* avoid sign-extension problems */
const char ch = ch_arg;
/* scan from left to right */
while (*s) {
/* if we hit it, return it */
if (*s == ch) {
return (char *)s;
}
s++;
}
/* if we were looking for the 0, return that */
if (*s == ch) {
return (char *)s;
}
/* didn't find it */
return NULL;
}

View File

@ -0,0 +1,90 @@
/*
* 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.
*/
/*
* This file is shared between libc and the kernel, so don't put anything
* in here that won't work in both contexts.
*/
#ifdef _KERNEL
#include <types.h>
#include <lib.h>
#else
#include <string.h>
#endif
/*
* Standard C string function: compare two strings and return their
* sort order.
*/
int
strcmp(const char *a, const char *b)
{
size_t i;
/*
* Walk down both strings until either they're different
* or we hit the end of A.
*
* If A and B strings are not the same length, when the
* shorter one ends, the two will be different, and we'll
* stop before running off the end of either.
*
* If they *are* the same length, it's sufficient to check
* that we haven't run off the end of A, because that's the
* same as checking to make sure we haven't run off the end of
* B.
*/
for (i=0; a[i]!=0 && a[i]==b[i]; i++) {
/* nothing */
}
/*
* If A is greater than B, return 1. If A is less than B,
* return -1. If they're the same, return 0. Since we have
* stopped at the first character of difference (or the end of
* both strings) checking the character under I accomplishes
* this.
*
* Note that strcmp does not handle accented characters,
* internationalization, or locale sort order; strcoll() does
* that.
*
* The rules say we compare order in terms of *unsigned* char.
*/
if ((unsigned char)a[i] > (unsigned char)b[i]) {
return 1;
}
else if (a[i] == b[i]) {
return 0;
}
return -1;
}

View File

@ -0,0 +1,63 @@
/*
* 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.
*/
/*
* This file is shared between libc and the kernel, so don't put anything
* in here that won't work in both contexts.
*/
#ifdef _KERNEL
#include <types.h>
#include <lib.h>
#else
#include <string.h>
#endif
/*
* Standard C string function: copy one string to another.
*/
char *
strcpy(char *dest, const char *src)
{
size_t i;
/*
* Copy characters until we hit the null terminator.
*/
for (i=0; src[i]; i++) {
dest[i] = src[i];
}
/*
* Add null terminator to result.
*/
dest[i] = 0;
return dest;
}

View File

@ -0,0 +1,55 @@
/*
* 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.
*/
/*
* This file is shared between libc and the kernel, so don't put anything
* in here that won't work in both contexts.
*/
#ifdef _KERNEL
#include <types.h>
#include <lib.h>
#else
#include <string.h>
#endif
/*
* C standard string function: get length of a string
*/
size_t
strlen(const char *str)
{
size_t ret = 0;
while (str[ret]) {
ret++;
}
return ret;
}

View File

@ -0,0 +1,69 @@
/*
* 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.
*/
/*
* This file is shared between libc and the kernel, so don't put anything
* in here that won't work in both contexts.
*/
#ifdef _KERNEL
#include <types.h>
#include <lib.h>
#else
#include <string.h>
#endif
/*
* C standard string function: find rightmost instance of a character
* in a string.
*/
char *
strrchr(const char *s, int ch_arg)
{
/* avoid sign-extension problems */
const char ch = ch_arg;
/* start one past the last character INCLUDING NULL TERMINATOR */
size_t i = strlen(s)+1;
/* go from right to left; stop at 0 */
while (i > 0) {
/* decrement first */
i--;
/* now check the character we're over */
if (s[i] == ch) {
return (char *)(s+i);
}
}
/* didn't find it */
return NULL;
}

View File

@ -0,0 +1,96 @@
/*
* 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.
*/
/*
* This file is shared between libc and the kernel, so don't put anything
* in here that won't work in both contexts.
*/
#ifdef _KERNEL
#include <types.h>
#include <lib.h>
#else
#include <string.h>
#endif
/*
* Standard C string function: tokenize a string splitting based on a
* list of separator characters. Reentrant version.
*
* The "context" argument should point to a "char *" that is preserved
* between calls to strtok_r that wish to operate on same string.
*/
char *
strtok_r(char *string, const char *seps, char **context)
{
char *head; /* start of word */
char *tail; /* end of word */
/* If we're starting up, initialize context */
if (string) {
*context = string;
}
/* Get potential start of this next word */
head = *context;
if (head == NULL) {
return NULL;
}
/* Skip any leading separators */
while (*head && strchr(seps, *head)) {
head++;
}
/* Did we hit the end? */
if (*head == 0) {
/* Nothing left */
*context = NULL;
return NULL;
}
/* skip over word */
tail = head;
while (*tail && !strchr(seps, *tail)) {
tail++;
}
/* Save head for next time in context */
if (*tail == 0) {
*context = NULL;
}
else {
*tail = 0;
tail++;
*context = tail;
}
/* Return current word */
return head;
}

199
configure vendored Executable file
View File

@ -0,0 +1,199 @@
#!/bin/sh
#
# Configure script for OS/161 tree.
# This generates the file "defs.mk" at the top level of the tree.
#
# Usage: ./configure [options]
# where you can get a list of the options by doing ./configure --help.
#
# Must be run with the top of the OS/161 tree as its current directory.
#
# Note: while this superficially acts like a GNU Autoconf configure
# script, it was not generated by autoconf. Scripts generated by
# autoconf are much harder to read. :-)
#
# If this script bombs out, you can create defs.mk by hand based on
# the comments in mk/os161.config.mk.
#
# Target hardware platform and machine type.
PLATFORM='sys161'
MACHINE='mips'
# Default optimize/debug flag: optimize.
DEBUG='-O2'
# Default location of the root of the installed system.
# Note that we quote it such that the reference to the home directory
# is a make variable, not a shell variable. This means it gets expanded
# when make runs rather than when this script runs.
OSTREE='$(HOME)/os161/root'
# By default don't explicitly configure a Python interpreter.
PYTHON_INTERPRETER=
# Assume this
HOST_CC=gcc
##################################################
#
# Check to make sure we're in the right place.
if [ ! -d kern/main ]; then
echo 'Please run configure from the top of the OS/161 tree.'
exit 1
fi
#
# Process the command-line options.
while [ "x$1" != x ]; do
case "$1" in
--debug) DEBUG='-g';;
--ostree=*) OSTREE=`echo $1 | sed 's,^[^=]*=,,'`;;
--help|*)
more <<EOF
Usage: ./configure [options]
where the options are:
--help Print this message.
--debug Compile the user-level programs with debug info.
This is disabled by default because there's no
support for userlevel source debugging in OS/161.
(Note: debug info in the kernel is controlled by
the kernel config file.)
--ostree=PATH Install the compiled system in a directory tree
rooted at PATH. Default is \$HOME/os161/root.
EOF
exit
;;
esac
shift
done
# Check if the host system supports 4.4BSD <err.h>.
printf "Checking for <err.h>... "
cat > __conftest.c <<EOF
#include <err.h>
int
main()
{
err(0, "works");
return 1;
}
EOF
OK=0
if $HOST_CC __conftest.c -o __conftest >/dev/null 2>&1; then
if ./__conftest >/dev/null 2>&1; then
OK=1
fi
fi
rm -f __conf*
if [ $OK = 1 ]; then
echo 'yes'
else
echo 'no'
COMPAT_CFLAGS="${COMPATCFLAGS} -DNEED_ERR"
COMPAT_TARGETS="${HOSTTARGETS} install-errh"
fi
# Check if the host system has ntohll() and htonll().
printf "Checking for ntohll()..."
cat > __conftest.c <<EOF
#include <arpa/inet.h>
int
main()
{
int ok = ntohll(0xbeefbeefbeefbeefULL) != 0;
return !ok; /* exit(0) for success */
}
EOF
OK=0
if $HOST_CC __conftest.c -o __conftest >/dev/null 2>&1; then
if ./__conftest >/dev/null 2>&1; then
OK=1
fi
fi
rm -f __conf*
if [ $OK = 1 ]; then
echo 'yes'
else
echo 'no'
COMPAT_CFLAGS="${COMPATCFLAGS} -DNEED_NTOHLL"
HOST_CFLAGS="${HOST_CFLAGS} -DDECLARE_NTOHLL"
fi
# Look for a Python interpreter.
PYTHON=
for PYNAME in \
python python2.7 \
/usr/local/bin/python /usr/local/bin/python2.7 \
/usr/pkg/bin/python /usr/pkg/bin/python2.7 \
/opt/bin/python /opt/bin/python2.7 \
; do
PYVERSION=`($PYNAME -V) 2>&1 || echo none`
case "$PYVERSION" in
Python\ 2.*|Python\ 3.*) PYTHON=$PYNAME;;
none) ;;
*) ;; # ?
esac
done
case "$PYTHON" in
python) ;;
/*) PYTHON_INTERPRETER="$PYTHON";;
*) PYTHON_INTERPRETER="/usr/bin/env $PYTHON";;
esac
####################
# Now generate defs.mk.
echo 'Generating defs.mk.'
(
# First, put an explanatory comment at the top.
cat <<EOF
# This file was generated by configure. Edits will disappear if you rerun
# configure. If you find that you need to edit this file to make things
# work, let the course staff know and we'll try to fix the configure script.
#
# The purpose of this file is to hold all the makefile definitions
# needed to adjust the OS/161 build process to any particular
# environment. If I've done it right, all you need to do is rerun the
# configure script and make clean if you start working on a different
# host OS. If I've done it mostly right, you may need to edit this
# file but you still hopefully won't need to edit any of the
# makefiles.
#
# The things that can be set here are documented in mk/os161.config.mk.
#
EOF
echo "OSTREE=${OSTREE}"
echo "PLATFORM=${PLATFORM}"
echo "MACHINE=${MACHINE}"
echo "COMPAT_CFLAGS=${COMPAT_CFLAGS}"
echo "COMPAT_TARGETS=${COMPAT_TARGETS}"
if [ "x$HOST_CFLAGS" != x ]; then
echo "HOST_CFLAGS+=$HOST_CFLAGS"
fi
if [ "x$PYTHON_INTERPRETER" != x ]; then
echo "PYTHON_INTERPRETER=$PYTHON_INTERPRETER"
fi
) > defs.mk

22
defs.mk Normal file
View File

@ -0,0 +1,22 @@
# This file was generated by configure. Edits will disappear if you rerun
# configure. If you find that you need to edit this file to make things
# work, let the course staff know and we'll try to fix the configure script.
#
# The purpose of this file is to hold all the makefile definitions
# needed to adjust the OS/161 build process to any particular
# environment. If I've done it right, all you need to do is rerun the
# configure script and make clean if you start working on a different
# host OS. If I've done it mostly right, you may need to edit this
# file but you still hopefully won't need to edit any of the
# makefiles.
#
# The things that can be set here are documented in mk/os161.config.mk.
#
OSTREE=/root/os161/root
PLATFORM=sys161
MACHINE=mips
COMPAT_CFLAGS= -DNEED_NTOHLL
COMPAT_TARGETS=
HOST_CFLAGS+= -DDECLARE_NTOHLL
PYTHON_INTERPRETER=/usr/bin/env

120
design/assignments.txt Normal file
View File

@ -0,0 +1,120 @@
The (potential) OS/161 assignments
----------------------------------
OS/161 is used by a wide variety of courses at a wide variety of
schools, no two of which have the exact same set of assignments and
assignment requirements. The code base has been (to the extent
reasonably possible) structured to allow this and not assume any
particular structure or (particularly) numbering of assignments.
That said, in various places comments and documentation must (to be
helpful, at least) refer to particular assignments and things that are
(typically) done in particular assignments. These are written in
fairly general terms. This file is provided as an index for those
terms.
*** Always refer to the course materials provided by your ***
*** instructors when trying to figure out what functionality ***
*** you are and are not required to implement. ***
Note that the OS/161 code base you are given may include solutions for
some parts of the assignments described below, or even some whole
assignments.
Also note that the text below refers to assorted technical terms and
OS concepts without much or any explanation; you may not be familiar
with most of them at first and that's perfectly ok.
OS/161 is intended to support six basic assignments, most of which can
be divided into smaller pieces. These six assignments are:
- synchronization;
- basic system calls;
- virtual memory;
- basic file system functionality;
- file system recovery via journaling;
- some additional piece of OS functionality.
Synchronization.
This assignment has (potentially) three parts:
- Implement (sleep) locks and condition variables.
- Implement reader-writer locks.
- Solve some synchronization problems of the dining-philosophers
variety.
Basic system calls. (And processes.)
This assignment has (potentially) up to six parts:
- Implement file tables and open-file objects.
- Implement the basic system calls for files, normally:
- open()
- dup2()
- read()
- write()
- lseek()
- close()
- chdir()
- __getcwd()
- Implement processes, process IDs, and the basic process system
calls, normally:
- getpid()
- fork()
- _exit()
- waitpid()
- Implement the execv() system call.
- Implement a scheduler.
Virtual memory.
This assignment entails replacing a provided very simple virtual
memory system with a real one. This possibly includes providing the
sbrk() system call. It does not split into parts readily.
Basic file system functionality.
This assignment has (potentially) up to five parts:
- Add more system calls for file system operations, typically taken
from these:
- sync()
- mkdir()
- rmdir()
- remove()
- link()
- rename()
- getdirentry()
- fstat()
- fsync()
- ftruncate()
- flock()
although others may be chosen.
- Implement a buffer cache.
- Replace a biglock with fine-grained locking in the VFS layer
and/or the SFS file system.
- Add support for subdirectories to SFS.
- Implement cross-directory rename in SFS.
- Implement larger files in SFS.
File system recovery via journaling.
This assignment has (potentially) five parts:
- Implement an on-disk container for a file system journal.
- Instrument the buffer cache to support write-ahead journaling.
- Design a system of journal records suitable for recovering the
file system after a crash.
- Add code to SFS to issue these journal records.
- Implement code to read the on-disk journal and recover from a
crash.
Additional projects.
There is a wide variety of things that can be done to build on the
above assignments. None are listed here, because this file is not
the place for it.

55
design/shell.txt Normal file
View File

@ -0,0 +1,55 @@
SHELL DESIGN NOTES
------------------
The shell has few bells and whistles. It allows up to 128
backgrounded jobs (after this point you have to wait for some to exit,
because the table it uses to track these cannot be resized.)
The background jobs are tracked in an array of MAXBG pid_t's. If an
open slot is found, a background job's pid can be stashed there.
Background jobs can be collected using the "wait" built-in command,
which removes any pids whose exit status it collects from the
background jobs table.
The wait built-in command takes an optional argument, the process
id to wait for. The shell will attempt to wait for any process, not
just the ones it actually started as its own background jobs. However,
since no facility exists for looking up the pids of running processes,
this ability is not necessarily useful. If no argument is provided,
wait waits for all outstanding background jobs.
The shell uses WNOHANG if WNOHANG is defined, in which case
background jobs are polled after every command, like in Unix shells.
If WNOHANG is not defined, background jobs are polled only by user
request. In OS/161 2.0, WNOHANG is always defined in the kernel header
files, but the implementation is only suggested, not required. To make
the shell stop trying to use WNOHANG, patch it, or remove WNOHANG from
kern/wait.h.
There are two other built-in commands: chdir, which uses the chdir
system call to change directory, and can also be accessed as just cd,
and exit, which causes the shell to exit with a specified exit status
(0 if not supplied).
Note that all these built-in commands must be built into the shell
in order to work usefully.
The shell processes commands by reading lines and then splitting
them up into words using whitespace characters (space, tab, carriage
return, and newline) as separators. No punctuation characters are
interpreted, except for `&'. No variable substitution or argument
wildcard expansion ("globbing") is performed.
The `&' character, if present as the last word on a command line,
is treated as the "background" operator: the command is run as a
background job, that is, after starting it the shell immediately
prints another prompt and accepts more commands. Note that the `&'
must be preceded by whitespace to be recognized. The process id of the
background job is printed as it starts. Note that shell builtins
cannot be backgrounded; furthermore, because the OS/161 console does
not support job control, starting background jobs that perform
terminal input (or, to a lesser extent, terminal output) may produce
confusing and/or unwanted results.
The shell also supports the "sh -c COMMAND" syntax in the hopes
that it will be useful.

24
design/usermalloc.txt Normal file
View File

@ -0,0 +1,24 @@
User-level malloc
-----------------
The user-level malloc implementation is defined to be simple, not
fast or efficient. It uses a very basic first-fit block algorithm.
There's an 8-byte header which holds the offsets to the previous
and next blocks, a used/free bit, and some magic numbers (for
consistency checking) in the remaining available header bits. It also
allocates in units of 8 bytes to guarantee proper alignment of
doubles. (It also assumes its own headers are aligned on 8-byte
boundaries.)
On malloc(), it searches the entire heap starting at the beginning
for the first block big enough to hold the allocation. If it doesn't
find one, it calls sbrk() to get more memory. If it does find one, it
marks the block in use. It splits the remaining portion of the block
off as a new free block only if said portion is large enough to hold
both a header and some data.
On free(), it marks the block free and then tries to merge it with
the adjacent blocks (both above and below) if they're free.
That's about all there is to it.

17
kern/Makefile Normal file
View File

@ -0,0 +1,17 @@
#
# Toplevel makefile for the OS/161 kernel tree.
#
# Note: actual kernels are not compiled here; they are compiled in
# compile/FOO where FOO is a kernel configuration name.
#
# We don't actually do anything from here except install includes.
#
TOP=..
.include "$(TOP)/mk/os161.config.mk"
INCLUDES=\
include/kern include/kern \
arch/$(MACHINE)/include/kern include/kern/$(MACHINE)
.include "$(TOP)/mk/os161.includes.mk"

View 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

View 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) }
}

View 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_ */

View 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_ */

View 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_ */

View 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_ */

View 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_ */

View 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_ */

View 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_ */

View 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_ */

View 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_ */

View 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_ */

View 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_ */

View 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_ */

View File

@ -0,0 +1,108 @@
/*
* 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_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_ */

View 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
View 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_ */

View 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

View File

@ -0,0 +1,366 @@
/*
* 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
.cfi_startproc
.cfi_signal_frame
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 35 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, -160
.cfi_def_cfa sp, 0
/*
* 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 uses the .cfi_offset assembler directives inserted below to
* to figure out where each register is stored. Since we've marked
* this function as a "signal handler" with the .cfi_signal_frame
* directive, gdb won't complain about the fact that the stack
* is noncontiguous (if we're coming from userland).
*
* We also play a trick with the return address: we mark the ra
* register as stored to the stack normally and then mark the
* return address for *this* function as being in the k1 register
* using the .cfi_return_column directive. gdb is then able to
* recognize that the ra we've stored here is the return address
* for the function that was executing when this exception was
* taken.
*
* All of the cfi (call frame information) material is compiled
* into the .eh_frame section of the compiled kernel.
*/
sw s8, 148(sp) /* save s8 */
.cfi_offset s8, 148
sw k1, 144(sp) /* real saved sp */
.cfi_offset sp, 144
sw gp, 140(sp) /* save gp */
nop /* delay slot for store */
.cfi_offset gp, 140
.cfi_return_column k1
mfc0 k1, c0_epc /* Copr.0 reg 13 == PC for exception */
sw k1, 152(sp) /* real saved PC */
.cfi_offset k1, 152
sw t9, 136(sp)
.cfi_offset t9, 136
sw t8, 132(sp)
.cfi_offset t8, 132
sw s7, 128(sp)
.cfi_offset s7, 128
sw s6, 124(sp)
.cfi_offset s6, 124
sw s5, 120(sp)
.cfi_offset s5, 120
sw s4, 116(sp)
.cfi_offset s4, 116
sw s3, 112(sp)
.cfi_offset s3, 112
sw s2, 108(sp)
.cfi_offset s2, 108
sw s1, 104(sp)
.cfi_offset s1, 104
sw s0, 100(sp)
.cfi_offset s0, 100
sw t7, 96(sp)
.cfi_offset t7, 96
sw t6, 92(sp)
.cfi_offset t6, 92
sw t5, 88(sp)
.cfi_offset t5, 88
sw t4, 84(sp)
.cfi_offset t4, 84
sw t3, 80(sp)
.cfi_offset t3, 80
sw t2, 76(sp)
.cfi_offset t2, 76
sw t1, 72(sp)
.cfi_offset t1, 72
sw t0, 68(sp)
.cfi_offset t0, 68
sw a3, 64(sp)
.cfi_offset a3, 64
sw a2, 60(sp)
.cfi_offset a2, 60
sw a1, 56(sp)
.cfi_offset a1, 56
sw a0, 52(sp)
.cfi_offset a0, 52
sw v1, 48(sp)
.cfi_offset v1, 48
sw v0, 44(sp)
.cfi_offset v0, 44
sw AT, 40(sp)
.cfi_offset AT, 40
sw ra, 36(sp)
.cfi_offset ra, 36
/*
* 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 */
/*
* 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 */
/*
* 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)
lw gp, 140(sp) /* restore gp */
/* 144(sp) stack pointer - below */
lw s8, 148(sp) /* restore s8 */
lw k1, 152(sp) /* fetch exception return PC into k1 */
lw sp, 144(sp) /* fetch saved sp (must be last) */
/* done */
jr k1 /* jump back */
rfe /* in delay slot */
.cfi_endproc
.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

View 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 35 registers long. */
KASSERT(sizeof(struct trapframe)==(35*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);
}

View 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;
}

309
kern/arch/mips/thread/cpu.c Normal file
View File

@ -0,0 +1,309 @@
/*
* 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.
*
* The values in the current cpu's slots in these arrays are updated
* with the current thread's information in trap.c before heading to
* userlevel, as well as being initialized in cpu_machdep_init below.
* This means that (unless something really horrible happens) on entry
* to the kernel, and when a new CPU starts up in cpu_start_secondary,
* they will have the information needed to figure out who we are and
* proceed.
*/
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();
}
}

View 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

View 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;
}

View 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_ */

View 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);
}

View 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

427
kern/arch/mips/vm/dumbvm.c Normal file
View File

@ -0,0 +1,427 @@
/*
* 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(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
View 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;
}

View 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

View File

@ -0,0 +1,34 @@
#
# Platform-dependent sources for System/161.
#
#
# locore
#
# Cache handling for the kind of MIPS we have
platform sys161 file arch/mips/locore/cache-mips161.S
# Exception handling (assembler entry points) for the kind of MIPS we have
platform sys161 file arch/mips/locore/exception-mips1.S
#
# VM
#
# TLB handling for the kind of MIPS we have
platform sys161 file arch/mips/vm/tlb-mips161.S
#
# Devices. We have LAMEbus.
#
platform sys161 file arch/sys161/dev/lamebus_machdep.c
include dev/lamebus/conf.lamebus
#
# Startup and initialization.
#
platform sys161 file arch/sys161/main/start.S

View File

@ -0,0 +1,344 @@
/*
* 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/unistd.h>
#include <lib.h>
#include <mips/specialreg.h>
#include <mips/trapframe.h>
#include <cpu.h>
#include <spl.h>
#include <clock.h>
#include <thread.h>
#include <current.h>
#include <membar.h>
#include <synch.h>
#include <mainbus.h>
#include <sys161/bus.h>
#include <lamebus/lamebus.h>
#include <lamebus/ltrace.h>
#include "autoconf.h"
/*
* CPU frequency used by the on-chip timer.
*
* Note that we really ought to measure the CPU frequency against the
* real-time clock instead of compiling it in like this.
*/
#define CPU_FREQUENCY 25000000 /* 25 MHz */
/*
* Access to the on-chip timer.
*
* The c0_count register increments on every cycle; when the value
* matches the c0_compare register, the timer interrupt line is
* asserted. Writing to c0_compare again clears the interrupt.
*/
static
void
mips_timer_set(uint32_t count)
{
/*
* $11 == c0_compare; we can't use the symbolic name inside
* the asm string.
*/
__asm volatile(
".set push;" /* save assembler mode */
".set mips32;" /* allow MIPS32 registers */
"mtc0 %0, $11;" /* do it */
".set pop" /* restore assembler mode */
:: "r" (count));
}
/*
* LAMEbus data for the system. (We have only one LAMEbus per system.)
* This does not need to be locked, because it's constant once
* initialized, and initialized before we start other threads or CPUs.
*/
static struct lamebus_softc *lamebus;
void
mainbus_bootstrap(void)
{
/* Interrupts should be off (and have been off since startup) */
KASSERT(curthread->t_curspl > 0);
/* Initialize the system LAMEbus data */
lamebus = lamebus_init();
/* Probe CPUs (should these be done as device attachments instead?) */
lamebus_find_cpus(lamebus);
/*
* Print the device name for the main bus.
*/
kprintf("lamebus0 (system main bus)\n");
/*
* Now we can take interrupts without croaking, so turn them on.
* Some device probes might require being able to get interrupts.
*/
spl0();
/*
* Now probe all the devices attached to the bus.
* (This amounts to all devices.)
*/
autoconf_lamebus(lamebus, 0);
/*
* Configure the MIPS on-chip timer to interrupt HZ times a second.
*/
mips_timer_set(CPU_FREQUENCY / HZ);
}
/*
* Start all secondary CPUs.
*/
void
mainbus_start_cpus(void)
{
lamebus_start_cpus(lamebus);
}
/*
* Function to generate the memory address (in the uncached segment)
* for the specified offset into the specified slot's region of the
* LAMEbus.
*/
void *
lamebus_map_area(struct lamebus_softc *bus, int slot, uint32_t offset)
{
uint32_t address;
(void)bus; // not needed
KASSERT(slot >= 0 && slot < LB_NSLOTS);
address = LB_BASEADDR + slot*LB_SLOT_SIZE + offset;
return (void *)address;
}
/*
* Read a 32-bit register from a LAMEbus device.
*/
uint32_t
lamebus_read_register(struct lamebus_softc *bus, int slot, uint32_t offset)
{
uint32_t *ptr;
ptr = lamebus_map_area(bus, slot, offset);
/*
* Make sure the load happens after anything the device has
* been doing.
*/
membar_load_load();
return *ptr;
}
/*
* Write a 32-bit register of a LAMEbus device.
*/
void
lamebus_write_register(struct lamebus_softc *bus, int slot,
uint32_t offset, uint32_t val)
{
uint32_t *ptr;
ptr = lamebus_map_area(bus, slot, offset);
*ptr = val;
/*
* Make sure the store happens before we do anything else to
* the device.
*/
membar_store_store();
}
/*
* Power off the system.
*/
void
mainbus_poweroff(void)
{
/*
*
* Note that lamebus_write_register() doesn't actually access
* the bus argument, so this will still work if we get here
* before the bus is initialized.
*/
lamebus_poweroff(lamebus);
}
/*
* Reboot the system.
*/
void
mainbus_reboot(void)
{
/*
* The MIPS doesn't appear to have any on-chip reset.
* LAMEbus doesn't have a reset control, so we just
* power off instead of rebooting. This would not be
* so great in a real system, but it's fine for what
* we're doing.
*/
kprintf("Cannot reboot - powering off instead, sorry.\n");
mainbus_poweroff();
}
/*
* Halt the system.
* On some systems, this would return to the boot monitor. But we don't
* have one.
*/
void
mainbus_halt(void)
{
cpu_halt();
}
/*
* Called to reset the system from panic().
*
* By the time we get here, the system may well be sufficiently hosed
* as to panic recursively if we do much of anything. So just power off.
* (We'd reboot, but System/161 doesn't do that.)
*/
void
mainbus_panic(void)
{
mainbus_poweroff();
}
/*
* Function to get the size of installed physical RAM from the LAMEbus
* controller.
*/
uint32_t
mainbus_ramsize(void)
{
uint32_t ramsize;
ramsize = lamebus_ramsize();
/*
* This is the same as the last physical address, as long as
* we have less than 508 megabytes of memory. The LAMEbus I/O
* area occupies the space between 508 megabytes and 512
* megabytes, so if we had more RAM than this it would have to
* be discontiguous. This is not a case we are going to worry
* about.
*/
if (ramsize > 508*1024*1024) {
ramsize = 508*1024*1024;
}
return ramsize;
}
/*
* Send IPI.
*/
void
mainbus_send_ipi(struct cpu *target)
{
lamebus_assert_ipi(lamebus, target);
}
/*
* Trigger the debugger.
*/
void
mainbus_debugger(void)
{
ltrace_stop(0);
}
/*
* Interrupt dispatcher.
*/
/* Wiring of LAMEbus interrupts to bits in the cause register */
#define LAMEBUS_IRQ_BIT 0x00000400 /* all system bus slots */
#define LAMEBUS_IPI_BIT 0x00000800 /* inter-processor interrupt */
#define MIPS_TIMER_BIT 0x00008000 /* on-chip timer */
void
mainbus_interrupt(struct trapframe *tf)
{
uint32_t cause;
bool seen = false;
/* interrupts should be off */
KASSERT(curthread->t_curspl > 0);
cause = tf->tf_cause;
if (cause & LAMEBUS_IRQ_BIT) {
lamebus_interrupt(lamebus);
seen = true;
}
if (cause & LAMEBUS_IPI_BIT) {
interprocessor_interrupt();
lamebus_clear_ipi(lamebus, curcpu);
seen = true;
}
if (cause & MIPS_TIMER_BIT) {
/* Reset the timer (this clears the interrupt) */
mips_timer_set(CPU_FREQUENCY / HZ);
/* and call hardclock */
hardclock();
seen = true;
}
if (!seen) {
if ((cause & CCA_IRQS) == 0) {
/*
* Don't panic here; this can happen if an
* interrupt line asserts (very) briefly and
* turns off again before we get as far as
* reading the cause register. This was
* actually seen... once.
*/
}
else {
/*
* But if we get an interrupt on an interrupt
* line that's not supposed to be wired up,
* complain.
*/
panic("Unknown interrupt; cause register is %08x\n",
cause);
}
}
}

View File

@ -0,0 +1,60 @@
/*
* 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 _SYS161_BUS_H_
#define _SYS161_BUS_H_
/*
* Generic bus interface file.
*
* The only bus on System/161 is LAMEbus.
* This would need to be a bit more complicated if that weren't the case.
*/
#include <machine/vm.h> /* for MIPS_KSEG1 */
#include <lamebus/lamebus.h> /* for LAMEbus definitions */
#define bus_write_register(bus, slot, offset, val) \
lamebus_write_register(bus, slot, offset, val)
#define bus_read_register(bus, slot, offset) \
lamebus_read_register(bus, slot, offset)
#define bus_map_area(bus, slot, offset) \
lamebus_map_area(bus, slot, offset)
/*
* Machine-dependent LAMEbus definitions
*/
/* Base address of the LAMEbus mapping area */
#define LB_BASEADDR (MIPS_KSEG1 + 0x1fe00000)
#endif /* _SYS161_BUS_H_ */

View 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 _SYS161_MAXCPUS_H_
#define _SYS161_MAXCPUS_H_
/*
* For various reasons (see mips/cpu.c) it's desirable to have a
* fixed-size per-cpu array in the data segment. This is
* platform-dependent rather than processor-dependent because there's
* nothing about the processor that determines how many CPUs can
* exist; however, any real platform has *some* limit. For System/161,
* the limit is 32.
*/
#define MAXCPUS 32
#endif /* _SYS161_MAXCPUS_H_ */

View File

@ -0,0 +1,335 @@
/*
* 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>
.set noreorder
.text
.globl __start
.type __start,@function
.ent __start
__start:
/*
* Stack frame. We save the return address register, even though
* it contains nothing useful. This is for gdb's benefit when it
* comes disassembling. We also need 16 bytes for making a call,
* and we have to align to an 8-byte (64-bit) boundary, so the
* total frame size is 24.
*
* Note that the frame here must match the frame we set up below
* when we switch off the bootup stack. Otherwise, gdb gets very
* confused.
*/
.frame sp, 24, $0 /* 24-byte sp-relative frame; return addr on stack */
.mask 0x80000000, -4 /* register 31 (ra) saved at (sp+24)-4 */
addiu sp, sp, -24
sw ra, 20(sp)
/*
* The System/161 loader sets up a boot stack for the first
* processor at the top of physical memory, and passes us a single
* string argument. The string lives on the very top of the stack.
* We get its address in a0.
*
* The kernel loads at virtual address 0x80000200, which is
* physical address 0x00000200. The space immediately below this
* is reserved for the exception vector code.
*
* The symbol _end is generated by the linker. It's the address of
* the end of the kernel. It's not a variable; the *value* of the
* _end symbol itself is this address. In C you'd use "&_end".
*
* We set up the memory map like this:
*
* top of memory
* free memory
* P + 0x1000
* first thread's stack (1 page)
* P
* wasted space (< 1 page)
* copy of the boot string
* _end
* kernel
* 0x80000200
* exception handlers
* 0x80000000
*
* where P is the next whole page after copying the argument string.
*/
la s0, _end /* stash _end in a saved register */
move a1, a0 /* move bootstring to the second argument */
move a0, s0 /* make _end the first argument */
jal strcpy /* call strcpy(_end, bootstring) */
nop /* delay slot */
move a0, s0 /* make _end the first argument again */
jal strlen /* call strlen(_end) */
nop
add t0, s0, v0 /* add in the length of the string */
addi t0, t0, 1 /* and the null terminator */
addi t0, t0, 4095 /* round up to next page boundary */
li t1, 0xfffff000
and t0, t0, t1
addi t0, t0, 4096 /* add one page to hold the stack */
move sp, t0 /* start the kernel stack for the first thread here */
sw t0, firstfree /* remember the first free page for later */
/*
* At this point, s0 contains the boot argument string, and no other
* registers contain anything interesting (except the stack pointer).
*/
/*
* Now set up a stack frame on the real kernel stack: a dummy saved
* return address and four argument slots for making function calls,
* plus a wasted slot for alignment.
*
* (This needs to match the stack frame set up at the top of the
* function, or the debugger gets confused.)
*/
addiu sp, sp, -24
sw $0, 20(sp)
/*
* Now, copy the exception handler code onto the first page of memory.
*/
li a0, EXADDR_UTLB
la a1, mips_utlb_handler
la a2, mips_utlb_end
sub a2, a2, a1
jal memmove
nop
li a0, EXADDR_GENERAL
la a1, mips_general_handler
la a2, mips_general_end
sub a2, a2, a1
jal memmove
nop
/*
* Flush the instruction cache to make sure the above changes show
* through to instruction fetch.
*/
jal mips_flushicache
nop
/*
* Initialize the TLB.
*/
jal tlb_reset
nop
/*
* Load NULL into the register we use for curthread.
*/
li s7, 0
/*
* Set up the status register.
*
* The MIPS has six hardware interrupt lines and two software interrupts.
* These are individually maskable in the status register. However, we
* don't use this feature (for simplicity) - we only use the master
* interrupt enable/disable flag in bit 0. So enable all of those bits
* now and forget about them.
*
* The BEV bit in the status register, if set, causes the processor to
* jump to a different set of hardwired exception handling addresses.
* This is so that the kernel's exception handling code can be loaded
* into RAM and that the boot ROM's exception handling code can be ROM.
* This flag is normally set at boot time, and we need to be sure to
* clear it.
*
* The KUo/IEo/KUp/IEp/KUc/IEc bits should all start at zero.
*
* We also want all the other random control bits (mostly for cache
* stuff) set to zero.
*
* Thus, the actual value we write is CST_IRQMASK.
*/
li t0, CST_IRQMASK /* get value */
mtc0 t0, c0_status /* set status register */
/*
* Load the CPU number into the PTBASE field of the CONTEXT
* register. This is necessary to read from cpustacks[] and
* cputhreads[] on trap entry from user mode. See further
* discussions elsewhere.
*
* Because the boot CPU is CPU 0, we can just send 0.
*/
mtc0 $0, c0_context
/*
* Load the GP register. This is a MIPS ABI feature; the GP
* register points to an address in the middle of the data segment,
* so data can be accessed relative to GP using one instruction
* instead of the two it takes to set up a full 32-bit address.
*/
la gp, _gp
/*
* We're all set up!
* Fetch the copy of the bootstring as the argument, and call main.
*/
jal kmain
move a0, s0 /* in delay slot */
/*
* kmain shouldn't return. panic.
* Loop back just in case panic returns too.
*/
1:
la a0, panicstr
jal panic
nop /* delay slot */
j 1b
nop /* delay slot */
.end __start
.rdata
panicstr:
.asciz "kmain returned\n"
/*
* CPUs started after the boot CPU come here.
*/
.text
.globl cpu_start_secondary
.type cpu_start_secondary,@function
.ent cpu_start_secondary
cpu_start_secondary:
/*
* When we get here our stack points to the CRAM area of the bus
* controller per-CPU space. This means we can, with a bit of
* caution, call C functions, but nothing very deeply nesting.
* However, we don't need to.
*
* The a0 register contains the value that was put in the second
* word of the CRAM area, which is the (software) cpu number for
* indexing cpustacks[]. None of the other registers contain
* anything useful.
*/
/*
* Stack frame. We save the return address register, even though
* it contains nothing useful. This is for gdb's benefit when it
* comes disassembling. We also need 16 bytes for making a call,
* and 4 bytes for alignment, so the total frame size is 24.
*
* Note that the frame here must match the frame we set up below
* when we switch stacks. Otherwise, gdb gets very confused.
*/
.frame sp, 24, $0 /* 24-byte sp-relative frame; return addr on stack */
.mask 0x80000000, -4 /* register 31 (ra) saved at (sp+24)-4 */
addiu sp, sp, -24
sw ra, 20(sp)
/*
* Fetch the stack out of cpustacks[].
*/
lui t0, %hi(cpustacks) /* load upper half of cpustacks base addr */
sll v0, a0, 2 /* get byte index for array (multiply by 4) */
addu t0, t0, v0 /* add it in */
lw sp, %lo(cpustacks)(t0) /* get the stack pointer */
/*
* Now fetch curthread out of cputhreads[].
*/
lui t0, %hi(cputhreads) /* load upper half of cpustacks base addr */
sll v0, a0, 2 /* get byte index for array (multiply by 4) */
addu t0, t0, v0 /* add it in */
lw s7, %lo(cputhreads)(t0) /* load curthread register */
/*
* Initialize the TLB.
*/
jal tlb_reset
nop
/*
* Set up the status register, as described above.
*/
li t0, CST_IRQMASK /* get value */
mtc0 t0, c0_status /* set status register */
/*
* Load the CPU number into the PTBASE field of the CONTEXT
* register, as described above.
*/
sll v0, a0, CTX_PTBASESHIFT
mtc0 v0, c0_context
/*
* Initialize the on-chip timer interrupt.
*
* This should be set to CPU_FREQUENCY/HZ, but we don't have either
* of those values here, so we'll arbitrarily set it to 100,000. It
* will get reset to the right thing after it first fires.
*/
li v0, 100000
mtc0 v0, c0_compare
/*
* Load the GP register.
*/
la gp, _gp
/*
* Set up a stack frame. Store zero into the return address slot so
* we show as the top of the stack.
*/
addiu sp, sp, -24
sw z0, 20(sp)
/*
* Off to MI code. Pass the cpu number as the argument; it's already
* in the a0 register.
*/
j cpu_hatch
nop /* delay slot for jump */
.end cpu_start_secondary

34
kern/conf/DUMBVM Normal file
View File

@ -0,0 +1,34 @@
# Kernel config file using dumbvm.
# This should be used until you have your own VM system.
include conf/conf.kern # get definitions of available options
debug # Compile with debug info and -Og.
#debugonly # Compile with debug info only (no -Og).
#options hangman # Deadlock detection. (off by default)
#
# Device drivers for hardware.
#
device lamebus0 # System/161 main bus
device emu* at lamebus* # Emulator passthrough filesystem
device ltrace* at lamebus* # trace161 trace control device
device ltimer* at lamebus* # Timer device
device lrandom* at lamebus* # Random device
device lhd* at lamebus* # Disk device
device lser* at lamebus* # Serial port
#device lscreen* at lamebus* # Text screen (not supported yet)
#device lnet* at lamebus* # Network interface (not supported yet)
device beep0 at ltimer* # Abstract beep handler device
device con0 at lser* # Abstract console on serial port
#device con0 at lscreen* # Abstract console on screen (not supported)
device rtclock0 at ltimer* # Abstract realtime clock
device random0 at lrandom* # Abstract randomness device
#options net # Network stack (not supported)
options semfs # Semaphores for userland
options sfs # Always use the file system
#options netfs # You might write this as a project.
options dumbvm # Chewing gum and baling wire.

37
kern/conf/DUMBVM-OPT Normal file
View File

@ -0,0 +1,37 @@
# Kernel config file using dumbvm.
# This should be used until you have your own VM system.
#
# This config builds with optimization for performance testing.
#
include conf/conf.kern # get definitions of available options
#debug # Optimizing compile (no debug).
#debugonly
options noasserts # Disable assertions.
#
# Device drivers for hardware.
#
device lamebus0 # System/161 main bus
device emu* at lamebus* # Emulator passthrough filesystem
device ltrace* at lamebus* # trace161 trace control device
device ltimer* at lamebus* # Timer device
device lrandom* at lamebus* # Random device
device lhd* at lamebus* # Disk device
device lser* at lamebus* # Serial port
#device lscreen* at lamebus* # Text screen (not supported yet)
#device lnet* at lamebus* # Network interface (not supported yet)
device beep0 at ltimer* # Abstract beep handler device
device con0 at lser* # Abstract console on serial port
#device con0 at lscreen* # Abstract console on screen (not supported)
device rtclock0 at ltimer* # Abstract realtime clock
device random0 at lrandom* # Abstract randomness device
#options net # Network stack (not supported)
options semfs # Semaphores for userland
options sfs # Always use the file system
#options netfs # You might write this as a project.
options dumbvm # Chewing gum and baling wire.

35
kern/conf/GENERIC Normal file
View File

@ -0,0 +1,35 @@
# Kernel config file for an ordinary, generic kernel.
# This config file should be used once you start working on
# your own VM system.
include conf/conf.kern # get definitions of available options
debug # Compile with debug info.
#debugonly # Compile with debug info only (no -Og).
#options hangman # Deadlock detection. (off by default)
#
# Device drivers for hardware.
#
device lamebus0 # System/161 main bus
device emu* at lamebus* # Emulator passthrough filesystem
device ltrace* at lamebus* # trace161 trace control device
device ltimer* at lamebus* # Timer device
device lrandom* at lamebus* # Random device
device lhd* at lamebus* # Disk device
device lser* at lamebus* # Serial port
#device lscreen* at lamebus* # Text screen (not supported yet)
#device lnet* at lamebus* # Network interface (not supported yet)
device beep0 at ltimer* # Abstract beep handler device
device con0 at lser* # Abstract console on serial port
#device con0 at lscreen* # Abstract console on screen (not supported)
device rtclock0 at ltimer* # Abstract realtime clock
device random0 at lrandom* # Abstract randomness device
#options net # Network stack (not supported)
options semfs # Semaphores for userland
options sfs # Always use the file system
#options netfs # You might write this as a project.
#options dumbvm # Use your own VM system now.

37
kern/conf/GENERIC-OPT Normal file
View File

@ -0,0 +1,37 @@
# Kernel config file for an ordinary, generic kernel.
# This config file should be used once you start working on
# your own VM system.
#
# This config builds with optimization for performance testing.
include conf/conf.kern # get definitions of available options
#debug # Optimizing compile (no debug).
#debugonly
options noasserts # Disable assertions.
#
# Device drivers for hardware.
#
device lamebus0 # System/161 main bus
device emu* at lamebus* # Emulator passthrough filesystem
device ltrace* at lamebus* # trace161 trace control device
device ltimer* at lamebus* # Timer device
device lrandom* at lamebus* # Random device
device lhd* at lamebus* # Disk device
device lser* at lamebus* # Serial port
#device lscreen* at lamebus* # Text screen (not supported yet)
#device lnet* at lamebus* # Network interface (not supported yet)
device beep0 at ltimer* # Abstract beep handler device
device con0 at lser* # Abstract console on serial port
#device con0 at lscreen* # Abstract console on screen (not supported)
device rtclock0 at ltimer* # Abstract realtime clock
device random0 at lrandom* # Abstract randomness device
#options net # Network stack (not supported)
options semfs # Semaphores for userland
options sfs # Always use the file system
#options netfs # You might write this as a project.
#options dumbvm # Use your own VM system now.

443
kern/conf/conf.kern Normal file
View File

@ -0,0 +1,443 @@
#
# Machine-independent kernel config definitions.
#
# The idea is that the files, options, and facilities in the system
# are declared by conf.kern and the various files it includes. Then a
# kernel config (such as ASST1, or GENERIC, or TEST, or whatever) is
# used to select options and facilities for a particular kernel build.
#
# To add new files to the system, you need to edit this file (or
# others like it) and rerun the config script.
#
# Note: when running the config script, be sure to be in the
# right directory (the same one this file is in) and run it as
# "./config", not just "config" - in the latter case you will
# probably get the host system's kernel config utility, which
# will likely make a mess and produce mysterious error messages.
#
# The documentation for the syntax of these files follows.
#
############################################################
#
# Kernel config file syntax:
#
# The syntax for including the system definition is:
#
# include conf.kern
#
# This should come first. This is because the system must be
# defined before you can do much else useful.
#
# You can also include other files using the same syntax.
#
#
# The syntax for turning on a kernel compile option is:
#
# options optname
#
# A previous "defoption" must have been seen first. See below
# for more information.
#
# The act of compiling with debug info is (has to be) handled
# specially, and is just "debug" without the "options".
#
#
# The syntax for turning on a device driver is:
#
# device foo%
# device foo% at bar%
#
# where the % is either a number or a star, which is treated as
# a wildcard. The first line enables a device foo that is not
# supposed to be "attached" to anything. The second line enables
# a device foo that is attached to a device bar. For more
# information about what this means, see below.
#
#
############################################################
#
# Kernel definition file syntax:
#
# Note: All source file names are relative to the top directory of the
# kernel source, that is, src/kern.
#
# The syntax for adding a regular source file is:
#
# [machine M | platform P] file sourcefile.c
#
# Such a file is always included automatically in every kernel
# built for machine M, or platform P, or all kernels.
#
#
# The syntax for defining optional source files is:
#
# defoption optname
# [machine M | platform P] optfile optname sourcefile.c
# [machine M | platform P] optofffile optname sourcefile.c
#
# "defoption" declares the name of a kernel option. These are
# then turned on by including "options optname" in a
# kernel config.
#
# Source files added with optfile are compiled in if the option
# specified is enabled. Source files added with optofffile are
# compiled in if the option specified is not enabled.
#
# Additionally, a file "opt-optname.h" is created in the compile
# directory, which defines a C preprocessor symbol OPT_OPTNAME.
# This symbol is #defined to either 0 or 1 in the logical way.
# Thus, you can have small bits of code that are enabled or
# disabled by particular options by writing constructs like
#
# #include "opt-foo.h"
# #if OPT_FOO
# code();
# #else
# other_code();
# #endif
#
# *** Be sure to use #if and not #ifdef - you want the value
# of the symbol.
# *** Be sure to remember to include the header file for the
# option - if you don't, cpp will silently assume it is 0,
# which can be quite frustrating.
#
# The defoption must be seen before any optional file
# declarations that use it.
#
#
# The syntax for defining device drivers is:
#
# defdevice devname sourcefile.c
# defattach devname% otherdevname% sourcefile.c
# pseudoattach devname%
#
# Declare a device driver and its "attachment(s)". (The device
# driver can then be selectively included or not included in any
# particular kernel by using the "device" statement in the
# kernel config file.)
#
# The specified source files are only compiled if the device
# is enabled.
#
# The % is either a specific number N, meaning "only the Nth
# such device can be attached this way", or a star (*), meaning
# "any such device can be attached this way".
#
# In OS/161, device drivers are conceptually organized into
# trees. This mimics the organization of real hardware, where
# several expansion cards are plugged into one bus and there
# might be several devices on each expansion card and so forth.
#
# There can be any number of these trees. However, devices at
# the root of each tree must be able to probe and "find"
# themselves completely on their own. This generally means that
# they are either all software with no hardware, or they are the
# system main bus which is located in a machine-dependent way.
#
# Software-only devices are known as "pseudo-devices". These
# are "attached" with the pseudoattach directive; functions
# of the form
#
# pseudoattach_devname
#
# are called from autoconf.c to create instances as requested.
# These calls are made from the function pseudoconfig(), which
# should be called from dev/init.c after hardware device
# initialization completes. The pseudoattach functions should
# perform all setup and initialization necessary. (No
# config_devname function will be called.)
#
# Devices with attachments are automatically probed and
# configured from code in autoconf.c. This file is generated
# by the config script. It contains functions called
# "autoconf_devname", for each device. These functions call
# other functions, which are supplied by device drivers,
# which have the following hardwired names:
#
# attach_devname1_to_devname2
#
# A "devname2" device has been found and configured;
# this function attempts to probe the devname2 for
# a "devname1" device. Returns NULL if nothing was
# found.
#
# config_devname
#
# A "devname" device has been found. This function
# can then perform initialization that's shared
# among all the possible things it can be attached
# to.
#
# The idea is that there can be multiple attachments for
# the same device to different underlying devices. In the
# real world this can be used to great effect when you have,
# for instance, the same ethernet chipset used on both PCI
# and ISA cards - the chipset behaves the same way in both
# cases, but the probe and attach logic is very different.
#
# The attach_foo_to_bar functions are put in the files
# specified with defattach; the config_foo function (and
# generally the rest of the driver for the foo device) is
# put in the file specified with defdevice.
#
# One selects particular attachments when including the device
# in the kernel. A top-level device with no attachments should
# be included with this syntax:
#
# device bar
#
# A pseudo-device should be included with this syntax:
#
# device bar0
#
# To make use of device foo, which can be found attached to
# device bar, one of the following syntaxes is used:
#
# device foo* at bar*
# device foo* at bar0
# device foo0 at bar*
# device foo0 at bar0
#
# depending on to what extent you want to configure only a
# specific device number.
#
# It sometimes matters what order things are handled in; probes
# occur more or less in the order things appear in the config,
# as constrained by the tree structure of the available devices.
#
# Note that OS/161 does not make extensive use of this
# functionality, and the device driver architecture outlined
# here is overkill for such a limited environment as System/161.
# However, it's similar to the way real systems are organized.
#
#
# The syntax for including other config/definition files is:
#
# include filename
#
# The filename is relative to the top of the kernel source tree.
#
# Thus,
# include conf/conf.foo includes src/kern/conf/conf.foo
#
#
############################################################
########################################
# #
# Generic machine-independent devices. #
# #
########################################
#
# These are abstract system services we expect the system hardware to
# provide: beeping, system console I/O, and time of day clock.
#
# These come before the archinclude so that the hardware device
# definitions, which are included from there, can define attachments
# for them.
#
defdevice beep dev/generic/beep.c
defdevice con dev/generic/console.c
defdevice rtclock dev/generic/rtclock.c
defdevice random dev/generic/random.c
########################################
# #
# Machine-dependent stuff #
# #
########################################
#
# Get the definitions for each machine and platform supported. The
# ones used will be selected by make at compile time based on the
# contents of the top-level defs.mk file.
#
# This will declare a bunch of machine-dependent source files and also
# declare all the hardware devices (since what sorts of hardware we
# expect to find is machine-dependent.)
#
include arch/mips/conf/conf.arch
include arch/sys161/conf/conf.arch
########################################
# #
# Support code #
# #
########################################
#
# Kernel utility code
#
file lib/array.c
file lib/bitmap.c
file lib/bswap.c
file lib/kgets.c
file lib/kprintf.c
file lib/misc.c
file lib/time.c
file lib/uio.c
defoption noasserts
#
# Standard C functions
#
# For most of these, we take the source files from our libc. Note
# that those files have to have been hacked a bit to support this.
#
file ../common/libc/printf/__printf.c
file ../common/libc/printf/snprintf.c
file ../common/libc/stdlib/atoi.c
file ../common/libc/string/bzero.c
file ../common/libc/string/memcpy.c
file ../common/libc/string/memmove.c
file ../common/libc/string/memset.c
file ../common/libc/string/strcat.c
file ../common/libc/string/strchr.c
file ../common/libc/string/strcmp.c
file ../common/libc/string/strcpy.c
file ../common/libc/string/strlen.c
file ../common/libc/string/strrchr.c
file ../common/libc/string/strtok_r.c
########################################
# #
# Core kernel source files #
# #
########################################
#
# Thread system
#
file thread/clock.c
file thread/spl.c
file thread/spinlock.c
file thread/synch.c
file thread/thread.c
file thread/threadlist.c
defoption hangman
optfile hangman thread/hangman.c
#
# Process system
#
file proc/proc.c
#
# Virtual memory system
# (you will probably want to add stuff here while doing the VM assignment)
#
file vm/kmalloc.c
optofffile dumbvm vm/addrspace.c
#
# Network
# (nothing here yet)
#
defoption net
#optfile net net/net.c
#
# VFS layer
#
file vfs/device.c
file vfs/vfscwd.c
file vfs/vfsfail.c
file vfs/vfslist.c
file vfs/vfslookup.c
file vfs/vfspath.c
file vfs/vnode.c
#
# VFS devices
#
file vfs/devnull.c
#
# System call layer
# (You will probably want to add stuff here while doing the basic system
# calls assignment.)
#
file syscall/loadelf.c
file syscall/runprogram.c
file syscall/time_syscalls.c
#
# Startup and initialization
#
file main/main.c
file main/menu.c
########################################
# #
# Filesystems #
# #
########################################
#
# semfs (fake filesystem providing userlevel semaphores)
#
defoption semfs
optfile semfs fs/semfs/semfs_fsops.c
optfile semfs fs/semfs/semfs_obj.c
optfile semfs fs/semfs/semfs_vnops.c
#
# sfs (the small/simple filesystem)
#
defoption sfs
optfile sfs fs/sfs/sfs_balloc.c
optfile sfs fs/sfs/sfs_bmap.c
optfile sfs fs/sfs/sfs_dir.c
optfile sfs fs/sfs/sfs_fsops.c
optfile sfs fs/sfs/sfs_inode.c
optfile sfs fs/sfs/sfs_io.c
optfile sfs fs/sfs/sfs_vnops.c
#
# netfs (the networked filesystem - you might write this as one assignment)
#
defoption netfs
#optfile netfs fs/netfs/netfs_fs.c # or whatever
#
# Note that "emufs" is completely contained in the "emu" device.
#
########################################
# #
# Test code #
# #
########################################
file test/arraytest.c
file test/bitmaptest.c
file test/threadlisttest.c
file test/threadtest.c
file test/tt3.c
file test/synchtest.c
file test/semunit.c
file test/kmalloctest.c
file test/fstest.c
optfile net test/nettest.c

1068
kern/conf/config Executable file

File diff suppressed because it is too large Load Diff

67
kern/conf/newvers.sh Executable file
View File

@ -0,0 +1,67 @@
#!/bin/sh
#
# newvers.sh - increment build number in current directory (a build directory)
# and emit vers.c.
# The build number is kept in the file "version".
#
# Usage: newvers.sh CONFIGNAME
#
# 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.
#
if [ ! -f autoconf.c ]; then
#
# If there's no file autoconf.c, we are in the wrong place.
#
echo "$0: Not in a kernel build directory"
exit 1
fi
if [ "x$1" = x ]; then
echo "Usage: $0 CONFIGNAME"
exit 1
fi
CONFIG="$1"
#
# Get and increment the version number
#
VERS=`cat version 2>/dev/null || echo 0`
VERS=`expr $VERS + 1`
echo "$VERS" > version
#
# Write vers.c
#
echo '/* This file is automatically generated. Edits will be lost.*/' > vers.c
echo "const int buildversion = $VERS;" >> vers.c
echo 'const char buildconfig[] = "'"$CONFIG"'";' >> vers.c

71
kern/dev/generic/beep.c Normal file
View File

@ -0,0 +1,71 @@
/*
* 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 <generic/beep.h>
#include "autoconf.h"
/*
* Machine-independent generic beep "device".
*
* Basically, all we do is remember something that can be used for
* beeping, and provide the beep() function to the rest of the kernel.
*
* The kernel config mechanism can be used to explicitly choose which
* of the available beeping devices to use, if more than one is
* available.
*/
static struct beep_softc *the_beep = NULL;
int
config_beep(struct beep_softc *bs, int unit)
{
/* We use only the first beep device. */
if (unit!=0) {
return ENODEV;
}
KASSERT(the_beep==NULL);
the_beep = bs;
return 0;
}
void
beep(void)
{
if (the_beep!=NULL) {
the_beep->bs_beep(the_beep->bs_devdata);
}
else {
kprintf("beep: Warning: no beep device\n");
}
}

43
kern/dev/generic/beep.h Normal file
View File

@ -0,0 +1,43 @@
/*
* 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 _GENERIC_BEEP_H_
#define _GENERIC_BEEP_H_
/*
* The device info for the generic MI beep device - a function
* to call and a context pointer for it.
*/
struct beep_softc {
void *bs_devdata;
void (*bs_beep)(void *devdata);
};
#endif /* _GENERIC_BEEP_H_ */

397
kern/dev/generic/console.c Normal file
View File

@ -0,0 +1,397 @@
/*
* 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.
*/
/*
* Machine (and hardware) independent console driver.
*
* We expose a simple interface to the rest of the kernel: "putch" to
* print a character, "getch" to read one.
*
* As long as the device we're connected to does, we allow printing in
* an interrupt handler or with interrupts off (by polling),
* transparently to the caller. Note that getch by polling is not
* supported, although such support could be added without undue
* difficulty.
*
* Note that nothing happens until we have a device to write to. A
* buffer of size DELAYBUFSIZE is used to hold output that is
* generated before this point. This means that (1) using kprintf for
* debugging problems that occur early in initialization is awkward,
* and (2) if the system crashes before we find a console, no output
* at all may appear.
*/
#include <types.h>
#include <kern/errno.h>
#include <lib.h>
#include <uio.h>
#include <cpu.h>
#include <thread.h>
#include <current.h>
#include <synch.h>
#include <generic/console.h>
#include <vfs.h>
#include <device.h>
#include "autoconf.h"
/*
* The console device.
*/
static struct con_softc *the_console = NULL;
/*
* Lock so user I/Os are atomic.
* We use two locks so readers waiting for input don't lock out writers.
*/
static struct lock *con_userlock_read = NULL;
static struct lock *con_userlock_write = NULL;
//////////////////////////////////////////////////
/*
* This is for accumulating characters printed before the
* console is set up. Upon console setup they are dumped
* to the actual console; thenceforth this space is unused.
*/
#define DELAYBUFSIZE 1024
static char delayed_outbuf[DELAYBUFSIZE];
static size_t delayed_outbuf_pos=0;
static
void
putch_delayed(int ch)
{
/*
* No synchronization needed: called only during system startup
* by main thread.
*/
KASSERT(delayed_outbuf_pos < sizeof(delayed_outbuf));
delayed_outbuf[delayed_outbuf_pos++] = ch;
}
static
void
flush_delay_buf(void)
{
size_t i;
for (i=0; i<delayed_outbuf_pos; i++) {
putch(delayed_outbuf[i]);
}
delayed_outbuf_pos = 0;
}
//////////////////////////////////////////////////
/*
* Print a character, using polling instead of interrupts to wait for
* I/O completion.
*/
static
void
putch_polled(struct con_softc *cs, int ch)
{
cs->cs_sendpolled(cs->cs_devdata, ch);
}
//////////////////////////////////////////////////
/*
* Print a character, using interrupts to wait for I/O completion.
*/
static
void
putch_intr(struct con_softc *cs, int ch)
{
P(cs->cs_wsem);
cs->cs_send(cs->cs_devdata, ch);
}
/*
* Read a character, using interrupts to wait for I/O completion.
*/
static
int
getch_intr(struct con_softc *cs)
{
unsigned char ret;
P(cs->cs_rsem);
ret = cs->cs_gotchars[cs->cs_gotchars_tail];
cs->cs_gotchars_tail =
(cs->cs_gotchars_tail + 1) % CONSOLE_INPUT_BUFFER_SIZE;
return ret;
}
/*
* Called from underlying device when a read-ready interrupt occurs.
*
* Note: if gotchars_head == gotchars_tail, the buffer is empty. Thus
* if gotchars_head+1 == gotchars_tail, the buffer is full. A slightly
* tidier way to implement this check (that avoids wasting a slot,
* too) would be with a second semaphore used with a nonblocking P,
* but we don't have that in OS/161.
*/
void
con_input(void *vcs, int ch)
{
struct con_softc *cs = vcs;
unsigned nexthead;
nexthead = (cs->cs_gotchars_head + 1) % CONSOLE_INPUT_BUFFER_SIZE;
if (nexthead == cs->cs_gotchars_tail) {
/* overflow; drop character */
return;
}
cs->cs_gotchars[cs->cs_gotchars_head] = ch;
cs->cs_gotchars_head = nexthead;
V(cs->cs_rsem);
}
/*
* Called from underlying device when a write-done interrupt occurs.
*/
void
con_start(void *vcs)
{
struct con_softc *cs = vcs;
V(cs->cs_wsem);
}
//////////////////////////////////////////////////
/*
* Exported interface.
*
* Warning: putch must work even in an interrupt handler or with
* interrupts disabled, and before the console is probed. getch need
* not, and does not.
*/
void
putch(int ch)
{
struct con_softc *cs = the_console;
if (cs==NULL) {
putch_delayed(ch);
}
else if (curthread->t_in_interrupt ||
curthread->t_curspl > 0 ||
curcpu->c_spinlocks > 0) {
putch_polled(cs, ch);
}
else {
putch_intr(cs, ch);
}
}
int
getch(void)
{
struct con_softc *cs = the_console;
KASSERT(cs != NULL);
KASSERT(!curthread->t_in_interrupt && curthread->t_iplhigh_count == 0);
return getch_intr(cs);
}
////////////////////////////////////////////////////////////
/*
* VFS interface functions
*/
static
int
con_eachopen(struct device *dev, int openflags)
{
(void)dev;
(void)openflags;
return 0;
}
static
int
con_io(struct device *dev, struct uio *uio)
{
int result;
char ch;
struct lock *lk;
(void)dev; // unused
if (uio->uio_rw==UIO_READ) {
lk = con_userlock_read;
}
else {
lk = con_userlock_write;
}
KASSERT(lk != NULL);
lock_acquire(lk);
while (uio->uio_resid > 0) {
if (uio->uio_rw==UIO_READ) {
ch = getch();
if (ch=='\r') {
ch = '\n';
}
result = uiomove(&ch, 1, uio);
if (result) {
lock_release(lk);
return result;
}
if (ch=='\n') {
break;
}
}
else {
result = uiomove(&ch, 1, uio);
if (result) {
lock_release(lk);
return result;
}
if (ch=='\n') {
putch('\r');
}
putch(ch);
}
}
lock_release(lk);
return 0;
}
static
int
con_ioctl(struct device *dev, int op, userptr_t data)
{
/* No ioctls. */
(void)dev;
(void)op;
(void)data;
return EINVAL;
}
static const struct device_ops console_devops = {
.devop_eachopen = con_eachopen,
.devop_io = con_io,
.devop_ioctl = con_ioctl,
};
static
int
attach_console_to_vfs(struct con_softc *cs)
{
struct device *dev;
int result;
dev = kmalloc(sizeof(*dev));
if (dev==NULL) {
return ENOMEM;
}
dev->d_ops = &console_devops;
dev->d_blocks = 0;
dev->d_blocksize = 1;
dev->d_data = cs;
result = vfs_adddev("con", dev, 0);
if (result) {
kfree(dev);
return result;
}
return 0;
}
////////////////////////////////////////////////////////////
/*
* Config routine called by autoconf.c after we are attached to something.
*/
int
config_con(struct con_softc *cs, int unit)
{
struct semaphore *rsem, *wsem;
struct lock *rlk, *wlk;
/*
* Only allow one system console.
* Further devices that could be the system console are ignored.
*
* Do not hardwire the console to be "con1" instead of "con0",
* or these asserts will go off.
*/
if (unit>0) {
KASSERT(the_console!=NULL);
return ENODEV;
}
KASSERT(the_console==NULL);
rsem = sem_create("console read", 0);
if (rsem == NULL) {
return ENOMEM;
}
wsem = sem_create("console write", 1);
if (wsem == NULL) {
sem_destroy(rsem);
return ENOMEM;
}
rlk = lock_create("console-lock-read");
if (rlk == NULL) {
sem_destroy(rsem);
sem_destroy(wsem);
return ENOMEM;
}
wlk = lock_create("console-lock-write");
if (wlk == NULL) {
lock_destroy(rlk);
sem_destroy(rsem);
sem_destroy(wsem);
return ENOMEM;
}
cs->cs_rsem = rsem;
cs->cs_wsem = wsem;
cs->cs_gotchars_head = 0;
cs->cs_gotchars_tail = 0;
the_console = cs;
con_userlock_read = rlk;
con_userlock_write = wlk;
flush_delay_buf();
return attach_console_to_vfs(cs);
}

View 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.
*/
#ifndef _GENERIC_CONSOLE_H_
#define _GENERIC_CONSOLE_H_
/*
* Device data for the hardware-independent system console.
*
* devdata, send, and sendpolled are provided by the underlying
* device, and are to be initialized by the attach routine.
*/
#define CONSOLE_INPUT_BUFFER_SIZE 32
struct con_softc {
/* initialized by attach routine */
void *cs_devdata;
void (*cs_send)(void *devdata, int ch);
void (*cs_sendpolled)(void *devdata, int ch);
/* initialized by config routine */
struct semaphore *cs_rsem;
struct semaphore *cs_wsem;
unsigned char cs_gotchars[CONSOLE_INPUT_BUFFER_SIZE];
unsigned cs_gotchars_head; /* next slot to put a char in */
unsigned cs_gotchars_tail; /* next slot to take a char out */
};
/*
* Functions called by lower-level drivers
*/
void con_input(/*struct con_softc*/ void *cs, int ch);
void con_start(/*struct con_softc*/ void *cs);
/*
* Functions called by higher-level code
*
* putch/getch - see <lib.h>
*/
#endif /* _GENERIC_CONSOLE_H_ */

158
kern/dev/generic/random.c Normal file
View File

@ -0,0 +1,158 @@
/*
* 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/fcntl.h>
#include <lib.h>
#include <uio.h>
#include <vfs.h>
#include <generic/random.h>
#include "autoconf.h"
/*
* Machine-independent generic randomness device.
*
* Remembers something that's a random source, and provides random()
* and randmax() to the rest of the kernel.
*
* The kernel config mechanism can be used to explicitly choose which
* of the available random sources to use, if more than one is
* available.
*/
static struct random_softc *the_random = NULL;
/*
* VFS device functions.
* open: allow reading only.
*/
static
int
randeachopen(struct device *dev, int openflags)
{
(void)dev;
if (openflags != O_RDONLY) {
return EIO;
}
return 0;
}
/*
* VFS I/O function. Hand off to implementation.
*/
static
int
randio(struct device *dev, struct uio *uio)
{
struct random_softc *rs = dev->d_data;
if (uio->uio_rw != UIO_READ) {
return EIO;
}
return rs->rs_read(rs->rs_devdata, uio);
}
/*
* VFS ioctl function.
*/
static
int
randioctl(struct device *dev, int op, userptr_t data)
{
/*
* We don't support any ioctls.
*/
(void)dev;
(void)op;
(void)data;
return EIOCTL;
}
static const struct device_ops random_devops = {
.devop_eachopen = randeachopen,
.devop_io = randio,
.devop_ioctl = randioctl,
};
/*
* Config function.
*/
int
config_random(struct random_softc *rs, int unit)
{
int result;
/* We use only the first random device. */
if (unit!=0) {
return ENODEV;
}
KASSERT(the_random==NULL);
the_random = rs;
rs->rs_dev.d_ops = &random_devops;
rs->rs_dev.d_blocks = 0;
rs->rs_dev.d_blocksize = 1;
rs->rs_dev.d_data = rs;
/* Add the VFS device structure to the VFS device list. */
result = vfs_adddev("random", &rs->rs_dev, 0);
if (result) {
return result;
}
return 0;
}
/*
* Random number functions exported to the rest of the kernel.
*/
uint32_t
random(void)
{
if (the_random==NULL) {
panic("No random device\n");
}
return the_random->rs_random(the_random->rs_devdata);
}
uint32_t
randmax(void)
{
if (the_random==NULL) {
panic("No random device\n");
}
return the_random->rs_randmax(the_random->rs_devdata);
}

46
kern/dev/generic/random.h Normal file
View 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 _GENERIC_RANDOM_H_
#define _GENERIC_RANDOM_H_
#include <device.h>
struct uio;
struct random_softc {
/* Initialized by lower-level attach routine */
void *rs_devdata;
uint32_t (*rs_random)(void *devdata);
uint32_t (*rs_randmax)(void *devdata);
int (*rs_read)(void *devdata, struct uio *uio);
struct device rs_dev;
};
#endif /* _GENERIC_RANDOM_H_ */

View File

@ -0,0 +1,70 @@
/*
* 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.
*/
/*
* Machine-independent generic clock "device".
*
* Basically, all we do is remember something that can be used for
* handling requests for the current time, and provide the gettime()
* function to the rest of the kernel.
*
* The kernel config mechanism can be used to explicitly choose which
* of the available clocks to use, if more than one is available.
*
* The system will panic if gettime() is called and there is no clock.
*/
#include <types.h>
#include <kern/errno.h>
#include <lib.h>
#include <clock.h>
#include <generic/rtclock.h>
#include "autoconf.h"
static struct rtclock_softc *the_clock = NULL;
int
config_rtclock(struct rtclock_softc *rtc, int unit)
{
/* We use only the first clock device. */
if (unit!=0) {
return ENODEV;
}
KASSERT(the_clock==NULL);
the_clock = rtc;
return 0;
}
void
gettime(struct timespec *ts)
{
KASSERT(the_clock!=NULL);
the_clock->rtc_gettime(the_clock->rtc_devdata, ts);
}

View File

@ -0,0 +1,45 @@
/*
* 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 _GENERIC_RTCLOCK_H_
#define _GENERIC_RTCLOCK_H_
/*
* The device info for the generic MI clock device - a function
* to call and a context pointer for it.
*/
struct timespec;
struct rtclock_softc {
void *rtc_devdata;
void (*rtc_gettime)(void *devdata, struct timespec *);
};
#endif /* _GENERIC_RTCLOCK_H_ */

View File

@ -0,0 +1,55 @@
/*
* 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.
*/
/*
* Attachment code for having the generic beep device use the LAMEbus
* ltimer device for beeping.
*/
#include <types.h>
#include <lib.h>
#include <generic/beep.h>
#include <lamebus/ltimer.h>
#include "autoconf.h"
struct beep_softc *
attach_beep_to_ltimer(int beepno, struct ltimer_softc *ls)
{
struct beep_softc *bs = kmalloc(sizeof(struct beep_softc));
if (bs==NULL) {
return NULL;
}
(void)beepno; // unused
bs->bs_devdata = ls;
bs->bs_beep = ltimer_beep;
return bs;
}

View File

@ -0,0 +1,59 @@
/*
* 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.
*/
/*
* Attachment code for having the generic console device use the LAMEbus
* screen device.
*/
#include <types.h>
#include <lib.h>
#include <generic/console.h>
#include <lamebus/lscreen.h>
#include "autoconf.h"
struct con_softc *
attach_con_to_lscreen(int consno, struct lscreen_softc *ls)
{
struct con_softc *cs = kmalloc(sizeof(struct con_softc));
if (cs==NULL) {
return NULL;
}
cs->cs_devdata = ls;
cs->cs_send = lscreen_write;
cs->cs_sendpolled = lscreen_write;
ls->ls_devdata = cs;
ls->ls_start = con_start;
ls->ls_input = con_input;
return cs;
}

View File

@ -0,0 +1,61 @@
/*
* 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.
*/
/*
* Attachment code for having the generic console device use the LAMEbus
* serial device.
*/
#include <types.h>
#include <lib.h>
#include <generic/console.h>
#include <lamebus/lser.h>
#include "autoconf.h"
struct con_softc *
attach_con_to_lser(int consno, struct lser_softc *ls)
{
struct con_softc *cs = kmalloc(sizeof(struct con_softc));
if (cs==NULL) {
return NULL;
}
(void)consno; // unused
cs->cs_devdata = ls;
cs->cs_send = lser_write;
cs->cs_sendpolled = lser_writepolled;
ls->ls_devdata = cs;
ls->ls_start = con_start;
ls->ls_input = con_input;
return cs;
}

View File

@ -0,0 +1,57 @@
#
# Kernel config definitions for LAMEbus devices.
#
# See conf/conf.kern for more information.
#
# System main bus.
defdevice lamebus dev/lamebus/lamebus.c
# Timer.
defdevice ltimer dev/lamebus/ltimer.c
defattach ltimer* lamebus* dev/lamebus/ltimer_att.c
# Random.
defdevice lrandom dev/lamebus/lrandom.c
defattach lrandom* lamebus* dev/lamebus/lrandom_att.c
# Disk.
defdevice lhd dev/lamebus/lhd.c
defattach lhd* lamebus* dev/lamebus/lhd_att.c
# Serial port.
defdevice lser dev/lamebus/lser.c
defattach lser* lamebus* dev/lamebus/lser_att.c
# Text screen.
defdevice lscreen dev/lamebus/lscreen.c
defattach lscreen* lamebus* dev/lamebus/lscreen_att.c
# Network interface.
defdevice lnet dev/lamebus/lnet.c
defattach lnet* lamebus* dev/lamebus/lnet_att.c
# Trace control device.
defdevice ltrace dev/lamebus/ltrace.c
defattach ltrace* lamebus* dev/lamebus/ltrace_att.c
# Emulator passthrough filesystem.
defdevice emu dev/lamebus/emu.c
defattach emu* lamebus* dev/lamebus/emu_att.c
#
# Attachments to generic interface devices
#
# Consoles.
defattach con0 lser* dev/lamebus/con_lser.c
defattach con0 lscreen* dev/lamebus/con_lscreen.c
# Beeper.
defattach beep* ltimer* dev/lamebus/beep_ltimer.c
# Clock.
defattach rtclock* ltimer* dev/lamebus/rtclock_ltimer.c
# Random.
defattach random0 lrandom* dev/lamebus/random_lrandom.c

1357
kern/dev/lamebus/emu.c Normal file

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More