add lab4 spoc discuss

This commit is contained in:
yuchen
2015-04-15 11:23:03 +08:00
parent 391e04ee98
commit 258bcb059e
65 changed files with 8589 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
OUTPUT_FORMAT("elf32-i386")
OUTPUT_ARCH(i386)
SECTIONS {
. = 0x7C00;
.startup : {
*bootasm.o(.text)
}
.text : { *(.text) }
.data : { *(.data .rodata) }
/DISCARD/ : { *(.eh_*) }
}

View File

@@ -0,0 +1,95 @@
OBJPREFIX := __objs_
.SECONDEXPANSION:
# -------------------- function begin --------------------
# list all files in some directories: (#directories, #types)
listf = $(filter $(if $(2),$(addprefix %.,$(2)),%),\
$(wildcard $(addsuffix $(SLASH)*,$(1))))
# get .o obj files: (#files[, packet])
toobj = $(addprefix $(OBJDIR)$(SLASH)$(if $(2),$(2)$(SLASH)),\
$(addsuffix .o,$(basename $(1))))
# get .d dependency files: (#files[, packet])
todep = $(patsubst %.o,%.d,$(call toobj,$(1),$(2)))
totarget = $(addprefix $(BINDIR)$(SLASH),$(1))
# change $(name) to $(OBJPREFIX)$(name): (#names)
packetname = $(if $(1),$(addprefix $(OBJPREFIX),$(1)),$(OBJPREFIX))
# cc compile template, generate rule for dep, obj: (file, cc[, flags, dir])
define cc_template
$$(call todep,$(1),$(4)): $(1) | $$$$(dir $$$$@)
@$(2) -I$$(dir $(1)) $(3) -MM $$< -MT "$$(patsubst %.d,%.o,$$@) $$@"> $$@
$$(call toobj,$(1),$(4)): $(1) | $$$$(dir $$$$@)
@echo + cc $$<
$(V)$(2) -I$$(dir $(1)) $(3) -c $$< -o $$@
ALLOBJS += $$(call toobj,$(1),$(4))
endef
# compile file: (#files, cc[, flags, dir])
define do_cc_compile
$$(foreach f,$(1),$$(eval $$(call cc_template,$$(f),$(2),$(3),$(4))))
endef
# add files to packet: (#files, cc[, flags, packet, dir])
define do_add_files_to_packet
__temp_packet__ := $(call packetname,$(4))
ifeq ($$(origin $$(__temp_packet__)),undefined)
$$(__temp_packet__) :=
endif
__temp_objs__ := $(call toobj,$(1),$(5))
$$(foreach f,$(1),$$(eval $$(call cc_template,$$(f),$(2),$(3),$(5))))
$$(__temp_packet__) += $$(__temp_objs__)
endef
# add objs to packet: (#objs, packet)
define do_add_objs_to_packet
__temp_packet__ := $(call packetname,$(2))
ifeq ($$(origin $$(__temp_packet__)),undefined)
$$(__temp_packet__) :=
endif
$$(__temp_packet__) += $(1)
endef
# add packets and objs to target (target, #packes, #objs[, cc, flags])
define do_create_target
__temp_target__ = $(call totarget,$(1))
__temp_objs__ = $$(foreach p,$(call packetname,$(2)),$$($$(p))) $(3)
TARGETS += $$(__temp_target__)
ifneq ($(4),)
$$(__temp_target__): $$(__temp_objs__) | $$$$(dir $$$$@)
$(V)$(4) $(5) $$^ -o $$@
else
$$(__temp_target__): $$(__temp_objs__) | $$$$(dir $$$$@)
endif
endef
# finish all
define do_finish_all
ALLDEPS = $$(ALLOBJS:.o=.d)
$$(sort $$(dir $$(ALLOBJS)) $(BINDIR)$(SLASH) $(OBJDIR)$(SLASH)):
@$(MKDIR) $$@
endef
# -------------------- function end --------------------
# compile file: (#files, cc[, flags, dir])
cc_compile = $(eval $(call do_cc_compile,$(1),$(2),$(3),$(4)))
# add files to packet: (#files, cc[, flags, packet, dir])
add_files = $(eval $(call do_add_files_to_packet,$(1),$(2),$(3),$(4),$(5)))
# add objs to packet: (#objs, packet)
add_objs = $(eval $(call do_add_objs_to_packet,$(1),$(2)))
# add packets and objs to target (target, #packes, #objs, cc, [, flags])
create_target = $(eval $(call do_create_target,$(1),$(2),$(3),$(4),$(5)))
read_packet = $(foreach p,$(call packetname,$(1)),$($(p)))
add_dependency = $(eval $(1): $(2))
finish_all = $(eval $(call do_finish_all))

