From 1f043fb6948e21894c32bd0e60a26f109b10edca Mon Sep 17 00:00:00 2001 From: winPond Date: Sat, 6 Jul 2019 15:59:43 +0800 Subject: [PATCH] HomeWork 8 is done --- xv6-public/.cvsignore | 16 + xv6-public/.dir-locals.el | 4 + xv6-public/.gdbinit.tmpl | 27 + xv6-public/.gitignore | 16 + xv6-public/BUGS | 7 + xv6-public/LICENSE | 24 + xv6-public/Makefile | 296 +++ xv6-public/Notes | 123 ++ xv6-public/README | 50 + xv6-public/TRICKS | 140 ++ xv6-public/alarmtest.c | 25 + xv6-public/asm.h | 18 + xv6-public/bio.c | 144 ++ xv6-public/bootasm.S | 88 + xv6-public/bootmain.c | 96 + xv6-public/buf.h | 14 + xv6-public/cat.c | 43 + xv6-public/console.c | 299 +++ xv6-public/cuth | 48 + xv6-public/date.c | 20 + xv6-public/date.h | 8 + xv6-public/defs.h | 190 ++ xv6-public/dot-bochsrc | 738 +++++++ xv6-public/echo.c | 13 + xv6-public/elf.h | 42 + xv6-public/entry.S | 68 + xv6-public/entryother.S | 93 + xv6-public/exec.c | 114 ++ xv6-public/fcntl.h | 4 + xv6-public/file.c | 157 ++ xv6-public/file.h | 37 + xv6-public/forktest.c | 56 + xv6-public/fs.c | 671 ++++++ xv6-public/fs.h | 57 + xv6-public/gdbutil | 291 +++ xv6-public/grep.c | 107 + xv6-public/ide.c | 169 ++ xv6-public/init.c | 37 + xv6-public/initcode.S | 32 + xv6-public/ioapic.c | 75 + xv6-public/kalloc.c | 96 + xv6-public/kbd.c | 50 + xv6-public/kbd.h | 112 + xv6-public/kernel.ld | 68 + xv6-public/kill.c | 17 + xv6-public/lapic.c | 229 +++ xv6-public/ln.c | 15 + xv6-public/log.c | 234 +++ xv6-public/ls.c | 85 + xv6-public/main.c | 116 ++ xv6-public/memide.c | 60 + xv6-public/memlayout.h | 15 + xv6-public/mkdir.c | 23 + xv6-public/mkfs.c | 297 +++ xv6-public/mmu.h | 181 ++ xv6-public/mp.c | 139 ++ xv6-public/mp.h | 56 + xv6-public/param.h | 14 + xv6-public/picirq.c | 19 + xv6-public/pipe.c | 121 ++ xv6-public/pr.pl | 36 + xv6-public/printf.c | 85 + xv6-public/printpcs | 14 + xv6-public/proc.c | 534 +++++ xv6-public/proc.h | 61 + xv6-public/rm.c | 23 + xv6-public/runoff | 246 +++ xv6-public/runoff.list | 80 + xv6-public/runoff.spec | 102 + xv6-public/runoff1 | 108 + xv6-public/sh.c | 493 +++++ xv6-public/show1 | 3 + xv6-public/sign.pl | 19 + xv6-public/sleep1.p | 134 ++ xv6-public/sleeplock.c | 56 + xv6-public/sleeplock.h | 10 + xv6-public/spinlock.c | 126 ++ xv6-public/spinlock.h | 11 + xv6-public/spinp | 16 + xv6-public/stat.h | 11 + xv6-public/stressfs.c | 49 + xv6-public/string.c | 105 + xv6-public/swtch.S | 29 + xv6-public/syscall.c | 186 ++ xv6-public/syscall.h | 25 + xv6-public/sysfile.c | 469 +++++ xv6-public/sysproc.c | 121 ++ xv6-public/toc.ftr | 13 + xv6-public/toc.hdr | 6 + xv6-public/trap.c | 148 ++ xv6-public/trapasm.S | 32 + xv6-public/traps.h | 38 + xv6-public/types.h | 4 + xv6-public/uart.c | 77 + xv6-public/ulib.c | 106 + xv6-public/umalloc.c | 90 + xv6-public/user.h | 44 + xv6-public/usertests.c | 1803 +++++++++++++++++ xv6-public/usys.S | 41 + xv6-public/uthread.c | 114 ++ xv6-public/uthread_switch.S | 28 + xv6-public/vectors.pl | 47 + xv6-public/vm.c | 394 ++++ xv6-public/wc.c | 54 + xv6-public/x86.h | 183 ++ .../xv6.si4project/Backup/Makefile(2542) | 291 +++ .../xv6.si4project/Backup/Makefile(5214) | 290 +++ .../xv6.si4project/Backup/Makefile(7715) | 296 +++ .../xv6.si4project/Backup/alarmtest(5755).c | 1 + xv6-public/xv6.si4project/Backup/ide(3563).c | 168 ++ xv6-public/xv6.si4project/Backup/proc(1173).h | 58 + xv6-public/xv6.si4project/Backup/proc(6211).c | 534 +++++ .../xv6.si4project/Backup/syscall(2531).h | 24 + .../xv6.si4project/Backup/syscall(3495).c | 182 ++ .../xv6.si4project/Backup/sysproc(2335).c | 101 + xv6-public/xv6.si4project/Backup/trap(2304).c | 133 ++ xv6-public/xv6.si4project/Backup/user(4192).h | 42 + xv6-public/xv6.si4project/Backup/usys(6843).S | 33 + .../Backup/uthread_switch(3995).S | 10 + .../cache/parse/alarmtest.c.sisc | Bin 0 -> 3547 bytes .../xv6.si4project/cache/parse/asm.h.sisc | Bin 0 -> 1780 bytes .../xv6.si4project/cache/parse/bio.c.sisc | Bin 0 -> 8866 bytes .../cache/parse/bootmain.c.sisc | Bin 0 -> 6187 bytes .../xv6.si4project/cache/parse/buf.h.sisc | Bin 0 -> 2119 bytes .../xv6.si4project/cache/parse/cat.c.sisc | Bin 0 -> 4932 bytes .../xv6.si4project/cache/parse/console.c.sisc | Bin 0 -> 21876 bytes .../xv6.si4project/cache/parse/date.c.sisc | Bin 0 -> 3362 bytes .../xv6.si4project/cache/parse/date.h.sisc | Bin 0 -> 1646 bytes .../xv6.si4project/cache/parse/defs.h.sisc | Bin 0 -> 78792 bytes .../xv6.si4project/cache/parse/echo.c.sisc | Bin 0 -> 2254 bytes .../xv6.si4project/cache/parse/elf.h.sisc | Bin 0 -> 4086 bytes .../xv6.si4project/cache/parse/exec.c.sisc | Bin 0 -> 5504 bytes .../xv6.si4project/cache/parse/fcntl.h.sisc | Bin 0 -> 1202 bytes .../xv6.si4project/cache/parse/file.c.sisc | Bin 0 -> 11485 bytes .../xv6.si4project/cache/parse/file.h.sisc | Bin 0 -> 4327 bytes .../cache/parse/forktest.c.sisc | Bin 0 -> 4616 bytes .../xv6.si4project/cache/parse/fs.c.sisc | Bin 0 -> 44413 bytes .../xv6.si4project/cache/parse/fs.h.sisc | Bin 0 -> 4736 bytes .../xv6.si4project/cache/parse/grep.c.sisc | Bin 0 -> 13180 bytes .../xv6.si4project/cache/parse/ide.c.sisc | Bin 0 -> 11055 bytes .../xv6.si4project/cache/parse/init.c.sisc | Bin 0 -> 3043 bytes .../xv6.si4project/cache/parse/ioapic.c.sisc | Bin 0 -> 6365 bytes .../xv6.si4project/cache/parse/kalloc.c.sisc | Bin 0 -> 8389 bytes .../xv6.si4project/cache/parse/kbd.c.sisc | Bin 0 -> 3629 bytes .../xv6.si4project/cache/parse/kbd.h.sisc | Bin 0 -> 3969 bytes .../xv6.si4project/cache/parse/kill.c.sisc | Bin 0 -> 2532 bytes .../xv6.si4project/cache/parse/lapic.c.sisc | Bin 0 -> 13737 bytes .../xv6.si4project/cache/parse/ln.c.sisc | Bin 0 -> 2439 bytes .../xv6.si4project/cache/parse/log.c.sisc | Bin 0 -> 13545 bytes .../xv6.si4project/cache/parse/ls.c.sisc | Bin 0 -> 6735 bytes .../xv6.si4project/cache/parse/main.c.sisc | Bin 0 -> 5180 bytes .../xv6.si4project/cache/parse/memide.c.sisc | Bin 0 -> 4293 bytes .../cache/parse/memlayout.h.sisc | Bin 0 -> 2632 bytes .../xv6.si4project/cache/parse/mkdir.c.sisc | Bin 0 -> 3099 bytes .../xv6.si4project/cache/parse/mkfs.c.sisc | Bin 0 -> 26526 bytes .../xv6.si4project/cache/parse/mmu.h.sisc | Bin 0 -> 14989 bytes .../xv6.si4project/cache/parse/mp.c.sisc | Bin 0 -> 9578 bytes .../xv6.si4project/cache/parse/mp.h.sisc | Bin 0 -> 5563 bytes .../xv6.si4project/cache/parse/param.h.sisc | Bin 0 -> 2058 bytes .../xv6.si4project/cache/parse/picirq.c.sisc | Bin 0 -> 1729 bytes .../xv6.si4project/cache/parse/pipe.c.sisc | Bin 0 -> 10556 bytes .../xv6.si4project/cache/parse/printf.c.sisc | Bin 0 -> 9903 bytes .../xv6.si4project/cache/parse/proc.c.sisc | Bin 0 -> 25493 bytes .../xv6.si4project/cache/parse/proc.h.sisc | Bin 0 -> 6820 bytes .../xv6.si4project/cache/parse/rm.c.sisc | Bin 0 -> 3100 bytes .../xv6.si4project/cache/parse/sh.c.sisc | Bin 0 -> 40514 bytes .../cache/parse/sleeplock.c.sisc | Bin 0 -> 5376 bytes .../cache/parse/sleeplock.h.sisc | Bin 0 -> 1473 bytes .../cache/parse/spinlock.c.sisc | Bin 0 -> 7492 bytes .../cache/parse/spinlock.h.sisc | Bin 0 -> 1477 bytes .../xv6.si4project/cache/parse/stat.h.sisc | Bin 0 -> 1832 bytes .../cache/parse/stressfs.c.sisc | Bin 0 -> 2864 bytes .../xv6.si4project/cache/parse/string.c.sisc | Bin 0 -> 12754 bytes .../xv6.si4project/cache/parse/syscall.c.sisc | Bin 0 -> 17711 bytes .../xv6.si4project/cache/parse/syscall.h.sisc | Bin 0 -> 3165 bytes .../xv6.si4project/cache/parse/sysfile.c.sisc | Bin 0 -> 27340 bytes .../xv6.si4project/cache/parse/sysproc.c.sisc | Bin 0 -> 7100 bytes .../xv6.si4project/cache/parse/trap.c.sisc | Bin 0 -> 9110 bytes .../xv6.si4project/cache/parse/traps.h.sisc | Bin 0 -> 3465 bytes .../xv6.si4project/cache/parse/types.h.sisc | Bin 0 -> 1192 bytes .../xv6.si4project/cache/parse/uart.c.sisc | Bin 0 -> 4314 bytes .../xv6.si4project/cache/parse/ulib.c.sisc | Bin 0 -> 11830 bytes .../xv6.si4project/cache/parse/umalloc.c.sisc | Bin 0 -> 7326 bytes .../xv6.si4project/cache/parse/user.h.sisc | Bin 0 -> 23483 bytes .../cache/parse/usertests.c.sisc | Bin 0 -> 103752 bytes .../xv6.si4project/cache/parse/uthread.c.sisc | Bin 0 -> 8852 bytes .../xv6.si4project/cache/parse/vm.c.sisc | Bin 0 -> 33227 bytes .../xv6.si4project/cache/parse/wc.c.sisc | Bin 0 -> 5994 bytes .../xv6.si4project/cache/parse/x86.h.sisc | Bin 0 -> 18937 bytes .../xv6.si4project/cache/parse/zombie.c.sisc | Bin 0 -> 1521 bytes xv6-public/xv6.si4project/xv6.SearchResults | 4 + xv6-public/xv6.si4project/xv6.bookmarks.xml | 7 + xv6-public/xv6.si4project/xv6.sip_sym | Bin 0 -> 987452 bytes xv6-public/xv6.si4project/xv6.sip_xab | Bin 0 -> 32768 bytes xv6-public/xv6.si4project/xv6.sip_xad | Bin 0 -> 648 bytes xv6-public/xv6.si4project/xv6.sip_xc | Bin 0 -> 196840 bytes xv6-public/xv6.si4project/xv6.sip_xf | Bin 0 -> 196840 bytes xv6-public/xv6.si4project/xv6.sip_xm | Bin 0 -> 388 bytes xv6-public/xv6.si4project/xv6.sip_xr | Bin 0 -> 196840 bytes xv6-public/xv6.si4project/xv6.sip_xsb | Bin 0 -> 126976 bytes xv6-public/xv6.si4project/xv6.sip_xsd | Bin 0 -> 1568 bytes xv6-public/xv6.si4project/xv6.siproj | Bin 0 -> 32328 bytes .../xv6.si4project/xv6.siproj_settings.xml | 22 + xv6-public/xv6.si4project/xv6.siwork | Bin 0 -> 65716 bytes xv6-public/xv6.si4project/xv6.snippets.xml | 7 + xv6-public/zombie.c | 14 + 206 files changed, 14995 insertions(+) create mode 100644 xv6-public/.cvsignore create mode 100644 xv6-public/.dir-locals.el create mode 100644 xv6-public/.gdbinit.tmpl create mode 100644 xv6-public/.gitignore create mode 100644 xv6-public/BUGS create mode 100644 xv6-public/LICENSE create mode 100644 xv6-public/Makefile create mode 100644 xv6-public/Notes create mode 100644 xv6-public/README create mode 100644 xv6-public/TRICKS create mode 100644 xv6-public/alarmtest.c create mode 100644 xv6-public/asm.h create mode 100644 xv6-public/bio.c create mode 100644 xv6-public/bootasm.S create mode 100644 xv6-public/bootmain.c create mode 100644 xv6-public/buf.h create mode 100644 xv6-public/cat.c create mode 100644 xv6-public/console.c create mode 100644 xv6-public/cuth create mode 100644 xv6-public/date.c create mode 100644 xv6-public/date.h create mode 100644 xv6-public/defs.h create mode 100644 xv6-public/dot-bochsrc create mode 100644 xv6-public/echo.c create mode 100644 xv6-public/elf.h create mode 100644 xv6-public/entry.S create mode 100644 xv6-public/entryother.S create mode 100644 xv6-public/exec.c create mode 100644 xv6-public/fcntl.h create mode 100644 xv6-public/file.c create mode 100644 xv6-public/file.h create mode 100644 xv6-public/forktest.c create mode 100644 xv6-public/fs.c create mode 100644 xv6-public/fs.h create mode 100644 xv6-public/gdbutil create mode 100644 xv6-public/grep.c create mode 100644 xv6-public/ide.c create mode 100644 xv6-public/init.c create mode 100644 xv6-public/initcode.S create mode 100644 xv6-public/ioapic.c create mode 100644 xv6-public/kalloc.c create mode 100644 xv6-public/kbd.c create mode 100644 xv6-public/kbd.h create mode 100644 xv6-public/kernel.ld create mode 100644 xv6-public/kill.c create mode 100644 xv6-public/lapic.c create mode 100644 xv6-public/ln.c create mode 100644 xv6-public/log.c create mode 100644 xv6-public/ls.c create mode 100644 xv6-public/main.c create mode 100644 xv6-public/memide.c create mode 100644 xv6-public/memlayout.h create mode 100644 xv6-public/mkdir.c create mode 100644 xv6-public/mkfs.c create mode 100644 xv6-public/mmu.h create mode 100644 xv6-public/mp.c create mode 100644 xv6-public/mp.h create mode 100644 xv6-public/param.h create mode 100644 xv6-public/picirq.c create mode 100644 xv6-public/pipe.c create mode 100644 xv6-public/pr.pl create mode 100644 xv6-public/printf.c create mode 100644 xv6-public/printpcs create mode 100644 xv6-public/proc.c create mode 100644 xv6-public/proc.h create mode 100644 xv6-public/rm.c create mode 100644 xv6-public/runoff create mode 100644 xv6-public/runoff.list create mode 100644 xv6-public/runoff.spec create mode 100644 xv6-public/runoff1 create mode 100644 xv6-public/sh.c create mode 100644 xv6-public/show1 create mode 100644 xv6-public/sign.pl create mode 100644 xv6-public/sleep1.p create mode 100644 xv6-public/sleeplock.c create mode 100644 xv6-public/sleeplock.h create mode 100644 xv6-public/spinlock.c create mode 100644 xv6-public/spinlock.h create mode 100644 xv6-public/spinp create mode 100644 xv6-public/stat.h create mode 100644 xv6-public/stressfs.c create mode 100644 xv6-public/string.c create mode 100644 xv6-public/swtch.S create mode 100644 xv6-public/syscall.c create mode 100644 xv6-public/syscall.h create mode 100644 xv6-public/sysfile.c create mode 100644 xv6-public/sysproc.c create mode 100644 xv6-public/toc.ftr create mode 100644 xv6-public/toc.hdr create mode 100644 xv6-public/trap.c create mode 100644 xv6-public/trapasm.S create mode 100644 xv6-public/traps.h create mode 100644 xv6-public/types.h create mode 100644 xv6-public/uart.c create mode 100644 xv6-public/ulib.c create mode 100644 xv6-public/umalloc.c create mode 100644 xv6-public/user.h create mode 100644 xv6-public/usertests.c create mode 100644 xv6-public/usys.S create mode 100644 xv6-public/uthread.c create mode 100644 xv6-public/uthread_switch.S create mode 100644 xv6-public/vectors.pl create mode 100644 xv6-public/vm.c create mode 100644 xv6-public/wc.c create mode 100644 xv6-public/x86.h create mode 100644 xv6-public/xv6.si4project/Backup/Makefile(2542) create mode 100644 xv6-public/xv6.si4project/Backup/Makefile(5214) create mode 100644 xv6-public/xv6.si4project/Backup/Makefile(7715) create mode 100644 xv6-public/xv6.si4project/Backup/alarmtest(5755).c create mode 100644 xv6-public/xv6.si4project/Backup/ide(3563).c create mode 100644 xv6-public/xv6.si4project/Backup/proc(1173).h create mode 100644 xv6-public/xv6.si4project/Backup/proc(6211).c create mode 100644 xv6-public/xv6.si4project/Backup/syscall(2531).h create mode 100644 xv6-public/xv6.si4project/Backup/syscall(3495).c create mode 100644 xv6-public/xv6.si4project/Backup/sysproc(2335).c create mode 100644 xv6-public/xv6.si4project/Backup/trap(2304).c create mode 100644 xv6-public/xv6.si4project/Backup/user(4192).h create mode 100644 xv6-public/xv6.si4project/Backup/usys(6843).S create mode 100644 xv6-public/xv6.si4project/Backup/uthread_switch(3995).S create mode 100644 xv6-public/xv6.si4project/cache/parse/alarmtest.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/asm.h.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/bio.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/bootmain.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/buf.h.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/cat.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/console.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/date.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/date.h.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/defs.h.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/echo.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/elf.h.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/exec.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/fcntl.h.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/file.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/file.h.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/forktest.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/fs.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/fs.h.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/grep.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/ide.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/init.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/ioapic.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/kalloc.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/kbd.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/kbd.h.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/kill.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/lapic.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/ln.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/log.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/ls.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/main.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/memide.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/memlayout.h.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/mkdir.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/mkfs.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/mmu.h.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/mp.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/mp.h.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/param.h.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/picirq.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/pipe.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/printf.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/proc.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/proc.h.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/rm.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/sh.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/sleeplock.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/sleeplock.h.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/spinlock.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/spinlock.h.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/stat.h.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/stressfs.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/string.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/syscall.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/syscall.h.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/sysfile.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/sysproc.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/trap.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/traps.h.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/types.h.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/uart.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/ulib.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/umalloc.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/user.h.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/usertests.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/uthread.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/vm.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/wc.c.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/x86.h.sisc create mode 100644 xv6-public/xv6.si4project/cache/parse/zombie.c.sisc create mode 100644 xv6-public/xv6.si4project/xv6.SearchResults create mode 100644 xv6-public/xv6.si4project/xv6.bookmarks.xml create mode 100644 xv6-public/xv6.si4project/xv6.sip_sym create mode 100644 xv6-public/xv6.si4project/xv6.sip_xab create mode 100644 xv6-public/xv6.si4project/xv6.sip_xad create mode 100644 xv6-public/xv6.si4project/xv6.sip_xc create mode 100644 xv6-public/xv6.si4project/xv6.sip_xf create mode 100644 xv6-public/xv6.si4project/xv6.sip_xm create mode 100644 xv6-public/xv6.si4project/xv6.sip_xr create mode 100644 xv6-public/xv6.si4project/xv6.sip_xsb create mode 100644 xv6-public/xv6.si4project/xv6.sip_xsd create mode 100644 xv6-public/xv6.si4project/xv6.siproj create mode 100644 xv6-public/xv6.si4project/xv6.siproj_settings.xml create mode 100644 xv6-public/xv6.si4project/xv6.siwork create mode 100644 xv6-public/xv6.si4project/xv6.snippets.xml create mode 100644 xv6-public/zombie.c diff --git a/xv6-public/.cvsignore b/xv6-public/.cvsignore new file mode 100644 index 0000000..081a43c --- /dev/null +++ b/xv6-public/.cvsignore @@ -0,0 +1,16 @@ +*.asm +*.d +*.sym +_* +kernel +user1 +userfs +usertests +xv6.img +vectors.S +bochsout.txt +bootblock +bootother +bootother.out +parport.out +fmt diff --git a/xv6-public/.dir-locals.el b/xv6-public/.dir-locals.el new file mode 100644 index 0000000..da72247 --- /dev/null +++ b/xv6-public/.dir-locals.el @@ -0,0 +1,4 @@ +((c-mode + (indent-tabs-mode . nil) + (c-file-style . "bsd") + (c-basic-offset . 2))) diff --git a/xv6-public/.gdbinit.tmpl b/xv6-public/.gdbinit.tmpl new file mode 100644 index 0000000..f71681a --- /dev/null +++ b/xv6-public/.gdbinit.tmpl @@ -0,0 +1,27 @@ +set $lastcs = -1 + +define hook-stop + # There doesn't seem to be a good way to detect if we're in 16- or + # 32-bit mode, but in 32-bit mode we always run with CS == 8 in the + # kernel and CS == 35 in user space + if $cs == 8 || $cs == 35 + if $lastcs != 8 && $lastcs != 35 + set architecture i386 + end + x/i $pc + else + if $lastcs == -1 || $lastcs == 8 || $lastcs == 35 + set architecture i8086 + end + # Translate the segment:offset into a physical address + printf "[%4x:%4x] ", $cs, $eip + x/i $cs*16+$eip + end + set $lastcs = $cs +end + +echo + target remote localhost:1234\n +target remote localhost:1234 + +echo + symbol-file kernel\n +symbol-file kernel diff --git a/xv6-public/.gitignore b/xv6-public/.gitignore new file mode 100644 index 0000000..3e2c9de --- /dev/null +++ b/xv6-public/.gitignore @@ -0,0 +1,16 @@ +*~ +_* +*.o +*.d +*.asm +*.sym +*.img +vectors.S +bootblock +entryother +initcode +initcode.out +kernel +kernelmemfs +mkfs +.gdbinit diff --git a/xv6-public/BUGS b/xv6-public/BUGS new file mode 100644 index 0000000..81d2220 --- /dev/null +++ b/xv6-public/BUGS @@ -0,0 +1,7 @@ +formatting: + need to fix PAGEBREAK mechanism + +sh: + can't always runcmd in child -- breaks cd. + maybe should hard-code PATH=/ ? + diff --git a/xv6-public/LICENSE b/xv6-public/LICENSE new file mode 100644 index 0000000..422c0cc --- /dev/null +++ b/xv6-public/LICENSE @@ -0,0 +1,24 @@ +The xv6 software is: + +Copyright (c) 2006-2018 Frans Kaashoek, Robert Morris, Russ Cox, + Massachusetts Institute of Technology + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/xv6-public/Makefile b/xv6-public/Makefile new file mode 100644 index 0000000..346f45c --- /dev/null +++ b/xv6-public/Makefile @@ -0,0 +1,296 @@ +OBJS = \ + bio.o\ + console.o\ + exec.o\ + file.o\ + fs.o\ + ide.o\ + ioapic.o\ + kalloc.o\ + kbd.o\ + lapic.o\ + log.o\ + main.o\ + mp.o\ + picirq.o\ + pipe.o\ + proc.o\ + sleeplock.o\ + spinlock.o\ + string.o\ + swtch.o\ + syscall.o\ + sysfile.o\ + sysproc.o\ + trapasm.o\ + trap.o\ + uart.o\ + vectors.o\ + vm.o\ + +# Cross-compiling (e.g., on Mac OS X) +# TOOLPREFIX = i386-jos-elf + +# Using native tools (e.g., on X86 Linux) +#TOOLPREFIX = + +# Try to infer the correct TOOLPREFIX if not set +ifndef TOOLPREFIX +TOOLPREFIX := $(shell if i386-jos-elf-objdump -i 2>&1 | grep '^elf32-i386$$' >/dev/null 2>&1; \ + then echo 'i386-jos-elf-'; \ + elif objdump -i 2>&1 | grep 'elf32-i386' >/dev/null 2>&1; \ + then echo ''; \ + else echo "***" 1>&2; \ + echo "*** Error: Couldn't find an i386-*-elf version of GCC/binutils." 1>&2; \ + echo "*** Is the directory with i386-jos-elf-gcc in your PATH?" 1>&2; \ + echo "*** If your i386-*-elf toolchain is installed with a command" 1>&2; \ + echo "*** prefix other than 'i386-jos-elf-', set your TOOLPREFIX" 1>&2; \ + echo "*** environment variable to that prefix and run 'make' again." 1>&2; \ + echo "*** To turn off this error, run 'gmake TOOLPREFIX= ...'." 1>&2; \ + echo "***" 1>&2; exit 1; fi) +endif + +# If the makefile can't find QEMU, specify its path here +# QEMU = qemu-system-i386 + +# Try to infer the correct QEMU +ifndef QEMU +QEMU = $(shell if which qemu > /dev/null; \ + then echo qemu; exit; \ + elif which qemu-system-i386 > /dev/null; \ + then echo qemu-system-i386; exit; \ + elif which qemu-system-x86_64 > /dev/null; \ + then echo qemu-system-x86_64; exit; \ + else \ + qemu=/Applications/Q.app/Contents/MacOS/i386-softmmu.app/Contents/MacOS/i386-softmmu; \ + if test -x $$qemu; then echo $$qemu; exit; fi; fi; \ + echo "***" 1>&2; \ + echo "*** Error: Couldn't find a working QEMU executable." 1>&2; \ + echo "*** Is the directory containing the qemu binary in your PATH" 1>&2; \ + echo "*** or have you tried setting the QEMU variable in Makefile?" 1>&2; \ + echo "***" 1>&2; exit 1) +endif + +CC = $(TOOLPREFIX)gcc +AS = $(TOOLPREFIX)gas +LD = $(TOOLPREFIX)ld +OBJCOPY = $(TOOLPREFIX)objcopy +OBJDUMP = $(TOOLPREFIX)objdump +CFLAGS = -fno-pic -static -fno-builtin -fno-strict-aliasing -O2 -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer +CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector) +ASFLAGS = -m32 -gdwarf-2 -Wa,-divide +# FreeBSD ld wants ``elf_i386_fbsd'' +LDFLAGS += -m $(shell $(LD) -V | grep elf_i386 2>/dev/null | head -n 1) + +# Disable PIE when possible (for Ubuntu 16.10 toolchain) +ifneq ($(shell $(CC) -dumpspecs 2>/dev/null | grep -e '[^f]no-pie'),) +CFLAGS += -fno-pie -no-pie +endif +ifneq ($(shell $(CC) -dumpspecs 2>/dev/null | grep -e '[^f]nopie'),) +CFLAGS += -fno-pie -nopie +endif + +xv6.img: bootblock kernel + dd if=/dev/zero of=xv6.img count=10000 + dd if=bootblock of=xv6.img conv=notrunc + dd if=kernel of=xv6.img seek=1 conv=notrunc + +xv6memfs.img: bootblock kernelmemfs + dd if=/dev/zero of=xv6memfs.img count=10000 + dd if=bootblock of=xv6memfs.img conv=notrunc + dd if=kernelmemfs of=xv6memfs.img seek=1 conv=notrunc + +bootblock: bootasm.S bootmain.c + $(CC) $(CFLAGS) -fno-pic -O -nostdinc -I. -c bootmain.c + $(CC) $(CFLAGS) -fno-pic -nostdinc -I. -c bootasm.S + $(LD) $(LDFLAGS) -N -e start -Ttext 0x7C00 -o bootblock.o bootasm.o bootmain.o + $(OBJDUMP) -S bootblock.o > bootblock.asm + $(OBJCOPY) -S -O binary -j .text bootblock.o bootblock + ./sign.pl bootblock + +entryother: entryother.S + $(CC) $(CFLAGS) -fno-pic -nostdinc -I. -c entryother.S + $(LD) $(LDFLAGS) -N -e start -Ttext 0x7000 -o bootblockother.o entryother.o + $(OBJCOPY) -S -O binary -j .text bootblockother.o entryother + $(OBJDUMP) -S bootblockother.o > entryother.asm + +initcode: initcode.S + $(CC) $(CFLAGS) -nostdinc -I. -c initcode.S + $(LD) $(LDFLAGS) -N -e start -Ttext 0 -o initcode.out initcode.o + $(OBJCOPY) -S -O binary initcode.out initcode + $(OBJDUMP) -S initcode.o > initcode.asm + +kernel: $(OBJS) entry.o entryother initcode kernel.ld + $(LD) $(LDFLAGS) -T kernel.ld -o kernel entry.o $(OBJS) -b binary initcode entryother + $(OBJDUMP) -S kernel > kernel.asm + $(OBJDUMP) -t kernel | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernel.sym + +_uthread: uthread.o uthread_switch.o + $(LD) $(LDFLAGS) -N -e main -Ttext 0 -o _uthread uthread.o uthread_switch.o $(ULIB) + $(OBJDUMP) -S _uthread > uthread.asm + +# kernelmemfs is a copy of kernel that maintains the +# disk image in memory instead of writing to a disk. +# This is not so useful for testing persistent storage or +# exploring disk buffering implementations, but it is +# great for testing the kernel on real hardware without +# needing a scratch disk. +MEMFSOBJS = $(filter-out ide.o,$(OBJS)) memide.o +kernelmemfs: $(MEMFSOBJS) entry.o entryother initcode kernel.ld fs.img + $(LD) $(LDFLAGS) -T kernel.ld -o kernelmemfs entry.o $(MEMFSOBJS) -b binary initcode entryother fs.img + $(OBJDUMP) -S kernelmemfs > kernelmemfs.asm + $(OBJDUMP) -t kernelmemfs | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernelmemfs.sym + +tags: $(OBJS) entryother.S _init + etags *.S *.c + +vectors.S: vectors.pl + ./vectors.pl > vectors.S + +ULIB = ulib.o usys.o printf.o umalloc.o + +_%: %.o $(ULIB) + $(LD) $(LDFLAGS) -N -e main -Ttext 0 -o $@ $^ + $(OBJDUMP) -S $@ > $*.asm + $(OBJDUMP) -t $@ | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $*.sym + +_forktest: forktest.o $(ULIB) + # forktest has less library code linked in - needs to be small + # in order to be able to max out the proc table. + $(LD) $(LDFLAGS) -N -e main -Ttext 0 -o _forktest forktest.o ulib.o usys.o + $(OBJDUMP) -S _forktest > forktest.asm + +mkfs: mkfs.c fs.h + gcc -Werror -Wall -o mkfs mkfs.c + +# Prevent deletion of intermediate files, e.g. cat.o, after first build, so +# that disk image changes after first build are persistent until clean. More +# details: +# http://www.gnu.org/software/make/manual/html_node/Chained-Rules.html +.PRECIOUS: %.o + +UPROGS=\ + _cat\ + _echo\ + _forktest\ + _grep\ + _init\ + _kill\ + _ln\ + _ls\ + _mkdir\ + _rm\ + _sh\ + _stressfs\ + _usertests\ + _wc\ + _zombie\ + _date\ + _alarmtest\ + _uthread\ + +fs.img: mkfs README $(UPROGS) + ./mkfs fs.img README $(UPROGS) + +-include *.d + +clean: + rm -f *.tex *.dvi *.idx *.aux *.log *.ind *.ilg \ + *.o *.d *.asm *.sym vectors.S bootblock entryother \ + initcode initcode.out kernel xv6.img fs.img kernelmemfs \ + xv6memfs.img mkfs .gdbinit \ + $(UPROGS) + +# make a printout +FILES = $(shell grep -v '^\#' runoff.list) +PRINT = runoff.list runoff.spec README toc.hdr toc.ftr $(FILES) + +xv6.pdf: $(PRINT) + ./runoff + ls -l xv6.pdf + +print: xv6.pdf + +# run in emulators + +bochs : fs.img xv6.img + if [ ! -e .bochsrc ]; then ln -s dot-bochsrc .bochsrc; fi + bochs -q + +# try to generate a unique GDB port +GDBPORT = $(shell expr `id -u` % 5000 + 25000) +# QEMU's gdb stub command line changed in 0.11 +QEMUGDB = $(shell if $(QEMU) -help | grep -q '^-gdb'; \ + then echo "-gdb tcp::$(GDBPORT)"; \ + else echo "-s -p $(GDBPORT)"; fi) +ifndef CPUS +CPUS := 2 +endif +QEMUOPTS = -drive file=fs.img,index=1,media=disk,format=raw -drive file=xv6.img,index=0,media=disk,format=raw -smp $(CPUS) -m 512 $(QEMUEXTRA) + +gdb: + gdb -x .gdbinit + +qemu: fs.img xv6.img + $(QEMU) -serial mon:stdio $(QEMUOPTS) + +qemu-memfs: xv6memfs.img + $(QEMU) -drive file=xv6memfs.img,index=0,media=disk,format=raw -smp $(CPUS) -m 256 + +qemu-nox: fs.img xv6.img + $(QEMU) -nographic $(QEMUOPTS) + +.gdbinit: .gdbinit.tmpl + sed "s/localhost:1234/localhost:$(GDBPORT)/" < $^ > $@ + +qemu-gdb: fs.img xv6.img .gdbinit + @echo "*** Now run 'gdb'." 1>&2 + $(QEMU) -serial mon:stdio $(QEMUOPTS) -S $(QEMUGDB) + +qemu-nox-gdb: fs.img xv6.img .gdbinit + @echo "*** Now run 'gdb'." 1>&2 + $(QEMU) -nographic $(QEMUOPTS) -S $(QEMUGDB) + +# CUT HERE +# prepare dist for students +# after running make dist, probably want to +# rename it to rev0 or rev1 or so on and then +# check in that version. + +EXTRA=\ + mkfs.c ulib.c user.h cat.c echo.c forktest.c grep.c kill.c\ + ln.c ls.c mkdir.c rm.c stressfs.c usertests.c wc.c zombie.c\ + printf.c umalloc.c\ + README dot-bochsrc *.pl toc.* runoff runoff1 runoff.list\ + .gdbinit.tmpl gdbutil\ + +dist: + rm -rf dist + mkdir dist + for i in $(FILES); \ + do \ + grep -v PAGEBREAK $$i >dist/$$i; \ + done + sed '/CUT HERE/,$$d' Makefile >dist/Makefile + echo >dist/runoff.spec + cp $(EXTRA) dist + +dist-test: + rm -rf dist + make dist + rm -rf dist-test + mkdir dist-test + cp dist/* dist-test + cd dist-test; $(MAKE) print + cd dist-test; $(MAKE) bochs || true + cd dist-test; $(MAKE) qemu + +# update this rule (change rev#) when it is time to +# make a new revision. +tar: + rm -rf /tmp/xv6 + mkdir -p /tmp/xv6 + cp dist/* dist/.gdbinit.tmpl /tmp/xv6 + (cd /tmp; tar cf - xv6) | gzip >xv6-rev10.tar.gz # the next one will be 10 (9/17) + +.PHONY: dist-test dist diff --git a/xv6-public/Notes b/xv6-public/Notes new file mode 100644 index 0000000..74c8aea --- /dev/null +++ b/xv6-public/Notes @@ -0,0 +1,123 @@ +bochs 2.2.6: +./configure --enable-smp --enable-disasm --enable-debugger --enable-all-optimizations --enable-4meg-pages --enable-global-pages --enable-pae --disable-reset-on-triple-fault +bochs CVS after 2.2.6: +./configure --enable-smp --enable-disasm --enable-debugger --enable-all-optimizations --enable-4meg-pages --enable-global-pages --enable-pae + +bootmain.c doesn't work right if the ELF sections aren't +sector-aligned. so you can't use ld -N. and the sections may also need +to be non-zero length, only really matters for tiny "kernels". + +kernel loaded at 1 megabyte. stack same place that bootasm.S left it. + +kinit() should find real mem size + and rescue useable memory below 1 meg + +no paging, no use of page table hardware, just segments + +no user area: no magic kernel stack mapping + so no copying of kernel stack during fork + though there is a kernel stack page for each process + +no kernel malloc(), just kalloc() for user core + +user pointers aren't valid in the kernel + +are interrupts turned on in the kernel? yes. + +pass curproc explicitly, or implicit from cpu #? + e.g. argument to newproc()? + hmm, you need a global curproc[cpu] for trap() &c + +no stack expansion + +test running out of memory, process slots + +we can't really use a separate stack segment, since stack addresses +need to work correctly as ordinary pointers. the same may be true of +data vs text. how can we have a gap between data and stack, so that +both can grow, without committing 4GB of physical memory? does this +mean we need paging? + +perhaps have fixed-size stack, put it in the data segment? + +oops, if kernel stack is in contiguous user phys mem, then moving +users' memory (e.g. to expand it) will wreck any pointers into the +kernel stack. + +do we need to set fs and gs? so user processes can't abuse them? + +setupsegs() may modify current segment table, is that legal? + +trap() ought to lgdt on return, since currently only done in swtch() + +protect hardware interrupt vectors from user INT instructions? + +test out-of-fd cases for creating pipe. +test pipe reader closes then write +test two readers, two writers. +test children being inherited by grandparent &c + +some sleep()s should be interruptible by kill() + +locks + init_lock + sequences CPU startup + proc_table_lock + also protects next_pid + per-fd lock *just* protects count read-modify-write + also maybe freeness? + memory allocator + printf + +in general, the table locks protect both free-ness and + public variables of table elements + in many cases you can use table elements w/o a lock + e.g. if you are the process, or you are using an fd + +lock order + per-pipe lock + proc_table_lock fd_table_lock kalloc_lock + console_lock + +do you have to be holding the mutex in order to call wakeup()? yes + +device interrupts don't clear FL_IF + so a recursive timer interrupt is possible + +what does inode->busy mean? + might be held across disk reads + no-one is allowed to do anything to the inode + protected by inode_table_lock +inode->count counts in-memory pointers to the struct + prevents inode[] element from being re-used + protected by inode_table_lock + +blocks and inodes have ad-hoc sleep-locks + provide a single mechanism? + +kalloc() can return 0; do callers handle this right? + +test: one process unlinks a file while another links to it +test: one process opens a file while another deletes it +test: deadlock d/.. vs ../d, two processes. +test: dup() shared fd->off +test: does echo foo > x truncate x? + +sh: ioredirection incorrect now we have pipes +sh: chain of pipes won't work, also ugly that parent closes fdarray entries too +sh: dynamic memory allocation? +sh: should sh support ; () & +sh: stop stdin on ctrl-d (for cat > y) + +really should have bdwrite() for file content + and make some inode updates async + so soft updates make sense + +disk scheduling +echo foo > bar should truncate bar + so O_CREATE should not truncate + but O_TRUNC should + +make it work on a real machine +release before acquire at end of sleep? +check 2nd disk (i.e. if not in .bochsrc) diff --git a/xv6-public/README b/xv6-public/README new file mode 100644 index 0000000..9e3cf19 --- /dev/null +++ b/xv6-public/README @@ -0,0 +1,50 @@ +xv6 is a re-implementation of Dennis Ritchie's and Ken Thompson's Unix +Version 6 (v6). xv6 loosely follows the structure and style of v6, +but is implemented for a modern x86-based multiprocessor using ANSI C. + +ACKNOWLEDGMENTS + +xv6 is inspired by John Lions's Commentary on UNIX 6th Edition (Peer +to Peer Communications; ISBN: 1-57398-013-7; 1st edition (June 14, +2000)). See also https://pdos.csail.mit.edu/6.828/, which +provides pointers to on-line resources for v6. + +xv6 borrows code from the following sources: + JOS (asm.h, elf.h, mmu.h, bootasm.S, ide.c, console.c, and others) + Plan 9 (entryother.S, mp.h, mp.c, lapic.c) + FreeBSD (ioapic.c) + NetBSD (console.c) + +The following people have made contributions: Russ Cox (context switching, +locking), Cliff Frey (MP), Xiao Yu (MP), Nickolai Zeldovich, and Austin +Clements. + +We are also grateful for the bug reports and patches contributed by Silas +Boyd-Wickizer, Anton Burtsev, Cody Cutler, Mike CAT, Tej Chajed, eyalz800, +Nelson Elhage, Saar Ettinger, Alice Ferrazzi, Nathaniel Filardo, Peter +Froehlich, Yakir Goaron,Shivam Handa, Bryan Henry, Jim Huang, Alexander +Kapshuk, Anders Kaseorg, kehao95, Wolfgang Keller, Eddie Kohler, Austin +Liew, Imbar Marinescu, Yandong Mao, Matan Shabtay, Hitoshi Mitake, Carmi +Merimovich, Mark Morrissey, mtasm, Joel Nider, Greg Price, Ayan Shafqat, +Eldar Sehayek, Yongming Shen, Cam Tenny, tyfkda, Rafael Ubal, Warren +Toomey, Stephen Tu, Pablo Ventura, Xi Wang, Keiichi Watanabe, Nicolas +Wolovick, wxdao, Grant Wu, Jindong Zhang, Icenowy Zheng, and Zou Chang Wei. + +The code in the files that constitute xv6 is +Copyright 2006-2018 Frans Kaashoek, Robert Morris, and Russ Cox. + +ERROR REPORTS + +Please send errors and suggestions to Frans Kaashoek and Robert Morris +(kaashoek,rtm@mit.edu). The main purpose of xv6 is as a teaching +operating system for MIT's 6.828, so we are more interested in +simplifications and clarifications than new features. + +BUILDING AND RUNNING XV6 + +To build xv6 on an x86 ELF machine (like Linux or FreeBSD), run +"make". On non-x86 or non-ELF machines (like OS X, even on x86), you +will need to install a cross-compiler gcc suite capable of producing +x86 ELF binaries (see https://pdos.csail.mit.edu/6.828/). +Then run "make TOOLPREFIX=i386-jos-elf-". Now install the QEMU PC +simulator and run "make qemu". diff --git a/xv6-public/TRICKS b/xv6-public/TRICKS new file mode 100644 index 0000000..8d1439f --- /dev/null +++ b/xv6-public/TRICKS @@ -0,0 +1,140 @@ +This file lists subtle things that might not be commented +as well as they should be in the source code and that +might be worth pointing out in a longer explanation or in class. + +--- + +[2009/07/12: No longer relevant; forkret1 changed +and this is now cleaner.] + +forkret1 in trapasm.S is called with a tf argument. +In order to use it, forkret1 copies the tf pointer into +%esp and then jumps to trapret, which pops the +register state out of the trap frame. If an interrupt +came in between the mov tf, %esp and the iret that +goes back out to user space, the interrupt stack frame +would end up scribbling over the tf and whatever memory +lay under it. + +Why is this safe? Because forkret1 is only called +the first time a process returns to user space, and +at that point, cp->tf is set to point to a trap frame +constructed at the top of cp's kernel stack. So tf +*is* a valid %esp that can hold interrupt state. + +If other tf's were used in forkret1, we could add +a cli before the mov tf, %esp. + +--- + +In pushcli, must cli() no matter what. It is not safe to do + + if(cpus[cpu()].ncli == 0) + cli(); + cpus[cpu()].ncli++; + +because if interrupts are off then we might call cpu(), get +rescheduled to a different cpu, look at cpus[oldcpu].ncli, +and wrongly decide not to disable interrupts on the new cpu. + +Instead do + + cli(); + cpus[cpu()].ncli++; + +always. + +--- + +There is a (harmless) race in pushcli, which does + + eflags = readeflags(); + cli(); + if(c->ncli++ == 0) + c->intena = eflags & FL_IF; + +Consider a bottom-level pushcli. +If interrupts are disabled already, then the right thing +happens: read_eflags finds that FL_IF is not set, +and intena = 0. If interrupts are enabled, then +it is less clear that the right thing happens: +the readeflags can execute, then the process +can get preempted and rescheduled on another cpu, +and then once it starts running, perhaps with +interrupts disabled (can happen since the scheduler +only enables interrupts once per scheduling loop, +not every time it schedules a process), it will +incorrectly record that interrupts *were* enabled. +This doesn't matter, because if it was safe to be +running with interrupts enabled before the context +switch, it is still safe (and arguably more correct) +to run with them enabled after the context switch too. + +In fact it would be safe if scheduler always set + c->intena = 1; +before calling swtch, and perhaps it should. + +--- + +The x86's processor-ordering memory model +matches spin locks well, so no explicit memory +synchronization instructions are required in +acquire and release. + +Consider two sequences of code on different CPUs: + +CPU0 +A; +release(lk); + +and + +CPU1 +acquire(lk); +B; + +We want to make sure that: + - all reads in B see the effects of writes in A. + - all reads in A do *not* see the effects of writes in B. + +The x86 guarantees that writes in A will go out +to memory before the write of lk->locked = 0 in +release(lk). It further guarantees that CPU1 +will observe CPU0's write of lk->locked = 0 only +after observing the earlier writes by CPU0. +So any reads in B are guaranteed to observe the +effects of writes in A. + +According to the Intel manual behavior spec, the +second condition requires a serialization instruction +in release, to avoid reads in A happening after giving +up lk. No Intel SMP processor in existence actually +moves reads down after writes, but the language in +the spec allows it. There is no telling whether future +processors will need it. + +--- + +The code in fork needs to read np->pid before +setting np->state to RUNNABLE. The following +is not a correct way to do this: + + int + fork(void) + { + ... + np->state = RUNNABLE; + return np->pid; // oops + } + +After setting np->state to RUNNABLE, some other CPU +might run the process, it might exit, and then it might +get reused for a different process (with a new pid), all +before the return statement. So it's not safe to just +"return np->pid". Even saving a copy of np->pid before +setting np->state isn't safe, since the compiler is +allowed to re-order statements. + +The real code saves a copy of np->pid, then acquires a lock +around the write to np->state. The acquire() prevents the +compiler from re-ordering. diff --git a/xv6-public/alarmtest.c b/xv6-public/alarmtest.c new file mode 100644 index 0000000..cef0a23 --- /dev/null +++ b/xv6-public/alarmtest.c @@ -0,0 +1,25 @@ +#include "types.h" +#include "stat.h" +#include "user.h" + +void periodic(); + +int +main(int argc, char *argv[]) +{ + int i; + printf(1, "alarmtest starting\n"); + alarm(10, periodic); + for(i = 0; i < 25*5000000; i++){ + if((i % 250000) == 0) + write(2, ".", 1); + } + exit(); +} + +void +periodic() +{ + printf(1, "alarm!\n"); +} + diff --git a/xv6-public/asm.h b/xv6-public/asm.h new file mode 100644 index 0000000..b8a7353 --- /dev/null +++ b/xv6-public/asm.h @@ -0,0 +1,18 @@ +// +// assembler macros to create x86 segments +// + +#define SEG_NULLASM \ + .word 0, 0; \ + .byte 0, 0, 0, 0 + +// The 0xC0 means the limit is in 4096-byte units +// and (for executable segments) 32-bit mode. +#define SEG_ASM(type,base,lim) \ + .word (((lim) >> 12) & 0xffff), ((base) & 0xffff); \ + .byte (((base) >> 16) & 0xff), (0x90 | (type)), \ + (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff) + +#define STA_X 0x8 // Executable segment +#define STA_W 0x2 // Writeable (non-executable segments) +#define STA_R 0x2 // Readable (executable segments) diff --git a/xv6-public/bio.c b/xv6-public/bio.c new file mode 100644 index 0000000..a45ff3e --- /dev/null +++ b/xv6-public/bio.c @@ -0,0 +1,144 @@ +// Buffer cache. +// +// The buffer cache is a linked list of buf structures holding +// cached copies of disk block contents. Caching disk blocks +// in memory reduces the number of disk reads and also provides +// a synchronization point for disk blocks used by multiple processes. +// +// Interface: +// * To get a buffer for a particular disk block, call bread. +// * After changing buffer data, call bwrite to write it to disk. +// * When done with the buffer, call brelse. +// * Do not use the buffer after calling brelse. +// * Only one process at a time can use a buffer, +// so do not keep them longer than necessary. +// +// The implementation uses two state flags internally: +// * B_VALID: the buffer data has been read from the disk. +// * B_DIRTY: the buffer data has been modified +// and needs to be written to disk. + +#include "types.h" +#include "defs.h" +#include "param.h" +#include "spinlock.h" +#include "sleeplock.h" +#include "fs.h" +#include "buf.h" + +struct { + struct spinlock lock; + struct buf buf[NBUF]; + + // Linked list of all buffers, through prev/next. + // head.next is most recently used. + struct buf head; +} bcache; + +void +binit(void) +{ + struct buf *b; + + initlock(&bcache.lock, "bcache"); + +//PAGEBREAK! + // Create linked list of buffers + bcache.head.prev = &bcache.head; + bcache.head.next = &bcache.head; + for(b = bcache.buf; b < bcache.buf+NBUF; b++){ + b->next = bcache.head.next; + b->prev = &bcache.head; + initsleeplock(&b->lock, "buffer"); + bcache.head.next->prev = b; + bcache.head.next = b; + } +} + +// Look through buffer cache for block on device dev. +// If not found, allocate a buffer. +// In either case, return locked buffer. +static struct buf* +bget(uint dev, uint blockno) +{ + struct buf *b; + + acquire(&bcache.lock); + + // Is the block already cached? + for(b = bcache.head.next; b != &bcache.head; b = b->next){ + if(b->dev == dev && b->blockno == blockno){ + b->refcnt++; + release(&bcache.lock); + acquiresleep(&b->lock); + return b; + } + } + + // Not cached; recycle an unused buffer. + // Even if refcnt==0, B_DIRTY indicates a buffer is in use + // because log.c has modified it but not yet committed it. + for(b = bcache.head.prev; b != &bcache.head; b = b->prev){ + if(b->refcnt == 0 && (b->flags & B_DIRTY) == 0) { + b->dev = dev; + b->blockno = blockno; + b->flags = 0; + b->refcnt = 1; + release(&bcache.lock); + acquiresleep(&b->lock); + return b; + } + } + panic("bget: no buffers"); +} + +// Return a locked buf with the contents of the indicated block. +struct buf* +bread(uint dev, uint blockno) +{ + struct buf *b; + + b = bget(dev, blockno); + if((b->flags & B_VALID) == 0) { + iderw(b); + } + return b; +} + +// Write b's contents to disk. Must be locked. +void +bwrite(struct buf *b) +{ + if(!holdingsleep(&b->lock)) + panic("bwrite"); + b->flags |= B_DIRTY; + iderw(b); +} + +// Release a locked buffer. +// Move to the head of the MRU list. +void +brelse(struct buf *b) +{ + if(!holdingsleep(&b->lock)) + panic("brelse"); + + releasesleep(&b->lock); + + acquire(&bcache.lock); + b->refcnt--; + if (b->refcnt == 0) { + // no one is waiting for it. + b->next->prev = b->prev; + b->prev->next = b->next; + b->next = bcache.head.next; + b->prev = &bcache.head; + bcache.head.next->prev = b; + bcache.head.next = b; + } + + release(&bcache.lock); +} +//PAGEBREAK! +// Blank page. + diff --git a/xv6-public/bootasm.S b/xv6-public/bootasm.S new file mode 100644 index 0000000..257867c --- /dev/null +++ b/xv6-public/bootasm.S @@ -0,0 +1,88 @@ +#include "asm.h" +#include "memlayout.h" +#include "mmu.h" + +# Start the first CPU: switch to 32-bit protected mode, jump into C. +# The BIOS loads this code from the first sector of the hard disk into +# memory at physical address 0x7c00 and starts executing in real mode +# with %cs=0 %ip=7c00. + +.code16 # Assemble for 16-bit mode +.globl start +start: + cli # BIOS enabled interrupts; disable + + # Zero data segment registers DS, ES, and SS. + xorw %ax,%ax # Set %ax to zero + movw %ax,%ds # -> Data Segment + movw %ax,%es # -> Extra Segment + movw %ax,%ss # -> Stack Segment + + # Physical address line A20 is tied to zero so that the first PCs + # with 2 MB would run software that assumed 1 MB. Undo that. +seta20.1: + inb $0x64,%al # Wait for not busy + testb $0x2,%al + jnz seta20.1 + + movb $0xd1,%al # 0xd1 -> port 0x64 + outb %al,$0x64 + +seta20.2: + inb $0x64,%al # Wait for not busy + testb $0x2,%al + jnz seta20.2 + + movb $0xdf,%al # 0xdf -> port 0x60 + outb %al,$0x60 + + # Switch from real to protected mode. Use a bootstrap GDT that makes + # virtual addresses map directly to physical addresses so that the + # effective memory map doesn't change during the transition. + lgdt gdtdesc + movl %cr0, %eax + orl $CR0_PE, %eax + movl %eax, %cr0 + +//PAGEBREAK! + # Complete the transition to 32-bit protected mode by using a long jmp + # to reload %cs and %eip. The segment descriptors are set up with no + # translation, so that the mapping is still the identity mapping. + ljmp $(SEG_KCODE<<3), $start32 + +.code32 # Tell assembler to generate 32-bit code now. +start32: + # Set up the protected-mode data segment registers + movw $(SEG_KDATA<<3), %ax # Our data segment selector + movw %ax, %ds # -> DS: Data Segment + movw %ax, %es # -> ES: Extra Segment + movw %ax, %ss # -> SS: Stack Segment + movw $0, %ax # Zero segments not ready for use + movw %ax, %fs # -> FS + movw %ax, %gs # -> GS + + # Set up the stack pointer and call into C. + movl $start, %esp + call bootmain + + # If bootmain returns (it shouldn't), trigger a Bochs + # breakpoint if running under Bochs, then loop. + movw $0x8a00, %ax # 0x8a00 -> port 0x8a00 + movw %ax, %dx + outw %ax, %dx + movw $0x8ae0, %ax # 0x8ae0 -> port 0x8a00 + outw %ax, %dx +spin: + jmp spin + +# Bootstrap GDT +.p2align 2 # force 4 byte alignment +gdt: + SEG_NULLASM # null seg + SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff) # code seg + SEG_ASM(STA_W, 0x0, 0xffffffff) # data seg + +gdtdesc: + .word (gdtdesc - gdt - 1) # sizeof(gdt) - 1 + .long gdt # address gdt + diff --git a/xv6-public/bootmain.c b/xv6-public/bootmain.c new file mode 100644 index 0000000..1f20e5b --- /dev/null +++ b/xv6-public/bootmain.c @@ -0,0 +1,96 @@ +// Boot loader. +// +// Part of the boot block, along with bootasm.S, which calls bootmain(). +// bootasm.S has put the processor into protected 32-bit mode. +// bootmain() loads an ELF kernel image from the disk starting at +// sector 1 and then jumps to the kernel entry routine. + +#include "types.h" +#include "elf.h" +#include "x86.h" +#include "memlayout.h" + +#define SECTSIZE 512 + +void readseg(uchar*, uint, uint); + +void +bootmain(void) +{ + struct elfhdr *elf; + struct proghdr *ph, *eph; + void (*entry)(void); + uchar* pa; + + elf = (struct elfhdr*)0x10000; // scratch space + + // Read 1st page off disk + readseg((uchar*)elf, 4096, 0); + + // Is this an ELF executable? + if(elf->magic != ELF_MAGIC) + return; // let bootasm.S handle error + + // Load each program segment (ignores ph flags). + ph = (struct proghdr*)((uchar*)elf + elf->phoff); + eph = ph + elf->phnum; + for(; ph < eph; ph++){ + pa = (uchar*)ph->paddr; + readseg(pa, ph->filesz, ph->off); + if(ph->memsz > ph->filesz) + stosb(pa + ph->filesz, 0, ph->memsz - ph->filesz); + } + + // Call the entry point from the ELF header. + // Does not return! + entry = (void(*)(void))(elf->entry); + entry(); +} + +void +waitdisk(void) +{ + // Wait for disk ready. + while((inb(0x1F7) & 0xC0) != 0x40) + ; +} + +// Read a single sector at offset into dst. +void +readsect(void *dst, uint offset) +{ + // Issue command. + waitdisk(); + outb(0x1F2, 1); // count = 1 + outb(0x1F3, offset); + outb(0x1F4, offset >> 8); + outb(0x1F5, offset >> 16); + outb(0x1F6, (offset >> 24) | 0xE0); + outb(0x1F7, 0x20); // cmd 0x20 - read sectors + + // Read data. + waitdisk(); + insl(0x1F0, dst, SECTSIZE/4); +} + +// Read 'count' bytes at 'offset' from kernel into physical address 'pa'. +// Might copy more than asked. +void +readseg(uchar* pa, uint count, uint offset) +{ + uchar* epa; + + epa = pa + count; + + // Round down to sector boundary. + pa -= offset % SECTSIZE; + + // Translate from bytes to sectors; kernel starts at sector 1. + offset = (offset / SECTSIZE) + 1; + + // If this is too slow, we could read lots of sectors at a time. + // We'd write more to memory than asked, but it doesn't matter -- + // we load in increasing order. + for(; pa < epa; pa += SECTSIZE, offset++) + readsect(pa, offset); +} diff --git a/xv6-public/buf.h b/xv6-public/buf.h new file mode 100644 index 0000000..3266495 --- /dev/null +++ b/xv6-public/buf.h @@ -0,0 +1,14 @@ +struct buf { + int flags; + uint dev; + uint blockno; + struct sleeplock lock; + uint refcnt; + struct buf *prev; // LRU cache list + struct buf *next; + struct buf *qnext; // disk queue + uchar data[BSIZE]; +}; +#define B_VALID 0x2 // buffer has been read from disk +#define B_DIRTY 0x4 // buffer needs to be written to disk + diff --git a/xv6-public/cat.c b/xv6-public/cat.c new file mode 100644 index 0000000..5ddc820 --- /dev/null +++ b/xv6-public/cat.c @@ -0,0 +1,43 @@ +#include "types.h" +#include "stat.h" +#include "user.h" + +char buf[512]; + +void +cat(int fd) +{ + int n; + + while((n = read(fd, buf, sizeof(buf))) > 0) { + if (write(1, buf, n) != n) { + printf(1, "cat: write error\n"); + exit(); + } + } + if(n < 0){ + printf(1, "cat: read error\n"); + exit(); + } +} + +int +main(int argc, char *argv[]) +{ + int fd, i; + + if(argc <= 1){ + cat(0); + exit(); + } + + for(i = 1; i < argc; i++){ + if((fd = open(argv[i], 0)) < 0){ + printf(1, "cat: cannot open %s\n", argv[i]); + exit(); + } + cat(fd); + close(fd); + } + exit(); +} diff --git a/xv6-public/console.c b/xv6-public/console.c new file mode 100644 index 0000000..a280d2b --- /dev/null +++ b/xv6-public/console.c @@ -0,0 +1,299 @@ +// Console input and output. +// Input is from the keyboard or serial port. +// Output is written to the screen and serial port. + +#include "types.h" +#include "defs.h" +#include "param.h" +#include "traps.h" +#include "spinlock.h" +#include "sleeplock.h" +#include "fs.h" +#include "file.h" +#include "memlayout.h" +#include "mmu.h" +#include "proc.h" +#include "x86.h" + +static void consputc(int); + +static int panicked = 0; + +static struct { + struct spinlock lock; + int locking; +} cons; + +static void +printint(int xx, int base, int sign) +{ + static char digits[] = "0123456789abcdef"; + char buf[16]; + int i; + uint x; + + if(sign && (sign = xx < 0)) + x = -xx; + else + x = xx; + + i = 0; + do{ + buf[i++] = digits[x % base]; + }while((x /= base) != 0); + + if(sign) + buf[i++] = '-'; + + while(--i >= 0) + consputc(buf[i]); +} +//PAGEBREAK: 50 + +// Print to the console. only understands %d, %x, %p, %s. +void +cprintf(char *fmt, ...) +{ + int i, c, locking; + uint *argp; + char *s; + + locking = cons.locking; + if(locking) + acquire(&cons.lock); + + if (fmt == 0) + panic("null fmt"); + + argp = (uint*)(void*)(&fmt + 1); + for(i = 0; (c = fmt[i] & 0xff) != 0; i++){ + if(c != '%'){ + consputc(c); + continue; + } + c = fmt[++i] & 0xff; + if(c == 0) + break; + switch(c){ + case 'd': + printint(*argp++, 10, 1); + break; + case 'x': + case 'p': + printint(*argp++, 16, 0); + break; + case 's': + if((s = (char*)*argp++) == 0) + s = "(null)"; + for(; *s; s++) + consputc(*s); + break; + case '%': + consputc('%'); + break; + default: + // Print unknown % sequence to draw attention. + consputc('%'); + consputc(c); + break; + } + } + + if(locking) + release(&cons.lock); +} + +void +panic(char *s) +{ + int i; + uint pcs[10]; + + cli(); + cons.locking = 0; + // use lapiccpunum so that we can call panic from mycpu() + cprintf("lapicid %d: panic: ", lapicid()); + cprintf(s); + cprintf("\n"); + getcallerpcs(&s, pcs); + for(i=0; i<10; i++) + cprintf(" %p", pcs[i]); + panicked = 1; // freeze other CPU + for(;;) + ; +} + +//PAGEBREAK: 50 +#define BACKSPACE 0x100 +#define CRTPORT 0x3d4 +static ushort *crt = (ushort*)P2V(0xb8000); // CGA memory + +static void +cgaputc(int c) +{ + int pos; + + // Cursor position: col + 80*row. + outb(CRTPORT, 14); + pos = inb(CRTPORT+1) << 8; + outb(CRTPORT, 15); + pos |= inb(CRTPORT+1); + + if(c == '\n') + pos += 80 - pos%80; + else if(c == BACKSPACE){ + if(pos > 0) --pos; + } else + crt[pos++] = (c&0xff) | 0x0700; // black on white + + if(pos < 0 || pos > 25*80) + panic("pos under/overflow"); + + if((pos/80) >= 24){ // Scroll up. + memmove(crt, crt+80, sizeof(crt[0])*23*80); + pos -= 80; + memset(crt+pos, 0, sizeof(crt[0])*(24*80 - pos)); + } + + outb(CRTPORT, 14); + outb(CRTPORT+1, pos>>8); + outb(CRTPORT, 15); + outb(CRTPORT+1, pos); + crt[pos] = ' ' | 0x0700; +} + +void +consputc(int c) +{ + if(panicked){ + cli(); + for(;;) + ; + } + + if(c == BACKSPACE){ + uartputc('\b'); uartputc(' '); uartputc('\b'); + } else + uartputc(c); + cgaputc(c); +} + +#define INPUT_BUF 128 +struct { + char buf[INPUT_BUF]; + uint r; // Read index + uint w; // Write index + uint e; // Edit index +} input; + +#define C(x) ((x)-'@') // Control-x + +void +consoleintr(int (*getc)(void)) +{ + int c, doprocdump = 0; + + acquire(&cons.lock); + while((c = getc()) >= 0){ + switch(c){ + case C('P'): // Process listing. + // procdump() locks cons.lock indirectly; invoke later + doprocdump = 1; + break; + case C('U'): // Kill line. + while(input.e != input.w && + input.buf[(input.e-1) % INPUT_BUF] != '\n'){ + input.e--; + consputc(BACKSPACE); + } + break; + case C('H'): case '\x7f': // Backspace + if(input.e != input.w){ + input.e--; + consputc(BACKSPACE); + } + break; + default: + if(c != 0 && input.e-input.r < INPUT_BUF){ + c = (c == '\r') ? '\n' : c; + input.buf[input.e++ % INPUT_BUF] = c; + consputc(c); + if(c == '\n' || c == C('D') || input.e == input.r+INPUT_BUF){ + input.w = input.e; + wakeup(&input.r); + } + } + break; + } + } + release(&cons.lock); + if(doprocdump) { + procdump(); // now call procdump() wo. cons.lock held + } +} + +int +consoleread(struct inode *ip, char *dst, int n) +{ + uint target; + int c; + + iunlock(ip); + target = n; + acquire(&cons.lock); + while(n > 0){ + while(input.r == input.w){ + if(myproc()->killed){ + release(&cons.lock); + ilock(ip); + return -1; + } + sleep(&input.r, &cons.lock); + } + c = input.buf[input.r++ % INPUT_BUF]; + if(c == C('D')){ // EOF + if(n < target){ + // Save ^D for next time, to make sure + // caller gets a 0-byte result. + input.r--; + } + break; + } + *dst++ = c; + --n; + if(c == '\n') + break; + } + release(&cons.lock); + ilock(ip); + + return target - n; +} + +int +consolewrite(struct inode *ip, char *buf, int n) +{ + int i; + + iunlock(ip); + acquire(&cons.lock); + for(i = 0; i < n; i++) + consputc(buf[i] & 0xff); + release(&cons.lock); + ilock(ip); + + return n; +} + +void +consoleinit(void) +{ + initlock(&cons.lock, "console"); + + devsw[CONSOLE].write = consolewrite; + devsw[CONSOLE].read = consoleread; + cons.locking = 1; + + ioapicenable(IRQ_KBD, 0); +} + diff --git a/xv6-public/cuth b/xv6-public/cuth new file mode 100644 index 0000000..cce8c0c --- /dev/null +++ b/xv6-public/cuth @@ -0,0 +1,48 @@ +#!/usr/bin/perl + +$| = 1; + +sub writefile($@){ + my ($file, @lines) = @_; + + sleep(1); + open(F, ">$file") || die "open >$file: $!"; + print F @lines; + close(F); +} + +# Cut out #include lines that don't contribute anything. +for($i=0; $i<@ARGV; $i++){ + $file = $ARGV[$i]; + if(!open(F, $file)){ + print STDERR "open $file: $!\n"; + next; + } + @lines = ; + close(F); + + $obj = "$file.o"; + $obj =~ s/\.c\.o$/.o/; + system("touch $file"); + + if(system("make CC='gcc -Werror' $obj >/dev/null 2>\&1") != 0){ + print STDERR "make $obj failed: $rv\n"; + next; + } + + system("cp $file =$file"); + for($j=@lines-1; $j>=0; $j--){ + if($lines[$j] =~ /^#include/){ + $old = $lines[$j]; + $lines[$j] = "/* CUT-H */\n"; + writefile($file, @lines); + if(system("make CC='gcc -Werror' $obj >/dev/null 2>\&1") != 0){ + $lines[$j] = $old; + }else{ + print STDERR "$file $old"; + } + } + } + writefile($file, grep {!/CUT-H/} @lines); + system("rm =$file"); +} diff --git a/xv6-public/date.c b/xv6-public/date.c new file mode 100644 index 0000000..4744c48 --- /dev/null +++ b/xv6-public/date.c @@ -0,0 +1,20 @@ +#include "types.h" +#include "user.h" +#include "date.h" + + + +int +main(int argc, char *argv[]) +{ + struct rtcdate r; + + if (date(&r)) { + printf(2, "date failed\n"); + exit(); + } + + // your code to print the time in any format you like... + printf(1, "%d-%d-%d %d:%d\n",r.year, r.month, r.day, r.hour, r.minute); + exit(); +} diff --git a/xv6-public/date.h b/xv6-public/date.h new file mode 100644 index 0000000..94aec4b --- /dev/null +++ b/xv6-public/date.h @@ -0,0 +1,8 @@ +struct rtcdate { + uint second; + uint minute; + uint hour; + uint day; + uint month; + uint year; +}; diff --git a/xv6-public/defs.h b/xv6-public/defs.h new file mode 100644 index 0000000..82fb982 --- /dev/null +++ b/xv6-public/defs.h @@ -0,0 +1,190 @@ +struct buf; +struct context; +struct file; +struct inode; +struct pipe; +struct proc; +struct rtcdate; +struct spinlock; +struct sleeplock; +struct stat; +struct superblock; + +// bio.c +void binit(void); +struct buf* bread(uint, uint); +void brelse(struct buf*); +void bwrite(struct buf*); + +// console.c +void consoleinit(void); +void cprintf(char*, ...); +void consoleintr(int(*)(void)); +void panic(char*) __attribute__((noreturn)); + +// exec.c +int exec(char*, char**); + +// file.c +struct file* filealloc(void); +void fileclose(struct file*); +struct file* filedup(struct file*); +void fileinit(void); +int fileread(struct file*, char*, int n); +int filestat(struct file*, struct stat*); +int filewrite(struct file*, char*, int n); + +// fs.c +void readsb(int dev, struct superblock *sb); +int dirlink(struct inode*, char*, uint); +struct inode* dirlookup(struct inode*, char*, uint*); +struct inode* ialloc(uint, short); +struct inode* idup(struct inode*); +void iinit(int dev); +void ilock(struct inode*); +void iput(struct inode*); +void iunlock(struct inode*); +void iunlockput(struct inode*); +void iupdate(struct inode*); +int namecmp(const char*, const char*); +struct inode* namei(char*); +struct inode* nameiparent(char*, char*); +int readi(struct inode*, char*, uint, uint); +void stati(struct inode*, struct stat*); +int writei(struct inode*, char*, uint, uint); + +// ide.c +void ideinit(void); +void ideintr(void); +void iderw(struct buf*); + +// ioapic.c +void ioapicenable(int irq, int cpu); +extern uchar ioapicid; +void ioapicinit(void); + +// kalloc.c +char* kalloc(void); +void kfree(char*); +void kinit1(void*, void*); +void kinit2(void*, void*); + +// kbd.c +void kbdintr(void); + +// lapic.c +void cmostime(struct rtcdate *r); +int lapicid(void); +extern volatile uint* lapic; +void lapiceoi(void); +void lapicinit(void); +void lapicstartap(uchar, uint); +void microdelay(int); + +// log.c +void initlog(int dev); +void log_write(struct buf*); +void begin_op(); +void end_op(); + +// mp.c +extern int ismp; +void mpinit(void); + +// picirq.c +void picenable(int); +void picinit(void); + +// pipe.c +int pipealloc(struct file**, struct file**); +void pipeclose(struct pipe*, int); +int piperead(struct pipe*, char*, int); +int pipewrite(struct pipe*, char*, int); + +//PAGEBREAK: 16 +// proc.c +int cpuid(void); +void exit(void); +int fork(void); +int growproc(int); +int kill(int); +struct cpu* mycpu(void); +struct proc* myproc(); +void pinit(void); +void procdump(void); +void scheduler(void) __attribute__((noreturn)); +void sched(void); +void setproc(struct proc*); +void sleep(void*, struct spinlock*); +void userinit(void); +int wait(void); +void wakeup(void*); +void yield(void); + +// swtch.S +void swtch(struct context**, struct context*); + +// spinlock.c +void acquire(struct spinlock*); +void getcallerpcs(void*, uint*); +int holding(struct spinlock*); +void initlock(struct spinlock*, char*); +void release(struct spinlock*); +void pushcli(void); +void popcli(void); + +// sleeplock.c +void acquiresleep(struct sleeplock*); +void releasesleep(struct sleeplock*); +int holdingsleep(struct sleeplock*); +void initsleeplock(struct sleeplock*, char*); + +// string.c +int memcmp(const void*, const void*, uint); +void* memmove(void*, const void*, uint); +void* memset(void*, int, uint); +char* safestrcpy(char*, const char*, int); +int strlen(const char*); +int strncmp(const char*, const char*, uint); +char* strncpy(char*, const char*, int); + +// syscall.c +int argint(int, int*); +int argptr(int, char**, int); +int argstr(int, char**); +int fetchint(uint, int*); +int fetchstr(uint, char**); +void syscall(void); + +// timer.c +void timerinit(void); + +// trap.c +void idtinit(void); +extern uint ticks; +void tvinit(void); +extern struct spinlock tickslock; + +// uart.c +void uartinit(void); +void uartintr(void); +void uartputc(int); + +// vm.c +void seginit(void); +void kvmalloc(void); +pde_t* setupkvm(void); +char* uva2ka(pde_t*, char*); +int allocuvm(pde_t*, uint, uint); +int deallocuvm(pde_t*, uint, uint); +void freevm(pde_t*); +void inituvm(pde_t*, char*, uint); +int loaduvm(pde_t*, char*, struct inode*, uint, uint); +pde_t* copyuvm(pde_t*, uint); +void switchuvm(struct proc*); +void switchkvm(void); +int copyout(pde_t*, uint, void*, uint); +void clearpteu(pde_t *pgdir, char *uva); + +// number of elements in fixed-size array +#define NELEM(x) (sizeof(x)/sizeof((x)[0])) diff --git a/xv6-public/dot-bochsrc b/xv6-public/dot-bochsrc new file mode 100644 index 0000000..ba13db7 --- /dev/null +++ b/xv6-public/dot-bochsrc @@ -0,0 +1,738 @@ +# You may now use double quotes around pathnames, in case +# your pathname includes spaces. + +#======================================================================= +# CONFIG_INTERFACE +# +# The configuration interface is a series of menus or dialog boxes that +# allows you to change all the settings that control Bochs's behavior. +# There are two choices of configuration interface: a text mode version +# called "textconfig" and a graphical version called "wx". The text +# mode version uses stdin/stdout and is always compiled in. The graphical +# version is only available when you use "--with-wx" on the configure +# command. If you do not write a config_interface line, Bochs will +# choose a default for you. +# +# NOTE: if you use the "wx" configuration interface, you must also use +# the "wx" display library. +#======================================================================= +#config_interface: textconfig +#config_interface: wx + +#======================================================================= +# DISPLAY_LIBRARY +# +# The display library is the code that displays the Bochs VGA screen. Bochs +# has a selection of about 10 different display library implementations for +# different platforms. If you run configure with multiple --with-* options, +# the display_library command lets you choose which one you want to run with. +# If you do not write a display_library line, Bochs will choose a default for +# you. +# +# The choices are: +# x use X windows interface, cross platform +# win32 use native win32 libraries +# carbon use Carbon library (for MacOS X) +# beos use native BeOS libraries +# macintosh use MacOS pre-10 +# amigaos use native AmigaOS libraries +# sdl use SDL library, cross platform +# svga use SVGALIB library for Linux, allows graphics without X11 +# term text only, uses curses/ncurses library, cross platform +# rfb provides an interface to AT&T's VNC viewer, cross platform +# wx use wxWidgets library, cross platform +# nogui no display at all +# +# NOTE: if you use the "wx" configuration interface, you must also use +# the "wx" display library. +# +# Specific options: +# Some display libraries now support specific option to control their +# behaviour. See the examples below for currently supported options. +#======================================================================= +#display_library: amigaos +#display_library: beos +#display_library: carbon +#display_library: macintosh +#display_library: nogui +#display_library: rfb, options="timeout=60" # time to wait for client +#display_library: sdl, options="fullscreen" # startup in fullscreen mode +#display_library: term +#display_library: win32, options="legacyF12" # use F12 to toggle mouse +#display_library: wx +#display_library: x + +#======================================================================= +# ROMIMAGE: +# The ROM BIOS controls what the PC does when it first powers on. +# Normally, you can use a precompiled BIOS in the source or binary +# distribution called BIOS-bochs-latest. The ROM BIOS is usually loaded +# starting at address 0xf0000, and it is exactly 64k long. +# You can also use the environment variable $BXSHARE to specify the +# location of the BIOS. +# The usage of external large BIOS images (up to 512k) at memory top is +# now supported, but we still recommend to use the BIOS distributed with +# Bochs. Now the start address can be calculated from image size. +#======================================================================= +romimage: file=$BXSHARE/BIOS-bochs-latest +#romimage: file=mybios.bin, address=0xfff80000 # 512k at memory top +#romimage: file=mybios.bin # calculate start address from image size + +#======================================================================= +# CPU: +# This defines cpu-related parameters inside Bochs: +# +# COUNT: +# Set the number of processors when Bochs is compiled for SMP emulation. +# Bochs currently supports up to 8 processors. If Bochs is compiled +# without SMP support, it won't accept values different from 1. +# +# IPS: +# Emulated Instructions Per Second. This is the number of IPS that bochs +# is capable of running on your machine. You can recompile Bochs with +# --enable-show-ips option enabled, to find your workstation's capability. +# Measured IPS value will then be logged into your log file or status bar +# (if supported by the gui). +# +# IPS is used to calibrate many time-dependent events within the bochs +# simulation. For example, changing IPS affects the frequency of VGA +# updates, the duration of time before a key starts to autorepeat, and +# the measurement of BogoMips and other benchmarks. +# +# Examples: +# Machine Mips +# ________________________________________________________________ +# 2.1Ghz Athlon XP with Linux 2.6/g++ 3.4 12 to 15 Mips +# 1.6Ghz Intel P4 with Win2000/g++ 3.3 5 to 7 Mips +# 650Mhz Athlon K-7 with Linux 2.4.4/egcs-2.91.66 2 to 2.5 Mips +# 400Mhz Pentium II with Linux 2.0.36/egcs-1.0.3 1 to 1.8 Mips +#======================================================================= +cpu: count=2, ips=10000000 + +#======================================================================= +# MEGS +# Set the number of Megabytes of physical memory you want to emulate. +# The default is 32MB, most OS's won't need more than that. +# The maximum amount of memory supported is 2048Mb. +#======================================================================= +#megs: 256 +#megs: 128 +#megs: 64 +megs: 32 +#megs: 16 +#megs: 8 + +#======================================================================= +# OPTROMIMAGE[1-4]: +# You may now load up to 4 optional ROM images. Be sure to use a +# read-only area, typically between C8000 and EFFFF. These optional +# ROM images should not overwrite the rombios (located at +# F0000-FFFFF) and the videobios (located at C0000-C7FFF). +# Those ROM images will be initialized by the bios if they contain +# the right signature (0x55AA) and a valid checksum. +# It can also be a convenient way to upload some arbitrary code/data +# in the simulation, that can be retrieved by the boot loader +#======================================================================= +#optromimage1: file=optionalrom.bin, address=0xd0000 +#optromimage2: file=optionalrom.bin, address=0xd1000 +#optromimage3: file=optionalrom.bin, address=0xd2000 +#optromimage4: file=optionalrom.bin, address=0xd3000 + +#optramimage1: file=/path/file1.img, address=0x0010000 +#optramimage2: file=/path/file2.img, address=0x0020000 +#optramimage3: file=/path/file3.img, address=0x0030000 +#optramimage4: file=/path/file4.img, address=0x0040000 + +#======================================================================= +# VGAROMIMAGE +# You now need to load a VGA ROM BIOS into C0000. +#======================================================================= +#vgaromimage: file=bios/VGABIOS-elpin-2.40 +vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest +#vgaromimage: file=bios/VGABIOS-lgpl-latest-cirrus + +#======================================================================= +# VGA: +# Here you can specify the display extension to be used. With the value +# 'none' you can use standard VGA with no extension. Other supported +# values are 'vbe' for Bochs VBE and 'cirrus' for Cirrus SVGA support. +#======================================================================= +#vga: extension=cirrus +#vga: extension=vbe +vga: extension=none + +#======================================================================= +# FLOPPYA: +# Point this to pathname of floppy image file or device +# This should be of a bootable floppy(image/device) if you're +# booting from 'a' (or 'floppy'). +# +# You can set the initial status of the media to 'ejected' or 'inserted'. +# floppya: 2_88=path, status=ejected (2.88M 3.5" floppy) +# floppya: 1_44=path, status=inserted (1.44M 3.5" floppy) +# floppya: 1_2=path, status=ejected (1.2M 5.25" floppy) +# floppya: 720k=path, status=inserted (720K 3.5" floppy) +# floppya: 360k=path, status=inserted (360K 5.25" floppy) +# floppya: 320k=path, status=inserted (320K 5.25" floppy) +# floppya: 180k=path, status=inserted (180K 5.25" floppy) +# floppya: 160k=path, status=inserted (160K 5.25" floppy) +# floppya: image=path, status=inserted (guess type from image size) +# +# The path should be the name of a disk image file. On Unix, you can use a raw +# device name such as /dev/fd0 on Linux. On win32 platforms, use drive letters +# such as a: or b: as the path. The parameter 'image' works with image files +# only. In that case the size must match one of the supported types. +#======================================================================= +floppya: 1_44=/dev/fd0, status=inserted +#floppya: image=../1.44, status=inserted +#floppya: 1_44=/dev/fd0H1440, status=inserted +#floppya: 1_2=../1_2, status=inserted +#floppya: 1_44=a:, status=inserted +#floppya: 1_44=a.img, status=inserted +#floppya: 1_44=/dev/rfd0a, status=inserted + +#======================================================================= +# FLOPPYB: +# See FLOPPYA above for syntax +#======================================================================= +#floppyb: 1_44=b:, status=inserted +floppyb: 1_44=b.img, status=inserted + +#======================================================================= +# ATA0, ATA1, ATA2, ATA3 +# ATA controller for hard disks and cdroms +# +# ata[0-3]: enabled=[0|1], ioaddr1=addr, ioaddr2=addr, irq=number +# +# These options enables up to 4 ata channels. For each channel +# the two base io addresses and the irq must be specified. +# +# ata0 and ata1 are enabled by default with the values shown below +# +# Examples: +# ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 +# ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 +# ata2: enabled=1, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11 +# ata3: enabled=1, ioaddr1=0x168, ioaddr2=0x360, irq=9 +#======================================================================= +ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 +ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 +ata2: enabled=0, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11 +ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9 + +#======================================================================= +# ATA[0-3]-MASTER, ATA[0-3]-SLAVE +# +# This defines the type and characteristics of all attached ata devices: +# type= type of attached device [disk|cdrom] +# mode= only valid for disks [flat|concat|external|dll|sparse|vmware3] +# mode= only valid for disks [undoable|growing|volatile] +# path= path of the image +# cylinders= only valid for disks +# heads= only valid for disks +# spt= only valid for disks +# status= only valid for cdroms [inserted|ejected] +# biosdetect= type of biosdetection [none|auto], only for disks on ata0 [cmos] +# translation=type of translation of the bios, only for disks [none|lba|large|rechs|auto] +# model= string returned by identify device command +# journal= optional filename of the redolog for undoable and volatile disks +# +# Point this at a hard disk image file, cdrom iso file, or physical cdrom +# device. To create a hard disk image, try running bximage. It will help you +# choose the size and then suggest a line that works with it. +# +# In UNIX it may be possible to use a raw device as a Bochs hard disk, +# but WE DON'T RECOMMEND IT. In Windows there is no easy way. +# +# In windows, the drive letter + colon notation should be used for cdroms. +# Depending on versions of windows and drivers, you may only be able to +# access the "first" cdrom in the system. On MacOSX, use path="drive" +# to access the physical drive. +# +# The path is always mandatory. For flat hard disk images created with +# bximage geometry autodetection can be used (cylinders=0 -> cylinders are +# calculated using heads=16 and spt=63). For other hard disk images and modes +# the cylinders, heads, and spt are mandatory. +# +# Default values are: +# mode=flat, biosdetect=auto, translation=auto, model="Generic 1234" +# +# The biosdetect option has currently no effect on the bios +# +# Examples: +# ata0-master: type=disk, mode=flat, path=10M.sample, cylinders=306, heads=4, spt=17 +# ata0-slave: type=disk, mode=flat, path=20M.sample, cylinders=615, heads=4, spt=17 +# ata1-master: type=disk, mode=flat, path=30M.sample, cylinders=615, heads=6, spt=17 +# ata1-slave: type=disk, mode=flat, path=46M.sample, cylinders=940, heads=6, spt=17 +# ata2-master: type=disk, mode=flat, path=62M.sample, cylinders=940, heads=8, spt=17 +# ata2-slave: type=disk, mode=flat, path=112M.sample, cylinders=900, heads=15, spt=17 +# ata3-master: type=disk, mode=flat, path=483M.sample, cylinders=1024, heads=15, spt=63 +# ata3-slave: type=cdrom, path=iso.sample, status=inserted +#======================================================================= +ata0-master: type=disk, mode=flat, path="xv6.img", cylinders=100, heads=10, spt=10 +ata0-slave: type=disk, mode=flat, path="fs.img", cylinders=1024, heads=1, spt=1 +#ata0-slave: type=cdrom, path=D:, status=inserted +#ata0-slave: type=cdrom, path=/dev/cdrom, status=inserted +#ata0-slave: type=cdrom, path="drive", status=inserted +#ata0-slave: type=cdrom, path=/dev/rcd0d, status=inserted + +#======================================================================= +# BOOT: +# This defines the boot sequence. Now you can specify up to 3 boot drives. +# You can either boot from 'floppy', 'disk' or 'cdrom' +# legacy 'a' and 'c' are also supported +# Examples: +# boot: floppy +# boot: disk +# boot: cdrom +# boot: c +# boot: a +# boot: cdrom, floppy, disk +#======================================================================= +#boot: floppy +boot: disk + +#======================================================================= +# CLOCK: +# This defines the parameters of the clock inside Bochs: +# +# SYNC: +# TO BE COMPLETED (see Greg explanation in feature request #536329) +# +# TIME0: +# Specifies the start (boot) time of the virtual machine. Use a time +# value as returned by the time(2) system call. If no time0 value is +# set or if time0 equal to 1 (special case) or if time0 equal 'local', +# the simulation will be started at the current local host time. +# If time0 equal to 2 (special case) or if time0 equal 'utc', +# the simulation will be started at the current utc time. +# +# Syntax: +# clock: sync=[none|slowdown|realtime|both], time0=[timeValue|local|utc] +# +# Example: +# clock: sync=none, time0=local # Now (localtime) +# clock: sync=slowdown, time0=315529200 # Tue Jan 1 00:00:00 1980 +# clock: sync=none, time0=631148400 # Mon Jan 1 00:00:00 1990 +# clock: sync=realtime, time0=938581955 # Wed Sep 29 07:12:35 1999 +# clock: sync=realtime, time0=946681200 # Sat Jan 1 00:00:00 2000 +# clock: sync=none, time0=1 # Now (localtime) +# clock: sync=none, time0=utc # Now (utc/gmt) +# +# Default value are sync=none, time0=local +#======================================================================= +#clock: sync=none, time0=local + + +#======================================================================= +# FLOPPY_BOOTSIG_CHECK: disabled=[0|1] +# Enables or disables the 0xaa55 signature check on boot floppies +# Defaults to disabled=0 +# Examples: +# floppy_bootsig_check: disabled=0 +# floppy_bootsig_check: disabled=1 +#======================================================================= +#floppy_bootsig_check: disabled=1 +floppy_bootsig_check: disabled=0 + +#======================================================================= +# LOG: +# Give the path of the log file you'd like Bochs debug and misc. verbiage +# to be written to. If you don't use this option or set the filename to +# '-' the output is written to the console. If you really don't want it, +# make it "/dev/null" (Unix) or "nul" (win32). :^( +# +# Examples: +# log: ./bochs.out +# log: /dev/tty +#======================================================================= +#log: /dev/null +log: bochsout.txt + +#======================================================================= +# LOGPREFIX: +# This handles the format of the string prepended to each log line. +# You may use those special tokens : +# %t : 11 decimal digits timer tick +# %i : 8 hexadecimal digits of cpu current eip (ignored in SMP configuration) +# %e : 1 character event type ('i'nfo, 'd'ebug, 'p'anic, 'e'rror) +# %d : 5 characters string of the device, between brackets +# +# Default : %t%e%d +# Examples: +# logprefix: %t-%e-@%i-%d +# logprefix: %i%e%d +#======================================================================= +#logprefix: %t%e%d + +#======================================================================= +# LOG CONTROLS +# +# Bochs now has four severity levels for event logging. +# panic: cannot proceed. If you choose to continue after a panic, +# don't be surprised if you get strange behavior or crashes. +# error: something went wrong, but it is probably safe to continue the +# simulation. +# info: interesting or useful messages. +# debug: messages useful only when debugging the code. This may +# spit out thousands per second. +# +# For events of each level, you can choose to crash, report, or ignore. +# TODO: allow choice based on the facility: e.g. crash on panics from +# everything except the cdrom, and only report those. +# +# If you are experiencing many panics, it can be helpful to change +# the panic action to report instead of fatal. However, be aware +# that anything executed after a panic is uncharted territory and can +# cause bochs to become unstable. The panic is a "graceful exit," so +# if you disable it you may get a spectacular disaster instead. +#======================================================================= +panic: action=ask +error: action=report +info: action=report +debug: action=ignore +#pass: action=fatal + +#======================================================================= +# DEBUGGER_LOG: +# Give the path of the log file you'd like Bochs to log debugger output. +# If you really don't want it, make it /dev/null or '-'. :^( +# +# Examples: +# debugger_log: ./debugger.out +#======================================================================= +#debugger_log: /dev/null +#debugger_log: debugger.out +debugger_log: - + +#======================================================================= +# COM1, COM2, COM3, COM4: +# This defines a serial port (UART type 16550A). In the 'term' you can specify +# a device to use as com1. This can be a real serial line, or a pty. To use +# a pty (under X/Unix), create two windows (xterms, usually). One of them will +# run bochs, and the other will act as com1. Find out the tty the com1 +# window using the `tty' command, and use that as the `dev' parameter. +# Then do `sleep 1000000' in the com1 window to keep the shell from +# messing with things, and run bochs in the other window. Serial I/O to +# com1 (port 0x3f8) will all go to the other window. +# Other serial modes are 'null' (no input/output), 'file' (output to a file +# specified as the 'dev' parameter), 'raw' (use the real serial port - under +# construction for win32), 'mouse' (standard serial mouse - requires +# mouse option setting 'type=serial' or 'type=serial_wheel') and 'socket' +# (connect a networking socket). +# +# Examples: +# com1: enabled=1, mode=null +# com1: enabled=1, mode=mouse +# com2: enabled=1, mode=file, dev=serial.out +# com3: enabled=1, mode=raw, dev=com1 +# com3: enabled=1, mode=socket, dev=localhost:8888 +#======================================================================= +#com1: enabled=1, mode=term, dev=/dev/ttyp9 + + +#======================================================================= +# PARPORT1, PARPORT2: +# This defines a parallel (printer) port. When turned on and an output file is +# defined the emulated printer port sends characters printed by the guest OS +# into the output file. On some platforms a device filename can be used to +# send the data to the real parallel port (e.g. "/dev/lp0" on Linux, "lpt1" on +# win32 platforms). +# +# Examples: +# parport1: enabled=1, file="parport.out" +# parport2: enabled=1, file="/dev/lp0" +# parport1: enabled=0 +#======================================================================= +parport1: enabled=1, file="/dev/stdout" + +#======================================================================= +# SB16: +# This defines the SB16 sound emulation. It can have several of the +# following properties. +# All properties are in the format sb16: property=value +# midi: The filename is where the midi data is sent. This can be a +# device or just a file if you want to record the midi data. +# midimode: +# 0=no data +# 1=output to device (system dependent. midi denotes the device driver) +# 2=SMF file output, including headers +# 3=output the midi data stream to the file (no midi headers and no +# delta times, just command and data bytes) +# wave: This is the device/file where wave output is stored +# wavemode: +# 0=no data +# 1=output to device (system dependent. wave denotes the device driver) +# 2=VOC file output, incl. headers +# 3=output the raw wave stream to the file +# log: The file to write the sb16 emulator messages to. +# loglevel: +# 0=no log +# 1=resource changes, midi program and bank changes +# 2=severe errors +# 3=all errors +# 4=all errors plus all port accesses +# 5=all errors and port accesses plus a lot of extra info +# dmatimer: +# microseconds per second for a DMA cycle. Make it smaller to fix +# non-continuous sound. 750000 is usually a good value. This needs a +# reasonably correct setting for the IPS parameter of the CPU option. +# +# For an example look at the next line: +#======================================================================= + +#sb16: midimode=1, midi=/dev/midi00, wavemode=1, wave=/dev/dsp, loglevel=2, log=sb16.log, dmatimer=600000 + +#======================================================================= +# VGA_UPDATE_INTERVAL: +# Video memory is scanned for updates and screen updated every so many +# virtual seconds. The default is 40000, about 25Hz. Keep in mind that +# you must tweak the 'cpu: ips=N' directive to be as close to the number +# of emulated instructions-per-second your workstation can do, for this +# to be accurate. +# +# Examples: +# vga_update_interval: 250000 +#======================================================================= +vga_update_interval: 300000 + +# using for Winstone '98 tests +#vga_update_interval: 100000 + +#======================================================================= +# KEYBOARD_SERIAL_DELAY: +# Approximate time in microseconds that it takes one character to +# be transfered from the keyboard to controller over the serial path. +# Examples: +# keyboard_serial_delay: 200 +#======================================================================= +keyboard_serial_delay: 250 + +#======================================================================= +# KEYBOARD_PASTE_DELAY: +# Approximate time in microseconds between attempts to paste +# characters to the keyboard controller. This leaves time for the +# guest os to deal with the flow of characters. The ideal setting +# depends on how your operating system processes characters. The +# default of 100000 usec (.1 seconds) was chosen because it works +# consistently in Windows. +# +# If your OS is losing characters during a paste, increase the paste +# delay until it stops losing characters. +# +# Examples: +# keyboard_paste_delay: 100000 +#======================================================================= +keyboard_paste_delay: 100000 + +#======================================================================= +# MOUSE: +# This option prevents Bochs from creating mouse "events" unless a mouse +# is enabled. The hardware emulation itself is not disabled by this. +# You can turn the mouse on by setting enabled to 1, or turn it off by +# setting enabled to 0. Unless you have a particular reason for enabling +# the mouse by default, it is recommended that you leave it off. +# You can also toggle the mouse usage at runtime (control key + middle +# mouse button on X11, SDL, wxWidgets and Win32). +# With the mouse type option you can select the type of mouse to emulate. +# The default value is 'ps2'. The other choices are 'imps2' (wheel mouse +# on PS/2), 'serial', 'serial_wheel' (one com port requires setting +# 'mode=mouse') and 'usb' (3-button mouse - one of the USB ports must be +# connected with the 'mouse' device - requires PCI and USB support). +# +# Examples: +# mouse: enabled=1 +# mouse: enabled=1, type=imps2 +# mouse: enabled=1, type=serial +# mouse: enabled=0 +#======================================================================= +mouse: enabled=0 + +#======================================================================= +# private_colormap: Request that the GUI create and use it's own +# non-shared colormap. This colormap will be used +# when in the bochs window. If not enabled, a +# shared colormap scheme may be used. Not implemented +# on all GUI's. +# +# Examples: +# private_colormap: enabled=1 +# private_colormap: enabled=0 +#======================================================================= +private_colormap: enabled=0 + +#======================================================================= +# fullscreen: ONLY IMPLEMENTED ON AMIGA +# Request that Bochs occupy the entire screen instead of a +# window. +# +# Examples: +# fullscreen: enabled=0 +# fullscreen: enabled=1 +#======================================================================= +#fullscreen: enabled=0 +#screenmode: name="sample" + +#======================================================================= +# ne2k: NE2000 compatible ethernet adapter +# +# Examples: +# ne2k: ioaddr=IOADDR, irq=IRQ, mac=MACADDR, ethmod=MODULE, ethdev=DEVICE, script=SCRIPT +# +# ioaddr, irq: You probably won't need to change ioaddr and irq, unless there +# are IRQ conflicts. +# +# mac: The MAC address MUST NOT match the address of any machine on the net. +# Also, the first byte must be an even number (bit 0 set means a multicast +# address), and you cannot use ff:ff:ff:ff:ff:ff because that's the broadcast +# address. For the ethertap module, you must use fe:fd:00:00:00:01. There may +# be other restrictions too. To be safe, just use the b0:c4... address. +# +# ethdev: The ethdev value is the name of the network interface on your host +# platform. On UNIX machines, you can get the name by running ifconfig. On +# Windows machines, you must run niclist to get the name of the ethdev. +# Niclist source code is in misc/niclist.c and it is included in Windows +# binary releases. +# +# script: The script value is optional, and is the name of a script that +# is executed after bochs initialize the network interface. You can use +# this script to configure this network interface, or enable masquerading. +# This is mainly useful for the tun/tap devices that only exist during +# Bochs execution. The network interface name is supplied to the script +# as first parameter +# +# If you don't want to make connections to any physical networks, +# you can use the following 'ethmod's to simulate a virtual network. +# null: All packets are discarded, but logged to a few files. +# arpback: ARP is simulated. Disabled by default. +# vde: Virtual Distributed Ethernet +# vnet: ARP, ICMP-echo(ping), DHCP and read/write TFTP are simulated. +# The virtual host uses 192.168.10.1. +# DHCP assigns 192.168.10.2 to the guest. +# TFTP uses the ethdev value for the root directory and doesn't +# overwrite files. +# +#======================================================================= +# ne2k: ioaddr=0x240, irq=9, mac=fe:fd:00:00:00:01, ethmod=fbsd, ethdev=en0 #macosx +# ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:00, ethmod=fbsd, ethdev=xl0 +# ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:00, ethmod=linux, ethdev=eth0 +# ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:01, ethmod=win32, ethdev=MYCARD +# ne2k: ioaddr=0x240, irq=9, mac=fe:fd:00:00:00:01, ethmod=tap, ethdev=tap0 +# ne2k: ioaddr=0x240, irq=9, mac=fe:fd:00:00:00:01, ethmod=tuntap, ethdev=/dev/net/tun0, script=./tunconfig +# ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:01, ethmod=null, ethdev=eth0 +# ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:01, ethmod=vde, ethdev="/tmp/vde.ctl" +# ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:01, ethmod=vnet, ethdev="c:/temp" + +#======================================================================= +# KEYBOARD_MAPPING: +# This enables a remap of a physical localized keyboard to a +# virtualized us keyboard, as the PC architecture expects. +# If enabled, the keymap file must be specified. +# +# Examples: +# keyboard_mapping: enabled=1, map=gui/keymaps/x11-pc-de.map +#======================================================================= +keyboard_mapping: enabled=0, map= + +#======================================================================= +# KEYBOARD_TYPE: +# Type of keyboard return by a "identify keyboard" command to the +# keyboard controler. It must be one of "xt", "at" or "mf". +# Defaults to "mf". It should be ok for almost everybody. A known +# exception is french macs, that do have a "at"-like keyboard. +# +# Examples: +# keyboard_type: mf +#======================================================================= +#keyboard_type: mf + +#======================================================================= +# USER_SHORTCUT: +# This defines the keyboard shortcut to be sent when you press the "user" +# button in the headerbar. The shortcut string is a combination of maximum +# 3 key names (listed below) separated with a '-' character. The old-style +# syntax (without the '-') still works for the key combinations supported +# in Bochs 2.2.1. +# Valid key names: +# "alt", "bksl", "bksp", "ctrl", "del", "down", "end", "enter", "esc", +# "f1", ... "f12", "home", "ins", "left", "menu", "minus", "pgdwn", "pgup", +# "plus", "right", "shift", "space", "tab", "up", and "win". +# +# Example: +# user_shortcut: keys=ctrl-alt-del +#======================================================================= +#user_shortcut: keys=ctrl-alt-del + +#======================================================================= +# I440FXSUPPORT: +# This option controls the presence of the i440FX PCI chipset. You can +# also specify the devices connected to PCI slots. Up to 5 slots are +# available now. These devices are currently supported: ne2k, pcivga, +# pcidev and pcipnic. If Bochs is compiled with Cirrus SVGA support +# you'll have the additional choice 'cirrus'. +# +# Example: +# i440fxsupport: enabled=1, slot1=pcivga, slot2=ne2k +#======================================================================= +#i440fxsupport: enabled=1 + +#======================================================================= +# USB1: +# This option controls the presence of the USB root hub which is a part +# of the i440FX PCI chipset. With the portX option you can connect devices +# to the hub (currently supported: 'mouse' and 'keypad'). If you connect +# the mouse to one of the ports and use the mouse option 'type=usb' you'll +# have a 3-button USB mouse. +# +# Example: +# usb1: enabled=1, port1=mouse, port2=keypad +#======================================================================= +#usb1: enabled=1 + +#======================================================================= +# CMOSIMAGE: +# This defines image file that can be loaded into the CMOS RAM at startup. +# The rtc_init parameter controls whether initialize the RTC with values stored +# in the image. By default the time0 argument given to the clock option is used. +# With 'rtc_init=image' the image is the source for the initial time. +# +# Example: +# cmosimage: file=cmos.img, rtc_init=image +#======================================================================= +#cmosimage: file=cmos.img, rtc_init=time0 + +#======================================================================= +# other stuff +#======================================================================= +#magic_break: enabled=1 +#load32bitOSImage: os=nullkernel, path=../kernel.img, iolog=../vga_io.log +#load32bitOSImage: os=linux, path=../linux.img, iolog=../vga_io.log, initrd=../initrd.img +#text_snapshot_check: enable + +#------------------------- +# PCI host device mapping +#------------------------- +#pcidev: vendor=0x1234, device=0x5678 + +#======================================================================= +# GDBSTUB: +# Enable GDB stub. See user documentation for details. +# Default value is enabled=0. +#======================================================================= +#gdbstub: enabled=0, port=1234, text_base=0, data_base=0, bss_base=0 + +#======================================================================= +# IPS: +# The IPS directive is DEPRECATED. Use the parameter IPS of the CPU +# directive instead. +#======================================================================= +#ips: 10000000 + +#======================================================================= +# for Macintosh, use the style of pathnames in the following +# examples. +# +# vgaromimage: :bios:VGABIOS-elpin-2.40 +# romimage: file=:bios:BIOS-bochs-latest, address=0xf0000 +# floppya: 1_44=[fd:], status=inserted +#======================================================================= diff --git a/xv6-public/echo.c b/xv6-public/echo.c new file mode 100644 index 0000000..806dee0 --- /dev/null +++ b/xv6-public/echo.c @@ -0,0 +1,13 @@ +#include "types.h" +#include "stat.h" +#include "user.h" + +int +main(int argc, char *argv[]) +{ + int i; + + for(i = 1; i < argc; i++) + printf(1, "%s%s", argv[i], i+1 < argc ? " " : "\n"); + exit(); +} diff --git a/xv6-public/elf.h b/xv6-public/elf.h new file mode 100644 index 0000000..d16c967 --- /dev/null +++ b/xv6-public/elf.h @@ -0,0 +1,42 @@ +// Format of an ELF executable file + +#define ELF_MAGIC 0x464C457FU // "\x7FELF" in little endian + +// File header +struct elfhdr { + uint magic; // must equal ELF_MAGIC + uchar elf[12]; + ushort type; + ushort machine; + uint version; + uint entry; + uint phoff; + uint shoff; + uint flags; + ushort ehsize; + ushort phentsize; + ushort phnum; + ushort shentsize; + ushort shnum; + ushort shstrndx; +}; + +// Program section header +struct proghdr { + uint type; + uint off; + uint vaddr; + uint paddr; + uint filesz; + uint memsz; + uint flags; + uint align; +}; + +// Values for Proghdr type +#define ELF_PROG_LOAD 1 + +// Flag bits for Proghdr flags +#define ELF_PROG_FLAG_EXEC 1 +#define ELF_PROG_FLAG_WRITE 2 +#define ELF_PROG_FLAG_READ 4 diff --git a/xv6-public/entry.S b/xv6-public/entry.S new file mode 100644 index 0000000..bc79bab --- /dev/null +++ b/xv6-public/entry.S @@ -0,0 +1,68 @@ +# The xv6 kernel starts executing in this file. This file is linked with +# the kernel C code, so it can refer to kernel symbols such as main(). +# The boot block (bootasm.S and bootmain.c) jumps to entry below. + +# Multiboot header, for multiboot boot loaders like GNU Grub. +# http://www.gnu.org/software/grub/manual/multiboot/multiboot.html +# +# Using GRUB 2, you can boot xv6 from a file stored in a +# Linux file system by copying kernel or kernelmemfs to /boot +# and then adding this menu entry: +# +# menuentry "xv6" { +# insmod ext2 +# set root='(hd0,msdos1)' +# set kernel='/boot/kernel' +# echo "Loading ${kernel}..." +# multiboot ${kernel} ${kernel} +# boot +# } + +#include "asm.h" +#include "memlayout.h" +#include "mmu.h" +#include "param.h" + +# Multiboot header. Data to direct multiboot loader. +.p2align 2 +.text +.globl multiboot_header +multiboot_header: + #define magic 0x1badb002 + #define flags 0 + .long magic + .long flags + .long (-magic-flags) + +# By convention, the _start symbol specifies the ELF entry point. +# Since we haven't set up virtual memory yet, our entry point is +# the physical address of 'entry'. +.globl _start +_start = V2P_WO(entry) + +# Entering xv6 on boot processor, with paging off. +.globl entry +entry: + # Turn on page size extension for 4Mbyte pages + movl %cr4, %eax + orl $(CR4_PSE), %eax + movl %eax, %cr4 + # Set page directory + movl $(V2P_WO(entrypgdir)), %eax + movl %eax, %cr3 + # Turn on paging. + movl %cr0, %eax + orl $(CR0_PG|CR0_WP), %eax + movl %eax, %cr0 + + # Set up the stack pointer. + movl $(stack + KSTACKSIZE), %esp + + # Jump to main(), and switch to executing at + # high addresses. The indirect call is needed because + # the assembler produces a PC-relative instruction + # for a direct jump. + mov $main, %eax + jmp *%eax + +.comm stack, KSTACKSIZE diff --git a/xv6-public/entryother.S b/xv6-public/entryother.S new file mode 100644 index 0000000..a3b6dc2 --- /dev/null +++ b/xv6-public/entryother.S @@ -0,0 +1,93 @@ +#include "asm.h" +#include "memlayout.h" +#include "mmu.h" + +# Each non-boot CPU ("AP") is started up in response to a STARTUP +# IPI from the boot CPU. Section B.4.2 of the Multi-Processor +# Specification says that the AP will start in real mode with CS:IP +# set to XY00:0000, where XY is an 8-bit value sent with the +# STARTUP. Thus this code must start at a 4096-byte boundary. +# +# Because this code sets DS to zero, it must sit +# at an address in the low 2^16 bytes. +# +# Startothers (in main.c) sends the STARTUPs one at a time. +# It copies this code (start) at 0x7000. It puts the address of +# a newly allocated per-core stack in start-4,the address of the +# place to jump to (mpenter) in start-8, and the physical address +# of entrypgdir in start-12. +# +# This code combines elements of bootasm.S and entry.S. + +.code16 +.globl start +start: + cli + + # Zero data segment registers DS, ES, and SS. + xorw %ax,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%ss + + # Switch from real to protected mode. Use a bootstrap GDT that makes + # virtual addresses map directly to physical addresses so that the + # effective memory map doesn't change during the transition. + lgdt gdtdesc + movl %cr0, %eax + orl $CR0_PE, %eax + movl %eax, %cr0 + + # Complete the transition to 32-bit protected mode by using a long jmp + # to reload %cs and %eip. The segment descriptors are set up with no + # translation, so that the mapping is still the identity mapping. + ljmpl $(SEG_KCODE<<3), $(start32) + +//PAGEBREAK! +.code32 # Tell assembler to generate 32-bit code now. +start32: + # Set up the protected-mode data segment registers + movw $(SEG_KDATA<<3), %ax # Our data segment selector + movw %ax, %ds # -> DS: Data Segment + movw %ax, %es # -> ES: Extra Segment + movw %ax, %ss # -> SS: Stack Segment + movw $0, %ax # Zero segments not ready for use + movw %ax, %fs # -> FS + movw %ax, %gs # -> GS + + # Turn on page size extension for 4Mbyte pages + movl %cr4, %eax + orl $(CR4_PSE), %eax + movl %eax, %cr4 + # Use entrypgdir as our initial page table + movl (start-12), %eax + movl %eax, %cr3 + # Turn on paging. + movl %cr0, %eax + orl $(CR0_PE|CR0_PG|CR0_WP), %eax + movl %eax, %cr0 + + # Switch to the stack allocated by startothers() + movl (start-4), %esp + # Call mpenter() + call *(start-8) + + movw $0x8a00, %ax + movw %ax, %dx + outw %ax, %dx + movw $0x8ae0, %ax + outw %ax, %dx +spin: + jmp spin + +.p2align 2 +gdt: + SEG_NULLASM + SEG_ASM(STA_X|STA_R, 0, 0xffffffff) + SEG_ASM(STA_W, 0, 0xffffffff) + + +gdtdesc: + .word (gdtdesc - gdt - 1) + .long gdt + diff --git a/xv6-public/exec.c b/xv6-public/exec.c new file mode 100644 index 0000000..b40134f --- /dev/null +++ b/xv6-public/exec.c @@ -0,0 +1,114 @@ +#include "types.h" +#include "param.h" +#include "memlayout.h" +#include "mmu.h" +#include "proc.h" +#include "defs.h" +#include "x86.h" +#include "elf.h" + +int +exec(char *path, char **argv) +{ + char *s, *last; + int i, off; + uint argc, sz, sp, ustack[3+MAXARG+1]; + struct elfhdr elf; + struct inode *ip; + struct proghdr ph; + pde_t *pgdir, *oldpgdir; + struct proc *curproc = myproc(); + + begin_op(); + + if((ip = namei(path)) == 0){ + end_op(); + cprintf("exec: fail\n"); + return -1; + } + ilock(ip); + pgdir = 0; + + // Check ELF header + if(readi(ip, (char*)&elf, 0, sizeof(elf)) != sizeof(elf)) + goto bad; + if(elf.magic != ELF_MAGIC) + goto bad; + + if((pgdir = setupkvm()) == 0) + goto bad; + + // Load program into memory. + sz = 0; + for(i=0, off=elf.phoff; i= MAXARG) + goto bad; + sp = (sp - (strlen(argv[argc]) + 1)) & ~3; + if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) + goto bad; + ustack[3+argc] = sp; + } + ustack[3+argc] = 0; + + ustack[0] = 0xffffffff; // fake return PC + ustack[1] = argc; + ustack[2] = sp - (argc+1)*4; // argv pointer + + sp -= (3+argc+1) * 4; + if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) + goto bad; + + // Save program name for debugging. + for(last=s=path; *s; s++) + if(*s == '/') + last = s+1; + safestrcpy(curproc->name, last, sizeof(curproc->name)); + + // Commit to the user image. + oldpgdir = curproc->pgdir; + curproc->pgdir = pgdir; + curproc->sz = sz; + curproc->tf->eip = elf.entry; // main + curproc->tf->esp = sp; + switchuvm(curproc); + freevm(oldpgdir); + return 0; + + bad: + if(pgdir) + freevm(pgdir); + if(ip){ + iunlockput(ip); + end_op(); + } + return -1; +} diff --git a/xv6-public/fcntl.h b/xv6-public/fcntl.h new file mode 100644 index 0000000..d565483 --- /dev/null +++ b/xv6-public/fcntl.h @@ -0,0 +1,4 @@ +#define O_RDONLY 0x000 +#define O_WRONLY 0x001 +#define O_RDWR 0x002 +#define O_CREATE 0x200 diff --git a/xv6-public/file.c b/xv6-public/file.c new file mode 100644 index 0000000..24b32c2 --- /dev/null +++ b/xv6-public/file.c @@ -0,0 +1,157 @@ +// +// File descriptors +// + +#include "types.h" +#include "defs.h" +#include "param.h" +#include "fs.h" +#include "spinlock.h" +#include "sleeplock.h" +#include "file.h" + +struct devsw devsw[NDEV]; +struct { + struct spinlock lock; + struct file file[NFILE]; +} ftable; + +void +fileinit(void) +{ + initlock(&ftable.lock, "ftable"); +} + +// Allocate a file structure. +struct file* +filealloc(void) +{ + struct file *f; + + acquire(&ftable.lock); + for(f = ftable.file; f < ftable.file + NFILE; f++){ + if(f->ref == 0){ + f->ref = 1; + release(&ftable.lock); + return f; + } + } + release(&ftable.lock); + return 0; +} + +// Increment ref count for file f. +struct file* +filedup(struct file *f) +{ + acquire(&ftable.lock); + if(f->ref < 1) + panic("filedup"); + f->ref++; + release(&ftable.lock); + return f; +} + +// Close file f. (Decrement ref count, close when reaches 0.) +void +fileclose(struct file *f) +{ + struct file ff; + + acquire(&ftable.lock); + if(f->ref < 1) + panic("fileclose"); + if(--f->ref > 0){ + release(&ftable.lock); + return; + } + ff = *f; + f->ref = 0; + f->type = FD_NONE; + release(&ftable.lock); + + if(ff.type == FD_PIPE) + pipeclose(ff.pipe, ff.writable); + else if(ff.type == FD_INODE){ + begin_op(); + iput(ff.ip); + end_op(); + } +} + +// Get metadata about file f. +int +filestat(struct file *f, struct stat *st) +{ + if(f->type == FD_INODE){ + ilock(f->ip); + stati(f->ip, st); + iunlock(f->ip); + return 0; + } + return -1; +} + +// Read from file f. +int +fileread(struct file *f, char *addr, int n) +{ + int r; + + if(f->readable == 0) + return -1; + if(f->type == FD_PIPE) + return piperead(f->pipe, addr, n); + if(f->type == FD_INODE){ + ilock(f->ip); + if((r = readi(f->ip, addr, f->off, n)) > 0) + f->off += r; + iunlock(f->ip); + return r; + } + panic("fileread"); +} + +//PAGEBREAK! +// Write to file f. +int +filewrite(struct file *f, char *addr, int n) +{ + int r; + + if(f->writable == 0) + return -1; + if(f->type == FD_PIPE) + return pipewrite(f->pipe, addr, n); + if(f->type == FD_INODE){ + // write a few blocks at a time to avoid exceeding + // the maximum log transaction size, including + // i-node, indirect block, allocation blocks, + // and 2 blocks of slop for non-aligned writes. + // this really belongs lower down, since writei() + // might be writing a device like the console. + int max = ((MAXOPBLOCKS-1-1-2) / 2) * 512; + int i = 0; + while(i < n){ + int n1 = n - i; + if(n1 > max) + n1 = max; + + begin_op(); + ilock(f->ip); + if ((r = writei(f->ip, addr + i, f->off, n1)) > 0) + f->off += r; + iunlock(f->ip); + end_op(); + + if(r < 0) + break; + if(r != n1) + panic("short filewrite"); + i += r; + } + return i == n ? n : -1; + } + panic("filewrite"); +} + diff --git a/xv6-public/file.h b/xv6-public/file.h new file mode 100644 index 0000000..0990c82 --- /dev/null +++ b/xv6-public/file.h @@ -0,0 +1,37 @@ +struct file { + enum { FD_NONE, FD_PIPE, FD_INODE } type; + int ref; // reference count + char readable; + char writable; + struct pipe *pipe; + struct inode *ip; + uint off; +}; + + +// in-memory copy of an inode +struct inode { + uint dev; // Device number + uint inum; // Inode number + int ref; // Reference count + struct sleeplock lock; // protects everything below here + int valid; // inode has been read from disk? + + short type; // copy of disk inode + short major; + short minor; + short nlink; + uint size; + uint addrs[NDIRECT+1]; +}; + +// table mapping major device number to +// device functions +struct devsw { + int (*read)(struct inode*, char*, int); + int (*write)(struct inode*, char*, int); +}; + +extern struct devsw devsw[]; + +#define CONSOLE 1 diff --git a/xv6-public/forktest.c b/xv6-public/forktest.c new file mode 100644 index 0000000..8bc984d --- /dev/null +++ b/xv6-public/forktest.c @@ -0,0 +1,56 @@ +// Test that fork fails gracefully. +// Tiny executable so that the limit can be filling the proc table. + +#include "types.h" +#include "stat.h" +#include "user.h" + +#define N 1000 + +void +printf(int fd, const char *s, ...) +{ + write(fd, s, strlen(s)); +} + +void +forktest(void) +{ + int n, pid; + + printf(1, "fork test\n"); + + for(n=0; n 0; n--){ + if(wait() < 0){ + printf(1, "wait stopped early\n"); + exit(); + } + } + + if(wait() != -1){ + printf(1, "wait got too many\n"); + exit(); + } + + printf(1, "fork test OK\n"); +} + +int +main(void) +{ + forktest(); + exit(); +} diff --git a/xv6-public/fs.c b/xv6-public/fs.c new file mode 100644 index 0000000..feb59fe --- /dev/null +++ b/xv6-public/fs.c @@ -0,0 +1,671 @@ +// File system implementation. Five layers: +// + Blocks: allocator for raw disk blocks. +// + Log: crash recovery for multi-step updates. +// + Files: inode allocator, reading, writing, metadata. +// + Directories: inode with special contents (list of other inodes!) +// + Names: paths like /usr/rtm/xv6/fs.c for convenient naming. +// +// This file contains the low-level file system manipulation +// routines. The (higher-level) system call implementations +// are in sysfile.c. + +#include "types.h" +#include "defs.h" +#include "param.h" +#include "stat.h" +#include "mmu.h" +#include "proc.h" +#include "spinlock.h" +#include "sleeplock.h" +#include "fs.h" +#include "buf.h" +#include "file.h" + +#define min(a, b) ((a) < (b) ? (a) : (b)) +static void itrunc(struct inode*); +// there should be one superblock per disk device, but we run with +// only one device +struct superblock sb; + +// Read the super block. +void +readsb(int dev, struct superblock *sb) +{ + struct buf *bp; + + bp = bread(dev, 1); + memmove(sb, bp->data, sizeof(*sb)); + brelse(bp); +} + +// Zero a block. +static void +bzero(int dev, int bno) +{ + struct buf *bp; + + bp = bread(dev, bno); + memset(bp->data, 0, BSIZE); + log_write(bp); + brelse(bp); +} + +// Blocks. + +// Allocate a zeroed disk block. +static uint +balloc(uint dev) +{ + int b, bi, m; + struct buf *bp; + + bp = 0; + for(b = 0; b < sb.size; b += BPB){ + bp = bread(dev, BBLOCK(b, sb)); + for(bi = 0; bi < BPB && b + bi < sb.size; bi++){ + m = 1 << (bi % 8); + if((bp->data[bi/8] & m) == 0){ // Is block free? + bp->data[bi/8] |= m; // Mark block in use. + log_write(bp); + brelse(bp); + bzero(dev, b + bi); + return b + bi; + } + } + brelse(bp); + } + panic("balloc: out of blocks"); +} + +// Free a disk block. +static void +bfree(int dev, uint b) +{ + struct buf *bp; + int bi, m; + + readsb(dev, &sb); + bp = bread(dev, BBLOCK(b, sb)); + bi = b % BPB; + m = 1 << (bi % 8); + if((bp->data[bi/8] & m) == 0) + panic("freeing free block"); + bp->data[bi/8] &= ~m; + log_write(bp); + brelse(bp); +} + +// Inodes. +// +// An inode describes a single unnamed file. +// The inode disk structure holds metadata: the file's type, +// its size, the number of links referring to it, and the +// list of blocks holding the file's content. +// +// The inodes are laid out sequentially on disk at +// sb.startinode. Each inode has a number, indicating its +// position on the disk. +// +// The kernel keeps a cache of in-use inodes in memory +// to provide a place for synchronizing access +// to inodes used by multiple processes. The cached +// inodes include book-keeping information that is +// not stored on disk: ip->ref and ip->valid. +// +// An inode and its in-memory representation go through a +// sequence of states before they can be used by the +// rest of the file system code. +// +// * Allocation: an inode is allocated if its type (on disk) +// is non-zero. ialloc() allocates, and iput() frees if +// the reference and link counts have fallen to zero. +// +// * Referencing in cache: an entry in the inode cache +// is free if ip->ref is zero. Otherwise ip->ref tracks +// the number of in-memory pointers to the entry (open +// files and current directories). iget() finds or +// creates a cache entry and increments its ref; iput() +// decrements ref. +// +// * Valid: the information (type, size, &c) in an inode +// cache entry is only correct when ip->valid is 1. +// ilock() reads the inode from +// the disk and sets ip->valid, while iput() clears +// ip->valid if ip->ref has fallen to zero. +// +// * Locked: file system code may only examine and modify +// the information in an inode and its content if it +// has first locked the inode. +// +// Thus a typical sequence is: +// ip = iget(dev, inum) +// ilock(ip) +// ... examine and modify ip->xxx ... +// iunlock(ip) +// iput(ip) +// +// ilock() is separate from iget() so that system calls can +// get a long-term reference to an inode (as for an open file) +// and only lock it for short periods (e.g., in read()). +// The separation also helps avoid deadlock and races during +// pathname lookup. iget() increments ip->ref so that the inode +// stays cached and pointers to it remain valid. +// +// Many internal file system functions expect the caller to +// have locked the inodes involved; this lets callers create +// multi-step atomic operations. +// +// The icache.lock spin-lock protects the allocation of icache +// entries. Since ip->ref indicates whether an entry is free, +// and ip->dev and ip->inum indicate which i-node an entry +// holds, one must hold icache.lock while using any of those fields. +// +// An ip->lock sleep-lock protects all ip-> fields other than ref, +// dev, and inum. One must hold ip->lock in order to +// read or write that inode's ip->valid, ip->size, ip->type, &c. + +struct { + struct spinlock lock; + struct inode inode[NINODE]; +} icache; + +void +iinit(int dev) +{ + int i = 0; + + initlock(&icache.lock, "icache"); + for(i = 0; i < NINODE; i++) { + initsleeplock(&icache.inode[i].lock, "inode"); + } + + readsb(dev, &sb); + cprintf("sb: size %d nblocks %d ninodes %d nlog %d logstart %d\ + inodestart %d bmap start %d\n", sb.size, sb.nblocks, + sb.ninodes, sb.nlog, sb.logstart, sb.inodestart, + sb.bmapstart); +} + +static struct inode* iget(uint dev, uint inum); + +//PAGEBREAK! +// Allocate an inode on device dev. +// Mark it as allocated by giving it type type. +// Returns an unlocked but allocated and referenced inode. +struct inode* +ialloc(uint dev, short type) +{ + int inum; + struct buf *bp; + struct dinode *dip; + + for(inum = 1; inum < sb.ninodes; inum++){ + bp = bread(dev, IBLOCK(inum, sb)); + dip = (struct dinode*)bp->data + inum%IPB; + if(dip->type == 0){ // a free inode + memset(dip, 0, sizeof(*dip)); + dip->type = type; + log_write(bp); // mark it allocated on the disk + brelse(bp); + return iget(dev, inum); + } + brelse(bp); + } + panic("ialloc: no inodes"); +} + +// Copy a modified in-memory inode to disk. +// Must be called after every change to an ip->xxx field +// that lives on disk, since i-node cache is write-through. +// Caller must hold ip->lock. +void +iupdate(struct inode *ip) +{ + struct buf *bp; + struct dinode *dip; + + bp = bread(ip->dev, IBLOCK(ip->inum, sb)); + dip = (struct dinode*)bp->data + ip->inum%IPB; + dip->type = ip->type; + dip->major = ip->major; + dip->minor = ip->minor; + dip->nlink = ip->nlink; + dip->size = ip->size; + memmove(dip->addrs, ip->addrs, sizeof(ip->addrs)); + log_write(bp); + brelse(bp); +} + +// Find the inode with number inum on device dev +// and return the in-memory copy. Does not lock +// the inode and does not read it from disk. +static struct inode* +iget(uint dev, uint inum) +{ + struct inode *ip, *empty; + + acquire(&icache.lock); + + // Is the inode already cached? + empty = 0; + for(ip = &icache.inode[0]; ip < &icache.inode[NINODE]; ip++){ + if(ip->ref > 0 && ip->dev == dev && ip->inum == inum){ + ip->ref++; + release(&icache.lock); + return ip; + } + if(empty == 0 && ip->ref == 0) // Remember empty slot. + empty = ip; + } + + // Recycle an inode cache entry. + if(empty == 0) + panic("iget: no inodes"); + + ip = empty; + ip->dev = dev; + ip->inum = inum; + ip->ref = 1; + ip->valid = 0; + release(&icache.lock); + + return ip; +} + +// Increment reference count for ip. +// Returns ip to enable ip = idup(ip1) idiom. +struct inode* +idup(struct inode *ip) +{ + acquire(&icache.lock); + ip->ref++; + release(&icache.lock); + return ip; +} + +// Lock the given inode. +// Reads the inode from disk if necessary. +void +ilock(struct inode *ip) +{ + struct buf *bp; + struct dinode *dip; + + if(ip == 0 || ip->ref < 1) + panic("ilock"); + + acquiresleep(&ip->lock); + + if(ip->valid == 0){ + bp = bread(ip->dev, IBLOCK(ip->inum, sb)); + dip = (struct dinode*)bp->data + ip->inum%IPB; + ip->type = dip->type; + ip->major = dip->major; + ip->minor = dip->minor; + ip->nlink = dip->nlink; + ip->size = dip->size; + memmove(ip->addrs, dip->addrs, sizeof(ip->addrs)); + brelse(bp); + ip->valid = 1; + if(ip->type == 0) + panic("ilock: no type"); + } +} + +// Unlock the given inode. +void +iunlock(struct inode *ip) +{ + if(ip == 0 || !holdingsleep(&ip->lock) || ip->ref < 1) + panic("iunlock"); + + releasesleep(&ip->lock); +} + +// Drop a reference to an in-memory inode. +// If that was the last reference, the inode cache entry can +// be recycled. +// If that was the last reference and the inode has no links +// to it, free the inode (and its content) on disk. +// All calls to iput() must be inside a transaction in +// case it has to free the inode. +void +iput(struct inode *ip) +{ + acquiresleep(&ip->lock); + if(ip->valid && ip->nlink == 0){ + acquire(&icache.lock); + int r = ip->ref; + release(&icache.lock); + if(r == 1){ + // inode has no links and no other references: truncate and free. + itrunc(ip); + ip->type = 0; + iupdate(ip); + ip->valid = 0; + } + } + releasesleep(&ip->lock); + + acquire(&icache.lock); + ip->ref--; + release(&icache.lock); +} + +// Common idiom: unlock, then put. +void +iunlockput(struct inode *ip) +{ + iunlock(ip); + iput(ip); +} + +//PAGEBREAK! +// Inode content +// +// The content (data) associated with each inode is stored +// in blocks on the disk. The first NDIRECT block numbers +// are listed in ip->addrs[]. The next NINDIRECT blocks are +// listed in block ip->addrs[NDIRECT]. + +// Return the disk block address of the nth block in inode ip. +// If there is no such block, bmap allocates one. +static uint +bmap(struct inode *ip, uint bn) +{ + uint addr, *a; + struct buf *bp; + + if(bn < NDIRECT){ + if((addr = ip->addrs[bn]) == 0) + ip->addrs[bn] = addr = balloc(ip->dev); + return addr; + } + bn -= NDIRECT; + + if(bn < NINDIRECT){ + // Load indirect block, allocating if necessary. + if((addr = ip->addrs[NDIRECT]) == 0) + ip->addrs[NDIRECT] = addr = balloc(ip->dev); + bp = bread(ip->dev, addr); + a = (uint*)bp->data; + if((addr = a[bn]) == 0){ + a[bn] = addr = balloc(ip->dev); + log_write(bp); + } + brelse(bp); + return addr; + } + + panic("bmap: out of range"); +} + +// Truncate inode (discard contents). +// Only called when the inode has no links +// to it (no directory entries referring to it) +// and has no in-memory reference to it (is +// not an open file or current directory). +static void +itrunc(struct inode *ip) +{ + int i, j; + struct buf *bp; + uint *a; + + for(i = 0; i < NDIRECT; i++){ + if(ip->addrs[i]){ + bfree(ip->dev, ip->addrs[i]); + ip->addrs[i] = 0; + } + } + + if(ip->addrs[NDIRECT]){ + bp = bread(ip->dev, ip->addrs[NDIRECT]); + a = (uint*)bp->data; + for(j = 0; j < NINDIRECT; j++){ + if(a[j]) + bfree(ip->dev, a[j]); + } + brelse(bp); + bfree(ip->dev, ip->addrs[NDIRECT]); + ip->addrs[NDIRECT] = 0; + } + + ip->size = 0; + iupdate(ip); +} + +// Copy stat information from inode. +// Caller must hold ip->lock. +void +stati(struct inode *ip, struct stat *st) +{ + st->dev = ip->dev; + st->ino = ip->inum; + st->type = ip->type; + st->nlink = ip->nlink; + st->size = ip->size; +} + +//PAGEBREAK! +// Read data from inode. +// Caller must hold ip->lock. +int +readi(struct inode *ip, char *dst, uint off, uint n) +{ + uint tot, m; + struct buf *bp; + + if(ip->type == T_DEV){ + if(ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].read) + return -1; + return devsw[ip->major].read(ip, dst, n); + } + + if(off > ip->size || off + n < off) + return -1; + if(off + n > ip->size) + n = ip->size - off; + + for(tot=0; totdev, bmap(ip, off/BSIZE)); + m = min(n - tot, BSIZE - off%BSIZE); + memmove(dst, bp->data + off%BSIZE, m); + brelse(bp); + } + return n; +} + +// PAGEBREAK! +// Write data to inode. +// Caller must hold ip->lock. +int +writei(struct inode *ip, char *src, uint off, uint n) +{ + uint tot, m; + struct buf *bp; + + if(ip->type == T_DEV){ + if(ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].write) + return -1; + return devsw[ip->major].write(ip, src, n); + } + + if(off > ip->size || off + n < off) + return -1; + if(off + n > MAXFILE*BSIZE) + return -1; + + for(tot=0; totdev, bmap(ip, off/BSIZE)); + m = min(n - tot, BSIZE - off%BSIZE); + memmove(bp->data + off%BSIZE, src, m); + log_write(bp); + brelse(bp); + } + + if(n > 0 && off > ip->size){ + ip->size = off; + iupdate(ip); + } + return n; +} + +//PAGEBREAK! +// Directories + +int +namecmp(const char *s, const char *t) +{ + return strncmp(s, t, DIRSIZ); +} + +// Look for a directory entry in a directory. +// If found, set *poff to byte offset of entry. +struct inode* +dirlookup(struct inode *dp, char *name, uint *poff) +{ + uint off, inum; + struct dirent de; + + if(dp->type != T_DIR) + panic("dirlookup not DIR"); + + for(off = 0; off < dp->size; off += sizeof(de)){ + if(readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) + panic("dirlookup read"); + if(de.inum == 0) + continue; + if(namecmp(name, de.name) == 0){ + // entry matches path element + if(poff) + *poff = off; + inum = de.inum; + return iget(dp->dev, inum); + } + } + + return 0; +} + +// Write a new directory entry (name, inum) into the directory dp. +int +dirlink(struct inode *dp, char *name, uint inum) +{ + int off; + struct dirent de; + struct inode *ip; + + // Check that name is not present. + if((ip = dirlookup(dp, name, 0)) != 0){ + iput(ip); + return -1; + } + + // Look for an empty dirent. + for(off = 0; off < dp->size; off += sizeof(de)){ + if(readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) + panic("dirlink read"); + if(de.inum == 0) + break; + } + + strncpy(de.name, name, DIRSIZ); + de.inum = inum; + if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) + panic("dirlink"); + + return 0; +} + +//PAGEBREAK! +// Paths + +// Copy the next path element from path into name. +// Return a pointer to the element following the copied one. +// The returned path has no leading slashes, +// so the caller can check *path=='\0' to see if the name is the last one. +// If no name to remove, return 0. +// +// Examples: +// skipelem("a/bb/c", name) = "bb/c", setting name = "a" +// skipelem("///a//bb", name) = "bb", setting name = "a" +// skipelem("a", name) = "", setting name = "a" +// skipelem("", name) = skipelem("////", name) = 0 +// +static char* +skipelem(char *path, char *name) +{ + char *s; + int len; + + while(*path == '/') + path++; + if(*path == 0) + return 0; + s = path; + while(*path != '/' && *path != 0) + path++; + len = path - s; + if(len >= DIRSIZ) + memmove(name, s, DIRSIZ); + else { + memmove(name, s, len); + name[len] = 0; + } + while(*path == '/') + path++; + return path; +} + +// Look up and return the inode for a path name. +// If parent != 0, return the inode for the parent and copy the final +// path element into name, which must have room for DIRSIZ bytes. +// Must be called inside a transaction since it calls iput(). +static struct inode* +namex(char *path, int nameiparent, char *name) +{ + struct inode *ip, *next; + + if(*path == '/') + ip = iget(ROOTDEV, ROOTINO); + else + ip = idup(myproc()->cwd); + + while((path = skipelem(path, name)) != 0){ + ilock(ip); + if(ip->type != T_DIR){ + iunlockput(ip); + return 0; + } + if(nameiparent && *path == '\0'){ + // Stop one level early. + iunlock(ip); + return ip; + } + if((next = dirlookup(ip, name, 0)) == 0){ + iunlockput(ip); + return 0; + } + iunlockput(ip); + ip = next; + } + if(nameiparent){ + iput(ip); + return 0; + } + return ip; +} + +struct inode* +namei(char *path) +{ + char name[DIRSIZ]; + return namex(path, 0, name); +} + +struct inode* +nameiparent(char *path, char *name) +{ + return namex(path, 1, name); +} diff --git a/xv6-public/fs.h b/xv6-public/fs.h new file mode 100644 index 0000000..3214f1d --- /dev/null +++ b/xv6-public/fs.h @@ -0,0 +1,57 @@ +// On-disk file system format. +// Both the kernel and user programs use this header file. + + +#define ROOTINO 1 // root i-number +#define BSIZE 512 // block size + +// Disk layout: +// [ boot block | super block | log | inode blocks | +// free bit map | data blocks] +// +// mkfs computes the super block and builds an initial file system. The +// super block describes the disk layout: +struct superblock { + uint size; // Size of file system image (blocks) + uint nblocks; // Number of data blocks + uint ninodes; // Number of inodes. + uint nlog; // Number of log blocks + uint logstart; // Block number of first log block + uint inodestart; // Block number of first inode block + uint bmapstart; // Block number of first free map block +}; + +#define NDIRECT 12 +#define NINDIRECT (BSIZE / sizeof(uint)) +#define MAXFILE (NDIRECT + NINDIRECT) + +// On-disk inode structure +struct dinode { + short type; // File type + short major; // Major device number (T_DEV only) + short minor; // Minor device number (T_DEV only) + short nlink; // Number of links to inode in file system + uint size; // Size of file (bytes) + uint addrs[NDIRECT+1]; // Data block addresses +}; + +// Inodes per block. +#define IPB (BSIZE / sizeof(struct dinode)) + +// Block containing inode i +#define IBLOCK(i, sb) ((i) / IPB + sb.inodestart) + +// Bitmap bits per block +#define BPB (BSIZE*8) + +// Block of free map containing bit for block b +#define BBLOCK(b, sb) (b/BPB + sb.bmapstart) + +// Directory is a file containing a sequence of dirent structures. +#define DIRSIZ 14 + +struct dirent { + ushort inum; + char name[DIRSIZ]; +}; + diff --git a/xv6-public/gdbutil b/xv6-public/gdbutil new file mode 100644 index 0000000..e0c362f --- /dev/null +++ b/xv6-public/gdbutil @@ -0,0 +1,291 @@ +# -*- gdb-script -*- + +# Utility functions to pretty-print x86 segment/interrupt descriptors. +# To load this file, run "source gdbutil" in gdb. +# printdesc and printdescs are the main entry points. + +# IA32 2007, Volume 3A, Table 3-2 +set $STS_T16A = 0x1 +set $STS_LDT = 0x2 +set $STS_T16B = 0x3 +set $STS_CG16 = 0x4 +set $STS_TG = 0x5 +set $STS_IG16 = 0x6 +set $STS_TG16 = 0x7 +set $STS_T32A = 0x9 +set $STS_T32B = 0xB +set $STS_CG32 = 0xC +set $STS_IG32 = 0xE +set $STS_TG32 = 0xF + +define outputsts + while 1 + if $arg0 == $STS_T16A + echo STS_T16A + loop_break + end + if $arg0 == $STS_LDT + echo STS_LDT\ + loop_break + end + if $arg0 == $STS_T16B + echo STS_T16B + loop_break + end + if $arg0 == $STS_CG16 + echo STS_CG16 + loop_break + end + if $arg0 == $STS_TG + echo STS_TG\ \ + loop_break + end + if $arg0 == $STS_IG16 + echo STS_IG16 + loop_break + end + if $arg0 == $STS_TG16 + echo STS_TG16 + loop_break + end + if $arg0 == $STS_T32A + echo STS_T32A + loop_break + end + if $arg0 == $STS_T32B + echo STS_T32B + loop_break + end + if $arg0 == $STS_CG32 + echo STS_CG32 + loop_break + end + if $arg0 == $STS_IG32 + echo STS_IG32 + loop_break + end + if $arg0 == $STS_TG32 + echo STS_TG32 + loop_break + end + echo Reserved + loop_break + end +end + +# IA32 2007, Volume 3A, Table 3-1 +set $STA_X = 0x8 +set $STA_E = 0x4 +set $STA_C = 0x4 +set $STA_W = 0x2 +set $STA_R = 0x2 +set $STA_A = 0x1 + +define outputsta + if $arg0 & $STA_X + # Code segment + echo code + if $arg0 & $STA_C + echo |STA_C + end + if $arg0 & $STA_R + echo |STA_R + end + else + # Data segment + echo data + if $arg0 & $STA_E + echo |STA_E + end + if $arg0 & $STA_W + echo |STA_W + end + end + if $arg0 & $STA_A + echo |STA_A + else + printf " " + end +end + +# xv6-specific +set $SEG_KCODE = 1 +set $SEG_KDATA = 2 +set $SEG_KCPU = 3 +set $SEG_UCODE = 4 +set $SEG_UDATA = 5 +set $SEG_TSS = 6 + +define outputcs + if ($arg0 & 4) == 0 + if $arg0 >> 3 == $SEG_KCODE + printf "SEG_KCODE<<3" + end + if $arg0 >> 3 == $SEG_KDATA + printf "SEG_KDATA<<3" + end + if $arg0 >> 3 == $SEG_KCPU + printf "SEG_KCPU<<3" + end + if $arg0 >> 3 == $SEG_UCODE + printf "SEG_UCODE<<3" + end + if $arg0 >> 3 == $SEG_UDATA + printf "SEG_UDATA<<3" + end + if $arg0 >> 3 == $SEG_TSS + printf "SEG_TSS<<3" + end + if ($arg0 >> 3 < 1) + ($arg0 >> 3 > 6) + printf "GDT[%d]", $arg0 >> 3 + end + else + printf "LDT[%d]", $arg0 >> 3 + end + if ($arg0 & 3) > 0 + printf "|" + outputdpl ($arg0&3) + end +end + +define outputdpl + if $arg0 == 0 + printf "DPL_KERN" + else + if $arg0 == 3 + printf "DPL_USER" + else + printf "DPL%d", $arg0 + end + end +end + +define printdesc + if $argc != 1 + echo Usage: printdesc expr + else + _printdesc ((uint*)&($arg0))[0] ((uint*)&($arg0))[1] + printf "\n" + end +end + +document printdesc +Print an x86 segment or gate descriptor. +printdesc EXPR +EXPR must evaluate to a descriptor value. It can be of any C type. +end + +define _printdesc + _printdesc1 $arg0 $arg1 ($arg1>>15&1) ($arg1>>13&3) ($arg1>>12&1) ($arg1>>8&15) +end + +define _printdesc1 + # 2:P 3:DPL 4:S 5:Type + if $arg2 == 0 + printf "P = 0 (Not present)" + else + printf "type = " + if $arg4 == 0 + # System segment + outputsts $arg5 + printf " (0x%x) ", $arg5 + _printsysdesc $arg0 $arg1 $arg5 + else + # Code/data segment + outputsta $arg5 + printf " " + _printsegdesc $arg0 $arg1 + end + + printf " DPL = " + outputdpl $arg3 + printf " (%d)", $arg3 + end +end + +define _printsysdesc + # 2:Type + # GDB's || is buggy + if ($arg2 == $STS_TG) + (($arg2&7) == $STS_IG16) + (($arg2&7) == $STS_TG16) + # Gate descriptor + _printgate $arg2 ($arg0>>16) ($arg0&0xFFFF) ($arg1>>16) + else + # System segment descriptor + _printsegdesc $arg0 $arg1 + end +end + +define _printgate + # IA32 2007, Voume 3A, Figure 5-2 + # 0:Type 1:CS 2:Offset 15..0 3:Offset 31..16 + printf "CS = " + outputcs $arg1 + printf " (%d)", $arg1 + + if (($arg0&7) == $STS_IG16) + (($arg0&7) == $STS_TG16) + printf " Offset = " + output/a $arg3 << 16 | $arg2 + end +end + +define _printsegdesc + # IA32 20007, Volume 3A, Figure 3-8 and Figure 4-1 + _printsegdesc1 ($arg0>>16) ($arg1&0xFF) ($arg1>>24) ($arg0&0xFFFF) ($arg1>>16&15) ($arg1>>23&1) + if ($arg1>>12&1) == 1 + printf " AVL = %d", $arg1>>20&1 + if ($arg1>>11&1) == 0 + # Data segment + if ($arg1>>22&1) == 0 + printf " B = small (0) " + else + printf " B = big (1) " + end + else + # Code segment + printf " D = " + if ($arg1>>22&1) == 0 + printf "16-bit (0)" + else + printf "32-bit (1)" + end + end + end +end + +define _printsegdesc1 + # 0:Base 0..15 1:Base 16..23 2:Base 24..32 3:Limit 0..15 4:Limit 16..19 5:G + printf "base = 0x%08x", $arg0 | ($arg1<<16) | ($arg2<<24) + printf " limit = 0x" + if $arg5 == 0 + printf "%08x", $arg3 | ($arg4<<16) + else + printf "%08x", (($arg3 | ($arg4<<16)) << 12) | 0xFFF + end +end + +define printdescs + if $argc < 1 || $argc > 2 + echo Usage: printdescs expr [count] + else + if $argc == 1 + _printdescs ($arg0) (sizeof($arg0)/sizeof(($arg0)[0])) + else + _printdescs ($arg0) ($arg1) + end + end +end + +document printdescs +Print an array of x86 segment or gate descriptors. +printdescs EXPR [COUNT] +EXPR must evaluate to an array of descriptors. +end + +define _printdescs + set $i = 0 + while $i < $arg1 + printf "[%d] ", $i + printdesc $arg0[$i] + set $i = $i + 1 + end +end diff --git a/xv6-public/grep.c b/xv6-public/grep.c new file mode 100644 index 0000000..adc4835 --- /dev/null +++ b/xv6-public/grep.c @@ -0,0 +1,107 @@ +// Simple grep. Only supports ^ . * $ operators. + +#include "types.h" +#include "stat.h" +#include "user.h" + +char buf[1024]; +int match(char*, char*); + +void +grep(char *pattern, int fd) +{ + int n, m; + char *p, *q; + + m = 0; + while((n = read(fd, buf+m, sizeof(buf)-m-1)) > 0){ + m += n; + buf[m] = '\0'; + p = buf; + while((q = strchr(p, '\n')) != 0){ + *q = 0; + if(match(pattern, p)){ + *q = '\n'; + write(1, p, q+1 - p); + } + p = q+1; + } + if(p == buf) + m = 0; + if(m > 0){ + m -= p - buf; + memmove(buf, p, m); + } + } +} + +int +main(int argc, char *argv[]) +{ + int fd, i; + char *pattern; + + if(argc <= 1){ + printf(2, "usage: grep pattern [file ...]\n"); + exit(); + } + pattern = argv[1]; + + if(argc <= 2){ + grep(pattern, 0); + exit(); + } + + for(i = 2; i < argc; i++){ + if((fd = open(argv[i], 0)) < 0){ + printf(1, "grep: cannot open %s\n", argv[i]); + exit(); + } + grep(pattern, fd); + close(fd); + } + exit(); +} + +// Regexp matcher from Kernighan & Pike, +// The Practice of Programming, Chapter 9. + +int matchhere(char*, char*); +int matchstar(int, char*, char*); + +int +match(char *re, char *text) +{ + if(re[0] == '^') + return matchhere(re+1, text); + do{ // must look at empty string + if(matchhere(re, text)) + return 1; + }while(*text++ != '\0'); + return 0; +} + +// matchhere: search for re at beginning of text +int matchhere(char *re, char *text) +{ + if(re[0] == '\0') + return 1; + if(re[1] == '*') + return matchstar(re[0], re+2, text); + if(re[0] == '$' && re[1] == '\0') + return *text == '\0'; + if(*text!='\0' && (re[0]=='.' || re[0]==*text)) + return matchhere(re+1, text+1); + return 0; +} + +// matchstar: search for c*re at beginning of text +int matchstar(int c, char *re, char *text) +{ + do{ // a * matches zero or more instances + if(matchhere(re, text)) + return 1; + }while(*text!='\0' && (*text++==c || c=='.')); + return 0; +} + diff --git a/xv6-public/ide.c b/xv6-public/ide.c new file mode 100644 index 0000000..021adb1 --- /dev/null +++ b/xv6-public/ide.c @@ -0,0 +1,169 @@ +// Simple PIO-based (non-DMA) IDE driver code. + +#include "types.h" +#include "defs.h" +#include "param.h" +#include "memlayout.h" +#include "mmu.h" +#include "proc.h" +#include "x86.h" +#include "traps.h" +#include "spinlock.h" +#include "sleeplock.h" +#include "fs.h" +#include "buf.h" + +#define SECTOR_SIZE 512 +#define IDE_BSY 0x80 +#define IDE_DRDY 0x40 +#define IDE_DF 0x20 +#define IDE_ERR 0x01 + +#define IDE_CMD_READ 0x20 +#define IDE_CMD_WRITE 0x30 +#define IDE_CMD_RDMUL 0xc4 +#define IDE_CMD_WRMUL 0xc5 + +// idequeue points to the buf now being read/written to the disk. +// idequeue->qnext points to the next buf to be processed. +// You must hold idelock while manipulating queue. + +static struct spinlock idelock; +static struct buf *idequeue; + +static int havedisk1; +static void idestart(struct buf*); + +// Wait for IDE disk to become ready. +static int +idewait(int checkerr) +{ + int r; + + while(((r = inb(0x1f7)) & (IDE_BSY|IDE_DRDY)) != IDE_DRDY) + ; + if(checkerr && (r & (IDE_DF|IDE_ERR)) != 0) + return -1; + return 0; +} + +void +ideinit(void) +{ + int i; + + initlock(&idelock, "ide"); + ioapicenable(IRQ_IDE, ncpu - 1); + idewait(0); + + // Check if disk 1 is present + outb(0x1f6, 0xe0 | (1<<4)); + for(i=0; i<1000; i++){ + if(inb(0x1f7) != 0){ + havedisk1 = 1; + break; + } + } + + // Switch back to disk 0. + outb(0x1f6, 0xe0 | (0<<4)); +} + +// Start the request for b. Caller must hold idelock. +static void +idestart(struct buf *b) +{ + if(b == 0) + panic("idestart"); + if(b->blockno >= FSSIZE) + panic("incorrect blockno"); + int sector_per_block = BSIZE/SECTOR_SIZE; + int sector = b->blockno * sector_per_block; + int read_cmd = (sector_per_block == 1) ? IDE_CMD_READ : IDE_CMD_RDMUL; + int write_cmd = (sector_per_block == 1) ? IDE_CMD_WRITE : IDE_CMD_WRMUL; + + if (sector_per_block > 7) panic("idestart"); + + idewait(0); + outb(0x3f6, 0); // generate interrupt + outb(0x1f2, sector_per_block); // number of sectors + outb(0x1f3, sector & 0xff); + outb(0x1f4, (sector >> 8) & 0xff); + outb(0x1f5, (sector >> 16) & 0xff); + outb(0x1f6, 0xe0 | ((b->dev&1)<<4) | ((sector>>24)&0x0f)); + if(b->flags & B_DIRTY){ + outb(0x1f7, write_cmd); + outsl(0x1f0, b->data, BSIZE/4); + } else { + outb(0x1f7, read_cmd); + } +} + +// Interrupt handler. +void +ideintr(void) +{ + struct buf *b; + + // First queued buffer is the active request. + acquire(&idelock); + + if((b = idequeue) == 0){ + release(&idelock); + return; + } + idequeue = b->qnext; + + // Read data if needed. + if(!(b->flags & B_DIRTY) && idewait(1) >= 0) + insl(0x1f0, b->data, BSIZE/4); + + // Wake process waiting for this buf. + b->flags |= B_VALID; + b->flags &= ~B_DIRTY; + wakeup(b); + + // Start disk on next buf in queue. + if(idequeue != 0) + idestart(idequeue); + + release(&idelock); +} + +//PAGEBREAK! +// Sync buf with disk. +// If B_DIRTY is set, write buf to disk, clear B_DIRTY, set B_VALID. +// Else if B_VALID is not set, read buf from disk, set B_VALID. +void +iderw(struct buf *b) +{ + struct buf **pp; + + if(!holdingsleep(&b->lock)) + panic("iderw: buf not locked"); + if((b->flags & (B_VALID|B_DIRTY)) == B_VALID) + panic("iderw: nothing to do"); + if(b->dev != 0 && !havedisk1) + panic("iderw: ide disk 1 not present"); + + + acquire(&idelock); //DOC:acquire-lock + // sti(); + // Append b to idequeue. + b->qnext = 0; + for(pp=&idequeue; *pp; pp=&(*pp)->qnext) //DOC:insert-queue + ; + *pp = b; + + // Start disk if necessary. + if(idequeue == b) + idestart(b); + + // Wait for request to finish. + while((b->flags & (B_VALID|B_DIRTY)) != B_VALID){ + sleep(b, &idelock); + } + + // cli(); + release(&idelock); +} diff --git a/xv6-public/init.c b/xv6-public/init.c new file mode 100644 index 0000000..046b551 --- /dev/null +++ b/xv6-public/init.c @@ -0,0 +1,37 @@ +// init: The initial user-level program + +#include "types.h" +#include "stat.h" +#include "user.h" +#include "fcntl.h" + +char *argv[] = { "sh", 0 }; + +int +main(void) +{ + int pid, wpid; + + if(open("console", O_RDWR) < 0){ + mknod("console", 1, 1); + open("console", O_RDWR); + } + dup(0); // stdout + dup(0); // stderr + + for(;;){ + printf(1, "init: starting sh\n"); + pid = fork(); + if(pid < 0){ + printf(1, "init: fork failed\n"); + exit(); + } + if(pid == 0){ + exec("sh", argv); + printf(1, "init: exec sh failed\n"); + exit(); + } + while((wpid=wait()) >= 0 && wpid != pid) + printf(1, "zombie!\n"); + } +} diff --git a/xv6-public/initcode.S b/xv6-public/initcode.S new file mode 100644 index 0000000..80ac5d8 --- /dev/null +++ b/xv6-public/initcode.S @@ -0,0 +1,32 @@ +# Initial process execs /init. +# This code runs in user space. + +#include "syscall.h" +#include "traps.h" + + +# exec(init, argv) +.globl start +start: + pushl $argv + pushl $init + pushl $0 // where caller pc would be + movl $SYS_exec, %eax + int $T_SYSCALL + +# for(;;) exit(); +exit: + movl $SYS_exit, %eax + int $T_SYSCALL + jmp exit + +# char init[] = "/init\0"; +init: + .string "/init\0" + +# char *argv[] = { init, 0 }; +.p2align 2 +argv: + .long init + .long 0 + diff --git a/xv6-public/ioapic.c b/xv6-public/ioapic.c new file mode 100644 index 0000000..cb0f015 --- /dev/null +++ b/xv6-public/ioapic.c @@ -0,0 +1,75 @@ +// The I/O APIC manages hardware interrupts for an SMP system. +// http://www.intel.com/design/chipsets/datashts/29056601.pdf +// See also picirq.c. + +#include "types.h" +#include "defs.h" +#include "traps.h" + +#define IOAPIC 0xFEC00000 // Default physical address of IO APIC + +#define REG_ID 0x00 // Register index: ID +#define REG_VER 0x01 // Register index: version +#define REG_TABLE 0x10 // Redirection table base + +// The redirection table starts at REG_TABLE and uses +// two registers to configure each interrupt. +// The first (low) register in a pair contains configuration bits. +// The second (high) register contains a bitmask telling which +// CPUs can serve that interrupt. +#define INT_DISABLED 0x00010000 // Interrupt disabled +#define INT_LEVEL 0x00008000 // Level-triggered (vs edge-) +#define INT_ACTIVELOW 0x00002000 // Active low (vs high) +#define INT_LOGICAL 0x00000800 // Destination is CPU id (vs APIC ID) + +volatile struct ioapic *ioapic; + +// IO APIC MMIO structure: write reg, then read or write data. +struct ioapic { + uint reg; + uint pad[3]; + uint data; +}; + +static uint +ioapicread(int reg) +{ + ioapic->reg = reg; + return ioapic->data; +} + +static void +ioapicwrite(int reg, uint data) +{ + ioapic->reg = reg; + ioapic->data = data; +} + +void +ioapicinit(void) +{ + int i, id, maxintr; + + ioapic = (volatile struct ioapic*)IOAPIC; + maxintr = (ioapicread(REG_VER) >> 16) & 0xFF; + id = ioapicread(REG_ID) >> 24; + if(id != ioapicid) + cprintf("ioapicinit: id isn't equal to ioapicid; not a MP\n"); + + // Mark all interrupts edge-triggered, active high, disabled, + // and not routed to any CPUs. + for(i = 0; i <= maxintr; i++){ + ioapicwrite(REG_TABLE+2*i, INT_DISABLED | (T_IRQ0 + i)); + ioapicwrite(REG_TABLE+2*i+1, 0); + } +} + +void +ioapicenable(int irq, int cpunum) +{ + // Mark interrupt edge-triggered, active high, + // enabled, and routed to the given cpunum, + // which happens to be that cpu's APIC ID. + ioapicwrite(REG_TABLE+2*irq, T_IRQ0 + irq); + ioapicwrite(REG_TABLE+2*irq+1, cpunum << 24); +} diff --git a/xv6-public/kalloc.c b/xv6-public/kalloc.c new file mode 100644 index 0000000..14cd4f4 --- /dev/null +++ b/xv6-public/kalloc.c @@ -0,0 +1,96 @@ +// Physical memory allocator, intended to allocate +// memory for user processes, kernel stacks, page table pages, +// and pipe buffers. Allocates 4096-byte pages. + +#include "types.h" +#include "defs.h" +#include "param.h" +#include "memlayout.h" +#include "mmu.h" +#include "spinlock.h" + +void freerange(void *vstart, void *vend); +extern char end[]; // first address after kernel loaded from ELF file + // defined by the kernel linker script in kernel.ld + +struct run { + struct run *next; +}; + +struct { + struct spinlock lock; + int use_lock; + struct run *freelist; +} kmem; + +// Initialization happens in two phases. +// 1. main() calls kinit1() while still using entrypgdir to place just +// the pages mapped by entrypgdir on free list. +// 2. main() calls kinit2() with the rest of the physical pages +// after installing a full page table that maps them on all cores. +void +kinit1(void *vstart, void *vend) +{ + initlock(&kmem.lock, "kmem"); + kmem.use_lock = 0; + freerange(vstart, vend); +} + +void +kinit2(void *vstart, void *vend) +{ + freerange(vstart, vend); + kmem.use_lock = 1; +} + +void +freerange(void *vstart, void *vend) +{ + char *p; + p = (char*)PGROUNDUP((uint)vstart); + for(; p + PGSIZE <= (char*)vend; p += PGSIZE) + kfree(p); +} +//PAGEBREAK: 21 +// Free the page of physical memory pointed at by v, +// which normally should have been returned by a +// call to kalloc(). (The exception is when +// initializing the allocator; see kinit above.) +void +kfree(char *v) +{ + struct run *r; + + if((uint)v % PGSIZE || v < end || V2P(v) >= PHYSTOP) + panic("kfree"); + + // Fill with junk to catch dangling refs. + memset(v, 1, PGSIZE); + + if(kmem.use_lock) + acquire(&kmem.lock); + r = (struct run*)v; + r->next = kmem.freelist; + kmem.freelist = r; + if(kmem.use_lock) + release(&kmem.lock); +} + +// Allocate one 4096-byte page of physical memory. +// Returns a pointer that the kernel can use. +// Returns 0 if the memory cannot be allocated. +char* +kalloc(void) +{ + struct run *r; + + if(kmem.use_lock) + acquire(&kmem.lock); + r = kmem.freelist; + if(r) + kmem.freelist = r->next; + if(kmem.use_lock) + release(&kmem.lock); + return (char*)r; +} + diff --git a/xv6-public/kbd.c b/xv6-public/kbd.c new file mode 100644 index 0000000..32c1463 --- /dev/null +++ b/xv6-public/kbd.c @@ -0,0 +1,50 @@ +#include "types.h" +#include "x86.h" +#include "defs.h" +#include "kbd.h" + +int +kbdgetc(void) +{ + static uint shift; + static uchar *charcode[4] = { + normalmap, shiftmap, ctlmap, ctlmap + }; + uint st, data, c; + + st = inb(KBSTATP); + if((st & KBS_DIB) == 0) + return -1; + data = inb(KBDATAP); + + if(data == 0xE0){ + shift |= E0ESC; + return 0; + } else if(data & 0x80){ + // Key released + data = (shift & E0ESC ? data : data & 0x7F); + shift &= ~(shiftcode[data] | E0ESC); + return 0; + } else if(shift & E0ESC){ + // Last character was an E0 escape; or with 0x80 + data |= 0x80; + shift &= ~E0ESC; + } + + shift |= shiftcode[data]; + shift ^= togglecode[data]; + c = charcode[shift & (CTL | SHIFT)][data]; + if(shift & CAPSLOCK){ + if('a' <= c && c <= 'z') + c += 'A' - 'a'; + else if('A' <= c && c <= 'Z') + c += 'a' - 'A'; + } + return c; +} + +void +kbdintr(void) +{ + consoleintr(kbdgetc); +} diff --git a/xv6-public/kbd.h b/xv6-public/kbd.h new file mode 100644 index 0000000..babbd6e --- /dev/null +++ b/xv6-public/kbd.h @@ -0,0 +1,112 @@ +// PC keyboard interface constants + +#define KBSTATP 0x64 // kbd controller status port(I) +#define KBS_DIB 0x01 // kbd data in buffer +#define KBDATAP 0x60 // kbd data port(I) + +#define NO 0 + +#define SHIFT (1<<0) +#define CTL (1<<1) +#define ALT (1<<2) + +#define CAPSLOCK (1<<3) +#define NUMLOCK (1<<4) +#define SCROLLLOCK (1<<5) + +#define E0ESC (1<<6) + +// Special keycodes +#define KEY_HOME 0xE0 +#define KEY_END 0xE1 +#define KEY_UP 0xE2 +#define KEY_DN 0xE3 +#define KEY_LF 0xE4 +#define KEY_RT 0xE5 +#define KEY_PGUP 0xE6 +#define KEY_PGDN 0xE7 +#define KEY_INS 0xE8 +#define KEY_DEL 0xE9 + +// C('A') == Control-A +#define C(x) (x - '@') + +static uchar shiftcode[256] = +{ + [0x1D] CTL, + [0x2A] SHIFT, + [0x36] SHIFT, + [0x38] ALT, + [0x9D] CTL, + [0xB8] ALT +}; + +static uchar togglecode[256] = +{ + [0x3A] CAPSLOCK, + [0x45] NUMLOCK, + [0x46] SCROLLLOCK +}; + +static uchar normalmap[256] = +{ + NO, 0x1B, '1', '2', '3', '4', '5', '6', // 0x00 + '7', '8', '9', '0', '-', '=', '\b', '\t', + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', // 0x10 + 'o', 'p', '[', ']', '\n', NO, 'a', 's', + 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', // 0x20 + '\'', '`', NO, '\\', 'z', 'x', 'c', 'v', + 'b', 'n', 'm', ',', '.', '/', NO, '*', // 0x30 + NO, ' ', NO, NO, NO, NO, NO, NO, + NO, NO, NO, NO, NO, NO, NO, '7', // 0x40 + '8', '9', '-', '4', '5', '6', '+', '1', + '2', '3', '0', '.', NO, NO, NO, NO, // 0x50 + [0x9C] '\n', // KP_Enter + [0xB5] '/', // KP_Div + [0xC8] KEY_UP, [0xD0] KEY_DN, + [0xC9] KEY_PGUP, [0xD1] KEY_PGDN, + [0xCB] KEY_LF, [0xCD] KEY_RT, + [0x97] KEY_HOME, [0xCF] KEY_END, + [0xD2] KEY_INS, [0xD3] KEY_DEL +}; + +static uchar shiftmap[256] = +{ + NO, 033, '!', '@', '#', '$', '%', '^', // 0x00 + '&', '*', '(', ')', '_', '+', '\b', '\t', + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', // 0x10 + 'O', 'P', '{', '}', '\n', NO, 'A', 'S', + 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', // 0x20 + '"', '~', NO, '|', 'Z', 'X', 'C', 'V', + 'B', 'N', 'M', '<', '>', '?', NO, '*', // 0x30 + NO, ' ', NO, NO, NO, NO, NO, NO, + NO, NO, NO, NO, NO, NO, NO, '7', // 0x40 + '8', '9', '-', '4', '5', '6', '+', '1', + '2', '3', '0', '.', NO, NO, NO, NO, // 0x50 + [0x9C] '\n', // KP_Enter + [0xB5] '/', // KP_Div + [0xC8] KEY_UP, [0xD0] KEY_DN, + [0xC9] KEY_PGUP, [0xD1] KEY_PGDN, + [0xCB] KEY_LF, [0xCD] KEY_RT, + [0x97] KEY_HOME, [0xCF] KEY_END, + [0xD2] KEY_INS, [0xD3] KEY_DEL +}; + +static uchar ctlmap[256] = +{ + NO, NO, NO, NO, NO, NO, NO, NO, + NO, NO, NO, NO, NO, NO, NO, NO, + C('Q'), C('W'), C('E'), C('R'), C('T'), C('Y'), C('U'), C('I'), + C('O'), C('P'), NO, NO, '\r', NO, C('A'), C('S'), + C('D'), C('F'), C('G'), C('H'), C('J'), C('K'), C('L'), NO, + NO, NO, NO, C('\\'), C('Z'), C('X'), C('C'), C('V'), + C('B'), C('N'), C('M'), NO, NO, C('/'), NO, NO, + [0x9C] '\r', // KP_Enter + [0xB5] C('/'), // KP_Div + [0xC8] KEY_UP, [0xD0] KEY_DN, + [0xC9] KEY_PGUP, [0xD1] KEY_PGDN, + [0xCB] KEY_LF, [0xCD] KEY_RT, + [0x97] KEY_HOME, [0xCF] KEY_END, + [0xD2] KEY_INS, [0xD3] KEY_DEL +}; + diff --git a/xv6-public/kernel.ld b/xv6-public/kernel.ld new file mode 100644 index 0000000..e24c860 --- /dev/null +++ b/xv6-public/kernel.ld @@ -0,0 +1,68 @@ +/* Simple linker script for the JOS 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(_start) + +SECTIONS +{ + /* Link the kernel at this address: "." means the current address */ + /* Must be equal to KERNLINK */ + . = 0x80100000; + + .text : AT(0x100000) { + *(.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); + + /* Conventionally, Unix linkers provide pseudo-symbols + * etext, edata, and end, at the end of the text, data, and bss. + * For the kernel mapping, we need the address at the beginning + * of the data section, but that's not one of the conventional + * symbols, because the convention started before there was a + * read-only rodata section between text and data. */ + PROVIDE(data = .); + + /* The data segment */ + .data : { + *(.data) + } + + PROVIDE(edata = .); + + .bss : { + *(.bss) + } + + PROVIDE(end = .); + + /DISCARD/ : { + *(.eh_frame .note.GNU-stack) + } +} diff --git a/xv6-public/kill.c b/xv6-public/kill.c new file mode 100644 index 0000000..364f6af --- /dev/null +++ b/xv6-public/kill.c @@ -0,0 +1,17 @@ +#include "types.h" +#include "stat.h" +#include "user.h" + +int +main(int argc, char **argv) +{ + int i; + + if(argc < 2){ + printf(2, "usage: kill pid...\n"); + exit(); + } + for(i=1; i>16) & 0xFF) >= 4) + lapicw(PCINT, MASKED); + + // Map error interrupt to IRQ_ERROR. + lapicw(ERROR, T_IRQ0 + IRQ_ERROR); + + // Clear error status register (requires back-to-back writes). + lapicw(ESR, 0); + lapicw(ESR, 0); + + // Ack any outstanding interrupts. + lapicw(EOI, 0); + + // Send an Init Level De-Assert to synchronise arbitration ID's. + lapicw(ICRHI, 0); + lapicw(ICRLO, BCAST | INIT | LEVEL); + while(lapic[ICRLO] & DELIVS) + ; + + // Enable interrupts on the APIC (but not on the processor). + lapicw(TPR, 0); +} + +int +lapicid(void) +{ + if (!lapic) + return 0; + return lapic[ID] >> 24; +} + +// Acknowledge interrupt. +void +lapiceoi(void) +{ + if(lapic) + lapicw(EOI, 0); +} + +// Spin for a given number of microseconds. +// On real hardware would want to tune this dynamically. +void +microdelay(int us) +{ +} + +#define CMOS_PORT 0x70 +#define CMOS_RETURN 0x71 + +// Start additional processor running entry code at addr. +// See Appendix B of MultiProcessor Specification. +void +lapicstartap(uchar apicid, uint addr) +{ + int i; + ushort *wrv; + + // "The BSP must initialize CMOS shutdown code to 0AH + // and the warm reset vector (DWORD based at 40:67) to point at + // the AP startup code prior to the [universal startup algorithm]." + outb(CMOS_PORT, 0xF); // offset 0xF is shutdown code + outb(CMOS_PORT+1, 0x0A); + wrv = (ushort*)P2V((0x40<<4 | 0x67)); // Warm reset vector + wrv[0] = 0; + wrv[1] = addr >> 4; + + // "Universal startup algorithm." + // Send INIT (level-triggered) interrupt to reset other CPU. + lapicw(ICRHI, apicid<<24); + lapicw(ICRLO, INIT | LEVEL | ASSERT); + microdelay(200); + lapicw(ICRLO, INIT | LEVEL); + microdelay(100); // should be 10ms, but too slow in Bochs! + + // Send startup IPI (twice!) to enter code. + // Regular hardware is supposed to only accept a STARTUP + // when it is in the halted state due to an INIT. So the second + // should be ignored, but it is part of the official Intel algorithm. + // Bochs complains about the second one. Too bad for Bochs. + for(i = 0; i < 2; i++){ + lapicw(ICRHI, apicid<<24); + lapicw(ICRLO, STARTUP | (addr>>12)); + microdelay(200); + } +} + +#define CMOS_STATA 0x0a +#define CMOS_STATB 0x0b +#define CMOS_UIP (1 << 7) // RTC update in progress + +#define SECS 0x00 +#define MINS 0x02 +#define HOURS 0x04 +#define DAY 0x07 +#define MONTH 0x08 +#define YEAR 0x09 + +static uint +cmos_read(uint reg) +{ + outb(CMOS_PORT, reg); + microdelay(200); + + return inb(CMOS_RETURN); +} + +static void +fill_rtcdate(struct rtcdate *r) +{ + r->second = cmos_read(SECS); + r->minute = cmos_read(MINS); + r->hour = cmos_read(HOURS); + r->day = cmos_read(DAY); + r->month = cmos_read(MONTH); + r->year = cmos_read(YEAR); +} + +// qemu seems to use 24-hour GWT and the values are BCD encoded +void +cmostime(struct rtcdate *r) +{ + struct rtcdate t1, t2; + int sb, bcd; + + sb = cmos_read(CMOS_STATB); + + bcd = (sb & (1 << 2)) == 0; + + // make sure CMOS doesn't modify time while we read it + for(;;) { + fill_rtcdate(&t1); + if(cmos_read(CMOS_STATA) & CMOS_UIP) + continue; + fill_rtcdate(&t2); + if(memcmp(&t1, &t2, sizeof(t1)) == 0) + break; + } + + // convert + if(bcd) { +#define CONV(x) (t1.x = ((t1.x >> 4) * 10) + (t1.x & 0xf)) + CONV(second); + CONV(minute); + CONV(hour ); + CONV(day ); + CONV(month ); + CONV(year ); +#undef CONV + } + + *r = t1; + r->year += 2000; +} diff --git a/xv6-public/ln.c b/xv6-public/ln.c new file mode 100644 index 0000000..cf8a64e --- /dev/null +++ b/xv6-public/ln.c @@ -0,0 +1,15 @@ +#include "types.h" +#include "stat.h" +#include "user.h" + +int +main(int argc, char *argv[]) +{ + if(argc != 3){ + printf(2, "Usage: ln old new\n"); + exit(); + } + if(link(argv[1], argv[2]) < 0) + printf(2, "link %s %s: failed\n", argv[1], argv[2]); + exit(); +} diff --git a/xv6-public/log.c b/xv6-public/log.c new file mode 100644 index 0000000..a64c0f6 --- /dev/null +++ b/xv6-public/log.c @@ -0,0 +1,234 @@ +#include "types.h" +#include "defs.h" +#include "param.h" +#include "spinlock.h" +#include "sleeplock.h" +#include "fs.h" +#include "buf.h" + +// Simple logging that allows concurrent FS system calls. +// +// A log transaction contains the updates of multiple FS system +// calls. The logging system only commits when there are +// no FS system calls active. Thus there is never +// any reasoning required about whether a commit might +// write an uncommitted system call's updates to disk. +// +// A system call should call begin_op()/end_op() to mark +// its start and end. Usually begin_op() just increments +// the count of in-progress FS system calls and returns. +// But if it thinks the log is close to running out, it +// sleeps until the last outstanding end_op() commits. +// +// The log is a physical re-do log containing disk blocks. +// The on-disk log format: +// header block, containing block #s for block A, B, C, ... +// block A +// block B +// block C +// ... +// Log appends are synchronous. + +// Contents of the header block, used for both the on-disk header block +// and to keep track in memory of logged block# before commit. +struct logheader { + int n; + int block[LOGSIZE]; +}; + +struct log { + struct spinlock lock; + int start; + int size; + int outstanding; // how many FS sys calls are executing. + int committing; // in commit(), please wait. + int dev; + struct logheader lh; +}; +struct log log; + +static void recover_from_log(void); +static void commit(); + +void +initlog(int dev) +{ + if (sizeof(struct logheader) >= BSIZE) + panic("initlog: too big logheader"); + + struct superblock sb; + initlock(&log.lock, "log"); + readsb(dev, &sb); + log.start = sb.logstart; + log.size = sb.nlog; + log.dev = dev; + recover_from_log(); +} + +// Copy committed blocks from log to their home location +static void +install_trans(void) +{ + int tail; + + for (tail = 0; tail < log.lh.n; tail++) { + struct buf *lbuf = bread(log.dev, log.start+tail+1); // read log block + struct buf *dbuf = bread(log.dev, log.lh.block[tail]); // read dst + memmove(dbuf->data, lbuf->data, BSIZE); // copy block to dst + bwrite(dbuf); // write dst to disk + brelse(lbuf); + brelse(dbuf); + } +} + +// Read the log header from disk into the in-memory log header +static void +read_head(void) +{ + struct buf *buf = bread(log.dev, log.start); + struct logheader *lh = (struct logheader *) (buf->data); + int i; + log.lh.n = lh->n; + for (i = 0; i < log.lh.n; i++) { + log.lh.block[i] = lh->block[i]; + } + brelse(buf); +} + +// Write in-memory log header to disk. +// This is the true point at which the +// current transaction commits. +static void +write_head(void) +{ + struct buf *buf = bread(log.dev, log.start); + struct logheader *hb = (struct logheader *) (buf->data); + int i; + hb->n = log.lh.n; + for (i = 0; i < log.lh.n; i++) { + hb->block[i] = log.lh.block[i]; + } + bwrite(buf); + brelse(buf); +} + +static void +recover_from_log(void) +{ + read_head(); + install_trans(); // if committed, copy from log to disk + log.lh.n = 0; + write_head(); // clear the log +} + +// called at the start of each FS system call. +void +begin_op(void) +{ + acquire(&log.lock); + while(1){ + if(log.committing){ + sleep(&log, &log.lock); + } else if(log.lh.n + (log.outstanding+1)*MAXOPBLOCKS > LOGSIZE){ + // this op might exhaust log space; wait for commit. + sleep(&log, &log.lock); + } else { + log.outstanding += 1; + release(&log.lock); + break; + } + } +} + +// called at the end of each FS system call. +// commits if this was the last outstanding operation. +void +end_op(void) +{ + int do_commit = 0; + + acquire(&log.lock); + log.outstanding -= 1; + if(log.committing) + panic("log.committing"); + if(log.outstanding == 0){ + do_commit = 1; + log.committing = 1; + } else { + // begin_op() may be waiting for log space, + // and decrementing log.outstanding has decreased + // the amount of reserved space. + wakeup(&log); + } + release(&log.lock); + + if(do_commit){ + // call commit w/o holding locks, since not allowed + // to sleep with locks. + commit(); + acquire(&log.lock); + log.committing = 0; + wakeup(&log); + release(&log.lock); + } +} + +// Copy modified blocks from cache to log. +static void +write_log(void) +{ + int tail; + + for (tail = 0; tail < log.lh.n; tail++) { + struct buf *to = bread(log.dev, log.start+tail+1); // log block + struct buf *from = bread(log.dev, log.lh.block[tail]); // cache block + memmove(to->data, from->data, BSIZE); + bwrite(to); // write the log + brelse(from); + brelse(to); + } +} + +static void +commit() +{ + if (log.lh.n > 0) { + write_log(); // Write modified blocks from cache to log + write_head(); // Write header to disk -- the real commit + install_trans(); // Now install writes to home locations + log.lh.n = 0; + write_head(); // Erase the transaction from the log + } +} + +// Caller has modified b->data and is done with the buffer. +// Record the block number and pin in the cache with B_DIRTY. +// commit()/write_log() will do the disk write. +// +// log_write() replaces bwrite(); a typical use is: +// bp = bread(...) +// modify bp->data[] +// log_write(bp) +// brelse(bp) +void +log_write(struct buf *b) +{ + int i; + + if (log.lh.n >= LOGSIZE || log.lh.n >= log.size - 1) + panic("too big a transaction"); + if (log.outstanding < 1) + panic("log_write outside of trans"); + + acquire(&log.lock); + for (i = 0; i < log.lh.n; i++) { + if (log.lh.block[i] == b->blockno) // log absorbtion + break; + } + log.lh.block[i] = b->blockno; + if (i == log.lh.n) + log.lh.n++; + b->flags |= B_DIRTY; // prevent eviction + release(&log.lock); +} + diff --git a/xv6-public/ls.c b/xv6-public/ls.c new file mode 100644 index 0000000..2862913 --- /dev/null +++ b/xv6-public/ls.c @@ -0,0 +1,85 @@ +#include "types.h" +#include "stat.h" +#include "user.h" +#include "fs.h" + +char* +fmtname(char *path) +{ + static char buf[DIRSIZ+1]; + char *p; + + // Find first character after last slash. + for(p=path+strlen(path); p >= path && *p != '/'; p--) + ; + p++; + + // Return blank-padded name. + if(strlen(p) >= DIRSIZ) + return p; + memmove(buf, p, strlen(p)); + memset(buf+strlen(p), ' ', DIRSIZ-strlen(p)); + return buf; +} + +void +ls(char *path) +{ + char buf[512], *p; + int fd; + struct dirent de; + struct stat st; + + if((fd = open(path, 0)) < 0){ + printf(2, "ls: cannot open %s\n", path); + return; + } + + if(fstat(fd, &st) < 0){ + printf(2, "ls: cannot stat %s\n", path); + close(fd); + return; + } + + switch(st.type){ + case T_FILE: + printf(1, "%s %d %d %d\n", fmtname(path), st.type, st.ino, st.size); + break; + + case T_DIR: + if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){ + printf(1, "ls: path too long\n"); + break; + } + strcpy(buf, path); + p = buf+strlen(buf); + *p++ = '/'; + while(read(fd, &de, sizeof(de)) == sizeof(de)){ + if(de.inum == 0) + continue; + memmove(p, de.name, DIRSIZ); + p[DIRSIZ] = 0; + if(stat(buf, &st) < 0){ + printf(1, "ls: cannot stat %s\n", buf); + continue; + } + printf(1, "%s %d %d %d\n", fmtname(buf), st.type, st.ino, st.size); + } + break; + } + close(fd); +} + +int +main(int argc, char *argv[]) +{ + int i; + + if(argc < 2){ + ls("."); + exit(); + } + for(i=1; istarted), 1); // tell startothers() we're up + scheduler(); // start running processes +} + +pde_t entrypgdir[]; // For entry.S + +// Start the non-boot (AP) processors. +static void +startothers(void) +{ + extern uchar _binary_entryother_start[], _binary_entryother_size[]; + uchar *code; + struct cpu *c; + char *stack; + + // Write entry code to unused memory at 0x7000. + // The linker has placed the image of entryother.S in + // _binary_entryother_start. + code = P2V(0x7000); + memmove(code, _binary_entryother_start, (uint)_binary_entryother_size); + + for(c = cpus; c < cpus+ncpu; c++){ + if(c == mycpu()) // We've started already. + continue; + + // Tell entryother.S what stack to use, where to enter, and what + // pgdir to use. We cannot use kpgdir yet, because the AP processor + // is running in low memory, so we use entrypgdir for the APs too. + stack = kalloc(); + *(void**)(code-4) = stack + KSTACKSIZE; + *(void(**)(void))(code-8) = mpenter; + *(int**)(code-12) = (void *) V2P(entrypgdir); + + lapicstartap(c->apicid, V2P(code)); + + // wait for cpu to finish mpmain() + while(c->started == 0) + ; + } +} + +// The boot page table used in entry.S and entryother.S. +// Page directories (and page tables) must start on page boundaries, +// hence the __aligned__ attribute. +// PTE_PS in a page directory entry enables 4Mbyte pages. + +__attribute__((__aligned__(PGSIZE))) +pde_t entrypgdir[NPDENTRIES] = { + // Map VA's [0, 4MB) to PA's [0, 4MB) + [0] = (0) | PTE_P | PTE_W | PTE_PS, + // Map VA's [KERNBASE, KERNBASE+4MB) to PA's [0, 4MB) + [KERNBASE>>PDXSHIFT] = (0) | PTE_P | PTE_W | PTE_PS, +}; + +//PAGEBREAK! +// Blank page. +//PAGEBREAK! +// Blank page. +//PAGEBREAK! +// Blank page. + diff --git a/xv6-public/memide.c b/xv6-public/memide.c new file mode 100644 index 0000000..ba267ac --- /dev/null +++ b/xv6-public/memide.c @@ -0,0 +1,60 @@ +// Fake IDE disk; stores blocks in memory. +// Useful for running kernel without scratch disk. + +#include "types.h" +#include "defs.h" +#include "param.h" +#include "mmu.h" +#include "proc.h" +#include "x86.h" +#include "traps.h" +#include "spinlock.h" +#include "sleeplock.h" +#include "fs.h" +#include "buf.h" + +extern uchar _binary_fs_img_start[], _binary_fs_img_size[]; + +static int disksize; +static uchar *memdisk; + +void +ideinit(void) +{ + memdisk = _binary_fs_img_start; + disksize = (uint)_binary_fs_img_size/BSIZE; +} + +// Interrupt handler. +void +ideintr(void) +{ + // no-op +} + +// Sync buf with disk. +// If B_DIRTY is set, write buf to disk, clear B_DIRTY, set B_VALID. +// Else if B_VALID is not set, read buf from disk, set B_VALID. +void +iderw(struct buf *b) +{ + uchar *p; + + if(!holdingsleep(&b->lock)) + panic("iderw: buf not locked"); + if((b->flags & (B_VALID|B_DIRTY)) == B_VALID) + panic("iderw: nothing to do"); + if(b->dev != 1) + panic("iderw: request not for disk 1"); + if(b->blockno >= disksize) + panic("iderw: block out of range"); + + p = memdisk + b->blockno*BSIZE; + + if(b->flags & B_DIRTY){ + b->flags &= ~B_DIRTY; + memmove(p, b->data, BSIZE); + } else + memmove(b->data, p, BSIZE); + b->flags |= B_VALID; +} diff --git a/xv6-public/memlayout.h b/xv6-public/memlayout.h new file mode 100644 index 0000000..d1615f7 --- /dev/null +++ b/xv6-public/memlayout.h @@ -0,0 +1,15 @@ +// Memory layout + +#define EXTMEM 0x100000 // Start of extended memory +#define PHYSTOP 0xE000000 // Top physical memory +#define DEVSPACE 0xFE000000 // Other devices are at high addresses + +// Key addresses for address space layout (see kmap in vm.c for layout) +#define KERNBASE 0x80000000 // First kernel virtual address +#define KERNLINK (KERNBASE+EXTMEM) // Address where kernel is linked + +#define V2P(a) (((uint) (a)) - KERNBASE) +#define P2V(a) ((void *)(((char *) (a)) + KERNBASE)) + +#define V2P_WO(x) ((x) - KERNBASE) // same as V2P, but without casts +#define P2V_WO(x) ((x) + KERNBASE) // same as P2V, but without casts diff --git a/xv6-public/mkdir.c b/xv6-public/mkdir.c new file mode 100644 index 0000000..6e4c954 --- /dev/null +++ b/xv6-public/mkdir.c @@ -0,0 +1,23 @@ +#include "types.h" +#include "stat.h" +#include "user.h" + +int +main(int argc, char *argv[]) +{ + int i; + + if(argc < 2){ + printf(2, "Usage: mkdir files...\n"); + exit(); + } + + for(i = 1; i < argc; i++){ + if(mkdir(argv[i]) < 0){ + printf(2, "mkdir: %s failed to create\n", argv[i]); + break; + } + } + + exit(); +} diff --git a/xv6-public/mkfs.c b/xv6-public/mkfs.c new file mode 100644 index 0000000..8e011a7 --- /dev/null +++ b/xv6-public/mkfs.c @@ -0,0 +1,297 @@ +#include +#include +#include +#include +#include +#include + +#define stat xv6_stat // avoid clash with host struct stat +#include "types.h" +#include "fs.h" +#include "stat.h" +#include "param.h" + +#ifndef static_assert +#define static_assert(a, b) do { switch (0) case 0: case (a): ; } while (0) +#endif + +#define NINODES 200 + +// Disk layout: +// [ boot block | sb block | log | inode blocks | free bit map | data blocks ] + +int nbitmap = FSSIZE/(BSIZE*8) + 1; +int ninodeblocks = NINODES / IPB + 1; +int nlog = LOGSIZE; +int nmeta; // Number of meta blocks (boot, sb, nlog, inode, bitmap) +int nblocks; // Number of data blocks + +int fsfd; +struct superblock sb; +char zeroes[BSIZE]; +uint freeinode = 1; +uint freeblock; + + +void balloc(int); +void wsect(uint, void*); +void winode(uint, struct dinode*); +void rinode(uint inum, struct dinode *ip); +void rsect(uint sec, void *buf); +uint ialloc(ushort type); +void iappend(uint inum, void *p, int n); + +// convert to intel byte order +ushort +xshort(ushort x) +{ + ushort y; + uchar *a = (uchar*)&y; + a[0] = x; + a[1] = x >> 8; + return y; +} + +uint +xint(uint x) +{ + uint y; + uchar *a = (uchar*)&y; + a[0] = x; + a[1] = x >> 8; + a[2] = x >> 16; + a[3] = x >> 24; + return y; +} + +int +main(int argc, char *argv[]) +{ + int i, cc, fd; + uint rootino, inum, off; + struct dirent de; + char buf[BSIZE]; + struct dinode din; + + + static_assert(sizeof(int) == 4, "Integers must be 4 bytes!"); + + if(argc < 2){ + fprintf(stderr, "Usage: mkfs fs.img files...\n"); + exit(1); + } + + assert((BSIZE % sizeof(struct dinode)) == 0); + assert((BSIZE % sizeof(struct dirent)) == 0); + + fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666); + if(fsfd < 0){ + perror(argv[1]); + exit(1); + } + + // 1 fs block = 1 disk sector + nmeta = 2 + nlog + ninodeblocks + nbitmap; + nblocks = FSSIZE - nmeta; + + sb.size = xint(FSSIZE); + sb.nblocks = xint(nblocks); + sb.ninodes = xint(NINODES); + sb.nlog = xint(nlog); + sb.logstart = xint(2); + sb.inodestart = xint(2+nlog); + sb.bmapstart = xint(2+nlog+ninodeblocks); + + printf("nmeta %d (boot, super, log blocks %u inode blocks %u, bitmap blocks %u) blocks %d total %d\n", + nmeta, nlog, ninodeblocks, nbitmap, nblocks, FSSIZE); + + freeblock = nmeta; // the first free block that we can allocate + + for(i = 0; i < FSSIZE; i++) + wsect(i, zeroes); + + memset(buf, 0, sizeof(buf)); + memmove(buf, &sb, sizeof(sb)); + wsect(1, buf); + + rootino = ialloc(T_DIR); + assert(rootino == ROOTINO); + + bzero(&de, sizeof(de)); + de.inum = xshort(rootino); + strcpy(de.name, "."); + iappend(rootino, &de, sizeof(de)); + + bzero(&de, sizeof(de)); + de.inum = xshort(rootino); + strcpy(de.name, ".."); + iappend(rootino, &de, sizeof(de)); + + for(i = 2; i < argc; i++){ + assert(index(argv[i], '/') == 0); + + if((fd = open(argv[i], 0)) < 0){ + perror(argv[i]); + exit(1); + } + + // Skip leading _ in name when writing to file system. + // The binaries are named _rm, _cat, etc. to keep the + // build operating system from trying to execute them + // in place of system binaries like rm and cat. + if(argv[i][0] == '_') + ++argv[i]; + + inum = ialloc(T_FILE); + + bzero(&de, sizeof(de)); + de.inum = xshort(inum); + strncpy(de.name, argv[i], DIRSIZ); + iappend(rootino, &de, sizeof(de)); + + while((cc = read(fd, buf, sizeof(buf))) > 0) + iappend(inum, buf, cc); + + close(fd); + } + + // fix size of root inode dir + rinode(rootino, &din); + off = xint(din.size); + off = ((off/BSIZE) + 1) * BSIZE; + din.size = xint(off); + winode(rootino, &din); + + balloc(freeblock); + + exit(0); +} + +void +wsect(uint sec, void *buf) +{ + if(lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE){ + perror("lseek"); + exit(1); + } + if(write(fsfd, buf, BSIZE) != BSIZE){ + perror("write"); + exit(1); + } +} + +void +winode(uint inum, struct dinode *ip) +{ + char buf[BSIZE]; + uint bn; + struct dinode *dip; + + bn = IBLOCK(inum, sb); + rsect(bn, buf); + dip = ((struct dinode*)buf) + (inum % IPB); + *dip = *ip; + wsect(bn, buf); +} + +void +rinode(uint inum, struct dinode *ip) +{ + char buf[BSIZE]; + uint bn; + struct dinode *dip; + + bn = IBLOCK(inum, sb); + rsect(bn, buf); + dip = ((struct dinode*)buf) + (inum % IPB); + *ip = *dip; +} + +void +rsect(uint sec, void *buf) +{ + if(lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE){ + perror("lseek"); + exit(1); + } + if(read(fsfd, buf, BSIZE) != BSIZE){ + perror("read"); + exit(1); + } +} + +uint +ialloc(ushort type) +{ + uint inum = freeinode++; + struct dinode din; + + bzero(&din, sizeof(din)); + din.type = xshort(type); + din.nlink = xshort(1); + din.size = xint(0); + winode(inum, &din); + return inum; +} + +void +balloc(int used) +{ + uchar buf[BSIZE]; + int i; + + printf("balloc: first %d blocks have been allocated\n", used); + assert(used < BSIZE*8); + bzero(buf, BSIZE); + for(i = 0; i < used; i++){ + buf[i/8] = buf[i/8] | (0x1 << (i%8)); + } + printf("balloc: write bitmap block at sector %d\n", sb.bmapstart); + wsect(sb.bmapstart, buf); +} + +#define min(a, b) ((a) < (b) ? (a) : (b)) + +void +iappend(uint inum, void *xp, int n) +{ + char *p = (char*)xp; + uint fbn, off, n1; + struct dinode din; + char buf[BSIZE]; + uint indirect[NINDIRECT]; + uint x; + + rinode(inum, &din); + off = xint(din.size); + // printf("append inum %d at off %d sz %d\n", inum, off, n); + while(n > 0){ + fbn = off / BSIZE; + assert(fbn < MAXFILE); + if(fbn < NDIRECT){ + if(xint(din.addrs[fbn]) == 0){ + din.addrs[fbn] = xint(freeblock++); + } + x = xint(din.addrs[fbn]); + } else { + if(xint(din.addrs[NDIRECT]) == 0){ + din.addrs[NDIRECT] = xint(freeblock++); + } + rsect(xint(din.addrs[NDIRECT]), (char*)indirect); + if(indirect[fbn - NDIRECT] == 0){ + indirect[fbn - NDIRECT] = xint(freeblock++); + wsect(xint(din.addrs[NDIRECT]), (char*)indirect); + } + x = xint(indirect[fbn-NDIRECT]); + } + n1 = min(n, (fbn + 1) * BSIZE - off); + rsect(x, buf); + bcopy(p, buf + off - (fbn * BSIZE), n1); + wsect(x, buf); + n -= n1; + off += n1; + p += n1; + } + din.size = xint(off); + winode(inum, &din); +} diff --git a/xv6-public/mmu.h b/xv6-public/mmu.h new file mode 100644 index 0000000..a82d8e2 --- /dev/null +++ b/xv6-public/mmu.h @@ -0,0 +1,181 @@ +// This file contains definitions for the +// x86 memory management unit (MMU). + +// Eflags register +#define FL_IF 0x00000200 // Interrupt Enable + +// Control Register flags +#define CR0_PE 0x00000001 // Protection Enable +#define CR0_WP 0x00010000 // Write Protect +#define CR0_PG 0x80000000 // Paging + +#define CR4_PSE 0x00000010 // Page size extension + +// various segment selectors. +#define SEG_KCODE 1 // kernel code +#define SEG_KDATA 2 // kernel data+stack +#define SEG_UCODE 3 // user code +#define SEG_UDATA 4 // user data+stack +#define SEG_TSS 5 // this process's task state + +// cpu->gdt[NSEGS] holds the above segments. +#define NSEGS 6 + +#ifndef __ASSEMBLER__ +// Segment Descriptor +struct segdesc { + uint lim_15_0 : 16; // Low bits of segment limit + uint base_15_0 : 16; // Low bits of segment base address + uint base_23_16 : 8; // Middle bits of segment base address + uint type : 4; // Segment type (see STS_ constants) + uint s : 1; // 0 = system, 1 = application + uint dpl : 2; // Descriptor Privilege Level + uint p : 1; // Present + uint lim_19_16 : 4; // High bits of segment limit + uint avl : 1; // Unused (available for software use) + uint rsv1 : 1; // Reserved + uint db : 1; // 0 = 16-bit segment, 1 = 32-bit segment + uint g : 1; // Granularity: limit scaled by 4K when set + uint base_31_24 : 8; // High bits of segment base address +}; + +// Normal segment +#define SEG(type, base, lim, dpl) (struct segdesc) \ +{ ((lim) >> 12) & 0xffff, (uint)(base) & 0xffff, \ + ((uint)(base) >> 16) & 0xff, type, 1, dpl, 1, \ + (uint)(lim) >> 28, 0, 0, 1, 1, (uint)(base) >> 24 } +#define SEG16(type, base, lim, dpl) (struct segdesc) \ +{ (lim) & 0xffff, (uint)(base) & 0xffff, \ + ((uint)(base) >> 16) & 0xff, type, 1, dpl, 1, \ + (uint)(lim) >> 16, 0, 0, 1, 0, (uint)(base) >> 24 } +#endif + +#define DPL_USER 0x3 // User DPL + +// Application segment type bits +#define STA_X 0x8 // Executable segment +#define STA_W 0x2 // Writeable (non-executable segments) +#define STA_R 0x2 // Readable (executable segments) + +// System segment type bits +#define STS_T32A 0x9 // Available 32-bit TSS +#define STS_IG32 0xE // 32-bit Interrupt Gate +#define STS_TG32 0xF // 32-bit Trap Gate + +// A virtual address 'la' has a three-part structure as follows: +// +// +--------10------+-------10-------+---------12----------+ +// | Page Directory | Page Table | Offset within Page | +// | Index | Index | | +// +----------------+----------------+---------------------+ +// \--- PDX(va) --/ \--- PTX(va) --/ + +// page directory index +#define PDX(va) (((uint)(va) >> PDXSHIFT) & 0x3FF) + +// page table index +#define PTX(va) (((uint)(va) >> PTXSHIFT) & 0x3FF) + +// construct virtual address from indexes and offset +#define PGADDR(d, t, o) ((uint)((d) << PDXSHIFT | (t) << PTXSHIFT | (o))) + +// Page directory and page table constants. +#define NPDENTRIES 1024 // # directory entries per page directory +#define NPTENTRIES 1024 // # PTEs per page table +#define PGSIZE 4096 // bytes mapped by a page + +#define PTXSHIFT 12 // offset of PTX in a linear address +#define PDXSHIFT 22 // offset of PDX in a linear address + +#define PGROUNDUP(sz) (((sz)+PGSIZE-1) & ~(PGSIZE-1)) +#define PGROUNDDOWN(a) (((a)) & ~(PGSIZE-1)) + +// Page table/directory entry flags. +#define PTE_P 0x001 // Present +#define PTE_W 0x002 // Writeable +#define PTE_U 0x004 // User +#define PTE_PS 0x080 // Page Size + +// Address in page table or page directory entry +#define PTE_ADDR(pte) ((uint)(pte) & ~0xFFF) +#define PTE_FLAGS(pte) ((uint)(pte) & 0xFFF) + +#ifndef __ASSEMBLER__ +typedef uint pte_t; + +// Task state segment format +struct taskstate { + uint link; // Old ts selector + uint esp0; // Stack pointers and segment selectors + ushort ss0; // after an increase in privilege level + ushort padding1; + uint *esp1; + ushort ss1; + ushort padding2; + uint *esp2; + ushort ss2; + ushort padding3; + void *cr3; // Page directory base + uint *eip; // Saved state from last task switch + uint eflags; + uint eax; // More saved state (registers) + uint ecx; + uint edx; + uint ebx; + uint *esp; + uint *ebp; + uint esi; + uint edi; + ushort es; // Even more saved state (segment selectors) + ushort padding4; + ushort cs; + ushort padding5; + ushort ss; + ushort padding6; + ushort ds; + ushort padding7; + ushort fs; + ushort padding8; + ushort gs; + ushort padding9; + ushort ldt; + ushort padding10; + ushort t; // Trap on task switch + ushort iomb; // I/O map base address +}; + +// Gate descriptors for interrupts and traps +struct gatedesc { + uint off_15_0 : 16; // low 16 bits of offset in segment + uint cs : 16; // code segment selector + uint args : 5; // # args, 0 for interrupt/trap gates + uint rsv1 : 3; // reserved(should be zero I guess) + uint type : 4; // type(STS_{IG32,TG32}) + uint s : 1; // must be 0 (system) + uint dpl : 2; // descriptor(meaning new) privilege level + uint p : 1; // Present + uint off_31_16 : 16; // high bits of offset in segment +}; + +// Set up a normal interrupt/trap gate descriptor. +// - istrap: 1 for a trap (= exception) gate, 0 for an interrupt gate. +// interrupt gate clears FL_IF, trap gate leaves FL_IF alone +// - sel: Code segment selector for interrupt/trap handler +// - off: Offset in code segment for interrupt/trap handler +// - dpl: Descriptor Privilege Level - +// the privilege level required for software to invoke +// this interrupt/trap gate explicitly using an int instruction. +#define SETGATE(gate, istrap, sel, off, d) \ +{ \ + (gate).off_15_0 = (uint)(off) & 0xffff; \ + (gate).cs = (sel); \ + (gate).args = 0; \ + (gate).rsv1 = 0; \ + (gate).type = (istrap) ? STS_TG32 : STS_IG32; \ + (gate).s = 0; \ + (gate).dpl = (d); \ + (gate).p = 1; \ + (gate).off_31_16 = (uint)(off) >> 16; \ +} + +#endif diff --git a/xv6-public/mp.c b/xv6-public/mp.c new file mode 100644 index 0000000..79bb0ad --- /dev/null +++ b/xv6-public/mp.c @@ -0,0 +1,139 @@ +// Multiprocessor support +// Search memory for MP description structures. +// http://developer.intel.com/design/pentium/datashts/24201606.pdf + +#include "types.h" +#include "defs.h" +#include "param.h" +#include "memlayout.h" +#include "mp.h" +#include "x86.h" +#include "mmu.h" +#include "proc.h" + +struct cpu cpus[NCPU]; +int ncpu; +uchar ioapicid; + +static uchar +sum(uchar *addr, int len) +{ + int i, sum; + + sum = 0; + for(i=0; iphysaddr == 0) + return 0; + conf = (struct mpconf*) P2V((uint) mp->physaddr); + if(memcmp(conf, "PCMP", 4) != 0) + return 0; + if(conf->version != 1 && conf->version != 4) + return 0; + if(sum((uchar*)conf, conf->length) != 0) + return 0; + *pmp = mp; + return conf; +} + +void +mpinit(void) +{ + uchar *p, *e; + int ismp; + struct mp *mp; + struct mpconf *conf; + struct mpproc *proc; + struct mpioapic *ioapic; + + if((conf = mpconfig(&mp)) == 0) + panic("Expect to run on an SMP"); + ismp = 1; + lapic = (uint*)conf->lapicaddr; + for(p=(uchar*)(conf+1), e=(uchar*)conf+conf->length; papicid; // apicid may differ from ncpu + ncpu++; + } + p += sizeof(struct mpproc); + continue; + case MPIOAPIC: + ioapic = (struct mpioapic*)p; + ioapicid = ioapic->apicno; + p += sizeof(struct mpioapic); + continue; + case MPBUS: + case MPIOINTR: + case MPLINTR: + p += 8; + continue; + default: + ismp = 0; + break; + } + } + if(!ismp) + panic("Didn't find a suitable machine"); + + if(mp->imcrp){ + // Bochs doesn't support IMCR, so this doesn't run on Bochs. + // But it would on real hardware. + outb(0x22, 0x70); // Select IMCR + outb(0x23, inb(0x23) | 1); // Mask external interrupts. + } +} diff --git a/xv6-public/mp.h b/xv6-public/mp.h new file mode 100644 index 0000000..4d17283 --- /dev/null +++ b/xv6-public/mp.h @@ -0,0 +1,56 @@ +// See MultiProcessor Specification Version 1.[14] + +struct mp { // floating pointer + uchar signature[4]; // "_MP_" + void *physaddr; // phys addr of MP config table + uchar length; // 1 + uchar specrev; // [14] + uchar checksum; // all bytes must add up to 0 + uchar type; // MP system config type + uchar imcrp; + uchar reserved[3]; +}; + +struct mpconf { // configuration table header + uchar signature[4]; // "PCMP" + ushort length; // total table length + uchar version; // [14] + uchar checksum; // all bytes must add up to 0 + uchar product[20]; // product id + uint *oemtable; // OEM table pointer + ushort oemlength; // OEM table length + ushort entry; // entry count + uint *lapicaddr; // address of local APIC + ushort xlength; // extended table length + uchar xchecksum; // extended table checksum + uchar reserved; +}; + +struct mpproc { // processor table entry + uchar type; // entry type (0) + uchar apicid; // local APIC id + uchar version; // local APIC verison + uchar flags; // CPU flags + #define MPBOOT 0x02 // This proc is the bootstrap processor. + uchar signature[4]; // CPU signature + uint feature; // feature flags from CPUID instruction + uchar reserved[8]; +}; + +struct mpioapic { // I/O APIC table entry + uchar type; // entry type (2) + uchar apicno; // I/O APIC id + uchar version; // I/O APIC version + uchar flags; // I/O APIC flags + uint *addr; // I/O APIC address +}; + +// Table entry types +#define MPPROC 0x00 // One per processor +#define MPBUS 0x01 // One per bus +#define MPIOAPIC 0x02 // One per I/O APIC +#define MPIOINTR 0x03 // One per bus interrupt source +#define MPLINTR 0x04 // One per system interrupt source + +//PAGEBREAK! +// Blank page. diff --git a/xv6-public/param.h b/xv6-public/param.h new file mode 100644 index 0000000..a7e90ef --- /dev/null +++ b/xv6-public/param.h @@ -0,0 +1,14 @@ +#define NPROC 64 // maximum number of processes +#define KSTACKSIZE 4096 // size of per-process kernel stack +#define NCPU 8 // maximum number of CPUs +#define NOFILE 16 // open files per process +#define NFILE 100 // open files per system +#define NINODE 50 // maximum number of active i-nodes +#define NDEV 10 // maximum major device number +#define ROOTDEV 1 // device number of file system root disk +#define MAXARG 32 // max exec arguments +#define MAXOPBLOCKS 10 // max # of blocks any FS op writes +#define LOGSIZE (MAXOPBLOCKS*3) // max data blocks in on-disk log +#define NBUF (MAXOPBLOCKS*3) // size of disk block cache +#define FSSIZE 1000 // size of file system in blocks + diff --git a/xv6-public/picirq.c b/xv6-public/picirq.c new file mode 100644 index 0000000..e26957f --- /dev/null +++ b/xv6-public/picirq.c @@ -0,0 +1,19 @@ +#include "types.h" +#include "x86.h" +#include "traps.h" + +// I/O Addresses of the two programmable interrupt controllers +#define IO_PIC1 0x20 // Master (IRQs 0-7) +#define IO_PIC2 0xA0 // Slave (IRQs 8-15) + +// Don't use the 8259A interrupt controllers. Xv6 assumes SMP hardware. +void +picinit(void) +{ + // mask all interrupts + outb(IO_PIC1+1, 0xFF); + outb(IO_PIC2+1, 0xFF); +} + +//PAGEBREAK! +// Blank page. diff --git a/xv6-public/pipe.c b/xv6-public/pipe.c new file mode 100644 index 0000000..e9abe7f --- /dev/null +++ b/xv6-public/pipe.c @@ -0,0 +1,121 @@ +#include "types.h" +#include "defs.h" +#include "param.h" +#include "mmu.h" +#include "proc.h" +#include "fs.h" +#include "spinlock.h" +#include "sleeplock.h" +#include "file.h" + +#define PIPESIZE 512 + +struct pipe { + struct spinlock lock; + char data[PIPESIZE]; + uint nread; // number of bytes read + uint nwrite; // number of bytes written + int readopen; // read fd is still open + int writeopen; // write fd is still open +}; + +int +pipealloc(struct file **f0, struct file **f1) +{ + struct pipe *p; + + p = 0; + *f0 = *f1 = 0; + if((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0) + goto bad; + if((p = (struct pipe*)kalloc()) == 0) + goto bad; + p->readopen = 1; + p->writeopen = 1; + p->nwrite = 0; + p->nread = 0; + initlock(&p->lock, "pipe"); + (*f0)->type = FD_PIPE; + (*f0)->readable = 1; + (*f0)->writable = 0; + (*f0)->pipe = p; + (*f1)->type = FD_PIPE; + (*f1)->readable = 0; + (*f1)->writable = 1; + (*f1)->pipe = p; + return 0; + +//PAGEBREAK: 20 + bad: + if(p) + kfree((char*)p); + if(*f0) + fileclose(*f0); + if(*f1) + fileclose(*f1); + return -1; +} + +void +pipeclose(struct pipe *p, int writable) +{ + acquire(&p->lock); + if(writable){ + p->writeopen = 0; + wakeup(&p->nread); + } else { + p->readopen = 0; + wakeup(&p->nwrite); + } + if(p->readopen == 0 && p->writeopen == 0){ + release(&p->lock); + kfree((char*)p); + } else + release(&p->lock); +} + +//PAGEBREAK: 40 +int +pipewrite(struct pipe *p, char *addr, int n) +{ + int i; + + acquire(&p->lock); + for(i = 0; i < n; i++){ + while(p->nwrite == p->nread + PIPESIZE){ //DOC: pipewrite-full + if(p->readopen == 0 || myproc()->killed){ + release(&p->lock); + return -1; + } + wakeup(&p->nread); + sleep(&p->nwrite, &p->lock); //DOC: pipewrite-sleep + } + p->data[p->nwrite++ % PIPESIZE] = addr[i]; + } + wakeup(&p->nread); //DOC: pipewrite-wakeup1 + release(&p->lock); + return n; +} + +int +piperead(struct pipe *p, char *addr, int n) +{ + int i; + + acquire(&p->lock); + while(p->nread == p->nwrite && p->writeopen){ //DOC: pipe-empty + if(myproc()->killed){ + release(&p->lock); + return -1; + } + sleep(&p->nread, &p->lock); //DOC: piperead-sleep + } + for(i = 0; i < n; i++){ //DOC: piperead-copy + if(p->nread == p->nwrite) + break; + addr[i] = p->data[p->nread++ % PIPESIZE]; + } + wakeup(&p->nwrite); //DOC: piperead-wakeup + release(&p->lock); + return i; +} diff --git a/xv6-public/pr.pl b/xv6-public/pr.pl new file mode 100644 index 0000000..46905bd --- /dev/null +++ b/xv6-public/pr.pl @@ -0,0 +1,36 @@ +#!/usr/bin/perl + +use POSIX qw(strftime); + +if($ARGV[0] eq "-h"){ + shift @ARGV; + $h = $ARGV[0]; + shift @ARGV; +}else{ + $h = $ARGV[0]; +} + +$page = 0; +$now = strftime "%b %e %H:%M %Y", localtime; + +@lines = <>; +for($i=0; $i<@lines; $i+=50){ + print "\n\n"; + ++$page; + print "$now $h Page $page\n"; + print "\n\n"; + for($j=$i; $j<@lines && $j<$i +50; $j++){ + $lines[$j] =~ s!//DOC.*!!; + print $lines[$j]; + } + for(; $j<$i+50; $j++){ + print "\n"; + } + $sheet = ""; + if($lines[$i] =~ /^([0-9][0-9])[0-9][0-9] /){ + $sheet = "Sheet $1"; + } + print "\n\n"; + print "$sheet\n"; + print "\n\n"; +} diff --git a/xv6-public/printf.c b/xv6-public/printf.c new file mode 100644 index 0000000..b3298aa --- /dev/null +++ b/xv6-public/printf.c @@ -0,0 +1,85 @@ +#include "types.h" +#include "stat.h" +#include "user.h" + +static void +putc(int fd, char c) +{ + write(fd, &c, 1); +} + +static void +printint(int fd, int xx, int base, int sgn) +{ + static char digits[] = "0123456789ABCDEF"; + char buf[16]; + int i, neg; + uint x; + + neg = 0; + if(sgn && xx < 0){ + neg = 1; + x = -xx; + } else { + x = xx; + } + + i = 0; + do{ + buf[i++] = digits[x % base]; + }while((x /= base) != 0); + if(neg) + buf[i++] = '-'; + + while(--i >= 0) + putc(fd, buf[i]); +} + +// Print to the given fd. Only understands %d, %x, %p, %s. +void +printf(int fd, const char *fmt, ...) +{ + char *s; + int c, i, state; + uint *ap; + + state = 0; + ap = (uint*)(void*)&fmt + 1; + for(i = 0; fmt[i]; i++){ + c = fmt[i] & 0xff; + if(state == 0){ + if(c == '%'){ + state = '%'; + } else { + putc(fd, c); + } + } else if(state == '%'){ + if(c == 'd'){ + printint(fd, *ap, 10, 1); + ap++; + } else if(c == 'x' || c == 'p'){ + printint(fd, *ap, 16, 0); + ap++; + } else if(c == 's'){ + s = (char*)*ap; + ap++; + if(s == 0) + s = "(null)"; + while(*s != 0){ + putc(fd, *s); + s++; + } + } else if(c == 'c'){ + putc(fd, *ap); + ap++; + } else if(c == '%'){ + putc(fd, c); + } else { + // Unknown % sequence. Print it to draw attention. + putc(fd, '%'); + putc(fd, c); + } + state = 0; + } + } +} diff --git a/xv6-public/printpcs b/xv6-public/printpcs new file mode 100644 index 0000000..81d039b --- /dev/null +++ b/xv6-public/printpcs @@ -0,0 +1,14 @@ +#!/bin/sh + +# Decode the symbols from a panic EIP list + +# Find a working addr2line +for p in i386-jos-elf-addr2line addr2line; do + if which $p 2>&1 >/dev/null && \ + $p -h 2>&1 | grep -q '\belf32-i386\b'; then + break + fi +done + +# Enable as much pretty-printing as this addr2line can do +$p $($p -h | grep ' -[aipsf] ' | awk '{print $1}') -e kernel "$@" diff --git a/xv6-public/proc.c b/xv6-public/proc.c new file mode 100644 index 0000000..8b6b996 --- /dev/null +++ b/xv6-public/proc.c @@ -0,0 +1,534 @@ +#include "types.h" +#include "defs.h" +#include "param.h" +#include "memlayout.h" +#include "mmu.h" +#include "x86.h" +#include "proc.h" +#include "spinlock.h" + +struct { + struct spinlock lock; + struct proc proc[NPROC]; +} ptable; + +static struct proc *initproc; + +int nextpid = 1; +extern void forkret(void); +extern void trapret(void); + +static void wakeup1(void *chan); + +void +pinit(void) +{ + initlock(&ptable.lock, "ptable"); +} + +// Must be called with interrupts disabled +int +cpuid() { + return mycpu()-cpus; +} + +// Must be called with interrupts disabled to avoid the caller being +// rescheduled between reading lapicid and running through the loop. +struct cpu* +mycpu(void) +{ + int apicid, i; + + if(readeflags()&FL_IF) + panic("mycpu called with interrupts enabled\n"); + + apicid = lapicid(); + // APIC IDs are not guaranteed to be contiguous. Maybe we should have + // a reverse map, or reserve a register to store &cpus[i]. + for (i = 0; i < ncpu; ++i) { + if (cpus[i].apicid == apicid) + return &cpus[i]; + } + panic("unknown apicid\n"); +} + +// Disable interrupts so that we are not rescheduled +// while reading proc from the cpu structure +struct proc* +myproc(void) { + struct cpu *c; + struct proc *p; + pushcli(); + c = mycpu(); + p = c->proc; + popcli(); + return p; +} + +//PAGEBREAK: 32 +// Look in the process table for an UNUSED proc. +// If found, change state to EMBRYO and initialize +// state required to run in the kernel. +// Otherwise return 0. +static struct proc* +allocproc(void) +{ + struct proc *p; + char *sp; + + acquire(&ptable.lock); + + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++) + if(p->state == UNUSED) + goto found; + + release(&ptable.lock); + return 0; + +found: + p->state = EMBRYO; + p->pid = nextpid++; + p->ticks = 0; + release(&ptable.lock); + + // Allocate kernel stack. + if((p->kstack = kalloc()) == 0){ + p->state = UNUSED; + return 0; + } + sp = p->kstack + KSTACKSIZE; + + // Leave room for trap frame. + sp -= sizeof *p->tf; + p->tf = (struct trapframe*)sp; + + // Set up new context to start executing at forkret, + // which returns to trapret. + sp -= 4; + *(uint*)sp = (uint)trapret; + + sp -= sizeof *p->context; + p->context = (struct context*)sp; + memset(p->context, 0, sizeof *p->context); + p->context->eip = (uint)forkret; + + return p; +} + +//PAGEBREAK: 32 +// Set up first user process. +void +userinit(void) +{ + struct proc *p; + extern char _binary_initcode_start[], _binary_initcode_size[]; + + p = allocproc(); + + initproc = p; + if((p->pgdir = setupkvm()) == 0) + panic("userinit: out of memory?"); + inituvm(p->pgdir, _binary_initcode_start, (int)_binary_initcode_size); + p->sz = PGSIZE; + memset(p->tf, 0, sizeof(*p->tf)); + p->tf->cs = (SEG_UCODE << 3) | DPL_USER; + p->tf->ds = (SEG_UDATA << 3) | DPL_USER; + p->tf->es = p->tf->ds; + p->tf->ss = p->tf->ds; + p->tf->eflags = FL_IF; + p->tf->esp = PGSIZE; + p->tf->eip = 0; // beginning of initcode.S + + safestrcpy(p->name, "initcode", sizeof(p->name)); + p->cwd = namei("/"); + + // this assignment to p->state lets other cores + // run this process. the acquire forces the above + // writes to be visible, and the lock is also needed + // because the assignment might not be atomic. + acquire(&ptable.lock); + + p->state = RUNNABLE; + + release(&ptable.lock); +} + +// Grow current process's memory by n bytes. +// Return 0 on success, -1 on failure. +int +growproc(int n) +{ + uint sz; + struct proc *curproc = myproc(); + + sz = curproc->sz; + if(n > 0){ + if((sz = allocuvm(curproc->pgdir, sz, sz + n)) == 0) + return -1; + } else if(n < 0){ + if((sz = deallocuvm(curproc->pgdir, sz, sz + n)) == 0) + return -1; + } + curproc->sz = sz; + switchuvm(curproc); + return 0; +} + +// Create a new process copying p as the parent. +// Sets up stack to return as if from system call. +// Caller must set state of returned proc to RUNNABLE. +int +fork(void) +{ + int i, pid; + struct proc *np; + struct proc *curproc = myproc(); + + // Allocate process. + if((np = allocproc()) == 0){ + return -1; + } + + // Copy process state from proc. + if((np->pgdir = copyuvm(curproc->pgdir, curproc->sz)) == 0){ + kfree(np->kstack); + np->kstack = 0; + np->state = UNUSED; + return -1; + } + np->sz = curproc->sz; + np->parent = curproc; + *np->tf = *curproc->tf; + + // Clear %eax so that fork returns 0 in the child. + np->tf->eax = 0; + + for(i = 0; i < NOFILE; i++) + if(curproc->ofile[i]) + np->ofile[i] = filedup(curproc->ofile[i]); + np->cwd = idup(curproc->cwd); + + safestrcpy(np->name, curproc->name, sizeof(curproc->name)); + + pid = np->pid; + + acquire(&ptable.lock); + + np->state = RUNNABLE; + + release(&ptable.lock); + + return pid; +} + +// Exit the current process. Does not return. +// An exited process remains in the zombie state +// until its parent calls wait() to find out it exited. +void +exit(void) +{ + struct proc *curproc = myproc(); + struct proc *p; + int fd; + + if(curproc == initproc) + panic("init exiting"); + + // Close all open files. + for(fd = 0; fd < NOFILE; fd++){ + if(curproc->ofile[fd]){ + fileclose(curproc->ofile[fd]); + curproc->ofile[fd] = 0; + } + } + + begin_op(); + iput(curproc->cwd); + end_op(); + curproc->cwd = 0; + + acquire(&ptable.lock); + + // Parent might be sleeping in wait(). + wakeup1(curproc->parent); + + // Pass abandoned children to init. + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ + if(p->parent == curproc){ + p->parent = initproc; + if(p->state == ZOMBIE) + wakeup1(initproc); + } + } + + // Jump into the scheduler, never to return. + curproc->state = ZOMBIE; + sched(); + panic("zombie exit"); +} + +// Wait for a child process to exit and return its pid. +// Return -1 if this process has no children. +int +wait(void) +{ + struct proc *p; + int havekids, pid; + struct proc *curproc = myproc(); + + acquire(&ptable.lock); + for(;;){ + // Scan through table looking for exited children. + havekids = 0; + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ + if(p->parent != curproc) + continue; + havekids = 1; + if(p->state == ZOMBIE){ + // Found one. + pid = p->pid; + kfree(p->kstack); + p->kstack = 0; + freevm(p->pgdir); + p->pid = 0; + p->parent = 0; + p->name[0] = 0; + p->killed = 0; + p->state = UNUSED; + release(&ptable.lock); + return pid; + } + } + + // No point waiting if we don't have any children. + if(!havekids || curproc->killed){ + release(&ptable.lock); + return -1; + } + + // Wait for children to exit. (See wakeup1 call in proc_exit.) + sleep(curproc, &ptable.lock); //DOC: wait-sleep + } +} + +//PAGEBREAK: 42 +// Per-CPU process scheduler. +// Each CPU calls scheduler() after setting itself up. +// Scheduler never returns. It loops, doing: +// - choose a process to run +// - swtch to start running that process +// - eventually that process transfers control +// via swtch back to the scheduler. +void +scheduler(void) +{ + struct proc *p; + struct cpu *c = mycpu(); + c->proc = 0; + + for(;;){ + // Enable interrupts on this processor. + sti(); + + // Loop over process table looking for process to run. + acquire(&ptable.lock); + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ + if(p->state != RUNNABLE) + continue; + + // Switch to chosen process. It is the process's job + // to release ptable.lock and then reacquire it + // before jumping back to us. + c->proc = p; + switchuvm(p); + p->state = RUNNING; + + swtch(&(c->scheduler), p->context); + switchkvm(); + + // Process is done running for now. + // It should have changed its p->state before coming back. + c->proc = 0; + } + release(&ptable.lock); + + } +} + +// Enter scheduler. Must hold only ptable.lock +// and have changed proc->state. Saves and restores +// intena because intena is a property of this +// kernel thread, not this CPU. It should +// be proc->intena and proc->ncli, but that would +// break in the few places where a lock is held but +// there's no process. +void +sched(void) +{ + int intena; + struct proc *p = myproc(); + + if(!holding(&ptable.lock)) + panic("sched ptable.lock"); + if(mycpu()->ncli != 1) + panic("sched locks"); + if(p->state == RUNNING) + panic("sched running"); + if(readeflags()&FL_IF) + panic("sched interruptible"); + intena = mycpu()->intena; + swtch(&p->context, mycpu()->scheduler); + mycpu()->intena = intena; +} + +// Give up the CPU for one scheduling round. +void +yield(void) +{ + acquire(&ptable.lock); //DOC: yieldlock + myproc()->state = RUNNABLE; + sched(); + release(&ptable.lock); +} + +// A fork child's very first scheduling by scheduler() +// will swtch here. "Return" to user space. +void +forkret(void) +{ + static int first = 1; + // Still holding ptable.lock from scheduler. + release(&ptable.lock); + + if (first) { + // Some initialization functions must be run in the context + // of a regular process (e.g., they call sleep), and thus cannot + // be run from main(). + first = 0; + iinit(ROOTDEV); + initlog(ROOTDEV); + } + + // Return to "caller", actually trapret (see allocproc). +} + +// Atomically release lock and sleep on chan. +// Reacquires lock when awakened. +void +sleep(void *chan, struct spinlock *lk) +{ + struct proc *p = myproc(); + + if(p == 0) + panic("sleep"); + + if(lk == 0) + panic("sleep without lk"); + + // Must acquire ptable.lock in order to + // change p->state and then call sched. + // Once we hold ptable.lock, we can be + // guaranteed that we won't miss any wakeup + // (wakeup runs with ptable.lock locked), + // so it's okay to release lk. + if(lk != &ptable.lock){ //DOC: sleeplock0 + acquire(&ptable.lock); //DOC: sleeplock1 + release(lk); + } + // Go to sleep. + p->chan = chan; + p->state = SLEEPING; + + sched(); + + // Tidy up. + p->chan = 0; + + // Reacquire original lock. + if(lk != &ptable.lock){ //DOC: sleeplock2 + release(&ptable.lock); + acquire(lk); + } +} + +//PAGEBREAK! +// Wake up all processes sleeping on chan. +// The ptable lock must be held. +static void +wakeup1(void *chan) +{ + struct proc *p; + + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++) + if(p->state == SLEEPING && p->chan == chan) + p->state = RUNNABLE; +} + +// Wake up all processes sleeping on chan. +void +wakeup(void *chan) +{ + acquire(&ptable.lock); + wakeup1(chan); + release(&ptable.lock); +} + +// Kill the process with the given pid. +// Process won't exit until it returns +// to user space (see trap in trap.c). +int +kill(int pid) +{ + struct proc *p; + + acquire(&ptable.lock); + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ + if(p->pid == pid){ + p->killed = 1; + // Wake process from sleep if necessary. + if(p->state == SLEEPING) + p->state = RUNNABLE; + release(&ptable.lock); + return 0; + } + } + release(&ptable.lock); + return -1; +} + +//PAGEBREAK: 36 +// Print a process listing to console. For debugging. +// Runs when user types ^P on console. +// No lock to avoid wedging a stuck machine further. +void +procdump(void) +{ + static char *states[] = { + [UNUSED] "unused", + [EMBRYO] "embryo", + [SLEEPING] "sleep ", + [RUNNABLE] "runble", + [RUNNING] "run ", + [ZOMBIE] "zombie" + }; + int i; + struct proc *p; + char *state; + uint pc[10]; + + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ + if(p->state == UNUSED) + continue; + if(p->state >= 0 && p->state < NELEM(states) && states[p->state]) + state = states[p->state]; + else + state = "???"; + cprintf("%d %s %s", p->pid, state, p->name); + if(p->state == SLEEPING){ + getcallerpcs((uint*)p->context->ebp+2, pc); + for(i=0; i<10 && pc[i] != 0; i++) + cprintf(" %p", pc[i]); + } + cprintf("\n"); + } +} diff --git a/xv6-public/proc.h b/xv6-public/proc.h new file mode 100644 index 0000000..5dc6b52 --- /dev/null +++ b/xv6-public/proc.h @@ -0,0 +1,61 @@ +// Per-CPU state +struct cpu { + uchar apicid; // Local APIC ID + struct context *scheduler; // swtch() here to enter scheduler + struct taskstate ts; // Used by x86 to find stack for interrupt + struct segdesc gdt[NSEGS]; // x86 global descriptor table + volatile uint started; // Has the CPU started? + int ncli; // Depth of pushcli nesting. + int intena; // Were interrupts enabled before pushcli? + struct proc *proc; // The process running on this cpu or null +}; + +extern struct cpu cpus[NCPU]; +extern int ncpu; + +//PAGEBREAK: 17 +// Saved registers for kernel context switches. +// Don't need to save all the segment registers (%cs, etc), +// because they are constant across kernel contexts. +// Don't need to save %eax, %ecx, %edx, because the +// x86 convention is that the caller has saved them. +// Contexts are stored at the bottom of the stack they +// describe; the stack pointer is the address of the context. +// The layout of the context matches the layout of the stack in swtch.S +// at the "Switch stacks" comment. Switch doesn't save eip explicitly, +// but it is on the stack and allocproc() manipulates it. +struct context { + uint edi; + uint esi; + uint ebx; + uint ebp; + uint eip; +}; + +enum procstate { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE }; + +// Per-process state +struct proc { + uint sz; // Size of process memory (bytes) + pde_t* pgdir; // Page table + char *kstack; // Bottom of kernel stack for this process + enum procstate state; // Process state + int pid; // Process ID + struct proc *parent; // Parent process + struct trapframe *tf; // Trap frame for current syscall + struct context *context; // swtch() here to run process + void *chan; // If non-zero, sleeping on chan + int killed; // If non-zero, have been killed + struct file *ofile[NOFILE]; // Open files + struct inode *cwd; // Current directory + char name[16]; // Process name (debugging) + int alarminterval; + void (*alarmhandler)(); // pointer of handler + int ticks; +}; + +// Process memory is laid out contiguously, low addresses first: +// text +// original data and bss +// fixed-size stack +// expandable heap diff --git a/xv6-public/rm.c b/xv6-public/rm.c new file mode 100644 index 0000000..4fd33c8 --- /dev/null +++ b/xv6-public/rm.c @@ -0,0 +1,23 @@ +#include "types.h" +#include "stat.h" +#include "user.h" + +int +main(int argc, char *argv[]) +{ + int i; + + if(argc < 2){ + printf(2, "Usage: rm files...\n"); + exit(); + } + + for(i = 1; i < argc; i++){ + if(unlink(argv[i]) < 0){ + printf(2, "rm: %s failed to delete\n", argv[i]); + break; + } + } + + exit(); +} diff --git a/xv6-public/runoff b/xv6-public/runoff new file mode 100644 index 0000000..be362d0 --- /dev/null +++ b/xv6-public/runoff @@ -0,0 +1,246 @@ +#!/bin/sh + +echo This script takes a minute to run. Be patient. 1>&2 + +LC_CTYPE=C export LC_CTYPE + +# pad stdin to multiple of 120 lines +pad() +{ + awk '{print} END{for(; NR%120!=0; NR++) print ""}' +} + +# create formatted (numbered) files +mkdir -p fmt +rm -f fmt/* +cp README fmt +echo > fmt/blank +files=`grep -v '^#' runoff.list | awk '{print $1}'` +n=99 +for i in $files +do + ./runoff1 -n $n $i >fmt/$i + nn=`tail -1 fmt/$i | sed 's/ .*//; s/^0*//'` + if [ "x$nn" != x ]; then + n=$nn + fi +done + +# create table of contents +cat toc.hdr >fmt/toc +pr -e8 -t runoff.list | awk ' +/^[a-z0-9]/ { + s=$0 + f="fmt/"$1 + getline"fmt/tocdata" + next +} +{ + print +}' | pr -3 -t >>fmt/toc +cat toc.ftr >>fmt/toc + +# check for bad alignments +perl -e ' + $leftwarn = 0; + while(<>){ + chomp; + s!#.*!!; + s!\s+! !g; + s! +$!!; + next if /^$/; + + if(/TOC: (\d+) (.*)/){ + $toc{$2} = $1; + next; + } + + if(/sheet1: (left|right)$/){ + print STDERR "assuming that sheet 1 is a $1 page. double-check!\n"; + $left = $1 eq "left" ? "13579" : "02468"; + $right = $1 eq "left" ? "02468" : "13579"; + next; + } + + if(/even: (.*)/){ + $file = $1; + if(!defined($toc{$file})){ + print STDERR "Have no toc for $file\n"; + next; + } + if($toc{$file} =~ /^\d\d[^0]/){ + print STDERR "$file does not start on a fresh page.\n"; + } + next; + } + + if(/odd: (.*)/){ + $file = $1; + if(!defined($toc{$file})){ + print STDERR "Have no toc for $file\n"; + next; + } + if($toc{$file} !~ /^\d\d5/){ + print STDERR "$file does not start on a second half page.\n"; + } + next; + } + + if(/(left|right): (.*)/){ + $what = $1; + $file = $2; + if(!defined($toc{$file})){ + print STDERR "Have no toc for $file\n"; + next; + } + if($what eq "left" && !($toc{$file} =~ /^\d[$left][05]/)){ + print STDERR "$file does not start on a left page [$toc{$file}]\n"; + } + # why does this not work if I inline $x in the if? + $x = ($toc{$file} =~ /^\d[$right][05]/); + if($what eq "right" && !$x){ + print STDERR "$file does not start on a right page [$toc{$file}] [$x]\n"; + } + next; + } + + print STDERR "Unknown spec: $_\n"; + } +' fmt/tocdata runoff.spec + +# make definition list +cd fmt +perl -e ' + while(<>) { + chomp; + + s!//.*!!; + s!/\*([^*]|[*][^/])*\*/!!g; + s!\s! !g; + s! +$!!; + + # look for declarations like char* x; + if (/^[0-9]+ typedef .* u(int|short|long|char);/) { + next; + } + if (/^[0-9]+ extern/) { + next; + } + if (/^[0-9]+ struct [a-zA-Z0-9_]+;/) { + next; + } + if (/^([0-9]+) #define +([A-za-z0-9_]+) +?\(.*/) { + print "$1 $2\n" + } + elsif (/^([0-9]+) #define +([A-Za-z0-9_]+) +([^ ]+)/) { + print "$1 $2 $3\n"; + } + elsif (/^([0-9]+) #define +([A-Za-z0-9_]+)/) { + print "$1 $2\n"; + } + + if(/^^([0-9]+) \.globl ([a-zA-Z0-9_]+)/){ + $isglobl{$2} = 1; + } + if(/^^([0-9]+) ([a-zA-Z0-9_]+):$/ && $isglobl{$2}){ + print "$1 $2\n"; + } + + if (/\(/) { + next; + } + + if (/^([0-9]+) (((static|struct|extern|union|enum) +)*([A-Za-z0-9_]+))( .*)? +([A-Za-z_][A-Za-z0-9_]*)(,|;|=| =)/) { + print "$1 $7\n"; + } + + elsif(/^([0-9]+) (enum|struct|union) +([A-Za-z0-9_]+) +{/){ + print "$1 $3\n"; + } + # TODO: enum members + } +' $files >defs + +(for i in $files +do + case "$i" in + *.S) + cat $i | sed 's;#.*;;; s;//.*;;;' + ;; + *) + cat $i | sed 's;//.*;;; s;"([^"\\]|\\.)*";;;' + esac +done +) >alltext + +perl -n -e 'print if s/^([0-9]+ [a-zA-Z0-9_]+)\(.*$/\1/;' alltext | + egrep -v ' (STUB|usage|main|if|for)$' >>defs +#perl -n -e 'print if s/^([0-9]+) STUB\(([a-zA-Z0-9_]+)\)$/\1 \2/;' alltext \ +# >>defs +( +>s.defs + +# make reference list +for i in `awk '{print $2}' defs | sort -f | uniq` +do + defs=`egrep '^[0-9]+ '$i'( |$)' defs | awk '{print $1}'` + echo $i $defs >>s.defs + uses=`egrep -h '([^a-zA-Z_0-9])'$i'($|[^a-zA-Z_0-9])' alltext | awk '{print $1}'` + if [ "x$defs" != "x$uses" ]; then + echo $i $defs + echo $uses |fmt -29 | sed 's/^/ /' +# else +# echo $i defined but not used >&2 + fi +done +) >refs + +# build defs list +awk ' +{ + printf("%04d %s\n", $2, $1); + for(i=3; i<=NF; i++) + printf("%04d \" \n", $i); +} +' s.defs > t.defs + +# format the whole thing +( + ../pr.pl README + ../pr.pl -h "table of contents" toc + # pr -t -2 t.defs | ../pr.pl -h "definitions" | pad + pr -t -l50 -2 refs | ../pr.pl -h "cross-references" | pad + # pr.pl -h "definitions" -2 t.defs | pad + # pr.pl -h "cross-references" -2 refs | pad + ../pr.pl blank # make sheet 1 start on left page + ../pr.pl blank + for i in $files + do + ../pr.pl -h "xv6/$i" $i + done +) | mpage -m50t50b -o -bLetter -T -t -2 -FCourier -L60 >all.ps +grep Pages: all.ps + +# if we have the nice font, use it +nicefont=LucidaSans-Typewriter83 +if [ ! -f ../$nicefont ] +then + if git cat-file blob font:$nicefont > ../$nicefont~; then + mv ../$nicefont~ ../$nicefont + fi +fi +if [ -f ../$nicefont ] +then + echo nicefont + (sed 1q all.ps; cat ../$nicefont; sed "1d; s/Courier/$nicefont/" all.ps) >allf.ps +else + echo ugly font! + cp all.ps allf.ps +fi +ps2pdf allf.ps ../xv6.pdf +# cd .. +# pdftops xv6.pdf xv6.ps diff --git a/xv6-public/runoff.list b/xv6-public/runoff.list new file mode 100644 index 0000000..2df9b81 --- /dev/null +++ b/xv6-public/runoff.list @@ -0,0 +1,80 @@ +# basic headers +types.h +param.h +memlayout.h +defs.h +x86.h +asm.h +mmu.h +elf.h +date.h + +# entering xv6 +entry.S +entryother.S +main.c + +# locks +spinlock.h +spinlock.c + +# processes +vm.c +proc.h +proc.c +swtch.S +kalloc.c + +# system calls +traps.h +vectors.pl +trapasm.S +trap.c +syscall.h +syscall.c +sysproc.c + +# file system +buf.h +sleeplock.h +fcntl.h +stat.h +fs.h +file.h +ide.c +bio.c +sleeplock.c +log.c +fs.c +file.c +sysfile.c +exec.c + +# pipes +pipe.c + +# string operations +string.c + +# low-level hardware +mp.h +mp.c +lapic.c +ioapic.c +kbd.h +kbd.c +console.c +uart.c + +# user-level +initcode.S +usys.S +init.c +sh.c + +# bootloader +bootasm.S +bootmain.c + +# link +kernel.ld diff --git a/xv6-public/runoff.spec b/xv6-public/runoff.spec new file mode 100644 index 0000000..9247948 --- /dev/null +++ b/xv6-public/runoff.spec @@ -0,0 +1,102 @@ +# Is sheet 01 (after the TOC) a left sheet or a right sheet? +sheet1: left + +# "left" and "right" specify which page of a two-page spread a file +# must start on. "left" means that a file must start on the first of +# the two pages. "right" means it must start on the second of the two +# pages. The file may start in either column. +# +# "even" and "odd" specify which column a file must start on. "even" +# means it must start in the left of the two columns (00). "odd" means it +# must start in the right of the two columns (50). +# +# You'd think these would be the other way around. + +# types.h either +# param.h either +# defs.h either +# x86.h either +# asm.h either +# mmu.h either +# elf.h either +# mp.h either + +even: entry.S # mild preference +even: entryother.S # mild preference +even: main.c +# mp.c don't care at all +# even: initcode.S +# odd: init.c + +left: spinlock.h +even: spinlock.h + +# This gets struct proc and allocproc on the same spread +left: proc.h +even: proc.h + +# goal is to have two action-packed 2-page spreads, +# one with +# userinit growproc fork exit wait +# and another with +# scheduler sched yield forkret sleep wakeup1 wakeup +right: proc.c # VERY important +even: proc.c # VERY important + +# A few more action packed spreads +# page table creation and process loading +# walkpgdir mappages setupkvm switch[ku]vm inituvm (loaduvm) +# process memory management +# allocuvm deallocuvm freevm +left: vm.c + +even: kalloc.c # mild preference + +# syscall.h either +# trapasm.S either +# traps.h either +# even: trap.c +# vectors.pl either +# syscall.c either +# sysproc.c either + +# buf.h either +# dev.h either +# fcntl.h either +# stat.h either +# file.h either +# fs.h either +# fsvar.h either +# left: ide.c # mild preference +even: ide.c +# odd: bio.c + +# log.c fits nicely in a spread +even: log.c +left: log.c + +# with fs.c starting on 2nd column of a left page, we get these 2-page spreads: +# ialloc iupdate iget idup ilock iunlock iput iunlockput +# bmap itrunc stati readi writei +# namecmp dirlookup dirlink skipelem namex namei +# fileinit filealloc filedup fileclose filestat fileread filewrite +# starting on 2nd column of a right page is not terrible either +odd: fs.c # VERY important +left: fs.c # mild preference +# file.c either +# exec.c either +# sysfile.c either + +# Mild preference, but makes spreads of mp.c, lapic.c, and ioapic.c+picirq.c +even: mp.c +left: mp.c + +# even: pipe.c # mild preference +# string.c either +# left: kbd.h # mild preference +even: kbd.h +even: console.c +odd: sh.c + +even: bootasm.S # mild preference +even: bootmain.c # mild preference diff --git a/xv6-public/runoff1 b/xv6-public/runoff1 new file mode 100644 index 0000000..532f844 --- /dev/null +++ b/xv6-public/runoff1 @@ -0,0 +1,108 @@ +#!/usr/bin/perl + +$n = 0; +$v = 0; +if($ARGV[0] eq "-v") { + $v = 1; + shift @ARGV; +} +if($ARGV[0] eq "-n") { + $n = $ARGV[1]; + shift @ARGV; + shift @ARGV; +} +$n = int(($n+49)/50)*50 - 1; + +$file = $ARGV[0]; +@lines = <>; +$linenum = 0; +foreach (@lines) { + $linenum++; + chomp; + s/\s+$//; + if(length() >= 75){ + print STDERR "$file:$linenum: line too long\n"; + } +} +@outlines = (); +$nextout = 0; + +for($i=0; $i<@lines; ){ + # Skip leading blank lines. + $i++ while $i<@lines && $lines[$i] =~ /^$/; + last if $i>=@lines; + + # If the rest of the file fits, use the whole thing. + if(@lines <= $i+50 && !grep { /PAGEBREAK/ } @lines){ + $breakbefore = @lines; + }else{ + # Find a good next page break; + # Hope for end of function. + # but settle for a blank line (but not first blank line + # in function, which comes after variable declarations). + $breakbefore = $i; + $lastblank = $i; + $sawbrace = 0; + $breaksize = 15; # 15 lines to get to function + for($j=$i; $j<$i+50 && $j < @lines; $j++){ + if($lines[$j] =~ /PAGEBREAK!/){ + $lines[$j] = ""; + $breakbefore = $j; + $breaksize = 100; + last; + } + if($lines[$j] =~ /PAGEBREAK:\s*([0-9]+)/){ + $breaksize = $1; + $breakbefore = $j; + $lines[$j] = ""; + } + if($lines[$j] =~ /^};?$/){ + $breakbefore = $j+1; + $breaksize = 15; + } + if($lines[$j] =~ /^{$/){ + $sawbrace = 1; + } + if($lines[$j] =~ /^$/){ + if($sawbrace){ + $sawbrace = 0; + }else{ + $lastblank = $j; + } + } + } + if($j<@lines && $lines[$j] =~ /^$/){ + $lastblank = $j; + } + + # If we are not putting enough on a page, try a blank line. + if($breakbefore - $i < 50 - $breaksize && $lastblank > $breakbefore && $lastblank >= $i+50 - 5){ + if($v){ + print STDERR "breakbefore $breakbefore i $i breaksize $breaksize\n"; + } + $breakbefore = $lastblank; + $breaksize = 5; # only 5 lines to get to blank line + } + + # If we are not putting enough on a page, force a full page. + if($breakbefore - $i < 50 - $breaksize && $breakbefore != @lines){ + $breakbefore = $i + 50; + $breakbefore = @lines if @lines < $breakbefore; + } + + if($breakbefore < $i+2){ + $breakbefore = $i+2; + } + } + + # Emit the page. + $i50 = $i + 50; + for(; $i<$breakbefore; $i++){ + printf "%04d %s\n", ++$n, $lines[$i]; + } + + # Finish page + for($j=$i; $j<$i50; $j++){ + printf "%04d \n", ++$n; + } +} diff --git a/xv6-public/sh.c b/xv6-public/sh.c new file mode 100644 index 0000000..054bab9 --- /dev/null +++ b/xv6-public/sh.c @@ -0,0 +1,493 @@ +// Shell. + +#include "types.h" +#include "user.h" +#include "fcntl.h" + +// Parsed command representation +#define EXEC 1 +#define REDIR 2 +#define PIPE 3 +#define LIST 4 +#define BACK 5 + +#define MAXARGS 10 + +struct cmd { + int type; +}; + +struct execcmd { + int type; + char *argv[MAXARGS]; + char *eargv[MAXARGS]; +}; + +struct redircmd { + int type; + struct cmd *cmd; + char *file; + char *efile; + int mode; + int fd; +}; + +struct pipecmd { + int type; + struct cmd *left; + struct cmd *right; +}; + +struct listcmd { + int type; + struct cmd *left; + struct cmd *right; +}; + +struct backcmd { + int type; + struct cmd *cmd; +}; + +int fork1(void); // Fork but panics on failure. +void panic(char*); +struct cmd *parsecmd(char*); + +// Execute cmd. Never returns. +void +runcmd(struct cmd *cmd) +{ + int p[2]; + struct backcmd *bcmd; + struct execcmd *ecmd; + struct listcmd *lcmd; + struct pipecmd *pcmd; + struct redircmd *rcmd; + + if(cmd == 0) + exit(); + + switch(cmd->type){ + default: + panic("runcmd"); + + case EXEC: + ecmd = (struct execcmd*)cmd; + if(ecmd->argv[0] == 0) + exit(); + exec(ecmd->argv[0], ecmd->argv); + printf(2, "exec %s failed\n", ecmd->argv[0]); + break; + + case REDIR: + rcmd = (struct redircmd*)cmd; + close(rcmd->fd); + if(open(rcmd->file, rcmd->mode) < 0){ + printf(2, "open %s failed\n", rcmd->file); + exit(); + } + runcmd(rcmd->cmd); + break; + + case LIST: + lcmd = (struct listcmd*)cmd; + if(fork1() == 0) + runcmd(lcmd->left); + wait(); + runcmd(lcmd->right); + break; + + case PIPE: + pcmd = (struct pipecmd*)cmd; + if(pipe(p) < 0) + panic("pipe"); + if(fork1() == 0){ + close(1); + dup(p[1]); + close(p[0]); + close(p[1]); + runcmd(pcmd->left); + } + if(fork1() == 0){ + close(0); + dup(p[0]); + close(p[0]); + close(p[1]); + runcmd(pcmd->right); + } + close(p[0]); + close(p[1]); + wait(); + wait(); + break; + + case BACK: + bcmd = (struct backcmd*)cmd; + if(fork1() == 0) + runcmd(bcmd->cmd); + break; + } + exit(); +} + +int +getcmd(char *buf, int nbuf) +{ + printf(2, "$ "); + memset(buf, 0, nbuf); + gets(buf, nbuf); + if(buf[0] == 0) // EOF + return -1; + return 0; +} + +int +main(void) +{ + static char buf[100]; + int fd; + + // Ensure that three file descriptors are open. + while((fd = open("console", O_RDWR)) >= 0){ + if(fd >= 3){ + close(fd); + break; + } + } + + // Read and run input commands. + while(getcmd(buf, sizeof(buf)) >= 0){ + if(buf[0] == 'c' && buf[1] == 'd' && buf[2] == ' '){ + // Chdir must be called by the parent, not the child. + buf[strlen(buf)-1] = 0; // chop \n + if(chdir(buf+3) < 0) + printf(2, "cannot cd %s\n", buf+3); + continue; + } + if(fork1() == 0) + runcmd(parsecmd(buf)); + wait(); + } + exit(); +} + +void +panic(char *s) +{ + printf(2, "%s\n", s); + exit(); +} + +int +fork1(void) +{ + int pid; + + pid = fork(); + if(pid == -1) + panic("fork"); + return pid; +} + +//PAGEBREAK! +// Constructors + +struct cmd* +execcmd(void) +{ + struct execcmd *cmd; + + cmd = malloc(sizeof(*cmd)); + memset(cmd, 0, sizeof(*cmd)); + cmd->type = EXEC; + return (struct cmd*)cmd; +} + +struct cmd* +redircmd(struct cmd *subcmd, char *file, char *efile, int mode, int fd) +{ + struct redircmd *cmd; + + cmd = malloc(sizeof(*cmd)); + memset(cmd, 0, sizeof(*cmd)); + cmd->type = REDIR; + cmd->cmd = subcmd; + cmd->file = file; + cmd->efile = efile; + cmd->mode = mode; + cmd->fd = fd; + return (struct cmd*)cmd; +} + +struct cmd* +pipecmd(struct cmd *left, struct cmd *right) +{ + struct pipecmd *cmd; + + cmd = malloc(sizeof(*cmd)); + memset(cmd, 0, sizeof(*cmd)); + cmd->type = PIPE; + cmd->left = left; + cmd->right = right; + return (struct cmd*)cmd; +} + +struct cmd* +listcmd(struct cmd *left, struct cmd *right) +{ + struct listcmd *cmd; + + cmd = malloc(sizeof(*cmd)); + memset(cmd, 0, sizeof(*cmd)); + cmd->type = LIST; + cmd->left = left; + cmd->right = right; + return (struct cmd*)cmd; +} + +struct cmd* +backcmd(struct cmd *subcmd) +{ + struct backcmd *cmd; + + cmd = malloc(sizeof(*cmd)); + memset(cmd, 0, sizeof(*cmd)); + cmd->type = BACK; + cmd->cmd = subcmd; + return (struct cmd*)cmd; +} +//PAGEBREAK! +// Parsing + +char whitespace[] = " \t\r\n\v"; +char symbols[] = "<|>&;()"; + +int +gettoken(char **ps, char *es, char **q, char **eq) +{ + char *s; + int ret; + + s = *ps; + while(s < es && strchr(whitespace, *s)) + s++; + if(q) + *q = s; + ret = *s; + switch(*s){ + case 0: + break; + case '|': + case '(': + case ')': + case ';': + case '&': + case '<': + s++; + break; + case '>': + s++; + if(*s == '>'){ + ret = '+'; + s++; + } + break; + default: + ret = 'a'; + while(s < es && !strchr(whitespace, *s) && !strchr(symbols, *s)) + s++; + break; + } + if(eq) + *eq = s; + + while(s < es && strchr(whitespace, *s)) + s++; + *ps = s; + return ret; +} + +int +peek(char **ps, char *es, char *toks) +{ + char *s; + + s = *ps; + while(s < es && strchr(whitespace, *s)) + s++; + *ps = s; + return *s && strchr(toks, *s); +} + +struct cmd *parseline(char**, char*); +struct cmd *parsepipe(char**, char*); +struct cmd *parseexec(char**, char*); +struct cmd *nulterminate(struct cmd*); + +struct cmd* +parsecmd(char *s) +{ + char *es; + struct cmd *cmd; + + es = s + strlen(s); + cmd = parseline(&s, es); + peek(&s, es, ""); + if(s != es){ + printf(2, "leftovers: %s\n", s); + panic("syntax"); + } + nulterminate(cmd); + return cmd; +} + +struct cmd* +parseline(char **ps, char *es) +{ + struct cmd *cmd; + + cmd = parsepipe(ps, es); + while(peek(ps, es, "&")){ + gettoken(ps, es, 0, 0); + cmd = backcmd(cmd); + } + if(peek(ps, es, ";")){ + gettoken(ps, es, 0, 0); + cmd = listcmd(cmd, parseline(ps, es)); + } + return cmd; +} + +struct cmd* +parsepipe(char **ps, char *es) +{ + struct cmd *cmd; + + cmd = parseexec(ps, es); + if(peek(ps, es, "|")){ + gettoken(ps, es, 0, 0); + cmd = pipecmd(cmd, parsepipe(ps, es)); + } + return cmd; +} + +struct cmd* +parseredirs(struct cmd *cmd, char **ps, char *es) +{ + int tok; + char *q, *eq; + + while(peek(ps, es, "<>")){ + tok = gettoken(ps, es, 0, 0); + if(gettoken(ps, es, &q, &eq) != 'a') + panic("missing file for redirection"); + switch(tok){ + case '<': + cmd = redircmd(cmd, q, eq, O_RDONLY, 0); + break; + case '>': + cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE, 1); + break; + case '+': // >> + cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE, 1); + break; + } + } + return cmd; +} + +struct cmd* +parseblock(char **ps, char *es) +{ + struct cmd *cmd; + + if(!peek(ps, es, "(")) + panic("parseblock"); + gettoken(ps, es, 0, 0); + cmd = parseline(ps, es); + if(!peek(ps, es, ")")) + panic("syntax - missing )"); + gettoken(ps, es, 0, 0); + cmd = parseredirs(cmd, ps, es); + return cmd; +} + +struct cmd* +parseexec(char **ps, char *es) +{ + char *q, *eq; + int tok, argc; + struct execcmd *cmd; + struct cmd *ret; + + if(peek(ps, es, "(")) + return parseblock(ps, es); + + ret = execcmd(); + cmd = (struct execcmd*)ret; + + argc = 0; + ret = parseredirs(ret, ps, es); + while(!peek(ps, es, "|)&;")){ + if((tok=gettoken(ps, es, &q, &eq)) == 0) + break; + if(tok != 'a') + panic("syntax"); + cmd->argv[argc] = q; + cmd->eargv[argc] = eq; + argc++; + if(argc >= MAXARGS) + panic("too many args"); + ret = parseredirs(ret, ps, es); + } + cmd->argv[argc] = 0; + cmd->eargv[argc] = 0; + return ret; +} + +// NUL-terminate all the counted strings. +struct cmd* +nulterminate(struct cmd *cmd) +{ + int i; + struct backcmd *bcmd; + struct execcmd *ecmd; + struct listcmd *lcmd; + struct pipecmd *pcmd; + struct redircmd *rcmd; + + if(cmd == 0) + return 0; + + switch(cmd->type){ + case EXEC: + ecmd = (struct execcmd*)cmd; + for(i=0; ecmd->argv[i]; i++) + *ecmd->eargv[i] = 0; + break; + + case REDIR: + rcmd = (struct redircmd*)cmd; + nulterminate(rcmd->cmd); + *rcmd->efile = 0; + break; + + case PIPE: + pcmd = (struct pipecmd*)cmd; + nulterminate(pcmd->left); + nulterminate(pcmd->right); + break; + + case LIST: + lcmd = (struct listcmd*)cmd; + nulterminate(lcmd->left); + nulterminate(lcmd->right); + break; + + case BACK: + bcmd = (struct backcmd*)cmd; + nulterminate(bcmd->cmd); + break; + } + return cmd; +} diff --git a/xv6-public/show1 b/xv6-public/show1 new file mode 100644 index 0000000..e0d3d83 --- /dev/null +++ b/xv6-public/show1 @@ -0,0 +1,3 @@ +#!/bin/sh + +runoff1 "$@" | pr.pl -h "xv6/$@" | mpage -m50t50b -o -bLetter -T -t -2 -FLucidaSans-Typewriter83 -L60 >x.ps; gv --swap x.ps diff --git a/xv6-public/sign.pl b/xv6-public/sign.pl new file mode 100644 index 0000000..d793035 --- /dev/null +++ b/xv6-public/sign.pl @@ -0,0 +1,19 @@ +#!/usr/bin/perl + +open(SIG, $ARGV[0]) || die "open $ARGV[0]: $!"; + +$n = sysread(SIG, $buf, 1000); + +if($n > 510){ + print STDERR "boot block too large: $n bytes (max 510)\n"; + exit 1; +} + +print STDERR "boot block is $n bytes (max 510)\n"; + +$buf .= "\0" x (510-$n); +$buf .= "\x55\xAA"; + +open(SIG, ">$ARGV[0]") || die "open >$ARGV[0]: $!"; +print SIG $buf; +close SIG; diff --git a/xv6-public/sleep1.p b/xv6-public/sleep1.p new file mode 100644 index 0000000..af69772 --- /dev/null +++ b/xv6-public/sleep1.p @@ -0,0 +1,134 @@ +/* +This file defines a Promela model for xv6's +acquire, release, sleep, and wakeup, along with +a model of a simple producer/consumer queue. + +To run: + spinp sleep1.p + +(You may need to install Spin, available at http://spinroot.com/.) + +After a successful run spin prints something like: + + unreached in proctype consumer + (0 of 37 states) + unreached in proctype producer + (0 of 23 states) + +After an unsuccessful run, the spinp script prints +an execution trace that causes a deadlock. + +The safe body of producer reads: + + acquire(lk); + x = value; value = x + 1; x = 0; + wakeup(0); + release(lk); + i = i + 1; + +If this is changed to: + + x = value; value = x + 1; x = 0; + acquire(lk); + wakeup(0); + release(lk); + i = i + 1; + +then a deadlock can happen, because the non-atomic +increment of value conflicts with the non-atomic +decrement in consumer, causing value to have a bad value. +Try this. + +If it is changed to: + + acquire(lk); + x = value; value = x + 1; x = 0; + release(lk); + wakeup(0); + i = i + 1; + +then nothing bad happens: it is okay to wakeup after release +instead of before, although it seems morally wrong. +*/ + +#define ITER 4 +#define N 2 + +bit lk; +byte value; +bit sleeping[N]; + +inline acquire(x) +{ + atomic { x == 0; x = 1 } +} + +inline release(x) +{ + assert x==1; + x = 0 +} + +inline sleep(cond, lk) +{ + assert !sleeping[_pid]; + if + :: cond -> + skip + :: else -> + atomic { release(lk); sleeping[_pid] = 1 }; + sleeping[_pid] == 0; + acquire(lk) + fi +} + +inline wakeup() +{ + w = 0; + do + :: w < N -> + sleeping[w] = 0; + w = w + 1 + :: else -> + break + od +} + +active[N] proctype consumer() +{ + byte i, x; + + i = 0; + do + :: i < ITER -> + acquire(lk); + sleep(value > 0, lk); + x = value; value = x - 1; x = 0; + release(lk); + i = i + 1; + :: else -> + break + od; + i = 0; + skip +} + +active[N] proctype producer() +{ + byte i, x, w; + + i = 0; + do + :: i < ITER -> + acquire(lk); + x = value; value = x + 1; x = 0; + release(lk); + wakeup(); + i = i + 1; + :: else -> + break + od; + i = 0; + skip +} + diff --git a/xv6-public/sleeplock.c b/xv6-public/sleeplock.c new file mode 100644 index 0000000..e0750ea --- /dev/null +++ b/xv6-public/sleeplock.c @@ -0,0 +1,56 @@ +// Sleeping locks + +#include "types.h" +#include "defs.h" +#include "param.h" +#include "x86.h" +#include "memlayout.h" +#include "mmu.h" +#include "proc.h" +#include "spinlock.h" +#include "sleeplock.h" + +void +initsleeplock(struct sleeplock *lk, char *name) +{ + initlock(&lk->lk, "sleep lock"); + lk->name = name; + lk->locked = 0; + lk->pid = 0; +} + +void +acquiresleep(struct sleeplock *lk) +{ + acquire(&lk->lk); + while (lk->locked) { + sleep(lk, &lk->lk); + } + lk->locked = 1; + lk->pid = myproc()->pid; + release(&lk->lk); +} + +void +releasesleep(struct sleeplock *lk) +{ + acquire(&lk->lk); + lk->locked = 0; + lk->pid = 0; + wakeup(lk); + release(&lk->lk); +} + +int +holdingsleep(struct sleeplock *lk) +{ + int r; + + acquire(&lk->lk); + r = lk->locked && (lk->pid == myproc()->pid); + release(&lk->lk); + return r; +} + + + diff --git a/xv6-public/sleeplock.h b/xv6-public/sleeplock.h new file mode 100644 index 0000000..110e6f3 --- /dev/null +++ b/xv6-public/sleeplock.h @@ -0,0 +1,10 @@ +// Long-term locks for processes +struct sleeplock { + uint locked; // Is the lock held? + struct spinlock lk; // spinlock protecting this sleep lock + + // For debugging: + char *name; // Name of lock. + int pid; // Process holding lock +}; + diff --git a/xv6-public/spinlock.c b/xv6-public/spinlock.c new file mode 100644 index 0000000..4020186 --- /dev/null +++ b/xv6-public/spinlock.c @@ -0,0 +1,126 @@ +// Mutual exclusion spin locks. + +#include "types.h" +#include "defs.h" +#include "param.h" +#include "x86.h" +#include "memlayout.h" +#include "mmu.h" +#include "proc.h" +#include "spinlock.h" + +void +initlock(struct spinlock *lk, char *name) +{ + lk->name = name; + lk->locked = 0; + lk->cpu = 0; +} + +// Acquire the lock. +// Loops (spins) until the lock is acquired. +// Holding a lock for a long time may cause +// other CPUs to waste time spinning to acquire it. +void +acquire(struct spinlock *lk) +{ + pushcli(); // disable interrupts to avoid deadlock. + if(holding(lk)) + panic("acquire"); + + // The xchg is atomic. + while(xchg(&lk->locked, 1) != 0) + ; + + // Tell the C compiler and the processor to not move loads or stores + // past this point, to ensure that the critical section's memory + // references happen after the lock is acquired. + __sync_synchronize(); + + // Record info about lock acquisition for debugging. + lk->cpu = mycpu(); + getcallerpcs(&lk, lk->pcs); +} + +// Release the lock. +void +release(struct spinlock *lk) +{ + if(!holding(lk)) + panic("release"); + + lk->pcs[0] = 0; + lk->cpu = 0; + + // Tell the C compiler and the processor to not move loads or stores + // past this point, to ensure that all the stores in the critical + // section are visible to other cores before the lock is released. + // Both the C compiler and the hardware may re-order loads and + // stores; __sync_synchronize() tells them both not to. + __sync_synchronize(); + + // Release the lock, equivalent to lk->locked = 0. + // This code can't use a C assignment, since it might + // not be atomic. A real OS would use C atomics here. + asm volatile("movl $0, %0" : "+m" (lk->locked) : ); + + popcli(); +} + +// Record the current call stack in pcs[] by following the %ebp chain. +void +getcallerpcs(void *v, uint pcs[]) +{ + uint *ebp; + int i; + + ebp = (uint*)v - 2; + for(i = 0; i < 10; i++){ + if(ebp == 0 || ebp < (uint*)KERNBASE || ebp == (uint*)0xffffffff) + break; + pcs[i] = ebp[1]; // saved %eip + ebp = (uint*)ebp[0]; // saved %ebp + } + for(; i < 10; i++) + pcs[i] = 0; +} + +// Check whether this cpu is holding the lock. +int +holding(struct spinlock *lock) +{ + int r; + pushcli(); + r = lock->locked && lock->cpu == mycpu(); + popcli(); + return r; +} + + +// Pushcli/popcli are like cli/sti except that they are matched: +// it takes two popcli to undo two pushcli. Also, if interrupts +// are off, then pushcli, popcli leaves them off. + +void +pushcli(void) +{ + int eflags; + + eflags = readeflags(); + cli(); + if(mycpu()->ncli == 0) + mycpu()->intena = eflags & FL_IF; + mycpu()->ncli += 1; +} + +void +popcli(void) +{ + if(readeflags()&FL_IF) + panic("popcli - interruptible"); + if(--mycpu()->ncli < 0) + panic("popcli"); + if(mycpu()->ncli == 0 && mycpu()->intena) + sti(); +} + diff --git a/xv6-public/spinlock.h b/xv6-public/spinlock.h new file mode 100644 index 0000000..0a9d8e2 --- /dev/null +++ b/xv6-public/spinlock.h @@ -0,0 +1,11 @@ +// Mutual exclusion lock. +struct spinlock { + uint locked; // Is the lock held? + + // For debugging: + char *name; // Name of lock. + struct cpu *cpu; // The cpu holding the lock. + uint pcs[10]; // The call stack (an array of program counters) + // that locked the lock. +}; + diff --git a/xv6-public/spinp b/xv6-public/spinp new file mode 100644 index 0000000..db9614b --- /dev/null +++ b/xv6-public/spinp @@ -0,0 +1,16 @@ +#!/bin/sh + +if [ $# != 1 ] || [ ! -f "$1" ]; then + echo 'usage: spinp file.p' 1>&2 + exit 1 +fi + +rm -f $1.trail +spin -a $1 || exit 1 +cc -DSAFETY -DREACH -DMEMLIM=500 -o pan pan.c +pan -i +rm pan.* pan +if [ -f $1.trail ]; then + spin -t -p $1 +fi + diff --git a/xv6-public/stat.h b/xv6-public/stat.h new file mode 100644 index 0000000..8a80933 --- /dev/null +++ b/xv6-public/stat.h @@ -0,0 +1,11 @@ +#define T_DIR 1 // Directory +#define T_FILE 2 // File +#define T_DEV 3 // Device + +struct stat { + short type; // Type of file + int dev; // File system's disk device + uint ino; // Inode number + short nlink; // Number of links to file + uint size; // Size of file in bytes +}; diff --git a/xv6-public/stressfs.c b/xv6-public/stressfs.c new file mode 100644 index 0000000..c0a4743 --- /dev/null +++ b/xv6-public/stressfs.c @@ -0,0 +1,49 @@ +// Demonstrate that moving the "acquire" in iderw after the loop that +// appends to the idequeue results in a race. + +// For this to work, you should also add a spin within iderw's +// idequeue traversal loop. Adding the following demonstrated a panic +// after about 5 runs of stressfs in QEMU on a 2.1GHz CPU: +// for (i = 0; i < 40000; i++) +// asm volatile(""); + +#include "types.h" +#include "stat.h" +#include "user.h" +#include "fs.h" +#include "fcntl.h" + +int +main(int argc, char *argv[]) +{ + int fd, i; + char path[] = "stressfs0"; + char data[512]; + + printf(1, "stressfs starting\n"); + memset(data, 'a', sizeof(data)); + + for(i = 0; i < 4; i++) + if(fork() > 0) + break; + + printf(1, "write %d\n", i); + + path[8] += i; + fd = open(path, O_CREATE | O_RDWR); + for(i = 0; i < 20; i++) +// printf(fd, "%d\n", i); + write(fd, data, sizeof(data)); + close(fd); + + printf(1, "read\n"); + + fd = open(path, O_RDONLY); + for (i = 0; i < 20; i++) + read(fd, data, sizeof(data)); + close(fd); + + wait(); + + exit(); +} diff --git a/xv6-public/string.c b/xv6-public/string.c new file mode 100644 index 0000000..a7cc61f --- /dev/null +++ b/xv6-public/string.c @@ -0,0 +1,105 @@ +#include "types.h" +#include "x86.h" + +void* +memset(void *dst, int c, uint n) +{ + if ((int)dst%4 == 0 && n%4 == 0){ + c &= 0xFF; + stosl(dst, (c<<24)|(c<<16)|(c<<8)|c, n/4); + } else + stosb(dst, c, n); + return dst; +} + +int +memcmp(const void *v1, const void *v2, uint n) +{ + const uchar *s1, *s2; + + s1 = v1; + s2 = v2; + while(n-- > 0){ + if(*s1 != *s2) + return *s1 - *s2; + s1++, s2++; + } + + return 0; +} + +void* +memmove(void *dst, const void *src, uint n) +{ + const char *s; + char *d; + + s = src; + d = dst; + if(s < d && s + n > d){ + s += n; + d += n; + while(n-- > 0) + *--d = *--s; + } else + while(n-- > 0) + *d++ = *s++; + + return dst; +} + +// memcpy exists to placate GCC. Use memmove. +void* +memcpy(void *dst, const void *src, uint n) +{ + return memmove(dst, src, n); +} + +int +strncmp(const char *p, const char *q, uint n) +{ + while(n > 0 && *p && *p == *q) + n--, p++, q++; + if(n == 0) + return 0; + return (uchar)*p - (uchar)*q; +} + +char* +strncpy(char *s, const char *t, int n) +{ + char *os; + + os = s; + while(n-- > 0 && (*s++ = *t++) != 0) + ; + while(n-- > 0) + *s++ = 0; + return os; +} + +// Like strncpy but guaranteed to NUL-terminate. +char* +safestrcpy(char *s, const char *t, int n) +{ + char *os; + + os = s; + if(n <= 0) + return os; + while(--n > 0 && (*s++ = *t++) != 0) + ; + *s = 0; + return os; +} + +int +strlen(const char *s) +{ + int n; + + for(n = 0; s[n]; n++) + ; + return n; +} + diff --git a/xv6-public/swtch.S b/xv6-public/swtch.S new file mode 100644 index 0000000..63a7dcc --- /dev/null +++ b/xv6-public/swtch.S @@ -0,0 +1,29 @@ +# Context switch +# +# void swtch(struct context **old, struct context *new); +# +# Save the current registers on the stack, creating +# a struct context, and save its address in *old. +# Switch stacks to new and pop previously-saved registers. + +.globl swtch +swtch: + movl 4(%esp), %eax + movl 8(%esp), %edx + + # Save old callee-saved registers + pushl %ebp + pushl %ebx + pushl %esi + pushl %edi + + # Switch stacks + movl %esp, (%eax) + movl %edx, %esp + + # Load new callee-saved registers + popl %edi + popl %esi + popl %ebx + popl %ebp + ret diff --git a/xv6-public/syscall.c b/xv6-public/syscall.c new file mode 100644 index 0000000..9a3be57 --- /dev/null +++ b/xv6-public/syscall.c @@ -0,0 +1,186 @@ +#include "types.h" +#include "defs.h" +#include "param.h" +#include "memlayout.h" +#include "mmu.h" +#include "proc.h" +#include "x86.h" +#include "syscall.h" + +// User code makes a system call with INT T_SYSCALL. +// System call number in %eax. +// Arguments on the stack, from the user call to the C +// library system call function. The saved user %esp points +// to a saved program counter, and then the first argument. + +// Fetch the int at addr from the current process. +int +fetchint(uint addr, int *ip) +{ + struct proc *curproc = myproc(); + + if(addr >= curproc->sz || addr+4 > curproc->sz) + return -1; + *ip = *(int*)(addr); + return 0; +} + +// Fetch the nul-terminated string at addr from the current process. +// Doesn't actually copy the string - just sets *pp to point at it. +// Returns length of string, not including nul. +int +fetchstr(uint addr, char **pp) +{ + char *s, *ep; + struct proc *curproc = myproc(); + + if(addr >= curproc->sz) + return -1; + *pp = (char*)addr; + ep = (char*)curproc->sz; + for(s = *pp; s < ep; s++){ + if(*s == 0) + return s - *pp; + } + return -1; +} + +// Fetch the nth 32-bit system call argument. +int +argint(int n, int *ip) +{ + return fetchint((myproc()->tf->esp) + 4 + 4*n, ip); +} + +// Fetch the nth word-sized system call argument as a pointer +// to a block of memory of size bytes. Check that the pointer +// lies within the process address space. +int +argptr(int n, char **pp, int size) +{ + int i; + struct proc *curproc = myproc(); + + if(argint(n, &i) < 0) + return -1; + if(size < 0 || (uint)i >= curproc->sz || (uint)i+size > curproc->sz) + return -1; + *pp = (char*)i; + return 0; +} + +// Fetch the nth word-sized system call argument as a string pointer. +// Check that the pointer is valid and the string is nul-terminated. +// (There is no shared writable memory, so the string can't change +// between this check and being used by the kernel.) +int +argstr(int n, char **pp) +{ + int addr; + if(argint(n, &addr) < 0) + return -1; + return fetchstr(addr, pp); +} + +extern int sys_chdir(void); +extern int sys_close(void); +extern int sys_dup(void); +extern int sys_dup2(void); + +extern int sys_exec(void); +extern int sys_exit(void); +extern int sys_fork(void); +extern int sys_fstat(void); +extern int sys_getpid(void); +extern int sys_kill(void); +extern int sys_link(void); +extern int sys_mkdir(void); +extern int sys_mknod(void); +extern int sys_open(void); +extern int sys_pipe(void); +extern int sys_read(void); +extern int sys_sbrk(void); +extern int sys_sleep(void); +extern int sys_unlink(void); +extern int sys_wait(void); +extern int sys_write(void); +extern int sys_uptime(void); +extern int sys_date(void); +extern int sys_alarm(void); + +// 函数指针数组 +// 初始化中写 [] 是指syscalls[SYS_fork=1] = sys_fork +static int (*syscalls[])(void) = { +[SYS_fork] sys_fork, +[SYS_exit] sys_exit, +[SYS_wait] sys_wait, +[SYS_pipe] sys_pipe, +[SYS_read] sys_read, +[SYS_kill] sys_kill, +[SYS_exec] sys_exec, +[SYS_fstat] sys_fstat, +[SYS_chdir] sys_chdir, +[SYS_dup] sys_dup, +[SYS_dup2] sys_dup2, +[SYS_getpid] sys_getpid, +[SYS_sbrk] sys_sbrk, +[SYS_sleep] sys_sleep, +[SYS_uptime] sys_uptime, +[SYS_open] sys_open, +[SYS_write] sys_write, +[SYS_mknod] sys_mknod, +[SYS_unlink] sys_unlink, +[SYS_link] sys_link, +[SYS_mkdir] sys_mkdir, +[SYS_close] sys_close, +[SYS_date] sys_date, +[SYS_alarm] sys_alarm, + +}; +/* +static char *syscall_name[] = { +[SYS_fork] "fork", +[SYS_exit] "exit", +[SYS_wait] "wait", +[SYS_pipe] "pipe", +[SYS_read] "read", +[SYS_kill] "kill", +[SYS_exec] "exec", +[SYS_fstat] "fstat", +[SYS_chdir] "chdir", +[SYS_dup] "dup", +[SYS_getpid] "getpid", +[SYS_sbrk] "sbrk", +[SYS_sleep] "sleep", +[SYS_uptime] "uptime", +[SYS_open] "open", +[SYS_write] "write", +[SYS_mknod] "mknod", +[SYS_unlink] "unlink", +[SYS_link] "link", +[SYS_mkdir] "mkdir", +[SYS_close] "close", +[SYS_date] "date", +[SYS_alarm] "alarm", + +}; +*/ + +void +syscall(void) +{ + int num; + // 关中断读取进程信息 + struct proc *curproc = myproc(); + //num 取值应该[1-最大的系统调用序号] + num = curproc->tf->eax; + // 检查系统调用是否存在 + if(num > 0 && num < NELEM(syscalls) && syscalls[num]) { + curproc->tf->eax = syscalls[num](); //存储系统调用返回值 + // cprintf("%s: -> %d\n",syscall_name[num], curproc->tf->eax); + } else { + cprintf("%d %s: unknown sys call %d\n", + curproc->pid, curproc->name, num); + curproc->tf->eax = -1; + } +} diff --git a/xv6-public/syscall.h b/xv6-public/syscall.h new file mode 100644 index 0000000..1f608b0 --- /dev/null +++ b/xv6-public/syscall.h @@ -0,0 +1,25 @@ +// System call numbers +#define SYS_fork 1 +#define SYS_exit 2 +#define SYS_wait 3 +#define SYS_pipe 4 +#define SYS_read 5 +#define SYS_kill 6 +#define SYS_exec 7 +#define SYS_fstat 8 +#define SYS_chdir 9 +#define SYS_dup 10 +#define SYS_getpid 11 +#define SYS_sbrk 12 +#define SYS_sleep 13 +#define SYS_uptime 14 +#define SYS_open 15 +#define SYS_write 16 +#define SYS_mknod 17 +#define SYS_unlink 18 +#define SYS_link 19 +#define SYS_mkdir 20 +#define SYS_close 21 +#define SYS_date 22 +#define SYS_dup2 23 +#define SYS_alarm 24 diff --git a/xv6-public/sysfile.c b/xv6-public/sysfile.c new file mode 100644 index 0000000..eb240bd --- /dev/null +++ b/xv6-public/sysfile.c @@ -0,0 +1,469 @@ +// +// File-system system calls. +// Mostly argument checking, since we don't trust +// user code, and calls into file.c and fs.c. +// + +#include "types.h" +#include "defs.h" +#include "param.h" +#include "stat.h" +#include "mmu.h" +#include "proc.h" +#include "fs.h" +#include "spinlock.h" +#include "sleeplock.h" +#include "file.h" +#include "fcntl.h" +#include "date.h" + +// Fetch the nth word-sized system call argument as a file descriptor +// and return both the descriptor and the corresponding struct file. +static int +argfd(int n, int *pfd, struct file **pf) +{ + int fd; + struct file *f; + + if(argint(n, &fd) < 0) + return -1; + if(fd < 0 || fd >= NOFILE || (f=myproc()->ofile[fd]) == 0) + return -1; + if(pfd) + *pfd = fd; + if(pf) + *pf = f; + return 0; +} + +// Allocate a file descriptor for the given file. +// Takes over file reference from caller on success. +static int +fdalloc(struct file *f) +{ + int fd; + struct proc *curproc = myproc(); + + for(fd = 0; fd < NOFILE; fd++){ + if(curproc->ofile[fd] == 0){ + curproc->ofile[fd] = f; + return fd; + } + } + return -1; +} + +int +sys_dup(void) +{ + struct file *f; + int fd; + + if(argfd(0, 0, &f) < 0) + return -1; + if((fd=fdalloc(f)) < 0) + return -1; + filedup(f); + return fd; +} + +int +sys_dup2(void) +{ + int old_fd,new_fd; + struct file *f1, *f2; + if(argfd(0, &old_fd, &f1) < 0 || argint(1, &new_fd) < 0) + return -1; + if(new_fd < 0 || new_fd >= NOFILE) + return -1; + if(new_fd != old_fd) { + f2 = myproc()->ofile[new_fd]; + if(f2) { + // 检查该文件描述符是否在使用中 + fileclose(f2); + } + myproc()->ofile[new_fd] = f1; + // 增加文件f1的引用计数 + filedup(f1); + } + return new_fd; +} +int +sys_read(void) +{ + struct file *f; + int n; + char *p; + + if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0) + return -1; + return fileread(f, p, n); +} + +int +sys_write(void) +{ + struct file *f; + int n; + char *p; + + if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0) + return -1; + return filewrite(f, p, n); +} + +int +sys_close(void) +{ + int fd; + struct file *f; + + if(argfd(0, &fd, &f) < 0) + return -1; + myproc()->ofile[fd] = 0; + fileclose(f); + return 0; +} + +int +sys_fstat(void) +{ + struct file *f; + struct stat *st; + + if(argfd(0, 0, &f) < 0 || argptr(1, (void*)&st, sizeof(*st)) < 0) + return -1; + return filestat(f, st); +} + +// Create the path new as a link to the same inode as old. +int +sys_link(void) +{ + char name[DIRSIZ], *new, *old; + struct inode *dp, *ip; + + if(argstr(0, &old) < 0 || argstr(1, &new) < 0) + return -1; + + begin_op(); + if((ip = namei(old)) == 0){ + end_op(); + return -1; + } + + ilock(ip); + if(ip->type == T_DIR){ + iunlockput(ip); + end_op(); + return -1; + } + + ip->nlink++; + iupdate(ip); + iunlock(ip); + + if((dp = nameiparent(new, name)) == 0) + goto bad; + ilock(dp); + if(dp->dev != ip->dev || dirlink(dp, name, ip->inum) < 0){ + iunlockput(dp); + goto bad; + } + iunlockput(dp); + iput(ip); + + end_op(); + + return 0; + +bad: + ilock(ip); + ip->nlink--; + iupdate(ip); + iunlockput(ip); + end_op(); + return -1; +} + +// Is the directory dp empty except for "." and ".." ? +static int +isdirempty(struct inode *dp) +{ + int off; + struct dirent de; + + for(off=2*sizeof(de); offsize; off+=sizeof(de)){ + if(readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) + panic("isdirempty: readi"); + if(de.inum != 0) + return 0; + } + return 1; +} + +//PAGEBREAK! +int +sys_unlink(void) +{ + struct inode *ip, *dp; + struct dirent de; + char name[DIRSIZ], *path; + uint off; + + if(argstr(0, &path) < 0) + return -1; + + begin_op(); + if((dp = nameiparent(path, name)) == 0){ + end_op(); + return -1; + } + + ilock(dp); + + // Cannot unlink "." or "..". + if(namecmp(name, ".") == 0 || namecmp(name, "..") == 0) + goto bad; + + if((ip = dirlookup(dp, name, &off)) == 0) + goto bad; + ilock(ip); + + if(ip->nlink < 1) + panic("unlink: nlink < 1"); + if(ip->type == T_DIR && !isdirempty(ip)){ + iunlockput(ip); + goto bad; + } + + memset(&de, 0, sizeof(de)); + if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) + panic("unlink: writei"); + if(ip->type == T_DIR){ + dp->nlink--; + iupdate(dp); + } + iunlockput(dp); + + ip->nlink--; + iupdate(ip); + iunlockput(ip); + + end_op(); + + return 0; + +bad: + iunlockput(dp); + end_op(); + return -1; +} + +static struct inode* +create(char *path, short type, short major, short minor) +{ + uint off; + struct inode *ip, *dp; + char name[DIRSIZ]; + + if((dp = nameiparent(path, name)) == 0) + return 0; + ilock(dp); + + if((ip = dirlookup(dp, name, &off)) != 0){ + iunlockput(dp); + ilock(ip); + if(type == T_FILE && ip->type == T_FILE) + return ip; + iunlockput(ip); + return 0; + } + + if((ip = ialloc(dp->dev, type)) == 0) + panic("create: ialloc"); + + ilock(ip); + ip->major = major; + ip->minor = minor; + ip->nlink = 1; + iupdate(ip); + + if(type == T_DIR){ // Create . and .. entries. + dp->nlink++; // for ".." + iupdate(dp); + // No ip->nlink++ for ".": avoid cyclic ref count. + if(dirlink(ip, ".", ip->inum) < 0 || dirlink(ip, "..", dp->inum) < 0) + panic("create dots"); + } + + if(dirlink(dp, name, ip->inum) < 0) + panic("create: dirlink"); + + iunlockput(dp); + + return ip; +} + +int +sys_open(void) +{ + char *path; + int fd, omode; + struct file *f; + struct inode *ip; + + if(argstr(0, &path) < 0 || argint(1, &omode) < 0) + return -1; + + begin_op(); + + if(omode & O_CREATE){ + ip = create(path, T_FILE, 0, 0); + if(ip == 0){ + end_op(); + return -1; + } + } else { + if((ip = namei(path)) == 0){ + end_op(); + return -1; + } + ilock(ip); + if(ip->type == T_DIR && omode != O_RDONLY){ + iunlockput(ip); + end_op(); + return -1; + } + } + + if((f = filealloc()) == 0 || (fd = fdalloc(f)) < 0){ + if(f) + fileclose(f); + iunlockput(ip); + end_op(); + return -1; + } + iunlock(ip); + end_op(); + + f->type = FD_INODE; + f->ip = ip; + f->off = 0; + f->readable = !(omode & O_WRONLY); + f->writable = (omode & O_WRONLY) || (omode & O_RDWR); + return fd; +} + +int +sys_mkdir(void) +{ + char *path; + struct inode *ip; + + begin_op(); + if(argstr(0, &path) < 0 || (ip = create(path, T_DIR, 0, 0)) == 0){ + end_op(); + return -1; + } + iunlockput(ip); + end_op(); + return 0; +} + +int +sys_mknod(void) +{ + struct inode *ip; + char *path; + int major, minor; + + begin_op(); + if((argstr(0, &path)) < 0 || + argint(1, &major) < 0 || + argint(2, &minor) < 0 || + (ip = create(path, T_DEV, major, minor)) == 0){ + end_op(); + return -1; + } + iunlockput(ip); + end_op(); + return 0; +} + +int +sys_chdir(void) +{ + char *path; + struct inode *ip; + struct proc *curproc = myproc(); + + begin_op(); + if(argstr(0, &path) < 0 || (ip = namei(path)) == 0){ + end_op(); + return -1; + } + ilock(ip); + if(ip->type != T_DIR){ + iunlockput(ip); + end_op(); + return -1; + } + iunlock(ip); + iput(curproc->cwd); + end_op(); + curproc->cwd = ip; + return 0; +} + +int +sys_exec(void) +{ + char *path, *argv[MAXARG]; + int i; + uint uargv, uarg; + + if(argstr(0, &path) < 0 || argint(1, (int*)&uargv) < 0){ + return -1; + } + memset(argv, 0, sizeof(argv)); + for(i=0;; i++){ + if(i >= NELEM(argv)) + return -1; + if(fetchint(uargv+4*i, (int*)&uarg) < 0) + return -1; + if(uarg == 0){ + argv[i] = 0; + break; + } + if(fetchstr(uarg, &argv[i]) < 0) + return -1; + } + return exec(path, argv); +} + +int +sys_pipe(void) +{ + int *fd; + struct file *rf, *wf; + int fd0, fd1; + + if(argptr(0, (void*)&fd, 2*sizeof(fd[0])) < 0) + return -1; + if(pipealloc(&rf, &wf) < 0) + return -1; + fd0 = -1; + if((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0){ + if(fd0 >= 0) + myproc()->ofile[fd0] = 0; + fileclose(rf); + fileclose(wf); + return -1; + } + fd[0] = fd0; + fd[1] = fd1; + return 0; +} + + diff --git a/xv6-public/sysproc.c b/xv6-public/sysproc.c new file mode 100644 index 0000000..7e62d34 --- /dev/null +++ b/xv6-public/sysproc.c @@ -0,0 +1,121 @@ +#include "types.h" +#include "x86.h" +#include "defs.h" +#include "date.h" +#include "param.h" +#include "memlayout.h" +#include "mmu.h" +#include "proc.h" + +int +sys_fork(void) +{ + return fork(); +} + +int +sys_exit(void) +{ + exit(); + return 0; // not reached +} + +int +sys_wait(void) +{ + return wait(); +} + +int +sys_kill(void) +{ + int pid; + + if(argint(0, &pid) < 0) + return -1; + return kill(pid); +} + +int +sys_getpid(void) +{ + return myproc()->pid; +} + +int +sys_sbrk(void) +{ + int addr; + int n; + + if(argint(0, &n) < 0) + return -1; + addr = myproc()->sz; + myproc()->sz += n; + return addr; +} + +int +sys_sleep(void) +{ + int n; + uint ticks0; + + if(argint(0, &n) < 0) + return -1; + acquire(&tickslock); + ticks0 = ticks; + while(ticks - ticks0 < n){ + if(myproc()->killed){ + release(&tickslock); + return -1; + } + sleep(&ticks, &tickslock); + } + release(&tickslock); + return 0; +} + +// return how many clock tick interrupts have occurred +// since start. +int +sys_uptime(void) +{ + uint xticks; + + acquire(&tickslock); + xticks = ticks; + release(&tickslock); + return xticks; +} + +int +sys_date(void) +{ + struct rtcdate *r; + if(argptr(0, (void*)&r, sizeof(struct rtcdate)) < 0) + return -1; + cmostime(r); + return 0; +} + +int +sys_alarm(void) +{ + // 间隔 + int interval; + // 函数指针 + void (*handler)(void); + + if(argint(0, &interval) < 0) + return -1; + if(argptr(1, (char **)&handler, 1) < 0) + return -1; + + myproc()->alarminterval = interval; + myproc()->alarmhandler = handler; + return 0; + +} + + diff --git a/xv6-public/toc.ftr b/xv6-public/toc.ftr new file mode 100644 index 0000000..0061c1d --- /dev/null +++ b/xv6-public/toc.ftr @@ -0,0 +1,13 @@ + + +The source listing is preceded by a cross-reference that lists every defined +constant, struct, global variable, and function in xv6. Each entry gives, +on the same line as the name, the line number (or, in a few cases, numbers) +where the name is defined. Successive lines in an entry list the line +numbers where the name is used. For example, this entry: + + swtch 2658 + 0374 2428 2466 2657 2658 + +indicates that swtch is defined on line 2658 and is mentioned on five lines +on sheets 03, 24, and 26. diff --git a/xv6-public/toc.hdr b/xv6-public/toc.hdr new file mode 100644 index 0000000..3698d81 --- /dev/null +++ b/xv6-public/toc.hdr @@ -0,0 +1,6 @@ +The numbers to the left of the file names in the table are sheet numbers. +The source code has been printed in a double column format with fifty +lines per column, giving one hundred lines per sheet (or page). +Thus there is a convenient relationship between line numbers and sheet numbers. + + diff --git a/xv6-public/trap.c b/xv6-public/trap.c new file mode 100644 index 0000000..273ce11 --- /dev/null +++ b/xv6-public/trap.c @@ -0,0 +1,148 @@ +#include "types.h" +#include "defs.h" +#include "param.h" +#include "memlayout.h" +#include "mmu.h" +#include "proc.h" +#include "x86.h" +#include "traps.h" +#include "spinlock.h" + +// Interrupt descriptor table (shared by all CPUs). +struct gatedesc idt[256]; +extern uint vectors[]; // in vectors.S: array of 256 entry pointers +struct spinlock tickslock; +uint ticks; + +void +tvinit(void) +{ + int i; + + for(i = 0; i < 256; i++) + SETGATE(idt[i], 0, SEG_KCODE<<3, vectors[i], 0); + SETGATE(idt[T_SYSCALL], 1, SEG_KCODE<<3, vectors[T_SYSCALL], DPL_USER); + + initlock(&tickslock, "time"); +} + +void +idtinit(void) +{ + lidt(idt, sizeof(idt)); +} + + + + +//PAGEBREAK: 41 +void +trap(struct trapframe *tf) +{ + if(tf->trapno == T_SYSCALL){ + if(myproc()->killed) + exit(); + myproc()->tf = tf; + syscall(); + if(myproc()->killed) + exit(); + return; + } + char *mem; + switch(tf->trapno){ + case T_IRQ0 + IRQ_TIMER: + if(cpuid() == 0){ + acquire(&tickslock); + ticks++; + + wakeup(&ticks); + release(&tickslock); + } + if(myproc() != 0 && (tf->cs & 3) == 3){ + myproc()->ticks++; + // 没有alarm任务的proc, 不会进入以下if,因为alarminterval为0 + if(myproc()->ticks == myproc()->alarminterval) { + myproc()->ticks = 0; + // 为什么不能像下面这样调用函数 + //myproc()->alarmhandler(); + tf->esp -= 4; + // eip压栈 + *(uint *)(tf->esp) = tf->eip; + tf->eip = (uint)myproc()->alarmhandler; + } + } + + lapiceoi(); + break; + case T_IRQ0 + IRQ_IDE: + ideintr(); + lapiceoi(); + break; + case T_IRQ0 + IRQ_IDE+1: + // Bochs generates spurious IDE1 interrupts. + break; + case T_IRQ0 + IRQ_KBD: + kbdintr(); + lapiceoi(); + break; + case T_IRQ0 + IRQ_COM1: + uartintr(); + lapiceoi(); + break; + case T_IRQ0 + 7: + case T_IRQ0 + IRQ_SPURIOUS: + cprintf("cpu%d: spurious interrupt at %x:%x\n", + cpuid(), tf->cs, tf->eip); + lapiceoi(); + break; + + // T_PGFLT = 14 + case T_PGFLT: + // kallo或mappages执行失败,则继续执行下面的default. + // In user space, assume process misbehaved. + // cr2包含发生页面错误时的线性地址. + mem = kalloc(); + if(mem != 0){ + uint va = PGROUNDDOWN(rcr2()); + memset(mem, 0, PGSIZE); + extern int mappages(pde_t *pgdir, void *va, uint size, uint pa, int perm); + if(mappages(myproc()->pgdir,(void *)va, PGSIZE, V2P(mem), PTE_W|PTE_U) >= 0) { + // 全部执行成功才break; + break; + } + } + + //PAGEBREAK: 13 + default: + // tf->cs&3 不明白 + if(myproc() == 0 || (tf->cs&3) == 0){ + // In kernel, it must be our mistake. + cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n", + tf->trapno, cpuid(), tf->eip, rcr2()); + panic("trap"); + } + // In user space, assume process misbehaved. + + cprintf("pid %d %s: trap %d err %d on cpu %d " + "eip 0x%x addr 0x%x--kill proc\n", + myproc()->pid, myproc()->name, tf->trapno, + tf->err, cpuid(), tf->eip, rcr2()); + myproc()->killed = 1; + } + + // Force process exit if it has been killed and is in user space. + // (If it is still executing in the kernel, let it keep running + // until it gets to the regular system call return.) + if(myproc() && myproc()->killed && (tf->cs&3) == DPL_USER) + exit(); + + // Force process to give up CPU on clock tick. + // If interrupts were on while locks held, would need to check nlock. + if(myproc() && myproc()->state == RUNNING && + tf->trapno == T_IRQ0+IRQ_TIMER) + yield(); + + // Check if the process has been killed since we yielded + if(myproc() && myproc()->killed && (tf->cs&3) == DPL_USER) + exit(); +} diff --git a/xv6-public/trapasm.S b/xv6-public/trapasm.S new file mode 100644 index 0000000..da8aefc --- /dev/null +++ b/xv6-public/trapasm.S @@ -0,0 +1,32 @@ +#include "mmu.h" + + # vectors.S sends all traps here. +.globl alltraps +alltraps: + # Build trap frame. + pushl %ds + pushl %es + pushl %fs + pushl %gs + pushal + + # Set up data segments. + movw $(SEG_KDATA<<3), %ax + movw %ax, %ds + movw %ax, %es + + # Call trap(tf), where tf=%esp + pushl %esp + call trap + addl $4, %esp + + # Return falls through to trapret... +.globl trapret +trapret: + popal + popl %gs + popl %fs + popl %es + popl %ds + addl $0x8, %esp # trapno and errcode + iret diff --git a/xv6-public/traps.h b/xv6-public/traps.h new file mode 100644 index 0000000..0bd1fd8 --- /dev/null +++ b/xv6-public/traps.h @@ -0,0 +1,38 @@ +// x86 trap and interrupt constants. + +// Processor-defined: +#define T_DIVIDE 0 // divide error +#define T_DEBUG 1 // debug exception +#define T_NMI 2 // non-maskable interrupt +#define T_BRKPT 3 // breakpoint +#define T_OFLOW 4 // overflow +#define T_BOUND 5 // bounds check +#define T_ILLOP 6 // illegal opcode +#define T_DEVICE 7 // device not available +#define T_DBLFLT 8 // double fault +// #define T_COPROC 9 // reserved (not used since 486) +#define T_TSS 10 // invalid task switch segment +#define T_SEGNP 11 // segment not present +#define T_STACK 12 // stack exception +#define T_GPFLT 13 // general protection fault +#define T_PGFLT 14 // page fault +// #define T_RES 15 // reserved +#define T_FPERR 16 // floating point error +#define T_ALIGN 17 // aligment check +#define T_MCHK 18 // machine check +#define T_SIMDERR 19 // SIMD floating point error + +// These are arbitrarily chosen, but with care not to overlap +// processor defined exceptions or interrupt vectors. +#define T_SYSCALL 64 // system call +#define T_DEFAULT 500 // catchall + +#define T_IRQ0 32 // IRQ 0 corresponds to int T_IRQ + +#define IRQ_TIMER 0 +#define IRQ_KBD 1 +#define IRQ_COM1 4 +#define IRQ_IDE 14 +#define IRQ_ERROR 19 +#define IRQ_SPURIOUS 31 + diff --git a/xv6-public/types.h b/xv6-public/types.h new file mode 100644 index 0000000..e4adf64 --- /dev/null +++ b/xv6-public/types.h @@ -0,0 +1,4 @@ +typedef unsigned int uint; +typedef unsigned short ushort; +typedef unsigned char uchar; +typedef uint pde_t; diff --git a/xv6-public/uart.c b/xv6-public/uart.c new file mode 100644 index 0000000..b8946da --- /dev/null +++ b/xv6-public/uart.c @@ -0,0 +1,77 @@ +// Intel 8250 serial port (UART). + +#include "types.h" +#include "defs.h" +#include "param.h" +#include "traps.h" +#include "spinlock.h" +#include "sleeplock.h" +#include "fs.h" +#include "file.h" +#include "mmu.h" +#include "proc.h" +#include "x86.h" + +#define COM1 0x3f8 + +static int uart; // is there a uart? + +void +uartinit(void) +{ + char *p; + + // Turn off the FIFO + outb(COM1+2, 0); + + // 9600 baud, 8 data bits, 1 stop bit, parity off. + outb(COM1+3, 0x80); // Unlock divisor + outb(COM1+0, 115200/9600); + outb(COM1+1, 0); + outb(COM1+3, 0x03); // Lock divisor, 8 data bits. + outb(COM1+4, 0); + outb(COM1+1, 0x01); // Enable receive interrupts. + + // If status is 0xFF, no serial port. + if(inb(COM1+5) == 0xFF) + return; + uart = 1; + + // Acknowledge pre-existing interrupt conditions; + // enable interrupts. + inb(COM1+2); + inb(COM1+0); + ioapicenable(IRQ_COM1, 0); + + // Announce that we're here. + for(p="xv6...\n"; *p; p++) + uartputc(*p); +} + +void +uartputc(int c) +{ + int i; + + if(!uart) + return; + for(i = 0; i < 128 && !(inb(COM1+5) & 0x20); i++) + microdelay(10); + outb(COM1+0, c); +} + +static int +uartgetc(void) +{ + if(!uart) + return -1; + if(!(inb(COM1+5) & 0x01)) + return -1; + return inb(COM1+0); +} + +void +uartintr(void) +{ + consoleintr(uartgetc); +} diff --git a/xv6-public/ulib.c b/xv6-public/ulib.c new file mode 100644 index 0000000..8e1e1a2 --- /dev/null +++ b/xv6-public/ulib.c @@ -0,0 +1,106 @@ +#include "types.h" +#include "stat.h" +#include "fcntl.h" +#include "user.h" +#include "x86.h" + +char* +strcpy(char *s, const char *t) +{ + char *os; + + os = s; + while((*s++ = *t++) != 0) + ; + return os; +} + +int +strcmp(const char *p, const char *q) +{ + while(*p && *p == *q) + p++, q++; + return (uchar)*p - (uchar)*q; +} + +uint +strlen(const char *s) +{ + int n; + + for(n = 0; s[n]; n++) + ; + return n; +} + +void* +memset(void *dst, int c, uint n) +{ + stosb(dst, c, n); + return dst; +} + +char* +strchr(const char *s, char c) +{ + for(; *s; s++) + if(*s == c) + return (char*)s; + return 0; +} + +char* +gets(char *buf, int max) +{ + int i, cc; + char c; + + for(i=0; i+1 < max; ){ + cc = read(0, &c, 1); + if(cc < 1) + break; + buf[i++] = c; + if(c == '\n' || c == '\r') + break; + } + buf[i] = '\0'; + return buf; +} + +int +stat(const char *n, struct stat *st) +{ + int fd; + int r; + + fd = open(n, O_RDONLY); + if(fd < 0) + return -1; + r = fstat(fd, st); + close(fd); + return r; +} + +int +atoi(const char *s) +{ + int n; + + n = 0; + while('0' <= *s && *s <= '9') + n = n*10 + *s++ - '0'; + return n; +} + +void* +memmove(void *vdst, const void *vsrc, int n) +{ + char *dst; + const char *src; + + dst = vdst; + src = vsrc; + while(n-- > 0) + *dst++ = *src++; + return vdst; +} diff --git a/xv6-public/umalloc.c b/xv6-public/umalloc.c new file mode 100644 index 0000000..a7e7d2c --- /dev/null +++ b/xv6-public/umalloc.c @@ -0,0 +1,90 @@ +#include "types.h" +#include "stat.h" +#include "user.h" +#include "param.h" + +// Memory allocator by Kernighan and Ritchie, +// The C programming Language, 2nd ed. Section 8.7. + +typedef long Align; + +union header { + struct { + union header *ptr; + uint size; + } s; + Align x; +}; + +typedef union header Header; + +static Header base; +static Header *freep; + +void +free(void *ap) +{ + Header *bp, *p; + + bp = (Header*)ap - 1; + for(p = freep; !(bp > p && bp < p->s.ptr); p = p->s.ptr) + if(p >= p->s.ptr && (bp > p || bp < p->s.ptr)) + break; + if(bp + bp->s.size == p->s.ptr){ + bp->s.size += p->s.ptr->s.size; + bp->s.ptr = p->s.ptr->s.ptr; + } else + bp->s.ptr = p->s.ptr; + if(p + p->s.size == bp){ + p->s.size += bp->s.size; + p->s.ptr = bp->s.ptr; + } else + p->s.ptr = bp; + freep = p; +} + +static Header* +morecore(uint nu) +{ + char *p; + Header *hp; + + if(nu < 4096) + nu = 4096; + p = sbrk(nu * sizeof(Header)); + if(p == (char*)-1) + return 0; + hp = (Header*)p; + hp->s.size = nu; + free((void*)(hp + 1)); + return freep; +} + +void* +malloc(uint nbytes) +{ + Header *p, *prevp; + uint nunits; + + nunits = (nbytes + sizeof(Header) - 1)/sizeof(Header) + 1; + if((prevp = freep) == 0){ + base.s.ptr = freep = prevp = &base; + base.s.size = 0; + } + for(p = prevp->s.ptr; ; prevp = p, p = p->s.ptr){ + if(p->s.size >= nunits){ + if(p->s.size == nunits) + prevp->s.ptr = p->s.ptr; + else { + p->s.size -= nunits; + p += p->s.size; + p->s.size = nunits; + } + freep = prevp; + return (void*)(p + 1); + } + if(p == freep) + if((p = morecore(nunits)) == 0) + return 0; + } +} diff --git a/xv6-public/user.h b/xv6-public/user.h new file mode 100644 index 0000000..11e86aa --- /dev/null +++ b/xv6-public/user.h @@ -0,0 +1,44 @@ +struct stat; +struct rtcdate; + +// system calls +int fork(void); +int exit(void) __attribute__((noreturn)); +int wait(void); +int pipe(int*); +int write(int, const void*, int); +int read(int, void*, int); +int close(int); +int kill(int); +int exec(char*, char**); +int open(const char*, int); +int mknod(const char*, short, short); +int unlink(const char*); +int fstat(int fd, struct stat*); +int link(const char*, const char*); +int mkdir(const char*); +int chdir(const char*); +int dup(int); +int getpid(void); +char* sbrk(int); +int sleep(int); +int uptime(void); +int date(struct rtcdate* ); +int dup2(int , int); +int alarm(int, void (*)()); + + + +// ulib.c +int stat(const char*, struct stat*); +char* strcpy(char*, const char*); +void *memmove(void*, const void*, int); +char* strchr(const char*, char c); +int strcmp(const char*, const char*); +void printf(int, const char*, ...); +char* gets(char*, int max); +uint strlen(const char*); +void* memset(void*, int, uint); +void* malloc(uint); +void free(void*); +int atoi(const char*); diff --git a/xv6-public/usertests.c b/xv6-public/usertests.c new file mode 100644 index 0000000..a1e97e7 --- /dev/null +++ b/xv6-public/usertests.c @@ -0,0 +1,1803 @@ +#include "param.h" +#include "types.h" +#include "stat.h" +#include "user.h" +#include "fs.h" +#include "fcntl.h" +#include "syscall.h" +#include "traps.h" +#include "memlayout.h" + +char buf[8192]; +char name[3]; +char *echoargv[] = { "echo", "ALL", "TESTS", "PASSED", 0 }; +int stdout = 1; + +// does chdir() call iput(p->cwd) in a transaction? +void +iputtest(void) +{ + printf(stdout, "iput test\n"); + + if(mkdir("iputdir") < 0){ + printf(stdout, "mkdir failed\n"); + exit(); + } + if(chdir("iputdir") < 0){ + printf(stdout, "chdir iputdir failed\n"); + exit(); + } + if(unlink("../iputdir") < 0){ + printf(stdout, "unlink ../iputdir failed\n"); + exit(); + } + if(chdir("/") < 0){ + printf(stdout, "chdir / failed\n"); + exit(); + } + printf(stdout, "iput test ok\n"); +} + +// does exit() call iput(p->cwd) in a transaction? +void +exitiputtest(void) +{ + int pid; + + printf(stdout, "exitiput test\n"); + + pid = fork(); + if(pid < 0){ + printf(stdout, "fork failed\n"); + exit(); + } + if(pid == 0){ + if(mkdir("iputdir") < 0){ + printf(stdout, "mkdir failed\n"); + exit(); + } + if(chdir("iputdir") < 0){ + printf(stdout, "child chdir failed\n"); + exit(); + } + if(unlink("../iputdir") < 0){ + printf(stdout, "unlink ../iputdir failed\n"); + exit(); + } + exit(); + } + wait(); + printf(stdout, "exitiput test ok\n"); +} + +// does the error path in open() for attempt to write a +// directory call iput() in a transaction? +// needs a hacked kernel that pauses just after the namei() +// call in sys_open(): +// if((ip = namei(path)) == 0) +// return -1; +// { +// int i; +// for(i = 0; i < 10000; i++) +// yield(); +// } +void +openiputtest(void) +{ + int pid; + + printf(stdout, "openiput test\n"); + if(mkdir("oidir") < 0){ + printf(stdout, "mkdir oidir failed\n"); + exit(); + } + pid = fork(); + if(pid < 0){ + printf(stdout, "fork failed\n"); + exit(); + } + if(pid == 0){ + int fd = open("oidir", O_RDWR); + if(fd >= 0){ + printf(stdout, "open directory for write succeeded\n"); + exit(); + } + exit(); + } + sleep(1); + if(unlink("oidir") != 0){ + printf(stdout, "unlink failed\n"); + exit(); + } + wait(); + printf(stdout, "openiput test ok\n"); +} + +// simple file system tests + +void +opentest(void) +{ + int fd; + + printf(stdout, "open test\n"); + fd = open("echo", 0); + if(fd < 0){ + printf(stdout, "open echo failed!\n"); + exit(); + } + close(fd); + fd = open("doesnotexist", 0); + if(fd >= 0){ + printf(stdout, "open doesnotexist succeeded!\n"); + exit(); + } + printf(stdout, "open test ok\n"); +} + +void +writetest(void) +{ + int fd; + int i; + + printf(stdout, "small file test\n"); + fd = open("small", O_CREATE|O_RDWR); + if(fd >= 0){ + printf(stdout, "creat small succeeded; ok\n"); + } else { + printf(stdout, "error: creat small failed!\n"); + exit(); + } + for(i = 0; i < 100; i++){ + if(write(fd, "aaaaaaaaaa", 10) != 10){ + printf(stdout, "error: write aa %d new file failed\n", i); + exit(); + } + if(write(fd, "bbbbbbbbbb", 10) != 10){ + printf(stdout, "error: write bb %d new file failed\n", i); + exit(); + } + } + printf(stdout, "writes ok\n"); + close(fd); + fd = open("small", O_RDONLY); + if(fd >= 0){ + printf(stdout, "open small succeeded ok\n"); + } else { + printf(stdout, "error: open small failed!\n"); + exit(); + } + i = read(fd, buf, 2000); + if(i == 2000){ + printf(stdout, "read succeeded ok\n"); + } else { + printf(stdout, "read failed\n"); + exit(); + } + close(fd); + + if(unlink("small") < 0){ + printf(stdout, "unlink small failed\n"); + exit(); + } + printf(stdout, "small file test ok\n"); +} + +void +writetest1(void) +{ + int i, fd, n; + + printf(stdout, "big files test\n"); + + fd = open("big", O_CREATE|O_RDWR); + if(fd < 0){ + printf(stdout, "error: creat big failed!\n"); + exit(); + } + + for(i = 0; i < MAXFILE; i++){ + ((int*)buf)[0] = i; + if(write(fd, buf, 512) != 512){ + printf(stdout, "error: write big file failed\n", i); + exit(); + } + } + + close(fd); + + fd = open("big", O_RDONLY); + if(fd < 0){ + printf(stdout, "error: open big failed!\n"); + exit(); + } + + n = 0; + for(;;){ + i = read(fd, buf, 512); + if(i == 0){ + if(n == MAXFILE - 1){ + printf(stdout, "read only %d blocks from big", n); + exit(); + } + break; + } else if(i != 512){ + printf(stdout, "read failed %d\n", i); + exit(); + } + if(((int*)buf)[0] != n){ + printf(stdout, "read content of block %d is %d\n", + n, ((int*)buf)[0]); + exit(); + } + n++; + } + close(fd); + if(unlink("big") < 0){ + printf(stdout, "unlink big failed\n"); + exit(); + } + printf(stdout, "big files ok\n"); +} + +void +createtest(void) +{ + int i, fd; + + printf(stdout, "many creates, followed by unlink test\n"); + + name[0] = 'a'; + name[2] = '\0'; + for(i = 0; i < 52; i++){ + name[1] = '0' + i; + fd = open(name, O_CREATE|O_RDWR); + close(fd); + } + name[0] = 'a'; + name[2] = '\0'; + for(i = 0; i < 52; i++){ + name[1] = '0' + i; + unlink(name); + } + printf(stdout, "many creates, followed by unlink; ok\n"); +} + +void dirtest(void) +{ + printf(stdout, "mkdir test\n"); + + if(mkdir("dir0") < 0){ + printf(stdout, "mkdir failed\n"); + exit(); + } + + if(chdir("dir0") < 0){ + printf(stdout, "chdir dir0 failed\n"); + exit(); + } + + if(chdir("..") < 0){ + printf(stdout, "chdir .. failed\n"); + exit(); + } + + if(unlink("dir0") < 0){ + printf(stdout, "unlink dir0 failed\n"); + exit(); + } + printf(stdout, "mkdir test ok\n"); +} + +void +exectest(void) +{ + printf(stdout, "exec test\n"); + if(exec("echo", echoargv) < 0){ + printf(stdout, "exec echo failed\n"); + exit(); + } +} + +// simple fork and pipe read/write + +void +pipe1(void) +{ + int fds[2], pid; + int seq, i, n, cc, total; + + if(pipe(fds) != 0){ + printf(1, "pipe() failed\n"); + exit(); + } + pid = fork(); + seq = 0; + if(pid == 0){ + close(fds[0]); + for(n = 0; n < 5; n++){ + for(i = 0; i < 1033; i++) + buf[i] = seq++; + if(write(fds[1], buf, 1033) != 1033){ + printf(1, "pipe1 oops 1\n"); + exit(); + } + } + exit(); + } else if(pid > 0){ + close(fds[1]); + total = 0; + cc = 1; + while((n = read(fds[0], buf, cc)) > 0){ + for(i = 0; i < n; i++){ + if((buf[i] & 0xff) != (seq++ & 0xff)){ + printf(1, "pipe1 oops 2\n"); + return; + } + } + total += n; + cc = cc * 2; + if(cc > sizeof(buf)) + cc = sizeof(buf); + } + if(total != 5 * 1033){ + printf(1, "pipe1 oops 3 total %d\n", total); + exit(); + } + close(fds[0]); + wait(); + } else { + printf(1, "fork() failed\n"); + exit(); + } + printf(1, "pipe1 ok\n"); +} + +// meant to be run w/ at most two CPUs +void +preempt(void) +{ + int pid1, pid2, pid3; + int pfds[2]; + + printf(1, "preempt: "); + pid1 = fork(); + if(pid1 == 0) + for(;;) + ; + + pid2 = fork(); + if(pid2 == 0) + for(;;) + ; + + pipe(pfds); + pid3 = fork(); + if(pid3 == 0){ + close(pfds[0]); + if(write(pfds[1], "x", 1) != 1) + printf(1, "preempt write error"); + close(pfds[1]); + for(;;) + ; + } + + close(pfds[1]); + if(read(pfds[0], buf, sizeof(buf)) != 1){ + printf(1, "preempt read error"); + return; + } + close(pfds[0]); + printf(1, "kill... "); + kill(pid1); + kill(pid2); + kill(pid3); + printf(1, "wait... "); + wait(); + wait(); + wait(); + printf(1, "preempt ok\n"); +} + +// try to find any races between exit and wait +void +exitwait(void) +{ + int i, pid; + + for(i = 0; i < 100; i++){ + pid = fork(); + if(pid < 0){ + printf(1, "fork failed\n"); + return; + } + if(pid){ + if(wait() != pid){ + printf(1, "wait wrong pid\n"); + return; + } + } else { + exit(); + } + } + printf(1, "exitwait ok\n"); +} + +void +mem(void) +{ + void *m1, *m2; + int pid, ppid; + + printf(1, "mem test\n"); + ppid = getpid(); + if((pid = fork()) == 0){ + m1 = 0; + while((m2 = malloc(10001)) != 0){ + *(char**)m2 = m1; + m1 = m2; + } + while(m1){ + m2 = *(char**)m1; + free(m1); + m1 = m2; + } + m1 = malloc(1024*20); + if(m1 == 0){ + printf(1, "couldn't allocate mem?!!\n"); + kill(ppid); + exit(); + } + free(m1); + printf(1, "mem ok\n"); + exit(); + } else { + wait(); + } +} + +// More file system tests + +// two processes write to the same file descriptor +// is the offset shared? does inode locking work? +void +sharedfd(void) +{ + int fd, pid, i, n, nc, np; + char buf[10]; + + printf(1, "sharedfd test\n"); + + unlink("sharedfd"); + fd = open("sharedfd", O_CREATE|O_RDWR); + if(fd < 0){ + printf(1, "fstests: cannot open sharedfd for writing"); + return; + } + pid = fork(); + memset(buf, pid==0?'c':'p', sizeof(buf)); + for(i = 0; i < 1000; i++){ + if(write(fd, buf, sizeof(buf)) != sizeof(buf)){ + printf(1, "fstests: write sharedfd failed\n"); + break; + } + } + if(pid == 0) + exit(); + else + wait(); + close(fd); + fd = open("sharedfd", 0); + if(fd < 0){ + printf(1, "fstests: cannot open sharedfd for reading\n"); + return; + } + nc = np = 0; + while((n = read(fd, buf, sizeof(buf))) > 0){ + for(i = 0; i < sizeof(buf); i++){ + if(buf[i] == 'c') + nc++; + if(buf[i] == 'p') + np++; + } + } + close(fd); + unlink("sharedfd"); + if(nc == 10000 && np == 10000){ + printf(1, "sharedfd ok\n"); + } else { + printf(1, "sharedfd oops %d %d\n", nc, np); + exit(); + } +} + +// four processes write different files at the same +// time, to test block allocation. +void +fourfiles(void) +{ + int fd, pid, i, j, n, total, pi; + char *names[] = { "f0", "f1", "f2", "f3" }; + char *fname; + + printf(1, "fourfiles test\n"); + + for(pi = 0; pi < 4; pi++){ + fname = names[pi]; + unlink(fname); + + pid = fork(); + if(pid < 0){ + printf(1, "fork failed\n"); + exit(); + } + + if(pid == 0){ + fd = open(fname, O_CREATE | O_RDWR); + if(fd < 0){ + printf(1, "create failed\n"); + exit(); + } + + memset(buf, '0'+pi, 512); + for(i = 0; i < 12; i++){ + if((n = write(fd, buf, 500)) != 500){ + printf(1, "write failed %d\n", n); + exit(); + } + } + exit(); + } + } + + for(pi = 0; pi < 4; pi++){ + wait(); + } + + for(i = 0; i < 2; i++){ + fname = names[i]; + fd = open(fname, 0); + total = 0; + while((n = read(fd, buf, sizeof(buf))) > 0){ + for(j = 0; j < n; j++){ + if(buf[j] != '0'+i){ + printf(1, "wrong char\n"); + exit(); + } + } + total += n; + } + close(fd); + if(total != 12*500){ + printf(1, "wrong length %d\n", total); + exit(); + } + unlink(fname); + } + + printf(1, "fourfiles ok\n"); +} + +// four processes create and delete different files in same directory +void +createdelete(void) +{ + enum { N = 20 }; + int pid, i, fd, pi; + char name[32]; + + printf(1, "createdelete test\n"); + + for(pi = 0; pi < 4; pi++){ + pid = fork(); + if(pid < 0){ + printf(1, "fork failed\n"); + exit(); + } + + if(pid == 0){ + name[0] = 'p' + pi; + name[2] = '\0'; + for(i = 0; i < N; i++){ + name[1] = '0' + i; + fd = open(name, O_CREATE | O_RDWR); + if(fd < 0){ + printf(1, "create failed\n"); + exit(); + } + close(fd); + if(i > 0 && (i % 2 ) == 0){ + name[1] = '0' + (i / 2); + if(unlink(name) < 0){ + printf(1, "unlink failed\n"); + exit(); + } + } + } + exit(); + } + } + + for(pi = 0; pi < 4; pi++){ + wait(); + } + + name[0] = name[1] = name[2] = 0; + for(i = 0; i < N; i++){ + for(pi = 0; pi < 4; pi++){ + name[0] = 'p' + pi; + name[1] = '0' + i; + fd = open(name, 0); + if((i == 0 || i >= N/2) && fd < 0){ + printf(1, "oops createdelete %s didn't exist\n", name); + exit(); + } else if((i >= 1 && i < N/2) && fd >= 0){ + printf(1, "oops createdelete %s did exist\n", name); + exit(); + } + if(fd >= 0) + close(fd); + } + } + + for(i = 0; i < N; i++){ + for(pi = 0; pi < 4; pi++){ + name[0] = 'p' + i; + name[1] = '0' + i; + unlink(name); + } + } + + printf(1, "createdelete ok\n"); +} + +// can I unlink a file and still read it? +void +unlinkread(void) +{ + int fd, fd1; + + printf(1, "unlinkread test\n"); + fd = open("unlinkread", O_CREATE | O_RDWR); + if(fd < 0){ + printf(1, "create unlinkread failed\n"); + exit(); + } + write(fd, "hello", 5); + close(fd); + + fd = open("unlinkread", O_RDWR); + if(fd < 0){ + printf(1, "open unlinkread failed\n"); + exit(); + } + if(unlink("unlinkread") != 0){ + printf(1, "unlink unlinkread failed\n"); + exit(); + } + + fd1 = open("unlinkread", O_CREATE | O_RDWR); + write(fd1, "yyy", 3); + close(fd1); + + if(read(fd, buf, sizeof(buf)) != 5){ + printf(1, "unlinkread read failed"); + exit(); + } + if(buf[0] != 'h'){ + printf(1, "unlinkread wrong data\n"); + exit(); + } + if(write(fd, buf, 10) != 10){ + printf(1, "unlinkread write failed\n"); + exit(); + } + close(fd); + unlink("unlinkread"); + printf(1, "unlinkread ok\n"); +} + +void +linktest(void) +{ + int fd; + + printf(1, "linktest\n"); + + unlink("lf1"); + unlink("lf2"); + + fd = open("lf1", O_CREATE|O_RDWR); + if(fd < 0){ + printf(1, "create lf1 failed\n"); + exit(); + } + if(write(fd, "hello", 5) != 5){ + printf(1, "write lf1 failed\n"); + exit(); + } + close(fd); + + if(link("lf1", "lf2") < 0){ + printf(1, "link lf1 lf2 failed\n"); + exit(); + } + unlink("lf1"); + + if(open("lf1", 0) >= 0){ + printf(1, "unlinked lf1 but it is still there!\n"); + exit(); + } + + fd = open("lf2", 0); + if(fd < 0){ + printf(1, "open lf2 failed\n"); + exit(); + } + if(read(fd, buf, sizeof(buf)) != 5){ + printf(1, "read lf2 failed\n"); + exit(); + } + close(fd); + + if(link("lf2", "lf2") >= 0){ + printf(1, "link lf2 lf2 succeeded! oops\n"); + exit(); + } + + unlink("lf2"); + if(link("lf2", "lf1") >= 0){ + printf(1, "link non-existant succeeded! oops\n"); + exit(); + } + + if(link(".", "lf1") >= 0){ + printf(1, "link . lf1 succeeded! oops\n"); + exit(); + } + + printf(1, "linktest ok\n"); +} + +// test concurrent create/link/unlink of the same file +void +concreate(void) +{ + char file[3]; + int i, pid, n, fd; + char fa[40]; + struct { + ushort inum; + char name[14]; + } de; + + printf(1, "concreate test\n"); + file[0] = 'C'; + file[2] = '\0'; + for(i = 0; i < 40; i++){ + file[1] = '0' + i; + unlink(file); + pid = fork(); + if(pid && (i % 3) == 1){ + link("C0", file); + } else if(pid == 0 && (i % 5) == 1){ + link("C0", file); + } else { + fd = open(file, O_CREATE | O_RDWR); + if(fd < 0){ + printf(1, "concreate create %s failed\n", file); + exit(); + } + close(fd); + } + if(pid == 0) + exit(); + else + wait(); + } + + memset(fa, 0, sizeof(fa)); + fd = open(".", 0); + n = 0; + while(read(fd, &de, sizeof(de)) > 0){ + if(de.inum == 0) + continue; + if(de.name[0] == 'C' && de.name[2] == '\0'){ + i = de.name[1] - '0'; + if(i < 0 || i >= sizeof(fa)){ + printf(1, "concreate weird file %s\n", de.name); + exit(); + } + if(fa[i]){ + printf(1, "concreate duplicate file %s\n", de.name); + exit(); + } + fa[i] = 1; + n++; + } + } + close(fd); + + if(n != 40){ + printf(1, "concreate not enough files in directory listing\n"); + exit(); + } + + for(i = 0; i < 40; i++){ + file[1] = '0' + i; + pid = fork(); + if(pid < 0){ + printf(1, "fork failed\n"); + exit(); + } + if(((i % 3) == 0 && pid == 0) || + ((i % 3) == 1 && pid != 0)){ + close(open(file, 0)); + close(open(file, 0)); + close(open(file, 0)); + close(open(file, 0)); + } else { + unlink(file); + unlink(file); + unlink(file); + unlink(file); + } + if(pid == 0) + exit(); + else + wait(); + } + + printf(1, "concreate ok\n"); +} + +// another concurrent link/unlink/create test, +// to look for deadlocks. +void +linkunlink() +{ + int pid, i; + + printf(1, "linkunlink test\n"); + + unlink("x"); + pid = fork(); + if(pid < 0){ + printf(1, "fork failed\n"); + exit(); + } + + unsigned int x = (pid ? 1 : 97); + for(i = 0; i < 100; i++){ + x = x * 1103515245 + 12345; + if((x % 3) == 0){ + close(open("x", O_RDWR | O_CREATE)); + } else if((x % 3) == 1){ + link("cat", "x"); + } else { + unlink("x"); + } + } + + if(pid) + wait(); + else + exit(); + + printf(1, "linkunlink ok\n"); +} + +// directory that uses indirect blocks +void +bigdir(void) +{ + int i, fd; + char name[10]; + + printf(1, "bigdir test\n"); + unlink("bd"); + + fd = open("bd", O_CREATE); + if(fd < 0){ + printf(1, "bigdir create failed\n"); + exit(); + } + close(fd); + + for(i = 0; i < 500; i++){ + name[0] = 'x'; + name[1] = '0' + (i / 64); + name[2] = '0' + (i % 64); + name[3] = '\0'; + if(link("bd", name) != 0){ + printf(1, "bigdir link failed\n"); + exit(); + } + } + + unlink("bd"); + for(i = 0; i < 500; i++){ + name[0] = 'x'; + name[1] = '0' + (i / 64); + name[2] = '0' + (i % 64); + name[3] = '\0'; + if(unlink(name) != 0){ + printf(1, "bigdir unlink failed"); + exit(); + } + } + + printf(1, "bigdir ok\n"); +} + +void +subdir(void) +{ + int fd, cc; + + printf(1, "subdir test\n"); + + unlink("ff"); + if(mkdir("dd") != 0){ + printf(1, "subdir mkdir dd failed\n"); + exit(); + } + + fd = open("dd/ff", O_CREATE | O_RDWR); + if(fd < 0){ + printf(1, "create dd/ff failed\n"); + exit(); + } + write(fd, "ff", 2); + close(fd); + + if(unlink("dd") >= 0){ + printf(1, "unlink dd (non-empty dir) succeeded!\n"); + exit(); + } + + if(mkdir("/dd/dd") != 0){ + printf(1, "subdir mkdir dd/dd failed\n"); + exit(); + } + + fd = open("dd/dd/ff", O_CREATE | O_RDWR); + if(fd < 0){ + printf(1, "create dd/dd/ff failed\n"); + exit(); + } + write(fd, "FF", 2); + close(fd); + + fd = open("dd/dd/../ff", 0); + if(fd < 0){ + printf(1, "open dd/dd/../ff failed\n"); + exit(); + } + cc = read(fd, buf, sizeof(buf)); + if(cc != 2 || buf[0] != 'f'){ + printf(1, "dd/dd/../ff wrong content\n"); + exit(); + } + close(fd); + + if(link("dd/dd/ff", "dd/dd/ffff") != 0){ + printf(1, "link dd/dd/ff dd/dd/ffff failed\n"); + exit(); + } + + if(unlink("dd/dd/ff") != 0){ + printf(1, "unlink dd/dd/ff failed\n"); + exit(); + } + if(open("dd/dd/ff", O_RDONLY) >= 0){ + printf(1, "open (unlinked) dd/dd/ff succeeded\n"); + exit(); + } + + if(chdir("dd") != 0){ + printf(1, "chdir dd failed\n"); + exit(); + } + if(chdir("dd/../../dd") != 0){ + printf(1, "chdir dd/../../dd failed\n"); + exit(); + } + if(chdir("dd/../../../dd") != 0){ + printf(1, "chdir dd/../../dd failed\n"); + exit(); + } + if(chdir("./..") != 0){ + printf(1, "chdir ./.. failed\n"); + exit(); + } + + fd = open("dd/dd/ffff", 0); + if(fd < 0){ + printf(1, "open dd/dd/ffff failed\n"); + exit(); + } + if(read(fd, buf, sizeof(buf)) != 2){ + printf(1, "read dd/dd/ffff wrong len\n"); + exit(); + } + close(fd); + + if(open("dd/dd/ff", O_RDONLY) >= 0){ + printf(1, "open (unlinked) dd/dd/ff succeeded!\n"); + exit(); + } + + if(open("dd/ff/ff", O_CREATE|O_RDWR) >= 0){ + printf(1, "create dd/ff/ff succeeded!\n"); + exit(); + } + if(open("dd/xx/ff", O_CREATE|O_RDWR) >= 0){ + printf(1, "create dd/xx/ff succeeded!\n"); + exit(); + } + if(open("dd", O_CREATE) >= 0){ + printf(1, "create dd succeeded!\n"); + exit(); + } + if(open("dd", O_RDWR) >= 0){ + printf(1, "open dd rdwr succeeded!\n"); + exit(); + } + if(open("dd", O_WRONLY) >= 0){ + printf(1, "open dd wronly succeeded!\n"); + exit(); + } + if(link("dd/ff/ff", "dd/dd/xx") == 0){ + printf(1, "link dd/ff/ff dd/dd/xx succeeded!\n"); + exit(); + } + if(link("dd/xx/ff", "dd/dd/xx") == 0){ + printf(1, "link dd/xx/ff dd/dd/xx succeeded!\n"); + exit(); + } + if(link("dd/ff", "dd/dd/ffff") == 0){ + printf(1, "link dd/ff dd/dd/ffff succeeded!\n"); + exit(); + } + if(mkdir("dd/ff/ff") == 0){ + printf(1, "mkdir dd/ff/ff succeeded!\n"); + exit(); + } + if(mkdir("dd/xx/ff") == 0){ + printf(1, "mkdir dd/xx/ff succeeded!\n"); + exit(); + } + if(mkdir("dd/dd/ffff") == 0){ + printf(1, "mkdir dd/dd/ffff succeeded!\n"); + exit(); + } + if(unlink("dd/xx/ff") == 0){ + printf(1, "unlink dd/xx/ff succeeded!\n"); + exit(); + } + if(unlink("dd/ff/ff") == 0){ + printf(1, "unlink dd/ff/ff succeeded!\n"); + exit(); + } + if(chdir("dd/ff") == 0){ + printf(1, "chdir dd/ff succeeded!\n"); + exit(); + } + if(chdir("dd/xx") == 0){ + printf(1, "chdir dd/xx succeeded!\n"); + exit(); + } + + if(unlink("dd/dd/ffff") != 0){ + printf(1, "unlink dd/dd/ff failed\n"); + exit(); + } + if(unlink("dd/ff") != 0){ + printf(1, "unlink dd/ff failed\n"); + exit(); + } + if(unlink("dd") == 0){ + printf(1, "unlink non-empty dd succeeded!\n"); + exit(); + } + if(unlink("dd/dd") < 0){ + printf(1, "unlink dd/dd failed\n"); + exit(); + } + if(unlink("dd") < 0){ + printf(1, "unlink dd failed\n"); + exit(); + } + + printf(1, "subdir ok\n"); +} + +// test writes that are larger than the log. +void +bigwrite(void) +{ + int fd, sz; + + printf(1, "bigwrite test\n"); + + unlink("bigwrite"); + for(sz = 499; sz < 12*512; sz += 471){ + fd = open("bigwrite", O_CREATE | O_RDWR); + if(fd < 0){ + printf(1, "cannot create bigwrite\n"); + exit(); + } + int i; + for(i = 0; i < 2; i++){ + int cc = write(fd, buf, sz); + if(cc != sz){ + printf(1, "write(%d) ret %d\n", sz, cc); + exit(); + } + } + close(fd); + unlink("bigwrite"); + } + + printf(1, "bigwrite ok\n"); +} + +void +bigfile(void) +{ + int fd, i, total, cc; + + printf(1, "bigfile test\n"); + + unlink("bigfile"); + fd = open("bigfile", O_CREATE | O_RDWR); + if(fd < 0){ + printf(1, "cannot create bigfile"); + exit(); + } + for(i = 0; i < 20; i++){ + memset(buf, i, 600); + if(write(fd, buf, 600) != 600){ + printf(1, "write bigfile failed\n"); + exit(); + } + } + close(fd); + + fd = open("bigfile", 0); + if(fd < 0){ + printf(1, "cannot open bigfile\n"); + exit(); + } + total = 0; + for(i = 0; ; i++){ + cc = read(fd, buf, 300); + if(cc < 0){ + printf(1, "read bigfile failed\n"); + exit(); + } + if(cc == 0) + break; + if(cc != 300){ + printf(1, "short read bigfile\n"); + exit(); + } + if(buf[0] != i/2 || buf[299] != i/2){ + printf(1, "read bigfile wrong data\n"); + exit(); + } + total += cc; + } + close(fd); + if(total != 20*600){ + printf(1, "read bigfile wrong total\n"); + exit(); + } + unlink("bigfile"); + + printf(1, "bigfile test ok\n"); +} + +void +fourteen(void) +{ + int fd; + + // DIRSIZ is 14. + printf(1, "fourteen test\n"); + + if(mkdir("12345678901234") != 0){ + printf(1, "mkdir 12345678901234 failed\n"); + exit(); + } + if(mkdir("12345678901234/123456789012345") != 0){ + printf(1, "mkdir 12345678901234/123456789012345 failed\n"); + exit(); + } + fd = open("123456789012345/123456789012345/123456789012345", O_CREATE); + if(fd < 0){ + printf(1, "create 123456789012345/123456789012345/123456789012345 failed\n"); + exit(); + } + close(fd); + fd = open("12345678901234/12345678901234/12345678901234", 0); + if(fd < 0){ + printf(1, "open 12345678901234/12345678901234/12345678901234 failed\n"); + exit(); + } + close(fd); + + if(mkdir("12345678901234/12345678901234") == 0){ + printf(1, "mkdir 12345678901234/12345678901234 succeeded!\n"); + exit(); + } + if(mkdir("123456789012345/12345678901234") == 0){ + printf(1, "mkdir 12345678901234/123456789012345 succeeded!\n"); + exit(); + } + + printf(1, "fourteen ok\n"); +} + +void +rmdot(void) +{ + printf(1, "rmdot test\n"); + if(mkdir("dots") != 0){ + printf(1, "mkdir dots failed\n"); + exit(); + } + if(chdir("dots") != 0){ + printf(1, "chdir dots failed\n"); + exit(); + } + if(unlink(".") == 0){ + printf(1, "rm . worked!\n"); + exit(); + } + if(unlink("..") == 0){ + printf(1, "rm .. worked!\n"); + exit(); + } + if(chdir("/") != 0){ + printf(1, "chdir / failed\n"); + exit(); + } + if(unlink("dots/.") == 0){ + printf(1, "unlink dots/. worked!\n"); + exit(); + } + if(unlink("dots/..") == 0){ + printf(1, "unlink dots/.. worked!\n"); + exit(); + } + if(unlink("dots") != 0){ + printf(1, "unlink dots failed!\n"); + exit(); + } + printf(1, "rmdot ok\n"); +} + +void +dirfile(void) +{ + int fd; + + printf(1, "dir vs file\n"); + + fd = open("dirfile", O_CREATE); + if(fd < 0){ + printf(1, "create dirfile failed\n"); + exit(); + } + close(fd); + if(chdir("dirfile") == 0){ + printf(1, "chdir dirfile succeeded!\n"); + exit(); + } + fd = open("dirfile/xx", 0); + if(fd >= 0){ + printf(1, "create dirfile/xx succeeded!\n"); + exit(); + } + fd = open("dirfile/xx", O_CREATE); + if(fd >= 0){ + printf(1, "create dirfile/xx succeeded!\n"); + exit(); + } + if(mkdir("dirfile/xx") == 0){ + printf(1, "mkdir dirfile/xx succeeded!\n"); + exit(); + } + if(unlink("dirfile/xx") == 0){ + printf(1, "unlink dirfile/xx succeeded!\n"); + exit(); + } + if(link("README", "dirfile/xx") == 0){ + printf(1, "link to dirfile/xx succeeded!\n"); + exit(); + } + if(unlink("dirfile") != 0){ + printf(1, "unlink dirfile failed!\n"); + exit(); + } + + fd = open(".", O_RDWR); + if(fd >= 0){ + printf(1, "open . for writing succeeded!\n"); + exit(); + } + fd = open(".", 0); + if(write(fd, "x", 1) > 0){ + printf(1, "write . succeeded!\n"); + exit(); + } + close(fd); + + printf(1, "dir vs file OK\n"); +} + +// test that iput() is called at the end of _namei() +void +iref(void) +{ + int i, fd; + + printf(1, "empty file name\n"); + + // the 50 is NINODE + for(i = 0; i < 50 + 1; i++){ + if(mkdir("irefd") != 0){ + printf(1, "mkdir irefd failed\n"); + exit(); + } + if(chdir("irefd") != 0){ + printf(1, "chdir irefd failed\n"); + exit(); + } + + mkdir(""); + link("README", ""); + fd = open("", O_CREATE); + if(fd >= 0) + close(fd); + fd = open("xx", O_CREATE); + if(fd >= 0) + close(fd); + unlink("xx"); + } + + chdir("/"); + printf(1, "empty file name OK\n"); +} + +// test that fork fails gracefully +// the forktest binary also does this, but it runs out of proc entries first. +// inside the bigger usertests binary, we run out of memory first. +void +forktest(void) +{ + int n, pid; + + printf(1, "fork test\n"); + + for(n=0; n<1000; n++){ + pid = fork(); + if(pid < 0) + break; + if(pid == 0) + exit(); + } + + if(n == 1000){ + printf(1, "fork claimed to work 1000 times!\n"); + exit(); + } + + for(; n > 0; n--){ + if(wait() < 0){ + printf(1, "wait stopped early\n"); + exit(); + } + } + + if(wait() != -1){ + printf(1, "wait got too many\n"); + exit(); + } + + printf(1, "fork test OK\n"); +} + +void +sbrktest(void) +{ + int fds[2], pid, pids[10], ppid; + char *a, *b, *c, *lastaddr, *oldbrk, *p, scratch; + uint amt; + + printf(stdout, "sbrk test\n"); + oldbrk = sbrk(0); + + // can one sbrk() less than a page? + a = sbrk(0); + int i; + for(i = 0; i < 5000; i++){ + b = sbrk(1); + if(b != a){ + printf(stdout, "sbrk test failed %d %x %x\n", i, a, b); + exit(); + } + *b = 1; + a = b + 1; + } + pid = fork(); + if(pid < 0){ + printf(stdout, "sbrk test fork failed\n"); + exit(); + } + c = sbrk(1); + c = sbrk(1); + if(c != a + 1){ + printf(stdout, "sbrk test failed post-fork\n"); + exit(); + } + if(pid == 0) + exit(); + wait(); + + // can one grow address space to something big? +#define BIG (100*1024*1024) + a = sbrk(0); + amt = (BIG) - (uint)a; + p = sbrk(amt); + if (p != a) { + printf(stdout, "sbrk test failed to grow big address space; enough phys mem?\n"); + exit(); + } + lastaddr = (char*) (BIG-1); + *lastaddr = 99; + + // can one de-allocate? + a = sbrk(0); + c = sbrk(-4096); + if(c == (char*)0xffffffff){ + printf(stdout, "sbrk could not deallocate\n"); + exit(); + } + c = sbrk(0); + if(c != a - 4096){ + printf(stdout, "sbrk deallocation produced wrong address, a %x c %x\n", a, c); + exit(); + } + + // can one re-allocate that page? + a = sbrk(0); + c = sbrk(4096); + if(c != a || sbrk(0) != a + 4096){ + printf(stdout, "sbrk re-allocation failed, a %x c %x\n", a, c); + exit(); + } + if(*lastaddr == 99){ + // should be zero + printf(stdout, "sbrk de-allocation didn't really deallocate\n"); + exit(); + } + + a = sbrk(0); + c = sbrk(-(sbrk(0) - oldbrk)); + if(c != a){ + printf(stdout, "sbrk downsize failed, a %x c %x\n", a, c); + exit(); + } + + // can we read the kernel's memory? + for(a = (char*)(KERNBASE); a < (char*) (KERNBASE+2000000); a += 50000){ + ppid = getpid(); + pid = fork(); + if(pid < 0){ + printf(stdout, "fork failed\n"); + exit(); + } + if(pid == 0){ + printf(stdout, "oops could read %x = %x\n", a, *a); + kill(ppid); + exit(); + } + wait(); + } + + // if we run the system out of memory, does it clean up the last + // failed allocation? + if(pipe(fds) != 0){ + printf(1, "pipe() failed\n"); + exit(); + } + for(i = 0; i < sizeof(pids)/sizeof(pids[0]); i++){ + if((pids[i] = fork()) == 0){ + // allocate a lot of memory + sbrk(BIG - (uint)sbrk(0)); + write(fds[1], "x", 1); + // sit around until killed + for(;;) sleep(1000); + } + if(pids[i] != -1) + read(fds[0], &scratch, 1); + } + // if those failed allocations freed up the pages they did allocate, + // we'll be able to allocate here + c = sbrk(4096); + for(i = 0; i < sizeof(pids)/sizeof(pids[0]); i++){ + if(pids[i] == -1) + continue; + kill(pids[i]); + wait(); + } + if(c == (char*)0xffffffff){ + printf(stdout, "failed sbrk leaked memory\n"); + exit(); + } + + if(sbrk(0) > oldbrk) + sbrk(-(sbrk(0) - oldbrk)); + + printf(stdout, "sbrk test OK\n"); +} + +void +validateint(int *p) +{ + int res; + asm("mov %%esp, %%ebx\n\t" + "mov %3, %%esp\n\t" + "int %2\n\t" + "mov %%ebx, %%esp" : + "=a" (res) : + "a" (SYS_sleep), "n" (T_SYSCALL), "c" (p) : + "ebx"); +} + +void +validatetest(void) +{ + int hi, pid; + uint p; + + printf(stdout, "validate test\n"); + hi = 1100*1024; + + for(p = 0; p <= (uint)hi; p += 4096){ + if((pid = fork()) == 0){ + // try to crash the kernel by passing in a badly placed integer + validateint((int*)p); + exit(); + } + sleep(0); + sleep(0); + kill(pid); + wait(); + + // try to crash the kernel by passing in a bad string pointer + if(link("nosuchfile", (char*)p) != -1){ + printf(stdout, "link should not succeed\n"); + exit(); + } + } + + printf(stdout, "validate ok\n"); +} + +// does unintialized data start out zero? +char uninit[10000]; +void +bsstest(void) +{ + int i; + + printf(stdout, "bss test\n"); + for(i = 0; i < sizeof(uninit); i++){ + if(uninit[i] != '\0'){ + printf(stdout, "bss test failed\n"); + exit(); + } + } + printf(stdout, "bss test ok\n"); +} + +// does exec return an error if the arguments +// are larger than a page? or does it write +// below the stack and wreck the instructions/data? +void +bigargtest(void) +{ + int pid, fd; + + unlink("bigarg-ok"); + pid = fork(); + if(pid == 0){ + static char *args[MAXARG]; + int i; + for(i = 0; i < MAXARG-1; i++) + args[i] = "bigargs test: failed\n "; + args[MAXARG-1] = 0; + printf(stdout, "bigarg test\n"); + exec("echo", args); + printf(stdout, "bigarg test ok\n"); + fd = open("bigarg-ok", O_CREATE); + close(fd); + exit(); + } else if(pid < 0){ + printf(stdout, "bigargtest: fork failed\n"); + exit(); + } + wait(); + fd = open("bigarg-ok", 0); + if(fd < 0){ + printf(stdout, "bigarg test failed!\n"); + exit(); + } + close(fd); + unlink("bigarg-ok"); +} + +// what happens when the file system runs out of blocks? +// answer: balloc panics, so this test is not useful. +void +fsfull() +{ + int nfiles; + int fsblocks = 0; + + printf(1, "fsfull test\n"); + + for(nfiles = 0; ; nfiles++){ + char name[64]; + name[0] = 'f'; + name[1] = '0' + nfiles / 1000; + name[2] = '0' + (nfiles % 1000) / 100; + name[3] = '0' + (nfiles % 100) / 10; + name[4] = '0' + (nfiles % 10); + name[5] = '\0'; + printf(1, "writing %s\n", name); + int fd = open(name, O_CREATE|O_RDWR); + if(fd < 0){ + printf(1, "open %s failed\n", name); + break; + } + int total = 0; + while(1){ + int cc = write(fd, buf, 512); + if(cc < 512) + break; + total += cc; + fsblocks++; + } + printf(1, "wrote %d bytes\n", total); + close(fd); + if(total == 0) + break; + } + + while(nfiles >= 0){ + char name[64]; + name[0] = 'f'; + name[1] = '0' + nfiles / 1000; + name[2] = '0' + (nfiles % 1000) / 100; + name[3] = '0' + (nfiles % 100) / 10; + name[4] = '0' + (nfiles % 10); + name[5] = '\0'; + unlink(name); + nfiles--; + } + + printf(1, "fsfull test finished\n"); +} + +void +uio() +{ + #define RTC_ADDR 0x70 + #define RTC_DATA 0x71 + + ushort port = 0; + uchar val = 0; + int pid; + + printf(1, "uio test\n"); + pid = fork(); + if(pid == 0){ + port = RTC_ADDR; + val = 0x09; /* year */ + /* http://wiki.osdev.org/Inline_Assembly/Examples */ + asm volatile("outb %0,%1"::"a"(val), "d" (port)); + port = RTC_DATA; + asm volatile("inb %1,%0" : "=a" (val) : "d" (port)); + printf(1, "uio: uio succeeded; test FAILED\n"); + exit(); + } else if(pid < 0){ + printf (1, "fork failed\n"); + exit(); + } + wait(); + printf(1, "uio test done\n"); +} + +void argptest() +{ + int fd; + fd = open("init", O_RDONLY); + if (fd < 0) { + printf(2, "open failed\n"); + exit(); + } + read(fd, sbrk(0) - 1, -1); + close(fd); + printf(1, "arg test passed\n"); +} + +unsigned long randstate = 1; +unsigned int +rand() +{ + randstate = randstate * 1664525 + 1013904223; + return randstate; +} + +int +main(int argc, char *argv[]) +{ + printf(1, "usertests starting\n"); + + if(open("usertests.ran", 0) >= 0){ + printf(1, "already ran user tests -- rebuild fs.img\n"); + exit(); + } + close(open("usertests.ran", O_CREATE)); + + argptest(); + createdelete(); + linkunlink(); + concreate(); + fourfiles(); + sharedfd(); + + bigargtest(); + bigwrite(); + bigargtest(); + bsstest(); + sbrktest(); + validatetest(); + + opentest(); + writetest(); + writetest1(); + createtest(); + + openiputtest(); + exitiputtest(); + iputtest(); + + mem(); + pipe1(); + preempt(); + exitwait(); + + rmdot(); + fourteen(); + bigfile(); + subdir(); + linktest(); + unlinkread(); + dirfile(); + iref(); + forktest(); + bigdir(); // slow + + uio(); + + exectest(); + + exit(); +} diff --git a/xv6-public/usys.S b/xv6-public/usys.S new file mode 100644 index 0000000..a7b25ca --- /dev/null +++ b/xv6-public/usys.S @@ -0,0 +1,41 @@ +#include "syscall.h" +#include "traps.h" + +#define SYSCALL(name) \ + .globl name; \ + name: \ + movl $SYS_ ## name, %eax; \ + int $T_SYSCALL; \ + ret + +/* + * 什么时候执行这段? + * 应该系统启动过程就会执行,注册一个函数! + * 当调用name()时,自动进入这个函数,再转向sys_name()函数 +*/ + +SYSCALL(fork) +SYSCALL(exit) +SYSCALL(wait) +SYSCALL(pipe) +SYSCALL(read) +SYSCALL(write) +SYSCALL(close) +SYSCALL(kill) +SYSCALL(exec) +SYSCALL(open) +SYSCALL(mknod) +SYSCALL(unlink) +SYSCALL(fstat) +SYSCALL(link) +SYSCALL(mkdir) +SYSCALL(chdir) +SYSCALL(dup) +SYSCALL(dup2) +SYSCALL(getpid) +SYSCALL(sbrk) +SYSCALL(sleep) +SYSCALL(uptime) +SYSCALL(date) +SYSCALL(alarm) + diff --git a/xv6-public/uthread.c b/xv6-public/uthread.c new file mode 100644 index 0000000..66fc1f8 --- /dev/null +++ b/xv6-public/uthread.c @@ -0,0 +1,114 @@ +#include "types.h" +#include "stat.h" +#include "user.h" + +/* Possible states of a thread; */ +#define FREE 0x0 +#define RUNNING 0x1 +#define RUNNABLE 0x2 + +#define STACK_SIZE 8192 +#define MAX_THREAD 4 + +typedef struct thread thread_t, *thread_p; +typedef struct mutex mutex_t, *mutex_p; + +struct thread { + int sp; /* saved stack pointer */ + char stack[STACK_SIZE]; /* the thread's stack */ + int state; /* FREE, RUNNING, RUNNABLE */ +}; +static thread_t all_thread[MAX_THREAD]; +thread_p current_thread; +thread_p next_thread; +extern void thread_switch(void); + +void +thread_init(void) +{ + // main() is thread 0, which will make the first invocation to + // thread_schedule(). it needs a stack so that the first thread_switch() can + // save thread 0's state. thread_schedule() won't run the main thread ever + // again, because its state is set to RUNNING, and thread_schedule() selects + // a RUNNABLE thread. + current_thread = &all_thread[0]; + current_thread->state = RUNNING; +} + +static void +thread_schedule(void) +{ + thread_p t; + + /* Find another runnable thread. */ + next_thread = 0; + for (t = all_thread; t < all_thread + MAX_THREAD; t++) { + if (t->state == RUNNABLE && t != current_thread) { + next_thread = t; + break; + } + } + + if (t >= all_thread + MAX_THREAD && current_thread->state == RUNNABLE) { + /* The current thread is the only runnable thread; run it. */ + next_thread = current_thread; + } + + if (next_thread == 0) { + printf(2, "thread_schedule: no runnable threads\n"); + exit(); + } + + if (current_thread != next_thread) { /* switch threads? */ + next_thread->state = RUNNING; + thread_switch(); + } else + next_thread = 0; +} + +void +thread_create(void (*func)()) +{ + thread_p t; + + for (t = all_thread; t < all_thread + MAX_THREAD; t++) { + if (t->state == FREE) break; + } + t->sp = (int) (t->stack + STACK_SIZE); // set sp to the top of the stack + t->sp -= 4; // space for return address + * (int *) (t->sp) = (int)func; // push return address on stack + t->sp -= 32; // space for registers that thread_switch expects + t->state = RUNNABLE; +} + +void +thread_yield(void) +{ + current_thread->state = RUNNABLE; + thread_schedule(); +} + +static void +mythread(void) +{ + int i; + printf(1, "my thread running\n"); + for (i = 0; i < 100; i++) { + printf(1, "my thread 0x%x\n", (int) current_thread); + thread_yield(); + } + printf(1, "my thread: exit\n"); + current_thread->state = FREE; + thread_schedule(); +} + + +int +main(int argc, char *argv[]) +{ + thread_init(); + thread_create(mythread); + thread_create(mythread); + thread_schedule(); + return 0; +} diff --git a/xv6-public/uthread_switch.S b/xv6-public/uthread_switch.S new file mode 100644 index 0000000..698b0cd --- /dev/null +++ b/xv6-public/uthread_switch.S @@ -0,0 +1,28 @@ + .text + +/* Switch from current_thread to next_thread. Make next_thread + * the current_thread, and set next_thread to 0. + * Use eax as a temporary register; it is caller saved. + */ + .globl thread_switch +thread_switch: + /* YOUR CODE HERE */ + // C语言函数调用会压入 ip + pushal + // eax 指向 sp + movl current_thread, %eax + // save sp + movl %esp, (%eax) + + + movl next_thread, %eax + movl %eax, current_thread + // restore sp + movl (%eax), %esp + + popal + + movl $0x0, next_thread + + // popal 后esp指向return address + ret /* pop return address from stack */ diff --git a/xv6-public/vectors.pl b/xv6-public/vectors.pl new file mode 100644 index 0000000..57b49dd --- /dev/null +++ b/xv6-public/vectors.pl @@ -0,0 +1,47 @@ +#!/usr/bin/perl -w + +# Generate vectors.S, the trap/interrupt entry points. +# There has to be one entry point per interrupt number +# since otherwise there's no way for trap() to discover +# the interrupt number. + +print "# generated by vectors.pl - do not edit\n"; +print "# handlers\n"; +print ".globl alltraps\n"; +for(my $i = 0; $i < 256; $i++){ + print ".globl vector$i\n"; + print "vector$i:\n"; + if(!($i == 8 || ($i >= 10 && $i <= 14) || $i == 17)){ + print " pushl \$0\n"; + } + print " pushl \$$i\n"; + print " jmp alltraps\n"; +} + +print "\n# vector table\n"; +print ".data\n"; +print ".globl vectors\n"; +print "vectors:\n"; +for(my $i = 0; $i < 256; $i++){ + print " .long vector$i\n"; +} + +# sample output: +# # handlers +# .globl alltraps +# .globl vector0 +# vector0: +# pushl $0 +# pushl $0 +# jmp alltraps +# ... +# +# # vector table +# .data +# .globl vectors +# vectors: +# .long vector0 +# .long vector1 +# .long vector2 +# ... + diff --git a/xv6-public/vm.c b/xv6-public/vm.c new file mode 100644 index 0000000..0275cec --- /dev/null +++ b/xv6-public/vm.c @@ -0,0 +1,394 @@ +#include "param.h" +#include "types.h" +#include "defs.h" +#include "x86.h" +#include "memlayout.h" +#include "mmu.h" +#include "proc.h" +#include "elf.h" + +extern char data[]; // defined by kernel.ld +pde_t *kpgdir; // for use in scheduler() + +// Set up CPU's kernel segment descriptors. +// Run once on entry on each CPU. +void +seginit(void) +{ + struct cpu *c; + + // Map "logical" addresses to virtual addresses using identity map. + // Cannot share a CODE descriptor for both kernel and user + // because it would have to have DPL_USR, but the CPU forbids + // an interrupt from CPL=0 to DPL=3. + c = &cpus[cpuid()]; + c->gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, 0); + c->gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0); + c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, DPL_USER); + c->gdt[SEG_UDATA] = SEG(STA_W, 0, 0xffffffff, DPL_USER); + lgdt(c->gdt, sizeof(c->gdt)); +} + +// Return the address of the PTE in page table pgdir +// that corresponds to virtual address va. If alloc!=0, +// create any required page table pages. +static pte_t * +walkpgdir(pde_t *pgdir, const void *va, int alloc) +{ + pde_t *pde; + pte_t *pgtab; + + pde = &pgdir[PDX(va)]; + if(*pde & PTE_P){ + pgtab = (pte_t*)P2V(PTE_ADDR(*pde)); + } else { + if(!alloc || (pgtab = (pte_t*)kalloc()) == 0) + return 0; + // Make sure all those PTE_P bits are zero. + memset(pgtab, 0, PGSIZE); + // The permissions here are overly generous, but they can + // be further restricted by the permissions in the page table + // entries, if necessary. + *pde = V2P(pgtab) | PTE_P | PTE_W | PTE_U; + } + return &pgtab[PTX(va)]; +} + +// Create PTEs for virtual addresses starting at va that refer to +// physical addresses starting at pa. va and size might not +// be page-aligned. +int +mappages(pde_t *pgdir, void *va, uint size, uint pa, int perm) +{ + char *a, *last; + pte_t *pte; + + a = (char*)PGROUNDDOWN((uint)va); + last = (char*)PGROUNDDOWN(((uint)va) + size - 1); + for(;;){ + if((pte = walkpgdir(pgdir, a, 1)) == 0) + return -1; + if(*pte & PTE_P) + panic("remap"); + *pte = pa | perm | PTE_P; + if(a == last) + break; + a += PGSIZE; + pa += PGSIZE; + } + return 0; +} + +// There is one page table per process, plus one that's used when +// a CPU is not running any process (kpgdir). The kernel uses the +// current process's page table during system calls and interrupts; +// page protection bits prevent user code from using the kernel's +// mappings. +// +// setupkvm() and exec() set up every page table like this: +// +// 0..KERNBASE: user memory (text+data+stack+heap), mapped to +// phys memory allocated by the kernel +// KERNBASE..KERNBASE+EXTMEM: mapped to 0..EXTMEM (for I/O space) +// KERNBASE+EXTMEM..data: mapped to EXTMEM..V2P(data) +// for the kernel's instructions and r/o data +// data..KERNBASE+PHYSTOP: mapped to V2P(data)..PHYSTOP, +// rw data + free physical memory +// 0xfe000000..0: mapped direct (devices such as ioapic) +// +// The kernel allocates physical memory for its heap and for user memory +// between V2P(end) and the end of physical memory (PHYSTOP) +// (directly addressable from end..P2V(PHYSTOP)). + +// This table defines the kernel's mappings, which are present in +// every process's page table. +static struct kmap { + void *virt; + uint phys_start; + uint phys_end; + int perm; +} kmap[] = { + { (void*)KERNBASE, 0, EXTMEM, PTE_W}, // I/O space + { (void*)KERNLINK, V2P(KERNLINK), V2P(data), 0}, // kern text+rodata + { (void*)data, V2P(data), PHYSTOP, PTE_W}, // kern data+memory + { (void*)DEVSPACE, DEVSPACE, 0, PTE_W}, // more devices +}; + +// Set up kernel part of a page table. +pde_t* +setupkvm(void) +{ + pde_t *pgdir; + struct kmap *k; + + if((pgdir = (pde_t*)kalloc()) == 0) + return 0; + memset(pgdir, 0, PGSIZE); + if (P2V(PHYSTOP) > (void*)DEVSPACE) + panic("PHYSTOP too high"); + for(k = kmap; k < &kmap[NELEM(kmap)]; k++) + if(mappages(pgdir, k->virt, k->phys_end - k->phys_start, + (uint)k->phys_start, k->perm) < 0) { + freevm(pgdir); + return 0; + } + return pgdir; +} + +// Allocate one page table for the machine for the kernel address +// space for scheduler processes. +void +kvmalloc(void) +{ + kpgdir = setupkvm(); + switchkvm(); +} + +// Switch h/w page table register to the kernel-only page table, +// for when no process is running. +void +switchkvm(void) +{ + lcr3(V2P(kpgdir)); // switch to the kernel page table +} + +// Switch TSS and h/w page table to correspond to process p. +void +switchuvm(struct proc *p) +{ + if(p == 0) + panic("switchuvm: no process"); + if(p->kstack == 0) + panic("switchuvm: no kstack"); + if(p->pgdir == 0) + panic("switchuvm: no pgdir"); + + pushcli(); + mycpu()->gdt[SEG_TSS] = SEG16(STS_T32A, &mycpu()->ts, + sizeof(mycpu()->ts)-1, 0); + mycpu()->gdt[SEG_TSS].s = 0; + mycpu()->ts.ss0 = SEG_KDATA << 3; + mycpu()->ts.esp0 = (uint)p->kstack + KSTACKSIZE; + // setting IOPL=0 in eflags *and* iomb beyond the tss segment limit + // forbids I/O instructions (e.g., inb and outb) from user space + mycpu()->ts.iomb = (ushort) 0xFFFF; + ltr(SEG_TSS << 3); + lcr3(V2P(p->pgdir)); // switch to process's address space + popcli(); +} + +// Load the initcode into address 0 of pgdir. +// sz must be less than a page. +void +inituvm(pde_t *pgdir, char *init, uint sz) +{ + char *mem; + + if(sz >= PGSIZE) + panic("inituvm: more than a page"); + mem = kalloc(); + memset(mem, 0, PGSIZE); + mappages(pgdir, 0, PGSIZE, V2P(mem), PTE_W|PTE_U); + memmove(mem, init, sz); +} + +// Load a program segment into pgdir. addr must be page-aligned +// and the pages from addr to addr+sz must already be mapped. +int +loaduvm(pde_t *pgdir, char *addr, struct inode *ip, uint offset, uint sz) +{ + uint i, pa, n; + pte_t *pte; + + if((uint) addr % PGSIZE != 0) + panic("loaduvm: addr must be page aligned"); + for(i = 0; i < sz; i += PGSIZE){ + if((pte = walkpgdir(pgdir, addr+i, 0)) == 0) + panic("loaduvm: address should exist"); + pa = PTE_ADDR(*pte); + if(sz - i < PGSIZE) + n = sz - i; + else + n = PGSIZE; + if(readi(ip, P2V(pa), offset+i, n) != n) + return -1; + } + return 0; +} + +// Allocate page tables and physical memory to grow process from oldsz to +// newsz, which need not be page aligned. Returns new size or 0 on error. +int +allocuvm(pde_t *pgdir, uint oldsz, uint newsz) +{ + char *mem; + uint a; + + if(newsz >= KERNBASE) + return 0; + if(newsz < oldsz) + return oldsz; + + a = PGROUNDUP(oldsz); + for(; a < newsz; a += PGSIZE){ + mem = kalloc(); + if(mem == 0){ + cprintf("allocuvm out of memory\n"); + deallocuvm(pgdir, newsz, oldsz); + return 0; + } + memset(mem, 0, PGSIZE); + if(mappages(pgdir, (char*)a, PGSIZE, V2P(mem), PTE_W|PTE_U) < 0){ + cprintf("allocuvm out of memory (2)\n"); + deallocuvm(pgdir, newsz, oldsz); + kfree(mem); + return 0; + } + } + return newsz; +} + +// Deallocate user pages to bring the process size from oldsz to +// newsz. oldsz and newsz need not be page-aligned, nor does newsz +// need to be less than oldsz. oldsz can be larger than the actual +// process size. Returns the new process size. +int +deallocuvm(pde_t *pgdir, uint oldsz, uint newsz) +{ + pte_t *pte; + uint a, pa; + + if(newsz >= oldsz) + return oldsz; + + a = PGROUNDUP(newsz); + for(; a < oldsz; a += PGSIZE){ + pte = walkpgdir(pgdir, (char*)a, 0); + if(!pte) + a = PGADDR(PDX(a) + 1, 0, 0) - PGSIZE; + else if((*pte & PTE_P) != 0){ + pa = PTE_ADDR(*pte); + if(pa == 0) + panic("kfree"); + char *v = P2V(pa); + kfree(v); + *pte = 0; + } + } + return newsz; +} + +// Free a page table and all the physical memory pages +// in the user part. +void +freevm(pde_t *pgdir) +{ + uint i; + + if(pgdir == 0) + panic("freevm: no pgdir"); + deallocuvm(pgdir, KERNBASE, 0); + for(i = 0; i < NPDENTRIES; i++){ + if(pgdir[i] & PTE_P){ + char * v = P2V(PTE_ADDR(pgdir[i])); + kfree(v); + } + } + kfree((char*)pgdir); +} + +// Clear PTE_U on a page. Used to create an inaccessible +// page beneath the user stack. +void +clearpteu(pde_t *pgdir, char *uva) +{ + pte_t *pte; + + pte = walkpgdir(pgdir, uva, 0); + if(pte == 0) + panic("clearpteu"); + *pte &= ~PTE_U; +} + +// Given a parent process's page table, create a copy +// of it for a child. +pde_t* +copyuvm(pde_t *pgdir, uint sz) +{ + pde_t *d; + pte_t *pte; + uint pa, i, flags; + char *mem; + + if((d = setupkvm()) == 0) + return 0; + for(i = 0; i < sz; i += PGSIZE){ + if((pte = walkpgdir(pgdir, (void *) i, 0)) == 0) + panic("copyuvm: pte should exist"); + if(!(*pte & PTE_P)) + panic("copyuvm: page not present"); + pa = PTE_ADDR(*pte); + flags = PTE_FLAGS(*pte); + if((mem = kalloc()) == 0) + goto bad; + memmove(mem, (char*)P2V(pa), PGSIZE); + if(mappages(d, (void*)i, PGSIZE, V2P(mem), flags) < 0) { + kfree(mem); + goto bad; + } + } + return d; + +bad: + freevm(d); + return 0; +} + +//PAGEBREAK! +// Map user virtual address to kernel address. +char* +uva2ka(pde_t *pgdir, char *uva) +{ + pte_t *pte; + + pte = walkpgdir(pgdir, uva, 0); + if((*pte & PTE_P) == 0) + return 0; + if((*pte & PTE_U) == 0) + return 0; + return (char*)P2V(PTE_ADDR(*pte)); +} + +// Copy len bytes from p to user address va in page table pgdir. +// Most useful when pgdir is not the current page table. +// uva2ka ensures this only works for PTE_U pages. +int +copyout(pde_t *pgdir, uint va, void *p, uint len) +{ + char *buf, *pa0; + uint n, va0; + + buf = (char*)p; + while(len > 0){ + va0 = (uint)PGROUNDDOWN(va); + pa0 = uva2ka(pgdir, (char*)va0); + if(pa0 == 0) + return -1; + n = PGSIZE - (va - va0); + if(n > len) + n = len; + memmove(pa0 + (va - va0), buf, n); + len -= n; + buf += n; + va = va0 + PGSIZE; + } + return 0; +} + +//PAGEBREAK! +// Blank page. +//PAGEBREAK! +// Blank page. +//PAGEBREAK! +// Blank page. + diff --git a/xv6-public/wc.c b/xv6-public/wc.c new file mode 100644 index 0000000..d6a54df --- /dev/null +++ b/xv6-public/wc.c @@ -0,0 +1,54 @@ +#include "types.h" +#include "stat.h" +#include "user.h" + +char buf[512]; + +void +wc(int fd, char *name) +{ + int i, n; + int l, w, c, inword; + + l = w = c = 0; + inword = 0; + while((n = read(fd, buf, sizeof(buf))) > 0){ + for(i=0; i> 16; + + asm volatile("lgdt (%0)" : : "r" (pd)); +} + +struct gatedesc; + +static inline void +lidt(struct gatedesc *p, int size) +{ + volatile ushort pd[3]; + + pd[0] = size-1; + pd[1] = (uint)p; + pd[2] = (uint)p >> 16; + + asm volatile("lidt (%0)" : : "r" (pd)); +} + +static inline void +ltr(ushort sel) +{ + asm volatile("ltr %0" : : "r" (sel)); +} + +static inline uint +readeflags(void) +{ + uint eflags; + asm volatile("pushfl; popl %0" : "=r" (eflags)); + return eflags; +} + +static inline void +loadgs(ushort v) +{ + asm volatile("movw %0, %%gs" : : "r" (v)); +} + +static inline void +cli(void) +{ + asm volatile("cli"); +} + +static inline void +sti(void) +{ + asm volatile("sti"); +} + +static inline uint +xchg(volatile uint *addr, uint newval) +{ + uint result; + + // The + in "+m" denotes a read-modify-write operand. + asm volatile("lock; xchgl %0, %1" : + "+m" (*addr), "=a" (result) : + "1" (newval) : + "cc"); + return result; +} + +static inline uint +rcr2(void) +{ + uint val; + asm volatile("movl %%cr2,%0" : "=r" (val)); + return val; +} + +static inline void +lcr3(uint val) +{ + asm volatile("movl %0,%%cr3" : : "r" (val)); +} + +//PAGEBREAK: 36 +// Layout of the trap frame built on the stack by the +// hardware and by trapasm.S, and passed to trap(). +struct trapframe { + // registers as pushed by pusha + uint edi; + uint esi; + uint ebp; + uint oesp; // useless & ignored + uint ebx; + uint edx; + uint ecx; + uint eax; + + // rest of trap frame + ushort gs; + ushort padding1; + ushort fs; + ushort padding2; + ushort es; + ushort padding3; + ushort ds; + ushort padding4; + uint trapno; + + // below here defined by x86 hardware + uint err; + uint eip; + ushort cs; + ushort padding5; + uint eflags; + + // below here only when crossing rings, such as from user to kernel + uint esp; + ushort ss; + ushort padding6; +}; diff --git a/xv6-public/xv6.si4project/Backup/Makefile(2542) b/xv6-public/xv6.si4project/Backup/Makefile(2542) new file mode 100644 index 0000000..9870287 --- /dev/null +++ b/xv6-public/xv6.si4project/Backup/Makefile(2542) @@ -0,0 +1,291 @@ +OBJS = \ + bio.o\ + console.o\ + exec.o\ + file.o\ + fs.o\ + ide.o\ + ioapic.o\ + kalloc.o\ + kbd.o\ + lapic.o\ + log.o\ + main.o\ + mp.o\ + picirq.o\ + pipe.o\ + proc.o\ + sleeplock.o\ + spinlock.o\ + string.o\ + swtch.o\ + syscall.o\ + sysfile.o\ + sysproc.o\ + trapasm.o\ + trap.o\ + uart.o\ + vectors.o\ + vm.o\ + +# Cross-compiling (e.g., on Mac OS X) +# TOOLPREFIX = i386-jos-elf + +# Using native tools (e.g., on X86 Linux) +#TOOLPREFIX = + +# Try to infer the correct TOOLPREFIX if not set +ifndef TOOLPREFIX +TOOLPREFIX := $(shell if i386-jos-elf-objdump -i 2>&1 | grep '^elf32-i386$$' >/dev/null 2>&1; \ + then echo 'i386-jos-elf-'; \ + elif objdump -i 2>&1 | grep 'elf32-i386' >/dev/null 2>&1; \ + then echo ''; \ + else echo "***" 1>&2; \ + echo "*** Error: Couldn't find an i386-*-elf version of GCC/binutils." 1>&2; \ + echo "*** Is the directory with i386-jos-elf-gcc in your PATH?" 1>&2; \ + echo "*** If your i386-*-elf toolchain is installed with a command" 1>&2; \ + echo "*** prefix other than 'i386-jos-elf-', set your TOOLPREFIX" 1>&2; \ + echo "*** environment variable to that prefix and run 'make' again." 1>&2; \ + echo "*** To turn off this error, run 'gmake TOOLPREFIX= ...'." 1>&2; \ + echo "***" 1>&2; exit 1; fi) +endif + +# If the makefile can't find QEMU, specify its path here +# QEMU = qemu-system-i386 + +# Try to infer the correct QEMU +ifndef QEMU +QEMU = $(shell if which qemu > /dev/null; \ + then echo qemu; exit; \ + elif which qemu-system-i386 > /dev/null; \ + then echo qemu-system-i386; exit; \ + elif which qemu-system-x86_64 > /dev/null; \ + then echo qemu-system-x86_64; exit; \ + else \ + qemu=/Applications/Q.app/Contents/MacOS/i386-softmmu.app/Contents/MacOS/i386-softmmu; \ + if test -x $$qemu; then echo $$qemu; exit; fi; fi; \ + echo "***" 1>&2; \ + echo "*** Error: Couldn't find a working QEMU executable." 1>&2; \ + echo "*** Is the directory containing the qemu binary in your PATH" 1>&2; \ + echo "*** or have you tried setting the QEMU variable in Makefile?" 1>&2; \ + echo "***" 1>&2; exit 1) +endif + +CC = $(TOOLPREFIX)gcc +AS = $(TOOLPREFIX)gas +LD = $(TOOLPREFIX)ld +OBJCOPY = $(TOOLPREFIX)objcopy +OBJDUMP = $(TOOLPREFIX)objdump +CFLAGS = -fno-pic -static -fno-builtin -fno-strict-aliasing -O2 -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer +CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector) +ASFLAGS = -m32 -gdwarf-2 -Wa,-divide +# FreeBSD ld wants ``elf_i386_fbsd'' +LDFLAGS += -m $(shell $(LD) -V | grep elf_i386 2>/dev/null | head -n 1) + +# Disable PIE when possible (for Ubuntu 16.10 toolchain) +ifneq ($(shell $(CC) -dumpspecs 2>/dev/null | grep -e '[^f]no-pie'),) +CFLAGS += -fno-pie -no-pie +endif +ifneq ($(shell $(CC) -dumpspecs 2>/dev/null | grep -e '[^f]nopie'),) +CFLAGS += -fno-pie -nopie +endif + +xv6.img: bootblock kernel + dd if=/dev/zero of=xv6.img count=10000 + dd if=bootblock of=xv6.img conv=notrunc + dd if=kernel of=xv6.img seek=1 conv=notrunc + +xv6memfs.img: bootblock kernelmemfs + dd if=/dev/zero of=xv6memfs.img count=10000 + dd if=bootblock of=xv6memfs.img conv=notrunc + dd if=kernelmemfs of=xv6memfs.img seek=1 conv=notrunc + +bootblock: bootasm.S bootmain.c + $(CC) $(CFLAGS) -fno-pic -O -nostdinc -I. -c bootmain.c + $(CC) $(CFLAGS) -fno-pic -nostdinc -I. -c bootasm.S + $(LD) $(LDFLAGS) -N -e start -Ttext 0x7C00 -o bootblock.o bootasm.o bootmain.o + $(OBJDUMP) -S bootblock.o > bootblock.asm + $(OBJCOPY) -S -O binary -j .text bootblock.o bootblock + ./sign.pl bootblock + +entryother: entryother.S + $(CC) $(CFLAGS) -fno-pic -nostdinc -I. -c entryother.S + $(LD) $(LDFLAGS) -N -e start -Ttext 0x7000 -o bootblockother.o entryother.o + $(OBJCOPY) -S -O binary -j .text bootblockother.o entryother + $(OBJDUMP) -S bootblockother.o > entryother.asm + +initcode: initcode.S + $(CC) $(CFLAGS) -nostdinc -I. -c initcode.S + $(LD) $(LDFLAGS) -N -e start -Ttext 0 -o initcode.out initcode.o + $(OBJCOPY) -S -O binary initcode.out initcode + $(OBJDUMP) -S initcode.o > initcode.asm + +kernel: $(OBJS) entry.o entryother initcode kernel.ld + $(LD) $(LDFLAGS) -T kernel.ld -o kernel entry.o $(OBJS) -b binary initcode entryother + $(OBJDUMP) -S kernel > kernel.asm + $(OBJDUMP) -t kernel | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernel.sym + +# kernelmemfs is a copy of kernel that maintains the +# disk image in memory instead of writing to a disk. +# This is not so useful for testing persistent storage or +# exploring disk buffering implementations, but it is +# great for testing the kernel on real hardware without +# needing a scratch disk. +MEMFSOBJS = $(filter-out ide.o,$(OBJS)) memide.o +kernelmemfs: $(MEMFSOBJS) entry.o entryother initcode kernel.ld fs.img + $(LD) $(LDFLAGS) -T kernel.ld -o kernelmemfs entry.o $(MEMFSOBJS) -b binary initcode entryother fs.img + $(OBJDUMP) -S kernelmemfs > kernelmemfs.asm + $(OBJDUMP) -t kernelmemfs | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernelmemfs.sym + +tags: $(OBJS) entryother.S _init + etags *.S *.c + +vectors.S: vectors.pl + ./vectors.pl > vectors.S + +ULIB = ulib.o usys.o printf.o umalloc.o + +_%: %.o $(ULIB) + $(LD) $(LDFLAGS) -N -e main -Ttext 0 -o $@ $^ + $(OBJDUMP) -S $@ > $*.asm + $(OBJDUMP) -t $@ | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $*.sym + +_forktest: forktest.o $(ULIB) + # forktest has less library code linked in - needs to be small + # in order to be able to max out the proc table. + $(LD) $(LDFLAGS) -N -e main -Ttext 0 -o _forktest forktest.o ulib.o usys.o + $(OBJDUMP) -S _forktest > forktest.asm + +mkfs: mkfs.c fs.h + gcc -Werror -Wall -o mkfs mkfs.c + +# Prevent deletion of intermediate files, e.g. cat.o, after first build, so +# that disk image changes after first build are persistent until clean. More +# details: +# http://www.gnu.org/software/make/manual/html_node/Chained-Rules.html +.PRECIOUS: %.o + +UPROGS=\ + _cat\ + _echo\ + _forktest\ + _grep\ + _init\ + _kill\ + _ln\ + _ls\ + _mkdir\ + _rm\ + _sh\ + _stressfs\ + _usertests\ + _wc\ + _zombie\ + _date\ + _alarmtest\ + +fs.img: mkfs README $(UPROGS) + ./mkfs fs.img README $(UPROGS) + +-include *.d + +clean: + rm -f *.tex *.dvi *.idx *.aux *.log *.ind *.ilg \ + *.o *.d *.asm *.sym vectors.S bootblock entryother \ + initcode initcode.out kernel xv6.img fs.img kernelmemfs \ + xv6memfs.img mkfs .gdbinit \ + $(UPROGS) + +# make a printout +FILES = $(shell grep -v '^\#' runoff.list) +PRINT = runoff.list runoff.spec README toc.hdr toc.ftr $(FILES) + +xv6.pdf: $(PRINT) + ./runoff + ls -l xv6.pdf + +print: xv6.pdf + +# run in emulators + +bochs : fs.img xv6.img + if [ ! -e .bochsrc ]; then ln -s dot-bochsrc .bochsrc; fi + bochs -q + +# try to generate a unique GDB port +GDBPORT = $(shell expr `id -u` % 5000 + 25000) +# QEMU's gdb stub command line changed in 0.11 +QEMUGDB = $(shell if $(QEMU) -help | grep -q '^-gdb'; \ + then echo "-gdb tcp::$(GDBPORT)"; \ + else echo "-s -p $(GDBPORT)"; fi) +ifndef CPUS +CPUS := 2 +endif +QEMUOPTS = -drive file=fs.img,index=1,media=disk,format=raw -drive file=xv6.img,index=0,media=disk,format=raw -smp $(CPUS) -m 512 $(QEMUEXTRA) + +gdb: + gdb -x .gdbinit + +qemu: fs.img xv6.img + $(QEMU) -serial mon:stdio $(QEMUOPTS) + +qemu-memfs: xv6memfs.img + $(QEMU) -drive file=xv6memfs.img,index=0,media=disk,format=raw -smp $(CPUS) -m 256 + +qemu-nox: fs.img xv6.img + $(QEMU) -nographic $(QEMUOPTS) + +.gdbinit: .gdbinit.tmpl + sed "s/localhost:1234/localhost:$(GDBPORT)/" < $^ > $@ + +qemu-gdb: fs.img xv6.img .gdbinit + @echo "*** Now run 'gdb'." 1>&2 + $(QEMU) -serial mon:stdio $(QEMUOPTS) -S $(QEMUGDB) + +qemu-nox-gdb: fs.img xv6.img .gdbinit + @echo "*** Now run 'gdb'." 1>&2 + $(QEMU) -nographic $(QEMUOPTS) -S $(QEMUGDB) + +# CUT HERE +# prepare dist for students +# after running make dist, probably want to +# rename it to rev0 or rev1 or so on and then +# check in that version. + +EXTRA=\ + mkfs.c ulib.c user.h cat.c echo.c forktest.c grep.c kill.c\ + ln.c ls.c mkdir.c rm.c stressfs.c usertests.c wc.c zombie.c\ + printf.c umalloc.c\ + README dot-bochsrc *.pl toc.* runoff runoff1 runoff.list\ + .gdbinit.tmpl gdbutil\ + +dist: + rm -rf dist + mkdir dist + for i in $(FILES); \ + do \ + grep -v PAGEBREAK $$i >dist/$$i; \ + done + sed '/CUT HERE/,$$d' Makefile >dist/Makefile + echo >dist/runoff.spec + cp $(EXTRA) dist + +dist-test: + rm -rf dist + make dist + rm -rf dist-test + mkdir dist-test + cp dist/* dist-test + cd dist-test; $(MAKE) print + cd dist-test; $(MAKE) bochs || true + cd dist-test; $(MAKE) qemu + +# update this rule (change rev#) when it is time to +# make a new revision. +tar: + rm -rf /tmp/xv6 + mkdir -p /tmp/xv6 + cp dist/* dist/.gdbinit.tmpl /tmp/xv6 + (cd /tmp; tar cf - xv6) | gzip >xv6-rev10.tar.gz # the next one will be 10 (9/17) + +.PHONY: dist-test dist diff --git a/xv6-public/xv6.si4project/Backup/Makefile(5214) b/xv6-public/xv6.si4project/Backup/Makefile(5214) new file mode 100644 index 0000000..bddf7a2 --- /dev/null +++ b/xv6-public/xv6.si4project/Backup/Makefile(5214) @@ -0,0 +1,290 @@ +OBJS = \ + bio.o\ + console.o\ + exec.o\ + file.o\ + fs.o\ + ide.o\ + ioapic.o\ + kalloc.o\ + kbd.o\ + lapic.o\ + log.o\ + main.o\ + mp.o\ + picirq.o\ + pipe.o\ + proc.o\ + sleeplock.o\ + spinlock.o\ + string.o\ + swtch.o\ + syscall.o\ + sysfile.o\ + sysproc.o\ + trapasm.o\ + trap.o\ + uart.o\ + vectors.o\ + vm.o\ + +# Cross-compiling (e.g., on Mac OS X) +# TOOLPREFIX = i386-jos-elf + +# Using native tools (e.g., on X86 Linux) +#TOOLPREFIX = + +# Try to infer the correct TOOLPREFIX if not set +ifndef TOOLPREFIX +TOOLPREFIX := $(shell if i386-jos-elf-objdump -i 2>&1 | grep '^elf32-i386$$' >/dev/null 2>&1; \ + then echo 'i386-jos-elf-'; \ + elif objdump -i 2>&1 | grep 'elf32-i386' >/dev/null 2>&1; \ + then echo ''; \ + else echo "***" 1>&2; \ + echo "*** Error: Couldn't find an i386-*-elf version of GCC/binutils." 1>&2; \ + echo "*** Is the directory with i386-jos-elf-gcc in your PATH?" 1>&2; \ + echo "*** If your i386-*-elf toolchain is installed with a command" 1>&2; \ + echo "*** prefix other than 'i386-jos-elf-', set your TOOLPREFIX" 1>&2; \ + echo "*** environment variable to that prefix and run 'make' again." 1>&2; \ + echo "*** To turn off this error, run 'gmake TOOLPREFIX= ...'." 1>&2; \ + echo "***" 1>&2; exit 1; fi) +endif + +# If the makefile can't find QEMU, specify its path here +# QEMU = qemu-system-i386 + +# Try to infer the correct QEMU +ifndef QEMU +QEMU = $(shell if which qemu > /dev/null; \ + then echo qemu; exit; \ + elif which qemu-system-i386 > /dev/null; \ + then echo qemu-system-i386; exit; \ + elif which qemu-system-x86_64 > /dev/null; \ + then echo qemu-system-x86_64; exit; \ + else \ + qemu=/Applications/Q.app/Contents/MacOS/i386-softmmu.app/Contents/MacOS/i386-softmmu; \ + if test -x $$qemu; then echo $$qemu; exit; fi; fi; \ + echo "***" 1>&2; \ + echo "*** Error: Couldn't find a working QEMU executable." 1>&2; \ + echo "*** Is the directory containing the qemu binary in your PATH" 1>&2; \ + echo "*** or have you tried setting the QEMU variable in Makefile?" 1>&2; \ + echo "***" 1>&2; exit 1) +endif + +CC = $(TOOLPREFIX)gcc +AS = $(TOOLPREFIX)gas +LD = $(TOOLPREFIX)ld +OBJCOPY = $(TOOLPREFIX)objcopy +OBJDUMP = $(TOOLPREFIX)objdump +CFLAGS = -fno-pic -static -fno-builtin -fno-strict-aliasing -O2 -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer +CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector) +ASFLAGS = -m32 -gdwarf-2 -Wa,-divide +# FreeBSD ld wants ``elf_i386_fbsd'' +LDFLAGS += -m $(shell $(LD) -V | grep elf_i386 2>/dev/null | head -n 1) + +# Disable PIE when possible (for Ubuntu 16.10 toolchain) +ifneq ($(shell $(CC) -dumpspecs 2>/dev/null | grep -e '[^f]no-pie'),) +CFLAGS += -fno-pie -no-pie +endif +ifneq ($(shell $(CC) -dumpspecs 2>/dev/null | grep -e '[^f]nopie'),) +CFLAGS += -fno-pie -nopie +endif + +xv6.img: bootblock kernel + dd if=/dev/zero of=xv6.img count=10000 + dd if=bootblock of=xv6.img conv=notrunc + dd if=kernel of=xv6.img seek=1 conv=notrunc + +xv6memfs.img: bootblock kernelmemfs + dd if=/dev/zero of=xv6memfs.img count=10000 + dd if=bootblock of=xv6memfs.img conv=notrunc + dd if=kernelmemfs of=xv6memfs.img seek=1 conv=notrunc + +bootblock: bootasm.S bootmain.c + $(CC) $(CFLAGS) -fno-pic -O -nostdinc -I. -c bootmain.c + $(CC) $(CFLAGS) -fno-pic -nostdinc -I. -c bootasm.S + $(LD) $(LDFLAGS) -N -e start -Ttext 0x7C00 -o bootblock.o bootasm.o bootmain.o + $(OBJDUMP) -S bootblock.o > bootblock.asm + $(OBJCOPY) -S -O binary -j .text bootblock.o bootblock + ./sign.pl bootblock + +entryother: entryother.S + $(CC) $(CFLAGS) -fno-pic -nostdinc -I. -c entryother.S + $(LD) $(LDFLAGS) -N -e start -Ttext 0x7000 -o bootblockother.o entryother.o + $(OBJCOPY) -S -O binary -j .text bootblockother.o entryother + $(OBJDUMP) -S bootblockother.o > entryother.asm + +initcode: initcode.S + $(CC) $(CFLAGS) -nostdinc -I. -c initcode.S + $(LD) $(LDFLAGS) -N -e start -Ttext 0 -o initcode.out initcode.o + $(OBJCOPY) -S -O binary initcode.out initcode + $(OBJDUMP) -S initcode.o > initcode.asm + +kernel: $(OBJS) entry.o entryother initcode kernel.ld + $(LD) $(LDFLAGS) -T kernel.ld -o kernel entry.o $(OBJS) -b binary initcode entryother + $(OBJDUMP) -S kernel > kernel.asm + $(OBJDUMP) -t kernel | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernel.sym + +# kernelmemfs is a copy of kernel that maintains the +# disk image in memory instead of writing to a disk. +# This is not so useful for testing persistent storage or +# exploring disk buffering implementations, but it is +# great for testing the kernel on real hardware without +# needing a scratch disk. +MEMFSOBJS = $(filter-out ide.o,$(OBJS)) memide.o +kernelmemfs: $(MEMFSOBJS) entry.o entryother initcode kernel.ld fs.img + $(LD) $(LDFLAGS) -T kernel.ld -o kernelmemfs entry.o $(MEMFSOBJS) -b binary initcode entryother fs.img + $(OBJDUMP) -S kernelmemfs > kernelmemfs.asm + $(OBJDUMP) -t kernelmemfs | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernelmemfs.sym + +tags: $(OBJS) entryother.S _init + etags *.S *.c + +vectors.S: vectors.pl + ./vectors.pl > vectors.S + +ULIB = ulib.o usys.o printf.o umalloc.o + +_%: %.o $(ULIB) + $(LD) $(LDFLAGS) -N -e main -Ttext 0 -o $@ $^ + $(OBJDUMP) -S $@ > $*.asm + $(OBJDUMP) -t $@ | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $*.sym + +_forktest: forktest.o $(ULIB) + # forktest has less library code linked in - needs to be small + # in order to be able to max out the proc table. + $(LD) $(LDFLAGS) -N -e main -Ttext 0 -o _forktest forktest.o ulib.o usys.o + $(OBJDUMP) -S _forktest > forktest.asm + +mkfs: mkfs.c fs.h + gcc -Werror -Wall -o mkfs mkfs.c + +# Prevent deletion of intermediate files, e.g. cat.o, after first build, so +# that disk image changes after first build are persistent until clean. More +# details: +# http://www.gnu.org/software/make/manual/html_node/Chained-Rules.html +.PRECIOUS: %.o + +UPROGS=\ + _cat\ + _echo\ + _forktest\ + _grep\ + _init\ + _kill\ + _ln\ + _ls\ + _mkdir\ + _rm\ + _sh\ + _stressfs\ + _usertests\ + _wc\ + _zombie\ + _date\ + +fs.img: mkfs README $(UPROGS) + ./mkfs fs.img README $(UPROGS) + +-include *.d + +clean: + rm -f *.tex *.dvi *.idx *.aux *.log *.ind *.ilg \ + *.o *.d *.asm *.sym vectors.S bootblock entryother \ + initcode initcode.out kernel xv6.img fs.img kernelmemfs \ + xv6memfs.img mkfs .gdbinit \ + $(UPROGS) + +# make a printout +FILES = $(shell grep -v '^\#' runoff.list) +PRINT = runoff.list runoff.spec README toc.hdr toc.ftr $(FILES) + +xv6.pdf: $(PRINT) + ./runoff + ls -l xv6.pdf + +print: xv6.pdf + +# run in emulators + +bochs : fs.img xv6.img + if [ ! -e .bochsrc ]; then ln -s dot-bochsrc .bochsrc; fi + bochs -q + +# try to generate a unique GDB port +GDBPORT = $(shell expr `id -u` % 5000 + 25000) +# QEMU's gdb stub command line changed in 0.11 +QEMUGDB = $(shell if $(QEMU) -help | grep -q '^-gdb'; \ + then echo "-gdb tcp::$(GDBPORT)"; \ + else echo "-s -p $(GDBPORT)"; fi) +ifndef CPUS +CPUS := 2 +endif +QEMUOPTS = -drive file=fs.img,index=1,media=disk,format=raw -drive file=xv6.img,index=0,media=disk,format=raw -smp $(CPUS) -m 512 $(QEMUEXTRA) + +gdb: + gdb -x .gdbinit + +qemu: fs.img xv6.img + $(QEMU) -serial mon:stdio $(QEMUOPTS) + +qemu-memfs: xv6memfs.img + $(QEMU) -drive file=xv6memfs.img,index=0,media=disk,format=raw -smp $(CPUS) -m 256 + +qemu-nox: fs.img xv6.img + $(QEMU) -nographic $(QEMUOPTS) + +.gdbinit: .gdbinit.tmpl + sed "s/localhost:1234/localhost:$(GDBPORT)/" < $^ > $@ + +qemu-gdb: fs.img xv6.img .gdbinit + @echo "*** Now run 'gdb'." 1>&2 + $(QEMU) -serial mon:stdio $(QEMUOPTS) -S $(QEMUGDB) + +qemu-nox-gdb: fs.img xv6.img .gdbinit + @echo "*** Now run 'gdb'." 1>&2 + $(QEMU) -nographic $(QEMUOPTS) -S $(QEMUGDB) + +# CUT HERE +# prepare dist for students +# after running make dist, probably want to +# rename it to rev0 or rev1 or so on and then +# check in that version. + +EXTRA=\ + mkfs.c ulib.c user.h cat.c echo.c forktest.c grep.c kill.c\ + ln.c ls.c mkdir.c rm.c stressfs.c usertests.c wc.c zombie.c\ + printf.c umalloc.c\ + README dot-bochsrc *.pl toc.* runoff runoff1 runoff.list\ + .gdbinit.tmpl gdbutil\ + +dist: + rm -rf dist + mkdir dist + for i in $(FILES); \ + do \ + grep -v PAGEBREAK $$i >dist/$$i; \ + done + sed '/CUT HERE/,$$d' Makefile >dist/Makefile + echo >dist/runoff.spec + cp $(EXTRA) dist + +dist-test: + rm -rf dist + make dist + rm -rf dist-test + mkdir dist-test + cp dist/* dist-test + cd dist-test; $(MAKE) print + cd dist-test; $(MAKE) bochs || true + cd dist-test; $(MAKE) qemu + +# update this rule (change rev#) when it is time to +# make a new revision. +tar: + rm -rf /tmp/xv6 + mkdir -p /tmp/xv6 + cp dist/* dist/.gdbinit.tmpl /tmp/xv6 + (cd /tmp; tar cf - xv6) | gzip >xv6-rev10.tar.gz # the next one will be 10 (9/17) + +.PHONY: dist-test dist diff --git a/xv6-public/xv6.si4project/Backup/Makefile(7715) b/xv6-public/xv6.si4project/Backup/Makefile(7715) new file mode 100644 index 0000000..d6925de --- /dev/null +++ b/xv6-public/xv6.si4project/Backup/Makefile(7715) @@ -0,0 +1,296 @@ +OBJS = \ + bio.o\ + console.o\ + exec.o\ + file.o\ + fs.o\ + ide.o\ + ioapic.o\ + kalloc.o\ + kbd.o\ + lapic.o\ + log.o\ + main.o\ + mp.o\ + picirq.o\ + pipe.o\ + proc.o\ + sleeplock.o\ + spinlock.o\ + string.o\ + swtch.o\ + syscall.o\ + sysfile.o\ + sysproc.o\ + trapasm.o\ + trap.o\ + uart.o\ + vectors.o\ + vm.o\ + +# Cross-compiling (e.g., on Mac OS X) +# TOOLPREFIX = i386-jos-elf + +# Using native tools (e.g., on X86 Linux) +#TOOLPREFIX = + +# Try to infer the correct TOOLPREFIX if not set +ifndef TOOLPREFIX +TOOLPREFIX := $(shell if i386-jos-elf-objdump -i 2>&1 | grep '^elf32-i386$$' >/dev/null 2>&1; \ + then echo 'i386-jos-elf-'; \ + elif objdump -i 2>&1 | grep 'elf32-i386' >/dev/null 2>&1; \ + then echo ''; \ + else echo "***" 1>&2; \ + echo "*** Error: Couldn't find an i386-*-elf version of GCC/binutils." 1>&2; \ + echo "*** Is the directory with i386-jos-elf-gcc in your PATH?" 1>&2; \ + echo "*** If your i386-*-elf toolchain is installed with a command" 1>&2; \ + echo "*** prefix other than 'i386-jos-elf-', set your TOOLPREFIX" 1>&2; \ + echo "*** environment variable to that prefix and run 'make' again." 1>&2; \ + echo "*** To turn off this error, run 'gmake TOOLPREFIX= ...'." 1>&2; \ + echo "***" 1>&2; exit 1; fi) +endif + +# If the makefile can't find QEMU, specify its path here +# QEMU = qemu-system-i386 + +# Try to infer the correct QEMU +ifndef QEMU +QEMU = $(shell if which qemu > /dev/null; \ + then echo qemu; exit; \ + elif which qemu-system-i386 > /dev/null; \ + then echo qemu-system-i386; exit; \ + elif which qemu-system-x86_64 > /dev/null; \ + then echo qemu-system-x86_64; exit; \ + else \ + qemu=/Applications/Q.app/Contents/MacOS/i386-softmmu.app/Contents/MacOS/i386-softmmu; \ + if test -x $$qemu; then echo $$qemu; exit; fi; fi; \ + echo "***" 1>&2; \ + echo "*** Error: Couldn't find a working QEMU executable." 1>&2; \ + echo "*** Is the directory containing the qemu binary in your PATH" 1>&2; \ + echo "*** or have you tried setting the QEMU variable in Makefile?" 1>&2; \ + echo "***" 1>&2; exit 1) +endif + +CC = $(TOOLPREFIX)gcc +AS = $(TOOLPREFIX)gas +LD = $(TOOLPREFIX)ld +OBJCOPY = $(TOOLPREFIX)objcopy +OBJDUMP = $(TOOLPREFIX)objdump +CFLAGS = -fno-pic -static -fno-builtin -fno-strict-aliasing -O2 -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer +CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector) +ASFLAGS = -m32 -gdwarf-2 -Wa,-divide +# FreeBSD ld wants ``elf_i386_fbsd'' +LDFLAGS += -m $(shell $(LD) -V | grep elf_i386 2>/dev/null | head -n 1) + +# Disable PIE when possible (for Ubuntu 16.10 toolchain) +ifneq ($(shell $(CC) -dumpspecs 2>/dev/null | grep -e '[^f]no-pie'),) +CFLAGS += -fno-pie -no-pie +endif +ifneq ($(shell $(CC) -dumpspecs 2>/dev/null | grep -e '[^f]nopie'),) +CFLAGS += -fno-pie -nopie +endif + +xv6.img: bootblock kernel + dd if=/dev/zero of=xv6.img count=10000 + dd if=bootblock of=xv6.img conv=notrunc + dd if=kernel of=xv6.img seek=1 conv=notrunc + +xv6memfs.img: bootblock kernelmemfs + dd if=/dev/zero of=xv6memfs.img count=10000 + dd if=bootblock of=xv6memfs.img conv=notrunc + dd if=kernelmemfs of=xv6memfs.img seek=1 conv=notrunc + +bootblock: bootasm.S bootmain.c + $(CC) $(CFLAGS) -fno-pic -O -nostdinc -I. -c bootmain.c + $(CC) $(CFLAGS) -fno-pic -nostdinc -I. -c bootasm.S + $(LD) $(LDFLAGS) -N -e start -Ttext 0x7C00 -o bootblock.o bootasm.o bootmain.o + $(OBJDUMP) -S bootblock.o > bootblock.asm + $(OBJCOPY) -S -O binary -j .text bootblock.o bootblock + ./sign.pl bootblock + +entryother: entryother.S + $(CC) $(CFLAGS) -fno-pic -nostdinc -I. -c entryother.S + $(LD) $(LDFLAGS) -N -e start -Ttext 0x7000 -o bootblockother.o entryother.o + $(OBJCOPY) -S -O binary -j .text bootblockother.o entryother + $(OBJDUMP) -S bootblockother.o > entryother.asm + +initcode: initcode.S + $(CC) $(CFLAGS) -nostdinc -I. -c initcode.S + $(LD) $(LDFLAGS) -N -e start -Ttext 0 -o initcode.out initcode.o + $(OBJCOPY) -S -O binary initcode.out initcode + $(OBJDUMP) -S initcode.o > initcode.asm + +kernel: $(OBJS) entry.o entryother initcode kernel.ld + $(LD) $(LDFLAGS) -T kernel.ld -o kernel entry.o $(OBJS) -b binary initcode entryother + $(OBJDUMP) -S kernel > kernel.asm + $(OBJDUMP) -t kernel | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernel.sym + +_uthread: uthread.o uthread_switch.o +$(LD) $(LDFLAGS) -N -e main -Ttext 0 -o _uthread uthread.o uthread_switch.o $(ULIB) +$(OBJDUMP) -S _uthread > uthread.asm + +# kernelmemfs is a copy of kernel that maintains the +# disk image in memory instead of writing to a disk. +# This is not so useful for testing persistent storage or +# exploring disk buffering implementations, but it is +# great for testing the kernel on real hardware without +# needing a scratch disk. +MEMFSOBJS = $(filter-out ide.o,$(OBJS)) memide.o +kernelmemfs: $(MEMFSOBJS) entry.o entryother initcode kernel.ld fs.img + $(LD) $(LDFLAGS) -T kernel.ld -o kernelmemfs entry.o $(MEMFSOBJS) -b binary initcode entryother fs.img + $(OBJDUMP) -S kernelmemfs > kernelmemfs.asm + $(OBJDUMP) -t kernelmemfs | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernelmemfs.sym + +tags: $(OBJS) entryother.S _init + etags *.S *.c + +vectors.S: vectors.pl + ./vectors.pl > vectors.S + +ULIB = ulib.o usys.o printf.o umalloc.o + +_%: %.o $(ULIB) + $(LD) $(LDFLAGS) -N -e main -Ttext 0 -o $@ $^ + $(OBJDUMP) -S $@ > $*.asm + $(OBJDUMP) -t $@ | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $*.sym + +_forktest: forktest.o $(ULIB) + # forktest has less library code linked in - needs to be small + # in order to be able to max out the proc table. + $(LD) $(LDFLAGS) -N -e main -Ttext 0 -o _forktest forktest.o ulib.o usys.o + $(OBJDUMP) -S _forktest > forktest.asm + +mkfs: mkfs.c fs.h + gcc -Werror -Wall -o mkfs mkfs.c + +# Prevent deletion of intermediate files, e.g. cat.o, after first build, so +# that disk image changes after first build are persistent until clean. More +# details: +# http://www.gnu.org/software/make/manual/html_node/Chained-Rules.html +.PRECIOUS: %.o + +UPROGS=\ + _cat\ + _echo\ + _forktest\ + _grep\ + _init\ + _kill\ + _ln\ + _ls\ + _mkdir\ + _rm\ + _sh\ + _stressfs\ + _usertests\ + _wc\ + _zombie\ + _date\ + _alarmtest\ + _uthread\ + +fs.img: mkfs README $(UPROGS) + ./mkfs fs.img README $(UPROGS) + +-include *.d + +clean: + rm -f *.tex *.dvi *.idx *.aux *.log *.ind *.ilg \ + *.o *.d *.asm *.sym vectors.S bootblock entryother \ + initcode initcode.out kernel xv6.img fs.img kernelmemfs \ + xv6memfs.img mkfs .gdbinit \ + $(UPROGS) + +# make a printout +FILES = $(shell grep -v '^\#' runoff.list) +PRINT = runoff.list runoff.spec README toc.hdr toc.ftr $(FILES) + +xv6.pdf: $(PRINT) + ./runoff + ls -l xv6.pdf + +print: xv6.pdf + +# run in emulators + +bochs : fs.img xv6.img + if [ ! -e .bochsrc ]; then ln -s dot-bochsrc .bochsrc; fi + bochs -q + +# try to generate a unique GDB port +GDBPORT = $(shell expr `id -u` % 5000 + 25000) +# QEMU's gdb stub command line changed in 0.11 +QEMUGDB = $(shell if $(QEMU) -help | grep -q '^-gdb'; \ + then echo "-gdb tcp::$(GDBPORT)"; \ + else echo "-s -p $(GDBPORT)"; fi) +ifndef CPUS +CPUS := 2 +endif +QEMUOPTS = -drive file=fs.img,index=1,media=disk,format=raw -drive file=xv6.img,index=0,media=disk,format=raw -smp $(CPUS) -m 512 $(QEMUEXTRA) + +gdb: + gdb -x .gdbinit + +qemu: fs.img xv6.img + $(QEMU) -serial mon:stdio $(QEMUOPTS) + +qemu-memfs: xv6memfs.img + $(QEMU) -drive file=xv6memfs.img,index=0,media=disk,format=raw -smp $(CPUS) -m 256 + +qemu-nox: fs.img xv6.img + $(QEMU) -nographic $(QEMUOPTS) + +.gdbinit: .gdbinit.tmpl + sed "s/localhost:1234/localhost:$(GDBPORT)/" < $^ > $@ + +qemu-gdb: fs.img xv6.img .gdbinit + @echo "*** Now run 'gdb'." 1>&2 + $(QEMU) -serial mon:stdio $(QEMUOPTS) -S $(QEMUGDB) + +qemu-nox-gdb: fs.img xv6.img .gdbinit + @echo "*** Now run 'gdb'." 1>&2 + $(QEMU) -nographic $(QEMUOPTS) -S $(QEMUGDB) + +# CUT HERE +# prepare dist for students +# after running make dist, probably want to +# rename it to rev0 or rev1 or so on and then +# check in that version. + +EXTRA=\ + mkfs.c ulib.c user.h cat.c echo.c forktest.c grep.c kill.c\ + ln.c ls.c mkdir.c rm.c stressfs.c usertests.c wc.c zombie.c\ + printf.c umalloc.c\ + README dot-bochsrc *.pl toc.* runoff runoff1 runoff.list\ + .gdbinit.tmpl gdbutil\ + +dist: + rm -rf dist + mkdir dist + for i in $(FILES); \ + do \ + grep -v PAGEBREAK $$i >dist/$$i; \ + done + sed '/CUT HERE/,$$d' Makefile >dist/Makefile + echo >dist/runoff.spec + cp $(EXTRA) dist + +dist-test: + rm -rf dist + make dist + rm -rf dist-test + mkdir dist-test + cp dist/* dist-test + cd dist-test; $(MAKE) print + cd dist-test; $(MAKE) bochs || true + cd dist-test; $(MAKE) qemu + +# update this rule (change rev#) when it is time to +# make a new revision. +tar: + rm -rf /tmp/xv6 + mkdir -p /tmp/xv6 + cp dist/* dist/.gdbinit.tmpl /tmp/xv6 + (cd /tmp; tar cf - xv6) | gzip >xv6-rev10.tar.gz # the next one will be 10 (9/17) + +.PHONY: dist-test dist diff --git a/xv6-public/xv6.si4project/Backup/alarmtest(5755).c b/xv6-public/xv6.si4project/Backup/alarmtest(5755).c new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/xv6-public/xv6.si4project/Backup/alarmtest(5755).c @@ -0,0 +1 @@ + diff --git a/xv6-public/xv6.si4project/Backup/ide(3563).c b/xv6-public/xv6.si4project/Backup/ide(3563).c new file mode 100644 index 0000000..b4c0b1f --- /dev/null +++ b/xv6-public/xv6.si4project/Backup/ide(3563).c @@ -0,0 +1,168 @@ +// Simple PIO-based (non-DMA) IDE driver code. + +#include "types.h" +#include "defs.h" +#include "param.h" +#include "memlayout.h" +#include "mmu.h" +#include "proc.h" +#include "x86.h" +#include "traps.h" +#include "spinlock.h" +#include "sleeplock.h" +#include "fs.h" +#include "buf.h" + +#define SECTOR_SIZE 512 +#define IDE_BSY 0x80 +#define IDE_DRDY 0x40 +#define IDE_DF 0x20 +#define IDE_ERR 0x01 + +#define IDE_CMD_READ 0x20 +#define IDE_CMD_WRITE 0x30 +#define IDE_CMD_RDMUL 0xc4 +#define IDE_CMD_WRMUL 0xc5 + +// idequeue points to the buf now being read/written to the disk. +// idequeue->qnext points to the next buf to be processed. +// You must hold idelock while manipulating queue. + +static struct spinlock idelock; +static struct buf *idequeue; + +static int havedisk1; +static void idestart(struct buf*); + +// Wait for IDE disk to become ready. +static int +idewait(int checkerr) +{ + int r; + + while(((r = inb(0x1f7)) & (IDE_BSY|IDE_DRDY)) != IDE_DRDY) + ; + if(checkerr && (r & (IDE_DF|IDE_ERR)) != 0) + return -1; + return 0; +} + +void +ideinit(void) +{ + int i; + + initlock(&idelock, "ide"); + ioapicenable(IRQ_IDE, ncpu - 1); + idewait(0); + + // Check if disk 1 is present + outb(0x1f6, 0xe0 | (1<<4)); + for(i=0; i<1000; i++){ + if(inb(0x1f7) != 0){ + havedisk1 = 1; + break; + } + } + + // Switch back to disk 0. + outb(0x1f6, 0xe0 | (0<<4)); +} + +// Start the request for b. Caller must hold idelock. +static void +idestart(struct buf *b) +{ + if(b == 0) + panic("idestart"); + if(b->blockno >= FSSIZE) + panic("incorrect blockno"); + int sector_per_block = BSIZE/SECTOR_SIZE; + int sector = b->blockno * sector_per_block; + int read_cmd = (sector_per_block == 1) ? IDE_CMD_READ : IDE_CMD_RDMUL; + int write_cmd = (sector_per_block == 1) ? IDE_CMD_WRITE : IDE_CMD_WRMUL; + + if (sector_per_block > 7) panic("idestart"); + + idewait(0); + outb(0x3f6, 0); // generate interrupt + outb(0x1f2, sector_per_block); // number of sectors + outb(0x1f3, sector & 0xff); + outb(0x1f4, (sector >> 8) & 0xff); + outb(0x1f5, (sector >> 16) & 0xff); + outb(0x1f6, 0xe0 | ((b->dev&1)<<4) | ((sector>>24)&0x0f)); + if(b->flags & B_DIRTY){ + outb(0x1f7, write_cmd); + outsl(0x1f0, b->data, BSIZE/4); + } else { + outb(0x1f7, read_cmd); + } +} + +// Interrupt handler. +void +ideintr(void) +{ + struct buf *b; + + // First queued buffer is the active request. + acquire(&idelock); + + if((b = idequeue) == 0){ + release(&idelock); + return; + } + idequeue = b->qnext; + + // Read data if needed. + if(!(b->flags & B_DIRTY) && idewait(1) >= 0) + insl(0x1f0, b->data, BSIZE/4); + + // Wake process waiting for this buf. + b->flags |= B_VALID; + b->flags &= ~B_DIRTY; + wakeup(b); + + // Start disk on next buf in queue. + if(idequeue != 0) + idestart(idequeue); + + release(&idelock); +} + +//PAGEBREAK! +// Sync buf with disk. +// If B_DIRTY is set, write buf to disk, clear B_DIRTY, set B_VALID. +// Else if B_VALID is not set, read buf from disk, set B_VALID. +void +iderw(struct buf *b) +{ + struct buf **pp; + + if(!holdingsleep(&b->lock)) + panic("iderw: buf not locked"); + if((b->flags & (B_VALID|B_DIRTY)) == B_VALID) + panic("iderw: nothing to do"); + if(b->dev != 0 && !havedisk1) + panic("iderw: ide disk 1 not present"); + + acquire(&idelock); //DOC:acquire-lock + + // Append b to idequeue. + b->qnext = 0; + for(pp=&idequeue; *pp; pp=&(*pp)->qnext) //DOC:insert-queue + ; + *pp = b; + + // Start disk if necessary. + if(idequeue == b) + idestart(b); + + // Wait for request to finish. + while((b->flags & (B_VALID|B_DIRTY)) != B_VALID){ + sleep(b, &idelock); + } + + + release(&idelock); +} diff --git a/xv6-public/xv6.si4project/Backup/proc(1173).h b/xv6-public/xv6.si4project/Backup/proc(1173).h new file mode 100644 index 0000000..1647114 --- /dev/null +++ b/xv6-public/xv6.si4project/Backup/proc(1173).h @@ -0,0 +1,58 @@ +// Per-CPU state +struct cpu { + uchar apicid; // Local APIC ID + struct context *scheduler; // swtch() here to enter scheduler + struct taskstate ts; // Used by x86 to find stack for interrupt + struct segdesc gdt[NSEGS]; // x86 global descriptor table + volatile uint started; // Has the CPU started? + int ncli; // Depth of pushcli nesting. + int intena; // Were interrupts enabled before pushcli? + struct proc *proc; // The process running on this cpu or null +}; + +extern struct cpu cpus[NCPU]; +extern int ncpu; + +//PAGEBREAK: 17 +// Saved registers for kernel context switches. +// Don't need to save all the segment registers (%cs, etc), +// because they are constant across kernel contexts. +// Don't need to save %eax, %ecx, %edx, because the +// x86 convention is that the caller has saved them. +// Contexts are stored at the bottom of the stack they +// describe; the stack pointer is the address of the context. +// The layout of the context matches the layout of the stack in swtch.S +// at the "Switch stacks" comment. Switch doesn't save eip explicitly, +// but it is on the stack and allocproc() manipulates it. +struct context { + uint edi; + uint esi; + uint ebx; + uint ebp; + uint eip; +}; + +enum procstate { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE }; + +// Per-process state +struct proc { + uint sz; // Size of process memory (bytes) + pde_t* pgdir; // Page table + char *kstack; // Bottom of kernel stack for this process + enum procstate state; // Process state + int pid; // Process ID + struct proc *parent; // Parent process + struct trapframe *tf; // Trap frame for current syscall + struct context *context; // swtch() here to run process + void *chan; // If non-zero, sleeping on chan + int killed; // If non-zero, have been killed + struct file *ofile[NOFILE]; // Open files + struct inode *cwd; // Current directory + char name[16]; // Process name (debugging) +}; + +// Process memory is laid out contiguously, low addresses first: +// text +// original data and bss +// fixed-size stack +// expandable heap diff --git a/xv6-public/xv6.si4project/Backup/proc(6211).c b/xv6-public/xv6.si4project/Backup/proc(6211).c new file mode 100644 index 0000000..806b1b1 --- /dev/null +++ b/xv6-public/xv6.si4project/Backup/proc(6211).c @@ -0,0 +1,534 @@ +#include "types.h" +#include "defs.h" +#include "param.h" +#include "memlayout.h" +#include "mmu.h" +#include "x86.h" +#include "proc.h" +#include "spinlock.h" + +struct { + struct spinlock lock; + struct proc proc[NPROC]; +} ptable; + +static struct proc *initproc; + +int nextpid = 1; +extern void forkret(void); +extern void trapret(void); + +static void wakeup1(void *chan); + +void +pinit(void) +{ + initlock(&ptable.lock, "ptable"); +} + +// Must be called with interrupts disabled +int +cpuid() { + return mycpu()-cpus; +} + +// Must be called with interrupts disabled to avoid the caller being +// rescheduled between reading lapicid and running through the loop. +struct cpu* +mycpu(void) +{ + int apicid, i; + + if(readeflags()&FL_IF) + panic("mycpu called with interrupts enabled\n"); + + apicid = lapicid(); + // APIC IDs are not guaranteed to be contiguous. Maybe we should have + // a reverse map, or reserve a register to store &cpus[i]. + for (i = 0; i < ncpu; ++i) { + if (cpus[i].apicid == apicid) + return &cpus[i]; + } + panic("unknown apicid\n"); +} + +// Disable interrupts so that we are not rescheduled +// while reading proc from the cpu structure +struct proc* +myproc(void) { + struct cpu *c; + struct proc *p; + pushcli(); + c = mycpu(); + p = c->proc; + popcli(); + return p; +} + +//PAGEBREAK: 32 +// Look in the process table for an UNUSED proc. +// If found, change state to EMBRYO and initialize +// state required to run in the kernel. +// Otherwise return 0. +static struct proc* +allocproc(void) +{ + struct proc *p; + char *sp; + + acquire(&ptable.lock); + + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++) + if(p->state == UNUSED) + goto found; + + release(&ptable.lock); + return 0; + +found: + p->state = EMBRYO; + p->pid = nextpid++; + + release(&ptable.lock); + + // Allocate kernel stack. + if((p->kstack = kalloc()) == 0){ + p->state = UNUSED; + return 0; + } + sp = p->kstack + KSTACKSIZE; + + // Leave room for trap frame. + sp -= sizeof *p->tf; + p->tf = (struct trapframe*)sp; + + // Set up new context to start executing at forkret, + // which returns to trapret. + sp -= 4; + *(uint*)sp = (uint)trapret; + + sp -= sizeof *p->context; + p->context = (struct context*)sp; + memset(p->context, 0, sizeof *p->context); + p->context->eip = (uint)forkret; + + return p; +} + +//PAGEBREAK: 32 +// Set up first user process. +void +userinit(void) +{ + struct proc *p; + extern char _binary_initcode_start[], _binary_initcode_size[]; + + p = allocproc(); + + initproc = p; + if((p->pgdir = setupkvm()) == 0) + panic("userinit: out of memory?"); + inituvm(p->pgdir, _binary_initcode_start, (int)_binary_initcode_size); + p->sz = PGSIZE; + memset(p->tf, 0, sizeof(*p->tf)); + p->tf->cs = (SEG_UCODE << 3) | DPL_USER; + p->tf->ds = (SEG_UDATA << 3) | DPL_USER; + p->tf->es = p->tf->ds; + p->tf->ss = p->tf->ds; + p->tf->eflags = FL_IF; + p->tf->esp = PGSIZE; + p->tf->eip = 0; // beginning of initcode.S + + safestrcpy(p->name, "initcode", sizeof(p->name)); + p->cwd = namei("/"); + + // this assignment to p->state lets other cores + // run this process. the acquire forces the above + // writes to be visible, and the lock is also needed + // because the assignment might not be atomic. + acquire(&ptable.lock); + + p->state = RUNNABLE; + + release(&ptable.lock); +} + +// Grow current process's memory by n bytes. +// Return 0 on success, -1 on failure. +int +growproc(int n) +{ + uint sz; + struct proc *curproc = myproc(); + + sz = curproc->sz; + if(n > 0){ + if((sz = allocuvm(curproc->pgdir, sz, sz + n)) == 0) + return -1; + } else if(n < 0){ + if((sz = deallocuvm(curproc->pgdir, sz, sz + n)) == 0) + return -1; + } + curproc->sz = sz; + switchuvm(curproc); + return 0; +} + +// Create a new process copying p as the parent. +// Sets up stack to return as if from system call. +// Caller must set state of returned proc to RUNNABLE. +int +fork(void) +{ + int i, pid; + struct proc *np; + struct proc *curproc = myproc(); + + // Allocate process. + if((np = allocproc()) == 0){ + return -1; + } + + // Copy process state from proc. + if((np->pgdir = copyuvm(curproc->pgdir, curproc->sz)) == 0){ + kfree(np->kstack); + np->kstack = 0; + np->state = UNUSED; + return -1; + } + np->sz = curproc->sz; + np->parent = curproc; + *np->tf = *curproc->tf; + + // Clear %eax so that fork returns 0 in the child. + np->tf->eax = 0; + + for(i = 0; i < NOFILE; i++) + if(curproc->ofile[i]) + np->ofile[i] = filedup(curproc->ofile[i]); + np->cwd = idup(curproc->cwd); + + safestrcpy(np->name, curproc->name, sizeof(curproc->name)); + + pid = np->pid; + + acquire(&ptable.lock); + + np->state = RUNNABLE; + + release(&ptable.lock); + + return pid; +} + +// Exit the current process. Does not return. +// An exited process remains in the zombie state +// until its parent calls wait() to find out it exited. +void +exit(void) +{ + struct proc *curproc = myproc(); + struct proc *p; + int fd; + + if(curproc == initproc) + panic("init exiting"); + + // Close all open files. + for(fd = 0; fd < NOFILE; fd++){ + if(curproc->ofile[fd]){ + fileclose(curproc->ofile[fd]); + curproc->ofile[fd] = 0; + } + } + + begin_op(); + iput(curproc->cwd); + end_op(); + curproc->cwd = 0; + + acquire(&ptable.lock); + + // Parent might be sleeping in wait(). + wakeup1(curproc->parent); + + // Pass abandoned children to init. + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ + if(p->parent == curproc){ + p->parent = initproc; + if(p->state == ZOMBIE) + wakeup1(initproc); + } + } + + // Jump into the scheduler, never to return. + curproc->state = ZOMBIE; + sched(); + panic("zombie exit"); +} + +// Wait for a child process to exit and return its pid. +// Return -1 if this process has no children. +int +wait(void) +{ + struct proc *p; + int havekids, pid; + struct proc *curproc = myproc(); + + acquire(&ptable.lock); + for(;;){ + // Scan through table looking for exited children. + havekids = 0; + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ + if(p->parent != curproc) + continue; + havekids = 1; + if(p->state == ZOMBIE){ + // Found one. + pid = p->pid; + kfree(p->kstack); + p->kstack = 0; + freevm(p->pgdir); + p->pid = 0; + p->parent = 0; + p->name[0] = 0; + p->killed = 0; + p->state = UNUSED; + release(&ptable.lock); + return pid; + } + } + + // No point waiting if we don't have any children. + if(!havekids || curproc->killed){ + release(&ptable.lock); + return -1; + } + + // Wait for children to exit. (See wakeup1 call in proc_exit.) + sleep(curproc, &ptable.lock); //DOC: wait-sleep + } +} + +//PAGEBREAK: 42 +// Per-CPU process scheduler. +// Each CPU calls scheduler() after setting itself up. +// Scheduler never returns. It loops, doing: +// - choose a process to run +// - swtch to start running that process +// - eventually that process transfers control +// via swtch back to the scheduler. +void +scheduler(void) +{ + struct proc *p; + struct cpu *c = mycpu(); + c->proc = 0; + + for(;;){ + // Enable interrupts on this processor. + sti(); + + // Loop over process table looking for process to run. + acquire(&ptable.lock); + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ + if(p->state != RUNNABLE) + continue; + + // Switch to chosen process. It is the process's job + // to release ptable.lock and then reacquire it + // before jumping back to us. + c->proc = p; + switchuvm(p); + p->state = RUNNING; + + swtch(&(c->scheduler), p->context); + switchkvm(); + + // Process is done running for now. + // It should have changed its p->state before coming back. + c->proc = 0; + } + release(&ptable.lock); + + } +} + +// Enter scheduler. Must hold only ptable.lock +// and have changed proc->state. Saves and restores +// intena because intena is a property of this +// kernel thread, not this CPU. It should +// be proc->intena and proc->ncli, but that would +// break in the few places where a lock is held but +// there's no process. +void +sched(void) +{ + int intena; + struct proc *p = myproc(); + + if(!holding(&ptable.lock)) + panic("sched ptable.lock"); + if(mycpu()->ncli != 1) + panic("sched locks"); + if(p->state == RUNNING) + panic("sched running"); + if(readeflags()&FL_IF) + panic("sched interruptible"); + intena = mycpu()->intena; + swtch(&p->context, mycpu()->scheduler); + mycpu()->intena = intena; +} + +// Give up the CPU for one scheduling round. +void +yield(void) +{ + acquire(&ptable.lock); //DOC: yieldlock + myproc()->state = RUNNABLE; + sched(); + release(&ptable.lock); +} + +// A fork child's very first scheduling by scheduler() +// will swtch here. "Return" to user space. +void +forkret(void) +{ + static int first = 1; + // Still holding ptable.lock from scheduler. + release(&ptable.lock); + + if (first) { + // Some initialization functions must be run in the context + // of a regular process (e.g., they call sleep), and thus cannot + // be run from main(). + first = 0; + iinit(ROOTDEV); + initlog(ROOTDEV); + } + + // Return to "caller", actually trapret (see allocproc). +} + +// Atomically release lock and sleep on chan. +// Reacquires lock when awakened. +void +sleep(void *chan, struct spinlock *lk) +{ + struct proc *p = myproc(); + + if(p == 0) + panic("sleep"); + + if(lk == 0) + panic("sleep without lk"); + + // Must acquire ptable.lock in order to + // change p->state and then call sched. + // Once we hold ptable.lock, we can be + // guaranteed that we won't miss any wakeup + // (wakeup runs with ptable.lock locked), + // so it's okay to release lk. + if(lk != &ptable.lock){ //DOC: sleeplock0 + acquire(&ptable.lock); //DOC: sleeplock1 + release(lk); + } + // Go to sleep. + p->chan = chan; + p->state = SLEEPING; + + sched(); + + // Tidy up. + p->chan = 0; + + // Reacquire original lock. + if(lk != &ptable.lock){ //DOC: sleeplock2 + release(&ptable.lock); + acquire(lk); + } +} + +//PAGEBREAK! +// Wake up all processes sleeping on chan. +// The ptable lock must be held. +static void +wakeup1(void *chan) +{ + struct proc *p; + + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++) + if(p->state == SLEEPING && p->chan == chan) + p->state = RUNNABLE; +} + +// Wake up all processes sleeping on chan. +void +wakeup(void *chan) +{ + acquire(&ptable.lock); + wakeup1(chan); + release(&ptable.lock); +} + +// Kill the process with the given pid. +// Process won't exit until it returns +// to user space (see trap in trap.c). +int +kill(int pid) +{ + struct proc *p; + + acquire(&ptable.lock); + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ + if(p->pid == pid){ + p->killed = 1; + // Wake process from sleep if necessary. + if(p->state == SLEEPING) + p->state = RUNNABLE; + release(&ptable.lock); + return 0; + } + } + release(&ptable.lock); + return -1; +} + +//PAGEBREAK: 36 +// Print a process listing to console. For debugging. +// Runs when user types ^P on console. +// No lock to avoid wedging a stuck machine further. +void +procdump(void) +{ + static char *states[] = { + [UNUSED] "unused", + [EMBRYO] "embryo", + [SLEEPING] "sleep ", + [RUNNABLE] "runble", + [RUNNING] "run ", + [ZOMBIE] "zombie" + }; + int i; + struct proc *p; + char *state; + uint pc[10]; + + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ + if(p->state == UNUSED) + continue; + if(p->state >= 0 && p->state < NELEM(states) && states[p->state]) + state = states[p->state]; + else + state = "???"; + cprintf("%d %s %s", p->pid, state, p->name); + if(p->state == SLEEPING){ + getcallerpcs((uint*)p->context->ebp+2, pc); + for(i=0; i<10 && pc[i] != 0; i++) + cprintf(" %p", pc[i]); + } + cprintf("\n"); + } +} diff --git a/xv6-public/xv6.si4project/Backup/syscall(2531).h b/xv6-public/xv6.si4project/Backup/syscall(2531).h new file mode 100644 index 0000000..56c922a --- /dev/null +++ b/xv6-public/xv6.si4project/Backup/syscall(2531).h @@ -0,0 +1,24 @@ +// System call numbers +#define SYS_fork 1 +#define SYS_exit 2 +#define SYS_wait 3 +#define SYS_pipe 4 +#define SYS_read 5 +#define SYS_kill 6 +#define SYS_exec 7 +#define SYS_fstat 8 +#define SYS_chdir 9 +#define SYS_dup 10 +#define SYS_getpid 11 +#define SYS_sbrk 12 +#define SYS_sleep 13 +#define SYS_uptime 14 +#define SYS_open 15 +#define SYS_write 16 +#define SYS_mknod 17 +#define SYS_unlink 18 +#define SYS_link 19 +#define SYS_mkdir 20 +#define SYS_close 21 +#define SYS_date 22 +#define SYS_dup2 23 \ No newline at end of file diff --git a/xv6-public/xv6.si4project/Backup/syscall(3495).c b/xv6-public/xv6.si4project/Backup/syscall(3495).c new file mode 100644 index 0000000..aa74c8d --- /dev/null +++ b/xv6-public/xv6.si4project/Backup/syscall(3495).c @@ -0,0 +1,182 @@ +#include "types.h" +#include "defs.h" +#include "param.h" +#include "memlayout.h" +#include "mmu.h" +#include "proc.h" +#include "x86.h" +#include "syscall.h" + +// User code makes a system call with INT T_SYSCALL. +// System call number in %eax. +// Arguments on the stack, from the user call to the C +// library system call function. The saved user %esp points +// to a saved program counter, and then the first argument. + +// Fetch the int at addr from the current process. +int +fetchint(uint addr, int *ip) +{ + struct proc *curproc = myproc(); + + if(addr >= curproc->sz || addr+4 > curproc->sz) + return -1; + *ip = *(int*)(addr); + return 0; +} + +// Fetch the nul-terminated string at addr from the current process. +// Doesn't actually copy the string - just sets *pp to point at it. +// Returns length of string, not including nul. +int +fetchstr(uint addr, char **pp) +{ + char *s, *ep; + struct proc *curproc = myproc(); + + if(addr >= curproc->sz) + return -1; + *pp = (char*)addr; + ep = (char*)curproc->sz; + for(s = *pp; s < ep; s++){ + if(*s == 0) + return s - *pp; + } + return -1; +} + +// Fetch the nth 32-bit system call argument. +int +argint(int n, int *ip) +{ + return fetchint((myproc()->tf->esp) + 4 + 4*n, ip); +} + +// Fetch the nth word-sized system call argument as a pointer +// to a block of memory of size bytes. Check that the pointer +// lies within the process address space. +int +argptr(int n, char **pp, int size) +{ + int i; + struct proc *curproc = myproc(); + + if(argint(n, &i) < 0) + return -1; + if(size < 0 || (uint)i >= curproc->sz || (uint)i+size > curproc->sz) + return -1; + *pp = (char*)i; + return 0; +} + +// Fetch the nth word-sized system call argument as a string pointer. +// Check that the pointer is valid and the string is nul-terminated. +// (There is no shared writable memory, so the string can't change +// between this check and being used by the kernel.) +int +argstr(int n, char **pp) +{ + int addr; + if(argint(n, &addr) < 0) + return -1; + return fetchstr(addr, pp); +} + +extern int sys_chdir(void); +extern int sys_close(void); +extern int sys_dup(void); +extern int sys_dup2(void); + +extern int sys_exec(void); +extern int sys_exit(void); +extern int sys_fork(void); +extern int sys_fstat(void); +extern int sys_getpid(void); +extern int sys_kill(void); +extern int sys_link(void); +extern int sys_mkdir(void); +extern int sys_mknod(void); +extern int sys_open(void); +extern int sys_pipe(void); +extern int sys_read(void); +extern int sys_sbrk(void); +extern int sys_sleep(void); +extern int sys_unlink(void); +extern int sys_wait(void); +extern int sys_write(void); +extern int sys_uptime(void); +extern int sys_date(void); + +// 函数指针数组 +// 初始化中写 [] 是指syscalls[SYS_fork=1] = sys_fork +static int (*syscalls[])(void) = { +[SYS_fork] sys_fork, +[SYS_exit] sys_exit, +[SYS_wait] sys_wait, +[SYS_pipe] sys_pipe, +[SYS_read] sys_read, +[SYS_kill] sys_kill, +[SYS_exec] sys_exec, +[SYS_fstat] sys_fstat, +[SYS_chdir] sys_chdir, +[SYS_dup] sys_dup, +[SYS_dup2] sys_dup2, +[SYS_getpid] sys_getpid, +[SYS_sbrk] sys_sbrk, +[SYS_sleep] sys_sleep, +[SYS_uptime] sys_uptime, +[SYS_open] sys_open, +[SYS_write] sys_write, +[SYS_mknod] sys_mknod, +[SYS_unlink] sys_unlink, +[SYS_link] sys_link, +[SYS_mkdir] sys_mkdir, +[SYS_close] sys_close, +[SYS_date] sys_date, + +}; +/* +static char *syscall_name[] = { +[SYS_fork] "fork", +[SYS_exit] "exit", +[SYS_wait] "wait", +[SYS_pipe] "pipe", +[SYS_read] "read", +[SYS_kill] "kill", +[SYS_exec] "exec", +[SYS_fstat] "fstat", +[SYS_chdir] "chdir", +[SYS_dup] "dup", +[SYS_getpid] "getpid", +[SYS_sbrk] "sbrk", +[SYS_sleep] "sleep", +[SYS_uptime] "uptime", +[SYS_open] "open", +[SYS_write] "write", +[SYS_mknod] "mknod", +[SYS_unlink] "unlink", +[SYS_link] "link", +[SYS_mkdir] "mkdir", +[SYS_close] "close", +[SYS_date] "date", +}; +*/ + +void +syscall(void) +{ + int num; + // 关中断读取进程信息 + struct proc *curproc = myproc(); + //num 取值应该[1-最大的系统调用序号] + num = curproc->tf->eax; + // 检查系统调用是否存在 + if(num > 0 && num < NELEM(syscalls) && syscalls[num]) { + curproc->tf->eax = syscalls[num](); //存储系统调用返回值 + // cprintf("%s: -> %d\n",syscall_name[num], curproc->tf->eax); + } else { + cprintf("%d %s: unknown sys call %d\n", + curproc->pid, curproc->name, num); + curproc->tf->eax = -1; + } +} diff --git a/xv6-public/xv6.si4project/Backup/sysproc(2335).c b/xv6-public/xv6.si4project/Backup/sysproc(2335).c new file mode 100644 index 0000000..b82f5c9 --- /dev/null +++ b/xv6-public/xv6.si4project/Backup/sysproc(2335).c @@ -0,0 +1,101 @@ +#include "types.h" +#include "x86.h" +#include "defs.h" +#include "date.h" +#include "param.h" +#include "memlayout.h" +#include "mmu.h" +#include "proc.h" + +int +sys_fork(void) +{ + return fork(); +} + +int +sys_exit(void) +{ + exit(); + return 0; // not reached +} + +int +sys_wait(void) +{ + return wait(); +} + +int +sys_kill(void) +{ + int pid; + + if(argint(0, &pid) < 0) + return -1; + return kill(pid); +} + +int +sys_getpid(void) +{ + return myproc()->pid; +} + +int +sys_sbrk(void) +{ + int addr; + int n; + + if(argint(0, &n) < 0) + return -1; + addr = myproc()->sz; + myproc()->sz += n; + return addr; +} + +int +sys_sleep(void) +{ + int n; + uint ticks0; + + if(argint(0, &n) < 0) + return -1; + acquire(&tickslock); + ticks0 = ticks; + while(ticks - ticks0 < n){ + if(myproc()->killed){ + release(&tickslock); + return -1; + } + sleep(&ticks, &tickslock); + } + release(&tickslock); + return 0; +} + +// return how many clock tick interrupts have occurred +// since start. +int +sys_uptime(void) +{ + uint xticks; + + acquire(&tickslock); + xticks = ticks; + release(&tickslock); + return xticks; +} + +int +sys_date(void) +{ + struct rtcdate *r; + if(argptr(0, (void*)&r, sizeof(struct rtcdate)) < 0) + return -1; + cmostime(r); + return 0; +} + diff --git a/xv6-public/xv6.si4project/Backup/trap(2304).c b/xv6-public/xv6.si4project/Backup/trap(2304).c new file mode 100644 index 0000000..f5f3562 --- /dev/null +++ b/xv6-public/xv6.si4project/Backup/trap(2304).c @@ -0,0 +1,133 @@ +#include "types.h" +#include "defs.h" +#include "param.h" +#include "memlayout.h" +#include "mmu.h" +#include "proc.h" +#include "x86.h" +#include "traps.h" +#include "spinlock.h" + +// Interrupt descriptor table (shared by all CPUs). +struct gatedesc idt[256]; +extern uint vectors[]; // in vectors.S: array of 256 entry pointers +struct spinlock tickslock; +uint ticks; + +void +tvinit(void) +{ + int i; + + for(i = 0; i < 256; i++) + SETGATE(idt[i], 0, SEG_KCODE<<3, vectors[i], 0); + SETGATE(idt[T_SYSCALL], 1, SEG_KCODE<<3, vectors[T_SYSCALL], DPL_USER); + + initlock(&tickslock, "time"); +} + +void +idtinit(void) +{ + lidt(idt, sizeof(idt)); +} + + + + +//PAGEBREAK: 41 +void +trap(struct trapframe *tf) +{ + if(tf->trapno == T_SYSCALL){ + if(myproc()->killed) + exit(); + myproc()->tf = tf; + syscall(); + if(myproc()->killed) + exit(); + return; + } + char *mem; + switch(tf->trapno){ + case T_IRQ0 + IRQ_TIMER: + if(cpuid() == 0){ + acquire(&tickslock); + ticks++; + wakeup(&ticks); + release(&tickslock); + } + lapiceoi(); + break; + case T_IRQ0 + IRQ_IDE: + ideintr(); + lapiceoi(); + break; + case T_IRQ0 + IRQ_IDE+1: + // Bochs generates spurious IDE1 interrupts. + break; + case T_IRQ0 + IRQ_KBD: + kbdintr(); + lapiceoi(); + break; + case T_IRQ0 + IRQ_COM1: + uartintr(); + lapiceoi(); + break; + case T_IRQ0 + 7: + case T_IRQ0 + IRQ_SPURIOUS: + cprintf("cpu%d: spurious interrupt at %x:%x\n", + cpuid(), tf->cs, tf->eip); + lapiceoi(); + break; + + // T_PGFLT = 14 + case T_PGFLT: + // kallo或mappages执行失败,则继续执行下面的default. + // In user space, assume process misbehaved. + // cr2包含发生页面错误时的线性地址. + mem = kalloc(); + if(mem != 0){ + uint va = PGROUNDDOWN(rcr2()); + memset(mem, 0, PGSIZE); + extern int mappages(pde_t *pgdir, void *va, uint size, uint pa, int perm); + if(mappages(myproc()->pgdir,(void *)va, PGSIZE, V2P(mem), PTE_W|PTE_U) >= 0) { + // 全部执行成功才break; + break; + } + } + + //PAGEBREAK: 13 + default: + // tf->cs&3 不明白 + if(myproc() == 0 || (tf->cs&3) == 0){ + // In kernel, it must be our mistake. + cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n", + tf->trapno, cpuid(), tf->eip, rcr2()); + panic("trap"); + } + // In user space, assume process misbehaved. + + cprintf("pid %d %s: trap %d err %d on cpu %d " + "eip 0x%x addr 0x%x--kill proc\n", + myproc()->pid, myproc()->name, tf->trapno, + tf->err, cpuid(), tf->eip, rcr2()); + myproc()->killed = 1; + } + + // Force process exit if it has been killed and is in user space. + // (If it is still executing in the kernel, let it keep running + // until it gets to the regular system call return.) + if(myproc() && myproc()->killed && (tf->cs&3) == DPL_USER) + exit(); + + // Force process to give up CPU on clock tick. + // If interrupts were on while locks held, would need to check nlock. + if(myproc() && myproc()->state == RUNNING && + tf->trapno == T_IRQ0+IRQ_TIMER) + yield(); + + // Check if the process has been killed since we yielded + if(myproc() && myproc()->killed && (tf->cs&3) == DPL_USER) + exit(); +} diff --git a/xv6-public/xv6.si4project/Backup/user(4192).h b/xv6-public/xv6.si4project/Backup/user(4192).h new file mode 100644 index 0000000..4e138ed --- /dev/null +++ b/xv6-public/xv6.si4project/Backup/user(4192).h @@ -0,0 +1,42 @@ +struct stat; +struct rtcdate; + +// system calls +int fork(void); +int exit(void) __attribute__((noreturn)); +int wait(void); +int pipe(int*); +int write(int, const void*, int); +int read(int, void*, int); +int close(int); +int kill(int); +int exec(char*, char**); +int open(const char*, int); +int mknod(const char*, short, short); +int unlink(const char*); +int fstat(int fd, struct stat*); +int link(const char*, const char*); +int mkdir(const char*); +int chdir(const char*); +int dup(int); +int getpid(void); +char* sbrk(int); +int sleep(int); +int uptime(void); +int date(struct rtcdate* ); +int dup2(int , int); + + +// ulib.c +int stat(const char*, struct stat*); +char* strcpy(char*, const char*); +void *memmove(void*, const void*, int); +char* strchr(const char*, char c); +int strcmp(const char*, const char*); +void printf(int, const char*, ...); +char* gets(char*, int max); +uint strlen(const char*); +void* memset(void*, int, uint); +void* malloc(uint); +void free(void*); +int atoi(const char*); diff --git a/xv6-public/xv6.si4project/Backup/usys(6843).S b/xv6-public/xv6.si4project/Backup/usys(6843).S new file mode 100644 index 0000000..9a40a57 --- /dev/null +++ b/xv6-public/xv6.si4project/Backup/usys(6843).S @@ -0,0 +1,33 @@ +#include "syscall.h" +#include "traps.h" + +#define SYSCALL(name) \ + .globl name; \ + name: \ + movl $SYS_ ## name, %eax; \ + int $T_SYSCALL; \ + ret + +SYSCALL(fork) +SYSCALL(exit) +SYSCALL(wait) +SYSCALL(pipe) +SYSCALL(read) +SYSCALL(write) +SYSCALL(close) +SYSCALL(kill) +SYSCALL(exec) +SYSCALL(open) +SYSCALL(mknod) +SYSCALL(unlink) +SYSCALL(fstat) +SYSCALL(link) +SYSCALL(mkdir) +SYSCALL(chdir) +SYSCALL(dup) +SYSCALL(dup2) +SYSCALL(getpid) +SYSCALL(sbrk) +SYSCALL(sleep) +SYSCALL(uptime) +SYSCALL(date) diff --git a/xv6-public/xv6.si4project/Backup/uthread_switch(3995).S b/xv6-public/xv6.si4project/Backup/uthread_switch(3995).S new file mode 100644 index 0000000..904c4f6 --- /dev/null +++ b/xv6-public/xv6.si4project/Backup/uthread_switch(3995).S @@ -0,0 +1,10 @@ + .text + +/* Switch from current_thread to next_thread. Make next_thread + * the current_thread, and set next_thread to 0. + * Use eax as a temporary register; it is caller saved. + */ + .globl thread_switch +thread_switch: + /* YOUR CODE HERE */ + ret /* pop return address from stack */ diff --git a/xv6-public/xv6.si4project/cache/parse/alarmtest.c.sisc b/xv6-public/xv6.si4project/cache/parse/alarmtest.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..109093d79136ef37258091d755bd52022b5cf13b GIT binary patch literal 3547 zcmeH}yK7Wg9LJ9_W}}Qd<2$0@AcD!pVp!HH+F1EmWdv;m#q7*zF6<^@5``@mLjD2^ z?G%F=(Jr_wi{1D@EEL4}g5AP0rJbGE@8_QTn|o#)BO*597k=|Q=XV~z_qkK*aqft7 z-2)=m<=o#n=br!5mCy@uX!if-Ib^fH!=M1b6H6s?s*=S3GqDhanj)GY!} z`YZW!mshN0Jg6EO61jm&zIg0ERZE6A#oV)(xn&YFWp#XWV>w5_51zTaIC`v>R%^UQ zWM?#N!Efp8p7>u&oZBXPDmtOLSSt#djI|$IS6g(%@v7!3wycUqE5Dzq){0vv{~WJP zbd791E-BWVmV~Do7zCLAV_fKYNNRbh$N zu<6;u3-dWHFvKx$4yEP`q5F^FXcTL?kZJ%ML|lp@s?-CCNB;+xVy#!xVlCUzH6`ER zCso2v-tJHIa2@i!;+>GG^TvejF{Ac)J>%O0y40mj4eFJTO|5VjlHFrc^l>{wJK>Y=kGIa`|b&fb=` z3$nO@?B7>8bCxq)V9w%{DVkf;SgvUTD;p+uhB48hXTo40HyqL6rl>51?^0n|9Q}5u zah7eoxbqfjZ~M|{bdrE#1Eq}7aQXy2CMznxnkHDdG~f0fwgq&!emdzHRB^$&ly4HZ zOOX|WOZ%^V`qHz9bO>EoiMM7gmzqowZdxjFq7V+^n4KONw}bocDqiw3uv5 zaO22q`M!QQx(XO9&{_KWJ}nUZm^OcxwY?$yRxjJY~1jL zO2Je`<8gI}vFtuU=%j7w#+h*X%HnH#KGn8z{U^I$|_lB}>P3wp_3 zUvGVZio9-jGhaE&xv%M~y+C1YQ_sL;i~HKvFqM(vI)_7NOLA=Ps&|$(5<92ows=2t z7AHxrIh(wj`jJQvV1t%OkX5~(Td1jUIz3E;-;w=>MLQ*%UKI{}anUy9M=32@`;?T` z5akEir-c5-FL-;=p6ttfv*N~L{50RzYs@!wG2bka_6;_!W6kgK;;(62BKeeXI1Ji3 z1#Mx^=Lc<@?pd3XRW);*G}2#M2bmdDJ1Y4%cc$%2pp}lW?d^*nle4em8g^h4Fk4C5 q8`)9*)xYSr2Oq*c1-()W2mKy1n7_vc`^NBz1bT*>Ny#2v=iUQ+7E1d7 literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/asm.h.sisc b/xv6-public/xv6.si4project/cache/parse/asm.h.sisc new file mode 100644 index 0000000000000000000000000000000000000000..976f13d681ebb804b3ca6ef4ae375de5f0d2a3ed GIT binary patch literal 1780 zcmeH`KTBLe6vZd*>Wa@*pC%B4!WK4mDJ|DRl0t*JO120X1&cre0WC~vXK7(+VY8q% z`D?(=!a_nU6$=YLLOwyp^Sf^*`+_S%%HV6)|p)Rx~Zj0?=msk|R(Z@8Y`~HOS_Xp|`^~vU^ zH0eA%{i_vxz{z?!QHW#89>5%^y$q7EbD}`po8J>c&AbYe*V@=6e$%`zq7(Bp?LKGy ziLXw9lkGCz4FwTWj7FXksF$7@rni{(rmK$(xU(Zz>0XUF^>pSq@){N9)J z%|J{EZRyTx%)B>S%B*zJ!q+P25NgJIUMB-O?X|h_g*vKaCLx2_pvt(FYJ3qkv{ZeG zDyOA{2xfyS<9||}CF^{5Rn$q(-GEi^x7KKxsyc3C=xc$hto?M>O&VG@bQk{oOR@%H zCotw52=3~xdByBoq;oT}=#wM0!}53JeHG2~$mimHGYifyu6}sGj3@<1>`}1#?f!`3 ztBAMZhUn7b%JQ_LV>O>>jQFq^GsRaCZ-e)-KA~D~-@F@9Ft>%x)l3sz*dG}0dG#et x#&(bL;flBuaeK=^&LIa7^Pv}ieNK~|i-L7ajER;wVybl1k1U3ofS$}){@1NegA)J% literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/bio.c.sisc b/xv6-public/xv6.si4project/cache/parse/bio.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..4cf1faac86a4019732c2934cf048045d4fbeb20f GIT binary patch literal 8866 zcmeI1O>A6O6~|x3c49JiVuu6`5Fki_RuD>xN@*K=>~TEcj4j(q z2cb&o2HH@hELdcLstBoSEEaJoA1*~oN-F4rO5L=|f<@HQs$C$A#3EwR$NzWlJ@f92 zr!zK{vp^i__}q8yx#!&TanF78JiIkYjwVU>?ZPCNB(HruNnZU;&f#mK;8TBnwGZA? zFD~^%yORII|4IbN{YQkm<^gcHIYQvSSfQuqxiE=gil3a^Ns z5#5J!!9~qIB+4WH0FDl1Jm%O(4DlY)bg(`p)5&0^Ix%x{vRvG|_=CCfLT-BRgW}@d zo*?IFu)w&Lg&^ukno2kT76$4TCd*S8zy&5g6oecN1{ilX@Ln#=jn9vtkcDw+Az>d5 z790&07`L(j&mc`Lynd&<>n<$JRjM*dWYs{>chs%8Ts$C_sz3Rt5O6f8XWUACW2Ec=cqew& z)t63ADM;Uuj$Yx-Lf}>*L5O*JmPHS>KPK*2+H;!r+0fNY-w(&Dv(?hX_{4Pik#A}0 z142^@MKK#R9vLzyyqx55)*wxZtcNaFX)Ym&YfGYrk*?wqQYsR^(0y4QzW?|B&R_k^ynu;;Pnb z-CBBhzOqBR&T>I5v z{_P*{a%J?co*$9EgU<}+dq4NfE>ze4lH~CO57`dg9e&&;_2|HK@_-%lvQu}zSF%ei z5|DWGe@wV5P-}C>%Nm*l1o2)-yaD#R=?q6SAgOx0agIPusqvbXN~8{HYOVywbX?ge z+`U4A14Rd$H(q<4O>7EwMPx&am#;`_B06aMMf*4~n<{pG)=ZaHavv4&yi?JOc#4 z06XSVr|htX#>AR-jY$EmHzwA^duZF3*huX3vK+kd6YunHS$$G?R%KfFSGt`|P?E^w zkU0%MHmFAjS&T#G0>6{fl;qPvmQ17HI-F6aZTy++9Rqg5Ue=W4soBcp*Cm7l`-M0G zr3qrlcs;&}h_e>b6iE*Ra7&49#%NfmmC0wrGwsuOpNKTBtZBrSU9acnsoD8rY1DW5 zoGSj#(t+@hbF~!b?4a^{%TVxK{e(ix4~O-4n_$NFF#UyhqQM zgmfhA9uT72sD|}%`gWoN@v23@rqFajQpwjCT`L>Sw6*{;j(^r zpf`z{PI$#gXYJ3;S7sJD^lU59kE^qkKWFm`LShfK@;Bbb%b)BW5<>41VzF0fytw?Y zuJOKI`O})rWoFPS2E+N=|2dEw+y1H6`DlUG3F#d%p#+i5&;E%P#8o|>pGj*bow4eeKE zre?-liG{!y2GtCzRdh8{TgBV_rr52PcolQ?s!C;iTd{wfenbxBHl+Y3ERU zBIbhIQnyR&|e5K6l?o$!j0&g+-59BWFkX@9$yB*Pw|cDox-G3IJ+32R?& z%aS82P$fAzE+j*s@#4zAu3y8NszaLEhbO~yw`^lor;v@~joV8{kRs#@_7zh$z z^6}yJGyX4?6Ia`qf_*q7;AzeMTR11)@L<-^c%^4Q*3dL;+0bkc%v*(;tnG{EX1F&n ztm3%v0Hg7^eG?;c9@tBF{ImCj7~X36r+%&c3fv|1xo3FShm0#-8i&C)1yHvX?mhL4_< z4Ae@-c*VG6p6OIF4@d*%B^u@vaz#ENumdK3)+eSNk z>yfeb8v5>dx1jAVa(4`06A;(KXn}c=g}}e6DV@_HnA9Z5c^VeTj0?X F{{txq+y4Ln literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/bootmain.c.sisc b/xv6-public/xv6.si4project/cache/parse/bootmain.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..39c9105343cca81367edc8019b80fb00965bdc5d GIT binary patch literal 6187 zcmeI0O>9(E6vrR^fa-vB5VR7F6T(7dVKGEeTr@!vFcGVOA;gak?bK;3ok=^@vM^z# zXiOx=1q&8zFjN*4Kaws?BuJEnCTvg=U8so>KVsOJU}Aj!fA8Ki@6PL_w2iPZp5)BA z_uPBWx##oUwtI0D?TVtdb;776iauEtMHfG6N$@LC@c6eEm%=-KZgLs4HToa^D;^;B zcL-O?pm&5vg*SU_69sxs<#ShGU6EsaRKfp7*eBkxEsJl0XApbXHoPpiL`}+@@IpBXDl7M|0ui>EJtngRyzSsOw2{|PCw&u@?&ldCp3GGaItlg5V zq(7m~IL_A>xLbZ`qJ5Vi+wUpO9Bd!!h9e!Uzy#~h3H2AFviR0zg6+TCLenZ;#e)h1NU52zyJQy{^8<* z%6Ls$c59_wxYX}VsMo?6PpS1Z0GbWr*!=5qq+{pSExUGZ-@8=_n;f(tLJLB>HcFTI zxkxneMU=BdW**0u8cy(%(Nb|>tn>mGW<_^Q;6D8#vmi`ULK6=YpJ(NED4A7C0^HKE zuTrV)FAj|$7+W?7fd_>MM%n$sEKHn@tVoh2JkgT)(hGjMI8+-L8ha7JB*epB!gf&v zW5H(6gIMsoK8=#Hv?b?aeB}i@PxRMtF`4i>5s9OZDk0WMyY z1fkKzTm-omj_#>^Zu&LXS59(RN_xbbSp7jO`Zj$Q<;W3`bMzIFhQ7iaz~u($vH7+7 z3Qh!`6rwXsEBJu%Hb&7($8o=neZ#DBy4zl=3=KS`eOv|s_!){5O%c38+DW3WFSDUf z-HJi&oUJz7a2j?FX| z(pG(Hp3pK}&9Xz z*+kE0dyffSkpZ!NIXojVp!mnNoZX`46KdW9J7- z#vfdP@F21zL(KL1Fj`#9T}Cm$#)``TzX?G4>c`}p0p3jV~wi;1zK z*Q-?!8180qH7Zt}H+%JD0@L&_hCW%gEz>J5sC@SPmRgIY0P?PvwN@@+8j^Z|@n*Ny z8iI>V8@(bM+A2-Zht|FVR|xknsj-M5yf?~Ns}3lDv5e#c1k$Yx0t^ wJ@CUlXY?=Fj<4OGP6P_vGU%=bo$D0D)Ki?j6Jpcdz literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/buf.h.sisc b/xv6-public/xv6.si4project/cache/parse/buf.h.sisc new file mode 100644 index 0000000000000000000000000000000000000000..9da00f286d12b22a3bba16b0d32a3b30ff44d2f5 GIT binary patch literal 2119 zcmeH{u}@S%5XM*D9iWdh9FVBJg?5ybVrWPx5D8+X2i#dm4upeXX9e_HTG)_?A#gD< zA=bv&7%QwSEd4K@-*5K~_jq@n*b*oC-n^Zi{bqJ%cSn1jn{}>mTW~$jt@k;1@}bA$ zyENGQaWa5y@6&z>9l8H)c?i`il z=9kFZup>z-$InZ#T>RKi=%b_M#WUc-vgPHubUQFkLbAiTp3$3*esrY z-Sw|7&hjRSMNM;9*r>tF8sqSKFvQ`%U(i+gqa+DYgTUT*_tD(=)Z_%bj0eJ0&?zsr zPQ11^mUQ5qn4Fn?cv*AV9!;x9w{}90A_Xj}(4+6m@z0mX5qx8xo$m>pq#3LI&CC_OLzKzc@Vg~KIMG)HIL+3bGj}2umRA;^)>rOnJ+}Z1r}~;S zyk_gpi&qfxC_sB(KNJQK7F`k`HCvvP#U@G8I^5WM*Q&L}dV^e<0PGz-BtUDnJZ&pG zPE2d$b6s7lZbC|q08+G(n(d!R>(#9W=Zd=oAVpJMGBsOwQpyyBOpDK8B~@+!fCX)= zX3Miu7n8RAFI5_qo0=U-k?jGg8rTA`^1aY=`>VEZ?q-(9`2}v`A{L)bH}!PPe+*B# V`IyEJpT~+n`0ea-Z%-u`>^EyZlw<$^ literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/cat.c.sisc b/xv6-public/xv6.si4project/cache/parse/cat.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..40c2277d0670957219a33aa24e8a2b5b338b179a GIT binary patch literal 4932 zcmeH~O=w(I6vtm?#;;DJNvImF)=8)`FlNs|cPQql8MpxMx z#YGl^UAPdX(5$SAkc~9jVym>viVGJ-5jP?(gA1Sk-@EtB+?gg#QL_;boH_TMbKd#B z_r4jvJBp4+QEosOWuj=VJBn_6o=NdLQSjUkH}=9icX_Q7nvMR4|4Ieu{UgGCO6XnT z`$COGv`3f|0vjK9=dZrilV{zh895|ez0jQ>{xwQ@@PWj`(V5QtUH&;0=tr-laF3@Q zqWG~{vUj0grG*^S3roV&o_k63nx0=0#a0V+HF?PHZxOmUjg=%Ccn`$V9akr37N*LD z{`%{4<@wBX|4DI)-n^vLdtkkl2eBKFBvST(hpvW)`Fg4D9U!n0rPMnx$L%SYLFo1l z7Us(}Ihc?Vy#(nCv{Ojr#)BV%1p_Zh2+skl?CFIHHhG600uKtYN3PamEgMzayxcx3 zS@|XkHv`$pQvI0L*n1eJ;AtT?nay6IfyLH)J<20DNRpi9i3ps{+-s${N|50&7c{t6 z-*Lmdp|>BGwF}}cU%Z~h*wR-~I=rk2hGAyC)nHok5~szmGVL_X&r3g+(eu10_(MqY z<`Z6M+t!C%EfA*=#zgW4#F1N^ji;W~f@;x`dp)HXI5J+riNsOz*V?;ewRRQFRHmMh z8usrK5*HLxm^7Yhj<+o#NzinFosR0O`XzSG65P>1Bv?1z6M@CUU$?jYfHWQO-hngI z@l3f;td7;nrKw_NYDn`sG#|fFo~>jundhX!P_XZD$8_-;As8=ow{#`SBR5DAYljar zt`w@H!(mF$>m6{lo#C1TuZV~ zYE*>L)C%4u`1%Q(KnUoS)V*I8ojDU zpZIw#i;-|#364fvHl*QSA0HD%Hk~q>a*?5b?vgdeB|n;JrFv8Ra*fbPakeNc9}LO`pVmZ?8{f`cBZ32;jPzoWeH_F(Fv7QF5F zp`NYpRChbOW+$cOLY{!-Os^;OY214yo91IWoU@_MvT{E9t>`Z~+2b o1y&%F!Q-pF literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/console.c.sisc b/xv6-public/xv6.si4project/cache/parse/console.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..d4e614184fff4481c41cc7319f5a7781f98b142e GIT binary patch literal 21876 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 KZr^?=;QbHic;iI? literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/date.c.sisc b/xv6-public/xv6.si4project/cache/parse/date.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..8fca5529fd3b0c5479e4b9469e94e5b500b52571 GIT binary patch literal 3362 zcmeHJy-!n76u;1lAYjW^z=*LBVj)H(25Y0@wCYW@nAEi{=h)7;r0-G@o4vr2E z4#tF75>XRl!f2uc{{ZUX;AC(zF2>2{?|0ulueVq<4laa~oSu8nJ@tp*u)CswU60@z%#0aNc`|vH^jV+pX7mIe@*FAR($LT+wlDclD~D57n;Q=C3klTYe@pU7E^9`il#**+PA;|01-^ zTB2xaB5+(Q0@OaaE{qK^LfDT`Dr6lKfD6(ZElmIkys-pHhJH5>FqJN55#T(G*kksV z)B%>PcWRCIBMH3dTV_5!xo!~lM1prN!5iuP3@23G!Y<0eu4w4fohRMY(>e9yoYWvY zdji1*S?)wMG=9tj*;5$ahM#%pR!3e2xNl@&IUsV!53=uZodZ;U!5lM=RMn0# zn;?5ItRh?nwFFL>M1OJ&=2V&}5-MLe>S32EO}2m6mFQj`f&5I72gBTX2u((|LNbo% zB1$!4swsT%_k)o&dJm?ZYZ*G_gbuol+zTmAsf*Z7d;jiq?i@C;+su-1rsTz;Q_-Qr zex^|Cwet0-ei~etmL4&=Iwy%=o(W$Qt`Xtv1*3>=zvVFuP*ys~v(xVoti5uZ^H(Fp z```g*h&mgaJ-}wqX!)P9$-HcA-USW^V;(k%kty&4=n}DpCg#qILrG$7#3si!4mc-? z9mk9#wb53HYqdzQC>Rk*TNwk3z4l)ElzA;IZmhM8y5>i{S}$NDYh8iv_2Ejb`Xr(M zpS2Rs%*}=~Axsk8pKB$eJYv4VOfKzAp!;;{6f?w(S>6`x03WvZVBY1^$5Us|OvHxc zN8+jJ^yKBj&61PJ7E<$bu|u<^$?1G1#r_TFV7pa`AR`kmB$;pa|JQyn;-{javbjXu z%S-eF|CkciCF14bV<4BvzWm9rm5-Ukhp8rcF!;jY&w9;A#f<+*1gA9C>pQ~d#=l)tt35UF2_De|!Z literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/date.h.sisc b/xv6-public/xv6.si4project/cache/parse/date.h.sisc new file mode 100644 index 0000000000000000000000000000000000000000..26b62a894d5805115324d16ad761454cbc67cb58 GIT binary patch literal 1646 zcmeH`y-osA5QVRRimntG3+!#|d;}lCzeGw2kYE8M2#FRxgBF$+HWU{Agv8QFVPYet z+L-8@tmoUi11l!P+IW()vv+pxnVGwD*JhmCaW1nex|DOhY3E+$k6dvnRgalmy{tPiJsHNR#jI*#%gDrC(hem(0aCFv{p0d4Ah3iLMpD3*%&0vfEm- zglJ=Pu{B>_>m-tOg&|dVP|M6gwcKn}kmcy09iz#bZ(LTPL;R4f?>9Q_>ZSt75}kHz z84W5m-(*>vK_8!~H9M^hZN?3$70b9HYQD*$r1pr4tCWtmwB#2;G_eaJn&z9VNt6eg z)AeSfU88-D8={J}_RTl0I;xFf9@7;L0S~pCmh;D^4y?lA(dil7IWD z%X9vBlJIZ*hkyG7>VD%ZAKr=VO8%MtPq6@V|8(�s5f$m&KWQM!Z7|Eqv_Sp85C9 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 literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/echo.c.sisc b/xv6-public/xv6.si4project/cache/parse/echo.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..a4f40c966c1697091efbb7a18064ba69b68df7b7 GIT binary patch literal 2254 zcmeHHF-u%Q5FYP6W6bk{FC?JE;t-p37D<2p0XZRoGzpyNp$Ew!cW2Ndke`sk!XiZ) z;SLK=A;ff|LYfpdrb>}N5V5p!{l0xW&%MWKDw~jjxo>xNcD|XNc{hDWK>o|W@&fGrIP@V3T8DmuhR}Ns0W#f~F`>{+U=C?G)o=`9nV9jBslY@PjK>1|1@d<JaSu2Z0$G~+z2AESZ2F^~% zFq$$nTjiD`;DJ7kMMt2-*%CA$@p^)lX0-u=IXJPGRLTgHSr0?C4_KxNtR6_D$sv z2ZZ~qV2Gsyy>JI5Ai1@0MIP(=sR(C26+a(im~A3l1+{vMkIB55qds6BYx1bAAaWO5 zE2}@UABQr#w5XSGC$#g8epY<)|<>)}^CD zq^RxYTA5uU%r~qol^au7@GGF|!((ZQNJiz5Q}ucgA9s7PgkD}Zx c;3MLWeGlxQsE;E3=<^vqrGvyriI|(pC7`p@G5`Po literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/elf.h.sisc b/xv6-public/xv6.si4project/cache/parse/elf.h.sisc new file mode 100644 index 0000000000000000000000000000000000000000..3cc90f61c19be60f09fc49c91c6a78c40e011805 GIT binary patch literal 4086 zcmeH~%WoT16vl@njvHLJ*rgEO0ac=9fmpI^)Vfinpr)p!Rgs!ljqR}%JH`{Lw0}XD zMPi9SLaIceq74!f3j~{PcrD9{MK|nOBC(i$zdLj6nQJQ%h!x^UC*Sp%JKuTUYv+yG zAUGEUGsmRCR1kc8AP63OJ>~RQA$se#2m7(zx_`S2P6z+Xf29KS{u$|$O6WuBN7AD7 zap{Z{IexcN+V^d>#QFoxNR0uwS1ASCcXFc;r}Ei*rSwBvFTO6aABA($9ogTJ!e>4lJ~6W4Q)8Z!te-fZ8$KhRx!Urn)wdRxPM>&N zpI|FUiT1D*PZg=z%&SbnpZ5b-CDuqBkNmjM?tB|a~N_GKxw6y0oD+WB96 zTHZkB(jo?J&u{1M2NT0ZL~XARo+;Bm?1Q!4UpPrpOnN*;+S+2A-H0o6n0+lQG__%|X=J?9nb-#Js@^TD#2V^N!MH?7Vh0ds~BRu)+qD zp|P6HXU#|JvG&8wRtr{Z609`KSXpE9S$B;!GFCc6HDLga)oecND7pz1Xl*pw5#I*% zg&~CqYx*Qp&$0%?-DPqAx2n1i`Q&^yfndNEZ!&^FY$4S!wg!yX7icZXEHXp z5%HeaW7@-w%x(}C>T5Qil{TBiF$0>2yIZ0#+8XrMw=uKP=JBSk^f%MrNnfh*1wB~% zs!|I7`eGVqT=TB)T2m0NdBMbMKARSPcn{g@n!hN&=jCilct=R`cGch3`mB^#^qbGc z01`yj<`*M>m0Px%3vxvS4EnQD5(6m=q-OI;^=K$#H+gz7ko0p>I6*tYX4{=}bfDoW zTy3nc59(Tx!1GdAL1Q(W&q`({V-wbgm5TvyFGyhp?OVreJ}b2`8T*;o>TEQl>jcYj zd{GK5Xu+Dzr`49Bj0M|mb`w_EUXmIbtJ!?ke6U_&-Q7s6%;`eP3L2}~{uXOvqtosk z5er8YwG*JF8!Tc%UrW{IazQ_~Zd8BBZr6^S*w&o!AAa~(xX6PX5zChQxHkm%RdyzD+xH;BNXN<_y7O^ literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/exec.c.sisc b/xv6-public/xv6.si4project/cache/parse/exec.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..5afd873f51e8d9e16fe8beb0c5f9c6f7ccc643f8 GIT binary patch literal 5504 zcmeI0O=w(I6vuC8CT-%hHd9TlSa2+YNf8NHBw7PmNL?sxS`~y^VLF*K5A*SyB$B%7 zR#zf|E>yZH7!Zt#TE&HEkuIvcstZ9kidtNVpssxWfA_uf-kX<6LZ$6OJaBUEJNMlG z`MUSMHyPgS+@sD_hQzMq+=U&^U3{ed6oH6)`mSR;~KV$2+Qw8*2WGOsv$Z!*{*ku@$0(#=~vimPgh=+FG8#g*J)t zV*s``zXm&_tunl%MQ;k|oRoVtJ}&t@K%$4Ge^N4e^g92iKhrUHeKzAqd4EwDmq^T9b5|3T+YN1oAR* zz_^pyqP_!ZdUmivl2EIrU1ni0J{>oThc($)pMY`zF6I9nRo)H z(rBM}<{$&{Rx#lq$r@18sjz9JQg=`kVHp#ko8}3VlgVmh?e`QBT@f*>AbX~e`*dS| zfiO80+j7!QkLik_G{9(8m;r4Efz>38Bs9`7T@f)$l`ylQ8I|WICrO=3ac_f-r2VWj zT@f=&woB^jQ1g%$6CeNthP1t8x+17dQi`Ii5CmG9e-=n~5zA|dyg}09L|25&?|{{i z;Uii?szCB$Lf#=ZNObE%(%zVea`WQ+LZkT%BJ3TnC{Bz8to zlsO>Ep76v((0)uKas+|Ekoqc2QPHiBn(YHnd*`MnJTNz`Wlh**f18+a8KWx#XHXQC z0}~U#Tbhe)J^`8<6C`g9%6^O3r<2p&n!BHNedelJd%)!#6BFxp29x!{ARL`-%(Q|* zuGOKT(b3^RQ-rx!Ox^AkV@|D1mv?hkZnFB~hMPDh*6p60YuAI(;X8FJjPjxmr!?9h z+}|pdN;uyqavQCRB_MDhGf;3$|fp3&RXH&A;v93o=2|^;`>{_a0 z`oMVngZS47`*uP+{&uZ;_UGj?Xne^a*;+)??bnFZp7P%DV>xZ~(ZS-wVvEgQ=17Qm z8S4Wf>xrH_KM*XVq)N@HM%w_>sdsDDpFZkLc1+2h{~=43pjmgVlC_TvBt)`|FFRRV zY{{NdVk61#Oy=lp|2xwCm?g`hXH#0T)+wnvh=SzlaypyeZ7(RMsX|QOOE>sS785rF zuc>Pl(`oATVZ15Gkvi4cD3`LBxJWon*D9uQ^{KZ|r%x2;8@b*QOW#$D>2_h0H*EdZ z&>s%=1Kdv7_FP@JN$($D=FMfXF4@v`jk-+!+jU)_(#x>h+||-u$@s5Sj9p`*&+Gxn z_5)|(l>U#ka=z>@X|q9}w;5+Yd>z}cS0VO{5iersP%NC@XZ}lo$NO?R`#EdZKX$wW Jp)eMH?LT8h=92&b literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/fcntl.h.sisc b/xv6-public/xv6.si4project/cache/parse/fcntl.h.sisc new file mode 100644 index 0000000000000000000000000000000000000000..c64c8aa0038132e5c8c6e1f8db6f8483a391b5c5 GIT binary patch literal 1202 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 literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/fs.c.sisc b/xv6-public/xv6.si4project/cache/parse/fs.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..37e53a7363401b6609c29db29c8f83e3bc81abae GIT binary patch literal 44413 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%0AhD`l394lS5BYS*L>iv2(1u-a0^L1IC%J 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 literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/fs.h.sisc b/xv6-public/xv6.si4project/cache/parse/fs.h.sisc new file mode 100644 index 0000000000000000000000000000000000000000..1c1e15e499a2693c73556426eca2c3d96db33140 GIT binary patch literal 4736 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 Z*ynmWMLY&k1c1*c$o&rc{)oq{{WoZq|A+tp literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/ide.c.sisc b/xv6-public/xv6.si4project/cache/parse/ide.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..ae3e108781ddc68cb1ef554479ba760e798f49af GIT binary patch literal 11055 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 literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/ioapic.c.sisc b/xv6-public/xv6.si4project/cache/parse/ioapic.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..0bb323754708b6960c966fc11c61320973665476 GIT binary patch literal 6365 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 bb9naga=*i)QUU()0%%|RJEb|`guH(Mt*3x| literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/kbd.c.sisc b/xv6-public/xv6.si4project/cache/parse/kbd.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..5d3f2e14ba08c4dd5556b201ee396ab527f04c35 GIT binary patch literal 3629 zcmeH}&ug4T7{{mCw5e{=W@~993WgXewJPfmB$q-Y284=@t(9t3NOw18X=y{V%J%F( zkb_4LUV4Z zpGZ{_?m_9G6j`}Yt6uwIN0ssOs*#tap9)*rb!RJ>iBEEKVWhfQAdfbuEkTBo-6V@2 zt0mi;?@3F8xv1aA*(5nG{Yc~Ar0;2*V5XvsmKbx}3{N)q;eD-`C6-$IRO93a&DQut z=j>8zd0=tk9ic>TUV=>?7_a9+a3S7rFUEM-UU=wEy(s>7g@Id!f=&G9xBmnd3&h@Q zaT0h&3;t$n!4AMxGKmD695BB31DrVC)B#jNj_XE|eNs4|kaETSGIrTjdk-+=hTKG0 zMm$5JeZSRdz{~!p!;Ev!%CZkX&m=52V?Vm8l`OdT6k9yC@wQKO&QRKUc~7g9Z+{=l z`>Yo36v>>hm0Ra4`0M`SLOH`tJnNOW;2_~0Nn?CO@9|Zz5>L}T=DZwzCge@oW4iS_ zvb(kUn@|m*MLU9-(;Ar~*Oqh0Z2W?bz_Uqjxm!drwu%yRNDFbpyG)^BAClt7Fmd<1 z>Y6IVd-EJQH!m-?7dl5YkFN)$6eyYDImh~0@o3_G>5x5J8;kR28mF7BgL>d9^r2GO zM2izP8`e*(sY1L@ITZr&z;fqx8P33V;>7aO8YNgiC0k9rFY69`usPqEe@z3*1u}XJ zc8AnR!TL#i6Hq=ux~cKDemOCh!x?r-gS!lSEW4=Nm%?c@8^!w(8-{%&?S*k7-M_!y zovpv6IZ_TQ`FunQJ7+K~XTSE7t1@rmJtvF;KAhP1)VovlV*-p6E22P7)^U`u;>x=h z`^n1|2>CXVhceqUTc15V!&iXUZBj~R_DU^w!}8dt6g#d>?*0lG{me^qhhIH7bAXk3 z)3~4pada&<4d$BC>tEKYKi^ob5CKh&yP`1IN7LA-0hITwg%ZoEt(VVp@^^ZeO0(!2T>_A{Hv- z--?MlhnxBcqCDM9d7^bvPvgR-{#Y$OLga{;u+)=G&wnhQk+Q$VZu3v-iB?E#_R%#9 zuZ{oy15=zR)Y;&Nr`yd*ZRV4NS}+<0M>s>DOKRJvKUXmy*g|b=B(`*;`Hk>=Up}_= z>tQx$_MX;oPWv=lKDf{|owa+p5-!x%aLM_ax*E>(uW^mFuBR*-Sz0vmXf&b2@}WR> ZM-#BgG=4I}=)lN$_>JA!E}MHX`3tmDVRrxk literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/kbd.h.sisc b/xv6-public/xv6.si4project/cache/parse/kbd.h.sisc new file mode 100644 index 0000000000000000000000000000000000000000..8cace800b6fbe5389135d1634c2c0cc3019b15f7 GIT binary patch literal 3969 zcmeH}zi%8>5XWD9aqReFz=;79kVqto1SDkW5Dk~RGq!xWJNeG}ArK)-Oo-&f0bE3g zKLClAA_WCa3Rf5;Dhi533N=zvQ6fQ2l>%w`erD(8o$sEpL>H8i=4SToywAR!{l49s zKM+Dcg#9PwVJw8VrbD>@u@aux|D^*w`xoT1x}mS--^gE- zpOEjDWAA)7Q=R*3x=Q}`!4S?!BOhw)*6S4=B`e%+U7fBnm&15g(lUF=<32^M6SWlQ z4$kpX3*!R3IuXKo#qTxw_sI~}GTOT^i%#y~U-4epeX_ifXjzRPr1(HcO{PP1hi+ z)cY-%JjN+GX3?4CIi?l*&j_>D>aY5|LtbOindEyjsVI$gPS$JPUaM1IMgiQYHl~?H z2b1T(|EhrY>S?%VHJ6)x%BUWl%UF(^v`=GW`$`2&_3A5~Rtq#r;Ef`hnMFsF=g{fy zGfHUAH+ywDOec>R)1y-v%Td#_hnlWo9bRspzp&Uj-K4{Ga@N5X9Za4B@9ac60z3h@ z*>3cd)5&M$m__H3@6C<7v+VEzxT{^TPs^W^V-_7tp2No7Lw!+Xu#GlYQNr`o$SgXR zJcmv9y$iOr0Cq+`C&w&0mOO_|!rBG9V%zPortAA=X3??aIjnu;ygn<2?z^j9RCYvu z)C(;-nEXG28*NmEn)ote79C8!H#l|sk;<0ZJ-DbTetj)EmpsSa+29Pf(QLIf7dgEw z$1FOR94_yf_^!EmFH{qW2N%zj>fKjAqiU3NT+V(wDW?W;#l>e5ySRSs;tiCBq88 zv0-rBo+{Cjhh7kuHd!wSg!Aa@x;;~!{Q0o$D&F{)u<}g$MW|d4QL;WF7aANprsF{y)&wjCuB0)Bzjjn4a<6y^5)Lx0-KN^XHwi<{yjK`nCW7 literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/kill.c.sisc b/xv6-public/xv6.si4project/cache/parse/kill.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..1ea2579ea6d94750dc7aca849453d914e2da99ba GIT binary patch literal 2532 zcmeH{ziSjh6vrpI_#s{-2GA6VKsDL_CPiuI}p5_bDL@M`1PTL z;aZ<_XQh*}VyoYrj}Zr1z{1_(1dZ_OC-l%3k3GRFjps2f+1_|hSnA#N@UkU8uFcov z$kaV040xw literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/lapic.c.sisc b/xv6-public/xv6.si4project/cache/parse/lapic.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..f3e323b39272181b13528566fa7027400ad227b0 GIT binary patch literal 13737 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 literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/log.c.sisc b/xv6-public/xv6.si4project/cache/parse/log.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..d74c5cdbb069667560e5d3bc6055279fbeb143e4 GIT binary patch literal 13545 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 H3NY^9?vm#; literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/ls.c.sisc b/xv6-public/xv6.si4project/cache/parse/ls.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..b91f736c3f2df9fd28d7f419480f57903cc715a0 GIT binary patch literal 6735 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 PF#pS81jhq&I+X5TvbO6! literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/memide.c.sisc b/xv6-public/xv6.si4project/cache/parse/memide.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..46bbc852592d8823ea6f4bf46f523d799687438c GIT binary patch literal 4293 zcmeH~PiS0q5XWD$sfoUB+ig>fqPSLD^dN{>iGPqFB6txkD^zSvcC)+n(QLBpZZ!2I zh~TjYK@T2sDK?-O3!*0#TRiEdQ0>7}!Rkfv7!i4XKfm{zeQ&qB*%s7;I53^x&ToF- znfcAk@1^(O5Co+l7{6B>j0M4;JA>fjCu5GklY~$IaB&B^)92Uo$XxJ0{a0>)+TS9c zQbKQw-xKc<^Ltzj&3{w~H?QPF)@Ri(m&LD3H?#I(PbdZsF z1O$4cw|COxvmS(R<>JT|UDPT!DRNm>M0ykEA}75E)`L7)$6+7GOmISEHq|XbyBRGl zE-##r69$KH-DI2ePSA~ZvQJhC;bdRxWU*FjdM__(hmdz9hKclE(2e$z4kTW7cD=Z9 zpjinvFNU1-@T>>Hqca*_>&i;qSAsBUY4DJDiNP@4A+3keRh5{lL`&t?$+>!aE@~W~ zYj?`6&b&?=_yMf}enf0e&~5F+9@gY-*xTH2~Fvn&gG)gFQbc%o5jfDNt+>ApqS={w~xnQZX; zY4w{ROk2fplc}I_CZcLBT8cX0lJIRFpeRYK#CW^7pQgVJLe3i{@g|xSx6?W-1M;O< z(4%5-Zx$aE8=-?%zY465(*2qyODTc+HGT-+fsvCfF` zkk#FhLA>;J5T;QPW8aG$)r*z;9s z(fqCdnww#uqxLy>EjGjOw>;0Ca9@z!o2E*ID}=Kbk~=XQg2>twWi$DGVq+M$a@LbI X)19V}vXTQ7Oot<~*$DC_AS3DfHX5(V!n>(alf$6T~)OZB1ee?!WviH$d%AOHYc>edzu53cPMY`GgNX-?0*N8)W!RD~|!(ih*ydVEL zB!4`;biL7BPOr*mY}XuYj*CAG7kVb%laWa{$HiK!kr8+A9MD#3$IpFK?X3>nHDdMb(2|2W^+tp{g~75Tw>*A$-oQKId7~k z14}bZks}EsEo>_MS_q zg7qSOtYH{qV~NYkTDyN+8~0Vb4!nXvB&AA}yJshGB3 zWM3>}T7FzfHa>Tma)EZ*zs;0ugelgTTCA#AEWgKe?NKH9__CMjH!(dMG3EIj7E{aDIZkJo-pg`+0OchOUjP6A literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/mkdir.c.sisc b/xv6-public/xv6.si4project/cache/parse/mkdir.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..6c5b01689e5b7e161f5f1e17e6c928faf728f312 GIT binary patch literal 3099 zcmeH}&r4KM6vwZQl{QW}+7F|kL0l+qED8b*{0qXM+JvR~BOj&7IEt9!gC*1YSGOtFJzD@_n-ci3{d+6;ynuJrueqFN~|{UQo`l# zXVX*9>eGy;E1Wy7KIxXO<-7Ab^iUX6?nWj}k1+KM`sj$KZLyRYZ{K>!&L+>qTfMjx zPnIN`b@+lLHp-~3q+@MY*#$64Ca~&(_@3 zI%rq~aN@a38yNIqSf#rjK>%pgNMA6j_oA#hX6|Lvi%+BG$msNS@f|hC{LEqsXHzd- z8UWsaB+Y@7jS9U(dL#UB2HLDS)WmKh7#Yhfn#Xbf}a)It}!s4P}qB9CZ zc16UwnqVkL_?<^DY6eD{4G**^JCeGjv+Dn$!|&k~JHv zNe?kM+N?>}$J(p7=HnOqtc(!r*N4)rm0|@m=l*7_^f^9=%laG%neO+ouDd+_!+m)U zCks2KV5c5OFA{46+l}s1DOj9g%7V2*NmWLGP12thc6|Y6lNL zXe7g=;g&aBuWW*Cx0v|3HI@t0CGT0|E0->BHg0A_-)%w05?$ znykl1#al QuRZHlNpuz@zhn@)p9-NtMgRZ+ literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/mkfs.c.sisc b/xv6-public/xv6.si4project/cache/parse/mkfs.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..c90745912107c57ee1a0dc3ca19ba64d2f63f054 GIT binary patch literal 26526 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 n2_EG%o|84ZWch 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 B{2~AV literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/mp.c.sisc b/xv6-public/xv6.si4project/cache/parse/mp.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..8aafa456ea076143b58cbddc21af03ac5b320aa1 GIT binary patch literal 9578 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 literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/param.h.sisc b/xv6-public/xv6.si4project/cache/parse/param.h.sisc new file mode 100644 index 0000000000000000000000000000000000000000..dae8fa1c62868a0acf41fe53593e0be2a8592537 GIT binary patch literal 2058 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 ZTmRdUBXs=x55zxLLg*}c>4hLk{tc-@PB#Dm literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/proc.c.sisc b/xv6-public/xv6.si4project/cache/parse/proc.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..18f6c83d8a80a22c2939117f8bcac674b2262467 GIT binary patch literal 25493 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 literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/proc.h.sisc b/xv6-public/xv6.si4project/cache/parse/proc.h.sisc new file mode 100644 index 0000000000000000000000000000000000000000..12666e6492e29a9f76925eeb88f4e9b97a3f3c66 GIT binary patch literal 6820 zcmeI1&2Lmy7{)K9r67aUQl)+&U*$suD=JnKjS{MmKwCZvh1AF}Gtdb`JDHhcbtCaF zV8OzL3l|W!Y{&+p#*&b@P{jCSD$eUq2x+~?l& zocFxvJ@=j|-HSZ$pyxGjmU~T}_fx0m-MZcs_%}lQ;&-=Fa2LP0ybN6E{cm?m23Y$C z=>CLX4YA1Z!nD1L;VT=ni#qoXO=|kM@5k4Yh9OIr-`%dQjmeEkNS(;@; z8H&U#jc~aTQR7@u?wQqzj!Km*G1fzJX1ZEVC)&m(XFs`esy%t_`#c#M!L??_Mk~3A z$^o@mp|$e+5{R~OH6pK50` ztn=sTRNbyXnVV$cta^go>t<3tyUOggKpcJ-7jqbco3Zrtw-TIPFP&Rc!CbCMqg8Wh z)BADL(r;7rJGXAC9mJUw???J3-#5ApEKW#RVx$F&UabLyO#Q#j8lXkvPYQ>HhxN#i z+Si0s0ON}eN*BD>;n>khOU75X#nQ!mCZDAOkRnXh27Fk~P{z5kx>dEh3Mgkra@p}h zuGFt*P#{q&BD`OSvT?35_so2sxI#mxsZ!>fKvxQduAl{LoGTfNum%W)Mr+~8Y=s?5 zUv^7dge!%FVw|g48)m#g&}>!tmnymJzNkNU(E+JB`Wolz#?cWgGYt*Cc{EeVQv`IT zfDr{LNJNcuMQam4uh0-(l-E~bG)=5@r*_#)AWMdm>}tCNmk^WW<;(VqFFn&mvqrOWfaWvftJFQlv4UL0Nn|Xi!Mx7PN&j z&YgTRrn;iaW%Fo~cMcb5f~IMltEoq-RzhH}6L;?Bz=Id3kZuOzM@7;ukjG zHLC~rK&x9-BStgE`KPtS%ehqvJ|@2!3EWWIUes&FF;7F*!rH3uwx~-0we=KNH?bs+ zSej)Z(cp+xBU?L!BO4#F7=_5zB+#OTbE6eiwYrl~@`%N9A>81IRTD3Rn$-y>k66?f z!VQjC4TR$rXXdSmBNiz_m*bS7WdhF4M3XqPx({r4#3GIkxs`6)#+lUYm*H=*5zXU0 z#uPW%|3mex!RwDHf|M@rWGj)LKf=DEg7N|}#<9|UR&7#qC%dj-4$H47{)6(X>bO9D zSsj|h52^jJ=1nQ{do1`60D6{F8lQIP4RVqR@|{R>?iRQB^_b=oCytn#%J1w48fM$)6CmG9A0a)JO&)VRi?ap+-Pi&I9HYGHmm!{XWj}r89J;UWeygtKp(WgTw7Nx!dQze9h|ft$RVZ^Tpx4yAN*P z+Ow@^xR5^nW_fJ9l*yHcC(dl&QXD^C$Y+L0;ntD6G+|wu7jFmqgo6vuBngVs|zRlh=FB3%%h5)w%(v9uBrL?V8SYV`%9nNFK_h5w)n2@6|^ zvGFUCE`zA4%We|8 zR_8u1c5e1wtLK-J@U?fdOVC}LsdOMS?mzu28KCxS#N7($lK84PD^?qLDdF3k- zu7L4mi*wu6C%w{5yB4oQ4@C(*x!4iVBTW5*K04xQK_X?w+qYh_v*|O*RxeH@lZTQ$ zI($?T8+FuK)3LU+Zn55nMGf~CgG1i*kBLokELp974I4weM4Pn)PE46PL7^>VS*LBpy8 zJ07{foIxK&S>5&61su(uErdnA7j?~X|4uI0_&RQm4xK(P?!21|Iwz+yfK5De0SsV>EnD93{FkC1xO&4}b zfwjGjgJq3i-zx!EKGuQ-3{w`Y6-uf)!r3(aZebe>@J;x`uVSADW$>~%uUB$f7ulK( zUl^ND8vgNSE666kEfW(zx5jc|y7WDpn{h#Xv(+9;a?!0DJXSmt7Ef=~JsUq99@*62 zD}7x-Zc&gVc-AP$H|Y+2tz)qJEVyYwGx_tT7jb!-oY(tD1}$F^7T9s?l`Bl`nk U_ElV8eAannA#@fbKV=ZQAFBsMU;qFB literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/sh.c.sisc b/xv6-public/xv6.si4project/cache/parse/sh.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..ae760ebbbc42442c1446405554e8421c1d43d753 GIT binary patch literal 40514 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 literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/spinlock.c.sisc b/xv6-public/xv6.si4project/cache/parse/spinlock.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..f79de5c5b9328ef0cefae26dc4b986efb4925544 GIT binary patch literal 7492 zcmeI0OKenS6vuBL(&F%Fp+rE96U100n3@gh;ePOfYeQK$IAbECj1@f$<$5Vc7)D_5b_sckbL?hdwZ1Vm!&2^WF1( z_nhyX^Zy=q+GYj8#vrJ_Lmbow!Sba+aPHk&$LA&CgI}MUgYMwz!*h{!!TLZJD@$agUf|b%9V3{^6;FuuDm&N(tDs?%>z24 zFr=IjG1K{R2qUXk$^K^Pu%rFPk(1s&?P~U28vXb%T;y9(CKko^`|^Fo+|GgFAs+?S zgiuFLdM~uAd6`}meSO2SPoc5X=&XC`?W3z^-(bfpmoIdwJkTWvISs;)Ei5O!1KQOb z7%0>&2dvzPNMB2wromF7zc|pfO-`Ot2gclrmINCZCNdVTk=N*h zI8EcDf!pRyABMA(jEdb^rGb*n;sO(f((KXZOz#&99QOW{ewTb)kZ$yWH|uaWemck) zIGGNo3Hs!YtVc&?lL!33&{U@hbw1=q2EpT!*tf-Cl5T6?6G0f2qvTw|urdq$*Y6l8 zbZ=0DoC7Z1sGPh>5=W-XR<@B~ObbC>F@<5JVi>J0ZeyM_d40K;t&(OET{dBI@uz8% zsd@J2`trP-EY99{nlp`GMa2Q5-Qtpp)B5eUeYo~pVe z8M1)ws4z*NwXb;Dan|To>&~1TC8?h2vWYb^ax%R}Dxf7GExR;eMwPEK9x%2-Is}+Q zzeRxINHZhIs|6TaAr_WNxr{@d959zzAxt_6nn1yg`+yBJ2b6@;k_u?p12~ed6=>`p zU{bE*yTKKMhKmHCK^kaGmra0Xu`U4`5>u7EIt`kpV_JA$PTW=l>0bHK?=rftTuabc zSSE?Z+E)Y`?%YYxoDgUlJ!onb*>-Webo+N5k9QijH4w^u#8R9=~^G#lzIY%VajHHbBW0L6nI2T zd5{faY?^Lzn~aReMPA?|3rmlQvHXOXo}})U#4JaSr7zCh-y`C^rY!^IY~lX4dkgp7 zt)CSua5w?2+RhI7#)Y~s|jf19|6Js`t4~y9ph;5S?GMQ|v5G}6L|0L(~w@pEH0Ljdm8xm(K z@@6r9OqWe8;j#DAn^z?=@>kEl3+yyJJS(PHNZV;lm)>cTMGM2q6LxCKJSR&tsxpkE z&go9+&iv}nX?>y-7VlxA? z`a1W~&BypW>A|C6QO&AYBq2ulvFE9;$p@a7@x??HT8Axn5@V!&X!^-6~*$@E*@rg1v7yXPSyNv!$LXnThGXH`DR|w%w%v z$>u&;U(yEcnT-9X?@rqnxBxSd;fMQNr?9c^<2v^dWn;K*yloPs@zWq=__ZJW_807!} literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/spinlock.h.sisc b/xv6-public/xv6.si4project/cache/parse/spinlock.h.sisc new file mode 100644 index 0000000000000000000000000000000000000000..5641e1a3d74aefcf6d30e621acca9de226955c76 GIT binary patch literal 1477 zcmeH`ze)o^5XLuu)Wl1K6B|1V8#~LCc?89X*eOX0QR6`nQd;@|mbL){f?C*Hh?SNx z7WxQ+Wg1=Qw|kSECxW&3!FRJev-8c(-rVw}F*RfIOG1-1<~?sr|2pgVC>C~~`z3tc z+g=%)GynK2H^8@_7tTpTC&E)*VUuA)1t;cO^RH={~I~p%K1mM)mfhL>YWIuIM$AAA~) zd?*QT{5Y6Ix3Ra?K-TO({VN?{_Ls#MRnWTlt+*~eS4s)H`618le4olVFAvGio=ErL z2k%S8lH|M?j5BnhryG|+t9*u1 z><~N?i~Bs%T)8zfzaW1yb>t{ZRL+A?(-0x_Vp7>?bLIBT-D#5L>P?8UgylR4)>Dw# z1|>VaG$#wAg2%*+j8~jp=Mkl{OW!Pxg)@^rzV`%4bXbQ@lV>5yf)^hxQ>S#i=gW zJ*70KzT&&jpR{J>O~**oc|vDE{ayu?={JSoB^AZh?zf(TiI%B2r;|eWSD5Y2WA=$= zQ@C?OXY%xW6%(6N-#&F7wL1^zWTuT&Ojbx1hL^6ZqNe-R*V482i`F$g=5K*}%_%?u zh6w`u9=+1vvVUCsAyQY#-KzSCMI6XuQqa5YJbSZSi_1?uY%V$D^F=YQelC1GKztw@ GMg9Uiwu62E literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/stressfs.c.sisc b/xv6-public/xv6.si4project/cache/parse/stressfs.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..3aa3798920c612792c65115674bd813ad8e86d1c GIT binary patch literal 2864 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 literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/sysfile.c.sisc b/xv6-public/xv6.si4project/cache/parse/sysfile.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..2486e8b6238ddcd9ea9bc87ac4bea5c2ebd07488 GIT binary patch literal 27340 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 mh!TH%)758rV}IyqKXI6`FSz9o}80Ig_j)I>KX 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 literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/types.h.sisc b/xv6-public/xv6.si4project/cache/parse/types.h.sisc new file mode 100644 index 0000000000000000000000000000000000000000..bb0f9cc36dc17dfde47f4899c5190364d5e21732 GIT binary patch literal 1192 zcmeHGJx>Bb5FL+$!tq!1$7v`PiAq&N6qH6KRV06;M2pEnj5(U+6!OdrRlR1TPcpikdmZ6@Z z#Ukr0WbE(gE@^MN$CX;+q2a+LTCjDH8flaeXl@%m=SU;1ZOr17ckq+*i?{)Y7gZ73 zvWw|26GeIsWAHUOP&AiZ_b&VKF131BUZ+o0&Y&+y zTL9TfKLi&uBKUz{s#o2!lXxFh+yzpV*+^9-Rh2xeVn5o^!M9yto?s8P2-W2@ZS2p{ QTgL9ms+t;fKVD`vU%T{9;s5{u literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/uart.c.sisc b/xv6-public/xv6.si4project/cache/parse/uart.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..bdad810e29730371f6d6fc7cf8180713fe451831 GIT binary patch literal 4314 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 literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/umalloc.c.sisc b/xv6-public/xv6.si4project/cache/parse/umalloc.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..aa4625ae507d1daaee3f49cdd282be48cbc48527 GIT binary patch literal 7326 zcmeI1O=w(I6vtmD)0&#LHf_~t3mt03)EbGXAlB4YC{&>uwPIA%PMWC+q?2bRkyI;m zAu6uA5bVN5H$q!Qt3`-{7_6uZ1re1l1nVb$p{^w0$MgTY_nnzLZ>CAQ$VNPHa_*da z@Ap6#?i-IqF@!1l1FT8tnDYPZ}AO0&5Aoogn zew7@0R`|SdiICrUA#mW8_O{6%m$os!Ud&GyM$wdbeJk^e;Ta?;9C>(Y+qq)$)8k#-PLziRTE7XFiD) zO}rDi+GPwR3A;S7ZqZ<=I8YizEFv%vfUXuIn(_I zv|C8NXd#Y%+~$-wC0#w>27Q1 z5(W``Y6`ia@x&**4o=Cw(3T`23m(va&SS;$NV)R(tr~~&kV}!^i|MHK#3-76H+!lq z(B8KN6(pj80_6liDO%PUFO(>D9VAIc;so}Ex%pjrnEck~=BVcW7RIlNx9&s>YdQJI zV2mX*<;HTMW!3eJXUh$1b_#oi=%NNV-%yTX$jf?LpO=~ij9TKcQ4S=wQ~g8^3L?{Z zS(%!uLXy-f4w?DN(4!?b*9B1l>r8|ApymdI%N5wCe?3|aB1QlRA&87azWR zm*x`0`_esD#8z}+VP6mwHabEZvW30OxAk0F-*#hIL<+c=y1hnrUoKmx6pE>*Uap>N z!h}n9u5l++shcv+FCGiYcU@t~$?WCbDWE)ilhS_(pVYXc)EKFr=~yaGJ1Z}rfg zLVvumKknLG$#I~1dfYJ1<#L=K3hh!Mayx~l%Xp!#j*qgsXdNEdw?ew&je(~A7-z%d z+pU_tF1??qrvc#>@qYN(AK&nj#x@|`;}wGAJ^98gZLK_ht3;roTS)JM z+QY?oib`Eu!!v`%9)yv^?kXX9f?A_AUREMCY|zjs2OIi8uhKhx+Na$5z%Ct^zVCb) z+PfODm@?mez+!I{S8RM%ePDd3JVw2Q_5HCNn@H<>zdX8tbcuKPiG|hrCcf;k`qr>% zeTQj8&s^*KJn4N=X(!k_MPCyAM+jImv~Lrm%-MM6S|>#wuqV$2&H*BOHwtkIYG0DZ zD+FaZ{dTs}GY6>Lzi+HmeWq`fIN}ARFUTb~hL^2Pv8vEm?R=eLKa!TEbfu_CgqM}b zoI%59e>_@xB*uO1if$5;C#bz&jF**4xC|P;&&%WGp|Q#?%@dbxLY8kAx{wFFwLw%5 zP5EyMO*=>uT=T%bmAbM!oxwfsqk2P6Pxp}cn0&Jk7y5*(T`n|UsAKxgZ02g$Ci~Xx z85u3aJx&X+5Pd3a+T?!e4MHTtv$9K#VS9R3tTA-!tbFi`Zw!1F<2Z_(UGC_029z=CcWiWz%G8 zQ%UpB2@i@l@sY+~F@ept}xnX666D+<|ji;&~FQ%E&(*o_xfVTW$Y(1s*g zrIjAgyNbuDJ%Ts)_~Vpyeu_#b=7xVj`d}#@3eTWdW*B2h-RI&YC={Bw$6BS&GdS0AWxv}K?d>+ z@6{MIm$n>Ni+Fx9g>W{&b`vqzeREmgY)vy>sB^aYaP67KGs(!#@jK*&<1@*x^&orM#Y$LjDEWWC`{F literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/user.h.sisc b/xv6-public/xv6.si4project/cache/parse/user.h.sisc new file mode 100644 index 0000000000000000000000000000000000000000..e8eee96ba3e57a558b23ca1be29683cf089b74ba GIT binary patch literal 23483 zcmeI4O>i8?b;p+^C@o`1Bq7FvKQ+{cy^?cKrF_6q$2~bz3{?>2VuS#*C=w(J1Z~KP z6WNlZOFm=D?I<&?y{p@GX1fEpTEB`Tu6-zth`0 z!E!)jtCGsAYP>gZW?uLI^?ThtJ+pZHu3BxjR-1TKrFOVhd+zC4?MH7MPRqZFQ(pPE zA5Efro@pN6oPSP{Qmai()@t{k zsMR*5o9XE-9QCJ#x?q0cI`QhFrk$Hb|}vGgIyA65zP(P5wd=I&bU2k)uX z4jbhgneM;qN$!B%XRbBtO&Rx~@v%2<4aWKkMO7MGCtmF8e^i1}r zd2MSl#J0QZJ2M|loV&Do9-}x)ZBGeqqsXz*?&en10g=(g^`$k8;^nmaa&DvOVx#Tv zj4=9{`OGLc%KIt7Z4}u?aR*d?V`~y*rXlz%ODl`Ns;F3vB|RB$RXQi2;lvW;eE)%@#QlMZ!s zySq_S&tAB6Ic+LH6{{)12_hVT99!*ucSKj6U%GGs{NQw?!0%VVD6);Zd)jZtO)b0u zgo(xV#j_X%r$Ze6eie)&+bG9S+)}|reOt6A{2rX5Ew-sYU@2WC#lplIzG3M|ZL<26Vz z1i^7LMv!e(VoF_kz)6N;*yxp&UnW=q`T?#G!QE118+A)t_r`fu3<>nr(fJGWtII?H zI1?2pQF%xOE6BF$=5>zWjDnRbGRh)ALjciA(@y6n;EBp16=a81-{{x2CY>!hE&Nem zU0z!~yYkGePJxus1cHA=1+&Pp+1}T;CY>-kEwe@P($>3|7nheWeR`4ReozJ65S(UW z7df`ueranm%!<LoeIG!a;4K9XMt2R&wy z>1E7%-TKaxH>RA5QV%0z@9gv*O* z*y71YxkdyBB4&_nR$@vkpS>|PIB;=AM#R@$%kvj5TuK)jgwbR9DY!>2T7R>7eD1Fz ztkQMgTVSPsNQQA>b=sJN)pAv=^ideYb8j?{H*%~Uo%^XuTe|Bnp1j8~Objvd8Y_BY zQfz=6vnZ*@$By5!du)LGaU6RZGUpo0Rq@bt!oa5Id1Q1+VZPQKiWjmaBjSJJ)0dVO z==jiyO*yRnwQPWSO6L|-W|VX@C$fO?w#PvS3}C6lz|5uU>-G+q60mW^tP5EEFEg-? zm^nFM`_GDqVKigmGp>kXB!J9AdA|{ZE!HLQ`&4kObx9C0owwo)w z#7u806}8mB;cRKa#}zRKX0EFHU@J#V47M&{ooHRPDc$sRG5<22kzbA&8W4_U978z8 zL_JmJB+o~rE@U3cRih=w+7qtr2y0iJ-PYW}wX7jYOCoC=Sp9fm4pz%mvEu7+*jpE_ z?L3Iz)w$0JV1s^r;a`p!D*;8{8Y}v;el2n)>(krq*IC(nO$BoQ`ib3~bC#=O_WZ&9 zV1avg$GRjK4eCcnY#5wv&97nR!6n67$f zM_ES}v1{yXqA>@xit(gmZ<(vg6f9mXLkgw8_&Sf{rJy|8JO!?+c@temgXJKFj0?>$x)Nfhn&2FoO9kF zGUuG-{pK9^v*7?gr9$UfmjpT2I(8d57e~yt(xd+J;F@h+PHetEix}R2I6dG8ogM~e zt}6Rr?>J&M1gw`YP#G;*<+r8V`HLcAm=*ByxFW`TKIW=A9a-V~jTmf^Zg8TXPPZ-z zBBrbN1v=HIp*^RvF{XnP^G9nBsM|O(e=OwX);J@^z|28o`Hmx|@jX4h9b0{8G(JdU91Kf+!$vZF@R^55gVY1;D~yv z&Pw0XJ)W67{hDLia@DB$72Qjlx!qeFZ@L z2wC1c5NTaTNJmO`?|Qn-n%wWMQdaM-ae0c+$F zyC15a;e z@DU87JbJ)StJo;IBzOd?|JOdo|DMMG&1he68(qG}F0agNvr-6gS>S50xVVSGi^z#7t-dHENBqips z(v8`UfUS21gLqTAnGY8odrCL+PWB+dI*9#gm^rPtyf@flnno&p@(`}gC}B4h#GL>u z0d-ns99Ve+3z>&8)yp8X49XK zZzo}AWz&62!a(MsToo^N!R$wJI0X#WCBbyoI}tB{c}1(gly-udGnrZX8I;L;B6gCEoy2)rRSW0bm&S3dMY8udV54t;F;Kj3XBN1FMX zk2=BI72apR{KNDYNK9(vBVQ0WZX^!W#W93GOtjr`!&t)ik7cpu>m4&(3z>(q@SaLf z=6^zaWs@513Hx?NSa+eF%IcK>l z-cRUW+QR*eYjEd?bxDvT^`Vcc>9vf&bLcUSLl4f$TQjc?uJ^jqolvw;Gar4!A^1UM zho?%TGN)e4^4=cVF~OxNfi(S!2q6SJqxIfK4%T})?eFW;y)PAeIk=Y!9WH-;&4fH_H=eh>0gHn`#BDoB)`&}L(5e|21n9n?$7sa(j24X107#Tq*T|Z@|NMH zFKRFfz(j>F(BTiN*l4cn8*P7Mgwe7s)Q)nep}*^~K>z;@y%^B**i*S=JM1tfs?3wG4VCDZ-iY$lT3 zvv4R;L9PUro~6NI-fgHCr}LiWO$23HU>|?B7^ayX*p=UJ-rWvZqUx%OdzeUo%tLwa zyeqOFtm(SkiH9-X!oYc;I+V-kl3>5H`^^zK5^kbm3=hE{P_a>TN$qey@tPYWep6T$ zi`$CD?Kl>td-?bCSkw?f98&2xViAz`ARMx;QY@B%Z7A-#(S*0D_AIwtYqH^&x}Z@r9y1+;vpwTIlxm7!CUR(9rNr~(bT~Ia!eNM~ zEph}IU6^>SuZ&1MjDA8l9mx$a(_tu4u~Bq7?$3BD^EcAHTB%dontmD_1z@lJbKkLj#%neqdecJQ+4g+3<(iIStvkuABlCJiZVz#4FwjHT-ub#yjCXc`zj~Y>#= zk7S4aU$t{+-QGDjk>8nhOuCWeq{9Fp;7r~0o^?r(bSLy%cAe@|Y0||Zv;Fs44MwkC zd(zeN1roozcYeV4@}jS!1r9OfQC{Sl(1QjGhYYrI$k44}$aM7>wvmHa+2YMDzHM}(|Fe*~q-Jd`ViO}Ie97$0TAPpHr%)+ND~z~jGh8)3ty zA>PCQ13%n*!qz20EUsLM7f3~lAstzsUynnvt)6IqXK+_|Te@do$VM;zR|CD_&^qW) zw6n}rb>D%NLoo*16R_=X557R1{s+AvY8PN}6oBCe1=hR4?nHA{+3)PV!A2dc)dFn} z({58(=dNa0JyJI`#?-%Bq+OzWNIj>W#L~1YYAbx>Ydy|z98)|}e>A_qoI}f%QtnEy zJi-7&Fr2}QPPZ-zvg4g+ZX@O5h}n@BXRZyVM@PE1^F=lPbp+2t@PmpN4_XFhPQ8}* zj+kh!W6+92W<$W5uMdVyQz0|+`66Uat3tf(kilVPBlUhmM&%vj`mj3yRPW5SMaxdHcXvt$6QON8_cOoBA`HwO*f=b5`G6rT28q1YJ zrVMOdz_#;{@m9~ebWi+2@e2AuRmfcEkf8x(A%inaIL9I65vJ@OU+?^QG*_5&Xt{E@ z(4cTgol$;FNBPka*wzb0ems=lW3UIEACG}hWFE?u0pmqLV+`PM-iHCgx-dUp{MYX1PJ+RmaD&!~Xw&;?TOiL&h~`b@SPlBZm8l6!<9>@K~3G zld%4mluq?&XhbdB*_xBXHlsCaTe>8F!sZ`T;SdOZ(37x%nNzRjN)ZECdL55Z@GqWY zJqUOCCCQWt6=+-kHl)+|r(@aC|E|Aa0xM+PMyEc8SOZXMidDs8bPI^LPUY0pz+=rXa2_VR`2m%g)#r%_j&d@&pP`&xgj~9_kBO_ z`ebMCXYIY$T6?Xv*WSlr5lw_S87q(M+s>D@Ii|Um(E{Ed9fNke3j$R zf!Z35T;!_2>uX{{!~-y-gSva#H(l4Uv2j_sZEM@+`CZH4fF(S|Lf`-{kAu(^n4H75 zzbbF+6^AR;7T$0Hl00xQ&hZ#b8rn}xsBr-36f0xs-PX1(Fpw@Qjzc3G0_D6R%#6Wx zy&JcR!AnF$My+^1%!~o$JO+snv=dBBWa9(>q{;|7Q4l7OtrHf?(mW^#wt3`fXE3=5 zI@^1;Z4!r8HI+vuT<8Ti8vy0$IpE_dFn~iU1L*y$-uAXl@L&}3_=FEF;b%N3=kZ7s zNjt&hqu92!t&E;Fs1*?hEA z#3a$1GUkIiWpJLV4lAxrd14|nJ*5R3uIs!+IdPFhUvka-gr?zQnyRkA#6+ekXztU~ zwt3?VRDcKxBa#zK5!7%oQ3hZzF=2{Kr%uDh_O2~$Td#h_Won^#l_dC5HVse)7ZZl5 z!Nf%3U&$fT?$^7mL%Ky?$k=Q?US+x+u9QV79R%omxUiUU7$EOH1y-dXZ+H2+ZQC~X zZo5JV#mvGAY6QItYw83Iq6_IK zEByvU1Vf7#EoP7gke;6mJCJVQy0I;l8cQ9fv^T|RZk{HDG=EZ z2%jw6svN>i3l}ZUVg#PCuYy3P=6%cE<&CRQ!&0SU1(y5(tO8l4^_{z5KZ7piT#JnvK zc_8)NG-^1N4c7hd!pMUg z6u_UER42mrcC~HY*wNX+q+_D*6XyT9fpD{M`}&xmV_@i43m0Q!118;)!fDB2GU+KwZlLlHf${~yu|18UJp9Ol)Tz=Mg3y6se+1b5617x}HtlJ=bdPb)aej<);Ffy@B*v;Xa*5`hiCl zU>XDbVqsxba+s(Z!WQ2eg?=;;xm>l#^kSvQatN1pJ+h$Mkryg#UZ&QmUo33j(v#{0 zZ5*St9)5zpKpET>0hd&Se*^a{i6X_Ks>NgxBBvUG-7=+D1v2jqq*=Fa$RXWw-;%`y zEd$ooeG>|)(EDxZzFKhzvQJmKIgog<;sCn%xYGM`$d*2~#IJq|75f#AE8MKsfo$(} z8$=e{9jkO@2rGSoEFS){fK#yo>)v_S0&H!N&gs;@k)lD;Cb6C%bez)lfyi(m{4C*K zl|#7UU3W$Pw!c=8%qjL4VP**e6PoS_H2x#dZ4&Oz9J+h{C8paTKgK|*9vYZ_+cs|O zAr>!J`j!#VYJq}b_Fslm*`VRQcP(I_WI!x#NOYMJ-goQfjxF0z1ES3jYtNa1>KVc< z2sooazV3Z@EogKIV)3HFDG3JsvLvB~OH{_A&JHxL40IcXdv*@p@^g!et7FAJRSvvQ z_tuS_=$5V2hCtwTfhgK)&mlT~c5yKaf&tF3zuRI-w_B5m4B?eZZwN#dDSD&ZHF)AcB1$5J~c4N}Mu#U-8Pez&buw$)IK%|D33h+mLw8B#?YV6+LBgou-rxU7Ia$k{m|sNrH|V-zH@fSr{AgcojY>*?U? zQ4%dVb$M76fiEkEDu<5*9C(BE?Zw5_x?llF7Xc{m17$++=}KP>1Qsd2LKH?{b40N! z(D%|>qVt@S?X$V9yNB^%8C!75A311o!>v+YM?v4$rWqgN)oSBlS+u^kNs5t!6M}ixv9;m(a)7iNBTCJE(%QzQTVcCka zN^pTHD;M0Dy~f3Gp3C0PP0yvhE9TNAsu+>@1eZo7<6=0^rSHC&OSVO(-&4Cg8`BMD z)3W*VPs+wKfByWJsvgHVMhRZWDj6@sd0tE9G_*6An8>aQ(Cx-}9ZCbj4Ss(9Lg;c$hn$35IOSvxh7);!KVa>>)1)=oe=pOh_z(RuohYJnCBZNyQ-73zZm*;WU6sfD^h3YPPH8?&R#7L9&&CHk%2KQL^Fui2ofq_&2lzT=!+C2gy{C}GTvaD9^RmwMxdtaGuMW z&%`!o?M{JF9+s^n*@{(SZKU>WCAgfUWLymAx$ON|%w^_lqexfTby#s_Z{%xb*|p`q z`3sQ=FGkNKj_1PHM7Bz%7V%#bt*7I{jcM&NnXn2_FPR3!e^(?^vv7l-&16CrvX9f=tJY@t{(xWNLWsot4cno6qBvY@I;1ygBJFhQNn*z;tu+R<&6o=ioy6 zh*G>>a1st!?#qvRy&x1LB)P2@hSS8E)q2q?8VvRdC5*@Bkz*#J;r!&={i%5J9io;g z(C-jU@vzC(7Czl#qZH`9ObH%sO2)%*p2yOU#yqki(XYX;NkobbN)YZ=N*XwvC%pIG zbT+Fxftpjq%9;d4RD7)xlzWs+WW#yNyA}CpXOI_PZNDD$a!l>YHz@Dz`+4Gpz7GEl@txu zT)H5!0(!zP=x2IDzPy=l`c!q&-j1i6`Lt(NU#tY}b|u`De3_ER#go#@F)@+(4ZP=f zCVM!L9ZIP7Y9)q4*>K+Z`aU%MeCg~syVl>DrL&>P-&%zmm2HuQ`GO#fg}fgA)+*cX z{b}_aC=1v8K<01Q6#2}yW-Fnp0J%NT2e9_u4rxvLA4PkA>lgo~FbA#>(SD`Tj~=vm z_?!<^R+@v<=XfPsY0y_5eGF*;pP9-;5FMgp7?honTnA2Ixi8Opg~6E-yiW<`lH=6y zG+gY=s;WSaGhePs#(0Agq+b(`8N1=UGcVOs39709*NY9Hv%g|=r_M)gQF*O!(0zjv z_0Tn(r`xwPj{UWZO70{neoV#>!A7)`88{;27r&4?B+qBS7#+d99+RYB{C7q{c~H2~ zhclUw1;xyjOjzmAKwnv*B>v6cPp>yVB8A*2#>1L8{og1oL^qtabN_*Bx;9DJz2r@j z1B5q#5BdeBo4A*WQM(3xh&m(_M#oH=KPoK}ey37bAZ8QjO%N7X?#qvR0{w%iFoDQz z0vT?W6X+t5K;(Z^f+RUp0-YLeYLc`}0Xp-#ZR)&PM|j9vm8c;Z&QG27!!w*Zs8pgP z1aZ5!D?yYpOvpXq9UqBzO|(cM>9=uH??!frjQbr*5Fb>ck^pTuPjvTPaR50;EmNT1 zLAnju*uA!NX7^dEO8UQYCHg?4?^8k_?^mKF$#6#(=2hawUg?8&26@*^l2C#^=mkMW zcB>LZDI3lcUL(;NqCw4NarE&b)iQ5BpoA2+E19&0^ZHnScWga0mjeA3DWG<*UAwwe zDj_eGkVM8|C6m{1M;GR2iV*26Ix{`#l|s@FdE0c%9KKTtc|WdXL=ETV?fZ1BU7}11 z^gC4Y+E%)Evz|lEyCz*!Fj^X2Yi$*-KLl-_eM43p3*qV!w8s?;*F`clN~UoqlUaYR zWWoS`XHyXW?O}1-t-A9RD@G;f`fW=R7e`O%2wj;>gp<6Wjd2X%W5?44ZTf6d>QaLC z4kh^gn-cnIJ3kR$)2h7=lstUW)Y);uvbGB7hRJ+*A>)mK{=1bMFT;6WOT|k~ zDljoI6|W5yfES&-&ReA4ozaG(BwVW&Z*)cgLk|F*>*1Rt;=emO6Bq#Zi(40%Ovr*< z^^&PszPTsT)39(m$8TML4EQF|hh)BKz9v)^m_7|T8{e$5o%k<}^fV?tHT^P^iSP)& zddXClOzR?<2EaKzv0xxqy<}?Crnw=yt~w|^^?fhX6MDst^^$2!I@uF#nw#1&^3V1Onv+owcQ{? zyiZQcR_J-k*(`rTiH$SB&H$gjn*)L6zC7#AGCNxw;L}PBik!&|Bf}{u^k;(6z@Sw?#Je?DTKn z5E?V6d0Y+Y&ph)g)noOaDk1JKluTU1d9v#ch+hKWoHYgd9qe|WdcrJk@7Z{l=Jej` zD_AAX>Gj`F;|y;{FhZn9w7FQ{(YTK@BOh1n{Y@$pd##(4#)Ml_I4JQgWWsk)k;$ZD zZk(Zw0enykU~6w)Y)V^Xd%TB)VEhj&nJx_H&9PIr0zADb_g#AF>V#8QtzL1=+EZ8M z?7Ny}gPp&two8j}JHDIlahMP0spNBE7m=;9%P@BNeYH%@!tMHL<}1uLbYylhJwwZb z$!@rr+J$!BR~q3T{P%DXy$Qnd=^fws-v(@tuh<^PWP+!+6UTs`q41fhOn0d5dI$)J zIEe6{O3)iqLLcbGaNcKjjKn@e%M{>GywnMA@t{6n~f zFSh7M&YxtqK*z{qws@kawMbX#X-qN=MKTp6)6mZ{nUDpjmrSjaX=xPx1|-v7`7HV& z)DU9uBMUW8w4RuhRsJNIb_YFuN(Lh4^$XYai=z(2UR=j!deXLXbgF!;sO5C~udA2+LHXGB;P<@c3UkbWK=p`OMdn@fh|jQO z8u~#x7m*2BFwb1c1YJKDN5y|<(9@WdF)HTclC%7+N0YaDnTwpX9H3-#5ew(dtH(PR zpDMmPMU#1W0|pV;T(nnEauN= z46TwMKRGHeXmkt==NUBAFyNFjg+v!(VD}Sj5Y&1<9F))PiRSCLd~;VgrQ_9cOh%fk zxe?1$l1xjZ^}Ge#&(ryeOpH(Jshdm#JGJkL*7H$fos$W72I{4!viNsJr{iVGxhBLl z^n@(vYOZ9$FT6h$KcUN`zfI%+XH>^~G%b>IVEKnD50pGvcrG+qTvIVOt|7MpeC&9- zJx08*u+JG-4oxf1I+k^*Gr}}!VB{;6BN)avoS&rI8{#NXdw+$`Bs4AKgC)yOu+NsP z$T`m+lW~V4Cu|jNuQ{Rn9s{z?#p23>#3s?4y;1xNd(soG{e*mzJgrp*Uw_CxmFv8R ztNn5%Gq_ZiYjCbO8o+0!2LG)HengEi{3R;?NrUH&_jf6Oua0jO{(qI$p%j5Fa`rh2 z%c-;StR168ouPlS7_uUhGYDlBoOCnAhSP?d4tzmpM=vzNLW>zgevopb32s(2^}+)* zG2SU6f}G@RXQ64hm?m`wHScEhZhSeLZS_g|vn7U(jh!;Mm}anrYH)^(1LK|74MmfV zQ9^~YXWCKD8+k?}hhh&`&^ZC1H##I|y`-1nrj{|27#Zicw_mCZd(xfF8u?R{8%c06 zNueshtMmqt+;`iSZEc&l%z!~o6B$^ZuAEwoW;h>VcIjg&ehZlQmK)zo(aqvsT|rE) z4iU1?3iK}s^f8#>JpHak>2j;;1oEy9$**+XiTQ`Ap~wiX43wGwhVzv7{CZ*Ksb4jb z8)UPC5r@a2&rTlSKs*SdhSorsvf(`8bs|iiLGI%lRQjcBSdnaZ6kP{dV)vxm4n9i5 zsL(aS%tdt7xT<987ypK^#J8%hL#a_q>`q+*!Z(n~#$YlDof};<_f0(%4Fl6Hr?jz4 zUuR1|CeiuI@m=g?IB$Rkol^Nzl^UPqM72kcD)pRo>X|(&SwySGJuX}92-}EFs=G<4 zBwWM32PGbZPtpe<#}<@5PmX~Sr|j~!3vk6Y*RHRjeu$R39Gw`byuS-M^m=0L0JI+TjSHT^iftV#5w4++8MY7W@k=k7W2j~y0s zfcaoJKk!|DjP)E{_RcO+^>B>}`Mr;o()|xgf;x7j4?sRwi~d@&); zwJ2x&7~F7v+LLL4%BAIqLf5Z;~^T)ZCX-xc^q8Qo2 z9MPRmWFQ_9572?Fk59Br%muHfe(~QM^i-A*`$^%0!WDjyy;HFi*_5U`Bf{?t;4@R( z-Kqie;kL__vn#tzX(AA^vmg6xp5;_qdDdq?5Jll#Vn|>hM=8oGxT&|oOsfpiNf0H3lmpdZgeBdm7nT{^^{UK>ci zA&^EfhV!Ji|0!O~YWFqCs#$i+W^ecP8*^e?`EJe6=(c8Adx$>WLS&dt`b;Ck29R+s z_BGJF(O<;c&ZPXkVR^mGnvr6m#OiSino7CW#S|UllMzcYtGH$$Pwzp zjIcPOV(wlG-!y;^?f_UUBu_Eb{~y&M@#B_&#?R5gTlwd5U!HaB;9MWWzg^` zaPj1Up+W7{1Fmr}M0&GiliM<2xTz_cf>JsQG;LlcI;d`kXra#cE2kBk8^if2)AeY! zM5~EZeGpj!^s9Ya1FUy|af}@tU|(@-P->M^c3qyn49a&$kq984Y9nOrXbT?_Fr5Po ztIZWj%hVAhLgAhI2fcq+jwUD@&TF9Iv3Nt2EobnryzP9M4sd{X1;SjjgD}ouI8S(& zW}~VqQ1gUb8t8CV_&^R)HwUsF=gIE*c}zCb8h!TRr4Qv*M(USAmj1Cia zdAI&y0G_vEVxv~Wc>{F)E_N6$^QC~CPm*2vj&75-&YF=_`1vxXVRt=RZHiG1d-Pd_ zg|NhJ5CE`GCX|t+V#Xc&A z(7Q`H#-nUFKj`hhh(l(yF%K8DHm_dG8--iioAhdEY1ImD1Tgoo-Oj*^XTsn`GMwkt zpf7x@ssc5a>r-BvS3#J;-xCPm=Lj3l6CTn=K}{-9Ls)Tt^D4OnExh%bWxa+d;uo}S z9$u41SG*3wBm}BQ#4n2fj!32!$*C`@CJ`T*&^oDJG7X6TjDFExLvQ$ zKG4VfI!Vb^MtmzT8W3U);A8roE*kJv{MU;&ljv6}^BmwimA^m)_`#=(#BfmQ*GjCM z!0oEDRnvY5z;f!X{J2-muZS7po}498SyBck9nE~z>`d-IqYFqem&xr?iQ%RuX_`!R z%DEY5kl2v^=$*W%Tv-Jd)1=Oz_6!n=>XGzjrGlc}Ev7vERicbO^3F@{Kbs0!C85HN zQQA=k7t2VDFsRvp^t4~BI;IBQj|e&LX(YkLBs1mVwiyHP^Lxr{K(OXlMFZ00crPRk z7n4Nu1~nTHUGTnKm26`ELquTsU&>)eKg0RuV2{pgRaJq>UJJWQE%2akiypT6UZ9JX z4d>}@|3iGcIog9{Hzrsl?VT`W`AHD{=T3CP`R8YwCekx2bxB|{(XUl47bM05-QNeg zsNQg1^d?>JXNU$96Vu$gO72^60d7mDF2QxEA9L)Ff!$+)9ab=06+6XVZ-R*lJT(RS z9Igeqr+w{O)KohD_?~ho5`*v-=wsc9z=yKoJfB@s7uGV!-Lg^X7yVWOal5R4v3yzKxnq5rK(DGoi8*Zj{p`VwjB>p?Y z)tPHl_im*!a{eLxG6gab8DPjQ?s-(df-FJH8Y|ek^$uP@RWY>?~Ash1$l3C z@uB2I5UXGjG-XzKqCG{VtMpWsOzR?<288Q>QYI6!prg5xi81>va#1?j`-60gyjfx8 zHFB9@*>l&v`z=HcUR*d*IZLZ;k%?$N%IGiwWHx}$OlK5Z<6nyC67j!4oo-WNn`~R- ze^VXLdJYNqtKdksJ+_~-vRqA)JEi20dwaaUm@#e0S;FCIIOzveF4Szmvh6Y5nKR_* z#z=yjnxtv5c6$shw#VeQJvLlSGpJ3iv0Ziq_4M&f^++gTX{gxtnDVT*$JbmWDyBlV z!cei>vXrOa9!D}JKXk-wr8oE6$&XTQngkb*I@2AaW`rq#PoK_Y&y78yrs$aD$0#?d z;9{y79jK~f0I1F{cVDWE4GZt%L7Myo<&ZR7Op*oNphi%BPqP=QI14A!P$f40OB zu`;lrx#9etd-&szBoSKG2~12(%YsLm(8Y;?MRQ<5pfj8w#rS6)NfxGrzW(Jt&X|6A zEqU!u5ynH_7BkYGL4G=P%!Z)RCkzkJgl{H zz&bY2g@@rh-SInO3*!qZK-aylx+xh%d&!gEXJDcq2x2DURo9_3 zB3w}?OX!LO6Mrldrgwjg_giS~_!>3-ywdwL@cotZ(gd5)i*=k_kPb$;ML0WK=VlmSxi8Q9Y@Jg~ z=>3KMF<8stYh?`z=gozh)8LEPaG?Tv8|8y^Y!tz1?sKM@3lkH`)*z{a&f-_K^=#?6 zYGcoJn_u0cW9H6ZiU_fT9I2sgIK}TOY2jy3b0;R;CnM(5AI{{M(P)B;X;NoUqk-hR zgeD!AbD+pPHj3b4ibjpR=5)BTgEMRbCZsr%BgdbOB)D0TEO+BhDC$Cyf;2f%7LtaG zNn#I!n)?!VDvUw!Uv(~AtDH{ECBylESJDQon&`CWsaJ^<;bn7Ru_ds8jN$yL@TeBi zYI{w~g5?UcZw)N|Ca}PWhV!E+-<@r5)kFr&S+3Gk;fuKT3w>Pdb%Fky0)5P2I6s8( zn%`ren!dvpteE0E1@cvl{neW4Bz=!JpsHGwb}$qeTS4{HygstU~f zRC|0xyVZRTsf4Kx(I{)DKlOF4G1?JPXCb! zS?FgnshDeG>J4abYMP0OZKrpIh~QFP%5iI^j^Vr&N;)(2E;HTKK{h|`qTG1LymZ`l ziD6LVUi0>SljmEpve|-su3Vc{&n_|W{3uR(RnP&hZ8$&n;z&GpG?fB6k1sK_1-e%U zy0kW&r(3=^_H4AD0(6VoMRuR9d(=(c$F1h6LaMw{Tcp5s!I`MTnFi(bjR%EYWVpmY zon)ztgAYrl9bwXK5YJ@NNv2laA0vL?NXRnR4$dnN@Msq^bk?byNPv+I=Z(?wso2PD zhEl*72gw-WgG4N#Ils7D(#V$4mIa09Xi+YHPdySPo&z^Ia0J44K7YI_eE75|1P z1h&c=ExHJW6YS%FyG9oz(2WK*2Df*dADn8*M@T$P0 zSBhYY_AAFj+4dQ(%0qM#UL69b-JqaiKlEV@y&*)wQPpuxrJ%^T_r>Xt46s2l)059t z6zmdh)DDkVN=V%E`k)3Th~fP3hijr>?Q=Cve8KgG8@kV4d(la&R~&ylKM4gN^Z~Z7964N z?cXf^Yoh7cFFA{cWip{F>_T3T9m$wv+8*>|)3G3#`Xv)G5F(g{lX$L-3Q zjwHi*KN+}h*3(gxs?1T;FqLhX+!=S}RTDt}P%(fn=k`Uuti+*vA>uocE`ftvE(c*1-#Z{6OIKA;-&bo>%!} zk0jw(T@uLS6~1Xw^$_26;`I{sz!yFoc-`T68Lo=g=VD&0^(io3-qGW-Eno6p-nG0# zD5lMwf&9lEdBb_~#V^I?s9m|LZc(i&=~b3hHQV}8!cuf0c0joC5RqGSnE_WrWaOKR zRYGK|!qS-d?~YD2TD5Z-3!64%!gZ0WUNVi`r@JOm`0kfXjZ4#&3z=|xQoUqq7XPlW z!xP(NmsR|%PJeXGLGGjPNj|cG>4C25B~zpLuZd(DknRSYo|s0+S1*~$($o6L#|x6F zusG8bvY@NEl8KXyLzVDZU{L&b|4(|eVU>`5R7iJSAI;t^)qF2BD%s5j=3w43%1+4u zJ{C@Ay7Y4A?F;I(N$W&Q;4!(Eru;8D+Ho&A{eA9UH@WHpBPFYGO#CYF`K{w)IL~L` z!I%%1&r`tehgIBbelnVr3-ye~Bpg)`9*P$A7U9Ykgf$VN#@t7`x@MpdDQfQG($dC2wCDWi}>WlPL5^l`t3GYI#ddbu%o$QJh^>NA6qQ{s_Pec;tYQ1D? zl}ziRE1)Ie%12}}ArJD^OQr$oWN)OWG0D{OluRa~7O7q`jf;O@q^D8g#+;t;Z|qku znabin6v;F!T*1i{&XwyX)39u}CyE6l;C^!WV)JqILyVd$J#nqTZxV~>>4)hi@pYQ; zw`<}z3)l43^j<9QkTj|f{$!g(Vng00F+2NAuSqZtV7g7>`!#sJ8_qXrxK{HA9WRqC zx2gP)i14*XuG;`F*6}*k+h&oCBw)EO&w8^6QRw|i|Cre142lKAa2hd>dw-#*IGEy-}gR~{QGKNN4~5g-MmT#`OE)Vpo#b?w_;jlfu=LRC%h z0jyy-FYxHD^mJO)3DgMOv5{x{2wXhLuC9fnl*5<}li~c;G$ZlKtK23_bJJH z*4GM2^jW4_G_pD{z=nqN42D0or1I%AHIaAaKAdV>-{U(ro)F$i?BJ7xOn994)WB{{ zV21$==h=V#zUdtrLf3@SsBq;Y?o75YB^ei2W3&i1S9inEsD;P*8Z^cvx9My+8MG>r z`H)@{$-4C%97Gv3n`pe69IwEe4HpwtRRwB@a_5=OUW+YSeD?02YOzaoH!2P5s>PTd zn}j)9ggIbZr0k{V7@)mDB4jw2Zb711hZ21(2-tM>fkEfMmB2tBFT=z{bznHWeM?Wf zCc(Ci^Q%IHbXYb1f;^^gzjXXhkpO%JX+XG!qtmY-F@Dq6bmKSAL^k-4fa%76f7-0j zrkrVn9+s#x^bSvpBr^g?Yr$A2DQy{BaMF>Md7*{>WF)*BG zQ2t^Z&}y#{h=K0hCOl4s2cC<-&?f#a4LtCF!+9P9A5C{Zs!pKBbMrnw*eWmG8{G{p z3%C7;hbJG(ClaGc62jEu^s^|>*}X8jYb=>|{wR|P<&)-0CdO+Xt74&9GOY_9&htym zv{vNYlgWfEfXPJJdlkpPpEJX`aD;4!hzU;dWaaEC@N&a>rx^eAlIQ~s$sR;#XWyTxXpm@LhV(jo_;q=aiJagd}u?>Nowwa6 z%R`XKHXwt-jXg8lfFO%a)2XHfQ`!JNGnI)A2v2PTI4xsatIp7CRt|5{@H zwN9J7Bu(tW(B}lge7*w0DBEzJa7)c>sJ+0iAJ9IIU5)l0=^kXo4L39?^woLyJ1>@rhc^qi zG;E5H2_qm^y<}<;|Dmt}F_~H)(Dmn^W_m&vV6J4s@P5_}Xx1+cGV!5_1H^cYNbvdz zzBQhF%jFp5B)bl$V(wy;ZA(&Tv$0GU3HXfqt)ls;60;8ASt*=XS@Ju6;P^d111rz^ zS{oO!F#JnI3}ujWUI!z?X*OnaS9lMTUBp5*`mqZUCyfz&o zZHIDdJkHPC@jK&rn+Bs5nHE>VL0mUKNT*Mn2 zp@qk?`0ojux+PN4p-M&Jc68pAT!cX;WC2Vj%6Y4!(WD+eBw)IEv@>m%{8AeyI9RG% zouPNFa;yU_!+EO=*Q{R2o>Q&UK8v;GYU)eZ7-*wgXwqu4qir}(yL5N#oRiY7oH0Wa zJ#BHc4d-dM$ni6eL`RwS)HQ#>8pl~82O5-9?fjoK5aXf{B|&5^97trVoO(<$?T!|Q z62UnvqR52ON%fMcUox$U7SXa~S{KgZkqKFVxsr)R#ZUfWY!@clwNl0sF&;tAQx8pS z#*L$8K^|MM&{^I@%VK1@`?9f2H_>hpy<6lQ3q_bn%~$LHs2s3G>s5i6< zt35BWx7@cR`GPEJMzXmGYmC6lG>%N+?6*^O|Ee?~nRfmr)h9CH(eyK!RLq^OUjMY0 zLKB#7y3%Na5`6~LiSfTRScS6TyuHgK@!8yAYMBCjvnPW#bSyg|d6i9{)2H5#epsVl zAA%Ki9ZHQF{hsfo3k_a{Q~-HBEHWaQmWH#ncJV}}LCMthoy<$H1lpcUi(Do8jQPf3 zk#{?b7_Q19pNuUMy*H*Eihr{(#~dXMb4N5m3J>b!RS!a7R6hmh${bDNL&EWZqWF*g zJl!CDRpIjEiYv{Mv+uC%1nlW*w@S&@Gj4R|t!FEQH-HCY0;ZcFLu$i1#&x*^H5MfcaMW`X{wgELYBpEu6r8NvjAyI(N15S2gI- zLZyq>qu09w-A_BZhVyiby7a^d4QjsOn9c7*^zgVR%?sF^*SHeMj4R>^5e#HUDwN%c8 z?gr7s`@RzBe%;YEoY%_0XQ$Und;2kKSKn|$<*lC1yhH-b`@-4^3aGpykoWH0` z0(o~((np6A&7aiSsV8nJ>MG_&^$i@V;XJQ_M`B*JckTl(##EW~>@W5P z9*;U6hC8~DJXfPu+FL&u>n=Ykq9?dN7U)hmx`y+zk3KZLhuI@enw|ED(+1w_gV&)- z^QCAa>%PjxE?GMa=L1*yOG_5xF9vxwnarEvMKIkz@LJ?}8LnzvUz`Q6&dwwpTzu8J zm!2QS#cLoq5aW81<7GI{Yh1R;9tN3amiG14@Z$Bu0|T#v9WTRqUIV+9EY9ZT)V!9R zkc{Y@%g@)l3mR94_z; z123NCHGemp=QXV89d?-Nm2ayGuizJ+*OBV;^uX(Q$IEb@S4sZP%3_c=w<^3UYo8XT z;1@@!pgcZ zsP^@#_@oNt9wl}Xox(|h&uYiVa8-QXa@T_FTrb~F*?5xGob`MybBe7)qteNN*J+NI z;XJRVcf@0wa_f){3P#5$Ju5Ie!!a_PXVmrYcP&8K2Gi_OGAp&I$1-6S# z17SaRR*Ai7lhWmZ$%`Bl!+9p#2V-qzaRDE5Uwu*lg@ce)SIQc78DvNFluU~*gX|7h zrAj)ll@Q6-Adze?u9U?xwdzXQuIO@6vv6yE7M_xkO#7-6Cvo+XsYU#EMpqOEcIhgk zo*`f_gq}F-ZmgqBW!Y|5WV?c7>e7RiCKJH{pQx9f2E~8R;_4^C3J>Ylm2UBwObwEU z6XklzRFq6h52%)D6u%Gmt+5@x#A$WCWEz%C>kh1zX-qOTgm=S`2_2!cddXCjora?4 zi3TN8(|0r5p(FNF^^$2o{MSeR)F|EU(vyYePwcst)lsG~@!$TWYTLC6x5McP9kJK1 zm!3-Kq*yIei*&cfo-C9`PFPVnLe@Em` zCE@lunYhNoIa|GCYL@NRMQh85WEygN6}IG@i`Pvi@n0YL__%O|Rr~SeM6y?5SIs$l zy<}>Up4P;+laG(B$z;Sk>LpXZbkY^cRFX_1 zt23E6Ge)j@$EJ~Pu3bB^_;UNV)%e@`S+ ztK=-5oXNzTV|}TYOrzpI6vd|j;f7DjWMa;-H>j6PMa{dN(b_U7-HkbaB8C$;>m}2$ zbh0$sj~67cg&TFTfU7-RhpLxM1^M`zXg^+lSTdcO>4|d|&d=*5Q>$d^i+p@s zG7X-P$;8FShC0eLD4B*LnTCZcyM4j2k_Wl!rKghk?~Y_@d_-%DvmL&KT=kNvUotgB z{xmGx4Y+y7oFg98OQuor?}}t<6s~ke=1*KQW$x8WrUB_`Mb-qYl(z@~#iQ#5t!uY6d>MXcyhlDLLnyMiShtNcLXetuCTc*rv`LiUxm7umQZ`(br0=@R6rvVr zC40t#isZ-r+z$uS##?GoR#|sg_0_8uMVA(xiP7KOf>Clj7k5UW?PV%x71|r3+wJg` zl8VCZc;SNN5jAA8L7PnI(OXQ130ON0Yz&mA^B&qwEw8#c!Y1=^Mg zwBwbk!vvC;5z6o|V^3#XKE1|L@lg%>QI%OP-m9G772?Awe+)Ej`M4fo1eW{q<6b^q zEuxs8+?Ef+#U2GigBp+O>>vy=cDkbna&&`T4L3DOTBZPlw}q-gM(#(MNZ)hkFqG0M>mL5Z*dM zD>&G#B8o5{48)aHaGrSAKgB{vT2bfG&q4u`g=FvoQV23^HLGv}ZD@m>a>oMd4#E zG+hLPUY8Pm-Xy`0?H}|HJy15BH^!cUcvHh=x)k91R2if4Wo@4Jls)v=@@XY)@Mz_A zFre`+jaHUM>7`j0+@QsDKsJDUF6;trFH=!6t&3zDm9G@SNj7$2#^En!7t=GeJecf; zo2gxB=Vcm{Obv&mtKHEe`XQxJ;R-|hCO0XNiP?&RO(uBet#;Ve06sI7=}xtcH^Mta z40`{jf95lW^FFiv&9TqaMxFNdvq~=#EynP!K=(b4uHii0b^j8FVMd=qqQkJKIk}WP z#|7%9K>B7!+Hjuq9-UhlDe}DMxa>`X?vui62dhs%{mL9SZ(0gArErZOQu%w-w}oBl5j1$hHH8v2kIu1^t2|@ z)3{{n*X9@fF!gXc9NMPd6CDl+H_(>LCQz14ec^1YL5d(`k4UD`-(;KL>?9!FNSJAfQeZ8>#TKIQRVGx?Z^ zG9Yr4gOeIgaR^i{)a?8^JG#`6G2bmxi2iBi94o8fd|VjPql&7kKwex3&-t!eeex-% zp7yLYrA19-r8-*RCd5e zz8ZLa!|^hle{ZJg1M%i|=DftFdhTkT?vAdM^lLtkhj_9_OBxPFLdJTm1^tp~D3WPF zGBuXc7>7(!QR2JxlBroTHAQRYuw)u=GU4A${d&nXESdVEt>K7d8VuL)(Gy__zpR%` z-Z}*x!AI{ z3OD?nY|UJ*J}Z@M%|vH;>mPIt;A0EIbZh4S$XP$3_N<++QTZsPgVp&qIn22snAy7d zEhe16a$lbHy4kAU(EqlGlK+o#gocOV{9>@@)_9R)E0F^I_^Ba#nPtni-sEM(R^h4p zZs73)$HQ=*N7MVK=V7mW7!Mx#N9G>}9zS+G4Ci@lzb)p$eTx*3)j#sDS1R@9!d1dz z_MZd}KX)7q=Q(uU6fZ;BOF(cqSemjo7kFz^EV%lC=l>$G_?2T}IL~62R-fP;>V-$v zUi}D)Iw`S4yBaa&e;pY7&M`2YXVCS*SW8?@OMx-)`&BlE4w>SlbQ~S3V)p(%u=%57 zV>r)d&->z4wDwJ`YBnjKHt}GVJsSA@$?-9q=QH%)n9rf=odUz*T_VpX(HYe~Tny+c z#GWXujtVy(LRf>CU=$L<)nl11iGNoVR-2LOx%1Lf5y`{=6;=28OUzvg@C?e5nJ`8hdHS-7R|p1+X!&;73^<=nrq?F{iPZ#%DRl`6kM`O|{XwzZj$q6C)v@~pQu+*u_E?<=BAAaWc8 zB~)-JN|;*6xg>D8TA_nQA_eIs$~k5jhVu(f!|n0<$&5*Xes(jcU1ew-80a4C=o-$` zU8h|b!!Vebs9l$Bht$25pHoWq7nntq3x@_ahdVZg^K5o$BUa4@{iT5T$%o84^h!R2 zQSlLh@R5$N;ryxp_M79IS(6a%5>ZrkR3O~w2pi5z+;vNOKB_JWOmSUApBh0iC#7%m zhHEg0aZKQKtm9=k&#Pf5-c8h=`&V`oo>|~UKsYY&YI3{`=Xni@mn{MeEN@)t`}dcg zf6jT&KcA1!BrL_NL+zR1D*~?*952IpUIWiAChvv92gv&_Lo}{rql6O>R89(fRy#h1 z^VeyL&nYg>rUQH?ae_7xCHkBa2=iSpn{|fs188}EJb>D5UgbX2vc6>}tXgq)&5gmL zmX;kyR9~4NQMfOiord;x+Or}AVF2OkvCSJ+81H*(wM_lO70$|JB8)I+>m^fB{D&f$ z3ew%!xtUC|S7NYw$y}o_G$LFvY^m@kW&^2S zGL6Vid!y5al5hiOW_n^y5~=DXQ;YcTjBWQ7=_#DbpeN+Pe)W=ROfoe@v7jKCn%8A| zBEq7pddV~_{@bIiXRC0d&6!L@W9DAHWGajQt|O~`ykEGHa4LiCkOf`Ml}yZO=#vAZ zvfY|sJ3a!*E3@Omjr}%zYIud(X#uHhhl!tg+hKHR0Da;=Fx__e7PaA#uVh=S+_t-C z2ZENXs$k_=Z+Goc(Q`zU$w5vqVK9ahDqCZP_b~ZKmg&uuBgdtTBDkq3vN)!YER~%d zSLq1NJy-qoSGYp|sA7ROoL|a|Ym0EKK+P9M?BSvAvra9oT*V_q@bnH)lmiZh!25aC zoh0!ah1+pt`ok>c=N13Z;Gxf$#$Ow?!qaSJ%`73mYZeJmiuy|Dx^Rb}+pPRRzfGVWxKA zU8*J}bPf!Q|Ms7xJDGWMnx|<3wn$Gqp1GiM6?moEJyXfn8Ezit`35hM8^C9#GVvQD zzgOcwD8En+#yayWDd68F|!{lAOG z@06Y|nzsu5ze<;iHlN-HZ0&jjeFT>K@~qb`RvIS9b`fPVk=sgRIH9IkyG&iF;udsv z^xEo0|0e~SEch7TaI>PR)r-MneEM@so}BBEMiX32lRAT%HxWg%7ozHv5W@=~dW>=- z3N9v!vJ7g8iYg~6X!1>=Cpl|4L=6`c&2)&1W^#j{*9Ju<7QL|zISY zH$V}SLWyZXZWc0JOfi!xN5*!XpHb4A{WUq0$z%i<2H=3#I9g%??+R!vyOp`i;n$dS(r7GT>e2cp2ukcR&V-)y=;rt?5IzPUM9X&qc z&wSIL?7_uw)*D3{*Linffwc|iS+txRvxr#*kQStVX5#QSdwgl~3)4d)4uYWtVj z3d=Fd6p}HEu-+$ZTe%9KU|b&#l<#nq4d*G3OXOJLqj@=B5kJzx1N#oO9XvE6!}weYBUV!4XP7 z5)-D^PXjXsVYn)0y5xaS1~qR^<|#@)Qz!cUKF}u$8_v^jSyzm{ zHJ&q=^v&$>Th=V;D^BX|)?i@9_TbULj3|c&2zG|^cWj5B7h7Z&%$SWdpC{^QZlAym z%^A)!8`llI>RB?g*+>K?vO^ab)yBLboFH+Mf*h@1(^I)&V_uS*5tA7-@=bN=&#%Ss zL0N!p68uUEjw^ge1cRPv3{4CYg3e_Xo#hm%(r!6&tWU*>X%IGqYJ1-;R@m2E;6yoGKcCV z(};AkG`avVC|q-R3=ElAk=YT}OQvz@q%V?bRJg|Qs3S75kh3h+OQvS&WPKD13X-Y( zm+3_bWMa){UersblK5|rWEv1|%*jNgXT_T)77R#FJA+Jjs_p;99 zk*FR^P(e%JjwrMaOQr!mrD-xD3v$&s5W|QzbS5txU zdfOGHr=h2%GF`2@cPf=7Q|YJaPun3A8&ozUCXGP*KPiWR=Z#l__Bi?lbOoSP1wdW@699@ZG@@yV&^UuptbK#Wl!f{aw1uqd%wt?hq31MWo#?%*t zQLKGo9K~sw0)v`YZqa{A{Awzal5?qsc81gB%T^WPJ=9z}+q$urzTPzbGQ+yy!dwTy zgGEvhP!m}@ zb29oRSDngwP@sI)+NSH|Rx7%?&n&N8dkP=MK}UW%jmn)G!p7lCsyj`xHp}gHw#-jn z^%}o4yXu5+Q$@N=S?ScWV{xw)9@t-j%!?ae}Vvrkbu& zb)!_h`)s2k3^_P}MaYv+WKs_VVi^>p`i zZ(DJud>b*n%?9L0T_KFLs}4UJkR4m^NjGujmSW}Cnh|QQR%Htz%^EefKQ}0Yvf;cE zN>@xDLegPtvwzIm^0?McEN+nZwv;Gm zpW*2UB46zY8_p9R)r_hpoH-C8+dGO3-@ELvrqR-{I^LqXKPrt0H@5uFp{nR(;$or@ex!n=5rE>M7Bz%;(ut<6J2p=k({N^W-=iQs+}vD z7_-;YsQB*+dU{xl?~p=TrKjT2*#={^`W&ic(UE!NO{~KNkl6q}xF;}Oblg{bKd5#V z6*uYF+^#1OwH$g@o^@orOr0_K%S9BrCv^-Ppf9_GC)($**$@l>$-v5NKKDwEpJ+r*$iqDhCwVes3Ge4Y zO{nW>+q}_Ej-o=gttA~EvJ#oiOzUZw%@-y3d^5PUk6N<{q6XEK@POeQs{@+yu2 zW~KprOh?m2SNhbC#268-<-SZN zWC7+%CNrbW`4Q=4m&qh$^ec@CH*#J!vAM$l*u+L>ejAWf>Yvf%7(OImx`6GsCN`Px z35u{BI#!#ty_vNX5#kd83)$J1O=f_&oxb}wmagCV0TB%vM zhBLDH!5Eh**;pA<-uxh>8odK2yUA!whKKG{b-q4s$8jExK9hm9x7@cg zoaMfb@?`kw>L#l$lP`~^ zwI!ddemcCb_vNW*)6SA_H(7b6bmRV$^^4oh?>l@eG@npH@In%Py@^X5d$4^Hy z?icrs>*HgiKN;TYXOho^#$;^_KUqE#{=SXT@wmM5WbN|sc{rn)SC@yg_LfiAX0rOp z@X*bx%fn69)?}Nkem1n?w()TukGRcr$0qONZTCdTFdgszr`6BJn9UA8kH_unybO8m z3}<=Vce3M|w2#}^vE{R&ZG9|{`^NbA*tegm&e~1aCa#Zu2?Ox%II;uMN1#>L+o@#n{d{? zpULpEp^?|ta5JG#o0+tm4bAD=K9M|UBRg_U)_yX)jm7fm+D%tK6`h&(H5%lPr;qiY zZQq%+pRP?@A0L}+aXwYMyt+JGO!NO0$J|fkUL#=l9CWwXPj6kN{n-9dD}u8yxP^P`=9H zUKQ?mzR%tH{QFS;mypAEAe7(caPJ7^_c+{*p*-ktZwTc#Io$QZ13uzB;q9S36mt09 z6w2>+xOauJ)zNN8z}@KD{cR}!lf%6!l>gD;UKh&N9(r#MxPNi&ZVlzz9q!6d{;QCy zYhhz3zrwZK6w190*AvQH9q#H-zSiOFRmls2-Qe-;P(I(;vN@E`bGS#t(-AKSx~FgQ zeHG? z2Zr(?A*b)6P=1ob9U96@9qx!w=J)6T`koZZCp+A6p}fN3tj{qHXZ0sKoYfl*c$^aI z*SL1cvwW(1dKj;Yg{7fqAb~t{A8aT$`jt%7#Lr#5DD4*ck@hBm1 zL7FB1SB3JaA!i&`KF{IK2<5XK&K_yCI{I4ub6mT(1{rR3^6dy^K1mMH_r0O~euv}L zb>Mvt_wG=(_Vj&cz*&26_EQ^bttcKxRXQqSq`@(l$#vx;85mgMF997 z9?Hud?&wfH&fywE`B;bJ$3lUl9BxG@pWtwJgf;9xLr$O1hVp|UN0x^|`4NY^JCyHn zI4j@ha9;}LuR5HSzv*!H=HFmg80^|C*dd20zkKHfC~{=wmRyAAkvhbyM2 z!t#)l9TUpOg&cZEgfcI~0^oS66RCsu#m@gO4CRX*jvq4u ztPXmg3ikR#$fDD(M$0D4~z<*z&3&qA3WngwY0!%+T-!+kT9 zzvXbo@B0pCa(&6+)`vCwuR;!=t3&zaA&2kgP%b-McPMXixNAeX$Kl#Sd85PGW5WIe z*gQ}R{Fn2M+d^#me8{PPAe0{pIr7~R$`3l+J)!(rhx=$K?{qjTf7;=AcMM1#)J%)X zR}Crhg=ql3FH1^_mmvpdf&v&>BLiuG5_o7gKiNjqO%2tQW&kH!- zp#s1?Ka?+VIKBb|oZ)aAL;1}ir@k+g`(3-&hVmO7&K}SIO7JWCek;Vdd0}pY`$fS0 z+Qq-`hVl;`?%Sbkb&TUD0cSM8Ss$wd_h@K0;pqK7l&y|-CWF<1dqa?Qu^R^;1_yo+ za@z5AO@I$%0^qFtJ%{5<{lLFD+}lEVhr{u`ZeXv&@##X~w+{DcDDxF;0KR;M9r%)K z$4AnEZ#W!Z-Ur_AaC~zfxXu|pe<=;Ep%^}{tB={FHeaG0L56#rELLwcp!eUQ-ed=NUZAti z(X+DgqTRDXz4;e7)4A1wv-fX5?cyZwb^>?1c)**az+Dda&tZOl(#`V^hw_~vhsWDP z`JE2;u28axMiVya>(Jq7wdo~hkIry zuXeaMrOgVT2sznXL-`#chu-@``8J2UJ(NG${%vLJ45*{hr2tJe-(1F-J$%GkTbULh4POaZY-3oj&}bUaNh|zxNn8>w;k@m fQ2wIBJrv51INW`q{D8xKC6vG6a6b*@afkcA2o_7Z literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/uthread.c.sisc b/xv6-public/xv6.si4project/cache/parse/uthread.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..df41a4aef6a081d167a36db239565671e3115877 GIT binary patch literal 8852 zcmeI1O>A6O6~|v(CviMUW4CDuxD+SjB+f^LlLne9an+=8>!`(~P9jYCaNY5^GsSU@ zJuc1y)CEYE5K@G?XeE#;q^d3(gb-2%5<;{KcUM#ubpcYu%3^`KV37sl@&Da>&%8U& z=e~3AJ>U1^z3JPLBv+H9^{6muNs<#^NRkhK+v4yqqTm~U{ctzDH{N|~ z5A=@Y|M0&O0doIY;XXO^ituN`&j@>ktwLb%j-JB%BdrD6r`nR_?p;Z;1n+~rjt3t| z1Kccs+^({6&#ps1DlG^51KlQy9;+pr3k^dW$ZIm@U&0Ypn31fpgqEeHKr>1D~-9Oz9Sm{ZOOr&2I$Cm^xfIe+2~uE zcGi0(KIyDZl_uxL%iRZSH>S(8EtP}c5?9LVTAa3^fp#+uV%H%}H8=noI_er`Yh$&b zfDV)Zjs^v$IPZcV>3>&OFgIJCk%Ff+j(Sko95@;j&{kO_^o$eDbQ|Dk5KX(8Xp0*%)6`}L z(O)?~GJ17zc;Ng+!hvd-z$vW*JH!;ig45_Gv%@I(Her$8Vf$EXA^uN zCrFRZ4=Avj;Askjtz{3R1kn402&R3HFmG{|G6Y-deK2-jpR1MUM{CH%*jVmiJ)2w| zekmCUcD!uZG2Yi-ktHSt=>G9X`U88>@DoP^I9gnQOdQ zjE2+{{dQsuskLh=s+J z7UH3ZMZEFy;^{L;)9hqHd||3QZ?d1!GaD|)2f>DtIOfxi6RgLi(o-zBh022)7K;S{(0lmG& z0$DO3GA+*2#>kYk+-v2pYZy7C*a0GiBubZsm50iMdF#oHU$$7kJ6M0CTAm!gCI*Fp z3xsAuh;ULxt>$6jWU+v&25cqUBGcQh-|*sz0aZ~ABfl$(U^4VV;6ZG8E-5CB)q=&C zKahrnmY%}GiGQ}EZ23U3VEY5ca6>|2v)hiz zRJXewp$k~=hQt_B^Oo?dLiCbc^g=1pn8y-|A+{w=Egas4mf7iHjfKfHq5-865gGIJ z*c8$RZqM#Sk^R4U#-;?qN+jSEMVvYSg? z1;&ydv`|o%9yOb$Cku?Xax>|9S~Agx4q|9j&3gN^Hv^V~#35}7BVU3#mbgW<&|}5vPlki**ftspxhC4Rf&awQiz2x`y=k_u&m;>KCHnQK4xtUW10dyoQzDG~S~Q z^gE66hP1_%zr>z)%rEmv_5DKFt39o9u&~8@wj5k1!&10;A_2(%u zV9oa>j)$6)bvv4Bij}OQr&q;GexKPy&am&(vT0fRr^C)Iwa%tR#qRPunN8S2Ubf06@(|~4LHb`0 zHdUqg^9sn@-Pli2wbP^G*PqZnj)SCmT#Ud*HG(^>A&^B3G&Opv{U3_cs9zT zwKsi=Ae3Ye2=58h-mi_<9qsvT59haGT=GC6w@%DWl{lJsctXet0kxyac#2B>AW?S% zG(Vb9bV*1&pA@12G+w;7^gfiWcMaLx(L|xe#jt-zPvKVX9<@Nx{>c|8FHgjfc^J7> z8>|(8<;AE}*7K(V$PQugk#P zcd}2v$B)w&C+Z`uia+Mg(u#O}?}l?rA0{l|(5<+0AUC$@Hmf(-^dI$oUjc1XLG_)^ zK0i=2#N3L9m^WLApR{3OPyf0uD3hxXKfinSZ z`Z6CVZg)0RjfQ*@Fp=xc-RL-zv(|X}R_kxZ-zaY_-OXg!_?WIWu329*UM$br>y9JO z)B#}iz~QrBx$gMQL6>VA!>9LnOq&+|{IC5O+ZL%A1I||9c~9Ig2N_WE#QoV}e>s>P zYz!Ae|8Ss?OQHQ#pgIieU*CEH4{|89AB%W={Q*vS;`H)L51jPG@%YpMocF}>_`m|3 V^ThG^=mR|DiR0O2ia!?&{tKyvn_d6_ literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/vm.c.sisc b/xv6-public/xv6.si4project/cache/parse/vm.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..c62e981c8846ffe8f2e4a0f49f060062a82169aa GIT binary patch literal 33227 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 DS(;`# literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/x86.h.sisc b/xv6-public/xv6.si4project/cache/parse/x86.h.sisc new file mode 100644 index 0000000000000000000000000000000000000000..d2539302282bb7c8a7727e49b9c7f0ef5b573b12 GIT binary patch literal 18937 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 literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/cache/parse/zombie.c.sisc b/xv6-public/xv6.si4project/cache/parse/zombie.c.sisc new file mode 100644 index 0000000000000000000000000000000000000000..f21b33398d4fa584a619bb74a86b61a1f6a8f54c GIT binary patch literal 1521 zcmeHGyGjE=6urr=&oz=o8w)`~5baWEZ)q99Rxu_4115;sfcXy#3yU-XQ>loMK2~ZQ zv9Pf9E5>tXXOf8#1WWP2**i1$aprM1Hz~3!;;(~}6j`1S>E9pVBeOT78`P!z3YxK>7F5KEmg##CJ!%D4q z+$fb-GEwuSTu&Zl_OQxb^EL==jRMEtDd<4+Q3}BZR7ejL>QNyw0(96b(bfoX{Cj~$ zy?hFR9TeeCr$8bFvMA@%;8%2e64-a5PbnYq@%Fe;zgno&Sio%#xeJ5tYTO)XCMkif zTdaL_JjR|qOTbO&0`#FdU`CpQbHWv8E^~;Vnu9TU&>oI+duVsOA;LZ%V6-8uTCD3; zYEc%EOdyBeSch69n~dZci57mAt769uj~(M*n= + + + diff --git a/xv6-public/xv6.si4project/xv6.sip_sym b/xv6-public/xv6.si4project/xv6.sip_sym new file mode 100644 index 0000000000000000000000000000000000000000..0a967729df25cb314cf48899b9db68df238e95e2 GIT binary patch literal 987452 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 literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/xv6.sip_xc b/xv6-public/xv6.si4project/xv6.sip_xc new file mode 100644 index 0000000000000000000000000000000000000000..a10e3dc1de3e621f0d89fce5706f263dcd7e5020 GIT binary patch literal 196840 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 literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/xv6.sip_xf b/xv6-public/xv6.si4project/xv6.sip_xf new file mode 100644 index 0000000000000000000000000000000000000000..c6c907b3b922983ef2a626c713d218a8dbf696f8 GIT binary patch literal 196840 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 j_0Q)epXT%V{JT1@KBW8C^Y-lCh1%0Ds;J?)2pRZ)rgHP4 literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/xv6.sip_xm b/xv6-public/xv6.si4project/xv6.sip_xm new file mode 100644 index 0000000000000000000000000000000000000000..da9442979569d321b7337b8a0fd3687aaf89bb88 GIT binary patch literal 388 zcmWl|hc-e1007XJ6+)4nP$^lV>=7X&Ws{ly|0`VgoZAY5;M;#8JM6T}ZhH*-A)F2OTnM%wb22JL;I@PB`h5(8x|kn=)<21+(T{H1CqjuDI%&1=rnh)1oD} z+;+!Z_uTiuLytVR?1`sVJoDTOt6qBLwKvwhwQj>Z?|tymC!cNm>x-|x+4S8HKm7wl CrV=p# literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/xv6.sip_xr b/xv6-public/xv6.si4project/xv6.sip_xr new file mode 100644 index 0000000000000000000000000000000000000000..83aad6c20285a182d928b5c850dd2d5d6e3a033a GIT binary patch literal 196840 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 z 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 literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/xv6.sip_xsd b/xv6-public/xv6.si4project/xv6.sip_xsd new file mode 100644 index 0000000000000000000000000000000000000000..71ea356e8bb715cb969afd2d8df8eca3863f6b03 GIT binary patch literal 1568 zcmc(fziU%b6vt26RBU3yt2ihb44oW-q ziJKt2!9fQxgOgAQZqg-#wu3(?=%NmKzURK=T<9Or1Mhp!J@@m@J@?0Z504R5iPDs! z12vE5Paita5@hm|tawiG^NVXb^Esc1ntwAG?51g4p{XOlW<(c6$MSX7;Q|}Ik7h{I zG}Mjmc*-p&FMmMmaXv2zaI;G^H|{NW{5Jd-kOFfBIMx=jG?Tbyagn<4pFoPt72#O> z?&Mp!9jqa`1&Nu9;aJ;A(fru=+l?FWHy{<}DsZg5bk@h zZcbzz&Tq=VQ|O4fk#t4;8Hc-L;}6gTTuz|%^;636w(=Gd35T+s5B<{Ie(pKo63<(L zV{KQ@gMxZj?v<>g!1)R~?>${F1s#7CZ@+^SnJX&y)~&DG0b!4|#9T?aa?YtQ;eG))xl$ zeEZ;fynpfnIz*fLKcKK%m;L*Qfgb1UX}}FzP?2fd??EVf&b#acQn^o*KXq54)7(L zhQ6L2+Z!2z@CAWi`PZO8;bT6MV@o1k7yFps`@aqg$Mf+ex4~>i=!TJ=Hw@QX;Gn{q z8OJf5&bK7fv5q=qX7CTJeBN|=-g@NYIDFsDfW$PUPtOhq5SFF|j-Am&%4||fK3)QB z&G2CH?<+m;Jba!D2gSIS&Vm)@6DL8bS!SI%=>}3bz6v<#T8eJfu%yi2(Q+K) zt+_JC-pCr{BAY~x8R?%OAH&3$7CFXa?P<#$&7Ixjo@YPvIyfFdCo&w6=-MYWEx*i| zR*|FSjz;SB32?*|#^bz(J_O^I>vM1^iZLz6Fvh zcRJr5&)Tfro9Fe+=e&?>boT%dbCS-D*0lUGV_GgBH^yUj2R$Gn^?ES!FN-4QH1uFJ zgjL>bZxucV#h4a3w#HKVq~#7R-m+n~`vw3XW6prN@XThb`<#OtWzu)7g%EJZE;X;_TK&H-5YU z9CKjDHF3Hks%iOU#a*^eGC0!*aDfva48Wvwq@fPnKM0Wq+;rs~OiK$E5LLPobar zJ2<`pK%W*L!9*Hc3*H6=jd3lh%=dqmu*FYsR#Mqvcv% z9QP!_k$Ztt#g!4iUhCe5aV^I&-Buny;vB%&!0{9S)rhOH(8#@*uPA7YYdMZN+x2>b zcf!@{QD_VsG4QShB>LQOP0KGcrX?K9^&0s&1{{|I5a)sPduS^;6kh-b#h4a3ntoP+ zKxEuA0UYxvUM4<>15=pdc%OrVVqA+Hmqa__tvFMmV^+%1?ss4PU{-HrIXF&3-!dIv zoPH&2z%4P&#^qzY)ArVa)t)7(#h;c2)v147r=+Q@qqv5fN13cG!1{~i<0$z^0bbPm_<(C=L`iP_9E?e^P zZE)nCYMuBdw3UPLS)X@gT+8Q(=M@ZNEcDkS(LY}Xc2@ureGX8$@A@kRjWI39v9rr+ z%jn~fe7qGLdvK>-{CL;~tHk_2{OG6Sm@%D=#qnb|IDQjoW{Fp#%yT~aTr=ZZ!m(Z7 zH&vE=d<5L);)`>ShHj}0r@)vNIcB2SsOdK=2*; zTR1)qj_g-vi+7>Vp*R)~ig7KUW5)JDDdBhk9J>MNGvW>`JdVawo68h5#-7uB$K?R@S@A(sXzqL6prA3X<#RNBD#e?c z86UeH^TMOxSdAQHpH2S}6To_`obh?$pcvCCax^^h**W%|NloB5e5B{$XuUflel@O( z^u~<9V@!)2vz@m071sQDvRkM44mfh1g6p>Q9RsXW=yhE(6^@o?*TwnFgW$+@ifhCR zQJ=%sDHzux$6UMZeEivsO)ejw#2|bXSaL0w{?jw6VH9|bX$i-2K4PEiEpR*obZjH( z`bl^f60Wx?oQ!EXj)}IE=@DdL{K)yt=fxe0Ux6LtT8?8f9?!V<#2HOX;dlo5$T7`) z@k}(19Ewj=&=}V$>l;w0RtcQO9j`sr40`W;e z#a2VV=eZcyD&c4}9Sa=Kf+M*t6kjtyJ~FQ5IOg%fJ*x}}MCx?~HeJc_dU4GF92wX0 zIcDRz9QL}5K8G~uKOJuT_&soJ!vkDgm!Q9TK-2QedfkF|OE?Wd zY(5@ZvU2ayiM^3~&>r@pkG>g@=%3>OxNA|fSEzoQF)iVk$r@e~zvRSy)3}cN4Dylt zT(^jiqdW|sb^bA~MUMGw)bxpp`Hjsxvf%g*`k5U7v{<|V<8r>!Bc-4*u2tY@`o*r& zUys0x%W44VR`H1QG%df(xR&GCor#w@_C`j7BbrEWiCE`hfgR&o=FN681S0uZ z4US~=1#uP8H;y8RS@^2=}w~ODxdU%)^*D7%2 z`yZ_?_$>Rzakt*H?*h-;gARKsAkn|60oV{Rrd7((=z@>b>r>!(eg(Q6K%(!z56{kE zF7u$m$(R;7ekmTyr?WY`TZY1s=gqDFAfD5s`97a8F{b4>cAD<3y;++UuR4bL^&o7z zZbAO>%o)8Gb^LOy`215rV@!)2H^i*2g!?q6?D^2Ok3R*+L+GRLz-{_lztyz-GGki8 z(P+acG^AcX3XXGd>rU}()a&8+JWYPBaA91F95>FLV|mz9oX@-rj(Y)Uh4@7d9-$`x zQvAud7CCN8ceW(VzHJZhAl-H0L5?3+jKz95`sS5@L{~qqY58Twv;rLM)@`ZRE5UIT z0C7%3zXEd!R}Fhy47W=}j_&^}WtXD2V*9F#UqXMq8XWP@J-@|gxEcYG9N9(&rJwI& zj2xrMXtvY6(B3A@d0(!nT910YABlGnn5+@s1&G|D!I8)kF|Jk2N26x|$m1{jXSw!q zH#oiquf{$4vK_zYXv#l%toBm+uV~MePwUt?kdmwHP$Jb Q0g2xF5BvyGbI85_0o@F#cmMzZ literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/xv6.siproj_settings.xml b/xv6-public/xv6.si4project/xv6.siproj_settings.xml new file mode 100644 index 0000000..ca84b35 --- /dev/null +++ b/xv6-public/xv6.si4project/xv6.siproj_settings.xml @@ -0,0 +1,22 @@ + + + + + + + + + diff --git a/xv6-public/xv6.si4project/xv6.siwork b/xv6-public/xv6.si4project/xv6.siwork new file mode 100644 index 0000000000000000000000000000000000000000..125f7ae55a1203663f7ca012469c334fda5b943f GIT binary patch literal 65716 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 literal 0 HcmV?d00001 diff --git a/xv6-public/xv6.si4project/xv6.snippets.xml b/xv6-public/xv6.si4project/xv6.snippets.xml new file mode 100644 index 0000000..a337f1d --- /dev/null +++ b/xv6-public/xv6.si4project/xv6.snippets.xml @@ -0,0 +1,7 @@ + + + + diff --git a/xv6-public/zombie.c b/xv6-public/zombie.c new file mode 100644 index 0000000..ee817da --- /dev/null +++ b/xv6-public/zombie.c @@ -0,0 +1,14 @@ +// Create a zombie process that +// must be reparented at exit. + +#include "types.h" +#include "stat.h" +#include "user.h" + +int +main(void) +{ + if(fork() > 0) + sleep(5); // Let child exit before parent. + exit(); +}