diff options
| -rw-r--r-- | src/Make.config | 4 | ||||
| -rw-r--r-- | src/Makefile.kernel | 3 | ||||
| -rw-r--r-- | src/devices/timer.c | 33 | ||||
| -rw-r--r-- | src/devices/timer.h | 5 | ||||
| -rw-r--r-- | src/examples/pfs.c | 2 | ||||
| -rw-r--r-- | src/lib/debug.h | 2 | ||||
| -rw-r--r-- | src/tests/Make.tests | 2 | ||||
| -rw-r--r-- | src/tests/filst/Make.tests | 16 | ||||
| -rw-r--r-- | src/tests/filst/sc-bad-write.c | 51 | ||||
| -rw-r--r-- | src/tests/filst/sc-bad-write.ck | 9 | ||||
| -rw-r--r-- | src/threads/init.c | 45 | ||||
| -rw-r--r-- | src/userprog/Make.vars | 2 | ||||
| -rw-r--r-- | src/userprog/process.c | 2 |
13 files changed, 143 insertions, 33 deletions
diff --git a/src/Make.config b/src/Make.config index b73cb46..aa7d572 100644 --- a/src/Make.config +++ b/src/Make.config @@ -46,7 +46,9 @@ endif DEFINES = WARNINGS = -Wall -W -Wstrict-prototypes -Wmissing-prototypes -Wsystem-headers # klaar36@ida 2015-03: -fno-omit-frame-pointer to get working backtrace -CFLAGS = -std=gnu99 -g -msoft-float -fno-omit-frame-pointer -O $(CFLAG_STACK_PROTECTOR) +# klaar36@ida 2016-05: -ffreestanding to assert freestanding environment +# klaar36@ida 2016-05: -fno-inline to ease debugging +CFLAGS = -std=gnu99 -ggdb -msoft-float -fno-omit-frame-pointer -ffreestanding -fno-inline -O $(CFLAG_STACK_PROTECTOR) CPPFLAGS = -nostdinc -I$(SRCDIR) -I$(SRCDIR)/lib ASFLAGS = -Wa,--gstabs LDFLAGS = diff --git a/src/Makefile.kernel b/src/Makefile.kernel index cf5c58a..95e9c89 100644 --- a/src/Makefile.kernel +++ b/src/Makefile.kernel @@ -16,5 +16,8 @@ build/Makefile: ../Makefile.build build/%: $(DIRS) build/Makefile cd build && $(MAKE) $* +examples: + make -C ../examples + clean: rm -rf build diff --git a/src/devices/timer.c b/src/devices/timer.c index 5bf8b27..750ac4c 100644 --- a/src/devices/timer.c +++ b/src/devices/timer.c @@ -10,13 +10,6 @@ /* See [8254] for hardware details of the 8254 timer chip. */ -#if TIMER_FREQ < 19 -#error 8254 timer requires TIMER_FREQ >= 19 -#endif -#if TIMER_FREQ > 1000 -#error TIMER_FREQ <= 1000 recommended -#endif - /* Number of timer ticks since OS booted. */ static int64_t ticks; @@ -24,6 +17,9 @@ static int64_t ticks; Initialized by timer_calibrate(). */ static unsigned loops_per_tick; +/* Interrupts per second, writen only by timer_init */ +static uint16_t TIMER_FREQ = 0; + static intr_handler_func timer_interrupt; static bool too_many_loops (unsigned loops); static void busy_wait (int64_t loops); @@ -33,8 +29,13 @@ static void real_time_sleep (int64_t num, int32_t denom); interrupt PIT_FREQ times per second, and registers the corresponding interrupt. */ void -timer_init (void) +timer_init (const uint16_t timer_freq) { + TIMER_FREQ = timer_freq; + + /* 8254 timer requires TIMER_FREQ >= 19 */ + ASSERT (TIMER_FREQ >= 19); + /* 8254 input frequency divided by TIMER_FREQ, rounded to nearest. */ uint16_t count = (1193180 + TIMER_FREQ / 2) / TIMER_FREQ; @@ -53,7 +54,14 @@ timer_calibrate (void) unsigned high_bit, test_bit; ASSERT (intr_get_level () == INTR_ON); - printf ("Calibrating timer... "); + ASSERT (TIMER_FREQ >= 19); + + /* klaar@ida 2016-05-03 (thanks to filst and antsu) + * TIMER_FREQ > 1000 => synchronization errors very rare + * TIMER_FREQ > 5000 => synchronization errors rare + * TIMER_FREQ > 10000 => frequent synch errors (good for testing) + */ + printf ("Calibrating timer... "); /* Approximate loops_per_tick as the largest power-of-two still less than one timer tick. */ @@ -128,6 +136,7 @@ timer_nsleep (int64_t ns) void timer_print_stats (void) { + printf ("Timer: %d interrupts per second\n", TIMER_FREQ); printf ("Timer: %"PRId64" ticks\n", timer_ticks ()); } @@ -174,7 +183,7 @@ busy_wait (int64_t loops) /* Sleep for approximately NUM/DENOM seconds. */ static void -real_time_sleep (int64_t num, int32_t denom) +real_time_sleep (int64_t num, int32_t denom) { /* Convert NUM/DENOM seconds into timer ticks, rounding down. @@ -185,6 +194,7 @@ real_time_sleep (int64_t num, int32_t denom) int64_t ticks = num * TIMER_FREQ / denom; ASSERT (intr_get_level () == INTR_ON); + ASSERT (TIMER_FREQ >= 19); if (ticks > 0) { /* We're waiting for at least one full timer tick. Use @@ -198,7 +208,6 @@ real_time_sleep (int64_t num, int32_t denom) sub-tick timing. We scale the numerator and denominator down by 1000 to avoid the possibility of overflow. */ ASSERT (denom % 1000 == 0); - busy_wait (loops_per_tick * num / 1000 * TIMER_FREQ / (denom / 1000)); + busy_wait (loops_per_tick * num / 1000 * TIMER_FREQ / (denom / 1000)); } } - diff --git a/src/devices/timer.h b/src/devices/timer.h index 45a3f72..aee6033 100644 --- a/src/devices/timer.h +++ b/src/devices/timer.h @@ -4,10 +4,7 @@ #include <round.h> #include <stdint.h> -/* Number of timer interrupts per second. */ -#define TIMER_FREQ 100 - -void timer_init (void); +void timer_init (uint16_t timer_freq); void timer_calibrate (void); int64_t timer_ticks (void); diff --git a/src/examples/pfs.c b/src/examples/pfs.c index a633e24..3359e5b 100644 --- a/src/examples/pfs.c +++ b/src/examples/pfs.c @@ -1,6 +1,6 @@ /* klaar@ida (cleanup of previous code by various IDA-employees) - pintos -v -k -T 120 --fs-disk=2 --qemu -p ../examples/pfs -a pfs -p ../examples/pfs_writer -a pfs_writer -p ../examples/pfs_reader -a pfs_reader -g messages -- -f -q run pfs + pintos -v -k -T 120 --fs-disk=2 --qemu -p ../examples/pfs -a pfs -p ../examples/pfs_writer -a pfs_writer -p ../examples/pfs_reader -a pfs_reader -g messages -- -F=20000 -f -q run pfs Tests that read and write are properly synchronized. Also stresses the filesystem somewhat. diff --git a/src/lib/debug.h b/src/lib/debug.h index 989dbd5..29390b6 100644 --- a/src/lib/debug.h +++ b/src/lib/debug.h @@ -23,7 +23,7 @@ void debug_panic (const char *file, int line, const char *function, void debug_backtrace (void); /* klaar@ida Parts from 100 to 210 exists (only in reference solution) */ -#define PART 210 +#define PART 190 #endif diff --git a/src/tests/Make.tests b/src/tests/Make.tests index bcaa2d1..a9a4459 100644 --- a/src/tests/Make.tests +++ b/src/tests/Make.tests @@ -85,7 +85,7 @@ endif ifeq ($(filter vm, $(KERNEL_SUBDIRS)), vm) TESTCMD += --swap-disk=4 endif -TESTCMD += -- -q +TESTCMD += -- -F=10000 -q TESTCMD += $(KERNELFLAGS) ifeq ($(filter userprog, $(KERNEL_SUBDIRS)), userprog) TESTCMD += -f diff --git a/src/tests/filst/Make.tests b/src/tests/filst/Make.tests new file mode 100644 index 0000000..68bffb1 --- /dev/null +++ b/src/tests/filst/Make.tests @@ -0,0 +1,16 @@ +# -*- makefile -*- + +tests/%.output: FSDISK = 2 +tests/%.output: PUTFILES = $(filter-out os.dsk, $^) + +tests/filst_TESTS = $(addprefix tests/filst/,sc-bad-write) + +tests/filst_PROGS = $(tests/filst_TESTS) # $(addprefix tests/filst/,child-simple) + +tests/filst/sc-bad-write_SRC = tests/filst/sc-bad-write.c tests/main.c + +$(foreach prog,$(tests/filst_PROGS),$(eval $(prog)_SRC += tests/lib.c)) + +tests/filst/read-bad-buf_PUTFILES += tests/filst/sample.txt +tests/filst/low-mem_PUTFILES += tests/filst/child-simple +tests/filst/exec-corrupt_PUTFILES += tests/filst/corrupt-elf diff --git a/src/tests/filst/sc-bad-write.c b/src/tests/filst/sc-bad-write.c new file mode 100644 index 0000000..2280d92 --- /dev/null +++ b/src/tests/filst/sc-bad-write.c @@ -0,0 +1,51 @@ +#include <syscall-nr.h> +#include <stdio.h> +#include <stdint.h> +#include "tests/lib.h" +#include "tests/main.h" + +/** + * From threads/vaddr.h: + */ +#define BITMASK(SHIFT, CNT) (((1ul << (CNT)) - 1) << (SHIFT)) + +#define PGSHIFT 0 /* Index of first offset bit. */ +#define PGBITS 12 /* Number of offset bits. */ +#define PGSIZE (1 << PGBITS) /* Bytes in a page. */ +#define PGMASK BITMASK(PGSHIFT, PGBITS) /* Page offset bits (0:12). */ + +static inline void *pg_round_up (const void *va) { + return (void *) (((uintptr_t) va + PGSIZE - 1) & ~PGMASK); +} + +/** + * A global variable that will give us an address in the BSS segment. + */ +int global = 3; + +void test_main(void) +{ + // Get the addres of the first unmapped page in the system. + unsigned page = (unsigned)pg_round_up(&global); + + // Reserve space for 3 parameters (write requires 4). + page -= sizeof(int) * 4; + + asm volatile ( + "movl %%esp, %%edi;" + "movl %0, %%esp;" // Set stack pointer to right below page boundary. + "movl %1, (%%esp);" // Try to call SYS_WRITE + "movl %2, 4(%%esp);" // Write to STDOUT + "movl %3, 8(%%esp);" // Load buffer. + //"movl $5, 12(%%esp);" // Can not write the last parameter as we would get a pagefault. + "int $0x30;" + "movl %%edi, %%esp;" // Restore esp in case we do not crash (as we should). + : + : "r" (page), + "i" (SYS_WRITE), + "i" (STDOUT_FILENO), + "i" ("TEST\n") + : "%esp", "%eax", "%edi"); + + fail("should have died."); +} diff --git a/src/tests/filst/sc-bad-write.ck b/src/tests/filst/sc-bad-write.ck new file mode 100644 index 0000000..bd393c0 --- /dev/null +++ b/src/tests/filst/sc-bad-write.ck @@ -0,0 +1,9 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(sc-bad-write) begin +sc-bad-write: exit(-1) +EOF +pass; diff --git a/src/threads/init.c b/src/threads/init.c index 43f491f..6633d2c 100644 --- a/src/threads/init.c +++ b/src/threads/init.c @@ -48,11 +48,20 @@ static bool format_filesys; /* -q: Power off after kernel tasks complete? */ bool power_off_when_done = false; -/* -Q: Force power off by klaar@ida... */ + +/* Options by klaar@ida */ + +/* -Q: Force power off */ bool force_off_when_done = false; -/* -tcf: Simulate failure in thread_create klaar@ida... */ +/* -F: Set timer frequency */ +static uint16_t init_timer_freq = 1000; +/* -tcf: Simulate failure in thread_create */ int thread_create_limit = 0; /* infinite */ +static bool prevent_reqursive_off = false; + +static void hard_power_off (void) NO_RETURN; + static void ram_init (void); static void paging_init (void); @@ -101,7 +110,7 @@ main (void) /* Initialize interrupt handlers. */ intr_init (); - timer_init (); + timer_init (init_timer_freq); kbd_init (); input_init (); #ifdef USERPROG @@ -244,6 +253,8 @@ parse_options (char **argv) power_off_when_done = true; else if (!strcmp (name, "-Q")) // klaar@ida power_off_when_done = force_off_when_done = true; + else if (!strcmp (name, "-F")) // klaar@ida + init_timer_freq = atoi (value); #ifdef FILESYS else if (!strcmp (name, "-f")) format_filesys = true; @@ -369,24 +380,20 @@ usage (void) #endif ); - /* klaar@ida disabled due to threads and locks not initialized + /* klaar@ida changed due to threads and locks not initialized * yet... and power_off() now use locks. */ -// power_off (); + hard_power_off (); } - /* Powers down the machine we're running on, as long as we're running on Bochs or QEMU. */ -void -power_off (void) +static void +hard_power_off (void) { const char s[] = "Shutdown"; const char *p; - printf ("# Preparing to power off...\n"); - DEBUG_thread_poweroff_check( force_off_when_done ); - #ifdef FILESYS filesys_done (); #endif @@ -412,6 +419,22 @@ power_off (void) for (;;); } +/* Powers down the machine we're running on, + as long as we're running on Bochs or QEMU. */ +void +power_off (void) +{ + if ( prevent_reqursive_off ) + hard_power_off (); + + prevent_reqursive_off = true; + + printf ("# Preparing to power off...\n"); + DEBUG_thread_poweroff_check( force_off_when_done ); + + hard_power_off (); +} + /* Print statistics about Pintos execution. */ static void print_stats (void) diff --git a/src/userprog/Make.vars b/src/userprog/Make.vars index 4335438..f158791 100644 --- a/src/userprog/Make.vars +++ b/src/userprog/Make.vars @@ -2,7 +2,7 @@ os.dsk: DEFINES += -DUSERPROG -DFILESYS KERNEL_SUBDIRS = threads devices lib lib/kernel userprog filesys -TEST_SUBDIRS = tests/klaar tests/userprog tests/filesys/base +TEST_SUBDIRS = tests/klaar tests/filst tests/userprog tests/filesys/base # tests/userprog/no-vm GRADING_FILE = $(SRCDIR)/tests/userprog/Grading SIMULATOR = --qemu diff --git a/src/userprog/process.c b/src/userprog/process.c index b4177d0..c013008 100644 --- a/src/userprog/process.c +++ b/src/userprog/process.c @@ -235,7 +235,7 @@ process_cleanup (void) * important to do this printf BEFORE you tell the parent process * that you exit. (Since the parent may be the main() function, * that may sometimes poweroff as soon as process_wait() returns, - * possibly before the prontf is completed.) + * possibly before the printf is completed.) */ printf("%s: exit(%d)\n", thread_name(), status); |