View File

@@ -0,0 +1,3 @@
file bin/kernel
target remote :1234
break kern_init

View File

@@ -0,0 +1,373 @@
#!/bin/sh
verbose=false
if [ "x$1" = "x-v" ]; then
verbose=true
out=/dev/stdout
err=/dev/stderr
else
out=/dev/null
err=/dev/null
fi
## make & makeopts
if gmake --version > /dev/null 2>&1; then
make=gmake;
else
make=make;
fi
makeopts="--quiet --no-print-directory -j"
make_print() {
echo `$make $makeopts print-$1`
}
## command tools
awk='awk'
bc='bc'
date='date'
grep='grep'
rm='rm -f'
sed='sed'
## symbol table
sym_table='obj/kernel.sym'
## gdb & gdbopts
gdb="$(make_print GDB)"
gdbport='1234'
gdb_in="$(make_print GRADE_GDB_IN)"
## qemu & qemuopts
qemu="$(make_print qemu)"
qemu_out="$(make_print GRADE_QEMU_OUT)"
if $qemu -nographic -help | grep -q '^-gdb'; then
qemugdb="-gdb tcp::$gdbport"
else
qemugdb="-s -p $gdbport"
fi
## default variables
default_timeout=30
default_pts=5
pts=5
part=0
part_pos=0
total=0
total_pos=0
## default functions
update_score() {
total=`expr $total + $part`
total_pos=`expr $total_pos + $part_pos`
part=0
part_pos=0
}
get_time() {
echo `$date +%s.%N 2> /dev/null`
}
show_part() {
echo "Part $1 Score: $part/$part_pos"
echo
update_score
}
show_final() {
update_score
echo "Total Score: $total/$total_pos"
if [ $total -lt $total_pos ]; then
exit 1
fi
}
show_time() {
t1=$(get_time)
time=`echo "scale=1; ($t1-$t0)/1" | $sed 's/.N/.0/g' | $bc 2> /dev/null`
echo "(${time}s)"
}
show_build_tag() {
echo "$1:" | $awk '{printf "%-24s ", $0}'
}
show_check_tag() {
echo "$1:" | $awk '{printf " -%-40s ", $0}'
}
show_msg() {
echo $1
shift
if [ $# -gt 0 ]; then
echo -e "$@" | awk '{printf " %s\n", $0}'
echo
fi
}
pass() {
show_msg OK "$@"
part=`expr $part + $pts`
part_pos=`expr $part_pos + $pts`
}
fail() {
show_msg WRONG "$@"
part_pos=`expr $part_pos + $pts`
}
run_qemu() {
# Run qemu with serial output redirected to $qemu_out. If $brkfun is non-empty,
# wait until $brkfun is reached or $timeout expires, then kill QEMU
qemuextra=
if [ "$brkfun" ]; then
qemuextra="-S $qemugdb"
fi
if [ -z "$timeout" ] || [ $timeout -le 0 ]; then
timeout=$default_timeout;
fi
t0=$(get_time)
(
ulimit -t $timeout
exec $qemu -nographic $qemuopts -serial file:$qemu_out -monitor null -no-reboot $qemuextra
) > $out 2> $err &
pid=$!
# wait for QEMU to start
sleep 1
if [ -n "$brkfun" ]; then
# find the address of the kernel $brkfun function
brkaddr=`$grep " $brkfun\$" $sym_table | $sed -e's/ .*$//g'`
brkaddr_phys=`echo $brkaddr | sed "s/^c0/00/g"`
(
echo "target remote localhost:$gdbport"
echo "break *0x$brkaddr"
if [ "$brkaddr" != "$brkaddr_phys" ]; then
echo "break *0x$brkaddr_phys"
fi
echo "continue"
) > $gdb_in
$gdb -batch -nx -x $gdb_in > /dev/null 2>&1
# make sure that QEMU is dead
# on OS X, exiting gdb doesn't always exit qemu
kill $pid > /dev/null 2>&1
fi
}
build_run() {
# usage: build_run <tag> <args>
show_build_tag "$1"
shift
if $verbose; then
echo "$make $@ ..."
fi
$make $makeopts $@ 'DEFS+=-DDEBUG_GRADE' > $out 2> $err
if [ $? -ne 0 ]; then
echo $make $@ failed
exit 1
fi
# now run qemu and save the output
run_qemu
show_time
cp $qemu_out .`echo $tag | tr '[:upper:]' '[:lower:]' | sed 's/ /_/g'`.log
}
check_result() {
# usage: check_result <tag> <check> <check args...>
show_check_tag "$1"
shift
# give qemu some time to run (for asynchronous mode)
if [ ! -s $qemu_out ]; then
sleep 4
fi
if [ ! -s $qemu_out ]; then
fail > /dev/null
echo 'no $qemu_out'
else
check=$1
shift
$check "$@"
fi
}
check_regexps() {
okay=yes
not=0
reg=0
error=
for i do
if [ "x$i" = "x!" ]; then
not=1
elif [ "x$i" = "x-" ]; then
reg=1
else
if [ $reg -ne 0 ]; then
$grep '-E' "^$i\$" $qemu_out > /dev/null
else
$grep '-F' "$i" $qemu_out > /dev/null
fi
found=$(($? == 0))
if [ $found -eq $not ]; then
if [ $found -eq 0 ]; then
msg="!! error: missing '$i'"
else
msg="!! error: got unexpected line '$i'"
fi
okay=no
if [ -z "$error" ]; then
error="$msg"
else
error="$error\n$msg"
fi
fi
not=0
reg=0
fi
done
if [ "$okay" = "yes" ]; then
pass
else
fail "$error"
if $verbose; then
exit 1
fi
fi
}
run_test() {
# usage: run_test [-tag <tag>] [-Ddef...] [-check <check>] checkargs ...
tag=
check=check_regexps
while true; do
select=
case $1 in
-tag)
select=`expr substr $1 2 ${#1}`
eval $select='$2'
;;
esac
if [ -z "$select" ]; then
break
fi
shift
shift
done
defs=
while expr "x$1" : "x-D.*" > /dev/null; do
defs="DEFS+='$1' $defs"
shift
done
if [ "x$1" = "x-check" ]; then
check=$2
shift
shift
fi
$make $makeopts touch > /dev/null 2>&1
build_run "$tag" "$defs"
check_result 'check result' "$check" "$@"
}
quick_run() {
# usage: quick_run <tag> [-Ddef...]
tag="$1"
shift
defs=
while expr "x$1" : "x-D.*" > /dev/null; do
defs="DEFS+='$1' $defs"
shift
done
$make $makeopts touch > /dev/null 2>&1
build_run "$tag" "$defs"
}
quick_check() {
# usage: quick_check <tag> checkargs ...
tag="$1"
shift
check_result "$tag" check_regexps "$@"
}
## kernel image
osimg=$(make_print ucoreimg)
## swap image
swapimg=$(make_print swapimg)
## set default qemu-options
qemuopts="-hda $osimg -drive file=$swapimg,media=disk,cache=writeback"
## set break-function, default is readline
brkfun=readline
## check now!!
quick_run 'Check VMM'
pts=5
quick_check 'check pmm' \
'memory management: default_pmm_manager' \
'check_alloc_page() succeeded!' \
'check_pgdir() succeeded!' \
'check_boot_pgdir() succeeded!'
pts=5
quick_check 'check page table' \
'PDE(0e0) c0000000-f8000000 38000000 urw' \
' |-- PTE(38000) c0000000-f8000000 38000000 -rw' \
'PDE(001) fac00000-fb000000 00400000 -rw' \
' |-- PTE(000e0) faf00000-fafe0000 000e0000 urw' \
' |-- PTE(00001) fafeb000-fafec000 00001000 -rw'
pts=25
quick_check 'check vmm' \
'check_vma_struct() succeeded!' \
'page fault at 0x00000100: K/W [no page found].' \
'check_pgfault() succeeded!' \
'check_vmm() succeeded.'
pts=20
quick_check 'check swap page fault' \
'page fault at 0x00001000: K/W [no page found].' \
'page fault at 0x00002000: K/W [no page found].' \
'page fault at 0x00003000: K/W [no page found].' \
'page fault at 0x00004000: K/W [no page found].' \
'write Virt Page e in fifo_check_swap' \
'page fault at 0x00005000: K/W [no page found].' \
'page fault at 0x00001000: K/W [no page found]' \
'page fault at 0x00002000: K/W [no page found].' \
'page fault at 0x00003000: K/W [no page found].' \
'page fault at 0x00004000: K/W [no page found].' \
'check_swap() succeeded!'
pts=5
quick_check 'check ticks' \
'++ setup timer interrupts'
pts=30
quick_check 'check initproc' \
'this initproc, pid = 1, name = "init"' \
'To U: "Hello world!!".' \
'To U: "en.., Bye, Bye. :)"'
## print final-score
show_final

