aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Make.config4
-rw-r--r--src/Makefile.kernel3
-rw-r--r--src/devices/timer.c33
-rw-r--r--src/devices/timer.h5
-rw-r--r--src/examples/pfs.c2
-rw-r--r--src/lib/debug.h2
-rw-r--r--src/tests/Make.tests2
-rw-r--r--src/tests/filst/Make.tests16
-rw-r--r--src/tests/filst/sc-bad-write.c51
-rw-r--r--src/tests/filst/sc-bad-write.ck9
-rw-r--r--src/threads/init.c45
-rw-r--r--src/userprog/Make.vars2
-rw-r--r--src/userprog/process.c2
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);