1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
QEMUIMAGEFILES = weensyos.img
all: $(QEMUIMAGEFILES)
# Place local configuration options, such as `CC=clang`, in
# `config.mk` so you don't have to list them every time.
-include config.mk
# `$(V)` controls whether the makefiles print verbose commands (the shell
# commands run by Make) or brief commands (like `COMPILE`).
# For brief commands, run `make all`.
# For verbose commands, run `make V=1 all`.
V = 0
ifeq ($(V),1)
cxxcompile = $(CXX) $(CPPFLAGS) $(DEPCFLAGS) $(1)
assemble = $(CXX) $(CPPFLAGS) $(DEPCFLAGS) $(ASFLAGS) $(1)
link = $(LD) $(LDFLAGS) $(1)
run = $(1) $(3)
else
cxxcompile = @/bin/echo " " $(2) && $(CXX) $(CPPFLAGS) $(DEPCFLAGS) $(1)
assemble = @/bin/echo " " $(2) && $(CXX) $(CPPFLAGS) $(DEPCFLAGS) $(ASFLAGS) $(1)
link = @/bin/echo " " $(2) $(patsubst %.full,%,$@) && $(LD) $(LDFLAGS) $(1)
run = @$(if $(2),/bin/echo " " $(2) $(3) &&,) $(1) $(3)
endif
# `$(D)` controls how QEMU responds to faults. Run `make D=1 run` to
# ask QEMU to print debugging information about interrupts and CPU resets,
# and to quit after the first triple fault instead of rebooting.
#
# `$(NCPU)` controls the number of CPUs QEMU should use. It defaults to 1.
NCPU = 1
LOG ?= file:log.txt
QEMUOPT = -net none -parallel $(LOG) -smp $(NCPU)
ifeq ($(D),1)
QEMUOPT += -d int,cpu_reset,guest_errors -no-reboot
endif
NOGDB=1
ifneq ($(NOGDB),1)
QEMUGDB ?= -gdb tcp::12949
endif
NO_SLOWDOWN = 0
TICK_LIMIT = 0
# Sets of object files
BOOT_OBJS = $(OBJDIR)/bootentry.o $(OBJDIR)/boot.o
KERNEL_OBJS = $(OBJDIR)/k-exception.ko \
$(OBJDIR)/kernel.ko $(OBJDIR)/k-vmiter.ko \
$(OBJDIR)/k-hardware.ko $(OBJDIR)/k-memviewer.ko \
$(OBJDIR)/lib.ko $(OBJDIR)/util.ko
KERNEL_LINKER_FILES = build/kernel.ld
PROCESSES = $(patsubst %.cc,%,$(wildcard p-*.cc)) \
p-allocator2 p-allocator3 p-allocator4
PROCESS_LIB_OBJS = $(OBJDIR)/lib.uo $(OBJDIR)/u-lib.uo
ALLOCATOR_OBJS = $(OBJDIR)/p-allocator.uo $(PROCESS_LIB_OBJS)
PROCESS_LINKER_FILES = build/process.ld
-include build/rules.mk
# How to make object files
#
$(OBJDIR)/kernel.ko: kernel.c $(KERNELBUILDSTAMPS)
$(call cxxcompile,$(KERNELCXXFLAGS) -DTICK_LIMIT=$(TICK_LIMIT) -O1 -DWEENSYOS_KERNEL -c $< -o $@,COMPILE $<)
$(OBJDIR)/util.ko: util.c $(KERNELBUILDSTAMPS)
$(call cxxcompile,$(KERNELCXXFLAGS) -O1 -DWEENSYOS_KERNEL -c $< -o $@,COMPILE $<)
$(OBJDIR)/%.ko: %.cc $(KERNELBUILDSTAMPS)
$(call cxxcompile,$(KERNELCXXFLAGS) -O1 -DWEENSYOS_KERNEL -c $< -o $@,COMPILE $<)
$(OBJDIR)/%.ko: %.S $(OBJDIR)/k-asm.h $(KERNELBUILDSTAMPS)
$(call assemble,-O2 -c $< -o $@,ASSEMBLE $<)
$(OBJDIR)/boot.o: $(OBJDIR)/%.o: boot.cc $(KERNELBUILDSTAMPS)
$(call cxxcompile,$(CXXFLAGS) -Os -fomit-frame-pointer -DWEENSYOS_KERNEL -c $< -o $@,COMPILE $<)
$(OBJDIR)/bootentry.o: $(OBJDIR)/%.o: \
bootentry.S $(OBJDIR)/k-asm.h $(KERNELBUILDSTAMPS)
$(call assemble,-Os -fomit-frame-pointer -c $< -o $@,ASSEMBLE $<)
$(OBJDIR)/%.uo: %.cc $(BUILDSTAMPS)
$(call cxxcompile,$(CXXFLAGS) -DNO_SLOWDOWN=$(NO_SLOWDOWN) -O1 -DWEENSYOS_PROCESS -c $< -o $@,COMPILE $<)
$(OBJDIR)/%.uo: %.S $(OBJDIR)/u-asm.h $(BUILDSTAMPS)
$(call assemble,-O2 -c $< -o $@,ASSEMBLE $<)
# How to make supporting source files
$(OBJDIR)/k-asm.h: kernel.hh lib.hh types.h x86-64.h build/mkkernelasm.awk $(KERNELBUILDSTAMPS)
$(call cxxcompile,-dM -E kernel.hh | awk -f build/mkkernelasm.awk | sort > $@,CREATE $@)
@if test ! -s $@; then echo '* Error creating $@!' 1>&2; exit 1; fi
$(OBJDIR)/u-asm.h: u-lib.hh lib.hh types.h x86-64.h build/mkkernelasm.awk $(BUILDSTAMPS)
$(call cxxcompile,-dM -E u-lib.hh | awk -f build/mkkernelasm.awk | sort > $@,CREATE $@)
@if test ! -s $@; then echo '* Error creating $@!' 1>&2; exit 1; fi
$(OBJDIR)/k-foreachimage.h: build/mkforeachimage.awk $(PROCESSES_BUILDSTAMP)
$(call run,awk -f build/mkforeachimage.awk -v processes="$(PROCESSES)" > $@,CREATE $@)
$(OBJDIR)/k-hardware.ko: $(OBJDIR)/k-foreachimage.h
# How to make binaries and the boot sector
PROCESS_BINARIES = $(patsubst %,obj/%,$(PROCESSES))
$(OBJDIR)/kernel.full: $(KERNEL_OBJS) $(PROCESS_BINARIES) $(KERNEL_LINKER_FILES)
$(call link,-T $(KERNEL_LINKER_FILES) -o $@ $(KERNEL_OBJS) -b binary $(PROCESS_BINARIES),LINK)
$(OBJDIR)/p-%.full: $(OBJDIR)/p-%.uo $(PROCESS_LIB_OBJS) $(PROCESS_LINKER_FILES)
$(call link,-T $(PROCESS_LINKER_FILES) -o $@ $< $(PROCESS_LIB_OBJS),LINK)
$(OBJDIR)/p-allocator%.full: $(ALLOCATOR_OBJS) build/p-allocator%.ld
$(call link,-T build/p-allocator$*.ld -o $@ $(ALLOCATOR_OBJS),LINK)
$(OBJDIR)/kernel: $(OBJDIR)/kernel.full $(OBJDIR)/mkchickadeesymtab
$(call run,$(OBJDUMP) -C -S -j .text -j .ctors $< >$@.asm)
$(call run,$(NM) -n $< >$@.sym)
$(call run,$(OBJCOPY) -j .text -j .rodata -j .data -j .bss -j .ctors -j .init_array $<,STRIP,$@)
$(call run,$(OBJDIR)/mkchickadeesymtab $@)
$(OBJDIR)/%: $(OBJDIR)/%.full
$(call run,$(OBJDUMP) -C -S -j .text -j .ctors $< >$@.asm)
$(call run,$(NM) -n $< >$@.sym)
$(call run,$(QUIETOBJCOPY) -j .text -j .rodata -j .data -j .bss -j .ctors -j .init_array $<,STRIP,$@)
$(OBJDIR)/bootsector: $(BOOT_OBJS) build/boot.ld
$(call link,-T build/boot.ld -o $@.full $(BOOT_OBJS),LINK)
$(call run,$(OBJDUMP) -C -S $@.full >$@.asm)
$(call run,$(NM) -n $@.full >$@.sym)
$(call run,$(OBJCOPY) -S -O binary -j .text $@.full $@)
# How to make host program for ensuring a loaded symbol table
$(OBJDIR)/mkchickadeesymtab: build/mkchickadeesymtab.cc $(BUILDSTAMPS)
$(call run,$(HOSTCXX) $(CPPFLAGS) $(HOSTCXXFLAGS) $(DEPCFLAGS) -g -o $@,HOSTCOMPILE,$<)
# How to make host programs for constructing & checking file systems
$(OBJDIR)/%.o: %.cc $(BUILDSTAMPS)
$(call run,$(HOSTCXX) $(CPPFLAGS) $(HOSTCXXFLAGS) $(DEPCFLAGS) -c -o $@,HOSTCOMPILE,$<)
$(OBJDIR)/%.o: build/%.cc $(BUILDSTAMPS)
$(call run,$(HOSTCXX) $(CPPFLAGS) $(HOSTCXXFLAGS) $(DEPCFLAGS) -c -o $@,HOSTCOMPILE,$<)
$(OBJDIR)/mkbootdisk: build/mkbootdisk.cc $(BUILDSTAMPS)
$(call run,$(HOSTCXX) $(CPPFLAGS) $(HOSTCXXFLAGS) $(DEPCFLAGS) -g -o $@,HOSTCOMPILE,$<)
weensyos.img: $(OBJDIR)/mkbootdisk $(OBJDIR)/bootsector $(OBJDIR)/kernel
$(call run,$(OBJDIR)/mkbootdisk $(OBJDIR)/bootsector $(OBJDIR)/kernel > $@,CREATE $@)
# How to run QEMU
QEMUIMG = -M q35 \
-device piix4-ide,bus=pcie.0,id=piix4-ide \
-drive file=weensyos.img,if=none,format=raw,id=bootdisk \
-device ide-hd,drive=bootdisk,bus=piix4-ide.0
run: run-$(QEMUDISPLAY)
@:
run-gdb-report:
@if test "$(QEMUGDB)" = "-gdb tcp::12949"; then echo '* Run `gdb -x build/weensyos.gdb` to connect gdb to qemu.' 1>&2; fi
run-graphic: $(QEMUIMAGEFILES) check-qemu run-gdb-report
$(call run,$(QEMU_PRELOAD) $(QEMU) $(QEMUOPT) $(QEMUGDB) $(QEMUIMG),QEMU $<)
run-nographic: $(QEMUIMAGEFILES) check-qemu
$(call run,$(QEMU_PRELOAD) $(QEMU) $(QEMUOPT) -nographic $(QEMUIMG),QEMU $<)
run-console: $(QEMUIMAGEFILES) check-qemu-console run-gdb-report
$(call run,$(QEMU) $(QEMUOPT) -curses $(QEMUGDB) $(QEMUIMG),QEMU $<)
run-monitor: $(QEMUIMAGEFILES) check-qemu
$(call run,$(QEMU_PRELOAD) $(QEMU) $(QEMUOPT) -monitor stdio $(QEMUIMG),QEMU $<)
run-gdb: run-gdb-$(QEMUDISPLAY)
@:
run-gdb-graphic: $(QEMUIMAGEFILES) check-qemu
$(call run,$(QEMU_PRELOAD) $(QEMU) $(QEMUOPT) -gdb tcp::12949 $(QEMUIMG) &,QEMU $<)
$(call run,sleep 0.5; gdb -x build/weensyos.gdb,GDB)
run-gdb-console: $(QEMUIMAGEFILES) check-qemu-console
$(call run,$(QEMU) $(QEMUOPT) -curses -gdb tcp::12949 $(QEMUIMG),QEMU $<)
run-$(RUNSUFFIX): run
run-nographic-$(RUNSUFFIX): run-nographic
run-graphic-$(RUNSUFFIX): run-graphic
run-console-$(RUNSUFFIX): run-console
run-monitor-$(RUNSUFFIX): run-monitor
run-gdb-$(RUNSUFFIX): run-gdb
run-gdb-graphic-$(RUNSUFFIX): run-gdb-graphic
run-gdb-console-$(RUNSUFFIX): run-gdb-console
# Tests
test1: clean
$(call run,rm log.txt > /dev/null 2>&1;$(MAKE) run-nographic TICK_LIMIT=500 NO_SLOWDOWN=1 > /dev/null 2>&1; python3 test_script.py -s 1)
test2: clean
$(call run,rm log.txt > /dev/null 2>&1;$(MAKE) run-nographic TICK_LIMIT=500 NO_SLOWDOWN=1 > /dev/null 2>&1; python3 test_script.py -s 2)
test3: clean
$(call run,rm log.txt > /dev/null 2>&1;$(MAKE) run-nographic TICK_LIMIT=500 NO_SLOWDOWN=1 > /dev/null 2>&1; python3 test_script.py -s 3)
test4: clean
$(call run,rm log.txt > /dev/null 2>&1;$(MAKE) run-nographic TICK_LIMIT=500 NO_SLOWDOWN=1 > /dev/null 2>&1; python3 test_script.py -s 4)
# Kill all my qemus
kill:
-killall -u $$(whoami) $(QEMU)
@sleep 0.2; if ps -U $$(whoami) | grep $(QEMU) >/dev/null; then killall -9 -u $$(whoami) $(QEMU); fi