View File

@@ -0,0 +1,58 @@
/* Simple linker script for the ucore kernel.
See the GNU ld 'info' manual ("info ld") to learn the syntax. */
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(kern_entry)
SECTIONS {
/* Load the kernel at this address: "." means the current address */
. = 0xC0100000;
.text : {
*(.text .stub .text.* .gnu.linkonce.t.*)
}
PROVIDE(etext = .); /* Define the 'etext' symbol to this value */
.rodata : {
*(.rodata .rodata.* .gnu.linkonce.r.*)
}
/* Include debugging information in kernel memory */
.stab : {
PROVIDE(__STAB_BEGIN__ = .);
*(.stab);
PROVIDE(__STAB_END__ = .);
BYTE(0) /* Force the linker to allocate space
for this section */
}
.stabstr : {
PROVIDE(__STABSTR_BEGIN__ = .);
*(.stabstr);
PROVIDE(__STABSTR_END__ = .);
BYTE(0) /* Force the linker to allocate space
for this section */
}
/* Adjust the address for the data segment to the next page */
. = ALIGN(0x1000);
/* The data segment */
.data : {
*(.data)
}
PROVIDE(edata = .);
.bss : {
*(.bss)
}
PROVIDE(end = .);
/DISCARD/ : {
*(.eh_frame .note.GNU-stack)
}
}

View File

@@ -0,0 +1,43 @@
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
int
main(int argc, char *argv[]) {
struct stat st;
if (argc != 3) {
fprintf(stderr, "Usage: <input filename> <output filename>\n");
return -1;
}
if (stat(argv[1], &st) != 0) {
fprintf(stderr, "Error opening file '%s': %s\n", argv[1], strerror(errno));
return -1;
}
printf("'%s' size: %lld bytes\n", argv[1], (long long)st.st_size);
if (st.st_size > 510) {
fprintf(stderr, "%lld >> 510!!\n", (long long)st.st_size);
return -1;
}
char buf[512];
memset(buf, 0, sizeof(buf));
FILE *ifp = fopen(argv[1], "rb");
int size = fread(buf, 1, st.st_size, ifp);
if (size != st.st_size) {
fprintf(stderr, "read '%s' error, size is %d.\n", argv[1], size);
return -1;
}
fclose(ifp);
buf[510] = 0x55;
buf[511] = 0xAA;
FILE *ofp = fopen(argv[2], "wb+");
size = fwrite(buf, 1, 512, ofp);
if (size != 512) {
fprintf(stderr, "write '%s' error, size is %d.\n", argv[2], size);
return -1;
}
fclose(ofp);
printf("build 512 bytes boot sector: '%s' success!\n", argv[2]);
return 0;
}

View File

@@ -0,0 +1,29 @@
#include <stdio.h>
int
main(void) {
printf("# handler\n");
printf(".text\n");
printf(".globl __alltraps\n");
int i;
for (i = 0; i < 256; i ++) {
printf(".globl vector%d\n", i);
printf("vector%d:\n", i);
if ((i < 8 || i > 14) && i != 17) {
printf(" pushl $0\n");
}
printf(" pushl $%d\n", i);
printf(" jmp __alltraps\n");
}
printf("\n");
printf("# vector table\n");
printf(".data\n");
printf(".globl __vectors\n");
printf("__vectors:\n");
for (i = 0; i < 256; i ++) {
printf(" .long vector%d\n", i);
}
return 0;
}